/* Steel Crawler Web-UI */

/*
  Farbwerte stehen als Variablen, damit das dunkle Schema sie an einer Stelle
  umdefinieren kann (siehe html[data-theme="dark"] weiter unten).

  Die Namen der ersten Gruppe sind die gewachsenen und bleiben massgeblich.
  Das Dashboard-Design brachte teils dieselben Begriffe unter anderem Namen
  mit (--bg-app, --bg-surface, --accent, --ok); die sind hier bewusst *nicht*
  zusaetzlich angelegt worden. Zwei Namen fuer eine Farbe heisst, dass beim
  naechsten Aendern einer stehen bleibt. Neu ist nur, was es vorher gar nicht
  gab: die Zwischenstufen der Flaechen und des Textes, die weichen
  Statusfarben und die Formangaben.
*/
:root {
    color-scheme: light;

    --bg: #f5f5f5;
    --card: #fff;
    --border: #ddd;
    --text: #333;
    --text-muted: #888;
    --primary: #2563eb;
    --primary-hover: #1d4ed8;
    --success: #16a34a;
    --danger: #dc2626;
    --badge-ok: #dcfce7;
    --badge-ok-text: #166534;
    --badge-blocked: #fee2e2;
    --badge-blocked-text: #991b1b;
    --badge-none: #f3f4f6;
    --badge-none-text: #6b7280;
    --badge-warn: #fef3c7;
    --badge-warn-text: #92400e;
    /* Befund GESTOERT: eine Abwehr der fremden Seite, kein Auftrag an uns.
       Blau und nicht Gelb, weil Gelb hier STUMM traegt - und das verlangt
       Nacharbeit, waehrend GESTOERT nur abzuwarten ist. */
    --badge-info: #dbeafe;
    --badge-info-text: #1e40af;

    /* Flaechen zwischen Seitengrund (--bg) und Karte (--card) */
    --bg-surface-2: #fafafb;   /* abgesetzt *innerhalb* einer Karte */
    --bg-elevated: #fff;       /* liegt ueber der Karte (Hover, Dialog) */

    /* Textstufen ueber --text und --text-muted hinaus */
    --text-strong: #14161c;    /* Ueberschriften, Kartentitel */
    --text-faint: #9ca3af;     /* Zeitangaben, Beschriftungen */

    --border-strong: #d1d5db;  /* Kante einer Karte unter dem Zeiger */

    /* Weiche Statusfarben: Grund einer Pille, deren Text die Vollfarbe traegt */
    --primary-soft: rgba(37, 99, 235, 0.12);
    --ok-soft: rgba(22, 163, 74, 0.14);
    --warn: #d97706;
    --warn-soft: rgba(217, 119, 6, 0.14);
    --danger-soft: rgba(220, 38, 38, 0.14);
    --info: #0284c7;
    --info-soft: rgba(2, 132, 199, 0.14);

    /* Form */
    --radius-sm: 8px;
    --radius: 14px;
    --radius-lg: 20px;
    --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06);
    --shadow: 0 4px 16px rgba(16, 24, 40, 0.08);
    --shadow-lg: 0 12px 32px rgba(16, 24, 40, 0.12);

    --sidebar-w: 260px;

    /*
      Text auf einer Vollfarbflaeche (Primaerknopf, aktive Pille, Signal-
      knoepfe). Im hellen Schema ist das Weiss, im dunklen sind --primary,
      --success und --danger selbst aufgehellt - dort traegt die Flaeche
      dunklen Text. Ein festes "white" ergaebe im Dunkeln Hellgrau auf
      Hellblau.
    */
    --auf-primary: #fff;
    --auf-signal: #fff;

    /*
      Toene, die vorher als feste Hex-Werte quer durch dieses Stylesheet
      standen. Ihre Hellwerte sind genau die alten - die Umstellung aendert
      am hellen Schema nichts. Gebraucht werden sie fuer das dunkle: eine
      hellgraue Zeilenhinterlegung mit hellem Text darauf ist dort nicht
      blass, sondern unlesbar. Aufgefallen ist das an der ausgewaehlten
      Zeile der Sichtung.
    */
    --flaeche-zart: #f9fafb;      /* Tabellenkopf, Zeile unter dem Zeiger */
    --flaeche-grau: #f3f4f6;      /* Knopf unter dem Zeiger, Listeneintrag */
    --flaeche-balken: #e5e7eb;    /* Grund eines Fortschrittsbalkens */

    --tint-blau: #dbeafe;         /* Zaehler-, Landpille */
    --tint-blau-text: #1e40af;
    --tint-blau-zart: #eff6ff;    /* ausgewaehlte Zeile, Ablagebereich */
    --tint-indigo: #e0e7ff;       /* Tag- und Kategoriebadge */
    --tint-indigo-text: #3730a3;
    --tint-indigo-leise: #6366f1; /* das x am Tag */
    --tint-violett: #ede9fe;      /* Tagpille an der Quellenzeile */
    --tint-violett-text: #5b21b6;
    --tint-tuerkis: #ccfbf1;      /* Themenfilter einer Quelle */
    --tint-tuerkis-text: #115e59;
    --tint-gruen: #bbf7d0;        /* markierte Zeile unter dem Zeiger */
    --erfolg-text: #047857;
    --tabellen-linie: #eee;       /* Zeilentrenner - heller als --border */
    --markiert-karte: #dcfce7;    /* Grund einer markierten Artikelkarte */
}

/*
  Dunkles Schema. Gesetzt wird es von theme.js am <html>, aus gespeicherter
  Wahl oder der Systemeinstellung.

  Umdefiniert werden **beide** Gruppen - auch die gewachsenen Variablen, denn
  an ihnen haengen nav, Seitengrund, Karten, Tabellen und Flash-Meldungen.
  Blieben sie hell, saehe man ein dunkles Dashboard in einem hellen Rahmen.

  Was hier nicht mitgeht: rund sechzig fest eingetragene Farbwerte in
  seitenspezifischen Regeln (Sichtung, Heftplanung, einzelne Badges). Diese
  Seiten sind im Dunkeln benutzbar, aber stellenweise noch hell. Sie in einem
  Zug mit umzustellen haette jede Regel dieses Stylesheets angefasst; sie
  gehoeren einzeln nachgezogen.

  color-scheme ist kein Beiwerk: daran haengen die vom Browser gemalten Teile
  - Bildlaufleisten, Auswahlfelder, Datumsfelder. Ohne die Angabe stehen
  weisse Formularfelder in einer dunklen Seite.
*/
html[data-theme="dark"] {
    color-scheme: dark;

    --bg: #0b0d12;
    --card: #141821;
    --border: #242a36;
    --text: #cdd2dd;
    --text-muted: #8b93a4;
    --primary: #818cf8;
    --primary-hover: #a5b4fc;
    --success: #4ade80;
    --danger: #f87171;
    --badge-ok: rgba(74, 222, 128, 0.16);
    --badge-ok-text: #86efac;
    --badge-blocked: rgba(248, 113, 113, 0.16);
    --badge-blocked-text: #fca5a5;
    --badge-none: rgba(148, 163, 184, 0.14);
    --badge-none-text: #cbd5e1;
    --badge-warn: rgba(251, 191, 36, 0.16);
    --badge-warn-text: #fcd34d;
    --badge-info: rgba(96, 165, 250, 0.16);
    --badge-info-text: #93c5fd;

    --bg-surface-2: #10141c;
    --bg-elevated: #1a1f2b;

    --text-strong: #f4f6fb;
    --text-faint: #626b7d;

    --border-strong: #333b4a;

    --primary-soft: rgba(129, 140, 248, 0.16);
    --ok-soft: rgba(74, 222, 128, 0.16);
    --warn: #fbbf24;
    --warn-soft: rgba(251, 191, 36, 0.16);
    --danger-soft: rgba(248, 113, 113, 0.16);
    --info: #38bdf8;
    --info-soft: rgba(56, 189, 248, 0.16);

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55);

    --auf-primary: #0b0d12;
    --auf-signal: #0b0d12;

    --flaeche-zart: #171c26;
    --flaeche-grau: #1f2532;
    --flaeche-balken: #2b323f;

    /*
      Die Toene sind im Dunkeln durchscheinend statt deckend: sie liegen auf
      Karten und Tabellen mit leicht verschiedenem Grund, und ein fester Ton
      passte immer nur auf einen davon.
    */
    --tint-blau: rgba(96, 165, 250, 0.20);
    --tint-blau-text: #93c5fd;
    --tint-blau-zart: rgba(96, 165, 250, 0.12);
    --tint-indigo: rgba(129, 140, 248, 0.20);
    --tint-indigo-text: #c7d2fe;
    --tint-indigo-leise: #a5b4fc;
    --tint-violett: rgba(167, 139, 250, 0.20);
    --tint-violett-text: #ddd6fe;
    --tint-tuerkis: rgba(45, 212, 191, 0.20);
    --tint-tuerkis-text: #99f6e4;
    --tint-gruen: rgba(74, 222, 128, 0.24);
    --erfolg-text: #6ee7b7;
    --tabellen-linie: #1e242f;
    /* Kraeftiger als der Badge-Ton derselben Farbe: auf dunklem Grund
       verschwindet ein Schleier von 16 Prozent, und markiert waere von
       unmarkiert nicht mehr zu unterscheiden. */
    --markiert-karte: rgba(74, 222, 128, 0.22);
}

/*
  Die Anwendungsleiste (body > nav) nimmt ihren Grund aus --text - im hellen Schema ein
  dunkles Grau, im dunklen aber die Textfarbe selbst und damit fast weiss.
  Sie bekommt deshalb hier ihre eigene Flaeche, statt --text im Dunkeln zu
  verbiegen: an --text haengt jeder Fliesstext der Anwendung.
*/
html[data-theme="dark"] body > nav {
    background: var(--card);
    border-bottom: 1px solid var(--border);
}

html[data-theme="dark"] .nav-links a { color: var(--text-muted); }
html[data-theme="dark"] .nav-links a:hover,
html[data-theme="dark"] .nav-links a.active {
    color: var(--text-strong);
    background: var(--primary-soft);
}
html[data-theme="dark"] .nav-brand { color: var(--text-strong); }

* { box-sizing: border-box; margin: 0; padding: 0; }

/*
  Das hidden-Attribut muss jede display-Regel schlagen.

  Der Browser bringt zwar [hidden] { display: none } mit, aber nur mit der
  Spezifitaet des User-Agent-Stylesheets: jede Klassenregel mit display
  gewinnt dagegen. Elemente wie .sichtung-zeile (grid), .artikel-panel (flex)
  oder .heft-artikel-text (flex) blieben deshalb sichtbar, obwohl das Skript
  sie auf hidden gesetzt hatte - die Live-Suche zeigte die richtige
  Trefferzahl an, filterte aber nichts weg.

  Eine Regel an einer Stelle statt einer je Klasse: sonst faellt der naechste
  Fall wieder auf, und zwar erst im Browser.
*/
[hidden] { display: none !important; }

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    background: var(--bg);
    color: var(--text);
    line-height: 1.5;
}

/* Navigation */
/*
  Die Anwendungsleiste - und ausdruecklich nur sie.

  Der Selektor hiess frueher schlicht `nav`. Das traf jedes <nav> im
  Dokument, und als das Dashboard eine Sidebar mit eigenen
  Navigationsbereichen bekam, holten die sich prompt die Optik der
  Anwendungsleiste: dunkler Grund, weisse Schrift, 1,5rem Innenabstand und
  `display:flex` mit 2rem Abstand. Die Eintraege standen dadurch
  nebeneinander statt untereinander und liefen ueber den Rand ihrer Karte
  hinaus.

  `body > nav` trifft genau das eine Element aus base.html - es ist dort
  direktes Kind von <body>. Jedes <nav> weiter innen gehoert einer Seite und
  bringt seine eigene Gestaltung mit.
*/
body > nav {
    background: var(--text);
    color: white;
    padding: 0.75rem 1.5rem;
    display: flex;
    align-items: center;
    gap: 2rem;
}

.nav-brand { font-weight: 700; font-size: 1.1rem; }
.nav-links { display: flex; gap: 1rem; }
.nav-links a { color: #ccc; text-decoration: none; padding: 0.25rem 0.5rem; border-radius: 4px; }
.nav-links a:hover, .nav-links a.active { color: white; background: rgba(255,255,255,0.15); }

/* Main */
main { max-width: 1400px; margin: 0 auto; padding: 1.5rem; }

h1 { margin-bottom: 1rem; }
h2 { margin: 1.5rem 0 0.75rem; }

/* Flash messages */
.flash { padding: 0.75rem 1rem; border-radius: 6px; margin-bottom: 1rem; }
.flash-success { background: var(--badge-ok); color: var(--badge-ok-text); }
.flash-error { background: var(--badge-blocked); color: var(--badge-blocked-text); }
.flash-info { background: var(--badge-none); color: var(--badge-none-text); }
.flash-warn { background: var(--badge-warn); color: var(--badge-warn-text); }
.flash-info strong { color: var(--text); }

/* Pfad zurueck durch die Einstiegsebenen (Bereiche > Bereich > Liste) */
.breadcrumb { font-size: 0.85rem; color: var(--text-muted); margin-bottom: 0.5rem; }
.breadcrumb a { color: var(--text-muted); }
.breadcrumb a:hover { color: var(--primary); }

/* Stats bar */
.stats-bar {
    display: flex;
    gap: 1.5rem;
    padding: 0.75rem 1rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    margin-bottom: 1rem;
    font-size: 0.9rem;
}

.stats-bar span { color: var(--text-muted); }

/* Filter bar */
.filter-bar {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    margin-bottom: 1rem;
    flex-wrap: wrap;
}

.filter-bar input[type="text"] {
    padding: 0.4rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    min-width: 200px;
}

.filter-bar select {
    padding: 0.4rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 4px;
}

.filter-bar button {
    padding: 0.4rem 1rem;
    background: var(--primary);
    color: var(--auf-primary);
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.filter-bar button:hover { background: var(--primary-hover); }

.filter-form {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    flex-wrap: wrap;
}

.filter-form label { white-space: nowrap; }

.filter-form input[type="date"] {
    padding: 0.4rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.85rem;
}

/* Table */
table {
    width: 100%;
    border-collapse: collapse;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
    font-size: 0.875rem;
}

thead { background: var(--flaeche-zart); }
th { text-align: left; padding: 0.6rem 0.75rem; font-weight: 600; border-bottom: 2px solid var(--border); }

.sort-link { color: var(--text); text-decoration: none; white-space: nowrap; }
.sort-link:hover { color: var(--primary); }
.sort-arrow { font-size: 0.7rem; margin-left: 0.2rem; }
td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--tabellen-linie); }
tr:hover { background: var(--flaeche-zart); }

.row-inactive { opacity: 0.5; }

.group-first td { border-top: 2px solid var(--border); }
.entity-cell { vertical-align: top; font-weight: 600; background: var(--flaeche-zart); }

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

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

/* Badges */
.badge {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    border-radius: 10px;
    font-size: 0.75rem;
    font-weight: 600;
}

