/**
 * Kajinga UI — core.css (Stufe 1, lädt global im Admin)
 *
 * Styles NUR für die ks-Runtime: Toasts, Command-Palette, Confirm-Dialog,
 * Busy-State, Swap-Animation, Icon-Alignment. Ausschließlich Token-basiert
 * (--kajinga-*, geliefert von kajinga-styler). Dark Mode via
 * body.kajinga-dark-mode-Overrides am Ende.
 *
 * Basis-Komponenten-CSS (.ks-btn, .ks-card, .ks-modal, …) liefert der Styler.
 */

/* =========================================
 * SCHRIFTEN (festgelegt 2026-07-18: Sora = Display, Inter = Text)
 * Lokal gehostet (DSGVO, kein CDN), variable Fonts, Latin-Subset.
 * Tokens --kajinga-font / --kajinga-font-display liefert design-tokens.css.
 * ========================================= */

/* Geist ist seit dem Font-Entscheid (2026-07-20) die EINZIGE Hausschrift —
   für Text und Display. Die Preview-Kandidaten Sora, Clash Display und Inter
   wurden samt woff2 entfernt. Fallback ist der System-Stack. */
@font-face {
    font-family: 'Geist';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url(../fonts/geist.woff2) format('woff2');
}

/* =========================================
 * ICONS (Inline-SVG-Alignment)
 * ========================================= */

.ks-icon {
    display: inline-block;
    vertical-align: -0.2em;
    flex-shrink: 0;
}

/* Farb-Utilities (v4.0.53) — fuer Icons UND Text.
 *
 * ks_icon() rendert SVG mit stroke="currentColor", eine Textfarbe faerbt das
 * Icon also automatisch mit. Deshalb heissen die Klassen .ks-text-* und nicht
 * .ks-icon-*: dieselbe Klasse traegt Icon, Label und beides zusammen.
 *
 * Ersetzt `style="color: var(--kajinga-danger)"` direkt am Element — davon
 * standen allein in kompass/crm/elementor rund 60 Stueck in den Views, jedes
 * eine eigene Fundstelle beim naechsten Farbwechsel.
 *
 * KEINE Groessen-Klassen: die Groesse gehoert ins ks_icon()-Argument
 * `['size' => 14|16|20|24]` (siehe Konvention in claude.md). Eine
 * .ks-icon-sm-Klasse waere die zweite Wahrheit daneben. */
