/* NXTGN Collaboration Tracker — Custom styles
 *
 * Tailwind macht das Layout, dieses File definiert NXTGN-spezifische
 * Tokens (Farben aus references/ci-web.md) und kleine Komponenten,
 * die in Tailwind unnötig verbos wären. Bewusst minimalistisch:
 * viel Weiß, Pink nur als Akzent, Beige nur für Hervorhebung.
 */

@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap');

:root {
  /* NXTGN Basisfarben */
  --nxtgn-black: #000;
  --nxtgn-white: #fff;
  --nxtgn-beige: #f6f4f0;

  /* Akzent */
  --nxtgn-pink: #e4368c;
  --nxtgn-pink-25: #B91A69;
  --nxtgn-pink-40: #EE86BA;
  --nxtgn-pink-60: #F4AFD1;
  --nxtgn-pink-80: #F9D7E8;

  /* Hauptfarben */
  --nxtgn-yellow: #ffd500;
  --nxtgn-orange: #ee712f;
  --nxtgn-purple: #694a98;
  --nxtgn-purple-80: #e1d8ed;   /* helle Lavendel-Tönung (CI-Palette) */
  --nxtgn-blue:   #1e1e80;

  /* Neutral-Skala (eigene, ergänzt Tailwind nicht – nur für CSS-Variablen) */
  --gray-50:  #fafafa;
  --gray-100: #f4f4f5;
  --gray-200: #e4e4e7;
  --gray-300: #d4d4d8;
  --gray-400: #a1a1aa;
  --gray-500: #71717a;
  --gray-600: #52525b;
  --gray-700: #3f3f46;
  --gray-900: #18181b;

  /* Radii */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;

  /* NXTGN Gradient */
  --nxtgn-gradient: linear-gradient(135deg, #ffd500, #ee712f, #e4368c, #694a98, #1e1e80);
}

* {
  box-sizing: border-box;
}

/* Das hidden-Attribut muss IMMER gewinnen — Elemente mit eigenem
 * display (flex/grid, z.B. .fstep) würden das UA-Stylesheet sonst
 * überstimmen und trotz hidden sichtbar bleiben (so blieben beim
 * Funnel-Downgrade die ausgeblendeten Stufen stehen). */
[hidden] { display: none !important; }

html {
  /* Scrollbar darf NIE die Seite verschieben. Zwei Mechanismen kombiniert:
   *  - `overflow-y: scroll` erzwingt einen permanenten vertikalen Scrollbar
   *    (auch wenn der Inhalt kürzer als der Viewport ist). Dadurch ändert
   *    sich die Viewport-Breite nie, egal ob der Inhalt durch Aufklappen
   *    länger/kürzer wird → kein horizontaler Sprung, auch nicht für
   *    zentrierte Modals. Greift in ALLEN Browsern (auch ohne
   *    scrollbar-gutter-Support).
   *  - `scrollbar-gutter: stable` hält den reservierten Platz zusätzlich,
   *    wenn der Scroll-Lock (Modal offen) `overflow: hidden` setzt — so
   *    bleibt die Breite auch dann konstant. */
  overflow-y: scroll;
  scrollbar-gutter: stable;
  /* Erste Linie gegen die horizontale Swipe-Navigation (zurück/vor). Reicht
   * in Chrome/macOS allein NICHT — die Geste wird abgefangen, bevor sie als
   * CSS-Overscroll am Root ankommt; der eigentliche Fix ist der wheel-Handler
   * in app.js. Nur die X-Achse; vertikales Scrollen bleibt unberührt. */
  overscroll-behavior-x: none;
}

/* Min-Höhe auf den Listing-Containern — verhindert dass die Page bei
 * wenigen Filter-Treffern plötzlich kurz wird und der Scroll-Cursor
 * nach oben springt. Die Filter-Bar bleibt damit immer an Ort und Stelle. */
#collab-results, #org-results { min-height: 70vh; }

/* Sticky-Layer-Offsets — drei Schichten stapeln sich oben am Viewport:
 *   1. page-header  (Titel + Subtitle + Action-Button) → top: 0
 *   2. funnel       (nur Collab-Liste)                 → top: --header-h
 *   3. filter-bar   (Such-/Multi-Select-Form)          → top: --header-h + --funnel-h
 *   4. table thead                                     → top: alle drei
 *
 * `--header-h` und `--filter-h` werden in JS gepflegt (content-abhängig),
 * `--funnel-h` ist statisch und schaltet per :has()-Selector zwischen
 * normal und compact. @property erlaubt smooth Interpolation der CSS-
 * Variablen — ohne die Deklaration würden Browser sie als Strings
 * behandeln und nicht animieren.
 */
@property --funnel-h {
  syntax: '<length>';
  initial-value: 0px;
  inherits: true;
}
@property --filter-h {
  syntax: '<length>';
  initial-value: 64px;
  inherits: true;
}
@property --header-h {
  syntax: '<length>';
  initial-value: 0px;
  inherits: true;
}
@property --meta-h {
  syntax: '<length>';
  initial-value: 0px;
  inherits: true;
}
:root {
  --header-h: 0px;
  --funnel-h: 0px;
  --filter-h: 64px;
  --meta-h: 0px;
}
/* --funnel-h = Höhe des gesamten sticky Funnel-Stacks (Reservoir + Hals +
 * Funnel-Section). Wird per JS aus .funnel-stack gemessen (ResizeObserver) —
 * der Stack-Inhalt ist modus-/compact-abhängig variabel (Reservoir wächst im
 * Impressionen-Modus, alles schrumpft beim Scrollen), darum gemessen statt
 * fixer Werte. Die folgenden CSS-Werte sind nur Pre-JS-Fallbacks gegen einen
 * Layout-Sprung vor der Messung; JS überschreibt sie per Inline-Style. */
:root:has(.funnel-stack) { --funnel-h: 160px; }
:root:has(.funnel-stack.is-compact) { --funnel-h: 116px; }

/* Page-Header — sticky am Viewport-Top, Background opak damit
 * darunter scrollender Inhalt nicht durchscheint. Padding und
 * Trennstrich-Abstand kommen aus `.page-header` selbst — die
 * `.is-sticky`-Variante setzt nur die Sticky-Mechanik, damit der
 * margin-bottom unter dem Strich erhalten bleibt. */
.page-header.is-sticky {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--nxtgn-white);
}
/* Elemente mit negativem Seiten-Margin (KPI-Kachel: margin 0 -9px) ragen
 * über die Content-Spalte hinaus; der Header-Background deckt nur die
 * eigene Box. ::before verbreitert die weiße Fläche um den Überhang,
 * sonst blitzt beim Scrollen der Rand der Kachel seitlich durch. Liegt
 * im Sticky-Stacking-Context hinter dem Header-Inhalt, aber über allem
 * darunter Scrollenden. */
.page-header.is-sticky::before {
  content: "";
  position: absolute;
  inset: 0 -9px;
  background: var(--nxtgn-white);
  z-index: -1;
}

/* Filter-Form selbst soll keine eigene Box im Layout sein — sonst
 * würden die sticky Children nur innerhalb der Form-Höhe kleben und
 * verschwinden, sobald man unter den Form-Endpunkt scrollt. Mit
 * `display: contents` ist das <form> für die Form-Mechanik weiter
 * im DOM (HTMX submittet alle Felder), aber Layout-mäßig "durchsichtig":
 * funnel-section und filter-row werden zu direkten Kindern von .main
 * und können über die gesamte Page-Höhe sticky bleiben. */
#collab-filters,
#org-filters,
#event-filters {
  display: contents;
}

/* Filter-Bar — sticky unterhalb von page-header + Funnel.
 * z-index 40 < Funnel-z-index 50 < page-header-z-index 60: damit
 * das Multi-Select-Popover (innerhalb des Filter-Stacking-Contexts)
 * über der Funnel-Bar liegt, falls es nach oben aufklappt.
 *
 * padding-top: 4px reserviert Platz oben für den Pink-Glow der
 * Multi-Select-Trigger bei Hover/Focus (3px box-shadow); ohne diesen
 * Puffer würde der Glow in die darüber liegende funnel-section ragen
 * und vom dortigen weißen Background verdeckt werden.
 *
 * padding-bottom: 8px hält knappen Abstand zur Liste/Tabelle darunter —
 * genug, dass die filter-row im Sticky-State nicht direkt am Tabellen-
 * Header klebt, aber dicht genug, dass die Filter sichtbar zur Tabelle
 * gehören. */
#collab-filters .filter-row,
#org-filters .filter-row,
#event-filters .filter-row {
  position: sticky;
  top: calc(var(--header-h) + var(--funnel-h));
  z-index: 40;
  background: var(--nxtgn-white);
  /* Haarspalten-Abdeckung nach oben, siehe .funnel-stack. */
  box-shadow: 0 -3px 0 var(--nxtgn-white);
  padding: 4px 0 8px;
  margin-bottom: 0;
}

/* Meta-Zeile (Count + Reset-Button) — sticky direkt unter der Filter-
 * Bar. Bleibt beim Scrollen durch die Tabelle sichtbar, sodass der
 * "Alle Filter aufheben"-Button und der "Y von X"-Counter immer
 * greifbar sind. Höhe wird vom JS als --meta-h gepflegt. */
.list-meta {
  position: sticky;
  top: calc(var(--header-h) + var(--funnel-h) + var(--filter-h));
  z-index: 35;
  background: var(--nxtgn-white);
  /* Haarspalten-Abdeckung nach oben, siehe .funnel-stack. */
  box-shadow: 0 -3px 0 var(--nxtgn-white);
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 2px 0 6px;
  flex-wrap: wrap;
}

/* Count-Text + Review-Chip („Serie ohne Event") als linke Gruppe; das
 * margin-right: auto schiebt den Reset-Button ans rechte Ende. */
.list-meta__lead {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-right: auto;
}

/* Text-Link-artiger Button (z.B. "✕ Alle Filter aufheben") — nimmt
 * nur Text-Höhe ein, kein Button-Padding. Damit ändert sich die
 * Meta-Zeile-Höhe nicht, wenn der Button erscheint/verschwindet. */
.link-action {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--gray-500);
  cursor: pointer;
  text-decoration: none;
  line-height: 1.5;
}
.link-action:hover {
  color: var(--nxtgn-pink);
  text-decoration: underline;
}
.link-action:focus-visible {
  outline: none;
  color: var(--nxtgn-pink);
  text-decoration: underline;
}

/* Tabellen-Header — sticky unter page-header + Funnel + Filter + Meta.
 * sticky auf den <th>-Zellen direkt (nicht auf <thead>) — Browser-
 * kompatibler. Eigener Background pro Cell, sonst scheinen scrollende
 * Rows durch. */
table.data thead th {
  position: sticky;
  top: calc(var(--header-h) + var(--funnel-h) + var(--filter-h) + var(--meta-h));
  /* z-index 36 > .list-meta (35): sonst überdeckt die sticky Meta-Zeile
   * (weißer Background) beim Scrollen die OBERE Header-Linie um ~1px, und
   * vom doppelten Strich bleibt nur die untere sichtbar. Bleibt unter
   * filter-row (40), funnel (50) und page-header (60). */
  z-index: 36;
  /* Beiger Header-Background hebt den thead von den weißen Rows ab.
   * Alle Rahmenlinien (top + seitlich 1px, bottom 2px) sind echte
   * Borders auf den Zellen — dank border-collapse: separate wandern sie
   * beim Sticky mit. Die Top-Linie liegt auf der Zelle (nicht auf dem
   * Wrapper), damit sie an den Eck-Zellen dem border-radius folgt:
   * border-radius rundet nur, wo top UND left/right zusammentreffen. */
  background: var(--nxtgn-beige);
  border-top: 1px solid var(--gray-200);
  /* Haarspalten-Abdeckung nach oben (weiß wie die Meta-Zeile darüber),
   * siehe .funnel-stack. */
  box-shadow: 0 -3px 0 var(--nxtgn-white);
}
/* Obere Ecken des Headers abrunden — deckungsgleich mit dem Wrapper-
 * Radius. Weil die Eck-Zelle jetzt border-top UND border-left/right
 * trägt, kurvt die Linie sauber um die Ecke (statt gerade nach oben zu
 * laufen) — at rest UND beim gestuckten Scroll-Header identisch. */
table.data thead th:first-child { border-top-left-radius: var(--radius-lg); }
table.data thead th:last-child { border-top-right-radius: var(--radius-lg); }
/* Notch-Abdeckung an den Eck-Zellen: der Bereich der Zell-Box AUSSERHALB
 * der Rundung ist transparent — beim gestuckten Header scrollen die Rows
 * darunter durch und ihr weißer BG + die Seiten-Border blitzen als eckige
 * Kante neben der Kurve auf. Ein radial-gradient malt exakt diese Notch
 * mit dem Seiten-Weiß zu: innerhalb des Radius transparent (Beige +
 * Border-Kurve bleiben sichtbar), außerhalb opak. Kinder werden vom
 * border-radius des th nicht geclippt, darum deckt das Pseudo-Element
 * die Notch zuverlässig ab — at rest unsichtbar (weiß auf weiß). */
table.data thead th:first-child::before,
table.data thead th:last-child::after {
  content: '';
  position: absolute;
  /* -1px: über die 1px-Border hinaus bis an die Border-Box-Ecke. */
  top: -1px;
  width: var(--radius-lg);
  height: var(--radius-lg);
  pointer-events: none;
}
table.data thead th:first-child::before {
  left: -1px;
  background: radial-gradient(circle at 100% 100%,
    transparent var(--radius-lg), var(--nxtgn-white) var(--radius-lg));
}
table.data thead th:last-child::after {
  right: -1px;
  background: radial-gradient(circle at 0 100%,
    transparent var(--radius-lg), var(--nxtgn-white) var(--radius-lg));
}

/* Review-Backlog-Filter im Spaltenkopf — kleines Trichter-Icon + Zähler, das
 * eine zur Spalte gehörende „braucht-Sichtung"-Teilmenge filtert (z.B. „Serie
 * ohne Event" in QUELLE, „Typ unklar" in TYP). Warn-Gelb wie .pill--warn; aktiv
 * gefülltes Orange. Vertraute „diese Spalte ist filterbar"-Metapher. */
