/* ============================================================================
   Reden-Viewer (templates/viewer.html) — seitenspezifische Styles.
   Rohwerte kommen aus static/tokens.css, gemeinsame Bausteine (Kopfzeile,
   Shell, Modus-Reiter, Fußzeile) aus static/portal.css. Hier wird nichts davon
   wiederholt.
   ============================================================================ */

/* ── Hero mit Suche ───────────────────────────────────────────────────────── */
.hh-hero {
  background: var(--hero-bg);
  border-radius: var(--radius-lg);
  padding: var(--space-lg) var(--space-xl);
  color: var(--hero-ink);
  margin-bottom: var(--space-md);
}
.hh-hero h1 {
  font-size: var(--text-display);
  font-weight: var(--weight-black);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  margin-bottom: var(--space-xs);
  /* Landtagsnamen sind lange Einzelwörter; die Überschrift muss auf jeder
     Breite hineinpassen. */
  hyphens: auto;
  overflow-wrap: break-word;
}
.hh-hero h1 em { font-style: italic; color: var(--accent); }
.hh-hero > p {
  color: var(--hero-ink-2);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  margin-bottom: var(--space-md);
}

/* Suchzeile: Feld, Sortierung, Abgeordnetenauswahl.
   Alle drei stehen als helle Felder auf dem blauen Panel. Die alte Variante
   (durchscheinendes Weiß mit 25%-Rand) erreichte am Rand keine 3:1 und war als
   Bedienelement kaum vom Panel zu trennen. */
.hh-hero-links {
  display: flex;
  gap: var(--space-md);
  flex-wrap: wrap;
  margin-bottom: var(--space-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
}
.hh-hero-links a {
  color: var(--hero-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.hh-search-row {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
  align-items: flex-start;
}
/* Die Suche steht auf einer eigenen, vollen Zeile — Sortierung und
   Abgeordnetenfilter bilden darunter eine eigene, LINKSBÜNDIGE Gruppe statt
   in dieselbe Zeile gequetscht zu werden und den Rest der Breite ungleich
   unter sich aufzuteilen. */
.hh-search {
  flex: 1 1 100%;
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  padding: var(--space-xs) var(--space-sm);
  transition: border-color var(--dur-fast) var(--ease);
}
.hh-search:focus-within {
  border-color: var(--structure);
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
.hh-search svg { color: var(--ink-3); flex-shrink: 0; }
.hh-search input {
  border: none;
  outline: none;
  background: transparent;
  font: inherit;
  font-size: var(--text-base);
  color: var(--ink);
  width: 100%;
  min-width: 0;
}
/* Platzhalter braucht dieselben 4,5:1 wie Fließtext — der Grauton von früher
   erreichte sie nicht. */
.hh-search input::placeholder { color: var(--ink-3); opacity: 1; }
.hh-search button {
  border: none;
  background: var(--accent);
  color: var(--on-accent);
  border-radius: var(--radius-sm);
  padding: var(--space-2xs) var(--space-sm);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease);
}
.hh-search button:hover { background: var(--accent-hover); }

.hh-filters {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
}
.hh-sort {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  padding: var(--space-xs) var(--space-sm);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-semi);
  cursor: pointer;
  max-width: 15rem;
  /* Ohne min-width:0 zieht ein <select> sich auf die Breite seiner LÄNGSTEN
     Option auf — bei „Alle Abgeordneten" sind das Einträge wie
     „Abgeordnete:r Nummer 79 (BÜNDNIS 90/DIE GRÜNEN)", und das Feld schießt
     seitlich aus dem Hero heraus. */
  min-width: 0;
}
.hh-sort option { color: var(--ink); background: var(--surface); }

/* ── Fraktionsbalken ───────────────────────────────────────────────────────
   Diagramm und Filter in einem. Jeder Balken ist ein <button> mit aria-pressed
   (früher ein <div onclick> — per Tastatur unerreichbar).
   Zahl über dem Balken, Name darunter, beides IMMER sichtbar: Höhe allein ist
   keine Angabe, und Fraktionsfarben sind für Farbfehlsichtige unbrauchbar. */
.hh-chips {
  display: flex;
  gap: var(--space-3xs);
  align-items: flex-end;
  padding: var(--space-md) 0 var(--space-2xs);
  flex-wrap: wrap;
}
.hh-bar-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3xs);
  min-width: 56px;
  padding: var(--space-2xs) var(--space-3xs);
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  font: inherit;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
.hh-bar-wrap:hover { background: rgb(255 255 255 / 0.14); }
.hh-bar-wrap[aria-pressed='true'] {
  background: rgb(255 255 255 / 0.20);
  box-shadow: inset 0 0 0 1.5px var(--hero-ink);
}
.hh-bar-cnt {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  color: var(--hero-ink);
  min-height: 14px;
}
.hh-bar {
  width: 34px;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  /* Gedämpft im Ruhezustand, voll bei Auswahl — die Sättigung verstärkt die
     Auswahl, trägt sie aber nicht allein (dafür Kontur + aria-pressed). */
  opacity: 0.72;
  transition: opacity var(--dur-fast) var(--ease);
}
.hh-bar-wrap[aria-pressed='true'] .hh-bar,
.hh-bar-wrap:hover .hh-bar { opacity: 1; }
/* Feste Höhe für zwei Zeilen. Ohne sie schiebt ein dreizeiliger Fraktionsname
   („BÜNDNIS 90/DIE GRÜNEN") seinen Balken nach oben, und die Reihe steht nicht
   mehr auf einer gemeinsamen Grundlinie — dann vergleicht das Auge Höhen, die
   gar nicht vergleichbar sind. Längere Namen werden sichtbar gekürzt; die
   vollständige Fassung steckt im aria-label des Knopfs. */
.hh-bar-nm {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  color: var(--hero-ink);
  text-align: center;
  width: 72px;
  min-height: 2.5em;
  line-height: 1.25;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── Wortverlauf ───────────────────────────────────────────────────────────
   Die große erzählende Grafik: wie oft der Suchbegriff über die Zeit fiel.
   Speist sich aus der Facettenverteilung über das Datumsfeld (siehe
   webapp.py, /api/{key}/search) und erscheint nur, wenn eine Suche läuft —
   ohne Suchbegriff hätte der Verlauf keine Aussage. */
.hh-trend {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-md) var(--space-md) var(--space-sm);
  margin-bottom: var(--space-md);
}
.hh-trend[hidden] { display: none; }
.hh-trend-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  flex-wrap: wrap;
  margin-bottom: var(--space-sm);
}
.hh-trend-title {
  font-size: var(--text-md);
  font-weight: var(--weight-black);
  color: var(--ink);
}
.hh-trend-sub {
  font-size: var(--text-xs);
  font-weight: var(--weight-semi);
  color: var(--ink-3);
}
/* Auf schmalen Geräten darf die Grafik seitlich scrollen, statt die Seite
   umzubrechen. Der Körper selbst scrollt nie horizontal. */
