:root {
  --color-bg: #ffffff;
  --color-surface: #f7f5f3;
  --color-text: #232323;
  --color-text-muted: #6b6b6b;
  --color-border: #e3ded8;
  --color-accent: #b22f1c;
  --color-accent-hover: #8f2716;
  --color-accent-tint: rgba(178, 47, 28, 0.08);
  --color-warning: #9a6400;
  --color-warning-tint: rgba(154, 100, 0, 0.1);
  --radius: 6px;
  --font-sans: "Inter", -apple-system, "system-ui", "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #1c1c1c;
    --color-surface: #262422;
    --color-text: #ededed;
    --color-text-muted: #a3a3a3;
    --color-border: #3a3733;
    --color-accent: #e2593f;
    --color-accent-hover: #ef6c52;
    --color-accent-tint: rgba(226, 89, 63, 0.14);
    --color-warning: #e0a530;
    --color-warning-tint: rgba(224, 165, 48, 0.14);
  }
}

* {
  box-sizing: border-box;
}

/* Für window.scrollTo()/scrollIntoView()-Aufrufe auf Seitenebene (siehe
   Konversationsansicht ab 900px, wo die Chat-Box selbst mitwächst statt
   intern zu scrollen) - ohne dies springt die Seite ruckartig statt sanft
   zu scrollen. */
html {
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.65;
  color: var(--color-text);
  background: var(--color-bg);
  max-width: min(980px, 92vw);
  margin: 0 auto;
  padding: clamp(1.5rem, 5vw, 3.5rem) clamp(1rem, 4vw, 2rem) 5rem;
}

h1, h2, h3 {
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.25;
}

h1 {
  font-size: 1.6rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

h3 {
  font-size: 0.95rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  margin-bottom: 0.75rem;
}

.brand-dot {
  width: 0.6em;
  height: 0.6em;
  border-radius: 50%;
  background: var(--color-accent);
  flex-shrink: 0;
}

/* Fix: Klick auf "BetaCodex Companion" öffnet die Konversationsseite mit
   leerer Konversation (siehe brand-link-Click-Handler in init-footer.js).
   Übernimmt die Flex-Ausrichtung der generischen h1-Regel, da diese jetzt
   nicht mehr direkt auf brand-dot/Text wirkt, sondern nur noch auf dieses
   einzelne <a>-Kind der h1. */
.brand-link {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  height: 100%;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

/* Backlog #58 (A11y): für Tastatur-/Screenreader-Nutzung - unsichtbar bis
   die Nutzer:in per Tab dorthin fokussiert, dann oben links sichtbar.
   translateY(-100%) statt eines festen top-Pixelwerts, weil ein fester Wert
   (z.B. -40px) kleiner als die tatsächliche gerenderte Höhe des Links sein
   kann (Padding + Zeilenhöhe) - dann ragt ein Stück permanent ins Bild,
   genau der Bug, der hier zuerst passiert ist. Die eigene Höhe ist dagegen
   immer korrekt, unabhängig von Text/Padding/Schriftgröße. */
.skip-link {
  position: absolute;
  top: 0;
  left: 0.5rem;
  transform: translateY(-100%);
  z-index: 100;
  background: var(--color-accent);
  color: #fff;
  padding: 0.6rem 1rem;
  border-radius: var(--radius);
  text-decoration: none;
  font-weight: 700;
  transition: transform 0.15s ease;
}

.skip-link:focus {
  transform: translateY(0);
}

/* Backlog #58: gebrandete 404-Seite statt Starlettes/FastAPIs nacktem
   Standard-"Not Found" - wird von Starlette automatisch für jeden nicht
   gefundenen statischen Pfad ausgeliefert (siehe StaticFiles html=True). */
.error-page {
  max-width: 32rem;
  margin: 4rem auto;
  padding: 0 1.5rem;
  text-align: center;
}

.error-page h2 {
  margin-bottom: 0.75rem;
}

/* Backlog #115: Datenschutzerklärung (datenschutz.html/privacy.html) -
   deutlich breiter/linksbündig als .error-page, da hier viel Fließtext mit
   Überschriften gelesen werden muss statt einer kurzen zentrierten Meldung. */
.legal-page {
  max-width: 42rem;
  margin: 2rem auto 4rem;
}

.legal-page h3 {
  margin-top: 2rem;
  margin-bottom: 0.5rem;
}

.legal-page p {
  margin-bottom: 1rem;
}

.legal-updated {
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.error-page p {
  color: var(--color-text-muted);
  margin-bottom: 1.5rem;
}

header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding-bottom: 1.5rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid var(--color-border);
}

header h1 {
  margin: 0;
  /* Fix: die Kopfzeile ist insgesamt höher als die reine Textzeile (z.B.
     durch den Namen unter dem Login-Icon rechts) - ohne align-self:stretch
     war die klickbare Fläche des Titel-Links nur so hoch wie der Text
     selbst, mit "totem" Bereich darüber/darunter, der optisch noch zur
     Titelzeile gehört. Kleinstes Maus-Zittern ließ den Cursor dort ständig
     zwischen Pointer und Pfeil umspringen. */
  align-self: stretch;
}

#conversation-link,
#import-link,
#question-log-link,
#changelog-link {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border: 1.5px solid var(--color-border);
  border-radius: 50%;
  color: var(--color-text);
  text-decoration: none;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

#conversation-link:hover,
#import-link:hover,
#question-log-link:hover,
#changelog-link:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
  background: var(--color-accent-tint);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
}

.auth-widget {
  position: relative;
  display: inline-flex;
  /* Auf Mobile wird .popover zu position:static (siehe @media (max-width:
     480px) weiter unten) und damit zu einem normalen Flex-Item dieses
     Containers - ohne column stünde das Popover fälschlich NEBEN statt
     UNTER dem Auth-Button. Auf Desktop (position:absolute) wirkungslos. */
  flex-direction: column;
}

.auth-widget-button--active {
  color: var(--color-accent);
}

/* Rechtsbündig statt zentriert - das Auth-Icon ist inzwischen immer das
   letzte Element in der Kopfzeile, ein zentriertes Label würde auf schmalen
   Bildschirmen über den rechten Seitenrand hinausragen. */
.auth-username-label {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 0.3rem;
  font-size: 0.7rem;
  color: var(--color-text-muted);
  white-space: nowrap;
  pointer-events: none;
}

/* #auth-widget-Präfix erhöht die Spezifität bewusst über die gemeinsame
   .popover-Basisregel (weiter unten in dieser Datei) hinaus - sonst gewinnt
   bei gleicher Spezifität die spätere Regel im Quellcode und das Popover
   bleibt mittig über dem schmalen Icon zentriert statt rechtsbündig daran. */
#auth-widget .auth-popover {
  left: auto;
  right: 0;
  transform: none;
  top: calc(100% + 14px);
  width: min(420px, calc(100vw - 3rem));
}

#auth-widget .auth-popover .popover-arrow {
  left: auto;
  right: 12px;
  transform: rotate(45deg);
}

.auth-login-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.auth-status {
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.auth-status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: -0.75rem;
}

.auth-roles {
  color: var(--color-text-muted);
  font-size: 0.85rem;
}

.auth-admin-section {
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-border);
}

.auth-section-heading {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-bottom: 0.5rem;
}

.auth-invite-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.auth-invite-form input {
  /* Immer die volle Zeile für sich - sonst bleibt neben Rollen-Auswahl
     und Button kaum Platz für die E-Mail-Adresse übrig. */
  flex: 1 1 100%;
  min-width: 0;
  margin-top: 0;
}

.auth-invite-form select {
  flex: 1;
  min-width: 0;
  margin-top: 0;
  width: auto;
}

.auth-invite-form button {
  flex: 0 0 auto;
}

.auth-user-list {
  list-style: none;
  padding: 0;
  margin: 0;
  max-height: 160px;
  overflow-y: auto;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.auth-user-list li {
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--color-border);
}

.auth-user-name-form {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.25rem;
  /* Ohne width:100% nimmt das Formular als Kind von .auth-user-name-row
     (selbst ein Flex-Container) nur so viel Breite wie nötig ein, statt die
     volle Popover-Breite auszufüllen. */
  width: 100%;
}

.auth-user-name-form input {
  flex: 1;
  min-width: 0;
  margin-top: 0;
  font-size: 0.85rem;
  padding: 0.3rem 0.5rem;
}

.auth-user-name-form button {
  flex: 0 0 auto;
}

.auth-user-name-row {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.25rem;
}

.auth-user-name-display {
  font-style: italic;
}