.th-flex { display: inline-flex; align-items: center; gap: 7px; }
.hdr-filter {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 6px;
  border: 1px solid #fde68a;
  border-radius: 7px;
  background: #fef3c7;
  color: #92400e;
  cursor: pointer;
  text-decoration: none;
  font-family: inherit;  /* auch als <button> (Org-TYP-Kopf) gleich aussehen */
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.hdr-filter:hover { background: #fde68a; text-decoration: none; }
.hdr-filter.is-on { background: #ee712f; border-color: #ee712f; color: var(--nxtgn-white); }
.hdr-filter__ic { width: 13px; height: 13px; display: block; }
.hdr-filter__cnt { font-size: 0.7rem; font-weight: 700; line-height: 1; }

/* Provenienz-Review-Toggle in der list-meta („N zu prüfen"): belegfreie
   KPI-Kandidaten (Stufe 4 ohne Beleg). Gleiche Warn-Optik wie .hdr-filter;
   aktiv gefülltes Orange. */
/* Zwei Review-Backlog-Chips als enge Gruppe (kleiner Gap untereinander),
 * mit dem üblichen Abstand zur Count-Zeile links. */
.review-flags {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: 10px;
}
.review-flags .review-flag { margin-left: 0; }

.review-flag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: 10px;
  padding: 2px 9px;
  border: 1px solid #fde68a;
  border-radius: 999px;
  background: #fef3c7;
  color: #92400e;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.review-flag:hover { background: #fde68a; }
.review-flag.is-on { background: #ee712f; border-color: #ee712f; color: var(--nxtgn-white); }
.review-flag__ic { font-size: 0.8rem; line-height: 1; }

/* Per-Zeile-Warn-Pill in der Status-Spalte: macht eine belegfreie
   KPI-Connection direkt in der Liste sichtbar. */
.pill.pill--review {
  margin-left: 6px;
  background: #fef3c7;
  color: #92400e;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 700;
}

/* „Nicht uns zuzuschreiben": neutraler grauer Pill — bewusst aus Funnel/KPI
 * genommen, aber weiter sichtbar. */
.pill.pill--muted {
  margin-left: 6px;
  background: #e4e4e7;
  color: #52525b;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 700;
}

/* Funnel-Stack — der gemeinsame sticky Container für Reservoir + Hals +
 * Funnel-Section. EIN sticky Block mit opakem weißem BG, der beim Scrollen
 * oben klebt und die durchscrollende Tabelle vollständig verdeckt. Weil alle
 * drei Schichten in EINEM sticky-Element liegen, kann zwischen ihnen keine
 * Lücke entstehen (kein Offset-Matching nötig). --funnel-h = gemessene Höhe
 * dieses Stacks (JS); darunter docken Filter-Bar/Meta/Thead an. */
.funnel-stack {
  position: sticky;
  top: var(--header-h);
  z-index: 50;
  background: var(--nxtgn-white);
  /* Weiße Schulter nach oben: die Sticky-Offsets stapeln GEMESSENE
   * (ganzzahlige) Höhen — bei Browser-Zoom sind die echten Höhen
   * gebrochen und es öffnen sich Haarspalten zwischen den Schichten,
   * durch die scrollender Tabellentext blitzt. Gilt für alle vier
   * Sticky-Schichten (Funnel, Filter, Meta, Tabellenkopf). */
  box-shadow: 0 -3px 0 var(--nxtgn-white);
}

/* Funnel-Section (Collabs) — Inhaltsblock IM Stack (nicht mehr selbst sticky),
 * transitioniert smooth zwischen groß und kompakt. Compact-State wird via
 * Scroll-Position vom JS gesetzt (`.is-compact`-Klasse). */
.funnel-section {
  background: var(--nxtgn-white);
  /* padding-top reserviert Platz oben für Hover-Animationen der Funnel-
   * Cards (translateY(-1px)) und für den is-active-Glow — sonst clipped
   * das overflow: hidden den oberen Rand ab. */
  height: 74px;
  padding-top: 3px;
  overflow: hidden;
  transition: height 220ms ease;
}
.funnel-section.is-compact { height: 50px; }

/* Funnel-Zeile: die 5-Stufen-Pipe (flex:1) plus rechts daneben die kompakte
 * „Abgebrochen"-Ausfahrt. NUR im Main-Funnel — die Mini-Funnel der Detail-
 * Modals nutzen .funnel-pipe ohne .funnel-row und bleiben unberührt. */
.funnel-row { display: flex; align-items: stretch; }
.funnel-row .funnel-pipe { flex: 1; }

/* Pipeline-Layout: die Stufen bilden EINE durchgehende Leiste mit
 * Chevron-Verbindern (kein gap — die Pfeile greifen ineinander). */
.funnel-pipe { display: flex; }

/* „Abgebrochen"-Ausfahrt (Terminal) — kompakte Mini-Stufe rechts am Funnel-
 * Ende, durch eine gestrichelte Linie abgesetzt. Neutral-grau (kein Score),
 * horizontal schmal. Toggelt den bucket=terminal-Filter; Aktiv-State per :has. */
.funnel-terminal {
  align-self: stretch;
  display: flex;
  align-items: center;
  margin-left: 12px;
  padding-left: 12px;
  border-left: 2px dashed var(--gray-200);
  cursor: pointer;
  user-select: none;
}
.funnel-terminal__body {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 4px 9px;
  border-radius: 8px;
  transition: background 120ms ease;
}
.funnel-terminal:hover .funnel-terminal__body { background: var(--gray-100); }
.funnel-terminal__num {
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1;
  color: var(--gray-400);
  transition: font-size 220ms ease, color 120ms ease;
}
.funnel-terminal__cap {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.64rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gray-400);
  white-space: nowrap;
  transition: color 120ms ease;
}
.funnel-terminal__cap svg { width: 11px; height: 11px; flex: 0 0 11px; }
/* Aktiv (Filter an): solides Slate-Chip mit sanftem Verlauf + weicher
 * Elevation — wirkt wie ein bewusst „aus dem Funnel herausgenommener" Zustand,
 * klar abgesetzt vom blassen Ruhezustand, ohne Layout-Shift. */
.funnel-terminal:has(input:checked) .funnel-terminal__body {
  background: linear-gradient(180deg, var(--gray-600), var(--gray-700));
  box-shadow: 0 3px 10px -3px rgba(0, 0, 0, .35);
}
.funnel-terminal:has(input:checked) .funnel-terminal__num { color: var(--nxtgn-white); }
.funnel-terminal:has(input:checked) .funnel-terminal__cap { color: rgba(255, 255, 255, .82); }
/* Beim Scrollen (Compact) mit-verkleinern — analog Reservoir/Cards. */
:root:has(.funnel-section.is-compact) .funnel-terminal__num { font-size: 1rem; }

.funnel-card {
  /* Links mehr Padding: der Chevron-Einschnitt des Vorgängers ragt
   * 14px in die Card hinein. Erste Card hat keinen Einschnitt. */
  padding: 8px 14px 8px 26px;
  transition: padding 220ms ease;
}
.funnel-card:first-child { padding-left: 18px; }
.funnel-section.is-compact .funnel-card {
  padding-top: 5px;
  padding-bottom: 5px;
}
.funnel-card .stat__label {
  font-size: 0.73rem;
  /* Dunkler Ruhe-Text — überschreibt das graue .stat__label-Default
   * (gray-500); aktiv wechselt es auf --score-fg (weiß). */
  color: var(--gray-900);
  transition: font-size 220ms ease;
  display: flex;
  align-items: center;
  gap: 6px;
  /* Nie umbrechen: beim Einklappen der Sidebar fällt der Hover-Zustand sofort
   * weg (voller „POC-Beauftragung"-Text), während die Breite erst über die
   * 220ms-Transition zurückkommt. Ohne nowrap bräche der Text in dem Moment
   * kurz um und ließe ALLE Cards höher springen. Einzeilig → kein Höhensprung
   * (im Transient notfalls kurz horizontal abgeschnitten, vom overflow:hidden
   * der Funnel-Section ohnehin sauber begrenzt). */
  white-space: nowrap;
}
/* Voller Score-Farbton als Dot — die Segmentfläche selbst ist pastell. */
.funnel-card .stat__label .dot {
  width: 8px;
  height: 8px;
  flex: 0 0 8px;
  border-radius: 999px;
  background: var(--score-color);
}
/* Im Ruhezustand (nicht gescrollt) prominente Zahlen; beim Scrollen schrumpfen
 * Card + Label + Zahl merkbar in den Compact-Modus. line-height straff (1.1),
 * damit die größere Zahl in die feste Funnel-Höhe (110px) passt. */
.funnel-card .stat__value { font-size: 1.65rem; line-height: 1.1; transition: font-size 220ms ease, line-height 220ms ease, margin-top 220ms ease; }
/* Wert-Zeile: große „je erreicht"-Zahl, rechts daneben (unten ausgerichtet)
 * die kleine „N aktuell"-Zahl. Bleibt EINE Zeile → die Card-Höhe ändert sich
 * gegenüber dem früheren Ein-Zahl-Stand nicht. */
.funnel-card .stat__valuerow {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.funnel-card .stat__sub {
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--gray-700);
  margin-left: auto;
  transition: font-size 220ms ease;
}
.funnel-section.is-compact .funnel-card .stat__label { font-size: 0.62rem; }
.funnel-section.is-compact .funnel-card .stat__value { font-size: 1rem; line-height: 1.2; }
.funnel-section.is-compact .funnel-card .stat__sub { font-size: 0.66rem; }
/* Aktiv: „aktuell"-Zahl auf die Kontrastfarbe der Stufe, gut lesbar. */
.funnel-card:has(input:checked) .stat__sub {
  color: var(--score-fg, #000);
  opacity: 0.92;
}
/* Stufe 4 „POC-Beauftragung": voller Name solange die Sidebar eingeklappt ist
 * (genug Platz). Bei aufgeklappter Sidebar (.sidebar:hover → schmalerer
 * Content) auf „POC-Beauftr." umschalten, damit das Label einzeilig bleibt
 * und keine Funnel-Card höher wird. .sidebar und .main sind Geschwister. */
.funnel-card .poc-lbl--short { display: none; }
.sidebar:hover ~ .main .funnel-card .poc-lbl--full { display: none; }
.sidebar:hover ~ .main .funnel-card .poc-lbl--short { display: inline; }

/* Trichter-Mund: Impressionen (Score 0) als „Reservoir" über dem 5-Stufen-
 * Funnel — die zweite „Welt", aus der sich der Funnel speist. Bewusst flach/
 * neutral-grau (kein Chevron, kein Score-Farbton). Liegt außerhalb der sticky,
 * fix hohen .funnel-section (scrollt also weg, fließt nicht in --funnel-h ein).
 * Klick = Impressionen-Modus (?impressions=1). Die Größe reagiert auf den
 * Zustand in DREI Stufen (siehe unten): Default kompakt · Impressionen-Modus
 * etwas größer · Funnel-Stufe aktiv am kleinsten. */
.funnel-base {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin: 0;                  /* der .funnel-neck darunter trägt den Abstand */
  padding: 9px 16px;          /* Default: mittlere Größe (zwischen klein & groß) */
  background: color-mix(in srgb, var(--gray-400) 13%, var(--nxtgn-white));
  border: 1px solid color-mix(in srgb, var(--gray-400) 26%, var(--nxtgn-white));
  border-radius: 10px;
  cursor: pointer;
  text-decoration: none;
  color: inherit;
  user-select: none;
  /* Smooth zwischen den drei Zuständen (Padding/Zahl-Größe/Sättigung). */
  transition: padding 240ms cubic-bezier(.4, 0, .2, 1), background 160ms ease,
              border-color 160ms ease, filter 220ms ease;
}
.funnel-base:hover {
  background: color-mix(in srgb, var(--gray-400) 21%, var(--nxtgn-white));
  text-decoration: none;
}
/* Statische Anzeige-Variante (Auswertungen): kein Filter dahinter →
 * keine Klick-Affordanz, kein Hover-Feedback. */
.funnel-base--static,
.funnel-terminal--static { cursor: default; }
.funnel-base--static:hover { background: color-mix(in srgb, var(--gray-400) 13%, var(--nxtgn-white)); }
.funnel-terminal--static:hover .funnel-terminal__body { background: transparent; }
.funnel-base__conv {
  margin-left: auto;
  font-size: 0.78rem;
  color: var(--gray-600);
  white-space: nowrap;
}
.funnel-base__dot {
  width: 8px;
  height: 8px;
  flex: 0 0 8px;
  border-radius: 999px;
  background: var(--gray-400);  /* Score-0-Grau (Impression) */
}
/* Label + Zahl in DERSELBEN Typo wie die Funnel-Cards (stat__label /
 * stat__value): kleines 600er-Label, große 700er-Zahl. */
/* Exakt die Typo der Funnel-Card-Labels (.stat__label): 600er, uppercase,
 * letter-spacing, gray-900 — und font-size skaliert über die Zeilen-Zustände
 * (default/compact/aktiv/geschrumpft) analog zur Zahl. */
.funnel-base__lbl {
  font-weight: 600; font-size: 0.73rem; color: var(--gray-900);
  text-transform: uppercase; letter-spacing: 0.08em; white-space: nowrap;
  transition: font-size 240ms ease, color 160ms ease;
}
.funnel-base__val {
  font-weight: 700; font-size: 1.3rem; line-height: 1.1; color: var(--gray-900);
  transition: font-size 240ms ease, color 160ms ease;
}
.funnel-base__go {
  margin-left: auto; color: var(--gray-400); display: inline-flex;
  transition: transform 240ms ease, color 160ms ease;
}
.funnel-base__go svg { width: 18px; height: 18px; display: block; }

/* Verjüngender „Hals" zwischen Reservoir und Funnel — die Trichter-Metapher.
 * Dezent, schrumpft/verblasst mit dem aktiven Welt-Zustand. */
.funnel-neck {
  width: 38%;
  height: 8px;
  margin: 0 auto 2px;         /* kleiner Abstand zum Funnel darunter */
  background: linear-gradient(
    color-mix(in srgb, var(--gray-400) 13%, var(--nxtgn-white)),
    color-mix(in srgb, var(--gray-400) 4%, var(--nxtgn-white)));
  clip-path: polygon(0 0, 100% 0, 70% 100%, 30% 100%);
  transition: opacity 220ms ease, height 240ms ease, filter 220ms ease;
}

/* ── Zustand A · Impressionen-Modus aktiv ──
 * Der State hängt AUSSCHLIESSLICH am Live-Checkbox-State (:has(input:checked)),
 * NICHT an einer server-gerenderten Klasse. Das ist die verbindliche Regel für
 * Checkbox-Toggle-Chips (siehe Kommentar bei `.funnel-card` unten): das
 * `checked`-Attribut trägt den Initial-Zustand (Server-Render), `:has` spiegelt
 * jede spätere Änderung (Klick, Programmatik, Refresh+Abwählen) ohne JS — so
 * kann KEINE stale Klasse hängenbleiben.
 *
 * Deutlich als AKTIV markiert (sonst grau-auf-grau gegen den ebenfalls grauen,
 * gedimmten Funnel): Score-0-Grau-Füllung + kräftiger Pink-Rahmen + Pink-
 * Akzentbalken links (inset) + Elevation-Schatten, der das Reservoir klar über
 * den flachen, entsättigten Funnel hebt. Pink ist die Marken-Aktiv-Farbe. */
.funnel-base:has(input:checked) {
  padding: 13px 16px;
  /* Kräftiges Grau (Score-0-Thema) statt hellgrau — weißer Text/Zahl
     brauchen genug Kontrast (heller Grund war zu schwach). Der kräftige
     Grund trägt den Aktiv-Zustand allein; Pink-Rahmen ist überflüssig
     (Border transparent, damit die Boxgröße zur Ruhe-Variante passt). */
  background: var(--gray-600);
  border: 1.5px solid transparent;
  /* Kein Pink mehr — der kräftige graue Grund trägt den Aktiv-Zustand
   * allein; nur ein sehr subtiler Drop-Schatten. */
  box-shadow: 0 1px 4px -2px rgba(0, 0, 0, .12);
}
.funnel-base:has(input:checked) .funnel-base__lbl { color: var(--nxtgn-white); font-size: 0.8rem; }
.funnel-base:has(input:checked) .funnel-base__val { font-size: 1.55rem; color: var(--nxtgn-white); }
.funnel-base:has(input:checked) .funnel-base__dot { background: var(--nxtgn-white); }
.funnel-base:has(input:checked) .funnel-base__go { color: rgba(255, 255, 255, .85); transform: rotate(90deg); }
/* „inaktive Welt" dimmen + den Funnel-Status-Filter ausblenden (im
 * Impressionen-Browser ist die Funnel-Stufe als Status bedeutungslos —
 * alle Zeilen sind Score 0). Über den gemeinsamen Vorfahren (:root:has),
 * damit es unabhängig von der DOM-Reihenfolge greift. */
:root:has(.funnel-base input:checked) .funnel-neck { opacity: .4; filter: grayscale(.6); }
/* WICHTIG: das Dimmen darf NICHT per opacity auf der .funnel-section laufen —
 * die Section ist (beim Scrollen) sticky und trägt den opaken weißen BG, der
 * die durchscrollende Tabelle verdeckt. opacity auf der Section macht AUCH
 * diesen BG transparent → die Tabelle scheint durch (war der Bug). Deshalb:
 * nur grayscale auf der Section (BG bleibt opak), die optische Abschwächung
 * läuft per opacity auf dem VORDERGRUND (Cards + Filter-Bar). */
:root:has(.funnel-base input:checked) .funnel-section { filter: grayscale(.92); }
:root:has(.funnel-base input:checked) .funnel-pipe,
:root:has(.funnel-base input:checked) .funnel-section .filter-bar { opacity: .5; }
:root:has(.funnel-base input:checked) .filter-row__field--status { display: none; }
/* Impression-Status-Filter: das Gegenstück zum Funnel-Status-Feld — nur im
 * Impressionen-Browser sichtbar (dort filtern die Score-0-Stati:
 * Event / Portfolio / Intro / Altbestand). Gleicher Live-State-Mechanismus,
 * kein server-gerendertes Umschalten nötig; app.js verwirft beim Request
 * den Param des jeweils unsichtbaren Felds. */
.filter-row__field.filter-row__field--imp-status { display: none; }
:root:has(.funnel-base input:checked) .filter-row__field.filter-row__field--imp-status { display: flex; }

/* Sticky-Verhalten: Reservoir, Hals und Funnel-Section liegen gemeinsam im
 * sticky .funnel-stack (siehe oben) — das Reservoir bleibt also automatisch
 * oben kleben, ohne eigene sticky-Regel/Offset.
 *
 * Beim Scrollen (Compact) verkleinert sich das Reservoir analog zu den Funnel-
 * Cards — in BEIDEN Modi (Collab UND Impressionen). Die .is-compact-Klasse
 * sitzt auf der .funnel-section; per :root:has greifen wir sie fürs davor
 * liegende Reservoir + den Hals ab. Nur die Größe (Padding/Zahl/Hals) schrumpft;
 * Farbe/Rahmen des aktiven Zustands bleiben über die spezifischeren
 * :has(input:checked)-Regeln erhalten. */
:root:has(.funnel-section.is-compact) .funnel-base { padding: 4px 16px; }
:root:has(.funnel-section.is-compact) .funnel-base__val { font-size: 1rem; }
:root:has(.funnel-section.is-compact) .funnel-base__lbl { font-size: 0.62rem; }
:root:has(.funnel-section.is-compact) .funnel-neck { height: 5px; }

/* ── Zustand B · eine Funnel-Stufe aktiv ──
 * Der Funnel ist die aktive Welt → Reservoir schrumpft auf Minimum und
 * entsättigt leicht; der Hals verblasst. Selektor über den gemeinsamen
 * Vorfahren (:has am :root), weil das Reservoir VOR den Cards steht und es
 * keinen Rückwärts-Geschwister-Selektor gibt. */
:root:has(.funnel-card input:checked) .funnel-base {
  padding: 3px 16px;
  filter: grayscale(.85) opacity(.62);
}
:root:has(.funnel-card input:checked) .funnel-base__val { font-size: 0.92rem; }
:root:has(.funnel-card input:checked) .funnel-base__lbl { font-size: 0.6rem; }
:root:has(.funnel-card input:checked) .funnel-neck { opacity: .25; height: 6px; }

/* Push/Pull-Badge in der Quelle-Spalte (Initiative-Dimension). Pull = Pink
 * (höheres Signal: Corporate ist aktiv auf uns zugekommen), Push neutral. */
.eng-tag {
  display: inline-block;
  margin-top: 3px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.eng-tag--push { background: var(--gray-100); color: var(--gray-600); }
.eng-tag--pull {
  background: color-mix(in srgb, var(--nxtgn-pink) 16%, var(--nxtgn-white));
  color: var(--nxtgn-pink);
}

/* Außerhalb-Funnels-Bar — im Compact-Mode etwas dichter ans Funnel-Grid. */
.funnel-section .filter-bar {
  margin-top: 8px;
  margin-bottom: 0;
  transition: margin-top 220ms ease;
}
.funnel-section.is-compact .filter-bar { margin-top: 4px; }
html, body {
  margin: 0;
  padding: 0;
  font-family: 'Montserrat', system-ui, -apple-system, Arial, sans-serif;
  font-weight: 300;
  color: var(--gray-900);
  background: var(--nxtgn-white);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Browser-Default-Fonts auf Form-Elementen explizit überschreiben.
 * Chrome/Safari nehmen sonst System-Sans für <button>, <input> &
 * Konsorten, auch wenn body Montserrat sagt. */
button, input, select, textarea, optgroup {
  font-family: 'Montserrat', system-ui, -apple-system, Arial, sans-serif;
  font-size: 0.875rem;
  color: inherit;
}
button { font-weight: 500; }

h1, h2, h3, h4, h5, h6 {
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--gray-900);
  margin: 0;
}

h1 { font-size: 1.75rem; line-height: 1.2; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1rem; }

a { color: var(--nxtgn-pink); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------- Layout ---------- */

/* Ausklappbare Icon-Sidebar.
 * Schmal (--sidebar-w) als Default; beim Hover fährt das Panel auf
 * --sidebar-w-open aus und überlagert den Content (position: fixed),
 * damit kein Layout-Shift entsteht. Die Grid-Spalte reserviert nur die
 * schmale Breite. */
:root {
  --sidebar-w: 68px;
  /* Aufgeklappt breit genug für das längste Nav-Label
   * („Projektmanagement", white-space: nowrap). */
  --sidebar-w-open: 230px;
  /* Gemeinsame Kantenlänge für Favicon, NXTGN-Logo-Höhe und Nav-Icon-Slot
   * — hält Brand-Mark und Nav-Icons exakt gleich groß und zentriert. */
  --brand-mark: 34px;
}

.app {
  display: flex;
  align-items: flex-start;
  min-height: 100vh;
}

.sidebar {
  position: sticky;
  top: 0;
  z-index: 20;
  flex: 0 0 var(--sidebar-w);
  display: flex;
  flex-direction: column;
  width: var(--sidebar-w);
  height: 100vh;
  padding: 18px 12px;
  background: var(--nxtgn-white);
  border-right: 1px solid var(--gray-200);
  overflow: hidden;
  /* In-Flow (Flex-Item): das Aufklappen verbreitert die Sidebar und
   * schiebt/staucht den Main-Bereich, statt ihn zu überlagern. */
  transition: flex-basis 170ms ease, width 170ms ease;
}
.sidebar:hover,
.sidebar:focus-within,
.sidebar.is-open {
  flex-basis: var(--sidebar-w-open);
  width: var(--sidebar-w-open);
}

/* ---------- Brand ---------- */

.sidebar__brand {
  display: block;
  padding: 0 5px;
  margin-bottom: 14px;
}
.sidebar__brand:hover { text-decoration: none; }

/* Logo-Morph: ein einziges SVG. Eingeklappt clippt es (overflow:hidden +
 * preserveAspectRatio="…slice") auf das quadratische Favicon-„N"; beim
 * Aufklappen wächst die Breite und der volle NXTGN-Schriftzug fährt ein.
 * Reines CSS, getriggert über dieselben Zustände wie das Panel. */
.sidebar__logobox {
  display: block;
  position: relative;
  height: var(--brand-mark, 34px);
  --nxtgn-dur: 240ms;
  --nxtgn-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}
.sidebar__logo-morph {
  display: block;
  height: var(--brand-mark, 34px);
  width: var(--brand-mark, 34px);            /* eingeklappt: Quadrat */
  overflow: hidden;
  transition: width var(--nxtgn-dur) var(--nxtgn-ease);
}
/* 350 / 124.32 ≈ 2.8153 = Seitenverhältnis des vollen Logos. */
.sidebar:hover .sidebar__logo-morph,
.sidebar:focus-within .sidebar__logo-morph,
.sidebar.is-open .sidebar__logo-morph { width: calc(var(--brand-mark, 34px) * 2.8153); }

/* Favicon-„N" (nx-sec) blendet aus, Schriftzug (nx-prim) ein. */
.sidebar__logo-morph .nx-sec { opacity: 1; transition: opacity calc(var(--nxtgn-dur) * 0.45) ease calc(var(--nxtgn-dur) * 0.25); }
.sidebar:hover .sidebar__logo-morph .nx-sec,
.sidebar:focus-within .sidebar__logo-morph .nx-sec,
.sidebar.is-open .sidebar__logo-morph .nx-sec { opacity: 0; transition: opacity calc(var(--nxtgn-dur) * 0.45) ease; }
.sidebar__logo-morph .nx-prim { opacity: 0; transition: opacity calc(var(--nxtgn-dur) * 0.45) ease; }
.sidebar:hover .sidebar__logo-morph .nx-prim,
.sidebar:focus-within .sidebar__logo-morph .nx-prim,
.sidebar.is-open .sidebar__logo-morph .nx-prim { opacity: 1; transition: opacity calc(var(--nxtgn-dur) * 0.45) ease calc(var(--nxtgn-dur) * 0.15); }

/* Der Hintergrund-Kasten dehnt sich, das „N" rückt an seine Zielposition. */
.sidebar__logo-morph .nx-rect { width: 122.75px; transition: width var(--nxtgn-dur) var(--nxtgn-ease); }
.sidebar:hover .sidebar__logo-morph .nx-rect,
.sidebar:focus-within .sidebar__logo-morph .nx-rect,
.sidebar.is-open .sidebar__logo-morph .nx-rect { width: 349px; }
.sidebar__logo-morph .nx-n { transform: translateX(6.5px); transition: transform var(--nxtgn-dur) var(--nxtgn-ease); }
.sidebar:hover .sidebar__logo-morph .nx-n,
.sidebar:focus-within .sidebar__logo-morph .nx-n,
.sidebar.is-open .sidebar__logo-morph .nx-n { transform: translateX(0); }

/* Buchstaben X-T-G-N staffeln beim Einfahren nach. */
.sidebar__logo-morph .nx-letter { opacity: 0; transform: translateX(-18px); transition: opacity calc(var(--nxtgn-dur) * 0.55) ease, transform calc(var(--nxtgn-dur) * 0.55) var(--nxtgn-ease); }
.sidebar:hover .sidebar__logo-morph .nx-letter,
.sidebar:focus-within .sidebar__logo-morph .nx-letter,
.sidebar.is-open .sidebar__logo-morph .nx-letter {
  opacity: 1; transform: translateX(0);
  transition: opacity calc(var(--nxtgn-dur) * 0.9) ease var(--nx-delay, 90ms), transform calc(var(--nxtgn-dur) * 0.9) var(--nxtgn-ease) var(--nx-delay, 90ms);
}
.sidebar__logo-morph .nx-l1 { --nx-delay: 90ms; }
.sidebar__logo-morph .nx-l2 { --nx-delay: 140ms; }
.sidebar__logo-morph .nx-l3 { --nx-delay: 190ms; }
.sidebar__logo-morph .nx-l4 { --nx-delay: 240ms; }

.sidebar__brand-sub {
  display: block;
  margin-top: 7px;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  white-space: nowrap;
  color: var(--gray-500);
  opacity: 0;
  transition: opacity 150ms ease;
}
.sidebar:hover .sidebar__brand-sub,
.sidebar:focus-within .sidebar__brand-sub,
.sidebar.is-open .sidebar__brand-sub { opacity: 1; }

/* ---------- Nav ---------- */

.nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 5px;
  border-radius: 12px;
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--gray-700);
  white-space: nowrap;
  transition: background 80ms ease, color 80ms ease;
}
.nav-item:hover {
  background: var(--gray-200);
  color: var(--gray-900);
  text-decoration: none;
}
.nav-item.is-active {
  background: var(--nxtgn-pink-80);
  color: var(--nxtgn-pink-25);
  font-weight: 600;
}
.nav-item__icon {
  flex: 0 0 auto;
  width: var(--brand-mark, 34px);
  height: var(--brand-mark, 34px);
  display: flex;
  align-items: center;
  justify-content: center;
  color: inherit;
}
.nav-item__icon svg { width: 24px; height: 24px; }

/* Nav-Labels werden im schmalen Zustand ausgeblendet und beim Aufklappen
 * eingeblendet. (Der Account-Name nutzt display-Toggling, s.u.) */
.nav-item__label {
  opacity: 0;
  transition: opacity 120ms ease;
}
.sidebar:hover .nav-item__label,
.sidebar:focus-within .nav-item__label,
.sidebar.is-open .nav-item__label {
  opacity: 1;
}

/* ---------- Account-Zeile ---------- */

/* Die ganze Account-Zeile ist ein Button und öffnet das Account-Menü
 * (Verlauf, Abmelden) — daher der Button-Reset (background/border/font). */
.sidebar__account {
  margin-top: auto;
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  /* padding-left 6px → Avatar-Mitte (6 + 16) liegt bei x=22px, exakt auf
   * der Mittelachse der Nav-Icons und des Brand-Favicons. Im eingeklappten
   * Zustand sitzt damit nur der Avatar unten links in der Ecke. Kompaktes,
   * symmetrisches Padding → der Hover-Pill ist eine schmale Zeile, nicht der
   * ganze Block unter dem Trenner. */
  padding: 7px 6px;
  margin-bottom: 4px;
  border: 0;
  border-radius: 10px;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  width: 100%;
}
/* Trenner als eigene Linie ÜBER dem Button (8px Abstand) statt border-top —
 * so bleibt die Hover-Fläche vom Strich getrennt und füllt nicht den ganzen
 * Bereich darunter aus. */
.sidebar__account::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -8px;
  height: 1px;
  background: var(--gray-200);
}
/* Hover/Fokus signalisiert die Klickbarkeit der Account-Zeile (öffnet das Menü). */
.sidebar__account:hover {
  background: var(--gray-50);
}
.sidebar:hover .sidebar__account:hover .sidebar__account-name,
.sidebar.is-open .sidebar__account:hover .sidebar__account-name {
  color: var(--nxtgn-pink);
}
.sidebar__account:focus-visible {
  outline: 2px solid var(--nxtgn-pink);
  outline-offset: -2px;
}
.sidebar__account-name { transition: color 90ms ease; }
.sidebar__avatar {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--nxtgn-pink);
  color: #fff;
  font-weight: 700;
  font-size: 0.85rem;
  overflow: hidden;  /* clippt das Profilbild auf den Kreis */
}
.sidebar__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Name + Logout-Icon nur im aufgeklappten Zustand — über display, nicht
 * opacity: sonst nähme der (umbrechende) Name im eingeklappten Zustand
 * vertikalen Platz ein und blähte die Account-Zeile auf. */
/* Feste Endbreite statt flex: 1 1 auto — sonst staucht der Text während
 * der Aufklapp-Animation, der Name bricht kurz über mehrere Zeilen um und
 * springt dann in eine Zeile. Mit fixer Breite legt er sein finales Layout
 * sofort an; das overflow: hidden der Sidebar gibt ihn beim Aufklappen nur
 * frei. Breite = open-Breite minus Sidebar-/Account-Padding, Avatar, Logout
 * und beide Gaps (24 + 12 + 32 + 30 + 20 = 118px). */
.sidebar__account-text {
  display: none;
  flex: 0 0 auto;
  width: calc(var(--sidebar-w-open) - 118px);
  min-width: 0;
  flex-direction: column;
  line-height: 1.2;
}
.sidebar:hover .sidebar__account-text,
.sidebar:focus-within .sidebar__account-text,
.sidebar.is-open .sidebar__account-text { display: flex; }

/* Name darf umbrechen (auch lange Tokens ohne Leerzeichen), damit er nie
 * abgeschnitten wird — die Sidebar ist im aufgeklappten Zustand schmal. */
.sidebar__account-name {
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--gray-900);
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Account-Menü (Popover über der Account-Zeile): fixed, Position setzt das
 * Inline-Script der Sidebar am Avatar-Rect — so funktioniert es auch in der
 * eingeklappten Sidebar (deren overflow: hidden ein absolut positioniertes
 * Menü clippen würde). Card-Look wie die NxtgnSelect-Popovers. */
.sidebar__account-menu {
  position: fixed;
  z-index: 300;   /* über der Sidebar und Sticky-Headern */
  min-width: 256px;
  padding: 6px;
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.16);
}
/* Kopfzeile: großer runder Avatar + Name + E-Mail. */
.sidebar__account-head {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 10px 10px;
}
.sidebar__account-head-avatar {
  flex: 0 0 40px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--nxtgn-pink);
  color: #fff;
  font-weight: 700;
  font-size: 1rem;
}
.sidebar__account-head-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.sidebar__account-head-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.25;
}
.sidebar__account-head-name {
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--gray-900);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar__account-head-mail {
  font-size: 0.78rem;
  color: var(--gray-500);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Feiner Trenner zwischen den Menü-Gruppen. */
.sidebar__account-sep {
  height: 1px;
  margin: 4px 6px;
  background: var(--gray-200);
}
.sidebar__account-item {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: 9px;
  background: none;
  font: inherit;
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--gray-800);
  text-decoration: none;
  cursor: pointer;
  transition: background 80ms ease, color 80ms ease;
}
.sidebar__account-item:hover {
  background: var(--gray-50);
  color: var(--nxtgn-pink);
  text-decoration: none;
}
.sidebar__account-item--danger:hover {
  background: #fff1f0;
  color: #d64545;
}
.sidebar__account-item:focus-visible {
  outline: 2px solid var(--nxtgn-pink);
  outline-offset: -2px;
}
.sidebar__account-item svg { width: 17px; height: 17px; flex: 0 0 17px; color: var(--gray-500); }
.sidebar__account-item:hover svg { color: inherit; }

.main {
  flex: 1 1 auto;
  min-width: 0;
  padding: 14px 40px 80px;
  /* Geringes padding-top, damit die Seiten-Überschrift auf Höhe des
   * Sidebar-Logos sitzt (Sidebar padding-top 18px). Kein max-width —
   * der Main-Bereich füllt den ganzen verfügbaren Viewport-Platz neben
   * der Sidebar. `min-width: 0` lässt ihn beim Aufklappen der Sidebar
   * mitschrumpfen (sonst würde der Flex-Item nicht unter seine
   * Content-Min-Breite gestaucht). */
}

/* Auf sehr breiten Bildschirmen mehr seitlichen Atem — damit Content
 * nicht ganz am Rand klebt, aber trotzdem die Breite nutzt. Das
 * padding-top bleibt klein (Logo-Höhe). */
@media (min-width: 1600px) {
  .main { padding: 16px 56px 80px; }
}
@media (min-width: 2200px) {
  .main { padding: 18px 80px 96px; }
}

.page-header {
  position: relative;
  padding-top: 6px;
  /* padding-bottom inkludiert ZWEI Abstände: oberhalb des Strichs
   * (zw. Subtitle und Strich) und unterhalb (zw. Strich und nächstem
   * Block). Der Strich selbst sitzt als ::after, damit beide Abstände
   * Teil der offsetHeight des Headers werden — das ist wichtig im
   * Sticky-Stack: das Funnel-Element klebt an `top: var(--header-h)`,
   * und --header-h = offsetHeight inkl. Padding. Mit border-bottom
   * hätten wir keinen Abstand unter dem Strich gehabt. */
  padding-bottom: 22px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}
.page-header::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 10px;
  height: 1px;
  background: var(--gray-200);
}
.page-header {
  flex-wrap: wrap;
}
.page-header h1 {
  margin: 0;
}
.page-header .subtitle {
  /* `flex: 1 1 100%` zwingt den Subtitle in eine eigene Zeile, auch
   * wenn er direkt im Header-Flex sitzt (ohne Wrapper-div neben h1).
   * Damit funktionieren BEIDE Markup-Varianten:
   *   <header><div><h1/><p.subtitle/></div><a.btn/></header>
   *   <header><h1/><p.subtitle/></header>                            */
  flex: 1 1 100%;
  margin-top: 4px;
  color: var(--gray-500);
  font-size: 0.88rem;
  max-width: 720px;
}
/* Sticky-Variante beim Scrollen: H1 bleibt gleich groß, nur der Subtitle
 * wird ausgeblendet, damit der fixe Header nicht zu viel Höhe frisst.
 * Die zwei Abstände bleiben proportional erhalten (etwas knapper). */
.page-header.is-sticky-compact {
  padding-top: 6px;
  padding-bottom: 22px;
}
.page-header.is-sticky-compact::after {
  bottom: 12px;
}
.page-header.is-sticky-compact .subtitle {
  max-height: 0;
  margin: 0;
  opacity: 0;
  overflow: hidden;
}
.page-header .subtitle {
  max-height: 60px;
  opacity: 1;
  overflow: hidden;
  transition: max-height 220ms ease, opacity 160ms ease, margin-top 220ms ease;
}

/* ---------- Cards & sections ---------- */

.card {
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  padding: 18px 20px;
}
.card.is-elevated {
  border-color: transparent;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.04);
}

.card-grid {
  display: grid;
  gap: 12px;
}
.card-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.card-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.card-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 980px) {
  .card-grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
}

.stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 16px;
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
}
.stat__label {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--gray-500);
}
.stat__value {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--gray-900);
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 36px;
  padding: 0 14px;
  border-radius: var(--radius-md);
  font-family: 'Montserrat', system-ui, -apple-system, Arial, sans-serif;
  font-weight: 500;
  font-size: 0.85rem;
  letter-spacing: -0.005em;
  line-height: 1;
  border: 1px solid var(--gray-200);
  background: var(--nxtgn-white);
  color: var(--gray-700);
  cursor: pointer;
  transition: background 100ms ease, border-color 100ms ease,
              color 100ms ease, box-shadow 100ms ease;
  text-decoration: none;
  white-space: nowrap;
  user-select: none;
}
.btn:hover {
  background: var(--gray-50);
  border-color: var(--gray-300);
  color: var(--gray-900);
  text-decoration: none;
}
.btn:active {
  background: var(--gray-100);
}
.btn:focus-visible {
  outline: none;
  border-color: var(--nxtgn-pink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--nxtgn-pink) 22%, transparent);
}
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

.btn--primary {
  background: var(--nxtgn-pink);
  color: var(--nxtgn-white);
  border-color: var(--nxtgn-pink);
  font-weight: 600;
  /* Pinker Soft-Schatten — hebt Primär-Aktionen von der Fläche ab. */
  box-shadow: 0 2px 10px rgba(228, 54, 140, 0.30);
}
.btn--primary:hover {
  background: var(--nxtgn-pink-25);
  border-color: var(--nxtgn-pink-25);
  color: var(--nxtgn-white);
  box-shadow: 0 4px 16px rgba(228, 54, 140, 0.38);
}
.btn--primary:active {
  background: var(--nxtgn-pink-25);
  filter: brightness(0.92);
}
.btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--gray-600);
}
.btn--ghost:hover {
  background: var(--gray-100);
  color: var(--gray-900);
  border-color: transparent;
}
.btn--danger {
  color: #b42318;
  border-color: #f0c4bf;
}
.btn--danger:hover {
  background: #fdeceb;
  border-color: #e3a59e;
  color: #911c14;
}
.btn--sm {
  height: 28px;
  padding: 0 10px;
  font-size: 0.78rem;
  border-radius: var(--radius-sm);
}
.btn--block {
  width: 100%;
}

/* ---------- Inputs ---------- */

.input, .select, .textarea {
  width: 100%;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  font-family: 'Montserrat', system-ui, -apple-system, Arial, sans-serif;
  font-size: 0.875rem;
  font-weight: 400;
  background: var(--nxtgn-white);
  color: var(--gray-900);
  transition: border-color 100ms ease, box-shadow 100ms ease,
              background 100ms ease;
}
.input:hover, .select:hover, .textarea:hover {
  border-color: var(--gray-300);
}
.input::placeholder, .textarea::placeholder {
  color: var(--gray-400);
  font-weight: 400;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--nxtgn-pink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--nxtgn-pink) 18%, transparent);
}
.input:disabled, .textarea:disabled, .select:disabled {
  background: var(--gray-50);
  color: var(--gray-400);
  cursor: not-allowed;
}
.textarea {
  height: auto;
  min-height: 96px;
  padding: 10px 12px;
  resize: vertical;
  line-height: 1.5;
}

