/**
 * Kajinga UI — components.css (Stufe 2, opt-in via ks_enqueue())
 *
 * CSS NUR für Komponenten, die der Styler nicht abdeckt: Page-Header,
 * Stat-Trends, Switch, Skeleton, Dropdown, Toolbar, Tabellen-Sortier-UI,
 * Card-Header-Ergänzungen. Ausschließlich Token-basiert, Dark Mode am Ende.
 */

/* =========================================
 * PAGE-HEADER
 * ========================================= */

.ks-page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--kajinga-space-5, 20px);
    flex-wrap: wrap;
    /* v4.0.85: 24 -> 20. Gilt für Hero UND plain-Variante — der Header soll
       insgesamt weniger Raum nehmen, nicht nur der farbige. */
    margin-bottom: var(--kajinga-space-5, 20px);
}

.ks-page-header--plain {
    padding: var(--kajinga-space-4, 16px) 0 0;
}

.ks-page-header-main {
    min-width: 0;
}

/* Zurück-Pfeil (v3.7.31): super simpel, nur das Chevron
 * v4.0.51: Hier stand ein zweiter, konkurrierender .ks-page-back-Block weiter
 * unten in dieser Datei (bei den Header-Actions). Gleiche Spezifitaet, also
 * gewann der spaetere — die Werte unten sind deshalb die EFFEKTIVEN von vorher:
 * margin-right/color/padding/border-radius/align-self kamen aus dem zweiten
 * Block, flex/justify-content/transition/text-decoration aus diesem. Der
 * doppelte :hover war redundant (setzte nur, was hier ohnehin steht, ohne
 * :focus abzudecken). Optik unveraendert, am Staging nachgemessen. */
.ks-page-back {
    flex: none;
    display: inline-flex;
    align-items: center;
    align-self: center;
    justify-content: center;
    margin-right: var(--kajinga-space-2, 8px);
    padding: 4px;
    border-radius: var(--kajinga-radius-sm, 6px);
    color: inherit;
    opacity: 0.8;
    transition: opacity 0.15s ease, transform 0.15s ease;
    text-decoration: none;
}

.ks-page-back:hover,
.ks-page-back:focus {
    opacity: 1;
    color: inherit;
    box-shadow: none;
    outline: none;
}

.ks-hero .ks-page-back {
    color: #fff;
}

.ks-hero .ks-page-back:hover {
    color: #fff;
    transform: translateX(-2px);
}

/* Hero-Rechts-Varianten (v3.8.12): Suchfeld bzw. Status-Block statt Button
 * — als Roh-HTML in den actions-Slot geben */
.ks-hero-search {
    display: flex;
    align-items: center;
    gap: 8px;
}

.ks-hero-search .ks-hero-search-input {
    width: min(320px, 34vw);
    height: 40px;
    padding: 0 14px;
    border: none;
    border-radius: 10px;
    background: #fff;
    color: var(--kajinga-text, #1d2327);
    font-size: 14px;
    box-shadow: inset 0 1px 2px rgba(16, 24, 40, 0.08);
}

.ks-hero-search .ks-hero-search-input:focus {
    outline: 2px solid rgba(255, 255, 255, 0.6);
    outline-offset: 1px;
}

.ks-hero-search .ks-btn-inverse {
    height: 40px;
}

.ks-hero-status {
    text-align: right;
    color: #fff;
}

.ks-hero-status .ks-hero-status-value {
    font-family: var(--kajinga-font-display, var(--kajinga-font, sans-serif));
    font-size: 24px;
    font-weight: 800;
    line-height: 1.2;
}

.ks-hero-status .ks-hero-status-label {
    font-size: 14.5px;
    color: rgba(255, 255, 255, 0.85);
}

/* Hero nach Builder-Muster (v3.7.28): Icon-Box links, Titel fett,
 * alles vertikal zentriert, Button rechts */
.ks-hero.ks-page-header {
    align-items: center;
    /* +3px: optischer Feinausgleich zur Sidebar-Karte (Wrap-Abstand bleibt 12px) */
    margin-top: 3px;
}

.ks-hero-iconbox {
    flex: none;
    /* Bestimmt die Mindesthöhe des Heros mit — weniger Innenabstand allein
       hätte kaum etwas gebracht (v4.0.85). */
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.16);
    border-radius: 12px;
    color: #fff;
}

.ks-hero .ks-page-header-main {
    flex: 1;
    min-width: 0;
}

.ks-page-header .ks-hero-title {
    /* v4.0.85: 26 -> 23. Zusammen mit der kleineren Icon-Box (52 -> 44) und
       17px statt 22px Innenabstand sinkt die Hero-Höhe von 104 auf 89 px. */
    font-size: 23px;
    font-weight: 800;
    line-height: 1.25;
}

/* Härtung (v3.8.19): Plugin-Alt-CSS aus der Vor-Hero-Ära (.plugin-wrap h1
   { color/margin … }) gewinnt per Spezifität gegen .ks-hero-title — Titelfarbe
   und Margin des Heros deshalb mit Element+Doppelklasse festnageln. */