.hh-trend-plot { position: relative; overflow-x: auto; overflow-y: hidden; }
.hh-trend svg { display: block; width: 100%; height: auto; }
/* min-width NUR am großen Diagramm, das in einem eigenen Scrollbehälter sitzt.
   Stand die Regel auf `.hh-trend svg`, erwischte sie auch die 246px breiten
   Fraktionsfelder — die liefen dann 87px über ihre Zelle hinaus. */
.hh-trend-plot svg { min-width: 320px; }
/* ── Diagramm-Grundelemente ────────────────────────────────────────────────
   BEWUSST NICHT auf .hh-trend beschränkt. Dieselben Klassen zeichnen auch die
   Sparkline im Abgeordnetenpanel; solange die Regeln unter .hh-trend hingen,
   bekamen deren Balken gar keine Füllung (SVG-Standard: schwarz) und die
   Achsenbeschriftung blieb unformatiert. */
.axis-line { stroke: var(--line-strong); stroke-width: 1; }
.grid-line { stroke: var(--line); stroke-width: 1; }
.axis-label {
  fill: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: var(--weight-semi);
  font-variant-numeric: tabular-nums;
}
.axis-unit {
  fill: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}
/* --bar wird inline je Reihe gesetzt (Fraktionsfarbe); ohne Angabe gilt die
   Strukturfarbe. Ein `stroke`/`fill`-ATTRIBUT würde hier verlieren —
   Präsentationsattribute stehen in der Kaskade unter jeder CSS-Regel. */