/* Eigene, immer sichtbare Variante statt .icon-button - dessen Ausblenden-
   bis-Hover-Verhalten ist an #source-list gekoppelt (siehe dort) und würde
   diesen Stift sonst dauerhaft unsichtbar machen. */
.auth-edit-name-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0.15rem;
  color: var(--color-text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
}

.auth-edit-name-btn:hover {
  color: var(--color-accent);
}

.lang-switcher {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

.lang-button {
  background: none;
  border: none;
  padding: 0;
  font-size: inherit;
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
}

.lang-button.active {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.lang-button:hover {
  color: var(--color-accent);
}

label {
  display: block;
  margin-bottom: 1.1rem;
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

input, textarea {
  display: block;
  width: 100%;
  margin-top: 0.35rem;
  font-family: inherit;
  /* Mind. 16px, sonst zoomen iOS Safari & viele Android-Browser beim Fokus
     automatisch hinein (Auslöser war das neue Suchfeld, Fix gilt aber
     global - jedes Eingabefeld unter 16px hätte denselben Effekt). */
  font-size: 1rem;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 0.65rem 0.8rem;
  box-sizing: border-box;
}

.field-with-magic {
  position: relative;
}

.field-with-magic > textarea,
.field-with-magic > input {
  padding-right: 2.5rem;
}

.magic-button {
  position: absolute;
  top: 0.65rem;
  right: 0.4rem;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
}

.magic-button:hover {
  color: var(--color-accent);
  border-color: var(--color-accent);
}

.magic-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

input:focus, textarea:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px var(--color-accent-tint);
}

textarea {
  resize: vertical;
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--color-text);
}

.checkbox-label input[type="checkbox"] {
  display: inline-block;
  width: auto;
  margin-top: 0;
  padding: 0;
  border: none;
  accent-color: var(--color-accent);
}

.audio-preview-player {
  display: block;
  width: 100%;
  margin-top: 0.35rem;
}

.markup-toolbar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0.35rem 0 0.5rem;
}

.markup-toolbar {
  display: flex;
  gap: 0.4rem;
}

.markup-button {
  width: 28px;
  height: 28px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-bg);
  color: var(--color-text);
  font-size: 0.85rem;
  cursor: pointer;
}

.markup-button:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.markup-button.markup-bold {
  font-weight: 800;
}

.markup-button.markup-italic {
  font-style: italic;
}

button {
  font-family: inherit;
}

button[type="submit"], #popover-load, #popover-upload {
  background: var(--color-accent);
  color: #fff;
  border: none;
  border-radius: var(--radius);
  padding: 0.7rem 1.75rem;
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s ease;
}

button[type="submit"]:hover, #popover-load:hover, #popover-upload:hover {
  background: var(--color-accent-hover);
}

/* Fix: #popover-load/#popover-upload sind type="button", nicht
   type="submit" - die :disabled-Regel griff deshalb nie, obwohl der Button
   während "Lade und extrahiere..."/"Lade hoch und extrahiere..." per JS
   korrekt deaktiviert wird (sah weiterhin voll aktiv/farbig aus). */
button[type="submit"]:disabled, #popover-load:disabled, #popover-upload:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.restricted-badge {
  flex-shrink: 0;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  white-space: nowrap;
}

.link-button {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  color: var(--color-accent);
  font-size: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.link-button:hover {
  color: var(--color-accent-hover);
}

/* Fix: disabled=true (z.B. Retry-Button während der Anfrage) hatte bisher
   keinerlei optischen Effekt - der Klick wirkte tot, bis Sekunden später die
   Status-Aktualisierung eintraf. */
.link-button:disabled {
  color: var(--color-text-muted);
  cursor: default;
  text-decoration: none;
}

#source-filter-status {
  color: var(--color-text);
  font-size: 1.15rem;
  font-weight: 700;
}

#source-filter-clear {
  font-size: 0.85rem;
}

section {
  margin-bottom: 3rem;
}

/* body als Flex-Spalte mit voller Bildschirmhöhe (nur auf der Chat-Seite,
   :has(#frage-bereich) schließt import.html aus) - Grundlage dafür, dass
   #frage-bereich per flex:1 den verbleibenden Platz zwischen Header/Tagline
   und Footer exakt ausfüllt und sein Inhalt darin zentrieren kann. */
body:has(#frage-bereich) {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

#frage-bereich {
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* Startzustand ohne laufende Konversation: nur das Eingabefeld zeigen,
   zentriert im verbleibenden Platz - Sidebar und (leerer) Nachrichtenverlauf
   bleiben unsichtbar. Sobald die erste Frage gestellt wird, setzt question.js
   die Klasse "chat-started" auf <body> und die volle Ansicht erscheint
   (Sidebar, Nachrichtenverlauf, die Chat-Box mit Rahmen). Gilt unverändert
   für Desktop und Mobile. */
body:not(.chat-started) #frage-bereich {
  display: flex;
  align-items: center;
  justify-content: center;
  /* #frage-bereich ist ein <section> und erbt dadurch margin-bottom: 3rem;
     zusammen mit dem margin-top des Footers ergäbe das eine Lücke NUR
     unterhalb dieser Box - justify-content:center würde dann nicht zwischen
     den beiden Trennlinien (Header-Rand/Footer-Rand) zentrieren, sondern
     spürbar zu weit oben. Hier auf 0 gesetzt, damit die Box wirklich bis
     zur Fußzeile reicht. */
  margin-bottom: 0;
}

body:not(.chat-started) #sources-sidebar,
body:not(.chat-started) #chat-messages {
  display: none;
}

body:not(.chat-started) .site-footer {
  /* Gleicher Abstand wie header -> #frage-bereich (1.5rem), damit die Box
     oben UND unten denselben Puffer zur jeweiligen Trennlinie hat - nur so
     zentriert justify-content:center wirklich zwischen den beiden Linien
     statt spürbar zu weit oben. */
  margin-top: 1.5rem;
}

body:not(.chat-started) #chat-column {
  /* Ohne dies würde die mobile Regel weiter unten (#chat-column { flex: 1 })
     die Box auf die volle Höhe von #frage-bereich aufblasen - dann sitzt das
     Formular oben statt zentriert. flex:initial lässt sie auf Inhaltsgröße
     schrumpfen, damit align-items/justify-content vom Elternelement greifen. */
  flex: initial;
  width: 100%;
  max-width: 560px;
  height: auto;
  min-height: 0;
  max-height: none;
  border: none;
  background: transparent;
}

body:not(.chat-started) #question-form {
  border-top: none;
  padding-left: 0;
  padding-right: 0;
}

/* Basisverhalten (Mobile/Tablet, <900px): feste Höhe mit intern scrollendem
   #chat-messages - siehe ausführliche Begründung bei der 640px-Regel weiter
   unten. Ab 900px hebt die Desktop-Regel diese Höhenbegrenzung bewusst auf
   (siehe dort) - dort soll die Box mit dem Antworttext mitwachsen wie im
   Chat-Modus von Claude, statt intern zu scrollen. */
#chat-column {
  display: flex;
  flex-direction: column;
  height: 70vh;
  min-height: 460px;
  max-height: 780px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
}

#chat-messages {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  overflow-y: auto;
  padding: 1.5rem;
  scroll-behavior: smooth;
}

.chat-message {
  display: flex;
  flex-direction: column;
  animation: chat-message-in 0.18s ease;
}

@media (min-width: 900px) {
  /* Reserviert Platz, damit scrollChatToBottom() (scrollIntoView) eine
     Nachricht nicht direkt hinter dem sticky Eingabefeld versteckt. */
  .chat-message {
    scroll-margin-bottom: 6rem;
  }
}

@keyframes chat-message-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.chat-message--user {
  align-items: flex-end;
}

.chat-bubble {
  border-radius: 18px;
  padding: 0.75rem 1.1rem;
  max-width: 85%;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

.chat-message--user .chat-bubble {
  background: var(--color-accent);
  color: #fff;
  border-bottom-right-radius: 6px;
}

.chat-message--assistant .chat-bubble {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  max-width: 100%;
  border-bottom-left-radius: 6px;
}

.chat-bubble p {
  margin: 0 0 0.9rem;
}

.chat-bubble p:last-child {
  margin-bottom: 0;
}

.chat-typing {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0.2rem 0.15rem;
}

.chat-typing-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-text-muted);
  animation: chat-typing-bounce 1.1s ease-in-out infinite;
}

.chat-typing-dot:nth-child(2) {
  animation-delay: 0.15s;
}