.badge-ok { background: var(--badge-ok); color: var(--badge-ok-text); }
.badge-blocked { background: var(--badge-blocked); color: var(--badge-blocked-text); }
.badge-none { background: var(--badge-none); color: var(--badge-none-text); }
.badge-warn { background: var(--badge-warn); color: var(--badge-warn-text); }
.badge-category { background: var(--tint-indigo); color: var(--tint-indigo-text); }
/* Themenfilter einer Site. Eigener Ton, und zwar ein bisher unbenutzter:
   das Badge steht in der Quellenzeile zwischen Status-Badges (die eine
   Stoerung melden) und Tagpillen (die am Unternehmen haengen). Es ist
   weder das eine noch das andere - ein Tagton wuerde genau die
   Verwechslung nahelegen, gegen die der Filter abgegrenzt ist. */
.badge-filter { background: var(--tint-tuerkis); color: var(--tint-tuerkis-text); }

/* Themenfilter einer Quelle: je Begriff eine Pill, dahinter der Knopf zum
   Ergaenzen. Der Knopf erscheint erst beim Ueberfahren der Zeile - dasselbe
   Muster wie die Farbpunkte an einer Kachel; staendig sichtbar waere er in
   294 Zeilen nur Rauschen. */
.filter-pills {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    flex-wrap: wrap;
}

.filter-pills-label { font-size: 0.75rem; color: var(--text-muted); }

.filter-pill { display: inline-flex; align-items: center; gap: 0.25rem; }

.filter-pill-weg {
    border: none;
    background: none;
    padding: 0;
    line-height: 1;
    cursor: pointer;
    color: inherit;
    opacity: 0.6;
    font-size: 0.95em;
}

.filter-pill-weg:hover { opacity: 1; }

.filter-pill-neu {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s;
    padding: 0.1rem 0.4rem;
    font-size: 0.75rem;
}

summary:hover .filter-pill-neu,
tr:hover .filter-pill-neu,
.filter-pills:focus-within .filter-pill-neu { opacity: 1; pointer-events: auto; }

.filter-pill-eingabe {
    width: 12rem;
    padding: 0.1rem 0.35rem;
    font-size: 0.8rem;
}

.filter-pill-fehler {
    font-size: 0.75rem;
    color: var(--badge-blocked-text);
}

/* Buttons */
.btn {
    display: inline-block;
    padding: 0.4rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--card);
    color: var(--text);
    text-decoration: none;
    cursor: pointer;
    font-size: 0.8rem;
}

.btn:hover { background: var(--flaeche-grau); }
.btn-primary { background: var(--primary); color: var(--auf-primary); border-color: var(--primary); }
.btn-primary:hover { background: var(--primary-hover); }
.btn-danger { color: var(--danger); border-color: var(--danger); }
.btn-danger:hover { background: var(--danger); color: var(--auf-signal); }
.btn-success { color: var(--success); border-color: var(--success); }
.btn-success:hover { background: var(--success); color: var(--auf-signal); }
.btn-small { padding: 0.2rem 0.5rem; font-size: 0.75rem; }

.btn-toggle {
    background: none;
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 0.15rem 0.5rem;
    cursor: pointer;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.btn-toggle.active {
    background: var(--badge-ok);
    color: var(--badge-ok-text);
    border-color: var(--success);
}

/* Forms */
.inline-form { display: inline; }

.actions { white-space: nowrap; }
.actions > *, .actions .inline-form { margin-right: 0.25rem; }

.edit-form {
    max-width: 600px;
    background: var(--card);
    padding: 1.5rem;
    border: 1px solid var(--border);
    border-radius: 6px;
}

.edit-form label {
    display: block;
    margin-top: 1rem;
    margin-bottom: 0.25rem;
    font-weight: 600;
    font-size: 0.9rem;
}

.edit-form label:first-child { margin-top: 0; }

.edit-form input[type="text"],
.edit-form input[type="url"],
.edit-form select {
    width: 100%;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.9rem;
}

.edit-form small { display: block; color: var(--text-muted); margin-top: 0.25rem; }

.checkbox-label {
    display: flex !important;
    align-items: center;
    gap: 0.5rem;
    font-weight: normal !important;
    margin-top: 1rem;
}

.form-actions {
    margin-top: 1.5rem;
    display: flex;
    gap: 0.5rem;
}

/* Site details */
.site-details {
    margin-top: 2rem;
    background: var(--card);
    padding: 1.5rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    max-width: 600px;
}

.site-details dl { display: grid; grid-template-columns: 150px 1fr; gap: 0.25rem 1rem; }
.site-details dt { font-weight: 600; color: var(--text-muted); font-size: 0.85rem; }
.site-details dd { font-size: 0.9rem; }

/* View Tabs */
.view-tabs {
    display: flex;
    gap: 0;
    margin-bottom: 1rem;
    border-bottom: 2px solid var(--border);
}

.view-tab {
    padding: 0.5rem 1rem;
    text-decoration: none;
    color: var(--text-muted);
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    font-size: 0.9rem;
}

.view-tab:hover { color: var(--text); }
.view-tab.active {
    color: var(--primary);
    border-bottom-color: var(--primary);
    font-weight: 600;
}

/* Mark-Button (Stern) */
.btn-mark {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.2rem;
    color: var(--text-muted);
    padding: 0;
    line-height: 1;
}

.btn-mark:hover { color: var(--success); }
.btn-mark.active { color: var(--success); font-weight: 700; }

/*
  Kopier-Knopf an einer Artikelzeile (Makro artikel_tabelle).

  Zurueckhaltend wie .btn-mark: er steht in 200 Zeilen und darf die echten
  Links der Zeile nicht entwerten. Die Farben kommen aus den Variablen -
  ein festes Grau waere im dunklen Schema nicht blass, sondern unlesbar.
*/
.btn-kopieren {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1rem;
    color: var(--text-muted);
    padding: 0;
    line-height: 1;
}

.btn-kopieren:hover { color: var(--primary); }
.btn-kopieren.kopiert { color: var(--success); font-weight: 700; }
.btn-kopieren.kopieren-fehler { color: var(--danger); font-weight: 700; }

/* Beispiel-Eingabe auf der Analyse-Seite */
.beispiel-felder {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.5rem 0.75rem;
    align-items: center;
    max-width: 46rem;
    margin-bottom: 0.75rem;
}

.beispiel-felder label { font-size: 0.9rem; }
.beispiel-felder input { width: 100%; }
.beispiel-felder > div { grid-column: 2; }

/* Sperrliste in der Geloescht-Ansicht: zugeklappt, damit sie die
   Artikelliste nicht verdraengt */
.blocklist {
    margin-bottom: 1rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--border);
    border-radius: 4px;
}

.blocklist > summary {
    cursor: pointer;
    font-weight: 600;
}

.blocklist table { margin-top: 0.5rem; }

.row-marked { background: var(--badge-ok); }
.row-marked:hover { background: var(--tint-gruen); }

/* Tags */
.tags-cell {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-items: center;
}

.tag-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    background: var(--tint-indigo);
    color: var(--tint-indigo-text);
    padding: 0.1rem 0.4rem;
    border-radius: 8px;
    font-size: 0.7rem;
    font-weight: 600;
    white-space: nowrap;
}

.tag-remove {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--tint-indigo-leise);
    font-size: 0.8rem;
    padding: 0;
    line-height: 1;
    margin-left: 0.1rem;
}

.tag-remove:hover { color: var(--danger); }

.tag-form {
    display: inline-flex;
    align-items: center;
    gap: 0;
}

.tag-input {
    width: 5rem;
    padding: 0.1rem 0.3rem;
    border: 1px solid var(--border);
    border-radius: 4px 0 0 4px;
    font-size: 0.7rem;
    outline: none;
}

.tag-input:focus { border-color: var(--primary); }

.tag-add-btn {
    background: var(--primary);
    color: var(--auf-primary);
    border: 1px solid var(--primary);
    border-radius: 0 4px 4px 0;
    cursor: pointer;
    font-size: 0.7rem;
    padding: 0.1rem 0.3rem;
    line-height: 1.3;
}

.tag-add-btn:hover { background: var(--primary-hover); }

/* Quick-Add Zone */
.quick-add-zone {
    background: var(--card);
    border: 2px dashed var(--border);
    border-radius: 8px;
    padding: 1rem 1.25rem;
    margin-bottom: 1rem;
    transition: border-color 0.2s, background 0.2s;
}

.quick-add-zone.drag-over {
    border-color: var(--primary);
    background: var(--tint-blau-zart);
}