.trend-line {
  fill: none;
  stroke: var(--bar, var(--structure));
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
  /* Die Linie behält ihre 2px, egal wie stark die SVG skaliert wird — sonst
     wird sie im schmalen Kleinfeld zum Faden und im breiten zum Balken. */
  vector-effect: non-scaling-stroke;
}
.trend-dot {
  fill: var(--bar, var(--structure));
  /* Kontur gegen die Fläche: FDP-Gelb erreicht hell 1,18:1, CDU-Schwarz dunkel
     1,05:1 — ohne Ring verschwinden die Punkte in ihrem eigenen Untergrund. */
  stroke: var(--surface);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}
/* Fadenkreuz und hervorgehobener Punkt beim Überfahren. */
.trend-cross {
  stroke: var(--line-strong);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
.trend-dot-on { pointer-events: none; }
/* Trefferfläche: unsichtbar, aber viel breiter als der Punkt — 3px Radius
   trifft niemand mit der Maus. */
.trend-hit { fill: transparent; }

.trend-tip {
  position: absolute;
  z-index: var(--z-tooltip);
  pointer-events: none;
  background: var(--ink);
  color: var(--surface);
  border-radius: var(--radius-sm);
  padding: var(--space-2xs) var(--space-xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-semi);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  box-shadow: var(--shadow-overlay);
}
.trend-tip b { font-weight: var(--weight-black); margin-right: var(--space-2xs); }
.trend-tip[hidden] { display: none; }
/* Textfassung derselben Daten für Screenreader. Eine Grafik, die nur als Bild
   existiert, ist dort schlicht nicht vorhanden. */
.hh-trend-table caption { text-align: left; }

/* Hinweiszeile: benennt die gemeinsame Skala oder erklärt, warum kein Diagramm
   erscheint. Steht bewusst als Fließtext da, nicht als Symbol. */
.hh-trend-note {
  font-size: var(--text-xs);
  color: var(--ink-3);
  font-weight: var(--weight-semi);
  max-width: var(--measure-ui);
  margin-bottom: var(--space-sm);
}
.hh-trend-sub2 {
  font-size: var(--text-2xs);
  font-weight: var(--weight-black);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-3);
  margin: var(--space-md) 0 var(--space-2xs);
}

/* ── Fraktionsfelder (Small Multiples) ────────────────────────────────────
   Ein Feld je Fraktion statt übereinandergelegter Linien. Der Grund steht
   ausführlich in viewer.js über loadTrend(): mit den echten Fraktionsfarben
   erreichen SPD-Rot und Linke-Magenta als zwei Linien nur ΔE 13,0 bei normalem
   Farbsehen, fraktionslos gegen DIE LINKE nur ΔE 4,5 bei Deuteranopie, und
   CDU-Schwarz kommt auf dunklem Grund auf 1,05:1. Getrennte Felder mit
   ausgeschriebenem Namen lösen alle drei Probleme auf einmal. */
.hh-trend-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-sm);
}
.hh-trend-cell {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--space-xs) var(--space-sm) var(--space-2xs);
  min-width: 0;
}
.hh-trend-cell figcaption {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-bottom: var(--space-2xs);
  font-size: var(--text-2xs);
}
.hh-trend-cell .tc-dot {
  width: 10px; height: 10px;
  border-radius: 3px;
  flex-shrink: 0;
  /* Kontur, weil CDU-Schwarz und FDP-Gelb sonst je nach Theme mit der Fläche
     verschmelzen (1,05:1 bzw. 1,47:1). */
  box-shadow: inset 0 0 0 1px rgb(128 128 128 / 0.55);
}
.hh-trend-cell .tc-name {
  font-weight: var(--weight-bold);
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hh-trend-cell .tc-n {
  margin-left: auto;
  font-weight: var(--weight-bold);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.hh-trend-cell svg { display: block; width: 100%; height: auto; }
/* In den Kleinfeldern liegt die Linie dichter an der Fläche als im großen
   Diagramm. Ein zusätzlicher Neutralschimmer unter der Linie hält FDP-Gelb
   (hell 1,18:1) und CDU-Schwarz (dunkel 1,05:1) sichtbar, ohne die Farbe
   anzutasten — sie ist hier Datum, nicht Gestaltung. */
.hh-trend-cell .trend-line,
.mp-spark .trend-line {
  paint-order: stroke;
  filter: drop-shadow(0 0 0.6px rgb(128 128 128 / 0.9));
}

/* ── Aktivität im Abgeordnetenprofil ─────────────────────────────────────
   Eckdaten plus Sparkline, in einer Fläche unter dem Profil. Getrennt durch
   eine Linie, nicht durch eine zweite Karte — Karte in Karte ist verboten. */
.mp-activity {
  flex: 0 0 100%;
  border-top: 1px solid var(--line);
  padding-top: var(--space-sm);
  margin-top: var(--space-2xs);
}
.mp-facts {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-lg);
  margin: 0 0 var(--space-sm);
  padding: 0;
  font-size: var(--text-sm);
  color: var(--ink-2);
}
.mp-facts li {
  display: flex;
  align-items: baseline;
  gap: var(--space-2xs);
}
.mp-facts b { color: var(--ink); font-variant-numeric: tabular-nums; }
/* Die Rechenregel steht am Wert, nicht in einer Fußnote. Eine Rangangabe ohne
   ihr Kriterium ist eine Behauptung. */
.mp-fact-note { color: var(--ink-3); font-size: var(--text-2xs); }

.mp-spark { margin-top: var(--space-2xs); }
.mp-spark-h {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--space-2xs);
}
/* Breite begrenzen, NICHT die Höhe. Mit `max-height` gegen `height:auto`
   bekommt die SVG eine Box, deren Seitenverhältnis nicht zur viewBox passt —
   preserveAspectRatio zentriert den Inhalt dann mit breiten Rändern links und
   rechts. */