.chat-typing-dot:nth-child(3) {
  animation-delay: 0.3s;
}

@keyframes chat-typing-bounce {
  0%, 60%, 100% {
    transform: translateY(0);
    opacity: 0.5;
  }
  30% {
    transform: translateY(-4px);
    opacity: 1;
  }
}

#question-form {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1rem 1.25rem;
  /* Auf iPhones mit Home-Indicator/Notch (viewport-fit=cover im Meta-Tag
     nötig, sonst liefert env() hier nur 0) darf die Eingabezeile nicht
     darunter verschwinden - max() behält auf normalen Geräten weiterhin
     den regulären 1rem-Abstand. */
  padding-bottom: max(1rem, env(safe-area-inset-bottom));
  border-top: 1px solid var(--color-border);
  background: var(--color-bg);
  flex-shrink: 0;
}

#question-form input {
  margin-top: 0;
  flex: 1;
  border-radius: var(--radius);
  padding: 0.7rem 1.25rem;
  background: var(--color-surface);
  /* Ohne dies erbt das Feld font-size: 0.95rem (~15px) von der generischen
     input/textarea-Regel - iOS Safari zoomt beim Fokussieren automatisch in
     jedes Feld mit weniger als 16px Schriftgröße hinein (der gemeldete
     "Zoom-Glitch" beim Start der Konversation). */
  font-size: 16px;
}

/* Ohne konfigurierten Turnstile-Site-Key bleibt der Container leer und darf
   keinen Platz in der Eingabezeile beanspruchen. */
.turnstile-container {
  flex-shrink: 0;
}

.turnstile-container:empty {
  display: none;
}

/* Cloudflare entfernt das gelöste Widget nicht aus dem DOM (der Container
   bleibt also nicht :empty) - ohne diese Regel bliebe die Box nach
   erfolgreicher Bestätigung sichtbar stehen. */
.turnstile-container.turnstile-verified {
  display: none;
}

/* Desktop: normaler Text-Button ("Absenden"/"Send"), Papierflieger-Icon
   bleibt versteckt - die Icon-Variante ist ausdrücklich nur eine
   Mobile-Lösung (siehe Media Query weiter unten), am Desktop ändert sich
   nichts. */
#question-form button.send-button {
  border-radius: var(--radius);
  flex-shrink: 0;
}

.send-icon {
  display: none;
}

/* Backlog #49: Mikrofon-Button für Spracheingabe - ausgeblendet per
   .hidden, solange static/speech.js keine Browser-Unterstützung meldet
   (progressive enhancement, Tippen funktioniert immer). */
.mic-button {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1.5px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.mic-button:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.mic-button.recording {
  border-color: var(--color-warning);
  background: var(--color-warning);
  color: var(--color-bg);
  animation: mic-recording-pulse 1.4s ease-in-out infinite;
}

@keyframes mic-recording-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--color-warning-tint); }
  50% { box-shadow: 0 0 0 6px var(--color-warning-tint); }
}

/* Lautsprecher-Icon pro Antwort-Bubble (manuelles Vorlesen) - dezent, wird
   erst bei Hover/Fokus der Bubble bzw. während des Sprechens sichtbar
   betont, ähnlich dem bestehenden .icon-button-Ausblendmuster, aber ohne
   dessen #source-list-Kopplung. */
.speak-answer-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0.2rem;
  margin-left: 0.4rem;
  color: var(--color-text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
}

.speak-answer-btn:hover {
  color: var(--color-accent);
}

.speak-answer-btn.speaking {
  color: var(--color-accent);
}

/* Vorlesegeschwindigkeit: schaltet per Klick durch SPEECH_RATES (speech.js)
   - bewusst ein reiner Text-Button statt eines Icons, da die Beschriftung
   (z.B. "1.5x") selbst der wichtigste Zustand ist. */
.speed-answer-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0.2rem 0.3rem;
  margin-left: 0.1rem;
  color: var(--color-text-muted);
  cursor: pointer;
  font-size: 0.75rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
}

.speed-answer-btn:hover {
  color: var(--color-accent);
}

.chat-sources-heading {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
  margin: 0.75rem 0 0.4rem;
}

#sources-sidebar {
  display: none;
}

/* Auf Mobile gibt es die Sidebar nicht - Quellen bleiben dort nur über die
   anklickbaren [1][2]-Verweise im Antworttext erreichbar. Ab hier genug
   Platz für eine zweispaltige Ansicht, deshalb wird die Seite insgesamt
   etwas breiter. */
@media (min-width: 900px) {
  body {
    max-width: min(1280px, 94vw);
  }

  #frage-bereich {
    display: grid;
    grid-template-columns: 260px 1fr;
    gap: 2.5rem;
    align-items: start;
  }

  #sources-sidebar {
    display: block;
    grid-column: 1;
    position: sticky;
    top: 1.5rem;
    /* Ohne Deckelung würde die Liste bei vielen zitierten Quellen beliebig
       lang und die Seite müsste allein deswegen gescrollt werden - stattdessen
       bekommt sie hier eine eigene, vom Konversationsbereich unabhängige
       Scrollleiste, sobald sie den verfügbaren vertikalen Platz sprengt. */
    max-height: calc(100vh - 3rem);
    overflow-y: auto;
  }

  /* #chat-column braucht eine EXPLIZITE Spalten-Zuweisung: ist die Sidebar
     leer (display:none, siehe :has()-Regel unten), rutscht sie sonst per
     Grid-Auto-Placement in die schmale erste Spalte statt in die breite
     zweite - genau das war der gemeldete Anzeigefehler beim leeren Chat. */
  #chat-column {
    grid-column: 2;
  }

  /* Vor der ersten beantworteten Frage ist die Liste leer - dann auch die
     Überschrift ausblenden, statt einen leeren Kasten zu zeigen. */
  #sources-sidebar:has(#sidebar-sources-list:empty) {
    display: none;
  }

  #sources-sidebar h3 {
    font-size: 0.95rem;
  }

  /* Ab hier wächst die Konversations-Box mit dem Antworttext mit statt
     intern zu scrollen (Vorbild: Chat-Modus von Claude) - das Eingabefeld
     bleibt per position:sticky immer mit sichtbarem Abstand zum unteren
     Bildschirmrand erreichbar, auch wenn die Seite dadurch insgesamt länger
     wird und selbst scrollt. Nur nach der ersten Frage relevant - vorher
     zeigt body:not(.chat-started) ohnehin die kompakte, zentrierte
     Startansicht (dortige Regeln haben höhere Spezifität und bleiben
     unberührt). */
  body.chat-started #chat-column {
    height: auto;
    max-height: none;
    overflow: visible;
  }

  body.chat-started #chat-messages {
    overflow-y: visible;
  }

  body.chat-started #question-form {
    position: sticky;
    bottom: max(1rem, env(safe-area-inset-bottom));
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
    z-index: 1;
  }
}

/* Mobile: der Chat soll wie eine moderne Chat-App möglichst den ganzen
   sichtbaren Bildschirm ausfüllen (Vorbild: eigenes CRT-Tool, dort per
   `.app-layout { height: 100dvh }` gelöst). Eine feste vh-Höhe wie am
   Desktop (siehe #chat-column oben) reicht auf dem Handy nicht - Header +
   Tagline + feste Prozenthöhe sprengen zusammen leicht die tatsächliche
   Viewport-Höhe, wodurch die Eingabezeile unten abgeschnitten wurde
   (per echtem Fenstertest verifiziert). Lösung: #chat-column bekommt
   `flex: 1` und füllt IMMER exakt den nach Header/Tagline verbleibenden
   Platz, unabhängig von der genauen Bildschirmhöhe. `:has(#frage-bereich)`
   sorgt dafür, dass NUR die Chat-Seite (index.html) betroffen ist, nicht
   die Quellen-Pflege (import.html) mit ihrer potenziell langen Liste, die
   ganz normal scrollen soll. */