.quick-add-input {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

.quick-add-input input[type="text"] {
    flex: 1;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.9rem;
}

.quick-add-hint {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-top: 0.35rem;
    text-align: center;
}

.quick-add-preview {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 1.25rem;
    margin-bottom: 1rem;
}

.quick-add-preview h3 { margin-bottom: 0.75rem; }

.quick-add-fields {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem 1rem;
}

.quick-add-fields label {
    display: block;
    font-weight: 600;
    font-size: 0.85rem;
    margin-bottom: 0.2rem;
}

.quick-add-fields input[type="text"],
.quick-add-fields select {
    width: 100%;
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.9rem;
}

/* Stammdaten: der Block unter den Kacheln, der die Rubriken nennt. Kein
   Kachelraster, weil Rubriken hier nicht pflegbar sind - eine Kachel, die
   auf nichts fuehrt, waere eine leere Zusage. */
.stammdaten-hinweis {
    margin-top: 2rem;
    padding: 1rem 1.25rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
}

.stammdaten-hinweis h2 { margin-bottom: 0.5rem; font-size: 1rem; }
.stammdaten-hinweis p { margin-bottom: 0.6rem; }
.stammdaten-hinweis .rubrik-pills { margin-bottom: 0.6rem; }

/* Was es zu dieser Adresse schon gibt: der Block zwischen Ueberschrift und
   Formular des Quick-Add. Ein Hinweiskasten und keine Fehlermeldung - eine
   vorhandene Domain ist kein Fehler, und das Anlegen bleibt erlaubt. Rot
   wird allein die Konfliktzeile (Adresse *und* Thema schon belegt), denn
   genau die lehnt /api/quick-add/confirm ab. */
.qa-vorhandene {
    margin-bottom: 1rem;
    border: 1px solid var(--border);
    border-left: 3px solid var(--warn);
    border-radius: 4px;
    background: var(--flaeche-zart);
    padding: 0.6rem 0.75rem;
}

.qa-vorhanden-gruppe + .qa-vorhanden-gruppe { margin-top: 0.75rem; }

.qa-vorhanden-kopf {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 0.35rem;
}

/* Eine Zeile je Eintrag: Name, Mitte (Thema bzw. Adresse), Status, Knopf.
   Der Knopf steht rechts an der Kante, damit die Zeilen untereinander
   spaltenweise lesbar bleiben. */
.qa-vorhanden-zeile {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0.4rem;
    border-radius: 4px;
    font-size: 0.85rem;
}

.qa-vorhanden-zeile + .qa-vorhanden-zeile {
    border-top: 1px solid var(--tabellen-linie);
}

.qa-vorhanden-name {
    font-weight: 600;
    color: var(--text);
    text-decoration: none;
    flex: 0 0 auto;
    max-width: 40%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Wie .entity-name: Text, der sich erst beim Ueberfahren als Weg zeigt. Ein
   auffaelliger Link waere hier falsch - daneben steht der echte Knopf. */
.qa-vorhanden-name:hover { text-decoration: underline dotted; }

.qa-vorhanden-mitte {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex: 1 1 auto;
    min-width: 0;
}

.qa-vorhanden-url {
    color: var(--text-muted);
    font-size: 0.8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.qa-vorhanden-status {
    display: flex;
    gap: 0.25rem;
    flex: 0 0 auto;
}

/* Dieselbe Adresse mit demselben Thema - der Eintrag, der nicht angelegt
   werden kann. */
.qa-vorhanden-konflikt {
    background: var(--badge-blocked);
    color: var(--badge-blocked-text);
}

.qa-vorhanden-konflikt .qa-vorhanden-name { color: inherit; }

/* Tag-Auswahl im Quick-Add. Spannt ueber beide Spalten des Feldrasters:
   die Tags sind eine Liste, kein Feld, und in halber Breite waeren sie
   zweizeilig pro Eintrag. Die Kaestchen selbst nutzen dieselben Klassen wie
   der Tag-Dialog der Quellenliste (.tag-picker-list / -item / -gruppe),
   damit die Auswahl an beiden Orten gleich aussieht. */
.quick-add-tags {
    grid-column: 1 / -1;
}

/* Die Tags selbst sind anklickbare Pills, keine Kaestchen: dieselbe Optik,
   in der sie danach an der Unternehmenszeile stehen (.tag-pill) und in der
   auch Rubriken und Filter gewaehlt werden. Ein Kaestchenraster war hier
   der Fremdkoerper - es stammte aus dem Tag-Dialog der Quellenliste, wo
   eine feste Rasterbreite den langen Dialog ordnet. */
.quick-add-tag-wahl {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    max-height: 11rem;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 0.5rem 0.6rem;
    background: var(--card);
}

/* Die Art-Ueberschrift bricht die Reihe um, damit Branche und Erzeugnis
   nicht ineinanderlaufen. */
.quick-add-tag-wahl .tag-picker-gruppe {
    flex: 0 0 100%;
    margin: 0.5rem 0 0.1rem;
}

.quick-add-tag-wahl .tag-picker-gruppe:first-child { margin-top: 0; }

/* Crawl-Seite */
.crawl-panel {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 1.25rem;
    margin-bottom: 1.5rem;
}

.crawl-panel h2 { margin: 0 0 0.5rem; font-size: 1.1rem; }

/* Bereiche und Set-Editor sind aufklappbar und starten zugeklappt. Der Kopf
   war ein <h2>; als <summary> muessen Groesse und Gewicht gesetzt werden,
   sonst faellt er auf die Schriftgroesse des Fliesstextes zurueck. Das
   Dreieck ersetzt den Vorgabemarker, damit es in beiden Zustaenden an
   derselben Stelle steht - dasselbe Muster wie beim Quick-Add. */
.crawl-fold > summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 1.1rem;
    font-weight: 600;
    user-select: none;
}

.crawl-fold > summary::-webkit-details-marker { display: none; }

.crawl-fold > summary::before {
    content: '\25B6';
    font-size: 0.6rem;
    color: var(--text-muted);
    transition: transform 0.15s;
}

.crawl-fold[open] > summary::before { transform: rotate(90deg); }
.crawl-fold > summary:hover { color: var(--primary); }
.crawl-fold[open] > summary { margin-bottom: 0.5rem; }

/* Die Anzahl neben dem Titel: zugeklappt ist sie das Einzige, was ueber den
   Inhalt Auskunft gibt. */
.crawl-fold > summary .fold-anzahl {
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--text-muted);
}

.crawl-categories {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.crawl-cat-label {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    cursor: pointer;
    font-size: 0.9rem;
}

.crawl-status-panel {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 1.25rem;
    margin-bottom: 1.5rem;
}

.crawl-status-panel h2 { margin: 0 0 0.75rem; font-size: 1.1rem; }

.crawl-progress {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.crawl-progress-bar {
    flex: 1;
    height: 1.25rem;
    background: var(--flaeche-balken);
    border-radius: 6px;
    overflow: hidden;
}

.crawl-progress-fill {
    height: 100%;
    background: var(--primary);
    border-radius: 6px;
    transition: width 0.3s ease;
}

.crawl-summary {
    margin-top: 1rem;
    padding: 0.75rem 1rem;
    background: var(--badge-ok);
    color: var(--badge-ok-text);
    border-radius: 6px;
}

.crawl-summary h3 { margin: 0 0 0.25rem; font-size: 1rem; }

/* Quellen (aufklappbare Entities) */
.quellen-entity {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    margin-bottom: 0.5rem;
    overflow: hidden;
}

.quellen-entity[open] { margin-bottom: 0.75rem; }

.quellen-summary {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 1rem;
    cursor: pointer;
    font-size: 0.9rem;
    user-select: none;
    list-style: none;
}

.quellen-summary::-webkit-details-marker { display: none; }

.quellen-summary::before {
    content: '\25B6';
    font-size: 0.6rem;
    color: var(--text-muted);
    transition: transform 0.15s;
    flex-shrink: 0;
}

.quellen-entity[open] > .quellen-summary::before { transform: rotate(90deg); }

.quellen-summary:hover { background: var(--flaeche-zart); }

.quellen-name { font-weight: 600; flex-shrink: 0; }
.quellen-count { color: var(--text-muted); font-size: 0.8rem; margin-left: auto; white-space: nowrap; flex-shrink: 0; }
.quellen-edit-btn { margin-left: 0.5rem; }

/* Zaehler in der Quellen-Zeile und in der Sites-Tabelle. Als Pill gestaltet,
   damit erkennbar ist, dass sie klickbar sind.

   Zwei Farben, zwei Aussagen: **blau** ist der Bestand ("hier liegen 21
   Artikel"), **gruen** das Erledigte ("3 davon sind markiert"). Gruen fuer
   beide waere die Auskunft wert, die man sucht: ob hier noch etwas zu tun
   ist. Ohne Artikel bleibt die Pill unauffaellig grau. */
.quellen-articles {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 10px;
    background: var(--tint-blau);
    color: var(--tint-blau-text);
    font-size: 0.75rem;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
    flex-shrink: 0;
    margin-left: 0.5rem;
}
.quellen-articles:hover { text-decoration: underline; }
/* Die markierten Artikel derselben Quelle - dieselbe Pill, andere Farbe. */
.quellen-markiert {
    background: var(--badge-ok);
    color: var(--badge-ok-text);
    margin-left: 0.25rem;
}
.quellen-articles-empty {
    background: var(--badge-none);
    color: var(--badge-none-text);
}

/* Hinweiszeile ueber der Artikelliste, wenn auf eine Quelle gefiltert wird */
.filter-hinweis {
    margin: -0.5rem 0 1rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* Kategorie-Auswahl direkt in der Quellen-Zeile. Bewusst unauffaellig
   gestaltet: sie soll wie ein Badge wirken, bis man sie anfasst. */
.quellen-category {
    font-size: 0.78rem;
    padding: 0.1rem 0.3rem;
    border: 1px solid transparent;
    border-radius: 4px;
    background: var(--badge-none);
    color: var(--badge-none-text);
    cursor: pointer;
    max-width: 12rem;
    transition: border-color 0.15s, background 0.15s;
}

/* Zugewiesene Kategorie farblich wie das bisherige Badge */
.quellen-category:has(option:checked:not([value=""])) {
    background: var(--tint-indigo);
    color: var(--tint-indigo-text);
}

.quellen-category:hover, .quellen-category:focus { border-color: var(--border); }
.quellen-category:disabled { opacity: 0.6; cursor: progress; }
.quellen-category.save-ok { border-color: var(--success); background: var(--badge-ok); color: var(--badge-ok-text); }
.quellen-category.save-error { border-color: var(--danger); background: var(--badge-blocked); color: var(--badge-blocked-text); }

.quellen-sites-table {
    border: none;
    border-radius: 0;
    border-top: 1px solid var(--border);
    margin: 0;
}

.quellen-sites-table thead { background: var(--flaeche-grau); }
.quellen-sites-table th { font-size: 0.8rem; padding: 0.4rem 0.75rem; border-bottom: 1px solid var(--border); }
.quellen-sites-table td { padding: 0.4rem 0.75rem; }

/* Pill-Filter (gespeicherte Filtersets der Quellen-Liste) */
.pill-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin: -0.5rem 0 1rem;
}

.pill-wrap { display: inline-flex; align-items: center; }

.pill {
    display: inline-block;
    padding: 0.2rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--card);
    color: var(--text);
    font-size: 0.8rem;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
}

.pill:hover { border-color: var(--primary); color: var(--primary); }

.pill-active {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--auf-primary);
    font-weight: 600;
}

.pill-active:hover { color: var(--auf-primary); }

/* Vorgabe-Pills sind nicht loeschbar und heben sich dezent ab */
.pill-builtin { background: var(--badge-none); }
.pill-builtin.pill-active { background: var(--primary); }

.pill-add {
    border-style: dashed;
    color: var(--text-muted);
}

/* Loeschbare Pills reservieren rechts Platz, in den der x-Knopf gezogen wird.
   So sitzt er innerhalb des Pills, ohne die Beschriftung zu ueberlappen. */
.pill-wrap:has(.pill-delete) .pill { padding-right: 1.6rem; }

.pill-delete {
    margin-left: -1.5rem;
    width: 1.4rem;
    padding: 0;
    border: none;
    background: none;
    color: var(--text-muted);
    font-size: 0.95rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s;
}

.pill-wrap:hover .pill-delete,
.pill-delete:focus { opacity: 1; pointer-events: auto; }
.pill-delete:hover { color: var(--danger); }
.pill-active + .pill-delete { color: rgba(255, 255, 255, 0.8); }
.pill-active + .pill-delete:hover { color: white; }

/* Inline-Bearbeitung der News-URL (Unternehmenszeile und Sites-Tabelle) */
.news-url-cell { min-width: 0; }
.quellen-sites-table .news-url-cell { min-width: 24rem; }

.news-url-view {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

/* Das hidden-Attribut steuert den Wechsel Anzeige <-> Formular. Ohne diese
   Regel wuerde das display:flex der beiden Bloecke es ueberstimmen. */

/* Lange URLs werden per Ellipsis gekuerzt statt auf feste Zeichenzahl:
   die vollstaendige URL bleibt im title und im href erhalten. */
.news-url-link {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* News-URL in der zugeklappten Unternehmenszeile */
.news-url-summary {
    display: flex;
    align-items: center;
    flex: 0 1 auto;
    min-width: 0;
    max-width: 32rem;
    font-weight: 400;
    font-size: 0.82rem;
}

.news-url-summary .news-url-input { flex-basis: 16rem; }

/* Fehlende News-URL ist eine Pflegeluecke und soll auffallen, nicht
   als unscheinbarer Gedankenstrich untergehen. */
.news-url-missing {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 4px;
    background: var(--badge-warn);
    color: var(--badge-warn-text);
    font-size: 0.75rem;
    font-weight: 600;
}

/* Bearbeiten-Knopf erst beim Ueberfahren der Zeile zeigen */
.news-url-edit { opacity: 0; pointer-events: none; transition: opacity 0.15s; }
.quellen-sites-table tr:hover .news-url-edit,
.quellen-summary:hover .news-url-edit,
.news-url-edit:focus { opacity: 1; pointer-events: auto; }

.news-url-form {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.news-url-input {
    flex: 1 1 20rem;
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.85rem;
}

.news-url-input:focus { outline: none; border-color: var(--primary); }
.news-url-input:disabled { opacity: 0.6; cursor: progress; }

.news-url-error {
    flex: 1 0 100%;
    color: var(--danger);
    font-size: 0.75rem;
}

/* Tags am Unternehmen (Quellen-Liste) */
.entity-tags {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex-wrap: wrap;
    min-width: 0;
}

.tag-pill {
    display: inline-block;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: var(--tint-violett);
    color: var(--tint-violett-text);
    font-size: 0.72rem;
    font-weight: 500;
    white-space: nowrap;
}

.tag-pill-empty {
    background: var(--badge-none);
    color: var(--badge-none-text);
    font-weight: 400;
}

/* Wie der Bearbeiten-Knopf der News-URL: erst beim Ueberfahren sichtbar */
.entity-tags-edit { opacity: 0; pointer-events: none; transition: opacity 0.15s; }
.quellen-summary:hover .entity-tags-edit,
.entity-tags-edit:focus { opacity: 1; pointer-events: auto; }

/* Tag-Auswahl-Dialog */
.tag-picker {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 1.25rem;
    max-width: 34rem;
    width: 90vw;
    color: var(--text);
    background: var(--card);
}

.tag-picker::backdrop { background: rgba(0, 0, 0, 0.35); }
.tag-picker h3 { margin-bottom: 0.75rem; font-size: 1rem; }

.tag-picker-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: 0.25rem 0.75rem;
    max-height: 50vh;
    overflow-y: auto;
    margin-bottom: 0.75rem;
}

.tag-picker-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    padding: 0.15rem 0.25rem;
    border-radius: 4px;
    cursor: pointer;
}

.tag-picker-item:hover { background: var(--flaeche-grau); }

.tag-picker-error {
    color: var(--danger);
    font-size: 0.8rem;
    margin-bottom: 0.5rem;
}

.tag-picker-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Heftplanung: Ausgaben-Uebersicht */
.ausgabe-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 0.75rem;
}

.ausgabe-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 0.85rem 1rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    text-decoration: none;
    color: var(--text);
    transition: border-color 0.15s, box-shadow 0.15s;
}

.ausgabe-card:hover {
    border-color: var(--primary);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

.ausgabe-card strong { font-size: 1.05rem; }
.ausgabe-card-meta { font-size: 0.8rem; color: var(--text-muted); }

/* Die Zahl ist die eigentliche Information der Karte */
.ausgabe-card-count {
    position: absolute;
    top: 0.7rem;
    right: 0.9rem;
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--primary);
    line-height: 1;
}

.ausgabe-card .badge { align-self: flex-start; margin-top: 0.35rem; }

/* Der Arbeitseimer hebt sich ab: hier liegt das, was noch zu tun ist */
.ausgabe-card-offen { border-style: dashed; }
.ausgabe-card-leer .ausgabe-card-count { color: var(--text-muted); font-weight: 400; }

/* Heftplanung: die Rubriken einer Ausgabe als Kacheln nebeneinander.
   Acht Rubriken auf einem Schirm statt acht Abschnitte untereinander - das
   ist die Frage der Seite ("was steht wo") als Bild. */
.heft-rubrik-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr));
    gap: 1rem;
    align-items: start;
    margin-top: 1rem;
}

.heft-rubrik-kachel {
    background: var(--card);
    border: 1px solid var(--border);
    /* Die Rubrikfarbe traegt die Kachel als Kante - dieselbe Farbe wie ihre
       Pille in der Sichtung, damit man die Rubrik wiedererkennt. */
    border-top: 3px solid var(--rubrik-farbe, var(--text-muted));
    border-radius: 6px;
    overflow: hidden;
}

.heft-rubrik-kachel-kopf {
    display: flex;
    align-items: baseline;
    gap: 0.45rem;
    padding: 0.6rem 0.8rem 0.5rem;
    border-bottom: 1px solid var(--border);
}

.heft-rubrik-name { font-weight: 600; font-size: 0.95rem; }

.heft-rubrik-kuerzel {
    padding: 0.05rem 0.4rem;
    border-radius: 4px;
    background: var(--rubrik-farbe, var(--badge-none));
    color: #fff;
    font-size: 0.72rem;
    font-weight: 600;
}

.heft-rubrik-count {
    margin-left: auto;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--rubrik-farbe, var(--text-muted));
}

.heft-rubrik-artikel { list-style: none; margin: 0; padding: 0; }
.heft-rubrik-artikel > li { border-bottom: 1px solid var(--border); }
.heft-rubrik-artikel > li:last-child { border-bottom: none; }

/* Ein Artikel in der Rubrikkachel: Titel in einer Zeile, darunter klein
   Quelle und Datum. Kein eigener Rahmen - die Kachel ist der Rahmen. */
.heft-artikel { padding: 0.4rem 0.8rem; }
.heft-artikel:hover { background: var(--flaeche-zart); }

.heft-artikel-kopf {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    cursor: pointer;
}

/* Abgeschnitten statt umgebrochen: sonst ist jede Zeile unterschiedlich
   hoch und die Kachel nicht mehr als Liste lesbar. Der volle Titel steht im
   title-Attribut und in der aufgeklappten Zeile. */
.heft-artikel-titel {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
    font-size: 0.9rem;
    text-decoration: none;
}

.heft-artikel-titel:hover { text-decoration: underline; }

.heft-artikel-meta {
    display: flex;
    gap: 0.5rem;
    font-size: 0.75rem;
    color: var(--text-muted);
    padding-left: 0.05rem;
}

