/* =========================================================================
   MagicDB — Gestaltung

   Die Farben kommen aus dem Druck von Spielkarten: Tiefschwarz, das Rot der
   Herz- und Karo-Farben, das Blau der Rider-Back-Rückseite. Die Neutraltöne
   sind leicht ins Blaue verschoben, damit sie gewählt und nicht geerbt
   wirken.

   Bodoni — die Schrift alter Zauberliteratur — traegt nur die grossen
   Ueberschriften. Alles, was gelesen oder bedient wird, steht in IBM Plex
   Sans, alle Kennzahlen und Etiketten in IBM Plex Mono. Detailseiten sind
   zum Lesen gebaut, Listenseiten zum Arbeiten.
   ========================================================================= */

@import url("schriften.83d89bbaea9c.css");

/* --- Farben und Maße ---------------------------------------------------- */

:root {
  --ground:      #EBEDF1;
  --surface:     #F9FAFB;
  --surface-alt: #E3E6EC;
  --ink:         #14181F;
  --ink-soft:    #3D4551;
  --muted:       #667083;
  --rule:        #CDD2DB;
  --rule-soft:   #DEE2E8;

  --accent:      #96202F;
  --accent-weich:#B8434F;
  --accent-grund:#F6E9EA;
  --blau:        #2E4878;
  --blau-grund:  #E7ECF5;

  --gut:         #2C6047;
  --gut-grund:   #E4EFE9;
  --warn:        #8A5B12;
  --warn-grund:  #F6EDDD;

  --schatten: 0 1px 2px rgba(20, 24, 31, .06);
  --radius: 3px;
  --rail: 15rem;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground:      #101319;
    --surface:     #171B23;
    --surface-alt: #1E232C;
    --ink:         #E3E7ED;
    --ink-soft:    #C2C8D2;
    --muted:       #8B94A4;
    --rule:        #2A303B;
    --rule-soft:   #21262F;

    --accent:      #E2707E;
    --accent-weich:#C15464;
    --accent-grund:#2C1B20;
    --blau:        #8AA8DC;
    --blau-grund:  #1A2233;

    --gut:         #6FB593;
    --gut-grund:   #16261F;
    --warn:        #D2A24E;
    --warn-grund:  #2A2115;

    --schatten: 0 1px 2px rgba(0, 0, 0, .35);
  }
}

:root[data-theme="dark"] {
  --ground:      #101319;
  --surface:     #171B23;
  --surface-alt: #1E232C;
  --ink:         #E3E7ED;
  --ink-soft:    #C2C8D2;
  --muted:       #8B94A4;
  --rule:        #2A303B;
  --rule-soft:   #21262F;

  --accent:      #E2707E;
  --accent-weich:#C15464;
  --accent-grund:#2C1B20;
  --blau:        #8AA8DC;
  --blau-grund:  #1A2233;

  --gut:         #6FB593;
  --gut-grund:   #16261F;
  --warn:        #D2A24E;
  --warn-grund:  #2A2115;

  --schatten: 0 1px 2px rgba(0, 0, 0, .35);
}

/* --- Grundlagen --------------------------------------------------------- */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-underline-offset: 2px; }
a:hover { color: var(--accent-weich); }

:where(a, button, input, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--blau);
  outline-offset: 2px;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* --- Typografische Rollen ----------------------------------------------- */

.display, h1, h2 {
  font-family: "Bodoni Moda", Didot, Georgia, serif;
  font-weight: 600;
  letter-spacing: -0.012em;
  line-height: 1.08;
  text-wrap: balance;
  margin: 0;
}

h1 { font-size: clamp(1.9rem, 4vw, 2.6rem); }
h2 { font-size: 1.35rem; }

h3 {
  font-family: "IBM Plex Sans", sans-serif;
  font-size: .95rem;
  font-weight: 600;
  margin: 0;
}

.etikett {
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .72rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Abschnitts- und Kartenüberschriften dürfen deutlicher sein als die
   kleinen Etiketten an Kennzahlen. */
.abschnitt > .etikett, .karte > .etikett {
  font-size: .78rem;
  letter-spacing: .1em;
  color: var(--ink-soft);
  font-weight: 500;
}

.mono, code {
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .86em;
}

.zahl { font-variant-numeric: tabular-nums; }

/* --- Kopfleiste --------------------------------------------------------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0 1.5rem;
  height: 3.25rem;
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
}

.marke {
  font-family: "Bodoni Moda", Didot, Georgia, serif;
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.marke em { font-style: italic; font-weight: 400; color: var(--accent); }

/* Kein flex:1 und kein overflow-x mehr. Beides stammte aus der Zeit, als
   alle zwölf Bereiche nebeneinander standen und notfalls scrollen mussten;
   seit nur noch drei draußen stehen, war das overflow-x nur noch eine
   Quelle für einen Scrollbalken, der gelegentlich zurückkam. */
.topbar nav { display: flex; gap: .1rem; min-width: 0; }

.topbar nav a {
  padding: .3rem .5rem;
  border-radius: var(--radius);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: .88rem;
  white-space: nowrap;
}
.topbar nav a:hover { background: var(--surface-alt); color: var(--ink); }
.topbar nav a[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--accent);
  border-radius: 0;
}

.topbar form { margin: 0; display: flex; align-items: center; }

/* Umschalter Hell / Dunkel / System. Das Zeichen setzt thema.js. */
.thema {
  flex: none;
  width: 2rem;
  height: 2rem;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-soft);
  font-size: .95rem;
  line-height: 1;
  cursor: pointer;
}
.thema:hover { border-color: var(--muted); color: var(--ink); }

/* --- Navigation: drei draußen, der Rest hinter dem „…“ ------------------- *
 *
 * Zwölf Bereiche nebeneinander waren eine Wand, durch die man nicht mehr
 * hindurchsah. Draußen stehen die drei, die man täglich braucht; alles
 * andere liegt einen Klick tief. Damit ist auch die Messerei überflüssig
 * geworden, die vorher entschied, ob überhaupt alles nebeneinander passt.
 *
 * Öffnen per Klick, nie per Hover — sonst wäre es auf einem Tablet nicht
 * bedienbar.
 */

/* Navigation und „…“ gehören zusammen und stehen deshalb in einem Block:
   das „…“ ist der Rest der Leiste, nicht ein Knopf bei der Suche. Der freie
   Platz sammelt sich dahinter, sodass Suche und Umschalter am rechten Rand
   sitzen. */
.nav-block {
  display: flex;
  align-items: center;
  gap: .35rem;
  min-width: 0;
  margin-right: auto;
}

.nav-primaer { display: flex; gap: .1rem; min-width: 0; }

.mehr { position: relative; display: flex; align-items: center; }
.mehr-knopf { font-size: 1.05rem; line-height: 1; letter-spacing: .05em; }

.mehr-menue {
  display: none;
  position: absolute;
  top: calc(100% + .45rem);
  left: 0;
  z-index: 30;
  min-width: 13rem;
  max-width: calc(100vw - 1.8rem);
  max-height: calc(100vh - 5rem);
  overflow-y: auto;
  padding: .4rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px rgb(0 0 0 / .18);
}
.topbar.offen .mehr-menue { display: block; }

.mehr-menue nav { display: flex; flex-direction: column; gap: 0; }
/* Die Zweitfassung der drei Bereiche. Sichtbar wird immer nur eine von
   beiden — die andere ist per display:none aus dem Dokument. */
.mehr-menue .nav-eng { display: none; }
.mehr-menue .nav-eng + nav {
  margin-top: .35rem;
  padding-top: .35rem;
  border-top: 1px solid var(--rule-soft);
}
.mehr-menue nav a {
  padding: .5rem .6rem;
  border-radius: var(--radius);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: .92rem;
  white-space: nowrap;
}
.mehr-menue nav a:hover { background: var(--surface-alt); color: var(--ink); }
/* Quer säße der Balken unter dem Wort in der Zeile darunter; als Strich
   links markiert er den Eintrag, ohne die Höhe zu verändern. */
.mehr-menue nav a[aria-current="page"] {
  background: var(--surface-alt);
  color: var(--ink);
  font-weight: 600;
  box-shadow: inset 2px 0 0 var(--accent);
}

.kopf-konto {
  display: flex;
  gap: .4rem;
  margin-top: .35rem;
  padding-top: .5rem;
  border-top: 1px solid var(--rule-soft);
}
.kopf-konto .knopf { flex: 1; justify-content: center; }
.kopf-konto form { flex: 1; display: flex; margin: 0; }
.kopf-konto form .knopf { width: 100%; }

/* --- Suche in der Kopfzeile: hinter der Lupe ---------------------------- *
 *
 * Zugeklappt bleibt der Platz für die Bereiche. Der Knopf ist die Lupe —
 * ein zweites Symbol im Feld daneben wäre dasselbe zweimal.
 */

.kopf-suche { display: flex; align-items: center; gap: .35rem; }
.lupe { flex: none; }

/* Über die Kennung und nicht über die Klasse: die allgemeine Feldregel
   weiter unten trägt fünf :not() und ist damit spezifischer als jede
   Klasse hier — mit .kopf-suche input bliebe das Feld einfach offen.
   Gemessen: 266 px statt 0. */
#kopfsuchfeld {
  width: 0;
  min-width: 0;
  padding: 0;
  border-width: 0;
  opacity: 0;
  background-image: none;
  transition: width .16s ease, opacity .16s ease;
}
.topbar.sucht #kopfsuchfeld {
  width: min(24rem, 42vw);
  padding: .38rem .7rem;
  border-width: 1px;
  opacity: 1;
}