@media (max-width: 640px) {
  /* Der Rollen-Schalter ist ein Test-/Entwickler-Werkzeug - auf dem Handy
     nimmt er im ohnehin knappen Konversations-Header nur unnötig Platz weg. */
  .desktop-only {
    display: none;
  }

  /* body ist standardmäßig nur 92vw breit (siehe max-width: min(980px, 92vw)
     oben) UND hat zusätzlich eigenes horizontales Padding - auf dem Handy
     verschenkt das spürbar Platz. Beides hier verkleinern, damit der Chat
     die Bildschirmbreite tatsächlich ausnutzt. */
  body {
    max-width: 100%;
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }

  header {
    align-items: flex-start;
    /* Fix: padding-bottom hier eigens etwas größer als margin-bottom - der
       absolut positionierte Nutzername unter dem Login-Icon
       (.auth-username-label) braucht diesen zusätzlichen Platz, sonst landet
       er auf der border-bottom-Trennlinie statt (wie am Desktop) klar
       darüber. */
    padding-bottom: 1.6rem;
    margin-bottom: 0.85rem;
  }

  /* Bricht der Header um (Titel + Actions passen nicht in eine Zeile),
     landet .header-actions als einzelnes Element auf seiner eigenen Zeile
     sonst am linken statt am rechten Rand - hier wie am Desktop erzwungen. */
  .header-actions {
    width: 100%;
    justify-content: flex-end;
  }

  header h1 {
    font-size: 1.25rem;
  }

  #frage-bereich {
    min-height: 0;
    /* In Flexbox kollabieren Geschwister-Margins NICHT wie im normalen
       Blockfluss - margin-bottom hier UND margin-top von .site-footer
       hätten sich sonst zu einer doppelt so großen Lücke addiert. */
    margin-bottom: 1rem;
  }

  #chat-column {
    flex: 1;
    height: auto;
    min-height: 280px;
    max-height: none;
    /* Der äußere Rahmen (Border/abgerundete Ecken/eigene Hintergrundfarbe)
       wirkt auf dem Handy wie eine unnötige Box um die Konversation -
       hier entfernt, damit der Chat direkt in die Seite integriert wirkt
       und nicht zusätzlich Breite "kostet". */
    border: none;
    border-radius: 0;
    background: transparent;
  }

  #question-form {
    padding-left: 0;
    padding-right: 0;
  }

  #chat-messages {
    padding-left: 0;
    padding-right: 0;
  }

  .chat-bubble {
    max-width: 92%;
  }

  body {
    padding-bottom: 1.5rem;
  }

  .site-footer {
    flex-shrink: 0;
    margin-top: 0;
  }

  /* Nur auf Mobile: Papierflieger-Icon statt Textbutton, spart Platz in
     der Eingabezeile - am Desktop bleibt der Textbutton unverändert. */
  .send-label {
    display: none;
  }

  .send-icon {
    display: inline-flex;
  }

  #question-form button.send-button {
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

.md-heading {
  display: block;
  margin-top: 0.6rem;
}

.citation-ref-wrap {
  white-space: nowrap;
}

.citation-ref {
  background: none;
  border: none;
  padding: 0;
  margin: 0 0.05em;
  color: var(--color-accent);
  font: inherit;
  font-weight: 700;
  font-size: 0.85em;
  vertical-align: super;
  cursor: pointer;
}

.citation-ref:hover {
  color: var(--color-accent-hover);
  text-decoration: underline;
}

.external-link {
  display: inline-flex;
  vertical-align: middle;
  margin-left: 0.35rem;
  color: var(--color-accent);
}

.external-link:hover {
  color: var(--color-accent-hover);
}

.citation-card {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);
  border-radius: var(--radius);
  padding: 0.9rem 1rem;
  margin: 0.6rem 0 1rem;
}

.citation-card-heading {
  font-weight: 600;
  margin: 0 0 0.5rem;
}

.citation-author-link {
  color: inherit;
  text-decoration: none;
}

.citation-author-link:hover {
  color: var(--color-accent);
}

.citation-card-text {
  color: var(--color-text-muted);
  margin: 0 0 0.5rem;
}

.citation-highlight {
  background: var(--color-accent-tint);
  color: var(--color-text);
  font-weight: 600;
  border-radius: 3px;
  padding: 0.05em 0.15em;
}

.chat-sources-list, #sidebar-sources-list, #source-list, #author-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.chat-sources-list li, #sidebar-sources-list li, #source-list li, #author-list li {
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--color-border);
}

#source-list li.source-row {
  display: block;
}

/* Backlog #75: kurzer visueller Hinweis für den ?source=<id>-Deep-Link (z.B.
   aus dem Embed-Widget oder von Zitaten in der Konversation) - zeigt an,
   WELCHE der ggf. vielen sichtbaren Quellen gerade angesprungen wurde, ohne
   (anders als der ?edit=-Deep-Link) den Bearbeitungsmodus zu öffnen. Die
   Klasse entfernt sich selbst wieder über den animationend-Listener in
   import.js, sobald die Animation einmal durchgelaufen ist. */
#source-list li.source-row.source-highlight-flash {
  animation: source-highlight-flash 2s ease-out;
}

@keyframes source-highlight-flash {
  0%, 15% {
    box-shadow: inset 0 0 0 2px var(--color-accent);
  }
  100% {
    box-shadow: inset 0 0 0 2px transparent;
  }
}

#source-list li.author-marker {
  border-bottom: none;
  padding: 1.25rem 0 0.3rem;
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--color-text);
}

#source-list li.author-marker:first-child {
  padding-top: 0;
}

/* Backlog #57: unsichtbares Sentinel-Element am Listenende, das per
   IntersectionObserver das Nachladen der nächsten Seite auslöst - overschreibt
   die generische li-Randlinie/-Polsterung, damit es nicht wie eine leere
   Trennzeile aussieht; grid-column sorgt in der Timeline-Ansicht (CSS-Grid)
   dafür, dass es nicht versehentlich in die Label-Spalte einsortiert wird. */
#source-list li.source-list-sentinel {
  padding: 0;
  margin: 0;
  border-bottom: none;
  height: 1px;
  grid-column: 1 / -1;
}

.source-row-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: 0.5rem 0.75rem;
  position: relative;
}

.source-row-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-shrink: 0;
}

.source-row-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
}

.source-summary {
  margin-top: 0.5rem;
}

.source-summary-icon {
  display: inline-flex;
  color: var(--color-accent);
  vertical-align: middle;
}

.source-title-toggle {
  text-align: left;
  color: var(--color-text);
  font-weight: inherit;
  text-decoration: none;
}

.source-title-toggle:hover {
  color: var(--color-text);
}

.source-summary-text {
  margin: 0.5rem 0 0;
  color: var(--color-text);
  line-height: 1.55;
}

.source-summary-text p {
  margin: 0;
}

.source-summary-text .md-heading {
  display: block;
  margin-top: 0.5rem;
}

.term-link {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--color-accent);
  cursor: pointer;
}

.term-link:hover {
  color: var(--color-accent-hover);
  text-decoration: underline;
}

.term-highlight {
  color: var(--color-text);
  font-weight: 700;
}

/* Klickbare Begriffs-Hervorhebung (filtert die Quellenübersicht nach diesem
   Schlagwort) - bewusst optisch identisch zu .term-highlight (schwarz, kein
   Unterstrich), NICHT wie .term-link in Akzentfarbe, damit ein allgemeines
   Schlagwort nicht wie ein Autor:innen-Link aussieht. Der Unterstrich beim
   Hover ist die einzige Erkennbarkeit, dass hier etwas klickbar ist. */
.term-highlight-button {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--color-text);
  font-weight: 700;
  cursor: pointer;
}

.term-highlight-button:hover {
  text-decoration: underline;
}

.source-open-link {
  display: inline-flex;
  vertical-align: middle;
  margin-left: 0.35rem;
  color: var(--color-accent);
}

.source-open-link:hover {
  color: var(--color-accent-hover);
}

.section-heading-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  margin-bottom: 1rem;
}

.section-heading-row h3 {
  margin: 0;
}

/* Bündelt "Neue Quelle hinzufügen" (quelltyp-buttons) und die Sortier-Icons
   zu einem Block rechtsbündig auf Höhe der Überschrift - margin-left:auto
   funktioniert dabei sowohl in derselben Zeile als auch (auf schmalen
   Bildschirmen) wenn der Block in eine eigene Zeile umbricht. */
.section-heading-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.25rem;
  margin-left: auto;
}

.section-heading-actions .sort-toolbar {
  padding-left: 1.25rem;
  border-left: 1px solid var(--color-border);
}

.section-heading-actions .search-toolbar {
  padding-left: 1.25rem;
  border-left: 1px solid var(--color-border);
}

/* Backlog #94, zweiter Anlauf: statt eines Popovers (auf Mobile unpraktikabel,
   auf Desktop schwer sauber am rechts sitzenden Icon auszurichten, siehe
   git-Historie dieser Datei) klappt hier ein Suchbereich in voller Breite
   auf, der die Alphabet-Sprungleiste ersetzt (siehe searchBarOpen in
   import.js) - robust bei jeder Bildschirmbreite, da kein absolut
   positioniertes Element mit fester Breite involviert ist. */