.ks-text-primary { color: var(--kajinga-primary, #2271b1); }
.ks-text-danger  { color: var(--kajinga-danger, #d63638); }
.ks-text-muted   { color: var(--kajinga-text-muted, #646970); }
/* ACHTUNG, hier NICHT var(--kajinga-success)/(--kajinga-warning) einsetzen:
 * die beiden Tokens sind FLAECHENfarben (#c3e6cb bzw. #ffeaa7) und als Text auf
 * Weiss unlesbar (Kontrast rund 1,4:1). Textfarben gibt es dafuer nicht als Token,
 * deshalb die -text-Variante mit Literal-Fallback — dasselbe Muster nutzt schon
 * components.css bei .ks-form-success. Die Werte entsprechen den Textfarben der
 * Badges (.ks-badge-success #155724, .ks-badge-pending #856404), nur leicht
 * aufgehellt, weil sie hier freistehend auf Weiss sitzen statt auf Pastellflaeche. */
.ks-text-success { color: var(--kajinga-success-text, #1a7f37); }
.ks-text-warning { color: var(--kajinga-warning-text, #8a6100); }

body.kajinga-dark-mode .ks-text-success { color: #4ade80; }
body.kajinga-dark-mode .ks-text-warning { color: #fbbf24; }
body.kajinga-dark-mode .ks-text-danger  { color: #f87171; }

.ks-rotate-180 {
    display: inline-flex;
    transform: rotate(180deg);
    transition: transform 0.2s ease;
}

[x-cloak] {
    display: none !important;
}

/* =========================================
 * TOASTS
 * ========================================= */

.ks-toasts {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 100200;
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: min(380px, calc(100vw - 48px));
    pointer-events: none;
}

.ks-toast {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
    background: var(--kajinga-card-solid, #fff);
    color: var(--kajinga-text, #1d2327);
    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));
    font-size: 14.5px;
    line-height: 1.45;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.2s ease, transform 0.2s ease;
    pointer-events: auto;
    border-left: 3px solid var(--kajinga-info, #2271b1);
}

.ks-toast--in {
    opacity: 1;
    transform: translateY(0);
}

.ks-toast--out {
    opacity: 0;
    transform: translateY(4px);
}

.ks-toast--success { border-left-color: var(--kajinga-success, #00a32a); }
.ks-toast--error   { border-left-color: var(--kajinga-danger, #d63638); }
.ks-toast--warning { border-left-color: var(--kajinga-warning, #dba617); }

.ks-toast-icon {
    display: inline-flex;
    margin-top: 1px;
}

.ks-toast--success .ks-toast-icon { color: var(--kajinga-success-text, #1a7f37); }
.ks-toast--error .ks-toast-icon   { color: var(--kajinga-danger, #d63638); }
.ks-toast--warning .ks-toast-icon { color: var(--kajinga-warning-text, #8a6100); }
.ks-toast--info .ks-toast-icon    { color: var(--kajinga-info, #2271b1); }

.ks-toast-msg {
    flex: 1;
    word-break: break-word;
}

/* Rueckgaengig-Knopf: eigene Zeile unter der Nachricht, damit er auch bei
   langem Text nicht neben ihr eingequetscht wird. */
.ks-toast-action {
    /* Block-Level statt inline: sonst fliesst der Knopf hinter dem letzten
       Wort weiter, statt eine eigene Zeile zu bekommen. */
    display: flex;
    align-items: center;
    width: fit-content;
    margin-top: 10px;
    padding: 4px 10px;
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.09);
    border: 1px solid rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.28);
    border-radius: var(--kajinga-radius-xs, 4px);
    color: var(--kajinga-primary, #2271b1);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.3;
    cursor: pointer;
}

.ks-toast-action:hover,
.ks-toast-action:focus-visible {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.16);
    color: var(--kajinga-primary, #2271b1);
}

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

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

/* =========================================
 * MODAL-ERGÄNZUNGEN (Basis-CSS im Styler)
 * ========================================= */

body.ks-modal-open {
    overflow: hidden;
}

/* Die Modal-Hülle MUSS den ganzen Viewport decken — das ist eine Invariante
   der Komponente, keine Gestaltungsfrage. Views legen ihre Modals irgendwo
   im .wrap ab, und ein Größen-Deckel des Aufrufers auf dessen Kinder trifft
   sie mit: ULTRA Social 2.12.4 setzt
   `.ultra-social-settings > :not(.uh-hero):not(.us-nav):not(.ultra-modal-overlay) { max-width: 1200px }`
   (Spezifität 0,4,0 — schlägt jeden vertretbaren Selektor hier, daher !important).
   Der Abdunkler endete dadurch mitten im Bild, der Rest der Seite blieb hell
   und anklickbar. Der Fehler ist breitenabhängig und fällt deshalb lange nicht
   auf: gemessen 0 px Fehlbetrag bei 1000 px Viewport, 200 px bei 1400, 500 px
   bei 1700 — unterhalb des Deckelwerts ist gar nichts zu sehen.
   Die Größe des sichtbaren Dialogs steuert `.ks-modal-content` (siehe unten),
   nie die Hülle. */
.ks-modal {
    max-width: none !important;
    max-height: none !important;
}

/* Einblendung: Abdunkler faded, Dialog steigt 8px auf.
 *
 * Warum `@starting-style` und nicht der naheliegende Weg über opacity allein:
 * `.ks-modal` schaltet von `display: none` auf `block`, und dazwischen gibt es
 * keinen Frame — eine gewöhnliche Transition feuert schlicht nicht. Der andere
 * verbreitete Ausweg wäre, display durch `visibility` zu ersetzen; das ist hier
 * bewusst NICHT gemacht, weil es Bestandscode betrifft: jQuerys `:visible`
 * meldet ein `visibility: hidden`-Element als sichtbar, und netzwerkweit prüfen
 * Plugins den Zustand ihrer Dialoge so.
 *
 * `allow-discrete` erlaubt die Transition über den display-Wechsel hinweg,
 * `@starting-style` liefert den Startwert. Browser, die beides nicht kennen,
 * blenden hart ein — also genau wie vor 4.0.80. Nur der Eintritt ist animiert:
 * Eine Austritts-Animation geriete mit dem Aufräumen der flüchtigen Modals
 * (`__ksEphemeral`, Entfernen nach 200 ms) und dem Fokus-Rücksprung ins Gehege. */
.ks-modal.active {
    opacity: 1;
    transition: opacity .2s ease, display .2s allow-discrete;
}

@starting-style {
    .ks-modal.active { opacity: 0; }
}

.ks-modal.active .ks-modal-content {
    transition: transform .22s var(--kajinga-ease-out, cubic-bezier(.22, 1, .36, 1)), opacity .22s ease;
}

@starting-style {
    .ks-modal.active .ks-modal-content {
        /* Der Zielwert translate(-50%, -50%) steht in token-utilities.tpl —
           die 8px sind der Versatz davon, nicht ein eigener Startpunkt.
           v4.0.91: Die leichte Verkleinerung kommt dazu, damit der Dialog auf
           den Betrachter zu wächst, statt nur von unten hereinzugleiten. */
        transform: translate(-50%, calc(-50% + 8px)) scale(0.98);
        opacity: 0;
    }
}

/* Der Abdunkler ist eine MATERIALSCHICHT, nicht nur ein Schleier (v4.0.91).
 *
 * Bis hierher lag über der Seite eine flache schwarze Fläche (0,5 Deckkraft,
 * token-utilities.tpl). Das dimmt, aber es schiebt den Hintergrund nicht
 * zurück: Der Text darunter blieb scharf und zog den Blick. Die Unschärfe
 * nimmt ihm die Lesbarkeit und damit die Aufmerksamkeit — der Dialog steht
 * dadurch frei, ohne dass die Fläche dunkler werden muss.
 *
 * Sie baut sich mit auf, statt fertig dazuliegen: Eine Glasfläche, die
 * schlagartig erscheint, wirkt wie ein Bildfehler; eine, die aufzieht, wirkt
 * wie ein Material, das ankommt.
 *
 * Bei gestapelten Dialogen blurrt der obere Abdunkler den unteren mit — das
 * ist erwünscht und staffelt die Tiefe von selbst.
 *
 * 3px sind bewusst wenig: Die Fläche deckt den ganzen Viewport, und jedes
 * zusätzliche Pixel Radius kostet Rechenzeit auf einer Ebene, die bei jedem
 * Dialog neu aufgebaut wird. Die Befehlspalette liegt mit 2px daneben. */
.ks-modal-overlay {
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}

.ks-modal.active .ks-modal-overlay {
    transition: backdrop-filter .2s ease, -webkit-backdrop-filter .2s ease;
}

@starting-style {
    .ks-modal.active .ks-modal-overlay {
        /* `0px`, nicht `0` — ohne Einheit interpoliert der Browser nicht. */
        backdrop-filter: blur(0px);
        -webkit-backdrop-filter: blur(0px);
    }
}

@media (prefers-reduced-motion: reduce) {
    .ks-modal.active,
    .ks-modal.active .ks-modal-content,
    .ks-modal.active .ks-modal-overlay { transition: none; }
}

/* Wer Transparenz abbestellt hat, bekommt die Trennung über die Fläche.
 *
 * Die Unschärfe trägt hier Bedeutung — sie schiebt den Hintergrund weg. Fällt
 * sie weg, muss die Deckkraft das übernehmen, sonst bliebe der Dialog vor
 * einem gut lesbaren Hintergrund stehen und die Trennung wäre schwächer als
 * vor der Änderung. Gilt für beide Schichten dieser Art. */
@media (prefers-reduced-transparency: reduce) {
    .ks-modal-overlay {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(0, 0, 0, 0.72);
    }

    .ks-palette-overlay {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(10, 12, 16, 0.72);
    }
}

.ks-modal--sm .ks-modal-content { max-width: 420px; width: calc(100vw - 40px); }
.ks-modal--lg .ks-modal-content { max-width: 860px; width: calc(100vw - 40px); }

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

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

.ks-modal-footer .ks-btn + .ks-btn {
    margin-left: var(--kajinga-space-2, 8px);
}

/* =========================================
 * BUSY-STATE
 * ========================================= */

.ks-is-busy {
    pointer-events: none;
    opacity: 0.75;
}

.ks-is-busy .ks-spinner {
    margin-right: 6px;
}

/* =========================================
 * SWAP-ANIMATION (AJAX-Partials)
 * ========================================= */

@keyframes ks-swap-flash {
    0%   { background-color: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.12); }
    100% { background-color: transparent; }
}

.ks-swap-in {
    animation: ks-swap-flash 0.7s ease-out;
}

/* =========================================
 * COMMAND-PALETTE
 * ========================================= */

.ks-palette {
    position: fixed;
    inset: 0;
    z-index: 100300;
    display: none;
}

.ks-palette.active {
    display: block;
}

.ks-palette-overlay {
    position: absolute;
    inset: 0;
    background: rgba(10, 12, 16, 0.45);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

.ks-palette-box {
    position: absolute;
    top: 18vh;
    left: 50%;
    transform: translateX(-50%);
    width: min(620px, calc(100vw - 40px));
    background: var(--kajinga-card-solid, #fff);
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    border-radius: var(--kajinga-radius-lg, 12px);
    box-shadow: 0 24px 70px rgba(0, 0, 0, 0.3);
    overflow: hidden;
    animation: ks-fade-in 0.15s ease-out;
}

.ks-palette-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--kajinga-gray-100, #f0f0f1);
    color: var(--kajinga-text-muted, #646970);
}

.ks-palette-input {
    flex: 1;
    border: none !important;
    outline: none !important;
    box-shadow: none !important;
    background: transparent !important;
    font-size: 15px;
    color: var(--kajinga-text, #1d2327);
    padding: 0;
    min-height: 24px;
}

.ks-palette-kbd {
    font-family: inherit;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 3px 6px;
    border: 1px solid var(--kajinga-gray-200, #e2e4e7);
    border-radius: var(--kajinga-radius-xs, 4px);
    color: var(--kajinga-text-muted, #646970);
    background: var(--kajinga-gray-50, #f6f7f7);
}

.ks-palette-list {
    max-height: min(46vh, 420px);
    overflow-y: auto;
    padding: 6px;
}

.ks-palette-group {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--kajinga-text-muted, #646970);
    padding: 8px 10px 4px;
}

.ks-palette-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    border-radius: var(--kajinga-radius-sm, 6px);
    cursor: pointer;
    font-size: 14.5px;
    color: var(--kajinga-text, #1d2327);
}

.ks-palette-item.active {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.09);
    color: var(--kajinga-primary, #2271b1);
}

.ks-palette-item-icon {
    display: inline-flex;
    color: var(--kajinga-text-muted, #646970);
}

.ks-palette-item.active .ks-palette-item-icon {
    color: var(--kajinga-primary, #2271b1);
}

.ks-palette-item-title {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ks-palette-item-group {
    font-size: 13px;
    color: var(--kajinga-text-muted, #646970);
    flex-shrink: 0;
}

.ks-palette-empty {
    padding: 24px 16px;
    text-align: center;
    font-size: 14.5px;
    color: var(--kajinga-text-muted, #646970);
}

/* =========================================
 * COUNTER-BUBBLE (v4.1.12)
 *
 * Der Zähler an einem Menüpunkt, Tab oder Button: „3 offene To-dos".
 * NICHT zu verwechseln mit .ks-badge-* — das sind Status-Etiketten auf
 * Pastellfläche („aktiv", „ausstehend"). Ein Counter ist eine Zahl, die
 * Aufmerksamkeit will, und ist immer rot.
 *
 * Warum Rot mit Ring, und nicht die Brand-Farbe:
 * Der Counter muss in zwei Umgebungen funktionieren — auf der dunkelblauen
 * Sidebar und auf hellem Content. Gemessen hat keine einzelne Füllfarbe das
 * geschafft: Weiß liegt auf der Sidebar bei 8,36:1 und im Content bei 1,13:1,
 * Primary-Dark genau umgekehrt (1,07 / 7,92). Der 1,5px-Ring in der Gegenfarbe
 * löst das — er trennt die Bubble von jedem Grund, auf dem sie sitzt.
 * Rot #d63638 trägt die Ziffer mit 4,73:1 (WCAG AA) und ist die Zähler-
 * Konvention, die Nutzer aus WordPress, iOS und Android mitbringen.
 *
 * Ring-Farbe über --ks-count-ring überschreibbar, falls eine Fläche mal weder
 * hell noch dunkel genug ist.
 * ========================================= */

.ks-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* v4.1.16: 16px. Startwert war 20 (bündig an der Textunterkante, Zeile
       wirkte überfüllt), dann 18. min-width läuft mit der Höhe mit, sonst wird
       die Bubble mit einstelliger Zahl zur liegenden Pille. */
    min-width: 16px;
    height: 16px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--kajinga-danger, #d63638);
    /* Bewusst Literal-Weiß, nicht --kajinga-danger-text: das ist #721c24 und
       gehört auf die Pastellfläche --kajinga-danger-bg, nicht auf Vollrot. */
    color: #fff;
    box-shadow: 0 0 0 1.5px var(--ks-count-ring, rgba(255, 255, 255, 0.85));
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    flex: none;
    box-sizing: border-box;
    /* Senkrechte Ausrichtung neben Text — gehört auf .ks-count, NICHT nur auf
       die Punkt-Variante (v4.1.21). Bis dahin trug allein `--dot` ein
       `vertical-align: middle`, die Zahl-Bubble lief auf dem Vorgabewert
       `baseline` mit. Zwei Varianten derselben Komponente richteten sich also
       verschieden aus, und beide daneben: der Punkt gemessene 1,34–1,49px zu
       TIEF, die Zahl im Menü 1,5px zu HOCH.

       Die 2px sind kein Augenmaß, sondern die Korrektur eines bekannten
       Verhaltens: `middle` richtet an *Baseline + halber x-Höhe* aus, und die
       x-Höhe liegt bei jeder Schrift unter der optischen Zeilenmitte — bei
       Geist im Admin-Menü um rund 1,4px. `margin-bottom` verschiebt die
       Margin-Box, deren Mitte `middle` ausrichtet: 3px unten heben die
       sichtbare Bubble um 1,5px. Nachgemessen bleiben unter 0,4px Rest, im
       Haupt- wie im Untermenü.

       Feste px sind hier richtig, nicht em: Die Bubble ist mit 16px selbst
       fest bemasst und skaliert nicht mit der Kontextschrift — der Ausgleich
       darf es also auch nicht. (`em` wäre auf `--dot` ohnehin wirkungslos,
       dort steht `font-size: 0`, und em rechnet gegen die EIGENE Schriftgröße.)
       Absolut positionierte Zähler wie der Kompass-Floating-Button sind nicht
       betroffen: Dort greift weder vertical-align noch ein margin-bottom ohne
       gegenüberliegendes `bottom`. */
    vertical-align: middle;
    margin-bottom: 3px;
}

/* Auf hellem Grund ist der weiße Ring unsichtbar und damit harmlos — auf
   farbigen Flächen (Floating-Button, Brand-Hero) trennt er die Bubble sauber ab. */

/* Punkt-Variante (v4.1.13): „hier liegt etwas an", ohne Anzahl.
   Für Sammel-Ebenen, unter denen die genauen Zahlen ohnehin stehen — ein
   Hauptmenü-Punkt über Unterpunkten mit eigenen Zählern etwa. Die Summe dort
   zu wiederholen wäre Redundanz, und sie addierte oft Unvergleichbares.
   Konvention aus iOS/Android/macOS; ein „!" wäre falsch, das ist in
   Oberflächen mit Warnung und Fehler belegt.
   Trägt keinen Text — die Beschriftung gehört als aria-label ans Element.

   v4.1.14: Volle Zähler-Größe statt eines kleinen 9px-Punkts. Der Punkt steht
   in derselben Leiste wie Bubbles mit Zahlen; kleiner gesetzt wirkte er wie ein
   anderes Element statt wie dieselbe Anzeige ohne Ziffer. `width` und
   `padding: 0` sind nötig, weil .ks-count sonst über `padding: 0 6px` zum Oval
   würde. Die Größe folgt .ks-count — wer sie dort ändert, ändert beide. */
.ks-count--dot {
    width: 16px;
    padding: 0;
    font-size: 0;
    /* vertical-align steht seit 4.1.21 auf .ks-count — beide Varianten
       richten sich gleich aus. Hier nichts mehr nötig. */
}

/* `display: inline-flex` oben schlägt das hidden-Attribut — ohne diese Regel
   bliebe ein <span class="ks-count" hidden> sichtbar. Gilt für beide Varianten,
   damit JS den Zähler ein- und ausblenden kann, statt ihn aus dem DOM zu nehmen
   (das erhält aria-label und Beschriftung). */
.ks-count[hidden] {
    display: none;
}

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

body.kajinga-dark-mode .ks-toast {
    background: var(--kajinga-card-solid, rgba(35, 38, 43, 0.98));
    border-color: rgba(255, 255, 255, 0.08);
}

body.kajinga-dark-mode .ks-toast-close:hover {
    background: rgba(255, 255, 255, 0.08);
}

body.kajinga-dark-mode .ks-toast-action {
    background: rgba(255, 255, 255, 0.07);
    border-color: rgba(255, 255, 255, 0.16);
}

body.kajinga-dark-mode .ks-toast-action:hover,
body.kajinga-dark-mode .ks-toast-action:focus-visible {
    background: rgba(255, 255, 255, 0.13);
}

body.kajinga-dark-mode .ks-palette-overlay {
    background: rgba(0, 0, 0, 0.6);
}

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

body.kajinga-dark-mode .ks-palette-head {
    border-bottom-color: rgba(255, 255, 255, 0.08);
}

body.kajinga-dark-mode .ks-palette-kbd {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.12);
}

body.kajinga-dark-mode .ks-palette-item.active {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.22);
}

/* =========================================
 * INVERSE BUTTON (auf Brand-Flächen)
 * Konvention: Der Haupt-Button einer Seite wandert in den Hero-Header
 * und ist invers — weiß mit Text in der Primary-/Scheme-Farbe.
 * ks_page_header (variant hero) setzt die Variante automatisch.
 * ========================================= */

.ks-btn.ks-btn-inverse {
    background: #fff;
    border-color: #fff;
    color: var(--kajinga-primary, #2271b1);
    font-weight: 600;
    box-shadow: 0 1px 3px rgba(16, 24, 40, 0.18);
}

.ks-btn.ks-btn-inverse:hover {
    background: #fff;
    border-color: #fff;
    color: var(--kajinga-primary-dark, #135e96);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(16, 24, 40, 0.22);
}

/* Druck-Rückmeldung für den WICHTIGSTEN Knopf der Seite (v4.0.93).
 *
 * `ks_page_header(variant hero)` setzt diese Variante automatisch auf die
 * Haupt-Aktion — und genau dort war von der Rückmeldung aus 4.0.90 nichts zu
 * sehen. Grund ist die Spezifität: Die Hover-Regel darüber trägt zwei Klassen
 * (0,3,0), die allgemeine `.ks-btn:active` in refresh.css nur eine (0,2,0).
 * Beim Drücken sind BEIDE Zustände aktiv, und die höhere Spezifität gewinnt —
 * der Knopf blieb im Hover-Zustand hängen.
 *
 * MERKREGEL: Wer eine `:hover`-Regel mit erhöhter Spezifität schreibt, muss
 * das `:active`-Gegenstück auf derselben Höhe mitliefern. Die allgemeine Regel
 * greift sonst nie. Aufspüren lassen sich solche Fälle, indem man alle
 * Transform-Regeln aus der CSSOM zieht und Hover gegen Active vergleicht. */
.ks-btn.ks-btn-inverse:active {
    transform: scale(0.97);
    box-shadow: 0 1px 3px rgba(16, 24, 40, 0.18);
    transition-duration: 0.06s;
}

.ks-btn.ks-btn-inverse:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.45);
}

a.ks-btn-inverse:focus,
a.ks-btn-inverse:active {
    color: var(--kajinga-primary, #2271b1);
}

/* Icons erben die Textfarbe */
.ks-btn.ks-btn-inverse .ks-icon,
.ks-btn.ks-btn-inverse svg {
    color: currentColor;
}

/* Dark Mode: Brand-Flächen bleiben farbig, der inverse Button bleibt weiß */
body.kajinga-dark-mode .ks-btn.ks-btn-inverse {
    background: #fff;
    color: var(--kajinga-primary, #2271b1);
}

/* =========================================
 * EINHEITLICHE CONTENT-BREITE
 * Konvention: Jeder Kajinga-Screen begrenzt seinen Haupt-Wrap auf
 * --kajinga-content-max (linksbündig, seit Floating-Card-Sidebar).
 * Opt-in via <div class="wrap ks-page">; magic-funnel läuft über
 * .mf-wrap mit derselben Variable. margin-right hält bei schmalen
 * Screens Abstand zum Bildschirmrand.
 * ========================================= */

:root {
    /* v4.2.33: 1100 → 1200. Die App-Bar und die Block-Editor-Fläche in
       admin-overrides.css lesen dieselbe Variable — sie enden bündig mit dem
       Content und ziehen jede Änderung hier automatisch mit. */
    --kajinga-content-max: 1200px;
}

.wrap.ks-page {
    max-width: var(--kajinga-content-max, 1200px);
    /* v3.9.10: 18px (+50% ggü. 12px-Raster) — mehr Luft zur Admin-Bar;
       die Sidebar-Karte bleibt bewusst auf 12px unter dem Viewport-Rand */
    margin-top: 18px;
    margin-left: 0;
    margin-right: 20px;
}

/* Emoji-Renderer (ks.emoji): getippte Unicode-Emojis werden im Admin durch
   lokale Fluent-SVGs aus kajinga-libs ersetzt — gleicher Look auf allen OS. */
img.ks-emoji {
    display: inline-block;
    width: 1.2em;
    height: 1.2em;
    vertical-align: -0.25em;
    margin: 0 0.05em;
    border: 0;
    box-shadow: none;
}

/* Druck-Rückmeldung im Palette-Eintrag — Fläche statt Bewegung, wie bei allen
   Listenzeilen (v4.0.90, Begründung im gleichnamigen Block in components.css). */
.ks-palette-item:active {
    background: rgba(var(--kajinga-primary-rgb, 34, 113, 177), 0.16);
}

/* =========================================
 * REDUZIERTE BEWEGUNG (v4.0.90)
 *
 * Vorher deckten die vorhandenen Klammern vier Selektoren ab: den Hover-Lift
 * von Knopf und Stat-Kachel (refresh.css) und die Modal-Einblendung (oben).
 * Alles andere lief unverändert weiter — allen voran `ks-shimmer` auf den
 * Skeletons: 1,4 s im Dauerlauf, also rund 0,7 Hz und damit genau in dem
 * Bereich, den die Barrierefreiheits-Leitlinien als problematisch führen.
 *
 * LADEANZEIGEN BLEIBEN IN BEWEGUNG, und das ist kein Versehen: „Reduzierte
 * Bewegung" heißt gedämpfte Rückmeldung, nicht gar keine. Ein eingefrorener
 * Spinner liest sich als abgestürzt. `.ks-spinner` und `.ks-cal-spin` sind
 * deshalb bewusst NICHT gelistet.
 *
 * WARUM EINE LISTE UND KEIN `*`-SELEKTOR: Der verbreitete Weg, im
 * reduced-motion-Fall pauschal jede Animation im Dokument abzuräumen, träfe
 * hier auch den Block-Editor, WordPress-Core und ~40 fremde Plugins — samt dem
 * JavaScript, das an deren Animationsenden hängt. In einem Netz dieser Größe
 * ist der vorhersagbare Weg der richtige. Preis: Wer eine neue Animation
 * ergänzt, trägt sie hier nach.
 *
 * `!important` ist nötig, weil core.css VOR components.css lädt und die
 * abgeräumten Regeln teilweise von dort stammen.
 * ========================================= */

@media (prefers-reduced-motion: reduce) {

    /* Dauerschleifen und Einblendungen */
    .ks-skeleton,
    .ks-swap-in,
    .ks-palette-box,
    .ks-dropdown-menu,
    .ks-tab-nav-submenu {
        animation: none !important;
    }

    /* Wege: Dauer auf praktisch null. Bewusst nicht `none` — ein Übergang von
       0 s feuert kein `transitionend`, und Bestandscode wartet darauf. */
    /* Das Auf-/Zuklappen des Accordions (4.0.97) laeuft ueber ein
       Pseudo-Element und braucht deshalb einen eigenen Selektor. */
    .ks-accordion__item::details-content,
    .ks-toast,
    .ks-tip-bubble,
    .ks-switch-thumb,
    .ks-switch-track,
    .ks-rotate-180,
    .ks-progress-bar > * {
        transition-duration: 0.01ms !important;
    }

    /* Hover- und Druck-Bewegung raus. Farbe, Fläche und Schatten bleiben —
       sie tragen die Rückmeldung weiter, ohne den Blick mitzuziehen. */
    :is(
        .ks-btn, .ks-btn-hero, .ks-btn-featured,
        .ks-stat-card, .ks-stat-card--link,
        .ks-widget, .ks-widget-stat,
        .ks-chip, .ks-tab-nav-link, .ks-page-back,
        .ks-dropdown-toggle, .ks-card-collapse, .ks-th-sortable,
        .ks-cal-navbtn, .ks-cal-todaybtn, .ks-cal-viewbtn, .ks-cal-add,
        .ks-page-link, .ks-row-action
    ):is(:hover, :active) {
        transform: none !important;
    }
}