.ks-page-header.ks-hero h1.ks-hero-title,
.ks-page-header.ks-hero h1.ks-hero-title span {
    color: var(--kajinga-hero-text, #fff);
}
.ks-page-header.ks-hero h1.ks-hero-title {
    margin: 0;
}

/* „Brand – Thema"-Titel (v3.8.16): Plugin-Name fett zur Verortung,
   Seitenthema halbfett, Trenner dezent. Gilt für Hero + plain-Variante. */
.ks-hero-brand {
    font-weight: 800;
}
.ks-hero-title-sep {
    font-weight: 400;
    opacity: 0.55;
    margin: 0 0.4em;
}
.ks-hero-topic {
    font-weight: 600;
}

.ks-hero .ks-hero-text {
    margin: 2px 0 0;
    font-size: 14.5px;
    /* v4.0.98: volles Weiß statt 0,92 — die Deckkraft kostete 0,28 Kontrast-
       stufen (3,36 → 3,07 auf dem alten Verlauf) und war der Unterschied
       zwischen „knapp drunter" und „deutlich drunter". Zusammen mit dem
       abgedunkelten Verlauf (token-utilities.tpl) steht der Untertitel jetzt
       bei 4,55:1. Der Ton der Zeile trägt die kleinere Schrift, nicht die
       Transparenz. */
    color: #ffffff;
}

.ks-page-header .ks-hero-title,
.ks-page-title {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    padding: 0;
}

.ks-page-title {
    font-size: 22px;
    font-weight: 600;
    color: var(--kajinga-text, #1d2327);
    line-height: 1.3;
}

.ks-page-subtitle {
    margin: 6px 0 0;
    font-size: 14.5px;
    color: var(--kajinga-text-muted, #646970);
}

/* Stufen-Badge im Titel (v4.0.52) — `ks_plan_badge()` fuer den title_badge-Slot.
 * Zeigt die gebuchte Stufe: „Pro" als Label, „Basis" als Link zum Upgrade.
 * Herkunft: .brain-tier-badge aus kajinga-brain, hier zentralisiert.
 *
 * ACHTUNG Spezifitaet: Im Hero faerbt `.ks-page-header.ks-hero h1.ks-hero-title span`
 * (0,3,1) JEDEN Span im Titel weiss. Brain setzte seine Textfarbe mit (0,1,0) und
 * verlor deshalb still — das Pro-Badge trug weisse Schrift auf Gold (Kontrast ~1,4:1
 * statt der beabsichtigten ~9:1). Die Farbregeln unten stehen darum zusaetzlich mit
 * dem Hero-Praefix (0,4,1). Wer eine weitere Stufe ergaenzt, MUSS beide Selektoren
 * mitnehmen, sonst ist die Schrift im Hero wieder weiss. */
.ks-plan-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    margin-left: 10px;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.5;
    border-radius: 999px;
    vertical-align: middle;
    text-decoration: none;
    transition: background-color 0.15s ease, box-shadow 0.15s ease;
}

.ks-plan-badge:hover,
.ks-plan-badge:focus {
    text-decoration: none;
    box-shadow: none;
}

/* Basis — neutrale Pille, klickbar (Upgrade-Ziel) */
.ks-page-header.ks-hero h1.ks-hero-title .ks-plan-badge--basic,
.ks-plan-badge--basic {
    background: var(--kajinga-gray-200, #e5e7eb);
    color: var(--kajinga-gray-700, #374151);
}

a.ks-plan-badge--basic { cursor: pointer; }

.ks-page-header.ks-hero h1.ks-hero-title a.ks-plan-badge--basic:hover,
a.ks-plan-badge--basic:hover,
a.ks-plan-badge--basic:focus {
    background: var(--kajinga-gray-300, #d1d5db);
    color: var(--kajinga-gray-800, #1f2937);
}

/* Pro — Gold. Textfarbe dunkel, sonst unlesbar (siehe Hinweis oben) */
.ks-page-header.ks-hero h1.ks-hero-title .ks-plan-badge--pro,
.ks-plan-badge--pro {
    background: linear-gradient(135deg, #ffd700, #ffb300);
    color: #3a2800;
    box-shadow: 0 1px 3px rgba(255, 179, 0, 0.3);
}

/* Beta — Bereich ist nutzbar, aber noch in Arbeit (v4.1.6).
 * Deckende Amber-Fläche, keine Tönung: Im Hero liegt das Badge auf dem
 * Marken-Verlauf, und eine halbtransparente Fläche würde dessen Farbe
 * durchlassen — je nach Plugin mal grün, mal blau unterlegt.
 * Wie bei --pro steht die Farbregel zusätzlich mit dem Hero-Präfix (0,4,1),
 * sonst überschreibt `.ks-page-header.ks-hero h1.ks-hero-title span` (0,3,1)
 * die Schriftfarbe still auf Weiß. */
.ks-page-header.ks-hero h1.ks-hero-title .ks-plan-badge--beta,
.ks-plan-badge--beta {
    background: #fef3c7;
    color: #92400e;
}

body.kajinga-dark-mode .ks-page-header.ks-hero h1.ks-hero-title .ks-plan-badge--beta,
body.kajinga-dark-mode .ks-plan-badge--beta {
    background: rgba(245, 158, 11, 0.22);
    color: #fcd34d;
}

.ks-plan-badge .ks-icon,
.ks-plan-badge svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

/* Verbrauchs-Zaehler „3 / 5" (v4.0.54) — steht neben dem Stufen-Badge.
 * Zentralisiert aus .brain-tier-counter und .mb-tier-counter; uebernommen ist
 * die Brain-Fassung, weil sie tabular-nums und einen Hover-State hatte.
 * tabular-nums ist hier kein Detail: ohne die Ziffern gleicher Breite springt
 * die Pille beim Hochzaehlen (9 -> 10) sichtbar in der Breite. */
.ks-usage-counter {
    display: inline-flex;
    align-items: center;
    margin-left: 8px;
    padding: 3px 11px;
    border-radius: 999px;
    background: var(--kajinga-gray-100, #f3f4f6);
    color: var(--kajinga-gray-700, #374151);
    font-size: 14px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    vertical-align: middle;
    text-decoration: none;
}

/* Im Hero faerbt der Styler jeden Titel-Span weiss (0,3,1) — dieselbe Falle wie
 * beim Stufen-Badge. Deshalb hier ebenfalls mit Hero-Praefix (0,4,1).
 *
 * WEISSE Pille mit Text in der Primaerfarbe, NICHT weisser Text auf einer
 * halbtransparent-weissen Flaeche. Der Hero ist ein Verlauf (#0b6fc0 ->
 * #179afc -> #36b3ff), und gegen das HELLE Ende gemessen ergab die transparente
 * Fassung nur 2,0:1 — unlesbar. Werte ueber die drei Stops:
 *   weiss 0.18 + weisser Text : 3,75 / 2,46 / 2,00
 *   schwarz 0.28 + weisser Text: 8,32 / 5,30 / 4,27
 *   weiss 0.92 + Primaerfarbe : 4,51 / 4,66 / 4,74  <- einzige, die ueberall AA haelt
 * Der Text nimmt die Familienfarbe an (Schemata faerben --kajinga-primary um);
 * das ist hier unkritisch, weil er auf Weiss steht und nicht auf der Flaeche. */
.ks-page-header.ks-hero h1.ks-hero-title .ks-usage-counter {
    background: rgba(255, 255, 255, 0.92);
    color: var(--kajinga-primary, #2271b1);
}

a.ks-usage-counter:hover,
a.ks-usage-counter:focus {
    background: var(--kajinga-gray-200, #e5e7eb);
    text-decoration: none;
}

.ks-page-header.ks-hero h1.ks-hero-title a.ks-usage-counter:hover,
.ks-page-header.ks-hero h1.ks-hero-title a.ks-usage-counter:focus {
    background: #fff;
    color: var(--kajinga-primary, #2271b1);
}

/* Neutrales Badge im title_badge-Slot (v4.1.11) — z. B. eine Versionsnummer
 * oder Kennung neben dem Seitentitel. .ks-badge bringt eigene Farben mit,
 * verliert im Hero aber gegen `h1.ks-hero-title span` (0,3,1) und stuende
 * sonst weiss auf hellgrau. Farbwahl wie beim Verbrauchs-Zaehler oben:
 * weisse Flaeche 0,92 + Primaerfarbe ist die einzige Kombination, die ueber
 * alle drei Verlaufs-Stops AA haelt (4,51 / 4,66 / 4,74).
 * Die getoenten Varianten (ks-badge-info/success/…) bleiben unangetastet —
 * ihre halbtransparente Flaeche gehoert nicht auf den Hero-Verlauf. */
.ks-page-header.ks-hero h1.ks-hero-title .ks-badge {
    margin-left: 10px;
    background: rgba(255, 255, 255, 0.92);
    color: var(--kajinga-primary, #2271b1);
    font-size: 13px;
    font-weight: 600;
    vertical-align: middle;
}

body.kajinga-dark-mode .ks-usage-counter {
    background: var(--kajinga-gray-700, #374151);
    color: var(--kajinga-gray-100, #f3f4f6);
}

body.kajinga-dark-mode .ks-plan-badge--basic {
    background: var(--kajinga-gray-700, #374151);
    color: var(--kajinga-gray-100, #f3f4f6);
}

body.kajinga-dark-mode a.ks-plan-badge--basic:hover {
    background: var(--kajinga-gray-600, #4b5563);
    color: #fff;
}

.ks-page-header-icon {
    color: var(--kajinga-primary, #2271b1);
}

.ks-hero .ks-page-header-icon {
    color: currentColor;
}

.ks-page-kpis {
    display: flex;
    gap: var(--kajinga-space-5, 20px);
    flex-wrap: wrap;
    margin-top: var(--kajinga-space-4, 16px);
    font-size: 14.5px;
}

/* Detail-Header: Meta-Zeile (Badges/Status einer Entität) unter dem Subtitle */
.ks-page-header-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: var(--kajinga-space-2, 8px);
    font-size: 14.5px;
}

.ks-page-header--plain .ks-page-header-meta {
    color: var(--kajinga-text-muted, #646970);
}

.ks-page-kpi strong {
    font-size: 17px;
    font-weight: 700;
    margin-right: 4px;
}

.ks-page-header--plain .ks-page-kpi {
    color: var(--kajinga-text-muted, #646970);
}

.ks-page-header--plain .ks-page-kpi strong {
    color: var(--kajinga-text, #1d2327);
}

.ks-page-header-actions {
    display: flex;
    gap: var(--kajinga-space-2, 8px);
    align-items: center;
    flex-shrink: 0;
    flex-wrap: wrap;
}

/* v4.0.51: Der hier frueher stehende zweite .ks-page-back-Block (plus sein
 * redundanter :hover) ist in den Basis-Block oben zusammengefuehrt. */
.ks-page-header--plain .ks-page-back {
    color: var(--kajinga-text-muted, #646970);
}

/* Sekundaer-Leiste unter dem Header (v3.8.9): "Anpassen"/Settings-
 * Aktionen — dezent, rechtsbuendig, zieht sich nah an den Header */
.ks-page-tools {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
    margin: calc(-1 * var(--kajinga-space-4, 16px)) 0 var(--kajinga-space-5, 20px);
}

.ks-page-tools .ks-btn-ghost {
    color: var(--kajinga-text-muted, #646970);
}

.ks-page-tools .ks-btn-ghost:hover {
    color: var(--kajinga-text, #1d2327);
}

/* Hero-Ghost (v3.10.4): Sekundäre Aktionen im Brand-Hero. Der Standard-Ghost
   trägt Border und Text in --kajinga-primary — auf dem Primary-Hintergrund des
   Heros wäre er unsichtbar (dasselbe „lila auf lila", weswegen der Haupt-Button
   dort invers ist). Nötig, seit die Header-Konvention bis zu 3 Aktionen erlaubt:
   ohne diese Variante werden alle gleich gewichtet.
   Betrifft nur Aktionen INNERHALB von .ks-hero; die .ks-page-tools-Leiste ist
   ein Geschwister (page_header schließt den Hero, bevor sie ausgegeben wird)
   und behält den gedeckten Standard-Ghost von oben. */
.ks-hero .ks-btn-ghost {
    background: transparent;
    border-color: rgba(255, 255, 255, 0.55);
    color: #fff;
}

.ks-hero .ks-btn-ghost:hover {
    background: rgba(255, 255, 255, 0.14);
    border-color: #fff;
    color: #fff;
}

/* Gleicher Fokus-Ring wie .ks-btn-inverse (core.css) — im Hero müssen beide
   Varianten identisch fokussieren. */
.ks-hero .ks-btn-ghost:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.45);
}

/* =========================================
 * CHIPS (Mehrfachauswahl-Filter)
 * ========================================= */

.ks-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.ks-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    border-radius: var(--kajinga-radius-full, 9999px);
    background: var(--kajinga-gray-50, #f6f7f7);
    color: var(--kajinga-text-muted, #646970);
    cursor: pointer;
    font-size: 14.5px;
    user-select: none;
    transition: var(--kajinga-transition-fast, all 0.12s ease);
}

.ks-chip:hover {
    border-color: var(--kajinga-gray-400, #a7aaad);
    color: var(--kajinga-text, #1d2327);
}

.ks-chip input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.ks-chip:has(input:checked) {
    background: var(--kajinga-primary, #2271b1);
    border-color: var(--kajinga-primary, #2271b1);
    color: #fff;
    font-weight: 500;
}

/* =========================================
 * AKTIONS-GRUPPEN (z.B. Tabellen-Zeilen)
 * ========================================= */

/* Buttons aus konkateniertem Markup (kein Whitespace) sauber auf Abstand
   bringen — Ersatz für die "natürlichen" Lücken durch Template-Zeilenumbrüche */
.ks-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

/* =========================================
 * ROW-ACTIONS (v3.9.53) — Aktions-Buttons in Tabellenzeilen
 * Icon-only + Tooltip. Hover nutzt --kajinga-primary, damit ULTRA (Pink)
 * und Magic (Lila) über die Schema-Overrides automatisch greifen.
 * ========================================= */

.ks-row-actions {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.ks-row-actions--end {
    justify-content: flex-end;
    width: 100%;
}

.ks-row-actions .ks-row-action.ks-btn {
    position: relative;
    /* v3.9.54: schlanker Rahmen bleibt (wie vorher in Boost) und das Icon
       wird zentriert — .ks-btn bringt kein justify-content mit, dadurch
       hing das Icon bei fester Breite links. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    width: 32px;
    height: 32px;
    padding: 0;
    min-height: 0;
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    background: var(--kajinga-card-solid, #fff);
    border-radius: 8px;
    color: var(--kajinga-text-muted, #646970);
    transition: background 0.14s ease, color 0.14s ease, border-color 0.14s ease;
}

.ks-row-actions .ks-row-action.ks-btn .ks-icon {
    width: 17px;
    height: 17px;
}

.ks-row-actions .ks-row-action.ks-btn:hover,
.ks-row-actions .ks-row-action.ks-btn:focus-visible {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.10);
    border-color: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.45);
    color: var(--kajinga-primary, #2271b1);
}

/* Destruktive Aktion: neutral bis zum Hover, dann eindeutig rot */
.ks-row-actions .ks-row-action--danger.ks-btn:hover,
.ks-row-actions .ks-row-action--danger.ks-btn:focus-visible {
    background: rgba(214, 54, 56, 0.10);
    border-color: rgba(214, 54, 56, 0.45);
    color: var(--kajinga-danger, #d63638);
}

/* =========================================
 * Zeilen-Ausklapper (4.2.30)
 * ks_row_actions(['detail' => true]) + ks_row_detail() + ks_detail_blocks().
 * Der Pfeil dreht über [aria-expanded] — kein .text() am Knopf (Inline-SVG).
 * ========================================= */
.ks-row-action--detail .ks-icon { transition: transform 0.15s var(--kajinga-ease-out, ease); }
.ks-row-action--detail[aria-expanded="true"] .ks-icon { transform: rotate(180deg); }

/* Die Detailzeile: keine Zebra-Färbung, flache Fläche, kein Rahmen zur Mutterzeile.
   [hidden] mit !important, weil Tabellen-CSS `display: table-row` setzen kann. */
tr[data-ks-detail][hidden] { display: none !important; }
tr[data-ks-detail] > td {
    padding: 0;
    background: var(--kajinga-gray-50, #f8fafc);
    border-top: 0;
}
.ks-table tr[data-ks-detail] > td,
.ks-table.striped tr[data-ks-detail] > td { background: var(--kajinga-gray-50, #f8fafc); }

/* Einrückung bis zur ersten Textspalte (Checkbox-Spalte + Avatar). Ohne die
   Checkbox nimmt das Plugin `indent => false` → --flush. */
.ks-detail {
    padding: 14px 18px 18px 62px;
    /* ⚠️ v4.2.41: `width: 0` + `min-width: 100%` — die Detailzeile darf die
       SPALTENBREITEN DER TABELLE NICHT VERÄNDERN. Ihr `<td>` trägt ein
       `colspan` über alle Spalten; bei `table-layout: auto` rechnet der Browser
       dessen max-content in die Spaltenverteilung ein, und ein breiter
       Detailinhalt (mehrspaltiges Raster, lange Zeilen) zieht die ganze Tabelle
       auseinander. Gemessen im CRM-Kontakt-Ausklapper: Tabelle 1198px
       geschlossen, 1331px mit drei geöffneten Zeilen — und weil sie
       unterschiedlich viel Inhalt haben, ragte jede unterschiedlich weit über
       den Container.

       `width: 0` nimmt den Inhalt aus der Spaltenberechnung heraus,
       `min-width: 100%` gibt ihm danach die volle Zellbreite zurück. */
    width: 0;
    min-width: 100%;
    box-sizing: border-box;
}
.ks-detail--flush { padding-left: 18px; }
.ks-detail__loading { margin: 0; color: var(--kajinga-text-muted, #64748b); display: flex; align-items: center; gap: 8px; }

.ks-detail__head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    margin-bottom: 12px;
}
.ks-detail__head strong { font-size: 14px; }
.ks-detail__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 12px 20px;
    align-items: start;
}
.ks-detail__block {
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    border-radius: 10px;
    padding: 12px 14px;
    min-width: 0;
}
.ks-detail__block--wide { grid-column: 1 / -1; }

/* v4.2.39: Mittelstufe zwischen einer Spalte und voller Breite. Ein Block mit
   elf Feldern bekam bisher genauso viel Raum wie einer mit einem — und eine
   E-Mail-Adresse brach in der 240px-Spalte immer um. Nur ab zwei möglichen
   Spalten, sonst ragte `span 2` in einem einspaltigen Grid heraus. */
@media (min-width: 720px) {
    .ks-detail__block--span2 { grid-column: span 2; }

    /* Die doppelte Breite soll die Angaben aufnehmen, nicht Leerraum erzeugen:
       die Liste fließt in zwei Spalten. `break-inside` hält Label und Wert
       zusammen — ohne das reißt der Umbruch sie auseinander. */
    .ks-detail__block--span2 dl { columns: 2; column-gap: 24px; }
    .ks-detail__block--span2 .ks-detail__row { break-inside: avoid; }
    /* Die Trennlinie über der ersten Zeile jeder Spalte wäre eine Linie ohne
       etwas darüber — sie entsteht nur, weil `+` den Spaltenwechsel nicht
       kennt. Deshalb hier keine Linien, die Spalten trennen schon genug. */
    .ks-detail__block--span2 .ks-detail__row + .ks-detail__row { border-top: 0; }
    .ks-detail__block--span2 .ks-detail__row { padding: 6px 0; }
}

/* Akzentkante je Blockart: gibt beim Überfliegen Orientierung, ohne dass eine
   zweite Farbfläche entsteht. Dieselbe Sprache wie die Karten der
   CRM-Kontaktansicht (`kcrm-section--blue`). */
.ks-detail__block--blue   { border-left: 3px solid var(--kajinga-primary, #179AFC); }
.ks-detail__block--violet { border-left: 3px solid #8b5cf6; }
.ks-detail__block--green  { border-left: 3px solid var(--kajinga-success, #10b981); }
.ks-detail__block--amber  { border-left: 3px solid var(--kajinga-warning, #d97706); }
.ks-detail__block--slate  { border-left: 3px solid var(--kajinga-gray-400, #94a3b8); }

.ks-detail__block h4 {
    display: flex; align-items: center; gap: 6px;
    margin: 0 0 10px;
    font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
    color: var(--kajinga-text-muted, #64748b);
}
.ks-detail__block h4 svg { flex: 0 0 auto; opacity: .75; }
.ks-detail__block > *:last-child { margin-bottom: 0; }
.ks-detail__block dl { margin: 0; }

/* v4.2.39: Label ÜBER dem Wert statt daneben. Das frühere `110px | Rest` gab
   dem Wert in einer 240px-Spalte rund 110px — jede E-Mail-Adresse brach um.
   Gestapelt steht dem Wert die volle Blockbreite zur Verfügung, und die
   Beschriftung tritt hinter die Angabe zurück, statt gleich laut zu sein. */
.ks-detail__row { padding: 5px 0; }
.ks-detail__row + .ks-detail__row { border-top: 1px solid var(--kajinga-gray-100, #f1f3f5); }
.ks-detail__row dt {
    margin: 0 0 1px;
    font-size: 11.5px; line-height: 1.4;
    color: var(--kajinga-text-muted, #64748b);
}
.ks-detail__row dd {
    margin: 0;
    font-size: 14px; font-weight: 500; line-height: 1.45;
    overflow-wrap: anywhere;
}
.ks-detail__empty { margin: 0; font-size: 13px; color: var(--kajinga-text-muted, #64748b); }
.ks-detail__block p { font-size: 13px; margin: 0 0 6px; }
.ks-detail__list { list-style: none; margin: 0; padding: 0; font-size: 13px; }
.ks-detail__list li { padding: 4px 0; border-bottom: 1px solid var(--kajinga-gray-100, #f1f3f5); }
.ks-detail__list li:last-child { border-bottom: 0; }

@media (max-width: 640px) {
    .ks-detail { padding-left: 18px; }
}

body.kajinga-dark-mode tr[data-ks-detail] > td,
body.kajinga-dark-mode .ks-table tr[data-ks-detail] > td { background: rgba(255,255,255,.03); }
body.kajinga-dark-mode .ks-detail__block { background: rgba(255,255,255,.04); border-color: rgba(255,255,255,.1); }
body.kajinga-dark-mode .ks-detail__row + .ks-detail__row { border-top-color: rgba(255,255,255,.08); }

.ks-row-actions .ks-row-action.ks-btn[disabled] {
    opacity: 0.4;
    pointer-events: none;
}

/* Tooltip — eigener statt nativem title (kein 500ms-Delay, stylebar) */
.ks-row-actions .ks-row-action[data-tip]::after {
    content: attr(data-tip);
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%) translateY(3px);
    padding: 5px 9px;
    border-radius: 7px;
    background: var(--kajinga-dark, #1d2327);
    color: #fff;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.3;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.13s ease, transform 0.13s ease;
    z-index: 20;
}

.ks-row-actions .ks-row-action[data-tip]:hover::after,
.ks-row-actions .ks-row-action[data-tip]:focus-visible::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* DER Z-INDEX GEHÖRT AUF DEN KNOPF, NICHT NUR AUF DEN TOOLTIP (v4.1.19).
 *
 * Der Tooltip trägt `z-index: 20` — und lag trotzdem HINTER dem Icon der
 * nächsten Tabellenzeile. Der Grund steckt zwei Regeln weiter oben in
 * refresh.css:211: `.ks-btn:hover { transform: translateY(-1px) }`. Ein
 * `transform` ungleich `none` erzeugt einen STAPELKONTEXT — und zwar genau in
 * dem Augenblick, in dem der Tooltip sichtbar wird. Sein `z-index: 20` gilt
 * dann nur noch INNERHALB des Knopfes; nach außen zählt der Knopf selbst, und
 * der hat `z-index: auto`. Gegen den gleichrangigen, aber später im DOM
 * stehenden Knopf der Folgezeile verliert er damit.
 *
 * Sichtbar wird das nur in der ERSTEN Tabellenzeile: Dort klappt der Tooltip
 * nach unten (Regel unten, damit der Tabellenkopf ihn nicht abschneidet) und
 * überlappt die zweite Zeile. In allen anderen Zeilen zeigt er nach oben, über
 * eine bereits gemalte Zeile — dort fällt es nicht auf.
 *
 * Deshalb hier und nicht am ::after: Ein noch höherer z-index am Tooltip
 * ändert nichts, solange er im Stapelkontext des Knopfes gefangen ist. Das ist
 * die klassische Falle — der Wert steht am falschen Element, und die Ursache
 * (ein Hover-Lift) sieht mit Tooltips auf den ersten Blick nichts zu tun. */
.ks-row-actions .ks-row-action[data-tip]:hover,
.ks-row-actions .ks-row-action[data-tip]:focus-visible {
    z-index: 30;
}

/* In der ersten Tabellenzeile nach unten klappen, sonst schneidet der
   Tabellenkopf den Tooltip ab. Gilt zusätzlich für den ersten Eintrag der
   ks_term_manager()-Liste (li statt tr) — sonst legt sich der Tooltip über
   die umgebende Karte und wird dort abgeschnitten. */
tr:first-child .ks-row-actions .ks-row-action[data-tip]::after,
.ks-term-list li:first-child .ks-row-actions .ks-row-action[data-tip]::after {
    bottom: auto;
    top: calc(100% + 6px);
    transform: translateX(-50%) translateY(-3px);
}
tr:first-child .ks-row-actions .ks-row-action[data-tip]:hover::after,
tr:first-child .ks-row-actions .ks-row-action[data-tip]:focus-visible::after,
.ks-term-list li:first-child .ks-row-actions .ks-row-action[data-tip]:hover::after,
.ks-term-list li:first-child .ks-row-actions .ks-row-action[data-tip]:focus-visible::after {
    transform: translateX(-50%) translateY(0);
}

/* LETZTE AKTION EINER RECHTSBÜNDIGEN GRUPPE: TOOLTIP AN DER RECHTEN KANTE (v4.1.38)
 *
 * Der Tooltip hängt zentriert am Knopf (`left: 50%` + `translateX(-50%)`) und ragt
 * damit um seine halbe Breite nach rechts über ihn hinaus. Beim letzten Knopf einer
 * `--end`-Gruppe ist rechts aber die Tabellenkante — und wenn die Tabelle in einem
 * Scroll-Container liegt, schneidet der ab.
 *
 * Gemessen an kajinga-turbo (Netzwerk → Turbo, Spalte „Aktionen"): Knopfmitte
 * x = 1288, Tooltip 71,3 px breit → rechte Kante 1323,6; `.kt-table-wrap` endet bei
 * 1319. Vier Komma sechs Pixel zu weit, sichtbar als fehlender letzter Buchstabe.
 *
 * Rechtsbündig statt zentriert löst es an der Wurzel: Die rechte Tooltip-Kante liegt
 * dann auf der rechten Knopfkante, weiter rechts als der Knopf kann er nicht mehr
 * kommen. Die Breite wächst nach links, wo Platz ist.
 *
 * Nur für `--end`: Dort liegt der letzte Knopf per `justify-content: flex-end` an der
 * Zellkante. Eine linksbündige Aktionsgruppe hat rechts neben sich Platz; ihr den
 * Tooltip zu verschieben wäre eine Lösung ohne Problem.
 *
 * ⚠️ Wer die Ausrichtung ändert, muss BEIDE Blöcke anfassen — der Regelsatz für die
 * erste Tabellenzeile darüber setzt `transform` mit höherer Spezifität (0,4,2 gegen
 * 0,4,1) und gewänne sonst mit seinem `translateX(-50%)` zurück. `left`/`right`
 * deklariert er nicht, die Kaskade arbeitet je Eigenschaft — deshalb steht unten nur
 * das `transform` noch einmal. */
.ks-row-actions--end .ks-row-action:last-child[data-tip]::after {
    left: auto;
    right: 0;
    transform: translateX(0) translateY(3px);
}

.ks-row-actions--end .ks-row-action:last-child[data-tip]:hover::after,
.ks-row-actions--end .ks-row-action:last-child[data-tip]:focus-visible::after {
    transform: translateX(0) translateY(0);
}

/* BREITE TABELLE IM EIGENEN SCROLL-CONTAINER (v4.1.38)
 *
 * `.ks-table-wrap` bringt bewusst KEIN `overflow` mit: Sobald eine Achse `auto`
 * ist, rechnet CSS die andere ebenfalls auf `auto` — und dann schnitte die Karte
 * die Zeilen-Tooltips ab, die über die Zeile hinausragen. Eine Tabelle mit vielen
 * Spalten braucht trotzdem seitliches Scrollen, also legt der Konsument einen
 * eigenen Container darum. Dafür ist diese Klasse da, statt dass jedes Plugin
 * sich einen eigenen erfindet (kajinga-turbo: `.kt-table-wrap`).
 *
 * DIE ZWEITE ZEILE IST DER EIGENTLICHE PUNKT. Ohne sie ist die Karte so breit wie
 * der SICHTAUSSCHNITT, nicht wie ihr Inhalt: Ihre Fläche, ihr Rand und ihre
 * Rundung enden an der Scrollkante, und die überstehenden Spalten liegen beim
 * Scrollen nackt auf dem Seitenhintergrund. Gemessen in Turbo bei 1100 px
 * Fensterbreite: Karte 798 px, Tabelle darin 964 — 166 px ohne Fläche.
 *
 * `min-width: 100%` verhindert den Gegenfehler: Ohne sie schrumpfte eine schmale
 * Tabelle auf ihre Inhaltsbreite und die Karte stünde als Stummel in der Seite. */
.ks-table-scroll {
    overflow-x: auto;
    max-width: 100%;
}

.ks-table-scroll > .ks-table-wrap {
    width: max-content;
    min-width: 100%;
}

/* Erste Zeile: klappt nach unten UND liegt rechts an. */
tr:first-child .ks-row-actions--end .ks-row-action:last-child[data-tip]::after,
.ks-term-list li:first-child .ks-row-actions--end .ks-row-action:last-child[data-tip]::after {
    transform: translateX(0) translateY(-3px);
}

tr:first-child .ks-row-actions--end .ks-row-action:last-child[data-tip]:hover::after,
tr:first-child .ks-row-actions--end .ks-row-action:last-child[data-tip]:focus-visible::after,
.ks-term-list li:first-child .ks-row-actions--end .ks-row-action:last-child[data-tip]:hover::after,
.ks-term-list li:first-child .ks-row-actions--end .ks-row-action:last-child[data-tip]:focus-visible::after {
    transform: translateX(0) translateY(0);
}

/* Touch: kein Hover -> Tooltip aus, Fläche größer */
@media (hover: none) {
    .ks-row-actions .ks-row-action[data-tip]::after { display: none; }
    .ks-row-actions .ks-row-action.ks-btn { width: 36px; height: 36px; }
}

/* =========================================
 * STAT-TREND
 * ========================================= */

.ks-stat-trend {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: var(--kajinga-space-2, 8px);
    font-size: 14px;
    font-weight: 600;
}

/* v4.0.53: war var(--kajinga-success) — das ist die FLAECHENfarbe #c3e6cb und
   als Text auf Weiss unlesbar. Gleiche Falle wie bei den .ks-text-*-Utilities. */
.ks-stat-trend--up   { color: var(--kajinga-success-text, #1a7f37); }
.ks-stat-trend--down { color: var(--kajinga-danger, #d63638); }
.ks-stat-trend--flat { color: var(--kajinga-text-muted, #646970); }

.ks-stat-trend-label {
    font-weight: 400;
    color: var(--kajinga-text-muted, #646970);
}

/* =========================================
 * STAT-GRÖSSE (size: compact, 4.0.55/4.0.56, Höhe seit 4.0.59)
 * Kleinere UND schmalere Kachel für Sekundär-Kennzahlen, die in DERSELBEN
 * Zeile wie Standard-Kacheln stehen soll (z.B. 2 Haupt- + 2 Nebenwerte auf
 * einer Zeile, subordinat statt gleich groß). Subordinat heißt seit 4.0.59
 * ausschließlich schmaler — NICHT niedriger: gleich hohe Kacheln in einer
 * Zeile lesen sich als eine Hierarchie, unterschiedlich hohe wie ein
 * Layout-Fehler. Siehe Teil B weiter unten für die Höhenangleichung.
 * ========================================= */

/* --- Teil A: Kachel-Optik (Padding/Schriftgrad) ---
 * Deckt Padding/Schriftgrad von value/label/icon/trend ab, die je nach
 * Ladereihenfolge aus refresh.css ODER token-utilities.tpl kommen können
 * (beide setzen .ks-stat-card mit derselben Spezifität 0,1,0). Der zusammen-
 * gesetzte Selektor .ks-stat-card.ks-stat-card--compact (0,2,0) gewinnt daher
 * unabhängig von der Ladereihenfolge, ganz ohne !important. Farben/Border
 * bleiben unverändert (nur Größe), deshalb kein eigener Dark-Mode-Block nötig
 * — analog zu .ks-switch--sm, das ebenfalls rein größenbezogen ist. */

.ks-stat-card.ks-stat-card--compact {
    padding: var(--kajinga-space-3, 12px);
    /* 4.0.59: die Kachel wird per Teil B/Container auf Zeilenhöhe der
       Standard-Kachel gebracht (mehr dazu dort) — ihr eigener Inhalt
       (Icon/Wert/Label/Trend) ist aber weiterhin kürzer als diese Höhe.
       Ohne Gegenmaßnahme bliebe der Inhalt oben kleben und darunter ein
       Leerraum vor dem Padding — sichtbar "gestreckt", nicht gestaltet.
       display:flex + justify-content:center zentriert den Inhaltsblock
       stattdessen senkrecht in der verfügbaren Höhe. align-items:stretch
       (= der Default für Flex-Spalten, hier explizit für Lesbarkeit)
       lässt Wert/Label auf voller Breite (wie zuvor als Blockelemente) und
       ändert nichts an deren horizontaler Textausrichtung — die kommt
       weiterhin aus refresh.css/token-utilities.tpl (Teil A oben ändert
       daran nichts). Das Icon behält seine feste Breite (26px, unten) und
       wird von stretch nicht berührt. Gilt unabhängig vom :has()-Gate in
       Teil B: auch im Fallback-Grid (Browser ohne :has()) bekommt die
       compact-Kachel dadurch eine ruhige vertikale Mitte statt an der
       Zellenoberkante zu kleben, falls das Grid sie dort streckt. */
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
}

.ks-stat-card.ks-stat-card--compact .ks-stat-icon {
    width: 26px;
    height: 26px;
    border-radius: 8px;
    font-size: 14.5px;
    margin-bottom: var(--kajinga-space-1, 4px);
}

.ks-stat-card.ks-stat-card--compact .ks-stat-value {
    font-size: 17px;
    margin: 1px 0 2px;
    /* Das negative Tracking der Standard-Kachel gilt ihren 28 px; bei 17 px
       zöge es die Ziffern zusammen. Zurück auf neutral (v4.0.90). */
    letter-spacing: 0;
}

.ks-stat-card.ks-stat-card--compact .ks-stat-label {
    font-size: 13px;
}

.ks-stat-card.ks-stat-card--compact .ks-stat-trend {
    margin-top: var(--kajinga-space-1, 4px);
    font-size: 13px;
}

/* --- Teil B: Zeilen-Verteilung (4.0.56/4.0.57) ---
 * Reine ks_stat_grid-Zeilen (nur Standard-Kacheln) bleiben unangetastet:
 * .ks-stat-grid/-3/-4 laufen unverändert als Grid mit gleich breiten Spalten
 * weiter (repeat(auto-fit,minmax(200px,1fr)) bzw. repeat(3|4,1fr) aus
 * token-utilities.tpl) — die Regeln unten greifen NUR, wenn der Container
 * mindestens eine .ks-stat-card--compact enthält (:has()-Gate, bereits
 * Codebase-Idiom, siehe .ks-chip:has(input:checked) weiter oben in dieser
 * Datei). Ein einziger Selektor auf der Basisklasse .ks-stat-grid reicht für
 * alle drei Spalten-Varianten (0/3/4): .ks-stat-grid trägt IMMER die Basis-
 * klasse, -3/-4 sind zusätzliche Klassen auf demselben Element, und 0,2,0
 * (Klasse + :has()) schlägt deren 0,1,0 so oder so — unabhängig von der
 * gewählten columns-Option.
 *
 * Ist mindestens eine compact-Kachel dabei, wechselt der Container von Grid
 * auf eine proportionale Flex-Zeile: Standard-Kacheln wachsen doppelt so
 * stark wie compact-Kacheln (flex-grow 2:1) UND starten mit größerer
 * Mindestbreite (220px vs. 130px) — zwei dominante, zwei subordinierte
 * Kacheln auf einer Linie, unabhängig von der Zusammensetzung (1+3, 2+2,
 * 3+1 Kacheln funktionieren alle über dasselbe Verhältnis).
 *
 * align-items (4.0.59-Korrektur): stand hier auf flex-start, damit compact-
 * Kacheln NICHT auf Standard-Höhe gestreckt werden — mit dem Effekt, dass sie
 * (gemessen: 94px vs. 151px) auch sichtbar NIEDRIGER wirkten, nicht nur
 * schmaler. Menschlicher Eindruck dazu: falsch — "schmaler, nicht kürzer"
 * war immer der Anspruch der Stufe (siehe Kommentar über Teil A), nur bei der
 * Höhe griff versehentlich dieselbe Bremse wie bei der Breite. Jetzt
 * align-items: stretch (= Flex-Default, hier explizit gesetzt): alle Kacheln
 * EINER Flex-Zeile übernehmen die Höhe der höchsten (= der Standard-Kachel).
 * Damit eine gestreckte compact-Kachel nicht oben am Inhalt klebt und darunter
 * Leerraum zeigt, zentriert Teil A oben (.ks-stat-card.ks-stat-card--compact)
 * ihren Inhalt jetzt selbst per display:flex + justify-content:center — die
 * beiden Änderungen gehören zusammen (Container gibt die Höhe vor, Kachel
 * verteilt ihren Inhalt darin).
 *
 * Schmalste Stelle liegt bei 1 Standard + 3 compact: ~150px Breite je
 * Kachel bei typischer Admin-Content-Breite — deutlich über der Illegibili-
 * tätsgrenze der kleinsten Schrift (11px Label).
 *
 * Breakpoints identisch zu den Nachbarregeln (900px/600px, siehe
 * .ks-stat-grid-3/-4 media queries oben in token-utilities.tpl): ab 900px
 * geht die Zeile auf 2 Kacheln pro Reihe (beide Basis-Klassen auf 50%
 * gesetzt — die Hierarchie bleibt durch das Seitenverhältnis der Kachel
 * selbst erhalten, nicht mehr durch die Breite), ab 600px auf 1 Kachel pro
 * Reihe (volle Breite). Kein Sliver-Risiko: die schmalste Stufe ist immer
 * mindestens halbe bzw. volle Containerbreite.
 *
 * 4.0.57-Korrektur: ".ks-stat-card" (Standard-Regel unten) und
 * ".ks-stat-card--compact" liegen beide auf Spezifität 0,3,0 — eine
 * compact-Kachel trägt IMMER auch die Basisklasse .ks-stat-card und erfüllt
 * damit BEIDE Selektoren gleichzeitig. Das war ein Unentschieden, das nur
 * durch Quellreihenfolge aufgelöst wurde (die --compact-Regel gewinnt bloß,
 * weil sie weiter unten steht) — genau die Instabilität, die der :has()-Griff
 * am Container bewusst vermeiden sollte. Fix: :not(.ks-stat-card--compact)
 * auf der Standard-Regel, damit sich beide Selektoren gegenseitig
 * ausschließen (0,4,0 vs. 0,3,0) — kein Unentschieden mehr, unabhängig von
 * Reihenfolge oder einem CSS-Postprocessor, der Deklarationen umsortiert.
 * Gleiches Idiom wie ks_tab_nav()s Dark-Mode-Block (siehe claude.md), der
 * :not(--cards) aus demselben Grund nutzt. Die zwei @media-Regeln darunter
 * sind NICHT betroffen: beide Selektoren dort teilen sich EINE Deklaration
 * mit demselben Wert (50% bzw. 100% für beide Größen) — es gibt dort keine
 * zwei konkurrierenden Werte, die je nach Reihenfolge kippen könnten.
 *
 * :has()-Fallback (bewusste Entscheidung, kein Bug): Browser ohne :has()-
 * Unterstützung (< Safari 15.4 / Chrome 105 / Firefox 121) matchen das Gate
 * nie — eine GEMISCHTE Zeile bleibt dann Grid mit gleich breiten Spalten,
 * während die compact-Kachel ihr kleineres Padding/Schriftgrad aus Teil A
 * trotzdem bekommt. Ergebnis: eine kleinere Box in einer gleich breiten
 * Zelle — exakt das Muster, das dieser Größenschritt vermeiden soll. Reine
 * Standard-Grids sind davon NICHT betroffen (dort greift :has() ohnehin nie,
 * ob unterstützt oder nicht). Akzeptiert, weil das reale Zeitfenster zum
 * Entscheidungsdatum (Juli 2026) verschwindend klein ist — alle Evergreen-
 * Browser unterstützen :has() seit 2023/2024 — und weil die Kachel dabei
 * lesbar bleibt, nur die Breiten-Hierarchie fehlt. Kein Fallback gebaut;
 * wer diese Grenze verschiebt, sollte hier ansetzen. Höhe ist davon NICHT
 * betroffen: CSS-Grid stretcht Zellen standardmäßig (align-items:stretch
 * ist der Grid-Default, hier nie überschrieben) — die compact-Zelle war im
 * Fallback-Grid schon vor 4.0.59 gleich hoch wie ihre Nachbarn, nur eben in
 * einer gleich breiten statt schmaleren Spalte. Die Vertikal-Zentrierung aus
 * Teil A (.ks-stat-card.ks-stat-card--compact) greift dort ebenso. */

.ks-stat-grid:has(.ks-stat-card--compact) {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
}

.ks-stat-grid:has(.ks-stat-card--compact) > .ks-stat-card:not(.ks-stat-card--compact) {
    flex: 2 1 220px;
}

.ks-stat-grid:has(.ks-stat-card--compact) > .ks-stat-card--compact {
    flex: 1 1 130px;
}

@media screen and (max-width: 900px) {
    .ks-stat-grid:has(.ks-stat-card--compact) > .ks-stat-card,
    .ks-stat-grid:has(.ks-stat-card--compact) > .ks-stat-card--compact {
        flex-basis: calc(50% - var(--kajinga-space-5, 20px) / 2);
    }
}

@media screen and (max-width: 600px) {
    .ks-stat-grid:has(.ks-stat-card--compact) > .ks-stat-card,
    .ks-stat-grid:has(.ks-stat-card--compact) > .ks-stat-card--compact {
        flex-basis: 100%;
    }
}

/* =========================================
 * SWITCH
 * ========================================= */

.ks-switch {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    user-select: none;
}

.ks-switch-input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.ks-switch-track {
    position: relative;
    display: inline-block;
    width: 36px;
    height: 20px;
    background: var(--kajinga-gray-300, #c3c4c7);
    border-radius: var(--kajinga-radius-full, 9999px);
    /* Dauer ausgeschrieben statt `var(--kajinga-transition-fast)` (v4.0.91).
       Das Token trägt auf `body` den Wert `all 0.15s ease` — als Teilwert
       hinter einer Eigenschaft ergibt das `background all 0.15s ease`, also
       ungültiges CSS, und der Browser verwirft die ganze Zeile. Im Ergebnis
       hatte der Schalter GAR KEINEN Übergang (gemessen: 0s). Siehe den
       ausführlichen Hinweis am Ende dieser Datei. */
    transition: background 0.15s ease;
    flex-shrink: 0;
}

.ks-switch-thumb {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    background: #fff;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
    /* Der Knopf legt eine Strecke zurück (16px) — das ist der Musterfall für
       die Auslauf-Kurve statt `ease` (v4.0.91). Zur ausgeschriebenen Dauer
       siehe den Hinweis am Track darüber: bis hierher sprang er ohne jeden
       Übergang von einer Seite zur anderen. */
    transition: transform 0.18s var(--kajinga-ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}

.ks-switch-input:checked + .ks-switch-track {
    background: var(--kajinga-primary, #2271b1);
}

.ks-switch-input:checked + .ks-switch-track .ks-switch-thumb {
    transform: translateX(16px);
}

.ks-switch-input:focus-visible + .ks-switch-track {
    outline: 2px solid var(--kajinga-primary, #2271b1);
    outline-offset: 2px;
}

.ks-switch-input:disabled ~ .ks-switch-track,
.ks-switch-input:disabled ~ .ks-switch-label {
    opacity: 0.55;
    cursor: default;
}

.ks-switch--sm .ks-switch-track { width: 30px; height: 16px; }
.ks-switch--sm .ks-switch-thumb { width: 12px; height: 12px; }
.ks-switch--sm .ks-switch-input:checked + .ks-switch-track .ks-switch-thumb { transform: translateX(14px); }

.ks-switch-label {
    font-size: 14.5px;
    color: var(--kajinga-text, #1d2327);
}

/* =========================================
 * SKELETON
 * ========================================= */

@keyframes ks-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

.ks-skeleton {
    display: block;
    border-radius: var(--kajinga-radius-xs, 4px);
    background: linear-gradient(
        90deg,
        var(--kajinga-gray-100, #f0f0f1) 25%,
        var(--kajinga-gray-200, #e2e4e7) 50%,
        var(--kajinga-gray-100, #f0f0f1) 75%
    );
    background-size: 200% 100%;
    animation: ks-shimmer 1.4s ease-in-out infinite;
}

.ks-skeleton--text  { height: 12px; width: 70%; margin: 6px 0; }
.ks-skeleton--title { height: 20px; width: 45%; margin: 8px 0; }
.ks-skeleton--row   { height: 38px; width: 100%; margin: 6px 0; }
.ks-skeleton--card  { height: 120px; width: 100%; border-radius: var(--kajinga-radius-lg, 12px); }
.ks-skeleton--stat  { height: 64px; width: 100%; }

/* =========================================
 * DROPDOWN (Zeilen-Aktionsmenü)
 * ========================================= */

.ks-dropdown {
    position: relative;
    display: inline-block;
}

.ks-dropdown-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    padding: 6px;
    cursor: pointer;
    color: var(--kajinga-text-muted, #646970);
    border-radius: var(--kajinga-radius-sm, 6px);
    transition: var(--kajinga-transition-fast, all 0.15s ease);
}

.ks-dropdown-toggle:hover,
.ks-dropdown.open .ks-dropdown-toggle {
    background: var(--kajinga-gray-100, #f0f0f1);
    color: var(--kajinga-text, #1d2327);
}

.ks-dropdown-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    min-width: 180px;
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    border-radius: var(--kajinga-radius-md, 8px);
    box-shadow: var(--kajinga-shadow-lg, 0 10px 30px rgba(0, 0, 0, 0.15));
    padding: 5px;
    z-index: 10010;
    display: none;
}

.ks-dropdown--right .ks-dropdown-menu {
    left: auto;
    right: 0;
}

/* Aufklappende Karten wachsen aus ihrem Auslöser (v4.0.91).
 *
 * `ks-fade-in` ist reines opacity 0→1 (erzeugt im DesignTokenHelper). Die Karte
 * erschien damit an Ort und Stelle aus dem Nichts — die räumliche Beziehung
 * zwischen Knopf und Inhalt ging verloren, obwohl genau sie erklärt, wozu die
 * Karte gehört. Im ganzen Plugin stand vorher ein einziges `transform-origin`.
 *
 * `ks-fade-in` bleibt unangetastet: Es ist netzwerkweite API — magic-products
 * und kajinga-elementor animieren damit ihre eigenen Elemente. Deshalb ein
 * eigenes Keyframe statt einer Änderung am bestehenden. */
@keyframes ks-pop-in {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: scale(1); }
}

.ks-dropdown.open .ks-dropdown-menu {
    display: block;
    /* Der Ursprung folgt der Ausrichtung: Die Karte hängt an `left: 0` unter
       dem Knopf, wächst also aus dessen linker oberer Ecke. */
    transform-origin: top left;
    animation: ks-pop-in 0.14s var(--kajinga-ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}

.ks-dropdown--right .ks-dropdown-menu {
    transform-origin: top right;
}

.ks-dropdown-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    background: none;
    border: none;
    border-radius: var(--kajinga-radius-sm, 6px);
    font-size: 14.5px;
    color: var(--kajinga-text, #1d2327);
    cursor: pointer;
    text-align: left;
    text-decoration: none;
    box-sizing: border-box;
}

.ks-dropdown-item:hover {
    background: var(--kajinga-gray-100, #f0f0f1);
    color: var(--kajinga-text, #1d2327);
}

.ks-dropdown-item--danger,
.ks-dropdown-item--danger:hover {
    color: var(--kajinga-danger, #d63638);
}

.ks-dropdown-item--danger:hover {
    background: rgba(214, 54, 56, 0.08);
}

.ks-dropdown-divider {
    height: 1px;
    background: var(--kajinga-gray-100, #f0f0f1);
    margin: 5px 0;
}

/* =========================================
 * TOOLBAR
 * ========================================= */

.ks-toolbar {
    display: flex;
    align-items: center;
    gap: var(--kajinga-space-3, 12px);
    flex-wrap: wrap;
    margin-bottom: var(--kajinga-space-4, 16px);
}

.ks-toolbar-spacer {
    flex: 1;
}

.ks-toolbar-search {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--kajinga-text-muted, #646970);
}

.ks-toolbar-search .ks-input {
    min-width: 220px;
}

/* v4.0.87: Der Toolbar-Vorfahre steht nicht aus Bequemlichkeit im Selektor.
   WordPress setzt in `forms.css` `.wp-core-ui select { max-width: 25rem }` — mit
   (0,1,1) schlägt das eine einzelne Klasse. Ein bloßes `.ks-toolbar-filter`
   (0,1,0) wurde deshalb NIE angewandt: Filter-Selects waren 400px breit, und
   sobald zwei davon neben dem Suchfeld standen, brach die Leiste in zwei Reihen
   um (gesehen in der CRM-Kontaktliste und auf der Audio/Video-Seite).
   `width: auto` gehört dazu, weil `.ks-input` seinerseits `width: 100%` setzt. */
.ks-toolbar .ks-toolbar-filter {
    width: auto;
    max-width: 220px;
}

.ks-toolbar-count {
    font-size: 14px;
    color: var(--kajinga-text-muted, #646970);
}

/* =========================================
 * TABELLE: SORTIER-UI + FILTER-EMPTY
 * ========================================= */

.ks-th-sortable {
    cursor: pointer;
    white-space: nowrap;
}

.ks-th-sortable:hover {
    color: var(--kajinga-primary, #2271b1);
}

/* Serverseitig sortierender Kopf (4.1.36): der Link trägt die Farbe der Kopfzeile,
   nicht das Admin-Blau — sonst sähen die sortierbaren Spalten aus wie Fremdkörper
   neben den clientseitigen, die nur ein <th> mit Cursor sind. */
.ks-th-sort-link,
.ks-th-sort-link:hover,
.ks-th-sort-link:focus {
    color: inherit;
    text-decoration: none;
    box-shadow: none;
}

/* Spalten-Ausrichtung (4.1.31) — ks_data_table setzt die Klasse auf th UND td,
   weil die Zelle ihre Spalte sonst nicht kennt (Zellen sind rohes HTML ohne Schlüssel).
   KEIN tabular-nums hier: `.ks-table` trägt es in refresh.css bereits für die ganze
   Tabelle, und font-variant-numeric vererbt sich — im Browser gemessen, die Ziffern
   stehen ohne Zutun untereinander. Eine Regel hier wäre eine zweite Wahrheit. */
/* Tabelle in einer Karte (4.1.34): Der Wrap gibt seine eigene Karten-Optik ab.
   Der Innenabstand von Toolbar und Pager bleibt — er richtet Suchfeld und erste
   Spalte aneinander aus und wäre ohne Fläche genauso nötig. */
.ks-table-wrap--flush {
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

.ks-table-wrap--flush > .ks-toolbar {
    padding-left: 0;
    padding-right: 0;
}

.ks-table-wrap--flush > .ks-table-pager {
    padding-left: 0;
    padding-right: 0;
}

/* Seitenweise Anzeige (4.1.32) — Pager unter der Tabelle. Zahlen mit fester
   Ziffernbreite, damit die Knöpfe beim Blättern von 9 auf 10 nicht springen. */
.ks-table-pager {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
    padding: 12px 14px 2px;
    font-variant-numeric: tabular-nums;
}

.ks-table-pager .ks-btn {
    min-width: 32px;
    justify-content: center;
}

.ks-table-pager-gap {
    padding: 0 4px;
    color: var(--kajinga-text-muted, #646970);
}

.ks-table-pager-info {
    margin-left: auto;
    font-size: 13px;
    color: var(--kajinga-text-muted, #646970);
}

@media (max-width: 600px) {
    .ks-table-pager-info { margin-left: 0; width: 100%; }
}

.ks-table .ks-col-end {
    text-align: right;
}

.ks-table .ks-col-center {
    text-align: center;
}

.ks-th-sort-indicator::after {
    content: '↕';
    opacity: 0.35;
    margin-left: 5px;
    font-size: 13px;
}

.ks-th-sortable.ks-sort-asc .ks-th-sort-indicator::after {
    content: '↑';
    opacity: 1;
    color: var(--kajinga-primary, #2271b1);
}

.ks-th-sortable.ks-sort-desc .ks-th-sort-indicator::after {
    content: '↓';
    opacity: 1;
    color: var(--kajinga-primary, #2271b1);
}

.ks-table-empty-filter {
    padding: var(--kajinga-space-6, 24px);
    text-align: center;
    font-size: 14.5px;
    color: var(--kajinga-text-muted, #646970);
    border: 1px dashed var(--kajinga-gray-200, #e2e4e7);
    border-top: none;
    border-radius: 0 0 var(--kajinga-radius-sm, 6px) var(--kajinga-radius-sm, 6px);
}

/* =========================================
 * CARD-ERGÄNZUNGEN (Header-Layout, Collapse)
 * ========================================= */

.ks-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--kajinga-space-3, 12px);
}

/* TITELGRÖSSE 16/700 statt 14/600 (v4.1.18).
 *
 * Der Anlass: In Mein Kajinga stand der Kartentitel („Ihre Websites") neben
 * einer Zwischenüberschrift derselben Karte („Ihre Käufe") — und beide maßen
 * exakt 14px/600. Es gab keine Hierarchie, weil es zwischen dem Seitentitel
 * (23px/800) und dem Kartentitel im System NICHTS gab.
 *
 * Man sieht die Lücke daran, dass sich jedes Plugin selbst eine
 * Zwischenüberschrift gebaut hat, in vier verschiedenen Größen: kajinga-funnel
 * 15/700, kajinga-main 14/600, ultra-ads 13/600, magic-magnets 12/600. Genau
 * das Muster, das oben bei ks_modal beschrieben ist („18 verschiedene Werte bei
 * 33 Overrides"). Deshalb schließt diese Änderung die Lücke hier und nicht ein
 * fünftes Mal lokal — .ks-section-label weiter unten ist die Gegenstufe.
 *
 * Das TRACKING bleibt bei 0 (refresh.css): Der Modal-Titel ist bereits 16px und
 * steht in derselben letter-spacing-Gruppe. Wer weiter hochgeht, zieht es mit,
 * siehe die Begründung dort.
 *
 * .ks-widget-title bleibt bewusst bei 14/600 — ein Dashboard-Widget ist eine
 * eigene Komponente mit eigener Dichte, kein kleiner Karten-Zwilling. */
.ks-card-title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    color: var(--kajinga-text, #1d2327);
    min-width: 0;
}

/* Die Gegenstufe: Zwischenüberschrift INNERHALB einer Karte (v4.1.18).
 *
 * Für Abschnitte, die zu klein für eine eigene Karte sind, aber eine
 * Beschriftung brauchen — „Ihre Käufe" unter den Freischaltungen, eine
 * Feldgruppe in einem längeren Formular. Klar untergeordnet: kleiner als der
 * Kartentitel UND gedämpft, damit die beiden nie um dieselbe Aufmerksamkeit
 * konkurrieren.
 *
 * Der Abstand nach oben ist großzügiger als der nach unten (20 gegen 8): Die
 * Überschrift gehört zu dem, was FOLGT, nicht zu dem, was über ihr steht. Ohne
 * dieses Gefälle liest sie sich als Fußnote des vorigen Blocks.
 *
 * :first-child nimmt den oberen Abstand wieder weg — steht sie direkt am Anfang
 * eines Kartenkörpers, hat die Karte ihr Polster schon mitgebracht. */
.ks-section-label {
    margin: var(--kajinga-space-5, 20px) 0 var(--kajinga-space-2, 8px);
    font-size: 13px;
    font-weight: 600;
    color: var(--kajinga-text-muted, #646970);
}

.ks-section-label:first-child {
    margin-top: 0;
}

.ks-card-title .ks-icon {
    color: var(--kajinga-primary, #2271b1);
}

/* Einklappbare Karte: der Titel schaltet mit (v4.2.5). Der Chevron rechts
   bleibt das bedienbare Element für Tastatur und Vorlesesoftware, aber mit
   der Maus trifft man den Titel deutlich leichter. */
.ks-card-title-toggle {
    cursor: pointer;
    user-select: none;
}

/* Beschreibungssatz im Kartenkopf (v4.2.5): nimmt den freien Platz zwischen
   Titel und Aktionen und kürzt, statt die Zeile umzubrechen. */
.ks-card-meta {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
    font-weight: 400;
    color: var(--kajinga-text-muted, #646970);
}

.ks-card-title-toggle + .ks-card-meta {
    cursor: pointer;
    user-select: none;
}

/* Steht ein Beschreibungssatz daneben, behält der Titel seine Breite und der
   Satz kürzt. Ohne das schrumpft der Titel zuerst — „Kajinga Builder" bricht
   auf zwei Zeilen, während daneben Platz für den Satz gemacht wird. */
.ks-card-header-meta > .ks-card-title {
    flex: 0 0 auto;
    white-space: nowrap;
}

/* Auf schmalen Bildschirmen ist für den Satz kein Platz — Titel und Anzahl
   genügen, der Satz steht ohnehin im Inhalt. */
@media (max-width: 782px) {
    .ks-card-meta {
        display: none;
    }
}

.ks-card-actions {
    display: flex;
    align-items: center;
    gap: var(--kajinga-space-2, 8px);
    flex-shrink: 0;
}

.ks-card-collapse {
    background: none;
    border: none;
    padding: 4px;
    cursor: pointer;
    color: var(--kajinga-text-muted, #646970);
    border-radius: var(--kajinga-radius-xs, 4px);
    display: inline-flex;
}

.ks-card-collapse:hover {
    background: var(--kajinga-gray-100, #f0f0f1);
    color: var(--kajinga-text, #1d2327);
}

.ks-card-body {
    min-width: 0;
}

.ks-card-header + .ks-card-body {
    margin-top: var(--kajinga-space-4, 16px);
}

/* =========================================
 * FORM-ERGÄNZUNGEN
 * ========================================= */

.ks-form-required {
    color: var(--kajinga-danger, #d63638);
}

.ks-form-checkbox {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14.5px;
    cursor: pointer;
}

/* =========================================
 * TABS-WRAPPER
 * ========================================= */

.ks-tabs-wrap .ks-tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* =========================================
 * ACCORDION (aufklappbarer Abschnitt)
 * Natives <details> — der Pfeil ersetzt den Browser-Marker.
 * ========================================= */

.ks-accordion {
    display: flex;
    flex-direction: column;
    gap: var(--kajinga-space-2, 8px);
    margin: var(--kajinga-space-4, 16px) 0;
}

.ks-accordion__item {
    background: var(--kajinga-card-solid, #f9f9f9);
    border: 1px solid var(--kajinga-gray-200, rgba(16, 24, 40, 0.08));
    border-radius: var(--kajinga-radius, 10px);
    /* Erlaubt, `height: auto` zu animieren (v4.0.97) — ohne diese Zeile
       springt der Wert, statt zu laufen.
       BEWUSST HIER UND NICHT AUF `:root`: Die Eigenschaft vererbt sich, auf
       dem Element gesetzt erreicht sie `::details-content` genauso. Global
       wäre sie ein Risiko — sie aktiviert die auto-Interpolation für JEDE
       Höhen-Transition im Dokument, und seit 4.0.92 sind netzwerkweit rund
       300 Übergänge lebendig, viele davon mit `all`. Ein Plugin mit
       `transition: all` auf einem Element, das seine Höhe ändert, bekäme
       damit unangekündigt eine Animation. */
    interpolate-size: allow-keywords;
}

/* Auf- und Zuklappen läuft, statt zu springen (v4.0.97).
 *
 * `<details>` war nie animierbar: Der Inhalt ist entweder da oder nicht,
 * dazwischen gibt es keinen Zwischenzustand. `::details-content` gibt dem
 * verborgenen Teil erstmals einen eigenen Selektor, und `allow-discrete`
 * trägt die Transition über den Sichtbarkeitswechsel hinweg.
 *
 * FALLBACK IST DAS BISHERIGE VERHALTEN: Browser, die `::details-content` oder
 * `interpolate-size` nicht kennen, ignorieren beide Regeln und klappen hart
 * auf — genau wie vor dieser Änderung. Nichts geht verloren, es kommt nur
 * etwas dazu, wo es unterstützt wird. Deshalb braucht es hier auch keine
 * @supports-Abfrage.
 *
 * Die Kurve ist `--kajinga-ease-out`: Aufklappen legt eine Strecke zurück. */
.ks-accordion__item::details-content {
    height: 0;
    overflow: hidden;
    transition: height 0.28s var(--kajinga-ease-out, cubic-bezier(0.22, 1, 0.36, 1)),
                content-visibility 0.28s allow-discrete;
}

.ks-accordion__item[open]::details-content {
    height: auto;
}

.ks-accordion__summary {
    display: flex;
    align-items: center;
    gap: var(--kajinga-space-2, 8px);
    padding: var(--kajinga-space-3, 12px) var(--kajinga-space-4, 16px);
    cursor: pointer;
    font-weight: 600;
    /* Standard-Dreieck weg — der Chevron im Markup tritt an seine Stelle.
       ::-webkit-details-marker zusätzlich für ältere WebKit-Versionen. */
    list-style: none;
}

.ks-accordion__summary::-webkit-details-marker {
    display: none;
}

/* Sichtbarer Fokus: summary ist das bedienbare Element, und ohne diese Regel
   erbt es nur den uneinheitlichen Browser-Standard. */
.ks-accordion__summary:focus-visible {
    outline: 2px solid var(--kajinga-primary, #2271b1);
    outline-offset: -2px;
    border-radius: var(--kajinga-radius, 10px);
}

.ks-accordion__title {
    flex: 0 0 auto;
}

/* Kopfzeile mit Zusatzangaben (v4.2.4): meta nimmt den freien Platz und
   kürzt bei Bedarf, badge bleibt immer vollständig lesbar. Ohne die beiden
   verhält sich die Zeile wie zuvor — title steht dann allein vor dem
   Chevron, den margin-left: auto nach rechts schiebt. */
.ks-accordion__meta {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 400;
    font-size: 13px;
    color: var(--kajinga-text-muted, #646970);
}

.ks-accordion__badge {
    flex: 0 0 auto;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--kajinga-gray-100, #f0f0f1);
    color: var(--kajinga-text-muted, #646970);
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}

/* Auf schmalen Bildschirmen ist für den Beschreibungssatz kein Platz —
   Titel und Zahl genügen, der Satz steht ohnehin im Inhalt. */
@media (max-width: 782px) {
    .ks-accordion__meta {
        display: none;
    }
}

.ks-accordion__marker {
    flex: 0 0 auto;
    /* Schiebt den Chevron an den rechten Rand, auch wenn weder meta noch
       badge gesetzt sind (v4.2.4 — vorher tat das title mit flex: 1). */
    margin-left: auto;
    color: var(--kajinga-text-muted, #6b7280);
    transition: transform 0.15s ease;
}

.ks-accordion__item[open] > .ks-accordion__summary .ks-accordion__marker {
    transform: rotate(180deg);
}

.ks-accordion__body {
    padding: 0 var(--kajinga-space-4, 16px) var(--kajinga-space-4, 16px);
}

/* Trennlinie erst im geöffneten Zustand — zugeklappt wäre sie ein Strich
   unter einer einzelnen Zeile. */
.ks-accordion__item[open] > .ks-accordion__body {
    padding-top: var(--kajinga-space-3, 12px);
    border-top: 1px solid var(--kajinga-gray-200, rgba(16, 24, 40, 0.08));
}

.ks-accordion__body > *:first-child {
    margin-top: 0;
}

.ks-accordion__body > *:last-child {
    margin-bottom: 0;
}

@media (prefers-reduced-motion: reduce) {
    .ks-accordion__marker {
        transition: none;
    }
}

/* =========================================
 * WIDGET-BOX (Dashboard-Kacheln)
 * ========================================= */

.ks-widget-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: var(--kajinga-space-5, 20px);
    margin-top: var(--kajinga-space-5, 20px);
}

.ks-widget {
    --ks-widget-accent: var(--ks-accent, #2271b1);
    display: flex;
    flex-direction: column;
    gap: var(--kajinga-space-4, 16px);
    padding: var(--kajinga-space-5, 20px);
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    border-radius: var(--kajinga-radius-lg, 16px);
    box-shadow: var(--kajinga-shadow-sm, 0 1px 2px rgba(16, 24, 40, 0.06));
    transition: box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
    /* v-widget-polish: Akzent-Kopfleiste sitzt oben, ::before wird an den
       Kartenrundungen sauber beschnitten */
    position: relative;
    overflow: hidden;
}

.ks-widget:hover {
    transform: translateY(-2px);
    box-shadow: var(--kajinga-shadow-md, 0 4px 12px rgba(16, 24, 40, 0.1));
    border-color: color-mix(in srgb, var(--ks-widget-accent) 28%, var(--kajinga-gray-200, #e2e4e7));
}

/* ============================================
 * WIDGET-POLISH (v-widget-polish) — angeglichen an das kajinga-main
 * Dashboard: immer sichtbare Akzent-Kopfleiste, farbiger/größerer Titel
 * mit Trennlinie, getönte Stat-Kacheln. Alles über --ks-widget-accent
 * (Default = Kajinga-Blau; Plugins setzen accent pro Widget). Varianten
 * brand/cover/inactive/soon opten aus der Kopfleiste aus.
 * ========================================= */

/* Hier stand bis v4.0.86 eine immer sichtbare 3px-Akzent-Kopfleiste (Verlauf in
   --ks-widget-accent, mit Hover-Shimmer). Entfernt: Auf einem Dashboard mit acht
   Kacheln standen acht farbige Balken nebeneinander und konkurrierten um
   Aufmerksamkeit, ohne eine Information zu tragen, die nicht schon im Icon und
   im Titel steckt.

   Die Farbcodierung pro Werkzeug bleibt erhalten — sie sitzt weiterhin in der
   Icon-Fläche, im Titel und in den Stat-Kacheln, alle über --ks-widget-accent.
   Wer den Balken wiederhaben will, braucht kein neues Konzept, nur diesen Block.

   Der Shimmer war ohnehin auf Nicht-Firefox beschränkt (backdrop-filter/
   Hover-Bug) — mit dem Balken entfällt auch diese Sonderbehandlung. */

/* Header mit Trennlinie */
.ks-widget-header {
    padding-bottom: var(--kajinga-space-3, 12px);
    border-bottom: 1px solid var(--kajinga-gray-150, rgba(0, 0, 0, 0.06));
}

/* Farbiger, größerer Titel (Brand behält Weiß über spätere Regel) */
.ks-widget-title {
    font-size: 16px;
    font-weight: 700;
    color: var(--ks-widget-accent);
}

.ks-widget-title a {
    color: inherit;
}

/* Getönte Stat-Kacheln in der Akzentfarbe */
.ks-widget-stat {
    background: color-mix(in srgb, var(--ks-widget-accent) 7%, transparent);
    border: 1px solid color-mix(in srgb, var(--ks-widget-accent) 12%, transparent);
    border-radius: var(--kajinga-radius-sm, 10px);
    padding: 10px 8px;
    text-align: center;
    transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.ks-widget-stat:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px color-mix(in srgb, var(--ks-widget-accent) 16%, transparent);
}

.ks-widget-header {
    display: flex;
    align-items: center;
    gap: 10px;
}

.ks-widget-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex: none;
    border-radius: var(--kajinga-radius-sm, 10px);
    background: color-mix(in srgb, var(--ks-widget-accent) 12%, transparent);
    color: var(--ks-widget-accent);
}

.ks-widget-title {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--kajinga-text, #1d2327);
}

.ks-widget-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(72px, 1fr));
    gap: var(--kajinga-space-2, 8px);
}

/* v3.7.41: Beschreibungs-Slot (zwischen Header und Stats) */
.ks-widget-text {
    margin: 0 0 var(--kajinga-space-3, 12px);
    /* v3.9.45: +2px (Beschreibungstext in Widget-Boxen) */
    font-size: 15px;
    line-height: 1.5;
    color: var(--kajinga-text-muted, #646970);
}

/* v3.7.41: Stats mit Icon / klickbar / Sub-Zeile */
.ks-widget-stat-icon {
    display: inline-flex;
    /* v-widget-polish: Akzent statt fixem Primary → folgt der Widget-Familie */
    color: var(--ks-widget-accent, var(--kajinga-primary, #2271b1));
    margin-bottom: 4px;
}

.ks-widget-stat-sub {
    font-size: 13px;
    color: var(--kajinga-text-muted, #646970);
    margin-top: 2px;
}

/* v-widget-polish: klickbare Stat-Kachel = volle Kachel (kein Negativ-Margin);
   Grund-Optik erbt sie von .ks-widget-stat */
a.ks-widget-stat--link {
    text-decoration: none;
    padding: 10px 8px;
    margin: 0;
    transition: background 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

a.ks-widget-stat--link:hover {
    background: color-mix(in srgb, var(--ks-widget-accent) 14%, transparent);
}

/* v3.7.41: Brand-Variante — dunkle Brand-Fläche für interaktive Boxen
   mit User-Eingabe (Referenz: ULTRA-Automat-Box) */
.ks-widget--brand {
    background: linear-gradient(135deg, #16181d 0%, #23262e 60%, var(--kajinga-primary, #2271b1) 220%);
    border-color: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.5);
    color: #fff;
}

.ks-widget--brand .ks-widget-title,
.ks-widget--brand .ks-widget-title a {
    color: #fff;
}

.ks-widget--brand .ks-widget-text {
    color: rgba(255, 255, 255, 0.85);
}

.ks-widget--brand .ks-widget-icon {
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
}

/* v-widget-polish: Brand-Fläche ist dunkel → Kopfleiste/Stat-Kacheln auf Weiß */
.ks-widget--brand .ks-widget-header {
    border-bottom-color: rgba(255, 255, 255, 0.14);
}

.ks-widget--brand .ks-widget-stat {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.14);
}

.ks-widget--brand .ks-widget-stat-icon,
.ks-widget--brand .ks-widget-stat-value {
    color: #fff;
}

.ks-widget--brand .ks-widget-stat-label {
    color: rgba(255, 255, 255, 0.7);
}

.ks-widget-stat-value {
    font-size: 22px;
    font-weight: 700;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
    /* v-widget-polish: Zahl in Akzentfarbe (kajinga-main-Parität) */
    color: var(--ks-widget-accent, var(--kajinga-text, #1d2327));
}

.ks-widget-stat-label {
    /* v3.9.45: +2px */
    font-size: 14.5px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--kajinga-text-muted, #646970);
}

.ks-widget-body {
    flex: 1;
    min-width: 0;
}

.ks-widget-footer {
    margin-top: auto;
    /* v3.10.15: Footer-Buttons zentriert (Standard-Entscheid). .ks-actions ist
       inline-flex und folgt dem text-align des Containers. */
    text-align: center;
}

.ks-widget-inactive,
.ks-widget-soon {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: var(--kajinga-space-4, 16px);
    border-radius: var(--kajinga-radius-sm, 10px);
    background: var(--kajinga-gray-100, #f6f7f7);
    color: var(--kajinga-text-muted, #646970);
    font-size: 14.5px;
    text-align: center;
}

.ks-widget--inactive {
    box-shadow: none;
}

.ks-widget--inactive:hover {
    transform: none;
    box-shadow: none;
}

.ks-widget--inactive .ks-widget-icon {
    background: var(--kajinga-gray-100, #f6f7f7);
    color: var(--kajinga-text-muted, #646970);
}

.ks-widget-soon {
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-size: 14px;
}

/* --- Erweiterte Karte (Cover, Meta, Badge, Fortschritt — seit 3.5.7) --- */

.ks-widget--cover {
    overflow: hidden;
}

.ks-widget-cover {
    display: block;
    position: relative;
    height: 150px;
    /* full-bleed über das Karten-Padding hinweg */
    margin: calc(-1 * var(--kajinga-space-5, 20px)) calc(-1 * var(--kajinga-space-5, 20px)) 0;
    background-size: cover;
    /* Oberkante zeigen — dort sitzen die Headlines der Cover */
    background-position: center top;
    background-color: var(--kajinga-gray-100, #f6f7f7);
}

a.ks-widget-cover {
    cursor: pointer;
}

.ks-widget-cover--plain {
    height: 72px;
}

.ks-widget-cover-bar {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 4px;
}

/* Status-Badge über dem Cover (v4.2.16). Die .ks-badge-Flächen sind halbtransparent
   (rgba-Tint auf hellem Grund) — direkt auf einem Coverbild schlägt das Motiv durch und
   die Schrift wird unleserlich. Deshalb trägt der Wrapper eine opake Grundfläche in
   Badge-Form, auf der der Tint wie gewohnt wirkt, plus einen Schatten zur Abgrenzung. */
.ks-widget-cover-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    background: var(--kajinga-white, #fff);
    border-radius: var(--kajinga-radius-full, 999px);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
    line-height: 0;
}

.ks-widget-heading {
    min-width: 0;
    flex: 1;
}

.ks-widget-title a {
    color: inherit;
    text-decoration: none;
}

.ks-widget-title a:hover {
    color: var(--kajinga-primary, #2271b1);
}

.ks-widget-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 2px;
    font-size: 14px;
    color: var(--kajinga-text-muted, #646970);
}

.ks-widget-meta-sep {
    opacity: 0.5;
}

.ks-widget-header-side {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 6px;
    flex: none;
}

.ks-widget-progress-head {
    display: flex;
    justify-content: space-between;
    margin-bottom: 6px;
    font-size: 14px;
    color: var(--kajinga-text-muted, #646970);
}

.ks-widget-progress-count {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--kajinga-text, #1d2327);
}

/* Info-Zeile für den body-Slot (z.B. „Nächster Schritt: …") */
.ks-widget-info {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14.5px;
    color: var(--kajinga-text-muted, #646970);
}

.ks-widget-info strong {
    color: var(--kajinga-text, #1d2327);
}

.ks-widget-info--success {
    color: var(--kajinga-success-text, #00a32a);
}

/* =========================================
 * DARK MODE
 * ========================================= */

body.kajinga-dark-mode .ks-widget {
    background: var(--kajinga-dark-card, #1e1e1e);
    border-color: rgba(255, 255, 255, 0.08);
}

body.kajinga-dark-mode .ks-widget-title,
body.kajinga-dark-mode .ks-widget-stat-value {
    color: var(--kajinga-text, #f2f2f2);
}

body.kajinga-dark-mode .ks-widget-inactive,
body.kajinga-dark-mode .ks-widget-soon,
body.kajinga-dark-mode .ks-widget--inactive .ks-widget-icon {
    background: rgba(255, 255, 255, 0.06);
    color: var(--kajinga-text-muted, #b5bcc2);
}

body.kajinga-dark-mode .ks-widget-cover {
    background-color: rgba(255, 255, 255, 0.06);
}

body.kajinga-dark-mode .ks-widget-cover-badge {
    background: var(--kajinga-bg, #1a1d21);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
}

body.kajinga-dark-mode .ks-widget-progress-count,
body.kajinga-dark-mode .ks-widget-info strong {
    color: var(--kajinga-text, #f2f2f2);
}

body.kajinga-dark-mode .ks-page-title {
    color: var(--kajinga-text, #f2f2f2);
}

body.kajinga-dark-mode .ks-switch-track {
    background: rgba(255, 255, 255, 0.18);
}

body.kajinga-dark-mode .ks-switch-input:checked + .ks-switch-track {
    background: var(--kajinga-primary, #2271b1);
}

body.kajinga-dark-mode .ks-skeleton {
    background: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0.06) 25%,
        rgba(255, 255, 255, 0.12) 50%,
        rgba(255, 255, 255, 0.06) 75%
    );
    background-size: 200% 100%;
}

body.kajinga-dark-mode .ks-dropdown-menu {
    border-color: rgba(255, 255, 255, 0.1);
}

body.kajinga-dark-mode .ks-dropdown-toggle:hover,
body.kajinga-dark-mode .ks-dropdown.open .ks-dropdown-toggle,
body.kajinga-dark-mode .ks-dropdown-item:hover,
body.kajinga-dark-mode .ks-card-collapse:hover {
    background: rgba(255, 255, 255, 0.08);
}

body.kajinga-dark-mode .ks-dropdown-divider {
    background: rgba(255, 255, 255, 0.08);
}

body.kajinga-dark-mode .ks-table-empty-filter {
    border-color: rgba(255, 255, 255, 0.12);
}

body.kajinga-dark-mode .ks-chip {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.14);
    color: var(--kajinga-text-muted, #b5bcc2);
}

body.kajinga-dark-mode .ks-chip:has(input:checked) {
    background: var(--kajinga-primary, #2271b1);
    border-color: var(--kajinga-primary, #2271b1);
    color: #fff;
}

/* Klickbare Stat-Kachel (Dashboard → Screen) */
a.ks-stat-card--link {
    text-decoration: none;
    color: inherit;
    display: block;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

a.ks-stat-card--link:hover {
    transform: translateY(-1px);
    box-shadow: var(--kajinga-shadow-md, 0 4px 12px rgba(16, 24, 40, 0.1));
}

a.ks-stat-card--link:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.3);
}

/* ==========================================================================
   Tooltips ueber [data-ks-tip]
   Jedes Element mit [data-ks-tip] zeigt bei Hover ODER Tastatur-Fokus eine
   Erklaerungs-Blase (Selektor in components.js seit 4.2.17 generisch). Der
   dezente Info-Indikator oben rechts bleibt der .ks-stat-card vorbehalten — er
   gehoert zur Kachel, nicht zum Tooltip; an einer Tabellenzelle waere er ein
   Fremdkoerper.
   Die Blase selbst wird per JS (components.js) an den <body> gehaengt
   (position:fixed) und ist damit immun gegen overflow-Clipping der Grid-/
   Card-Container.
   ========================================================================== */
.ks-stat-card[data-ks-tip] { position: relative; cursor: help; }
.ks-stat-card[data-ks-tip]::after {
    content: "i";
    position: absolute; top: 7px; right: 8px;
    width: 15px; height: 15px; line-height: 15px;
    font-family: Georgia, "Times New Roman", serif; font-style: italic;
    font-weight: 700; font-size: 13px; text-align: center;
    border-radius: 50%;
    background: rgba(120,130,145,.18); color: currentColor;
    opacity: .45; transition: opacity .15s ease; pointer-events: none;
}
.ks-stat-card[data-ks-tip]:hover::after,
.ks-stat-card[data-ks-tip]:focus-visible::after { opacity: .9; }

.ks-tip-bubble {
    position: fixed; z-index: 100050;
    /* 270 -> 340 (v4.0.96). Erhebung über alle 203 Tooltips im Netz: bei 270px
       passten nur 43 % in zwei Zeilen, bei 340px sind es 69 %. Eine Zeile CSS
       gegen 52 zu lange Blasen. Breiter wäre kontraproduktiv — eine Blase, die
       über die halbe Kachelreihe reicht, verdeckt wieder, was sie erklärt. */
    max-width: 340px;
    background: #1f2430; color: #fff;
    padding: 8px 11px; border-radius: 8px;
    font-size: 14px; line-height: 1.45; font-weight: 400;
    text-align: left; letter-spacing: .1px;
    /* `pre-line` (4.2.17): ein `\n` im Attribut wird zum Umbruch, alles andere
       kollabiert wie bisher. Fuer die 203 einzeiligen Bestands-Tooltips ohne
       Zeilenumbruch aendert sich dadurch nichts. Erst damit kann eine Blase
       einen Datensatz tragen — Name, Firma, Anschrift — statt nur eines Satzes. */
    white-space: pre-line;
    box-shadow: 0 8px 28px rgba(0,0,0,.24);
    pointer-events: none; opacity: 0; transform: translateY(4px);
    transition: opacity .12s ease, transform .12s ease;
}
.ks-tip-bubble.is-visible { opacity: 1; transform: translateY(0); }
.ks-tip-bubble::after {
    content: ""; position: absolute;
    left: var(--ks-tip-arrow, 50%); transform: translateX(-50%);
    border: 6px solid transparent;
}
.ks-tip-bubble.is-above::after { bottom: -6px; border-top-color: #1f2430; border-bottom: 0; }
.ks-tip-bubble.is-below::after { top: -6px; border-bottom-color: #1f2430; border-top: 0; }

/* =========================================
 * TAB-NAVIGATION (seit 3.6.0)
 *
 * ZWEI ROLLEN, die nicht vermischt werden dürfen (Wording seit 4.0.36):
 *
 *   Navigation 1 — Untermenü-System .ks-tab-nav (Pill-Leiste)
 *     App-Chrome unter dem Hero. Stellt bei komplexeren Plugins die wichtigsten
 *     Funktionen übersichtlich bereit und wechselt dabei die SEITE (echte URLs).
 *     Sie doppelt das Admin-Untermenü zur Bequemlichkeit — deshalb unter 782px
 *     ausgeblendet, wo WordPress das Menü ohnehin zum Overlay klappt.
 *     Untermenüs (children) gehören hierher.
 *
 *   Navigation 2 — Karteireiter .ks-tab-nav--cards + .ks-tab-sheet
 *     Schaltet den INHALT derselben Seite um — ob per ?tab=-URL oder per JS.
 *     Trägt die Seite und bleibt deshalb auf jedem Schirm sichtbar.
 *
 * Faustregel: Wechselt die Seite → Pill-Leiste. Wechselt der Inhalt → cards.
 * Eine Leiste ohne cards, die per JS Panes umschaltet, ist falsch eingeordnet.
 * ========================================= */

.ks-tab-nav {
    display: flex;
    align-items: center;
    gap: 2px;
    /* Kein Umbruch: eine Navigationsleiste, die in zwei Zeilen zerfällt, wirkt
       wie zwei Ebenen — Punkte der zweiten Zeile scheinen unter denen der ersten
       zu hängen. Wird es eng, kürzen sich die Labels (siehe unten).
       Bewusst KEIN overflow-x: das würde die Hover-Untermenüs abschneiden. */
    flex-wrap: nowrap;
    padding: 4px;
    margin-bottom: var(--kajinga-space-5, 20px);
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    border-radius: var(--kajinga-radius-md, 12px);
    box-shadow: var(--kajinga-shadow-sm, 0 1px 2px rgba(16, 24, 40, 0.06));
}

.ks-tab-nav-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: var(--kajinga-radius-sm, 10px);
    color: var(--kajinga-text-muted, #646970);
    font-size: 14.5px;
    font-weight: 500;
    text-decoration: none;
    transition: background 0.12s ease, color 0.12s ease;
    white-space: nowrap;
}

.ks-tab-nav-link:hover {
    background: var(--kajinga-gray-100, #f6f7f7);
    color: var(--kajinga-text, #1d2327);
}

/* Wird die Leiste zu breit, kürzen sich die Labels statt umzubrechen.
   Icons bleiben immer sichtbar — sie tragen die Orientierung. */
.ks-tab-nav-link {
    min-width: 0;
}

.ks-tab-nav-link > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ks-tab-nav-link > svg {
    flex: 0 0 auto;
}

.ks-tab-nav-link.active {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.1);
    color: var(--kajinga-primary, #2271b1);
    font-weight: 600;
}

/* Maus-Fokus beim Aktivieren: WP-Core legt auf a:focus einen blauen Ring um den
   ganzen Reiter — zu laut. Unterdrücken; die :focus-visible-Regel darunter
   gewinnt bei Tastatur-Fokus (gleiche Spezifität, spätere Quelle) — der
   Ring bleibt also für die Tastatur-Navigation erhalten. */
.ks-tab-nav-link:focus {
    outline: none;
    box-shadow: none;
}

.ks-tab-nav-link:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.3);
}

/* ---------------------------------------------------------------------------
   Karteireiter (variant => 'cards')

   Zweite Navigationsebene unter der Pill-Leiste: Die Reiter sitzen auf der
   Inhaltsfläche auf, der aktive verschmilzt mit ihr. Dadurch ist ohne Nachdenken
   erkennbar, dass sie den Inhalt darunter umschalten — während die Pill-Leiste
   darüber die Seite wechselt. Zwei Pill-Leisten übereinander wären dagegen
   nicht auseinanderzuhalten.
   --------------------------------------------------------------------------- */

.ks-tab-nav--cards {
    gap: 3px;
    padding: 0;
    margin-bottom: 0;
    /* Die Basis-Leiste ist eine schwebende weiße Box (Rahmen, Schatten, 12 px
       Radius rundum). Für Karteireiter muss das weg: eine gerundete Box unter
       den Reitern bricht genau den Übergang, den das Design herstellen soll.
       Es bleibt allein die Trennlinie, auf der die Reiter aufsitzen. */
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--kajinga-border, #d5dde6);
    border-radius: 0;
    box-shadow: none;
}

.ks-tab-nav--cards .ks-tab-nav-link {
    /* Eigene Größe seit 4.1.4: Karteireiter sitzen auf der Fläche, die sie
       umschalten, und stehen dichter beieinander als die Pill-Leiste — sie
       tragen deshalb eine halbe Stufe weniger. Bis dahin teilten sich beide
       Navigationsebenen die Basis-Regel und ließen sich nicht trennen. */
    font-size: 13px;
    padding: 8px 16px 10px;
    /* Die Aktiv-Kante ist der obere RAHMEN, kein aufgesetzter Balken: nur so
       folgt sie den runden oberen Ecken. Ein absolut positioniertes ::before
       wäre eine gerade Linie über einer Rundung — das passt nie zusammen.
       Inaktiv liegt sie transparent bereit, damit beim Wechsel nichts springt. */
    border: 1px solid transparent;
    border-top-width: 1px;
    border-bottom: none;
    /* Oben rund, unten scharf — die Reiter enden bündig auf der Fläche.
       Runde Unterkanten würden sie zu Pillen machen und den Übergang brechen. */
    border-radius: var(--kajinga-radius-sm, 10px) var(--kajinga-radius-sm, 10px) 0 0;
    /* überlappt die Trennlinie, damit der aktive Reiter sie durchbricht */
    margin-bottom: -1px;
    /* Auch inaktive Reiter sind Karteikarten und brauchen eine eigene Fläche:
       transparent genügt nur auf weißem Grund. Im Admin liegt darunter der
       blaue Flächenverlauf — dort verschwänden sie sonst ganz. Gedämpft, damit
       der aktive Reiter trotzdem hervorsticht. */
    background: var(--kajinga-gray-50, #f7f9fc);
    font-weight: 500;
}

.ks-tab-nav--cards .ks-tab-nav-link:hover {
    background: var(--kajinga-gray-100, #f2f5f9);
    color: var(--kajinga-text, #1d2327);
}

/* Angedeutete Kante beim Überfahren — zeigt die Zielform, ohne den aktiven
   Reiter nachzuahmen. */
.ks-tab-nav--cards .ks-tab-nav-link:hover:not(.active) {
    border-top-color: var(--kajinga-gray-300, #c3cbd5);
}

.ks-tab-nav--cards .ks-tab-nav-link.active {
    background: var(--kajinga-card-solid, #fff);
    border-color: var(--kajinga-border, #d5dde6);
    border-top-color: var(--kajinga-primary, #179afc);
    color: var(--kajinga-primary, #179afc);
    font-weight: 600;
}

/* Die Fläche, auf der die Reiter aufsitzen.
   NICHT .ks-tab-panel nennen — die Klasse gehört ks_tabs (Alpine) und ist per
   display:none versteckt, bis x-show sie einblendet. */
.ks-tab-sheet {
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-border, #d5dde6);
    border-top: none;
    border-radius: 0 0 var(--kajinga-radius-md, 12px) var(--kajinga-radius-md, 12px);
    padding: 20px;
    box-shadow: var(--kajinga-shadow-sm, 0 1px 2px rgba(16, 24, 40, .04));
}

/* Karteireiter INNERHALB einer bestehenden Karte (4.0.36).

   Sitzt die Leiste schon in einer .ks-card, darf die Fläche keine zweite Karte
   aufmachen. Es bleibt allein der Innenabstand nach oben — die Trennlinie
   bringt .ks-tab-nav--cards selbst mit, und der aktive Reiter verschmilzt mit
   der Kartenfläche, weil beide dieselbe Farbe tragen.
   Referenz: CRM Booking, Mail-Templates. */
.ks-tab-sheet--flush {
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    padding: 18px 0 0;
}

/* Panes: der Inhalt je Karteireiter, wenn die Umschaltung über JS läuft
   (4.0.36).

   NICHT .ks-tab-panel — die Klasse gehört ks_tabs/Alpine und ist per
   display:none versteckt, bis x-show sie einblendet. Hier schaltet das
   verbrauchende Plugin selbst, deshalb ein eigener Container: die Klasse
   kommt ZUSÄTZLICH zur plugin-eigenen Pane-Klasse, an der dessen JS hängt.

   Ohne diesen Container liefe die Karten-Entschärfung darunter ins Leere —
   sie greift nur auf direkte Kinder, und mit Pane dazwischen steckte jede
   Karte sichtbar in der Sheet-Karte. */
.ks-tab-sheet-pane[hidden] {
    display: none;
}

/* Karten in der Fläche verlieren ihren eigenen Rahmen — sonst steckt eine Karte
   in einer Karte. Mehrere Abschnitte trennt eine feine Linie statt eines
   zweiten Kastens. Gilt direkt in der Fläche wie auch innerhalb eines Panes. */
.ks-tab-sheet > .ks-card,
.ks-tab-sheet > .ks-tab-sheet-pane > .ks-card {
    border: none;
    box-shadow: none;
    padding: 0;
    background: transparent;
}

/* 28px statt 22px (v4.1.18) — passend zum größeren Kartentitel oben: Eine
 * Überschrift, die mehr Gewicht bekommt, braucht auch mehr Luft davor, sonst
 * rückt sie optisch an den Block darüber heran. Der sichtbare Abstand zwischen
 * zwei Karten ist die Summe aus margin und padding, die Trennlinie liegt
 * mittig — deshalb tragen beide denselben Wert.
 *
 * ACHTUNG, gilt NUR im Tab-Sheet. Die allgemeine Stapelregel
 * (.ks-card + .ks-card, 20px) steht in assets/css/token-utilities.tpl und damit
 * in einer GENERIERTEN Datei: Sie wird nur neu gebaut, wenn design-tokens.css
 * fehlt oder jemand die Styler-Einstellungen speichert (maybe_regenerate_css()).
 * Eine Änderung dort käme auf den meisten der 1200+ Sites schlicht nicht an —
 * wer die beiden Werte angleichen will, muss die Regenerierung mit einplanen. */
.ks-tab-sheet > .ks-card + .ks-card,
.ks-tab-sheet > .ks-tab-sheet-pane > .ks-card + .ks-card {
    margin-top: var(--kajinga-space-7, 28px);
    padding-top: var(--kajinga-space-7, 28px);
    border-top: 1px solid var(--kajinga-gray-150, #eef1f5);
}

/* Der erste Titel im Pane sitzt bündig oben — die Sheet bringt ihr eigenes
   Padding mit, ein zusätzlicher Kopfabstand ließe den Reiter abheben. */
.ks-tab-sheet > .ks-tab-sheet-pane > :first-child {
    margin-top: 0;
}

/* Zähler-Badge im Reiter (Anzahl Termine, offene Fehler …) */
.ks-tab-nav-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    padding: 1px 7px;
    border-radius: 10px;
    background: var(--kajinga-gray-200, #e3e6ea);
    color: var(--kajinga-text-muted, #646970);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.6;
}

/* Im aktiven Reiter trägt das Badge die Brand-Farbe mit */
.ks-tab-nav-link.active .ks-tab-nav-count {
    background: var(--kajinga-primary, #179afc);
    color: #fff;
}

.ks-tab-nav-count--highlight {
    background: var(--kajinga-primary, #179afc);
    color: #fff;
}

.ks-tab-nav-count--danger {
    background: var(--kajinga-danger, #dc2626);
    color: #fff;
}

.ks-tab-nav-caret {
    margin-left: -2px;
    opacity: 0.6;
}

.ks-tab-nav-dropdown {
    position: relative;
}

/* Die Karte hängt LINKS am Punkt, nicht rechts (4.0.60).
   Vorher: right: 0 + min-width: 210px. Beides zusammen ergab bei kurzen
   Einträgen ("Termine", "Quiz-Funnel") eine Karte, die deutlich breiter war
   als ihr Inhalt UND deren Überbreite komplett nach links über den Auslöser
   hinausragte — sie schien zu einem Punkt weiter links zu gehören. Jetzt
   bestimmt der längste Eintrag die Breite (max-content), der Punkt darüber
   die Mindestbreite (min-width: 100% = Breite des .ks-tab-nav-dropdown), und
   die linke Kante liegt auf der des Auslösers. max-width als Deckel, damit ein
   ungewöhnlich langes Label die Karte nicht über die halbe Leiste zieht — dort
   bricht der Eintrag dann um, wie zuvor bei 210px. */
.ks-tab-nav-submenu {
    position: absolute;
    top: 100%;
    left: 0;
    right: auto;
    width: max-content;
    min-width: 100%;
    max-width: 280px;
    padding: 5px;
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    border-radius: var(--kajinga-radius-md, 12px);
    box-shadow: var(--kajinga-shadow-lg, 0 10px 30px rgba(0, 0, 0, 0.15));
    z-index: 100;
    display: none;
}

/* Steht das Dropdown am Ende der Leiste, hat es rechts nichts mehr neben sich,
   über das die Karte hängen könnte — dort klappt sie nach links auf. Die Leiste
   hat bewusst kein overflow (sonst schnitte sie die Karten ab), ein Überlauf
   würde also über den Inhaltsrand hinauslaufen statt zu scrollen. */
.ks-tab-nav-dropdown:last-child .ks-tab-nav-submenu {
    left: auto;
    right: 0;
}

.ks-tab-nav-dropdown:hover .ks-tab-nav-submenu,
.ks-tab-nav-dropdown:focus-within .ks-tab-nav-submenu {
    display: block;
    /* Wächst aus der linken oberen Ecke des Punktes — dieselbe Kante, an der
       die Karte per `left: 0` hängt (siehe Block oben). Beim letzten Punkt der
       Leiste klappt sie nach links auf, dort liegt der Ursprung rechts. */
    transform-origin: top left;
    animation: ks-pop-in 0.14s var(--kajinga-ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}

.ks-tab-nav-dropdown:last-child .ks-tab-nav-submenu {
    transform-origin: top right;
}

.ks-tab-nav-sublink {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-radius: var(--kajinga-radius-sm, 10px);
    color: var(--kajinga-text, #1d2327);
    font-size: 14.5px;
    text-decoration: none;
}

.ks-tab-nav-sublink:hover,
.ks-tab-nav-sublink.active {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.08);
    color: var(--kajinga-primary, #2271b1);
}

/* Navigation 1: die Pill-Leiste IST die Karte und wird dunkel eingefärbt.
   Karteireiter ausgenommen — sie sind bewusst flächenlos und würden hier
   ihren Rundum-Rahmen zurückbekommen (die Regel ist mit 0,2,1 spezifischer
   als .ks-tab-nav--cards mit 0,1,0). */
body.kajinga-dark-mode .ks-tab-nav:not(.ks-tab-nav--cards),
body.kajinga-dark-mode .ks-tab-nav-submenu {
    background: var(--kajinga-dark-card, #1e1e1e);
    border-color: rgba(255, 255, 255, 0.08);
}

body.kajinga-dark-mode .ks-tab-nav-link:hover {
    background: rgba(255, 255, 255, 0.06);
    color: var(--kajinga-text, #f2f2f2);
}

body.kajinga-dark-mode .ks-tab-nav-sublink {
    color: var(--kajinga-text, #f2f2f2);
}

/* Navigation 2 im Dark Mode (4.0.36).
   Die Karteireiter griffen auf die Graustufen --kajinga-gray-50/100/300 und
   -150 zurück, und genau die definiert design-tokens.css im Dark Mode NICHT um
   (dort wechseln nur bg/card/text/text_muted/primary/border). Ergebnis waren
   hellgraue Reiter und eine helle Trennlinie auf dunklem Grund. */
body.kajinga-dark-mode .ks-tab-nav--cards {
    background: transparent;
    border-bottom-color: var(--kajinga-border, #2a3446);
}

body.kajinga-dark-mode .ks-tab-nav--cards .ks-tab-nav-link {
    background: rgba(255, 255, 255, 0.04);
    border-color: transparent;
}

body.kajinga-dark-mode .ks-tab-nav--cards .ks-tab-nav-link:hover:not(.active) {
    background: rgba(255, 255, 255, 0.07);
    border-top-color: rgba(255, 255, 255, 0.18);
}

body.kajinga-dark-mode .ks-tab-nav--cards .ks-tab-nav-link.active {
    background: var(--kajinga-card-solid, #1e1e1e);
    border-color: var(--kajinga-border, #2a3446);
    border-top-color: var(--kajinga-primary, #179afc);
    color: var(--kajinga-primary, #179afc);
}

body.kajinga-dark-mode .ks-tab-sheet > .ks-card + .ks-card,
body.kajinga-dark-mode .ks-tab-sheet > .ks-tab-sheet-pane > .ks-card + .ks-card {
    border-top-color: rgba(255, 255, 255, 0.08);
}

/* ---------------------------------------------------------------------------
   Smartphone (v4.0.35, auf die Rollen-Trennung gezogen in 4.0.36)

   Die Leiste ist auf schmalen Schirmen unbrauchbar: nowrap + 5-8 Punkte heißt,
   die Labels kürzen sich auf ein paar Buchstaben. Die Rollen entscheiden, was
   das heißt:

     Navigation 1 (Pill-Leiste) doppelt das Admin-Untermenü → entbehrlich, weg.
     Navigation 2 (Karteireiter) trägt den Seiteninhalt     → bleibt, scrollt.

   Damit hängt die Regel allein an der Rolle, nicht an Markup-Indizien. Wer eine
   Leiste baut, die per JS Panes umschaltet, gibt ihr `variant => 'cards'` —
   dann stimmt Optik und Mobil-Verhalten von selbst.
   --------------------------------------------------------------------------- */
@media screen and (max-width: 782px) {
    .ks-tab-nav:not(.ks-tab-nav--cards) {
        display: none;
    }

    /* Karteireiter scrollen seitwärts, statt sich zu Buchstabenresten zu
       quetschen. Gefahrlos, weil Untermenüs (children) zu Navigation 1
       gehören — ein Karteireiter mit Hover-Flyout wäre ein Widerspruch. */
    .ks-tab-nav--cards {
        overflow-x: auto;
        scrollbar-width: none;
    }

    .ks-tab-nav--cards::-webkit-scrollbar {
        display: none;
    }

    .ks-tab-nav--cards .ks-tab-nav-link {
        flex: 0 0 auto;
    }

    /* Die Fläche darunter darf auf dem Telefon nicht auch noch 20px je Seite
       verschenken. */
    .ks-tab-sheet {
        padding: 14px;
    }
}

/* =========================================
 * WIZARD-STEPS (v3.8.7 — ersetzt mm-/mp-/mmo-steps)
 * ========================================= */

.ks-wsteps {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    margin: 0 0 var(--kajinga-space-6, 24px);
    flex-wrap: wrap;
}

.ks-wstep {
    display: inline-flex;
    align-items: center;
    gap: 14px;
}

.ks-wstep-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--kajinga-gray-100, #f0f0f1);
    color: var(--kajinga-text-muted, #646970);
    font-size: 18px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    flex: none;
}

/* Häkchen (done) kommt serverseitig mit size 14 — auf die neue Kreisgröße skalieren */
.ks-wstep-number svg {
    width: 20px;
    height: 20px;
}

.ks-wstep-label {
    font-size: 20px;
    color: var(--kajinga-text-muted, #646970);
    white-space: nowrap;
}

.ks-wstep--active .ks-wstep-number {
    background: var(--kajinga-primary, #2271b1);
    color: #fff;
}

.ks-wstep--active .ks-wstep-label {
    color: var(--kajinga-text, #1d2327);
    font-weight: 600;
}

.ks-wstep--done .ks-wstep-number {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.12);
    color: var(--kajinga-primary, #2271b1);
}

.ks-wstep-connector {
    flex: 1 1 40px;
    min-width: 24px;
    max-width: 96px;
    height: 2px;
    background: var(--kajinga-gray-200, #e2e4e7);
}

body.kajinga-dark-mode .ks-wstep-number { background: rgba(255, 255, 255, 0.08); color: var(--kajinga-text-muted, #a0a5aa); }
body.kajinga-dark-mode .ks-wstep--active .ks-wstep-number { background: var(--kajinga-primary, #2271b1); color: #fff; }
body.kajinga-dark-mode .ks-wstep-connector { background: rgba(255, 255, 255, 0.1); }

/* =========================================
 * SUPPORT-MODUS-BANNER (v3.8.7)
 * ========================================= */

.ks-support-banner {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    margin: 0 0 var(--kajinga-space-5, 20px);
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.06);
    border: 1px solid rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.25);
    border-radius: var(--kajinga-radius-md, 10px);
    font-size: 14.5px;
    color: var(--kajinga-text, #1d2327);
}

.ks-support-banner .ks-icon {
    color: var(--kajinga-primary, #2271b1);
    flex: none;
}

body.kajinga-dark-mode .ks-support-banner {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.15);
    color: var(--kajinga-text, #e2e2e2);
}

/* =========================================
 * Mobile (<=782px) — v3.9.38: Untertitel aus, Interaktives in Zeile 2
 * ========================================= */
@media screen and (max-width: 782px) {
    /* Untertitel auf Mobile konsequent weglassen.
     *
     * DAS IST EINE ENTSCHEIDUNG, KEIN VERSEHEN — bestätigt am 2026-08-04.
     *
     * Eine Design-Kritik hat es als Mangel gemeldet („der Hero zeigt mobil nur
     * noch den Plugin-Namen"), und die Beobachtung stimmt; die Schlussfolgerung
     * war trotzdem falsch. Auf einem 390px-Schirm ist senkrechter Platz das
     * knappste Gut, und der Untertitel beschreibt die Funktion der Seite —
     * also genau das, was jemand schon weiß, der die Seite aufgerufen hat.
     * Der Titel trägt die Verortung, der Inhalt beginnt früher.
     *
     * Wer das ändern will, ändert eine Festlegung, kein Detail. */
    .ks-page-header .ks-hero-text,
    .ks-page-header .ks-page-subtitle { display: none; }

    /* Titel kompakter; Umbruch nicht direkt hinter dem Trenner */
    .ks-page-header .ks-hero-title,
    .ks-page-header .ks-page-title { font-size: 20px; line-height: 1.25; }

    /* v4.0.85: Mobil war der Hero proportional höher als auf Desktop, weil
       Innenabstand und Icon-Box unverändert blieben, während der Untertitel
       ohnehin ausgeblendet ist. */
    .ks-hero { padding: 14px 18px; border-radius: 14px; }
    .ks-hero-iconbox { width: 38px; height: 38px; border-radius: 10px; }
    .ks-hero-iconbox svg { width: 20px; height: 20px; }
    .ks-hero-title .ks-hero-title-sep { white-space: nowrap; }
    .ks-hero-title .ks-hero-brand { white-space: nowrap; }

    /* Buttons/Suche grundsätzlich in die zweite Zeile (Header ist flex-wrap) */
    .ks-page-header-actions,
    .ks-page-header .ks-hero-search {
        flex-basis: 100%;
        width: 100%;
        margin-top: 10px;
        display: flex;
        gap: 8px;
    }
    /* v3.9.55: Suchfeld-Input mobil über die volle Breite (statt fixer 320px) */
    .ks-page-header .ks-hero-search .ks-hero-search-input { width: 100%; }
    .ks-page-header-actions .ks-btn {
        flex: 1;
        justify-content: center;
    }

    /* v3.9.43: Breite Tabellen horizontal scrollbar machen. Ohne das sprengt
       z.B. eine 874px-Listentabelle den Layout-Viewport (Chrome weitet ihn auf
       die Tabellenbreite auf) und die GANZE Seite wird herausgezoomt. */
    .ks-page table.wp-list-table,
    .ks-page table.widefat,
    .ks-page .ks-table,
    .ks-page table.ks-table {
        display: block;
        width: 100%;
        max-width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* Sonstige breite Blöcke (Grids, Code, Karten-Reihen) nicht überlaufen lassen */
    .ks-page pre,
    .ks-page .ks-card { max-width: 100%; overflow-x: auto; }

    /* v3.9.43: Formularfelder mit fester Breite (WP-Core .regular-text = 25em,
       Selects, Suchfelder) auf Viewport-Breite klemmen — sie weiteten sonst
       ebenfalls den Layout-Viewport auf */
    .ks-page input[type="text"],
    .ks-page input[type="search"],
    .ks-page input[type="email"],
    .ks-page input[type="url"],
    .ks-page input[type="number"],
    .ks-page input[type="password"],
    .ks-page select,
    .ks-page textarea,
    .ks-page .regular-text,
    .ks-page .large-text {
        /* An den VIEWPORT klemmen, nicht an den Parent: Selects mit langen
           Options lassen ihren Container mitwachsen -> max-width:100% liefe
           ins Leere (Zirkelschluss) */
        max-width: calc(100vw - 36px);
        box-sizing: border-box;
    }

    /* Container, die durch shrink-to-fit mitwachsen, ebenfalls klemmen */
    .ks-page .ks-page-header,
    .ks-page > div,
    .ks-page > form { max-width: 100%; }

    /* Flex-Toolbars (Suchfeld + Button o.ä.): Kinder dürfen schrumpfen —
       ohne min-width:0 bleibt ein Input auf seiner Wunschbreite und
       schiebt den Container über den Viewport */
    .ks-page [class*="toolbar"],
    .ks-page [class*="search"],
    .ks-page [class*="filter"] { flex-wrap: wrap; max-width: 100%; }
    .ks-page [class*="toolbar"] > *,
    .ks-page [class*="search"] > *,
    .ks-page [class*="filter"] > * { min-width: 0; }
}

/* v3.9.43: Schlusssicherung — kein horizontaler Seiten-Overflow im Admin.
   Verhindert, dass ein einzelnes zu breites Element den Layout-Viewport
   aufweitet und damit die ganze Seite herauszoomt. Inhalte mit echtem
   Platzbedarf (Tabellen) scrollen oben in ihrem eigenen Container. */
@media screen and (max-width: 782px) {
    html.wp-toolbar,
    body.wp-admin {
        max-width: 100vw;
        overflow-x: hidden;
    }
}

/* =========================================
 * ACTION-LAYOUT (v3.9.56) — Einstellungsseiten mit CTA-Box rechts
 * Konvention: Optionen/Felder links (schmaler), Haupt-Aktion (Speichern/
 * Prozess starten) rechts oben in eigener sticky Karte. Ref: ULTRA SEO Generator.
 * ========================================= */

.ks-action-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 20px;
    align-items: start;
    margin-top: 16px;
}

.ks-action-main {
    display: flex;
    flex-direction: column;
    gap: 20px;
    min-width: 0;
}

.ks-action-aside {
    position: sticky;
    top: 68px; /* unter der schwebenden App-Bar (56px + Luft) */
}

.ks-action-card {
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    border-radius: var(--kajinga-radius-lg, 12px);
    box-shadow: var(--kajinga-shadow-sm, 0 1px 2px rgba(16, 24, 40, 0.06));
    padding: 24px;
    text-align: center;
}

.ks-action-card-badge {
    width: 52px;
    height: 52px;
    margin: 0 auto 14px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.10);
    color: var(--kajinga-primary, #2271b1);
}

.ks-action-card-title {
    margin: 0 0 8px;
    font-family: var(--kajinga-font-display, var(--kajinga-font, sans-serif));
    font-size: 17px;
    font-weight: 700;
    color: var(--kajinga-text, #1d2327);
}

.ks-action-card-text {
    margin: 0 0 18px;
    font-size: 14.5px;
    line-height: 1.55;
    color: var(--kajinga-text-muted, #646970);
}

.ks-action-card .ks-action-card-btn {
    width: 100%;
    justify-content: center;
}

.ks-action-card-note {
    margin: 12px 0 0;
    font-size: 14px;
    color: var(--kajinga-text-muted, #646970);
}

@media (max-width: 960px) {
    .ks-action-layout { grid-template-columns: 1fr; }
    .ks-action-aside { position: static; }
}

/* =========================================
   TERM-VERWALTUNG (ks_term_manager, v3.10.0)
   ========================================= */

.ks-term-manager {
    display: flex;
    flex-direction: column;
    gap: var(--kajinga-space-3);
}

.ks-term-list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--kajinga-space-1);
}

.ks-term-item {
    display: flex;
    align-items: center;
    gap: var(--kajinga-space-2);
    margin: 0;
    padding: var(--kajinga-space-2) var(--kajinga-space-3);
    border: 1px solid var(--kajinga-gray-200);
    border-radius: var(--kajinga-radius-md);
    background: var(--kajinga-card-solid);
}

.ks-term-marker {
    flex: 0 0 auto;
    width: 12px;
    height: 12px;
    border-radius: var(--kajinga-radius-full);
}

.ks-term-marker--icon {
    display: inline-flex;
    width: auto;
    height: auto;
    color: var(--kajinga-text-muted);
}

.ks-term-label {
    flex: 1 1 auto;
    min-width: 0;
}

.ks-term-name {
    display: block;
    font-weight: 600;
    font-size: 14.5px;
    /* Lange Namen kürzen statt in den Zähler laufen zu lassen */
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.ks-term-desc {
    display: block;
    max-width: 46ch;
    margin-top: 2px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 14px;
    color: var(--kajinga-text-muted);
}

.ks-term-usage {
    flex: 0 0 auto;
    font-size: 14px;
    color: var(--kajinga-text-muted);
    font-variant-numeric: tabular-nums;
}

.ks-term-empty {
    padding: var(--kajinga-space-4);
    text-align: center;
    color: var(--kajinga-text-muted);
    font-size: 14.5px;
}

.ks-term-add {
    display: flex;
    align-items: center;
    gap: var(--kajinga-space-2);
}

.ks-term-add .ks-input {
    flex: 1 1 auto;
    min-width: 0;
}

.ks-term-error {
    margin: 0;
    font-size: 14px;
    color: var(--kajinga-danger);
}

body.kajinga-dark-mode .ks-term-item {
    border-color: rgba(255, 255, 255, .08);
}

/* =========================================================================
 * ks_calendar() — geteilte Kalender-Komponente (v3.9.64)
 * Monat/Woche/Liste, Filter, Drag-Reschedule. Farben je Event über --evc.
 * ========================================================================= */
.ks-cal {
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-border, #e4e7ec);
    border-radius: var(--kajinga-radius-lg, 14px);
    padding: 16px;
    box-shadow: var(--kajinga-shadow-sm, 0 1px 3px rgba(16,24,40,.06));
}
.ks-cal-toolbar {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
}
.ks-cal-nav { display: flex; align-items: center; gap: 8px; }
.ks-cal-navbtn, .ks-cal-todaybtn {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 34px; height: 34px; padding: 0 10px;
    border: 1px solid var(--kajinga-border, #e4e7ec);
    background: var(--kajinga-card-solid, #fff);
    color: var(--kajinga-text, #101828);
    border-radius: 9px; cursor: pointer; font-size: 15px; line-height: 1;
    transition: background .12s ease, border-color .12s ease;
}
.ks-cal-navbtn:hover, .ks-cal-todaybtn:hover { background: var(--kajinga-gray-50, #f9fafb); border-color: var(--kajinga-primary, #179afc); }
.ks-cal-navbtn:disabled { opacity: .4; cursor: not-allowed; }
.ks-cal-navbtn { font-size: 20px; font-weight: 600; }
.ks-cal-period {
    font-family: var(--kajinga-font-display, inherit);
    font-weight: 700; font-size: 17px; color: var(--kajinga-text, #101828); margin-left: 4px;
}
.ks-cal-spin {
    width: 14px; height: 14px; border: 2px solid var(--kajinga-gray-200, #e4e7ec);
    border-top-color: var(--kajinga-primary, #179afc); border-radius: 50%;
    animation: ks-cal-spin .7s linear infinite;
}
@keyframes ks-cal-spin { to { transform: rotate(360deg); } }
.ks-cal-views { display: inline-flex; background: var(--kajinga-gray-100, #f2f4f7); border-radius: 9px; padding: 3px; gap: 2px; }
.ks-cal-viewbtn {
    border: 0; background: transparent; color: var(--kajinga-gray-600, #475467);
    padding: 6px 14px; border-radius: 7px; cursor: pointer; font-size: 14px; font-weight: 600;
    transition: background .12s ease, color .12s ease;
}
.ks-cal-viewbtn:hover { color: var(--kajinga-text, #101828); }
.ks-cal-viewbtn.active { background: var(--kajinga-card-solid, #fff); color: var(--kajinga-primary, #179afc); box-shadow: 0 1px 2px rgba(16,24,40,.1); }

.ks-cal-filters { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }
.ks-cal-search {
    height: 34px; padding: 0 12px; border: 1px solid var(--kajinga-border, #e4e7ec);
    border-radius: 9px; font-size: 14px; min-width: 200px; background: var(--kajinga-card-solid, #fff); color: var(--kajinga-text, #101828);
}
.ks-cal-search:focus { outline: none; border-color: var(--kajinga-primary, #179afc); }
.ks-cal-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; }
.ks-cal-legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: 13.5px; color: var(--kajinga-gray-600, #475467); cursor: pointer; user-select: none; }
.ks-cal-legend-item input { margin: 0; }
.ks-cal-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }

/* --- Monat --- */
.ks-cal-weekdays { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); margin-bottom: 6px; }
.ks-cal-weekdays span { text-align: center; font-size: 13px; font-weight: 600; color: var(--kajinga-gray-500, #667085); text-transform: uppercase; letter-spacing: .3px; }
/* minmax(0,1fr) statt 1fr: sonst blähen lange Event-Titel eine Spalte auf und
 * drücken die restlichen aus dem Grid (Overflow rechts). */
.ks-cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); grid-auto-rows: minmax(96px, auto); gap: 6px; }
.ks-cal-cell {
    border: 1px solid var(--kajinga-border, #e4e7ec); border-radius: 10px; padding: 6px;
    background: var(--kajinga-card-solid, #fff); min-height: 96px; min-width: 0; display: flex; flex-direction: column; gap: 4px;
    transition: border-color .12s ease, background .12s ease;
}
.ks-cal-cell.is-empty { background: var(--kajinga-gray-50, #f9fafb); opacity: .6; }
.ks-cal-cell.today { border-color: var(--kajinga-primary, #179afc); box-shadow: inset 0 0 0 1px var(--kajinga-primary, #179afc); }
.ks-cal-cell.has-events { background: var(--kajinga-card-solid, #fff); }
.ks-cal-daynum { display: flex; align-items: center; justify-content: space-between; font-size: 13.5px; font-weight: 600; color: var(--kajinga-gray-700, #344054); min-height: 20px; }
.ks-cal-cell.is-empty .ks-cal-daynum { color: var(--kajinga-gray-400, #98a2b3); }
.ks-cal-cell.today .ks-cal-daynum { color: var(--kajinga-primary, #179afc); }
.ks-cal-add {
    width: 20px; height: 20px; border: 0; border-radius: 6px; cursor: pointer;
    background: var(--kajinga-gray-100, #f2f4f7); color: var(--kajinga-gray-600, #475467);
    font-size: 15px; line-height: 1; display: inline-flex; align-items: center; justify-content: center;
    opacity: 0; transition: opacity .12s ease, background .12s ease;
}
.ks-cal-cell:hover .ks-cal-add, .ks-cal-weekcol:hover .ks-cal-add { opacity: 1; }
.ks-cal-add:hover { background: var(--kajinga-primary, #179afc); color: #fff; }
.ks-cal-events { display: flex; flex-direction: column; gap: 3px; overflow: hidden; }
.ks-cal-event {
    --evc: var(--kajinga-primary, #179afc);
    display: flex; align-items: baseline; gap: 5px; cursor: pointer;
    background: color-mix(in srgb, var(--evc) 12%, transparent);
    border-left: 3px solid var(--evc); border-radius: 4px; padding: 2px 6px;
    font-size: 12.5px; line-height: 1.35; min-width: 0;
}
.ks-cal-event:hover { background: color-mix(in srgb, var(--evc) 20%, transparent); }
.ks-cal-event[draggable="true"] { cursor: grab; }
.ks-cal-ev-time { font-weight: 700; color: var(--evc); flex: 0 0 auto; font-variant-numeric: tabular-nums; }
.ks-cal-ev-title { color: var(--kajinga-text, #101828); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.ks-cal-ev-title img { height: 1.05em; width: auto; vertical-align: -2px; }

/* --- Woche --- */
.ks-cal-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.ks-cal-weekcol { border: 1px solid var(--kajinga-border, #e4e7ec); border-radius: 10px; overflow: hidden; display: flex; flex-direction: column; min-height: 260px; }
.ks-cal-weekcol.today { border-color: var(--kajinga-primary, #179afc); }
.ks-cal-weekhead { display: flex; align-items: center; gap: 5px; padding: 7px 8px; background: var(--kajinga-gray-50, #f9fafb); border-bottom: 1px solid var(--kajinga-border, #e4e7ec); font-size: 13px; }
.ks-cal-wd { font-weight: 600; color: var(--kajinga-gray-500, #667085); text-transform: uppercase; }
.ks-cal-wn { font-weight: 700; color: var(--kajinga-text, #101828); }
.ks-cal-weekcol.today .ks-cal-wn { color: var(--kajinga-primary, #179afc); }
.ks-cal-weekhead .ks-cal-add { margin-left: auto; }
.ks-cal-weekbody { display: flex; flex-direction: column; gap: 4px; padding: 6px; flex: 1; }
.ks-cal-week .ks-cal-event { font-size: 13px; }

/* --- Liste --- */
.ks-cal-list { display: flex; flex-direction: column; gap: 14px; }
.ks-cal-list-day { display: flex; flex-direction: column; gap: 4px; }
.ks-cal-list-date { font-weight: 700; font-size: 14px; color: var(--kajinga-gray-700, #344054); padding-bottom: 4px; border-bottom: 1px solid var(--kajinga-border, #e4e7ec); }
.ks-cal-list-row { display: flex; align-items: center; gap: 10px; padding: 8px 6px; border-radius: 8px; cursor: pointer; transition: background .12s ease; }
.ks-cal-list-row:hover { background: var(--kajinga-gray-50, #f9fafb); }
.ks-cal-list-time { font-weight: 700; font-size: 13.5px; color: var(--kajinga-gray-600, #475467); font-variant-numeric: tabular-nums; min-width: 42px; }
.ks-cal-list-title { font-size: 14px; color: var(--kajinga-text, #101828); }
.ks-cal-list-title img { height: 1.1em; width: auto; vertical-align: -2px; }
.ks-cal-empty { padding: 32px; text-align: center; color: var(--kajinga-gray-500, #667085); font-size: 14px; }

/* --- Dark Mode --- */
body.kajinga-dark-mode .ks-cal { background: var(--kajinga-card, #1a2233); border-color: var(--kajinga-border, #2a3446); }
body.kajinga-dark-mode .ks-cal-navbtn, body.kajinga-dark-mode .ks-cal-todaybtn, body.kajinga-dark-mode .ks-cal-search { background: var(--kajinga-card, #1a2233); color: var(--kajinga-text, #e4e9f2); border-color: var(--kajinga-border, #2a3446); }
body.kajinga-dark-mode .ks-cal-views { background: rgba(255,255,255,.06); }
body.kajinga-dark-mode .ks-cal-viewbtn.active { background: var(--kajinga-card, #1a2233); }
body.kajinga-dark-mode .ks-cal-cell { background: var(--kajinga-card, #1a2233); border-color: var(--kajinga-border, #2a3446); }
body.kajinga-dark-mode .ks-cal-cell.is-empty { background: rgba(255,255,255,.02); }
body.kajinga-dark-mode .ks-cal-weekhead { background: rgba(255,255,255,.04); }
body.kajinga-dark-mode .ks-cal-ev-title, body.kajinga-dark-mode .ks-cal-list-title, body.kajinga-dark-mode .ks-cal-wn { color: var(--kajinga-text, #e4e9f2); }
body.kajinga-dark-mode .ks-cal-add { background: rgba(255,255,255,.08); color: var(--kajinga-text, #e4e9f2); }

/* --- Responsive --- */
@media (max-width: 768px) {
    .ks-cal { padding: 12px; }
    .ks-cal-grid { grid-auto-rows: minmax(72px, auto); gap: 4px; }
    .ks-cal-cell { min-height: 72px; padding: 4px; }
    .ks-cal-ev-title { font-size: 0; } /* auf Mobile nur Zeit + Farbe zeigen, Titel im Detail */
    .ks-cal-ev-time { font-size: 11px; }
    .ks-cal-event { padding: 2px 4px; }
    .ks-cal-week { grid-template-columns: repeat(7, minmax(120px, 1fr)); overflow-x: auto; }
    .ks-cal-toolbar { gap: 8px; }
}

/* =========================================
   FELDER & NAVIGATION (3.10.5)
   ks_color_field · ks_media_field · ks_pagination
   (ks_copy_button nutzt ks-btn + Row-Action-Tooltip, kein eigenes CSS)
   ========================================= */

/* --- Farb-Feld --- */
.ks-color-field {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    position: relative;
}

/* allow_empty: „keine Farbe gesetzt" muss man sehen können — das Preview zeigt
   sonst den Ersatzwert, als hätte der Nutzer ihn gewählt. */
.ks-color-field--clearable.ks-is-empty .ks-color-preview {
    opacity: .3;
}

.ks-color-field--clearable.ks-is-empty::before {
    content: "";
    position: absolute;
    left: 2px;
    top: 50%;
    width: 36px;
    height: 2px;
    border-radius: 2px;
    background: var(--kajinga-danger, #dc2626);
    transform: rotate(-34deg);
    transform-origin: center;
    pointer-events: none;
}

/* Eckiger Rahmen um den (unsichtbaren) nativen Picker + das Preview-Element.
   Die Optik lebt hier, nicht im nativen <input type=color>. */
.ks-color-field .ks-color-swatch-wrap {
    position: relative;
    width: 40px;
    height: 32px;
    border: 1px solid var(--kajinga-border, #d5dde6);
    border-radius: var(--kajinga-radius-sm, 8px);
    overflow: hidden;
    cursor: pointer;
    flex: 0 0 auto;
    /* Dauer ausgeschrieben — Token-Falle, siehe Hinweis am Dateiende (v4.0.91). */
    transition: border-color .15s ease, box-shadow .15s ease;
}

/* Eigenes eckiges Farbfeld — zeigt die gewählte Farbe. */
.ks-color-field .ks-color-preview {
    position: absolute;
    inset: 3px;
    border-radius: 5px;
}

/* Nativer Picker: unsichtbar, aber volle Fläche und klickbar (öffnet den
   Farbwähler). appearance:none unterdrückt das native Chrome zusätzlich. */
.ks-color-field .ks-color-swatch {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    border: none;
    background: none;
    opacity: 0;
    cursor: pointer;
}

/* Hover/Fokus als eckiger Ring auf dem Rahmen (folgt dem Radius) — identisch
   zum Hex-Feld, damit beide Teile des Felds gleich reagieren. */
.ks-color-field .ks-color-swatch-wrap:hover,
.ks-color-field .ks-color-swatch-wrap:focus-within {
    border-color: var(--kajinga-primary, #179afc);
    box-shadow: 0 0 0 3px rgba(var(--kajinga-primary-rgb, 23, 154, 252), .15);
}

.ks-color-field .ks-color-hex {
    width: 92px;
    min-height: 32px;
    padding: 0 10px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 14.5px;
    color: var(--kajinga-text, #1f2937);
    border: 1px solid var(--kajinga-border, #d5dde6);
    border-radius: var(--kajinga-radius-sm, 8px);
    background: var(--kajinga-card-solid, #fff);
}

.ks-color-field .ks-color-hex:focus {
    outline: none;
    border-color: var(--kajinga-primary, #179afc);
    box-shadow: 0 0 0 3px rgba(var(--kajinga-primary-rgb, 23, 154, 252), .15);
}

/* --- Medien-Feld --- */
.ks-media-field {
    display: flex;
    flex-direction: column;
    gap: 10px;
    align-items: flex-start;
}

.ks-media-preview img {
    display: block;
    max-width: 220px;
    max-height: 160px;
    border: 1px solid var(--kajinga-border, #d5dde6);
    border-radius: var(--kajinga-radius-md, 10px);
    background: var(--kajinga-gray-50, #f8fafc);
}

.ks-media-buttons {
    display: flex;
    gap: 8px;
    align-items: center;
}

.ks-media-desc {
    margin: 0;
    font-size: 14px;
    color: var(--kajinga-text-muted, #64748b);
}

/* --- Pagination --- */
.ks-pagination {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.ks-pagination .ks-page-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    font-size: 14.5px;
    font-weight: 600;
    color: var(--kajinga-text, #1f2937);
    text-decoration: none;
    border: 1px solid var(--kajinga-border, #d5dde6);
    border-radius: var(--kajinga-radius-sm, 8px);
    background: var(--kajinga-card-solid, #fff);
    /* Dauer ausgeschrieben — Token-Falle, siehe Hinweis am Dateiende (v4.0.91). */
    transition: border-color .15s ease,
                background .15s ease;
}

.ks-pagination a.ks-page-link:hover {
    border-color: var(--kajinga-primary, #179afc);
    color: var(--kajinga-primary, #179afc);
}

.ks-pagination .ks-page-link.is-current {
    background: var(--kajinga-primary, #179afc);
    border-color: var(--kajinga-primary, #179afc);
    color: #fff;
    cursor: default;
}

.ks-pagination .ks-page-link.is-disabled {
    opacity: .4;
    pointer-events: none;
}

.ks-pagination .ks-page-ellipsis {
    padding: 0 4px;
    color: var(--kajinga-text-muted, #64748b);
    user-select: none;
}

/* --- Dark Mode --- */
body.kajinga-dark-mode .ks-color-field .ks-color-swatch,
body.kajinga-dark-mode .ks-color-field .ks-color-hex,
body.kajinga-dark-mode .ks-accordion__item {
    background: var(--kajinga-card, #1a2233);
    border-color: var(--kajinga-border, #2a3446);
}

body.kajinga-dark-mode .ks-accordion__item[open] > .ks-accordion__body {
    border-top-color: var(--kajinga-border, #2a3446);
}

body.kajinga-dark-mode .ks-pagination .ks-page-link {
    background: var(--kajinga-card, #1a2233);
    border-color: var(--kajinga-border, #2a3446);
    color: var(--kajinga-text, #e4e9f2);
}

body.kajinga-dark-mode .ks-pagination .ks-page-link.is-current {
    background: var(--kajinga-primary, #179afc);
    border-color: var(--kajinga-primary, #179afc);
    color: #fff;
}

body.kajinga-dark-mode .ks-media-preview img {
    border-color: var(--kajinga-border, #2a3446);
    background: rgba(255, 255, 255, .04);
}

/* Async-Panel (v4.0.11): Skeleton sofort, Inhalt per AJAX nachgeladen */
.ks-async-panel { position: relative; }
/* v4.0.14: sanfter Höhen-Floor gegen Kollaps/Sprung beim Skeleton→Inhalt-Swap.
   Panels mit viel Inhalt setzen zusätzlich min_height (inline, nach Laden gelöst). */
.ks-async-panel-body { display: block; min-height: 160px; }
/* v4.0.12: Ladezustand bei Panel-interner Navigation (Sortieren/Suchen) */
.ks-async-panel--loading .ks-async-panel-body {
    opacity: .55;
    pointer-events: none;
    transition: opacity .15s ease;
}
.ks-async-retry {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    font-size: 14.5px;
    color: var(--kajinga-danger, #d63638);
    background: none;
    border: none;
    cursor: pointer;
}
.ks-async-retry:hover { text-decoration: underline; }

/* =========================================
 * EINSTELLUNGS-ZEILEN (ks_settings_rows, v4.0.65)
 * Ersetzt WP <table class="form-table"> (netzwerkweit 29 Plugins).
 *
 * Grid statt Tabelle: Die WP-Variante braucht unter 782px einen CSS-Hack,
 * der Zellen auf display:block umschaltet — ein Grid stapelt von selbst.
 *
 * Es kommen ausschliesslich die semantischen Tokens vor (text/text-muted/
 * border): sie benennen die ROLLE, nicht den Farbwert, und der Dark Mode
 * dreht sie mit. Deshalb braucht dieser Block keinen eigenen Dark-Abschnitt.
 * (Nachgemessen 2026-07-30: --kajinga-gray-50..900 werden im Dark-Block
 * ebenfalls umdefiniert. Die Palette-Grays waeren hier also nicht kaputt,
 * nur unpassend — sie sagen "hellgrau 200" statt "Rand".)
 * ========================================= */

.ks-settings-rows {
    --ks-settings-label-w: 220px;
    /* Abstand gehoert IN die Komponente (Konvention v4.0.49): margin-bottom,
       kein margin-top, und am Ende einer ks-card keiner. */
    margin-bottom: 20px;
}
.ks-settings-rows:last-child { margin-bottom: 0; }

.ks-settings-row {
    display: grid;
    grid-template-columns: var(--ks-settings-label-w) minmax(0, 1fr);
    gap: 4px 24px;
    align-items: start;
    padding: 14px 0;
    border-bottom: 1px solid var(--kajinga-border, #e2e8f0);
}
.ks-settings-row:last-child { border-bottom: none; padding-bottom: 0; }
.ks-settings-row:first-child { padding-top: 0; }

/* Bedingt sichtbare Zeile (visible_when, v4.1.29). Die Regel ist PFLICHT, kein
   Feinschliff: `display: grid` steht in der Zeile darueber und schlaegt das
   native `[hidden]` des Browsers — ohne sie bliebe eine versteckte Zeile
   sichtbar, und zwar lautlos. Dieselbe Falle wie bei `.ks-count[hidden]`. */
.ks-settings-row[hidden] { display: none; }

.ks-settings-label {
    font-weight: 600;
    color: var(--kajinga-text, #1e293b);
    /* 8px richten die Beschriftung optisch auf die erste Zeile des Feldes aus
       (Input-Innenabstand), ohne sie an dessen Hoehe zu koppeln. */
    padding-top: 8px;
    line-height: 1.4;
}
.ks-settings-label label { cursor: pointer; }

.ks-settings-control { min-width: 0; }

/* Ein Eingabefeld soll durch seine Breite andeuten, wie viel erwartet wird —
   ohne Deckel liefe das Feld fuer einen Absendernamen ueber die volle Spalte
   (~1100px auf grossen Schirmen). WordPress loest das mit .regular-text (25em).
   Der Deckel gilt bewusst NUR fuer Felder: 'content' bleibt unbeschraenkt,
   damit Tabellen, Karten oder Diagramme dort die ganze Breite nutzen koennen. */
.ks-settings-control .ks-input { max-width: 480px; }
.ks-settings-control textarea.ks-input { max-width: 640px; }

/* Das durchgereichte Feld bringt seinen eigenen Abstand mit — in der Zeile
   waere er doppelt, weil die Zeile bereits padding hat. */
.ks-settings-control .ks-form-group { margin-bottom: 0; }
.ks-settings-control .ks-form-hint:last-child,
.ks-settings-control .ks-form-error:last-child { margin-bottom: 0; }

/* Feld + Begleiter in einer Zeile (ks_form_field 'after', v4.1.23) — der
   „Verbindung testen"-Knopf, eine Status-Anzeige, eine Einheit hinter der Zahl.
   68 von 449 Eingabezellen im Netz brauchen das.

   Steht bewusst HIER und nicht in token-utilities.tpl, wo das uebrige
   Formular-CSS liegt: Jene Datei ist GENERIERT und wird nur neu gebaut, wenn
   design-tokens.css fehlt oder jemand die Einstellungen speichert — eine Regel
   dort erreicht die meisten der 1200+ Sites nie. components.css wird statisch
   ausgeliefert.

   `align-items: center` statt stretch, damit ein Knopf neben einem einzeiligen
   Feld nicht auf dessen Hoehe gezogen wird; `flex-wrap`, damit lange Begleiter
   auf schmalen Schirmen umbrechen statt das Feld zu quetschen. Der
   480px-Deckel oben greift weiter, weil er am .ks-input haengt. */
.ks-form-control-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}
.ks-form-control-row > .ks-input { flex: 1 1 auto; min-width: 0; }
/* Einheit hinter einem Zahlenfeld („px", „%") — kein eigenes Bedienelement,
   deshalb gedämpft und nicht anklickbar. */
.ks-form-unit { color: var(--kajinga-text-muted, #64748b); font-size: 13px; }
.ks-form-control-row > input[type="number"] { flex: 0 0 auto; width: 120px; }

/* Auswahlknöpfe (ks_form_field type radio, v4.1.27). Untereinander ist der
   Vorgabefall — er bleibt bei langen Beschriftungen lesbar; `inline` stellt
   sie nebeneinander, was bei zwei kurzen Möglichkeiten kompakter ist. */
.ks-form-radios { display: flex; flex-direction: column; gap: 6px; }
.ks-form-radios--inline { flex-direction: row; flex-wrap: wrap; gap: 6px 18px; }
.ks-form-radio { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; }
.ks-form-radio input { margin: 0; }

.ks-settings-section {
    font-size: 14px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--kajinga-text-muted, #64748b);
    padding: 22px 0 6px;
    border-bottom: 1px solid var(--kajinga-border, #e2e8f0);
}
/* Steht ein Abschnitt ganz oben, soll er nicht vom Karten-Innenabstand abheben */
.ks-settings-section:first-child { padding-top: 0; }

@media screen and (max-width: 782px) {
    .ks-settings-row {
        grid-template-columns: minmax(0, 1fr);
        gap: 6px;
    }
    .ks-settings-label { padding-top: 0; }
}

/* =========================================
 * FORTSCHRITT (ks_progress, v4.0.66)
 *
 * Die innere .ks-progress-bar ist die BESTEHENDE Utility aus
 * token-utilities.tpl und wird hier NICHT umdefiniert — sonst braechen die
 * 8 vorhandenen Verwendungen und die Overrides in magic-products/magic-funnel.
 * Groesse und Farbe haengen deshalb an Modifiern auf dem Wrapper.
 *
 * Fuellfarben kommen aus den *-rgb-Tokens, nicht aus --kajinga-success/warning:
 * die tragen im Light die blassen Notice-Randfarben (#c3e6cb, #ffeaa7) und
 * waeren auf grauer Spur kaum zu sehen. Die -rgb-Werte sind in beiden Modi
 * kraeftig (nachgemessen: 76,175,80 hell → 74,222,128 dunkel).
 * ========================================= */

.ks-progress { margin-bottom: 16px; }
.ks-progress:last-child { margin-bottom: 0; }

.ks-progress-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 6px;
    font-size: 14.5px;
    line-height: 1.4;
}
.ks-progress-label {
    font-weight: 600;
    color: var(--kajinga-text, #1e293b);
}
.ks-progress-value {
    color: var(--kajinga-text-muted, #64748b);
    /* Gleiche Ziffernbreite wie beim Verbrauchs-Zaehler (4.0.54): ohne sie
       springt der Wert beim Hochzaehlen von 9 auf 10 sichtbar. */
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Die drei realen Groessen aus dem Bestand: 5px (magic-products),
   8px (Default/Utility), 12px (magic-funnel-Editor). */
.ks-progress--sm .ks-progress-bar { height: 5px; }
.ks-progress--lg .ks-progress-bar { height: 12px; }

/* DARK MODE: DIE SPUR IST HIER DER HEBEL — UND NUR HIER (v4.1.39)
 *
 * Gemessen auf dem Styleguide: Spur `--kajinga-gray-200`, im Dark #6e6e6e (L 0,156).
 * Gegen die hellen Dark-Füllungen ergab das primary 2,02 · success 2,93 · warning 3,05 ·
 * danger 1,84 — WCAG 1.4.11 verlangt 3:1 für die Grenze zwischen Füllung und Spur.
 * Mit #4a4a4a (L 0,069) sind es 3,2 bis 5,8. Die Füllfarben bleiben unangetastet.
 *
 * IM LIGHT MODE GEHT DAS NICHT, und das korrigiert die frühere Annahme in dieser
 * Datei: Dort ist die Spur #e1e4e8 (L 0,773) und die Füllung HELLER als der nötige
 * Grenzwert. success (L 0,328) bräuchte eine Spur mit L ≥ 1,08 — heller als Weiß.
 * Rechnerisch unmöglich; dort muss die Füllung dunkler werden. Steht aus, weil es die
 * Statusfarben netzwerkweit sichtbar verändert.
 *
 * Der Selektor trägt `.ks-progress`, damit die nackte Utility `.ks-progress-bar`
 * unberührt bleibt — sie hat acht Verwendungen ausserhalb der Komponente. Ein per
 * `track`-Argument gesetzter Inline-Style gewinnt weiterhin. */
body.kajinga-dark-mode .ks-progress .ks-progress-bar {
    background: #4a4a4a;
}

.ks-progress--success .ks-progress-bar > * { background: rgb(var(--kajinga-success-rgb, 76 175 80)); }
.ks-progress--warning .ks-progress-bar > * { background: rgb(var(--kajinga-warning-rgb, 255 193 7)); }
.ks-progress--danger  .ks-progress-bar > * { background: rgb(var(--kajinga-error-rgb, 220 53 69)); }

/* LIGHT MODE: SUCCESS UND WARNING DUNKLER (v4.1.40)
 *
 * Nachtrag zu 4.1.39, das nur die Dark-Spur behoben hat. Im Light Mode ist die Spur
 * #e1e4e8 und die Füllung HELLER als der für 3:1 nötige Grenzwert (L ≤ 0,224) —
 * `success` #4caf50 kam auf 2,18, `warning` #ffc107 auf 1,28. Über die Spur ist das
 * nicht zu lösen: `success` bräuchte eine Spur mit L ≥ 1,08, heller als Weiß.
 * Deshalb hier die Füllung. Gemessen gegen #e1e4e8: 3,23 und 3,32.
 *
 * `primary` (4,05) und `danger` (3,55) erfüllen die Anforderung ohne Eingriff.
 *
 * ⚠️ `body:not(.kajinga-dark-mode)` ist PFLICHT, kein Zierrat. Die `-rgb`-Tokens
 * tragen im Dark Mode ANDERE Werte (success 74 222 128, warning 251 191 36) — helle
 * Füllungen auf der dunklen Spur, die dort seit 4.1.39 bei 5,09 und 5,31 liegen. Wer
 * diese beiden Farben unbedingt setzt, ersetzt korrekte Dark-Werte durch dunkles Grün
 * auf dunkler Spur und macht 4.1.39 zunichte.
 *
 * Literale statt Tokens: Die `-rgb`-Tokens gelten netzwerkweit auch für Badges,
 * Notices und Icons; sie zu verschieben, um einen Balken zu retten, wäre die falsche
 * Ebene. Der Wert steht deshalb nur dort, wo er gebraucht wird. */
body:not(.kajinga-dark-mode) .ks-progress--success .ks-progress-bar > * { background: #388e3c; }
body:not(.kajinga-dark-mode) .ks-progress--warning .ks-progress-bar > * { background: #b26a00; }

/* =========================================
 * DRUCK-RÜCKMELDUNG (v4.0.90)
 *
 * Vorher gab es netzwerkweit elf `:active`-Regeln, neun davon auf Buttons —
 * und die eine im `.ks-btn` nahm bloß den Hover-Lift zurück. Beim Drücken
 * passierte also nichts: Die Oberfläche reagierte auf Nähe (Hover), aber nicht
 * auf Berührung, und die erste sichtbare Antwort kam mit dem Seitenwechsel.
 *
 * DREI ABSTUFUNGEN, nach Größe und Rolle getrennt — eine einheitliche
 * Skalierung wäre auf einer Kachel zu viel und in einer Liste unruhig:
 *
 *   Controls (Knöpfe, Chips, Reiter)   scale(.97)
 *   Flächen (Kacheln, Karten)          scale(.985) + Lift zurücknehmen
 *   Listenzeilen                       keine Bewegung, kräftigere Fläche
 *
 * WARUM DIESER BLOCK HIER STEHT UND NICHT IN refresh.css: components.css lädt
 * NACH refresh.css. Ein `:active` dort (0,2,0) verlöre gegen jedes `:hover`
 * von hier (ebenfalls 0,2,0) — und beim Drücken sind beide Zustände aktiv.
 * Die Regel muss also hinter der Hover-Regel stehen, die sie überstimmt.
 * Grundregel beim Ergänzen: dieselbe Datei, dieselbe oder höhere Spezifität.
 *
 * Die kurze Übergangsdauer ist Absicht — hinein sofort, heraus ausklingend.
 *
 * SPEZIFITÄTS-FALLE (nachgetragen v4.0.93, nachdem sie zugeschlagen hat):
 * Beim Drücken sind `:hover` UND `:active` aktiv. Trägt die Hover-Regel eines
 * Elements MEHR Spezifität als die passende Active-Regel, gewinnt der Hover —
 * die Rückmeldung bleibt unsichtbar. So geschehen beim inversen Hero-Knopf
 * (`.ks-btn.ks-btn-inverse:hover`, 0,3,0 gegen `.ks-btn:active`, 0,2,0): dem
 * wichtigsten Knopf jeder Seite fehlte der Effekt, während alle anderen ihn
 * hatten. Wer eine `:hover`-Regel mit erhöhter Spezifität schreibt, liefert
 * das `:active`-Gegenstück auf derselben Höhe mit.
 * ========================================= */

/* --- Controls mit Beschriftung --- */
.ks-chip:active,
.ks-tab-nav-link:active,
.ks-dropdown-toggle:active,
.ks-th-sortable:active,
.ks-cal-todaybtn:active,
.ks-cal-viewbtn:active,
.ks-pagination a.ks-page-link:active {
    transform: scale(0.97);
    /* Fläche mitnehmen — Begründung im .ks-btn:active-Block in refresh.css:
       Skalierung allein ist zu schwach, um als Rückmeldung durchzukommen. */
    filter: brightness(0.94);
    transition-duration: 0.06s;
}

/* --- Kleine Icon-Knöpfe: stärker, damit man es überhaupt sieht (v4.0.93) ---
 *
 * Prozente sind relativ, der Eindruck ist es nicht: 3 % von einem 200 px
 * breiten Knopf sind 6 px und deutlich sichtbar — dieselben 3 % von einem
 * 32-px-Kästchen sind EIN Pixel und damit praktisch nichts. Die Rückmeldung
 * muss aber überall gleich stark ankommen, nicht überall gleich gerechnet
 * sein. Deshalb 8 % für alles, was nur ein Icon trägt. */
.ks-card-collapse:active,
.ks-page-back:active,
.ks-cal-navbtn:active,
.ks-cal-add:active,
.ks-row-actions .ks-row-action.ks-btn:active {
    transform: scale(0.92);
    filter: brightness(0.94);
    transition-duration: 0.06s;
}

/* Im Hero verschiebt sich der Zurück-Pfeil beim Überfahren um 2px nach links
 * (`.ks-hero .ks-page-back:hover`, 0,3,0). Diese Regel muss dieselbe Höhe
 * erreichen, sonst gewinnt der Hover-Zustand beim Drücken — derselbe Fehler
 * wie beim inversen Knopf (siehe core.css). Der Versatz bleibt erhalten,
 * sonst spränge der Pfeil beim Drücken zurück nach rechts. */
.ks-hero .ks-page-back:active {
    transform: translateX(-2px) scale(0.92);
    transition-duration: 0.06s;
}

/* --- Flächen: Lift zurücknehmen und leicht einsinken ---
   Nur verlinkte Kacheln. Den Hover-Lift trägt auch die reine Anzeige, ein
   Einsinken behauptet dagegen ein Ziel — das darf nicht ins Leere zeigen. */
a.ks-widget-stat:active,
a.ks-stat-card--link:active,
a.ks-widget:active,
.ks-widget > a.ks-widget-cover:active {
    transform: translateY(0) scale(0.985);
    transition-duration: 0.06s;
}

/* --- Listenzeilen: Fläche statt Bewegung ---
   Ein Eintrag, der beim Drücken schrumpft, lässt die ganze Liste zappeln.
   Die Rückmeldung kommt deshalb über den Hintergrund. */
.ks-dropdown-item:active,
.ks-tab-nav-sublink:active,
.ks-cal-list-row:active,
.ks-cal-event:active {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.16);
    transition-duration: 0.06s;
}


/* =========================================
 * MOTION-TOKENS: die `all`-Falle (Rückblick, behoben in v4.0.92)
 *
 * Die vier Transitions in dieser Datei sind mit ausgeschriebener Dauer notiert
 * statt mit `var(--kajinga-transition-fast)`. Das ist heute nicht mehr nötig —
 * es bleibt so, weil es eindeutig ist, und als Anker für diese Erklärung.
 *
 * WAS DER FEHLER WAR: Die Motion-Tokens existierten in zwei widersprüchlichen
 * Fassungen — `:root { 0.2s ease }` aus dem DesignTokenHelper und
 * `body { all 0.15s ease }` aus refresh.css. Für jedes Element in <body>
 * gewinnt der nähere Vorfahre, also die Fassung MIT `all`. Wer das Token
 * hinter eine Eigenschaft schrieb, erzeugte damit
 *
 *     transition: transform all 0.15s ease;      <-- ungültig
 *
 * und der Browser verwarf die komplette Deklaration. Der Übergang fand nicht
 * verkürzt statt, sondern GAR NICHT — ohne Fehlermeldung, ohne dass im
 * Quelltext etwas falsch aussah. Als GANZER Wert war dieselbe Variable
 * gültig (`transition: var(--kajinga-transition-fast)`), weshalb es über Jahre
 * niemandem auffiel.
 *
 * Gemessen am Schalter dieser Datei: `transitionDuration` = "0s". Knopf und
 * Fläche sprangen. Aufgefallen erst, als die Bewegungskurve aus 4.0.91 dort
 * eingesetzt werden sollte und nicht wirkte.
 *
 * REICHWEITE: 232 Stellen in 50 Dateien über rund 25 Plugins nutzten die
 * Teilwert-Schreibweise, dazu 96 Stellen `transition: all var(--kajinga-
 * transition)` (ergab „all all 0.2s ease", ebenfalls ungültig). Alle waren
 * seit jeher wirkungslos.
 *
 * BEHOBEN mit einer Zeile in refresh.css: beide Tokens tragen jetzt reine
 * Dauer + Kurve, ohne `all`. Die Begründung steht dort ausführlich — und dort
 * ist auch der Ort, an dem ein Rückbau Schaden anrichten würde, nicht hier.
 * ========================================= */

/* ==========================================================================
   ks_term_picker() — Begriffe zuweisen (Lightbox mit Chips)
   Ruhezustand sind Chips plus ein Knopf; der Dialog zeigt je Gruppe eine
   Spalte. Ersetzt drei handgebaute Fassungen derselben Sache.
   ========================================================================== */
.ks-term-picker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.ks-term-picker-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    min-width: 0;
}
.ks-term-picker-leer {
    color: var(--kajinga-text-muted, #64748b);
    font-size: 13px;
}
.ks-term-picker-open { flex: 0 0 auto; }

/* Im Dialog: das bereits Gewählte über den Spalten, damit die Frage
   „was ist zugeordnet?" beantwortet ist, bevor man scrollt. */
.ks-term-picker-auswahl {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    min-height: 28px;
    padding-bottom: 12px;
    margin-bottom: 12px;
    border-bottom: 1px solid var(--kajinga-border, #e2e8f0);
}
.ks-term-picker-chip.is-removable {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 0;
    cursor: pointer;
}

.ks-term-picker-spalten {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 20px;
}
.ks-term-picker-spalte-titel {
    margin: 0 0 8px;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--kajinga-text-muted, #64748b);
}
.ks-term-picker-suche { margin-bottom: 8px; }
/* Begrenzt, damit eine lange Liste den Dialog nicht aus dem Bild schiebt —
   die Spalten scrollen einzeln, der Dialog selbst bleibt stehen. */
.ks-term-picker-liste {
    max-height: 260px;
    overflow-y: auto;
    /* `overflow` erzeugt einen Beschneidungsrahmen: Ohne dieses Polster
       schneidet er den Fokus-/Auswahlrand des ersten Ankreuzfelds an der
       linken Kante ab. Rechts dieselbe Breite, damit die Liste mittig bleibt. */
    padding: 2px 4px;
}
.ks-term-picker-eintrag {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 2px;
    cursor: pointer;
}

.ks-term-picker-verwalten {
    margin: 16px 0 0;
    padding-top: 12px;
    border-top: 1px solid var(--kajinga-border, #e2e8f0);
    font-size: 13px;
}


/* ==========================================================================
   ks_funnel_flow — Konversions-Fluss „Strom" (v4.2.22)
   Aus kajinga-funnel (admin.css ab Zeile 321) hierher verschoben. Ein Funnel ist
   ein Rohr, das sich verengt: Der Verbinder ist ein Band, dessen rechte Höhe die
   Durchlassrate IST. Die Form kommt aus dem SVG-Pfad in ComponentHelper::funnel_flow().
   --ks-flow-th MUSS zur Bandhöhe im PHP passen ($bh = 132). Einheitenlos, damit ein
   Konsument mit iframe-Vorschau seinen Maßstab rechnen kann (--ks-flow-nw / 1280).
   ========================================================================== */
.ks-flow, .ks-flow * { box-sizing: border-box; }
.ks-flow { --ks-flow-nw: 218; --ks-flow-th: 132; }

.ks-flow-kpi {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    margin: 0 0 20px;
    border: 1px solid var(--kajinga-border, #e2e8f0);
    border-radius: 10px;
    background: var(--kajinga-gray-50, #f8fafc);
    overflow: hidden;
}
.ks-flow-kpi > div { padding: 13px 18px; border-left: 1px solid var(--kajinga-border, #e2e8f0); }
.ks-flow-kpi > div:first-child { border-left: 0; }
.ks-flow-kpi dt { margin: 0 0 4px; font-size: 11px; font-weight: 650; letter-spacing: .075em; text-transform: uppercase; color: var(--kajinga-text-muted, #64748b); }
.ks-flow-kpi dd { margin: 0; font-family: var(--kajinga-font-display, var(--kajinga-font, inherit)); font-size: 24px; font-weight: 760; line-height: 1.05; letter-spacing: -.03em; color: var(--kajinga-text, #1e1e1e); font-variant-numeric: tabular-nums; }
.ks-flow-kpi-item.is-green dd { color: #16a34a; }
body.kajinga-dark-mode .ks-flow-kpi-item.is-green dd { color: #4ade80; }
@media (max-width: 782px) {
    .ks-flow-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .ks-flow-kpi > div:nth-child(3) { border-left: 0; }
    .ks-flow-kpi > div:nth-child(n+3) { border-top: 1px solid var(--kajinga-border, #e2e8f0); }
}

.ks-flow-scroll { overflow-x: auto; padding: 2px 2px 14px; }
.ks-flow-track { display: flex; align-items: flex-start; min-width: min-content; }
.ks-flow-node { flex: 0 0 calc(var(--ks-flow-nw) * 1px); }
.ks-flow-card {
    display: flex; flex-direction: column; overflow: hidden;
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-border, #e2e8f0);
    border-radius: 12px;
    box-shadow: var(--kajinga-shadow-sm, 0 1px 3px rgba(0,0,0,.1));
    transition: transform .42s cubic-bezier(.22,1,.36,1), box-shadow .42s cubic-bezier(.22,1,.36,1);
}
.ks-flow-node:hover .ks-flow-card { transform: translateY(-3px); box-shadow: 0 14px 32px -14px rgba(16,24,40,.3), 0 1px 3px rgba(16,24,40,.08); }
body.kajinga-dark-mode .ks-flow-node:hover .ks-flow-card { box-shadow: 0 16px 34px -14px rgba(0,0,0,.65); }

.ks-flow-face { position: relative; height: calc(var(--ks-flow-th) * 1px); border-bottom: 1px solid var(--kajinga-border, #e2e8f0); overflow: hidden; }
.ks-flow-cap { position: absolute; top: 0; left: 0; right: 0; height: 3px; z-index: 3; }
.ks-flow-tag { position: absolute; left: 8px; bottom: 8px; z-index: 2; padding: 5px 7px; border-radius: 5px; font-size: 9.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; line-height: 1; color: #fff; opacity: .92; pointer-events: none; }

.ks-flow-body { display: flex; flex-direction: column; flex: 1; padding: 11px 14px 14px; }
.ks-flow-name { font-size: 14px; font-weight: 640; line-height: 1.3; letter-spacing: -.006em; color: var(--kajinga-text, #1e1e1e); min-height: 2.6em; }
.ks-flow-figs { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 14px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--kajinga-border, #e2e8f0); }
.ks-flow-fig b { display: block; font-family: var(--kajinga-font-display, var(--kajinga-font, inherit)); font-size: 19px; font-weight: 760; line-height: 1; letter-spacing: -.028em; color: var(--kajinga-text, #1e1e1e); font-variant-numeric: tabular-nums; }
.ks-flow-fig span { display: block; margin-top: 3px; font-size: 10.5px; font-weight: 650; letter-spacing: .07em; text-transform: uppercase; color: var(--kajinga-text-muted, #64748b); }
.ks-flow-fig.is-sub b { font-size: 14.5px; color: var(--kajinga-text-muted, #64748b); }
.ks-flow-fig.is-green b { color: #16a34a; }
body.kajinga-dark-mode .ks-flow-fig.is-green b { color: #4ade80; }
.ks-flow-actions { margin-top: 12px; }

.ks-flow-link { flex: 0 0 96px; position: relative; height: calc(var(--ks-flow-th) * 1px); display: grid; place-items: center; align-self: flex-start; }
.ks-flow-band { position: absolute; inset: 0; width: 100%; height: 100%; }
.ks-flow-rate { position: relative; z-index: 2; text-align: center; white-space: nowrap; padding: 6px 10px; border-radius: 999px; background: var(--kajinga-card-solid, #fff); border: 1px solid var(--kajinga-border, #e2e8f0); box-shadow: var(--kajinga-shadow-sm, 0 1px 3px rgba(0,0,0,.1)); }
.ks-flow-rate b { display: block; font-family: var(--kajinga-font-display, var(--kajinga-font, inherit)); font-size: 15px; font-weight: 770; line-height: 1.1; letter-spacing: -.03em; color: var(--kajinga-text, #1e1e1e); font-variant-numeric: tabular-nums; }
.ks-flow-rate span { display: block; margin-top: 1px; font-size: 9px; font-weight: 620; line-height: 1.25; letter-spacing: .05em; text-transform: uppercase; color: var(--kajinga-text-muted, #64748b); }

@media (prefers-reduced-motion: reduce) {
    .ks-flow-card { transition: none; }
    .ks-flow-node:hover .ks-flow-card { transform: none; }
}

/* ==========================================================================
   ks_term_area() — gemeinsame Huelle eines Begriffs-Bereichs
   Titel, optionaler Hinweis, Pillen-Reihe, darunter genau ein Panel.
   Geteilt wird der Rahmen, nicht die Darstellung der Zeilen: Auf derselben
   Seite treffen Begriffe mit sehr verschiedenen Faehigkeiten aufeinander.
   ========================================================================== */
.ks-term-area + .ks-term-area { margin-top: var(--kajinga-space-4, 20px); }

.ks-term-area-titel {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 4px;
    font-size: 16px;
}
.ks-term-area-hinweis { margin: 0 0 14px; }

.ks-term-area-pillen {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 16px;
}
.ks-term-area-pille {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid var(--kajinga-border, #e2e8f0);
    border-radius: 999px;
    background: transparent;
    color: var(--kajinga-text, #1e293b);
    cursor: pointer;
    font-size: 13px;
    line-height: 1.4;
}
.ks-term-area-pille:hover { border-color: var(--kajinga-primary, #2271b1); }
.ks-term-area-pille.is-active {
    border-color: var(--kajinga-primary, #2271b1);
    background: var(--kajinga-primary-soft, #eff6ff);
    font-weight: 600;
}

/* Anlege-Zeile im Auswahl-Dialog (v4.2.24) — abgesetzter Streifen unter der
   Liste, angeglichen an ultra-seo (.useo-terms-modal__anlegen) und die dortige
   Vorlage kajinga-media: eigene Flaeche statt bloss einer Trennlinie, damit die
   Eingabe nicht wie ein weiterer Listeneintrag wirkt. */
.ks-term-picker-neu {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 10px;
    padding: 8px 10px;
    border-top: 1px solid var(--kajinga-gray-200, #e2e8f0);
    background: var(--kajinga-gray-50, #f8fafc);
}
.ks-term-picker-neu .ks-input { flex: 1 1 auto; min-width: 0; }
.ks-term-picker-neu .ks-btn { flex: 0 0 auto; }
body.kajinga-dark-mode .ks-term-picker-neu { background: #23262b; }