.search-bar {
  margin-bottom: 1rem;
}

.search-bar label {
  margin-bottom: 0;
}

/* Job-Warteschlange auf Mobile: gleiches Prinzip wie .search-bar oben -
   ein vollbreiter Bereich unterhalb der Icon-Leiste statt eines Popovers,
   da dieses als position:static-Flex-Item (siehe @media max-width:480px
   weiter unten) sonst alle Icons der Zeile beim Öffnen verschob. Auf
   Desktop bleibt stattdessen #jobs-popover aktiv (siehe .jobs-bar
   @media min-width:481px weiter unten sowie isMobileLayout() in
   import.js). */
.jobs-bar {
  position: relative;
  margin-bottom: 1rem;
  padding: 1rem 2.5rem 1rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.jobs-bar-close {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
}

.jobs-bar-close:hover {
  color: var(--color-accent);
}

#jobs-bar-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

#jobs-bar-list li {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--color-border);
}

#jobs-bar-list li:last-child {
  border-bottom: none;
}

@media (min-width: 481px) {
  .jobs-bar {
    display: none !important;
  }
}

.sort-toolbar {
  display: flex;
  gap: 0.5rem;
}

.sort-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1.5px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-text-muted);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.sort-button:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.sort-button.active {
  border-color: var(--color-accent);
  color: var(--color-accent);
  background: var(--color-accent-tint);
}

/* Backlog #65: Alphabet-Sprungleiste - nur in der Autor:innen-Sortierung
   sichtbar (siehe updateAlphabetJumpBar in import.js). */
.alphabet-jump-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-bottom: 1rem;
}

.alphabet-jump-btn {
  min-width: 1.6rem;
  padding: 0.15rem 0.3rem;
  border: none;
  background: none;
  color: var(--color-accent);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  border-radius: 3px;
}

.alphabet-jump-btn:hover {
  color: var(--color-accent-hover);
  background: var(--color-accent-tint);
}

.alphabet-jump-btn:disabled {
  color: var(--color-text-muted);
  opacity: 0.4;
  cursor: default;
}

/* Timeline-Ansicht: CSS-Grid mit drei Spuren (Label / Zeitlinie / Inhalt).
   Die Zeitlinie ist ein einzelnes Grid-Item (::before des Containers), das
   über grid-row: 1 / -1 durchgängig über alle Zeilen läuft - dadurch kann
   sie nie durch Text gekreuzt werden und braucht keine Pixel-Arithmetik. */
#source-list.timeline-mode {
  display: grid;
  grid-template-columns: max-content 1.25rem 1fr;
  column-gap: 0.75rem;
  row-gap: 0;
  border-left: none;
  margin-left: 0;
  padding-left: 0;
}

#source-list.timeline-mode::after {
  content: "";
  grid-column: 2;
  grid-row: 1 / var(--timeline-row-end, 2);
  justify-self: center;
  width: 2px;
  background: var(--color-border);
  z-index: 0;
}

#source-list.timeline-mode li.source-row {
  grid-column: 3;
  position: relative;
  /* Zieht die Trennlinie (border-bottom) bis genau an die Zeitlinie heran
     (nicht darüber hinaus) - der Versatz entspricht exakt dem Abstand von
     Spalte 3 zur Mitte der Zeitlinie (Spalte 2). Padding gleicht den
     Margin-Versatz für die Textposition wieder aus. */
  margin-left: -1.375rem;
  padding-left: 1.375rem;
}

#source-list.timeline-mode li.source-row .source-row-header::before {
  content: "";
  position: absolute;
  /* left relativ zur Padding-Box von .source-row-header (die - anders als
     die li selbst - NICHT per margin verschoben ist, also noch an der
     ursprünglichen Spalte-3-Position sitzt): gleicher Versatz wie zuvor,
     um exakt auf der Zeitlinie zu landen. Vertikal auf 50% der Kopfzeile
     zentriert (nicht auf die ganze li, die z.B. bei ausgeklappter
     Kurzfassung viel höher ist). */
  left: -1.375rem;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-accent);
  z-index: 1;
}

#source-list .timeline-marker {
  grid-column: 1;
  align-self: start;
  padding: 0.6rem 1.375rem 0.6rem 0;
  /* Zieht die Trennlinie unter dem Label genau bis zur Zeitlinie (gleicher
     Versatz wie bei li.source-row, nur nach rechts statt nach links). */
  margin-right: -1.375rem;
  border-bottom: 1px solid var(--color-border);
  font-weight: 700;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  text-align: right;
  white-space: nowrap;
}

/* Backlog #99: Änderungs-Log - gleiches Zeitstrahl-Grid wie
   #source-list.timeline-mode (siehe Kommentar dort), nur nach Kalendertag
   statt Monat/Jahr gruppiert und mit eigenen Klassennamen, damit die
   bestehende Quellenübersicht unangetastet bleibt. */
#changelog-list.timeline-mode {
  display: grid;
  grid-template-columns: max-content 1.25rem 1fr;
  column-gap: 0.75rem;
  row-gap: 0;
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
}

#changelog-list.timeline-mode::after {
  content: "";
  grid-column: 2;
  grid-row: 1 / var(--timeline-row-end, 2);
  justify-self: center;
  width: 2px;
  background: var(--color-border);
  z-index: 0;
}

#changelog-list .changelog-day-marker {
  grid-column: 1;
  align-self: start;
  padding: 0.6rem 1.375rem 0.6rem 0;
  margin-right: -1.375rem;
  border-bottom: 1px solid var(--color-border);
  font-weight: 700;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  text-align: right;
  white-space: nowrap;
}

#changelog-list .changelog-entry {
  grid-column: 3;
  position: relative;
  margin-left: -1.375rem;
  padding: 0.85rem 0 0.85rem 1.375rem;
  border-bottom: 1px solid var(--color-border);
}

#changelog-list .changelog-entry::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.25rem;
  transform: translateX(-50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-accent);
  z-index: 1;
}

.changelog-entry-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  color: var(--color-text);
}

.changelog-entry-icon {
  display: inline-flex;
  flex-shrink: 0;
}

.changelog-entry-icon--created { color: #2f7a3d; }
.changelog-entry-icon--updated { color: var(--color-text-muted); }
.changelog-entry-icon--deleted { color: var(--color-accent); }
.changelog-entry-icon--reverted { color: #8a6d1f; }

.changelog-entity-icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--color-text-muted);
}

.changelog-ai-badge {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--color-accent);
}

.changelog-actor {
  font-weight: 700;
}

.changelog-target-label {
  color: var(--color-text-muted);
}

.changelog-time {
  margin-left: auto;
  flex-shrink: 0;
  font-size: 0.8rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

.changelog-field-list {
  margin: 0.5rem 0 0;
  padding-left: 1.1rem;
  color: var(--color-text-muted);
  font-size: 0.92rem;
}

.changelog-field-list li {
  margin-bottom: 0.15rem;
}

.changelog-field-list strong {
  color: var(--color-text);
}

.changelog-revert-row {
  margin-top: 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.9rem;
}

.changelog-reverted-label {
  color: var(--color-text-muted);
  font-size: 0.85rem;
  font-style: italic;
}

.changelog-status {
  color: var(--color-text-muted);
}

/* Backlog #97: eigenständiger, deutlich schlankerer Zeitstrahl fürs
   Fragen-Log (nur Uhrzeit + Fragetext, kein Icon/Diff/Rückgängig) - gleiche
   3-Spalten-Grid-Mechanik wie #changelog-list.timeline-mode oben, aber als
   eigene, parallele Regel-Gruppe (dort bewusst nichts geändert). */
#question-log-list.timeline-mode {
  display: grid;
  grid-template-columns: max-content 1.25rem 1fr;
  column-gap: 0.75rem;
  row-gap: 0;
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
}

#question-log-list.timeline-mode::after {
  content: "";
  grid-column: 2;
  grid-row: 1 / var(--timeline-row-end, 2);
  justify-self: center;
  width: 2px;
  background: var(--color-border);
  z-index: 0;
}

#question-log-list .question-log-day-marker {
  grid-column: 1;
  align-self: start;
  padding: 0.6rem 1.375rem 0.6rem 0;
  margin-right: -1.375rem;
  border-bottom: 1px solid var(--color-border);
  font-weight: 700;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  text-align: right;
  white-space: nowrap;
}

#question-log-list .question-log-entry {
  grid-column: 3;
  position: relative;
  margin-left: -1.375rem;
  padding: 0.85rem 0 0.85rem 1.375rem;
  border-bottom: 1px solid var(--color-border);
}