/* Native <select> bekommt eigenes Chevron statt Browser-Standard */
.select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 36px;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3e%3cpath d='M4 6l4 4 4-4' stroke='%2371717a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 14px;
  cursor: pointer;
}

.label {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--gray-700);
  margin-bottom: 6px;
  letter-spacing: -0.005em;
}

.form-row {
  display: grid;
  gap: 16px;
  margin-bottom: 18px;
}
/* minmax(0, 1fr) statt nacktem 1fr — letzteres entspricht minmax(auto,1fr)
 * und lässt die Grid-Spalte bei langem Inhalt (z.B. lange Org-Namen im
 * Single-Select) über 50% aufquellen. minmax(0, ...) erzwingt das fest
 * geteilte 50/50-Layout; der Wert wird im .nx-select__value mit Ellipsis
 * abgeschnitten. */
.form-row.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.form-row.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Checkbox / Radio basics */
.checkbox-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--gray-700);
  cursor: pointer;
  user-select: none;
}
.checkbox-label input[type="checkbox"],
.checkbox-label input[type="radio"] {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--nxtgn-pink);
}

/* ---------- Pills, dots, badges ---------- */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 9px;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: 999px;
  background: var(--gray-100);
  color: var(--gray-700);
}
.pill .dot {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: currentColor;
}

.bucket {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--gray-700);
}
.bucket .dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
}

/* ---------- Tables ---------- */

.table-wrap {
  /* Die abgerundete Tabellen-Karte wird AUSSCHLIESSLICH von den Zellen
   * gebildet (Borders + radius auf den Eck-Zellen, siehe table.data-
   * Regeln) — der Wrapper trägt KEINEN eigenen Hintergrund, Border oder
   * overflow-Clip. Grund: ein weißer Wrapper-Hintergrund mit eigenem
   * border-radius schaut an den Ecken als heller 1px-Saum hinter den
   * abgerundeten Zell-Ecken hervor (Subpixel-Konkurrenz Clip ↔ Zell-
   * Radius). Ohne Clip bleibt zudem das sticky thead garantiert
   * funktional (overflow: hidden/clip am Ancestor kann sticky brechen).
   * border-radius bleibt nur, damit der Schatten der Rundung folgt. */
  border-radius: var(--radius-lg);
  /* Schatten nur nach UNTEN. |spread| >= blur, sonst reicht der Blur-
   * Ausläufer über die Seiten-/Oberkante und beim Scrollen ziehen sich
   * Schatten-Streifen an der Tabelle hoch. 16/16/-16: oben und seitlich
   * exakt null. */
  box-shadow: 0 16px 16px -16px rgba(0, 0, 0, 0.12);
}
table.data {
  width: 100%;
  /* separate statt collapse: collapsed Borders bleiben bei sticky-Cells
   * beim Scrollen an der alten Position hängen (Chrome) — mit separate
   * wandern die Zell-Borders korrekt mit dem gestuckten Header mit und
   * folgen dem border-radius der Eck-Zellen. */
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.85rem;
}
/* Feste Spaltenbreiten (über <colgroup> gesetzt) statt inhalts-abhängiger
 * Auto-Verteilung — verhindert, dass Spalten beim Filtern springen.
 * Lange Inhalte brechen um (overflow-wrap), auch lange Tokens ohne
 * Whitespace (z.B. URLs/Slugs), damit sie die feste Breite nicht sprengen. */
table.data--fixed { table-layout: fixed; }
table.data--fixed th,
table.data--fixed td { overflow-wrap: anywhere; }
table.data th {
  text-align: left;
  font-weight: 700;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-500);
  padding: 10px 14px;
  background: var(--nxtgn-beige);
  border-bottom: 2px solid var(--gray-200);
}
table.data td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--gray-100);
  vertical-align: middle;
  /* Einheitliche Tabellen-Typo: Basis Regular (400, statt geerbtem
   * Light 300) in gray-700 (volles Schwarz wirkt zu hart), Namen via
   * <strong> in 600 (statt 700) in derselben Farbe, Sekundärinfos
   * weiterhin text-xs muted. Drei klare Stufen statt Wildwuchs. */
  color: var(--gray-700);
  font-weight: 400;
}
table.data strong { font-weight: 600; }
/* Seitliche Rahmenlinien auf den Rand-Zellen (statt auf .table-wrap):
 * wandern beim Sticky mit und kurven dank border-radius der Eck-Zellen
 * sauber um die Ecken. */
table.data th:first-child,
table.data td:first-child { border-left: 1px solid var(--gray-200); }
table.data th:last-child,
table.data td:last-child { border-right: 1px solid var(--gray-200); }
/* Unterer Abschluss der Karte inkl. runder Ecken. */
table.data tr:last-child td { border-bottom: 1px solid var(--gray-200); }
table.data tr:last-child td:first-child { border-bottom-left-radius: var(--radius-lg); }
table.data tr:last-child td:last-child { border-bottom-right-radius: var(--radius-lg); }
table.data tr:hover td { background: var(--gray-50); }

/* Status-Chip: Score-Zahl als rundes farbiges Badge + Label als freier
 * Text. Ersetzt die frühere Voll-Pill, deren Hintergrund bei Zeilen-
 * umbruch breiter als der Text wurde (atomic inline box) — hier ist die
 * Hinterlegung nie breiter als die Zahl, und der Score sticht heraus. */
.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.status-chip__score {
  flex: 0 0 auto;
  width: 23px;
  height: 23px;
  border-radius: 999px;
  display: inline-block;
  /* Zentrierung über line-height = Höhe + text-align — exakt und
   * UNABHÄNGIG vom Kontext. Die frühere flex-Zentrierung saß je nach
   * geerbter line-height (Tabelle 1.5, Modal …) unterschiedlich, und
   * ein pauschales padding schob das ✕ der Terminal-Variante zu tief. */
  line-height: 23px;
  text-align: center;
  padding: 0;
  font-size: 0.8rem;
  /* 700 = schwerstes von Montserrat geliefertes Gewicht; 800 erzwingt
   * Faux-Bold (Browser-Verschmierung), das die Ziffer optisch schräg
   * wirken lässt. */
  font-weight: 700;
}
.status-chip__score--terminal {
  background: var(--gray-200);
  color: var(--gray-600);
  font-size: 0.7rem;
  font-weight: 700;
}
/* Projektmanagement-Stati (bucket 'pm') — violett abgesetzt: weder
 * Funnel-Stufe noch Terminal. */
.status-chip__score--pm {
  background: #efe9f7;
  color: var(--nxtgn-purple);
  font-size: 0.7rem;
  font-weight: 700;
}
.status-chip__label {
  font-weight: 400;
  line-height: 1.3;
  min-width: 0;
}

/* Quelle-Spalte — bewusst in normaler Lesegröße/-farbe (nicht muted). */
.cell-source { font-weight: 400; }

/* ---------- Formular-Validierung (Pflichtfelder) ---------- */

.input.is-invalid,
.select.is-invalid,
.textarea.is-invalid {
  border-color: #d92d20;
  box-shadow: 0 0 0 3px rgba(217, 45, 32, 0.12);
}
/* NxtgnSelect: die Markierung sitzt auf dem Wrapper, gestylt wird der
 * sichtbare Trigger-Button. */
.nx-select.is-invalid .nx-select__trigger {
  border-color: #d92d20;
  box-shadow: 0 0 0 3px rgba(217, 45, 32, 0.12);
}
.field-error {
  color: #b42318;
  font-size: 0.75rem;
  font-weight: 500;
  margin-top: 4px;
}
/* Gefüllte Single-Selects zeigen ihren Wert APP-WEIT in SemiBold — der
 * gewählte Wert darf nicht wie ein Placeholder aussehen. */
.nx-select--single:not(.is-empty) .nx-select__value { font-weight: 600; }
.nx-tree__value:not(.is-placeholder) { font-weight: 600; }

/* Aktive Filter in Filterleisten sind unübersehbar: gefüllter Select/Baum/
 * Suchfeld bekommt pinken Rahmen + zarte Tönung (hängt am LIVE-State der
 * Controls — :has/:checked/:placeholder-shown, nie an server-gerenderten
 * Klassen, die nach Partial-Swaps stale wären). */
.filter-row .nx-select:not(.is-empty) .nx-select__trigger,
.filter-row .nx-tree:has([data-src-inputs] input) .nx-tree__trigger,
.filter-row .input--search:not(:placeholder-shown) {
  border-color: var(--nxtgn-pink);
  /* background-color (nicht die background-Kurzform): sonst überschreibt die
   * Tönung das background-image und die Lupe verschwindet beim Tippen. */
  background-color: color-mix(in srgb, var(--nxtgn-pink) 5%, var(--nxtgn-white));
}
.filter-row .input--search:not(:placeholder-shown) { font-weight: 600; }

/* NXTGN-Checkbox: gezeichnete Box statt Browser-Default. Pink gefüllt mit
 * weißem Häkchen (clip-path), sobald checked — überall verwenden, wo eine
 * native Checkbox als Formular-Feld auftaucht. */
.nx-check {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  margin: 0;
  border: 1.5px solid var(--gray-300);
  border-radius: 5px;
  background: var(--nxtgn-white);
  display: inline-grid;
  place-content: center;
  cursor: pointer;
  transition: background-color .12s ease, border-color .12s ease;
}
.nx-check:hover { border-color: var(--nxtgn-pink-40); }
.nx-check:checked {
  background: var(--nxtgn-pink);
  border-color: var(--nxtgn-pink);
}
.nx-check:checked::after {
  content: "";
  width: 10px;
  height: 10px;
  background: var(--nxtgn-white);
  clip-path: polygon(14% 44%, 0 65%, 40% 100%, 100% 16%, 82% 2%, 38% 66%);
}
.nx-check:focus-visible {
  outline: 2px solid var(--nxtgn-pink);
  outline-offset: 2px;
}

/* Flag-Filter-Chip (Projektmanagement-Board: „Inno Circle").
 * Toggle-Optik hängt am Live-Checkbox-State (:has(input:checked)) —
 * gleiche Aktiv-Sprache wie die übrigen Filter-Controls. */
.filter-row .filter-row__field--flags {
  flex: 0 0 auto;
  flex-direction: row;
  gap: 8px;
  align-items: center;
}
.flagchip {
  display: inline-flex;
  align-items: center;
  padding: 0 14px;
  height: 100%;
  min-height: 34px;
  border: 1px solid var(--gray-300);
  border-radius: 999px;
  background: var(--nxtgn-white);
  font-size: 0.8rem;
  color: var(--gray-600);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.flagchip input { position: absolute; opacity: 0; pointer-events: none; }
.flagchip:hover { border-color: var(--nxtgn-pink-40); }
.flagchip:has(input:checked) {
  border-color: var(--nxtgn-pink);
  background-color: color-mix(in srgb, var(--nxtgn-pink) 8%, var(--nxtgn-white));
  color: var(--nxtgn-pink-25);
  font-weight: 600;
}
.flagchip:has(input:focus-visible) {
  outline: 2px solid var(--nxtgn-pink);
  outline-offset: 2px;
}

/* Bearbeiter:in-Filter: bewusst schmal (wenige, kurze Namen). Doppel-
 * klassig, damit die Regel die generische .filter-row__field-Basis (steht
 * später in der Datei) sicher überstimmt. */
.filter-row .filter-row__field--editor {
  flex: 0 1 150px;
  min-width: 130px;
}

/* ---------- Filter-Icons (Filterleisten über Tabellen/Board) ----------
 * Ein Icon vor dem Titel/Wert jedes echten Filters — gesetzt per
 * data-filter-icon="…" am .filter-row__field. Bewusst NUR in Filterleisten,
 * nicht in Formular-Selects (Erfassen/Edit). SVG-Masken erben die Textfarbe
 * (grau als Placeholder, dunkel/pink wenn aktiv). */
.filter-row__field[data-filter-icon] .nx-select__value::before,
.filter-row__field[data-filter-icon] .nx-tree__value::before {
  content: "";
  display: inline-block;
  flex: 0 0 13px;
  width: 13px;
  height: 13px;
  margin-right: 7px;
  vertical-align: -2px;
  background-color: currentColor;
  -webkit-mask: var(--filter-icon) center / contain no-repeat;
  mask: var(--filter-icon) center / contain no-repeat;
}
/* Zeigt der Wert einen Personen-Avatar (Bearbeiter:in gewählt), ersetzt
 * dieser das Icon. */
.filter-row__field[data-filter-icon] .nx-select__value:has(.chist-actor)::before {
  content: none;
}
.filter-row__field[data-filter-icon="user"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2'/><circle cx='12' cy='7' r='4'/></svg>");
}
.filter-row__field[data-filter-icon="building"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z'/><path d='M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2'/><path d='M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2'/></svg>");
}
.filter-row__field[data-filter-icon="link"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/><path d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/></svg>");
}
.filter-row__field[data-filter-icon="layers"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z'/><path d='m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65'/><path d='m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65'/></svg>");
}
.filter-row__field[data-filter-icon="status"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><circle cx='12' cy='12' r='1.6'/></svg>");
}
.filter-row__field[data-filter-icon="calendar"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><rect width='18' height='18' x='3' y='4' rx='2'/><path d='M16 2v4'/><path d='M8 2v4'/><path d='M3 10h18'/></svg>");
}
.filter-row__field[data-filter-icon="tag"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z'/><circle cx='7.5' cy='7.5' r='1'/></svg>");
}
.filter-row__field[data-filter-icon="shapes"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z'/><rect x='3' y='14' width='7' height='7' rx='1'/><circle cx='17.5' cy='17.5' r='3.5'/></svg>");
}
.filter-row__field[data-filter-icon="database"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><ellipse cx='12' cy='5' rx='9' ry='3'/><path d='M3 5V19A9 3 0 0 0 21 19V5'/><path d='M3 12A9 3 0 0 0 21 12'/></svg>");
}
.filter-row__field[data-filter-icon="package"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z'/><path d='M12 22V12'/><path d='m3.3 7 8.7 5 8.7-5'/></svg>");
}
.filter-row__field[data-filter-icon="kanban"] {
  --filter-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M5 3v14'/><path d='M12 3v8'/><path d='M19 3v18'/></svg>");
}

/* Personen-Avatar in Select-Optionen/-Trigger (Bearbeiter:in): Initialen-
 * Kreis, vom M365-Foto-Loader gegen das echte Bild getauscht. */
/* Avatar in Select-Optionen/-Wert: flex-basis 18px setzt die Breite, aber
 * die Basis-.chist-actor-Regel gäbe 24px Höhe → oval. Höhe + Breite hier
 * explizit gleich setzen (höhere Spezifität gewinnt gegen .chist-actor). */
.nx-select__option .nx-avatar,
.nx-select__value .nx-avatar { flex: 0 0 18px; width: 18px; height: 18px; }
.nx-select__option .nx-avatar img,
.nx-select__value .nx-avatar img { width: 18px; height: 18px; }

/* Paar-Filter („… und (Paar)"): erscheint erst, wenn die erste Org gewählt
 * ist — vorher belegt er nur Platz. Bedingung über den Live-Select-State
 * (leere Option :checked = kein Filter). */
#collab-filters:has(select[name="org"] option[value=""]:checked) .filter-row__field--pair {
  display: none;
}

/* Bestehende Connection im Dup-Check des Erfassen-Modals: kompakte,
 * klickbare Titel-Zeile — Klick öffnet das Detail über dem Formular. */
.dup-row {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 12px;
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--gray-900);
  cursor: pointer;
  transition: border-color 100ms ease;
}
.dup-row:hover { border-color: var(--nxtgn-pink); }

/* Herkunfts-Hinweis unter einem automatisch vorbefüllten Feld (z.B.
 * Datum-aus-Event beim Erfassen) — sichtbarer Text statt Tooltip. */
.field-hint {
  color: var(--nxtgn-pink-25, #b91a69);
  font-size: 0.72rem;
  font-weight: 600;
  margin-top: 4px;
}

/* ---------- Zustands-Sprache der Formular-Modals (.modal-form) ----------
 * leer    = weiß + Light-Placeholder
 * Fokus   = pinker Ring (Basis-Styles oben)
 * gefüllt = SemiBold-Wert + pinkes Häkchen (Single-Selects)
 * Bewusst KEIN getönter Leer-Grund (sah nach „nicht ausfüllbar" aus) —
 * Häkchen + Schriftgewicht tragen den Unterschied. Auf .modal-form
 * gescoped, Filterleisten/Listen bleiben ruhig. */
.modal-form .input,
.modal-form .textarea { font-weight: 600; }
.modal-form .input::placeholder,
.modal-form .textarea::placeholder { font-weight: 300; }

.modal-form .nx-select.is-empty .nx-select__value.is-placeholder { font-weight: 300; }
.modal-form .nx-select:not(.is-empty) .nx-select__value { font-weight: 600; }

/* Gefüllt-Häkchen: JS legt das Element in jedem Single-Select an; sichtbar
 * macht es NUR dieses CSS — in .modal-form und mit gewähltem Wert. */
.nx-select__done { display: none; }
.modal-form .nx-select--single:not(.is-empty) .nx-select__done {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 17px;
  width: 17px;
  height: 17px;
  border-radius: 999px;
  background: var(--nxtgn-pink);
  color: #fff;
}
.nx-select__done svg { width: 10px; height: 10px; }

/* Org-Typ-Tag im Select-Trigger (aus data-type der gewählten Option):
 * macht sichtbar, WAS gewählt wurde — Startup pink, Corporate lila,
 * andere Typen grau. */
.nx-select__orgtype {
  flex: 0 0 auto;
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: #fff;
  background: var(--gray-400);
  border-radius: 4px;
  padding: 2px 6px;
}
.nx-select__orgtype--startup { background: var(--nxtgn-pink); }
.nx-select__orgtype--corporate { background: var(--nxtgn-purple); }


/* ---------- Status-Verwaltung (Modal) ---------- */

.status-mgr__group {
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  padding: 10px 14px 8px;
}
.status-mgr__group-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--gray-100);
}
.status-mgr__group-name {
  flex: 1;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-600);
}
.status-mgr__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 4px;
  border-bottom: 1px solid var(--gray-100);
  font-size: 0.85rem;
}
.status-mgr__row:last-of-type { border-bottom: none; }
.status-mgr__label { flex: 1; min-width: 0; font-weight: 500; }
/* Feste Spalten für Count und Aktionen — die Zahl steht immer an
 * derselben Stelle, unabhängig davon, ob der Papierkorb klickbar ist. */
.status-mgr__count {
  flex: 0 0 150px;
  text-align: right;
  font-size: 0.72rem;
  color: var(--gray-500);
}
.status-mgr__actions {
  flex: 0 0 54px;
  display: flex;
  gap: 2px;
  justify-content: flex-end;
}
/* Edit-/Anlege-Karte: die aktive Zeile hebt sich subtil aus der Liste —
 * pink getönter Grund + Rahmen statt der Listen-Trennlinie (rein visuell,
 * kein erklärender Text). Aufbau: Bezeichnung + Mapping · Erklärung ·
 * Aktionen unten rechts. */
.status-mgr__row.status-mgr__row--form {
  flex-wrap: wrap;
  gap: 8px;
  padding: 12px;
  margin: 6px 0;
  background: color-mix(in srgb, var(--nxtgn-pink) 4%, var(--nxtgn-white));
  border: 1px solid color-mix(in srgb, var(--nxtgn-pink) 24%, var(--nxtgn-white));
  border-radius: var(--radius-md);
  box-shadow: 0 2px 10px color-mix(in srgb, var(--nxtgn-pink) 10%, transparent);
}
.status-mgr__row--form .input,
.status-mgr__row--form .select { height: 32px; padding-top: 0; padding-bottom: 0; }
/* Erklärungs-Feld (description): eigene volle Zeile unter Bezeichnung +
 * Mapping — der Inhalt der Info-Hovercard, direkt hier editierbar. */
.status-mgr__desc-input { flex: 1 0 100%; }
.status-mgr__form-actions {
  flex: 1 0 100%;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* Info-Hovercard neben jedem Status: selbst gestaltetes Hover-Fenster
 * (Haus-Regel: keine title-Tooltips) mit der Status-Erklärung. Öffnet bei
 * Hover UND Tastatur-Fokus; der Inhalt ist ohne Hover über das
 * Edit-Formular der Zeile erreichbar. */
.status-info {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  color: var(--gray-400);
  cursor: default;
}
.status-info:hover,
.status-info:focus-visible { color: var(--gray-600); outline: none; }
.status-info svg { width: 14px; height: 14px; }
.status-info__card {
  display: none;
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%);
  z-index: 30;
  width: max-content;
  max-width: 320px;
  padding: 8px 12px;
  background: var(--nxtgn-white, #fff);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  font-size: 0.78rem;
  font-weight: 400;
  line-height: 1.45;
  color: var(--gray-700);
  white-space: normal;
}
.status-info:hover .status-info__card,
.status-info:focus-visible .status-info__card,
.status-info:focus .status-info__card { display: block; }

/* Sortierbare Spaltenköpfe — Pattern angelehnt an Linear/Stripe:
 *   • Inaktive Spalte: NUR Label, Pfeil unsichtbar.
 *   • Hover: Pfeil erscheint blass neben dem Label, Cursor=pointer.
 *   • Aktive Spalte: einzelner pinker Pfeil (↑/↓) neben dem Label.
 * Keine Boxen, kein Background-Hervorheben — der aktive Pfeil ist der
 * visuelle Anker. */
table.data th.sortable { padding: 0; }
table.data th.sortable a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 12px;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
  transition: color 80ms ease;
}
table.data th.sortable a:hover { color: var(--gray-900); text-decoration: none; }
table.data th.sortable a:focus-visible {
  outline: 2px solid var(--nxtgn-pink);
  outline-offset: -2px;
  border-radius: 4px;
}
/* Sort-Indikator als SVG (chevrons stacked inactive, single chevron active).
 * Wichtig: KEIN Hover-Color-Wechsel am Icon — nur am Header-Text. Das Icon
 * bleibt bei Hover gray, dadurch wirkt der Text-Hover sauberer. Vertikal
 * zentriert via flex auf dem <a>; SVG hat eigene fixe Box, kein Baseline-
 * Versatz mehr. */
table.data th.sortable .sort-ind {
  flex: 0 0 11px;
  width: 11px;
  height: 11px;
  color: var(--gray-400);
}
table.data th.sortable.is-active .sort-ind { color: var(--nxtgn-pink); }
table.data th.sortable.is-active a { color: var(--gray-900); }

/* „Geändert"-Spalte: kompakter Avatar des letzten Bearbeiters (nutzt die
 * chist-actor-Mechanik der Historie inkl. M365-Foto-Loader, Name bei
 * Hover) + Datum der letzten Bearbeitung — eine Zeile. */
.cell-edited { display: inline-flex; align-items: center; gap: 6px; }
.cell-edited__when { font-size: 0.74rem; color: var(--gray-500); }
.chist-actor--xs { flex: 0 0 18px; width: 18px; height: 18px; font-size: 0.56rem; }
.chist-actor--xs img { width: 18px; height: 18px; }

/* ---------- Filter-Bar (Collab-Listing) ---------- */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin-bottom: 12px;
}
.filter-bar__label {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-500);
}

/* Klickbare Pill als Filter-Toggle: heller Ruhezustand mit feiner Kontur,
 * Aktiv = pink (über :has(input:checked), s.u.). .is-active nur für <a>-Chips. */
.pill.pill--link {
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-200);
  color: var(--gray-600);
  padding: 3px 12px;
  text-transform: none;
  letter-spacing: 0;
  text-decoration: none;
  cursor: pointer;
  transition: background 90ms ease, color 90ms ease, border-color 90ms ease;
}
.pill.pill--link:hover {
  background: var(--gray-50);
  border-color: var(--gray-300);
  text-decoration: none;
}
.pill.pill--link.is-active {
  background: var(--nxtgn-pink);
  border-color: var(--nxtgn-pink);
  color: var(--nxtgn-white);
}
.pill.pill--link.is-active:hover {
  background: var(--nxtgn-pink-25);
}

/* Warn-Pill — z.B. series_ambiguous-Collabs, „Neu"-Filter auf /products.
 * Im is-active-Zustand intensiver Orange. */
.pill.pill--warn {
  background: #fef3c7;
  color: #92400e;
}
.pill.pill--link.pill--warn {
  border-color: #f6d98a;
}
.pill.pill--link.pill--warn:hover {
  background: #fde68a;
  border-color: #f0c761;
}
.pill.pill--link.pill--warn.is-active {
  background: #ee712f;
  border-color: #ee712f;
  color: var(--nxtgn-white);
}
.pill.pill--link.pill--warn.is-active:hover {
  background: #d65f1e;
}

/* Sub-Trenner in filter-bar — z.B. zwischen „Funnel"-Pills und
 * „Offene Zuordnung"-Pill, damit die Gruppen optisch getrennt bleiben. */
.filter-bar__divider {
  display: inline-block;
  width: 1px;
  height: 18px;
  background: var(--gray-200);
  margin: 0 4px;
}

/* ---------- Score-Transition-Timeline (Detail-Modal) ---------- */

