/*
 * Design-Tokens.
 *
 * Drei Regeln halten das System zusammen:
 *
 *   Gruen ist die Lernfarbe. Es markiert Sinnabschnitte und sonst nichts -
 *   keine Knoepfe, keine Zustaende, keine Verzierung. Wer Gruen sieht, sieht
 *   etwas, das er mitnehmen kann.
 *
 *   Serife ist der deutsche Text, Grotesk ist die Anwendung drumherum. Am
 *   Schriftschnitt erkennt man, was Lernmaterial ist und was Bedienung.
 *
 *   Handschrift ist die eigene Mitschrift. Sie kommt genau einmal vor - auf
 *   dem Lernzettel unter dem Lesetext -, und sie ist die Ausnahme, die die
 *   Regel bestaetigt: Der Zettel ist weder Lesetext noch Bedienung, sondern
 *   das, was der Leser selbst mitgeschrieben haette.
 *
 * ACHTUNG: Der Prototyp in design/DeutschLern-Assistent.dc.html traegt noch
 * die alte, cremefarbene Fassung. Wer ihn neu aus dem Canvas zieht, holt sie
 * sich zurueck - dort muessen dieselben Werte nachgezogen werden.
 */
:root {
  --bg: #F1F3F6;
  --surface: #FFFFFF;
  --surface-hover: #F5F8FA;
  --border: #DEE4EA;
  --primary: #12283D;
  --primary-dark: #0A1725;
  /* Die Lernfarbe. --accent-light ist ihre Fassung fuer dunklen Grund
     (Buehne des Lese-Videos), --accent-surface die ruhige Flaeche darunter. */
  --accent: #0B6E5B;
  --accent-text: #07564A;
  --accent-surface: #E3F1ED;
  --accent-light: #6FD9C0;
  --text: #3A4757;
  --text-strong: #0B1A2A;
  --text-muted: #5A6878;
  --text-faint: #93A0AE;
  --pill-track: #E7ECF1;
  --info-surface: #DDE7F3;
  --info-text: #35547C;
  /* Statusgruen des Admin-Bereichs. Im Reader hat Gruen eine andere
     Bedeutung - dort tragen dieselben Etiketten den neutralen Ton. */
  --ok-surface: #E4EFE3;
  --ok-text: #3F6B45;
  --ok-dot: #5BAA6A;
  --neutral-surface: #E7ECF1;
  --neutral-text: #4C5A6B;
  --display: 'Archivo', 'Public Sans', ui-sans-serif, system-ui, sans-serif;
  --read: 'Newsreader', Georgia, 'Times New Roman', serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  /* Bauhoehe der klebenden Kopfzeile: 22 + 28 + 13 + 1px Kante. Sie steht als
     Token da, weil die zweite klebende Leiste der Leseansicht darunter
     andocken muss - ohne den Wert schoebe sie sich unter die Kopfzeile.
     Damit die Rechnung stimmt und nicht an Schriftmetriken haengt, hat der
     Navigationslink eine gesetzte Hoehe (.navlink). */
  --masthead-h: 64px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Public Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--primary); text-decoration: none; }
a:hover { color: var(--primary-dark); }

/* Die Leseansicht ist weiss bis an den Rand. Ein Blatt Papier auf grauem
   Grund waere ein Rahmen mit anderen Mitteln: der Lesetext saesse eingerueckt
   im Blatt, die Schlagzeile darueber am Seitenrand, und die beiden Kanten
   liefen nicht mehr uebereinander.

   Das Lese-Video ist ausgenommen - dort stehen Buehne und Transkript als
   weisse Flaechen auf dem Grund, und ein weisser Grund liesse sie
   verschwinden.

   Die Marke haengt am Tauschbereich und nicht am <main>: Der Abspielknopf
   wechselt den Modus, ohne die Seite neu zu laden, und tauscht dabei nur
   diesen Bereich. Stuende sie darueber, bliebe der Grund nach dem Wechsel
   weiss und die Buehne verschwaende darin.                                 */
body:has(.reading), body:has(.feed) { background: var(--surface); }
body:has(#article-view.listening) { background: var(--bg); }

.shell { max-width: 1080px; margin: 0 auto; padding: 28px 24px 64px; }

/* Die Leseansicht steht im selben Raster wie alles andere.
 *
 * Sie hatte lange eine eigene Breite: 760px Textspalte, und damit die Spalte
 * nicht links in einem 1080er Raster stand, wurde die ganze Seite auf 808px
 * verengt. Das machte die Leseansicht zu einer Ausnahme - schmaler als Feed,
 * Vokabel-Netz und Uebersicht, mit einem sichtbaren Sprung bei jedem Wechsel
 * zwischen ihnen.
 *
 * Jetzt gilt fuer den Artikel dieselbe Breite wie fuer jede andere Seite:
 * 1080px. Kopfzeile, Aufmacher, Schlagzeile und Lesetext haben eine linke und
 * eine rechte Kante, die Seite steht in der Mitte des Fensters - und beim
 * Weg vom Feed in den Artikel und zurueck bleibt der Rand, wo er war. */

/* --- Kopfzeile ------------------------------------------------------------
   Eine Kopfzeile fuer alle Seiten. Sie war einmal nur im Feed klebend und mit
   Milchglas, ueberall sonst eine schlichte Zeile ohne Kante - und damit sprang
   beim Weg vom Feed in den Artikel die Marke um, obwohl derselbe Kopf dasteht.
   Wer zwischen Feed, Artikel, Vokabel-Netz und Uebersicht wechselt, wechselt
   den Inhalt und nicht die Anwendung; der Rahmen darf das nicht behaupten.

   Das Milchglas ist dabei kein Effekt, sondern die Bedingung: durchsichtig
   waere die Leiste ueber laufendem Text unlesbar, deckend waere sie ein
   Deckel, der die Seite abschneidet. Milchglas zeigt, dass da noch etwas ist,
   ohne es zu behaupten.                                                     */
.masthead {
  display: flex; align-items: center; gap: 10px;
  position: sticky; top: 0; z-index: 8;
  /* Bis an die Kante des Rasters, damit unter den Raendern nichts vorbeizieht. */
  margin: -28px -24px 28px; padding: 22px 24px 13px;
  /* Der Literalwert zuerst: faellt color-mix aus, bliebe die Leiste sonst
     ganz durchsichtig - und damit unlesbar statt nur unbunt. */
  background: rgba(255, 255, 255, 0.72);
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  backdrop-filter: blur(14px) saturate(1.7);
  -webkit-backdrop-filter: blur(14px) saturate(1.7);
  border-bottom: 1px solid var(--border);
}
/* Zeichen und Wortmarke sind ein Ziel. Der Abstand zwischen beiden steht
   deshalb hier und nicht im gap der Kopfzeile - sonst klaffte mitten im Link
   eine Luecke, die nicht mitklickt. */
.brand {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; color: inherit; border-radius: 6px;
}
.brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Das Zeichen bringt seine Farben selbst mit (siehe layout.html) - hier steht
   nur noch sein Platz. Frueher war es ein tintenfarbenes Quadrat mit einem
   weissen Glyph darin; die Flaeche ist mit der Sprechblase weggefallen. */
.mark {
  width: 24px; height: 26px;
  display: flex; align-items: center; justify-content: center;
}

/* Die Wortmarke steht in der Leseschrift und nicht in der Bedienschrift: Ein
   Gruss ist deutsche Sprache, kein Bedienelement - dieselbe Regel, nach der
   der Lesetext eine Serife traegt.

   line-height ist gesetzt, damit die Zeile nicht an Schriftmetriken haengt:
   Die Kopfzeile rechnet mit 28px Inhaltshoehe (--masthead-h), und die darf
   die Wortmarke nicht ueberschreiten. */
.wordmark {
  font-family: var(--read); font-size: 19px; font-weight: 600; line-height: 1.2;
  color: var(--text-strong); letter-spacing: -0.02em;
}

/* Die Navigation ist auf breiten Fenstern eine Zeile und traegt dort denselben
   Abstand wie die Kopfzeile selbst - sie steht in ihr und nicht daneben. */
.nav { display: flex; align-items: center; gap: 10px; }

/* Der Knopf gehoert dem schmalen Fenster; breit gibt es nichts aufzuklappen. */
.burger { display: none; }

/* --- Die Sprachwahl in der Kopfzeile --------------------------------------
   Dieselbe Bauform wie die Gruppe im Chunk-Panel, Zeichen fuer Zeichen: Es ist
   dieselbe Wahl, und zwei Schalter, die dasselbe tun und verschieden aussehen,
   sind zwei Schalter.

   Der Zustand haengt an aria-current und nicht an einer Klasse. Der
   Screenreader liest ihn ohnehin, und zwei Quellen fuer denselben Zustand
   laufen frueher oder spaeter auseinander.

   Die eigene [hidden]-Regel ist noetig, weil display: flex die Regel des
   Browsers schlaegt - derselbe Fall wie beim .layertoggle.               */
.langtip { margin-right: 2px; }
.langpick {
  display: flex; gap: 4px; padding: 3px;
  background: var(--pill-track); border-radius: 10px;
}
.langpick[hidden] { display: none; }
.langpick button {
  height: 22px; padding: 0 9px; border: none; border-radius: 8px;
  background: none; color: var(--text-muted);
  font-family: inherit; font-size: 11.5px; font-weight: 500; cursor: pointer;
}
.langpick button[aria-current='true'] { background: var(--surface); color: var(--text-strong); }

/* --- Das Konto in der Kopfzeile ------------------------------------------
   Variante A aus design/anmeldung/: rechts hinter einem Strich, links die
   Bereiche, rechts die eigene Person. Anonym ein Link mit Wort auf die
   Anmeldeseite - dieselbe Pillenform wie .navlink, aber mit Kante, weil er
   eine Handlung ist und kein Ort. Angemeldet Anfangsbuchstabe und Vorname.

   Das Menue der Angemeldeten ist ein <details>; die Tafel faellt darunter
   heraus, deckend und mit Kante wie das Menue auf dem Telefon - unter ihr
   laeuft der Feed weiter. Die Hoehe bleibt 28px, damit --masthead-h stimmt. */
.kontotrenner { width: 1px; height: 20px; background: var(--border); margin: 0 2px; }
.kontoknopf { position: relative; }
.kontoknopf > summary { list-style: none; cursor: pointer; }
.kontoknopf > summary::-webkit-details-marker { display: none; }
.kontoknopf > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.einstieg {
  height: 28px; display: inline-flex; align-items: center; gap: 6px; padding: 0 12px 0 10px;
  font-size: 12.5px; font-weight: 600; color: var(--text-strong);
  border-radius: 999px; border: 1px solid var(--border); background: var(--surface);
}
.einstieg svg { color: var(--text-muted); }
.einstieg:hover,
.einstieg[aria-current='page'] { border-color: var(--text-faint); background: var(--surface-hover); }
.einstieg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.kontoknopf .person {
  height: 28px; display: inline-flex; align-items: center; gap: 7px; padding: 0 9px 0 2px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--surface);
  font-size: 12.5px; font-weight: 600; color: var(--text-strong);
}
.kontoknopf .person:hover,
.kontoknopf[open] .person { border-color: var(--text-faint); }
.kontoknopf .person svg { color: var(--text-faint); }
.kontoknopf .initial {
  width: 22px; height: 22px; border-radius: 50%; display: inline-flex; align-items: center;
  justify-content: center; background: var(--primary); color: #FFFFFF; font-size: 11px; font-weight: 700;
}
.kontotafel {
  position: absolute; right: 0; top: calc(100% + 10px); z-index: 9; width: 340px;
  padding: 18px 18px 16px; text-align: left;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  box-shadow: 0 18px 40px -18px rgba(11, 26, 42, 0.35), 0 1px 2px rgba(11, 26, 42, 0.05);
}
.kontotafel.menue { width: 260px; padding: 8px; }
.kontotafel .wer { padding: 8px 10px 10px; margin-bottom: 6px; border-bottom: 1px solid var(--border); }
.kontotafel .werzeile { display: block; font-size: 11.5px; color: var(--text-muted); }
.kontotafel .wer strong { display: block; font-size: 13.5px; color: var(--text-strong); }
.kontotafel .webid { font-family: var(--mono); font-size: 11.5px; color: var(--text-muted); word-break: break-all; }
.kontotafel form { margin: 0; }
.kontotafel .punkt {
  display: flex; align-items: center; width: 100%; height: 34px; padding: 0 10px;
  border: none; border-radius: 6px; background: none; cursor: pointer;
  font-family: inherit; font-size: 13px; color: var(--text); text-align: left;
}
.kontotafel .punkt:hover { background: var(--surface-hover); color: var(--text-strong); }
.kontotafel .punkt.leise { color: var(--text-muted); }
.kontotafel hr { border: none; border-top: 1px solid var(--border); margin: 6px 0; }
.kontotafel .loeschen > summary { list-style: none; }
.kontotafel .loeschen > summary::-webkit-details-marker { display: none; }
.kontotafel .loeschform { display: flex; flex-direction: column; gap: 8px; padding: 6px 10px 8px; font-size: 12.5px; color: var(--text-muted); }
.kontotafel .loeschform label { display: flex; gap: 6px; align-items: flex-start; }

/* Auf dem Telefon steht vom Knopf nur das Zeichen in der Zeile - neben Marke,
   Sprachwahl und Menueknopf ist fuer das Wort kein Platz. Die Tafel nimmt die
   ganze Breite unter der Kopfzeile. */