#question-log-list .question-log-entry::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.25rem;
  transform: translateX(-50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-accent);
  z-index: 1;
}

.question-log-time {
  display: block;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

.question-log-text {
  margin: 0.2rem 0 0;
  color: var(--color-text);
}

.icon-button {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0.25rem;
  color: var(--color-text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
}

.icon-button:hover {
  color: var(--color-accent);
}

.icon-button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.icon-button:disabled:hover {
  color: var(--color-text-muted);
}

@media (hover: hover) and (pointer: fine) {
  .icon-button {
    opacity: 0;
    transition: opacity 0.15s ease;
  }

  #source-list li:hover .icon-button,
  #source-list li:focus-within .icon-button {
    opacity: 1;
  }

  .icon-button.warning-icon {
    opacity: 1;
  }

  .icon-button.add-author-btn,
  .icon-button.remove-author-btn {
    opacity: 1;
  }

  .icon-button.auth-widget-button {
    opacity: 1;
  }

  .icon-button.author-info-edit-btn {
    opacity: 1;
  }
}

#source-list li.source-row--unreachable {
  background: var(--color-warning-tint);
  border-left: 3px solid var(--color-warning);
  padding-left: 0.6rem;
  margin-left: -0.85rem;
}

/* Ein Autor mit nur einer Quelle bekommt keine eigene Zwischenüberschrift
   (siehe buildAuthorMarker) - folgt er direkt auf einen Autor MIT
   Zwischenüberschrift, braucht es trotzdem sichtbaren Abstand, sonst
   wirkt seine Quelle wie ein weiterer Eintrag des vorherigen Autors. */
#source-list li.source-row--after-author-group {
  margin-top: 1.25rem;
}

/* In der Timeline-Ansicht hat li.source-row bereits eigene margin/padding,
   damit Trennlinie und Punkt exakt auf der Zeitlinie sitzen - diese
   Positionierung darf die Warnzeile nicht überschreiben. */
#source-list.timeline-mode li.source-row--unreachable {
  margin-left: -1.375rem;
  padding-left: 1.375rem;
  border-left: none;
}

.warning-icon {
  color: var(--color-warning);
}

.warning-icon:hover {
  color: var(--color-warning);
}

/* Backlog #163: Statuszeile im Bearbeiten-Panel mit dem konkreten
   Fehlergrund einer nicht erreichbaren Quelle (siehe import.js:
   unreachableSourceInfo/urlErrorText) - gleiche Warnfarbe wie das
   Warn-Icon, gleiche Größe wie bestehende Meta-Texte im Formular
   (z.B. .relevance-slider-label-row). */
.url-health-status {
  color: var(--color-warning);
  font-size: 0.85rem;
  margin-top: -0.6rem;
  margin-bottom: 0.9rem;
}

#typ-jobs {
  position: relative;
}

#typ-jobs.has-error #jobs-icon-progress {
  stroke: var(--color-warning);
}

.jobs-icon-count {
  position: absolute;
  top: -0.2rem;
  right: -0.2rem;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 0.2rem;
  border-radius: 999px;
  background: var(--color-accent);
  color: #fff;
  font-size: 0.65rem;
  font-weight: 700;
  line-height: 1.1rem;
  text-align: center;
}

/* ToDo: schlägt eine Quelle in der Warteschlange fehl, soll das direkt am
   Icon sichtbar sein, statt nur an der (dezenten) Ringfarbe erkennbar zu
   sein - eigenes Warnzeichen-Badge unten rechts, analog zur Zahlen-Badge
   oben rechts positioniert, damit sich beide bei Bedarf nicht überlappen. */
.jobs-icon-warning {
  position: absolute;
  bottom: -0.2rem;
  right: -0.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 999px;
  background: var(--color-warning);
  color: #fff;
}

#jobs-popover {
  min-width: 260px;
  max-width: 320px;
}

#jobs-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 260px;
  overflow-y: auto;
}

#jobs-list li {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--color-border);
}

#jobs-list li:last-child {
  border-bottom: none;
}

.jobs-list-title {
  font-weight: 600;
  display: block;
}

.jobs-list-step {
  color: var(--color-text-muted);
  font-size: 0.85rem;
}

.jobs-list-error {
  color: var(--color-warning);
  font-size: 0.85rem;
  margin: 0.2rem 0;
}

/* Ohne explizite Spalten-Zuweisung landet das Bearbeiten-Panel im Grid der
   Timeline-Ansicht per Auto-Placement in Spalte 1 (links der Zeitlinie) -
   es soll aber wie li.source-row in Spalte 3 (rechts der Zeitlinie, unter
   der Überschrift der Quelle) erscheinen. */
#source-list.timeline-mode li.source-edit-panel {
  grid-column: 3;
}

#source-list li.source-edit-panel {
  display: block;
  background: var(--color-surface);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin: 0.5rem 0 1rem;
  border-bottom: none;
}

#source-list li.source-edit-panel--pending-deletion label,
#source-list li.source-edit-panel--pending-deletion .checkbox-label {
  opacity: 0.6;
}

.source-edit-panel input:disabled,
.source-edit-panel textarea:disabled {
  cursor: not-allowed;
  background: var(--color-border);
}

.source-edit-panel label {
  margin-bottom: 0.9rem;
}

.field-row {
  display: flex;
  gap: 1rem;
  margin-bottom: 0.9rem;
}

.field-row label {
  flex: 1;
  margin-bottom: 0;
  min-width: 0;
}

/* Backlog #51: Relevanz-Score-Slider auf Höhe des Titels - Titel nimmt 2/3,
   Slider das übrige Drittel (statt einer eigenen vollbreiten Zeile). */
.title-relevance-row {
  display: flex;
  gap: 1rem;
  margin-bottom: 0.9rem;
}

.title-relevance-row label {
  flex: 2;
  margin-bottom: 0;
  min-width: 0;
}

.relevance-slider-field {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.relevance-slider-label-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: 0.4rem;
}

.relevance-slider-value {
  font-weight: 700;
  color: var(--color-accent);
}

.relevance-slider {
  width: 100%;
  height: 1.4rem;
  margin-top: auto;
  appearance: none;
  background: transparent;
  cursor: pointer;
}

.relevance-slider::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 999px;
  background: var(--color-border);
}

.relevance-slider::-moz-range-track {
  height: 4px;
  border-radius: 999px;
  background: var(--color-border);
}

.relevance-slider::-webkit-slider-thumb {
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--color-accent);
  margin-top: -6px;
  border: none;
}

.relevance-slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--color-accent);
  border: none;
}

.author-input-group {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin-top: 0.35rem;
}

.author-input-group .author-input {
  flex: 1;
  min-width: 0;
  margin-top: 0;
}

.author-extra-rows:not(:empty) {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-bottom: 0.9rem;
}

/* Fix: das "Autorenprofil pflegen"-Panel des ERSTEN Autors sitzt direkt in
   .author-fields (zwischen .field-row und .author-extra-rows) und hatte
   keinen margin-bottom - die nächste Autor:innen-Zeile klebte dadurch direkt
   an der Box, statt den sonst üblichen Zeilenabstand einzuhalten (0.9rem,
   wie bei .field-row). Bewusst NICHT pauschal auf .new-author-profile
   gesetzt: bei einer 2./3. Person sitzt dasselbe Panel innerhalb von
   .author-extra-row-group, wo der Flex-gap des umgebenden
   .author-extra-rows bereits für konsistenten Abstand sorgt - ein
   zusätzlicher margin-bottom dort würde die Lücke verdoppeln. */
.author-fields > .new-author-profile {
  margin-bottom: 0.9rem;
}

.author-extra-row {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  /* KEIN eigenes max-width mehr - die Breitenbegrenzung übernimmt bereits
     der umschließende .author-extra-row-group (siehe dort). Beide Regeln
     mit demselben calc(50% - 0.5rem) hätten sich sonst verdoppelt: die
     zweite Berechnung bezieht sich auf die Breite des bereits halbierten
     Wrappers, wodurch am Ende nur ~25% statt 50% übrig blieben - genau der
     Bug, der hier gemeldet wurde. */
  width: 100%;
}

.author-extra-row .author-input {
  flex: 1;
  min-width: 0;
  margin-top: 0;
}

/* Backlog #86: hüllt eine Autor:innen-Eingabezeile und das dazugehörige,
   optionale "Autorenprofil pflegen"-Panel gemeinsam ein, damit "+"/"-"
   beide zusammen verschieben/entfernen (siehe buildExtraRow in import.js).
   Gleiche Breite wie das erste Autorenfeld, das sich per .field-row
   (flex:1 + 1rem gap) die Zeile mit dem Datumsfeld teilt. */