.timeline {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 8px;
}
.timeline__row {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 14px;
  align-items: start;
  padding: 8px 0 8px 14px;
  border-left: 2px solid var(--gray-200);
  position: relative;
}
.timeline__row::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 12px;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--gray-300);
}
.timeline__row.is-latest { border-left-color: var(--nxtgn-pink); }
.timeline__row.is-latest::before { background: var(--nxtgn-pink); }
.timeline__transition {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.timeline__arrow {
  color: var(--gray-400);
  font-weight: 500;
}
.timeline__when {
  font-size: 0.78rem;
  color: var(--gray-600);
  font-weight: 500;
}
.timeline__meta {
  font-size: 0.7rem;
  color: var(--gray-500);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: 2px;
}
.timeline__notes {
  font-size: 0.8rem;
  color: var(--gray-700);
  margin-top: 4px;
}
.timeline__hint {
  font-size: 0.78rem;
  color: var(--gray-500);
  background: var(--gray-50);
  border-left: 2px solid var(--gray-200);
  padding: 8px 12px;
  margin-top: 8px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}


/* ---------- Toast ---------- */

.toast {
  position: fixed;
  /* Unten rechts, nicht oben: oben läge der Toast über dem
     "＋ Connection"-Button im Sticky-Header und blockierte das
     Serien-Erfassen, bis er ausgeblendet ist. */
  bottom: 24px;
  right: 24px;
  z-index: 1000;   /* über dem Modal-Backdrop (200): Lösch-Undo-/Fehler-Toast
                      erscheint, während das Modal noch offen/am Schließen ist */
  display: flex;
  align-items: flex-start;   /* mehrzeilig (Titel + Sub + Details) */
  gap: 11px;
  padding: 13px 15px;
  border-radius: var(--radius-md);
  background: var(--gray-900);
  color: var(--nxtgn-white);
  font-size: 0.85rem;
  font-weight: 500;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  max-width: 380px;
  opacity: 0;
  pointer-events: none;
  transform: translateY(6px);
  transition: opacity 160ms ease, transform 160ms ease;
}
.toast.is-visible {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
/* Icon-Farbe je Art: Erfolg grün, Fehler rot, Verbindung gelb. Vereinheitlicht
   mit der grünen .callout--ok- / roten .callout--error-Semantik. */
.toast__ic { width: 18px; height: 18px; flex: 0 0 18px; margin-top: 1px; }
.toast.is-success .toast__ic { color: #5fe39a; }
.toast--error .toast__ic { color: #ff6b6b; }
.toast--net .toast__ic { color: #ffd166; }

.toast__body { flex: 1; min-width: 0; }
.toast__title { font-weight: 600; }
.toast__sub {
  font-size: 0.78rem;
  font-weight: 400;
  color: rgba(255,255,255,0.7);
  margin-top: 2px;
  word-break: break-word;
}
.toast__actions { display: flex; gap: 6px; margin-top: 9px; }
.toast__btn {
  background: rgba(255,255,255,0.12);
  border: none;
  color: var(--nxtgn-white);
  font-family: inherit;
  font-weight: 600;
  font-size: 0.78rem;
  cursor: pointer;
  padding: 5px 10px;
  border-radius: 6px;
}
.toast__btn:hover { background: rgba(255,255,255,0.2); }
.toast__x {
  background: transparent;
  border: none;
  color: rgba(255,255,255,0.55);
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 2px 5px;
  flex: 0 0 auto;
}
.toast__x:hover { color: var(--nxtgn-white); }
/* Aufklappbare technische Details (z.B. HTTP-Status + Constraint-Name). */
.toast__details { margin-top: 7px; }
.toast__details summary { font-size: 0.74rem; color: rgba(255,255,255,0.6); cursor: pointer; }
.toast__details pre {
  margin: 6px 0 0;
  font-size: 0.7rem;
  background: rgba(255,255,255,0.08);
  padding: 7px 9px;
  border-radius: 6px;
  white-space: pre-wrap;
  color: rgba(255,255,255,0.85);
  max-height: 120px;
  overflow: auto;
}
/* Ablaufende Zeitleiste — visualisiert die verbleibende Undo-Zeit (Success). */
.toast__bar {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: #5fe39a;
  border-bottom-left-radius: var(--radius-md);
  transform-origin: left;
  animation: toast-drain linear forwards;
}
@keyframes toast-drain { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* Row-Highlight (E) — neu angelegte/geänderte Zeile leuchtet grün auf und
   verblasst. Greift über ?new=<id> → .is-new auf der <tr> im Listing. */
@keyframes row-flash { 0% { background: #eefaf0; } 100% { background: transparent; } }
@keyframes row-flash-bar { 0%, 65% { opacity: 1; } 100% { opacity: 0; } }
tr.is-new td { animation: row-flash 2.4s ease forwards; }
tr.is-new td:first-child { position: relative; }
tr.is-new td:first-child::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: #1f8a4c;
  animation: row-flash-bar 2.4s ease forwards;
}
@media (prefers-reduced-motion: reduce) {
  .toast__bar, tr.is-new td, tr.is-new td:first-child::before { animation: none; }
}

/* ---------- Misc ---------- */

.muted { color: var(--gray-500); }
.text-sm { font-size: 0.8rem; }
.text-xs { font-size: 0.72rem; }
/* <summary> ohne Aufklapp-Dreieck — braucht BEIDE Regeln: list-style deckt
 * Chrome/Firefox ab, Safari zeichnet den Marker über ::-webkit-details-marker. */
summary.no-marker { list-style: none; }
summary.no-marker::-webkit-details-marker { display: none; }
.code {
  font-family: 'SF Mono', Menlo, ui-monospace, monospace;
  font-size: 0.78rem;
  padding: 1px 6px;
  border-radius: 3px;
  background: var(--gray-100);
  color: var(--gray-700);
}
.divider {
  border: 0;
  height: 1px;
  background: var(--gray-200);
  margin: 24px 0;
}
.empty {
  padding: 48px 24px;
  text-align: center;
  color: var(--gray-500);
  font-size: 0.9rem;
  border: 1px dashed var(--gray-200);
  border-radius: var(--radius-md);
}
.empty h3 { color: var(--gray-700); margin-bottom: 6px; }

.gradient-accent {
  height: 4px;
  background: var(--nxtgn-gradient);
  border-radius: 999px;
}

/* ---------- Funnel-Card (Pipeline-Segment, klickbar, multi-select) ----------
 * Die 6 Stufen bilden eine durchgehende Leiste; jedes Segment ist per
 * clip-path zum Chevron geschnitten (Pfeilspitze rechts, Einschnitt
 * links), sodass die Funnel-Metapher zur Form wird. Flächen-Tints laufen
 * direkt über die Vollfarbe der Stufe (--score-color) mit per-Stufe
 * gesetzter Sättigung: --tint im Ruhezustand (schwach, leicht steigend),
 * --tint-active beim Anklicken (springt auf nahezu Vollton). Der Kontrast
 * entsteht also bewusst erst durch die Auswahl. */

.funnel-card {
  flex: 1;
  background: color-mix(in srgb, var(--score-color, var(--gray-300)) var(--tint, 24%), var(--nxtgn-white));
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 50%, calc(100% - 14px) 100%, 0 100%, 14px 50%);
  text-decoration: none;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: 4px;
  position: relative;
  transition: background 120ms ease;
  cursor: pointer;
  user-select: none;
}
/* Erste/letzte Card: außen gerade Kante mit Radius statt Chevron. */
.funnel-card:first-child {
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 50%, calc(100% - 14px) 100%, 0 100%);
  border-radius: 10px 0 0 10px;
}
.funnel-card:last-child {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 14px 50%);
  border-radius: 0 10px 10px 0;
}
.funnel-card:hover {
  background: color-mix(in srgb, var(--score-color, var(--gray-300)) calc(var(--tint, 24%) + 12%), var(--nxtgn-white));
  text-decoration: none;
}
/* Active state — Card springt auf --tint-active (nahezu Vollton) + Unter-
 * kante in einer ABGEDUNKELTEN Stufenfarbe, damit sie sich auch bei voll
 * gesättigten Cards (4/5) klar abhebt. KEIN Layout-Shift. Active-State hängt
 * AUSSCHLIESSLICH am Live-Checkbox-State (:has), nie an einer server-
 * gerenderten `.is-active`-Klasse — siehe verbindliche Regel im Kommentar
 * unten an `.pill.pill--link:has`. */
.funnel-card:has(input:checked) {
  background: color-mix(in srgb, var(--score-color) var(--tint-active, 72%), var(--nxtgn-white));
  box-shadow: inset 0 -4px 0 color-mix(in srgb, var(--score-color), #000 32%);
}
.funnel-card:has(input:checked):hover {
  background: color-mix(in srgb, var(--score-color) calc(var(--tint-active, 72%) + 8%), var(--nxtgn-white));
}
/* Aktiv: Label, Wert und Dot wechseln auf die Kontrastfarbe der Stufe
 * (--score-fg, weiß bei den satten Stufen 3–5, schwarz sonst). */
.funnel-card:has(input:checked) .stat__label {
  color: var(--score-fg, #000);
  opacity: 0.9;
}
.funnel-card:has(input:checked) .stat__label .dot {
  background: var(--score-fg, #000);
}
.funnel-card:has(input:checked) .stat__value {
  color: var(--score-fg, #000);
}

/* ════════════════════════════════════════════════════════════════════════
 * VERBINDLICHE REGEL für Checkbox-Toggle-Chips (Funnel-Cards, Reservoir,
 * Filter-Pills): den Aktiv-Zustand AUSSCHLIESSLICH über :has(input:checked)
 * stylen — NIEMALS zusätzlich über eine server-gerenderte `.is-active`-Klasse.
 *
 * Warum: Diese Chips liegen OUTSIDE des HTMX-Swap-Targets und werden bei
 * Partial-Swaps nicht neu gerendert. Eine server-gesetzte `.is-active`-Klasse
 * bleibt deshalb nach dem Abwählen kleben (klassischer Bug: Refresh im aktiven
 * Zustand → abwählen → Filter ist serverseitig weg, Chip sieht aber weiter
 * aktiv aus). `:has(input:checked)` liest den LIVE-`:checked`-State und spiegelt
 * jede Änderung (Klick, programmatisches .checked=false, Refresh+Abwählen)
 * ohne JS — es gibt keine zweite Quelle der Wahrheit, die veralten kann.
 *
 * Das `checked`-ATTRIBUT auf dem <input> trägt den Initial-Zustand aus dem
 * Server-Render — das genügt, kein `.is-active` als „Fallback" nötig.
 *
 * `.is-active` ist NUR für <a>-Link-Chips erlaubt (z.B. „Serie ohne Event"),
 * die einen Full-Reload auslösen — dort kann die Klasse nie stale werden.
 * ════════════════════════════════════════════════════════════════════════ */
.pill.pill--link:has(input:checked) {
  background: var(--nxtgn-pink);
  border-color: var(--nxtgn-pink);
  color: var(--nxtgn-white);
}
.pill.pill--link:has(input:checked):hover {
  background: var(--nxtgn-pink-25);
}
/* Warn-Variante als Checkbox-Chip (z.B. „Neu"-Status-Filter auf /products,
 * „Typ unklar" auf /organizations) — gleicher Orange-Aktiv-Look wie die
 * .is-active-Link-Variante, nur über :has statt Klasse. */
.pill.pill--link.pill--warn:has(input:checked) {
  background: #ee712f;
  border-color: #ee712f;
  color: var(--nxtgn-white);
}
.pill.pill--link.pill--warn:has(input:checked):hover {
  background: #d65f1e;
}
/* Farbige Status-Chips (/products): im Ruhezustand der Tabellen-Badge-Ton
 * (pill--todo/ok/muted mit !important), im Aktiv-Zustand kräftig gefüllt.
 * !important nötig, um den !important-Ruhezustand zu überschreiben. */
.pill.pill--link.pill--todo:has(input:checked) {
  background: var(--nxtgn-pink) !important;
  border-color: var(--nxtgn-pink);
  color: var(--nxtgn-white) !important;
}
.pill.pill--link.pill--todo:has(input:checked):hover {
  background: var(--nxtgn-pink-25) !important;
}
.pill.pill--link.pill--ok:has(input:checked) {
  background: #1f6b3a !important;
  border-color: #1f6b3a;
  color: var(--nxtgn-white) !important;
}
.pill.pill--link.pill--ok:has(input:checked):hover {
  background: #17532d !important;
}
.pill.pill--link.pill--muted:has(input:checked) {
  background: var(--gray-600) !important;
  border-color: var(--gray-600);
  color: var(--nxtgn-white) !important;
}
.pill.pill--link.pill--muted:has(input:checked):hover {
  background: var(--gray-700) !important;
}

/* ---------- Clickable Table Rows ---------- */

table.data--clickable tbody tr {
  cursor: pointer;
  transition: background 80ms ease;
}
table.data--clickable tbody tr:hover td {
  background: var(--nxtgn-beige);
}

/* ---------- Inline-Edit der Collab-Liste (Klickzonen) ----------
 * Zwei Klickzonen pro Zeile: td[data-inline] (Status/Topic) editiert
 * direkt in der Zelle, der Rest öffnet das Detail-Modal. Affordance
 * rein visuell beim Hover der ZELLE: pinker Inset-Ring + Stift-Icon —
 * kein Platzverbrauch im Ruhezustand. */
.cell-inline { position: relative; }
.cell-inline:hover,
.cell-inline:focus-visible,
.cell-inline.is-editing {
  box-shadow: inset 0 0 0 1.5px var(--nxtgn-pink);
  border-radius: var(--radius-sm);
  outline: none;
}
.cell-inline__pen {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-200);
  color: var(--nxtgn-pink);
}
.cell-inline__pen svg { width: 11px; height: 11px; }
.cell-inline:hover .cell-inline__pen,
.cell-inline:focus-visible .cell-inline__pen,
.cell-inline.is-editing .cell-inline__pen { display: inline-flex; }

/* Aktiver Inline-Edit (Klassen setzt das InlineEdit-Modul, app.js):
 * die editierte Zeile friert ihre Hover-Optik ein — auch wenn die Maus
 * ins Popover/Input wandert weiß man, WO man gerade ändert. Solange
 * editiert wird (.inline-editing am #collab-results), ist das Hovern
 * aller ANDEREN Zeilen aus (Background + Zellen-Ring + Stift + ✎). */
table.data--clickable tbody tr.row-editing td {
  background: var(--nxtgn-beige);
}
#collab-results.inline-editing table.data--clickable tbody
  tr:not(.row-editing):hover td {
  background: transparent;
}
#collab-results.inline-editing tr:not(.row-editing) .cell-inline:hover {
  box-shadow: none;
}
#collab-results.inline-editing tr:not(.row-editing) .cell-inline:hover .cell-inline__pen {
  display: none;
}
#collab-results.inline-editing tr:not(.row-editing):hover .row-act {
  opacity: 0;
}

/* Topic-Input in der Zelle (ersetzt den Zellinhalt bis zum Zeilen-Swap).
 * Der Input trägt den pinken Rahmen dann SELBST — der Zellen-Ring
 * (.is-editing) fällt solange weg, sonst rahmt es doppelt. */
.cell-inline.is-editing:has(.cell-inline__input) { box-shadow: none; }
.cell-inline__input {
  width: 100%;
  font: inherit;
  font-size: 0.85rem;
  color: inherit;
  background: var(--nxtgn-white);
  border: 1.5px solid var(--nxtgn-pink);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  outline: none;
}

/* Zeilen-Aktion (✎ = Modal direkt im Edit-Modus) — schmale letzte Spalte,
 * erst bei Zeilen-Hover/Fokus sichtbar (platzsparend, Zustand visuell
 * statt dauerpräsenter Icon-Wand). Ein Detail-Icon gibt es bewusst nicht:
 * der Klick überall sonst in der Zeile öffnet das Detail. */
td.cell-acts {
  padding-left: 2px !important;
  padding-right: 6px !important;
  text-align: right;
  white-space: nowrap;
}
.row-act {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-left: auto;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 7px;
  background: transparent;
  color: var(--gray-400);
  cursor: pointer;
  opacity: 0;
}
.row-act svg { width: 16px; height: 16px; }
table.data--clickable tbody tr:hover .row-act,
.row-act:focus-visible { opacity: 1; }
.row-act:hover,
.row-act:focus-visible {
  color: var(--nxtgn-pink);
  border-color: var(--gray-200);
  background: var(--nxtgn-white);
  outline: none;
}

/* Status-Popover des Inline-Edits: erbt den NxtgnSelect-Popover-Look
 * (fixed, Koordinaten setzt InlineEdit in app.js). */
.inline-status-pop { z-index: 240; }

/* ---------- Modal ---------- */

/* Body-Scroll-Lock, solange irgendwo ein Modal-Backdrop sichtbar ist.
 * Verhindert, dass Trackpad-Wheel-Events in den Page-Hintergrund laufen,
 * wenn der modal-card__body selbst nicht scrollbar ist (Inhalt kürzer
 * als max-height — `overscroll-behavior: contain` greift dann nicht,
 * weil kein scrollender Container da ist). Body locked → kein Scroll
 * mehr in der Seite; die Wheel-Events landen dann automatisch beim
 * modal-card__body, der ggf. scrollt. :has() ist in allen evergreen
 * Browsern (Chrome 105+, Safari 15.4+, Firefox 121+). */
/* Scroll-Lock bei offenem Modal — auf HTML (dem Scroll-Container, seit
 * html `overflow-y: scroll` trägt), nicht auf body. scrollbar-gutter: stable
 * hält dabei den Gutter reserviert, sodass das Ausblenden des Scrollbars die
 * Seite (und das zentrierte Modal) NICHT verschiebt. */
html:has(.modal-backdrop.is-visible) {
  overflow: hidden;
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 15, 25, 0.45);
  /* -webkit-Präfix: Safari kann backdrop-filter erst ab 18 unpräfixiert. */
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 60px 20px;
  /* Über allen sticky-Layern (page-header z-60, funnel z-50, filter z-40,
   * meta z-35). Modal-Backdrop muss alles abdunkeln, sonst leuchten Titel
   * und Funnel-Bar durch. */
  z-index: 200;
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms ease;
  /* Defensive: kein Scroll im Backdrop selbst und kein Chaining in die
   * Seite dahinter — gilt auch wenn der modal-card__body gar nicht
   * scrollen muss (Inhalt kürzer als max-height). */
  overflow: hidden;
  overscroll-behavior: contain;
}
.modal-backdrop.is-visible {
  opacity: 1;
  pointer-events: auto;
}
.modal-card {
  background: var(--nxtgn-white);
  border-radius: var(--radius-lg);
  max-width: 720px;
  width: 100%;
  max-height: calc(100vh - 120px);
  /* Scroll-Container ist `__body`, nicht `modal-card` selbst — so bleibt
   * der Header oben fixiert (kein sticky nötig, weil er ausserhalb des
   * Scroll-Bereichs liegt). */
  overflow: hidden;
  overscroll-behavior: contain;
  box-shadow: 0 24px 48px rgba(0, 0, 0, 0.18);
  display: flex;
  flex-direction: column;
}
.modal-card__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  padding: 20px 24px 12px;
  border-bottom: 1px solid var(--gray-200);
  /* Bleibt durch flex-shrink:0 ausserhalb des Scroll-Bereichs sichtbar. */
  flex-shrink: 0;
  background: var(--nxtgn-white);
}
.modal-card__head h2 { margin: 0; font-size: 1.2rem; line-height: 1.3; }
.modal-card__body {
  /* padding-top als CSS-Variable, damit der Sticky-thead darunter den
   * Bereich exakt abdecken kann (top: calc(-1 * var)). Ohne diesen
   * Trick scrollt Inhalt durch den 18px padding-top-Bereich zwischen
   * Modal-Header und Sticky-thead durch. */
  --body-pad-top: 18px;
  padding: var(--body-pad-top) 24px 24px;
  display: grid;
  gap: 18px;
  /* Eigenes Scrolling für den Body — der Header darüber bleibt fix.
   * overscroll-behavior: contain verhindert, dass am Scroll-Ende die
   * Seite dahinter mitscrollt (typisches iOS/Trackpad-Verhalten). */
  overflow-y: auto;
  /* Horizontal darf der Modal-Body NIE scrollen — überlange Inhalte
   * werden per Ellipsis/Umbruch gekappt (z.B. Änderungs-Historie). */
  overflow-x: hidden;
  /* Scrollbar-Gutter immer reservieren — wächst der Modal-Inhalt durch
   * Aufklappen (Dup-Check, Event-Feld …) über max-height hinaus, erscheint
   * hier ein interner Scrollbar. Ohne reservierten Gutter würde dessen
   * Auftauchen den Inhalt nach links rücken. */
  scrollbar-gutter: stable;
  flex: 1;
  min-height: 0;
  overscroll-behavior: contain;
  /* Lesbarkeit: Body-Default ist Light (300) — im Modal wirkt das zu
   * schwach. Werte auf Regular anheben, volle Textfarbe. */
  font-weight: 400;
  color: var(--gray-900);
}

/* Sticky Tabellen-Header innerhalb des Modal-Bodies (z.B. Event-Assign-
 * Modal). top: -var(--body-pad-top) klebt den Header bündig an die
 * Border-Top des Bodies, sodass der padding-top-Bereich abgedeckt wird
 * und kein Inhalt durchscheint. background opak + z-index 2 (über
 * hover-Highlights der tbody-Zellen, die bei z-index auto sind). */
.modal-card__body .table-wrap table.data thead th {
  position: sticky;
  top: calc(-1 * var(--body-pad-top));
  background: var(--nxtgn-beige);
  z-index: 2;
}

.modal-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}
/* Spalten-Stabilität: lange Inhalte (Event-Namen, Topics) brechen um,
 * statt die Drittelung zu verschieben. */
.modal-grid > div { min-width: 0; overflow-wrap: anywhere; }
.modal-grid__label {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-500);
  margin-bottom: 4px;
}

.modal-section {
  background: var(--gray-50);
  border-radius: var(--radius-md);
  padding: 14px 16px;
}

.modal-section__head {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-500);
  margin-bottom: 6px;
  display: flex;
  align-items: center;
}
.modal-notes {
  white-space: pre-wrap;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--gray-900);
}

/* „Daraus entstandene Kollaborationen": klickbare Karten-Zeilen. Kopf trägt
   den kleinen „＋ Kollaboration"-Button rechts. Die Zeilen sehen bewusst nach
   anklickbaren Karten aus (Rahmen, Hover-Tönung, Chevron → pink). */
.rel-collabs__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.rel-collab {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  margin-bottom: 6px;
  border: 1px solid var(--gray-200);
  border-radius: 9px;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
.rel-collab:last-child { margin-bottom: 0; }
.rel-collab:hover { background: #f6f4f0; border-color: var(--gray-300); }
.rel-collab__title {
  flex: 1;
  min-width: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--gray-800);
}
.rel-collab__go { display: flex; flex-shrink: 0; color: var(--gray-400); }
.rel-collab__go svg { width: 16px; height: 16px; }
.rel-collab:hover .rel-collab__go { color: var(--nxtgn-pink); }

/* Event-Teilnehmer nach Org-Typ gruppiert. Gruppen-Überschrift + 2-Spalten-
   Namensraster darunter. */
.ptcpt-group { margin-bottom: 12px; }
.ptcpt-group:last-child { margin-bottom: 0; }
.ptcpt-group__head {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--gray-500);
  margin-bottom: 4px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.ptcpt-group__count {
  font-weight: 700;
  color: var(--gray-400);
}
.ptcpt-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 12px; }
.ptcpt { font-size: 0.85rem; padding: 2px 0; }

/* Breite Variante — Detail-Modals mit viel Inhalt (Collab-Detail). */
.modal-card--wide {
  max-width: 920px;
}

/* Schmale Variante — Erfassen-Formulare (kompaktes Single-Purpose-Modal). */
.modal-card--form {
  max-width: 720px;
}

/* Kompaktes Form-Layout im Modal: das modal-card__body ist ein Grid mit
 * gap; die .form-row brächten zusätzlich noch margin-bottom mit → doppelter
 * Abstand. Hier auf einen einzigen, dichteren Rhythmus reduziert. */
.modal-form { gap: 12px; }
.modal-form .form-row { margin-bottom: 0; gap: 12px; }
.modal-form .label { margin-bottom: 4px; }
/* Disambiguierungs-Box (#dup-check): leer trägt sie sonst einen vollen
 * Grid-Gap als Phantom-Abstand; mit Inhalt soll der Abstand zum nächsten
 * Feld dichter sein als der Standard-Rhythmus. */
.modal-form #dup-check:empty { display: none; }
.modal-form #dup-check:not(:empty) { margin-bottom: -4px; }

/* Brand-Header: NXTGN-Gradient mit Noise-Körnung, weiße Typo.
 * Eigener Modifier, damit Form-Modals (Edit, Event-Assign) den
 * neutralen Header behalten. */
.modal-card__head--brand {
  position: relative;
  overflow: hidden;
  background: var(--nxtgn-gradient);
  border-bottom: none;
  padding: 22px 26px 20px;
}
.modal-card__head--brand::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.1  0 0 0 0 0.1  0 0 0 0 0.1  0 0 0 0.18 0'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='0.55'/></svg>");
  mix-blend-mode: overlay;
  pointer-events: none;
}
/* Inhalt über das Noise-Overlay heben. */
.modal-card__head--brand > * { position: relative; z-index: 1; }
.modal-card__head--brand h2 {
  color: var(--nxtgn-white);
  font-size: 1.45rem;
  letter-spacing: -0.01em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}
.modal-card__head--brand .modal-head__eyebrow {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.85);
}
.modal-card__head--brand .modal-head__sub {
  margin-top: 7px;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--nxtgn-white);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.10);
}

/* Icon-Buttons (Bearbeiten/Löschen/Schließen im Modal-Header) —
 * kein Background, kein Schatten; Hover wechselt NUR die Farbe. */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--gray-500);
  transition: color 100ms ease;
}
.icon-btn:hover { color: var(--gray-900); background: none; box-shadow: none; }
.icon-btn svg { width: 18px; height: 18px; }
.icon-btn:focus-visible {
  outline: 2px solid var(--nxtgn-pink);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.icon-btn:disabled,
.icon-btn[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}
.icon-btn--sm { width: 26px; height: 26px; }
.icon-btn--sm svg { width: 15px; height: 15px; }
/* Lösch-Icon in Listen-Zeilen (heller Kontext): Hover → Rot. */
.icon-btn--row-danger:hover { color: #b42318; }
/* Auf dem Gradient-Header: halbtransparentes Weiß, Hover → voll. */
.icon-btn--onbrand { color: rgba(255, 255, 255, 0.72); }
.icon-btn--onbrand:hover { color: var(--nxtgn-white); }
/* Lösch-Icon: Hover in Rot (heller Ton, damit er auf dem dunklen
 * Gradient-Ende lesbar bleibt). */
.icon-btn--onbrand.icon-btn--danger:hover { color: #ff5a5a; }
.icon-btn--onbrand:focus-visible { outline-color: var(--nxtgn-white); }

/* ---------- Funnel-Zeitstrahl (horizontal, links → rechts) ---------- */

.fsteps {
  display: flex;
  align-items: flex-start;
  padding: 6px 2px 2px;
  overflow-x: auto;
}
.fstep {
  flex: 1;
  min-width: 96px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  position: relative;
  text-align: center;
}
/* Connector — Linie zur Vorgänger-Stufe. */
.fstep + .fstep::before {
  content: "";
  position: absolute;
  top: 8px;
  right: 50%;
  width: 100%;
  height: 2px;
  background: var(--gray-200);
  z-index: 0;
}
.fstep__dot {
  width: 18px;
  height: 18px;
  border-radius: 999px;
  background: var(--fstep-color, var(--gray-300));
  border: 3px solid var(--nxtgn-white);
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--fstep-color, var(--gray-300)) 60%, transparent);
  position: relative;
  z-index: 1;
}
.fstep.is-latest .fstep__dot {
  width: 22px;
  height: 22px;
  margin-top: -2px;
  box-shadow:
    0 0 0 2px var(--fstep-color, var(--gray-300)),
    0 0 12px color-mix(in srgb, var(--fstep-color, transparent) 60%, transparent);
}
/* Connector-Linien zielen auf die 18px-Standard-Dots (top: 8px) — der
 * größere Latest-Dot bleibt durch margin-top: -2px zentriert dazu. */
.fstep__label {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--gray-900);
  line-height: 1.25;
}
/* Aktueller Stand: Label als gefüllte Pill in der Score-Farbe (Text-
 * Farbe setzt das Template passend zur Stufe) + „Aktuell"-Unterzeile. */
.fstep.is-latest .fstep__label {
  padding: 3px 11px;
  border-radius: 999px;
  background: var(--fstep-color, var(--gray-300));
  font-weight: 700;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--fstep-color, transparent) 45%, transparent);
}
/* Datum pro Step — bewusst prominent: es ersetzt die frühere
 * Datums-Spalte im Stammdaten-Grid. */
.fstep__date {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--gray-700);
  margin-top: -1px;
}
/* Latest-Pill-Textfarbe als Variable (statt nur inline) — der Edit-Modus
 * togglet is-latest per JS zwischen Steps; die Farbe muss mitwandern. */
.fstep.is-latest .fstep__label { color: var(--fstep-fg, #000); }
/* Editierbares Stufen-Datum direkt im Zeitstrahl (Edit-Modus).
 * Gestrichelter Rahmen als klare „hier kannst du tippen"-Affordance;
 * transparent + kompakt, damit nichts die Label-Pill/Schatten verdeckt.
 * Der data-date-slot ist ein Flex-Item des zentrierenden .fstep —
 * display:block + margin auto zentriert das Input exakt unter der Pill. */
.fstep [data-date-slot] { display: block; margin: 0; }
/* Datum-Pill: das native Date-Input als runde, klar editierbare Pill —
 * vertikal zentriert (flex statt fixer Zeilenhöhe), tabellarische Ziffern,
 * App-Font statt System-Widget-Font. Hover/Fokus = pinker Ring. Die
 * .edit-mirror-Prefixe halten die Pill gegen die generischen
 * .edit-mirror .input-Regeln (Höhe/Padding/Grund) stabil. */
.fstep__date-input,
.edit-mirror .fstep__date-input,
.edit-mirror .modal-section .fstep__date-input {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 4px auto 0;
  width: 130px;
  height: 28px;
  padding: 0 10px;
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--gray-900);
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-300);
  border-radius: 999px;
}
.fstep__date-input::-webkit-datetime-edit { padding: 0; }
.fstep__date-input::-webkit-calendar-picker-indicator { cursor: pointer; opacity: 0.55; }
.fstep__date-input:hover,
.fstep__date-input:focus,
.edit-mirror .modal-section .fstep__date-input:hover,
.edit-mirror .modal-section .fstep__date-input:focus {
  border-color: var(--nxtgn-pink);
  box-shadow: 0 0 0 3px var(--nxtgn-pink-80);
  outline: none;
}