/* Sehr schmal: die drei Bereiche wandern ins Menü. Sonst liefen sie über
   den Rand hinaus — gemessen ab etwa 480 px, und ein Scrollbalken oben war
   genau das, was hier weg sollte. */
@media (max-width: 30rem) {
  /* .topbar davor, weil „.topbar nav“ mit Klasse UND Typ spezifischer ist
     als „.nav-primaer“ allein — ohne das blieb die Leiste sichtbar und lief
     über den Rand. Ein Medienabschnitt ändert an der Spezifität nichts. */
  .topbar .nav-primaer { display: none; }
  .mehr-menue .nav-eng { display: flex; }
}

/* Auf dem Telefon liegt das Menü als Blatt unter der Leiste statt am Knopf:
   am Knopf ausgerichtet ragte es über den rechten Rand hinaus und erzeugte
   dabei einen Scrollbalken für die ganze SEITE. */
@media (max-width: 34rem) {
  .mehr-menue {
    position: fixed;
    left: .9rem;
    right: .9rem;
    top: 3.6rem;
    min-width: 0;
    max-width: none;
  }
}

/* Wer sucht, sucht gerade: bei schmalem Fenster weichen erst die Bereiche
   und dann die Wortmarke, statt dass alles gequetscht nebeneinander steht.
   Gemessen: ohne die zweite Stufe blieben auf einem Telefon 88 px Suchfeld
   übrig — breit genug für „Kart“ und sonst nichts. */
@media (max-width: 52rem) {
  .topbar.sucht .nav-primaer { display: none; }
  .topbar.sucht #kopfsuchfeld { width: min(24rem, 60vw); }
}
@media (max-width: 34rem) {
  .topbar.sucht .marke { display: none; }
  /* Das Formular muss mitwachsen — und der freie Platz darf nicht vorher
     im auto-Rand der Navigation versickern, sonst bleibt das Feld schmal,
     obwohl daneben nichts mehr steht. */
  .topbar.sucht .nav-block { margin-right: 0; }
  .topbar.sucht .kopf-suche { flex: 1 1 auto; min-width: 0; }
  .topbar.sucht #kopfsuchfeld { width: 100%; }
}

/* --- Gerüst ------------------------------------------------------------- */

.seite { max-width: 78rem; margin: 0 auto; padding: 1.75rem 1.5rem 5rem; }
.seite--schmal { max-width: 60rem; }

/* Solange die Spalte nicht danebenpasst, IST die Seite die Textspalte —
   und zentriert sich mit ihrem eigenen margin:auto. Kopfzeile und Inhalt
   stehen damit auch dann mittig, wenn die Ergänzung darunter rutscht. */
.seite--mittig { max-width: calc(36rem + 3rem); }

.kopfzeile {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}

.kopfzeile .anzahl { color: var(--muted); font-size: .85rem; }

/* --- Listenseite: Filterleiste plus Ergebnisse -------------------------- */

.arbeitsflaeche {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  gap: 1.75rem;
  align-items: start;
}

.filter {
  position: sticky;
  top: 4.5rem;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  font-size: .875rem;
  max-height: calc(100vh - 6rem);
  overflow-y: auto;
  padding-right: .25rem;
}

/* Breite Fenster: die Filter stehen offen da, der Knopf ist überflüssig.
   Umgekehrt gedacht — zugeklappt ist der Ausnahmefall, nicht der Normalfall. */
.filter-schalter { display: none; }

.filter-inhalt {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.filter-gruppe { display: flex; flex-direction: column; gap: .3rem; }
.filter-gruppe > .etikett { margin-bottom: .1rem; }

.filter-wahl {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .18rem .35rem;
  border-radius: var(--radius);
  cursor: pointer;
  color: var(--ink-soft);
  line-height: 1.35;
}
.filter-wahl:hover { background: var(--surface-alt); color: var(--ink); }
.filter-wahl input { margin: 0; accent-color: var(--accent); flex: none; }
.filter-wahl .n {
  margin-left: auto;
  font-family: "IBM Plex Mono", monospace;
  font-size: .72rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.filter-wahl:has(input:checked) { color: var(--ink); font-weight: 500; }

.filter-leeren {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font-size: .8rem;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* --- Suchfeld ----------------------------------------------------------- */

.suche { position: relative; display: flex; }

/* Lupe als SVG im Hintergrund statt als Schriftzeichen ⌕: das Zeichen ist
   je nach Schrift winzig oder fehlt ganz, und es sass zu weit rechts, sodass
   der Platzhaltertext darueberlief. Die Grafik hat eine feste Groesse und
   der Innenabstand links ist darauf abgestimmt. */
.suche input {
  width: 100%;
  padding: .5rem .75rem .5rem 2.35rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: .9rem;

  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23667083' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='8.5' cy='8.5' r='5.5'/%3E%3Cpath d='M12.5 12.5 L17 17'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: .6rem center;
  background-size: 1.05rem 1.05rem;
}
.suche input::placeholder { color: var(--muted); }

/* Zugeklappt nimmt die Suche nur die Lupe ein. Hier stand einmal
   width: min(19rem, 30vw) — das hielt den Platz fürs Feld auch dann frei,
   wenn es gar nicht da war: gemessen 304 px Leere zwischen Lupe und
   Umschalter. Die Breite kommt jetzt allein vom Zustand. */
.kopf-suche { flex: none; }
.kopf-suche input { font-size: .85rem; }

.nachladen {
  display: block;
  width: 100%;
  padding: .7rem 1rem;
  border: none;
  border-top: 1px solid var(--rule-soft);
  border-radius: 0;
  background: var(--surface);
  color: var(--accent);
  font: inherit;
  font-size: .87rem;
  cursor: pointer;
}
.nachladen:hover { background: var(--surface-alt); }

.bereichswahl { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: 1.25rem; }
.bereichswahl .chip { padding: .3rem .7rem; font-size: .82rem; }
.bereichswahl .zahl { opacity: .65; margin-left: .2rem; }

/* Textausschnitt im Suchtreffer: normale Schrift statt Mono, weil hier
   Fließtext steht und keine Kennzahlen. */
.zeile .auszug {
  font-family: inherit;
  font-size: .85rem;
  color: var(--ink-soft);
  line-height: 1.5;
}

/* --- Trefferliste ------------------------------------------------------- */

.treffer {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}

.zeile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: .2rem 1rem;
  padding: .8rem 1rem;
  border-bottom: 1px solid var(--rule-soft);
  text-decoration: none;
  color: inherit;
}
.zeile:last-child { border-bottom: none; }
.zeile:hover { background: var(--surface-alt); }

/* Bewusst NICHT in Bodoni: die Didone hat haarfeine Striche, die bei
   Listengroesse ausfransen und auf dunklem Grund fast verschwinden. Bodoni
   bleibt den grossen Ueberschriften vorbehalten, wo sie traegt. */
.zeile .titel {
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.006em;
  color: var(--ink);
}
.zeile:hover .titel { color: var(--accent); }

/* Über beide Spalten und einzeilig: so ist jede Zeile der Liste gleich
   hoch — vorher wuchs sie mit dem Inhalt, und die Liste wirkte zerfranst.
   Was nicht mehr hinpasst, blendet am rechten Rand aus statt umzubrechen. */
/* Die Kurzbeschreibung. Zwei Zeilen fest — auch wenn der Text nur eine
   braucht oder ganz fehlt: sonst wäre jede Zeile der Liste wieder anders
   hoch, und genau das war schon einmal das Problem. Was nicht hineinpasst,
   endet in Auslassungspunkten; bei Fließtext ist das ehrlicher als ein
   Verlauf, weil man sieht, dass abgeschnitten wurde. */
.zeile .kurzzeile {
  grid-column: 1 / -1;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  min-height: 2.6em;
  margin-top: .1rem;
  font-size: .875rem;
  line-height: 1.3;
  color: var(--ink-soft);
}

.zeile .unterzeile {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: nowrap;
  overflow: hidden;
  position: relative;
  gap: .1rem .7rem;
  font-size: .8rem;
  color: var(--muted);
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
}
.zeile .unterzeile b { font-weight: 400; color: var(--ink-soft); }
.zeile .unterzeile > span { white-space: nowrap; }

/* Ausdrücklich Spalte 2, Zeile 1. Mit bloßem „span 2“ schob die
   automatische Platzierung den Block eine Zeile nach unten — er begann auf
   Höhe der Unterzeile und riss darunter eine weitere Rasterzeile auf.
   Gemessen kostete das 25 px in JEDER Zeile jeder Liste. */
.zeile .rechts {
  grid-column: 2;
  grid-row: 1;
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: nowrap;
  justify-content: flex-end;
}

/* Die Marken über die ganze Breite, einzeilig, mit weichem Abriss am Rand.
   Die feste Mindesthöhe hält auch Zeilen ohne Marken auf Maß — sonst wäre
   ausgerechnet der karge Trick der, der aus der Reihe fällt. */
.zeile .markenzeile {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  min-width: 0;
  min-height: 1.45rem;
  position: relative;
}
.zeile .marken {
  display: flex;
  flex-wrap: nowrap;
  gap: .35rem;
  min-width: 0;
  overflow: hidden;
}
.zeile .marken .chip { flex: none; }

/* Der weiche Abriss liegt am ZEILENRAND, nicht auf dem Inhalt. Als Maske auf
   dem Inhalt blendete er auch dann die letzte Marke aus, wenn noch die halbe
   Zeile frei war — im Bild gesehen. So liegt er über leerem Grund, solange
   nichts überläuft, und wird erst sichtbar, wenn etwas darunter gerät. */
.zeile .unterzeile::after,
.zeile .markenzeile::after {
  content: "";
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: 2.5rem;
  pointer-events: none;
  background: linear-gradient(to right, transparent, var(--surface));
}
.zeile:hover .unterzeile::after,
.zeile:hover .markenzeile::after {
  background: linear-gradient(to right, transparent, var(--surface-alt));
}

/* Bloß verzeichnet, nicht erfasst: kein Link, also auch kein Hover und kein
   Akzent beim Überfahren. Gedämpft, aber lesbar — die Zeile ist ja der Grund,
   warum das Verzeichnis existiert. Der Strich links trennt sie vom Erfassten,
   ohne dass man zwei Listen bräuchte. */
.zeile--verzeichnet {
  cursor: default;
  background: linear-gradient(to right, var(--surface-alt), transparent 40%);
}
.zeile--verzeichnet:hover { background: linear-gradient(to right, var(--surface-alt), transparent 40%); }
.zeile--verzeichnet .titel { font-weight: 500; color: var(--ink-soft); }
.zeile--verzeichnet .rechts form { margin: 0; }

/* Die Kurzbeschreibung steht in der Unterzeile, die sonst Kennzahlen trägt —
   also zurück auf die Fließschrift. Mono läse sich hier wie ein Protokoll. */
.verzeichnis-text { font-family: inherit; color: var(--ink-soft); }

.knopf--klein { padding: .2rem .55rem; font-size: .76rem; }

/* Eine Auswahl aus zwei Möglichkeiten, untereinander. Djangos RadioSelect
   liefert je ein <div> mit einem <label> darin, das den Knopf umschließt —
   das Label ist also die anklickbare Zeile und nicht nur der Text daneben. */
.wahlfeld { border: 0; padding: 0; margin: 0; min-width: 0; }
.wahlfeld legend {
  padding: 0;
  font-size: .82rem;
  color: var(--ink-soft);
  font-weight: 500;
}
.wahlliste { margin-top: .35rem; }
.wahlliste label {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .25rem 0;
  margin: 0;
  font: inherit;
  color: var(--ink);
  cursor: pointer;
}
.wahlliste input { accent-color: var(--accent); margin: 0; flex: none; }

.formularknoepfe { display: flex; gap: .5rem; align-items: center; margin: 0; }

/* --- Zustandsmarken ----------------------------------------------------- */

.marke-status, .chip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .1rem .45rem;
  border-radius: 2px;
  font-size: .72rem;
  line-height: 1.5;
  white-space: nowrap;
  border: 1px solid transparent;
}

.marke-status {
  font-family: "IBM Plex Mono", monospace;
  letter-spacing: .04em;
}
.marke-status::before { content: "●"; font-size: .6em; }

.status-reif     { background: var(--gut-grund);    color: var(--gut);    border-color: var(--gut); }
.status-lerne    { background: var(--warn-grund);   color: var(--warn);   border-color: var(--warn); }
.status-idee     { background: var(--surface-alt);  color: var(--muted);  border-color: var(--rule); }
.status-abgelegt { background: transparent;         color: var(--muted);  border-color: var(--rule); }

.chip {
  background: var(--surface-alt);
  color: var(--ink-soft);
  border-color: var(--rule-soft);
  text-decoration: none;
}
a.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip--effekt { background: var(--blau-grund); color: var(--blau); border-color: transparent; }
.chip--form   { background: var(--accent-grund); color: var(--accent); border-color: transparent; }
/* „+3“ — bewusst farblos: es ist eine Zählung, keine weitere Kategorie. */
.chip--rest   { background: transparent; color: var(--muted); border-color: var(--rule-soft); }

.sterne { color: var(--accent); letter-spacing: .06em; font-size: .8rem; white-space: nowrap; }
.sterne .rest { color: var(--rule); }

/* --- Detailseite -------------------------------------------------------- */

.detail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 19rem;
  gap: 2.5rem;
  align-items: start;
}