.author-extra-row-group {
  max-width: calc(50% - 0.5rem);
}

.new-author-profile {
  margin-top: 0.5rem;
  padding: 0.5rem 0.8rem;
  font-size: 0.9rem;
  /* Dünner Rahmen + farbliche Akzentuierung, damit sichtbar wird, wo dieses
     Panel (und damit die Felder für die gerade aufgeklappte Person) endet -
     ohne die Akzentuierung ging die Grenze zwischen Autorenfeld und
     Formular-Rest visuell verloren. */
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);
  border-radius: 6px;
  background: var(--color-accent-tint);
}

.new-author-profile-body {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  margin-top: 0.6rem;
}

.new-author-profile-body label {
  margin-bottom: 0;
}

.label-inline-icon {
  margin-left: 0.4rem;
  vertical-align: middle;
}

@media (hover: hover) and (pointer: fine) {
  .label-inline-icon {
    opacity: 1;
  }
}

.source-edit-panel .edit-status {
  color: var(--color-text-muted);
  font-size: 0.9rem;
  margin: 0.5rem 0 0;
}

.source-edit-panel .link-button {
  margin-left: 1rem;
}

.edit-panel-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  margin-top: 0.5rem;
}

/* Fix: das Formular zum Anlegen einer neuen Text-Quelle hatte bisher nur
   einen "Importieren"-Button, keine Möglichkeit, ohne Speichern
   abzubrechen. */
.create-form-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.edit-panel-actions .delete-button {
  flex-shrink: 0;
}

/* Autor:innen-Profile (Backlog #55): Klick auf einen Namen filtert wie
   bisher die Quellenliste - auf Desktop erscheint daneben (2/3 Quellen
   links, 1/3 Profil rechts), auf Mobil darüber, ein Info-/Bearbeiten-Panel
   für genau diese Person (siehe #quellen-liste-body weiter unten). Kopfzeile:
   Name links (darf mehrzeilig umbrechen), Foto + Bearbeiten-Stift rechts als
   eigene Spalte; die Vita steht darunter über die volle Breite. */
.author-info-photo-col {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
  flex-shrink: 0;
}

.author-photo {
  width: 157px;
  height: 157px;
  border-radius: 50%;
  object-fit: cover;
}

/* Vorschau direkt neben dem Foto-URL-Feld im Bearbeiten-Formular, damit
   Quellen-Admins sofort sehen, welches Bild hinter der URL steckt. */
.photo-field-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.35rem;
}

.photo-field-row input {
  flex: 1;
  min-width: 0;
  margin-top: 0;
}

.author-photo-preview {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.author-bio-section {
  margin-top: 0.9rem;
}

.author-bio-text {
  margin: 0;
  color: var(--color-text);
  line-height: 1.55;
  /* Die Info-Spalte ist auf Desktop nur 1/3 breit - lange (deutsche)
     Wörter brauchen Silbentrennung, damit der Umbruch nicht unnötig
     viel Leerraum am Zeilenende erzeugt. Nutzt document.documentElement.lang
     (siehe i18n.js), daher automatisch DE/EN-Regeln je nach Sprache. */
  hyphens: auto;
  overflow-wrap: break-word;
}

.author-bio-text--empty {
  color: var(--color-text-muted);
  font-style: italic;
}

.author-links-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin-top: 0.5rem;
}

.author-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--color-accent);
  font-size: 0.9rem;
}

.author-link:hover {
  color: var(--color-accent-hover);
}

.author-link-icon {
  display: inline-flex;
}


.author-info-view,
.author-edit-panel {
  background: var(--color-surface);
  border-radius: var(--radius);
  padding: 1.25rem;
}

.author-info-header-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem;
}

.author-info-heading {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
}

.author-info-edit-btn {
  flex-shrink: 0;
}

.author-info-edit-row {
  display: flex;
  justify-content: flex-end;
  margin-top: 0.75rem;
}

.author-edit-panel label {
  margin-bottom: 0.9rem;
}

.author-edit-panel .link-button {
  margin-left: 1rem;
}

/* Standard: einspaltig, DOM-Reihenfolge ist Info-Panel, Filter-Hinweis,
   Quellenliste - auf Mobil damit automatisch "Vita oben, Filter-Hinweis
   darunter, Quellen zuletzt" ohne zusätzliches CSS. */
.quellen-liste-body {
  display: flex;
  flex-direction: column;
}

.quellen-liste-body--author-filtered #author-info-panel {
  margin-bottom: 1.5rem;
}

@media (min-width: 641px) {
  /* Ab hier zweigeteilt: Quellen links (2/3), Autor:innen-Info rechts (1/3) -
     "order" dreht die visuelle Reihenfolge um, ohne die DOM-Reihenfolge (und
     damit die mobile Stapel-Reihenfolge) zu verändern. Der Filter-Hinweis
     rutscht hier per flex-basis:100% in eine eigene volle Zeile ÜBER den
     beiden Spalten (wie vor der Umstellung), statt Teil der Reihe zu sein. */
  .quellen-liste-body--author-filtered {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 2rem;
  }

  .quellen-liste-body--author-filtered #source-filter-status {
    order: -1;
    flex-basis: 100%;
  }

  .quellen-liste-body--author-filtered #source-list {
    flex: 2;
    order: 1;
    min-width: 0;
  }

  .quellen-liste-body--author-filtered #author-info-panel {
    flex: 1;
    order: 2;
    min-width: 0;
    margin-bottom: 0;
  }
}

.social-links-field {
  margin-top: 0.35rem;
}

.social-link-rows:not(:empty) {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}

.social-link-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.social-platform-input {
  flex: 0 0 40%;
  min-width: 0;
  margin-top: 0;
}

.social-url-input {
  flex: 1;
  min-width: 0;
  margin-top: 0;
}

details {
  cursor: pointer;
}

details summary {
  font-weight: 600;
}

details p {
  color: var(--color-text-muted);
  margin: 0.6rem 0;
}

details a {
  color: var(--color-accent);
}

.hidden {
  /* !important bewusst: .hidden ist eine generelle "immer ausblenden"-
     Utility-Klasse, die mit beliebigen anderen Klassen kombiniert wird
     (z.B. .circle-button setzt selbst display:flex) - ohne !important
     gewinnt bei gleicher Spezifität die spätere Regel im Stylesheet,
     unabhängig vom Inhalt (siehe Bug: #typ-jobs blieb trotz .hidden
     sichtbar, weil .circle-button weiter unten steht). */
  display: none !important;
}

.quelltyp-buttons {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.quelltyp-item--anchor {
  position: relative;
  display: flex;
  /* Auf Mobile wird .popover zu position:static (siehe @media (max-width:
     480px) weiter unten) und damit zu einem normalen Flex-Item dieses
     Containers - ohne column stünde das Popover fälschlich NEBEN statt
     UNTER dem Icon-Button. Auf Desktop (position:absolute) wirkungslos. */
  flex-direction: column;
}

.circle-button {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 1.5px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.circle-button:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
  background: var(--color-accent-tint);
}

.circle-button--sm {
  width: 32px;
  height: 32px;
}

/* #quelltyp-bereich-Präfix erhöht die Spezifität bewusst über die gemeinsame
   .popover-Basisregel hinaus - die Buttons sitzen jetzt rechts oben in der
   Kopfzeile, ein mittig zentriertes Popover würde dort über den Bildschirmrand
   hinausragen. Gleiches Muster wie beim Login-Popover (#auth-widget). */
#quelltyp-bereich .popover {
  left: auto;
  right: 0;
  transform: none;
}

#quelltyp-bereich .popover-arrow {
  left: auto;
  right: 12px;
  transform: rotate(45deg);
}

.popover {
  position: absolute;
  top: calc(100% + 18px);
  left: 50%;
  transform: translateX(-50%);
  width: min(360px, calc(100vw - 3rem));
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
  padding: 1.5rem;
  z-index: 10;
  text-align: left;
}