/* Editierbare Felder zeigen ihre Interaktivität schon beim Überfahren
 * (pinker Rahmen), nicht erst im Fokus — gilt für Erfassen- UND Edit-
 * Formulare app-weit. Nach den Basis-Hover-Regeln definiert → gewinnt. */
.modal-form .input:hover:not(:focus),
.modal-form .textarea:hover:not(:focus),
.modal-form .nx-select__trigger:hover {
  border-color: var(--nxtgn-pink-40);
}

/* ---------- Edit-Mirror: Bearbeiten im Detail-Skelett ---------- */
/* Eingabefelder sehen aus wie Eingabefelder: weißer Grund + sichtbarer
 * Rahmen (das Detail zeigt Werte rahmenlos — der Rahmen IST der sichtbare
 * Unterschied zwischen Ansehen und Bearbeiten). Hover pink, Fokus pink. */
.edit-mirror .input,
.edit-mirror .textarea {
  background: var(--nxtgn-white);
  border-color: var(--gray-300);
}
.edit-mirror .input { height: 32px; padding: 4px 9px; }
.edit-mirror .textarea { min-height: 90px; padding: 8px 9px; }
.edit-mirror .input:hover,
.edit-mirror .textarea:hover { border-color: var(--nxtgn-pink-40); }
.edit-mirror .input:focus,
.edit-mirror .textarea:focus { border-color: var(--nxtgn-pink); }
/* Das Funnel-Datum ist ausgenommen: eigene Regeln als Datum-Pill
 * (siehe .fstep__date-input). */
.edit-mirror .modal-section .input:not(.fstep__date-input),
.edit-mirror .modal-section .textarea {
  background: var(--nxtgn-white);
  border-color: var(--gray-300);
}
.edit-mirror .nx-select__trigger {
  background: var(--nxtgn-white);
  border-color: var(--gray-300);
  min-height: 32px;
  height: 32px;
}
.edit-mirror .nx-select__trigger:hover { border-color: var(--nxtgn-pink-40); }
/* Topic-Wert wie im Detail semibold. */
.edit-mirror [data-topic-input] { font-weight: 600; }
/* „automatisch"-Label neben dem Kennengelernt-Label (gesperrte Provenienz
 * bei origin='generated') — sichtbarer Text statt Tooltip. */
.edit-mirror__auto {
  margin-left: 8px;
  font-size: 0.66rem;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  color: var(--gray-400);
  border: 1px dashed var(--gray-300);
  border-radius: 999px;
  padding: 1px 8px;
}
/* Badge im Select-Trigger (z.B. Score-Kreis im Status-Dropdown). */
.nx-select__value.has-badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

/* ---------- Änderungs-Historie (cleane Zeilen-Liste) ---------- */

.history {
  display: flex;
  flex-direction: column;
}
.history__row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 7px 0;
  font-size: 0.82rem;
  border-bottom: 1px solid var(--gray-100);
}
.history__row:last-child { border-bottom: none; }
.history__action {
  flex: 0 0 110px;
  font-weight: 600;
  color: var(--gray-700);
}
.history__row.is-latest .history__action { color: var(--nxtgn-pink); }
/* Kleine Begegnungs-Icons (Touchpoint-Zeilen, Dup-Check-Chips): gleiche
 * Symbole wie die Sidebar-Reiter Events/Produkte. */
.tp-icon {
  width: 15px;
  height: 15px;
  vertical-align: -2.5px;
  margin-right: 3px;
  color: var(--gray-500);
  flex: none;
}

.history__changes {
  flex: 1;
  min-width: 0;
  color: var(--gray-600);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.history__when {
  flex: 0 0 auto;
  color: var(--gray-500);
  font-size: 0.78rem;
}
/* Per-Zeile „auf diesen Stand zurücksetzen" — dezent, Pink-Akzent bei Hover.
 * Auf der aktuellen (jüngsten) Zeile wird das Icon nicht gerendert. */
.history__restore {
  flex: 0 0 auto;
  align-self: center;
  color: var(--gray-400);
}
.history__restore:hover { color: var(--nxtgn-pink); }

/* ═══ Änderungs-Historie — wiederverwendbares Timeline-Element (.chist) ═══
 * In allen Detail-Fenstern. Linie + Punkt sind beide am selben x-Anker
 * (left:9px) und je um die halbe Eigenbreite zurückgezogen → konzentrisch. */
.chist-item { display: flex; align-items: stretch; }
.chist-marker { position: relative; flex: 0 0 18px; }
.chist-line { position: absolute; left: 9px; margin-left: -1px; top: 0; bottom: 0; width: 2px; background: var(--gray-200); }
.chist-item:first-child .chist-line { top: 13px; }
.chist-item:last-child .chist-line { bottom: auto; height: 13px; }
.chist-dot { position: absolute; left: 9px; margin-left: -6px; top: 7px; width: 12px; height: 12px;
  border-radius: 50%; background: #fff; border: 2px solid var(--gray-300); box-sizing: border-box; z-index: 1; }
.chist-item.is-current .chist-dot { background: var(--nxtgn-pink); border-color: var(--nxtgn-pink); box-shadow: 0 0 0 4px var(--nxtgn-pink-80); }
.chist-body { flex: 1; min-width: 0; padding: 0 0 12px 8px; }
.chist-body > summary { list-style: none; cursor: pointer; }
.chist-body > summary::-webkit-details-marker { display: none; }
.chist-row { display: flex; align-items: center; gap: 8px; min-height: 26px; }
.chist-chev { width: 13px; height: 13px; flex: 0 0 13px; color: var(--gray-400); transition: transform 120ms ease; }
.chist-body[open] > summary .chist-chev { transform: rotate(90deg); }
.chist-chev-ghost { flex: 0 0 13px; }
.chist-act { font-weight: 600; font-size: 0.84rem; color: var(--gray-900); white-space: nowrap; }
.chist-item.is-current .chist-act { color: var(--nxtgn-pink); }
.chist-fields { display: flex; flex-wrap: wrap; gap: 5px; min-width: 0; }
.chist-chip { font-size: 0.7rem; font-weight: 500; background: var(--gray-100); color: var(--gray-600);
  border-radius: 999px; padding: 2px 9px; white-space: nowrap; }
.chist-spacer { flex: 1 1 auto; }
.chist-when { font-size: 0.8rem; color: var(--gray-600); font-weight: 500; white-space: nowrap; flex: 0 0 auto; }
/* Akteur: Initialen-Avatar; Name bei Hover (kein title-Tooltip). data-actor-email
 * → JS ersetzt durch das M365-Foto (Graph), Initialen bleiben Fallback. */
/* Fallback-Initialenkreis: helle Lavendel-Tönung statt Beige — Beige ist die
 * Row-Hover-Farbe der Tabellen (.data--clickable tr:hover td), da wäre der
 * Kreis beim Hovern unsichtbar. Lavendel kontrastiert gegen Weiß UND Beige
 * und trägt den Purple-Text mit. */
.chist-actor { position: relative; flex: 0 0 24px; width: 24px; height: 24px; border-radius: 999px;
  background: var(--nxtgn-purple-80); color: var(--nxtgn-purple); font-size: 0.64rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center; }
.chist-actor.has-photo { background: none; }
.chist-actor img { width: 24px; height: 24px; border-radius: 999px; object-fit: cover; display: block; }
/* System-Akteur (auto-resolver, …): Zahnrad-SVG statt Initialen. Neutral
   grau, damit es sich klar von den lila Personen-Avataren abhebt; das SVG
   füllt den Kreis fast aus und wird per flex zentriert (kein Glyph-Versatz). */
.chist-actor--system { background: var(--gray-200); color: var(--gray-600); }
.chist-actor .chist-gear { width: 15px; height: 15px; display: block; }
.chist-actor--xs .chist-gear { width: 12px; height: 12px; }
.chist-name { position: absolute; top: 132%; left: 50%; transform: translateX(-50%); background: var(--gray-900);
  color: #fff; font-size: 0.7rem; font-weight: 500; white-space: nowrap; padding: 3px 8px; border-radius: 6px;
  opacity: 0; pointer-events: none; transition: opacity 100ms ease; z-index: 5; }
.chist-actor:hover .chist-name { opacity: 1; }
.chist-restore { flex: 0 0 24px; width: 24px; height: 24px; display: inline-flex; align-items: center;
  justify-content: center; border: 1px solid var(--gray-300); border-radius: 999px; background: #fff;
  color: var(--gray-600); cursor: pointer; padding: 0; transition: all 100ms ease; }
.chist-restore:hover { border-color: var(--nxtgn-pink); color: var(--nxtgn-pink); background: var(--nxtgn-pink-80); }
.chist-restore svg { width: 13px; height: 13px; }
.chist-vals { margin: 6px 0 0 21px; padding: 8px 11px; background: var(--gray-50); border-radius: var(--radius-sm);
  font-size: 0.78rem; color: var(--gray-600); line-height: 1.7; }
/* Verlaufs-Seite (/history): chist-Timeline als Seiten-Feed. Zusätzlich
 * pro Zeile eine Entitätstyp-Pill + der Datensatz-Name als Link ins
 * jeweilige Detail-Modal. */
.hist-feed { max-width: 980px; }
.hist-feed .chist-body { padding-bottom: 16px; }
.hist-type { background: var(--gray-100); color: var(--gray-600); flex: 0 0 auto; }
.hist-target {
  background: none; border: none; padding: 0; margin: 0; font: inherit;
  font-size: 0.84rem; font-weight: 500; color: var(--gray-900);
  cursor: pointer; text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0; max-width: 340px;
}
.hist-target:hover { color: var(--nxtgn-pink); text-decoration: underline; }
.hist-target--plain { cursor: default; }
.hist-target--plain:hover { color: var(--gray-900); text-decoration: none; }
.chist-f { color: var(--gray-500); }
.chist-old { color: var(--gray-500); text-decoration: line-through; }
.chist-arr { color: var(--gray-400); margin: 0 5px; }
.chist-new { color: var(--gray-900); font-weight: 600; }
/* Aufklappbare Detail-Zeilen (volle Vorher→Nachher-Werte). */
.history__item summary::-webkit-details-marker { display: none; }
.history__item summary::marker { content: ""; }
details.history__item[open] > summary { border-bottom: none; }
/* Affordance: Chevron vor jeder aufklappbaren Zeile (rotiert bei [open])
 * + Hover-Hintergrund — macht sichtbar, DASS sich die Zeile öffnen lässt. */
details.history__item > summary.history__row {
  transition: background 80ms ease;
  border-radius: var(--radius-sm);
}
details.history__item > summary.history__row:hover { background: var(--gray-50); }
details.history__item > summary.history__row::before {
  content: "";
  flex: 0 0 10px;
  width: 10px;
  height: 10px;
  align-self: center;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a1a1aa' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9 18l6-6-6-6'/></svg>") center / contain no-repeat;
  transition: transform 120ms ease;
}
details.history__item[open] > summary.history__row::before { transform: rotate(90deg); }
/* Nicht-aufklappbare Zeilen im selben Block: Platzhalter-Einzug, damit
 * die Aktions-Spalte mit den Chevron-Zeilen fluchtet (10px + 10px gap). */
.history__item > div.history__row { padding-left: 20px; }
.history__details {
  /* Einzug = Chevron (10) + gap (10) + Aktions-Spalte (110) + gap (10). */
  padding: 2px 0 9px 140px;
  font-size: 0.76rem;
  color: var(--gray-600);
  border-bottom: 1px solid var(--gray-100);
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
/* Lange Vorher→Nachher-Werte werden mit „…" gekappt — NIE horizontales
 * Scrolling im Modal. */
.history__details > div {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}


/* ---------- NxtgnSelect — eigene Searchable Dropdowns ----------
 *
 * Eigene Komponente statt Tom Select. Drei Trigger-Klassen:
 *   .nx-select              — Wurzel (Wrapper neben hidden <select>)
 *   .nx-select--single      — Single-Select
 *   .nx-select--multi       — Multi-Select mit Tickboxen + "Alle"-Header
 *   .nx-select--required    — required → kein Clear-Button
 *
 * Sub-Klassen:
 *   .nx-select__trigger     — der sichtbare Pseudo-Select-Button
 *   .nx-select__value       — Anzeige des aktuellen Werts / Placeholders
 *   .nx-select__clear       — × bei optionalen Single-Selects
 *   .nx-select__chevron     — Pfeil ▼
 *   .nx-select__popover     — Dropdown-Panel (default absolute below trigger)
 *   .nx-select__all         — "Alle (de)selektieren"-Header bei Multi
 *   .nx-select__search      — Such-Input im Popover
 *   .nx-select__list        — scrollbare Optionsliste
 *   .nx-select__option      — eine Option
 *   .nx-select__check       — Tickbox-Glyph (Multi) bzw. Häkchen-Glyph
 *   .nx-select__create      — "＋ Neu anlegen: …" Eintrag
 *   .nx-select__empty       — "Keine Treffer für …"
 *   .nx-select__more        — "… N weitere — bitte präziser suchen"
 *
 * Modus-Klassen:
 *   .is-open                — Popover sichtbar
 *   .is-flipped             — Popover über dem Trigger (statt darunter)
 *   .is-empty               — keine Auswahl gesetzt
 *   .is-placeholder         — Value-Span zeigt den Placeholder
 *   .is-selected            — Option ist ausgewählt
 *   .is-active              — Option ist tastatur-/maus-hover
 *   .is-checked             — Multi-Check ist gefüllt
 *   .is-indeterminate       — Multi-Header zeigt Tri-State Mitte
 */

.nx-select {
  position: relative;
  display: inline-block;
  width: 100%;
  font-family: inherit;
  font-size: 0.875rem;
}

.nx-select__trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 40px;
  padding: 6px 12px;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  background: var(--nxtgn-white);
  color: var(--gray-900);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 100ms ease, box-shadow 100ms ease;
}
.nx-select__trigger:hover { border-color: var(--gray-300); }
.nx-select__trigger:focus-visible,
.nx-select.is-open .nx-select__trigger {
  outline: none;
  border-color: var(--nxtgn-pink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--nxtgn-pink) 18%, transparent);
}

.nx-select__value {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nx-select__value.is-placeholder { color: var(--gray-400); }

/* Pill-Modus: mehrere ausgewählte Werte als kleine Kästchen. Wrap erlaubt,
 * Trigger wächst dadurch nach Bedarf in die Höhe. Ab 4+ Pills greift der
 * Fallback "N ausgewählt" (siehe JS) — damit der Trigger nicht ins Uferlose
 * wächst. */
.nx-select__value.has-pills {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  overflow: visible;
  white-space: normal;
  padding: 2px 0;
}
.nx-select__pill {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--nxtgn-pink) 13%, var(--nxtgn-white));
  border: 1px solid color-mix(in srgb, var(--nxtgn-pink) 22%, transparent);
  color: var(--nxtgn-pink);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 0 0 auto;
}
/* "+N" Counter — dezenter als die normalen Pills, ohne pink, damit klar
 * ist dass das ein Zähler ist und kein zusätzlicher Wert. */
.nx-select__pill--count {
  background: var(--gray-100);
  border-color: var(--gray-200);
  color: var(--gray-700);
}

.nx-select__clear {
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath d='M4 4l8 8M12 4l-8 8' stroke='%2371717a' stroke-width='1.6' stroke-linecap='round'/%3e%3c/svg%3e");
  background-position: center;
  background-repeat: no-repeat;
  background-size: 10px 10px;
  cursor: pointer;
  opacity: 0.6;
  transition: background-color 100ms ease, opacity 100ms ease;
}
.nx-select__clear:hover { background-color: var(--gray-100); opacity: 1; }
.nx-select.is-empty .nx-select__clear { display: none; }

.nx-select__chevron {
  flex: 0 0 14px;
  width: 14px;
  height: 14px;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3e%3cpath d='M4 6l4 4 4-4' stroke='%2371717a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
  background-position: center;
  background-repeat: no-repeat;
  pointer-events: none;
  transition: transform 120ms ease;
}
.nx-select.is-open .nx-select__chevron { transform: rotate(180deg); }

/* Popover — schwebt unter dem Trigger. position: fixed (Koordinaten setzt
 * _positionPopover in app.js): so entkommt es JEDEM overflow-Clip — vor
 * allem dem Modal-Body, der absolut positionierte Popovers unten abschnitt
 * (Listenende nur per Modal-Scroll erreichbar). Bei wenig Platz unten
 * flippt das JS auf "is-flipped" (über dem Trigger, bottom-verankert). */
.nx-select__popover {
  position: fixed;
  z-index: 240;
  display: flex;
  flex-direction: column;
  max-height: 340px;
  padding: 6px;
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08),
              0 2px 6px rgba(0, 0, 0, 0.04);
  font-size: 0.875rem;
}
.nx-select__popover[hidden] { display: none; }

.nx-select__all {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--gray-100);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--gray-700);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  user-select: none;
}
.nx-select__all:hover { background: var(--gray-50); }
.nx-select__all-label { flex: 1; }

.nx-select__search {
  width: 100%;
  margin-bottom: 6px;
  padding: 8px 10px;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-sm);
  background: var(--nxtgn-white);
  font: inherit;
  outline: none;
  transition: border-color 100ms ease, box-shadow 100ms ease;
}
.nx-select__search:focus {
  border-color: var(--nxtgn-pink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--nxtgn-pink) 18%, transparent);
}
.nx-select__search::placeholder { color: var(--gray-400); }

.nx-select__list {
  flex: 1 1 auto;
  overflow-y: auto;
  /* Scrollen in der Optionsliste darf NICHT auf die Seite dahinter
   * durchschlagen (Scroll-Chaining), wenn man am Listenende ankommt. */
  overscroll-behavior: contain;
  /* Mit einem Padding-Inset (statt -y nur), damit Scrollbalken nicht
   * direkt am Tickbox-Rand klebt. */
  padding-right: 2px;
}

.nx-select__option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  color: var(--gray-800);
  line-height: 1.35;
  cursor: pointer;
  transition: background-color 80ms ease;
}
.nx-select__option.is-active,
.nx-select__option:hover {
  background: color-mix(in srgb, var(--nxtgn-pink) 9%, var(--nxtgn-white));
  color: var(--gray-900);
}
.nx-select__option.is-selected {
  color: var(--nxtgn-pink);
  font-weight: 600;
}
.nx-select__option.is-selected.is-active {
  background: color-mix(in srgb, var(--nxtgn-pink) 16%, var(--nxtgn-white));
}
.nx-select__option + .nx-select__option { margin-top: 1px; }

.nx-select__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* Optionales Options-Badge (farbiger Kreis, z.B. Score im Status-Dropdown)
 * — Farben kommen inline aus data-badge-bg/-fg am <option>. Zentrierung
 * via line-height = Höhe (kontextunabhängig, wie .status-chip__score). */
.nx-select__badge {
  flex: 0 0 19px;
  width: 19px;
  height: 19px;
  border-radius: 999px;
  line-height: 19px;
  text-align: center;
  font-size: 0.66rem;
  font-weight: 700;
}
.nx-select__label mark {
  background: transparent;
  color: var(--nxtgn-pink);
  font-weight: 600;
}

/* Tickbox-Glyph in Multi-Options + "Alle"-Header. Eigener Custom-Style
 * (kein <input>), damit Klick-Verhalten konsistent über JS läuft. */
.nx-select__check {
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  border: 1.5px solid var(--gray-300);
  border-radius: 4px;
  background: var(--nxtgn-white);
  position: relative;
  transition: border-color 80ms ease, background-color 80ms ease;
}
.nx-select__option.is-selected .nx-select__check,
.nx-select__all .nx-select__check.is-checked,
.nx-select__all .nx-select__check.is-indeterminate {
  background: var(--nxtgn-pink);
  border-color: var(--nxtgn-pink);
}
.nx-select__option.is-selected .nx-select__check::after,
.nx-select__all .nx-select__check.is-checked::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath d='M3.5 8.2l3 3 6-6.4' fill='none' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
  background-position: center;
  background-repeat: no-repeat;
  background-size: 12px 12px;
}
.nx-select__all .nx-select__check.is-indeterminate::after {
  content: "";
  position: absolute;
  inset: 4px;
  background: white;
  border-radius: 1px;
}

.nx-select__create {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  padding: 8px 10px;
  border-top: 1px dashed var(--gray-200);
  border-radius: var(--radius-sm);
  color: var(--nxtgn-pink);
  font-weight: 600;
  cursor: pointer;
  transition: background-color 80ms ease;
}
.nx-select__create.is-active,
.nx-select__create:hover {
  background: color-mix(in srgb, var(--nxtgn-pink) 9%, var(--nxtgn-white));
}
.nx-select__create strong { color: inherit; }

.nx-select__empty,
.nx-select__more {
  padding: 10px;
  text-align: center;
  font-size: 0.78rem;
  color: var(--gray-500);
}

/* Trennlinie zwischen gepinnten (ausgewählten) Optionen und dem Rest —
 * nur im Multi-Modus ohne aktive Suche (siehe _renderList). */
.nx-select__sep {
  height: 1px;
  background: var(--gray-200);
  margin: 5px 8px;
}


/* Generische Filter-Bar — wird auf /organizations UND /collaborations
 * verwendet. Alle Controls in einer Flex-Row mit sinnvollen Mindest-
 * breiten; das Such-Feld bekommt doppelten Wachstums-Anteil, die Multi-
 * Select-Felder teilen sich den Rest. Wird der Viewport zu schmal,
 * fliegen die Felder dank flex-wrap auf eigene Zeilen statt sich gegen-
 * seitig zu zerquetschen.
 *
 * Labels stecken nicht mehr drüber oder drin — die Placeholders
 * beschreiben das Feld selbst ("Suchen…", "Quelle", "Kombination").
 * Maximale Platzersparnis, klar lesbar bei wenigen Filtern. */
.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: stretch;
}
.filter-row__field {
  flex: 1.35 1 170px;
  min-width: 150px;
  display: flex;
  flex-direction: column;
}
/* Suchfeld bewusst NICHT mehr das dominante Feld — die Dropdowns brauchen den
 * Platz für lange Org-/Status-Namen. Deutlich kleinerer flex-grow + kleinere
 * Basis als die Felder, damit der freie Platz überwiegend an die Dropdowns
 * geht und die Suche schmaler bleibt. */
.filter-row__field--grow {
  flex: 0.6 1 160px;
  min-width: 150px;
}
.filter-row__field .input,
.filter-row__field .select {
  height: 38px;
  font-size: 0.85rem;
}
.filter-row__field .nx-select__trigger {
  min-height: 38px;
}
/* Multi-Select-Pills im Filter dürfen den Trigger nicht aufquellen
 * lassen — nowrap, was nicht passt wird vom JS abgeschnitten. */
.filter-row__field .nx-select__value.has-pills {
  flex-wrap: nowrap;
  overflow: hidden;
}
.filter-row__check {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.85rem;
  white-space: nowrap;
  padding-bottom: 9px;  /* visuell auf Höhe der Input-Unterkante */
}
.filter-row__btn { align-self: flex-end; }
/* Auto-breites Filterfeld (z.B. der Segment-Schalter) — wächst nicht mit,
 * zentriert seinen Inhalt vertikal in der ansonsten gestretchten Zeile. */
.filter-row__field--auto {
  flex: 0 0 auto;
  min-width: 0;
  justify-content: center;
}

/* Segmentierter Filter-Schalter (z.B. Alle/Intern/Extern) — passt in die
 * Filter-Zeile (38px Höhe). Pink-Akzent + weiße Pille für das aktive
 * Segment, im Stil der NxtgnSelect-Trigger. */
.seg-control {
  display: inline-flex;
  align-items: center;
  height: 38px;
  padding: 3px;
  gap: 2px;
  background: var(--gray-100);
  border: 1px solid var(--gray-200);
  border-radius: 999px;
  margin: 0;
}
.seg-control__opt {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  /* Anker für das absolut positionierte versteckte Radio — sonst hängt es
   * am nächsten positionierten Vorfahren und der Fokus-Scroll springt. */
  position: relative;
  padding: 0 12px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--gray-500);
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: color .15s ease, background .15s ease, box-shadow .15s ease;
}
.seg-control__opt input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.seg-control__opt:hover { color: var(--gray-700); }
.seg-control__opt:has(input:checked) {
  background: var(--nxtgn-white);
  color: var(--nxtgn-pink);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .08);
}
.seg-control__opt:has(input:focus-visible) {
  outline: 2px solid var(--nxtgn-pink-60);
  outline-offset: 1px;
}
/* Icon-Variante (Initiative-Filter): Richtungs-Icon vor dem Label, etwas
 * engeres Padding. Das Icon erbt die Textfarbe (pink wenn aktiv). */
.seg-control--icon .seg-control__opt { gap: 4px; padding: 0 9px; }
.seg-control--icon .seg-ic { width: 14px; height: 14px; flex: 0 0 14px; }

/* Tag-Zuweisungs-Form (Event- & Serien-Detail): Multi-Select + Speichern-
 * Button auf einer Zeile, Button vertikal mittig zum Select-Trigger. */
.tag-assign-form {
  display: flex;
  gap: 8px;
  align-items: center;
}
.tag-assign-form__field { flex: 1; min-width: 0; }

/* Kompaktes Farb-Swatch (type=color) — als kleine Pille statt riesigem
 * Farbblock. Browser-Default-Chrome wegstylen. */
.input--color {
  width: 52px;
  padding: 4px;
  cursor: pointer;
}
.input--color::-webkit-color-swatch-wrapper { padding: 0; }
.input--color::-webkit-color-swatch {
  border: none;
  border-radius: var(--radius-sm);
}
.input--color::-moz-color-swatch {
  border: none;
  border-radius: var(--radius-sm);
}

/* Inline-Anlege-Form (z.B. Tags) — Felder mit Labels darüber auf einer
 * Zeile, Submit-Button unten bündig. */
.inline-form {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
}
.inline-form__field { display: flex; flex-direction: column; }
.inline-form__field--grow { flex: 1 1 240px; min-width: 200px; }

/* Such-Input mit Lupen-Glyph links — wiederverwendbar via `.input--search`.
 * Das Icon ist ein SVG-Background; das Padding-left lässt Platz fürs Icon. */
.input--search {
  padding-left: 38px;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3e%3ccircle cx='7' cy='7' r='4.5' stroke='%2371717a' stroke-width='1.6'/%3e%3cpath d='M10.5 10.5L14 14' stroke='%2371717a' stroke-width='1.6' stroke-linecap='round'/%3e%3c/svg%3e");
  background-position: 12px center;
  background-repeat: no-repeat;
  background-size: 16px 16px;
}


/* KPI-Progress (Collab-Liste): prominente Hero-Zahl + Gradient-Bar.
 * Counter zählt beim Load von 0 hoch (siehe initKpiCounter in app.js),
 * Bar füllt sich parallel via CSS-Transition. Layout: riesige Zahl ganz
 * links, daneben Label + Bar als Block; "in your face" beim Reload. */