.heft-artikel-meta .heft-artikel-quelle {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.heft-artikel-datum { margin-left: auto; white-space: nowrap; }

/* Aufgeklappt: der Titel darf dann umbrechen, man will ihn ja ganz lesen. */
.heft-artikel-offen .heft-artikel-titel {
    white-space: normal;
    overflow: visible;
}

.heft-artikel-text {
    margin: 0.3rem 0 0.5rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.heft-artikel-zuordnung {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.heft-artikel-entfernen { margin-left: auto; }

.heft-artikel-verschoben {
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: var(--badge-warn);
    color: var(--badge-warn-text);
    font-size: 0.7rem;
}

/* Bereichskacheln (Startseite Quellen) --------------------------------------
   Jede Kachel traegt eine Farbklasse farbe-<name>. Die Toene stehen nur hier;
   in der Datenbank steht bloss der Name, damit sich die Palette an einer
   Stelle aendern laesst. Die Farbe traegt einen kraeftigen Balken und einen
   hellen Grund - die Kachel bleibt lesbar, die Zuordnung sichtbar. */
.farbe-blau    { --bereich: #2563eb; --bereich-hell: #eff6ff; }
.farbe-gruen   { --bereich: #16a34a; --bereich-hell: #f0fdf4; }
.farbe-orange  { --bereich: #ea580c; --bereich-hell: #fff7ed; }
.farbe-violett { --bereich: #7c3aed; --bereich-hell: #f5f3ff; }
.farbe-rot     { --bereich: #dc2626; --bereich-hell: #fef2f2; }
.farbe-tuerkis { --bereich: #0d9488; --bereich-hell: #f0fdfa; }
.farbe-gelb    { --bereich: #ca8a04; --bereich-hell: #fefce8; }
.farbe-grau    { --bereich: #6b7280; --bereich-hell: #f9fafb; }

/*
  Dieselben acht Farben im dunklen Schema. --bereich wird aufgehellt, damit
  es auf dunklem Grund traegt; --bereich-hell ist die zugehoerige Flaeche und
  muss dunkel werden - die hellen Toene oben waeren sonst leuchtende Bloecke
  in einer dunklen Seite.

  Die Farbnamen bleiben, was sie sind: sie stehen als Wert in der Datenbank
  (bereiche.farbe, kachel_farben) und beschreiben die Wahl, nicht den
  Zahlenwert. Genau deshalb laesst sich der hier ohne Datenaenderung
  austauschen.
*/
html[data-theme="dark"] .farbe-blau    { --bereich: #60a5fa; --bereich-hell: #16233c; }
html[data-theme="dark"] .farbe-gruen   { --bereich: #4ade80; --bereich-hell: #12281c; }
html[data-theme="dark"] .farbe-orange  { --bereich: #fb923c; --bereich-hell: #2e1c0e; }
html[data-theme="dark"] .farbe-violett { --bereich: #a78bfa; --bereich-hell: #221a3a; }
html[data-theme="dark"] .farbe-rot     { --bereich: #f87171; --bereich-hell: #2e1517; }
html[data-theme="dark"] .farbe-tuerkis { --bereich: #2dd4bf; --bereich-hell: #0e2726; }
html[data-theme="dark"] .farbe-gelb    { --bereich: #facc15; --bereich-hell: #2a2410; }
html[data-theme="dark"] .farbe-grau    { --bereich: #9ca3af; --bereich-hell: #1a1e26; }

.bereich-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
    gap: 0.75rem;
}

.bereich-kachel {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border);
    border-left: 5px solid var(--bereich, var(--border));
    border-radius: 6px;
    background: var(--bereich-hell, var(--card));
    overflow: hidden;
    transition: box-shadow 0.15s, transform 0.15s;
}

.bereich-kachel:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); }

.bereich-kachel-flaeche {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.8rem 0.9rem 0.6rem;
    text-decoration: none;
    color: var(--text);
    flex: 1;
}

.bereich-name {
    font-size: 1.02rem;
    font-weight: 700;
    color: var(--bereich, var(--text));
}

.bereich-kriterium {
    font-size: 0.78rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bereich-zahlen { margin-top: 0.4rem; font-size: 0.85rem; }
.bereich-zahlen strong { font-size: 1.25rem; color: var(--bereich, var(--text)); }
.bereich-zahlen-neben { color: var(--text-muted); font-size: 0.78rem; }
/* Zweizeilig, seit neben dem Crawl auch Artikeldatum und Fundzeitpunkt
   darin stehen. */
.bereich-frische { font-size: 0.75rem; color: var(--text-muted); margin-top: 0.15rem;
                  line-height: 1.45; }

.bereich-aktionen {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.9rem 0.6rem;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
}

/* Farbwahl: erst beim Ueberfahren der Kachel sichtbar, damit die Kachel
   ruhig bleibt und die Zahl im Vordergrund steht. */
.bereich-farbwahl {
    display: flex;
    gap: 0.2rem;
    margin-left: auto;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s;
}

.bereich-kachel:hover .bereich-farbwahl,
.bereich-farbwahl:focus-within { opacity: 1; pointer-events: auto; }

.farbpunkt {
    width: 0.85rem;
    height: 0.85rem;
    padding: 0;
    border: 1px solid rgba(0, 0, 0, 0.15);
    border-radius: 50%;
    background: var(--bereich);
    cursor: pointer;
}

.farbpunkt-aktiv { box-shadow: 0 0 0 2px var(--card), 0 0 0 3px var(--bereich); }

.bereich-kachel-rest { border-left-style: dashed; }

/* Die gerade gewaehlte Kachel der Technik-Uebersicht. Ein Ring statt einer
   anderen Fuellung: die Fuellfarbe traegt dort schon eine Bedeutung. */
.bereich-kachel-aktiv { box-shadow: 0 0 0 2px var(--primary); }

.bereich-neu {
    margin-top: 1.5rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0.6rem 0.9rem;
}

.bereich-neu summary { cursor: pointer; font-weight: 600; font-size: 0.9rem; }
.bereich-neu-inhalt { margin-top: 0.75rem; }
.bereich-neu .filter-bar { margin-bottom: 0; }

/* Pills der Listenseite in ihrer Bereichsfarbe */
.pill.farbe-blau:not(.pill-active),
.pill.farbe-gruen:not(.pill-active),
.pill.farbe-orange:not(.pill-active),
.pill.farbe-violett:not(.pill-active),
.pill.farbe-rot:not(.pill-active),
.pill.farbe-tuerkis:not(.pill-active),
.pill.farbe-gelb:not(.pill-active) {
    border-color: var(--bereich);
    color: var(--bereich);
}

.pill.pill-active { background: var(--bereich, var(--primary)); border-color: var(--bereich, var(--primary)); }

/* Empty state */
.empty-state {
    text-align: center;
    padding: 3rem;
    color: var(--text-muted);
}

/* ------------------------------------------------------------- Diagnose --- */

.diagnose-gruppe {
    margin-top: 2rem;
}

.diagnose-gruppe-titel {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.15rem;
    /* War frueher ein <h2>; als <summary> muessen Groesse und Gewicht
       ausdruecklich gesetzt werden. */
    font-size: 1.3rem;
    font-weight: 600;
}

/* Ein <summary> mit display:flex zeigt keinen Marker an - deshalb ein
   eigenes Dreieck, das sich beim Aufklappen dreht. */
.diagnose-gruppe-titel::before {
    content: "";
    flex: none;
    width: 0;
    height: 0;
    border-left: 0.42rem solid var(--text-muted);
    border-top: 0.3rem solid transparent;
    border-bottom: 0.3rem solid transparent;
    transition: transform 0.15s ease;
}

.diagnose-gruppe[open] > .diagnose-gruppe-titel::before {
    transform: rotate(90deg);
}

/* "Erneut pruefen" je Ursachengruppe: rechts im Kopf, damit es die Zeile
   nicht vom Namen der Ursache und ihrer Anzahl wegdraengt. Kleinere Schrift,
   weil der Kopf selbst 1.3rem hat und der Knopf ihn sonst aufblaeht. */
.diagnose-gruppe-pruefen {
    margin-left: auto;
    font-size: 0.75rem;
    font-weight: 400;
    flex: none;
}

.diagnose-gruppe-text {
    margin: 0 0 0.6rem 0;
    font-size: 0.85rem;
}

.diagnose-tabelle {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}

.diagnose-tabelle th,
.diagnose-tabelle td {
    text-align: left;
    padding: 0.55rem 0.6rem;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
}

.diagnose-tabelle th {
    background: var(--flaeche-zart);
    font-weight: 600;
    font-size: 0.8rem;
}

.diagnose-url a {
    word-break: break-all;
}

/* Selektor-Kandidat samt Titelvorschau. Ohne die Vorschau laesst sich nicht
   beurteilen, ob der Selektor Artikel oder Navigation trifft. */
.diagnose-kandidat {
    display: block;
    padding: 0.4rem 0.5rem;
    margin-bottom: 0.35rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    cursor: pointer;
}

.diagnose-kandidat:hover {
    background: var(--flaeche-zart);
}

.diagnose-kandidat code {
    font-size: 0.82rem;
}

.diagnose-titel {
    margin: 0.3rem 0 0 1.4rem;
    padding: 0;
    font-size: 0.78rem;
    color: var(--text-muted);
}

.diagnose-titel li {
    margin-bottom: 0.1rem;
}

.diagnose-angewendet {
    margin-top: 0.4rem;
    font-size: 0.8rem;
    color: var(--erfolg-text);
}

/* Diagnose-Gruppen sind alle aufklappbar; erledigte starten zugeklappt */
.diagnose-gruppe > summary {
    cursor: pointer;
    list-style: none;          /* eigenes Dreieck, siehe ::before oben */
    padding: 0.15rem 0;
}

.diagnose-gruppe > summary::-webkit-details-marker { display: none; }
.diagnose-gruppe > summary:hover { color: var(--primary); }


/* Fusszeile: nennt auf jeder Seite, was nach einer Aenderung zu tun ist */
.app-footer {
    margin-top: 2.5rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--border);
    font-size: 0.75rem;
    color: var(--text-muted);
}
.app-footer strong { color: var(--text); font-weight: 600; }
/* Die Fusszeile ist eine Zeile Fliesstext. Ein <form> ist von sich aus ein
   Block und riss den Abmelden-Knopf samt Trennpunkt in eine eigene Zeile. */
.abmelden-form { display: inline; }

/* Neustart des Servers: Overlay waehrend der Prozess wechselt */
.neustart-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
}
.neustart-box {
    background: var(--card);
    border-radius: 8px;
    padding: 1.5rem 2rem;
    max-width: 30rem;
    text-align: center;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
}
.neustart-text { font-weight: 600; margin-bottom: 0.4rem; }
.neustart-hinweis { font-size: 0.85rem; color: var(--text-muted); }
.app-footer .server-neustart { margin-left: 0.25rem; }
.flash-warn .server-neustart { margin-left: 0.5rem; }

/* Aktionsleiste einer Sammlungsansicht (Kacheln und Liste): der Knopf, der
   die gerade gezeigte Menge als Ganzes crawlt */
.sammlung-aktionen {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

/* Sperrseite bei veraltetem Servercode */
.neustart-seite {
    max-width: 42rem;
    margin: 3rem auto;
    background: var(--card);
    border: 1px solid var(--border);
    border-left: 4px solid var(--badge-warn-text);
    border-radius: 8px;
    padding: 1.5rem 2rem;
}
.neustart-seite p { margin-bottom: 0.75rem; }
.neustart-seite-aktionen {
    display: flex;
    gap: 0.5rem;
    margin: 1.25rem 0 1rem;
}

/* Gruppentitel in der Tag-Auswahl (eine Zeile je Tag-Art) */
.tag-picker-gruppe {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    margin: 0.6rem 0 0.15rem;
    border-bottom: 1px solid var(--border);
    padding-bottom: 0.15rem;
}
.tag-picker-gruppe:first-child { margin-top: 0; }

/* Ueberschrift eines Kachelblocks (eine je Tag-Art) */
.kachel-block-titel {
    font-size: 1rem;
    margin: 1.25rem 0 0.5rem;
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}
.kachel-block-titel .text-muted { font-size: 0.8rem; font-weight: 400; }

/* Sammelschalter ueber einer gruppierten Liste */
.listen-steuerung {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 1.25rem 0 0.5rem;
}
.listen-steuerung .text-muted { font-size: 0.85rem; }

/* Heft-Rubriken sind aufklappbar; der Kopf ist jetzt ein <summary>.
   Wie bei den Diagnose-Gruppen: display:flex unterdrueckt den eigenen
   Marker, deshalb ein selbstgezeichnetes Dreieck. */
.heft-rubrik > summary { cursor: pointer; list-style: none; }
/* War ein <h2>; als <summary> muss das Schriftgewicht gesetzt werden. */
.heft-rubrik-kopf { font-weight: 600; }
.heft-rubrik > summary::-webkit-details-marker { display: none; }
.heft-rubrik > summary:hover { color: var(--primary); }
.heft-rubrik-kopf::before {
    content: "";
    flex: none;
    width: 0;
    height: 0;
    border-left: 0.42rem solid var(--text-muted);
    border-top: 0.3rem solid transparent;
    border-bottom: 0.3rem solid transparent;
    transition: transform 0.15s ease;
}
.heft-rubrik[open] > .heft-rubrik-kopf::before { transform: rotate(90deg); }

/* Landkuerzel in der zugeklappten Unternehmenszeile. Bewusst schmal und
   monospace, damit die Kuerzel untereinander in einer Flucht stehen.

   Eine Farbe fuer alle Laender: die Farbe kennzeichnet die Pill-Art, nicht
   das einzelne Land. Blau, weil die Tag-Pills daneben violett sind und
   beide auf einen Blick unterscheidbar bleiben sollen. */
.land-pill {
    flex: none;
    /* Ist ein <button>: Browser-Vorgaben abraeumen, Aussehen bleibt Pill */
    border: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    cursor: pointer;
    padding: 0.05rem 0.4rem;
    border-radius: 4px;
    background: var(--tint-blau);
    color: var(--tint-blau-text);
    font-size: 0.7rem;
    font-weight: 600;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    letter-spacing: 0.03em;
}
/* Fehlender Eintrag: sichtbar, aber zurueckhaltend - es sind viele Zeilen */
.land-pill-leer {
    background: transparent;
    color: var(--border);
    border: 1px dashed var(--border);
}

/* Die Laender eines Unternehmens stehen als mehrere Pills beieinander -
   Konzerne arbeiten ueber Laendergrenzen hinweg. Der Behaelter ist das
   Flex-Kind der Zeile, nicht die einzelne Pill; ohne ihn rissen zwei Laender
   die Zeile auseinander. */
.entity-laender {
    display: flex;
    align-items: center;
    gap: 0.2rem;
    flex: none;
    flex-wrap: wrap;
}

/* Laender als Kaestchen in den Formularen (/entities/new, /entities/<id>).
   Dieselbe Rasterbreite wie der Dialog, damit die Namen in einer Flucht
   stehen; scrollbar, weil 36 Laender keine Seite fuellen sollen. */
.land-kaestchen {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
    gap: 0.1rem 0.5rem;
    max-height: 11rem;
    overflow-y: auto;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--card);
}

.land-kaestchen-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
    font-size: 0.85rem;
    padding: 0.1rem 0.15rem;
    border-radius: 4px;
    cursor: pointer;
}

/* Die Stammdatenzeile gibt ihren Eingabefeldern 12rem Mindestbreite - das
   trifft sonst auch das Haekchen: es wuerde 12rem breit, schoebe seinen
   Namen weit nach rechts und das Raster ueber die Seite hinaus. */
.land-kaestchen input[type="checkbox"] {
    flex: none;
    min-width: 0;
    width: auto;
    padding: 0;
}

.land-kaestchen-item:hover { background: var(--flaeche-grau); }

/* Das Kaestchenraster braucht die ganze Breite der Stammdatenzeile - als
   schmales Feld neben Name und Kategorie waere es eine einspaltige Liste. */
.entity-stammdaten-feld-breit { flex: 1 1 100%; }

/* Landauswahl hinter der Pill. Erbt Rahmen und Backdrop von .tag-picker;
   die Liste ist einspaltig, weil die Eintraege ganze Laendernamen tragen. */
.land-picker-suche {
    width: 100%;
    padding: 0.4rem 0.6rem;
    margin-bottom: 0.6rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.9rem;
}

.land-picker-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
    gap: 0.15rem 0.5rem;
    max-height: 50vh;
    overflow-y: auto;
    margin-bottom: 0.75rem;
}

.land-picker-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.25rem 0.4rem;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: var(--text);
    font-size: 0.85rem;
    text-align: left;
    cursor: pointer;
}

.land-picker-item:hover { background: var(--flaeche-grau); }
.land-picker-item-aktiv { background: var(--tint-blau); font-weight: 600; }

/* Kuerzel in einer festen Breite, damit die Namen in einer Flucht stehen */
.land-picker-kuerzel {
    flex: none;
    width: 1.9rem;
    color: var(--text-muted);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.72rem;
    font-weight: 600;
}

/* --- Artikelkacheln (Gruppierung nach Bereich, Kategorie oder Land) ------
   Die Kacheln selbst nutzen .bereich-grid / .bereich-kachel wie die
   Quellen-Startseite: es ist derselbe Schritt, nur mit Artikeln statt
   Quellen dahinter. Hier steht nur, was davon abweicht. */

/* In der Artikelansicht sind die Kacheln reine Einstiege ohne Aktionsleiste;
   die Flaeche darf deshalb bis zum unteren Rand gehen. */
.bereich-grid .bereich-kachel-flaeche:only-child { padding-bottom: 0.9rem; }

/* Nebenangabe in einer Ueberschrift (z.B. "5 Unternehmen") */
.h1-neben {
    font-size: 0.85rem;
    font-weight: 400;
    color: var(--text-muted);
    margin-left: 0.5rem;
}

/* Letzte Diagnoselaeufe (Diagnose-Seite) */
.diagnose-laeufe {
    list-style: none;
    margin: 0 0 0.6rem;
    padding: 0;
    font-size: 0.85rem;
}

.diagnose-laeufe li {
    padding: 0.2rem 0;
    border-bottom: 1px solid var(--border);
}

.diagnose-laeufe li:last-child { border-bottom: none; }

/* Unternehmensname als Klickflaeche (Makro entity_name, entity-edit.js).
   Sieht aus wie Text - erst beim Ueberfahren zeigt die gepunktete Linie, dass
   dahinter etwas steckt. Ein auffaelliger Link waere hier falsch: der Name
   steht in Tabellen, Kacheln und Zeilen dicht neben echten Links. */
.entity-name,
.entity-link {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
    border-bottom: 1px dotted transparent;
}

/* Der Name bleibt optisch Text - er steht dicht neben echten Links
   (News-URL, Artikel), und ein auffaelliger Link entwertete die. */
.entity-link { text-decoration: none; }

.entity-name:hover,
.entity-name:focus-visible,
.entity-link:hover,
.entity-link:focus-visible {
    color: var(--primary);
    border-bottom-color: currentColor;
}

/* Bearbeiten-Dialog: schmaler als die Tag-Auswahl, es sind drei Felder */
.entity-picker { max-width: 26rem; }

.entity-picker-form { display: flex; flex-direction: column; gap: 0.15rem; }
.entity-picker-form label { font-size: 0.8rem; color: var(--text-muted); margin-top: 0.5rem; }
.entity-picker-form input,
.entity-picker-form select {
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.9rem;
    background: var(--card);
    color: var(--text);
}
.entity-picker-form .tag-picker-actions { margin-top: 0.9rem; }

/* Abgelehnter Diagnose-Vorschlag: wie der Uebernommen-Vermerk, aber grau -
   es wurde nichts geaendert, nur entschieden. */
.diagnose-abgelehnt {
    margin-top: 0.4rem;
    padding: 0.25rem 0.45rem;
    border-radius: 4px;
    background: var(--badge-none);
    color: var(--badge-none-text);
    font-size: 0.78rem;
}

/* "N neu" auf einer Unternehmenskachel: beim letzten Crawl dazugekommen.
   Gruen und gefuellt, weil es die einzige Zahl auf der Kachel ist, die zum
   Hinsehen auffordert - alles andere ist Bestand. */
.kachel-neu {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: var(--badge-ok);
    color: var(--badge-ok-text);
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
}

/* ---------------------------------------------------- Artikel-Panel ---
   Drawer am rechten Rand, den eine Unternehmenskachel oeffnet. Feste
   Position statt Spalte im Layout: die Kachelansicht soll unveraendert
   stehenbleiben, das Panel legt sich darueber. */
.artikel-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(58rem, 92vw);
    z-index: 60;
    display: flex;
    flex-direction: column;
    background: var(--card);
    border-left: 1px solid var(--border);
    box-shadow: -4px 0 20px rgba(0, 0, 0, 0.12);
    /* Ausgefahren wartet es rechts ausserhalb des Sichtfelds */
    transform: translateX(100%);
    transition: transform 0.18s ease;
}

.artikel-panel.offen { transform: translateX(0); }

.artikel-panel-kopf {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.7rem 0.9rem;
    border-bottom: 1px solid var(--border);
}

.artikel-panel-kopf h2 {
    margin: 0;
    font-size: 1.05rem;
    /* Nimmt den Platz bis zu den Knoepfen ein und kuerzt lange Namen, statt
       den Schliessen-Knopf aus dem Panel zu schieben. */
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.artikel-panel-schliessen {
    flex: none;
    background: none;
    border: none;
    font-size: 1.5rem;
    line-height: 1;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0 0.2rem;
}

.artikel-panel-schliessen:hover { color: var(--danger); }

.artikel-panel-inhalt {
    flex: 1;
    overflow-y: auto;
    padding: 0.8rem 0.9rem 1.5rem;
}

/* Die Tabelle im Panel ist schmaler als auf der Seite - die Spaltenbreiten
   der Seitenansicht wuerden sie sonst ueber den Rand schieben. */
.artikel-panel-inhalt table { width: 100%; font-size: 0.85rem; }
.artikel-panel-inhalt table th,
.artikel-panel-inhalt table td { width: auto; }

.panel-zahlen {
    margin: 0 0 0.7rem;
    font-size: 0.8rem;
    color: var(--text-muted);
    line-height: 1.5;
}

.panel-zahlen strong { font-size: 1.1rem; color: var(--text); }

.panel-hintergrund {
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgba(0, 0, 0, 0.25);
}

/* Waehrend das Panel offen ist, scrollt der Inhalt darin - nicht die Seite
   dahinter, die sonst unter dem Drawer wegwandert. */
body.panel-offen { overflow: hidden; }

@media (max-width: 640px) {
    .artikel-panel { width: 100vw; }
}

/* Aktionszeile ueber der Artikeltabelle (Crawl-Knopf der Detailansicht) */
.panel-aktionen { margin: 0 0 0.8rem; }

/* Rubrik- und Ausgabe-Zuordnung als Pills (Heftansicht). Nutzt die
   Pill-Optik der Quellenliste; ausgegraut, solange gespeichert wird. */
.rubrik-pills,
.ausgabe-pills {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    flex-wrap: wrap;
}

/* Die Ausgabe-Reihe steht etwas ab: zwei Reihen nebeneinander verschwimmen
   sonst zu einer einzigen langen Kette. */
.ausgabe-pills {
    margin-left: 0.5rem;
    padding-left: 0.6rem;
    border-left: 1px solid var(--border);
}

.rubrik-pill,
.ausgabe-pill { cursor: pointer; }

/* Rubrik-Kuerzel sind kurz und stehen zu zehnt nebeneinander - kleiner
   gesetzt, damit die Zeile nicht von ihnen beherrscht wird. */
.rubrik-pill { font-size: 0.7rem; padding: 0.05rem 0.35rem; }

.pills-speichert { opacity: 0.6; pointer-events: none; }

/* Kompakte Artikelzeile: Titel kuerzen statt umbrechen, damit jede Zeile
   gleich hoch bleibt und die Liste als Liste lesbar ist. */
.heft-artikel-kopf { flex-wrap: nowrap; }

.heft-artikel-titel {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.heft-artikel-quelle,
.heft-artikel-datum { flex: none; white-space: nowrap; }
.heft-artikel-datum { margin-left: 0; }

/* Knopf fuer die Zusammenfassung. Traegt hidden im HTML und wird erst von
   heft-kompakt.js sichtbar gemacht. */
/* Chevron am Zeilenende: zeigt, dass die Zeile mehr hergibt. Klickbar ist
   die ganze Kopfzeile - der Knopf ist die sichtbare Zusage dafuer. */
.heft-artikel-mehr {
    flex: none;
    background: none;
    border: none;
    padding: 0 0.2rem;
    font-size: 0.8rem;
    line-height: 1;
    color: var(--text-muted);
    cursor: pointer;
    transition: transform 0.15s ease;
}

.heft-artikel-kopf:hover .heft-artikel-mehr { color: var(--primary); }

/* Aufgeklappte Zeile: gedrehter Pfeil und ein ruhiger Hintergrund, damit
   erkennbar bleibt, welche Zeile gerade offen steht. */
.heft-artikel-offen .heft-artikel-mehr { transform: rotate(180deg); }
.heft-artikel-offen { background: var(--flaeche-zart); }

/* Verteilung der Rubriken im Kopf - die Antwort auf "was steht wo",
   noch vor der ersten Gruppe. */
.heft-verteilung {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin: 0.6rem 0 0.9rem;
}

.heft-verteilung-marke {
    display: inline-flex;
    align-items: baseline;
    gap: 0.3rem;
    padding: 0.2rem 0.55rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--card);
    text-decoration: none;
    color: var(--text);
}

.heft-verteilung-marke:hover { border-color: var(--primary); text-decoration: none; }

.heft-verteilung-kuerzel {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.heft-verteilung-zahl { font-weight: 600; font-size: 0.95rem; }

@media (max-width: 720px) {
    /* Auf schmalen Schirmen darf die Kopfzeile wieder umbrechen - sonst
       bleibt vom Titel nichts uebrig. */
    .heft-artikel-kopf { flex-wrap: wrap; }
    .heft-artikel-titel { white-space: normal; }
}

/* Bereichskachel mit fester Auswahl: der Hinweis muss auffallen, weil er
   erklaert, warum die Zahl nicht mitwaechst. */
.bereich-kriterium.bereich-fest {
    color: var(--badge-warn-text, #92400e);
    font-weight: 500;
}

/* News-Status je Site (Unternehmens-Detailseite). Wie die Kategorie-Auswahl
   der Quellenliste: kurze farbige Rueckmeldung beim Speichern. */
.site-status {
    padding: 0.15rem 0.3rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.78rem;
    max-width: 13rem;
}

.site-status:disabled { opacity: 0.6; cursor: progress; }
.site-status.save-ok { border-color: var(--success); background: var(--badge-ok); color: var(--badge-ok-text); }
.site-status.save-error { border-color: var(--danger); background: var(--badge-blocked); color: var(--badge-blocked-text); }

/* Stammdaten eines Unternehmens auf seiner Detailseite. Eine Zeile, weil es
   drei kurze Felder sind - ein gestapeltes Formular schoebe die Sites, um die
   es auf der Seite eigentlich geht, unter den Falz. */
.entity-stammdaten {
    display: flex;
    align-items: flex-end;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
    padding: 0.7rem 0.9rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
}

.entity-stammdaten-feld { display: flex; flex-direction: column; gap: 0.15rem; }
.entity-stammdaten-feld label { font-size: 0.75rem; color: var(--text-muted); }

.entity-stammdaten input,
.entity-stammdaten select {
    padding: 0.3rem 0.45rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.9rem;
    min-width: 12rem;
}


/* ------------------------------------------------------------ Dashboard ---
   Die Startseite benutzt sonst durchweg vorhandene Bausteine (stats-bar,
   bereich-grid, artikel_tabelle). Eigen sind nur die Suchzeile und die
   Ueberschriftzeile ihrer Bloecke. */

.dashboard-suche {
    display: flex;
    gap: 0.5rem;
    margin: 1rem 0 1.5rem;
}

.dashboard-suche input[type="search"] {
    flex: 1;
    padding: 0.6rem 0.8rem;
    font-size: 1rem;
    border: 1px solid var(--border);
    border-radius: 4px;
}

.dashboard-block { margin-top: 2rem; }

/* Ueberschrift und Einordnung nebeneinander: die Zeile soll sagen, was der
   Block zeigt, ohne einen eigenen Absatz darunter zu brauchen. */
.dashboard-block-kopf {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.dashboard-block-kopf h2 { margin: 0; }
.dashboard-block-kopf .text-muted { font-size: 0.85rem; }


/* -------------------------------------------------------------- Sichtung ---
   Die Arbeitsansicht: Kacheln als Einstieg, darunter eine dichte Liste mit
   der Rubrikspalte rechts an der Zeile. Dichter als die uebrigen Listen -
   hier werden zweihundert Zeilen am Stueck durchgesehen, und jede Zeile
   Hoehe kostet einen Bildschirm mehr Scrollen. */

.sichtung-kopf {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.4rem 1.2rem;
    margin-bottom: 0.35rem;
}

.sichtung-kopf h1 { margin: 0; }

.sichtung-zaehler-block { display: inline-flex; align-items: baseline; gap: 0.4rem; }

/* Die offene Menge ist die Zahl, nach der die Seite bedient wird - deshalb
   gross und in Signalfarbe, bis nichts mehr offen ist. */
.sichtung-zaehler {
    font-size: 1.8rem;
    font-weight: 600;
    line-height: 1;
    color: var(--danger);
    font-variant-numeric: tabular-nums;
}
.sichtung-zaehler.leer { color: var(--success); }

/* Live-Suche zwischen Kacheln und Liste. Bewusst breit und gross: sie ist
   der Einstieg in eine Liste von bis zu 200 Zeilen, kein Nebenschalter im
   Seitenkopf. */
.sichtung-suchleiste {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    flex-wrap: wrap;
    margin: 1.2rem 0 0.8rem;
}

.sichtung-suche-feld {
    flex: 1;
    min-width: 18rem;
    max-width: 34rem;
    padding: 0.55rem 0.8rem;
    border: 2px solid var(--border);
    border-radius: 6px;
    font-size: 1.05rem;
    background: var(--card);
    color: var(--text);
}

.sichtung-suche-feld::placeholder { color: var(--text-muted); }

.sichtung-suche-feld:focus {
    border-color: var(--primary);
    outline: none;
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}

.sichtung-suche-treffer {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
}

.sichtung-suche-treffer.leer { color: var(--danger); }

.sichtung-suche-hinweis { font-size: 0.78rem; }

.sichtung-suche-hinweis kbd {
    padding: 0.05rem 0.3rem;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: var(--badge-none);
    font-family: inherit;
    font-size: 0.95em;
}

/* Steht im Kopf der Heftspalte, nicht mehr im Seitenkopf: das gewaehlte
   Heft ist die Ueberschrift der rechten Haelfte und nicht der Seite. */
.sichtung-heftwahl {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}
.sichtung-heftwahl select {
    font: inherit;
    padding: 0.3rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--card);
    color: var(--text);
}

.sichtung-lauf { font-size: 0.82rem; margin-bottom: 0.9rem; }
.sichtung-hinweis { font-size: 0.82rem; margin: 0.9rem 0 0.3rem; }

/* ----------------------------------------------------- Kacheln ------------ */

.sichtung-kacheln {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: 0.5rem;
    margin-bottom: 1.25rem;
}

.sichtung-kachel-huelle { position: relative; }

.sichtung-kachel {
    position: relative;
    display: block;
    height: 100%;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 0.7rem 0.75rem 0.6rem 0.95rem;
    text-decoration: none;
    color: var(--text);
}
/* Farbstreifen links statt farbiger Flaeche: die Kacheln stehen dicht
   beieinander, und acht farbige Flaechen nebeneinander waeren Unruhe. */
.sichtung-kachel::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--bereich, var(--border));
    border-radius: 4px 0 0 4px;
}
.sichtung-kachel:hover { border-color: var(--bereich, var(--primary)); }
.sichtung-kachel.kachel-gewaehlt {
    border-color: var(--text);
    box-shadow: inset 0 0 0 1px var(--text);
}
.sichtung-kachel-rest::before { background: var(--text-muted); }

.sichtung-kachel-name {
    display: block;
    font-size: 0.82rem;
    font-weight: 600;
    margin-bottom: 0.45rem;
}

/* Die Vorschlagsrubrik der Kategorie - erklaert die gestrichelte Pille
   unten an der Zeile. */
.sichtung-kachel-rubrik {
    font-weight: 500;
    font-size: 0.7rem;
    color: var(--text-muted);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 0 0.25rem;
    margin-left: 0.3rem;
}

.sichtung-kachel-zahl {
    font-size: 1.6rem;
    font-weight: 600;
    line-height: 1;
    color: var(--danger);
    font-variant-numeric: tabular-nums;
}
.sichtung-kachel-zahl.leer { color: var(--text-muted); }
.sichtung-kachel-einheit { font-size: 0.75rem; color: var(--text-muted); margin-left: 0.35rem; }

.sichtung-kachel-fuss {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-top: 0.5rem;
    padding-top: 0.45rem;
    border-top: 1px solid var(--border);
    font-size: 0.72rem;
    color: var(--text-muted);
}

/* Farbpunkte wie bei den anderen Kacheln: erst beim Ueberfahren sichtbar. */
.sichtung-kachel-aktionen {
    position: absolute;
    right: 0.5rem;
    bottom: 0.4rem;
    opacity: 0;
    transition: opacity 0.12s;
}
.sichtung-kachel-huelle:hover .sichtung-kachel-aktionen,
.sichtung-kachel-aktionen:focus-within { opacity: 1; }

/* ------------------------------------------------------- Artikelliste ----- */

.sichtung-liste { border-top: 1px solid var(--border); }

/* Zwei Spalten: Titel und Meta links, die Rubrikspalte rechts ueber beide
   Zeilen. Die Spalte darf nicht umbrechen - eine Reihe, die mal rechts und
   mal unter der Zeile steht, kostet beim Zielen mehr als sie an Breite
   spart. */
.sichtung-zeile {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) max-content;
    gap: 0.15rem 1.2rem;
    align-items: start;
    padding: 0.55rem 0.7rem 0.55rem 0.8rem;
    background: var(--card);
    border-bottom: 1px solid var(--border);
}
.sichtung-zeile:focus { outline: none; }

.sichtung-zeile.zeile-aktiv { background: var(--tint-blau-zart); }
.sichtung-zeile.zeile-aktiv::after {
    content: "";
    position: absolute;
    inset: 0;
    outline: 2px solid var(--primary);
    outline-offset: -2px;
    pointer-events: none;
}
/* Entschiedene Zeilen bleiben stehen und treten zurueck: ein sofortiges
   Ausblenden zoege den Eintrag unter dem Mauszeiger weg und nahme den
   Rueckweg. */
.sichtung-zeile.zeile-erledigt .sichtung-titel a { color: var(--text-muted); }
.sichtung-zeile.zeile-verworfen { opacity: 0.55; }

/* Der Titel bleibt einzeilig: unterschiedlich hohe Zeilen sind als Liste
   nicht mehr lesbar. Der volle Titel steht im Artikel selbst. */
.sichtung-titel {
    grid-column: 1;
    font-size: 0.95rem;
    font-weight: 500;
    margin: 0;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sichtung-titel a { color: inherit; text-decoration: none; }
.sichtung-titel a:hover { text-decoration: underline; }

/* Punkt statt Wort: "neu" an zweihundert Zeilen waere zweihundertmal
   dieselbe Auskunft. */
.sichtung-punkt {
    display: inline-block;
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--danger);
    margin-right: 0.45rem;
    vertical-align: 2px;
}
.zeile-erledigt .sichtung-punkt, .zeile-verworfen .sichtung-punkt { visibility: hidden; }

.sichtung-meta {
    grid-column: 1;
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    align-items: center;
    font-size: 0.78rem;
    color: var(--text-muted);
}
.sichtung-meta .sichtung-quelle { color: var(--text); }

.sichtung-aktionen {
    grid-row: 1 / span 2;
    grid-column: 2;
    display: flex;
    align-items: center;
    gap: 0.15rem;
    flex-wrap: nowrap;
    white-space: nowrap;
}

/* Die Rubrikpillen tragen ihre Farbe aus der Datenbank (rubriken.farbe),
   gesetzt als --rubrik-farbe am Element. Ungewaehlt faerbt sie nur die
   Schrift, gewaehlt die Flaeche - so bleibt eine Reihe aus neun Pillen
   ruhig und die getroffene Wahl trotzdem eindeutig. */
.sichtung-aktionen .rubrik-pill {
    padding: 0.25rem 0;
    width: 1.9rem;
    text-align: center;
    border-radius: 3px;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--rubrik-farbe, var(--text-muted));
}
.sichtung-aktionen .rubrik-pill:hover {
    border-color: var(--rubrik-farbe, var(--primary));
    color: var(--rubrik-farbe, var(--primary));
}
/* Der Vorschlag der Kategorie: gestrichelt, nicht gesetzt. Ein automatisch
   gesetzter Wert waere eine Entscheidung, die der Redaktion gehoert. */
.sichtung-aktionen .rubrik-pill.pill-vorschlag {
    border-color: var(--rubrik-farbe, var(--border));
    border-style: dashed;
}
.sichtung-aktionen .rubrik-pill.pill-active {
    background: var(--rubrik-farbe, var(--primary));
    border-color: var(--rubrik-farbe, var(--primary));
    color: #fff;
}

.sichtung-trenner {
    width: 1px;
    align-self: stretch;
    background: var(--border);
    margin: 0 0.25rem;
}

.sichtung-knopf {
    font: inherit;
    font-size: 0.78rem;
    line-height: 1;
    padding: 0.3rem 0;
    width: 1.7rem;
    text-align: center;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: var(--card);
    color: var(--text-muted);
    cursor: pointer;
}
.sichtung-knopf:hover { border-color: var(--text); color: var(--text); }
.sichtung-verwerfen:hover { border-color: var(--danger); color: var(--danger); }

.sichtung-vermerk {
    grid-column: 1 / -1;
    font-size: 0.78rem;
    color: var(--success);
    margin-top: 0.15rem;
}
.sichtung-vermerk-fehler { color: var(--danger); }

.sichtung-zurueck {
    font: inherit;
    font-size: 0.78rem;
    background: none;
    border: 0;
    padding: 0 0 0 0.4rem;
    color: var(--text-muted);
    text-decoration: underline;
    cursor: pointer;
}

/* Tastenleiste: steht dauerhaft am Fuss, weil die Seite ueber die Tastatur
   bedient wird - was man nicht sieht, benutzt man nicht. */
.sichtung-tasten {
    position: sticky;
    bottom: 0;
    display: flex;
    gap: 1.1rem;
    flex-wrap: wrap;
    justify-content: center;
    margin-top: 1.5rem;
    padding: 0.5rem 1rem;
    background: rgba(31, 41, 55, 0.94);
    color: #e5e7eb;
    font-size: 0.78rem;
    border-radius: 4px;
}
.sichtung-tasten kbd {
    font: inherit;
    font-size: 0.72rem;
    background: #374151;
    border: 1px solid #4b5563;
    border-radius: 3px;
    padding: 0 0.3rem;
    margin-right: 0.25rem;
}

/* ------------------------------------------------- Die Arbeitsflaeche ----- */
/*
  Untereinander, nicht nebeneinander: das Heft ist der Arbeitsplatz und
  bekommt die ganze Breite. Erst so stehen die neun Rubriken in einer Reihe
  und sind als Gliederung des Hefts zu lesen - in einer halben
  Bildschirmbreite standen sie in drei Reihen uebereinander.
*/
.sichtung-arbeit { display: block; }

/*
  Die offenen Funde: zugeklappt der Ausgangspunkt, denn sie sind der Zulauf
  und nicht die Arbeit. Aufgeklappt bleibt der Block beim Scrollen oben
  stehen, damit man aus ihm heraus auch auf eine weiter unten stehende
  Rubrik ziehen kann - ein Ziehbeginn, der aus dem Bild gescrollt ist,
  nuetzt so wenig wie ein Ziel, das es ist.
*/
.sichtung-fold { margin-bottom: 1rem; }

.sichtung-fold[open] {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    padding-bottom: 0.5rem;
}

/* Die Hoehe ist gedeckelt: ohne das schoebe eine Liste von zweihundert
   Zeilen das Heft aus dem Bild, und gezogen wird zwischen beiden. */
.sichtung-fold-inhalt {
    max-height: 45vh;
    overflow-y: auto;
}

.sichtung-fold-hinweis { font-size: 0.78rem; font-weight: 400; }
.sichtung-fold[open] > summary .sichtung-fold-hinweis { display: none; }

.sichtung-heft {
    min-width: 0;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0.7rem 0.75rem 0.9rem;
}
/* Waehrend eines Zugs: die ganze Haelfte zeigt, dass hier abgelegt wird. */
.sichtung-heft.ziele-an { border-color: var(--primary); }

.sichtung-heft-kopf {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    flex-wrap: wrap;
    padding-bottom: 0.6rem;
    margin-bottom: 0.7rem;
    border-bottom: 1px solid var(--border);
    font-size: 0.82rem;
    color: var(--text-muted);
}
.sichtung-heft-summe { font-weight: 600; color: var(--text); }
.sichtung-heft-weg { margin-left: auto; font-size: 0.8rem; white-space: nowrap; }

.sichtung-heft-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: 0.5rem;
}

/* Eine Rubrik als Ablagefeld. Die Mindesthoehe ist Absicht: eine leere
   Rubrik muss gross genug bleiben, um sie treffen zu koennen. */
.sichtung-heft-rubrik {
    min-height: 6rem;
    /* Ohne das macht ein langer Titel die Spalte breit: ein Grid-Kind darf
       von sich aus nicht unter seinen Inhalt schrumpfen, und die
       Kuerzung per Ellipsis kaeme nie zum Zuge. */
    min-width: 0;
    background: var(--bg);
    border: 1px solid var(--border);
    border-top: 2px solid var(--rubrik-farbe, var(--border));
    border-radius: 4px;
    padding: 0.35rem 0.4rem 0.45rem;
}
.sichtung-heft-rubrik.sichtung-ziel-aktiv {
    background: var(--tint-blau-zart);
    border-color: var(--rubrik-farbe, var(--primary));
    box-shadow: inset 0 0 0 1px var(--rubrik-farbe, var(--primary));
}

.sichtung-heft-rubrik-kopf {
    display: flex;
    align-items: baseline;
    gap: 0.3rem;
    margin-bottom: 0.3rem;
}
.sichtung-heft-kuerzel {
    font-family: inherit;
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--rubrik-farbe, var(--text-muted));
}
.sichtung-heft-rubrik-name {
    min-width: 0;
    font-size: 0.72rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sichtung-heft-rubrik-zahl {
    margin-left: auto;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.sichtung-heft-karten {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.25rem;
}

/* Auch hier bleibt der Titel einzeilig: eine Spalte aus unterschiedlich
   hohen Karten ist als Liste nicht mehr lesbar. */
.sichtung-heft-karte {
    min-width: 0;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 0.25rem 0.35rem;
    cursor: grab;
}
.sichtung-heft-karte-titel {
    display: block;
    font-size: 0.76rem;
    color: var(--text);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sichtung-heft-karte-titel:hover { text-decoration: underline; }
.sichtung-heft-karte-meta {
    display: block;
    font-size: 0.68rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sichtung-heft-karte.sichtung-karte-fehler { border-color: var(--danger); }

/* Kurzes Aufblitzen nach dem Ablegen: die Karte landet oben in ihrer
   Spalte, und ohne Hinweis ist nicht zu sehen, welche gerade dazukam. */
.sichtung-karte-neu { animation: sichtung-karte-blitz 0.9s ease-out; }
@keyframes sichtung-karte-blitz {
    from { background: var(--tint-blau); }
    to { background: var(--card); }
}

.sichtung-zieht { opacity: 0.45; }

/* Der Griff sagt, dass die Zeile zu ziehen ist. Er erscheint erst beim
   Ueberfahren - staendig sichtbar waere er in zweihundert Zeilen nur
   Rauschen, und die Zeile ist ohnehin als Ganzes zu greifen. */
.sichtung-griff {
    display: inline-block;
    width: 0.7rem;
    margin-right: 0.25rem;
    color: var(--text-muted);
    font-size: 0.8rem;
    letter-spacing: -3px;
    cursor: grab;
    opacity: 0;
}
.sichtung-zeile:hover .sichtung-griff { opacity: 1; }

/* ------------------------------------------ Ablageleiste im Panel -------- */
/*
  Unter der Artikelliste des Panels: eine Zeile auf eine Rubrik ziehen legt
  sie in den Pool. Die Leiste bleibt am Fuss des Panels stehen, waehrend die
  Liste darueber scrollt - ein Ziehziel, das aus dem Bild gescrollt ist, kann
  man nicht treffen. Dieselbe Ueberlegung wie bei der Heftspalte der
  Sichtung.
*/
.panel-ablage {
    position: sticky;
    bottom: -1.5rem;   /* hebt die untere Polsterung des Inhalts auf */
    margin: 0.8rem -0.9rem -1.5rem;
    padding: 0.5rem 0.9rem 0.6rem;
    background: var(--card);
    border-top: 1px solid var(--border);
    box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.06);
}
.panel-ablage.ablage-an { border-top-color: var(--primary); }

.panel-ablage-kopf {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin: 0 0 0.4rem;
    font-size: 0.78rem;
    color: var(--text-muted);
}
.panel-ablage-titel { font-weight: 600; color: var(--text); }
.panel-ablage-weg { margin-left: auto; font-size: 0.76rem; }

.panel-ablage-pillen {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}

/* Dieselbe Optik wie die Rubrikpillen an der Sichtungszeile: Schrift in der
   Rubrikfarbe, Flaeche erst beim Treffen. Eine zweite Formensprache fuer
   dieselbe Sache waere an zwei Orten zu pflegen. */
.panel-ablage-pillen .rubrik-pill {
    padding: 0.25rem 0.5rem;
    border-radius: 3px;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--rubrik-farbe, var(--text-muted));
}
.panel-ablage-pillen .rubrik-pill:hover,
.panel-ablage-pillen .rubrik-pill.pille-ziel {
    background: var(--rubrik-farbe, var(--primary));
    border-color: var(--rubrik-farbe, var(--primary));
    color: #fff;
}

.panel-ablage-hinweis { margin: 0.35rem 0 0; font-size: 0.72rem; }
.panel-ablage-fehler { color: var(--danger); }

/* Die gewaehlte Zeile im Panel - das Gegenstueck zum Zeilenklick, ohne den
   die Pillen nicht wuessten, worauf sie wirken. */
#artikel-panel tbody tr.zeile-gewaehlt {
    background: var(--tint-blau-zart);
    box-shadow: inset 2px 0 0 var(--primary);
}
#artikel-panel tbody tr.zeile-zieht { opacity: 0.45; }
#artikel-panel tbody tr.zeile-speichert { opacity: 0.6; }

/* Wohin ein Artikel einsortiert ist. Steht in der Titelspalte neben dem
   Titel, weil es zu ihm gehoert und nicht zu den Aktionen. */
.rubrik-badge {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0 0.3rem;
    border: 1px solid var(--rubrik-farbe, var(--border));
    border-radius: 3px;
    font-size: 0.68rem;
    font-weight: 600;
    white-space: nowrap;
    color: var(--rubrik-farbe, var(--text-muted));
}

/* --------------------------------------------- Pool in den Heftspalten --- */
/*
  Eine Pool-Karte steht in den Spalten des Hefts, weil der Pool ihm gehoert -
  zugeordnet ist sie ihm nicht. Gestrichelt statt durchgezogen: dieselbe
  Sprache wie die Vorschlagspille in der Sichtung, wo gestrichelt ebenfalls
  "gilt, ist aber nicht gesetzt" heisst.
*/
.sichtung-heft-karte.karte-pool {
    border-style: dashed;
    border-left: 3px dashed var(--rubrik-farbe, var(--border));
    background: transparent;
}

/* Die Handgriffe an einer Karte: erst beim Ueberfahren sichtbar - in einer
   Spalte voller Karten waeren sie sonst nur Rauschen, und zu lesen ist hier
   der Titel. */
.sichtung-karte-aktionen {
    display: none;
    gap: 0.25rem;
    margin-top: 0.15rem;
}
.sichtung-heft-karte:hover .sichtung-karte-aktionen,
.sichtung-karte-aktionen:focus-within { display: flex; }

.sichtung-karte-insheft,
.sichtung-karte-weiter,
.sichtung-karte-verwerfen {
    padding: 0 0.3rem;
    font: inherit;
    font-size: 0.66rem;
    line-height: 1.5;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: var(--card);
    color: var(--text-muted);
    cursor: pointer;
}
.sichtung-karte-insheft:hover,
.sichtung-karte-weiter:hover { border-color: var(--primary); color: var(--primary); }

/* Das Ziel steht auf dem Knopf, nicht nur im Titel: "weiter" allein liesse
   offen, wohin - und in welchem Heft eine Meldung landet, ist genau die
   Frage, die man an dieser Stelle hat. */
.sichtung-karte-weiter { white-space: nowrap; }

/* Verwerfen steht rechts und traegt die Warnfarbe erst beim Ueberfahren -
   es ist der einzige Handgriff an der Karte, der etwas wegnimmt. */
.sichtung-karte-verwerfen {
    margin-left: auto;
    font-size: 0.8rem;
    line-height: 1.2;
}
.sichtung-karte-verwerfen:hover { border-color: var(--danger); color: var(--danger); }

.sichtung-pool-summe { font-weight: 400; color: var(--text-muted); }

/* ------------------------------------------- Rueckgaengig-Streifen ------- */
/*
  Entschiedene Zeilen verlassen die Liste, also braucht das Zuruecknehmen
  einen eigenen Ort. Er steht ueber der Liste, wo man ohnehin hinsieht, und
  haelt nur die letzten Handgriffe - ein langes Protokoll verstellte den
  Blick auf die Arbeit.
*/
.sichtung-rueckgaengig {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    margin: 0 0 0.6rem;
    padding: 0.4rem 0.6rem;
    background: var(--flaeche-zart);
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.8rem;
}
.sichtung-rueckgaengig-kopf {
    color: var(--text-muted);
    white-space: nowrap;
}
.sichtung-rueckgaengig-liste {
    list-style: none;
    margin: 0;
    padding: 0;
    min-width: 0;
    flex: 1;
    display: grid;
    gap: 0.15rem;
}
.sichtung-rg-eintrag {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    min-width: 0;
}
.sichtung-rg-text {
    min-width: 0;
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sichtung-rg-knopf {
    font: inherit;
    font-size: 0.78rem;
    background: none;
    border: 0;
    padding: 0;
    color: var(--primary);
    text-decoration: underline;
    cursor: pointer;
    white-space: nowrap;
}
.sichtung-rg-knopf:disabled { color: var(--text-muted); cursor: default; }

/* In einem schmalen Fenster nuetzt das Stehenbleiben nichts mehr: der Block
   naehme den halben Schirm, und gezogen wird dort ohnehin nicht - dafuer
   sind die Pillen an der Zeile da. */
@media (max-width: 900px) {
    .sichtung-fold[open] { position: static; }
    .sichtung-fold-inhalt { max-height: none; }
}

/* Erst wenn Titel und Rubrikspalte nicht mehr nebeneinander passen, wandert
   die Spalte unter die Zeile. */
@media (max-width: 900px) {
    .sichtung-zeile { grid-template-columns: 1fr; }
    .sichtung-aktionen {
        grid-row: auto;
        grid-column: 1;
        justify-content: flex-start;
        margin-top: 0.3rem;
        flex-wrap: wrap;
    }
    .sichtung-titel { white-space: normal; }
}

/* Zweite Kachelzahl neben "N neu": was hier noch zum Durchsehen liegt.
   Gedaempfter als "neu", weil "offen" der Dauerzustand ist und "neu" der
   Befund des letzten Laufs. */
.kachel-offen {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0 0.35rem;
    border-radius: 3px;
    background: var(--badge-warn);
    color: var(--badge-warn-text);
    font-size: 0.72rem;
    font-weight: 600;
}

/* Livefilter ueber einem Kachelgitter (Quellen-Startseite). Gleiche Optik
   wie die Suche der Sichtung - es ist dieselbe Handlung. */
.kachel-filterleiste {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    flex-wrap: wrap;
    margin: 0 0 0.9rem;
}

.kachel-filter-feld {
    flex: 1;
    min-width: 18rem;
    max-width: 30rem;
    padding: 0.5rem 0.75rem;
    border: 2px solid var(--border);
    border-radius: 6px;
    font-size: 1rem;
    background: var(--card);
    color: var(--text);
}

.kachel-filter-feld:focus {
    border-color: var(--primary);
    outline: none;
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}

.kachel-filter-treffer {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
}

.kachel-filter-treffer.leer { color: var(--danger); }

/* Die Wege aus der Seite heraus, jetzt oben statt am Fuss */
.quellen-wege { margin: 0.6rem 0 1rem; }

/* ---------------------------------------------------- Quellenliste ------ */

/* Eigene Breite fuer /quellen/liste. <main> gibt 1400px vor - das ist fuer
   Kachelgitter und die Artikeltabelle richtig, fuer diese Liste nicht: die
   zugeklappte Zeile ist eine Flexbox, in der der Site-Zaehler per
   margin-left:auto nach rechts wandert. Ueber die volle Breite stehen Name
   und Zahlen so weit auseinander, dass die Zeile nicht mehr als Zeile zu
   lesen ist. Der Wrapper umfasst auch Filterleiste und Pills, damit alles
   dieselbe Kante hat. */
.quellen-seite {
    max-width: 1100px;
    margin: 0 auto;
}

/* Quick-Add auf der Quellenliste: zugeklappt als Ausgangspunkt. Die
   Zusammenfassung sieht aus wie ein Knopf, weil sie einer ist - anders als
   die Gruppen der Liste, die als Zeilen gelesen werden wollen. */
.quick-add-fold {
    margin-bottom: 1rem;
}

.quick-add-fold > summary {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.9rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--card);
    cursor: pointer;
    font-size: 0.9rem;
    user-select: none;
    list-style: none;
}

.quick-add-fold > summary::-webkit-details-marker { display: none; }

.quick-add-fold > summary::before {
    content: '\25B6';
    font-size: 0.6rem;
    color: var(--text-muted);
    transition: transform 0.15s;
}

.quick-add-fold[open] > summary::before { transform: rotate(90deg); }
.quick-add-fold > summary:hover { border-color: var(--primary); }

/* Der Abstand steckt schon in .quick-add-zone; im aufgeklappten Zustand
   soll er nicht doppelt zaehlen. */
.quick-add-fold[open] > summary { margin-bottom: 0.6rem; }

/* Die gesetzten Filterwerte der Quellenliste, jeder einzeln aufhebbar.
   Seit die Pills kumulativ wirken, koennen mehrere Kriterien gleichzeitig
   gelten - ohne diese Zeile filterte die Liste unsichtbar, und ein einzelner
   Wert liesse sich nicht mehr herausnehmen. */
.filter-chip-zeile {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin: -0.4rem 0 0.8rem;
}

.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.2rem 0.4rem 0.2rem 0.7rem;
    border-radius: 12px;
    background: var(--badge-ok);
    color: var(--badge-ok-text);
    font-size: 0.85rem;
}

.filter-chip-loeschen {
    color: inherit;
    text-decoration: none;
    font-size: 1.1rem;
    line-height: 1;
    padding: 0 0.3rem;
    border-radius: 8px;
    opacity: 0.7;
}

.filter-chip-loeschen:hover { opacity: 1; background: rgba(0, 0, 0, 0.08); }


/* Kopfzeile des laufenden Crawls: was gecrawlt wird, wie lange schon, welche
   Quelle gerade dran ist. Eine Zeile statt dreier Zeilen - sie steht ueber
   dem Fortschrittsbalken und soll ihn nicht verdraengen. */
.crawl-meta {
    margin: 0 0 0.75rem;
    font-size: 0.85rem;
}
.crawl-meta strong { color: var(--text); }

/* ==========================================================================
   Dashboard: Sidebar, Kopfleiste, Karten-Feed
   ==========================================================================

   Uebernommen aus dem Entwurf in docs/ref/rss-dashboard.html, mit einer
   wesentlichen Anpassung: dort ist das Ganze die *Seite* - ein Raster ueber
   100vh, dessen beide Spalten je fuer sich scrollen. Hier liegt es innerhalb
   von <main>, mit der Navigationsleiste darueber und der Fusszeile darunter.
   Feste Hoehen und eigene Scrollbereiche waeren dort falsch: die Seite
   bekaeme zwei Bildlaufleisten, und die Fusszeile stuende nie im Bild.

   Also ein gewoehnliches Raster im Textfluss. Die Sidebar bleibt beim
   Scrollen stehen (sticky), aber ohne den Rest der Seite festzunageln.

   Alle Klassen tragen das Praefix dash-, damit nichts mit den gewachsenen
   Regeln kollidiert. Genutzt werden die Variablen von oben - eigene
   Farbwerte stehen hier keine, sonst haette das dunkle Schema einen zweiten
   Ort zu pflegen.
*/

.dash {
    display: grid;
    grid-template-columns: var(--sidebar-w) 1fr;
    gap: 1.5rem;
    align-items: start;
}

/* ------------------------------------------------------------- Sidebar --- */

.dash-sidebar {
    position: sticky;
    top: 1rem;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    /* Laenger als der Bildschirm darf sie fuer sich scrollen - aber erst
       dann. Ohne die Grenze waechst sie darueber hinaus und ihr unterer
       Teil (die Crawl-Karte) waere nie zu sehen. */
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
    padding: 1rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.dash-gruppe-titel {
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--text-faint);
    padding: 0 0.5rem 0.4rem;
}

.dash-nav-liste {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.dash-nav-eintrag {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.45rem 0.5rem;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    text-decoration: none;
    font-size: 0.88rem;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.dash-nav-eintrag:hover {
    background: var(--bg-surface-2);
    color: var(--text-strong);
}

.dash-nav-eintrag[aria-current="page"] {
    background: var(--primary-soft);
    color: var(--primary);
    font-weight: 600;
}

/* Farbpunkt einer Gruppe. Die Farbe kommt aus der vorhandenen Klasse
   .farbe-<name> ueber deren Variable --bereich - dieselbe Farbe wie die
   Kachel derselben Gruppe auf /articles und /quellen/bereiche. */
.dash-punkt {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--bereich, var(--text-muted));
}

.dash-nav-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dash-zahl {
    margin-left: auto;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-faint);
    background: var(--bg-surface-2);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 0 0.5rem;
    min-width: 1.7rem;
    text-align: center;
    flex-shrink: 0;
}

.dash-nav-eintrag[aria-current="page"] .dash-zahl {
    background: transparent;
    border-color: transparent;
    color: var(--primary);
}

/* Fortschritt des laufenden Crawls, bzw. der letzte Lauf */
.dash-crawl-karte {
    margin-top: auto;
    background: var(--bg-surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.75rem;
}

.dash-crawl-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.dash-crawl-titel {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-strong);
}

.dash-fortschritt {
    height: 7px;
    border-radius: 999px;
    background: var(--border);
    overflow: hidden;
}

.dash-fortschritt-balken {
    height: 100%;
    border-radius: inherit;
    background: var(--primary);
    transition: width 0.3s ease;
}

.dash-crawl-meta {
    display: flex;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: 0.4rem;
    font-size: 0.72rem;
    color: var(--text-muted);
}

/* ---------------------------------------------------------- Kopfleiste --- */
/*
   Die Kopfzeile des Entwurfs, hier als Kopf des Dashboard-Inhalts. Sie ist
   ausdruecklich *kein* zweiter App-Header ueber der Navigationsleiste: die
   globale Navigation steht in base.html und bleibt, wo sie ist.
*/
.dash-kopf {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.75rem 1rem;
    margin-bottom: 1rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.dash-kopf-titel h1 {
    font-size: 1.15rem;
    margin: 0;
    color: var(--text-strong);
}

.dash-kopf-titel p {
    font-size: 0.78rem;
    color: var(--text-muted);
    margin: 0;
}

/*
  Die Suche nimmt den freien Platz, gibt ihn aber nicht bis zur
  Unkenntlichkeit her: unter 16rem war vom Platzhalter nur noch
  "Alle Artikel durchsu" zu lesen. Reicht der Platz nicht, bricht die
  Kopfleiste um (flex-wrap steht an .dash-kopf) - das ist besser als drei
  gequetschte Elemente nebeneinander.
*/
.dash-suche {
    flex: 1 1 18rem;
    min-width: 16rem;
    max-width: 30rem;
    margin-left: auto;
    display: flex;
    gap: 0.4rem;
}

.dash-suche input {
    flex: 1;
    min-width: 0;
    font: inherit;
    font-size: 0.88rem;
    padding: 0.45rem 0.9rem;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg-surface-2);
    color: var(--text);
}

.dash-suche input::placeholder { color: var(--text-faint); }

.dash-suche input:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px var(--primary-soft);
}

.dash-status {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    /* Die Pillen tragen Zahlen - schrumpfen sie, wird die Zahl abgeschnitten
       und die Anzeige sagt etwas Falsches. */
    flex-shrink: 0;
}

.dash-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    font-size: 0.76rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    border: 1px solid transparent;
}

.dash-pill-ok    { color: var(--success);    background: var(--ok-soft); }
.dash-pill-warn  { color: var(--warn);       background: var(--warn-soft); }
.dash-pill-info  { color: var(--info);       background: var(--info-soft); }
.dash-pill-still { color: var(--text-muted); background: var(--bg-surface-2); border-color: var(--border); }

a.dash-pill:hover { border-color: currentColor; }

.dash-pill-punkt {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}

/* Nur der laufende Crawl pulsiert - ein ruhender Zustand, der blinkt, sagt
   etwas Falsches. */
.dash-pill-ok .dash-pill-punkt { animation: dash-puls 1.8s ease-in-out infinite; }

@keyframes dash-puls {
    0%, 100% { box-shadow: 0 0 0 0 var(--ok-soft); }
    50%      { box-shadow: 0 0 0 5px transparent; }
}

@media (prefers-reduced-motion: reduce) {
    .dash-pill-ok .dash-pill-punkt { animation: none; }
}

/* Rund und so hoch wie eine Statuspille: er steht in derselben Reihe, und
   ein Knopf, der dort einen halben Zentimeter herausragt, zieht die ganze
   Zeile auf. */
.dash-icon-knopf {
    display: grid;
    place-items: center;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: 999px;
    color: var(--text-muted);
    border: 1px solid var(--border);
    background: var(--bg-surface-2);
    cursor: pointer;
    flex-shrink: 0;
}

.dash-icon-knopf:hover {
    background: var(--bg-elevated);
    color: var(--text-strong);
}

/* Sonne im hellen, Mond im dunklen Schema: gezeigt wird, was gerade gilt. */
.dash-theme-knopf .icon-mond { display: none; }
.dash-theme-knopf .icon-sonne { display: block; }
html[data-theme="dark"] .dash-theme-knopf .icon-mond { display: block; }
html[data-theme="dark"] .dash-theme-knopf .icon-sonne { display: none; }

/* ------------------------------------------------------ Werkzeugleiste --- */

.dash-werkzeug {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.dash-chip {
    padding: 0.3rem 0.8rem;
    border-radius: 999px;
    font-size: 0.8rem;
    color: var(--text-muted);
    text-decoration: none;
    background: var(--card);
    border: 1px solid var(--border);
}

.dash-chip:hover {
    color: var(--text-strong);
    border-color: var(--border-strong);
}

.dash-chip[aria-pressed="true"] {
    color: var(--auf-primary);
    background: var(--primary);
    border-color: var(--primary);
}

.dash-werkzeug-luecke { flex: 1; }

/* -------------------------------------------------------- Karten-Feed --- */

.dash-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
    gap: 1.1rem;
}

.dash-karte {
    display: flex;
    flex-direction: column;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}

.dash-karte:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-lg);
    border-color: var(--border-strong);
}

@media (prefers-reduced-motion: reduce) {
    .dash-karte:hover { transform: none; }
}

/*
  Der Entwurf zeigt hier ein Artikelbild. Der Crawler holt keine Bilder - er
  liest die Uebersichtsseite und nimmt Titel, Adresse, Datum und
  Zusammenfassung. Statt lauter gleicher grauer Kaesten steht deshalb die
  Farbflaeche der Gruppe, zu der die Quelle gehoert: sie traegt dieselbe
  Information wie der Punkt in der Sidebar und macht die Karten
  unterscheidbar.
*/
/*
  Ein flaches Farbband, kein Bildplatz.

  Zuerst stand hier die Hoehe eines 16:9-Bildes aus dem Entwurf. Ohne Bild
  darin sah die Karte aus, als sei eines nicht geladen - eine leere Flaeche,
  die etwas verspricht. Das Band ist nur noch so hoch, wie sein Badge
  braucht: es ordnet die Karte ein und gibt vor, keinen Platz fuer mehr zu
  haben.
*/
.dash-karte-flaeche {
    position: relative;
    display: flex;
    align-items: center;
    min-height: 2.5rem;
    padding: 0.35rem 0.9rem;
    background: var(--bereich-hell, var(--bg-surface-2));
    border-bottom: 1px solid var(--border);
}

.dash-karte-flaeche::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 4px;
    background: var(--bereich, var(--text-muted));
}

.dash-karte-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--text-strong);
    background: var(--bg-elevated);
    box-shadow: var(--shadow-sm);
    max-width: 100%;
}