/* Der Text ist der Inhalt, die Spalte daneben eine Ergänzung. Mittig gehört
   deshalb der TEXT und nicht der Block aus beidem — sonst sitzt das, worauf
   es ankommt, links aus der Mitte, und das sieht schief aus, weil es schief
   ist.

   Der Kniff ist eine dritte, leere Spalte links, genauso breit wie die
   rechte. Damit steht die Textspalte in der Mitte, und die Ergänzung haengt
   rechts daneben. Die Textspalte nimmt, was uebrig bleibt: bei 1200 Pixeln
   Inhaltsbreite sind das 512, bei 1088 noch 400 — nie mehr als das
   Zeilenmaß und nie weniger als rund 52 Zeichen. */
@media (min-width: 71rem) {
  .seite--mittig { max-width: 78rem; }

  .seite--mittig .detail {
    grid-template-columns: minmax(0, 19rem) minmax(0, 36rem) 19rem;
    justify-content: center;
  }
  .seite--mittig .detail > :first-child { grid-column: 2; }
  .seite--mittig .detail > .rail { grid-column: 3; }

  /* Die Kopfzeile gehört zum Text und muss mit ihm wandern. Gleiche Ränder
     links und rechts heißt: dieselbe Spanne wie die mittlere Spalte. */
  .seite--mittig .detail-kopf {
    margin-left: calc(19rem + 2.5rem);
    margin-right: calc(19rem + 2.5rem);
  }
}

.detail-kopf { display: flex; flex-direction: column; gap: .6rem; margin-bottom: 1.75rem; }

.detail-kopf .zurueck {
  font-family: "IBM Plex Mono", monospace;
  font-size: .75rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
}

.detail-kopf .marken { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }

/* Zwei Kacheln je Zeile, und genauso breit wie der Fließtext daneben.

   Vorher liefen sie über die ganze Spalte, während der Text bei 64ch endete
   — dazwischen stand eine Stufe von rund 280 Pixeln, und die sah aus wie ein
   Fehler. Dasselbe Maß für beides, und die Kante stimmt wieder.

   Im Fluss statt im Raster: bei ungerader Kachelzahl ließ das Raster die
   letzte Zeile halb leer, und weil die Fugen die Linienfarbe zeigen, war das
   ein dunkler Klotz ohne Inhalt. So zieht sich die letzte über die Zeile. */
.kennzahlen {
  display: flex;
  flex-wrap: wrap;
  max-width: 64ch;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  margin: 1.5rem 0;
  overflow: hidden;
}

/* Etwas Luft zwischen Kante und Inhalt. Seit die Kacheln nur noch zwei je
   Zeile sind, sind sie breiter — und mit dem alten, engen Innenrand klebte
   der Wert am Rahmen. */
.kennzahlen > div {
  flex: 1 1 45%;
  min-height: 4.2rem;
  background: var(--surface);
  padding: .8rem 1.1rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .2rem;
}
.kennzahlen dt { font-family: "IBM Plex Mono", monospace; font-size: .64rem;
                 letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.kennzahlen dd { margin: 0; font-size: .92rem; font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.kennzahlen .fehlt { color: var(--muted); font-weight: 400; }

.abschnitt { margin-bottom: 2rem; display: flex; flex-direction: column; gap: .6rem; }
/* Flex, damit rechts ein Stand stehen kann („12 von 58 erfasst“). Mit nur
   einem Textkind sieht es aus wie vorher — alle anderen Abschnitte bleiben
   deshalb unberührt. */
.abschnitt > .etikett {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  border-bottom: 1px solid var(--rule);
  padding-bottom: .35rem;
}
.etikett-zahl { letter-spacing: .06em; text-transform: none; color: var(--muted); font-weight: 400; }

.fliesstext { max-width: 64ch; color: var(--ink-soft); }
.fliesstext p { margin: 0 0 .8rem; }
.fliesstext p:last-child { margin-bottom: 0; }

/* Ein Text, der zugeklappt anfängt. Sechs Zeilen sagen, worum es geht; der
   Rest läuft aus, statt abgehackt zu enden — eine harte Kante liest sich wie
   ein Fehler, ein Verlauf wie „da kommt noch was“.

   Der Verlauf steht auf dem Seitengrund und nicht auf --surface: der Text
   liegt in beiden Themes direkt auf der Seite. Läge er einmal auf einer
   Karte, bekäme diese Karte ihre eigene Regel. */
.gekuerzt {
  position: relative;
  overflow: hidden;
  max-height: calc(var(--zeilen, 6) * 1.6em);
}
.gekuerzt::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 3em;
  background: linear-gradient(to bottom, transparent, var(--ground));
  pointer-events: none;
}
/* Solange gekürzt wird, ist der ganze Block der Schalter — auf dem Telefon
   ist die Fläche das Ziel, nicht die Zeile Text darunter. */
.gekuerzt--klickbar { cursor: pointer; }
.gekuerzt--offen { max-height: none; cursor: auto; }
.gekuerzt--offen::after { display: none; }

.mehr-text {
  display: inline-block;
  margin-top: .5rem;
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font: inherit;
  font-size: .85rem;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Die Methode ist das Geheimnis — sie bekommt eine eigene Anmutung, damit
   beim Überfliegen klar ist, was der Zuschauer sehen darf und was nicht. */
.methode {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: .9rem 1.1rem;
}

/* --- Anleitung: Text, Bilder, Video ------------------------------------- */

.anleitung > :first-child { margin-top: 0; }
.anleitung h2, .anleitung h3, .anleitung h4 {
  font-family: "IBM Plex Sans", sans-serif;
  font-size: .98rem;
  font-weight: 600;
  color: var(--ink);
  margin: 1.4rem 0 .4rem;
  letter-spacing: 0;
}
.anleitung ul, .anleitung ol { margin: 0 0 .9rem; padding-left: 1.3rem; }
.anleitung li { margin-bottom: .3rem; }
.anleitung li::marker { color: var(--accent); }
.anleitung blockquote {
  margin: 0 0 .9rem;
  padding-left: .9rem;
  border-left: 2px solid var(--rule);
  color: var(--muted);
}
.anleitung pre {
  background: var(--surface-alt);
  padding: .7rem .9rem;
  border-radius: var(--radius);
  overflow-x: auto;
}
/* Ein Bild im Text ist so breit wie der Text und keinen Pixel breiter.
   Ohne Deckel nimmt der Browser die Naturgröße der Datei — ein Foto aus der
   Kamera schiebt sich damit quer über die Seitenspalte hinweg und aus der
   Seite heraus. Die Höhe bekommt denselben Deckel, sonst wäre ein hochkant
   fotografiertes Blatt drei Bildschirme lang.

   Klein ist hier Absicht: groß gibt es das Bild mit einem Klick, in der
   Bildschau über der Seite. Daher der Zeiger mit dem Plus. */
.fliesstext img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 70vh;
  margin: 1rem 0;
  border-radius: var(--radius);
  border: 1px solid var(--rule);
  cursor: zoom-in;
}

.medium { margin: 1rem 0 0; }
.medium img, .medium video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  border: 1px solid var(--rule);
  background: var(--surface-alt);
}
.medium img { cursor: zoom-in; }
.medium figcaption {
  margin-top: .35rem;
  font-size: .8rem;
  color: var(--muted);
}