.kpi-progress {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 22px;
  padding: 5px 9px;
  margin: 0 -9px 8px;
  border: 1px solid transparent;
  border-radius: 12px;
  background: var(--nxtgn-white);
  cursor: pointer;
  transition: background .14s ease, border-color .14s ease, box-shadow .14s ease;
}
/* Klickbar: dezenter Hover (Tönung), aktiv pink umrandet. */
.kpi-progress:hover {
  background: #f6f4f0;
  border-color: var(--gray-200);
}
.kpi-progress:focus-visible {
  outline: none;
  border-color: var(--nxtgn-pink);
}
.kpi-progress.is-on {
  border-color: var(--nxtgn-pink);
  background: color-mix(in srgb, var(--nxtgn-pink) 6%, var(--nxtgn-white));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nxtgn-pink) 35%, transparent);
}
.kpi-progress__hero {
  display: flex;
  align-items: baseline;
  gap: 6px;
  line-height: 1;
  letter-spacing: -0.03em;
}
.kpi-progress__current {
  font-size: 3.4rem;
  font-weight: 800;
  color: var(--nxtgn-pink);
}
.kpi-progress__divider {
  font-size: 1.4rem;
  font-weight: 600;
  color: var(--gray-300);
}
.kpi-progress__target {
  font-size: 1.4rem;
  font-weight: 600;
  color: var(--gray-500);
}
.kpi-progress__body {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}
/* Prozentzahl sitzt direkt rechts hinter der Bar, auf Track-Höhe. */
.kpi-progress__pct {
  flex: none;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--nxtgn-pink);
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.kpi-progress__track {
  height: 14px;
  background: var(--gray-100);
  border-radius: 999px;
  overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.06);
}
.kpi-progress__fill {
  height: 100%;
  background: var(--nxtgn-gradient);
  border-radius: 999px;
  box-shadow:
    0 0 8px color-mix(in srgb, var(--nxtgn-pink) 45%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.4);
  /* Längere, weiche Transition damit die Fill-Bewegung sich mit dem
   * Counter-Hochzählen synchron anfühlt. */
  transition: width 1.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* Jahresziele-Marken auf der KPI-Bar. Die Marken liegen als eigene Ebene
 * über/unter dem Track (der seinerseits overflow:hidden behält, damit der
 * Fill sauber geclippt wird). Jede Marke sitzt an der Position ihres
 * kumulierten Soll-Werts (left: cum/1000); Zahl darüber, Trennstrich durch
 * die Bar, Jahr darunter — alles am Strich zentriert. */
.kpi-progress__scale {
  position: relative;
  flex: 1;
  min-width: 0;
  padding: 16px 0 18px;
}
.kpi-progress__marks {
  position: absolute;
  left: 0; right: 0; top: 0; bottom: 0;
  pointer-events: none;
}
.kpi-mark {
  position: absolute;
  top: 0; bottom: 0;
}
.kpi-mark__num {
  position: absolute;
  top: 0;
  left: 0;
  transform: translateX(-50%);
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--gray-600);
  white-space: nowrap;
}
.kpi-mark__line {
  position: absolute;
  top: 16px;
  height: 14px;
  width: 2px;
  left: 0;
  transform: translateX(-50%);
  background: var(--gray-400);
  border-radius: 1px;
}
.kpi-mark__year {
  position: absolute;
  bottom: 0;
  left: 0;
  transform: translateX(-50%);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--gray-400);
  white-space: nowrap;
}
/* Aktuelles Jahr: pink hervorgehoben (Strich + Zahl). */
.kpi-mark.is-current .kpi-mark__line {
  background: var(--nxtgn-pink);
  width: 3px;
}
.kpi-mark.is-current .kpi-mark__num {
  color: var(--nxtgn-pink);
  font-weight: 800;
}
.kpi-mark.is-current .kpi-mark__year {
  color: var(--gray-600);
  font-weight: 700;
}
/* Endmarke (Ziel, 100 %): kein Trennstrich, Labels an die Bar-Kante. */
.kpi-mark.is-end .kpi-mark__num,
.kpi-mark.is-end .kpi-mark__year {
  transform: translateX(-100%);
}

@media (max-width: 700px) {
  .kpi-progress { grid-template-columns: 1fr; gap: 8px; }
  .kpi-progress__current { font-size: 2.6rem; }
  .kpi-mark__num { font-size: 0.66rem; }
  .kpi-mark__year { font-size: 0.6rem; }
}

/* Callouts — Inline-Hinweisboxen (Disambiguierung beim Anlegen,
 * Dup-Check, Undo-Bestätigung etc.). Warn = amber, ok = grün, beide
 * dezent abgesetzt mit Rahmen + farbigem Linksbalken für klare
 * visuelle Abgrenzung. */
.callout {
  position: relative;
  padding: 12px 14px 12px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--gray-200);
  background: var(--gray-50);
  color: var(--gray-800);
  font-size: 0.85rem;
  line-height: 1.5;
}
.callout--warn {
  background: #fff8e6;
  border-color: #f3d98a;
  color: #6b4d00;
}
.callout--ok {
  background: #eefaf0;
  border-color: #bfe6c8;
  color: #1f6b3a;
}
/* Harter Fehler im Formular (Duplikat, ungültige Kombination, abgelehnt) —
   rot, abgesetzt vom amber-warnenden callout--warn. */
.callout--error {
  background: #fef3f2;
  border-color: #f0c4bf;
  color: #b42318;
}
/* Callout im Disambiguierungs-Slot (#dup-check): erkennbarer Abstand zur
 * folgenden Form-Zeile, damit der Hinweis nicht an den nächsten Selects
 * klebt. */
#dup-check .callout { margin: 6px 0 22px 0; }

/* ------------------------------------------------------------------
 * Split-View-Posteingang (/syncs, Tab „Zu prüfen"): kompakte Item-Liste
 * links, Dossier rechts. Beide Panes scrollen intern — die Liste bleibt
 * beim Lesen langer Mailverläufe stehen. Kategorie-Punkte statt Emojis;
 * Score-Kacheln aus SCORE_COLORS (inline gesetzt).
 * ------------------------------------------------------------------ */
.review-split {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
  height: calc(100vh - 200px);
  min-height: 520px;
}
.review-list {
  border-right: 1px solid var(--gray-200);
  background: var(--gray-50);
  overflow-y: auto;
}
/* Abschnitts-Köpfe der Liste: getönte Icon-Kachel + Label in der
 * Sektions-Farbe + Zähler als Voll-Kreis rechts — die zwei Queues
 * (Matching-Mails pink, Org-/Event-Abgleich blau) trennen sich über das
 * Design selbst, keine Trennlinie nötig. */
/* Sektions-Header der Item-Liste: weiß hinterlegt + kräftige obere
 * Trennlinie, damit sich die Abschnitte klar voneinander absetzen. Count in
 * Klammern hinter dem Namen (kein Kreis-Badge). Jede Sektion trägt ihre
 * Akzentfarbe: Mails pink · Portfolio-Katalog orange · Abgleich blau. */