.mp-spark svg { display: block; width: 100%; max-width: 560px; height: auto; }

/* ── Kennzahlen ───────────────────────────────────────────────────────────── */
.hh-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
}
.hh-stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-sm) var(--space-md);
}
.hh-stat .sl {
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: var(--weight-bold);
  margin-bottom: var(--space-2xs);
}
.hh-stat .sv {
  font-size: var(--text-2xl);
  font-weight: var(--weight-black);
  line-height: 1;
  color: var(--structure);
  font-variant-numeric: tabular-nums;
}
.hh-stat .sv span { font-size: var(--text-base); font-weight: var(--weight-semi); color: var(--ink-3); }

/* ── Werkzeugleiste und aktive Filter ─────────────────────────────────────── */
.hh-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin-bottom: var(--space-sm);
  flex-wrap: wrap;
}
.hh-count { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--ink-2); }
.hh-count b { color: var(--structure); font-variant-numeric: tabular-nums; }
.hh-active-filter {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  padding: var(--space-2xs) var(--space-2xs) var(--space-2xs) var(--space-sm);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
}
/* Das ✕ ist ein eigener Knopf mit eigener Beschriftung — ein Zeichen allein ist
   für Screenreader kein Name. */
.hh-active-filter .x {
  cursor: pointer;
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--surface-inset);
  color: var(--ink-2);
  font: inherit;
  font-weight: var(--weight-bold);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.hh-active-filter .x:hover { background: var(--accent); color: var(--on-accent); }