.bildstrecke {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 1rem;
  margin-top: .5rem;
}
.bildstrecke .medium { margin: 0; }

.videolink {
  display: flex;
  align-items: center;
  gap: .8rem;
  margin-top: 1rem;
  padding: .75rem .9rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  text-decoration: none;
  color: var(--ink);
  max-width: 64ch;
}
.videolink:hover { border-color: var(--accent); }
.videolink .play {
  flex: none;
  width: 2rem; height: 2rem;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--accent); color: #fff;
  font-size: .9rem;
}
.videolink span span { display: block; }
.videolink .rolle { font-size: .78rem; color: var(--muted); }

/* --- Bildschau: ein Bild über der ganzen Seite --------------------------- *

   Im Text ist eine Abbildung so breit wie die Spalte. Das reicht, um zu
   sehen, dass da ein Bild ist — nicht, um eine Markierung am Rand einer
   Spielkarte zu finden. Ein Klick legt das Bild in voller Größe über die
   Seite, ein zweiter räumt es weg.

   Ein <dialog> und kein eigener Kasten: Escape, der Fokusfang und das
   Stilllegen der Seite dahinter kommen dann vom Browser.

   Dunkel in beiden Themes. Ein Bild braucht einen Grund, der ihm keine
   Farbe leiht, und der ist schwarz — auch wenn die Seite hell ist. */

.bildschau {
  /* Der Standard-Dialog ist ein Kasten in der Mitte. Hier ist er die ganze
     Fläche, damit auch der Rand neben dem Bild noch zum Wegklicken taugt. */
  width: 100%;
  max-width: 100%;
  height: 100%;
  max-height: 100%;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  color: #F2F3F5;
  overflow: hidden;
}
/* Fast, aber nicht ganz deckend: ein Rest der Seite bleibt zu ahnen, damit
   klar ist, dass hier nichts weg ist, sondern nur etwas davor liegt. */
.bildschau::backdrop { background: rgba(6, 8, 11, .94); }

.bildschau-flaeche {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .8rem;
  padding: 3rem 1.5rem 2rem;
  box-sizing: border-box;
  cursor: zoom-out;
}

/* Deckel auf Breite und Höhe, beide Maße sonst „auto“: so rechnet der
   Browser das Bild selbst auf die passende Größe herunter und behält dabei
   sein Seitenverhältnis. Mit object-fit stünde stattdessen ein Kasten in
   Naturgröße da, in dem das Bild schwebt — und der Rahmen läge um den
   Kasten statt um das Bild. Die 9rem sind Polster, Abstand und Zeile
   darunter; wo dvh geht, ist es dvh, denn auf dem Telefon zählt vh die
   eingeklappte Adresszeile mit. */
.bildschau-bild {
  flex: none;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: calc(100vh - 9rem);
  max-height: calc(100dvh - 9rem);
  border-radius: var(--radius);
  /* Ein heller Rahmen: sonst verliert ein Bild mit weißem Grund seine Kante
     im dunklen Feld und franst aus. */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .14), 0 18px 50px rgba(0, 0, 0, .55);
}

.bildschau-text {
  margin: 0;
  flex: none;
  max-width: 64ch;
  text-align: center;
  font-size: .84rem;
  color: #A8AEBB;
}

.bildschau-zu {
  position: absolute;
  top: .85rem;
  right: .85rem;
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, .2);
  border-radius: 50%;
  background: rgba(255, 255, 255, .08);
  color: #F2F3F5;
  cursor: pointer;
}
.bildschau-zu:hover { background: rgba(255, 255, 255, .18); }

/* --- Seitenspalte der Detailseite --------------------------------------- */

.rail { display: flex; flex-direction: column; gap: 1.25rem; position: sticky; top: 4.5rem; }

.karte {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--schatten);
  overflow: hidden;
}
.karte > .etikett { display: block; padding: .6rem .9rem; border-bottom: 1px solid var(--rule); }
.karte ul { list-style: none; margin: 0; padding: 0; }
.karte li { padding: .55rem .9rem; border-bottom: 1px solid var(--rule-soft); font-size: .87rem; }
.karte li:last-child { border-bottom: none; }
.karte .leerhinweis { padding: .8rem .9rem; color: var(--muted); font-size: .84rem; }

.fundstelle { display: flex; flex-direction: column; gap: .15rem; }
.fundstelle .wo { display: flex; gap: .5rem; align-items: baseline; }
.fundstelle .stelle {
  margin-left: auto;
  font-family: "IBM Plex Mono", monospace;
  font-size: .78rem;
  color: var(--accent);
  white-space: nowrap;
}
.fundstelle .rolle { font-size: .72rem; color: var(--muted); }

/* Beherrschungsgrad eines Griffs — Form trägt die Information mit, nicht
   nur die Farbe. */
.griff { display: flex; align-items: center; gap: .5rem; }
.griff .stand { flex: none; width: .55rem; height: .55rem; border-radius: 50%; border: 1.5px solid var(--muted); }
.griff .stand--sitzt  { background: var(--gut);  border-color: var(--gut); }
.griff .stand--uebung { background: linear-gradient(90deg, var(--warn) 50%, transparent 50%); border-color: var(--warn); }
.griff .stand--offen  { background: transparent; }
.griff .name { flex: 1; min-width: 0; }

/* --- Balken für Größenvergleiche ---------------------------------------- */

.balken { display: flex; flex-direction: column; gap: .45rem; }

.balken-zeile {
  display: grid;
  grid-template-columns: minmax(6rem, 11rem) 1fr auto;
  align-items: center;
  gap: .75rem;
  font-size: .87rem;
}

.balken-name { color: var(--ink-soft); overflow-wrap: anywhere; }

.balken-spur {
  height: .8rem;
  background: var(--surface-alt);
  border-radius: 2px;
  overflow: hidden;
}

/* Eine Farbe für alle Größenbalken. Das ist ein Groessenvergleich, kein
   Nebeneinander verschiedener Reihen — verschiedene Farben wuerden eine
   Unterscheidung behaupten, die es nicht gibt. */
.balken-strich {
  display: block;
  height: 100%;
  min-width: 2px;
  background: var(--blau);
  border-radius: 2px;
}

/* Statusbalken tragen die Zustandsfarben. Beschriftung und Wert stehen
   daneben im Klartext — die Farbe ist Beiwerk, nicht der Traeger der
   Bedeutung. So bleibt es lesbar bei Farbenblindheit und im Ausdruck. */
.balken-strich--0 { background: var(--muted); }
.balken-strich--1 { background: var(--warn); }
.balken-strich--2 { background: var(--gut); }
.balken-strich--3 { background: var(--rule); }