.review-list__label {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  background: #fff;
  border-top: 2px solid var(--gray-200);
  border-bottom: 1px solid var(--gray-200);
}
.review-list__label:first-child { border-top: 0; }
.review-list__icon {
  width: 27px; height: 27px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  flex: none;
}
.review-list__icon svg { width: 14px; height: 14px; }
.review-list__count {
  font-weight: 700;
  opacity: 0.75;
  text-transform: none;
  letter-spacing: 0;
}
.review-list__label--mail { color: var(--nxtgn-pink); }
.review-list__label--mail .review-list__icon { background: var(--nxtgn-pink-80); color: var(--nxtgn-pink); }
.review-list__label--catalog { color: var(--nxtgn-orange); }
.review-list__label--catalog .review-list__icon { background: #fce3d3; color: var(--nxtgn-orange); }
.review-list__label--sync { color: var(--nxtgn-blue); }
.review-list__label--sync .review-list__icon { background: #c6c6f2; color: var(--nxtgn-blue); }
.review-item {
  display: block;
  padding: 12px 16px;
  border-bottom: 1px solid var(--gray-200);
  position: relative;
  color: inherit;
}
/* Listen-Einträge sind <a> (Direktlink-Fallback) — die globale
 * a:hover-Unterstreichung würde sonst den ganzen Eintrag unterstreichen. */
.review-item, .review-item:hover { text-decoration: none; }
/* aktiver Eintrag: weiß + Pink-Kante links; Hover: leichte Pink-Tönung */
.review-item::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: transparent;
}
.review-item:hover:not(.is-active) { background: #fbf4f8; }
/* Aktiver Eintrag: subtil in der Sektions-Akzentfarbe hinterlegt + Kante. */
.review-item.is-active { background: #fbe9f3; }
.review-item.is-active::before { background: var(--nxtgn-pink); }
.review-item[data-section="finding"]:hover:not(.is-active) { background: #f3f3fb; }
.review-item[data-section="finding"].is-active { background: #e9e9f7; }
.review-item[data-section="finding"].is-active::before { background: var(--nxtgn-blue); }
.review-item[data-section="catalog"]:hover:not(.is-active) { background: #fdf6f0; }
.review-item[data-section="catalog"].is-active { background: #fcecdf; }
.review-item[data-section="catalog"].is-active::before { background: var(--nxtgn-orange); }
.review-item__top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}
.review-item__title {
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--gray-900);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.review-item__score {
  flex: none;
  width: 20px; height: 20px;
  border-radius: 5px;
  display: grid;
  place-items: center;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
}
.review-item__snip {
  margin-top: 3px;
  color: var(--gray-500);
  font-size: 0.78rem;
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.review-item__meta {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 7px;
  flex-wrap: wrap;
}

/* Kategorie-Tag: Punkt UND Text in der Kategorie-Farbe (data-cat =
 * abgeleitete Kategorie via mail_display_category bzw. 'merge' für
 * Sync-Funde). 'kollaboration' = Score >= 4, die KPI-Sprache in Blau. */
.rv-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--gray-500);
}
.rv-tag i { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.rv-tag[data-cat="connection"] { color: var(--nxtgn-pink); }
.rv-tag[data-cat="kollaboration"] { color: var(--nxtgn-blue); }
.rv-tag[data-cat="success_case"] { color: var(--nxtgn-blue); }
.rv-tag[data-cat="impression"] { color: var(--gray-500); }
.rv-tag[data-cat="catalog"] { color: var(--nxtgn-orange); }
.rv-tag[data-cat="ongoing"],
.rv-tag[data-cat="unklar"] { color: #b45309; }
.rv-tag[data-cat="irrelevant"] { color: var(--gray-400); }
.rv-tag[data-cat="merge"] { color: var(--nxtgn-blue); }

.rv-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.75rem;
  color: var(--gray-600);
  background: var(--gray-50);
  border: 1px solid var(--gray-200);
  border-radius: 999px;
  padding: 2px 10px;
  white-space: nowrap;
}
.rv-chip--score { font-weight: 600; color: var(--gray-900); background: #fff; }
.rv-chip--score i { width: 8px; height: 8px; border-radius: 50%; }
.rv-chip--warn { color: #92610a; background: #fbf3df; border-color: #eeddb4; }
.rv-chip--link { color: var(--nxtgn-pink); background: #fdf0f7; border-color: #f6cadf; text-decoration: none; }
a.rv-chip--link:hover, button.rv-chip--link:hover { border-color: var(--nxtgn-pink); }
button.rv-chip { cursor: pointer; font-family: inherit; }
/* Ähnlichkeits-Prozent: kräftige gelbe Pille (CI-Gelb, schwarzer Text). */
.rv-chip--pct {
  background: var(--nxtgn-yellow);
  border: 0;
  color: #000;
  font-weight: 700;
  border-radius: 8px;
  padding: 3px 10px;
}
/* Kollaborations-Thema in der Liste, Optik wie board-card__topic auf dem
 * Kanban-Board (Wiedererkennung), eine Spur kleiner für die dichte Liste. */
.review-item__topic {
  margin-top: 3px;
  font-size: 0.79rem;
  font-weight: 500;
  line-height: 1.35;
  color: var(--gray-800);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Org-Paar hebt sich vom Rest der Karte ab: kräftiger + minimal größer,
 * das × tritt zurück (wie board-card__orgs/__x auf dem Kanban-Board). */
.review-item__org {
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--gray-900);
}
.review-item__x {
  font-weight: 300;
  color: var(--gray-400);
  padding: 0 5px;
}
/* Stufen-Datum rechtsbündig in der Meta-Zeile (wie board-card__meta);
 * fehlendes Datum wird explizit benannt statt still wegzufallen. */
.review-item__date {
  margin-left: auto;
  font-size: 0.72rem;
  color: var(--gray-500);
}
.review-item__date--missing { color: var(--gray-400); }

/* Dossier rechts. Flex-Spalte, damit die Aktionszeile bei kurzem Inhalt
 * unten sitzt (margin-top:auto) und bei langem einfach folgt. */
.review-detail {
  padding: 22px 26px 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.rv-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.rv-head__tags { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.rv-title { margin: 8px 0 0; font-size: 1.35rem; font-weight: 700; letter-spacing: -0.01em; }

/* --- Dossier-Header mit NXTGN-Verlauf (Mockup inbox-header-mail, A2) ------
 * Gradient-Block randlos oben im Dossier-Panel (negative Margins gegen das
 * .review-detail-Padding), darunter eine schmale Kante in der Sektionsfarbe
 * (Mail pink · Portfolio-Katalog orange · Abgleich blau). Beim Mail-Dossier
 * folgt ein weißes DB-Status-Band (vollfarbige Badges auf Weiß). */
.rvh {
  background: var(--nxtgn-gradient);
  color: #fff;
  margin: -22px -26px 0;
  padding: 16px 26px 14px;
}
.rvh__eyebrow {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  opacity: 0.92;
}
.rvh__title {
  margin-top: 5px;
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.rvh__x { font-weight: 300; opacity: 0.8; }
/* Typ-Tag (corporate/startup) als neutrale Glas-Pill auf dem Verlauf. */
.rvh__type {
  font-size: 0.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.4);
  align-self: center;
}
.rvh__chips { margin-top: 9px; display: flex; gap: 6px; flex-wrap: wrap; }
.rvh__chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.74rem;
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.35);
  color: #fff;
}
/* Weißes DB-Status-Band direkt unter dem Verlauf (nur Mail-Dossier). */
.rvh__band {
  display: flex;
  gap: 18px;
  align-items: center;
  flex-wrap: wrap;
  margin: 0 -26px;
  padding: 9px 26px;
  background: #fff;
  border-bottom: 1px solid var(--gray-200);
}
/* Erkennungs-Hinweis (Umbenennung/Variante): Badge links fix, Text daneben
 * — Umbruchzeilen bleiben am Textanfang ausgerichtet (kein Wrap unters
 * Badge). */
.rvh__band--hint { flex-wrap: nowrap; align-items: flex-start; }
.rvh__band--hint .rvh__badge { flex: none; margin-top: 1px; white-space: nowrap; }
.rvh__band--hint .rvh__band-text { flex: 1; min-width: 0; }
.rvh__band .who { font-size: 0.8rem; font-weight: 600; color: var(--gray-600); }
.rvh__badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.74rem;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
}
.rvh__badge--ok { color: #1f6b3a; background: #eefaf0; }
.rvh__badge--new { color: #b45309; background: #fdf3e2; }
.rvh__band .sim { font-size: 0.74rem; color: var(--gray-500); }

/* Sticky Footer im Portfolio-Dossier, EINE Zeile: links die Empfehlung
 * (Eyebrow + Primär-Button, Konsequenz-Zeile darunter), rechts die
 * Alternativen als ruhige Buttons mit Info-Icon plus das Zuweisungs-Select
 * direkt in der Zeile. Kein Umbruch: notfalls schrumpft das Select. */
.rv-footer {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: auto -26px 0;
  padding: 12px 26px 14px;
  background: #fff;
  border-top: 1px solid var(--gray-200);
  /* Container-Query-Bezug: unten schaltet der Footer bei wenig Breite
   * auf kompaktere Buttons um, statt überzulaufen. */
  container-type: inline-size;
}
.rv-decide { display: flex; align-items: flex-start; gap: 12px; flex-wrap: nowrap; }
/* Die Empfehlung nimmt den Platz, den die Alternativen übrig lassen
 * (flex-grow + flex-shrink statt fester Breiten): der Primär-Button darf
 * breit sein und die Konsequenz-Zeile bleibt kurz; geschrumpft wird nur,
 * wenn die Buttons rechts es erzwingen. */
.rv-reco {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  flex: 1 1 auto;
  min-width: 200px;
  max-width: 560px;
}
.rv-reco > .btn { align-self: stretch; }
.rv-reco__eyebrow {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--nxtgn-pink);
}
.rv-reco__sub { font-size: 0.74rem; color: var(--gray-600); }
.rv-alts {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin-left: auto;
  /* Natürliche Breite behalten: schrumpfen muss die Empfehlung links,
   * sonst laufen die Buttons rechts aus dem Footer. */
  flex: 0 0 auto;
  /* fluchtet die Alternativ-Buttons mit dem Primär-Button (Eyebrow-Höhe) */
  padding-top: 17px;
}
/* Kleine Info-Icons zentrieren sich in einer Box mit Button-Höhe, damit
 * align-items: flex-start sie nicht nach oben zieht. */
.rv-alts > .rv-info { height: 36px; align-items: center; }

/* Manuelle Zuweisung: Toggle-Button in der Zeile; das Panel (Select +
 * Zuweisen) klappt darunter auf, rechtsbündig am Toggle. Der Footer
 * wächst dabei nach oben (sticky bottom), nichts läuft aus dem Viewport. */
.rv-assign-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}
.rv-assign-chk:checked ~ .rv-assign-toggle { color: var(--nxtgn-pink); border-color: var(--nxtgn-pink-60); }
.rv-assign { display: none; }
.rv-assign-chk:checked ~ .rv-assign { display: flex; gap: 8px; }
.rv-assign .nx-select { width: 280px; }
.rv-chev { font-size: 0.7rem; }

/* Wenig Platz (schmales Fenster/Split): kompaktere Buttons und schmalere
 * Empfehlungs-Spalte halten die eine Zeile; erst darunter darf der
 * rechte Block kontrolliert umbrechen (besser als Überlaufen). */
@container (max-width: 940px) {
  .rv-alts { gap: 4px; }
  .rv-alts .btn { padding: 0 10px; font-size: 0.8rem; }
}
@container (max-width: 810px) {
  .rv-decide { flex-wrap: wrap; }
  .rv-alts { padding-top: 0; }
}

/* Info-Icon + Popover: Konsequenz-Text bei Hover ODER Tastatur-Fokus.
 * Selbst gestaltetes Hover-Fenster (kein title-Attribut); der Inhalt
 * beschreibt die Konsequenz des danebenstehenden Buttons. */
.rv-info { position: relative; display: inline-flex; margin-right: 4px; }
.rv-info__btn {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  border: 1px solid var(--gray-300);
  background: #fff;
  color: var(--gray-500);
  font-size: 0.62rem;
  font-weight: 700;
  font-family: inherit;
  cursor: default;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.rv-info__btn:hover, .rv-info__btn:focus-visible {
  border-color: var(--nxtgn-pink);
  color: var(--nxtgn-pink);
  outline: none;
}
.rv-info__pop {
  position: absolute;
  bottom: calc(100% + 8px);
  right: -8px;
  width: 250px;
  background: var(--gray-900);
  color: #fff;
  font-size: 0.74rem;
  font-weight: 400;
  line-height: 1.45;
  padding: 9px 11px;
  border-radius: 8px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s;
  z-index: 5;
}
@media (prefers-reduced-motion: reduce) { .rv-info__pop { transition: none; } }
.rv-info:hover .rv-info__pop,
.rv-info__btn:focus-visible + .rv-info__pop { opacity: 1; }


/* Review-Formular (Portfolio-Katalog-Dossier): kräftige Feld-Überschriften
 * + großzügigeres Spacing als das kompakte Modal-Formular. */
/* Das Review-Formular füllt die Resthöhe des Dossier-Panels als
 * Flex-Spalte: der Footer (margin-top: auto) ankert damit auch bei kurzem
 * Inhalt am unteren Panel-Rand und ist nur so hoch wie sein Inhalt. */
.rv-form { margin-top: 18px; display: flex; flex-direction: column; flex: 1 0 auto; }
.rv-form .label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--gray-800);
}
.rv-form .form-row { margin-bottom: 20px; }

/* Empfänger eines Portfolios (Detail-Modal): DIE Kern-Info des Eintrags,
 * daher deutlich prominenter als normale Pills — weiße Karten-Chips mit
 * kräftigem Namen auf der grauen Sektionsfläche. */
.recipient-chip {
  display: inline-flex;
  align-items: center;
  padding: 8px 16px;
  background: #fff;
  border: 1px solid var(--gray-200);
  border-left: 3px solid var(--nxtgn-pink);
  border-radius: 10px;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--gray-900);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

/* Empfänger-Feld bei Breit-Produkten (Tech Briefing/Scouting Spotlight):
 * Auswahl ausgeblendet, stattdessen ein ausgegrautes „an alle Member"-Feld
 * + kurzer Hinweis. Toggle per is-broad (JS am Produkt-Select). */
[data-recipient-field] [data-broad-note],
[data-recipient-field] [data-broad-hint] { display: none; }
[data-recipient-field].is-broad .nx-select,
[data-recipient-field].is-broad select[name="recipient_org_ids"] { display: none; }
[data-recipient-field].is-broad [data-broad-note] {
  display: block;
  color: var(--gray-500);
  background: var(--gray-50);
}
[data-recipient-field].is-broad [data-broad-hint] { display: block; }

/* Das Org-Paar als EIN Block (ersetzt Titel + Org-Karten): Typ-Pill wie im
 * Erfassen-Formular vor dem großen Namen, darunter der DB-Stand. */
.rv-pair {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.rv-pair__row { display: flex; align-items: center; gap: 9px; }
.rv-pair__row .nx-select__orgtype { font-size: 0.62rem; padding: 3px 7px; }
.rv-pair__name { font-size: 1.3rem; font-weight: 700; letter-spacing: -0.01em; }
.rv-pair__x {
  color: var(--gray-500);
  font-size: 1.45rem;
  font-weight: 600;
  align-self: flex-start;
  margin-top: 1px;
}
.rv-pair__hint { margin-top: 4px; font-size: 0.74rem; font-weight: 600; }
.rv-pair__hint--ok { color: #1f8a54; }
.rv-pair__hint--new { color: #b45309; }
/* Fuzzy-Hinweis unter „wird neu angelegt": es gibt eine ähnliche Org. */
.rv-pair__similar { margin-top: 2px; font-size: 0.72rem; color: var(--gray-500); font-weight: 400; }

/* Anlegen-Angebot unterm Org-Select (Erfassen-Modal, Postfach-Vorschlag
 * mit noch nicht angelegter Org): amber Hinweis + Button in einer Zeile. */
.neworg-hint {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 7px;
  padding: 8px 11px;
  background: #fbf3df;
  border: 1px solid #eeddb4;
  border-radius: var(--radius-md);
  font-size: 0.78rem;
  color: #6b4d00;
}
.neworg-hint .btn { flex: none; background: #fff; }

/* Fakten-Band: Status (status-chip wie überall) + Datum + Wie kennengelernt —
 * die Entscheidungs-Infos, immer sichtbar, Beige als Hervorhebung (CI).
 * Feste Spalten-Verteilung: Status ~1/3 (Label darf umbrechen), Datum
 * schmal, „Wie kennengelernt" bekommt die Hälfte. */
.rv-facts {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.45fr) minmax(0, 1.5fr);
  gap: 24px;
  background: var(--nxtgn-beige);
  border-radius: var(--radius-md);
  padding: 13px 18px;
  margin-top: 18px;
}
.rv-facts .status-chip { align-items: flex-start; }
.rv-facts .status-chip__label { white-space: normal; line-height: 1.35; }
@media (max-width: 700px) {
  .rv-facts { grid-template-columns: 1fr 1fr; }
}
.rv-fact__label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--gray-500);
  margin-bottom: 5px;
}
.rv-fact__value { font-size: 0.88rem; font-weight: 600; color: var(--gray-900); }
.rv-fact__empty { color: var(--gray-400); font-weight: 700; }
/* Freitext-Detail der Mail unterm „Wie kennengelernt"-Wert. */
.rv-fact__sub { margin-top: 3px; font-size: 0.74rem; color: var(--gray-500); max-width: 52ch; }
/* Thema-Fakt: volle Breite unter den drei Spalten des beigen Bands. */
.rv-fact--wide { grid-column: 1 / -1; }

/* Eingebettetes Erfassen-Formular im Mail-Dossier (Neuanlage-Fall):
 * derselbe Feldsatz wie das Modal (_form_fields.html), im beigen Band
 * des Dossiers statt als Overlay — die Mail bleibt daneben sichtbar. */
.rv-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--nxtgn-beige);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  margin-top: 18px;
}
.rv-form .form-row { margin-bottom: 0; gap: 12px; }
.rv-form .label { margin-bottom: 4px; }
.rv-form .input,
.rv-form .textarea { font-weight: 600; }
.rv-form .input::placeholder,
.rv-form .textarea::placeholder { font-weight: 400; }

.rv-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
.rv-label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gray-400);
  margin: 18px 0 7px;
}
.rv-summary { margin: 0; font-size: 0.9rem; line-height: 1.55; max-width: 75ch; }
.rv-missing { margin-top: 8px; font-size: 0.8rem; color: #92610a; }
.rv-quotes { display: flex; flex-direction: column; gap: 6px; }
.rv-quote {
  border-left: 2px solid var(--gray-300);
  padding: 1px 0 1px 11px;
  color: var(--gray-600);
  font-style: italic;
  font-size: 0.83rem;
}
.rv-mailmeta { color: var(--gray-400); font-size: 0.78rem; }
.rv-mailmeta a { color: var(--nxtgn-pink); text-decoration: none; }
/* Mailverlauf: fließt frei mit (KEIN Innen-Scroll, kein Höhen-Deckel) —
 * gescrollt wird das Dossier-Pane; die sticky Aktionszeile bleibt sichtbar. */
.rv-mail {
  margin: 9px 0 0;
  background: var(--gray-50);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  padding: 13px 15px;
  font-size: 12.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--gray-600);
}

/* Aktionszeile: klebt am unteren Rand des Dossier-Panes (bei langem Inhalt
 * immer erreichbar), negative Ränder spannen sie über das Pane-Padding. */
.rv-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: auto -26px 0;
  padding: 14px 26px;
  background: #fff;
  border-top: 1px solid var(--gray-200);
}
.rv-actions__spacer { flex: 1; }
.rv-empty { color: var(--gray-400); font-size: 0.85rem; }
/* Luft zwischen letztem Inhalt und Aktionszeile (margin-top:auto der
 * Aktionen kollabiert bei langem Inhalt auf 0). */
.review-detail > *:nth-last-child(2) { margin-bottom: 20px; }

@media (max-width: 860px) {
  .review-split { grid-template-columns: 1fr; height: auto; }
  .review-list {
    max-height: 300px;
    border-right: 0;
    border-bottom: 1px solid var(--gray-200);
  }
}

/* ------------------------------------------------------------------
 * Top-Tab-Bar — horizontale Tabs unter Page-Header, z.B. /events
 * ------------------------------------------------------------------ */
.tab-bar {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--gray-200);
  margin: 6px 0 22px;
}
.tab-link {
  padding: 10px 18px;
  font-weight: 500;
  font-size: 0.92rem;
  color: var(--gray-600);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  text-decoration: none;
  transition: color 80ms ease, border-color 80ms ease;
}
.tab-link:hover {
  color: var(--gray-900);
  text-decoration: none;
}
.tab-link.is-active {
  color: var(--nxtgn-pink);
  border-bottom-color: var(--nxtgn-pink);
  font-weight: 600;
}
.tab-link__count {
  margin-left: 8px;
  font-size: 0.78rem;
  color: var(--gray-500);
  font-weight: 500;
}
.tab-link.is-active .tab-link__count { color: var(--nxtgn-pink); opacity: 0.7; }

/* Tag-Chip — kleines Inline-Element für Tag-Anzeige in Listings, Details
 * und Filter-Bars. Farbe optional über --chip-bg gesetzt. */
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 500;
  background: var(--chip-bg, var(--gray-100));
  color: var(--gray-800);
  margin-right: 4px;
  line-height: 1.5;
}
.tag-chip--inherited {
  border: 1px dashed var(--gray-300);
  background: transparent;
  color: var(--gray-600);
}
.tag-chip__dot {
  width: 6px; height: 6px; border-radius: 999px;
  background: var(--chip-color, var(--gray-500));
}

/* ------------------------------------------------------------------
 * Sync-Feature: Status-Töne, Sidebar-Notification, Posteingangs-Karten
 * ------------------------------------------------------------------ */

/* Generische Status-Töne (wiederverwendbar): ok=grün, err=rot. */
.pill--ok {
  background: #eefaf0 !important;
  color: #1f6b3a !important;
  border: 1px solid #bfe6c8;
}
.pill--err {
  background: #fdecec !important;
  color: #b42318 !important;
  border: 1px solid #f5c2c0;
}
/* „Zu kuratieren" (offen, in Arbeit) — dezenter Pink-Ton, actionable ohne zu
 * schreien. „Übersprungen" (bewusst verworfen) — neutral grau. */
.pill--todo {
  background: var(--nxtgn-pink-80) !important;
  color: var(--nxtgn-pink-25) !important;
  border: 1px solid var(--nxtgn-pink-60);
}
.pill--muted {
  background: var(--gray-100) !important;
  color: var(--gray-500) !important;
  border: 1px solid var(--gray-200);
}

/* Eintrags-Name der Produkt-Liste: normaler Fließtext (kein Monospace-Chip),
 * nur leicht hervorgehoben. */
.prod-entry {
  font-weight: 600;
  color: var(--gray-900);
}
/* Member „nicht anwendbar" (Breit-Produkte an alle Member): ausgegraut,
 * kursiv — signalisiert, dass hier bewusst kein einzelner Member steht. */
.member-na {
  color: var(--gray-400);
  font-style: italic;
}

/* Apple-Style Notification-Badge am Nav-Icon — sitzt auf dem Icon und
 * ist damit auch in der eingeklappten Sidebar sichtbar. */
.nav-item__icon { position: relative; }
.nav-badge {
  position: absolute;
  top: -1px;
  right: -3px;
  /* Reiner Status-Punkt ohne Zahl: signalisiert nur „es gibt offene
   * Sync-Funde", die genaue Anzahl steht in der Syncs-Ansicht selbst. */
  width: 9px;
  height: 9px;
  border-radius: 999px;
  background: #e02b2b;
  border: 1.5px solid var(--nxtgn-white);
  z-index: 1;
}

/* Posteingangs-Karte: Icon-Bubble + Inhalt + Aktionen. */
.finding-card {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 16px 18px;
  background: #fff;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
}
.finding-card__bubble {
  flex: 0 0 40px;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  background: var(--gray-100);
}
.finding-card__bubble--decide { background: #fff3f8; }   /* Pink-Tint: Entscheidung */
.finding-card__bubble--warn   { background: #fff8e6; }
.finding-card__bubble--err    { background: #fdecec; }
.finding-card__bubble--info   { background: #eefaf0; }
.finding-card__kind {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--nxtgn-pink);
  margin-bottom: 3px;
}
.finding-card__title { font-weight: 600; line-height: 1.4; }
.finding-card__meta { font-size: 0.78rem; color: var(--gray-500); margin-top: 4px; }

/* Änderungs-Chips in der Lauf-Historie (statt rohem Terminal-Log). */
.stat-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  margin: 2px 4px 2px 0;
  background: var(--gray-100);
  color: var(--gray-600);
}
.stat-chip--ok   { background: #eefaf0; color: #1f6b3a; }
.stat-chip--warn { background: #fff8e6; color: #6b4d00; }
.stat-chip--err  { background: #fdecec; color: #b42318; }

/* Sync-Quelle-Karte (Jetzt synchronisieren). */
.sync-source {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  background: #fff;
  border: 1px solid var(--gray-200);
  border-radius: 14px;
}
/* Noch nicht freigeschaltete Quelle (Mailbox-Extraktion, Testphase):
   gedämpft, gestrichelter Rahmen, Trigger ausgegraut. */
.sync-source--soon {
  background: var(--gray-50);
  border-style: dashed;
}
.sync-source--soon > div:first-child > div:first-child { color: var(--gray-500); }
.pill--soon {
  background: var(--nxtgn-pink-80);
  color: var(--nxtgn-pink-25);
}
.sync-source__log {
  font-size: 0.7rem;
  max-height: 220px;
  overflow: auto;
  background: var(--gray-50);
  border-radius: 10px;
  padding: 10px 12px;
  margin-top: 8px;
}

/* Verteilungs-Funnel im Detail-Modal (Org/Event/Serie): nutzt 1:1 die
 * .funnel-pipe/.funnel-card-Optik der Collab-Liste. Die Cards sind hier
 * <a>-Links (Deep-Link auf die gefilterte Liste) — .funnel-card bringt
 * cursor/text-decoration/color schon mit. Nur Modal-Spezifika hier. */
.funnel-pipe--modal {
  overflow-x: auto;          /* schmales Modal: notfalls horizontal scrollen */
  padding-bottom: 6px;       /* Platz für den Hover-Lift-Schatten */
  padding-top: 3px;
}
/* Im Modal: „aktuell"-Zahl UNTER die große Zahl stapeln (statt daneben) —
 * kompaktere, weniger gedrängte Cards, und kein Konflikt mit dem ›-Deep-Link-
 * Pfeil (.funnel-card__go) unten rechts. */
.funnel-pipe--modal .stat__valuerow {
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
}
.funnel-pipe--modal .stat__sub { margin-left: 0; }
/* Klickbare Funnel-Cards (nur Modals): als interaktiv lesbar machen.
 * Affordanz funktioniert OHNE Hover (Touch): permanent sichtbarer ›-Pfeil
 * oben rechts (im flachen, nicht vom Chevron beschnittenen Bereich). Auf
 * Hover hebt die Card an + Schatten + der Pfeil rückt nach rechts/dunkelt. */
.funnel-card--link {
  transition: background 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.funnel-card__go {
  position: absolute;
  bottom: 7px;
  right: 15px;
  display: inline-flex;
  color: var(--gray-600, #52525b);
  opacity: 0;                /* nur bei Hover sichtbar */
  pointer-events: none;
  transition: opacity 120ms ease, transform 120ms ease;
}
.funnel-card__go svg { width: 14px; height: 14px; display: block; }
.funnel-card--link:hover {
  transform: translateY(-3px);
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.14);
  z-index: 1;
}
.funnel-card--link:hover .funnel-card__go {
  opacity: 0.95;
  transform: translateY(-2px);
}
.funnel-card--link:focus-visible {
  outline: 2px solid var(--nxtgn-pink);
  outline-offset: 2px;
}
.mini-funnel__terminal {
  margin-top: 8px;
  font-size: 0.72rem;
  color: var(--gray-500, #71717a);
}
.mini-funnel__terminal a { color: inherit; }


/* ---------------------------------------------------------------------------
 * NxtgnTree — hierarchisches Quelle-Filter-Dropdown. Trigger/Popover optisch
 * an .nx-select angelehnt; die Knoten sind echte Checkboxen (name="src").
 * ------------------------------------------------------------------------ */
.nx-tree { position: relative; display: inline-block; width: 100%; font-size: 0.875rem; }
.nx-tree__trigger {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px;
  padding: 6px 12px; border: 1px solid var(--gray-200); border-radius: var(--radius-md);
  background: var(--nxtgn-white); color: var(--gray-900); font: inherit; text-align: left;
  cursor: pointer; transition: border-color 100ms ease, box-shadow 100ms ease;
}
.nx-tree__trigger:hover { border-color: var(--gray-300); }
.nx-tree.is-open .nx-tree__trigger {
  outline: none; border-color: var(--nxtgn-pink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--nxtgn-pink) 18%, transparent);
}
.nx-tree__value { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nx-tree__value.is-placeholder { color: var(--gray-400); }
/* Auswahl als Pills im Trigger — identische Optik zu NxtgnSelect Multi. */
.nx-tree__value.has-pills {
  display: flex; align-items: center; gap: 4px;
  overflow: hidden; white-space: nowrap; text-overflow: clip;
}
.nx-tree__chevron {
  flex: 0 0 14px; width: 14px; height: 14px;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3e%3cpath d='M4 6l4 4 4-4' stroke='%2371717a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
  background-position: center; background-repeat: no-repeat; pointer-events: none;
  transition: transform 120ms ease;
}
.nx-tree.is-open .nx-tree__chevron { transform: rotate(180deg); }
.nx-tree__popover {
  position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 50;
  display: flex; flex-direction: column; min-width: 260px; max-width: max(100%, 320px);
  max-height: 380px; padding: 6px; background: var(--nxtgn-white);
  border: 1px solid var(--gray-200); border-radius: var(--radius-md);
  box-shadow: 0 10px 30px rgba(0,0,0,0.08), 0 2px 6px rgba(0,0,0,0.04);
}
.nx-tree__popover[hidden] { display: none; }
.nx-tree__search {
  width: 100%; margin-bottom: 6px; padding: 8px 10px; border: 1px solid var(--gray-200);
  border-radius: var(--radius-sm); background: var(--nxtgn-white); font: inherit; outline: none;
}
.nx-tree__search:focus {
  border-color: var(--nxtgn-pink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--nxtgn-pink) 18%, transparent);
}
/* --tree-rc = vertikale Zeilenmitte (Pfeil-/Checkbox-Mitte); Anker für die
 * horizontalen Äste und das Stoppen der Vertikalen beim letzten Kind. */
/* --tree-rc = Y der ersten Zeile (= Checkbox-Mitte: Option-Padding-Top 5 +
 * halbe Checkbox 8 = 13px). Anker für die Verbindungslinien. */
.nx-tree__list { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; padding-right: 2px; --tree-rc: 13px; }
/* flex-start: Pfeil, Checkbox und Ast sitzen auf der ERSTEN Zeile (Höhe
 * --tree-rc). Bei align-items:center würden sie bei mehrzeiligen Labels (z.B.
 * „LBBW Branchenmatchmaking") in die Zeilenmitte rutschen und vom fix
 * positionierten Ast abweichen. */
.nx-tree__row { display: flex; align-items: flex-start; gap: 0; min-height: 30px; }

/* Verschachtelung + Verbindungslinien (klassischer Baum):
 *  - Kinder-Container 16px eingerückt; die VERTIKALE entspringt der Pfeilspitze
 *    des Eltern-Knotens (Toggle-Mitte 8px → left:-8px).
 *  - HORIZONTALER Ast endet KURZ VOR dem Ziel (nie direkt andockend): bei
 *    Blättern kurz vor der Checkbox (Kante node-x 26 → Stopp bei 22), bei
 *    aufklappbaren Knoten kurz vor dem Pfeil. Höhe = --tree-rc (erste Zeile),
 *    durch flex-start auch bei mehrzeiligen Labels korrekt.
 *  - Das letzte Kind stoppt die Vertikale auf Asthöhe (└ statt │). */
.nx-tree__children { position: relative; padding-left: 16px; }
.nx-tree__children[hidden] { display: none; }
.nx-tree__children > .nx-tree__node { position: relative; }
.nx-tree__children > .nx-tree__node::before {
  content: ""; position: absolute; left: -8px; top: 0; bottom: 0;
  width: 1px; background: var(--gray-300);
}
.nx-tree__children > .nx-tree__node:last-child::before {
  bottom: auto; height: var(--tree-rc);
}
/* Blatt-Knoten (kein Pfeil): Ast bis kurz vor die Checkbox. */
.nx-tree__children > .nx-tree__node::after {
  content: ""; position: absolute; left: -8px; top: var(--tree-rc);
  width: 30px; height: 1px; background: var(--gray-300);
}
/* Aufklappbarer Knoten (mit Pfeil): Ast endet kurz vor dem Pfeil. */
.nx-tree__children > .nx-tree__node:has(> .nx-tree__row > .nx-tree__toggle)::after {
  width: 6px;
}

/* Aufklapp-Pfeil — schmal, ohne Box, dezent. Höhe 26px (= 2×--tree-rc), damit
 * die zentrierte Pfeilspitze bei oberer Zeilen-Ausrichtung (flex-start) genau
 * auf der Checkbox-Mitte (13px) sitzt — auch bei mehrzeiligen Labels. */
.nx-tree__toggle {
  flex: 0 0 16px; width: 16px; height: 26px; border: 0; padding: 0;
  background-color: transparent; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3e%3cpath d='M9 6l6 6-6 6' stroke='%2371717a' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
  background-position: center; background-repeat: no-repeat; background-size: 13px 13px;
  transition: transform 120ms ease;
}
.nx-tree__node.is-expanded > .nx-tree__row > .nx-tree__toggle { transform: rotate(90deg); }
.nx-tree__spacer { flex: 0 0 16px; }

/* Wählbarer Knoten: renutzt .nx-select__option (Check-Glyph + Label + Hover).
 * Native Checkbox ausgeblendet — der :has-State färbt das nx-select__check.
 * Etwas knapperes Padding, damit die Zeilenmitte zu --tree-rc passt. */
.nx-tree__opt { flex: 1; min-width: 0; margin: 0; cursor: pointer; }
/* align-items: flex-start → Checkbox bleibt auf der ERSTEN Zeile (oben), statt
 * bei mehrzeiligem Label in die Mitte zu rutschen; Checkbox-Mitte = 5 + 8 =
 * 13px = --tree-rc, deckungsgleich mit Pfeil und Ast. */
.nx-tree__opt.nx-select__option { padding-top: 5px; padding-bottom: 5px; align-items: flex-start; }
.nx-tree__opt input[type=checkbox] {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.nx-tree__opt:has(input:checked) .nx-select__label,
.nx-tree__opt:has(input:indeterminate) .nx-select__label { color: var(--nxtgn-pink); }
.nx-tree__opt:has(input:checked) .nx-select__check,
.nx-tree__opt:has(input:indeterminate) .nx-select__check {
  background: var(--nxtgn-pink); border-color: var(--nxtgn-pink);
}
.nx-tree__opt:has(input:checked) .nx-select__check::after {
  content: ""; position: absolute; inset: 0;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath d='M3.5 8.2l3 3 6-6.4' fill='none' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
  background-position: center; background-repeat: no-repeat; background-size: 12px 12px;
}
/* Indeterminate (nur ein Teil der Kinder gewählt): Punkt/Strich in der Box —
 * exakt wie der Tri-State im "Alle"-Header der Multi-Selects. */
.nx-tree__opt:has(input:indeterminate) .nx-select__check::after {
  content: ""; position: absolute; inset: 4px; background: white; border-radius: 1px;
}

/* Hierarchie-Stufen optisch klar: Kategorie kräftig, Serie/Format mittel,
 * Blätter dezent + kleiner. */
.nx-tree__node[data-depth="0"] > .nx-tree__row .nx-select__label {
  font-weight: 700; font-size: 0.82rem; color: var(--gray-900);
  text-transform: uppercase; letter-spacing: 0.03em;
}
.nx-tree__node[data-depth="1"] > .nx-tree__row .nx-select__label {
  font-weight: 600; color: var(--gray-800);
}
.nx-tree__node[data-depth="2"] > .nx-tree__row .nx-select__label {
  font-weight: 400; font-size: 0.84rem; color: var(--gray-600);
}
/* Kategorie-Zeile (depth 0) bekommt eine zarte Trennlinie nach oben. */
.nx-tree__node[data-depth="0"] + .nx-tree__node[data-depth="0"] {
  margin-top: 4px; border-top: 1px solid var(--gray-100); padding-top: 4px;
}

/* Zweizeilige Quelle-Zelle (Kategorie oben, konkretes Event/Portfolio unten). */
.cell-source__cat { font-weight: 500; }
.cell-source__detail { color: var(--gray-500); font-size: 0.78rem; margin-top: 1px; }


/* ════════════════════════════════════════════════════════════════════════
   Lade-Zustände — drei Schichten (Logik in app.js):
     (1) #nx-progress  · globaler Top-Balken
     (2) .nx-skeleton  · Platzhalter-Modal beim Öffnen
     (3) .htmx-request · Button-/Icon-Spinner (Klasse setzt HTMX selbst)
   ════════════════════════════════════════════════════════════════════════ */

/* ---- (1) Globaler Top-Progress-Balken ---------------------------------- */
/* Fixiert über allem (z-index > Modal-Backdrop 200), dünn, Marken-Pink.
   Breite wird per JS getrickelt; opacity blendet am Ende weich aus. */
#nx-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 0;
  height: 3px;
  z-index: 300;
  background: linear-gradient(90deg, var(--nxtgn-pink), var(--nxtgn-pink-25));
  box-shadow: 0 0 8px rgba(228, 54, 140, 0.5);
  opacity: 0;
  pointer-events: none;
  transition: width 0.2s ease;
}
#nx-progress.is-active { opacity: 1; }
/* Abschluss: schnell auf 100 %, dann ausblenden. */
#nx-progress.is-done { transition: width 0.15s ease, opacity 0.3s ease 0.1s; opacity: 0; }

/* ---- (2) Skeleton-Platzhalter (Shimmer) -------------------------------- */
/* Graue Platzhalter-Balken mit durchlaufendem Shimmer. Reuse der Modal-
   Klassen (.modal-backdrop/.modal-card) — die Hülle sieht aus wie ein
   echtes Detail-Modal, nur ohne Inhalt. */
.skel {
  height: 14px;
  border-radius: 6px;
  background: linear-gradient(90deg,
    var(--gray-100) 25%, var(--gray-200) 37%, var(--gray-100) 63%);
  background-size: 400% 100%;
  animation: nx-shimmer 1.4s ease infinite;
}
/* Auf dem dunklen Gradient-Header: helle, halbtransparente Variante. */
.skel--onbrand {
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0.22) 25%, rgba(255, 255, 255, 0.5) 37%, rgba(255, 255, 255, 0.22) 63%);
  background-size: 400% 100%;
}
@keyframes nx-shimmer {
  from { background-position: 100% 0; }
  to   { background-position: -100% 0; }
}

/* ---- (3) Button-/Icon-Spinner während des Requests --------------------- */
/* HTMX setzt .htmx-request auf das auslösende Element. Label/Icon wird
   transparent, ein zentrierter Spinner erscheint; Klicks sind blockiert,
   das verhindert Doppel-Submits. */
/* Zwei Fälle: Button löst selbst aus (.btn.htmx-request) ODER der Button
   ist Submit eines gerade abschickenden Formulars — beim Form-Submit setzt
   HTMX die Klasse aufs <form>, nicht auf den Button. Beide Selektoren
   liefern denselben Spinner; das deckt „＋ Erfassen/Anlegen" mit ab.
   (Pure CSS greift erst, wenn HTMX die Klasse setzt — also nach der
   Validierung; ein abgebrochener Submit zeigt korrekt keinen Spinner.) */
.btn.htmx-request,
form.htmx-request button[type="submit"].btn {
  position: relative;
  /* transition: none → Label snappt sofort weg statt über die .btn-eigene
     color-Transition (100ms) langsam auszublenden. */
  transition: none;
  color: transparent !important;
  pointer-events: none;
}
.btn.htmx-request::after,
form.htmx-request button[type="submit"].btn::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 15px;
  height: 15px;
  margin: -8px 0 0 -8px;
  border: 2px solid var(--gray-400);
  border-right-color: transparent;
  border-radius: 50%;
  animation: nx-spin 0.6s linear infinite;
}
/* Auf gefüllten Buttons (Pink/Danger) ist der Spinner weiß. */
.btn--primary.htmx-request::after,
.btn--danger.htmx-request::after,
form.htmx-request button[type="submit"].btn--primary::after,
form.htmx-request button[type="submit"].btn--danger::after { border-color: var(--nxtgn-white); border-right-color: transparent; }

.icon-btn.htmx-request {
  position: relative;
  pointer-events: none;
}
.icon-btn.htmx-request svg { opacity: 0; }
.icon-btn.htmx-request::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border: 2px solid var(--gray-500);
  border-right-color: transparent;
  border-radius: 50%;
  animation: nx-spin 0.6s linear infinite;
}
/* Auf dem Gradient-Header (Detail-Modal-Aktionen) weiß. */
.icon-btn--onbrand.htmx-request::after { border-color: var(--nxtgn-white); border-right-color: transparent; }

@keyframes nx-spin { to { transform: rotate(360deg); } }

/* Reduzierte Bewegung respektieren: keine Spin-/Shimmer-/Trickle-Animation,
   die Zustände bleiben aber sichtbar (statischer Balken/Platzhalter/Spinner). */
@media (prefers-reduced-motion: reduce) {
  .skel { animation: none; }
  .btn.htmx-request::after,
  form.htmx-request button[type="submit"].btn::after,
  .icon-btn.htmx-request::after { animation: none; }
  #nx-progress { transition: opacity 0.2s ease; }
}


/* ════════════════════════════════════════════════════════════════════════
   KPI-Erfolg (Option C) — Feier, wenn eine Collab NEU Stufe 4/5 erreicht
   (max_reached_score ≥ 4 → zählt zur 2030-Zahl). JS: NXTGN.kpiReached() /
   NXTGN.confetti(). Konfetti liegt fix über allem (auch über Modals).
   ════════════════════════════════════════════════════════════════════════ */

/* Konfetti-Partikel — von JS am Element-Zentrum gespawnt (position: fixed,
   damit es auch über dem Detail-Modal sichtbar ist). */
.nx-confetti {
  position: fixed;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  z-index: 1100;            /* > Toast (1000) > Modal (200) */
  pointer-events: none;
  opacity: 0;
  will-change: transform, opacity;
}
.nx-confetti.go { animation: nx-confetti-fly 0.9s ease-out forwards; }
@keyframes nx-confetti-fly {
  0%   { opacity: 1; transform: translate(0, 0) rotate(0); }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)) rotate(var(--r)); }
}

/* KPI-Hero braucht position:relative, damit „+1" und Glow-Ring relativ dazu
   sitzen. (Wird dynamisch befüllt; siehe app.js.) */
.kpi-progress__hero { position: relative; }

/* Zahl pulst beim Hochzählen kurz auf. */
.kpi-progress__current.kpi-bump { animation: kpi-bump 0.6s cubic-bezier(.2,.9,.3,1.5); }
@keyframes kpi-bump {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.22); color: var(--nxtgn-pink-25); }
  100% { transform: scale(1); }
}

/* Pink-Glow-Ring, der von der Zahl nach außen strahlt. */
.kpi-glowring {
  position: absolute;
  left: 1.5rem;
  top: 50%;
  width: 80px;
  height: 80px;
  border-radius: 999px;
  transform: translate(-50%, -50%) scale(.4);
  border: 3px solid var(--nxtgn-pink);
  opacity: 0;
  pointer-events: none;
}
.kpi-glowring.go { animation: kpi-glow 0.7s ease-out forwards; }
@keyframes kpi-glow {
  0%   { opacity: .65; transform: translate(-50%, -50%) scale(.4); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.8); }
}

/* „+1", das über der Zahl aufsteigt und verblasst. */
.kpi-plusone {
  position: absolute;
  left: 1.5rem;
  top: 0;
  transform: translate(-50%, 8px);
  font-size: 1.4rem;
  font-weight: 800;
  color: #1f8a4c;
  pointer-events: none;
  opacity: 0;
}
.kpi-plusone.go { animation: kpi-plusone 1s cubic-bezier(.2,.8,.3,1) forwards; }
@keyframes kpi-plusone {
  0%   { opacity: 0; transform: translate(-50%, 8px) scale(.8); }
  20%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -44px) scale(1.1); }
}

/* In-Modal-Feier (Upgrade): Banner im Detail-Modal, wenn die Collab gerade
   die 2030-Schwelle (Stufe 4) überschritten hat. */
.kpi-reached-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--nxtgn-yellow) 18%, #fff),
    color-mix(in srgb, var(--nxtgn-pink) 18%, #fff));
  border: 1px solid color-mix(in srgb, var(--nxtgn-pink) 30%, #fff);
  font-weight: 600;
  color: var(--gray-900);
}
.kpi-reached-banner__badge {
  flex: 0 0 38px;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--nxtgn-gradient);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
}
.kpi-reached-banner__sub {
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--gray-600);
  margin-top: 1px;
}

@media (prefers-reduced-motion: reduce) {
  .nx-confetti, .kpi-progress__current.kpi-bump, .kpi-glowring, .kpi-plusone { animation: none; }
  .kpi-plusone, .kpi-glowring, .nx-confetti { display: none; }
}

/* ============================================================
   Auswertungen-Dashboard (/analysis)
   ============================================================ */
:root {
  --score-4-collab: #694A98;   /* Kollaboration ab Stufe 4 (violett) */
}

.analysis-section { margin: 0 0 22px; }
.analysis-h2 {
  font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em;
  margin: 0 0 12px;
}

/* Grids */
.grid { display: grid; gap: 16px; }
.grid--2 { grid-template-columns: 1fr 1fr; }
.grid--kpi { grid-template-columns: 1.5fr 1fr 1fr 1fr; }
@media (max-width: 1080px) { .grid--2, .grid--kpi { grid-template-columns: 1fr; } }

.stat__dot { display:inline-block; width:9px; height:9px; border-radius:999px; margin-right:7px; vertical-align:middle; }

/* KPI-Hero */
.hero {
  border: 1px solid var(--gray-200); border-radius: var(--radius-md);
  padding: 18px 20px; display: flex; flex-direction: column; justify-content: center;
  background: radial-gradient(120% 140% at 100% 0%,
    color-mix(in srgb, var(--nxtgn-pink) 8%, transparent), transparent 60%), var(--nxtgn-white);
}
.hero__label { font-size:0.68rem; font-weight:600; text-transform:uppercase; letter-spacing:0.07em; color:var(--gray-500); }
.hero__num { font-size:2.4rem; font-weight:700; letter-spacing:-0.03em; line-height:1; margin:8px 0 2px; }
.hero__num .cur { color: var(--nxtgn-pink); }
.hero__num .target { color: var(--gray-400); font-size:1.4rem; font-weight:600; }
.hero__track { height:10px; border-radius:999px; background:var(--gray-100); overflow:hidden; margin:14px 0 8px; }
.hero__fill { height:100%; border-radius:999px; background:var(--nxtgn-gradient); }
.hero__meta { display:flex; gap:18px; font-size:0.76rem; color:var(--gray-600); flex-wrap:wrap; }
.hero__meta b { color:var(--gray-900); font-weight:700; }

/* Split-Bar-Funnel */
/* Zeile 1 des Überblicks: KPI-Hero links, Bestands-Funnel rechts. */
.grid--hero-funnel { grid-template-columns: minmax(280px, 1fr) 2.6fr; align-items: stretch; }
@media (max-width: 1080px) { .grid--hero-funnel { grid-template-columns: 1fr; } }
.card--funnel { padding: 14px 16px; display: flex; flex-direction: column; justify-content: center; }