@media (max-width: 480px) {
  .popover {
    position: static;
    width: auto;
    transform: none;
    margin-top: 1rem;
    box-shadow: none;
  }

  .popover-arrow {
    display: none;
  }

  /* Ersetzt hier durch #jobs-bar (siehe oben) - als position:static-Flex-
     Item würde dieses Popover sonst weiterhin alle Icons der Zeile
     verschieben. */
  #jobs-popover {
    display: none !important;
  }

  /* Fix: "Alle Quellen neu indizieren" ist ein seltener Wartungs-Button
     für Quellen-Admins am Schreibtisch - auf Mobile bewusst ausgeblendet. */
  #reindex-bereich {
    display: none !important;
  }

  /* Backlog #75: Embed-Snippet ist für die Website-Pflege am Desktop gedacht
     (Copy-Paste in fremden HTML-Code) - auf Mobile ohnehin kaum sinnvoll
     nutzbar, deshalb dort ausgeblendet. */
  .footer-embed {
    display: none;
  }

  /* Fix: Footer auf schmalen Bildschirmen knapper halten - "Beta Hof" ist
     als externer Beratungs-Link auf Mobile verzichtbar, betacodex.org/
     Versionsnummer/Impressum/Datenschutz bleiben erhalten. */
  .footer-betahof-link {
    display: none;
  }

  /* Fix: Grafik-Glitch - der native Date-Picker (input[type=date]) hat auf
     iOS eine eigene Mindestbreite für seine Tag/Monat/Jahr-Segmente, die
     .field-row (Autor + Erscheinungsdatum nebeneinander) auf schmalen
     Bildschirmen über den rechten Rand des Bearbeiten-Panels hinausdrückt -
     min-width:0 auf dem Flex-Item allein reicht dagegen nicht, da es sich
     um die intrinsische Mindestbreite des nativen Eingabe-Widgets selbst
     handelt. Auf Mobile deshalb gestapelt statt nebeneinander, Datum zuerst
     (siehe Feedback: "Date Picker sollte über den Autoren stehen"). */
  .field-row {
    flex-direction: column;
  }

  .field-row label:last-child {
    order: -1;
  }

  /* Drei Anläufe ohne Erfolg getestet: max-width/min-width (Standard-
     Properties), overflow:hidden auf dem <label> (hat Overflow zwar
     verdeckt, dabei aber den rechten Rand abgeschnitten UND das native
     Kalender-Popup nicht mehr offen gehalten) und -webkit-min-logical-width
     (WebKit-spezifische "logical width" fuer date/time-Felder). Alle drei
     setzen voraus, dass WebKit dem Feld ueberhaupt erlaubt, unter seine
     eigene, intern berechnete Breite fuer die native Menulist-Darstellung
     zu schrumpfen - das war offenbar nirgends der Fall. Einziger
     verbleibender Hebel: die native Darstellung (inkl. ihrer eigenen
     Breitenberechnung) komplett abschalten und das Feld wie ein normales
     Eingabefeld nach Standard-Boxmodell layouten. Tippen zum Oeffnen des
     nativen Kalender-Wheels bleibt davon unberuehrt (an den type="date"
     haengt die Picker-Funktion, nicht an der Menulist-Optik) - es
     verschwindet lediglich das kleine native Kalender-Icon, das Feld sieht
     dann aus wie jedes andere Textfeld in diesem Formular. */
  .field-row input[type="date"] {
    width: 100%;
    max-width: 100%;
    -webkit-appearance: none;
    appearance: none;
  }

  /* Fix: .author-extra-row-group war fest auf halbe Breite gedeckelt (siehe
     Kommentar dort), weil sich die erste Autorenzeile früher die Zeile mit
     dem Datumsfeld teilte (50/50 via .field-row). Jetzt, wo .field-row auf
     Mobile gestapelt ist, nimmt die erste Zeile die volle Breite ein - die
     zusätzlichen Zeilen (mit + UND -) müssen das hier nachziehen, sonst
     bleiben sie schmaler als die erste Zeile und lassen rechts Platz frei. */
  .author-extra-row-group {
    max-width: 100%;
  }

  /* Backlog: Relevanz-Score-Slider soll auf Mobile unter dem Titel stehen
     statt daneben - DOM-Reihenfolge ist bereits Titel zuerst, Relevanz
     danach, daher reicht das Stapeln ohne zusätzliches "order". */
  .title-relevance-row {
    flex-direction: column;
  }
}

.popover label {
  margin-bottom: 1.25rem;
}

.popover #popover-load, .popover #popover-upload {
  width: 100%;
}

.popover #popover-status, .popover #upload-status {
  margin-top: 0.75rem;
  margin-bottom: 0;
}

.popover-arrow {
  position: absolute;
  top: -7px;
  left: 50%;
  width: 12px;
  height: 12px;
  transform: translateX(-50%) rotate(45deg);
  border-left: 1px solid var(--color-border);
  border-top: 1px solid var(--color-border);
  background: var(--color-bg);
}

#import-status, #popover-status, #upload-status, .feedback-status {
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.site-footer {
  margin-top: 3rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  /* Fix: enger gestellt (vorher 0.6rem), damit die Links auf schmalen
     Bildschirmen eher in einer Zeile bleiben, ohne die Schrift zu
     verkleinern oder etwas auszublenden/scrollbar zu machen. */
  gap: 0.4rem;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

.footer-tagline {
  margin-right: auto;
}

.site-footer a {
  color: var(--color-text-muted);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--color-accent);
}

.footer-version {
  font-variant-numeric: tabular-nums;
}

/* Backlog #85: Feedback-Trigger statt reinem GitHub-Issues-Link - soll
   weiterhin wie die übrigen Footer-Links aussehen, nicht wie ein
   hervorgehobener .link-button (Standard: fett, unterstrichen). */
.footer-feedback-trigger {
  color: var(--color-text-muted);
  font-weight: inherit;
  font-size: inherit;
  text-decoration: none;
}

.footer-feedback-trigger:hover {
  color: var(--color-accent);
}

/* Fix: statt eines Popovers (position:absolute) klappt der Feedback-
   Bereich wie die Volltextsuche in import.js (#search-bar) in normalem
   Seitenfluss auf - robuster bei jeder Bildschirmbreite, kein Clipping
   durch overflow auf Vorfahren-Elementen möglich. Sitzt als Geschwister-
   Element VOR <footer id="site-footer"> im DOM (siehe ensureFeedbackPanel
   in footer.js), erscheint dadurch automatisch oberhalb von dessen
   Trennlinie (border-top), ohne dass extra Positionierung nötig wäre. */
.footer-feedback-panel {
  position: relative;
  margin-top: 3rem;
  padding: 1.5rem 2.75rem 1.5rem 1.5rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  font-size: 0.9rem;
}

.footer-feedback-panel label {
  margin-bottom: 1.25rem;
}

.footer-feedback-panel button[type="submit"] {
  width: 100%;
}

/* Gleiches Muster wie .jobs-bar-close (import.js/style.css) - Schließen-
   Kreuz oben rechts im Panel. */
.footer-feedback-panel-close {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
}

.footer-feedback-panel-close:hover {
  color: var(--color-accent);
}

/* Nur wenn das Panel tatsächlich sichtbar ist, übernimmt SEIN margin-top
   den Abstand zum Seiteninhalt darüber - sonst stünden bei geöffnetem
   Panel zwei Abstände (Panel- + site-footer-margin-top) hintereinander.
   Ist das Panel (wie im Regelfall) unsichtbar/nicht vorhanden, bleibt der
   ursprüngliche Abstand von .site-footer selbst unverändert bestehen. */
.footer-feedback-panel:not(.hidden) + .site-footer {
  margin-top: 1rem;
}

/* Backlog #75: Embed-Snippet-Popover - bleibt bewusst beim Popover-Muster
   (Trigger-Button + nach oben öffnendes .popover), da hier kein Clipping-
   Risiko besteht wie beim Feedback-Bereich oben. */
.footer-embed {
  position: relative;
  display: inline-flex;
  flex-direction: column;
}

.footer-embed > .link-button {
  color: var(--color-text-muted);
  font-weight: inherit;
  font-size: inherit;
  text-decoration: none;
}

.footer-embed > .link-button:hover {
  color: var(--color-accent);
}

.embed-popover {
  top: auto;
  bottom: calc(100% + 18px);
  left: 0;
  transform: none;
}

.embed-popover .popover-arrow {
  top: auto;
  bottom: -7px;
  left: 12px;
  transform: rotate(225deg);
}

.embed-popover-heading {
  margin-top: 0;
  font-weight: 600;
  color: var(--color-text);
}

.embed-popover label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.embed-popover input[type="number"] {
  width: 5rem;
}

.embed-snippet {
  width: 100%;
  min-height: 4.5rem;
  font-family: monospace;
  font-size: 0.8rem;
  resize: vertical;
}

.embed-popover button[type="button"]:last-child {
  width: 100%;
}