.balken-wert {
  color: var(--ink);
  font-family: "IBM Plex Mono", monospace;
  font-size: .82rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --- Programmnummer im Routinenablauf ----------------------------------- */

.programmnummer {
  display: inline-grid;
  place-items: center;
  width: 1.4rem; height: 1.4rem;
  margin-right: .4rem;
  border: 1px solid var(--rule);
  border-radius: 50%;
  background: var(--ground);
  font-family: "IBM Plex Mono", monospace;
  font-size: .72rem;
  color: var(--muted);
  vertical-align: .05em;
}

/* --- Chat --------------------------------------------------------------- */

.nachricht {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  padding: .9rem 1.1rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  margin-bottom: .75rem;
}

/* Die eigene Frage abgesetzt, damit man den Gesprächsverlauf beim
   Überfliegen wiederfindet. */
.nachricht--ich {
  background: var(--surface-alt);
  border-color: var(--rule-soft);
}
.nachricht--ich .fliesstext { color: var(--ink); }

.nachricht .fliesstext { max-width: none; }
.nachricht .fliesstext > :first-child { margin-top: 0; }
.nachricht .fliesstext > :last-child { margin-bottom: 0; }

.werkzeugspur { margin-top: .4rem; }
.werkzeugspur summary {
  font-family: "IBM Plex Mono", monospace;
  font-size: .74rem;
  color: var(--muted);
  cursor: pointer;
  list-style: none;
}
.werkzeugspur summary::-webkit-details-marker { display: none; }
.werkzeugspur summary::before { content: "▸ "; }
.werkzeugspur[open] summary::before { content: "▾ "; }
.werkzeugspur ul {
  list-style: none;
  margin: .4rem 0 0;
  padding: .5rem .7rem;
  background: var(--ground);
  border-radius: var(--radius);
  font-size: .78rem;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.werkzeugspur .rolle { color: var(--muted); font-size: .74rem; }

.chat-eingabe { display: flex; gap: .5rem; margin-top: 1rem; }
.chat-eingabe input { flex: 1; }
.chat-eingabe button { flex: none; }

/* htmx sperrt Feld und Knopf, solange die Antwort läuft. */
.chat-eingabe button:disabled { opacity: .55; cursor: wait; }
.chat-eingabe input:disabled { opacity: .7; }

/* --- Leerzustand ----------------------------------------------------- */

.leerzustand {
  background: var(--surface);
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  padding: 3rem 1.5rem;
  text-align: center;
  color: var(--muted);
}
.leerzustand p { margin: 0 0 1rem; }

/* --- Schaltflächen ------------------------------------------------------ */

.knopf {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .42rem .85rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-size: .87rem;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.knopf:hover { filter: brightness(1.08); color: #fff; }

.knopf--stumm {
  background: var(--surface);
  color: var(--ink);
  border-color: var(--rule);
}
.knopf--stumm:hover { color: var(--ink); border-color: var(--muted); filter: none; }

/* --- Ladeanzeige -------------------------------------------------------- */

.htmx-request .treffer { opacity: .55; transition: opacity .12s; }

/* --- Formulare der Anwendung -------------------------------------------- */

.formular { display: flex; flex-direction: column; gap: 1.75rem; }

/* Einklappbare Bereiche. <details> statt eigener Klapplogik: das kann der
   Browser, es ist mit der Tastatur bedienbar, und es funktioniert auch ohne
   JavaScript. */
.feldgruppe {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}

.feldgruppe > summary {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .85rem 1.35rem;
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--ink);
  cursor: pointer;
  user-select: none;
  list-style: none;
}
.feldgruppe > summary::-webkit-details-marker { display: none; }

/* Eigener Pfeil, damit er in beiden Themen sitzt und sich mitdreht. */
.feldgruppe > summary::before {
  content: "";
  flex: none;
  width: .42rem; height: .42rem;
  border-right: 1.75px solid var(--accent);
  border-bottom: 1.75px solid var(--accent);
  transform: rotate(-45deg);
  margin-left: .12rem;
  transition: transform .14s ease;
}
.feldgruppe[open] > summary::before { transform: rotate(45deg); margin-top: -.2rem; }

.feldgruppe > summary:hover { background: var(--surface-alt); }
.feldgruppe[open] > summary { border-bottom: 1px solid var(--rule); }

.feldgruppe-inhalt {
  display: flex;
  flex-direction: column;
  gap: .9rem;
  padding: 1.15rem 1.35rem 1.35rem;
}

/* Muss abgeschickt werden, soll aber niemand sehen: das Löschkästchen der
   Fundstellen wird über das × der Zeile bedient. */
.nur-fuer-formular {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.feld { display: flex; flex-direction: column; gap: .3rem; }
.feld > label { font-size: .82rem; color: var(--muted); }
.feld--fehler input, .feld--fehler textarea, .feld--fehler select { border-color: var(--accent); }

.feld-haken { display: flex; align-items: center; gap: .5rem; color: var(--ink); font-size: .9rem; }
.feld-haken input { accent-color: var(--accent); margin: 0; }

.hilfe { font-size: .78rem; color: var(--muted); line-height: 1.45; }

input[type="file"] {
  font-size: .85rem;
  color: var(--ink-soft);
  padding: .45rem;
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  background: var(--ground);
  width: 100%;
}
input[type="file"]::file-selector-button {
  margin-right: .7rem;
  padding: .3rem .7rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: .82rem;
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover { border-color: var(--accent); color: var(--accent); }

.feldreihe {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: .9rem;
}

/* --- Tag-Auswahl -------------------------------------------------------- */

.taggruppe { gap: .45rem; }

.tagwahl { display: flex; flex-wrap: wrap; gap: .4rem; }

.tagmarke {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .22rem .55rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--ground);
  font-size: .82rem;
  color: var(--ink-soft);
  cursor: pointer;
}
.tagmarke:hover { border-color: var(--muted); }
.tagmarke input { margin: 0; accent-color: var(--accent); }
.tagmarke:has(input:checked) {
  background: var(--accent-grund);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 500;
}

/* --- Markdown-Editor ---------------------------------------------------- */

.editor {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}

.editor-leiste {
  display: flex;
  flex-wrap: wrap;
  gap: .15rem;
  padding: .3rem;
  background: var(--surface-alt);
  border-bottom: 1px solid var(--rule);
}

.editor-knopf {
  padding: .22rem .5rem;
  min-width: 1.9rem;
  border: 1px solid transparent;
  border-radius: 2px;
  background: transparent;
  color: var(--ink-soft);
  font-family: "IBM Plex Mono", monospace;
  font-size: .78rem;
  line-height: 1.4;
  cursor: pointer;
}
.editor-knopf:hover { background: var(--surface); border-color: var(--rule); color: var(--ink); }
.editor-vorschau { margin-left: auto; font-family: inherit; }

.editor textarea {
  border: none;
  border-radius: 0;
  background: var(--surface);
  font-family: "IBM Plex Mono", monospace;
  font-size: .84rem;
  line-height: 1.6;
  resize: vertical;
}
.editor textarea:focus-visible { outline-offset: -2px; }

.editor-ausgabe { padding: .9rem 1rem; min-height: 6rem; }

/* --- Bildauswahl im Editor ---------------------------------------------- */

.editor-leiste { position: relative; }

.bildwahl {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 30;
  width: min(24rem, 90vw);
  max-height: 20rem;
  overflow-y: auto;
  margin-top: .3rem;
  padding: .4rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
}
.bildwahl .hilfe { padding: .5rem; margin: 0; }

.bildwahl-eintrag {
  display: flex;
  align-items: center;
  gap: .6rem;
  width: 100%;
  padding: .35rem;
  border: 1px solid transparent;
  border-radius: 2px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: .84rem;
  text-align: left;
  cursor: pointer;
}
.bildwahl-eintrag:hover { background: var(--surface-alt); border-color: var(--rule); }
.bildwahl-eintrag img {
  flex: none;
  width: 3.2rem; height: 2.2rem;
  object-fit: cover;
  border-radius: 2px;
  border: 1px solid var(--rule);
}

/* Die Miniatur in Dateilisten: absichtlich klein, sie steht neben dem
   Dateinamen. Fuer ein Foto auf einer Detailseite ist sie das falsche
   Werkzeug — dort gehoert .bildkarte hin. */
.dateivorschau {
  flex: none;
  width: 2.4rem; height: 1.7rem;
  object-fit: cover;
  border-radius: 2px;
  border: 1px solid var(--rule);
}

/* Ein Bild, das seine Karte ausfuellt: Umschlag, Portraet, Foto eines
   Requisits. Alle drei sahen vorher gleich aus, waren es aber nicht — zwei
   trugen denselben Inline-Stil, das dritte die Miniaturklasse und war
   deshalb 38 Pixel breit. `display: block`, weil ein Bild sonst auf der
   Grundlinie sitzt und darunter ein heller Streifen bleibt. */
.bildkarte img {
  display: block;
  width: 100%;
}

.einfuegeknopf {
  flex: none;
  padding: .2rem .5rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--surface);
  color: var(--ink-soft);
  font: inherit;
  font-size: .74rem;
  cursor: pointer;
}
.einfuegeknopf:hover { border-color: var(--accent); color: var(--accent); }

/* --- Suchfeld für Auswahllisten ----------------------------------------- */

.suchwahl { position: relative; min-width: 0; }

/* Die zweite Zeile wiederholt die Ausnahmeliste der Grundregel fuer
   Eingabefelder und haengt ein Glied an. Ohne sie schlaegt deren
   width:100% (fuenf :not(), also spezifischer als eine Klasse) das
   width:1px hier: nachgemessen 910 statt 1 Pixel. Das Feld ist unsichtbar,
   aber absolut positioniert — es ragte also unsichtbar aus der Seite und
   schob je nach Fensterbreite den Scrollbalken herein, sobald sein Bereich
   aufgeklappt war. Bei <select> tritt das nicht auf: dessen Grundregel
   traegt keine Ausnahmeliste und verliert gegen die Klasse. */
.suchwahl-verborgen,
input.suchwahl-verborgen:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="submit"]):not([type="button"]) {
  /* Bleibt im Dokument, damit das Formular unveraendert den echten Wert
     schickt — nur unsichtbar und nicht anspringbar. */
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.suchwahl-feld { width: 100%; font-size: .84rem; padding: .35rem .5rem; }

/* Fest positioniert, nicht absolut: absolut hinge sie im nächsten
   positionierten Vorfahren, und .feldgruppe schneidet mit overflow:hidden
   alles ab, was über ihre runden Ecken hinausragt — die Liste endete an der
   Kastenkante. Maße und Ort setzt editor.js, weil sie sonst niemand kennt. */
.suchwahl-liste {
  position: fixed;
  z-index: 40;
  max-height: 14rem;
  overflow-y: auto;
  margin: .2rem 0 0;
  padding: .2rem;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
}
.suchwahl-liste li {
  padding: .3rem .45rem;
  border-radius: 2px;
  font-size: .84rem;
  cursor: pointer;
}
.suchwahl-liste li:hover, .suchwahl-liste li.an { background: var(--accent-grund); color: var(--accent); }
.suchwahl-liste .suchwahl-leer { color: var(--muted); cursor: default; }
.suchwahl-liste .suchwahl-leer:hover { background: transparent; color: var(--muted); }

/* --- Fundstellen-Zeilen ------------------------------------------------- */

.zeilenblock {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
  padding: .5rem 0;
  border-bottom: 1px solid var(--rule-soft);
}
.zeilenblock:last-of-type { border-bottom: none; }

.zeile-felder {
  display: grid;
  grid-template-columns: minmax(0, 2.2fr) minmax(0, .9fr) minmax(0, .9fr) minmax(0, 1.1fr);
  gap: .4rem;
  flex: 1;
  min-width: 0;
}
.zeile-felder select, .zeile-felder input { font-size: .84rem; padding: .35rem .5rem; }

.zeile-weg { display: flex; align-items: center; gap: .3rem; font-size: .78rem; color: var(--muted); }
.zeile-weg input { accent-color: var(--accent); }

/* Zum Löschen vorgemerkt — bleibt sichtbar, damit klar ist, was beim
   Speichern verschwindet. */
.zeile-gestrichen { opacity: .45; }
.zeile-gestrichen .zeile-felder { text-decoration: line-through; }

/* --- Dateiliste --------------------------------------------------------- */

.dateiliste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .3rem; }
.dateiliste li {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .4rem .6rem;
  background: var(--ground);
  border: 1px solid var(--rule-soft);
  border-radius: var(--radius);
  font-size: .86rem;
}
.dateiliste .rolle { margin-left: auto; font-size: .74rem; color: var(--muted); }

.loeschknopf {
  flex: none;
  width: 1.6rem; height: 1.6rem;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.loeschknopf svg { display: block; }
.loeschknopf:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-grund); }