/* ── Abgeordnetenpanel ────────────────────────────────────────────────────── */
.hh-member {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-lg);
  margin-bottom: var(--space-md);
  display: none;
  gap: var(--space-lg);
  align-items: flex-start;
  flex-wrap: wrap;
}
.hh-member.show { display: flex; }
.hh-member .mp-photo {
  width: 96px;
  height: 120px;
  border-radius: var(--radius-md);
  object-fit: cover;
  flex-shrink: 0;
  border: 2px solid var(--line-strong);
}
.hh-member .mp-info { flex: 1 1 320px; min-width: 0; }
.hh-member .mp-name {
  font-size: var(--text-xl);
  font-weight: var(--weight-black);
  color: var(--ink);
  line-height: var(--leading-tight);
}
.hh-member .mp-role { font-size: var(--text-xs); font-weight: var(--weight-bold); margin-top: var(--space-3xs); }
.hh-member .mp-rows {
  margin-top: var(--space-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  font-size: var(--text-sm);
  color: var(--ink-2);
}
.hh-member .mp-rows a {
  color: var(--structure);
  font-weight: var(--weight-semi);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.hh-member .mp-socials { display: flex; gap: var(--space-xs); margin-top: var(--space-sm); flex-wrap: wrap; }
.hh-member .mp-socials a {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-pill);
  background: var(--surface-inset);
  color: var(--ink-2);
  border: 1px solid var(--line-strong);
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.hh-member .mp-socials a:hover { border-color: var(--structure); color: var(--structure); }
/* Ausschüsse: eigene Spalte rechts. Getrennt durch eine Linie, nicht durch eine
   zweite Karte — verschachtelte Karten sind verboten. */
.hh-member .mp-committees {
  flex: 0 0 300px;
  align-self: stretch;
  font-size: var(--text-xs);
  color: var(--ink-2);
  border-left: 1px solid var(--line);
  padding-left: var(--space-lg);
}
.hh-member .mp-committees-h { font-weight: var(--weight-bold); color: var(--ink); margin-bottom: var(--space-xs); }
.hh-member .mp-committees ul {
  margin: 0;
  padding-left: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

/* ── Trefferliste ─────────────────────────────────────────────────────────── */
.hh-list { display: flex; flex-direction: column; gap: var(--space-sm); }
.hh-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: box-shadow var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.hh-card:hover {
  box-shadow: var(--shadow-hover);
  border-color: var(--line-strong);
  transform: translateY(-2px);
}
.hh-card-body { padding: var(--space-md) var(--space-md); min-width: 0; position: relative; }
.hh-card-top {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-wrap: wrap;
  margin-bottom: var(--space-2xs);
}
.hh-avatar {
  width: 40px; height: 40px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--line-strong);
  flex-shrink: 0;
}
.hh-avatar-ph {
  width: 40px; height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-weight: var(--weight-black);
  font-size: var(--text-base);
  flex-shrink: 0;
}
/* Seit der Sprechername ein echtes <a href="…/abgeordnete/{id}"> ist (statt
   eines <button>), damit Suchmaschinen und Mittelklick die Profilseite finden,
   braucht es text-decoration:none — sonst unterstriche der Browser ihn
   dauerhaft, und die Hover-Regel darunter verlöre ihre Wirkung. */
.hh-speaker {
  font-size: var(--text-md);
  font-weight: var(--weight-black);
  color: var(--ink);
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  text-align: left;
  text-decoration: none;
}
.hh-speaker:hover { color: var(--structure); text-decoration: underline; text-underline-offset: 2px; }
.hh-pbadge {
  font-size: var(--text-2xs);
  font-weight: var(--weight-black);
  letter-spacing: 0.03em;
  border-radius: var(--radius-xs);
  padding: 2px var(--space-xs);
}
.hh-role { font-size: var(--text-2xs); font-weight: var(--weight-bold); color: var(--ink-3); }
/* Namensblock rechts vom Foto.
   Breit: `display: contents` löst den Block auf, Name / Fraktion / Datum sind
   dann wieder direkte Flex-Kinder von .hh-card-top und stehen wie bisher in
   einer umbrechenden Zeile.
   Schmal (siehe @media unten): derselbe Block wird zur zweizeiligen Spalte. */
.hh-ident { display: contents; }
.hh-ident-name { display: flex; align-items: center; min-width: 0; }
.hh-ident-sub {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-wrap: wrap;
  min-width: 0;
}
.hh-card-meta {
  font-size: var(--text-xs);
  color: var(--ink-3);
  font-weight: var(--weight-semi);
  display: flex;
  gap: var(--space-xs);
  flex-wrap: wrap;
  align-items: center;
  font-variant-numeric: tabular-nums;
}
.hh-card-meta .sep { opacity: 0.6; }
.hh-top {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--structure);
  margin-bottom: var(--space-xs);
  line-height: var(--leading-snug);
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  text-align: left;
  display: inline-block;
}
.hh-top:hover { text-decoration: underline; text-underline-offset: 2px; }

/* Redetext. Dieselbe Familie wie die Oberfläche — der Registerwechsel läuft
   über Größe, Gewicht und Zeilenabstand: 15px statt 13px, regulärer statt
   mittlerer Schnitt, 1,7 Zeilenabstand.

   Der Wortlaut nutzt die volle Kartenbreite. Das ist eine bewusste
   Entscheidung gegen die übliche Empfehlung von 60–75 Zeichen je Zeile: bei
   1100px Shell-Breite werden daraus rund 120 Zeichen. Der erhöhte
   Zeilenabstand von 1,7 ist die Gegenmaßnahme — er hält den Rücksprung ans
   Zeilenende auffindbar, was bei langen Zeilen die eigentliche Schwierigkeit
   ist. */
.hh-snippet, .hh-full {
  font-size: var(--text-read);
  font-weight: var(--weight-normal);
  line-height: var(--leading-read);
  color: var(--ink-2);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.hh-snippet { cursor: pointer; }
.hh-full { display: none; margin-top: var(--space-3xs); }
.hh-full em, .hh-snippet em { font-style: italic; color: var(--ink-3); }
.hh-card.open .hh-snippet { display: none; }
.hh-card.open .hh-full { display: block; }

.hh-expand {
  margin-top: var(--space-xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--structure);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  background: none;
  border: none;
  font-family: inherit;
  padding: var(--space-3xs) 0;
}
.hh-expand:hover { text-decoration: underline; text-underline-offset: 2px; }
.hh-expand svg { transition: transform var(--dur-base) var(--ease); }
.hh-card.open .hh-expand svg { transform: rotate(180deg); }

.hh-play {
  float: right;
  margin: 0 0 var(--space-xs) var(--space-sm);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  background: var(--structure);
  color: var(--on-structure);
  border-radius: var(--radius-pill);
  padding: var(--space-2xs) var(--space-sm);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  transition: background var(--dur-fast) var(--ease);
}
/* Das Dreieck ist Flex-Kind eines inline-flex-Knopfes und würde sonst
   mitschrumpfen, sobald die Beschriftung ("Rede ansehen") den Platz knapp macht
   — dieselbe Vorsichtsmaßnahme wie bei .hh-search svg. Die Maße doppeln die
   width/height-Attribute aus viewer.js, damit CSS gewinnt und nicht das
   Flex-Layout. */
.hh-play svg { width: 11px; height: 11px; flex-shrink: 0; }

/* Teilen: oben rechts, LINKS von .hh-play (siehe Dokumentreihenfolge in
   viewer.js:card — beide float:right, .hh-share-top steht im Markup NACH
   .hh-play und rückt dadurch an dessen linke Seite). Bewusst nur ein Icon
   und schmaler/leiser als .hh-play: zwei gleich schwere Pillen nebeneinander
   in einer so schmalen Ecke hätten sich gegenseitig erdrückt, und "Protokoll"
   ist die wichtigere der beiden Aktionen. */
.hh-share-top {
  float: right;
  margin: 0 var(--space-2xs) var(--space-xs) var(--space-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: none;
  border: 1px solid var(--line-strong);
  color: var(--ink-3);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.hh-share-top:hover { background: var(--surface-inset); color: var(--ink); }
/* Kurze Bestätigung nach dem Kopieren — --vote-for ist das einzige Grün im
   System (sonst nichts als "positiv" ausgezeichnet). */
.hh-share-top.kopiert { color: var(--vote-for); border-color: var(--vote-for); }
.hh-play:hover { background: var(--structure-hover); }

/* ── Zustände ─────────────────────────────────────────────────────────────── */
.hh-empty {
  text-align: center;
  padding: var(--space-3xl) var(--space-lg);
  color: var(--ink-2);
  font-weight: var(--weight-semi);
}
.hh-empty-title {
  display: block;
  font-size: var(--text-xl);
  font-weight: var(--weight-black);
  color: var(--ink);
  margin-bottom: var(--space-xs);
}
.hh-empty-hint { display: block; font-size: var(--text-base); color: var(--ink-3); max-width: 46ch; margin: 0 auto; }

/* Platzhalterkarten statt einer Textzeile: die Liste behält ihre Höhe, statt
   beim Eintreffen der Treffer zu springen. */
.hh-loading { display: flex; flex-direction: column; gap: var(--space-sm); }
.hh-skeleton {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-md);
  height: 132px;
}
.hh-skeleton span {
  display: block;
  height: 12px;
  border-radius: var(--radius-xs);
  background: var(--surface-inset);
  margin-bottom: var(--space-sm);
}
.hh-skeleton span:nth-child(1) { width: 38%; height: 16px; }
.hh-skeleton span:nth-child(2) { width: 92%; }
.hh-skeleton span:nth-child(3) { width: 84%; }
.hh-skeleton span:nth-child(4) { width: 60%; }
@media (prefers-reduced-motion: no-preference) {
  .hh-skeleton span { animation: hh-pulse 1.4s var(--ease) infinite; }
  @keyframes hh-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
}

/* ── Seitenzahlen ─────────────────────────────────────────────────────────── */
.hh-pager {
  display: flex;
  justify-content: center;
  gap: var(--space-2xs);
  margin-top: var(--space-lg);
  flex-wrap: wrap;
}
.hh-pager button {
  min-width: 38px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: var(--space-2xs) var(--space-sm);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--ink-2);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.hh-pager button:hover:not(:disabled):not(.on) { border-color: var(--structure); color: var(--structure); }
.hh-pager button.on { background: var(--structure); color: var(--on-structure); border-color: var(--structure); }
.hh-pager button:disabled { opacity: 0.45; cursor: default; }
/* Die Auslassung ist keine Schaltfläche, nur eine Marke. */
.hh-pager .gap { border: none; background: none; color: var(--ink-3); min-width: 20px; }

/* ── Schmale Ansichten ────────────────────────────────────────────────────── */
@media (max-width: 760px) {
  .hh-stats { grid-template-columns: repeat(2, 1fr); }
  .hh-header-inner .right { display: none; }
  .hh-hero { padding: var(--space-md); }
  .hh-sort { flex: 1 1 100%; width: 100%; max-width: none; }
  /* Eine Zeile, egal wie viele Fraktionen (brandenburg/sachsen haben bis zu 8) —
     ohne nowrap brach das in 3er-Reihen um, und die Balkenhöhen (die einzige
     Aussage des Diagramms) waren dann nicht mehr auf einer Grundlinie
     vergleichbar. flex-shrink:0 verhindert, dass die Balken beim Scrollen
     gequetscht werden statt Platz zu überlaufen. */
  .hh-chips { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; gap: var(--space-2xs); }
  .hh-bar-wrap { flex-shrink: 0; padding: var(--space-3xs); }
  /* Den Abstand macht NICHT die Lücke, sondern die Beschriftung: sie ist 72px
     breit und spreizt damit jeden 34px-Balken auf 88px Rasterabstand. 56px
     bringt das auf 64px herunter, ohne einen echten Fraktionsnamen zu brechen —
     gemessen in Montserrat 700 bei 11px ist das längste Wort, das auf eine
     Zeile muss, „BÜNDNIS" mit 54,6px (danach „WÄHLER" aus FREIE WÄHLER mit
     52,2px). Unter 56px bräche zuerst „BÜNDNIS". */
  .hh-bar-nm { width: 56px; }
}
@media (max-width: 720px) {
  .hh-member .mp-committees {
    flex-basis: 100%;
    border-left: none;
    padding-left: 0;
    border-top: 1px solid var(--line);
    padding-top: var(--space-sm);
  }
  /* Kopf der Redenkarte: Foto links, rechts daneben zwei Zeilen — oben der Name,
     darunter Fraktion und Datum. Vorher standen Name, Fraktion und Datum als drei
     vollbreite Blöcke untereinander; auf einem Telefon war damit die halbe Karte
     verbraucht, bevor ein Wort der Rede zu lesen war.
     .hh-ident gibt sein `display: contents` hier auf und wird zur Spalte —
     dadurch rutschen Fraktion und Datum in EINE Zeile neben das Foto. */
  .hh-card-top { flex-wrap: nowrap; align-items: center; }
  .hh-ident {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3xs);
    min-width: 0;
  }
  /* Der Name darf umbrechen statt das Foto zu quetschen. */
  .hh-ident-name { flex-wrap: wrap; }
  .hh-ident-sub { row-gap: var(--space-3xs); }

  /* Der "Protokoll (PDF)"-Knopf schwamm bisher per float in der Kopfzeile —
     ein float verengt aber die verfügbare Breite eines BFC-Elements (hier:
     die Flex-Spalte .hh-ident) über seine GESAMTE Höhe, nicht nur neben sich
     selbst. Auf schmalen Geräten reichte das nicht mehr für "Fraktion ·
     Datum" in einer Zeile, und das Datum rutschte in eine dritte Zeile.
     position:absolute nimmt den Knopf komplett aus dem Textfluss — die
     Kopfzeile bekommt ihre volle Breite zurück, nur der Name (erste Zeile)
     spart sich per padding-right den Platz, den der Knopf oben rechts
     überdeckt. */
  .hh-play {
    position: absolute;
    top: var(--space-md);
    right: var(--space-md);
    float: none;
    margin: 0;
    /* Der Knopf muss in die Höhe der Namenszeile passen, sonst reicht er in die
       Zeile darunter. Mit --leading-normal (1.6) wird er 26px hoch, die
       Namenszeile ist 19px — die 5px Überstand zwangen dazu, auch die zweite
       Zeile freizuhalten, und „SPD · Präsidentin · 04.06.2026" brach dann in
       eine dritte Zeile um. Mit --leading-tight sind es 20px, die zweite Zeile
       beginnt darunter und darf die volle Breite nutzen. */
    line-height: var(--leading-tight);
  }
  /* Nur die ERSTE Zeile spart sich den Platz — die zweite liegt vollständig
     unter dem Knopf und braucht nichts.
     136px = 126px Knopfbreite + 10px Luft. Gemessen an der längsten
     Beschriftung, die parliaments.py vergibt: „Protokoll (PDF)" in Montserrat
     700 bei 11px, zwölf von dreizehn Ländern nutzen sie (die übrigen: „Video
     ansehen", „Rede ansehen", beide kürzer). Wird die Beschriftung länger, ist
     das hier die Stelle, die mitwachsen muss. */
  .hh-ident-name { padding-right: 136px; }

  /* Weniger Vorschauzeilen auf schmalen Geräten — der volle Wortlaut klappt
     ohnehin erst auf Anforderung auf. */
  .hh-card:not(.open) .hh-snippet {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* ── Alle Fraktionen in EINEM Graphen: gestapelte Bänder ───────────────────
   Bänder statt Linien — es kreuzt sich nichts mehr, und die Oberkante ist die
   Gesamtzahl. Zwei Nachbarbänder können mit den offiziellen Parteifarben sehr
   nah beieinanderliegen (GRÜNE gegen SPD: ΔE 2,7 bei Deuteranopie), deshalb
   trennt eine Fuge in FLÄCHENfarbe jedes Band vom nächsten. */
.ts-band {
  fill: var(--bar, var(--structure));
  opacity: 0.92;
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease);
}
/* Die Fuge ist bewusst ein NEUTRALTON und nicht die Flächenfarbe. Die übliche
   Regel „2px Fuge in Flächenfarbe" setzt voraus, dass kein Band der Fläche
   gleicht — hier tut eines das: CDU-Schwarz #151518 liegt im Dunkelmodus auf
   1,05:1 zur Fläche #171a24. Eine Fuge in Flächenfarbe wäre dort unsichtbar,
   und das Band läse sich als Loch im Stapel. Ein halbtransparenter Neutralton
   trennt auf beiden Themes und macht das Band sichtbar, ohne seine Farbe
   anzutasten. */
.ts-fuge {
  fill: none;
  stroke: rgb(128 128 128 / 0.55);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
.tm-swatch-r { fill: var(--bar, var(--structure)); }
/* Der Name trägt Ink-Farbe, nicht die Bandfarbe: FDP-Gelb wäre als Text auf
   heller Fläche mit 1,18:1 unlesbar. Die Farbe steckt im Plättchen daneben. */
.tm-name {
  fill: var(--ink-2);
  font-family: var(--font-ui);
  font-size: 10.5px;
  font-weight: var(--weight-bold);
}
.tm-name .tm-val { fill: var(--ink-3); font-weight: var(--weight-semi); }
.tm-end { cursor: pointer; }
.tm-end.tm-fest .tm-name { fill: var(--ink); text-decoration: underline; text-underline-offset: 2px; }

/* Hervorheben: das angefasste Band tritt vor, die anderen treten zurück. */
.ts-band.tm-aus { opacity: 0.12; }
.tm-name.tm-aus, .tm-swatch-r.tm-aus { opacity: 0.3; }
.ts-band.tm-an { opacity: 1; }
.tm-name.tm-an { fill: var(--ink); }

.hh-trend-multi svg { min-width: 560px; }

.tm-readout {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2xs) var(--space-sm);
  min-height: 2.6em;
  margin-bottom: var(--space-2xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-semi);
  color: var(--ink-3);
}
.tm-ro-jahr {
  font-size: var(--text-md);
  font-weight: var(--weight-black);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.tm-ro-summe {
  font-weight: var(--weight-bold);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.tm-ro-item { display: inline-flex; align-items: center; gap: var(--space-3xs); color: var(--ink-2); }
.tm-ro-item i {
  width: 9px; height: 9px; border-radius: 2px; flex-shrink: 0;
  box-shadow: inset 0 0 0 1px rgb(128 128 128 / 0.55);
}
.tm-ro-item b {
  color: var(--ink);
  font-weight: var(--weight-black);
  font-variant-numeric: tabular-nums;
  margin-left: var(--space-3xs);
}