.dash-karte-badge .dash-badge-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dash-karte-koerper {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    padding: 0.9rem;
    flex: 1;
}

.dash-karte-quelle {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.76rem;
    color: var(--text-muted);
    min-width: 0;
}

/* Kuerzel der Quelle als farbiges Kaestchen - die Stelle, an der im Entwurf
   das Logo der Publikation steht. Ein Logo haben wir nicht. */
.dash-quelle-kuerzel {
    display: grid;
    place-items: center;
    width: 1.3rem;
    height: 1.3rem;
    border-radius: 5px;
    font-size: 0.62rem;
    font-weight: 700;
    color: var(--auf-signal);
    background: var(--bereich, var(--text-muted));
    flex-shrink: 0;
}

.dash-karte-titel {
    font-size: 0.98rem;
    font-weight: 650;
    line-height: 1.35;
    margin: 0;
}

.dash-karte-titel a {
    color: var(--text-strong);
    text-decoration: none;
    /* Hoechstens zwei Zeilen: sonst ist jede Karte anders hoch und das
       Raster liest sich nicht mehr als Raster. Der ganze Titel steht im
       title-Attribut. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.dash-karte-titel a:hover { color: var(--primary); }

.dash-zusammenfassung {
    font-size: 0.84rem;
    color: var(--text-muted);
    line-height: 1.5;
    padding: 0.5rem 0.6rem;
    border-radius: var(--radius-sm);
    background: var(--bg-surface-2);
    border: 1px solid var(--border);
}

.dash-zusammenfassung-label {
    display: block;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-faint);
    margin-bottom: 0.2rem;
}

.dash-zusammenfassung p {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.dash-karte-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-items: center;
}

.dash-karte-fuss {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: auto;
    padding-top: 0.3rem;
}

.dash-karte-zeit { font-size: 0.74rem; color: var(--text-faint); }

.dash-karte-aktionen {
    display: flex;
    gap: 0.25rem;
    align-items: center;
}

/*
  Markierte Karte: gruen getoenter Grund, kein Rahmen und keine Kante.

  Zwei Anlaeufe davor waren schlechter. Ein **gruener Rahmen rundum** wurde
  im Raster mit mehreren markierten Karten zu einer Wand aus Rechtecken und
  stritt mit dem Kategorieband um dieselbe Stelle. Eine **Kante an der
  rechten Seite** verschwand oben unter dem Farbband - das ist ein Kind der
  Karte und deckt deren Innenschatten ab -, sodass ein gruener Strich
  mitten am Rand begann und wie ein Darstellungsfehler aussah.

  Die Flaeche hat beide Probleme nicht: sie liegt hinter allem, hoert von
  selbst dort auf, wo die Karte aufhoert, und ist auch dann noch als Gruppe
  zu erkennen, wenn dreissig Karten nebeneinander stehen. Es ist zugleich
  dieselbe Kennzeichnung wie bei einer markierten Tabellenzeile
  (--badge-ok), nur eine Ebene tiefer angesetzt: nicht die ganze Karte,
  sondern ihr Textteil - das Farbband darueber behaelt seine Aussage.
*/
.dash-karte.row-marked .dash-karte-koerper {
    background: var(--markiert-karte);
}

.dash-leer {
    grid-column: 1 / -1;
    padding: 2rem;
    text-align: center;
    color: var(--text-muted);
    background: var(--card);
    border: 1px dashed var(--border);
    border-radius: var(--radius);
}

/* -------------------------------------------------- Schmale Bildschirme --- */

@media (max-width: 60rem) {
    .dash { grid-template-columns: 1fr; }

    /* Die Sidebar wandert ueber den Inhalt und hoert auf zu kleben: als
       liegender Block braucht sie die Hoehe nicht, und sticky wuerde sie
       ueber den Feed schieben. */
    .dash-sidebar {
        position: static;
        max-height: none;
        overflow: visible;
    }

    .dash-nav-liste { flex-direction: row; flex-wrap: wrap; }
    .dash-nav-eintrag { border: 1px solid var(--border); }
    .dash-crawl-karte { margin-top: 0; }
}

@media (max-width: 40rem) {
    .dash-suche {
        order: 3;
        max-width: none;
        flex-basis: 100%;
        margin-left: 0;
    }
    .dash-kopf-titel p { display: none; }
    .dash-grid { grid-template-columns: 1fr; }
}

/* --- Anmeldeseite -------------------------------------------------------
   Eine Karte in der Mitte, dieselbe Optik wie die Sperrseite "Neustart
   noetig" (.neustart-seite) - beides sind Seiten, die anstelle der
   Oberflaeche stehen, und sie sollen als dieselbe Art Seite zu erkennen
   sein. Unterschied ist allein die farbige Kante: dort Warnung, hier keine,
   denn eine Anmeldung ist kein Stoerfall. */
.anmelden-seite {
    max-width: 26rem;
    margin: 4rem auto;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 1.75rem 2rem 1.5rem;
}
.anmelden-seite h1 { margin-bottom: 0.35rem; }
.anmelden-seite > p { margin-bottom: 1.25rem; }
.anmelden-form { display: flex; flex-direction: column; gap: 0.4rem; }
.anmelden-form label { font-weight: 600; font-size: 0.9rem; }
/* Grund und Textfarbe kommen vom Browser - color-scheme am :root sorgt
   dafuer, dass er im dunklen Schema auch dunkel malt (siehe oben). */
.anmelden-form input {
    padding: 0.55rem 0.7rem;
    font-size: 1rem;
    border: 1px solid var(--border);
    border-radius: 4px;
}
.anmelden-form input:focus { border-color: var(--primary); outline: none; }
.anmelden-form button { margin-top: 0.6rem; }
.anmelden-hinweis { margin-top: 1.25rem; font-size: 0.85rem; }

/* --- Bereichsseite: Quellen mit Befund -----------------------------------
   Die Farben kommen aus den vorhandenen Badge-Variablen und sind damit im
   dunklen Schema schon mitgedacht. Eigene Hexwerte hier waeren der Fall,
   den "Fest eingetragene Farben gehoeren in Variablen" beschreibt. */
.befund-leiste {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 1rem;
}
.befund-zahl {
    padding: 0.3rem 0.7rem;
    border-radius: 6px;
    background: var(--flaeche-zart);
    color: var(--text);
    font-size: 0.85rem;
    text-decoration: none;
    border: 1px solid transparent;
}
a.befund-zahl:hover { text-decoration: underline; }
/* Der gewaehlte Filter traegt eine Kante statt einer anderen Farbe: die
   Farbe sagt hier den Befund, und zwei Bedeutungen auf einem Merkmal waeren
   an keiner Stelle verlaesslich. */
.befund-zahl-aktiv { border-color: var(--text-muted); font-weight: 600; }

.befund-pill {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 10px;
    font-size: 0.75rem;
    font-weight: 500;
    white-space: nowrap;
}
.befund-ok      { background: var(--badge-ok);      color: var(--badge-ok-text); }
.befund-warn    { background: var(--badge-warn);    color: var(--badge-warn-text); }
.befund-fehler  { background: var(--badge-blocked); color: var(--badge-blocked-text); }
.befund-info    { background: var(--badge-info);    color: var(--badge-info-text); }
.befund-neutral { background: var(--badge-none);    color: var(--badge-none-text); }

.bereich-quellen { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.bereich-quellen th {
    text-align: left;
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid var(--tabellen-linie);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
}
.bereich-quellen td {
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid var(--tabellen-linie);
    vertical-align: middle;
}
.bereich-quellen tr:hover td { background: var(--flaeche-zart); }
.bereich-quellen .zahl { text-align: right; white-space: nowrap; }
/* Name und News-URL untereinander: die Adresse ist beim Nacharbeiten das
   Erste, was man sehen will, und als eigene Spalte waere sie zu breit. */
/* Ein Crawl aus der Zeile heraus: die Zeile bleibt stehen und zeigt
   selbst, dass dort etwas laeuft (crawl-zeile.js). Der Streifen am linken
   Rand sagt, WELCHE Quelle laeuft - der Spinner allein steht in der
   letzten Spalte und ist bei dreihundert Zeilen schwer zuzuordnen. */
tr.crawl-zeile-laeuft { box-shadow: inset 3px 0 0 var(--primary); }

/* Die Flaeche liegt auf den Zellen, nicht auf der Zeile: `tr:hover td`
   faerbt sonst beim Ueberfahren darueber, und ausgerechnet die laufende
   Zeile verloere ihre Markierung unter dem Mauszeiger. Der zweite Selektor
   wiegt die hoehere Spezifitaet von `.bereich-quellen tr:hover td` auf. */
tr.crawl-zeile-laeuft > td,
.bereich-quellen tr.crawl-zeile-laeuft > td { background: var(--tint-blau-zart); }

/* Nach dem Lauf kurz hervorheben: oft aendert sich an den Zahlen nichts,
   und ohne das Aufblitzen saehe der Austausch wie ein Nichtgeschehen aus. */
tr.crawl-zeile-fertig > td,
.bereich-quellen tr.crawl-zeile-fertig > td {
    background: var(--tint-blau-zart);
    transition: background 1.5s ease-out;
}

.crawl-spinner {
    display: inline-block;
    width: 0.85rem;
    height: 0.85rem;
    vertical-align: -0.1rem;
    border: 2px solid var(--primary);
    border-top-color: transparent;
    border-radius: 50%;
    animation: crawl-dreht 0.7s linear infinite;
}

@keyframes crawl-dreht { to { transform: rotate(360deg); } }

/* Wer Bewegung abgeschaltet hat, soll die Auskunft trotzdem bekommen:
   dann pulst es statt zu drehen. Ganz ohne Anzeige waere die Zeile
   waehrend des Laufs stumm. */
@media (prefers-reduced-motion: reduce) {
    .crawl-spinner { animation: crawl-pulst 1.4s ease-in-out infinite; }
    @keyframes crawl-pulst { 50% { opacity: 0.25; } }
}

.bereich-quellen-name { display: flex; flex-direction: column; gap: 0.1rem; }
.bereich-quellen-name .news-url-link { font-size: 0.75rem; }
/* Letzter Crawl und Status stehen in zwei Spalten: das Alter beantwortet
   *wann*, der Status *wie* der Lauf ausging. Beide umbruchfrei - "vor 34
   Tagen" und "KEINE_ARTIKEL" ueber zwei Zeilen gebrochen machen die Zeile
   hoeher als ihre Nachbarn und die Tabelle unruhig. */
.bereich-lauf { white-space: nowrap; }
.bereich-lauf-status { white-space: nowrap; font-size: 0.75rem; opacity: 0.8; }
.bereich-quellen-aktionen { white-space: nowrap; text-align: right; }
/* Die Knoepfe stoeren beim Lesen der Liste und erscheinen erst beim
   Ueberfahren - dasselbe Muster wie die Farbpunkte an einer Kachel. */
.bereich-quellen-aktionen .btn { opacity: 0; transition: opacity 0.1s; }
.bereich-quellen tr:hover .bereich-quellen-aktionen .btn,
.bereich-quellen-aktionen .btn:focus { opacity: 1; }

/* "neu" ist Arbeit, nicht Erfolg - deshalb Warnfarbe und nicht das Gruen
   der markiert-Pill, das in dieser Anwendung "abgearbeitet" heisst. */
.bereich-neu { background: var(--badge-warn); color: var(--badge-warn-text); }

/* "Zu Bereich hinzufuegen" neben "Diese Liste crawlen": derselbe Umfang,
   anderer Zweck - der Filter fuellt einen Bereich, statt ihn zu definieren. */
.zu-bereich { display: inline-flex; gap: 0.3rem; align-items: center; }
.zu-bereich select {
    padding: 0.3rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.85rem;
}

/* --- Landfilter auf der Bereichsseite -----------------------------------
   .land-pill ist fuer den <button> der Quellenliste gebaut (oeffnet dort
   die Landauswahl). In der Bereichstabelle ist sie ein <a> und filtert -
   deshalb hier nur das, was ein Link mitbringt und ein Button nicht. */
a.land-pill { text-decoration: none; display: inline-block; }
a.land-pill:hover { filter: brightness(0.95); }

.land-filter { display: inline-flex; align-items: center; }
.land-filter select {
    padding: 0.3rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.85rem;
}
/* Der gesetzte Landfilter als aufhebbarer Chip - dieselbe Rolle wie die
   Chips ueber der Quellenliste, deshalb auch dieselbe zurueckhaltende
   Flaeche und kein Signalton. */
.befund-chip {
    background: var(--tint-blau);
    color: var(--tint-blau-text);
    font-weight: 600;
}