/* --- Fuss des Formulars ------------------------------------------------- */

.formular-fuss {
  display: flex;
  align-items: center;
  gap: .75rem;
  flex-wrap: wrap;
  padding-top: .25rem;
}

/* Löschen steht bewusst abgesetzt und farblos, damit es nicht versehentlich
   neben „Speichern“ getroffen wird. */
.formular-fuss .loeschen {
  margin-left: auto;
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--muted);
  font-size: .85rem;
  padding: .42rem .85rem;
  border-radius: var(--radius);
  cursor: pointer;
}
.formular-fuss .loeschen:hover { border-color: var(--accent); color: var(--accent); }

/* --- Formulare (Login und Passkey) -------------------------------------- */

/* Feldabsaetze stapeln Beschriftung und Feld untereinander. Hilfetexte
   ausgenommen: als Flexbehaelter wird darin jedes <b> und <em> zum eigenen
   Block und reisst mitten im Satz eine Zeile auf. */
form p:not(.hilfe) { display: flex; flex-direction: column; gap: .3rem; }
label { font-size: .82rem; color: var(--muted); }

/* Bewusst als Ausschluss statt als Aufzaehlung der Typen: sonst faellt jedes
   Feld durch, dessen Typ man beim Schreiben nicht auf dem Zettel hatte —
   number und url sahen genau deshalb im Dunkelmodus weiss aus. */
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="submit"]):not([type="button"]),
select, textarea {
  padding: .5rem .7rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  width: 100%;
}

/* Grundgestalt für Knöpfe ohne eigene Klasse — vor allem die, die allauth
   auf den Anmeldeseiten selbst erzeugt.

   :where() bewusst gewählt: es zählt bei der Spezifität als null. Damit
   gewinnt jede Komponentenklasse ohne Ausnahmeliste. Vorher stand hier
   button:not(.knopf):not(.filter-leeren) — das war spezifischer als
   .loeschknopf und hat dessen Innenabstand überschrieben, bis vom Kreuz
   darin nichts mehr zu sehen war. Wer hier eine Ausnahme ergänzen will,
   vergibt dem nächsten Knopf denselben Fehler: dann lieber eine Klasse. */
:where(button) {
  padding: .5rem 1rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent);
  color: #fff;
  font: inherit;
  cursor: pointer;
}
button.passkey { width: 100%; padding: .7rem 1rem; font-size: 1rem; }
button.sekundaer { background: transparent; color: var(--ink); border-color: var(--rule); }

.trenner {
  display: flex; align-items: center; gap: .75rem;
  color: var(--muted); font-size: .8rem; margin: 1.5rem 0 1rem;
}
.trenner::before, .trenner::after { content: ""; flex: 1; border-top: 1px solid var(--rule); }

.fehler { color: var(--accent); font-size: .84rem; }

.messages { list-style: none; padding: 0; margin: 0 0 1.5rem; }
.messages li {
  padding: .6rem .9rem;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface);
  margin-bottom: .5rem;
}

/* --- Regal: Quellen als Umschläge -------------------------------------- */

.ansichtwahl {
  display: inline-flex;
  gap: 0;
  margin: 0 0 1rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.ansichtwahl label { display: inline-flex; margin: 0; cursor: pointer; }
/* Der Knopf ist das Label; das Radio bleibt bedienbar, nur unsichtbar —
   sonst ginge die Tastaturbedienung verloren. */
.ansichtwahl input { position: absolute; opacity: 0; pointer-events: none; }
.ansichtwahl span {
  padding: .32rem .8rem;
  font-size: .85rem;
  color: var(--ink-soft);
  background: var(--surface);
}
.ansichtwahl label + label span { border-left: 1px solid var(--rule); }
.ansichtwahl input:checked + span {
  background: var(--surface-alt);
  color: var(--ink);
  font-weight: 600;
}
.ansichtwahl input:focus-visible + span { outline: 2px solid var(--blau); outline-offset: -2px; }

.regal {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 1.5rem 1.25rem;
  align-items: start;
}

.regalstueck { display: block; text-decoration: none; color: inherit; }

.regalstueck img,
.regalstueck .ruecken {
  width: 100%;
  /* Buchformat statt Quadrat — ein Umschlag ist höher als breit. */
  aspect-ratio: 5 / 7;
  object-fit: cover;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--schatten);
}
.regalstueck img { display: block; }

/* Ohne Bild: ein gesetzter Rücken statt eines leeren Kastens.
   Die Anzeigeart steht hier und NICHT in der Regel darüber: dort stünde
   sie mit derselben Genauigkeit wie „display: block“ fürs Bild, und der
   Rücken bliebe ein Block — Titel und Art klebten dann aneinander. */
.regalstueck .ruecken {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: .5rem;
  padding: .9rem .8rem;
  background: linear-gradient(160deg, var(--surface-alt), var(--surface));
}
.ruecken-titel {
  font-family: "Bodoni Moda", Didot, Georgia, serif;
  font-size: 1.05rem;
  line-height: 1.15;
  color: var(--ink);
  overflow: hidden;
}
.ruecken-typ {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: .65rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}

.regal-titel {
  display: block;
  margin-top: .5rem;
  font-size: .87rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--ink);
}
.regalstueck:hover .regal-titel { color: var(--accent); }
.regal-zeile { display: block; font-size: .78rem; color: var(--muted); }

/* Der Nachladeknopf sitzt im Raster und soll über die ganze Breite gehen. */
.nachladen--regal { grid-column: 1 / -1; border-top: 0; border: 1px solid var(--rule-soft); border-radius: var(--radius); }

.suchwahl-anlegen { color: var(--accent); font-weight: 600; }

.kopf-knoepfe { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }

/* --- Warten auf etwas, das dauert --------------------------------------- */

/* Ein abgeschalteter Knopf muss auch abgeschaltet aussehen — sonst klickt
   man weiter darauf und haelt die Anwendung für kaputt. */
.knopf:disabled, button.knopf[disabled] {
  opacity: .5;
  cursor: wait;
  pointer-events: none;
}

.warten { margin-top: 1rem; max-width: 26rem; }

.warten-balken {
  height: 4px;
  border-radius: 2px;
  background: var(--surface-alt);
  overflow: hidden;
  position: relative;
}
/* Unbestimmt, weil die Dauer unbekannt ist: ein Streifen wandert, statt
   einen Fortschritt zu behaupten, den niemand kennt. */
.warten-balken::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 35%;
  border-radius: 2px;
  background: var(--accent);
  animation: warten-lauf 1.4s ease-in-out infinite;
}
@keyframes warten-lauf {
  0%   { left: -35%; }
  100% { left: 100%; }
}