/* Fluss-Diagramm „Weg zur Kollaboration" (SVG aus renderFlow) */
.flowchart svg { display: block; width: 100%; height: auto; }
/* Labels dürfen das Hover auf den Strängen darunter nicht abfangen. */
.flowchart svg text { pointer-events: none; }

/* Stufen-Chips des Zeit-Charts: Multi-Select-Legende. Aktiv-Optik NUR über
 * :has(input:checked) — server-gerenderte Aktiv-Klassen blieben beim
 * Abwählen ohne Reload stale. */
.chip-row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.chart-chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 12px; border-radius: 999px;
  border: 1px solid var(--gray-200); background: var(--nxtgn-white);
  font-size: 0.75rem; font-weight: 600; color: var(--gray-500);
  cursor: pointer; user-select: none;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.chart-chip:hover { border-color: var(--gray-400); }
.chart-chip__dot {
  width: 9px; height: 9px; border-radius: 999px; flex: 0 0 auto;
  background: var(--gray-300); transition: background 120ms ease;
}
.chart-chip:has(input:checked) {
  background: color-mix(in srgb, var(--sc) 16%, var(--nxtgn-white));
  border-color: color-mix(in srgb, var(--sc) 55%, var(--nxtgn-white));
  color: var(--gray-900);
}
.chart-chip:has(input:checked) .chart-chip__dot { background: var(--sc); }

/* Chart-Toolbar + Legende */
.chart-toolbar { display:flex; gap:10px; flex-wrap:wrap; margin-bottom:14px; }
.chart-toolbar .seg-control { height:32px; }
.chart-toolbar .seg-control__opt { font-size:0.75rem; padding:0 11px; cursor:pointer; }
/* Client-seitige Chart-Umschalter (kein Reload) → Aktiv-Zustand via .is-active. */
.chart-toolbar .seg-control__opt.is-active {
  background: var(--nxtgn-white); color: var(--nxtgn-pink); box-shadow: 0 1px 2px rgba(0,0,0,.08);
}
.chart-legend { display:flex; gap:14px; flex-wrap:wrap; font-size:0.74rem; color:var(--gray-600); margin-top:10px; }
.chart-legend span { display:inline-flex; align-items:center; gap:6px; }
.chart-legend i { width:18px; height:3px; border-radius:2px; display:inline-block; }
.timechart svg { display:block; }

/* Matrix */
.matrix { position:relative; width:100%; }
.matrix svg { display:block; width:100%; height:auto; overflow:visible; }
.matrix__bubble { opacity:0.82; stroke:#fff; stroke-width:1.5; }
.matrix__lbl { font-size:10px; font-weight:700; fill:#fff; text-anchor:middle; pointer-events:none; }
.matrix__lbl--out { fill:var(--gray-700); }
.matrix__quad { font-size:10px; font-weight:700; fill:var(--gray-300); text-transform:uppercase; letter-spacing:0.05em; }
.matrix__quad--star { fill:var(--nxtgn-pink-25); }
.matrix__axis { font-size:11px; fill:var(--gray-500); font-weight:600; }
.matrix__tick { font-size:9px; fill:var(--gray-400); }

/* Farbfamilien */
.cat-broad  { background: var(--nxtgn-pink); }
.cat-member { background: var(--nxtgn-orange); }
.cat-series { background: var(--nxtgn-blue); }
.cat-neutral{ background: var(--gray-400); }
.legend { display:flex; gap:16px; flex-wrap:wrap; font-size:0.74rem; color:var(--gray-600); }
.legend span { display:inline-flex; align-items:center; gap:6px; }
.legend i { width:11px; height:11px; border-radius:3px; display:inline-block; }

/* Balken-Rankings */
.bars { display:flex; flex-direction:column; gap:11px; }
.bar-row { display:grid; grid-template-columns:150px 1fr 46px; align-items:center; gap:12px; }
.bar-row__label { font-size:0.82rem; font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bar-row__sub { font-size:0.7rem; color:var(--gray-500); font-weight:400; }
.bar-row__track { height:22px; background:var(--gray-100); border-radius:var(--radius-sm); overflow:hidden; }
.bar-row__fill { height:100%; border-radius:var(--radius-sm); position:relative; }
/* dunkles Teilsegment im Balken (z.B. „davon verstetigt") */
.bar-row__seg { position:absolute; left:0; top:0; height:100%; border-radius:var(--radius-sm) 0 0 var(--radius-sm); background:rgba(0,0,0,0.4); }
.bar-row__val { font-size:0.85rem; font-weight:700; text-align:right; }

.pill.good { background:#dcfce7; color:#15803d; }
.pill.warn { background:#fef3c7; color:#b45309; }

/* Abstand unter der Filter-Zeile */
#analysis-filters { margin-bottom: 14px; }

/* Matrix-Größenlegende */
.matrix-sizekey { display:inline-flex; align-items:center; gap:6px; color:var(--gray-500); }
.matrix-sizekey svg { display:block; }

/* Hover-Detail-Panel (Matrix-Blasen) — eigenes Panel, kein title-Attribut */
.nx-tip {
  position:fixed; z-index:60; pointer-events:none; max-width:240px;
  background:var(--nxtgn-white); border:1px solid var(--gray-200);
  border-radius:var(--radius-md); box-shadow:0 4px 16px rgba(0,0,0,0.12);
  padding:10px 12px; font-size:0.8rem;
}
.nx-tip[hidden] { display:none; }
.nx-tip__h { font-weight:700; display:flex; align-items:center; gap:7px; margin-bottom:2px; }
.nx-tip__dot { width:9px; height:9px; border-radius:999px; flex:0 0 auto; }
.nx-tip__cat { font-size:0.7rem; color:var(--gray-500); margin-bottom:8px; }
.nx-tip__row { display:flex; justify-content:space-between; gap:18px; padding:2px 0; color:var(--gray-600); }
.nx-tip__row b { color:var(--gray-900); }
.nx-tip__note { margin-top:6px; padding-top:6px; border-top:1px solid var(--gray-100); font-size:0.7rem; color:var(--nxtgn-orange); line-height:1.35; }

/* Effizienz-Tabelle */
.perf-table { width:100%; border-collapse:collapse; font-size:0.85rem; }
.perf-table th { text-align:left; font-size:0.66rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--gray-500); font-weight:600; padding:8px 10px; border-bottom:1px solid var(--gray-200); }
.perf-table th.num, .perf-table td.num { text-align:right; }
.perf-table td { padding:11px 10px; border-bottom:1px solid var(--gray-100); }
.perf-table tr:last-child td { border-bottom:none; }
.perf-name { font-weight:600; display:flex; align-items:center; gap:8px; }
.perf-dot { width:9px; height:9px; border-radius:999px; flex:0 0 auto; }
.perf-conv { display:flex; align-items:center; gap:8px; }
.perf-bar { height:6px; border-radius:999px; background:var(--gray-100); overflow:hidden; min-width:70px; flex:1; max-width:120px; }
.perf-bar i { display:block; height:100%; border-radius:999px; }


/* ════════════════════════════════════════════════════════════════════════
   Fehler-Zustände (E + F) — siehe app.js (htmx:responseError/sendError) und
   web/templates/error.html.
   ════════════════════════════════════════════════════════════════════════ */

/* E · Slot-Fehler: ein Detail-Modal/Partial konnte nicht geladen werden
   (GET 4xx/5xx). Wird in app.js in ein .modal-backdrop/.modal-card gehüllt →
   erscheint zentriert wie ein echtes Modal, statt totem/leerem Slot. */
.slot-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 14px 12px 6px;
  color: #b42318;
}
.slot-error__ic { width: 34px; height: 34px; color: #d92d20; margin-bottom: 10px; }
.slot-error h3 { margin: 0 0 4px; font-size: 1.05rem; color: var(--gray-900); }
.slot-error p { margin: 0 0 18px; color: var(--gray-600); font-size: 0.85rem; }
.slot-error__actions { display: flex; gap: 8px; justify-content: center; }

/* F · Ganzseitige Fehlerseite (Direktnavigation 404/403/500). */
.errpage {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 64px 24px;
  min-height: 60vh;
  justify-content: center;
}
.errpage__code {
  font-size: 3.4rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  background: var(--nxtgn-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.errpage h1 { margin: 12px 0 4px; }
.errpage p { color: var(--gray-500); margin: 0 0 20px; max-width: 420px; }

/* ---------------------------------------------------------------------------
 * Projektmanagement-Board (Kanban) — /projects
 *
 * Horizontale Spalten-Leiste (eigener overflow-x-Scroller), Spalten auf
 * Beige, Karten weiß mit dezentem Schatten. PM-Einträge (kind='project')
 * tragen eine violette Kante — visuelle Unterscheidung statt Erklär-Label.
 * ------------------------------------------------------------------------ */
/* Kleiner Abstand Filterzeile → Board; die Meta-Zeile (Count + „Filter
 * aufheben") liefert selbst schon optischen Puffer. Der Fokus-Glow der
 * Filter-Felder würde vom Sticky-Header (opaker Hintergrund, endet exakt auf
 * der Filter-Oberkante) übermalt — statt mehr Abstand nach oben hebt sich die
 * Zeile bei Fokus/offenem Dropdown ÜBER den Header (nur dann; beim Scrollen
 * ohne Fokus bleibt der Header normal obenauf). */
#board-filters .filter-row { margin-bottom: 6px; }
#board-filters .filter-row:focus-within { position: relative; z-index: 70; }

/* Board-Meta: nicht sticky (die kurze Zeile braucht kein Mitscrollen), eng an
 * die Filterzeile, dezente Größe wie der Count auf /collaborations. */
.list-meta--board { position: static; padding: 0 0 6px; }

/* --- Fix-Layout des Kanban-Boards (body.board-page) ----------------------
 * Die Seite selbst scrollt NICHT: .main füllt exakt den Viewport, Header +
 * Filter + Meta sitzen fix oben, das Board füllt den Rest und die einzelnen
 * Spalten scrollen intern. Gilt nur fürs Board (nicht die Galerie, die die
 * Klasse nicht setzt). */
body.board-page .app { height: 100vh; min-height: 0; overflow: hidden; }
body.board-page .main {
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding-bottom: 16px;  /* statt 80px — kein Platz für Page-Scroll nötig */
}
/* Header + Filterzeile behalten ihre natürliche Höhe; #board-results nimmt
 * den Rest und ist selbst wieder Flex-Column (Meta fix, .board füllt auf). */
body.board-page .page-header,
body.board-page #board-filters { flex: 0 0 auto; }
body.board-page #board-results {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
body.board-page .board { flex: 1 1 auto; min-height: 0; padding-bottom: 0; }
/* Die leeren Modal-Slots dürfen das Flex-Layout nicht strecken. */
body.board-page #collab-create,
body.board-page #collab-detail,
body.board-page #event-modal { flex: 0 0 auto; }

.board {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  overflow-x: auto;
  padding: 4px 2px 20px;
}
.board-col {
  flex: 0 0 300px;
  max-width: 300px;
  background: var(--nxtgn-beige);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  /* Füllt die Höhe des .board-Containers (der im Fix-Layout den Rest des
   * Viewports einnimmt) — lange Spalten scrollen intern (board-col__body),
   * die Seite selbst scrollt nicht. */
  max-height: 100%;
}
.board-col--terminal { background: var(--gray-100); }
.board-col__head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  position: sticky;
  top: 0;
}
.board-col__name {
  font-weight: 600;
  font-size: 0.82rem;
  line-height: 1.25;
  min-width: 0;
}
.board-col__count {
  color: var(--gray-500);
  font-size: 0.8rem;
  font-weight: 600;
  margin-left: auto;
}
.board-col__add { flex: 0 0 auto; }
.board-col__body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 2px 10px 12px;
  overflow-y: auto;
  min-height: 60px;  /* leere Spalte bleibt Drop-Ziel */
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}
/* Drop-Feedback: Spalte hebt sich, solange eine Karte darüber schwebt. */
.board-col.is-over .board-col__body {
  outline: 2px dashed var(--nxtgn-pink);
  outline-offset: -4px;
  border-radius: var(--radius-md);
}
.board-card {
  background: #fff;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  cursor: grab;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.04);
}
.board-card:hover { border-color: var(--gray-300); box-shadow: 0 2px 6px rgb(0 0 0 / 0.07); }
.board-card.is-dragging { opacity: 0.45; cursor: grabbing; }
/* PM-Eintrag: violette Kante (vgl. status-chip--pm) statt Text-Label. */
.board-card--project { border-left: 3px solid var(--nxtgn-purple); }
/* On hold: Karte tritt entsättigt/gedimmt zurück + Pause-Glyphe oben
 * rechts — Zustand rein visuell, kein Text-Label. Hover holt die Karte
 * zurück in den Fokus (Inhalt bleibt lesbar/bedienbar). */
.board-card--onhold {
  position: relative;
  opacity: 0.55;
  filter: grayscale(0.85);
  background: var(--gray-50);
  transition: opacity .15s ease, filter .15s ease;
}
.board-card--onhold:hover { opacity: 0.95; filter: grayscale(0.25); }
.board-card--onhold .board-card__hold {
  position: absolute;
  top: 8px;
  right: 8px;
  color: var(--gray-400);
}
.board-card--onhold .board-card__hold svg { width: 13px; height: 13px; display: block; }
/* Platz fürs Pause-Icon, damit lange Org-Namen nicht drunterrutschen. */
.board-card--onhold .board-card__orgs { padding-right: 18px; }
.board-card__orgs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 6px;
  align-items: baseline;
  font-weight: 600;
  font-size: 0.86rem;
  line-height: 1.3;
}
.board-card__x { font-weight: 300; color: var(--gray-400); }
.board-card__source {
  margin-top: 4px;
  font-size: 0.74rem;
  color: var(--gray-500);
}
/* Topic hebt sich nur leicht ab — etwas kräftiger als Notiz/Quelle (500),
 * aber bewusst NICHT so stark wie die Org-Zeile (600/0.86rem). */
.board-card__topic {
  margin-top: 6px;
  font-size: 0.8rem;
  font-weight: 500;
  line-height: 1.35;
}
.board-card__notes {
  margin-top: 4px;
  font-size: 0.76rem;
  color: var(--gray-500);
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.board-card__meta {
  margin-top: 8px;
  font-size: 0.72rem;
  color: var(--gray-500);
}
.board-empty {
  text-align: center;
  padding: 72px 24px;
  max-width: 480px;
  margin: 0 auto;
}
.board-empty__title { font-weight: 700; font-size: 1.05rem; margin-bottom: 6px; }

/* Spalten-Reorder (Pointer-Events): Header ist der Griff. Die gegriffene
 * Spalte wird halbtransparent + gestrichelt markiert und rückt live an ihre
 * neue Position; die übrigen reflowen. touch-action:none, damit ein Zug am
 * Header nicht die Seite scrollt. */
.board-col__head { cursor: grab; touch-action: none; }
.board-col.is-col-dragging {
  opacity: 0.5;
  outline: 2px dashed var(--nxtgn-pink-60);
  outline-offset: -2px;
}
body.is-col-reordering,
body.is-col-reordering * { cursor: grabbing !important; user-select: none; }

/* „An neuem Platz"-Bestätigung: kurzer, dezenter pinker Ring, der ausklingt
 * (kein Toast — nur an der Box). */
@keyframes nx-col-settled {
  0%   { box-shadow: 0 0 0 2px var(--nxtgn-pink); }
  100% { box-shadow: 0 0 0 2px transparent; }
}
.board-col.is-just-moved { animation: nx-col-settled 0.9s ease-out; }

/* --- Sortier-Menü (/projects) — cleanes Icon + eigenes Popover ------------ */
.sortmenu { position: relative; }
.sortmenu__trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  background: var(--nxtgn-white);
  color: var(--gray-600);
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.sortmenu__trigger svg { width: 18px; height: 18px; }
.sortmenu__trigger:hover { border-color: var(--gray-300); color: var(--gray-900); }
/* Aktiv = etwas anderes als der Default (neueste zuerst) gewählt. */
.sortmenu.is-active .sortmenu__trigger {
  background: var(--nxtgn-pink-80);
  border-color: var(--nxtgn-pink-60);
  color: var(--nxtgn-pink-25);
}
.sortmenu.is-open .sortmenu__trigger { border-color: var(--nxtgn-pink); color: var(--nxtgn-pink); }

.sortmenu__pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 80;
  min-width: 210px;
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .12);
  padding: 6px;
}
.sortmenu__head {
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gray-400);
  font-weight: 700;
  padding: 6px 10px 8px;
}
.sortmenu__opt {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  background: none;
  border-radius: 6px;
  font: inherit;
  font-size: 0.83rem;
  color: var(--gray-700);
  cursor: pointer;
  text-align: left;
}
.sortmenu__opt:hover { background: var(--gray-50); }
.sortmenu__opt.is-sel { background: var(--nxtgn-pink-80); color: var(--nxtgn-pink-25); font-weight: 600; }
.sortmenu__ic { flex: 0 0 auto; display: inline-flex; color: var(--gray-400); }
.sortmenu__opt.is-sel .sortmenu__ic { color: var(--nxtgn-pink-25); }
.sortmenu__ic svg { width: 15px; height: 15px; }
.sortmenu__lbl { flex: 1 1 auto; }
.sortmenu__check { flex: 0 0 auto; display: none; color: var(--nxtgn-pink-25); }
.sortmenu__check svg { width: 15px; height: 15px; }
.sortmenu__opt.is-sel .sortmenu__check { display: inline-flex; }

/* ---------------------------------------------------------------------------
 * Board-Kopf + Saved-Views-UX (/projects) — Kombi aus Galerie-Einstieg
 * (Mockup C) und View-Button mit Verwaltungs-Popover (Mockup B).
 * ------------------------------------------------------------------------ */
.board-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.board-head__back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-md);
  color: var(--gray-500);
  flex: 0 0 auto;
}
.board-head__back:hover { background: var(--gray-100); color: var(--gray-900); }
.board-head__back svg { width: 19px; height: 19px; }
.board-head__eyebrow {
  font-size: 0.66rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--gray-400);
  margin-bottom: 1px;
}
.board-head__row { display: flex; align-items: center; gap: 12px; min-width: 0; }

/* Der Board-Name IST der View-Wechsler: Titel-groß, öffnet das Popover. */
.viewmenu { position: relative; min-width: 0; }
.viewmenu__trigger {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  border: none;
  background: none;
  padding: 2px 6px 2px 0;
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--gray-900);
  cursor: pointer;
  max-width: 46vw;
  min-width: 0;
}
.viewmenu__trigger:hover .viewmenu__title { color: var(--nxtgn-pink); }
.viewmenu__ic { display: inline-flex; color: var(--nxtgn-pink); flex: 0 0 auto; }
.viewmenu__ic svg { width: 20px; height: 20px; }
.viewmenu__title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.3;
}
.viewmenu__chev { display: inline-flex; color: var(--gray-400); flex: 0 0 auto; }
.viewmenu__chev svg { width: 15px; height: 15px; }
.viewmenu.is-open .viewmenu__chev { transform: rotate(180deg); }

.viewmenu__pop {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 80;
  width: 400px;
  max-width: 90vw;
  background: var(--nxtgn-white);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-lg);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .14);
  overflow: hidden;
}
.viewmenu__search {
  display: block;
  width: calc(100% - 20px);
  margin: 10px;
  padding: 8px 12px;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-md);
  font: inherit;
  font-size: 0.8rem;
}
.viewmenu__search:focus { outline: none; border-color: var(--nxtgn-pink); }
.viewmenu__list { max-height: 320px; overflow-y: auto; padding-bottom: 4px; }
.viewmenu__row { display: flex; align-items: center; gap: 6px; padding: 0 8px 0 0; }
.viewmenu__row:hover { background: var(--gray-50); }
/* Aktive Zeile nur zart pink hinterlegt (pink-80 wirkte zu kräftig). */
.viewmenu__row.is-active { background: color-mix(in srgb, var(--nxtgn-pink) 8%, #fff); }
.viewmenu__open {
  flex: 1 1 auto;
  min-width: 0;
  padding: 9px 6px 9px 14px;
  text-decoration: none;
  color: inherit;
}
.viewmenu__open:hover { text-decoration: none; }
.viewmenu__name-lbl {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.viewmenu__meta { display: block; font-size: 0.68rem; color: var(--gray-500); margin-top: 1px; }
/* Zeilen-Aktionen (Umbenennen/Löschen) erst beim Hover — ruhige Liste. */
.viewmenu__acts { display: none; flex: 0 0 auto; gap: 2px; }
.viewmenu__row:hover .viewmenu__acts,
.viewmenu__row:focus-within .viewmenu__acts { display: inline-flex; }
.viewmenu__rename { margin: 6px 0; font-size: 0.85rem; padding: 4px 8px; width: 100%; }
.viewmenu__empty { padding: 18px 14px; font-size: 0.8rem; color: var(--gray-500); text-align: center; }
.viewmenu__foot { border-top: 1px solid var(--gray-100); padding: 8px 10px; }
.viewmenu__saveas {
  display: block;
  width: 100%;
  border: none;
  background: none;
  padding: 6px 4px;
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--nxtgn-pink);
  text-align: left;
  cursor: pointer;
  border-radius: 6px;
}
.viewmenu__saveas:hover { background: var(--gray-50); }
.viewmenu__saveas-form { display: flex; gap: 6px; align-items: center; padding: 2px; }
.viewmenu__saveas-form .input { flex: 1 1 auto; }

/* Zustands-Chip neben dem Board-Namen (✓ gespeichert / ● geändert / …). */
.statechip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}
.statechip--saved { background: #ecfdf5; color: #047857; }
.statechip--dirty { background: #fff7ed; border: 1px solid #fed7aa; color: #9a3412; padding-right: 5px; }
.statechip--unsaved {
  background: var(--gray-100);
  color: var(--gray-600);
  border: none;
  font-family: inherit;
  cursor: pointer;
}
.statechip--unsaved:hover { background: var(--nxtgn-pink-80); color: var(--nxtgn-pink-25); }
.statechip__act {
  border: none;
  background: var(--nxtgn-pink);
  color: #fff;
  border-radius: 999px;
  padding: 3px 11px;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
}
.statechip__act:hover { background: var(--nxtgn-pink-25); }
.statechip__ghost { color: #9a3412; font-weight: 500; padding: 3px 6px; text-decoration: none; }
.statechip__ghost:hover { text-decoration: underline; }

/* Galerie (Einstieg): Karten der gespeicherten Boards. */
.board-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px;
}
.gcard {
  display: block;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-lg);
  padding: 18px 20px;
  background: var(--nxtgn-white);
  color: inherit;
  text-decoration: none;
}
.gcard:hover {
  text-decoration: none;
  border-color: var(--nxtgn-pink-60);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .06);
}
.gcard__name { margin: 0 0 10px; font-size: 0.98rem; line-height: 1.3; }
.gcard__mini { display: flex; gap: 4px; margin-bottom: 12px; }
.gcard__mini span {
  flex: 1;
  height: 34px;
  background: var(--nxtgn-beige);
  border-radius: 4px;
  position: relative;
}
.gcard__mini span::after {
  content: "";
  position: absolute;
  top: 5px;
  left: 5px;
  right: 5px;
  height: 7px;
  background: var(--nxtgn-white);
  border-radius: 2px;
}
.gcard__scope { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.gcard__chip {
  background: var(--nxtgn-pink-80);
  color: var(--nxtgn-pink-25);
  border-radius: 999px;
  padding: 2px 10px;
  font-size: 0.72rem;
  font-weight: 600;
}
.gcard__chip--muted { background: var(--gray-100); color: var(--gray-600); }
.gcard__meta { font-size: 0.7rem; color: var(--gray-500); }
.gcard--new {
  border-style: dashed;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--gray-500);
  font-weight: 600;
  font-size: 0.9rem;
  min-height: 150px;
  background: var(--gray-50);
}
.gcard--new:hover { color: var(--nxtgn-pink); box-shadow: none; }

/* ---------------------------------------------------------------------------
   Org-Hovercard — Nuntium-Profil (Beschreibung, Land, Gründungsjahr, Links).
   Affordance: Orgs MIT Profil bekommen in den dichten Ansichten (Collab-
   Tabelle, Kanban, Collab-Detail-Header) eine gepunktete Unterstreichung;
   Orgs ohne Profil bleiben unangetastet. Die Karte selbst wird vom
   OrgHovercard-Modul (app.js) lazy geladen und fixed positioniert.
--------------------------------------------------------------------------- */
.org-hint {
  text-decoration: underline dotted var(--gray-400) 1.5px;
  text-underline-offset: 3px;
}
.org-hint:hover,
.org-hint:focus-visible { text-decoration-color: var(--nxtgn-pink); }
/* Auf dem Gradient-Header (Collab-Detail): weiße Punkte statt grauer. */
.org-hint--onbrand { text-decoration-color: rgba(255, 255, 255, 0.55); }
.org-hint--onbrand:hover,
.org-hint--onbrand:focus-visible { text-decoration-color: #fff; }
/* Klick öffnet das Org-Detail (nur wo data-org-open gesetzt ist). */
[data-org-open] { cursor: pointer; }

.org-hovercard {
  position: fixed;
  z-index: 300; /* über Modal-Backdrops — die Karte gehört zum Trigger darunter */
  width: 320px;
  background: #fff;
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.16);
  padding: 14px 16px 0;
  color: var(--gray-900);
  font-weight: 400;
  /* Beim internen Scrollen (aufgeklappte Beschreibung) am Rand NICHT zur
   * Seite durchscrollen. */
  overscroll-behavior: contain;
}
.org-hovercard__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.org-hovercard__name { font-weight: 700; font-size: 0.95rem; }
.org-hovercard__type {
  flex: 0 0 auto;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  background: var(--nxtgn-beige);
  color: var(--gray-700);
  border-radius: 4px;
  padding: 3px 7px;
}
.org-hovercard__desc {
  margin: 8px 0 0;
  font-size: 0.79rem;
  line-height: 1.5;
  color: var(--gray-700);
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* „mehr anzeigen" hebt die Klammerung auf (Toggle im OrgHovercard-Modul).
 * Die Beschreibung wächst voll aus; scrollt bei Überlauf die GANZE Karte
 * (maxHeight/overflow setzt das JS), damit die Karte nicht nach oben
 * springt und unter dem Cursor wegrutscht. */
.org-hovercard__desc.is-expanded {
  display: block;
  -webkit-line-clamp: unset;
  max-height: none;
  overflow: visible;
}
.org-hovercard__more {
  border: none;
  background: none;
  padding: 0;
  margin-top: 4px;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--gray-500);
  cursor: pointer;
}
.org-hovercard__more:hover { color: var(--gray-700); }
.org-hovercard__facts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.org-hovercard__chip {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--gray-700);
  background: var(--nxtgn-beige);
  border-radius: 4px;
  padding: 3px 8px;
}
.org-hovercard__links {
  display: flex;
  gap: 14px;
  margin-top: 10px;
  font-size: 0.78rem;
  font-weight: 600;
}
.org-hovercard__links a { color: var(--nxtgn-pink); text-decoration: none; }
.org-hovercard__links a:hover { text-decoration: underline; }
.org-hovercard__ext { font-size: 0.66rem; }
.org-hovercard__foot {
  margin-top: 12px;
  padding: 8px 0 9px;
  border-top: 1px solid var(--gray-100);
  font-size: 0.67rem;
  color: var(--gray-400);
}

/* Profil-Sektion im Org-Detail-Modal (gleiche Daten, voll sichtbar). */
.org-profile__desc {
  margin: 0 0 10px;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--gray-900);
}
.org-profile__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  align-items: center;
}
.org-profile__link {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--nxtgn-pink);
  text-decoration: none;
}
.org-profile__link:hover { text-decoration: underline; }
.org-profile__source { margin-top: 10px; }