@media (max-width: 640px) {
  .kontotrenner { display: none; }
  .kontoknopf { position: static; }
  .einstieg { width: 32px; padding: 0; justify-content: center; }
  .einstiegwort { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .kontoknopf .person { padding: 0 2px; }
  .kontoknopf .person .vorname, .kontoknopf .person svg { display: none; }
  .kontotafel, .kontotafel.menue { right: 16px; left: 16px; width: auto; top: 100%; margin-top: 8px; }
}

/* --- Die Anmeldeseite ---------------------------------------------------
   Nach design/anmeldung/Seite*.dc.html, im Aufbau des Dribbble-Vorbilds:
   eine Karte in der Mitte, links und rechts Strichzeichnungen auf einer
   gemeinsamen Bodenlinie, darunter eine leise Zeile. Die Karte haelt immer
   Abstand zur Linie, die Zeile steht immer darunter - auch wenn eine
   Fehlermeldung die Karte laenger macht.                                    */
.anmeldebuehne {
  position: relative; display: flex; flex-direction: column; align-items: center;
  padding: 56px 24px 132px; overflow: hidden;
}
.anmeldeboden {
  position: absolute; left: 40px; right: 40px; bottom: 92px; height: 1px;
  background: var(--text-faint); opacity: 0.6;
}
.anmeldezeichnung { position: absolute; color: var(--text-strong); }
.anmeldezeichnung.links { left: 40px; bottom: 80px; }
.anmeldezeichnung.rechts { right: 40px; bottom: 60px; }
.anmeldestreifen { display: none; }

.anmeldekarte {
  position: relative; z-index: 1; width: 380px; max-width: 100%; box-sizing: border-box;
  padding: 32px 32px 24px; text-align: center;
  border: 1px solid var(--border); border-radius: 16px; background: var(--surface);
  box-shadow: 0 24px 48px -24px rgba(11, 26, 42, 0.28), 0 1px 2px rgba(11, 26, 42, 0.05);
}
.anmeldekarte h1 {
  margin: 0; font-family: var(--display); font-size: 24px; font-weight: 700;
  letter-spacing: -0.015em; color: var(--text-strong);
}
.anmeldekarte .wozu { margin: 8px auto 22px; max-width: 290px; font-size: 13.5px; line-height: 1.55; color: var(--text-muted); }
.anmeldekarte form { margin: 0; text-align: left; }
.anmeldekarte .los, .anmeldekarte .weiter {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px;
  border-radius: 8px; font-family: inherit; font-weight: 600; cursor: pointer;
}
.anmeldekarte .los { height: 40px; border: none; background: var(--primary); color: #FFFFFF; font-size: 13.5px; }
.anmeldekarte .los:hover { background: var(--primary-dark); }
/* Der zweite Weg: mit Kante statt gefuellt, er ist nicht der uebliche. */
.anmeldekarte .weiter {
  height: 38px; margin-top: 10px; border: 1px solid var(--border); background: var(--surface);
  color: var(--text-strong); font-size: 13px;
}
.anmeldekarte .weiter:hover { border-color: var(--text-faint); background: var(--surface-hover); }
.anmeldekarte .los:focus-visible, .anmeldekarte .weiter:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.anmeldekarte .wasistpod { margin: 10px 0 0; font-size: 13px; line-height: 1.55; color: var(--text-muted); }
.anmeldekarte .wasistpod strong { color: var(--text-strong); font-weight: 600; }
.anmeldekarte .feldfehler { margin: 6px 0 0; font-size: 13px; line-height: 1.5; color: #8A1F16; }
.anmeldekarte .feldfehler code { font-size: 12px; }
.anmeldekarte input[aria-invalid='true'] { border-color: #B4442F; }
.sprachhinweis { font-size: 12px; font-weight: 400; opacity: 0.8; }
.anmeldekarte .oder { display: flex; align-items: center; gap: 10px; margin: 20px 0 14px; font-size: 11.5px; color: var(--text-muted); }
.anmeldekarte .oder::before, .anmeldekarte .oder::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.webidform label {
  display: block; margin-bottom: 6px; font-size: 11.5px; font-weight: 600; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.webidform input {
  width: 100%; box-sizing: border-box; height: 40px; padding: 0 12px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface);
  font-family: var(--mono); font-size: 12.5px; color: var(--text-strong);
}
.webidform input:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: transparent; }
.webidform .hilfe { margin-top: 8px; font-size: 12px; color: var(--text-muted); }
.webidform .hilfe summary { cursor: pointer; width: max-content; text-decoration: underline; text-underline-offset: 2px; list-style: none; }
.webidform .hilfe summary::-webkit-details-marker { display: none; }
.webidform .hilfe p { margin: 6px 0 0; line-height: 1.5; }
.webidform .hilfe code { font-family: var(--mono); font-size: 11.5px; word-break: break-all; }
.anmeldekarte .ohnepod { margin: 20px 0 0; font-size: 12.5px; color: var(--text-muted); }
.anmeldekarte .ohnepod a { font-weight: 600; color: var(--accent-text); }
/* Die Toene von .gateerror und .pill-failed - eine Fehlfarbe reicht. */
.anmeldefehler {
  margin: 0 0 16px; padding: 10px 12px; border-radius: 8px; text-align: left;
  font-size: 12.5px; line-height: 1.45; background: #F4E0DB; color: #9A4A3F;
}
.anmeldefuss {
  position: absolute; bottom: 58px; left: 0; right: 0; margin: 0; text-align: center;
  font-size: 12px; color: var(--text-muted);
}
.anmeldefuss a { color: var(--text-muted); }

/* Unter 900px ist neben der Karte kein Platz mehr fuer die Zeichnungen;
   uebrig bleibt ein Streifen ueber der Karte, und die Zeile laeuft mit. */
@media (max-width: 900px) {
  .anmeldebuehne { padding: 0 16px 24px; }
  .anmeldeboden, .anmeldezeichnung { display: none; }
  .anmeldestreifen { display: block; width: 100%; max-width: 380px; margin: 8px 0 -6px; color: var(--text-strong); }
  .anmeldekarte { width: 100%; max-width: 380px; padding: 24px 20px 20px; }
  .anmeldefuss { position: static; margin-top: 18px; }
}

/* --- Die Kopfzeile auf dem Telefon ----------------------------------------
   Unter 640px reicht die Zeile fuer die vier Eintraege nicht mehr. Sie brach
   um - und eine klebende Kopfzeile, die umbricht, ist zweierlei kaputt: sie
   nimmt dem Lesetext die halbe Schirmhoehe, und sie ist nicht mehr so hoch
   wie --masthead-h, an dem die Niveau-Leiste der Leseansicht andockt.

   Deshalb liegen die Eintraege hier hinter dem Knopf, und die Zeile behaelt
   ihre Bauhoehe: der Knopf ist so hoch wie ein .navlink, den er ersetzt.

   Aufgeklappt faellt die Tafel unter die Kopfzeile statt in sie hinein -
   deckend und mit Kante, denn unter ihr laeuft der Text weiter, und durch
   zwei Scheiben uebereinander liest sich keine Beschriftung.

   Scharf schaltet die Regeln erst masthead.js ([data-menu]): ohne JavaScript
   waere die Navigation hinter einem Knopf verschwunden, der nichts tut. */
@media (max-width: 640px) {
  .masthead[data-menu] .burger {
    height: 28px; width: 32px; padding: 0; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 999px; border: 1px solid var(--border);
    background: var(--surface); color: var(--text-strong);
  }
  .masthead[data-menu] .burger:hover { background: var(--surface-hover); }
  .masthead[data-menu] .burger { position: relative; }
  .masthead[data-menu] .burgerzahl { display: inline-flex; position: absolute; top: -7px; right: -8px; }
  .masthead[data-menu] .nav {
    display: none;
    /* Die Kopfzeile klebt und ist damit selbst der Bezug; 24px sind ihr
       Innenrand, die Tafel steht also buendig zur Textkante darunter. */
    position: absolute; top: 100%; right: 24px; margin-top: 8px;
    flex-direction: column; align-items: stretch; gap: 2px;
    min-width: 176px; padding: 6px;
    border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
    box-shadow: 0 18px 40px -18px rgba(11, 26, 42, 0.25), 0 1px 2px rgba(11, 26, 42, 0.05);
  }
  .masthead[data-menu][data-open] .nav { display: flex; }
  /* In der Tafel ist jeder Eintrag eine Zeile: linksbuendig und so breit wie
     die Tafel, damit der Daumen die Zeile trifft und nicht die Schrift. */
  .masthead[data-menu] .nav .navlink { height: 34px; padding: 0 12px; font-size: 13px; }
  /* Drei Kuerzel stehen jetzt zwischen Wortzeichen und Knopf. Sie ruecken
     zusammen, statt zu verschwinden: Die Sprachwahl ist auf dem Telefon eher
     wichtiger als am Schreibtisch, und hinter dem Knopf laege sie zwei Griffe
     entfernt. */
  .langpick { padding: 2px; gap: 2px; }
  .langpick button { padding: 0 7px; }
  /* Die Wortmarke darf auch im schmalen Fenster nicht umbrechen. Eine
     klebende Kopfzeile, die umbricht, ist zweierlei kaputt: Sie nimmt dem
     Lesetext Schirmhoehe, und sie ist nicht mehr so hoch wie --masthead-h, an
     dem die Niveau-Leiste der Leseansicht andockt.

     Frueher stand hier zusaetzlich eine Regel, die das zweite Wort abgab -
     "DeutschLern Assistent" mass 154px und brach um. "Guten Tag" ist kurz
     genug, dass es beide Woerter behalten kann. */
  .wordmark { white-space: nowrap; }
}

/* --- Filterleiste --- */
.filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 24px 0 14px; }
.filters .spacer { flex: 1; }

.chip {
  height: 28px; display: inline-flex; align-items: center; padding: 0 12px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--surface);
  color: var(--text-muted); font: inherit; font-size: 12.5px; cursor: pointer;
}
.chip:hover { background: var(--surface-hover); }
.chip[aria-current='true'] { background: var(--primary); border-color: var(--primary); color: #FFFFFF; font-weight: 600; }

/* --- Niveau-Umschalter --- */
.levels { display: flex; gap: 4px; padding: 3px; background: var(--pill-track); border-radius: 10px; }
.levels a {
  height: 28px; min-width: 34px; padding: 0 10px; display: inline-flex;
  align-items: center; justify-content: center; border-radius: 8px;
  color: var(--text-muted); font-size: 12.5px; font-weight: 500;
}
.levels a:hover { color: var(--text-strong); }
.levels a[aria-current='true'] { background: var(--primary); color: #FFFFFF; font-weight: 600; }
/* Eine Stufe ohne Fassung bleibt sichtbar und wird nicht anklickbar - so
   sieht man, dass es sie gibt und dass sie noch nicht fertig ist. */
.levels a.is-disabled { opacity: 0.35; pointer-events: none; }
.levels button {
  height: 26px; min-width: 34px; padding: 0 9px; border: none; border-radius: 8px;
  background: transparent; color: var(--text-muted); font: inherit; font-size: 12px;
  font-weight: 500; cursor: pointer;
}
.levels button[aria-current='true'] { background: var(--primary); color: #FFFFFF; font-weight: 600; }
.levels button:disabled { opacity: 0.35; cursor: not-allowed; }

/* --- Feed: der Seitenspiegel ----------------------------------------------
   Statt zwoelf gleich grosser Kaestchen vier Rhythmen auf einer Seite: der
   Aufmacher auf dunkler Flaeche mit Bild daneben, darunter vier Kacheln
   ("Neu heute"), dann eine Spalte aus knappen Zeilen neben einem grossen
   Bildfeld, zuletzt die aelteren Meldungen als Liste. Wer scrollt, sieht am
   Wechsel des Rhythmus, wo er ist.

   Getrennt wird ansonsten mit Haarlinien statt mit Rahmen: eine Linie sagt
   "hier endet der eine Text und faengt der naechste an", ein Rahmen sagt
   zusaetzlich "das hier ist ein Ding" - und ein Ding ist eine Meldung nicht.
   Die zwei Ausnahmen tragen ein Bild bis an ihre Kante: der Aufmacher und das
   Bildfeld. Dort ist der Rahmen keine Behauptung, sondern das Bild selbst.

   Die Koederfrage steht in der Leseschrift, so wie jeder deutsche Satz in
   dieser App. Titel bleiben in der Grotesk: eine Schlagzeile ist Anzeige,
   kein Lesetext.                                                            */

/* Die Bildflaeche jeder Karte. Sie bleibt auch ohne Bild stehen - ein
   Artikel ohne Foto ist ein schwaecherer Artikel, kein Loch im Raster.

   Ohne Bild aber unsichtbar: eine graue Platte neben jeder zweiten Zeile
   sieht aus wie ein Fehler beim Laden. Nur im Kachelraster bleibt sie
   angedeutet - dort haelt sie die Reihe zusammen (siehe .card .shot). */
.shot { position: relative; overflow: hidden; background: var(--pill-track); }
.shot img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Ohne Foto das Farbfeld des Artikels - derselbe Verlauf, den auch die
   Buehne seines Lese-Videos aufzieht: zwei Farbwolken ueber einem schraegen
   Verlauf. Die Rubrik gibt die drei Toene (siehe [data-category] weiter
   unten), der Artikel Winkel und Mitten (Inline-Stil aus SceneField).

   Das ist der Unterschied zwischen "hier fehlt etwas" und "hier ist etwas":
   eine graue Platte sieht aus wie ein Ladefehler, ein Farbfeld sagt, worum
   es geht - und faerbt den Feed nach Rubriken ein, ohne dafuer ein Etikett
   mehr zu brauchen. */
.shot.is-blank, .opener.is-plate {
  --plate-a: var(--scene-a); --plate-b: var(--scene-b); --plate-c: var(--scene-c);
  background:
    radial-gradient(58% 48% at var(--gx1, 30%) var(--gy1, 25%), var(--plate-c) 0%, transparent 62%),
    radial-gradient(64% 54% at var(--gx2, 70%) var(--gy2, 65%), var(--plate-a) 0%, transparent 68%),
    linear-gradient(var(--angle, 165deg), var(--plate-a) 0%, var(--plate-b) 78%);
}

/* Wie schwer das Feld sein darf, entscheidet seine Nachbarschaft. Aufmacher
   und Bildfeld stehen ohnehin dunkel und tragen weisse Schrift; die Kacheln
   und Listenzeilen stehen auf Weiss, und vier tiefe Bloecke nebeneinander
   waeren ein Riegel quer durch die Seite. Dort wird derselbe Ton in den
   Papierton eingeruehrt - dieselbe Farbe, andere Lautstaerke. */
@supports (color: color-mix(in oklab, red 50%, white)) {
  .card .shot.is-blank, .brief .shot.is-blank, .entry .shot.is-blank,
  .relation .shot.is-blank {
    --plate-a: color-mix(in oklab, var(--scene-a) 42%, var(--surface));
    --plate-b: color-mix(in oklab, var(--scene-b) 24%, var(--surface));
    --plate-c: color-mix(in oklab, var(--scene-c) 50%, var(--surface));
  }
}

/* Ohne Foto keine Bildflaeche (UX-Befund feed-3, 16.10.2026). Das Farbfeld
   war als "hier ist etwas" gedacht, wurde aber als Bild gelesen, das nie
   fertig laedt - auf /vietnam standen 13 von 16 davon untereinander, und auf
   dem Telefon schob ein verschwommenes Feld die Schlagzeile unter den Falz.

   Wo die Vorschau eine Beigabe ist (Listenzeilen, Vorschlaege), faellt sie
   weg und der Text nimmt die Breite. Der Aufmacher wird zur reinen
   Textkarte, das Bildfeld behaelt seine dunkle Platte, nur ohne Wolken. In
   der Reihe "Neu heute" bleibt ein schmales Band mit der Rubrik: Die Reihe
   lebt von ihrer gemeinsamen Oberkante, und das Band haelt sie, ohne ein
   Bild vorzutaeuschen. Das Lese-Video zieht sein Farbfeld weiter auf - dort
   ist es Buehne und kein Platzhalter. */
.brief .shot.is-blank, .entry .shot.is-blank, .relation .shot.is-blank { display: none; }
.entry:has(> .shot.is-blank) { grid-template-columns: minmax(0, 1fr); }
.hero:has(.shot.is-blank) { grid-template-columns: minmax(0, 1fr); }
.hero:has(.shot.is-blank) .hero-picture { display: none; }
.hero:has(.shot.is-blank) .hero-text { padding: 38px clamp(24px, 4vw, 48px); }
.hero:has(.shot.is-blank) .hero-text h2 { max-width: 28ch; }
.feature .shot.is-blank { display: none; }
.card .shot.is-blank {
  height: 34px; display: flex; align-items: center; padding: 0 12px;
  background: var(--pill-track);
}
.card .shot.is-blank::after {
  content: attr(data-category); font-size: 11px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted);
}

/* Die Urheberzeile liegt auf dem Bild - und ein Foto kann an der Stelle hell
   oder dunkel sein. Der Schatten allein reicht ueber einem Gletscher nicht,
   eine deckende Platte wuerde ein Loch ins Foto schneiden. Milchglas loest
   beides: es daempft, was darunter liegt, und verdeckt es nicht. */
.hero-picture figcaption, .card figcaption, .feature .credit {
  padding: 2px 6px; border-radius: 5px;
  background: rgba(10, 23, 37, 0.3);
  backdrop-filter: blur(7px) saturate(1.3);
  -webkit-backdrop-filter: blur(7px) saturate(1.3);
}

/* --- Der Aufmacher --- */
.hero {
  display: grid; grid-template-columns: minmax(0, 44fr) minmax(0, 56fr);
  border-radius: 20px; overflow: hidden; background: var(--primary);
  color: inherit;
}
.hero-text { padding: 34px 32px; display: flex; flex-direction: column; justify-content: center; }
/* Die Zeile ueber der Schlagzeile sagt, warum diese Meldung oben steht.
   Nicht in der Lernfarbe: Gruen markiert Sinnabschnitte und sonst nichts. */
.hero-text .eyebrow {
  display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: rgba(255, 255, 255, 0.6);
}
.hero-text .eyebrow .spacer { flex: 1; }
/* "VOR 2 STD." in Versalien waere ein Ruf, wo eine Angabe stehen soll - und
   auf jeder anderen Karte steht sie ohnehin so wie hier. */
.hero-text .eyebrow .when {
  text-transform: none; letter-spacing: 0.02em; font-weight: 500;
  color: rgba(255, 255, 255, 0.55); white-space: nowrap;
}
/* Schmal brach die Zeile mitten in "ARTIKEL DES / TAGES" und "vor 1 /
   Std." um. Dort bekommt "Artikel des Tages" eine eigene Zeile, darunter
   Rubrik und Zeit. */
@media (max-width: 640px) {
  .hero-text .eyebrow { flex-wrap: wrap; row-gap: 4px; }
  .hero-text .eyebrow .kind { flex-basis: 100%; }
  .hero-text .eyebrow .punkt { display: none; }
}
.hero-text h2 {
  margin: 14px 0 0; font-family: var(--display); font-size: clamp(24px, 2.9vw, 32px);
  font-weight: 700; color: #FFFFFF; line-height: 1.14; letter-spacing: -0.03em;
  text-wrap: pretty;
}
.hero-text p { margin: 12px 0 0; font-size: 14px; line-height: 1.55; color: rgba(255, 255, 255, 0.72); text-wrap: pretty; }
.hero-text p.hook {
  font-family: var(--read); font-size: 19px; line-height: 1.45;
  color: rgba(255, 255, 255, 0.94); max-width: 34ch;
}
.hero-text p.teaser {
  margin-top: 10px; font-size: 13px; color: rgba(255, 255, 255, 0.62); max-width: 44ch;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.hero-text .tags {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 22px;
  font-size: 11px; color: rgba(255, 255, 255, 0.55);
}
.hero-text .tags .src { font-family: var(--mono); }
.hero:hover h2 { color: var(--accent-light); }

/* Feste Proportion, damit die Seite beim Nachladen nicht springt - und damit
   der Seitenspiegel unabhaengig davon steht, welches Format das gefundene
   Foto hat. */
.hero-picture { position: relative; margin: 0; min-height: 300px; }
.hero-picture .shot { position: absolute; inset: 0; }
.hero-picture .shot:not(.is-blank) { background: var(--primary-dark); }
/* Die Pflichtangabe. Klein, aber vorhanden - wer ein Bild unter freier
   Lizenz zeigt, nennt den Urheber. Auf dem Bild statt darunter, weil das
   Bild bis an die Kante der Karte laeuft. */
.hero-picture figcaption {
  position: absolute; right: 12px; bottom: 10px; max-width: 70%;
  font-family: var(--mono); font-size: 10px; line-height: 1.4; text-align: right;
  color: rgba(255, 255, 255, 0.7); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
  text-wrap: pretty;
}

/* --- Die Bandzeile ueber jedem Abschnitt --- */
.band {
  display: flex; align-items: baseline; gap: 10px;
  border-top: 2px solid var(--text-strong); padding-top: 10px; margin-bottom: 6px;
}
.band h3 {
  margin: 0; font-family: var(--display); font-size: 16px; font-weight: 700;
  color: var(--text-strong); letter-spacing: -0.015em;
}
.band .count { font-size: 12px; color: var(--text-muted); }

/* --- Neu heute: eine Reihe mit Bild, die seitlich laeuft --- */
.fresh { margin-top: 34px; }

/* Die Blaetterknoepfe stehen am rechten Ende der Bandzeile - dort, wo die
   Reihe darunter weitergeht. Sichtbar macht sie erst feed-rail.js: ohne
   JavaScript koennten sie nichts tun, und die Reihe scrollt auch ohne sie. */
.rail-nav { display: flex; gap: 6px; align-self: center; }
.rail-nav button {
  width: 28px; height: 28px; padding: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface); color: var(--text-muted);
  transition: color 0.18s ease, border-color 0.18s ease;
}
.rail-nav button:hover:not(:disabled) { color: var(--text-strong); border-color: var(--text-faint); }
/* Am Ende der Reihe ausgegraut statt weg: ein Knopf, der verschwindet,
   verschiebt den anderen unter dem Zeiger. */
.rail-nav button:disabled { opacity: 0.3; cursor: default; }

/* Mit dem Finger waren Rubrik-Pillen und Blaetterknoepfe 28px hoch und
   schwer zu treffen (UX feed-5). Die Pillen wachsen auf 40px, die
   Blaetterknoepfe gehen weg - die Reihe wischt man ohnehin. */
@media (pointer: coarse) {
  .filters .chip { height: 40px; padding: 0 14px; font-size: 13.5px; }
  .rail-nav { display: none; }
}

/* Drei Kacheln nebeneinander, die vierte lugt hervor - daran sieht man, dass
   es weitergeht, bevor man scrollt. Die Rasterpunkte fangen jede Kachel in
   der Mitte ab, sonst bliebe die Reihe irgendwo zwischen zwei Kacheln
   stehen. */
.cards {
  display: flex; align-items: start; gap: 22px; margin-top: 14px;
  /* Unten Platz fuer die Kachel, die vorn steht: die Reihe scrollt seitlich
     und beschneidet deshalb auch oben und unten. Ohne diesen Streifen waere
     die vergroesserte Kachel an ihrer Unterkante abgeschnitten. */
  padding-bottom: 28px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* Die Leiste selbst bleibt weg: Sie stuende quer unter einer Reihe, die
     ihre Fortsetzung schon zeigt. Geblaettert wird mit Finger, Trackpad,
     den Knoepfen in der Bandzeile oder den Pfeiltasten. */
  scrollbar-width: none;
}
.cards::-webkit-scrollbar { display: none; }
.cards:focus-visible { outline: 2px solid var(--primary); outline-offset: 6px; border-radius: 6px; }
@media (prefers-reduced-motion: no-preference) { .cards { scroll-behavior: smooth; } }
/* Auf dem Telefon faellt der Streifen weg, und mit ihm der Grund, aus dem es
   ihn gab: die vordere Kachel waechst dort nicht mehr (siehe .card.is-focus).
   Sie ist auf einem Schirm dieser Breite ohnehin fast die einzige, die man
   sieht - vergroessern hiesse, sie gegen nichts abzuheben, und die 28px, die
   ihr Wachstum braucht, stuenden den Rest der Zeit leer zwischen der Reihe
   und dem naechsten Abschnitt. Die Helligkeit unterscheidet weiter. */
@media (max-width: 640px) {
  .cards { padding-bottom: 0; }
  .cards.is-live .card.is-focus { transform: none; }
}

.card {
  flex: 0 0 clamp(215px, 27vw, 296px); scroll-snap-align: center;
  display: block; color: inherit;
}
/* Die Abblendung des Prototyps, jetzt mit Bedeutung: Wo ein Raster nur die
   Fensterbreite kannte, weiss die Reihe, welche Kachel in der Mitte steht.
   Gesetzt wird sie erst von feed-rail.js - ohne JavaScript stehen alle
   Kacheln gleich hell da, statt dauerhaft abgeblendet. */
.cards.is-live .card { transition: transform 0.22s ease; }
/* Abgeblendet wird nur das Bild, nie der Text (UX-Befund feed-4): mit der
   ganzen Kachel auf 62 % hatten Schlagzeile und Koederfrage nur noch 2,6 bis
   3,4 : 1 Kontrast - genau der Text, den man hier lesen soll. */
.cards.is-live .card .shot { opacity: 0.55; transition: opacity 0.22s ease; }
/* Vorn heisst auch groesser. Die Helligkeit allein unterscheidet zwei
   Kacheln erst, wenn man sie nebeneinander sieht - die Groesse sieht man
   sofort, und sie sagt dasselbe wie das Wort: Diese hier ist gemeint.

   Vergroessert wird mit transform und nicht mit einer breiteren Kachel: die
   Reihe rastet ein, und eine Kachel, die im Umbruch waechst, verschoebe alle
   anderen unter der laufenden Scrollposition weg. transform laesst das
   Layout in Ruhe und damit auch die Rasterpunkte.

   Der Ursprung liegt oben: die Reihe lebt von ihrer gemeinsamen Oberkante,
   und die soll auch die vordere Kachel halten. Am Anfang und am Ende der
   Reihe wandert er zusaetzlich nach aussen - dort steht die aeusserste
   Kachel vorn, und nach aussen ist kein Platz, sondern der Rand. */
.cards.is-live .card.is-focus {
  transform: scale(1.06); transform-origin: top center;
}
.cards.is-live .card.is-focus .shot { opacity: 1; }
.cards.is-live .card.is-focus:first-child { transform-origin: top left; }
.cards.is-live .card.is-focus:last-child { transform-origin: top right; }
/* Der Wechsel darf wachsen, aber nicht wandern. */
@media (prefers-reduced-motion: reduce) {
  .cards.is-live .card { transition: none; }
}
/* Was unter dem Zeiger liegt, ist gemeint - auch wenn es nicht in der Mitte
   steht. Eine Kachel, die abgeblendet bleibt, waehrend man auf sie zeigt,
   waere die falsche Antwort auf einen Mauszeiger. Dasselbe fuer die Tastatur:
   Wer sich durch die Reihe tabbt, soll sehen, wo er gerade ist. */
.cards.is-live .card:hover .shot,
.cards.is-live .card:focus-visible .shot { opacity: 1; }
/* Die Pflichtangabe liegt auf dem Bild und nicht darunter: eine Zeile, die
   es nur bei Kacheln mit Bild gibt, wuerde die Schlagzeilen der Reihe auf
   verschiedene Hoehen setzen - und die Reihe lebt von der einen Kante. */
.card figure { position: relative; margin: 0; }
.card .shot { height: 148px; border-radius: 12px; }
.card figcaption {
  position: absolute; right: 8px; bottom: 7px; max-width: 85%;
  font-family: var(--mono); font-size: 9.5px; line-height: 1.35; text-align: right;
  color: rgba(255, 255, 255, 0.78); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
  text-wrap: pretty;
}
.card h4 {
  margin: 7px 0 0; font-family: var(--display); font-size: 15.5px; font-weight: 700;
  color: var(--text-strong); line-height: 1.25; letter-spacing: -0.015em; text-wrap: pretty;
}
.card:hover h4 { color: var(--primary); }
.card p {
  margin: 7px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-muted); text-wrap: pretty;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
.card p.hook { font-family: var(--read); font-size: 14.5px; line-height: 1.45; color: var(--text); }
.card .meta { margin-top: 10px; }

/* --- Spalte und Bildfeld --- */
.split {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 28px; align-items: stretch; margin-top: 34px;
}
/* Die Nebenmeldung: Vorschau und drei Zeilen. Nicht .row - so heisst die
   Zeile der Admin-Tabelle, und die ist ein siebenspaltiges Raster. */
.brief { display: flex; gap: 14px; align-items: flex-start; color: inherit; padding: 15px 0 16px; }
.brief + .brief { border-top: 1px solid var(--border); }
/* Die Vorschau steht auf der Mittellinie der Zeile: bei drei Zeilen
   Schlagzeile haengt sie sonst oben und die Zeile kippt nach unten weg. */
.brief .shot { flex: 0 0 88px; width: 88px; height: 66px; border-radius: 8px; align-self: center; }
.brief .body { flex: 1; min-width: 0; }
.brief h4 {
  margin: 6px 0 0; font-family: var(--display); font-size: 14.5px; font-weight: 700;
  color: var(--text-strong); line-height: 1.28; letter-spacing: -0.015em; text-wrap: pretty;
}
.brief:hover h4 { color: var(--primary); }

/* Das Bildfeld: eine Meldung, die nur aus Bild und Schlagzeile besteht. Der
   Schleier ist kein Effekt, sondern die Bedingung dafuer, dass weisse Schrift
   auf einem unbekannten Foto lesbar bleibt. */
.feature {
  position: relative; display: flex; align-items: flex-end; overflow: hidden;
  border-radius: 16px; min-height: 320px; height: 100%; color: inherit; background: var(--primary);
}
.feature .shot { position: absolute; inset: 0; }
.feature .shot:not(.is-blank) { background: var(--primary-dark); }
/* Der Schleier daempft nur noch, statt die untere Haelfte zuzudecken - die
   Schlagzeile traegt jetzt ihre eigene Platte. */
.feature .veil {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top,
      rgba(10, 23, 37, 0.45) 0%, rgba(10, 23, 37, 0.12) 55%, rgba(10, 23, 37, 0) 100%);
}
/* Die Platte liegt im Bild und nicht auf der ganzen Breite: so bleibt zu
   sehen, dass sie eine Ebene ueber dem Foto ist und nicht dessen Rand. Die
   helle Haarlinie oben ist die Kante des Glases - ohne sie schwimmt die
   Platte im Bild, statt darauf zu liegen. */
.feature .caption {
  position: relative; margin: 14px; padding: 20px 22px; border-radius: 13px;
  background: rgba(10, 23, 37, 0.42);
  backdrop-filter: blur(16px) saturate(1.4);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 8px 26px -14px rgba(0, 0, 0, 0.7);
}
.feature .caption .meta { color: rgba(255, 255, 255, 0.7); }
.feature .caption .meta .src { font-family: var(--mono); }
.feature h4 {
  margin: 9px 0 0; font-family: var(--display); font-size: clamp(19px, 2.1vw, 23px);
  font-weight: 700; color: #FFFFFF; line-height: 1.2; letter-spacing: -0.02em; text-wrap: pretty;
}
.feature p {
  margin: 9px 0 0; font-size: 13px; line-height: 1.55; color: rgba(255, 255, 255, 0.76);
  max-width: 42ch; text-wrap: pretty;
}
.feature p.hook { font-family: var(--read); font-size: 16px; line-height: 1.45; color: rgba(255, 255, 255, 0.92); }
.feature .credit {
  position: absolute; right: 12px; top: 10px; max-width: 60%;
  font-family: var(--mono); font-size: 10px; line-height: 1.4; text-align: right;
  color: rgba(255, 255, 255, 0.68); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
  text-wrap: pretty;
}
.feature:hover h4 { color: var(--accent-light); }

/* --- Aeltere Meldungen --- */
.older { margin-top: 34px; }
.entries {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  column-gap: 34px; margin-top: 4px;
}
/* Bild rechts statt links: die Schlagzeilen der Liste stehen dadurch
   untereinander auf einer Kante, und die Vorschau bleibt die Beigabe, die
   sie hier ist.

   Zwei Spalten, drei Zeilen: Kopfzeile und Marken laufen ueber beide Spalten,
   Text und Vorschau teilen sich die mittlere Zeile. Die Kopfzeile misst
   dadurch die ganze Zeilenbreite - die Zeitangabe steht an derselben rechten
   Kante wie das Bild darunter. */
.entry {
  display: grid; grid-template-columns: minmax(0, 1fr) 88px;
  column-gap: 14px; align-items: start; color: inherit;
  border-top: 1px solid var(--border); padding: 16px 0 20px;
}
.entry .meta, .entry .tags { grid-column: 1 / -1; }
.entry .body { grid-column: 1; min-width: 0; }
/* Die Vorschau steht auf der Mitte von Schlagzeile und Koederfrage, nicht auf
   der Mitte der ganzen Zeile: Kopfzeile und Marken gehoeren nicht zu dem, was
   das Bild zeigt. */
.entry .shot { grid-column: 2; align-self: center; height: 66px; border-radius: 8px; }
.entry h4 {
  margin: 8px 0 0; font-family: var(--display); font-size: 15.5px; font-weight: 700;
  color: var(--text-strong); line-height: 1.25; letter-spacing: -0.015em; text-wrap: pretty;
}
.entry:hover h4 { color: var(--primary); }
.entry p {
  margin: 7px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-muted); text-wrap: pretty;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
.entry p.hook { font-family: var(--read); font-size: 14.5px; line-height: 1.45; color: var(--text); }

/* Die Blaetterleiste steht im Gitter der Liste, ueber die ganze Breite: Der
   Knopf "Ältere Beiträge" wird beim Nachladen durch die neuen Zeilen samt
   neuer Leiste ersetzt, und dafuer muss er dort stehen, wo die Zeilen
   hingehoeren. */
.entries > .pager { grid-column: 1 / -1; border-top: 1px solid var(--border); padding-top: 14px; }
.chip.more { color: var(--text-strong); font-weight: 600; }
.chip.more:hover { border-color: var(--text-faint); }
/* Waehrend nachgeladen wird, ist der Knopf blass und stumm - zweimal
   druecken haenge sonst denselben Ausschnitt zweimal an. */
.chip.more.htmx-request { opacity: 0.5; pointer-events: none; }

/* --- Der Kalender am Fuss des Feeds ------------------------------------

   Er haengt an der Bandzeile ueber der Liste und legt sich beim Aufklappen
   darueber, statt die Seite auseinanderzuschieben: Wer einen Tag sucht, will
   die Liste sehen, gegen die er sucht.                                     */
.daypick-wrap { position: relative; }
.daypick-wrap > summary { list-style: none; cursor: pointer; }
.daypick-wrap > summary::-webkit-details-marker { display: none; }
.daypick-wrap[open] > summary { border-color: var(--text-faint); color: var(--text-strong); }
/* Am Schreibtisch trifft der Zeiger die 28 Pixel der Pille genau; der Daumen
   tut das nicht. In der Bandzeile stehen die Pillen deshalb auf dem Telefon
   hoeher - beide, denn "Alle Tage" steht neben dem Kalenderknopf, und zwei
   verschieden hohe Pillen nebeneinander lesen sich als Versehen. */
@media (max-width: 640px) {
  .older .band .chip { height: 36px; padding: 0 14px; font-size: 13px; }
}

.daypick {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 20; width: 264px;
  padding: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 18px 40px -18px rgba(11, 26, 42, 0.35), 0 1px 2px rgba(11, 26, 42, 0.05);
}
.daypick-head { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
.daypick-head strong {
  flex: 1; text-align: center; font-size: 13px; font-weight: 600; color: var(--text-strong);
}
.daypick-head .step {
  width: 26px; height: 26px; flex: 0 0 26px; display: inline-flex;
  align-items: center; justify-content: center; border: 1px solid var(--border);
  border-radius: 999px; background: var(--surface); color: var(--text-muted);
  font-size: 15px; line-height: 1;
}
.daypick-head .step:hover { background: var(--surface-hover); color: var(--text-strong); }
/* Kein Monat mehr in dieser Richtung: Das Zeichen bleibt stehen, damit die
   Zeile nicht springt, ist aber sichtlich kein Knopf. */
.daypick-head .step.off { color: var(--border); }

.cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dow {
  text-align: center; font-size: 10px; font-weight: 600; letter-spacing: 0.04em;
  color: var(--text-muted); padding-bottom: 4px;
}
.cal-day {
  position: relative; height: 30px; display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; color: var(--text-strong); cursor: pointer;
}
/* Die Tage vor dem Monatsersten halten den Platz, ohne etwas zu behaupten. */
.cal-day.filler { visibility: hidden; }
.cal-day > span {
  width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px;
}
.cal-day:hover > span { background: var(--surface-hover); }
/* Der Radiobutton traegt die Auswahl, sichtbar ist die Scheibe daneben: So
   waehlt die Tastatur mit den Pfeiltasten durch den Monat wie durch jede
   andere Gruppe - ein Gitter aus Links koennte das nicht. */
.cal-day input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.cal-day input:checked + span { background: var(--primary); color: #FFFFFF; font-weight: 600; }
.cal-day input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 2px; }
/* Heute bekommt eine Marke und keine Fuellung - gewaehlt ist etwas anderes. */
.cal-day.today > span { box-shadow: inset 0 0 0 1px var(--text-faint); }
/* Ein Tag ohne Meldung ist nicht anklickbar. Das steht nicht nur im
   disabled-Attribut, sondern muss man sehen: Sonst klickt man dreimal und
   haelt die App fuer kaputt. */
.cal-day.off { color: var(--text-faint); opacity: 0.4; cursor: not-allowed; }
.cal-day.off:hover > span { background: none; }

.daypick button { width: 100%; justify-content: center; margin-top: 12px; }
.chip.primary { background: var(--primary); border-color: var(--primary); color: #FFFFFF; font-weight: 600; }
.chip.primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); }

/* --- Was unter dem Zeiger liegt ----------------------------------------

   Bisher wechselte auf jeder Karte nur die Schlagzeile die Farbe. Das ist zu
   wenig Antwort fuer eine Karte, die als Ganzes ein Link ist: Wer auf das
   Foto zeigt, zeigt auf die Meldung und nicht auf die Zeile darueber - und
   bekam von der Stelle, auf die er zeigt, nichts zurueck.

   Zwei Antworten, je nachdem, was die Karte hat. Wo ein grosses Bild steht,
   holt es sich unter dem Zeiger etwas heran; der Ausschnitt bleibt stehen,
   nur der Inhalt waechst. Wo nur eine Vorschau von 88 Pixeln steht - in den
   Zeilen -, waere dieselbe Bewegung ein Zucken, und dort antwortet
   stattdessen die Flaeche der ganzen Zeile.

   Beides gilt fuer die Tastatur mit: Wer sich durch den Feed tabbt, soll an
   derselben Stelle dasselbe sehen. */
.hero .shot img, .card .shot img, .feature .shot img { transition: transform 0.45s ease-out; }
.hero:hover .shot img, .hero:focus-visible .shot img,
.card:hover .shot img, .card:focus-visible .shot img,
.feature:hover .shot img, .feature:focus-visible .shot img { transform: scale(1.045); }

/* Und die Schlagzeile bekommt eine Unterstreichung. Den Farbwechsel gab es
   schon, nur sah ihn niemand: Auf Papierton wechselte sie von --text-strong
   (#0B1A2A) nach --primary (#12283D), zwei Nuancen Schwarz. Die Linie ist auf
   jedem Grund zu sehen - auch auf dem dunklen Aufmacher - und sagt nebenbei,
   was der Farbwechsel nie gesagt hat: Hier geht es weiter. */
.hero:hover h2, .hero:focus-visible h2,
.card:hover h4, .card:focus-visible h4,
.brief:hover h4, .brief:focus-visible h4,
.feature:hover h4, .feature:focus-visible h4,
.entry:hover h4, .entry:focus-visible h4 {
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
}

/* Die Flaeche greift ueber den Text hinaus und holt sich denselben Weg als
   negativen Aussenabstand zurueck - so bekommt sie Luft, ohne dass die
   Schlagzeilen der Liste ihre Kante verlassen. */
.brief, .entry {
  padding-inline: 12px; margin-inline: -12px; border-radius: 10px;
  transition: background-color 0.16s ease;
}
.brief:hover, .brief:focus-visible,
.entry:hover, .entry:focus-visible { background: var(--surface-hover); }

/* Wer keine Bewegung will, bekommt trotzdem eine Antwort: die Flaeche der
   Zeilen bleibt, nur das Heranholen faellt weg. */
@media (prefers-reduced-motion: reduce) {
  .hero .shot img, .card .shot img, .feature .shot img { transition: none; }
  .hero:hover .shot img, .hero:focus-visible .shot img,
  .card:hover .shot img, .card:focus-visible .shot img,
  .feature:hover .shot img, .feature:focus-visible .shot img { transform: none; }
}

/* Was alle Karten des Feeds gemeinsam haben. */
.card .meta, .brief .meta, .feature .meta, .entry .meta {
  display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--text-muted);
  letter-spacing: 0.02em;
}
.brief .meta .src, .entry .meta .src { font-family: var(--mono); }
/* Die Zeitangabe steht auf jeder Karte an derselben rechten Kante. Sie
   beantwortet eine andere Frage als Quelle und Rubrik - "wie frisch ist das"
   statt "was ist das" - und bekommt dafuer eine eigene Spalte statt eines
   weiteren Trennpunkts in der Reihe. Wer den Feed ueberfliegt, liest sie
   dadurch als Spalte und nicht als Fund.

   Die Angabe bricht nicht um - "vor 3" über "Std." wäre keine Angabe mehr. */
.meta .when, .crumbs .when { white-space: nowrap; }
.meta .spacer { flex: 1; }
/* In der schmalsten Zeile - "Aelter", drei Spalten, daneben die Vorschau -
   passt nicht beides ungekuerzt. Gekuerzt wird die Quelle: "deutschlandfun…"
   sagt noch, woher es kommt, "vor 16 St…" sagt gar nichts mehr. Und die
   Vorschau liegt als positioniertes Element ueber dem Text - ohne diese
   Zeile verschwindet die Angabe unter ihr, statt nur eng zu stehen. */
.meta .when { flex: 0 0 auto; }
.meta .src { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.card .tags, .brief .tags, .entry .tags { display: flex; align-items: center; gap: 6px; margin-top: 11px; }

/* Zwei Rueckfaelle, damit aus dem Glas nie eine Lesehuerde wird.

   Ohne backdrop-filter (aeltere Browser) wird aus der Scheibe eine Platte:
   was nicht unscharf werden kann, muss decken, sonst steht Schrift auf
   Schrift. Und wer Transparenz abbestellt hat, hat sie abbestellt - dann
   deckt sie ebenfalls. */
/* Am Telefon steht auf den Feed-Bildern nur "Symbolbild · Lizenz" (UX
   feed-10). Der volle Nachweis steht im title und auf der Beitragsseite,
   auf die jede Karte fuehrt - warum das reicht, steht an
   VideoView.Picture.shortCredit. */
.hero-picture figcaption .kurz, .card figcaption .kurz, .feature .credit .kurz { display: none; }
@media (max-width: 640px) {
  .hero-picture figcaption .voll, .card figcaption .voll, .feature .credit .voll { display: none; }
  .hero-picture figcaption .kurz, .card figcaption .kurz, .feature .credit .kurz { display: inline; }
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .masthead { background: var(--surface); }
  .hero-picture figcaption, .card figcaption, .feature .credit { background: rgba(10, 23, 37, 0.72); }
  .feature .caption { background: rgba(10, 23, 37, 0.8); }
}
@media (prefers-reduced-transparency: reduce) {
  .masthead {
    background: var(--surface); backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .hero-picture figcaption, .card figcaption, .feature .credit {
    background: rgba(10, 23, 37, 0.82); backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .feature .caption {
    background: rgba(10, 23, 37, 0.88); backdrop-filter: none; -webkit-backdrop-filter: none;
  }
}

/* Unter 860px steht nichts mehr nebeneinander: die Textspalte des Aufmachers
   waere neben dem Bild zu schmal fuer die Koederfrage, und die Kachelspalte
   neben dem Bildfeld zu schmal fuer eine Schlagzeile. Das Bild wandert dabei
   nach oben - es ist der Grund, warum jemand haengenbleibt. */
@media (max-width: 860px) {
  .hero { grid-template-columns: minmax(0, 1fr); }
  .hero-picture { min-height: 0; aspect-ratio: 16 / 9; order: -1; }
  .split { grid-template-columns: minmax(0, 1fr); }
  .feature { min-height: 260px; }
}

.tag {
  height: 22px; display: inline-flex; align-items: center; gap: 5px; padding: 0 9px;
  border-radius: 999px; font-size: 11.5px; font-weight: 500; white-space: nowrap;
}
.tag-chunks { background: var(--accent-surface); color: var(--accent-text); }
.tag-audio { background: var(--info-surface); color: var(--info-text); }
.tag-ok { background: var(--neutral-surface); color: var(--neutral-text); }
.tag-ok .dot { width: 5px; height: 5px; border-radius: 999px; background: var(--text-faint); }


/* --- Der Blick auf eine Karte ---------------------------------------------
   Ein Kasten fuer alle Karten, position: fixed und von feed-peek.js hinter
   die Karte gehaengt, auf die gezeigt wird. Dieselbe Huelle wie das
   Chunk-Panel - Rand, Schatten, das Aufgehen -, nur schmaler: Eine
   Schlagzeile braucht keine 348 Pixel.

   Die eigene [hidden]-Regel, weil display gesetzt wird und die Regel des
   Browsers sonst unterliegt - wie ueberall im Haus.                         */
.cardtip {
  position: fixed; z-index: 9; width: 320px; max-width: calc(100vw - 24px);
  padding: 12px 14px 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 4px;
  box-shadow: 0 18px 40px -18px rgba(11, 26, 42, 0.25), 0 1px 2px rgba(11, 26, 42, 0.05);
  animation: popIn 150ms cubic-bezier(0.4, 0, 0.2, 1);
}
.cardtip[hidden] { display: none; }
/* Die Schlagzeile in der Grotesk, nicht in der Leseschrift: Sie ist die
   Uebersetzung und damit Erklaerung, nicht Lernmaterial. Auf Deutsch steht
   hier die Koederfrage - dieselbe, die auf der Karte in der Grotesk steht. */
.cardtip .headline {
  margin: 9px 0 0; font-size: 14.5px; line-height: 1.45; font-weight: 500;
  color: var(--text-strong); text-wrap: pretty;
}
.cardtip .headline[hidden] { display: none; }
.cardtip .teaser {
  margin: 10px 0 0; font-size: 13px; line-height: 1.5; color: var(--text);
  text-wrap: pretty; border-top: 1px dashed var(--border); padding-top: 9px;
}
.cardtip .teaser[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
  .cardtip { animation: none; }
}
/* --- Leseansicht --- */
/* Die Kruemelzeile bricht um statt zu schrumpfen: auf einem Telefon passt
   sie nicht in eine Zeile, und ohne nowrap trennte der Browser mitten im
   Namen des Feeds ("News-" / "Feed"). Umgebrochen wird zwischen den
   Kruemeln, nicht in ihnen.

   Ausgerichtet wird auf der Grundlinie und nicht auf der Mitte. In der Zeile
   stehen drei Schriften nebeneinander - die Leseschrift, die Schmalschrift
   der Quelle und der Text in den Pillen -, und ihre Zeilenhoehen sind
   verschieden. Zentriert man die Kaesten, sitzt jede Schrift ein Stueck
   woanders; auf der Grundlinie stehen alle auf derselben Linie, auch die in
   der Pille: Eine inline-flex-Schachtel gibt die Grundlinie ihrer ersten
   Zeile nach aussen weiter. */
.crumbs {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px;
  font-size: 12.5px; color: var(--text-muted);
}
.crumbs > * { white-space: nowrap; }
.crumbs .src { font-family: var(--mono); }
.headline {
  font-family: var(--display); font-size: clamp(30px, 3.4vw, 38px); font-weight: 700;
  letter-spacing: -0.03em; color: var(--text-strong);
  line-height: 1.14; margin: 20px 0 0; text-wrap: pretty;
}

/* --- Der Aufmacher der Leseansicht ----------------------------------------
   Bis hierher war die Leseansicht eine Textspalte auf weissem Grund: eine
   Kruemelzeile, eine Schlagzeile, vier Zeilen Lesetext. Was im Feed die Karte
   trug, blieb dabei liegen - der Artikel hat seine Bilder laengst, sie standen
   nur im Lese-Video.

   Seit das Lese-Video ein Modus dieser Seite ist, liegt der Abspielknopf im
   Bild. Der Aufmacher ist damit beides: das Bild, das im Feed auf der Karte
   stand, und die Schaltflaeche, die zum Hoeren fuehrt.

   Und er ist in beiden Modi dieselbe Flaeche - siehe --opener-ratio.        */
.opener { margin: 18px 0 0; }
/* Die figure und nicht der Rahmen traegt die Pflichtangabe: Sie liegt im Bild
   und damit ueber dem Abspielknopf, der den Rahmen ganz ausfuellt. Beide im
   selben Rahmen, und der Knopf mit seinem z-index deckte sie zu. */
.opener figure { margin: 0; position: relative; }
/* Die Bezugsflaeche fuer alles, was im Bild liegt - und nicht die figure:
   sonst zaehlte die Bildunterschrift zur Mitte, und der Knopf saesse zu tief. */
.opener .frame { position: relative; }
.opener .shot { border-radius: 16px; }

/* --- Ein Mass fuer beide Modi ---------------------------------------------
   Der Aufmacher beim Lesen und die Buehne beim Hoeren sind dieselbe Flaeche
   an derselben Stelle. Also muessen sie gleich hoch sein: Wer zwischen den
   Reitern wechselt, soll das Bild stehen sehen und nicht springen.

   Sie hatten verschiedene Masse, weil sie einmal verschiedene Seiten waren -
   der Aufmacher 16:7 wie die Feed-Karte, die Buehne 330px fest. Bei 1032px
   Spaltenbreite sind das 451px gegen 330px, und der Sprung war die ganze
   Hoehe der Reiterzeile.

   Das gemeinsame Mass ist das der Buehne, als Verhaeltnis statt als fester
   Zahl: So bleibt es auf jeder Fensterbreite dasselbe fuer beide. Die
   Mindesthoehe faengt schmale Fenster ab, wo 3:1 nur noch ein Streifen waere -
   sie gilt ebenfalls fuer beide, sonst liefen sie unten wieder auseinander.

   Und die Breite steht ausdruecklich da, obwohl sie die der Spalte ist: Ein
   Seitenverhaeltnis rechnet in beide Richtungen. Ohne feste Breite nimmt es
   auf dem Handy die Mindesthoehe und macht daraus 780 Pixel Breite - die
   Buehne sprengte die Spalte und mit ihr die ganze Seite. Mit ihr bestimmt
   das Verhaeltnis nur noch die Hoehe, und die Mindesthoehe hebt sie an.    */
:root { --opener-ratio: 3 / 1; --opener-min: 260px; }
.opener .shot,
.opener.is-plate .frame,
.stage {
  width: 100%; aspect-ratio: var(--opener-ratio); min-height: var(--opener-min);
}
/* Hinter einem Foto mit anderem Seitenverhaeltnis steht Tiefe statt Grau. */
.opener .shot:not(.is-blank) { background: var(--primary-dark); }

/* Die zweite Gestalt: kein Foto, sondern das Farbfeld des Artikels. Es steht
   im selben Seitenverhaeltnis, damit die Seite gleich aussieht, ob der
   Bilder-Worker den Artikel schon erreicht hat oder nicht - und es ist kein
   Platzhalter mehr, seit der Abspielknopf darauf liegt. */
.opener.is-plate { border-radius: 16px; overflow: hidden; }
/* Ohne Foto ein schmales Band statt einer 344px hohen Platte (UX leser-13):
   Die Platte wirkte wie ein Bild, das nicht laedt, und schob den Text nach
   unten. Das Band traegt Stufe, Laenge und den Abspielknopf. Wenn die
   Beitragsmedien eine Illustration bringen, steht wieder die volle Flaeche
   da - dann ist es ein Bild. */
.opener.is-plate .frame { aspect-ratio: auto; min-height: 0; height: 88px; }
.opener.is-plate .disc { width: 52px; height: 52px; }
.opener.is-plate .disc svg { width: 22px; height: 22px; }
.opener.is-plate .badges { top: 50%; transform: translateY(-50%); }

/* Der Abspielknopf - und er ist das ganze Bild.
 *
 * Der Link liegt ueber der ganzen Flaeche, die Scheibe steht in ihrer Mitte:
 * Getroffen werden muss nichts, angesehen wird alles. Sie ist die Anzeige des
 * Links und nicht seine Flaeche, deshalb traegt sie keine eigene Klickflaeche
 * und antwortet auf den Zeiger, der irgendwo im Bild steht.
 *
 * Milchglas statt einer vollen Flaeche: Die Scheibe liegt auf einem Foto, das
 * sie nicht zudecken soll, und auf einem Farbfeld, dessen Toene durchscheinen
 * duerfen. Auf beiden bleibt das weisse Dreieck lesbar. backdrop-filter ist
 * dabei eine Zugabe: Wo er fehlt, bleibt die halbdeckende Flaeche darunter
 * stehen und die Scheibe ist dieselbe, nur ohne Unschaerfe.               */
.playbutton {
  position: absolute; inset: 0; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  color: #FFFFFF;
}
.playbutton .disc {
  width: 72px; height: 72px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(21, 35, 58, 0.52);
  border: 1px solid rgba(255, 255, 255, 0.28);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  transition: background 160ms ease-out, transform 160ms ease-out;
}
.playbutton svg { margin-left: 4px; }
.playbutton:hover, .playbutton:focus-visible { color: #FFFFFF; }
.playbutton:hover .disc, .playbutton:focus-visible .disc {
  background: rgba(21, 35, 58, 0.72); transform: scale(1.12);
}
/* Ohne Zeiger gibt es keinen Hover - die Tastatur braucht trotzdem eine
   Antwort, und eine Scheibe, die nur ein Zehntel groesser wird, ist keine. */
.playbutton:focus-visible { outline: none; }
.playbutton:focus-visible .disc {
  outline: 2px solid #FFFFFF; outline-offset: 3px;
}
/* Und das Bild kommt mit heran - dieselbe Antwort wie auf den Karten des
   Feeds. Dort sagt sie "das hier ist ein Weg"; hier sagt sie dasselbe. */
.opener .shot img { transition: transform 0.45s ease-out; }
.opener:has(.playbutton:hover) .shot img,
.opener:has(.playbutton:focus-visible) .shot img { transform: scale(1.045); }
/* Die Pillen liegen ueber dem Link und duerfen ihn nicht abfangen. */
.opener .badges { pointer-events: none; }

/* Auf der Buehne ist dieselbe Flaeche der Play/Pause-Schalter. Ein Knopf und
   kein Link - hier wird nichts geoeffnet, sondern etwas angehalten. */
.playbutton { border: 0; padding: 0; background: none; cursor: pointer; }
.playbutton:disabled { cursor: not-allowed; }
.playbutton:disabled .disc { opacity: 0.4; }
.stage .icon-pause { display: none; }
.stage.is-playing .icon-play { display: none; }
.stage.is-playing .icon-pause { display: block; }
/* Waehrend der Ton laeuft, tritt die Scheibe zurueck: Ein Bedienelement, das
   die ganze Zeit ueber dem Bild steht, ist im Weg. Unter dem Zeiger ist es
   wieder da - und wer die Tastatur nimmt, holt es sich mit dem Fokus. */
.stage.is-playing .disc { opacity: 0; transition: opacity 320ms ease-out, background 160ms ease-out, transform 160ms ease-out; }
.stage.is-playing .playbutton:hover .disc,
.stage.is-playing .playbutton:focus-visible .disc { opacity: 1; }
/* Die Pflichtangabe fuehrt auf ihre Nachweise und muss deshalb ueber dem
   Schalter liegen - sonst faengt er den Klick auf den Lizenztext ab. Beim
   Lesen ist der Schalter ein Link ueber dem ganzen Bild, beim Hoeren ein
   Knopf ueber dem ganzen Bild; in beiden Faellen liegt er dazwischen. */
.stage .credit, .opener .credit { z-index: 3; }
@media (prefers-reduced-motion: reduce) {
  .playbutton:hover .disc, .playbutton:focus-visible .disc { transform: none; }
  .opener:has(.playbutton:hover) .shot img,
  .opener:has(.playbutton:focus-visible) .shot img { transform: none; }
}
/* Der Vorspann: die Koederfrage, die im Feed auf der Karte stand. In der
   Leseschrift, weil sie deutscher Satz ist - groesser als der Lesetext und in
   dessen Breite, damit sie als Frage steht und nicht als erster Absatz. */
.standfirst {
  margin: 14px 0 0;
  font-family: var(--read); font-size: 20px; line-height: 1.5;
  color: var(--text-muted); text-wrap: pretty;
}

/* --- Lesen oder hoeren ----------------------------------------------------
   Die beiden Modi des Artikels. Links und keine Knoepfe: der Modus steht in
   der Adresse, also ist der Wechsel ein Seitenwechsel - er funktioniert ohne
   JavaScript, laesst sich weitergeben, und die Zurueck-Taste tut, was sie
   soll. Dieselbe Pillenspur wie der Niveau-Umschalter, weil beides dasselbe
   ist: eine Wahl zwischen wenigen festen Moeglichkeiten.                     */
.modes { display: flex; align-items: center; gap: 14px; margin: 20px 0 0; }
.modes .tabs { display: flex; gap: 4px; padding: 3px; background: var(--pill-track); border-radius: 10px; }
.modes .tabs a {
  height: 30px; display: inline-flex; align-items: center; padding: 0 14px;
  border-radius: 8px; font-size: 13px; color: var(--text-muted);
}
.modes .tabs a:hover { color: var(--text-strong); }
.modes .tabs a[aria-current='true'] { background: var(--primary); color: #FFFFFF; font-weight: 600; }

/* Die zweite klebende Leiste der Leseansicht. Sie haelt an der Unterkante der
   Kopfzeile an statt bei 0 - sonst schoebe sie sich unter sie und das Niveau
   waere beim Lesen genau dann verdeckt, wenn man es braucht. Deckend und
   nicht als Glas: zwei Scheiben uebereinander zeigen den Text doppelt
   verwaschen durch. */
.levelbar {
  display: flex; align-items: center; gap: 12px; margin: 24px 0 0; padding: 12px 0;
  border: 0; border-bottom: 1px solid var(--border); background: var(--surface);
  position: sticky; top: var(--masthead-h); z-index: 2;
}
.levelbar .label {
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 600; color: var(--text-muted);
}
.levelbar .words { font-size: 11.5px; color: var(--text-muted); font-family: var(--mono); }

/* Beim Lesen ist die Seite weiss, und die Leiste steht deshalb ohne sichtbaren
   Grund im Text - man sieht die Stufen, nicht das Feld darunter. Im Lese-Video
   ist der Seitengrund grau, und dieselbe weisse Flaeche wurde dort zum Band
   zwischen Buehne und Transkript.

   Sie behaelt einen Grund, weil sie klebt und der Text unter ihr durchlaeuft -
   nur nimmt sie den der Seite. Das ist derselbe Fall wie beim Lesen: die
   Leiste deckt, ohne sich zu zeigen.                                        */
#article-view.listening .levelbar { background: var(--bg); }

/* Auf dem Telefon passt die Leiste nicht in eine Zeile: Beschriftung, fuenf
   Stufen, der Umschalter, das Hinweiszeichen und die Wortzahl sind zusammen
   breiter als der Schirm. Sie stand ueber den Rand hinaus - und weil das eine
   Seite seitlich schiebbar macht, wanderte beim Lesen auch der Lesetext.

   Sie bricht deshalb um: oben die Stufen, darunter, was ueber den Text sagt.
   Und sie klebt dort nicht mehr. Zwei klebende Leisten uebereinander, die
   zweite davon zweizeilig, naehmen einem Telefon ein Fuenftel der Schirmhoehe
   - und das ist genau der Platz, um den es beim Lesen geht. Die Stufen sind
   einen Wisch nach oben wieder da. */
@media (max-width: 560px) {
  /* top: auto muss mit. Die Regel oben setzt top: var(--masthead-h) fuer das
     Kleben; bleibt der Wert stehen, schiebt position: relative die Leiste um
     genau diese 64px nach unten, ohne dass ihr Platz im Fluss mitwandert.
     Unter dem Reiterband klaffte dadurch eine leere Zeile, und die verrutschte
     Leiste deckte mit ihrem Grund die ersten Zeilen des Lesetextes zu. */
  .levelbar { position: relative; top: auto; flex-wrap: wrap; gap: 8px 12px; }
  /* Der Hinweis haengt am Zeichen und waechst von dort nach links. In der
     umgebrochenen Leiste steht das Zeichen nicht mehr am rechten Rand,
     sondern in der Mitte - und die Box lief ueber die linke Kante hinaus.
     Hier haengt sie deshalb an der Leiste selbst und steht unter ihr, so
     breit wie die Textspalte. */
  .levelbar .tip { position: static; }
  .levelbar .tipbox { left: 0; right: 0; width: auto; max-width: none; }
}

.hint {
  font-size: 12.5px; color: var(--text-muted); margin: 14px 0 18px;
  display: flex; align-items: center; gap: 7px;
}

/* --- Hinweise am Bedienelement --------------------------------------------
   Drei Zeilen standen einmal fest im Lesefluss und erklaerten, was die
   Reiter, die Markierungen und der Abfrageknopf tun. Beim ersten Artikel ist
   das die Antwort auf eine offene Frage; beim zwanzigsten ist es Text, den
   man ueberliest - und der den Lesetext um drei Zeilen nach unten schiebt.

   Jetzt haengt jeder Hinweis an dem Bedienelement, das er erklaert, und
   kommt, wenn man darauf zeigt. Ohne JavaScript: Die Box liegt als
   Geschwister im .tip und wird bei :hover und bei :focus-within sichtbar -
   letzteres ist der Weg der Tastatur und zugleich der des Fingers, denn ein
   Tipp auf ein fokussierbares Element oeffnet sie ebenso.

   Verborgen wird mit opacity und nicht mit visibility oder display: So
   bleibt die Box im Baum, den der Screenreader liest, und das
   aria-describedby am Anker findet sie auch im unsichtbaren Zustand.      */
.tip { position: relative; display: inline-flex; align-items: center; }

/* Ein Anker, dessen Bedienelement noch gar nicht dasteht, hat nichts zu
   erklaeren: Der Abfrageknopf bleibt verborgen, bis chunk-review.js ihn
   freigibt, und der Hinweis darf nicht frueher aufgehen als er. */
.tip:has(> [hidden]) { display: none; }

.tipbox {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 7;
  width: max-content; max-width: 34ch;
  padding: 9px 12px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--surface);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.10);
  /* Die Anker stehen in Leisten aus Versalien und Sperrung. Der Hinweis ist
     ein Satz und erbt davon nichts. */
  font-size: 12.5px; line-height: 1.45; font-weight: 400;
  letter-spacing: 0; text-transform: none; text-align: left;
  color: var(--text-muted); text-wrap: pretty;
  opacity: 0; pointer-events: none; transition: opacity 120ms ease;
}
.tip:hover > .tipbox, .tip:focus-within > .tipbox { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .tipbox { transition: none; } }

/* Am rechten Rand einer Leiste waechst die Box nach links - sonst stuende
   sie ueber der Kante. */
.tipbox.is-right { left: auto; right: 0; }

/* Das Fragezeichen in der Niveauleiste. Ein Knopf und kein Zeichen im Text,
   weil es den Fokus annehmen koennen muss: nur so kommt der Hinweis auch bei
   dem an, der nicht mit der Maus zeigt. Es steht immer da, auch wo der
   Ebenenumschalter fehlt - die zwei Klickstufen der Markierungen gelten auch
   fuer Artikel, die der Nachlauf noch nicht erreicht hat. */
.tipmark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; padding: 0;
  border: 0; border-radius: 999px; background: none;
  color: var(--text-muted); cursor: help;
}
.tipmark:hover, .tipmark:focus-visible { color: var(--text-strong); }

/* Die Quellenzeile ueber den Karten des Vietnam-Feeds. Sie stand einmal unter
   dem Einleitungssatz und wurde mit einem negativen Rand an ihn herangezogen;
   seit der Satz weg ist, folgt sie den Rubriken und haelt deren Abstand. */
.sources {
  font-family: var(--mono); font-size: 11.5px; color: var(--text-muted);
  margin: 14px 0 18px;
}

.prose {
  border: 0; border-radius: 0; background: none;
  padding: 30px 0 34px;
}
/* pre-wrap: die Fassungen sind in Absaetze gegliedert, getrennt durch eine
   Leerzeile. Das Template haengt die Abschnitte bewusst ohne Zeilenumbruch
   aneinander, deshalb zeigt pre-wrap genau die Umbrueche, die im Text stehen. */
.prose .body {
  font-family: var(--read); font-size: 20px; line-height: 1.7;
  color: var(--text-strong); white-space: pre-wrap;
  /* Rund 70 Zeichen je Zeile (UX-Befund leser-2): Ueber die volle Breite von
     1032px waren es 120, und man fand den naechsten Zeilenanfang schwer.
     Bild, Leisten und Raster bleiben breit - nur der Lesetext wird schmal. */
  max-width: 34em;
}
.prose .rule { height: 1px; background: var(--border); margin: 26px 0 18px; }
.prose .footer { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.prose .footer .model { font-size: 11.5px; color: var(--text-muted); font-family: var(--mono); }
.prose .footer .spacer { flex: 1; }
/* Auf dem Telefon passen die Etiketten und der Link nicht in eine Zeile: Der
   Link faellt in die zweite - und dort steht der Fueller nicht mehr vor ihm,
   sondern eine Zeile hoeher. Er ruecke also nach links, obwohl er die rechte
   Ecke der Zeile ist. margin-left: auto schiebt ihn dorthin zurueck, wo er in
   der ungebrochenen Zeile stuende.

   Und weil die Fusszeile nun zwei Zeilen hoch ist, kommt der Abstand zur
   Wortgruppen-Liste schon von ihr: Die Trennlinie rueckt naeher heran, und
   die Ueberschrift der Liste braucht keine 30px mehr. */
@media (max-width: 560px) {
  .prose { padding-bottom: 20px; }
  .prose .rule { margin: 20px 0 14px; }
  .prose .footer { row-gap: 6px; }
  .prose .footer > a { margin-left: auto; }
}

/* Smart Chunks: eine Unterstreichung in der Lernfarbe, keine Flaeche.
   Ein Satz soll wie ein Satz aussehen und nicht wie ein Textmarker-Feld -
   markiert wird mit dem Mittel, das die Typografie dafuer hat. Die Flaeche
   kommt erst beim Ueberfahren dazu, als Antwort auf den Zeiger.

   text-decoration statt box-shadow: eine Wortgruppe, die ueber den
   Zeilenumbruch geht, bekommt so auf beiden Zeilen ihren Strich.            */
.chunk {
  background: none; border-radius: 0; padding: 0; box-shadow: none;
  text-decoration: underline; text-decoration-color: var(--accent);
  text-decoration-thickness: 2px; text-underline-offset: 4px;
  cursor: pointer;
}
.chunk:hover, .chunk:focus-visible { background: var(--accent-surface); outline: none; }

/* Die dichte Ebene: jede Sinneinheit markiert. Dieselbe Flaeche wie bei den
   Wortgruppen waere hier eine durchgehend eingefaerbte Seite - deshalb nur
   eine feine Linie unter dem Wort und eine Luecke dazwischen, damit man
   sieht, wo eine Einheit endet und die naechste beginnt. Erst beim
   Ueberfahren wird daraus dieselbe Flaeche wie oben.                        */
.chunk.unit {
  background: none; box-shadow: none;
  text-decoration: underline dotted var(--text-faint);
  text-decoration-thickness: 1px; text-underline-offset: 4px;
}
.chunk.unit:hover, .chunk.unit:focus-visible {
  background: var(--accent-surface);
  text-decoration: underline solid var(--accent); text-decoration-thickness: 2px;
}

/* Leiser (UX-Befund leser-3, 16.10.2026): Fast jedes Wort grau gepunktet,
   dazu nach jedem Satz ein buntes Zeichen - der Text sah aus wie ein
   Formular. Die Punktlinie erscheint jetzt erst im Satz, auf den man zeigt
   oder in dem der Fokus steht; antippen laesst sich jedes Wort weiterhin.
   Was immer zu sehen bleibt, sind die Lern-Wortgruppen (is-lern, gesetzt von
   word-layer.js) - mit demselben gruenen Strich wie in "Nur Wortgruppen". */
.chunk.unit { text-decoration-color: transparent; }
.sent:hover .chunk.unit, .sent:focus-within .chunk.unit, .sent.is-translating .chunk.unit,
.lines .line:hover .chunk.unit, .lines .line:focus-within .chunk.unit {
  text-decoration-color: var(--text-faint);
}
.chunk.unit.is-lern,
.sent:hover .chunk.unit.is-lern, .sent:focus-within .chunk.unit.is-lern,
.lines .line:hover .chunk.unit.is-lern, .lines .line:focus-within .chunk.unit.is-lern {
  text-decoration: underline solid var(--accent); text-decoration-thickness: 2px;
}

/* Der Umschalter zwischen den Ebenen. Kein Knopf im Vordergrund: er steht in
   der Levelbar neben der Wortzahl und soll nicht mit den Niveaustufen
   konkurrieren, die dort die eigentliche Wahl sind.                         */
.layertoggle {
  border: 1px solid var(--border); background: var(--surface); border-radius: 999px;
  padding: 5px 11px; font: inherit; font-size: 11.5px; color: var(--text-muted);
  cursor: pointer; white-space: nowrap;
}
.layertoggle:hover { color: var(--text-strong); border-color: var(--text-faint); }
.layertoggle[aria-pressed='true'] {
  background: var(--accent-surface); border-color: var(--accent); color: var(--accent-text);
}
.layertoggle[hidden] { display: none; }

/* Was schon im Tresor liegt (tresor-merken.js, UX leser-14): ein kleiner
   Punkt hinter der Stelle, in der Farbe des Tresors. Zart, weil er den
   Lesefluss nicht stoeren soll - er beantwortet nur "hab ich das schon?". */
.chunk.im-tresor::after {
  content: ''; display: inline-block; width: 5px; height: 5px; margin: 0 1px 0 2px;
  border-radius: 999px; background: var(--primary); opacity: 0.55; vertical-align: 0.55em;
}

/* Der Ebenenschalter als Segment: beide Namen stehen da, der gewaehlte ist
   gruen hinterlegt. aria-pressed sagt dasselbe fuer Vorleseprogramme -
   gedrueckt heisst "Jedes Wort". */
.layertoggle.ebenen,
.layertoggle.ebenen[aria-pressed='true'] {
  display: inline-flex; gap: 2px; padding: 2px; background: var(--pill-track);
  border-color: var(--border); color: var(--text-muted);
}
.layertoggle.ebenen[hidden] { display: none; }
.layertoggle.ebenen .seg { padding: 3px 9px; border-radius: 999px; }
.layertoggle.ebenen[aria-pressed='true'] .seg[data-seg='units'],
.layertoggle.ebenen[aria-pressed='false'] .seg[data-seg='chunks'] {
  background: var(--accent-surface); color: var(--accent-text); font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--accent);
}


/* Der Schieber (schieber.js): Die Farbe des gewaehlten Knopfes gleitet zum
   naechsten, statt zu springen. Er liegt hinter den Knoepfen - isolation haelt
   ihn ueber dem Hintergrund des Schalters -, und deren eigene Flaeche faellt
   weg, sobald er steht. Wer weniger Bewegung eingestellt hat, bekommt den
   Sprung wie bisher. */
.hat-daumen { position: relative; isolation: isolate; }
.daumen {
  position: absolute; left: 0; top: 0; z-index: -1; pointer-events: none;
  transition: transform 0.28s cubic-bezier(0.3, 0.7, 0.2, 1), width 0.28s cubic-bezier(0.3, 0.7, 0.2, 1);
}
.daumen.ohne-zug { transition: none; }
@media (prefers-reduced-motion: reduce) { .daumen { transition: none; } }

.layertoggle.ebenen .daumen {
  border-radius: 999px; background: var(--accent-surface); box-shadow: inset 0 0 0 1px var(--accent);
}
.layertoggle.ebenen.hat-daumen[aria-pressed] .seg[data-seg] { background: none; box-shadow: none; }
.langpick .daumen, .chunkpop .langs .daumen {
  border-radius: 8px; background: var(--surface); box-shadow: 0 1px 2px rgba(11, 26, 42, 0.08);
}
.langpick.hat-daumen button[aria-current='true'],
.chunkpop .langs.hat-daumen button[aria-current='true'] { background: none; }
.levels .daumen { border-radius: 8px; background: var(--primary); }
.levels.hat-daumen a[aria-current='true'],
.levels.hat-daumen button[aria-current='true'] { background: none; }
/* Die Stufe faehrt beim Tippen los, die Antwort des Servers kommt spaeter -
   bis dahin tauschen die beiden Knoepfe schon die Schriftfarbe. */
.levels .wird-aktiv { color: #FFFFFF; }
.levels button.war-aktiv[aria-current='true'] { color: var(--text-muted); font-weight: 500; }

/* --- Der Uebersetzungsknopf am Satzende -----------------------------------
   Er steht hinter dem letzten Zeichen des Satzes, nicht davor und nicht in
   einer Spalte daneben: Wer ihn sucht, hat den Satz gelesen.

   Er haelt seinen Platz immer frei und wird beim Zeigen nur heller. Ein Knopf,
   der erst beim Zeigen erscheint, schoebe die Zeile um, waehrend man sie
   liest - derselbe Grund, aus dem die Hinweisboxen mit opacity arbeiten und
   nicht mit display.

   Grau und nicht in der Lernfarbe. Gruen markiert, was man mitnehmen kann;
   dieser Knopf ist Bedienung. An jedem Satzende ein gruenes Zeichen waere
   ausserdem eine gruene Seite, und die Wortgruppen darin verschwaenden.

   Ohne JavaScript steht er auf hidden und faellt weg - ein Knopf, der nichts
   tut, ist schlimmer als keiner.                                            */
.sent { }
/* Der Satz, dessen Uebertragung gerade unter ihm steht: dieselbe Flaeche wie
   die aktive Wortgruppe, damit klar ist, wovon das Panel spricht. clone,
   damit ein Satz ueber zwei Zeilen an beiden Enden gerundet ist. */
.sent.is-translating {
  background: var(--accent-surface); border-radius: 3px;
  padding: 1px 0; box-decoration-break: clone; -webkit-box-decoration-break: clone;
}
/* Der ganze Satz springt beim Antippen dorthin (video.js) - das sagt der Zeiger. */
.lines .line:not(.is-static) .text { cursor: pointer; }
.lines .line.is-translating .text { background: var(--accent-surface); border-radius: 6px; }
.transmark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; padding: 0; margin-left: 3px;
  vertical-align: -3px; border: 0; border-radius: 999px;
  background: transparent; color: var(--text-strong); cursor: pointer;
  opacity: 1;
  /* Der Zeiger laesst das Zeichen aufgehen. transform und nicht width: Eine
     Groessenaenderung im Fliesstext schoebe die Zeile, die Skalierung liegt
     ueber dem Satz und ruehrt ihn nicht an. Die Kurve laeuft weich aus -
     schnell am Anfang, langsam am Ende. */
  transform: scale(1);
  transform-origin: center;
  transition: transform 160ms cubic-bezier(0.2, 0.7, 0.3, 1),
              background-color 120ms ease, color 120ms ease;
}

/* Welche Fahne zu sehen ist, entscheidet data-lang am <html>, das
   lang-pick.js schreibt. Alle drei liegen im Markup (siehe
   fragments/speech-mark.html); hier faellt die Wahl - dadurch wechseln alle
   Zeichen einer Seite mit, sobald oben umgeschaltet wird, ohne eine Zeile
   JavaScript und ohne einen Serverbesuch.

   Ohne Attribut steht Deutsch da: So sieht die Seite aus, bis lang-pick.js
   gelaufen ist. */
.flag-vi, .flag-en { display: none; }
html[data-lang="vi"] .flag-de { display: none; }
html[data-lang="vi"] .flag-vi { display: block; }
html[data-lang="en"] .flag-de { display: none; }
html[data-lang="en"] .flag-en { display: block; }
/* Dasselbe fuer die Uebersetzungen in "In diesem Text" und auf dem
   Lernzettel: Englisch ist die Vorgabe, mit VI steht Vietnamesisch da. */
.tr-vi { display: none; }
html[data-lang="vi"] .tr-en { display: none; }
html[data-lang="vi"] .tr-vi { display: inline; }
/* Das Zeichen am Satzende tritt zurueck, bis man den Satz meint: halb
   durchsichtig und ohne Farbe, voll erst im Satz unter dem Zeiger, mit
   Fokus oder waehrend seine Uebersetzung offen ist (leser-3). */
.transmark { opacity: 0.5; filter: grayscale(1); }
.sent:hover .transmark, .transmark:focus-visible, .sent.is-translating .transmark {
  opacity: 1; filter: none;
}
.transmark[hidden] { display: none; }
.transmark:hover,
.transmark:focus-visible { background: var(--pill-track); transform: scale(1.35); }

/* Im Transkript sitzt er am anderen Ende der Zeile als der Abspielknopf und
   ist deshalb kein Zeichen im Fliesstext, sondern ein Feld wie .cue. */
.lines .transmark {
  flex: 0 0 26px; width: 26px; height: 26px; margin: 1px 0 0; opacity: 1;
}
.lines .line.is-spoken .transmark { color: rgba(255, 255, 255, 0.85); }
.lines .line.is-spoken .transmark:hover,
.lines .line.is-spoken .transmark:focus-visible {
  background: rgba(255, 255, 255, 0.16); color: #FFFFFF;
}

/* Wer Bewegung abbestellt hat, bekommt den Zuwachs ohne den Weg dorthin -
   das Zeichen springt auf seine Groesse, statt zu wachsen. */
@media (prefers-reduced-motion: reduce) {
  .transmark { transition: none; }
}
.section-label {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 600; color: var(--text-muted); margin: 30px 0 12px;
}
.section-label .spacer { flex: 1; }
/* Siehe die Fusszeile des Lesetextes: Sie ist auf dem Telefon zweizeilig und
   bringt den Abstand schon mit. */
@media (max-width: 560px) {
  .section-label { margin-top: 18px; }
}

/* --- Die Liste "In diesem Text" -------------------------------------------
   Ein Raster statt einer umbrechenden Reihe: Die Eintraege sind jetzt
   Schaltflaechen, und Schaltflaechen von acht verschiedenen Breiten in drei
   Zeilen sind kein Ziel, sondern ein Suchbild. Gleich breite Karten geben der
   Liste eine Kante - und der Uebersetzung ihren festen Platz, an dem im
   Abfragemodus die Luecke steht.                                            */
.chunklist {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 8px;
}
.chunklist .item {
  display: grid; gap: 3px; padding: 10px 13px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  font: inherit; font-size: 13px; color: var(--text-strong); text-align: left;
}
/* Erst wenn das Skript sie uebernommen hat, sehen sie auch bedienbar aus. */
.chunklist.is-live .item { cursor: pointer; }
.chunklist.is-live .item:hover, .chunklist.is-live .item:focus-visible {
  background: var(--surface-hover); border-color: var(--text-faint); outline: none;
}
.chunklist.is-live .item:focus-visible { border-color: var(--primary); }
/* Die Wortgruppe selbst ist deutscher Text und traegt deshalb die Leseschrift,
   die Angaben daneben nicht. */
.chunklist .item .phrase { font-family: var(--read); font-size: 16px; line-height: 1.3; }
.chunklist .item .type {
  font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted);
}
/* Die Karte traegt die Farbe ihrer Stufe - dieselben Toene wie die Etiketten
   der Wortfamilie, damit dieselbe Stufe im ganzen Reader denselben Ton hat.

   Die Liste steht nach Stufe sortiert und laeuft von links nach rechts: Wer
   sie ueberfliegt, sieht die Steigung, bevor er ein Wort gelesen hat. Ohne
   Stufe bleibt die Karte grau - unbekannt ist nicht leicht. */
.chunklist .item.level-a1 { background: #E4EFE3; border-color: #A9C6AC; }
.chunklist .item.level-a2 { background: #DCEDEC; border-color: #9CC3C0; }
.chunklist .item.level-b1 { background: #DCE6F3; border-color: #A3B7D3; }
.chunklist .item.level-b2 { background: #EAE4F3; border-color: #B7A9CE; }
.chunklist .item.level-c1 { background: #F6E3E6; border-color: #D6AAB3; }
.chunklist .item.level-unbekannt { background: #EEF1F4; border-color: #C3CCD6; }
/* Der Zeigerzustand bleibt sichtbar, ohne die Stufe zu ueberdecken: nicht die
   Flaeche wechselt, sondern die Kante. */
.chunklist.is-live .item:hover, .chunklist.is-live .item:focus-visible {
  background: inherit; border-color: var(--text-faint);
}

/* Die Stufe sitzt am rechten Rand derselben Zeile wie das Muster: Sie ist die
   Angabe, nach der man die Liste ueberfliegt, und am Rand liegen alle Stufen
   untereinander statt hinter verschieden langen Musternamen. */
.chunklist .item .type { grid-row: 2; grid-column: 1; }
.chunklist .item .step {
  grid-row: 2; grid-column: 2; justify-self: end;
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-muted);
  cursor: help;
}
.chunklist .item { grid-template-columns: 1fr auto; }
.chunklist .item .phrase { grid-row: 1; grid-column: 1 / -1; }
.chunklist .item .translation { grid-row: 3; grid-column: 1 / -1; }
.chunklist .item .translation { font-size: 12px; color: var(--text-muted); }

/* Abfragemodus: Die Uebersetzung bleibt stehen, wo sie steht, und wird
   zugedeckt. Ausgeblendet wuerde sie die Karte kuerzer machen, und eine
   Liste, die beim Aufdecken springt, verliert genau die Stelle, auf die man
   gerade zeigt. */
.chunklist.is-quiz .item:not(.is-revealed) .translation {
  color: transparent; background: var(--pill-track); border-radius: 4px;
}
.chunklist.is-quiz .item:not(.is-revealed) .translation::selection { background: var(--pill-track); }

/* --- Vertiefung: aehnliche Artikel unter dem Lesetext ---------------------
   Die Grundlage steht neben der Ueberschrift, weil "nach Bedeutung" und
   "ueber gemeinsame Wortgruppen" zwei verschiedene Versprechen sind.        */

.section-label .basis {
  margin-left: 8px; text-transform: none; letter-spacing: 0;
  font-weight: 400; color: var(--text-muted);
}
.relations { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; }
.relation {
  display: block; border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface); padding: 0; overflow: hidden; color: inherit;
  transition: transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease;
}
/* Dieselbe Antwort wie im Feed: Die Karte unter dem Zeiger waechst.
   Dieselben sechs Prozent und dieselbe Dauer wie bei der Kachel in "Neu
   heute" - zwei Seiten, die dieselbe Karte zeigen, sollen sich unter dem
   Zeiger nicht verschieden anfuehlen.

   Der Ursprung liegt in der Mitte und nicht oben: Diese drei stehen in einer
   Zeile ohne Rasterpunkte, und keine von ihnen ist "die vordere". Der
   Schatten kommt dazu, weil die Karte hier auf Weiss steht und nicht in einer
   abgeblendeten Reihe - ohne ihn waere das Wachsen die einzige Antwort und
   liefe ins Leere. */
.relation:hover, .relation:focus-visible {
  background: var(--surface-hover); color: inherit;
  transform: scale(1.06);
  border-color: var(--text-faint);
  box-shadow: 0 10px 24px rgba(11, 26, 42, 0.10);
}
/* Das Foto holt sich zusaetzlich etwas heran - genau wie auf den Kacheln des
   Feeds. */
.relation .shot img { transition: transform 0.45s ease-out; }
.relation:hover .shot img, .relation:focus-visible .shot img { transform: scale(1.045); }
.relation:hover .title, .relation:focus-visible .title {
  text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 3px;
}

/* Wer keine Bewegung will, behaelt Flaeche, Rand und Linie - nur das Wachsen
   faellt weg. Dieselbe Teilung wie im Feed. */
@media (prefers-reduced-motion: reduce) {
  .relation { transition: box-shadow 0.22s ease, border-color 0.22s ease; }
  .relation:hover, .relation:focus-visible { transform: none; }
  .relation .shot img { transition: none; }
  .relation:hover .shot img, .relation:focus-visible .shot img { transform: none; }
}
/* Bild oben, Text darunter - dieselbe Kachel wie in "Neu heute". Die Hoehe
   ist gesetzt und nicht aus dem Foto gerechnet: drei Vorschlaege sollen eine
   Reihe ergeben, auch wenn ihre Bilder drei Formate haben. */
.relation .shot { height: 124px; }
.relation .body { padding: 12px 14px 15px; }
.relation .meta { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--text-muted); }
.relation .meta .src { font-family: var(--mono); }
.relation .title {
  margin-top: 7px; font-family: var(--display); font-size: 14px; font-weight: 700;
  color: var(--text-strong); line-height: 1.3; letter-spacing: -0.01em; text-wrap: pretty;
}
.relation p { margin: 6px 0 0; font-size: 12px; line-height: 1.5; color: var(--text-muted); text-wrap: pretty; }

/* Der zweite Weg aus dem Artikel heraus: dieselbe
   Karte, nur leise. Dunkel und hell nebeneinander waeren zwei Angebote
   gleichen Ranges; das Video ist das naheliegendere, das Netz das fuer den,
   der es sucht. Als graue Zeile unter drei Karten mit Bild war es gar
   keins - es stand da und wurde nicht gesehen. */
.netlink {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
  gap: 14px; margin-top: 10px; padding: 15px 18px;
  border: 1px solid var(--border); border-radius: 16px; background: var(--surface);
  color: inherit;
}
.netlink:hover { background: var(--surface-hover); border-color: var(--text-faint); color: inherit; }
.netlink .glyph {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 10px;
  background: var(--pill-track); color: var(--primary);
}
.netlink .title {
  display: block; font-family: var(--display); font-size: 15px; font-weight: 700;
  letter-spacing: -0.015em; color: var(--text-strong);
}
.netlink .lead { display: block; margin-top: 2px; font-size: 12.5px; color: var(--text-muted); }
.netlink .arrow { color: var(--text-faint); font-size: 15px; }
.netlink:hover .arrow { color: var(--primary); }

/* --- Blaetterleiste & Leerzustand --- */
.pager { display: flex; align-items: center; gap: 12px; margin-top: 28px; font-size: 12.5px; color: var(--text-muted); }
.empty {
  border: 1px dashed var(--border); border-radius: 4px; padding: 40px 24px;
  text-align: center; color: var(--text-muted); background: var(--surface);
}

/* Waehrend HTMX nachlaedt, den Text leicht abblenden. */
.htmx-request .body { opacity: 0.45; transition: opacity 120ms ease; }

/* ---------------------------------------------------------------- Lese-Video */

/* Dieselbe Flaeche wie der Aufmacher beim Lesen - gleicher Radius, gleiche
   Kante, gleiche Stelle auf der Seite. Der Wechsel zwischen den Modi soll
   kein Sprung sein, sondern ein Wechsel des Innenlebens. Die Hoehe steht
   deshalb bei beiden - siehe "Ein Mass fuer beide Modi".                    */
.stage {
  position: relative; border: 1px solid var(--border); border-radius: 16px;
  overflow: hidden; background: var(--pill-track);
  /* Zwei Dinge stehen im Fluss und stapeln sich am unteren Rand: der
     Untertitel und darunter die Transportleiste. Alles andere - Bildwelt,
     Schleier, Abspielknopf, Pillen, Bildunterschrift - liegt absolut darueber
     oder darunter und zaehlt hier nicht mit. */
  display: flex; flex-direction: column; justify-content: flex-end;
}

/* --- Die Bildwelt der Buehne ----------------------------------------------
   Es gibt keine Fotos zu diesen Artikeln, und es soll auch keine erfundenen
   geben: ein generiertes Bild zu einer echten Meldung behauptet etwas, das
   nicht stimmt. Was die Buehne stattdessen zeigt, ist ein Farbfeld, das aus
   dem Artikel selbst kommt - Rubrik gibt den Farbraum, die Tonspur gibt den
   Takt. Es tut nicht so, als waere es ein Bild vom Ereignis.

   Die Szenen wechseln an den Grenzen der Sinnabschnitte, nicht nach einem
   Timer: ihre Zeiten stehen in denselben Untertiteln, aus denen auch das
   Karaoke-Highlighting kommt. Bewegung, die neben dem Ton herlaeuft, waere
   Zierat; Bewegung, die mit ihm endet, ist Teil des Stuecks.               */

.backdrop { position: absolute; inset: 0; overflow: hidden; background: var(--scene-b); }

/* Ein Farbraum je Rubrik. Tief und entsaettigt, weil darueber ein Schleier
   und weisse Schrift liegen - helle Toene liessen den Untertitel absaufen. */
/* Nicht mehr nur die Buehne: dieselben Toene fuellen im Feed die Flaeche
   einer Karte, zu der es kein Foto gibt. Die Rubrik waehlt also einmal, und
   der Artikel sieht in Uebersicht und Video gleich aus. Deshalb haengen die
   Werte am Attribut und nicht mehr an .stage. */
.stage, .shot { --scene-a: #24384F; --scene-b: #0A1725; --scene-c: #4A6280; }
[data-category='Gesellschaft'] { --scene-a: #3E4E6B; --scene-b: #1B2A4A; --scene-c: #6D7FA0; }
[data-category='Kultur']       { --scene-a: #5A3350; --scene-b: #2A1B33; --scene-c: #8A5A7E; }
[data-category='Alltag']       { --scene-a: #2F5147; --scene-b: #122E2E; --scene-c: #4F7F70; }
[data-category='Politik']      { --scene-a: #57282C; --scene-b: #231A1C; --scene-c: #8A4A4E; }
[data-category='Wirtschaft']   { --scene-a: #2E5364; --scene-b: #0F2833; --scene-c: #4E8296; }
[data-category='Bildung']      { --scene-a: #4E5326; --scene-b: #22270F; --scene-c: #7C8244; }
[data-category='Umwelt']       { --scene-a: #2A5044; --scene-b: #12291D; --scene-c: #4A8068; }
[data-category='Verkehr']      { --scene-a: #364356; --scene-b: #141C2B; --scene-c: #5E7189; }

/* Eine Szene: das Farbfeld, darueber die Wortgruppe, die gerade dran ist.
   Beide liegen uebereinander und driften verschieden schnell - die Tiefe
   entsteht aus dem Unterschied, nicht aus einem Schatten.                  */
.scene {
  position: absolute; inset: 0; opacity: 0;
  transition: opacity 700ms ease;
}
.scene.is-live { opacity: 1; }

/* Das Foto, wenn es eines gibt. Es liegt ueber dem Farbfeld und nicht an
   seiner Stelle: laedt das Bild nicht, steht darunter die Farbe der Rubrik
   statt eines schwarzen Rechtecks. Dieselbe Fahrt wie das Feld - beide
   bewegen sich als ein Bild.

   inset: 0 und nicht -8%: Im Ruhezustand soll die Buehne genau den Ausschnitt
   zeigen, den der Aufmacher beim Lesen zeigt - dasselbe Bild, dieselbe Kante,
   derselbe Beschnitt. Ein Vorlauf von acht Prozent rings herum machte daraus
   einen anderen Ausschnitt, und beim Reiterwechsel sprang das Bild. Den
   Spielraum fuer die Fahrt bringt jetzt die Vergroesserung in den Keyframes
   mit; unter 100 Prozent geht keine von ihnen.                            */
.scene .photo {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  animation: drift var(--dur, 30s) linear both;
  will-change: transform;
}

.scene .field {
  position: absolute; inset: 0;
  background:
    radial-gradient(58% 48% at var(--gx1) var(--gy1), var(--scene-c) 0%, transparent 62%),
    radial-gradient(64% 54% at var(--gx2) var(--gy2), var(--scene-a) 0%, transparent 68%),
    linear-gradient(var(--angle), var(--scene-a) 0%, var(--scene-b) 78%);
  animation: drift var(--dur, 30s) linear both;
  will-change: transform;
}

/* Ein feines Korn nimmt den Verlaeufen das Digitale. Als Data-URI, damit die
   Buehne keine zweite Anfrage braucht. */
.backdrop::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0.35;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.32'/%3E%3C/svg%3E");
}

/* Die Wortgruppe der Szene, gross und leise im Hintergrund. In der
   Leseschrift, weil sie deutscher Text ist - dieselbe Regel wie ueberall. */
.scene .motif {
  position: absolute; left: 30px; top: 24px; right: 30px;
  font-family: var(--read); font-size: clamp(30px, 5.2vw, 58px); line-height: 1.06;
  font-weight: 500; color: #FFFFFF; opacity: 0.14; letter-spacing: -0.01em;
  text-wrap: balance; pointer-events: none;
  animation: motif var(--dur, 30s) linear both;
}

/* Vier Fahrten, damit aus dem Wechsel keine Diaschau wird: mal hinein, mal
   heraus, jedes Mal in eine andere Ecke. Die Dauer ist die Laenge der Szene,
   also endet die Fahrt mit dem letzten Satz und nicht irgendwo.            */
/* Jede Fahrt beruehrt an einem Ende scale(1) ohne Versatz - den Ausschnitt
   des Aufmachers. Die erste Szene faengt dort an, und weil sie steht, bis
   jemand abspielt, ist der Wechsel vom Lesen zum Hoeren kein Bildsprung.
   Unter 100 Prozent geht keine Fahrt: Seit die Flaeche buendig sitzt, waere
   das ein Rand aus nichts. */
@keyframes drift {
  from { transform: scale(1) translate3d(0, 0, 0); }
  to   { transform: scale(1.12) translate3d(-2.2%, -1.6%, 0); }
}
.scene:nth-child(4n+2) :is(.field, .photo) { animation-name: drift-b; }
.scene:nth-child(4n+3) :is(.field, .photo) { animation-name: drift-c; }
.scene:nth-child(4n+4) :is(.field, .photo) { animation-name: drift-d; }
@keyframes drift-b {
  from { transform: scale(1.14) translate3d(1.8%, 1.2%, 0); }
  to   { transform: scale(1) translate3d(0, 0, 0); }
}
@keyframes drift-c {
  from { transform: scale(1) translate3d(0, 0, 0); }
  to   { transform: scale(1.13) translate3d(1.4%, -1.1%, 0); }
}
@keyframes drift-d {
  from { transform: scale(1.12) translate3d(-1.5%, 1.2%, 0); }
  to   { transform: scale(1) translate3d(0, 0, 0); }
}
/* Die Schrift zieht langsamer als das Feld - daher die Tiefe. */
@keyframes motif {
  from { transform: translate3d(0, 10px, 0); }
  to   { transform: translate3d(0, -14px, 0); }
}

/* Steht der Ton, steht das Bild. Ohne diese Zeile zoomt die Buehne weiter,
   waehrend nichts zu hoeren ist - der haeufigste Fehler bei solchen
   Umsetzungen und sofort als falsch zu erkennen.                          */
.stage.is-paused :is(.field, .motif, .photo) { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  .scene :is(.field, .motif, .photo) { animation: none; }
  .scene { transition: none; }
}

/* Die Bildunterschrift. Klein und oben rechts, wo sonst nichts steht - der
   Untertitel braucht den unteren Rand. Eine Pflichtangabe darf leise sein,
   fehlen darf sie nicht.

   Und sie steht in beiden Modi an derselben Stelle. Beim Lesen stand sie
   einmal unter dem Bild: Beim Wechsel in den Reiter "Lese-Video" sprang sie
   von dort in die obere Ecke des Bildes, und der Lesetext darunter rutschte
   um ihre Zeile nach oben. Es ist dieselbe Angabe zu demselben Foto in
   derselben Flaeche - also steht sie an derselben Stelle.

   Der Schriftschatten ist der Preis dafuer: Im Bild liegt sie auf dem Foto,
   und oben ist der Schleier der Buehne fast durchsichtig. Weiss auf einem
   hellen Himmel braucht die Kante.                                         */
.stage .credit, .opener .credit {
  position: absolute; top: 20px; right: 20px; max-width: 46%;
  margin: 0;
  font-family: var(--mono); font-size: 10.5px; line-height: 1.4; text-align: right;
  color: rgba(255, 255, 255, 0.72); text-wrap: pretty;
  text-shadow: 0 1px 3px rgba(7, 12, 20, 0.65);
}
.stage .credit:hover, .opener .credit:hover { color: rgba(255, 255, 255, 0.96); }
/* Die beiden Nachweise - Lizenztext und Dateiseite. Unterstrichen, weil eine
   Pflichtangabe nur dann eine ist, wenn man ihr auch ansieht, dass sie
   irgendwohin fuehrt. */
.stage .credit a, .opener .credit a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.stage .credit a:hover, .opener .credit a:hover { color: #fff; }
.stage .credit[hidden] { display: none; }

.scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgba(7, 12, 20, 0.88) 0%, rgba(7, 12, 20, 0.58) 46%, rgba(7, 12, 20, 0.16) 100%);
}

.badges { position: absolute; top: 18px; left: 20px; display: flex; gap: 6px; z-index: 1; }
.badge {
  height: 22px; display: inline-flex; align-items: center; gap: 5px; padding: 0 9px;
  border-radius: 999px; background: rgba(255, 255, 255, 0.9);
  font-size: 11.5px; font-weight: 500; color: var(--info-text);
}
.badge.accent { color: var(--accent-text); }
.badge.mono { font-family: var(--mono); }

/* Auf der Buehne steht nur der gerade gesprochene Satz - gross genug, um ihn
   zu hoeren statt zu lesen. Das ganze Transkript steht rechts. */
.subtitle {
  position: relative; margin: 0; padding: 24px 30px 14px; width: 100%;
  font-family: var(--read); font-size: clamp(19px, 2.4vw, 26px); line-height: 1.45;
  font-weight: 400; color: #FFFFFF; letter-spacing: 0; text-wrap: pretty;
}
/* Der Satzwechsel wird gezeigt, nicht nur vollzogen: der neue Satz steigt
   herein. Ohne das springt die Buehne, und bei einem Stueck, das man hoert
   statt liest, ist der Sprung die einzige Stelle, an der man merkt, dass
   etwas passiert ist. */
.subtitle.is-fresh { animation: subtitle-in 420ms cubic-bezier(0.2, 0, 0.1, 1) both; }
@keyframes subtitle-in {
  from { opacity: 0.25; transform: translateY(9px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .subtitle.is-fresh { animation: none; }
}

/* Wortgruppen auf der Buehne: nur die Markierung, ohne Klickflaeche. */
.chunk-light {
  text-decoration: underline; text-decoration-color: var(--accent-light);
  text-decoration-thickness: 2px; text-underline-offset: 5px;
}

/* --- Die Transportleiste --------------------------------------------------
   Sie stand unter der Buehne, als eigene weisse Leiste. Damit lag die
   Bedienung des Stuecks ausserhalb des Stuecks: der Knopf im Bild, der Balken
   darunter, und der Blick sprang zwischen zwei Flaechen. Jetzt liegt sie im
   Bild, auf dem unteren Ende des Schleiers, der ohnehin dafuer da ist, dass
   weisse Schrift auf einem Foto lesbar bleibt.

   Ein Abspielknopf steht nicht darin: Das ist das Bild selbst. Was hier steht,
   sind die Dinge, die eine Flaeche nicht kann - die Stelle, der Satz, das
   Tempo, der Ton.

   Sie steht immer da und blendet sich nicht weg. Bei einem Film waere das
   Zierat vor dem Bild; hier ist der Balken das, woran man sieht, wo im Text
   man ist, und der Satzknopf das, was man am haeufigsten braucht.          */
.transport {
  position: relative; z-index: 4;
  display: flex; flex-direction: column; gap: 2px;
  padding: 0 22px 14px;
  /* Weiss auf dem Bild - dieselbe Schrift wie der Untertitel darueber, nur
     leiser. Volle Deckung bekommt, was gerade angefasst wird. */
  color: rgba(255, 255, 255, 0.82);
}

/* Der Balken. Die Flaeche zum Anfassen ist hoeher als die Schiene darin:
   Fuenf Pixel trifft niemand, achtzehn schon - und die Schiene bleibt
   trotzdem eine Schiene und kein Riegel.

   touch-action: none, damit ein Ziehen auf dem Handy den Balken bewegt und
   nicht die Seite.                                                          */
.transport .bar {
  position: relative; display: flex; align-items: center;
  height: 18px; cursor: pointer; touch-action: none;
}
.transport .track {
  position: relative; width: 100%; height: 5px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.28); overflow: hidden;
  transition: height 120ms ease-out;
}
.transport .bar:hover .track,
.transport .bar:focus-visible .track,
.transport .bar.is-held .track { height: 8px; }
/* Weiss und nicht gruen: Gruen markiert Sinnabschnitte und sonst nichts. */
.transport .fill { height: 100%; width: 0; background: #FFFFFF; border-radius: 999px; }

/* Wo die Szenen wechseln. Der Balken sagt sonst nur, wie weit es noch ist -
   mit den Marken sagt er ausserdem, wie das Stueck gebaut ist. Und wer eine
   trifft, landet genau am Anfang ihrer Szene: video.js faengt den Klick in
   ihrer Naehe ab, denn zwei Pixel trifft man nicht absichtlich. */
.transport .tick {
  position: absolute; top: 0; bottom: 0; width: 2px;
  background: rgba(7, 12, 20, 0.55);
}

/* Der Griff steht nur da, wenn jemand danach greift - sonst ist der Balken
   eine Anzeige und kein Bedienelement mit einem Punkt darauf. */
.transport .knob {
  position: absolute; top: 50%; left: 0; width: 13px; height: 13px;
  margin: -6.5px 0 0 -6.5px; border-radius: 999px; background: #FFFFFF;
  box-shadow: 0 1px 4px rgba(7, 12, 20, 0.5);
  opacity: 0; transition: opacity 120ms ease-out; pointer-events: none;
}
.transport .bar:hover .knob,
.transport .bar:focus-visible .knob,
.transport .bar.is-held .knob { opacity: 1; }
.transport .bar:focus-visible { outline: none; }
.transport .bar:focus-visible .knob { outline: 2px solid #FFFFFF; outline-offset: 2px; }

/* Die Zeit unter dem Zeiger, bevor geklickt wird. Ohne sie ist ein Sprung im
   Balken ein Versuch. */
.transport .peek {
  position: absolute; bottom: 22px; transform: translateX(-50%);
  padding: 2px 6px; border-radius: 5px; background: rgba(7, 12, 20, 0.86);
  font-family: var(--mono); font-size: 10.5px; color: #FFFFFF;
  pointer-events: none; white-space: nowrap;
}
.transport .peek[hidden] { display: none; }

.transport .controls { display: flex; align-items: center; gap: 2px; }
.transport .gap { flex: 1; }

/* Die Knoepfe der Leiste. Rund und leer, bis der Zeiger darauf steht - ein
   Kasten je Knopf waere ein Werkzeugkasten vor dem Bild. */
.tbtn {
  width: 32px; height: 32px; flex: none; padding: 0; border: 0; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; color: inherit; cursor: pointer;
  transition: background 140ms ease-out, color 140ms ease-out;
}
.tbtn.wide { width: auto; min-width: 40px; padding: 0 9px; font-family: var(--mono); font-size: 12px; }
.tbtn:hover { background: rgba(255, 255, 255, 0.18); color: #FFFFFF; }
.tbtn:focus-visible { outline: 2px solid #FFFFFF; outline-offset: 2px; }
/* Was eingeschaltet ist, wird umgedreht statt eingefaerbt: Gruen ist die
   Lernfarbe und gehoert den Sinnabschnitten, und ein zweiter Farbton auf
   einem Foto ist einer zu viel. */
.tbtn[aria-pressed='true'] { background: #FFFFFF; color: var(--primary-dark); }
.tbtn[aria-pressed='true']:hover { background: rgba(255, 255, 255, 0.88); }

.transport .time {
  font-family: var(--mono); font-size: 11.5px; margin: 0 4px 0 8px; white-space: nowrap;
}

/* Das Tempo-Menue klappt nach oben auf - nach unten waere es ausserhalb des
   Bildes, und die Buehne schneidet ab, was ueber ihre Kante geht. */
.transport .menu { position: relative; }
.transport .rates {
  position: absolute; bottom: 38px; right: 0; z-index: 5;
  display: flex; flex-direction: column; gap: 1px; padding: 4px;
  border-radius: 10px; border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(9, 15, 25, 0.92);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.transport .rates[hidden] { display: none; }
.transport .rates button {
  border: 0; background: none; cursor: pointer; border-radius: 6px;
  padding: 5px 12px; text-align: right;
  font-family: var(--mono); font-size: 12px; color: rgba(255, 255, 255, 0.78);
}
.transport .rates button:hover { background: rgba(255, 255, 255, 0.16); color: #FFFFFF; }
.transport .rates button[aria-checked='true'] { color: #FFFFFF; font-weight: 600; }

/* Der Ton. Der Regler faehrt unter dem Zeiger aus: Er wird selten gebraucht,
   und ein Schieberegler, der immer da steht, waere das Auffaelligste an einer
   Leiste, in der es um den Text geht. */
.transport .volume { display: flex; align-items: center; }
.transport .vol {
  width: 0; opacity: 0; margin: 0; height: 18px; cursor: pointer;
  -webkit-appearance: none; appearance: none; background: none;
  transition: width 160ms ease-out, opacity 160ms ease-out;
}
.transport .volume:hover .vol,
.transport .volume:focus-within .vol { width: 68px; opacity: 1; margin-right: 4px; }
.transport .vol::-webkit-slider-runnable-track {
  height: 4px; border-radius: 999px;
  background: linear-gradient(to right, #FFFFFF var(--vol, 100%),
      rgba(255, 255, 255, 0.28) var(--vol, 100%));
}
.transport .vol::-moz-range-track { height: 4px; border-radius: 999px; background: rgba(255, 255, 255, 0.28); }
.transport .vol::-moz-range-progress { height: 4px; border-radius: 999px; background: #FFFFFF; }
.transport .vol::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; margin-top: -4px;
  width: 12px; height: 12px; border-radius: 999px; background: #FFFFFF; border: 0;
  box-shadow: 0 1px 4px rgba(7, 12, 20, 0.5);
}
.transport .vol::-moz-range-thumb {
  width: 12px; height: 12px; border-radius: 999px; background: #FFFFFF; border: 0;
  box-shadow: 0 1px 4px rgba(7, 12, 20, 0.5);
}
.transport .vol:focus-visible { outline: 2px solid #FFFFFF; outline-offset: 3px; }
#mute .icon-muted { display: none; }
#mute[aria-pressed='true'] .icon-loud { display: none; }
#mute[aria-pressed='true'] .icon-muted { display: block; }

/* Ohne Tonspur steht statt der Leiste der Grund dafuer. */
.transport .hint {
  margin: 0; padding: 6px 0; font-size: 12.5px; color: rgba(255, 255, 255, 0.78);
}

/* Auf schmalen Fenstern faellt weg, was sich anders erreichen laesst: die
   Lautstaerke regelt dort das Geraet, die Kerbenzeit die Fingerspitze. */
/* Der erste Satz kommt mit dem Ton (UX leser-9). */
.stage:not(.has-played):has(.playbutton:not(:disabled)) .subtitle { visibility: hidden; }

/* Am Telefon eine Zeile Nachweis statt drei, die ins Bild ragen (UX leser-9).
   Antippen klappt sie auf - die Links darin bleiben erreichbar. */
@media (max-width: 560px) {
  .stage .credit, .opener .credit {
    top: 12px; right: 14px; max-width: calc(100% - 150px);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .stage .credit:hover, .stage .credit:focus-within,
  .opener .credit:hover, .opener .credit:focus-within {
    white-space: normal; background: rgba(7, 12, 20, 0.72); padding: 6px 8px; border-radius: 6px;
  }
}

@media (max-width: 560px) {
  .transport { padding: 0 14px 12px; }
  .transport .volume { display: none; }
  .transport .time { margin-left: 4px; }
  .subtitle { padding: 20px 16px 10px; }
}

/* --- Das Transkript -------------------------------------------------------
   Es stand einmal als schmale Spalte neben der Buehne; jetzt steht es unter
   ihr, an derselben Stelle und in derselben Breite wie der Lesetext. Es ist
   derselbe Artikel - nur in die Saetze der Tonspur zerlegt.

   Eine eigene Rollflaeche und nicht die ganze Seite: video.js haelt den
   gesprochenen Satz sichtbar, und wenn dafuer die Seite scrollen muesste,
   zoege sie die Buehne unter dem oberen Rand weg. Innerhalb dieser Flaeche
   wandert nur der Text, die Buehne bleibt stehen.

   position: relative, weil video.js die Zeilen ueber offsetTop mittig setzt. */
.tabbody {
  position: relative; padding: 6px 16px 10px; max-height: 62vh; overflow-y: auto;
  border: 1px solid var(--border); border-radius: 4px; background: var(--surface);
}

.lines { list-style: none; margin: 0; padding: 0; }
.lines .line {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 10px 8px; border-radius: 12px;
  border-bottom: 1px solid var(--border);
  transition: background 160ms ease, color 160ms ease;
}
.lines .line:last-child { border-bottom: 0; }
.lines .line.is-spoken { background: var(--primary-dark); border-bottom-color: transparent; }

.lines .cue {
  flex: 0 0 26px; width: 26px; height: 26px; margin-top: 1px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 999px; background: transparent;
  color: var(--text-muted); cursor: pointer;
}
.lines .cue:hover { background: var(--pill-track); color: var(--primary); }
.lines .line.is-spoken .cue { color: rgba(255, 255, 255, 0.85); }
.lines .line.is-spoken .cue:hover { background: rgba(255, 255, 255, 0.16); color: #FFFFFF; }
/* Am Satz, der gerade laeuft, ist der Knopf die Pause (video.js setzt .spielt). */
.lines .cue .zeichen-pause,
.lines.spielt .line.is-spoken .cue .zeichen-abspielen { display: none; }
.lines.spielt .line.is-spoken .cue .zeichen-pause { display: inline; }

.lines .text {
  flex: 1; font-family: var(--read); font-size: 18px; line-height: 1.6;
  color: var(--text-strong); text-wrap: pretty;
}
.lines .line.is-spoken .text { color: #FFFFFF; }

/* Wortgruppen in der laufenden Zeile. Dort ist der Grund dunkel und die
   Schrift weiss - die helle Flaeche von oben loescht sie aus, und die satte
   Lernfarbe verschwindet im Dunkeln. Auf dunklem Grund antwortet der Zeiger
   deshalb mit einem aufgehellten Grund, wie ihn der Satzknopf daneben schon
   benutzt, und die Markierung traegt die helle Fassung der Lernfarbe.       */
.lines .line.is-spoken .chunk { text-decoration-color: var(--accent-light); }
.lines .line.is-spoken .chunk:hover,
.lines .line.is-spoken .chunk:focus-visible,
.lines .line.is-spoken .chunk.is-active {
  background: rgba(255, 255, 255, 0.18);
  text-decoration-color: var(--accent-light);
}
.lines .line.is-spoken .chunk.unit:hover,
.lines .line.is-spoken .chunk.unit:focus-visible {
  background: rgba(255, 255, 255, 0.18);
  text-decoration: underline solid var(--accent-light);
  text-decoration-thickness: 2px;
}

/* Das gerade gesprochene Wort. Nur in der laufenden Zeile und auf der Buehne
   gibt es eines, und beide haben dunklen Grund - daher der helle Akzent.
   Nur die Farbe wechselt: eine fettere Schrift wuerde die Zeile bei jedem
   Wort neu umbrechen. */
.word.is-now { color: var(--accent-light); }

/* In einer Wortgruppe liegt heller Grund darunter - dort die satte Farbe. */
.chunk .word.is-now { color: #FFFFFF; background: var(--accent); border-radius: 2px; }

/* In der dichten Ebene nicht: dort steckt jedes Wort in einer Einheit, und
   der satte Grund waere kein Hinweis mehr, sondern ein Laufband quer durch
   den Satz. Die Einheit hat ihren Grund ohnehin erst beim Ueberfahren.      */
.chunk.unit .word.is-now { color: var(--accent-light); background: none; }

/* --- Admin: Artikel-Queue -------------------------------------------------
   Statusfarben und Rastermasse stammen aus dem Prototyp
   (design/README.md, Abschnitt "Status-Farbtoene").                        */

/* Gesetzte Hoehe wie beim .chip - und hier zusaetzlich, weil --masthead-h
   davon abhaengt: liesse man sie der Schrift, waere die Bauhoehe der Kopfzeile
   eine Messung statt einer Zahl, und die Niveau-Leiste dockte daneben an. */
.navlink {
  height: 28px; display: inline-flex; align-items: center; padding: 0 10px;
  font-size: 12.5px; font-weight: 500; color: var(--text-muted);
  border-radius: 999px; border: 1px solid transparent;
}
.navlink:hover { color: var(--text-strong); border-color: var(--border); background: var(--surface); }
.navlink[aria-current='true'] {
  background: var(--primary); border-color: var(--primary); color: #FFFFFF; font-weight: 600;
}
.navlink[aria-current='true']:hover { background: var(--primary-dark); color: #FFFFFF; }

/* Der Tresor im Kopf, mit der Zahl der faelligen Karten (design/tresor/).
   Die Zahl steht im Ton der Bedienung, nicht in der Lernfarbe: Sie ist eine
   Meldung, kein Lernstoff. Auf dem aktiven Link kehrt sie sich um. */
.tresorlink { gap: 6px; padding-right: 5px; }
.tresorzahl, .burgerzahl {
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 700; line-height: 1;
  background: var(--primary); color: #FFFFFF;
}
.navlink[aria-current='true'] .tresorzahl { background: var(--surface); color: var(--primary); }
.burgerzahl { display: none; }

/* Nach dem Merken: die Zahl springt, der Eintrag leuchtet einmal auf. */
.tresorzahl.springt, .burgerzahl.springt { animation: tresorSprung 420ms cubic-bezier(0.34, 1.56, 0.64, 1); }
.tresorlink.leuchtet, .burger.leuchtet {
  border-color: var(--primary); background: var(--pill-track);
  animation: tresorLeuchten 700ms ease-out;
  transition: background 400ms, border-color 400ms;
}
@keyframes tresorSprung {
  0% { transform: scale(1); }
  35% { transform: scale(1.4); }
  70% { transform: scale(0.94); }
  100% { transform: scale(1); }
}
@keyframes tresorLeuchten {
  from { box-shadow: 0 0 0 0 rgba(18, 40, 61, 0.45); }
  to { box-shadow: 0 0 0 12px rgba(18, 40, 61, 0); }
}
/* Die kleine Karte, die vom Merken-Knopf in den Kopf fliegt. */
.flugkarte {
  position: fixed; z-index: 50; width: 22px; height: 16px; border-radius: 3px;
  background: var(--primary); box-shadow: 0 4px 10px rgba(11, 26, 42, 0.3);
  pointer-events: none; opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
  .tresorzahl.springt, .burgerzahl.springt, .tresorlink.leuchtet, .burger.leuchtet { animation: none; }
}

.pagehead { margin-bottom: 24px; }
.pagehead h1 {
  font-family: var(--display); font-size: 24px; font-weight: 700; letter-spacing: -0.025em;
  color: var(--text-strong); margin: 0 0 6px;
}
.pagehead p { font-size: 13px; line-height: 1.6; color: var(--text-muted); margin: 0; max-width: 62ch; }

/* align-items: start, weil die Kacheln verschieden viel tragen. Solange jede
   hoechstens einen Knopf hatte, war Strecken richtig - die Knoepfe sassen dann
   auf einer Hoehe. Seit an der Queue drei Aktionen haengen, wuerde es die
   anderen vier auf dreifache Hoehe ziehen und mit leerer Flaeche fuellen. */
.tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px; align-items: start;
}
/* Die Kachel traegt einen Link und darunter, wo es welche gibt, ihre Aktionen. */
.tile {
  border: 1px solid var(--border); border-radius: 4px; background: var(--surface);
  display: flex; flex-direction: column;
}
.tile[aria-current='true'] { border-color: var(--primary); }
.tilelink { display: block; flex: 1; padding: 16px 18px; color: inherit; }
.tilelink:hover { background: var(--surface-hover); }
.tileaction { margin: 0; padding: 0 18px 14px; }
.tileaction .action { height: 26px; font-size: 12px; }
/* Der Einwurf: Feld und Herkunft nebeneinander, der Knopf darunter in voller
   Kachelbreite - drei Dinge in einer Reihe waeren in 240 Pixeln zu eng. */
.tileaction.submit { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 8px; }
.tileaction.submit input, .tileaction.submit select {
  height: 26px; font-size: 12px; font-family: inherit;
  border: 1px solid var(--border); border-radius: 3px;
  background: var(--surface); color: var(--text-strong); padding: 0 6px;
}
.tileaction.submit input { flex: 1 1 130px; min-width: 0; }
.tileaction.submit select { flex: 0 1 auto; }
.tileaction.submit .action { flex: 1 0 100%; }
.tile .label {
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 600; color: var(--text-muted);
}
.tile .value {
  font-family: var(--mono); font-size: 24px; font-weight: 600;
  letter-spacing: -0.02em; color: var(--text-strong); margin-top: 8px;
}
.tile .note { font-size: 11.5px; color: var(--text-muted); margin-top: 4px; }

.queue {
  border: 1px solid var(--border); border-radius: 4px; background: var(--surface);
  margin-top: 24px; overflow: hidden;
}
.queue .head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 14px 20px; border-bottom: 1px solid var(--border);
}
.queue .head .title {
  font-family: var(--display); font-size: 15.5px; font-weight: 700;
  letter-spacing: -0.015em; color: var(--text-strong);
}
.queue .head .reset { font-size: 12.5px; color: var(--text-muted); }
.queue .head .search input {
  height: 30px; width: 220px; padding: 0 10px; border: 1px solid var(--border); border-radius: 4px;
  background: var(--surface); color: var(--text-strong); font: inherit; font-size: 12.5px;
}
.queue .head .search input:focus { outline: none; border-color: var(--primary); }
.queue .head form { margin: 0; }

.action {
  height: 30px; display: flex; align-items: center; gap: 6px; padding: 0 12px;
  border-radius: 4px; border: 1px solid var(--border); background: var(--surface);
  color: var(--text-strong); font-size: 12.5px; font-weight: 500;
  font-family: inherit; cursor: pointer;
}
.action:hover { background: var(--surface-hover); }
.action:disabled { opacity: 0.5; cursor: default; }
.action:disabled:hover { background: var(--surface); }

.queue .message {
  margin: 0; padding: 11px 20px; border-bottom: 1px solid var(--border);
  background: var(--info-surface); color: var(--info-text); font-size: 12.5px;
}

/* Waehrend HTMX laedt, wird der ganze Block gedaempft - die Aktionen dauern
   Sekunden, und ohne Rueckmeldung klickt man zweimal. */
.htmx-request #admin-queue, #admin-queue.htmx-request { opacity: 0.55; }

.tablewrap { overflow-x: auto; }
/* Schmaler als vorher: Bei 1080px Mindestbreite war "Im Ziel" am Desktop
   abgeschnitten (UX admin-2). */
.row {
  min-width: 900px; display: grid;
  grid-template-columns: 28px 56px minmax(200px, 1fr) 128px 170px 84px 84px 64px 64px;
  align-items: center; gap: 0; padding: 11px 20px; border-bottom: 1px solid var(--border);
}
.row:last-child { border-bottom: none; }
.row:not(.rowhead):hover { background: var(--surface-hover); }
.rowhead {
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 600; color: var(--text-muted); background: var(--surface-hover);
}
.row .id, .row .src, .row .num { font-family: var(--mono); font-size: 12.5px; color: var(--text-muted); }
.row .id { color: var(--text-muted); }
/* Die Auswahl ist ein Betriebsgriff, kein Lernmaterial: Systemhaken in Akzentfarbe. */
.row .pick input { margin: 0; accent-color: var(--accent-text); display: block; }
.row .title {
  display: block; font-size: 13px; color: var(--text-strong); padding-right: 16px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row a.title:hover { color: var(--primary); text-decoration: underline; }
.row .busy, .row .read { font-size: 11.5px; color: var(--text-muted); margin-left: 4px; }
/* Der Weg in die Leseansicht: leise wie die Vermerke daneben, aber als Link
   erkennbar, sobald der Zeiger darauf steht. */
.row a.read:hover { color: var(--primary); text-decoration: underline; }
/* Die Zeit seit dem Statuswechsel: Text, keine Zahl - "14 Tagen" liest sich in
   Mono nicht besser. Der genaue Zeitpunkt steht im Tooltip, deshalb der Zeiger. */
.row .age { font-size: 12.5px; color: var(--text-muted); }
.row .age[title] { cursor: help; }

/* Die Reiter ueber allen Admin-Seiten (fragments/admin-reiter.html). */
.adminreiter { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 18px; }
.adminreiter a {
  height: 36px; display: inline-flex; align-items: center; padding: 0 14px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-muted);
  font-size: 13px; font-weight: 500;
}
.adminreiter a:hover { color: var(--text-strong); background: var(--surface-hover); }
.adminreiter a[aria-current='page'] { background: var(--primary); border-color: var(--primary); color: #FFFFFF; font-weight: 600; }

/* Am Telefon (UX admin-2): Die fuenf Kacheln zweispaltig und knapp, die
   Tabelle als Zeilenkarten - Titel, darunter Quelle und Status, rechts das
   Alter. Vorher sah man nur ID und Titel und musste ahnen, dass die Tabelle
   seitlich weitergeht. Versuche und Niveaus stehen am Desktop. */
@media (max-width: 640px) {
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .tilelink { padding: 10px 12px; }
  .tile .value { font-size: 20px; margin-top: 4px; }
  .tile .note { font-size: 11px; }
  .tileaction { padding: 0 12px 10px; }
  .row {
    min-width: 0; grid-template-columns: 28px minmax(0, 1fr) auto;
    grid-template-areas: "pick title age" "pick meta meta";
    row-gap: 4px; padding: 10px 14px;
  }
  .rowhead { display: none; }
  .row > :nth-child(1) { grid-area: pick; }
  .row > :nth-child(2), .row > :nth-child(7), .row > :nth-child(8), .row > :nth-child(9) { display: none; }
  .row > .title { grid-area: title; white-space: normal; padding-right: 8px; }
  .row > .src { grid-area: meta; }
  .row > :nth-child(5) { grid-area: meta; justify-self: end; }
  .row > .age { grid-area: age; font-size: 11.5px; }
  .queue .head { padding: 12px 14px; }
  .queue .head .search, .queue .head .search input { width: 100%; }
}

.pill {
  height: 22px; display: inline-flex; align-items: center; gap: 5px; padding: 0 9px;
  border-radius: 999px; font-size: 11.5px; font-weight: 500;
  background: var(--pill-track); color: var(--text-muted);
}
.pill .dot { width: 5px; height: 5px; border-radius: 999px; background: currentColor; opacity: 0.7; }
/* Wo ein Tooltip wartet, sagt der Zeiger es. */
.pill[title] { cursor: help; }
.pill-ready { background: var(--ok-surface); color: var(--ok-text); }
.pill-new { background: var(--pill-track); color: var(--text-muted); }
.pill-enriching_text { background: var(--info-surface); color: var(--info-text); }
.pill-enriching_media { background: var(--accent-surface); color: var(--accent-text); }
.pill-failed { background: #F4E0DB; color: #9A4A3F; }
/* Aussortiert ist kein Fehler, nur erledigt - deshalb blasser statt roter. */
.pill-ignored { background: var(--pill-track); color: var(--text-muted); }
/* Von Hand aussortiert: dasselbe Fach, aber ein Mensch dahinter - deshalb die
   Kontur statt einer eigenen Farbe. */
.pill-cancelled {
  background: var(--pill-track); color: var(--text-muted);
  box-shadow: inset 0 0 0 1px var(--border);
}

.notes { margin-top: 16px; display: grid; gap: 8px; }
.note-line {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--text-muted);
}
.note-line .mono { font-family: var(--mono); font-size: 12px; }

/* --- Chunk-Panel im Reader ------------------------------------------------
   Masse aus dem Prototyp: 348 px breit, unter der Wortgruppe, weiche Kante.  */

.chunkpop {
  position: fixed; z-index: 9;
  background: var(--surface); border: 1px solid var(--border); border-radius: 4px;
  box-shadow: 0 18px 40px -18px rgba(11, 26, 42, 0.25), 0 1px 2px rgba(11, 26, 42, 0.05);
  padding: 14px 16px 16px;
  animation: popIn 150ms cubic-bezier(0.4, 0, 0.2, 1);

  /* Das Panel scrollt in sich, statt ueber das Wort hinauszuwachsen.
     Die Hoehe setzt popcard.js - sie ist der Platz, der zur naeheren
     Fensterkante hin uebrig bleibt.

     Auf einem Telefon war das der haeufigste Fall: Nach "Uebersetzung
     zeigen" wird aus einem Kasten von vier Zeilen einer mit Bedeutungen,
     Synonymen und Gegenteilen - und der passte weder unter noch ueber das
     Wort. Er verdeckte dann den Satz, zu dem er gehoert.

     overscroll-behavior verhindert das Zweite, was dabei stoert: Wer im
     Panel bis ans Ende wischt, soll nicht ploetzlich die Seite dahinter
     weiterschieben und die Textstelle verlieren. */
  overflow-y: auto;
  overscroll-behavior: contain;
}
.chunkpop[hidden] { display: none; }

/* Das Blatt von unten - am Telefon statt des Kastens am Wort (UX leser-7).
   Breite, Lage und Hoehe setzt dann nicht popcard.js, sondern das hier. */
.chunkpop.als-blatt {
  top: auto; left: 0; right: 0; bottom: 0; width: auto;
  max-height: 62vh; border-radius: 14px 14px 0 0; border-bottom: 0;
  padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -12px 32px -12px rgba(11, 26, 42, 0.3);
  animation: blattAuf 180ms cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes blattAuf {
  from { transform: translateY(24px); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .chunkpop.als-blatt { animation: none; } }
.chunkpop:focus { outline: none; }
.chunkpop:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

@keyframes popIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

.chunkpop .pophead { display: flex; align-items: center; gap: 8px; }

/* Das Zeichen im Kopf des Satz-Panels. Es steht in der Farbe der leisen
   Schrift, nicht in der des Sprachnamens - es benennt die Herkunft und soll
   die Antwort darunter nicht ueberstimmen. */
.sentpop .popmark { flex: 0 0 auto; color: var(--text-faint); }
.chunkpop .pill-type { background: var(--info-surface); color: var(--info-text); }

.chunkpop .langs { display: flex; gap: 4px; padding: 3px; background: var(--pill-track); border-radius: 10px; }
.chunkpop .langs button {
  height: 22px; padding: 0 9px; border: none; border-radius: 8px;
  background: none; color: var(--text-muted);
  font-family: inherit; font-size: 11.5px; font-weight: 500; cursor: pointer;
}
.chunkpop .langs button[aria-current='true'] { background: var(--surface); color: var(--text-strong); }

.chunkpop .close {
  width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
  border: none; background: none; padding: 0; color: var(--text-muted); cursor: pointer;
}
.chunkpop .close:hover { color: var(--text); }

/* Die Wortgruppe ist deutscher Text - hier steht sie in der Leseschrift, in
   der sie oben im Artikel auch steht. Alles andere im Panel ist Erklaerung
   und bleibt in der Grotesk. */
.chunkpop .phrase {
  font-family: var(--read); font-size: 21px; font-weight: 500; color: var(--text-strong);
  letter-spacing: 0; margin-top: 12px; text-wrap: pretty;
}
/* Der Tipp steht dort, wo sonst die Uebersetzung steht - er vertritt sie. */
.chunkpop .hint { font-size: 15px; color: var(--text); margin-top: 5px; text-wrap: pretty; }
/* Derselbe Knopf im Blick auf eine Karte: "Anriss zeigen" ist dieselbe Geste
   wie "Uebersetzung zeigen" - erst das Kurze, das Lange auf Wunsch. */
.chunkpop .reveal, .cardtip .reveal {
  margin-top: 12px; width: 100%; height: 30px;
  border: 1px solid var(--border); border-radius: 4px; background: var(--surface);
  color: var(--text-muted); font-family: inherit; font-size: 12.5px; font-weight: 500;
  cursor: pointer;
}
.chunkpop .reveal:hover, .cardtip .reveal:hover { background: var(--surface-hover); color: var(--text-strong); }
.chunkpop .reveal[hidden], .cardtip .reveal[hidden] { display: none; }
.chunkpop .langs[hidden] { display: none; }
.chunkpop .translation { font-size: 15px; color: var(--text); margin-top: 12px; }

/* Fundstellen und Videolink - beides Zugaben, also leiser als der Rest. */
.chunkpop .elsewhere {
  margin-top: 12px; padding-top: 11px; border-top: 1px dashed var(--border);
  font-size: 12px; line-height: 1.6;
}
.chunkpop .elsewhere .label { color: var(--text-muted); margin-bottom: 6px; }
/* Das Wort, ueber das gefunden wurde, traegt die Zeile - es ist der Grund,
   warum dieser fremde Beitrag hier steht. */
.chunkpop .elsewhere .label .term { color: var(--text-strong); font-weight: 600; }

/* Die Fundstellen als Liste und nicht als Reihe abgeschnittener Zeilen.
   Einzeilig mit Auslassungspunkten passten in die 348 Pixel des Panels rund
   vierzig Zeichen - eine Schlagzeile, die dort endet, fuehrt niemanden in
   einen anderen Beitrag. Sie bricht jetzt um, und die Zeile bekommt Flaeche,
   damit sie sich anfassen laesst: ein Ziel von 348 mal 30 Pixeln trifft auch
   ein Daumen. */
.chunkpop .elsewhere .links { display: grid; gap: 1px; }
.chunkpop .elsewhere a {
  display: grid; grid-template-columns: 9px 1fr; gap: 7px; align-items: start;
  margin: 0 -8px; padding: 5px 8px; border-radius: 6px;
  color: var(--primary); line-height: 1.4; text-wrap: pretty;
}
/* Der Winkel steht fuer den Weg hinaus - er macht aus drei blauen Absaetzen
   eine Liste, die man von oben nach unten liest. */
.chunkpop .elsewhere a::before {
  content: '\203A'; color: var(--text-faint); font-size: 13px; line-height: 1.35;
}
.chunkpop .elsewhere a:hover, .chunkpop .elsewhere a:focus-visible {
  background: var(--surface-hover); outline: none;
}
.chunkpop .elsewhere a:hover::before, .chunkpop .elsewhere a:focus-visible::before {
  color: var(--primary);
}
/* Zwei Zeilen und nicht mehr: Sonst schoebe eine einzige lange Schlagzeile das
   halbe Panel aus dem Bild. */
.chunkpop .elsewhere a .title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.chunkpop .youglish {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 12px;
  font-size: 12px; color: var(--text-muted);
}
.chunkpop .youglish:hover { color: var(--primary); }
.chunkpop .youglish[hidden] { display: none; }
.chunkpop .example { font-size: 12.5px; line-height: 1.55; color: var(--text-muted); margin-top: 12px; text-wrap: pretty; }

/* --- Die Karte: Kopf, Hoer-Knopf, Bedeutungen ----------------------------
   Das Vorbild ist der Eintrag in einem zweisprachigen Woerterbuch: oben das
   Wort mit dem Lautsprecher, darunter die grammatischen Zeilen, dann die
   Bedeutungen an einem Balken und zuletzt das Beispiel mit eigenem Knopf.

   Eine Lautschrift steht nicht dabei. Es gibt sie in keiner Quelle im Haus,
   und geraten waere sie schlimmer als keine - der Knopf sagt ohnehin mehr. */
.chunkpop .cardhead {
  display: flex; align-items: flex-start; gap: 6px; margin-top: 12px;
}
.chunkpop .cardhead .phrase { margin-top: 0; flex: 1; min-width: 0; }

.chunkpop .listen {
  flex: 0 0 auto; width: 28px; height: 28px; margin-top: 1px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 999px; background: none; padding: 0;
  color: var(--text-muted); cursor: pointer;
}
.chunkpop .listen:hover { background: var(--pill-track); color: var(--primary); }
.chunkpop .listen:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.chunkpop .listen[hidden] { display: none; }
/* Waehrend es spielt: derselbe Ton wie beim Zeigen, damit sichtbar ist, dass
   der Klick angekommen ist. Ohne diese Rueckmeldung klickt man zweimal. */
.chunkpop .listen.is-playing { color: var(--primary); background: var(--pill-track); }

/* Merken (design/tresor/Main.dc.html). Neben dem Hoeren, mit Wort. Gemerkt
   gefuellt in der Farbe der Bedienung; ohne Anmeldung in der Warnfarbe, damit
   niemand glaubt, es sei gespeichert. Welches Zeichen gilt, sagt data-zustand. */
.chunkpop .merken {
  flex: 0 0 auto; height: 28px; padding: 0 10px 0 8px; margin-top: 1px;
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface);
  color: var(--text-strong); font-family: inherit; font-size: 12px; font-weight: 600;
  white-space: nowrap; cursor: pointer;
}
.chunkpop .merken[hidden] { display: none; }
.chunkpop .merken:hover { background: var(--surface-hover); }
.chunkpop .merken:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.chunkpop .merken:disabled { cursor: progress; opacity: 0.7; }
.chunkpop .merken svg { color: var(--text-muted); }
.chunkpop .merken .zeichen-drin, .chunkpop .merken .zeichen-nicht { display: none; }
.chunkpop .merken[data-zustand='drin'] { background: var(--primary); border-color: var(--primary); color: #FFFFFF; }
.chunkpop .merken[data-zustand='drin']:hover { background: var(--primary-dark); }
.chunkpop .merken[data-zustand='drin'] svg { color: #FFFFFF; }
.chunkpop .merken[data-zustand='drin'] .zeichen-merken { display: none; }
.chunkpop .merken[data-zustand='drin'] .zeichen-drin { display: inline; }
.chunkpop .merken[data-zustand='nicht'] { background: #FBEAE8; border-color: #D9A39C; color: #8A1F16; }
.chunkpop .merken[data-zustand='nicht'] svg { color: #8A1F16; }
.chunkpop .merken[data-zustand='nicht'] .zeichen-merken { display: none; }
.chunkpop .merken[data-zustand='nicht'] .zeichen-nicht { display: inline; }
.chunkpop .merknote { margin-top: 6px; font-size: 12px; line-height: 1.45; color: var(--text-muted); }
.chunkpop .merknote[hidden] { display: none; }
.chunkpop .merknote a { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; }
.chunkpop .cardhead:has(.merken[data-zustand='nicht']) + .merknote {
  padding: 8px 10px; border-radius: 6px; background: #FBEAE8; border: 1px solid #EBC7C2; color: #8A1F16;
}
.chunkpop .cardhead:has(.merken[data-zustand='nicht']) + .merknote a { color: #8A1F16; font-weight: 700; }

/* Die Bedeutungen tragen den Balken, die Lehre nicht mehr: Drei Balken
   untereinander sind kein Aufbau, sondern ein Zaun. Der Balken gehoert dorthin,
   wo die Antwort steht - auf Deutsch und in der Zielsprache. */
.chunkpop .hint, .chunkpop .translation {
  border-left: 2px solid var(--accent-text); padding-left: 9px;
}
.chunkpop .lesson { display: grid; grid-template-columns: 13px minmax(0, 1fr); gap: 6px; }
.chunkpop .lesson::before { content: '✎'; color: var(--text-faint); font-size: 11px; line-height: 1.6; }
/* Die zweite Zeile ruecken wir ein statt ihr ein zweites Zeichen zu geben:
   Zwei Stifte untereinander sehen nach einer Liste aus, und es ist keine -
   die eine Zeile ist nachgeschlagen, die andere vom Modell geschrieben. */
.chunkpop .lesson-usage { margin-top: 3px; }
.chunkpop .lesson-usage::before { content: ''; }

/* Das Beispiel mit eigenem Knopf: Wer die Wendung gehoert hat, hat sie noch
   nicht im Satz gehoert - und dort steht die Betonung woanders. */
.chunkpop .example {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px; align-items: start;
}
.chunkpop .example[hidden] { display: none; }
.chunkpop .example .listen { width: 22px; height: 22px; margin-top: -1px; }

/* Der Steckbrief der dichten Ebene: Grundform, Formen, Merksatz. Zweispaltig
   wie in einem Woerterbuch - die Beschriftung schmal und leise, damit das Auge
   die Werte untereinander findet und nicht die Etiketten liest.             */
.chunkpop .steckbrief { margin-top: 10px; display: grid; gap: 4px; }
.chunkpop .steckbrief[hidden] { display: none; }
/* Nicht ".row": den Klassennamen belegt weiter oben die Admin-Tabelle, mit
   min-width: 960px und sieben Spalten. Die Steckbrief-Zeile war damit fast
   dreimal so breit wie das Panel, und der Merksatz stand neben dem Kasten
   statt darin.
   minmax(0, 1fr) statt 1fr, weil eine Spalte von sich aus nie schmaler wird
   als ihr laengstes Wort - eine lange Zusammensetzung im Merksatz zoege die
   Zeile sonst genauso ueber die Kante.                                    */
.chunkpop .steckbrief .line { display: grid; grid-template-columns: 74px minmax(0, 1fr); gap: 8px; align-items: baseline; }
.chunkpop .steckbrief .key { font-size: 10.5px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); }
.chunkpop .steckbrief .val { font-size: 13px; line-height: 1.5; color: var(--text); text-wrap: pretty; overflow-wrap: break-word; }
.chunkpop .regenerate { margin-top: 8px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.chunkpop .regenerate[hidden] { display: none; }
.chunkpop .regenerate button {
  height: 26px; padding: 0 10px; border: 1px dashed var(--border); border-radius: 4px;
  background: transparent; color: var(--text-muted); font-family: inherit; font-size: 11.5px; cursor: pointer;
}
.chunkpop .regenerate button:hover { background: var(--surface-hover); color: var(--text-strong); }
.chunkpop .regenerate button:disabled { cursor: progress; opacity: 0.6; }
.chunkpop .regenerate .note { font-size: 11.5px; color: var(--text-muted); }

/* Die Nachschlage-Links unter der Uebersetzung - dieselbe Zeile wie YouGlish,
   weil es dieselbe Sorte Angebot ist: ein Link nach draussen, kein Nachladen. */
.chunkpop .lookup {
  display: flex; align-items: center; gap: 6px; margin-top: 10px;
  font-size: 12px; color: var(--text-muted); text-decoration: none;
}
.chunkpop .lookup:hover { color: var(--primary); }
.chunkpop .lookup[hidden] { display: none; }

/* Die Wortfamilie im Panel. Dieselben fuenf Farbtoene wie im Vokabel-Netz -
   wer dort "Nomen" violett gelernt hat, findet es hier wieder.               */
.chunkpop .wordfamily { margin-top: 12px; }
.chunkpop .wordfamily[hidden] { display: none; }
.chunkpop .wordfamily .label { font-size: 11px; color: var(--text-muted); margin-bottom: 5px; }
/* Die Bedeutungen stehen untereinander, die Woerter einer Bedeutung
   nebeneinander. Ohne diese Trennung stuenden "abmagern" und "wegnehmen" in
   einer Reihe - beide Synonyme von "abnehmen", aber nicht voneinander. */
.chunkpop .wordfamily .chips { display: grid; gap: 5px; }
/* min-width: 0, weil die Reihe im Raster der Bedeutungen steht: Ein Etikett
   mit Gebrauchshinweis nimmt die volle Breite (has-usage weiter unten), und
   ohne diese Null rechnet der Browser die Spur nach dem Hinweis in einer
   Zeile - die Reihe wurde dreimal so breit wie das Panel und der Hinweis lief
   quer ueber die Seite. */
.chunkpop .wordfamily .chips .row { display: flex; flex-wrap: wrap; gap: 5px; min-width: 0; }
.chunkpop .wordfamily .chips .sense {
  font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--text-muted); margin-top: 2px;
}
.chunkpop .wordfamily .chips .sense:first-child { margin-top: 0; }
.chunkpop .wordfamily .word {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 3px 8px; border-radius: 8px; border: 1px solid;
  font-size: 12.5px; line-height: 1.4;
}
.chunkpop .wordfamily .word .kind { font-size: 10px; opacity: 0.7; }
/* Die Farbe steht fuer die Stufe, nicht fuer die Wortart.

   Vorher trennte sie Synonym von Nomen von Verb - eine Auskunft, die ohnehin
   danebensteht, in Buchstaben. Wonach der Lernende die Reihe absucht, ist eine
   andere: Welches dieser Woerter ist fuer mich schon dran? Das beantwortet A2
   gegen C1, und das darf die Farbe sagen.

   Fuenf Stufen und keine sechs: Der Referenzrahmen kennt C2, dieses Haus nicht
   - CefrLevel hoert bei C1 auf, und eine Farbe fuer eine Stufe, die nie
   vorkommt, waere eine Farbe zum Raten.

   Die Toene sind dieselben fuenf wie vorher, nur neu geordnet: von kuehl und
   hell nach warm und tief. Kein Ampelverlauf - Gruen nach Rot liest sich als
   richtig und falsch, und ein C1-Wort ist nicht falsch, sondern spaeter
   dran. */
.chunkpop .wordfamily .level-a1 { background: #E4EFE3; border-color: #3F6B45; color: #3F6B45; }
.chunkpop .wordfamily .level-a2 { background: #DCEDEC; border-color: #2F6E6A; color: #2F6E6A; }
.chunkpop .wordfamily .level-b1 { background: #DCE6F3; border-color: #35547C; color: #35547C; }
.chunkpop .wordfamily .level-b2 { background: #EAE4F3; border-color: #5B4A80; color: #5B4A80; }
.chunkpop .wordfamily .level-c1 { background: #F6E3E6; border-color: #8A4A58; color: #8A4A58; }
/* Keine Liste kennt das Wort - dann steht dort auch keine Stufe, und das
   Etikett bleibt grau. Vierzig von hundert Woertern der Wortfamilie trifft
   das. */
.chunkpop .wordfamily .level-unbekannt { background: #EEF1F4; border-color: #97A3B2; color: #5C6B7F; }

/* Das Gegenteil an der gestrichelten Kante. Die Farbe kann es nicht mehr
   sagen, und "Gegenteil" steht zwar am Wort - aber wer eine Reihe ueberfliegt,
   liest Farben und Formen, nicht Beschriftungen. Ein Gegenteil, das fuer ein
   Synonym gehalten wird, ist der schlimmste Irrtum, den diese Reihe anrichten
   kann. */
.chunkpop .wordfamily .word.is-opposite { border-style: dashed; }

/* Stufe und Lehre der Wortgruppe.

   Die Stufe steht als zweite Pille neben dem Muster, in einem anderen Ton:
   Beide sind Angaben ueber die Wendung, aber sie beantworten verschiedene
   Fragen - das Muster "was ist das?", die Stufe "ist das schon dran?". Zwei
   Pillen in derselben Farbe waeren eine Angabe in zwei Kaesten.

   Die Lehre steht unter dem Tipp und leiser als er. Sie ist eine Randnotiz zur
   Form, keine zweite Bedeutung; wer nur die Uebersetzung sucht, soll ueber sie
   hinweglesen koennen. */
.chunkpop .pill-level {
  background: var(--pill-track); color: var(--text-muted);
  font-variant-numeric: tabular-nums; cursor: help;
}
.chunkpop .pill-level[hidden] { display: none; }
/* Der Balken sass einmal hier. Er ist zu den Bedeutungen gewandert: Drei
   Balken untereinander sind kein Aufbau, sondern ein Zaun, und er gehoert
   dorthin, wo die Antwort steht. Die Lehre traegt stattdessen ihr Zeichen. */
.chunkpop .lesson {
  margin-top: 7px;
  font-size: 12.5px; line-height: 1.5; color: var(--text-muted); text-wrap: pretty;
}
.chunkpop .lesson[hidden] { display: none; }

/* Stufe und Gebrauchshinweis am Wort der Wortfamilie.

   Die Stufe erbt die Farbe ihres Etiketts und wird nur blasser - sie gehoert
   zum Wort und nicht neben es. Der Gebrauchshinweis dagegen ist ein halber
   Satz und bricht die Zeile: Deshalb legt has-usage das Etikett von der Reihe
   auf zwei Zeilen um, waehrend die Etiketten ohne Hinweis so schmal bleiben
   wie zuvor. */
.chunkpop .wordfamily .word .step {
  font-size: 10px; font-weight: 600; letter-spacing: 0.04em; opacity: 0.65;
}
.chunkpop .wordfamily .word.has-usage {
  display: grid; grid-template-columns: auto auto 1fr; align-items: baseline;
  column-gap: 5px; width: 100%;
}
.chunkpop .wordfamily .word.has-usage .usage {
  grid-column: 1 / -1; margin-top: 2px;
  font-size: 11.5px; line-height: 1.45; opacity: 0.85; text-wrap: pretty;
}

/* Die angeklickte Wortgruppe bleibt sichtbar, solange das Panel offen ist.
   Der dickere Strich haelt die Verbindung zur Hinweisspalte: dort steht die
   Erklaerung, hier steht die Stelle, zu der sie gehoert.                     */
.chunk.is-active {
  background: var(--accent-surface); text-decoration-thickness: 3px;
}


/* --- Das Satz-Panel -------------------------------------------------------
   Es erbt die Huelle des Chunk-Panels ueber die Klasse chunkpop; hier stehen
   nur die vier Zeilen, die es zusaetzlich hat.

   Der Satz in der Leseschrift, die Antwort in der Grotesk: dieselbe Regel wie
   beim Chunk-Panel und dieselbe Begruendung - am Schnitt sieht man, was
   Lernmaterial ist und was Erklaerung.                                      */
.sentpop .saytext { font-size: 15px; color: var(--text); margin-top: 12px; text-wrap: pretty; }
.sentpop .saytext[hidden] { display: none; }

/* Die Wartezeile ist zugleich die Live-Region. Eine zweite, unsichtbare
   Fassung daneben liefe frueher oder spaeter auseinander - und angesagt wuerde
   dann etwas anderes, als dasteht. Leer faellt sie weg, statt eine Zeile Luft
   zu lassen. */
.sentpop .pending { font-size: 12.5px; color: var(--text-muted); margin: 10px 0 0; }
.sentpop .pending:empty { display: none; }

.sentpop .hardwords {
  margin-top: 14px; padding-top: 11px; border-top: 1px dashed var(--border);
}
.sentpop .hardwords[hidden] { display: none; }
.sentpop .hardwords .label {
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 600; color: var(--text-muted); margin-bottom: 7px;
}
.sentpop .hardwords dl { margin: 0; display: grid; gap: 8px; }
.sentpop .hardwords dt { font-family: var(--read); font-size: 15px; color: var(--text-strong); }
/* Der gruene Strich darf hier stehen: Diese Zeilen sind Lernstoff, keine
   Bedienung - dieselbe Ausnahme, die auch die Wortfamilie traegt. */
.sentpop .hardwords dd {
  margin: 2px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-muted);
  border-left: 2px solid var(--accent); padding-left: 8px;
}

/* Der Knopf, aus dem das Panel kam, bleibt sichtbar markiert - sonst weiss man
   nach dem zweiten Satz nicht mehr, zu welchem die Karte gehoert. */
.transmark.is-active { opacity: 1; color: var(--accent-text); background: var(--accent-surface); }
/* --- Warum das Panel immer schwebt ----------------------------------------
   Hier stand eine zweite Spalte: ab 1180px dockte das Chunk-Panel rechts
   neben dem Lesetext an, nach dem Vorbild der Vorschlagsspalte von Grammarly.
   Der Gedanke stimmt - ein Panel, das den Satz verdeckt, den es erklaert,
   zwingt zum Hin- und Herschauen. Die Rechnung stimmte trotzdem nicht:

   Die Spalte war reserviert, nicht belegt. Sie kostete 348 Pixel auf jedem
   Artikel und trug waehrend des Lesens einen Hinweis, den man einmal liest.
   Bezahlt hat das der Lesetext: Auf einem Fenster von 1187 Pixeln war er 684
   breit statt 760 - das breitere Fenster machte die Textspalte schmaler, und
   das ist verkehrt herum.

   Die Naehe, die den Ausschlag gab, hatte die Spalte ausserdem gar nicht: Ihr
   Platz ist fest, oben rechts. Zu einer Wendung in der letzten Zeile lag die
   Erklaerung quer ueber die Seite. Das schwebende Panel steht unter der
   Stelle, auf die geklickt wurde - naeher geht es nicht.

   Was es verdeckt, sind ein, zwei Zeilen darunter, und es geht mit Escape,
   mit einem Klick daneben oder beim Scrollen wieder weg. Bei einem Lesetext
   von fuenf Zeilen ist das der bessere Tausch.                              */

/* --- Vokabel-Netz ---------------------------------------------------------
   Die Zeichenflaeche bekommt eine feste Hoehe: vis-network misst seinen
   Container, und ein Container, der sich nach seinem Inhalt richtet, waere
   beim ersten Zeichnen null Pixel hoch.                                     */

.graphwrap {
  border: 1px solid var(--border); border-radius: 4px; background: var(--surface);
  overflow: hidden;
}
#graph { height: min(68vh, 640px); background: var(--surface-hover); }

.graphlegend {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 11px 18px; border-top: 1px solid var(--border);
  font-size: 12px; color: var(--text-muted);
}
.graphlegend .key { display: inline-flex; align-items: center; gap: 6px; }
.graphlegend .key .dot { width: 9px; height: 9px; border-radius: 999px; border: 1.5px solid; }
/* Dieselben Werte wie ARTICLE und CHUNK in graph.js: Die Legende zeigte
   Wortgruppen gruen und Artikel als Punkt, gezeichnet sind sie beige und als
   Kasten. Wer die Werte dort aendert, aendert sie hier mit. */
.graphlegend .key-article .dot { width: 14px; height: 9px; border-radius: 3px; background: #DCE8F5; border-color: #2A3F5F; }
.graphlegend .key-chunk .dot { background: #FBEEDB; border-color: #8B6438; }

/* Die Wortfamilie. Ein Farbton je Wortart, dieselben Werte wie in graph.js -
   fuenf sind das Aeusserste, was sich noch auseinanderhalten laesst.          */
.graphlegend .sep { width: 1px; height: 13px; background: var(--border); }
.graphlegend .key-synonym .dot { background: #E4EFE3; border-color: #3F6B45; }
.graphlegend .key-nomen .dot { background: #EAE4F3; border-color: #5B4A80; }
.graphlegend .key-verb .dot { background: #DCEDEC; border-color: #2F6E6A; }
.graphlegend .key-adjektiv .dot { background: #F6E3E6; border-color: #8A4A58; }
.graphlegend .key-gegenteil .dot { background: #E7E9ED; border-color: #5C6B7F; }
.graphlegend .graphstatus { font-family: var(--mono); font-size: 11.5px; color: var(--text-muted); }

/* Mehr vom Netz - dieselbe Pillenleiste wie die Wahl in Mein Netz, aber
   Handlungen und keine Schalter: kein gedrueckter Zustand. Sie liegt oben
   rechts auf der Zeichenflaeche, wo man nach "mehr" sucht, und nicht in der
   Legende, die bei 1280 px sonst in eine zweite Zeile umbricht.            */
.graphwrap { position: relative; }
.graphmehr {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  display: inline-flex; gap: 4px; padding: 3px; background: var(--pill-track); border-radius: 10px;
  box-shadow: 0 1px 2px rgba(11, 26, 42, 0.08);
}
.graphmehr:not(:has(button:not([hidden]))) { display: none; }
.graphmehr button {
  height: 28px; padding: 0 12px; border: none; border-radius: 8px; background: var(--surface);
  font: inherit; font-size: 12.5px; font-weight: 500; color: var(--text-strong); cursor: pointer;
}
#graph-mehr:not([hidden]) + #graph-alle { background: none; color: var(--text-muted); }
.graphmehr button:hover { color: var(--accent-text); }
.graphmehr button:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 1px; }

.graphwrap .hint { margin: 14px 18px; }

/* Seitenteil und Liste unter dem Netz (UX netz-3). Die Karte nimmt die
   Gestalt aus Mein Netz (.netzkarte); die Liste ist der Weg fuer die
   Tastatur. */
.graphunten { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; margin-top: 16px; }
.graphkarte { flex: 1 1 320px; }
.graphkartenzeile { margin: 10px 0 4px; font-size: 13px; color: var(--text-muted); }
.graphkartenliste { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; }
.graphkartenliste a, .graphkartenliste button {
  font: inherit; font-size: 14px; color: var(--primary); text-align: left; background: none; border: 0;
  padding: 4px 0; cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--border);
}
.graphlesen { display: inline-flex; margin-top: 12px; font-weight: 600; color: var(--primary); }
.graphlesen[hidden] { display: none; }
.graphliste {
  flex: 1 1 320px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  padding: 0 16px;
}
.graphliste summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; font-weight: 600; font-size: 14px; }
.graphlistehinweis { margin: 0 0 8px; font-size: 12.5px; color: var(--text-muted); }
.graphliste ul { margin: 0 0 12px; padding: 0; list-style: none; max-height: 320px; overflow-y: auto; }
.graphliste li button {
  width: 100%; min-height: 36px; text-align: left; font: inherit; font-size: 13.5px; color: var(--text);
  background: none; border: 0; border-top: 1px solid var(--border); cursor: pointer; padding: 0 4px;
}
.graphliste li button:hover, .graphliste li button:focus-visible { background: var(--surface-hover); }
.graphliste li.art-chunk button::before { content: '●'; color: #8B6438; margin-right: 8px; font-size: 10px; }
.graphliste li.art-word button::before { content: '●'; color: #5B4A80; margin-right: 8px; font-size: 10px; }
.graphliste li.art-article button::before { content: '■'; color: #2A3F5F; margin-right: 8px; font-size: 10px; }

/* --- Der Lernzettel -------------------------------------------------------
   Der Abschluss eines gelesenen Artikels: drei Punkte und ein Merksatz. Er
   steht unter der Liste "In diesem Text".

   Papier, aber kein cremefarbenes. Die alte Fassung dieser Anwendung war
   creme, und sie ist mit Absicht weg; ein warmes Blatt mitten in einem kuehlen
   System waere ein Rueckfall und kein Zitat. Das Papier ist deshalb ein sehr
   helles Grau mit einem Karo darin - was einen Zettel zum Zettel macht, ist
   das Raster und nicht die Waerme.

   Die Flaechen der Kaesten sind die Stufenfarben aus der Wortgruppen-Liste,
   und wie dort stehen sie als Literalwerte da und nicht als --ok-*: Im Reader
   bedeutet dieses Gruen die Stufe A1 und nicht "in Ordnung". Hier sagen sie
   ueberhaupt nichts aus - sie halten drei Kaesten auseinander, mehr nicht.
   Und die Lernfarbe kommt genau einmal vor: als Textmarker unter den
   Wendungen. Das ist dieselbe Regel wie im Lesetext, nur mit dem breiteren
   Strich, den ein Zettel vertraegt.                                          */
.zettel {
  margin-top: 34px; padding: 26px 30px 30px;
  border: 1px solid var(--border); border-radius: 4px;
  background-color: #FCFCFD;
  background-image:
    linear-gradient(to right, rgba(147, 160, 174, 0.13) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(147, 160, 174, 0.13) 1px, transparent 1px);
  background-size: 26px 26px;
  box-shadow: 0 1px 2px rgba(11, 26, 42, 0.04), 0 14px 30px -24px rgba(11, 26, 42, 0.5);
}

.zettel-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.zettel-head h2 {
  margin: 0; font-family: 'Caveat', 'Segoe Script', cursive;
  font-size: 42px; font-weight: 700; line-height: 1; color: var(--text-strong); letter-spacing: 0.01em;
}
.zettel-head .swoosh { display: block; margin: 2px 0 0; color: var(--text-faint); }
/* Welcher Artikel - fuer den Fall, dass jemand den Zettel
   abfotografiert und ihn spaeter ohne die Seite darum ansieht. */
.zettel-head .ref {
  margin-left: auto; font-family: 'Caveat', 'Segoe Script', cursive;
  font-size: 19px; color: var(--text-muted);
}

.zettel-body { display: grid; grid-template-columns: minmax(0, 1fr) 268px; gap: 26px; margin-top: 18px; }

.zettel .points { display: flex; flex-direction: column; gap: 12px; }
.zettel .point {
  display: flex; gap: 13px; align-items: flex-start;
  border: 2px dashed; border-radius: 10px; padding: 13px 16px 15px;
}
/* Die leichte Drehung ist der ganze Trick: Drei Kaesten, die exakt
   uebereinanderstehen, sind ein Formular.

   Der Ton des Kastens steht als eigene Eigenschaft da, weil drei Stellen ihn
   tragen: die Ueberschrift, die Nummer im Kreis und die Striche vor den
   Unterpunkten. Ohne sie stuenden hier neun Regeln statt drei. */
.zettel .point-0 { --kasten: #9A4A3F; transform: rotate(-0.35deg); --flaeche: #F4E0DB; background: var(--flaeche); border-color: #D6ABA3; }
.zettel .point-1 { --kasten: #3F6B45; transform: rotate(0.25deg); --flaeche: #E4EFE3; background: var(--flaeche); border-color: #A9C6AC; }
.zettel .point-2 { --kasten: #35547C; transform: rotate(-0.2deg); --flaeche: #DCE6F3; background: var(--flaeche); border-color: #A3B7D3; }
.zettel .point h3, .zettel .point .num { color: var(--kasten); }

.zettel .point .num { position: relative; flex: 0 0 34px; height: 34px; margin-top: 1px; }
.zettel .point .num svg { position: absolute; inset: 0; }
.zettel .point .num span {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: 'Caveat', 'Segoe Script', cursive; font-size: 22px; font-weight: 700; padding-bottom: 2px;
}
.zettel .point h3 {
  margin: 1px 0 3px; font-family: 'Caveat', 'Segoe Script', cursive;
  font-size: 25px; font-weight: 700; line-height: 1.12; letter-spacing: 0.01em;
}
/* Die Unterpunkte. Der Gedankenstrich sitzt als ::before und nicht als
   list-style: So bleibt die zweite Zeile eines Punktes auf der Fluchtlinie der
   ersten, und der Strich traegt den Ton des Kastens statt der Textfarbe. */
.zettel .point ul {
  display: flex; flex-direction: column; gap: 5px;
  margin: 5px 0 0; padding: 0; list-style: none;
}
.zettel .point li {
  position: relative; padding-left: 15px;
  font-family: var(--read);
  font-size: 16.5px; line-height: 1.5; color: var(--text); text-wrap: pretty;
}
.zettel .point li::before {
  content: '–'; position: absolute; left: 0; top: 0;
  color: var(--kasten); opacity: 0.75;
}

.zettel .side { display: flex; flex-direction: column; gap: 20px; }
.zettel .postit {
  position: relative; transform: rotate(-2.4deg); padding: 18px 18px 20px;
  background: #F6E3E6;
  box-shadow: 0 1px 1px rgba(11, 26, 42, 0.08), 0 12px 20px -16px rgba(90, 40, 55, 0.75);
}
/* Ein Streifen Klebeband. Er ist kein Schmuck, sondern die Auskunft, dass der
   Zettel aufgeklebt ist und nicht zum Blatt darunter gehoert - deshalb steht
   der Merksatz auch quer. */
.zettel .postit .tape {
  position: absolute; top: -11px; left: 50%; width: 74px; height: 21px;
  transform: translateX(-50%) rotate(-1.6deg);
  background: rgba(222, 228, 234, 0.72);
  border-left: 1px solid rgba(147, 160, 174, 0.3);
  border-right: 1px solid rgba(147, 160, 174, 0.3);
}
.zettel .postit .label {
  display: block; margin-bottom: 4px; font-family: 'Caveat', 'Segoe Script', cursive;
  font-size: 20px; font-weight: 700; color: #8A4A58;
}
.zettel .postit p {
  margin: 0; font-family: 'Patrick Hand', 'Segoe Print', cursive;
  font-size: 20px; line-height: 1.42; color: #57282C; text-wrap: pretty;
}

/* Auf dem Telefon steht der Zettel in einer Spalte: Das Post-it wandert hinter
   die drei Punkte, die Wendungen untereinander. Der Rand wird schmaler - 30px
   Innenrand auf einem 342px breiten Blatt liesse fuer den Text nicht genug
   uebrig. */
@media (max-width: 720px) {
  .zettel-body { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .zettel .postit { margin: 4px 6px 0; }
}
/* Am Telefon sitzt die Nummer auf dem Rand des Kastens, wie ein Reiter, und
   Ueberschrift und Unterpunkte beginnen an seiner Kante: Sonst blieben von
   390px fuer den Text keine 250 uebrig, und jeder Satz brach nach drei
   Woertern um. Ein Rand bleibt - zum Durchatmen, nicht als Einzug.
   text-wrap: pretty faellt hier weg: Es zog in der schmalen Spalte ganze
   Woerter in die naechste Zeile und liess rechts Luecken, die wie ein Fehler
   aussahen. */
@media (max-width: 560px) {
  .zettel { margin-top: 24px; padding: 16px 12px 20px; background-size: 24px 24px; }
  .zettel-head h2 { font-size: 36px; }
  .zettel-head .ref { margin-left: 0; }
  .zettel .points { gap: 22px; padding-top: 12px; }
  .zettel .point { display: block; position: relative; padding: 16px 14px 14px; }
  .zettel .point .num {
    position: absolute; top: -16px; left: 12px; width: 30px; height: 30px;
    border-radius: 50%; background: var(--flaeche);
  }
  .zettel .point .num svg { width: 100%; height: 100%; }
  .zettel .point .num span { font-size: 19px; }
  .zettel .point ul { margin-top: 6px; }
  .zettel .point li { padding-left: 13px; text-wrap: wrap; }
}

/* --- Die Tuer: Anmeldung und Abmelden -------------------------------------
   Schmal, mittig, ohne Schmuck. Wer hier steht, soll eine Sache tun und sonst
   nichts sehen - deshalb traegt die Seite auch keinen .pagehead.          */

.gate {
  max-width: 340px; margin: 12vh auto 0; padding: 24px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
}
.gate h1 {
  font-family: var(--display); font-size: 20px; font-weight: 700; letter-spacing: -0.02em;
  color: var(--text-strong); margin: 0 0 6px;
}
.gate form { margin: 16px 0 0; }
.gatehint { font-size: 12.5px; line-height: 1.6; color: var(--text-muted); margin: 0; }
.gatehint code { font-family: var(--mono); font-size: 11.5px; }
/* Dieselben Toene wie .pill-failed in der Queue - eine Fehlfarbe reicht. */
.gateerror {
  margin: 14px 0 0; padding: 9px 12px; border-radius: 4px;
  background: #F4E0DB; color: #9A4A3F; font-size: 12.5px;
}
.gatelabel {
  display: block; font-size: 12px; font-weight: 600; color: var(--text-muted);
  margin-bottom: 6px;
}
.gate input[type='password'] {
  width: 100%; height: 34px; padding: 0 10px; box-sizing: border-box;
  border: 1px solid var(--border); border-radius: 4px;
  background: var(--bg); color: var(--text-strong);
  font-family: var(--mono); font-size: 14px; letter-spacing: 0.15em;
}
.gate input[type='password']:focus { outline: none; border-color: var(--primary); }
.gatesubmit { margin-top: 14px; width: 100%; justify-content: center; }

/* Der Weg hinaus steht oben rechts im Seitenkopf der Queue. */
.pagehead { position: relative; }
.signout { position: absolute; top: 0; right: 0; margin: 0; }

/* --- Fusszeile und Rechtsseiten ----------------------------------------
   Die Fusszeile traegt Impressum und Datenschutz, und die muessen von jeder
   Seite aus erreichbar sein. Leise gehalten: Sie soll da sein, wenn jemand
   sie sucht, und nicht mit dem Lesetext konkurrieren. */

.seitenfuss {
  max-width: 720px; margin: 48px auto 32px; padding: 20px 16px 0;
  border-top: 1px solid var(--border);
  display: flex; flex-wrap: wrap; gap: 8px 24px;
  align-items: baseline; justify-content: space-between;
}
.seitenfuss .fussnote {
  margin: 0; font-size: 12.5px; color: var(--text-muted); max-width: 44ch;
  text-wrap: pretty;
}
.seitenfuss .fusslinks { display: flex; gap: 16px; flex-wrap: wrap; }
.seitenfuss .fusslinks a { font-size: 12.5px; color: var(--text-muted); }
.seitenfuss .fusslinks a:hover { color: var(--text); }

/* vorlaeufig - wandert ueber eine Entwurfstafel in den Kopf.
   Das Konto im Fuss: eine eigene Zeile, so leise wie die Links daneben. */
.seitenfuss .konto {
  flex: 1 0 100%; display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center;
  font-size: 12.5px; color: var(--text-muted);
}
.seitenfuss .konto form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0; }
.seitenfuss .konto input[type="text"] { min-width: 0; flex: 1 1 16em; }
.seitenfuss .konto .kontomeldung { flex: 1 0 100%; margin: 0; color: var(--text-muted); }
/* Anonym nur der Einstieg; das Formular kommt beim Aufklappen nach. */

.rechtseite { max-width: 680px; margin: 0 auto; padding: 24px 16px 8px; }
/* "Datenschutzerklaerung" ist breiter als ein Telefon mit 360px: Die
   Seite scrollte seitlich (UX recht-1). Trennen, notfalls brechen. */
.rechtseite h1 { margin-bottom: 4px; hyphens: auto; overflow-wrap: break-word; }
.rechtseite h2 { margin-top: 28px; font-size: 17px; }
.rechtseite p, .rechtseite li { text-wrap: pretty; line-height: 1.6; }
.rechtseite ul { padding-left: 20px; }
.rechtseite .rechtlead { color: var(--text-muted); margin-bottom: 20px; }

/* Eine fehlende Angabe wird benannt und nicht versteckt: Die fehlende ist ein
   offener Punkt, eine erfundene waere eine falsche Auskunft. */
.rechtfehlt {
  margin: 16px 0 24px; padding: 12px 14px;
  border: 1px dashed var(--border); border-radius: 4px;
  background: var(--info-surface); font-size: 14px;
}
.rechtluecke { color: var(--text-muted); font-style: italic; }

/* --- Die Grammatikseite ---------------------------------------------------

   Nachschlagewerk, nicht Mitschrift: Grotesk und Serife wie ueberall, keine
   Handschrift - die bleibt dem Lernzettel. Gezeichnet ist nur der Baum.

   Die fuenf Stufenfarben stehen schon weiter oben an den Wortgruppen
   (.chunklist .item.level-*) und in der Wortfamilie (.chunkpop .wordfamily
   .level-*). Hier bekommen sie zum ersten Mal Variablennamen, weil drei
   Dinge sie brauchen - Pille, Spaltenkante und Streifen. Dieselben Werte,
   nicht neue: Eine Stufe sieht auf dieser Seite aus wie im Panel daneben. */
.grammatik .a1 { --flaeche: #E4EFE3; --kante: #A9C6AC; --schrift: #3F6B45; }
.grammatik .a2 { --flaeche: #DCEDEC; --kante: #9CC3C0; --schrift: #2F6E6A; }
.grammatik .b1 { --flaeche: #DCE6F3; --kante: #A3B7D3; --schrift: #35547C; }
.grammatik .b2 { --flaeche: #EAE4F3; --kante: #B7A9CE; --schrift: #5B4A80; }
.grammatik .c1 { --flaeche: #F6E3E6; --kante: #D6AAB3; --schrift: #8A4A58; }

/* Die Leiste: links die Sicht, rechts das Sieb. Beide sind Verweise - der
   Zustand steht in der Adresse, nicht in einer Sitzung. */
.grammatik .leiste { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin: 4px 0 6px; }
.grammatik .sicht { display: flex; gap: 4px; padding: 3px; background: var(--pill-track); border-radius: 10px; }
.grammatik .sicht a {
  padding: 6px 13px; border-radius: 8px; text-decoration: none;
  font-size: 13.5px; font-weight: 500; color: var(--text-muted);
}
.grammatik .sicht a:hover { color: var(--text-strong); }
.grammatik .sicht a[aria-current='true'] { background: var(--primary); color: #FFFFFF; font-weight: 600; }

.grammatik .sieb { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-left: auto; }
.grammatik .sieb .wort { font-size: 12.5px; color: var(--text-muted); margin-right: 2px; }
.grammatik .sieb a {
  display: inline-flex; align-items: center; gap: 6px; text-decoration: none;
  border: 1px solid var(--kante); background: var(--flaeche); color: var(--schrift);
  border-radius: 999px; padding: 5px 12px 6px;
  font-family: var(--mono); font-size: 12px; font-weight: 500;
}
/* Abgewaehlt heisst blass und nicht weg: Die Stufe muss anklickbar bleiben,
   sonst kaeme man nicht zurueck. */
.grammatik .sieb a.aus { background: var(--surface); border-color: var(--border); color: var(--text-muted); }
.grammatik .sieb a .zahl { font-size: 11px; opacity: 0.75; }
.grammatik .sieb a .haken { font-family: var(--body); font-size: 11px; margin-right: -2px; }
.grammatik .sieb a.zurueck { border-style: dashed; border-color: var(--border); background: none; color: var(--text-muted); }

/* Zwei Spalten, damit die zehn Sachgebiete auf einen Blick passen; jedes
   Gebiet bleibt zusammen. */
.grammatik .baum { columns: 2; column-gap: 22px; margin-top: 14px; }
.grammatik .ast {
  break-inside: avoid; margin: 0 0 18px; padding: 15px 18px 17px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
}
.grammatik .ast h2 {
  display: flex; align-items: baseline; gap: 9px; margin: 0 0 4px;
  font-size: 16.5px; font-weight: 700; color: var(--text-strong);
}
.grammatik .ast h2 .zahl { font-family: var(--mono); font-size: 11.5px; font-weight: 500; color: var(--text-muted); }

.grammatik .verlauf {
  display: flex; height: 4px; margin: 0 0 12px;
  border-radius: 2px; overflow: hidden; background: var(--pill-track);
}
.grammatik .verlauf span { display: block; height: 100%; background: var(--kante); }

/* Die Zweige. Der senkrechte Strich ist der Stamm, der waagerechte Stummel je
   Zeile der Zweig - gezeichnet und nicht als Bild, damit beides mitwaechst,
   wenn ein Thema zwei Zeilen braucht. */
.grammatik .zweige { list-style: none; margin: 0; padding: 0 0 0 4px; }
.grammatik .zweige li { position: relative; display: flex; align-items: flex-start; padding: 3px 0 3px 18px; }
.grammatik .zweige li::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 1px; background: var(--border);
}
.grammatik .zweige li:last-child::before { bottom: auto; height: 13px; }
.grammatik .zweige li::after {
  content: ''; position: absolute; left: 0; top: 13px; width: 11px; height: 1px; background: var(--border);
}
.grammatik .zweige .pille {
  flex: 0 0 auto; margin-top: 1px;
  border: 1px solid var(--kante); background: var(--flaeche); color: var(--schrift);
  border-radius: 999px; padding: 1px 7px 2px;
  font-family: var(--mono); font-size: 10.5px; font-weight: 500;
}
.grammatik .zweige .thema { margin-left: 9px; font-size: 14px; line-height: 1.4; color: var(--text); text-wrap: pretty; }
.grammatik .zweige .tiefer { margin-left: 8px; font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.grammatik .zweige .wieder {
  margin-left: 4px; border: 1px solid var(--kante); color: var(--schrift);
  border-radius: 999px; padding: 0 5px 1px; font-family: var(--mono); font-size: 9.5px;
}

/* Die zweite Sicht. Hier traegt die Farbe nichts bei, was die Spalte nicht
   schon sagt - sie bleibt trotzdem, damit eine Stufe zwischen den Sichten
   wiedererkannt wird. */
.grammatik .spalten {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 14px; margin-top: 14px; align-items: start;
}
.grammatik .spalte {
  padding: 14px 14px 16px; background: var(--surface);
  border: 1px solid var(--border); border-top: 3px solid var(--kante); border-radius: 12px;
}
.grammatik .spalte h2 {
  display: flex; align-items: baseline; gap: 7px; margin: 0 0 3px;
  font-family: var(--mono); font-size: 14px; font-weight: 600; color: var(--schrift);
}
.grammatik .spalte h2 .zahl { font-size: 11px; font-weight: 500; color: var(--text-muted); }
.grammatik .spalte .wozu { display: block; margin: 0 0 12px; font-size: 11.5px; line-height: 1.4; color: var(--text-muted); }
.grammatik .gruppe { margin: 0 0 11px; }
.grammatik .gruppe h3 {
  margin: 0 0 3px; font-size: 11px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted);
}
.grammatik .gruppe ul { list-style: none; margin: 0; padding: 0; }
.grammatik .gruppe li { position: relative; padding: 2px 0 2px 10px; font-size: 13px; line-height: 1.38; color: var(--text); text-wrap: pretty; }
.grammatik .gruppe li::before {
  content: ''; position: absolute; left: 0; top: 9px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--kante);
}

/* Auf dem Telefon faellt die zweite Spalte weg, und die fuenf Stufenspalten
   legen sich untereinander: Fuenf Spalten auf 390px waeren je 70 Pixel. */
@media (max-width: 780px) {
  .grammatik .baum { columns: 1; }
  .grammatik .spalten { grid-template-columns: minmax(0, 1fr); }
  .grammatik .sieb { margin-left: 0; }
}

/* 83 Themen untereinander, jedes 17px hoch: Am Telefon traf man das
   Nachbarthema. Auf groben Zeigern wird die ganze Zeile zur Flaeche von
   44px - der Verweis spannt ein ::after ueber die Zeile, die Pille und das
   "vertieft" daneben fangen den Finger also mit. Der Zweigstummel rueckt in
   die neue Mitte. Die Schalter oben bekommen dieselbe Hoehe. */
@media (pointer: coarse) {
  .grammatik .zweige li { min-height: 44px; align-items: center; padding-block: 0; }
  .grammatik .zweige li::after { top: 22px; }
  .grammatik .zweige li:last-child::before { height: 22px; }
  .grammatik .zweige .pille { margin-top: 0; }
  .grammatik .gruppe li { min-height: 44px; display: flex; align-items: center; padding-block: 0; }
  .grammatik .gruppe li::before { top: 20px; }
  .grammatik .zweige a.thema::after,
  .grammatik .gruppe a::after { content: ''; position: absolute; inset: 0; }
  .grammatik .gruppe li { position: relative; }
  .grammatik .sicht a { display: inline-flex; align-items: center; min-height: 38px; }
  .grammatik .sieb a { min-height: 40px; box-sizing: border-box; }
}

/* --- Die Erklaerseite eines Grammatikthemas -------------------------------

   Drei Teile in der Reihenfolge, in der man sie braucht: Regel, Beispiel,
   Uebung. Der Lesetext steht in der Serife wie jeder deutsche Text der App,
   die Bedienung in der Grotesk - die Uebung gehoert zur Bedienung, ihre
   Saetze aber zum Lesetext. Deshalb laeuft die Serife bis in die Aufgabe
   hinein und hoert erst am Knopf auf. */
.grammatik.thema { max-width: 720px; }

.grammatik .kruemel { display: flex; gap: 8px; align-items: baseline; margin-bottom: 10px; font-size: 13px; color: var(--text-muted); }
.grammatik .kruemel a { color: var(--text-muted); text-decoration: none; }
.grammatik .kruemel a:hover { color: var(--text-strong); text-decoration: underline; }

.grammatik.thema .pagehead h1 { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.grammatik.thema .pagehead .pille {
  border: 1px solid var(--kante); background: var(--flaeche); color: var(--schrift);
  border-radius: 999px; padding: 2px 10px 3px;
  font-family: var(--mono); font-size: 13px; font-weight: 500;
}
.grammatik.thema .weiter { font-family: var(--display); font-size: 13.5px; color: var(--text-muted); }
.grammatik.thema .weiter .wieder {
  border: 1px solid var(--kante); color: var(--schrift); border-radius: 999px;
  padding: 0 6px 1px; font-family: var(--mono); font-size: 11px;
}

/* Was noch nicht geschrieben ist, wird benannt und nicht versteckt - dieselbe
   Haltung wie bei den fehlenden Angaben auf den Rechtsseiten. */
.grammatik .nochnicht {
  margin: 18px 0; padding: 16px 18px;
  border: 1px dashed var(--border); border-radius: 8px; background: var(--surface);
  font-family: var(--read); font-size: 16px; line-height: 1.6; color: var(--text-muted);
}
.grammatik .nochnicht p { margin: 0 0 8px; }
.grammatik .nochnicht p:last-child { margin-bottom: 0; font-family: var(--display); font-size: 14px; }

.grammatik.thema section { margin-top: 26px; }
.grammatik.thema h2 { margin: 0 0 10px; font-size: 15px; font-weight: 600; color: var(--text-strong); }

.grammatik .erklaerung p { margin: 0; font-family: var(--read); font-size: 17.5px; line-height: 1.62; color: var(--text); text-wrap: pretty; }
/* Der Merksatz traegt die Lernfarbe - dieselbe, mit der im Lesetext die
   Wortgruppen unterstrichen sind. Sie steht in dieser App fuer "das hier
   nimmst du mit". */
.grammatik .merksatz {
  margin-top: 14px !important; padding: 11px 14px;
  border-left: 3px solid var(--accent); border-radius: 0 6px 6px 0;
  background: var(--accent-surface); color: var(--accent-text) !important;
  font-size: 16.5px !important;
}

.grammatik .beispiele ul { list-style: none; margin: 0; padding: 0; }
.grammatik .beispiele li {
  padding: 10px 14px; margin-bottom: 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
}
.grammatik .beispiele .satz { display: block; font-family: var(--read); font-size: 17px; line-height: 1.5; color: var(--text-strong); }
.grammatik .beispiele .hinweis { display: block; margin-top: 3px; font-size: 12.5px; color: var(--text-muted); }

.grammatik .uebungen .anleitung { margin: -4px 0 12px; font-size: 13px; color: var(--text-muted); }
.grammatik .aufgaben { margin: 0; padding: 0 0 0 22px; }
.grammatik .aufgaben li {
  margin-bottom: 10px; padding: 9px 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  font-family: var(--read); font-size: 17px; line-height: 1.7; color: var(--text-strong);
}
/* Das Feld sitzt in der Zeile und nicht darunter: Der Satz soll ein Satz
   bleiben, in dem etwas fehlt. */
/* Ausdruecklich nur das Textfeld. Seit es die Auswahlaufgabe gibt, steht in
   derselben Liste auch ein Radiobutton - und der wurde von der Breitenregel
   auf 8.5em gezogen, sodass zwischen dem Knopf und seiner Beschriftung ein
   Loch von achtzig Pixeln klaffte. */
.grammatik .aufgaben input[type="text"] {
  width: 8.5em; margin: 0 2px; padding: 2px 8px 3px;
  border: 0; border-bottom: 2px solid var(--text-faint); border-radius: 3px 3px 0 0;
  background: var(--surface-hover); color: var(--text-strong);
  font-family: var(--read); font-size: 17px;
}
.grammatik .aufgaben input[type="text"]:focus { outline: 2px solid var(--primary); outline-offset: 1px; }

/* Auf dem Telefon schmaler - sonst bricht die Zeile VOR dem Feld.
   Ein Eingabefeld ist unteilbar: Passt es nicht mehr in die Restzeile, rutscht
   es ganz in die naechste, und aus dem Satz werden drei Zeilen mit einem
   Kasten dazwischen. Gemessen bei 390px: 8.5em sind rund 145px, und nach vier
   Woertern ist links nichts mehr frei.

   Die Breite bleibt fest und richtet sich NICHT nach der Loesung. Ein Feld,
   das genau so lang ist wie die Antwort, verraet sie halb - wer "geh" erwartet,
   tippt nicht "gehen". Lieber ein Feld, das fuer alles gleich aussieht. */
@media (max-width: 480px) {
  .grammatik .aufgaben { padding-left: 18px; }
  .grammatik .aufgaben li { padding: 9px 10px; font-size: 16px; line-height: 1.8; }
  /* Ausdruecklich nur das Textfeld. Seit es die Auswahlaufgabe gibt, steht in
   derselben Liste auch ein Radiobutton - und der wurde von der Breitenregel
   auf 8.5em gezogen, sodass zwischen dem Knopf und seiner Beschriftung ein
   Loch von achtzig Pixeln klaffte. */
.grammatik .aufgaben input[type="text"] { width: 5.5em; font-size: 16px; padding: 2px 6px 3px; }
}
.grammatik .aufgaben li.richtig { border-color: #A9C6AC; background: #F3F8F2; }
.grammatik .aufgaben li.falsch { border-color: #D6ABA3; background: #FBF4F2; }
.grammatik .aufgaben li.richtig input { border-bottom-color: var(--ok-text); }
.grammatik .aufgaben li.falsch input { border-bottom-color: #9A4A3F; }
.grammatik .aufgaben .marke { margin-left: 8px; font-family: var(--display); font-weight: 700; }
/* Der Behaelter, auf den das Eingabefeld mit aria-describedby zeigt. Er
   darf die Anordnung nicht aendern: Wink, Loesung und "noch einmal" standen
   vorher als Geschwister im li, und .wink ist display:block. Ein Block in
   einem inline-Kasten ginge, aber als Block ist es dasselbe wie vorher. */
.grammatik .aufgaben .rueckmeldung { display: block; }
.grammatik .aufgaben li.richtig .marke { color: var(--ok-text); }
.grammatik .aufgaben li.falsch .marke { color: #9A4A3F; }
.grammatik .aufgaben .loesung { margin-left: 8px; font-family: var(--display); font-size: 13px; color: #9A4A3F; }
.grammatik .aufgaben .loesung strong { font-family: var(--read); font-size: 16px; }
/* Gemessen am 01.10.2026: Der Wink stand in --text-faint auf der
   Fehlerflaeche bei 2,45:1, die Anleitung bei 2,66:1 auf weiss. WCAG AA
   fordert 4,5:1 - das ist nicht knapp verfehlt, sondern gut die Haelfte.
   Und es trifft den Satz, der in der Minute erscheint, in der jemand nicht
   weiterweiss: auf dem Telefon bei Tageslicht war er schlicht weg.
   --text-muted bringt 5,7:1. */
.grammatik .aufgaben .wink { display: block; margin-top: 2px; font-family: var(--display); font-size: 13.5px; color: var(--text-muted); }

.grammatik .absenden { display: flex; align-items: center; gap: 14px; margin-top: 14px; flex-wrap: wrap; }
.grammatik .absenden button {
  cursor: pointer; border: 0; border-radius: 8px;
  background: var(--primary); color: #FFFFFF;
  padding: 9px 20px 10px; font-family: var(--display); font-size: 14px; font-weight: 600;
}
.grammatik .absenden button:hover { background: var(--primary-dark); }
.grammatik .absenden .stand { font-size: 13.5px; color: var(--text-muted); }

/* Der Verweis vom Baum auf die Erklaerseite. Nur Themen, zu denen schon etwas
   geschrieben ist, sind Verweise - ein Link auf eine leere Seite ist ein
   gebrochenes Versprechen. */
.grammatik .zweige a.thema { margin-left: 0; color: var(--text); text-decoration: none; border-bottom: 1px solid var(--border); }
.grammatik .zweige a.thema:hover { color: var(--text-strong); border-bottom-color: var(--text-faint); }

/* Ein Thema, zu dem noch nichts geschrieben ist. Erreichbar bleibt es - die
   Seite sagt dann selbst, dass sie noch kommt -, aber der gepunktete Strich
   sagt es schon vorher. */
.grammatik .zweige a.thema.offen,
.grammatik .gruppe a.offen { color: var(--text-muted); border-bottom-style: dotted; }
/* Der gepunktete Strich allein wurde uebersehen: Man tippte auf ein leeres
   Thema. Das Wort sagt es, bevor man tippt. */
.grammatik .bald {
  margin-left: 6px; font-size: 11px; font-weight: 500; color: var(--text-muted);
  border: 1px dashed var(--border); border-radius: 999px; padding: 0 6px 1px; white-space: nowrap;
}
.grammatik .gruppe a { color: var(--text); text-decoration: none; border-bottom: 1px solid var(--border); }
.grammatik .gruppe a:hover { color: var(--text-strong); border-bottom-color: var(--text-faint); }

/* --- Der Lesetisch: Grammatikseiten freigeben -----------------------------

   Ein Entwurf steht hier ganz da, damit man ihn lesen kann, bevor man ihn
   verantwortet. Er sieht deshalb aus wie die Seite, die er werden will, nur
   enger gesetzt und mit den Loesungen sichtbar. */
.grammatik.lesetisch { max-width: 760px; }

.grammatik .entwurfband {
  margin: 0 0 20px; padding: 11px 15px;
  border: 1px dashed #D6ABA3; border-radius: 8px; background: #FBF4F2;
  font-size: 13.5px; line-height: 1.5; color: #7C3F35;
}
.grammatik .entwurfband strong { color: #9A4A3F; }
.grammatik .entwurfband a { margin-left: 4px; color: #9A4A3F; }

.grammatik .nebenan { margin: 6px 0 0; font-size: 13.5px; }

.grammatik .meldung {
  margin: 0 0 18px; padding: 10px 14px;
  border-left: 3px solid var(--accent); border-radius: 0 6px 6px 0;
  background: var(--accent-surface); color: var(--accent-text); font-size: 14px;
}

.grammatik .stand { display: flex; flex-wrap: wrap; gap: 18px; margin: 0 0 22px; font-size: 13.5px; color: var(--text-muted); }
.grammatik .stand strong { font-family: var(--mono); font-weight: 600; color: var(--text-strong); }
.grammatik .stand .aus { color: #9A4A3F; }
.grammatik .lesetisch .leer { font-family: var(--read); font-size: 16px; color: var(--text-muted); }

.grammatik .entwurf {
  margin: 0 0 20px; padding: 18px 20px 20px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
}
.grammatik .entwurfkopf { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.grammatik .entwurfkopf h2 { display: flex; align-items: center; gap: 9px; margin: 0; font-size: 18px; font-weight: 700; }
.grammatik .entwurfkopf h2 a { color: var(--text-strong); text-decoration: none; border-bottom: 1px solid var(--border); }
.grammatik .entwurfkopf h2 a:hover { border-bottom-color: var(--text-faint); }
.grammatik .entwurfkopf .pille {
  border: 1px solid var(--kante); background: var(--flaeche); color: var(--schrift);
  border-radius: 999px; padding: 1px 8px 2px; font-family: var(--mono); font-size: 11px; font-weight: 500;
}
.grammatik .entwurfkopf .lauf { margin-left: auto; font-family: var(--mono); font-size: 11.5px; color: var(--text-muted); }

.grammatik .entwurf .text { margin: 0; font-family: var(--read); font-size: 16.5px; line-height: 1.6; color: var(--text); }
.grammatik .entwurf .merksatz { margin-top: 10px !important; font-size: 15.5px !important; }

.grammatik .entwurf .beispiele { list-style: none; margin: 14px 0 0; padding: 0; }
.grammatik .entwurf .beispiele li { padding: 5px 0; border-top: 1px solid var(--border); }
.grammatik .entwurf .satz { font-family: var(--read); font-size: 16px; color: var(--text-strong); }
.grammatik .entwurf .hinweis { margin-left: 8px; font-size: 12px; color: var(--text-muted); }

.grammatik .entwurf .aufgaben { margin: 14px 0 0; padding: 0 0 0 20px; }
.grammatik .entwurf .aufgaben li { padding: 5px 0; border-top: 1px solid var(--border); }
/* Die Loesung steht offen daneben - hier wird nicht geuebt, hier wird
   geprueft, ob sie stimmt. */
.grammatik .entwurf .loesung {
  margin-left: 8px; padding: 1px 7px 2px; border-radius: 4px;
  background: var(--accent-surface); color: var(--accent-text);
  font-family: var(--read); font-size: 15px;
}
.grammatik .entwurf .neben,
.grammatik .entwurf .wink { margin-left: 8px; font-size: 12px; color: var(--text-muted); }

.grammatik .entscheidung { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
.grammatik .entscheidung form { margin: 0; }
.grammatik .entscheidung button {
  cursor: pointer; border: 1px solid transparent; border-radius: 8px;
  padding: 8px 18px 9px; font-family: var(--display); font-size: 13.5px; font-weight: 600;
}
.grammatik .entscheidung .ja { background: var(--accent); color: #FFFFFF; }
.grammatik .entscheidung .ja:hover { background: var(--accent-text); }
/* Verwerfen ist der stillere Knopf: Es ist die Entscheidung, die man nicht aus
   Versehen treffen soll - sie loescht den Text. */
.grammatik .entscheidung .nein { background: var(--surface); border-color: #D6ABA3; color: #9A4A3F; }
.grammatik .entscheidung .nein:hover { background: #FBF4F2; }
.grammatik .entscheidung .folge { font-size: 12.5px; color: var(--text-muted); }

.grammatik .zurueck { margin-top: 26px; font-size: 13.5px; }

/* --- Themenseite: Merkkasten und Beispielkarten ------------------------
   Nach den Lernkarten, die als Vorbild dienten: ein Merkkasten je Seite, und
   jede Regel in einer eigenen Karte statt in einer Zeile einer Aufzaehlung.

   Die Farbe kommt aus der Stufe des Themas (--flaeche/--kante/--schrift sind
   oben an .grammatik .a1 ff. gesetzt) - keine neue Farbwelt. Steht keine
   Stufe am Element, greifen die Ersatzwerte, und der Kasten sieht aus wie
   jeder andere ruhige Kasten der App. */

/* Die Stufe faerbt den Kasten. Das ist die eine Idee, die den Lernkarten
   ihre Uebersicht gibt: Die Farbe traegt eine Aussage und ist nicht Zierde.
   Hier sagt sie, auf welcher Stufe dieses Thema drankommt - dieselben fuenf
   Toene wie an den Wortgruppen im Lesetext und an den Pillen im Baum.

   Die Ersatzwerte greifen, wenn keine Stufe danebensteht; dann sieht der
   Kasten aus wie jeder andere ruhige Kasten der App. */
.grammatik .merkkasten {
  position: relative;
  margin: 18px 0 24px;
  padding: 16px 18px 16px 20px;
  border-radius: 4px;
  /* Der Rueckfall steht IN der Verwendung und nicht als eigene Zuweisung
     daneben. Setzte man hier --flaeche, --kante und --schrift selbst, gewaenne
     diese Regel gegen ".grammatik .b2" - gleiche Spezifitaet, spaeter im
     Stylesheet - und die Stufenfarbe kaeme nie an. Genau das ist mir beim
     ersten Anlauf passiert: Die Pille war violett, der Kasten blieb blau. */
  background: var(--flaeche, var(--info-surface));
  border: 1px solid var(--kante, var(--border));
  border-left: 4px solid var(--schrift, var(--text-strong));
}
.grammatik .merkkasten .marke {
  display: block; margin-bottom: 4px;
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--schrift, var(--text-strong));
}
.grammatik .merkkasten p {
  margin: 0; font-size: 16px; line-height: 1.5;
  color: var(--text-strong); text-wrap: pretty;
}

/* Die Karten. Der Satz ist das Erste, was man sieht - in einer Liste standen
   Satz und Hinweis nebeneinander und waren gleich laut, und man las den
   Hinweis zuerst. */
.grammatik .karten { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.grammatik .karten li {
  position: relative;
  padding: 14px 16px 14px 46px;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: 4px;
}
/* Die Zahl kommt aus dem ol, nicht aus dem Text: Wer eine Karte streicht,
   soll nicht umnummerieren muessen. */
.grammatik .karten { counter-reset: karte; }
.grammatik .karten li::before {
  counter-increment: karte; content: counter(karte);
  position: absolute; left: 14px; top: 13px;
  width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700;
  background: var(--pill-track); color: var(--text-faint);
}
/* Die Leseschrift, wie bei den Beispielen vorher auch: Das ist deutscher
   Text zum Lesen und keine Bedienung. Ohne diese Zeile gewinnt meine
   spaetere Regel gegen .grammatik .beispiele .satz - gleiche Spezifitaet,
   und der Satz staende ploetzlich in der Oberflaechenschrift. */
.grammatik .karten .satz {
  margin: 0; font-family: var(--read); font-size: 17px; line-height: 1.5;
  color: var(--text-strong); text-wrap: pretty;
}
.grammatik .karten .hinweis {
  margin: 6px 0 0; font-size: 13px; color: var(--text-muted); text-wrap: pretty;
}

@media (max-width: 480px) {
  .grammatik .karten li { padding: 12px 14px 12px 42px; }
  .grammatik .karten .satz { font-size: 16px; }
}

/* Der Aufruf zum zweiten Versuch. Er steht in der Lernfarbe und nicht in
   Rot: Das Kreuz daneben sagt schon, dass es danebenging - diese Zeile sagt
   das Gegenteil davon, naemlich dass es weitergeht. */
.grammatik .aufgaben .nochmal {
  display: inline-block; margin-left: 8px;
  font-size: 12.5px; font-weight: 500; color: var(--accent, var(--primary));
}

/* --- Die Auswahlaufgabe ---------------------------------------------------

   Sie prueft, was eine Luecke nicht pruefen kann: welche von mehreren richtig
   gebildeten Formen zur Situation passt. Deshalb steht die Frage in der
   Grotesk - sie ist die Anweisung - und die Antworten in der Leseschrift:
   Das sind deutsche Saetze zum Lesen, nicht Knoepfe. */
.grammatik .aufgaben .frage {
  margin: 0 0 8px; font-size: 14px; line-height: 1.5; color: var(--text-strong);
}
.grammatik .aufgaben .wahl { list-style: none; margin: 0; padding: 0; }
.grammatik .aufgaben .wahl li { margin: 0 0 4px; padding: 0; border: 0; background: none; }
.grammatik .aufgaben .wahl label {
  display: flex; align-items: baseline; gap: 9px;
  padding: 6px 9px; border-radius: 8px; cursor: pointer;
  font-family: var(--read); font-size: 16px; line-height: 1.5; color: var(--text);
}
.grammatik .aufgaben .wahl label:hover { background: var(--pill-track); }
/* Die ganze Zeile ist anklickbar, nicht nur der Punkt: Auf dem Telefon ist
   ein Radiobutton knapp zwoelf Pixel breit. */
.grammatik .aufgaben .wahl input { flex: none; margin: 0; accent-color: var(--accent); }
.grammatik .aufgaben .wahl label:has(input:checked) {
  background: var(--accent-surface); color: var(--text-strong);
}

/* --- Wozu man es braucht --------------------------------------------------

   Vier benannte Faelle, je einer mit einem Satz. Die Nummer kommt aus dem
   ol und nicht aus dem Text - wer einen Fall streicht, soll nicht
   umnummerieren muessen; dieselbe Regel wie bei den Beispielkarten. */
.grammatik .wozu { margin: 24px 0 0; }
.grammatik .wozu ol { margin: 0; padding-left: 20px; }
.grammatik .wozu li { margin: 0 0 10px; }
.grammatik .wozu .fall { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--text-muted); }
.grammatik .wozu .fall strong { color: var(--text-strong); font-weight: 600; }

/* Der Beispielsatz eingerueckt und in der Leseschrift, mit einem Strich in
   der Stufenfarbe davor: Das ist der deutsche Satz, auf den es ankommt, und
   er soll sich von der Erklaerung daneben abheben, ohne ein eigener Kasten
   zu werden. */
.grammatik .wozu .satz {
  margin: 3px 0 0; padding-left: 10px;
  border-left: 2px solid var(--kante);
  font-family: var(--read); font-size: 16px; line-height: 1.6; color: var(--text);
}

/* --- Die Erklaerung in Abschnitten ----------------------------------------

   Der erste Absatz steht ohne Ueberschrift, danach ein Abschnitt je Fall.
   Die Ueberschriften sind h3 und kleiner als die Abschnittsueberschriften
   der Seite: "Die du-Form" ist ein Teil der Erklaerung und kein eigener
   Teil der Seite wie "Jetzt du". */
.grammatik .abschnitte { margin: 20px 0 0; }
.grammatik .abschnitte .abschnitt { margin: 0 0 16px; }
.grammatik .abschnitte h3 {
  margin: 0 0 4px; font-size: 13.5px; font-weight: 600; color: var(--text-strong);
}
.grammatik .abschnitte p {
  margin: 0; font-family: var(--read); font-size: 16px; line-height: 1.7;
  color: var(--text); text-wrap: pretty;
}

/* Achtung und Tipp als Kasten. Die Grenze der Regel - "e wird i, aber a
   bleibt a" - ist die Stelle, an der es schiefgeht; als weiterer Absatz
   zwischen anderen geht sie unter.

   Der Rahmen ist gestrichelt und die Flaeche blass: Das ist derselbe
   Gegenstand wie der Absatz daneben, nur eine Stufe lauter. Ein voller
   Kasten in der Stufenfarbe waere ein zweiter Merkkasten, und den gibt es
   oben schon. */
.grammatik .abschnitte .achtung,
.grammatik .abschnitte .tipp {
  padding: 11px 14px 12px; border-radius: 10px;
  border: 1.5px dashed var(--kante); background: var(--surface);
}
.grammatik .abschnitte .tipp { border-color: var(--border); }
.grammatik .abschnitte h3 .marke {
  display: inline-block; margin-right: 7px; padding: 1px 7px 2px;
  border-radius: 999px; background: var(--flaeche); color: var(--schrift);
  font-family: var(--mono); font-size: 10px; font-weight: 600;
  letter-spacing: 0.05em; text-transform: uppercase;
}
.grammatik .abschnitte .tipp h3 .marke {
  background: var(--pill-track); color: var(--text-muted);
}

/* Der Ausblick auf hoehere Stufen. Blasser als der Rest und ohne
   Leseschrift: Das ist kein Lernstoff fuer diese Seite, sondern eine
   Auskunft darueber, was noch kommt. */
.grammatik .spaeter {
  margin: 26px 0 0; padding-top: 16px; border-top: 1px solid var(--border);
}
.grammatik .spaeter h2 { color: var(--text-muted) !important; }
.grammatik .spaeter ul { list-style: none; margin: 0; padding: 0; }
.grammatik .spaeter li {
  display: flex; align-items: baseline; gap: 9px; margin: 0 0 7px;
}
.grammatik .spaeter .pille {
  flex: none;
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  color: var(--schrift); background: var(--flaeche);
  border: 1px solid var(--kante); border-radius: 999px; padding: 1px 6px 2px;
}
.grammatik .spaeter .wozu { font-size: 13.5px; line-height: 1.5; color: var(--text-muted); }
.grammatik .spaeter .wozu strong { color: var(--text); font-weight: 600; }

/* --- Die Formentafel ------------------------------------------------------

   Zeilen Verben, Spalten Personen, und in den Zellen die fertige Form. Fuer
   eine Erstsprache ohne Flexion ist die Tabelle die Regel - sechs Formen
   untereinander sagen mehr als drei Saetze darueber, dass es sechs gibt.

   Die Formen stehen in der Leseschrift und die Koepfe in der Grotesk: Das
   ist derselbe Schnitt wie ueberall - was in der Serife steht, ist Deutsch
   zum Lernen, was in der Grotesk steht, sagt etwas darueber. */
/* Die Ueberschrift kommt aus .grammatik.thema h2 und steht deshalb nicht
   hier: "Die Formen" ist ein Abschnitt wie "So sieht das aus", und zwei
   Groessen fuer dieselbe Sache waeren ein Versehen, das aussieht wie Absicht. */
.grammatik .formen { margin: 26px 0 0; }

/* Der Rahmen scrollt, nicht die Seite. Vier Spalten mal "Kommen Sie!" sind
   auf 390px breiter als das Telefon, und eine Tabelle, die die ganze Seite
   seitlich schiebt, verschiebt auch die Uebung darunter. */
.grammatik .tafelrahmen {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border); border-radius: 12px;
  /* Der Schatten an der Kante sagt, dass es seitlich weitergeht. Ohne ihn
     sieht eine abgeschnittene Spalte aus wie eine kaputte Tabelle - auf dem
     Telefon ist genau das der Normalfall, vier Spalten mal "Kommen Sie!"
     passen dort nicht nebeneinander.

     Vier Verlaeufe, und der Trick steckt in background-attachment: Die
     beiden hellen liegen auf "local" und scrollen also mit dem Inhalt, die
     beiden Schatten auf "scroll" und bleiben stehen. Am linken Anschlag
     deckt der helle den Schatten zu, und sobald man schiebt, wandert er weg
     und der Schatten kommt hervor. Kein Skript, keine Ereignisse. */
  background:
    linear-gradient(to right, var(--surface) 40%, rgba(255, 255, 255, 0)) left / 28px 100% no-repeat local,
    linear-gradient(to left, var(--surface) 40%, rgba(255, 255, 255, 0)) right / 28px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(17, 24, 39, 0.28), rgba(17, 24, 39, 0)) left / 22px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(17, 24, 39, 0.28), rgba(17, 24, 39, 0)) right / 22px 100% no-repeat scroll,
    var(--surface);
}
/* --- Nomen-Verb-Verbindungen: die belegte Liste ---------------------------

   Nach Linhs Karten vom 03.10.2026. Vier Spalten, sonst nichts - und die
   vierte ist kein erfundener Beispielsatz, sondern einer aus einem Beitrag.
   Der Grund steht am Template: Die Prosa der geschriebenen Seiten war das,
   was durchgefallen ist, nicht die Tabellen. */
.grammatik .wendungen .unter {
  margin: 10px 0 0; max-width: 64ch;
  font-family: var(--read); font-size: 16.5px; line-height: 1.55; color: var(--text-muted);
}
.grammatik .wendungen .unter b { color: var(--text-strong); font-family: var(--display); font-weight: 600; }

/* Die Zahl sagt, worauf die Liste steht. Ohne sie koennte sie erfunden sein. */
.grammatik .wendungen .stand { display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 0; }
.grammatik .wendungen .stand span {
  padding: 5px 12px 6px; border-radius: 999px; background: var(--surface);
  border: 1px solid var(--border); font-family: var(--mono); font-size: 12px; color: var(--text-muted);
}
.grammatik .wendungen .stand b { color: var(--text-strong); font-weight: 600; }

.grammatik .wendungen .liste { margin: 18px 0 0; }
.grammatik .wendungen .zeile {
  display: grid; grid-template-columns: 200px 150px 1fr; gap: 14px; align-items: start;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 13px 16px 14px; margin-bottom: 7px;
}
.grammatik .wendungen .wendung { font-size: 17px; font-weight: 700; color: var(--text-strong); line-height: 1.25; }
.grammatik .wendungen .wendung .gleich {
  display: block; margin-top: 3px; font-size: 13px; font-weight: 400; color: var(--accent);
}
/* Die Rektion. Sie steht in der Schreibmaschinenschrift wie jede andere
   Angabe, die man abliest und nicht liest - und sie ist die Zeile, auf die
   eine Lernende ohne Kasus in ihrer Erstsprache am meisten angewiesen ist. */
.grammatik .wendungen .wendung .rektion {
  display: inline-block; margin-top: 5px; padding: 1px 8px 2px;
  border-radius: 999px; background: var(--pill-track); color: var(--text-muted);
  font-family: var(--mono); font-size: 11.5px; font-weight: 500;
}
.grammatik .wendungen .viet { font-family: var(--read); font-size: 15.5px; color: #35547C; line-height: 1.35; }

/* Der Beleg steht in der Leseschrift wie im Artikel selbst - er ist ein Zitat
   und keine Erfindung, und das soll man sehen. */
.grammatik .wendungen .beleg p { margin: 0; font-family: var(--read); font-size: 16px; line-height: 1.5; color: var(--text); }
.grammatik .wendungen .beleg b { font-weight: 600; color: #8A4A58; }
.grammatik .wendungen .quelle { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; margin-top: 7px; }
.grammatik .wendungen .quelle a { font-size: 13px; color: var(--accent); text-decoration: none; border-bottom: 1px solid var(--accent-surface); }
/* Die Zahl ist der Weg zu den anderen Fundstellen - die Verbindung, nach der
   die Seite gebaut ist. Bei einem Beitrag fehlt sie: "in 1 Beitrag" waere
   kein Angebot. */
.grammatik .wendungen .mehr {
  padding: 2px 9px 3px; border-radius: 999px; background: #F6E3E6;
  border: 1px solid #D6AAB3; color: #8A4A58; font-family: var(--mono); font-size: 11px;
}
.grammatik .wendungen .fuss {
  margin: 24px 0 0; padding: 15px 18px 16px; border-radius: 12px;
  background: var(--primary); color: #E7ECF1;
  font-family: var(--read); font-size: 15.5px; line-height: 1.55;
}

@media (max-width: 640px) {
  /* Auf dem Telefon untereinander: Drei Spalten auf 390px machen aus jedem
     Beleg eine Spalte aus Einzelwoertern. */
  .grammatik .wendungen .zeile { grid-template-columns: 1fr; gap: 6px; }
  .grammatik .wendungen .viet { font-size: 15px; }
}

/* --- Lesetisch: der Stapel ------------------------------------------------

   Vierunddreissig Entwuerfe einzeln freizugeben heisst vierunddreissig volle
   Seitenaufbauten, und jeder wirft die Stelle weg, an der man gerade las. Das
   Kreuz ist die Entscheidung, der Knopf unten nur das Abschicken. */
.grammatik .entwurf .sammeln {
  display: inline-flex; align-items: center; gap: 7px;
  margin-right: 14px; font-size: 14px; color: var(--text-muted);
  cursor: pointer;
}
.grammatik .entwurf .sammeln input { width: 17px; height: 17px; accent-color: var(--accent); }
.grammatik .entwurf:has(.sammeln input:checked) { border-color: var(--accent); }

.grammatik .stapel {
  position: sticky; bottom: 0; z-index: 2;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 22px 0 0; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 -2px 12px rgba(17, 24, 39, 0.07);
}
.grammatik .stapel .gross { font-size: 15px; padding: 10px 18px; }

/* Die Marke am Entwurf, der genauer zu lesen ist. Nicht rot: Es ist kein
   Fehler, sondern ein Hinweis, wo einer wahrscheinlicher ist. */
.grammatik .entwurf .achtung {
  display: inline-block; margin-left: 10px; padding: 2px 9px;
  font-family: var(--display); font-size: 12px; font-weight: 600;
  color: #8B6438; background: #FBEEDB;
  border: 1px solid #E6C9A0; border-radius: 999px;
}

/* Da fuer das Ohr, weg fuer das Auge. Ein Text, der nur vorgelesen wird,
   darf nicht display:none sein - dann liest ihn auch der Screenreader nicht.
   Also ein Pixel gross, weggeschnitten und aus dem Textfluss genommen. */
.nur-vorgelesen {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Der Rahmen ist anspringbar, also muss man sehen, wo man ist. */
.grammatik .tafelrahmen:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.grammatik .tafel { border-collapse: collapse; width: 100%; }
.grammatik .tafel th, .grammatik .tafel td {
  padding: 9px 14px; text-align: left; border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.grammatik .tafel tr:last-child th, .grammatik .tafel tr:last-child td { border-bottom: 0; }
.grammatik .tafel thead th {
  background: var(--flaeche, var(--pill-track)); color: var(--schrift, var(--text-strong));
  font-size: 12.5px; font-weight: 600; letter-spacing: 0.01em;
  border-bottom: 1px solid var(--kante, var(--border));
}
/* Die erste Spalte traegt den Infinitiv und oft den Wechsel in Klammern -
   sie darf umbrechen, die Formen daneben nicht. */
.grammatik .tafel tbody th {
  font-family: var(--read); font-size: 15px; font-weight: 500;
  color: var(--text-muted); white-space: normal; min-width: 8em;
}
.grammatik .tafel td { font-family: var(--read); font-size: 16px; color: var(--text); }

/* Der wechselnde Buchstabe. Er ist das eigentliche Mittel der Tafel: Er
   zeigt die Regel, statt sie zu behaupten - N(i)mm!, spr(i)ch!.

   In der Lernfarbe, weil hier Lernstoff markiert wird und keine Bedienung -
   dieselbe Begruendung wie an den harten Woertern im Satz-Panel.

   Als Flaeche und nicht als Unterstrich: Ein inset-Schatten an einem
   inline-Element in einer Tabellenzelle kam bei 16px Schriftgroesse auf
   knapp drei Pixel heraus und war auf dem Bildschirm nicht zu sehen. Die
   Tafel lebt von dieser einen Markierung; sie muss auffallen. */
.grammatik .tafel .wechsel {
  font-weight: 700; color: var(--accent-text);
  background: var(--accent-surface); border-radius: 3px; padding: 0 2px;
}

@media (max-width: 480px) {
  .grammatik .tafel th, .grammatik .tafel td { padding: 8px 11px; }
  .grammatik .tafel td { font-size: 15px; }
  .grammatik .tafel tbody th { font-size: 14px; min-width: 6.5em; }
}

/* --- Die Stufenleiter auf der Themenseite --------------------------------

   Ein Hinweis am Rand, kein Kapitel. Sie steht nur auf Seiten, deren Text
   zufaellig ein Wort enthaelt, zu dem es eine Leiter gibt - und zeigt dort
   die Kette einmal und dann zwei Saetze: den einfachsten und den gehobensten,
   beide aus einer Meldung, beide mit dem Weg dorthin.

   Die fuenf Stufenfarben kommen aus .grammatik .a1 ff. weiter oben; dieser
   Kasten liegt darin. */
.grammatik .stufenleiter {
  margin: 26px 0 0; padding: 16px 18px 14px;
  border: 1px solid var(--border); border-radius: 14px; background: var(--surface);
}
.grammatik .stufenleiter h2 {
  margin: 0 0 10px; font-size: 12.5px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-muted);
}

/* Die Kette. Stufe und Wort stehen aneinander und nicht uebereinander: Die
   Zeile soll sich lesen lassen wie ein Satz. */
.grammatik .stufenleiter .kette {
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin: 0 0 14px;
}
.grammatik .stufenleiter .pfeil { color: var(--text-faint); font-size: 12px; }
.grammatik .stufenleiter .sprosse { display: inline-flex; align-items: baseline; gap: 6px; }
.grammatik .stufenleiter .sprosse .stufe {
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  color: var(--schrift); background: var(--flaeche);
  border: 1px solid var(--kante); border-radius: 999px; padding: 1px 6px 2px;
}
.grammatik .stufenleiter .sprosse .wort {
  font-family: var(--read); font-size: 15.5px; color: var(--text);
}

/* Die zwei Saetze. Der Streifen links traegt die Stufenfarbe - er sagt, auf
   welcher Stufe der Satz steht, ohne dass noch eine Pille danebenmuss. */
.grammatik .stufenleiter .beleg {
  border-left: 3px solid var(--kante); padding: 2px 0 2px 12px; margin-bottom: 12px;
}
.grammatik .stufenleiter .beleg:last-child { margin-bottom: 0; }
.grammatik .stufenleiter .satz {
  margin: 0; font-family: var(--read); font-size: 16px; line-height: 1.6;
  color: var(--text); text-wrap: pretty;
}
/* Das Wort im Satz. Halbfett und in der Stufenfarbe unterstrichen - nicht
   farbig gesetzt: Ein eingefaerbtes Wort mitten im Satz liest sich wie ein
   Verweis, und hier fuehrt es nirgendwohin. */
.grammatik .stufenleiter .satz b {
  font-weight: 600; color: var(--text-strong);
  border-bottom: 2px solid var(--kante); padding-bottom: 1px;
}
.grammatik .stufenleiter .quelle {
  display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
  margin-top: 5px; text-decoration: none; font-size: 12.5px; color: var(--text-muted);
}
.grammatik .stufenleiter .quelle:hover { color: var(--text-strong); }
.grammatik .stufenleiter .quelle:hover span:first-child { text-decoration: underline; }
.grammatik .stufenleiter .mehr { color: var(--schrift); white-space: nowrap; }

@media (max-width: 480px) {
  .grammatik .stufenleiter { padding: 14px 14px 12px; }
  .grammatik .stufenleiter .satz { font-size: 15.5px; }
}

/* Der Hinweis nach dem Abmelden (fragments/konto-meldung.html): eine ruhige
   Zeile unter dem Kopf, in der Farbe der Hinweise und nicht der Lernfarbe. */
.kontohinweis {
  max-width: 1040px; margin: 0 auto 20px; padding: 10px 14px; border-radius: 8px;
  background: var(--info-surface); color: var(--info-text); font-size: 13px; line-height: 1.5;
}

/* --- Grammatikseite bearbeiten ----------------------------------------
   Ein Textfeld in der Schrift fuer Code: Die senkrechten Striche trennen
   die Teile einer Zeile, und in gleichbreiter Schrift sieht man, wo einer
   fehlt. */
.grammatik.bearbeiten .zeilenfeld { display: block; }
.grammatik.bearbeiten .zeilenfeld span {
  display: block; margin: 0 0 6px; font-size: 12.5px; font-weight: 600; color: var(--text-muted);
}
.grammatik.bearbeiten textarea {
  width: 100%; box-sizing: border-box; padding: 12px 14px; resize: vertical;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface);
  color: var(--text-strong); font-family: var(--mono); font-size: 13px; line-height: 1.6;
  /* Umbrechen statt seitlich schieben: Am Telefon waren die Zeilen sonst
     abgeschnitten (UX admin-4). Eine Zeile bleibt eine Zeile - der Umbruch
     ist nur Anzeige, im Text steht kein neuer Zeilenwechsel. */
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.grammatik.bearbeiten textarea:focus { outline: none; border-color: var(--accent); }
.grammatik.bearbeiten .abbrechen { font-size: 13.5px; color: var(--text-muted); }
.grammatik.bearbeiten .fehler {
  margin: 0 0 18px; padding: 11px 15px;
  border: 1px solid #D6ABA3; border-radius: 8px; background: #FBF4F2;
  font-size: 13.5px; line-height: 1.5; color: #7C3F35;
}
.grammatik.bearbeiten .fehler ul { margin: 6px 0 0; padding-left: 18px; }
.grammatik.bearbeiten .fehler li { font-family: var(--mono); font-size: 12.5px; overflow-wrap: anywhere; }
.grammatik.bearbeiten .legende { margin-top: 24px; font-size: 13.5px; color: var(--text); }
.grammatik.bearbeiten .legende summary { cursor: pointer; color: var(--text-muted); }
.grammatik.bearbeiten .legende dt { margin-top: 10px; font-family: var(--mono); font-size: 12.5px; color: var(--text-strong); }
.grammatik.bearbeiten .legende dd { margin: 2px 0 0; }

/* Der Knopf zum Bearbeiten oben rechts im Seitenkopf - fuer die
   Betreiberin. Ein Raster und nicht absolut wie .signout: Lange Themennamen
   liefen sonst auf dem Telefon unter den Knopf. */
.grammatik.thema .pagehead:has(> .bearbeiten) {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 16px; align-items: start;
}
.grammatik.thema .pagehead > :not(h1, .bearbeiten) { grid-column: 1 / -1; }
.grammatik .pagehead .bearbeiten {
  display: inline-flex; align-items: center; white-space: nowrap;
  padding: 7px 16px 8px; border-radius: 8px; border: 1px solid var(--accent);
  background: var(--surface); color: var(--accent-text); text-decoration: none;
  font-family: var(--display); font-size: 13.5px; font-weight: 600;
}
.grammatik .pagehead .bearbeiten:hover { background: var(--accent-surface); }

/* --- Der Tresor (design/tresor/) --------------------------------------------
   Die Seite mit allem Gemerkten, die Karteikarten und der Sprung zur Stelle
   im Leser. Gruen bleibt der Lernstoff im Text; die Wortarten tragen die
   Farben des Vokabel-Netzes (graph.js), die Wendung den Ton der Wortgruppen. */

.tresorkopf { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 16px 24px; }
.tresorkopf-text { flex: 1 1 320px; }
.tresorkopf h1 {
  margin: 0; font-family: var(--display); font-size: 30px; font-weight: 700;
  color: var(--text-strong); letter-spacing: -0.02em;
}
.tresorzahlen { margin: 6px 0 0; font-size: 13.5px; color: var(--text-muted); }
.tresorzahlen strong { color: var(--text-strong); font-weight: 600; }
.wiederholen {
  height: 44px; padding: 0 18px 0 16px; border-radius: 8px; background: var(--primary); color: #FFFFFF;
  display: inline-flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600;
}
.wiederholen:hover { background: var(--primary-dark); color: #FFFFFF; }
.wiederholenzahl {
  height: 22px; min-width: 22px; padding: 0 6px; border-radius: 999px; background: rgba(255, 255, 255, 0.16);
  display: inline-flex; align-items: center; justify-content: center; font-size: 12px;
}

.tresorwoche {
  list-style: none; margin: 20px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px;
}
.tresorwoche li {
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px 9px;
  display: flex; flex-direction: column;
}
.tresorwoche .tagname { font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); }
.tresorwoche .taganzahl { font-family: var(--display); font-size: 18px; font-weight: 600; color: var(--text-muted); }
.tresorwoche li.heute { border-color: var(--primary); }
.tresorwoche li.heute .tagname { color: var(--primary); }
.tresorwoche li.heute .taganzahl { color: var(--text-strong); }

.tresorliste { margin-top: 24px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; }
.tresorliste > header { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 16px 18px 12px; }
.tresorliste h2 { margin: 0; font-family: var(--display); font-size: 16px; font-weight: 700; color: var(--text-strong); }
.tresorsieb { margin-left: auto; display: flex; gap: 4px; padding: 3px; background: var(--pill-track); border-radius: 10px; }
.tresorsieb a {
  height: 28px; padding: 0 12px; border-radius: 8px; display: inline-flex; align-items: center;
  font-size: 12.5px; font-weight: 500; color: var(--text-muted);
}
.tresorsieb a[aria-current='true'] { background: var(--surface); color: var(--text-strong); }
.tresorleer { margin: 0; padding: 18px; border-top: 1px solid var(--border); font-size: 13.5px; color: var(--text-muted); }
.tresorleer a { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; }

.tresoreintraege { list-style: none; margin: 0; padding: 0; }
.tresoreintrag {
  display: grid; grid-template-columns: minmax(160px, 1.1fr) minmax(0, 2fr) auto 36px;
  align-items: center; gap: 4px 16px; padding: 11px 18px; border-top: 1px solid var(--border);
}
.tresoreintrag:hover { background: var(--surface-hover); }
.eintragwort { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 10px; }
.eintragwort .wortzeile { grid-column: 2; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.eintragwort .kurzbedeutung {
  grid-column: 2; font-size: 13px; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.eintragbild {
  grid-column: 1; grid-row: 1 / span 2; width: 40px; height: 40px; object-fit: contain;
  background: #FFFFFF; border: 1px solid var(--border); border-radius: 6px;
}
/* Ohne Wortbild keine leere Spalte davor. */
.eintragwort:not(:has(.eintragbild)) { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
.eintragwort:not(:has(.eintragbild)) > * { grid-column: 1; }
.tresorwochezeile { margin: 16px 0 0; font-size: 13.5px; color: var(--text-muted); }
.tresorwochezeile strong { color: var(--text-strong); font-weight: 600; }
.tresorbildnachweis { margin: 10px 2px 0; font-size: 11.5px; color: var(--text-muted); }
.eintragwort .wort { font-family: var(--read); font-size: 17px; font-weight: 500; color: var(--text-strong); }
.eintragherkunft { min-width: 0; display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: var(--text-muted); }
.eintragherkunft .aus { overflow: hidden; text-overflow: ellipsis; }
.eintragherkunft .aus { white-space: nowrap; }
.auchlink {
  color: var(--primary); text-decoration: underline; text-decoration-color: var(--text-faint);
  text-decoration-thickness: 1px; text-underline-offset: 3px;
}
.auchlink:hover { color: var(--primary-dark); text-decoration-color: var(--primary); }
.mehrknopf {
  display: inline-flex; align-items: center; gap: 3px; height: 22px; padding: 0 8px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--surface-hover);
  color: var(--primary); font-size: 11.5px; font-weight: 600; cursor: pointer; list-style: none;
}
.mehrknopf::-webkit-details-marker { display: none; }
.mehrknopf:hover { background: var(--pill-track); border-color: var(--text-faint); }
.mehr[open] .mehrknopf svg { transform: rotate(90deg); }
.mehrliste .mehrweiterzeile { list-style: none; margin: 2px 0 0 -16px; }
.mehrliste { margin: 6px 0 2px; padding-left: 16px; display: grid; gap: 3px; }
.eintragstand { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.fach { display: flex; gap: 2px; }
.fach i { width: 10px; height: 10px; border-radius: 2px; background: var(--pill-track); }
.fach i.voll { background: var(--primary); }
.wann { font-size: 12px; color: var(--text-muted); }
.wann.heute { color: var(--primary); font-weight: 600; }
.eintragweg button {
  width: 44px; height: 44px; border: none; border-radius: 50%; background: none; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; color: var(--text-muted); cursor: pointer;
}
.eintragweg button:hover { background: var(--pill-track); color: var(--text-strong); }
.eintragweg { margin: 0; }
/* Die Leiste nach dem Entfernen: unten, ueber allem, mit "Rueckgaengig" als
   einzigem Knopf (tresor-liste.js). Dunkel wie die Hinweise der App, damit
   sie sich vom Inhalt abhebt, ohne ihn zu verdecken. */
.tresorrueck {
  position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); z-index: 40;
  display: flex; align-items: center; gap: 14px; padding: 6px 6px 6px 16px;
  width: max-content; max-width: calc(100vw - 32px); border-radius: 12px;
  background: var(--primary); color: #FFFFFF; font-size: 14px;
  box-shadow: 0 10px 28px -10px rgba(11, 26, 42, 0.5);
}
.tresorrueck[hidden], .tresoreintrag[hidden] { display: none; }
.tresorrueck button {
  height: 44px; padding: 0 14px; border: none; border-radius: 8px; cursor: pointer;
  background: rgba(255, 255, 255, 0.14); color: #FFFFFF; font: inherit; font-weight: 700;
}
.tresorrueck button:hover { background: rgba(255, 255, 255, 0.24); }
.tresorrueck button:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; }

.wortart {
  height: 20px; padding: 0 8px; border-radius: 999px; display: inline-flex; align-items: center;
  font-family: 'Public Sans', ui-sans-serif, system-ui, sans-serif; font-size: 11px; font-weight: 600;
  background: var(--neutral-surface); color: var(--neutral-text);
}
.wortart-nomen { background: #EAE4F3; color: #5B4A80; }
.wortart-verb { background: #DCEDEC; color: #2F6E6A; }
.wortart-adjektiv { background: #F6E3E6; color: #8A4A58; }
.wortart-adverb { background: var(--info-surface); color: var(--info-text); }
.wortart-wendung { background: #FBEEDB; color: #8B6438; }

@media (max-width: 640px) {
  .tresorkopf h1 { font-size: 26px; }
  .wiederholen { width: 100%; justify-content: center; height: 48px; }
  .tresorwoche { gap: 4px; }
  .tresorwoche li { padding: 5px 0 6px; align-items: center; border-radius: 6px; }
  .tresorwoche .tagname { font-size: 10px; letter-spacing: 0.02em; }
  .tresorwoche .taganzahl { font-size: 15px; }
  .tresorliste > header { padding: 14px 14px 10px; }
  .tresoreintrag { grid-template-columns: minmax(0, 1fr) auto 44px; padding: 10px 14px; gap: 2px 10px; }
  .eintragwort { grid-column: 1; }
  .eintragherkunft { grid-column: 1; grid-row: 2; }
  .eintragstand { grid-column: 2; grid-row: 1 / span 2; }
  .eintragweg { grid-column: 3; grid-row: 1 / span 2; }
}

/* --- Wiederholen: die Karteikarte ------------------------------------------- */

.wiederholseite { max-width: 600px; margin: 0 auto; }
.rundenleiste { display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text-muted); }
.rundenleiste .leiste { flex: 1; height: 4px; border-radius: 999px; background: var(--pill-track); overflow: hidden; }
.rundenleiste .leiste i { display: block; height: 100%; width: 0; background: var(--primary); transition: width 700ms ease-out; }
.rundenleiste a { color: var(--text-muted); text-decoration: underline; text-underline-offset: 2px; }

.stapel { position: relative; margin-top: 26px; min-height: 520px; display: flex; }
.stapel[hidden] { display: none; }
.unterkarte { position: absolute; inset: 0; border-radius: 14px; background: var(--surface); border: 1px solid var(--border); }
.unterkarte.a { transform: translate(6px, 6px) rotate(0.8deg); }
.unterkarte.b { transform: translate(12px, 12px) rotate(1.6deg); opacity: 0.6; }
.karteikarte {
  position: relative; flex: 1; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  outline: 2px solid transparent; outline-offset: -1px;
  box-shadow: 0 24px 48px -26px rgba(11, 26, 42, 0.32), 0 1px 2px rgba(11, 26, 42, 0.05);
  padding: 22px 28px 22px; touch-action: none; user-select: none; cursor: grab;
}
.karteikarte:focus-visible { outline-color: var(--primary); }
.karteikarte[data-richtung='links'] { outline-color: #A3500B; }
.karteikarte[data-richtung='oben'] { outline-color: #35547C; }
.karteikarte[data-richtung='rechts'] { outline-color: #3F6B45; }

/* Die Stempel sitzen auf der Oberkante, ausserhalb des Inhalts - ueber dem
   Text waeren sie unlesbar und er auch. */
.stempel {
  position: absolute; top: -15px; height: 28px; padding: 0 12px; border-radius: 999px;
  display: inline-flex; align-items: center; gap: 5px; color: #FFFFFF; font-size: 12.5px; font-weight: 700;
  box-shadow: 0 4px 10px rgba(11, 26, 42, 0.18); opacity: 0; pointer-events: none;
}
.stempel-links { left: 24px; background: #A3500B; }
.stempel-oben { left: 50%; transform: translateX(-50%); background: #35547C; }
.stempel-rechts { right: 24px; background: #3F6B45; }

.kartenkopf { display: flex; align-items: center; gap: 8px; }
.fachangabe { margin-left: auto; font-size: 11.5px; color: var(--text-muted); }
.kartenwortzeile { margin-top: 22px; display: flex; align-items: center; justify-content: center; gap: 4px; }
.karteikarte.ist-hinten .kartenwortzeile { margin-top: 14px; }
.kartenhoeren {
  flex: 0 0 auto; width: 36px; height: 36px; border: none; border-radius: 999px; background: none; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; color: var(--text-muted); cursor: pointer;
}
.kartenhoeren:hover, .kartenhoeren.is-playing { background: var(--pill-track); color: var(--primary); }
.kartenwort {
  margin: 0; text-align: center; font-family: var(--read); font-size: 40px; font-weight: 500;
  color: var(--text-strong); letter-spacing: -0.01em; line-height: 1.15;
}
.karteikarte.ist-hinten .kartenwort { font-size: 32px; }
.kartenvorne, .kartenhinten { flex: 1; display: flex; flex-direction: column; }
.kartenvorne[hidden], .kartenhinten[hidden] { display: none; }
.kartensatz { margin: 14px auto 0; max-width: 460px; text-align: center; font-family: var(--read); font-size: 17px; line-height: 1.5; color: var(--text); }
.kartensatz mark { background: linear-gradient(transparent 55%, rgba(11, 110, 91, 0.22) 55%); color: inherit; padding: 0 1px; }
.kartenquelle { margin: 8px 0 0; text-align: center; font-size: 12px; line-height: 1.6; color: var(--text-muted); }
.kartenquelle a { color: var(--primary); text-decoration: underline; text-decoration-color: var(--text-faint); text-underline-offset: 3px; }
.kartenbild { margin: 14px auto 18px; width: 100%; max-width: 380px; display: flex; flex-direction: column; gap: 4px; }
.kartenbild[hidden] { display: none; }
.kartenbild img { width: 100%; max-height: 190px; object-fit: cover; border-radius: 10px; border: 1px solid var(--border); }
.kartenbild figcaption { font-size: 10.5px; color: var(--text-muted); text-align: right; }
.umdrehen {
  margin: auto auto 0; width: 260px; height: 44px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-strong);
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.umdrehen:hover { background: var(--surface-hover); }
.karteikarte kbd {
  font-family: var(--mono); font-size: 10.5px; padding: 1px 5px; border-radius: 4px;
  border: 1px solid var(--border); background: var(--surface-hover); color: var(--text-muted);
}
.kartenhilfe { margin: 8px 0 0; text-align: center; font-size: 11.5px; color: var(--text-muted); }
.kurzgezeigt {
  margin: 10px auto 0; padding: 6px 12px; border-radius: 999px; background: #FCEBD9; color: #A3500B;
  font-size: 12.5px; font-weight: 600; text-align: center;
}
.kurzgezeigt[hidden] { display: none; }
.kartenbedeutung {
  margin: 14px auto 0; width: 100%; max-width: 460px; font-size: 15.5px; color: var(--text);
  border-left: 2px solid var(--accent-text); padding-left: 10px;
}
.kartenuebersetzung { margin: 6px auto 0; width: 100%; max-width: 460px; font-size: 14px; color: var(--text-muted); padding-left: 12px; }
.kartenbedeutung[hidden], .kartenuebersetzung[hidden] { display: none; }
.kartenhinten .steckbrief { margin: 10px auto 0; width: 100%; max-width: 460px; display: grid; gap: 4px; }
.kartenhinten .steckbrief .line { display: grid; grid-template-columns: 74px minmax(0, 1fr); gap: 8px; align-items: baseline; }
.kartenhinten .steckbrief .key { font-size: 10.5px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); }
.kartenhinten .steckbrief .val { font-size: 13px; line-height: 1.5; color: var(--text); }

.richtungen { margin-top: auto; padding: 18px 0 10px; display: flex; justify-content: space-between; gap: 8px; }
.richtung {
  display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 12px; border-radius: 999px;
  border: 1.5px solid var(--border); background: var(--surface); font-size: 13px; font-weight: 700;
  transition: transform 500ms, background 500ms, border-color 500ms;
}
.richtung.richtung-links { color: #A3500B; }
.richtung.richtung-oben { color: #35547C; }
.richtung.richtung-rechts { color: #3F6B45; }
.richtung.richtung-links.an { border-color: #A3500B; background: #FCEBD9; transform: scale(1.08); }
.richtung.richtung-oben.an { border-color: #35547C; background: #DDE7F3; transform: scale(1.08); }
.richtung.richtung-rechts.an { border-color: #3F6B45; background: #E4EFE3; transform: scale(1.08); }
.antworten { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
/* Nochmal allein in der oberen Zeile, flacher - es ist die seltene Antwort. */
.antworten .allein { grid-column: 1 / -1; height: 40px; flex-direction: row; gap: 8px; }
/* Die Knoepfe stehen unten auf der Karte, wo der Daumen ist - die freie
   Flaeche liegt zwischen Inhalt und Knoepfen statt unter ihnen. */
.kartenhinten .antworten { margin-top: auto; padding-top: 16px; }
.antworten button {
  height: 54px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font-family: inherit; cursor: pointer;
}
.antworten button:hover { border-color: var(--primary); background: var(--surface-hover); }
.antworten strong { font-size: 13px; font-weight: 600; color: var(--text-strong); }
.antworten strong i { font-style: normal; font-weight: 700; }
.antworten .richtung-links strong i { color: #A3500B; }
.antworten .richtung-oben strong i { color: #35547C; }
.antworten .richtung-rechts strong i { color: #3F6B45; }
/* Waehrend des Wischens leuchtet der Knopf, auf dem die Karte landet. */
.antworten button { transition: background 300ms, border-color 300ms; }
.antworten button.richtung-links.an { border-color: #A3500B; background: #FCEBD9; }
.antworten button.richtung-oben.an { border-color: #35547C; background: #DDE7F3; }
.antworten button.richtung-rechts.an { border-color: #3F6B45; background: #E4EFE3; }
.antworten span { font-size: 11px; color: var(--text-muted); }

.rundenende {
  margin-top: 26px; padding: 34px 30px; text-align: center; background: var(--surface);
  border: 1px solid var(--border); border-radius: 14px;
}
.rundenende[hidden] { display: none; }
.rundenende h1 { margin: 0; font-family: var(--display); font-size: 24px; font-weight: 700; color: var(--text-strong); }
.rundenende p { margin: 8px 0 0; font-size: 14px; color: var(--text-muted); }
.termine { list-style: none; margin: 14px auto 0; padding: 0; max-width: 320px; text-align: left; }
.termine li { display: flex; justify-content: space-between; gap: 16px; padding: 6px 0; border-top: 1px solid var(--border); font-size: 13px; color: var(--text-muted); }
.termine .wort { font-family: var(--read); font-size: 15px; color: var(--text-strong); }
.rundenende .zurueck {
  display: inline-flex; margin-top: 18px; height: 44px; padding: 0 20px; align-items: center; border-radius: 8px;
  border: 1px solid var(--border); font-size: 13px; font-weight: 600; color: var(--text-strong);
}
.rundenfehler { margin-top: 18px; color: #8A1F16; font-size: 13.5px; }
.rundenfehler[hidden] { display: none; }

@media (max-width: 640px) {
  .karteikarte { padding: 20px 16px 16px; }
  .kartenwort { font-size: 32px; }
  .karteikarte.ist-hinten .kartenwort { font-size: 28px; }
  .antworten { gap: 6px; }
  .richtung { padding: 0 9px; font-size: 12px; }
}
/* Vier Knoepfe in einer Reihe waren am Telefon je 80px breit: "<- Nochmal"
   brach um, der Pfeil rutschte ueber das Wort und "gleich noch mal" aus dem
   Knopf. Jetzt drei in der Reihe, Nochmal darueber; nichts bricht um. */
@media (max-width: 480px) {
  .antworten button { height: 56px; }
  .antworten .allein { height: 42px; }
  .antworten strong { font-size: 14px; }
  .antworten strong, .antworten span { white-space: nowrap; }
  .stapel { min-height: 480px; }
}
@media (prefers-reduced-motion: reduce) {
  .karteikarte, .richtung, .rundenleiste .leiste i { transition: none !important; }
}

/* --- Der Sprung aus dem Tresor zur Stelle im Leser -------------------------- */

.tresorsprung {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin: 0 0 16px;
  padding: 10px 14px; border-radius: 10px; background: var(--primary); color: #FFFFFF; font-size: 13px;
}
.tresorsprung .sprungtext { flex: 1 1 240px; }
.sprungzurueck {
  display: inline-flex; align-items: center; height: 32px; padding: 0 12px; border-radius: 999px;
  background: #FFFFFF; color: var(--primary); font-weight: 600;
}
.sprungzurueck:hover { color: var(--primary-dark); }
.body.hat-stelle .sent { transition: opacity 400ms; }
.body.hat-stelle .sent:not(.tresorstelle) { opacity: 0.6; }
.sent.tresorstelle {
  border-radius: 4px; background-color: rgba(232, 176, 36, 0.22); box-shadow: inset 0 -2px 0 #E8B024;
  animation: tresorStelle 1.6s ease-out 1;
}
/* Das Wort selbst im markierten Satz - wie auf der Entwurfstafel
   (LeserStelle): fett, mit gruener Unterlegung. */
.tresorstelle .tresorwort, .tresorstelle .tresorwortersatz {
  font-weight: 600; color: var(--text-strong);
  background: linear-gradient(transparent 55%, rgba(11, 110, 91, 0.3) 55%);
}
@keyframes tresorStelle {
  from { background-color: rgba(232, 176, 36, 0.55); }
  to { background-color: rgba(232, 176, 36, 0.22); }
}
@media (prefers-reduced-motion: reduce) {
  .sent.tresorstelle { animation: none; }
}
@media (max-width: 640px) {
  /* Auf dem Telefon gibt es keine Tasten - der Hinweis darauf faellt weg. */
  .kartenhinten .kartenhilfe { display: none; }
}
/* Hinten stehen Quelle und Bild unter dem Steckbrief, in der Flaeche, die
   sonst leer bliebe. */
.hintenquelle { margin: 6px auto 0; width: 100%; max-width: 460px; }
.hintenquelle .kartenquelle { text-align: left; }
.hintenquelle .kartenbild { margin: 10px 0 0; max-width: none; }
.hintenquelle .kartenbild img { max-height: 150px; }
/* Piktogramm (ARASAAC): ganz zeigen statt beschneiden, auf festem Weiss -
   die Linien sind schwarz und verschwaenden sonst im dunklen Modus. */
.kartenbild.ist-piktogramm img {
  object-fit: contain; height: 170px; max-height: none; background: #fff; padding: 10px; box-sizing: border-box;
}
.hintenquelle .kartenbild.ist-piktogramm img { height: 130px; }
.kartenbild .bildflaeche { position: relative; }
.bildgemeldet {
  position: absolute; top: 8px; left: 8px; padding: 2px 8px; border-radius: 999px;
  background: #FFF4DB; color: #7A5300; font-size: 11px; font-weight: 600;
}
/* Angabe und "Bild passt nicht?" teilen sich die Zeile; wird es eng, rutscht
   der Link darunter, statt die Lizenz mitten im Wort umzubrechen. */
.kartenbild figcaption { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: flex-end; gap: 2px 10px; }
.kartenbild figcaption span { flex: 1 1 auto; }
.bildmelden { white-space: nowrap; }
.bildmelden, .bildadmin button, .bildadmin a {
  border: 0; background: none; padding: 0; cursor: pointer; font: inherit; font-size: 11.5px;
  color: var(--text-strong); text-decoration: underline; text-underline-offset: 2px;
}
.meldefeld {
  display: flex; flex-direction: column; gap: 10px; margin-top: 6px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
}
.meldefeld p { margin: 0; font-size: 13px; font-weight: 600; color: var(--text-strong); }
.meldegruende { display: flex; flex-wrap: wrap; gap: 8px; }
.meldegruende button, .meldeknoepfe button {
  min-height: 36px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font: inherit; font-size: 12.5px; cursor: pointer;
}
.meldegruende button[aria-pressed="true"] { background: var(--text-strong); border-color: var(--text-strong); color: var(--bg); }
.meldeknoepfe { display: flex; justify-content: flex-end; gap: 8px; }
.meldeknoepfe button { border-radius: 8px; }
.meldeknoepfe .haupt { background: var(--text-strong); border-color: var(--text-strong); color: var(--bg); font-weight: 600; }
.meldedank { margin: 4px 0 0; font-size: 12.5px; color: var(--accent-text); text-align: center; }
.bildadmin { display: flex; justify-content: flex-end; gap: 14px; }
.kartenbild [hidden] { display: none; }

/* --- Mein Netz (design/tresor/Netz.dc.html) ---------------------------------
   Die Zeichenflaeche mit Legende links, das Seitenteil rechts; auf dem
   Telefon untereinander. Die Toene der Knoten und Striche stehen auch in
   tresor-netz.js - wer sie hier aendert, aendert sie dort mit. */
.netzkopf { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 24px; }
.netzkopf-text { flex: 1 1 320px; }
.netzpfad { margin: 0 0 4px; font-size: 12.5px; color: var(--text-muted); }
.netzpfad a { color: var(--text-muted); }
.netzkopf h1 {
  margin: 0; font-family: var(--display); font-size: 28px; font-weight: 700;
  color: var(--text-strong); letter-spacing: -0.02em;
}
.netzkopf-text > p:last-child { margin: 6px 0 0; font-size: 13.5px; color: var(--text-muted); }
.netzwahl { display: flex; gap: 4px; padding: 3px; background: var(--pill-track); border-radius: 10px; }
.netzwahl button {
  height: 30px; padding: 0 12px; border: none; border-radius: 8px; background: none;
  font: inherit; font-size: 12.5px; font-weight: 500; color: var(--text-muted); cursor: pointer;
}
.netzwahl button[aria-pressed='true'] { background: var(--surface); color: var(--text-strong); }

.netzflaeche { display: flex; flex-wrap: wrap; gap: 20px; align-items: flex-start; margin-top: 18px; }
.netzbild {
  flex: 999 1 560px; min-width: 0; background: var(--surface);
  border: 1px solid var(--border); border-radius: 12px; overflow: hidden;
}
#tresornetz { height: min(64vh, 520px); }
/* Bis das Netz steht, bliebe die Flaeche weiss - das sah nach "kaputt" aus. */
.netzbild { position: relative; }
.netzladen {
  position: absolute; left: 0; right: 0; top: calc(min(64vh, 520px) / 2 - 12px); margin: 0;
  text-align: center; font-family: var(--read); font-size: 17px; color: var(--text-muted); pointer-events: none;
}
.netzladen[hidden] { display: none; }
.netzlegende {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px;
  padding: 10px 18px 14px; border-top: 1px solid var(--border); font-size: 12px; color: var(--text-muted);
}
.netzlegende .key { display: inline-flex; align-items: center; gap: 6px; }
.netzlegende .dot { width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid; box-sizing: border-box; }
.netzlegende .key-wort .dot { background: var(--accent-surface); border-color: var(--accent-text); }
.netzlegende .key-wendung .dot { background: #FBEEDB; border-color: #8B6438; }
.netzlegende .key-vorschlag .dot { background: var(--surface); border: 1.5px dashed var(--text-muted); }
.netzlegende .strich { width: 18px; border-top: 2px solid; }
.netzlegende .key-familie .strich { border-color: #2F6E6A; }
.netzlegende .key-bedeutung .strich { border-top-style: dashed; border-color: #35547C; }
.netzlegende .key-gegenteil .strich { border-color: #5C6B7F; opacity: 0.6; }
.netzlegende .key-artikel .strich { border-top-style: dotted; border-color: var(--text-muted); }
.netzlegende .netzstatus { margin-left: auto; font-family: var(--mono); font-size: 11.5px; color: var(--text-muted); }
.netzbild .hint { margin: 14px 18px; }

/* Der Weg aus dem Tresor ins Netz - eine Zeile vor der Liste. */
.tresornetzlink {
  margin-top: 24px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
}
.tresornetzlink a {
  display: flex; align-items: center; gap: 8px; min-height: 48px; padding: 0 16px;
  font-size: 13.5px; font-weight: 600; color: var(--text-strong);
}
.tresornetzlink a:hover { background: var(--surface-hover); border-radius: 12px; }
.tresornetzlink .netzlinkzahl {
  flex: 1; min-width: 0; font-weight: 400; font-size: 12px; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tresornetzlink + .tresorliste { margin-top: 12px; }

.netzseitenteil { flex: 1 1 280px; display: flex; flex-direction: column; gap: 12px; }
.netzkarte {
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 16px 18px; display: flex; flex-direction: column; gap: 8px;
}
.netzkarte[hidden] { display: none; }
.netzkartenart {
  margin: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-muted);
}
.netzkarte h2 { margin: 0; font-family: var(--read); font-size: 22px; font-weight: 500; color: var(--text-strong); }
.netzgrund { margin: 0; font-size: 13px; line-height: 1.5; color: var(--text-muted); }
.netzmerken {
  margin-top: 4px; height: 44px; border-radius: 8px; border: 1px solid var(--primary);
  background: var(--primary); color: #FFFFFF; display: inline-flex; align-items: center;
  justify-content: center; gap: 8px; font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
}
.netzmerken:hover { background: var(--primary-dark); }
.netzmerken:disabled { opacity: 0.6; cursor: progress; }
.netzmerken[hidden] { display: none; }
.netzweitere ul { list-style: none; margin: 0; padding: 0; }
.netzweitere li {
  display: flex; align-items: center; gap: 8px; min-height: 44px; border-top: 1px solid var(--border);
}
.weiterwort {
  flex: 0 1 auto; max-width: 55%; padding: 0; border: none; background: none; text-align: left; cursor: pointer;
  font-family: var(--read); font-size: 16px; color: var(--text-strong);
}
.weiterwort:hover { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; }
.weitergrund { flex: 1; min-width: 0; font-size: 12px; color: var(--text-muted); text-align: right; }
.netzhinweis { margin: 0; font-size: 13px; color: var(--text-muted); }
.netzhinweis[hidden] { display: none; }

@media (max-width: 640px) {
  .netzkopf h1 { font-size: 26px; }
  #tresornetz { height: 58vh; }
  .netzladen { top: calc(29vh - 12px); }
  .netzlegende { padding: 10px 14px 12px; }
  .netzlegende .netzstatus { margin-left: 0; flex-basis: 100%; }
}

/* --- Wortbilder pruefen (design/tresor, AdminWortbilder) --------------------
   Eine Zeile je Bild: links das jetzige, in der Mitte Wort, Meldegruende und
   die Suche, rechts die Entscheidungen. Auf dem Telefon untereinander. */
.wortbildpruefung { max-width: 1040px; }
.wortbildpruefung .meldung {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
  margin: 0 0 18px; padding: 10px 14px; border-radius: 8px;
  background: var(--accent-surface); color: var(--accent-text); font-size: 14px;
}
.wortbildpruefung .meldung form { margin: 0; }
.wortbildpruefung .leise {
  border: 0; background: none; padding: 0; font: inherit; font-weight: 600;
  color: inherit; text-decoration: underline; cursor: pointer;
}
.wortbildpruefung .reiter { display: flex; flex-wrap: wrap; gap: 8px; padding-bottom: 12px; margin-bottom: 18px; border-bottom: 1px solid var(--border); }
.wortbildpruefung .reiter a {
  display: inline-flex; align-items: center; height: 34px; padding: 0 14px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--text); font-size: 13px; text-decoration: none;
}
.wortbildpruefung .reiter a[aria-current="page"] { background: var(--text-strong); border-color: var(--text-strong); color: var(--bg); font-weight: 600; }
.wortbildpruefung .leer { color: var(--text-muted); font-size: 15px; }
.wortbildzeile {
  display: flex; flex-wrap: wrap; gap: 18px 26px; align-items: flex-start;
  padding: 18px 20px; margin-bottom: 14px; border: 1px solid var(--border); border-radius: 14px;
}
.wortbildjetzt { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 11px; color: var(--text-muted); }
/* Piktogramme auf festem Weiss - wie auf der Karte. */
.wortbildrahmen {
  width: 140px; height: 140px; border-radius: 10px; border: 1px solid var(--border); background: #fff;
  display: flex; align-items: center; justify-content: center; color: #5A6878; font-size: 12px;
}
.wortbildrahmen img { max-width: 122px; max-height: 122px; }
.wortbildmitte { flex: 999 1 320px; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.wortbildmitte h2 { margin: 0; font-family: var(--read); font-size: 24px; font-weight: 600; color: var(--text-strong); }
.wortbildmitte .gruende { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 6px; }
.wortbildmitte .gruende li { padding: 3px 10px; border-radius: 999px; background: #FFF4DB; color: #7A5300; font-size: 12px; font-weight: 600; }
.wortbildsuche[hidden], .wortbildsuche [hidden] { display: none; }
.suchstand { padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--surface); display: flex; flex-direction: column; gap: 8px; }
.suchkopf { display: flex; justify-content: space-between; font-size: 12.5px; font-weight: 600; color: var(--text-strong); }
.suchkopf .uhr { font-family: var(--mono); font-weight: 500; color: var(--text-muted); }
.suchbalken { height: 6px; border-radius: 999px; background: var(--border); overflow: hidden; }
.suchbalken i { display: block; height: 100%; width: 0; background: var(--text-strong); transition: width 0.25s; }
.wortbildsuche .auswahl { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.wortbildsuche .auswahl p { margin: 0; font-size: 12.5px; color: var(--text-muted); }
.kandidaten { display: flex; flex-wrap: wrap; gap: 10px; }
.kandidaten .keine { font-size: 12.5px; color: var(--text-muted); }
.kandidat { position: relative; width: 92px; height: 92px; border-radius: 10px; border: 1px solid var(--border); background: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.kandidat input { position: absolute; opacity: 0; }
.kandidat img { max-width: 76px; max-height: 76px; }
.kandidat:has(input:checked) { border: 3px solid var(--text-strong); }
.kandidat:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.wortbildsuche .auswahl .action { align-self: flex-start; height: 40px; padding: 0 16px; font-weight: 600; }
.wortbildknoepfe { flex: 1 1 100%; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.wortbildknoepfe form { margin: 0; }
.wortbildknoepfe .action { height: 40px; padding: 0 16px; font-weight: 600; }
.wortbildknoepfe .action.nein { color: #9A3412; }
.wortbildquelle { font-size: 12px; color: var(--text-muted); }

/* --- Trefferflaechen fuer den Finger (UX-Befunde nav-2, leser-4) ---------
   Auf dem Telefon waren die meistbenutzten Schalter 18 bis 30px hoch:
   Sprachwahl, Menue, Niveau, Lesen/Video, das Satzzeichen, die Info, "Nur
   Wortgruppen", Sprache und Schliessen im Popup. Man traf A1 statt A2 und VI
   statt EN.

   Vergroessert wird unsichtbar: Ein ::after ragt ueber den Knopf hinaus und
   faengt den Finger, das Aussehen bleibt, und vor allem bleibt die Kopfzeile
   so hoch wie --masthead-h, an dem die Niveau-Leiste andockt. Waagerecht
   ragt die Flaeche kaum hinaus - die Knoepfe einer Gruppe stehen 2 bis 4px
   auseinander, und ueberlappende Flaechen naehmen dem Nachbarn den Treffer.
   Dafuer werden sie dort etwas breiter.

   Nur fuer grobe Zeiger: Mit der Maus traefe man durch die Flaeche hindurch
   Dinge, die man gar nicht zeigt. */
@media (pointer: coarse) {
  .langpick button, .chunkpop .langs button,
  .einstieg, .kontoknopf .person,
  .levels a, .levels button, .modes .tabs a,
  .layertoggle, .tipmark, .chunkpop .close, .transmark { position: relative; }
  .langpick button::after, .chunkpop .langs button::after,
  .levels a::after, .levels button::after, .modes .tabs a::after {
    content: ''; position: absolute; left: -2px; right: -2px; top: -8px; bottom: -8px;
  }
  .einstieg::after, .kontoknopf .person::after, .masthead[data-menu] .burger::after,
  .layertoggle::after { content: ''; position: absolute; inset: -6px -6px -9px; }
  .chunkpop .close::after { content: ''; position: absolute; inset: -9px; }
  .tipmark::after { content: ''; position: absolute; inset: -13px -10px; }
  /* Das Satzzeichen steht im Fliesstext: Eine volle 44px-Flaeche griffe in
     die Zeilen darueber und darunter und naehme den Woertern dort den Tipp.
     38 x 34 ist der Kompromiss. */
  .transmark::after { content: ''; position: absolute; inset: -8px -10px; }
  .langpick button, .chunkpop .langs button { padding: 0 11px; }
  .levels a, .levels button { min-width: 40px; }
  .masthead[data-menu] .nav .navlink { height: 44px; }
}

/* --- Fehlerseite (templates/error.html, UX fehler-1) -----------------------
   Ruhig und kurz: eine Zeile, was los ist, darunter die Wege zurueck. */
.fehlerseite { max-width: 640px; margin: 0 auto; padding: 56px 0 72px; }
.fehlerseite h1 { margin: 0; font-family: var(--display); font-size: 34px; line-height: 1.15; color: var(--text-strong); text-wrap: balance; }
.fehlerlead { margin: 12px 0 0; font-family: var(--read); font-size: 19px; line-height: 1.5; color: var(--text-muted); }
.fehlerknopf {
  display: inline-flex; align-items: center; min-height: 44px; margin-top: 8px; padding: 0 18px; border-radius: 8px;
  background: var(--primary); color: #FFFFFF; font-size: 14px; font-weight: 600; text-decoration: none;
}
.fehlerknopf:hover { background: var(--primary-dark); }
.fehlerwege { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 28px; }
.fehlerwege a {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-strong);
  font-size: 14px; font-weight: 500; text-decoration: none;
}
.fehlerwege a:hover { background: var(--surface-hover); }
@media (max-width: 640px) {
  .fehlerseite { padding: 32px 0 48px; }
  .fehlerseite h1 { font-size: 27px; }
}