.warten-text {
  margin: .5rem 0 0;
  font-size: .85rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Wer Bewegung abgestellt hat, bekommt einen ruhigen Balken — die Auskunft
   steckt ohnehin im Text daneben, nicht in der Animation. */
@media (prefers-reduced-motion: reduce) {
  .warten-balken::after { animation: none; left: 0; width: 100%; opacity: .5; }
}

/* --- Vorschlag des Assistenten ------------------------------------------ */

.vorschlagkasten {
  margin: 0 0 1.75rem;
  padding: 1rem 1.1rem;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--blau);
  border-radius: var(--radius);
  background: var(--blau-grund);
}
.vorschlag-kopf { margin: 0 0 .75rem; font-size: .92rem; }
.vorschlag-block { margin: .75rem 0 0; font-size: .88rem; }
.vorschlag-block ul { margin: .35rem 0 0; padding-left: 1.1rem; }
.vorschlag-block li { margin: .15rem 0; }
.vorschlag-block summary { cursor: pointer; color: var(--ink-soft); font-size: .85rem; }
.vorschlagkasten .hilfe { margin: .75rem 0 0; }

/* Die Trefferzahl steht zweimal im Dokument: einmal in der Kopfzeile und
   einmal im Ergebnisblock, von wo htmx sie per hx-swap-oob in die Kopfzeile
   hebt. Beim gewöhnlichen Seitenaufruf findet dieser Tausch nicht statt —
   dann stünde sie sichtbar doppelt da. Die Kopie im Block bleibt deshalb
   verborgen; nach dem Tausch sitzt sie in der Kopfzeile und ist sichtbar. */
#treffer > .anzahl { display: none; }

/* Sicherungswarnung. Traegt Farbe UND Text — wer die Farbe nicht sieht,
   liest trotzdem, was los ist. */
.sicherungswarnung {
  padding: .7rem 1rem;
  margin: 0 0 1.5rem;
  border: 1px solid var(--warn);
  border-left: 3px solid var(--warn);
  border-radius: var(--radius);
  background: var(--warn-grund);
  color: var(--warn);
  font-size: .9rem;
}
.sicherungswarnung code { font-size: .85em; }

.fussnote {
  margin-top: 2.5rem;
  color: var(--muted);
  font-size: .82rem;
}

/* --- Schmale Fenster ---------------------------------------------------- */

/* Die Spalte bleibt lange neben dem Text stehen — bis 52rem statt 62rem.
   Solange sie das tut, ist der Hauptteil nie breiter als das Zeilenmaß, und
   Text, Kacheln und Trennlinien enden an derselben Kante.

   Darunter stapelt sich alles, und der Hauptteil waere auf einen Schlag
   fast doppelt so breit wie der Text. Deshalb bekommt der ganze Block dort
   dasselbe Maß: lieber links buendig mit Freiraum rechts — so steht es in
   jedem Buch — als eine Stufe mitten in der Seite. */
/* 70.99 und nicht 71: „max-width: 71rem“ und „min-width: 71rem“ treffen
   beide zu, wenn das Fenster genau 1136 Pixel breit ist. Dann lagen die drei
   Spalten und die gestapelte Fassung uebereinander, und der Text war 108
   Pixel breit. Nachgemessen, nicht vermutet. */
@media (max-width: 70.99rem) {
  .detail {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.75rem;
    max-width: 64ch;
  }
  .rail { position: static; }
}

@media (max-width: 52rem) {
  .arbeitsflaeche { grid-template-columns: minmax(0, 1fr); }

  /* Hier liegen die Filter über der Liste statt daneben. Offen schoben sie
     die Treffer aus dem Bild — auf einem Telefon so weit, dass man erst an
     allen Facetten vorbeiscrollen musste, um zu sehen, was man gesucht hat.
     Also fangen sie zugeklappt an. */
  .filter {
    position: static;
    max-height: none;
    gap: .7rem;
  }

  .filter-schalter {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    padding: .55rem .8rem;
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    color: var(--ink);
    font: inherit;
    font-size: .875rem;
    cursor: pointer;
  }
  .filter-schalter .n {
    font-family: "IBM Plex Mono", monospace;
    font-size: .72rem;
    padding: .05rem .4rem;
    border-radius: 999px;
    background: var(--accent-grund);
    color: var(--accent);
  }
  /* Ein Winkel aus zwei Strichen: dreht sich beim Aufklappen um. Zeichen wie
     ▾ sind je nach Schrift mal riesig, mal gar nicht vorhanden. */
  .filter-schalter .pfeil {
    margin-left: auto;
    width: .5rem;
    height: .5rem;
    border-right: 1.5px solid var(--muted);
    border-bottom: 1.5px solid var(--muted);
    transform: translateY(-2px) rotate(45deg);
    transition: transform .15s ease;
  }
  .filter.offen .filter-schalter .pfeil { transform: translateY(1px) rotate(225deg); }

  .filter-inhalt {
    display: none;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 1rem;
    padding: 1rem;
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
  }
  .filter.offen .filter-inhalt { display: grid; }

  .seite { padding: 1.25rem .9rem 4rem; }
  /* Der Innenrand ist hier kleiner; ohne das Nachziehen bliebe rechts ein
     Rest stehen und der Text stuende um die Haelfte davon daneben. */
  .seite--mittig { max-width: calc(36rem + 1.8rem); }

  /* Unter 16px zoomt Safari auf dem iPhone die ganze Seite, sobald ein Feld
     den Fokus bekommt — und zoomt nicht wieder heraus. Man tippt einmal ins
     Suchfeld und schiebt danach von Hand zurück. Alle Felder lagen bei 15px,
     einige bei 13,44px.

     Die lange :not()-Kette ist die aus der Grundregel weiter oben plus
     einem Glied, damit sie deren „font: inherit“ schlaegt; die beiden
     Klassenregeln stehen daneben, weil sie ihrerseits spezifischer sind
     als ein blosses select. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="submit"]):not([type="button"]):not([type="hidden"]),
  select, textarea,
  .zeile-felder select, .zeile-felder input, .zeile-felder textarea,
  .editor textarea,
  .suchwahl-feld {
    font-size: 16px;
  }

  /* In der Liste bekam der Titel 113 Pixel und die rechte Spalte 198 — fuenf
     Sterne plus Statusmarke waren breiter als das, wonach man sucht, und der
     Titel brach auf zwei Zeilen um. Der Status bleibt: danach scannt man
     eine Liste. Die Bewertung steht auf der Detailseite. */
  .zeile .sterne { display: none; }

  /* Kacheln, in denen nur ein Gedankenstrich steht. Am Rechner sind sie ein
     vollstaendiges Raster und eine Aufforderung, sie zu fuellen; hier waren
     es bei einem frisch angelegten Buch vier Reihen Nichts zwischen Titel
     und Beschreibung. Steht in keiner Kachel etwas, faellt der ganze
     Kasten weg statt leer dazustehen. */
  .kennzahlen div:has(.fehlt) { display: none; }
  .kennzahlen:not(:has(div:not(:has(.fehlt)))) { display: none; }
}

@media (max-width: 52rem) {
  .topbar { gap: .6rem; padding: 0 .9rem; }
}

/* Sehr schmal: die Wortmarke kleiner, sonst bleibt für die Suche nichts. */
@media (max-width: 26rem) {
  .marke { font-size: 1.05rem; }
  .topbar { gap: .45rem; padding: 0 .6rem; }
}

/* --- Posten ohne Produkt ------------------------------------------------- */
/* Der Rahmen wandert von der Zeile auf den Block: sonst zöge sich zwischen
   Zeile und Nachtrag ein Strich, und der Block wirkte wie zwei Posten. */
.postenblock { border-bottom: 1px solid var(--rule-soft); }
.postenblock:last-child { border-bottom: none; }
.postenblock > .zeile { border-bottom: none; }

.postenwahl { padding: 0 1rem .8rem; }

.postenwahl-form { display: flex; flex-direction: column; gap: .6rem; }
.postenwahl-form .hilfe { margin: 0; }
/* Sonst zieht die Spalte den Knopf über die volle Breite — ein roter Balken
   quer durch die Rechnung, für eine Kleinigkeit. */
.postenwahl-form .knopf { align-self: start; }

/* Zwei Felder nebeneinander, solange Platz ist. Untereinander wären sie
   leicht als „erst das, dann das“ zu lesen — gemeint ist aber „entweder
   oder“. */
.postenwahl-felder {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: .6rem;
}

/* --- Aus einer Rechnung übernommen --------------------------------------- */
/* Muss vor der Regel darunter stehen und ausdrücklich dastehen: das
   display:flex von .uebernahme schlägt das hidden-Attribut, und der Kasten
   stünde leer und blau im Formular, bevor irgendetwas übernommen wurde. */
.uebernahme[hidden] { display: none; }

.uebernahme {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  padding: .7rem .85rem;
  background: var(--blau-grund);
  border-left: 2px solid var(--blau);
  border-radius: var(--radius);
}
.uebernahme .hilfe { margin: 0; color: var(--ink-soft); }

/* Ein übernommener Wert soll sich vom selbst Getippten unterscheiden — sonst
   prüft man ihn nicht, und ein falsch geratenes Datum steht für immer drin. */
.uebernommen { border-color: var(--blau); }

/* --- Rechnungszeile: was bestellt wurde ---------------------------------- */
/* Einzeilig mit Auslassung statt Umbruch: die Liste soll gleichmäßig
   bleiben. Wer alles sehen will, klickt die Rechnung an. */
.zeile .postenzeile {
  grid-column: 1 / -1;
  min-width: 0;
  font-size: .82rem;
  color: var(--ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zeile .unterzeile .offen { color: var(--warn); }

/* --- Mehrfachauswahl mit Suche ------------------------------------------- */
.mehrfach { display: flex; flex-direction: column; gap: .5rem; }
.mehrfach-gewaehlt { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.mehrfach-gewaehlt .hilfe { margin: 0; }

/* Das Gewählte sieht aus wie ein angekreuztes Kästchen — es IST ja dasselbe,
   nur anders bedient. */
.tagmarke--gewaehlt {
  background: var(--accent-grund);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 500;
}
/* Was es noch nicht gibt: erkennbar anders, damit man vor dem Speichern
   sieht, was neu angelegt wird. */
.tagmarke--neu {
  background: var(--blau-grund);
  border-color: var(--blau);
  color: var(--blau);
  border-style: dashed;
}
.tagmarke-weg { margin-left: .1rem; font-size: 1.05em; line-height: 1; opacity: .7; }
.tagmarke--gewaehlt:hover .tagmarke-weg { opacity: 1; }

/* --- Theorie ------------------------------------------------------------- */

.notizen { display: flex; flex-direction: column; gap: .75rem; }

.notiz {
  padding: .8rem 1rem;
  background: var(--surface);
  border: 1px solid var(--rule-soft);
  border-left: 3px solid var(--rule);
  border-radius: var(--radius);
}
/* Ein wörtliches Zitat ist etwas anderes als eine Zusammenfassung — man
   darf niemandem in den Mund legen, was er so nicht geschrieben hat. */
.notiz--zitat { border-left-color: var(--blau); background: var(--blau-grund); }

.notiz .fliesstext p { margin: 0 0 .4rem; }
.notiz-herkunft {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  font-size: .82rem;
  color: var(--muted);
}

/* Die Notiz steht über die volle Breite, die Herkunft in einer Reihe
   darunter: ein dreizeiliger Gedanke in einer Rasterspalte von zwei
   Zentimetern wäre nicht schreibbar. */
/* Verzeichniszeile: Seite schmal voran, dann Titel, Urheber, Art — und die
   Kurzbeschreibung darunter über die ganze Breite. Sie ist der Satz, an dem
   man den Trick später wiedererkennt, und in ein Viertel der Reihe passt er
   nicht. */
.zeilenliste--verzeichnis .zeile-felder {
  grid-template-columns: minmax(0, .7fr) minmax(0, 2.4fr) minmax(0, 1.3fr) minmax(0, 1.1fr);
}
/* Zweite Reihe: die Kurzbeschreibung über drei Spalten, „erfasst als“ in der
   vierten. Beide ausdrücklich gesetzt, damit die Reihenfolge im HTML egal
   ist. Die Fassungsauswahl steckt ab zwölf Fassungen in einer .suchwahl-Hülle
   — dann ist die Hülle das Rasterfeld, sonst die Auswahlliste selbst. */
.zeilenliste--verzeichnis .feld-breit { grid-column: 1 / 4; grid-row: 2; }
.zeilenliste--verzeichnis .zeile-felder > .suchwahl,
.zeilenliste--verzeichnis .zeile-felder > select[name$="-variante"] {
  grid-column: 4;
  grid-row: 2;
}

.zeilenliste--notiz .zeile-felder { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.zeilenliste--notiz .zeile-felder textarea { grid-column: 1 / -1; }
.zeilenliste--notiz .zeile-felder .suchwahl { grid-column: 1 / -1; }
.zeilenliste--notiz .zeile-felder label { display: flex; align-items: center; gap: .35rem; }

/* --- Fassungen: dieselbe Wirkung, andere Anleitung ----------------------- */
/* Eine Falte, keine Notiz: was drinsteht, ist eine vollständige Anleitung
   mit Bildern. Zugeklappt steht genau das da, was zum Auswählen reicht. */
.fassungen { display: flex; flex-direction: column; gap: .6rem; }

.fassung {
  background: var(--surface);
  border: 1px solid var(--rule-soft);
  border-left: 3px solid var(--rule);
  border-radius: var(--radius);
}
/* Die eigene Fassung hebt sich ab: auf einer Seite mit sechs Handhabungen
   ist die eine, die man tatsächlich macht, die gesuchte. */
.fassung--meine { border-left-color: var(--accent); }

.fassung > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .35rem .6rem;
  padding: .7rem 1rem;
  cursor: pointer;
  user-select: none;
  list-style: none;
}
.fassung > summary::-webkit-details-marker { display: none; }
.fassung > summary:hover { background: var(--surface-alt); }

/* Eigener Winkel statt des Standardpfeils — derselbe wie an den
   Formularbereichen, damit „hier lässt sich etwas aufklappen“ überall
   gleich aussieht. */
.fassung > summary::before {
  content: "";
  flex: none;
  align-self: center;
  width: .4rem; height: .4rem;
  border-right: 1.75px solid var(--accent);
  border-bottom: 1.75px solid var(--accent);
  transform: rotate(-45deg);
  transition: transform .14s ease;
}
.fassung[open] > summary::before { transform: rotate(45deg); margin-top: -.18rem; }

.fassung-kopf {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
}
/* Schiebt die Herkunft ans Ende der Zeile, solange Platz ist — und bricht
   sie darunter, wenn nicht. */
.fassung-herkunft {
  margin-left: auto;
  font-size: .82rem;
  color: var(--muted);
}

.fassung-inhalt {
  padding: .2rem 1rem 1rem;
  border-top: 1px solid var(--rule-soft);
}
/* Innerhalb einer Falte sitzen die Kennzahlen enger — der Kasten hat schon
   einen Rahmen, ein zweiter darin wirkt wie eine Schachtel in der Schachtel. */
.fassung-inhalt .kennzahlen { margin-top: .9rem; }

/* Muss vor der Regel darunter stehen und ausdrücklich dastehen: das
   display:flex schlägt sonst das hidden-Attribut, und die Karten aller
   Fassungen stünden gleichzeitig da. Derselbe Fehler wie einmal beim
   Übernahmekasten. */
.fassung-karten[hidden] { display: none; }

/* Die Karten einer Fassung — in der Seitenspalte, unter denen, die für den
   ganzen Trick gelten. Neben dem Text und nicht darunter: es sind
   Nachschlagewerte, keine Fortsetzung der Anleitung. Und dort kosten sie
   dem Text keine Breite. */
.fassung-karten {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

/* Bei mehreren Fassungen sagt der Kopf, zu welcher die Karten gehören —
   sonst rät man beim Umklappen, ob sie mitgewandert sind. */
.fassung-karten-kopf {
  font-family: "IBM Plex Mono", monospace;
  font-size: .64rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
}

/* In der schmalen Spalte untereinander: nebeneinander wären sie dort
   fingerbreit. */
.kennzahlen--schmal { flex-direction: column; margin-top: 0; }

.karten-fuss { display: flex; flex-direction: column; gap: .6rem; }

/* Der Auszug steht dort, wo bei Tricks die Marken stehen: bei einem Gedanken
   IST der Text die Sache, und der Titel allein sagt selten genug, um ihn
   wiederzuerkennen. Einzeilig wie alles andere in der Zeile. */
.zeile .auszugzeile {
  display: block;
  font-size: .84rem;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* Ein Ankreuzfeld in einer Zeilenliste braucht seine Beschriftung — ein
   nacktes Kästchen sagt niemandem, was es bedeutet. */
.zeile-haken {
  display: flex;
  align-items: center;
  gap: .4rem;
  font-size: .82rem;
  color: var(--ink-soft);
  white-space: nowrap;
  cursor: pointer;
}
.zeile-haken input { accent-color: var(--accent); margin: 0; }

/* Notiz hinzufügen, ohne die Seite zu verlassen. */
.notiz-neu { margin-top: .75rem; }
.notiz-neu > summary {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .42rem .85rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-soft);
  font-size: .85rem;
  cursor: pointer;
  list-style: none;
}
.notiz-neu > summary::-webkit-details-marker { display: none; }
.notiz-neu > summary::before { content: "+"; color: var(--accent); font-weight: 600; }
.notiz-neu > summary:hover { border-color: var(--accent); color: var(--accent); }

.notiz-neu-form {
  display: flex;
  flex-direction: column;
  gap: .7rem;
  margin-top: .7rem;
  padding: .9rem 1rem;
  background: var(--surface);
  border: 1px solid var(--rule-soft);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
}
.notiz-neu-form .knopf { align-self: start; }

/* --- Wunschliste --------------------------------------------------------- */

/* Eintragen oben, die Liste mit Abstand darunter. */
.wunsch-neu { margin-bottom: 1.5rem; }

/* Die Zeile ist ein <summary>: ein Klick klappt das Ändern auf, ohne JS. */
.wunsch > summary { list-style: none; cursor: pointer; }
.wunsch > summary::-webkit-details-marker { display: none; }
.wunsch:last-child > summary { border-bottom: none; }
.wunsch[open] > summary { background: var(--surface-alt); border-bottom-color: transparent; }

.wunsch .titel a { color: inherit; text-decoration: none; }
.wunsch .titel a:hover { color: var(--accent); text-decoration: underline; }

.wunsch-seit {
  font-size: .78rem;
  color: var(--muted);
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
}

/* Die Notiz ist der Grund für den Eintrag — also ganz, nicht abgeschnitten. */
.wunsch-notiz {
  grid-column: 1 / -1;
  font-size: .875rem;
  line-height: 1.4;
  color: var(--ink-soft);
}

.wunsch-form {
  display: flex;
  flex-direction: column;
  gap: .7rem;
  padding: .3rem 1rem 1rem;
  background: var(--surface-alt);
  border-bottom: 1px solid var(--rule-soft);
}
.wunsch:last-child .wunsch-form { border-bottom: none; }
