/* =================================================== */
/* CantorHub – Design System                           */
/* =================================================== */

/* ─── Tokens ─────────────────────────────────────── */
:root {
    --brand:           #c14468;
    /* Von --brand abgeleitet (nicht literal), damit BRAND_FARBE-Überschreibungen
       (siehe _brand_boot.html) Hover-Zustand, Tint und Fokusring mitziehen. */
    --brand-dark:      color-mix(in srgb, var(--brand) 85%, black);
    --brand-light:     color-mix(in srgb, var(--brand) 10%, transparent);
    --brand-ring:      color-mix(in srgb, var(--brand) 22%, transparent);
    /* Dieselbe Markenfarbe in zwei Rollen: als *Fläche* (--brand-dark, weiße
       Schrift darauf) und als *Schrift* auf einer Karte (--brand-text). Im hellen
       Thema ist das derselbe Ton; im dunklen gehen die Rollen auseinander, weil
       eine hellere Fläche ihre weiße Schrift verlöre und der abgedunkelte Ton als
       Buchstabe auf der dunklen Karte verschwände. Vorbild ist die Stimmpalette,
       die für dieselbe Lage ebenfalls zwei Tokens führt (--stimme-X und
       --stimme-X-text). */
    --brand-text:      var(--brand-dark);
    --cal-geb:         #157347;
    --cal-geb-bg:      rgba(21, 128, 61, 0.13);
    --cal-weekend:     #dc2626;

    /* Kategoriale Palette — Berechtigungskategorien (Artikel/Forum/Dateien/
       Orte/Termine/Repertoire/Mitglieder). Kategorie „Termine" ist die
       Akzentfarbe (var(--brand)), alle weiteren sind domain-feste
       Kategoriefarben, nicht pro Verein konfigurierbar. Tints entstehen per
       color-mix() direkt an der Verwendungsstelle, damit
       Opazitaetsunterschiede (Light/Dark, Base/Hover) ohne weitere Tokens greifen.
       Die Stimmen hatten hier frueher mitgewohnt — siehe --stimme-* darunter. */
    --kat-1:           #7c3aed;   /* violett  — Artikel     */
    --kat-2:           #0369a1;   /* blau    — Forum       */
    --kat-3:           #059669;   /* gruen   — Dateien     */
    --kat-4:           #b45309;   /* orange  — Orte        */
    --kat-5:           #0891b2;   /* cyan    — Repertoire  */
    --kat-6:           #65a30d;   /* limette — Mitglieder   */

    /* Stimmpalette — eigene Familie, damit die Stimmen unabhaengig von den
       Berechtigungskategorien gestaltbar sind und eine BRAND_FARBE-Ueberschreibung
       keine zwei Stimmen gleich faerben kann.
       In OKLCH konstruiert, mit zwei Eigenschaften, die beide gebraucht werden:
       gleichmaessiger Farbtonabstand (kleinster Paarabstand 100 statt der 3,7 der
       alten Flaechen-Tints) UND von Sopran nach Bass monoton fallende Helligkeit
       (0.282 > 0.201 > 0.171 > 0.090). Die Helligkeitstreppe traegt die Tonhoehe
       auch dort, wo die Farbe nicht ankommt: Rot-Gruen-Schwaeche, Graustufendruck,
       schlechter Beamer.
       Chorleiter und Musiker sind keine Stimmlage, sondern Rollen, und bekommen
       deshalb bewusst keinen eigenen Farbton, sondern den neutralen --t4.
       Der Vollton ist die Markierungsfarbe (Zeilenbalken, Kartenkante,
       Portraetring, Flaechen des Gruppenstreifens); wo aber der Buchstabe der
       Stimme auf der Kartenflaeche steht — die Pille in der Topbar der
       Mitgliedskarte — braucht derselbe Ton eine dunklere Fassung. Sie wird deshalb abgeleitet statt gepflegt (wie
       --brand-dark), weil Sopran als Flaeche kraeftig sein muss, als Text auf
       Weiss aber nicht darf. */
    --stimme-s:        #c28500;   /* Sopran — Gold   */
    --stimme-a:        #d05255;   /* Alt    — Rot    */
    --stimme-t:        #007f8d;   /* Tenor  — Petrol */
    --stimme-b:        #5347a4;   /* Bass   — Indigo */
    --stimme-s-text:   color-mix(in srgb, var(--stimme-s) 80%, black);
    --stimme-a-text:   color-mix(in srgb, var(--stimme-a) 80%, black);
    --stimme-t-text:   color-mix(in srgb, var(--stimme-t) 80%, black);
    --stimme-b-text:   color-mix(in srgb, var(--stimme-b) 80%, black);

    /* Sidebar */
    --sb-bg:           #ffffff;
    --sb-hover:        rgba(0, 0, 0, 0.04);
    --sb-active-bg:    var(--brand-light);
    --sb-text:         #6b7280;
    --sb-text-hover:   #374151;
    --sb-text-active:  var(--brand);
    --sb-divider:      #e5e7eb;
    /* waechst mit der Schriftgroesse, schmale Handys behalten Rand zum Schliessen */
    --sb-width:        min(calc(232rem / 14), 85vw);

    /* Top bar */
    --tb-bg:           #ffffff;
    --tb-border:       #e5e7eb;
    --tb-h:            52px;
    --tb-icon:         #9ca3af;

    /* Surfaces */
    --bg-app:          #f1f3f5;
    --bg-card:         #ffffff;
    --shadow-xs:       0 1px 2px rgba(0,0,0,0.05);
    --shadow-sm:       0 1px 4px rgba(0,0,0,0.08), 0 0 0 1px rgba(0,0,0,0.03);
    --shadow-md:       0 4px 16px rgba(0,0,0,0.10);

    /* Text */
    --t1: #111827;
    --t2: #374151;
    --t3: #6b7280;
    --t4: #9ca3af;

    /* Border */
    --border:          #e5e7eb;
    --border-dark:     #d1d5db;

    /* Radius */
    --r-sm: 4px;
    --r:    8px;
    --r-lg: 12px;

    /* Typography */
    --font:       -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-sans:  -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --mono:       ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, monospace;

    /* Table */
    --bg-thead:     #f9fafb;
    --bg-row-alt:   #f5f6f8;
    --bg-row-hover: #eef0f3;

    /* Forum */
    --forum-bg:         #f8f9fb;
    --msg-bg:           #ffffff;
    --msg-border:       #e5e7eb;
    --msg-me-bg:        color-mix(in srgb, var(--brand) 10%, white);
    --msg-me-border:    color-mix(in srgb, var(--brand) 25%, white);
    --mention-bg:       #ecfdf5;
    --mention-border:   #6ee7b7;
    --mention-color:    #065f46;

    /* Search highlight */
    --search-hl-bg:     #c7f0d8;
    --search-hl-color:  #0c6b3c;

    /* Videofläche hinter dem Bild — im Hellmodus bewusst dunkel, ein weißer
       Rahmen um ein Video blendet. */
    --video-bg:         #111827;

    /* Code / pre */
    --pre-bg:           #f8f9fa;
    --code-bg:          #f1f3f5;
    --code-bar-bg:      #e4e6ea;
    --code-bar-dots:    rgba(0,0,0,0.15);
    --code-color:       var(--t1);

    /* Warning / outdated banner */
    --warn-bg:          #fffbeb;
    --warn-border:      #fcd34d;
    --warn-text:        #92400e;
    --warn-strong:      #78350f;
    --warn-icon:        #d97706;

    /* Error / validation */
    --error-bg:         #fef2f2;
    --error-border:     #fecaca;
    --error-text:       #b91c1c;
    /* Vollton fuer destruktive Buttons — --error-bg ist eine Flaeche und
       traegt keine weisse Schrift */
    --error-solid:      #c53030;
    --error-solid-hover:#9b2c2c;

    /* Ampel-Status (Zusage / Anwesenheit): weiche Flaeche + kraeftige
       Vollton-Variante fuer aktive bzw. Hover-Zustaende */
    --status-success-bg:     #dcfce7;
    --status-success-text:   #166534;
    --status-success-border: #bbf7d0;
    --status-success-solid:  #16a34a;
    --status-warning-bg:     #fef9c3;
    --status-warning-text:   #854d0e;
    --status-warning-border: #fde68a;
    --status-warning-solid:  #ca8a04;
    --status-danger-bg:      #fee2e2;
    --status-danger-text:    #991b1b;
    --status-danger-border:  #fecaca;
    --status-danger-solid:   #dc2626;
    --aufst-eventuell:       #facc15;   /* kräftiges Gelb der Eventuell-Kästchen */

    /* Password-strength meter (score 0-4) */
    --strength-0:       #dc2626;
    --strength-1:       #f0ad4e;
    --strength-2:       #eab308;
    --strength-3:       #84cc16;
    --strength-4:       #22c55e;

    /* Hover surfaces */
    --hover-bg:         #f3f4f6;
    --hover-icon-bg:    #f3f4f6;

    /* Aliases */
    --text-muted:  #6b7280;

    --ease: 0.18s ease;
}

/* ─── Dark Mode ──────────────────────────────────── */
[data-theme="dark"] {
    /* Die Markenfarbe als Schrift auf der dunklen Karte. ``--brand-dark`` ist die
       für Flächen abgedunkelte Marke und bliebe hier bei 2,7:1 — bei 10,5 px
       Beschriftung zu wenig. 70 % Marke mit Weiß trägt 5,8:1 und bleibt eine
       Ableitung von --brand, folgt also einer konfigurierten BRAND_FARBE mit.
       Die Flächen (a.btn:hover, .cal-today-btn:hover …) bleiben bei --brand-dark:
       dort steht weiße Schrift darauf, eine hellere Fläche nähme ihr den Grund. */
    --brand-text:      color-mix(in srgb, var(--brand) 70%, white);

    --cal-geb:         #4ade80;
    --cal-geb-bg:      rgba(74, 222, 128, 0.16);
    --cal-weekend:     #f87171;

    --kat-1:           #a78bfa;
    --kat-2:           #38bdf8;
    --kat-3:           #34d399;
    --kat-4:           #fbbf24;
    --kat-5:           #22d3ee;
    --kat-6:           #86efac;

    /* Stimmpalette, Dark: gleiche Farbtoene, auf die dunkle Karte gehoben
       (Kontrast 7,4-10,2:1 auf --bg-card). Die Helligkeitstreppe der Light-
       Palette kehrt sich hier nicht um — sie traegt dort die Tonhoehe, hier
       traegt sie der Farbton, weil auf dunklem Grund alle vier hell sein
       muessen. Die Textvariante ist der Vollton selbst: er steht auf --bg-card
       hell genug, ein Abdunkeln waere hier verkehrt herum. */
    --stimme-s:        #ebb353;
    --stimme-a:        #fc8987;
    --stimme-t:        #5ed9e6;
    --stimme-b:        #a8a4f9;
    --stimme-s-text:   var(--stimme-s);
    --stimme-a-text:   var(--stimme-a);
    --stimme-t-text:   var(--stimme-t);
    --stimme-b-text:   var(--stimme-b);

    --sb-bg:           #111117;
    --sb-hover:        rgba(255, 255, 255, 0.05);
    --sb-active-bg:    color-mix(in srgb, var(--brand) 14%, transparent);
    --sb-text:         #a0a3b8;
    --sb-text-hover:   #c9ccde;
    --sb-text-active:  #ffffff;
    --sb-divider:      rgba(255, 255, 255, 0.07);

    --tb-bg:           #1a1a2e;
    --tb-border:       rgba(255, 255, 255, 0.07);
    --tb-icon:         #7c7f93;

    --bg-app:          #12121a;
    --bg-card:         #1a1a2e;
    --shadow-xs:       0 1px 2px rgba(0,0,0,0.20);
    --shadow-sm:       0 1px 4px rgba(0,0,0,0.30), 0 0 0 1px rgba(255,255,255,0.04);
    --shadow-md:       0 4px 16px rgba(0,0,0,0.35);

    --t1:              #e5e7eb;
    --t2:              #c9ccde;
    --t3:              #a0a3b8;
    --t4:              #7c7f93;

    --border:          rgba(255, 255, 255, 0.07);
    --border-dark:     rgba(255, 255, 255, 0.10);

    --bg-thead:        #22222e;
    --bg-row-alt:      rgba(255, 255, 255, 0.025);
    --bg-row-hover:    rgba(255, 255, 255, 0.05);

    --forum-bg:        #16161e;
    --msg-bg:          #1e1e2e;
    --msg-border:      rgba(255, 255, 255, 0.07);
    --msg-me-bg:       color-mix(in srgb, var(--brand) 22%, transparent);
    --msg-me-border:   color-mix(in srgb, var(--brand) 35%, transparent);
    --mention-bg:      rgba(6, 95, 70, 0.15);
    --mention-border:  rgba(110, 231, 183, 0.30);
    --mention-color:   #6ee7b7;

    --search-hl-bg:    rgba(34, 197, 94, 0.30);
    --search-hl-color: #86efac;

    --video-bg:        #000000;

    --pre-bg:          #22222e;
    --code-bg:         #1e1e2e;
    --code-bar-bg:     #2a2a3e;
    --code-bar-dots:   rgba(255,255,255,0.2);
    --code-color:      #cdd6f4;

    --warn-bg:         #2a2410;
    --warn-border:     #5b4a1a;
    --warn-text:       #e5c97a;
    --warn-strong:     #f3e0a6;
    --warn-icon:       #e0a93a;

    --error-bg:        #2e1416;
    --error-border:    #5b2326;
    --error-text:      #f5a3a3;
    --error-solid:     #9b2c2c;
    --error-solid-hover:#7f1d1d;

    /* Ampel-Status: gedaempfte Flaechen, der Vollton bleibt identisch */
    --status-success-bg:     rgba(22,101,52,.25);
    --status-success-text:   #86efac;
    --status-success-border: rgba(22,101,52,.40);
    --status-warning-bg:     rgba(133,77,14,.25);
    --status-warning-text:   #fde047;
    --status-warning-border: rgba(133,77,14,.40);
    --status-danger-bg:      rgba(153,27,27,.25);
    --status-danger-text:    #fca5a5;
    --status-danger-border:  rgba(153,27,27,.40);
    --aufst-eventuell:       #facc15;

    --strength-0:      #ef4444;
    --strength-1:      #f59e0b;
    --strength-2:      #facc15;
    --strength-3:      #a3e635;
    --strength-4:      #4ade80;

    --hover-bg:        rgba(255, 255, 255, 0.04);
    --hover-icon-bg:   rgba(255, 255, 255, 0.06);

    --text-muted:      #a0a3b8;
}

[data-theme="dark"] .sidebar-title { color: var(--t1); }
[data-theme="dark"] thead th { background: var(--bg-thead); }
[data-theme="dark"] td { border-bottom-color: rgba(255,255,255,0.05); }
[data-theme="dark"] tbody tr:hover td { background: var(--bg-row-hover); }
[data-theme="dark"] .hamburger:hover,
[data-theme="dark"] .toolicon:hover { background: var(--hover-icon-bg); }
[data-theme="dark"] .messages { background: var(--forum-bg); }
[data-theme="dark"] .message .content { background: var(--msg-bg); border-color: var(--msg-border); }
[data-theme="dark"] .message .avatar img { border-color: rgba(255,255,255,0.10); }
[data-theme="dark"] .message_me .content_me { background: var(--msg-me-bg); border-color: var(--msg-me-border); }
[data-theme="dark"] .mention { background: var(--mention-bg); border-color: var(--mention-border); color: var(--mention-color); }
[data-theme="dark"] .wiki pre { background: var(--pre-bg); }
[data-theme="dark"] #app-main.drag-active .upload-overlay { background: color-mix(in srgb, var(--brand) 18%, transparent); }
[data-theme="dark"] span.not_found { background: rgba(254,249,195,0.10); }
[data-theme="dark"] .offcanvas { box-shadow: -2px 0 16px rgba(0,0,0,0.30); }

/* ─── Reset ──────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

/* ─── Base ───────────────────────────────────────── */
/* Alle Schriftgroessen haengen an dieser Wurzel (calc(Nrem / 14) statt Npx),
   damit die Schriftgroessen-Einstellung der Sidebar sie gemeinsam skaliert.
   --schrift-faktor setzt _theme_boot.html vor dem ersten Paint. */
html { font-size: calc(14px * var(--schrift-faktor, 1)); }

html, body {
    height: 100%;
    margin: 0;
    font-family: var(--font);
    color: var(--t1);
    background: var(--sb-bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow: hidden;
}

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

/* =================================================== */
/* App Shell                                           */
/* =================================================== */
body {
    display: flex;
}

.sidebar {
    width: var(--sb-width);
    height: 100vh;
    height: 100dvh;
    background: var(--sb-bg);
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    overflow: hidden;
    position: relative;
    z-index: 200;
    border-right: 1px solid var(--sb-divider);
    transition: width var(--ease), transform var(--ease);
}

.sidebar.collapsed {
    width: 0;
    border-right: none;
    overflow: hidden;
}

.app-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    height: 100vh;
    height: 100dvh;
    padding-bottom: env(safe-area-inset-bottom);
    position: relative;
}

/* =================================================== */
/* Sidebar – Brand                                     */
/* =================================================== */
.sidebar-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 14px;
    height: var(--tb-h);
    border-bottom: 1px solid var(--sb-divider);
    flex-shrink: 0;
    box-sizing: border-box;
}

.sidebar-logo {
    width: 28px;
    height: 28px;
    object-fit: contain;
    flex-shrink: 0;
}

.sidebar-title {
    font-size: calc(13.5rem / 14);
    font-weight: 700;
    color: var(--t1);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: 0.015em;
}

/* =================================================== */
/* Sidebar – Navigation                                */
/* =================================================== */
.sidebar-nav {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 6px 0;
    scrollbar-width: none;
}
.sidebar-nav::-webkit-scrollbar { display: none; }

.nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 12px;
    margin: 1px 6px;
    border-radius: var(--r-sm);
    color: var(--sb-text);
    text-decoration: none;
    font-size: calc(13rem / 14);
    font-weight: 500;
    transition: background var(--ease), color var(--ease);
    cursor: pointer;
    border: none;
    background: none;
    width: calc(100% - 12px);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    position: relative;
    line-height: 1.4;
}

.nav-item:hover {
    background: var(--sb-hover);
    color: var(--sb-text-hover);
    text-decoration: none;
}

.nav-item.active {
    background: var(--sb-active-bg);
    color: var(--sb-text-active);
}

.nav-item.active::before {
    content: '';
    position: absolute;
    left: -6px;
    top: 20%;
    bottom: 20%;
    width: 3px;
    background: var(--brand);
    border-radius: 0 2px 2px 0;
}

/* Flashing indicator for nav items with pending action */
.nav-item-offen::after {
    content: '';
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--brand);
    animation: nav-offen-pulse 1.6s ease-in-out infinite;
}
@keyframes nav-offen-pulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 50%, transparent); }
    50%       { opacity: .7; box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 0%, transparent); }
}

.nav-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    opacity: 0.65;
    transition: opacity var(--ease);
}

.nav-item:hover .nav-icon,
.nav-item.active .nav-icon {
    opacity: 1;
}

.nav-divider {
    height: 1px;
    background: var(--sb-divider);
    margin: 5px 14px;
}

/* =================================================== */
/* Sidebar – Footer                                    */
/* =================================================== */
.sidebar-bottom {
    padding: 6px 0;
    border-top: 1px solid var(--sb-divider);
    flex-shrink: 0;
}

.version-string {
    font-size: calc(10rem / 14);
    color: var(--sb-text);
    opacity: 0.35;
    padding: 2px 20px 6px;
    white-space: nowrap;
}

/* Beide Zeilen des Fußes sind Links — „Datenschutz" und die Kennung der
   laufenden Version (führt auf die Änderungsseite). Sie teilen sich die Klasse,
   damit sie in einer Fluchtlinie stehen und dieselbe Trefferbreite haben:
   display: block zieht die Zeile über den ganzen Fuß, das senkrechte Padding
   wird dadurch erst wirksam. Der Ruhezustand bleibt opacity 0.35 auf
   --sb-text (oben) — eine Unterstreichung wäre dort unsichtbar, deshalb trägt
   hier der Farbwechsel den Zustand. Kein Rahmen, kein Hintergrund, wie
   .offcanvas-close/.dialog-close und wie .nav-item ohne Unterstreichung. */
a.version-string {
    display: block;
    cursor: pointer;
    transition: color var(--ease), opacity var(--ease);
}

a.version-string:hover,
a.version-string:focus-visible {
    color: var(--brand);
    opacity: 0.85;
    text-decoration: none;
}

/* =================================================== */
/* Upload overlay (app-main drag target)               */
/* =================================================== */
.upload-overlay {
    display: none;
    position: absolute;
    inset: 0;
    z-index: 400;
    pointer-events: none;
}

#app-main.drag-active .upload-overlay {
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--brand) 10%, transparent);
    border: 2px dashed var(--brand);
    border-radius: var(--r);
}

.upload-overlay-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    color: var(--brand);
    font-size: calc(18rem / 14);
    font-weight: 600;
    pointer-events: none;
    user-select: none;
}

.upload-overlay-inner svg {
    width: 52px;
    height: 52px;
}

/* =================================================== */
/* Top Bar                                             */
/* =================================================== */
.top-bar {
    height: var(--tb-h);
    background: var(--tb-bg);
    border-bottom: 1px solid var(--tb-border);
    display: flex;
    align-items: center;
    padding: 0 10px 0 14px;
    gap: 2px;
    flex-shrink: 0;
    box-shadow: var(--shadow-xs);
}

.top-bar .title {
    flex: 0 1 auto;
    font-size: calc(15rem / 14);
    font-weight: 600;
    color: var(--t1);
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0 6px;
    letter-spacing: -0.01em;
}

/* Die Stimme in der Topbar: die Pille neben dem Namen.

   Sie traegt den Ton als Flaeche und den Buchstaben in --bg-card. Die Umkehr
   ist noetig, weil die Topbar in beiden Themen dieselbe Farbe hat wie die
   Karte (--tb-bg = --bg-card, #ffffff bzw. #1a1a2e): eine kartenfarbene Pille
   waere dort unsichtbar, waehrend sie gegen den Ton in beiden Themes liest.
   Das Verhaeltnis ist richtungsunabhaengig, die 4,5:1 des Tokenkommentars
   gelten also getauscht weiter (hell Sopran 4,7 · Alt 6,0 · Tenor 6,7 ·
   Bass 9,8; dunkel dunkle Schrift auf Pastell 7,4-10,2).

   In calc(Nrem / 14) wie alles, was Text traegt, damit Pille und Buchstabe mit
   der Schriftgroessen-Einstellung der Sidebar mitwachsen.

   Der Buchstabe steht im Template und nicht als generierter Inhalt: so steht er
   auch bei einem unbekannten Code (stimme-x) da, und fuer Screenreader und
   Copy-Paste bleibt er erhalten.

   Chorleiter und Musiker sind Rollen: neutraler Ton. Weil --t4 als Flaeche die
   4,5:1 nicht haelt (hell 2,5:1 gegen Weiss), hier --t3 (hell 4,8:1, dunkel
   6,8:1) — nur die Pille weicht ab, ein Strich und ein Rahmen duerfen leise
   sein, ein Buchstabe nicht. „Keine Stimme" (N) bekommt gar keine Pille: kein
   Ton heisst kein Marker, genau wie tables.py solche Zeilen ohne Klasse
   laesst. */
.stimme-pille {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    flex: none;
    margin-left: calc(2rem / 14);
    min-width: calc(18rem / 14);
    height: calc(17rem / 14);
    padding: 0 calc(2rem / 14);
    border-radius: 999px;
    font-size: calc(10rem / 14);
    font-weight: 700;
    line-height: 1;
    background: var(--stimme-farbe-text, var(--t3));
    color: var(--bg-card);
}
.stimme-pille.stimme-c,
.stimme-pille.stimme-m { background: var(--t3); }
.stimme-pille.stimme-n { display: none; }

/* Section icon left of the topbar title */
.topbar-icon {
    width: 17px;
    height: 17px;
    flex-shrink: 0;
    color: var(--t3);
    stroke: currentColor;
    display: block;
    margin-left: 4px;
}

/* Filter chips in topbar */
.filter-chips {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 1;
    min-width: 0;
    overflow: hidden;
}
.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 0 5px;
    height: 16px;
    font-size: calc(10rem / 14);
    font-weight: 600;
    border-radius: 3px;
    white-space: nowrap;
    text-decoration: none;
    line-height: calc(16rem / 14);
    transition: opacity var(--ease);
}
.filter-chip:hover { opacity: 0.8; }
.filter-chip--default { background: var(--bg-row-hover); color: var(--t3); }
.filter-chip--true  { background: #dcfce7; color: #166534; }
.filter-chip--false { background: #fee2e2; color: #991b1b; }
.filter-chip-x {
    font-size: calc(10rem / 14);
    font-weight: 700;
    opacity: 0.55;
    line-height: 1;
}
.filter-chip:hover .filter-chip-x { opacity: 1; }

/* Das „+n" der abgekuerzten Filterkette: eine Schaltflaeche, kein Link -- es entfernt
   nichts, es oeffnet den Filter. */
button.filter-chip {
    font-family: inherit;
    border: 1px dashed var(--border-dark);
    background: transparent;
    color: var(--t2);
    cursor: pointer;
}
button.filter-chip:hover { opacity: 1; border-color: var(--brand); color: var(--brand-text); }
/* Das Konnektorwort zwischen zwei Bedingungen. Traegt die Logik der Kette und darf
   deshalb nicht wie ein Chip aussehen, den man wegklicken kann. */
.filter-verb,
.filter-klammer {
    flex-shrink: 0;
    font-size: calc(10rem / 14);
    font-weight: 600;
    color: var(--t3);
}
.filter-klammer { color: var(--t4); }

[data-theme="dark"] .filter-chip--default { background: rgba(255,255,255,0.08); color: var(--t3); }
[data-theme="dark"] .filter-chip--true  { background: rgba(16,185,129,0.20); color: #6ee7b7; }
[data-theme="dark"] .filter-chip--false { background: rgba(239,68,68,0.20); color: #fca5a5; }

.breadcrumb-nav {
    flex: 1;
    display: flex;
    align-items: center;
    min-width: 0;
    overflow: hidden;
    padding: 0 6px;
    gap: 2px;
    font-size: calc(14rem / 14);
}

.breadcrumb-seg {
    white-space: nowrap;
    color: var(--brand);
    text-decoration: none;
    font-weight: 500;
    flex-shrink: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.breadcrumb-seg:hover { text-decoration: underline; }

.breadcrumb-current {
    color: var(--t1);
    font-weight: 600;
    pointer-events: none;
}

.breadcrumb-sep {
    color: var(--t4);
    flex-shrink: 0;
    padding: 0 2px;
    font-size: calc(13rem / 14);
}

/* ─── Top Bar Icons ──────────────────────────────── */
.hamburger {
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--r-sm);
    cursor: pointer;
    color: var(--tb-icon);
    flex-shrink: 0;
    transition: background var(--ease), color var(--ease);
    stroke: currentColor;
}

.hamburger:hover {
    background: var(--hover-icon-bg);
    color: var(--brand);
}

.toolicon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    color: var(--tb-icon);
    transition: color var(--ease);
    stroke: currentColor;
}

/* Auf-/Zuklappen-Button: Icon dreht sich mit dem Zustand */
.kf-toggle-all-icon {
    transition: transform var(--ease), color var(--ease);
}
.kf-toggle-all-open .kf-toggle-all-icon {
    transform: rotate(180deg);
}

.top-bar a {
    display: flex;
    align-items: center;
    padding: 7px;
    border-radius: var(--r-sm);
    transition: background var(--ease);
}

.top-bar a:hover {
    background: var(--hover-icon-bg);
    text-decoration: none;
}

.top-bar a:hover .toolicon { color: var(--brand); }

.topbar-actions button {
    display: flex;
    align-items: center;
    padding: 7px;
    border: none;
    background: none;
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: background var(--ease);
    color: var(--tb-icon);
}
.topbar-actions button:hover { background: var(--hover-icon-bg); }
.topbar-actions button:hover .toolicon { color: var(--brand); }

.topbar-actions {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-left: auto;
    flex-shrink: 0;
}

/* ─── Top Bar Search ─────────────────────────────── */
.topbar-search {
    position: relative;
    display: flex;
    align-items: center;
    flex-shrink: 0;
    margin: 0 2px;
}

.topbar-search-icon {
    position: absolute;
    left: 9px;
    width: 14px;
    height: 14px;
    color: var(--tb-icon);
    pointer-events: none;
    stroke: currentColor;
    transition: color var(--ease);
}

.topbar-search input[type="search"] {
    width: 150px;
    height: 30px;
    font-family: var(--font);
    font-size: calc(13rem / 14);
    color: var(--t1);
    background: var(--bg-app);
    border: 1px solid transparent;
    border-radius: 999px;
    padding: 0 12px 0 30px;
    outline: none;
    transition: width var(--ease), background var(--ease),
                border-color var(--ease), box-shadow var(--ease);
}

.topbar-search input[type="search"]::placeholder { color: var(--t4); }

.topbar-search input[type="search"]::-webkit-search-cancel-button { cursor: pointer; }

.topbar-search input[type="search"]:hover { background: var(--hover-icon-bg); }

.topbar-search input[type="search"]:focus {
    width: 220px;
    background: var(--bg-card);
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

.topbar-search:focus-within .topbar-search-icon { color: var(--brand); }

.hamburger { display: none; }

/* ─── Sidebar Submenu ────────────────────────────── */
.nav-submenu {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.2s ease;
}

.nav-submenu.open {
    max-height: calc(300rem / 14);
}

.nav-subitem {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 12px 6px 38px;
    margin: 1px 6px;
    border-radius: var(--r-sm);
    color: var(--sb-text);
    text-decoration: none;
    font-size: calc(13rem / 14);
    font-weight: 500;
    cursor: pointer;
    border: none;
    background: none;
    width: calc(100% - 12px);
    white-space: nowrap;
}

.nav-subitem:hover {
    background: var(--sb-hover);
    color: var(--sb-text-hover);
    text-decoration: none;
}

.nav-subitem .nav-icon {
    width: 14px;
    height: 14px;
}

/* Schriftgroesse: Zeile mit eigenen Knoepfen, selbst kein Klickziel */
.nav-subitem.schriftgroesse { cursor: default; padding-right: 6px; }
.nav-subitem.schriftgroesse:hover { background: none; color: var(--sb-text); }
.schriftgroesse-steuerung {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: calc(3rem / 14);
}
.schriftgroesse-btn {
    width: calc(20rem / 14);
    height: calc(20rem / 14);
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--sb-divider);
    border-radius: 50%;
    background: none;
    color: var(--sb-text);
    font-family: inherit;
    font-size: calc(13rem / 14);
    line-height: 1;
    font-weight: 600;
    cursor: pointer;
    touch-action: manipulation;
}
.schriftgroesse-btn:hover:not(:disabled) {
    background: var(--sb-hover);
    color: var(--sb-text-hover);
}
.schriftgroesse-btn:disabled { opacity: 0.4; cursor: default; }

/* Mein Profil: die ganze Zeile oeffnet das Profil (gestreckter Link), der Stift
   rechts die Bearbeitung — er liegt darueber und faengt seinen Klick selbst. */
.nav-subitem.nav-profil { position: relative; padding-right: 6px; }
.nav-profil-link {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1;
    min-width: 0;
    color: inherit;
    text-decoration: none;
}
.nav-profil-link:hover { color: inherit; text-decoration: none; }
.nav-profil-link::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
}
.nav-profil-bearbeiten {
    position: relative;
    z-index: 1;
    margin-left: auto;
    width: calc(22rem / 14);
    height: calc(22rem / 14);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border: 1px solid var(--sb-divider);
    border-radius: 50%;
    color: var(--sb-text);
}
.nav-profil-bearbeiten:hover {
    background: var(--sb-hover);
    color: var(--sb-text-hover);
    border-color: currentColor;
}
.nav-subitem .nav-profil-bearbeiten .nav-icon { width: 12px; height: 12px; }
.schriftgroesse-wert {
    min-width: 3em;
    text-align: center;
    font-size: calc(11rem / 14);
    opacity: 0.7;
    font-variant-numeric: tabular-nums;
}

.nav-chevron {
    width: 12px;
    height: 12px;
    margin-left: auto;
    flex-shrink: 0;
    opacity: 0.45;
    transition: transform 0.2s ease;
}

.nav-item-settings.open .nav-chevron {
    transform: rotate(180deg);
}

/* =================================================== */
/* Content Area                                        */
/* =================================================== */
.content {
    flex: 1;
    overflow-y: auto;
    background: var(--bg-app);
    position: relative;
    min-height: 0;
}

.content header {
    background: var(--bg-card);
    padding: 12px 20px;
    border-bottom: 1px solid var(--border);
}

.content h2 {
    margin: 0 0 8px;
    color: var(--t1);
    font-size: 1.2rem;
}

/* =================================================== */
/* Buttons                                             */
/* =================================================== */
button,
.btn,
a.btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    background: var(--brand);
    color: #fff;
    border: none;
    border-radius: var(--r-sm);
    font-size: calc(13rem / 14);
    font-weight: 500;
    font-family: var(--font);
    cursor: pointer;
    transition: background var(--ease), box-shadow var(--ease);
    text-decoration: none;
    line-height: 1.4;
    white-space: nowrap;
    letter-spacing: 0.01em;
}

button:hover,
.btn:hover,
a.btn:hover {
    background: var(--brand-dark);
    text-decoration: none;
    box-shadow: 0 2px 10px color-mix(in srgb, var(--brand) 28%, transparent);
}

/* Gesperrter Knopf — die Deckkraft traegt die Themefarbe mit, hell wie dunkel.
   Bewusst an einer eigenen Klasse statt an button:disabled: global wuerde
   pointer-events den Tooltip am gesperrten Loeschen-Knopf (gruppen.html) und
   den cursor: wait der Anwesenheitsspeicherung schlucken.
   pointer-events statt :hover:not(:disabled), weil ein solcher Ausschluss an
   den Hover-Regeln oben deren Spezifitaet ueber .btn-danger:hover hoebe und den
   Loeschen-Knopf beim Ueberfahren markenfarben faerbte.  Der erklaerende
   Tooltip haengt ohnehin am umschliessenden Element, nicht am Knopf. */
.btn.btn-gesperrt:disabled {
    opacity: 0.45;
    box-shadow: none;
    pointer-events: none;
}

.btn-secondary,
a.btn-secondary {
    background: transparent;
    color: var(--t2);
    border: 1px solid var(--border-dark);
    box-shadow: none;
}

.btn-secondary:hover,
a.btn-secondary:hover {
    background: var(--bg-app);
    border-color: var(--t4);
    color: var(--t1);
    box-shadow: none;
}

.btn-sm { padding: 4px 10px; font-size: calc(12rem / 14); }
.btn-danger { background: var(--error-solid); }
.btn-danger:hover { background: var(--error-solid-hover); box-shadow: 0 2px 10px rgba(197, 48, 48, 0.28); }
.text-muted { color: var(--t4); }

/* =================================================== */
/* Forms & Inputs                                      */
/* =================================================== */
input[type="text"],
input[type="password"],
input[type="email"],
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="number"],
input[type="tel"],
input[type="url"],
select,
textarea {
    font-family: var(--font);
    font-size: calc(13rem / 14);
    color: var(--t1);
    background: var(--bg-card);
    border: 1px solid var(--border-dark);
    border-radius: var(--r-sm);
    padding: 7px 10px;
    transition: border-color var(--ease), box-shadow var(--ease);
    outline: none;
    width: 100%;
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

input::placeholder,
textarea::placeholder {
    color: var(--t4);
}

label {
    font-size: calc(13rem / 14);
    font-weight: 500;
    color: var(--t2);
    display: block;
    margin-bottom: 4px;
}

.form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px 16px;
    padding: 8px 0;
}

.form-grid .form-group {
    display: contents;
}

.form-group {
    margin-bottom: 10px;
}

.inline-input {
    font-family: var(--font);
    font-size: calc(13rem / 14);
    color: var(--t1);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    padding: 4px 8px;
    width: 100%;
    transition: border-color var(--ease), box-shadow var(--ease);
    outline: none;
    resize: none;
}

.inline-input:focus {
    background: var(--bg-card);
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

.inline-input[readonly] {
    color: var(--t3);
}

.invalid-feedback {
    font-size: calc(11.5rem / 14);
    color: var(--error-text);
    margin-top: 3px;
}

.form-privacy {
    grid-column: 1 / -1;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    justify-self: end;
    margin: -4px 0 2px;
    font-size: calc(12rem / 14);
    color: var(--t2);
    cursor: pointer;
    user-select: none;
}
.form-privacy input[type="checkbox"] {
    margin: 0;
}

.error,
ul.errorlist {
    background: var(--error-bg);
    color: var(--error-text);
    border: 1px solid var(--error-border);
    border-radius: var(--r-sm);
    padding: 10px 14px;
    margin: 8px 0;
    list-style: none;
    font-size: calc(13rem / 14);
}

/* =================================================== */
/* Table View (full-height layout)                     */
/* =================================================== */

/* Fills the content area so .table-container gets a defined height */
.table-view {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}

/* =================================================== */
/* Tables                                              */
/* =================================================== */
.table-container {
    background: var(--bg-card);
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border);
    /* Fills the table-view and scrolls — giving sticky thead its scroll context */
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: auto;
}

table,
.forum table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font);
    font-size: calc(13rem / 14);
    background: var(--bg-card);
    margin: 0;
}

thead th {
    position: sticky;
    top: 0;
    background: var(--bg-thead);
    z-index: 2;
    border-bottom: 1px solid var(--border);
}

th {
    padding: 9px 12px;
    text-align: left;
    font-size: calc(11rem / 14);
    font-weight: 700;
    color: var(--t3);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    position: relative;
}

th.orderable:hover {
    background: var(--hover-bg);
    color: var(--t1);
}

th.orderable a {
    text-decoration: none;
    color: inherit;
    display: flex;
    align-items: center;
    gap: 4px;
}

td {
    padding: 9px 12px;
    border-bottom: 1px solid var(--bg-row-hover);
    color: var(--t2);
    vertical-align: middle;
}

tr:last-child td { border-bottom: none; }

tr[data-href] { cursor: pointer; }

/* Zebrastreifen zur Zeilenverfolgung. :where() zaehlt nicht mit, die Regel
   wiegt so viel wie der Hover darunter und verliert gegen ihn, gegen
   Drag-over (!important) und die row-fresh-Animation.
   Tabellen mit eigener Zeilenfaerbung stehen in der :not()-Liste. Die
   Mitgliederliste stand frueher hier, faerbt ihre Zeilen aber nicht mehr —
   die Stimme sitzt jetzt im Balken (siehe .row-stimme-*). */
:where(table:not(.wiki-table, .perm-matrix, .diff-unified, .diff))
    tbody tr:nth-child(even) td { background: var(--bg-row-alt); }

tbody tr:hover td { background: var(--bg-row-hover); }

th.right, td.right { text-align: right; }
th.center, td.center { text-align: center; }
/* Sortierbare Kopfzellen tragen das Label in einem Flex-Link, an dem
   text-align abprallt; die Ausrichtung muss dort als justify-content stehen. */
th.right a { justify-content: flex-end; }
th.center a { justify-content: center; }

/* Zahlenspalte: so schmal wie ihr Inhalt, rechtsbuendig, gleich breite Ziffern. */
th.zahl, td.zahl {
    width: 1%;
    white-space: nowrap;
    text-align: right;
    font-variant-numeric: tabular-nums;
}
th.zahl a { justify-content: flex-end; }

/* Kategorie der Forenliste: so schmal wie ihr Inhalt. */
th.kategorie, td.kategorie { width: 1%; white-space: nowrap; }

th.asc a::after  { content: " ↑"; color: var(--brand); font-size: calc(10rem / 14); font-weight: 700; }
th.desc a::after { content: " ↓"; color: var(--brand); font-size: calc(10rem / 14); font-weight: 700; }

time {
    font-size: calc(11.5rem / 14);
    color: var(--t4);
}

.table-container img { max-width: 100%; height: auto; }

/* =================================================== */
/* Konzert Split Layout                                */
/* =================================================== */
.split-layout {
    display: flex;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

.split-layout input[name="csrfmiddlewaretoken"] { display: none; }

.split-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--bg-card);
    border: 1px solid var(--border);
}

.split-panel--konzert {
    width: 60%;
    flex: 0 0 auto;
    border-radius: var(--r) 0 0 var(--r);
    border-right: none;
}

.split-panel--pool {
    width: 40%;
    flex: 0 0 auto;
    border-radius: 0 var(--r) var(--r) 0;
}

.split-divider {
    width: 5px;
    background: var(--border);
    cursor: col-resize;
    flex-shrink: 0;
    position: relative;
    transition: background var(--ease);
}

.split-divider:hover,
.split-divider.dragging {
    background: var(--brand);
}

/* Touch target for divider */
.split-divider::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: -8px;
    right: -8px;
}

.split-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 16px;
    height: 36px;
    border-bottom: 2px solid var(--brand);
    flex-shrink: 0;
    background: var(--bg-card);
}

.split-header strong {
    font-size: 0.875rem;
    color: var(--t1);
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.pool-search {
    position: relative;
    display: flex;
    align-items: center;
}
.pool-search-icon {
    position: absolute;
    left: 7px;
    width: 13px;
    height: 13px;
    color: var(--t4);
    pointer-events: none;
    stroke: currentColor;
    transition: color var(--ease);
}
.pool-search input[type="search"] {
    width: 120px;
    height: 28px;
    font-family: var(--font);
    font-size: calc(13rem / 14);
    color: var(--t1);
    background: var(--bg-app);
    border: 1px solid transparent;
    border-radius: 999px;
    padding: 0 10px 0 26px;
    outline: none;
    transition: width var(--ease), background var(--ease),
                border-color var(--ease), box-shadow var(--ease);
}
.pool-search input[type="search"]::placeholder { color: var(--t4); }
.pool-search input[type="search"]::-webkit-search-cancel-button { cursor: pointer; }
.pool-search input[type="search"]:hover { background: var(--hover-icon-bg); }
.pool-search input[type="search"]:focus {
    width: 180px;
    background: var(--bg-card);
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}
.pool-search:focus-within .pool-search-icon { color: var(--brand); }

.split-body {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 4px 0;
}

.split-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 16px;
    border-bottom: 1px solid var(--bg-row-hover);
    transition: background var(--ease);
    font-size: calc(13rem / 14);
    user-select: none;
}

.split-item:hover { background: var(--hover-bg); }

.split-item-handle {
    flex-shrink: 0;
    color: var(--t4);
    font-size: calc(14rem / 14);
    cursor: grab;
    opacity: 0.25;
    transition: opacity var(--ease);
    line-height: 1;
}

.split-item:hover .split-item-handle,
.split-item-handle:active { opacity: 1; }

.split-item-pos {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--brand);
    color: #fff;
    font: 700 calc(11rem / 14) var(--mono);
    font-variant-numeric: tabular-nums;
}

.split-item-titel {
    flex: 1;
    min-width: 0;
    color: var(--t1);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 500;
}

.split-item-eig {
    flex-shrink: 0;
    white-space: nowrap;
    font-size: 0;  /* collapse chip whitespace */
}

.split-item-eig .eig-chip { margin-left: 3px; }
.split-item-eig .eig-chip:first-child { margin-left: 0; }

.split-empty {
    padding: 32px 16px;
    text-align: center;
    color: var(--t4);
    font-size: calc(13rem / 14);
}

/* Drag feedback */
.split-item.sortable-ghost {
    opacity: 0.3;
    background: var(--brand-light);
}

.split-item.sortable-chosen {
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
    border-radius: var(--r);
}

.split-item.sortable-drag {
    opacity: 0.9;
}

/* Dark mode */
[data-theme="dark"] .split-item-pos {
    background: var(--brand-dark);
}


[data-theme="dark"] .split-item.sortable-chosen {
    box-shadow: 0 2px 8px rgba(0,0,0,0.40);
}

[data-theme="dark"] .split-divider:hover,
[data-theme="dark"] .split-divider.dragging {
    background: var(--brand);
}

/* Mobile: stack vertically */
@media (max-width: 600px) {
    .split-layout {
        flex-direction: column;
    }
    .split-divider {
        width: auto;
        height: 5px;
        cursor: row-resize;
    }
    .split-divider::after {
        left: 0;
        right: 0;
        top: -8px;
        bottom: -8px;
    }
    .split-panel--konzert {
        width: auto;
        height: 50%;
        border-radius: var(--r) var(--r) 0 0;
        border-right: 1px solid var(--border);
        border-bottom: none;
    }
    .split-panel--pool {
        width: auto;
        flex: 1;
        border-radius: 0 0 var(--r) var(--r);
    }
}

/* =================================================== */
/* Offcanvas Panels                                    */
/* =================================================== */
.offcanvas {
    position: fixed;
    top: var(--tb-h);
    right: 0;
    height: calc(100% - var(--tb-h));
    background: var(--bg-card);
    box-shadow: -2px 0 16px rgba(0,0,0,0.10);
    transform: translateX(calc(100% + 2px));
    transition: transform var(--ease);
    overflow-y: auto;
    padding: 16px;
    z-index: 500;
    border-left: 1px solid var(--border);
    font-size: calc(13rem / 14);
}

.offcanvas.open { transform: translateX(0); }

.offcanvas-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
}
.offcanvas-header strong { font-size: 0.875rem; color: var(--t1); }
.offcanvas-close {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.1rem;
    color: var(--text-muted);
    padding: 0 4px;
    line-height: 1;
}
.offcanvas-close:hover { color: var(--brand); }

#ColumnSelector { width: 200px; z-index: 503; }
#Filter         { width: 320px; z-index: 501; }
@media (max-width: 480px) {
    #Filter     { width: 100%; max-width: 360px; }
}
#Action         { width: min(300px, calc(100vw - 24px)); z-index: 502; display: flex; flex-direction: column; gap: 8px; padding: 12px; }
#AddPanel       { width: 420px; z-index: 504; font-size: 1rem; }
.add-panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
    padding-bottom: 10px;
    border-bottom: 2px solid var(--brand);
}
.add-panel-header strong { font-size: 1rem; color: var(--t1); }
.add-panel-close {
    background: none; border: none; cursor: pointer;
    font-size: 1.2rem; color: var(--text-muted); padding: 0 4px;
}
.add-panel-close:hover { color: var(--brand); }
.add-panel form .form-group { margin-bottom: 14px; }
.add-panel form label { display: block; font-size: 0.875rem; font-weight: 600; margin-bottom: 4px; color: var(--t2); }
.add-panel form .checkbox-label { display: flex; align-items: center; gap: 8px; font-weight: normal; }
.add-panel form input[type="text"],
.add-panel form input[type="email"],
.add-panel form input[type="password"],
.add-panel form input[type="number"],
.add-panel form input[type="date"],
.add-panel form input[type="datetime-local"],
.add-panel form select,
.add-panel form textarea { width: 100%; }
.add-panel-checkboxes { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
.add-panel-checkboxes label { display: flex; align-items: center; gap: 6px; font-weight: normal; font-size: 0.875rem; }
.add-panel-actions { display: flex; gap: 10px; margin-top: 20px; }
.add-panel-actions .btn { flex: 1; }
.add-panel-hint { font-size: 0.8rem; color: var(--t3); margin: 8px 0 16px; line-height: 1.4; }
.artikel-add-label { display: block; font-size: 0.875rem; font-weight: 600; margin-bottom: 6px; color: var(--t2); }
.artikel-add-input {
    width: 100%;
    padding: 12px 14px;
    font-size: 1.05rem;
    font-family: var(--font);
    border: 1px solid var(--border-dark);
    border-radius: var(--r);
    background: var(--bg-card);
    color: var(--t1);
    outline: none;
    transition: border-color var(--ease), box-shadow var(--ease);
}
.artikel-add-input::placeholder { color: var(--t3); }
.artikel-add-input:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-ring); }
.artikel-add-input.is-invalid { border-color: #c53030; box-shadow: 0 0 0 3px rgba(197, 48, 48, 0.18); }
.artikel-add-error { display: none; margin-top: 6px; font-size: 0.8rem; color: #c53030; }
.artikel-add-input.is-invalid ~ .artikel-add-error { display: block; }

/* Dropzone fields in AddPanel */
.dropzone-field {
    border: 2px dashed var(--border-dark);
    border-radius: var(--r-sm);
    padding: 16px;
    text-align: center;
    cursor: pointer;
    min-height: 48px;
    margin-bottom: 8px;
    transition: border-color var(--ease), background var(--ease);
}
.dropzone-field:hover,
.dropzone-field.dz-drag-hover {
    border-color: var(--brand);
    background: var(--brand-light);
}
.dropzone-field-placeholder {
    font-size: 0.8125rem;
    color: var(--text-muted);
}
.dropzone-field-uploading {
    font-size: 0.8125rem;
    color: var(--t3);
}
.dropzone-field-done {
    font-size: 0.8125rem;
    color: var(--brand);
    font-weight: 600;
}
.dropzone-field-thumb {
    width: 32px;
    height: 32px;
    object-fit: cover;
    border-radius: var(--r-sm);
    vertical-align: middle;
    margin-right: 8px;
}

.action-header {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    padding-bottom: 4px;
    border-bottom: 1px solid var(--border);
}

.action-divider {
    border-top: 1px solid var(--border);
    margin: 4px 0;
}

.action-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* Aktionen sind eine Liste: volle Breite, Icon links, Text linksbündig —
   so bleibt jeder Button lesbar, egal wie lang die Beschriftung ist. */
.action-btn {
    width: 100%;
    justify-content: flex-start;
    text-align: left;
    flex-shrink: 0;
}

.action-btn svg { flex: 0 0 auto; }

.action-move-btns {
    display: grid;
    gap: 6px;
    flex: 0 0 auto;   /* auf niedrigen Fenstern schrumpft die Ordnerliste, nicht die Buttons */
}

.folder-picker {
    flex: 0 1 auto;   /* wächst nur mit dem Inhalt, gibt bei Platzmangel als Erstes nach */
    min-height: 0;
    max-height: 240px;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--bg-app);
}

.folder-picker-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 8px;
    font-size: 0.8125rem;
    cursor: pointer;
    border-radius: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--t2);
    margin: 0;
    font-weight: normal;
}

.folder-picker-item input[type="radio"] {
    flex-shrink: 0;
    accent-color: var(--brand);
}

.folder-picker-item:hover { background: var(--bg-row-hover); }

.folder-picker-item:has(input:checked) {
    background: var(--brand-light);
    color: var(--brand);
    font-weight: 600;
}

/* Native <dialog> styling */
.app-dialog {
    border: none;
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-md);
    padding: 24px 28px;
    min-width: 300px;
    font-family: var(--font);
    font-size: 0.9375rem;
    position: relative;
}

.app-dialog::backdrop {
    background: rgba(0, 0, 0, 0.35);
}

.app-dialog h3 {
    margin: 0 0 16px;
    font-size: 1rem;
    font-weight: 700;
    color: var(--t1);
}

.dialog-close {
    position: absolute;
    top: 12px;
    right: 14px;
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.1rem;
    color: var(--text-muted);
    padding: 0 4px;
    line-height: 1;
}
.dialog-close:hover { color: var(--brand); }

.app-dialog input[type="text"] {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border-dark);
    border-radius: var(--r-sm);
    font-size: 0.9375rem;
    font-family: var(--font);
    margin-bottom: 16px;
    outline: none;
}

.app-dialog input[type="text"]:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

.dialog-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}

/* ─── File ID column in Ordner table ────────────────── */
.file-id-cell {
    font-size: 0.75rem;
    color: var(--text-muted);
    white-space: nowrap;
    width: 1%;
    user-select: all;
}

/* ─── Inline new-folder row ─────────────────────────── */
.nf-row td { padding-top: 6px; padding-bottom: 6px; }
.nf-name-cell { display: flex; align-items: center; gap: 6px; }
.nf-input {
    flex: 1;
    min-width: 0;
    padding: 4px 8px;
    border: 1px solid var(--border-dark);
    border-radius: var(--r-sm);
    font-size: 0.875rem;
    font-family: var(--font);
    background: var(--bg-card);
    color: var(--t1);
    outline: none;
}
.nf-input:focus { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-ring); }
.nf-input.nf-error { border-color: #c53030; }
.nf-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: 1px solid var(--border-dark);
    border-radius: var(--r-sm);
    background: none;
    cursor: pointer;
    color: var(--t3);
    padding: 0;
    transition: color var(--ease), border-color var(--ease);
}
.nf-btn:hover { color: var(--brand); border-color: var(--brand); }
.nf-confirm { border-color: var(--border); }
[data-theme="dark"] .nf-input { background: var(--bg-card); }

/* ─── Filter offcanvas (redesigned) ──────────────── */
#Filter {
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
}

#Filter .offcanvas-header {
    padding: 12px 16px;
    margin-bottom: 0;
    flex-shrink: 0;
}

.filter-form {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.filter-body {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 14px 16px 8px;
}

/* Each field wrapper from {{ form.as_div }} */
.filter-body > div {
    display: flex;
    flex-direction: column;
    margin-bottom: 14px;
}

.filter-body > div:last-child { margin-bottom: 0; }

/* Field labels become section headers */
.filter-body label {
    font-size: calc(10.5rem / 14);
    font-weight: 700;
    color: var(--t3);
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* Inputs and selects */
.filter-body input[type="text"],
.filter-body input[type="number"],
.filter-body input[type="search"],
.filter-body select {
    width: 100%;
    padding: 8px 10px;
    font-size: calc(13rem / 14);
    font-family: inherit;
    color: var(--t1);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    transition: border-color var(--ease), box-shadow var(--ease);
}

.filter-body input[type="text"]:focus,
.filter-body input[type="number"]:focus,
.filter-body input[type="search"]:focus,
.filter-body select:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

/* ── Tri-state sliding toggle switch ── */
.tri-toggle-select { display: none !important; }

/* Row layout in filter panel: label left, control right */
.filter-body > div:has(.tri-toggle-wrap),
.filter-body > div:has(.filter-inline) {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}
.filter-body > div:has(.tri-toggle-wrap) label,
.filter-body > div:has(.filter-inline) label { margin-bottom: 0; }

.filter-body .filter-inline { width: auto; padding: 4px 6px; font-size: calc(11rem / 14); border-radius: 999px; }

/* ── Filter-Baukasten (Zeilen-Editor) ──
   Steht als erstes Kind in .filter-body, ueber den festen Feldern. Das Panel ist nur
   320px breit: eine Zeile stapelt ihre Bedienelemente, statt vier davon in eine
   Reihe zu zwaengen. */
.filter-baukasten { margin-bottom: 16px; }
.filter-zeile {
    background: var(--bg-app);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 10px 10px 2px;
    margin-bottom: 8px;
}
/* Verknuepfung, Feld, Operator und Kreuz in einer Reihe; die Auswahlen nehmen nur
   ihre Inhaltsbreite, das Kreuz steht immer rechts. Wird es zu eng, bricht der
   Operator um. */
.filter-zeile-kopf {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 8px;
}
.filter-zeile-auswahl {
    width: auto !important;
    max-width: 100%;
    padding: 4px 6px !important;
    font-size: calc(12rem / 14) !important;
}
.filter-zeile-auswahl[hidden] { display: none; }
/* Der Konnektor beschriftet die Zeile, er ist kein Formularfeld wie die anderen --
   deshalb die kleine, gesperrte Form statt der vollen Select-Hoehe. */
.filter-zeile-verbindung {
    width: auto !important;
    padding: 2px 6px !important;
    font-size: calc(10.5rem / 14) !important;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--brand-text) !important;
}
.filter-zeile-weg {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--t4);
    font-size: 1rem;
    line-height: 1;
    padding: 0 4px;
    margin-left: auto;
}
.filter-zeile-weg:hover { color: var(--brand); }
.filter-zeile-feld,
.filter-zeile-operator {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 8px;
}
.filter-zeile-feld > span,
.filter-zeile-operator > span {
    font-size: calc(10.5rem / 14);
    font-weight: 700;
    color: var(--t3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
/* Wert und Schalter nebeneinander. Ohne Schalter nimmt der Wert die Breite (Chip-
   Liste, Text); mit Schalter kollabiert er auf seinen Inhalt, damit die Pille direkt
   daneben sitzt. */
.filter-zeile-wertreihe {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}
.filter-zeile-werte { flex: 1 1 auto; min-width: 0; }
.filter-zeile-wertreihe:has([data-filter-schalter]) .filter-zeile-werte { flex: 0 1 auto; }
.filter-zeile-wertreihe:has([data-filter-schalter]) select { width: auto !important; max-width: 100%; }
.filter-zeile-schalterplatz:empty { display: none; }
.filter-zeile-wertreihe .tri-toggle,
.filter-fest .tri-toggle { flex: none; }
/* Die Zusage braucht zwei Auswahlen -- Termin und Antwort -- und der Offcanvas ist
   zu schmal fuer eine Reihe. */
.filter-zusage {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
/* Felder ohne Wert (Zugang): der Operator sagt alles, hier steht nur der Hinweis. */
.filter-ohne {
    margin: 0;
    font-size: calc(11rem / 14);
    color: var(--t3);
}
.filter-hinzufuegen { width: 100%; font-size: calc(12rem / 14); }
.filter-baukasten-leer {
    margin: 8px 0 0;
    font-size: calc(12rem / 14);
    color: var(--t3);
}
/* Die festen Ja/Nein-Schalter unter der Kette: ein kompaktes Zweierraster, je
   Zelle Bezeichnung und Pille. */
.filter-feste {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px 16px;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
}
.filter-fest {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-width: 0;
}
.filter-fest-label {
    font-size: calc(12rem / 14);
    color: var(--t2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Was nicht in eine Zeile passt: ein festes Feld unter der Kette (das Konzert des
   Repertoires). Optisch abgesetzt, damit es nicht wie eine Bedingung wirkt. */
.filter-zusatz {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
}
/* Ablauf-Ansicht: dort wird nicht gefiltert, und das soll dastehen. */
.split-hinweis {
    display: block;
    padding: 10px 16px 4px;
    font-size: calc(12rem / 14);
    color: var(--t3);
}

.tri-toggle-wrap { display: flex; align-items: center; }

/* The pill-shaped track */
.tri-toggle {
    position: relative;
    display: inline-flex;
    background: var(--bg-app);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 1px;
    user-select: none;
}

/* Sliding thumb — one segment wide, absolutely positioned */
.tri-toggle-thumb {
    position: absolute;
    top: 1px;
    left: 1px;
    width: 14px;
    height: calc(100% - 2px);
    border-radius: 999px;
    background: #ef4444;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
    pointer-events: none;
    z-index: 0;
    transition: transform .16s cubic-bezier(.4, 0, .2, 1),
                background .16s ease;
}

/* Thumb color by state — transform is set via JS/inline style */
.tri-toggle[data-value="false"]   .tri-toggle-thumb { background: #ef4444; }
.tri-toggle[data-value="unknown"] .tri-toggle-thumb { background: #9ca3af; }
.tri-toggle[data-value="true"]    .tri-toggle-thumb { background: #22c55e; }

[data-theme="dark"] .tri-toggle[data-value="false"]   .tri-toggle-thumb { background: #dc2626; }
[data-theme="dark"] .tri-toggle[data-value="unknown"] .tri-toggle-thumb { background: #4b5563; }
[data-theme="dark"] .tri-toggle[data-value="true"]    .tri-toggle-thumb { background: #16a34a; }

/* Segments sit above the thumb (z-index 1) */
.tri-toggle-seg {
    position: relative;
    z-index: 1;
    width: 14px;
    height: 13px;
    border: none;
    background: transparent;
    color: var(--t4);
    font-size: calc(9rem / 14);
    font-weight: 700;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    line-height: 1;
    transition: color .12s ease;
}

/* White text on the active (thumb-covered) segment */
.tri-toggle-seg.selected { color: #fff; }

/* Neutral hover highlight — covers the thumb color */
.tri-toggle-seg:hover { background: rgba(255, 255, 255, 0.45); border-radius: 999px; }
[data-theme="dark"] .tri-toggle-seg:hover { background: rgba(255, 255, 255, 0.12); }

/* Action buttons in the header bar */
.filter-header-actions {
    display: flex;
    align-items: center;
    gap: 6px;
}

.filter-header-actions .btn {
    padding: 4px 10px;
    font-size: calc(11rem / 14);
}

/* =================================================== */
/* Forum                                               */
/* =================================================== */

/* Full-height flex column so messages fill remaining space */
.forum-layout {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

.forum-entry {
    position: sticky;
    top: 0;
    background: var(--bg-card);
    z-index: 10;
    display: flex;
    align-items: flex-end;
    gap: 8px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-xs);
}

.text-container {
    display: flex;
    flex: 1;
    gap: 8px;
}

.forum-entry form {
    display: flex;
    flex: 1;
    gap: 8px;
    width: 100%;
    align-items: flex-end;
}

.forum-entry textarea {
    flex: 1;
    min-height: 68px;
    resize: vertical;
    font-size: calc(13rem / 14);
    padding: 8px 10px;
    line-height: 1.5;
}

.forum-entry button[type="submit"] {
    width: 34px;
    height: 34px;
    padding: 0;
    border-radius: 50%;
    background: var(--brand);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: none;
}

.forum-entry button[type="submit"]:hover {
    background: var(--brand-dark);
    box-shadow: 0 2px 8px color-mix(in srgb, var(--brand) 28%, transparent);
}

.forum-entry button[type="submit"]::before {
    content: "";
    border: solid #fff;
    border-width: 0 4px 4px 0;
    display: inline-block;
    padding: 4px;
    transform: translate(-2px, -1px) rotate(-45deg);
}

.messages {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 16px;
    background: var(--forum-bg);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* Unread markers (intern/forum_gelesen.py) */
tr.ungelesen td { font-weight: 600; color: var(--t1); }
/* Deaktiviertes Forum: nur die Schrift etwas heller, der Hintergrund bleibt. Steht
   hinter tr.ungelesen, damit es auch dessen dunkle Farbe überschreibt. */
tr.forum-inaktiv td { color: var(--t3); }
/* Ungelesen-Badge und Gesamtzahl stehen zusammen in der Zahlenspalte. Die Gesamtzahl
   braucht eine eigene Regel, weil die Zeile darüber fett und dunkel gesetzt ist. */
td.zahl .badge { margin-right: 6px; vertical-align: 1px; }
td.zahl .gesamtzahl { color: var(--text-muted); font-weight: 400; }

.forum-neu-trenner {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 8px 0;
    color: var(--brand);
    font-size: calc(11rem / 14);
    font-weight: 600;
}
.forum-neu-trenner::before,
.forum-neu-trenner::after {
    content: '';
    flex: 1;
    border-top: 1px solid color-mix(in srgb, var(--brand) 45%, transparent);
}

.message,
.message_me {
    display: flex;
    align-items: flex-start;
    font-size: calc(13.5rem / 14);
    line-height: 1.55;
}

.message_me { flex-direction: row-reverse; }

.message .avatar {
    width: 42px;
    margin-right: 10px;
    text-align: center;
    flex-shrink: 0;
}

.message_me .avatar { width: 0; }

.message .avatar img {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--bg-card);
    box-shadow: 0 1px 3px rgba(0,0,0,0.10);
    display: block;
}

.message .avatar div {
    margin-top: 3px;
    font-size: calc(10.5rem / 14);
    color: var(--t3);
}

div.avatar { cursor: pointer; }

.message .content {
    background: var(--msg-bg);
    border-radius: 2px 12px 12px 12px;
    padding: 8px 12px;
    max-width: 78%;
    width: max-content;
    flex: 0 1 auto;
    overflow-y: visible;
    box-shadow: var(--shadow-xs);
    border: 1px solid var(--msg-border);
}

.message_me .content_me {
    background: var(--msg-me-bg);
    border-radius: 12px 2px 12px 12px;
    padding: 8px 12px;
    max-width: 78%;
    width: max-content;
    box-shadow: var(--shadow-xs);
    border: 1px solid var(--msg-me-border);
}

.message .content p,
.message_me .content_me p { margin: 0; }

.message .content time,
.message_me .content_me time {
    display: block;
    font-size: calc(10.5rem / 14);
    color: var(--t4);
    margin-top: 3px;
    text-align: right;
}

/* ── Reaktionen (XEP-0444) ───────────────────────────────── */
.reactions {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 5px;
}
.reactions:empty { display: none; }

.reaction-chip {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: calc(12rem / 14);
    line-height: 1;
    padding: 3px 7px;
    border-radius: 11px;
    cursor: pointer;
    background: var(--bg-card);
    border: 1px solid var(--msg-border);
    color: var(--t3);
    transition: border-color .12s, background .12s;
}
.reaction-chip:hover { border-color: var(--brand); }
.reaction-chip.mine {
    background: color-mix(in srgb, var(--brand) 12%, var(--bg-card));
    border-color: var(--brand);
    color: var(--brand);
}

/* Dezenter "+"-Auslöser, erscheint beim Hover über der Nachricht. */
.reaction-add {
    align-self: center;
    margin: 0 6px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1px solid var(--msg-border);
    background: var(--bg-card);
    color: var(--t3);
    font-size: calc(15rem / 14);
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity .12s, border-color .12s, color .12s;
}
.message:hover .reaction-add,
.message_me:hover .reaction-add,
.reaction-add:focus-visible { opacity: 1; }
.reaction-add:hover { border-color: var(--brand); color: var(--brand); }

.reaction-picker {
    position: absolute;
    z-index: 1000;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px;
    max-width: 230px;
    padding: 6px;
    border-radius: 10px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-md);
}
.reaction-pick {
    border: 0;
    background: transparent;
    font-size: calc(19rem / 14);
    line-height: 1;
    padding: 4px;
    border-radius: 7px;
    cursor: pointer;
}
.reaction-pick:hover { background: var(--msg-border); }
.reaction-input {
    width: 46px;
    margin-left: 4px;
    padding: 4px 6px;
    font-size: calc(15rem / 14);
    border-radius: 7px;
    border: 1px solid var(--msg-border);
    background: var(--bg-card);
    color: var(--t2, var(--t3));
}

.message_me img,
.message img,
.message_me video,
.message video {
    max-width: 100%;
    max-height: 280px;
    height: auto;
    display: block;
    border-radius: var(--r-sm);
    border: 1px solid var(--border);
    margin-top: 4px;
}

.mention {
    background: var(--mention-bg);
    border: 1px solid var(--mention-border);
    padding: 1px 7px;
    border-radius: 10px;
    font-weight: 600;
    font-size: calc(12rem / 14);
    color: var(--mention-color);
}

.search-hl {
    background: var(--search-hl-bg);
    color: var(--search-hl-color);
    border-radius: 3px;
    padding: 0 2px;
    font-weight: 600;
}

/* ─── Forum Search Results ───────────────────────── */
.forum-search {
    height: 100%;
    overflow-y: auto;
    padding: 16px;
    background: var(--forum-bg);
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.forum-search-row {
    display: flex;
    align-items: flex-start;
    gap: 14px;
}

.forum-search-forum {
    flex-shrink: 0;
    width: 170px;
    padding-top: 9px;
    font-size: calc(12.5rem / 14);
    font-weight: 600;
    color: var(--brand);
    text-decoration: none;
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.forum-search-forum:hover { text-decoration: underline; }

.forum-search-msg {
    flex: 1;
    min-width: 0;
}

.forum-search-empty {
    color: var(--t3);
    font-size: calc(13rem / 14);
    padding: 24px 4px;
}

@media (max-width: 768px) {
    .forum-search-row { flex-direction: column; gap: 3px; }
    .forum-search-forum {
        width: auto;
        text-align: left;
        padding-top: 0;
    }
}

/* =================================================== */
/* Stimme: Mitgliederliste und Mitgliedskarte          */
/* =================================================== */
/* Stimme auf der Mitgliedskarte: die Seitenkante und der Portraetring.

   Vorher trug die Karte den Ruecken: eine 4-px-Kante am linken Rand eines
   760 px breiten Kastens mit Rand, Radius und Schatten. Der Kasten musste
   fallen — diese Seite ist laenger als der Rollbereich, also sind Ober- und
   Unterkante nie gleichzeitig im Bild und der weisse Block las sich als
   kaputt. Die Kante bleibt: sie wandert von der Karte eine Ebene hoch auf die
   Seite selbst und laeuft dort von Oberkante bis Unterkante, statt 20 px
   eingerueckt zu beginnen. Damit steht die Stimme bei jeder Scrollposition am
   Rand — genau die Eigenschaft, die den Ruecken vorher getragen hat.

   Auf der Kante steht kein Text, sie darf deshalb den Vollton tragen und
   stellt keine Kontrastfrage. padding-left 20 px + 4 px Kante = 24 px, also
   buendig mit dem padding von .detail-page auf allen anderen Detailseiten.

   Der Fallback ist transparent, nicht --border: ein 4-px-grauer Seitenrand
   waere ein Gestaltungselement ohne Aussage. „Kein Ton, kein Marker" gilt hier
   wie fuer die Zeile und die Pille. Die Geometrie bleibt gleich (die Kante ist
   immer 4 px breit), die Ausrichtung also unveraendert; nur die Farbe fehlt.

   Im dunklen Thema derselbe Ton zu 55 %, woertlich die Regel des Zeilenbalkens
   in der Mitgliederliste: die hellen Pastelle grellen als Vollton, und dieser
   Streifen ist ein Vielfaches so lang wie der Balken einer Zeile. C/M/N bleiben
   unberuehrt, --t4 ist bereits gedaempft.

   Der Ring um das Portraet ist die Stelle, an der die Stimme zuerst auffaellt,
   und die einzige ganz ohne Text — er traegt deshalb auch im dunklen Thema den
   Vollton, wie der Pillenbuchstabe in der Topbar. Das Portraet sitzt im
   .detail-icon der Detailseiten (56 px, border-radius var(--r)); die 3-px-Kante
   wirkt auf dieser kleineren Flaeche kraeftiger als auf dem alten 110-px-Bild.
   Sein Fallback bleibt --border: ein Fotorahmen ist auch ohne Ton unauffaellig.

   max-width ohne margin:auto: der Deckel haelt die Zeilenlaenge im Lesbaren
   (das zweispaltige Raster gaebe auf breiten Schirmen ueber 100 Zeichen je
   Zeile, .detail-card-content ist Fliesstext), aber die Seite bleibt
   linksbuendig wie ihre Geschwister und wird nicht wieder zur zentrierten
   Insel.

   --stimme-farbe kommt aus dem Setter weiter unten. Der Fallback haelt die
   Seite ohne Stimme („N") und bei unbekanntem Code (stimme-x) genau wie heute:
   gleiche Geometrie, nur ohne Ton. */
.detail-page.member-voice {
    max-width: 1100px;
    border-left: calc(4rem / 14) solid var(--stimme-farbe, transparent);
    padding-left: 20px;
}
[data-theme="dark"] .detail-page.member-voice {
    border-left-color: color-mix(in srgb, var(--stimme-farbe, transparent) 55%, transparent);
}
.member-voice .detail-icon {
    overflow: hidden;
    border: calc(3rem / 14) solid var(--stimme-farbe, var(--border));
}
.member-voice .detail-icon img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Stimme in der Mitgliederliste: Farbbalken statt Flaechen-Tint.

   Vorher faerbte die Stimme die ganze Zeile mit 7 % Deckkraft ein. Das hatte
   zwei Probleme: die sechs Toene der Kategorie-Palette standen zu dicht
   beieinander (Tenor und Musiker trennten auf Weiss 3,7 sRGB-Einheiten, also
   nichts), und .mitglied-table musste dafuer aus den Zebrastreifen
   aussteigen — womit die Zeilenverfolgung ueber die sehr breite Tabelle an
   ebendiesen 3,7 Einheiten hing.

   Jetzt bleibt die Zeile neutral (Zebra greift wieder, siehe die
   :where()-Regel weiter oben) und die Stimme sitzt in einem 4-px-Balken am
   linken Rand. Weil auf dem Balken kein Text steht, darf er Vollton sein —
   der kleinste Paarabstand liegt damit bei 100 statt 3,7.

   Der Balken ist ein inset-box-shadow, kein border: box-shadow malt ueber den
   Zellhintergrund und ueberlebt Zebra, Hover und die row-fresh-Animation ohne
   eine einzige Sonderregel. Inaktive Zeilen tragen row-inactive statt
   row-stimme-*, --stimme-farbe bleibt dort ungesetzt, der Fallback greift —
   die Vorrangregel „inaktiv schlaegt Stimme" bleibt so von selbst erhalten.

   Derselbe Setter bedient auch die Mitgliedskarte (Ruecken und Portraetring)
   und die Pille in ihrer Topbar; deshalb steht jede Zeile mit beiden Klassen
   da, statt die Zuordnung zweimal zu pflegen — die Deklarationen sind
   unveraendert. --stimme-farbe ist der Markierungston (Balken, Ruecken, Ring),
   --stimme-farbe-text der Ton, der als Flaeche lesbar bleibt (die Pille der
   Topbar). Kein .stimme-n: kein Ton, kein Marker — genau wie tables.py die
   Zeilenklasse fuer „keine Stimme" leer laesst.

   Chorleiter und Musiker sind keine Stimmlage, sondern Rollen: neutraler Ton.
   Sie tragen ihren Text in --t3 statt --t4, weil --t4 als Textfarbe die 4,5:1
   nicht haelt (hell 2,2:1 auf der Tintflaeche, die .stimme-merged-inner
   beschriftet). --stimme-farbe bleibt --t4: Balken und Ruecken duerfen leise
   sein, ein Buchstabe nicht. */
.row-stimme-s, .stimme-s { --stimme-farbe: var(--stimme-s); --stimme-farbe-text: var(--stimme-s-text); }
.row-stimme-a, .stimme-a { --stimme-farbe: var(--stimme-a); --stimme-farbe-text: var(--stimme-a-text); }
.row-stimme-t, .stimme-t { --stimme-farbe: var(--stimme-t); --stimme-farbe-text: var(--stimme-t-text); }
.row-stimme-b, .stimme-b { --stimme-farbe: var(--stimme-b); --stimme-farbe-text: var(--stimme-b-text); }
.row-stimme-c, .stimme-c { --stimme-farbe: var(--t4);       --stimme-farbe-text: var(--t3); }
.row-stimme-m, .stimme-m { --stimme-farbe: var(--t4);       --stimme-farbe-text: var(--t3); }

table.mitglied-table tbody td:first-child {
    box-shadow: inset 4px 0 0 var(--stimme-farbe, transparent);
}

.row-inactive td { background: var(--bg-app); }


.avatar-circle {
    border-radius: 50%;
    object-fit: cover;
    display: block;
}

table.mitglied-table tbody td {
    border-bottom: 1px solid var(--border);
}

table.mitglied-table tr.stimme-group-start td {
    border-top: 2px solid var(--border);
}

/* Der senkrecht beschriftete Gruppenstreifen, den tabelle.js beim Sortieren
   nach Stimme per rowSpan aufzieht. Er traegt die Stimmfarbe als kraeftigen
   Tint — der Streifen grenzt damit selbst ab und braucht die frueheren grauen
   Raender nicht mehr. 16 % ist die Obergrenze, bei der die abgeleitete
   Textfarbe darauf noch ihre 4,5:1 haelt. */
.stimme-merged-cell {
    position: relative;
    padding: 0;
    width: 24px;
    background: color-mix(in srgb, var(--stimme-farbe, var(--bg-card)) 16%, var(--bg-card)) !important;
}

.stimme-merged-inner {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    writing-mode: vertical-rl;
    color: var(--stimme-farbe-text, var(--t2));
    font-weight: 700;
    font-size: calc(11rem / 14);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* =================================================== */
/* Detail Pages                                        */
/* =================================================== */
.detail-page {
    padding: 20px 24px;
}

.detail-header {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 24px;
}

.detail-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: var(--r);
    background: var(--brand-light);
    color: var(--brand);
    flex-shrink: 0;
}

.detail-info h1 {
    margin: 0;
    font-size: 1.3rem;
    color: var(--t1);
    font-weight: 600;
}

.detail-subtitle {
    margin: 4px 0 0;
    font-size: 0.85rem;
    color: var(--t4);
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}

.detail-cards {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}

.detail-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r);
    padding: 16px 20px;
    box-shadow: var(--shadow-sm);
    /* Grid-Kinder schrumpfen sonst nicht unter ihre Inhaltsbreite und ragen
       auf dem Handy rechts aus dem Bild (mit grosser Schrift noch weiter). */
    min-width: 0;
}

/* Map card: flex column so the map fills remaining card height */
.detail-card:has(.detail-map) {
    display: flex;
    flex-direction: column;
}

.detail-card h3 {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--brand-text);
    margin: 0 0 12px;
    padding-bottom: 8px;
    border-bottom: 2px solid var(--brand);
    display: flex;
    align-items: center;
    gap: 8px;
}

.detail-card h3 a {
    color: inherit;
    text-decoration: none;
}

.detail-card h3 a:hover {
    text-decoration: underline;
}

.detail-card h3 .h3-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}

.detail-card h3 a.h3-edit {
    display: inline-flex;
    align-items: center;
    opacity: 0.4;
    text-decoration: none;
}

.detail-card h3 a.h3-edit:hover {
    opacity: 1;
}

.detail-card-content {
    font-size: calc(14rem / 14);
    line-height: 1.6;
    color: var(--t2);
}

/* Die Karte „Extern“ zeigt den Ankündigungstext aus dem Altsystem, und der
   bringt eigenes Markup mit. Die Umbruchregel ist keine Kosmetik: die Altdaten
   enthalten URLs von über 100 Zeichen, die in der halben Karte sonst rechts
   aus dem Kasten laufen. */
.extern-text {
    overflow-wrap: anywhere;
}

/* Forms inside detail cards */
.detail-card .form-group {
    margin-bottom: 12px;
}
.detail-card .form-group:last-child {
    margin-bottom: 0;
}
.detail-card .form-grid {
    padding: 0;
}
.detail-card .checkbox-group {
    display: flex;
    align-items: center;
    gap: 6px;
}

.detail-card-danger {
    border-color: #fecaca;
}
.detail-card-danger h3 { color: #b91c1c; border-bottom-color: #fecaca; }
.danger-desc { margin-bottom: 12px; }
.detail-cards-spaced { margin-top: 24px; }

.detail-card-row {
    display: flex;
    gap: 8px;
    font-size: calc(13rem / 14);
    padding: 6px 0;
    border-bottom: 1px solid var(--bg-row-hover);
}
.detail-card-row:last-child { border-bottom: none; }
.detail-card-row .label {
    min-width: 100px;
}

/* Die Zeilenform der Detailseiten. .label und .value stehen hier, weil
   .detail-card-row ihr Hauptverbraucher ist (datei, titel, termin, ort_detail,
   mitglied); die alte Mitgliedskarte war der letzte Nutzer ausserhalb einer
   .detail-card und ist entfallen. In der Zeile gilt die 100-px-Labelbreite
   oben, ausserhalb die 155 px hier. */
.label {
    font-weight: 500;
    min-width: 155px;
    color: var(--t3);
}

.value {
    flex: 1;
    color: var(--t1);
}

/* Badges */
.badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    font-size: calc(11rem / 14);
    font-weight: 600;
    border-radius: 10px;
    background: var(--bg-row-hover);
    color: var(--t4);
    line-height: 1.5;
}
.badge-primary {
    background: var(--brand-light);
    color: var(--brand);
}

/* Tags */
.tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.tag {
    display: inline-block;
    padding: 3px 10px;
    font-size: calc(12.5rem / 14);
    border-radius: 14px;
    background: var(--bg-row-hover);
    color: var(--t2);
}
.tag-active {
    background: var(--brand-light);
    color: var(--brand);
}

/* Media rows */
.media-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 0;
    border-bottom: 1px solid var(--bg-row-hover);
}
.media-row:last-child { border-bottom: none; }
.media-actions {
    display: flex;
    align-items: center;
    gap: 4px;
}
.media-label {
    font-size: calc(13rem / 14);
    font-weight: 500;
    color: var(--t3);
}

/* Ordered list (song list) */
.detail-list {
    margin: 0;
    padding: 0 0 0 20px;
    font-size: calc(13rem / 14);
    line-height: 1.8;
    color: var(--t2);
}

/* Attendance table */
.attendance-table {
    width: 100%;
    border-collapse: collapse;
    font-size: calc(13rem / 14);
}
.attendance-table th {
    font-size: calc(11rem / 14);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    text-align: left;
    padding: 6px 10px;
    border-bottom: 2px solid var(--border);
    color: var(--t3);
}
.attendance-table td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--bg-row-hover);
    vertical-align: top;
}
.attendance-table tbody tr:last-child td { border-bottom: none; }
.att-voice {
    font-weight: 600;
    color: var(--brand);
    white-space: nowrap;
}
.att-count {
    display: inline-block;
    font-weight: 700;
    min-width: 16px;
    text-align: center;
    padding: 0 5px;
    border-radius: 8px;
    font-size: calc(11rem / 14);
    line-height: calc(18rem / 14);
    margin-right: 4px;
}
.att-yes .att-count { background: var(--status-success-bg); color: var(--status-success-text); }
.att-maybe .att-count { background: var(--status-warning-bg); color: var(--status-warning-text); }
.att-no .att-count { background: var(--status-danger-bg); color: var(--status-danger-text); }
.att-na .att-count { background: var(--bg-row-hover); color: var(--t4); }

.att-names {
    font-size: calc(12rem / 14);
    color: var(--t4);
}
/* Vor- und Nachname bleiben zusammen, umbrochen wird nur nach dem Komma. */
.att-name { white-space: nowrap; }

/* Aufstellung (Terminliste, groß als Karte auf der Terminseite): ein Kästchen
   pro Mitglied, hinten T|B, vorn S|A, Chorleiter/Musiker abgesetzt. Die
   Grid-Spalten sind so breit wie die längste Stimme ihrer Seite, dadurch steht
   der Gang in beiden Reihen übereinander. Die Maße hängen an Variablen, die
   .aufst-gross überschreibt. */
.aufst {
    --aufst-p: calc(8rem / 14);
    --aufst-abstand: 2px;
    --aufst-gang: calc(5rem / 14);
    --aufst-radius: 2px;
    display: flex;
    align-items: center;
}
.aufst-gross {
    --aufst-p: 1rem;
    --aufst-abstand: 3px;
    --aufst-gang: .75rem;
    --aufst-radius: 3px;
    justify-content: center;
    padding-block: .5rem;
}
.aufst-buehne {
    display: grid;
    grid-template-columns: auto auto auto;
    column-gap: var(--aufst-gang);
    row-gap: var(--aufst-abstand);
    flex-shrink: 0;
}
.aufst-block {
    display: flex;
    gap: var(--aufst-abstand);
    min-height: var(--aufst-p);
}
.aufst-links  { grid-column: 1; justify-content: flex-end; }
.aufst-rechts { grid-column: 2; justify-content: flex-start; }
.aufst-extra  { grid-column: 3; grid-row: 1; margin-left: calc(var(--aufst-gang) + var(--aufst-p)); }
.aufst-p {
    display: block;
    width: var(--aufst-p);
    height: var(--aufst-p);
    border-radius: var(--aufst-radius);
}
.aufst-yes   { background: var(--status-success-solid); }
.aufst-maybe { background: var(--aufst-eventuell); }
.aufst-no    { background: var(--status-danger-solid); }
.aufst-na    { background: color-mix(in srgb, var(--t4) 45%, transparent); }
.aufst-ich   { outline: 1.5px solid var(--brand); outline-offset: 1px; }
.aufst-gross .aufst-ich { outline-width: 2px; }
/* „Meine Antwort fehlt" (offen oder „Eventuell"): das eigene Kästchen der Aufstellung
   pulsiert — und mit ihm
   der Terminname in der Liste (``.termin-offen``, siehe Terminliste unten). Beide
   teilen **dieselbe** Animation, damit sie im Gleichtakt laufen; die Ruhephase
   bleibt sichtbar (Rahmen an), die Animation blendet ihn nur aus und wieder ein,
   statt zwischen zwei Zuständen zu wechseln. */
@keyframes offen-puls {
    0%, 100% { outline-color: var(--brand); }
    50%      { outline-color: transparent; }
}
.aufst-ich.aufst-na,
.aufst-ich.aufst-maybe { animation: offen-puls 1.6s ease-in-out infinite; }
@media (max-width: 640px) {
    .aufst-gross { --aufst-p: calc(10rem / 14); --aufst-abstand: 2px; --aufst-gang: .5rem; }
}

/* Admin drag-and-drop chips */
.att-chips {
    list-style: none;
    padding: 0;
    margin: 0;
    display: none;
    flex-wrap: wrap;
    gap: 4px;
    min-height: 1.5em;
}
.attendance-edit-mode .att-display { display: none; }
.attendance-edit-mode .att-chips { display: flex; }
.attendance-edit-mode .att-chips:empty::before {
    content: "–";
    color: var(--t4);
    font-size: calc(12rem / 14);
}
.att-chip {
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--bg-row-hover);
    color: var(--t2);
    font-size: calc(12rem / 14);
    line-height: 1.4;
    white-space: nowrap;
    user-select: none;
    border: 1px solid transparent;
}
.attendance-edit-mode .attendance-single .att-chip { cursor: grab; }
.attendance-edit-mode .attendance-single .att-chip:active { cursor: grabbing; }
.attendance-edit-mode .attendance-split .att-chip { cursor: pointer; }
.att-chip.att-chip-dirty {
    border-color: var(--brand);
    box-shadow: 0 0 0 2px var(--brand-ring);
}
.att-chip.sortable-ghost { opacity: 0.4; }
.att-chip.sortable-chosen { background: var(--brand); color: #fff; }

/* Mobile tap-to-move popover for attendance chips (mirrors .reaction-picker) */
.att-move-picker {
    position: absolute;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 120px;
    padding: 6px;
    border-radius: 10px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-md);
}
.att-move-pick {
    border: 0;
    background: transparent;
    text-align: left;
    font-size: calc(13rem / 14);
    padding: 6px 8px;
    border-radius: 7px;
    cursor: pointer;
    color: var(--t2);
}
.att-move-pick:hover,
.att-move-pick:focus-visible { background: var(--msg-border); }

.detail-card h3 button.h3-edit {
    display: inline-flex;
    align-items: center;
    opacity: 0.4;
    background: transparent;
    border: 0;
    padding: 0;
    color: inherit;
    cursor: pointer;
}
.detail-card h3 button.h3-edit:hover { opacity: 1; }
.detail-card h3 button.h3-edit[hidden] { display: none; }

.anwesenheit-save-btn,
.anwesenheit-cancel-btn {
    display: inline-block;
    padding: 2px 10px;
    font-size: calc(11rem / 14);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-radius: 6px;
    border: 1px solid var(--brand);
    cursor: pointer;
}
.anwesenheit-save-btn { background: var(--brand); color: #fff; }
.anwesenheit-save-btn:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
.anwesenheit-cancel-btn { background: transparent; color: var(--brand); }
.anwesenheit-cancel-btn:hover { background: var(--brand-light); }
.anwesenheit-save-btn[hidden],
.anwesenheit-cancel-btn[hidden] { display: none; }
.anwesenheit-save-btn:disabled { opacity: 0.6; cursor: wait; }

/* Attendance split layout (mobile) */
.attendance-split {
    display: none;
    gap: 12px;
    /* Vier Spalten passen mit grosser Schrift nicht immer in die Karte: dann
       scrollt die Tabelle in der Karte statt die Seite zu verbreitern. Das
       Verschiebe-Popover haengt an <body> und wird nicht abgeschnitten. */
    overflow-x: auto;
}

.attendance-split .attendance-table {
    flex: 1;
    min-width: 0;
}

.attendance-split .attendance-table th { white-space: normal; }

.attendance-split .attendance-table + .attendance-table { margin-top: 12px; }

/* Mobile: hide single table, show split */
@media (max-width: 768px) {
    .attendance-single { display: none; }
    .attendance-split { display: block; }
}

.detail-card-wide {
    grid-column: 1 / -1;
}

.detail-map {
    flex: 1;
    min-height: 250px;
    width: 100%;
    border-radius: var(--r-sm);
    z-index: 0;
}

/* yes/maybe/no brauchen hier nichts: die --status-*-Tokens sind bereits
   dunkelmodus-tauglich. Nur „keine Angabe" hat kein Ampel-Pendant. */
[data-theme="dark"] .att-na .att-count { background: rgba(255,255,255,0.08); color: var(--t4); }

/* =================================================== */
/* Zusage Widget                                        */
/* =================================================== */
.zusage-widget {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    animation: zusage-fade 0.2s ease;
}

@keyframes zusage-fade {
    from { opacity: 0; transform: translateY(-3px); }
    to   { opacity: 1; transform: translateY(0); }
}

.zusage-state-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px;
    border-radius: 10px;
    font-size: calc(12rem / 14);
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: 1.5;
}

.zusage-state-yes   { background: var(--status-success-bg); color: var(--status-success-text); border: 1.5px solid var(--status-success-border); }
.zusage-state-no    { background: var(--status-danger-bg);  color: var(--status-danger-text);  border: 1.5px solid var(--status-danger-border); }
.zusage-state-maybe { background: var(--status-warning-bg); color: var(--status-warning-text); border: 1.5px solid var(--status-warning-border); }
.zusage-state-na    { background: var(--bg-row-hover); color: var(--t4); border: 1.5px solid var(--border); }

.zusage-locked-note { font-size: calc(12rem / 14); color: var(--t4); font-style: italic; }

.zusage-actions      { display: flex; gap: 6px; flex-wrap: wrap; }
.zusage-actions form { margin: 0; padding: 0; }

.zusage-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 11px;
    border-radius: var(--r-sm);
    font-size: calc(12rem / 14);
    font-weight: 500;
    font-family: var(--font);
    cursor: pointer;
    border: 1.5px solid transparent;
    background: transparent;
    line-height: 1.5;
    white-space: nowrap;
    transition: background var(--ease), border-color var(--ease),
                color var(--ease), box-shadow var(--ease);
}

.zusage-btn-yes   { background: var(--status-success-bg); color: var(--status-success-text); border-color: var(--status-success-border); }
.zusage-btn-yes:hover   { background: var(--status-success-solid); color: #fff; border-color: var(--status-success-solid); box-shadow: 0 2px 8px rgba(22,163,74,.25); }
.zusage-btn-maybe { background: var(--status-warning-bg); color: var(--status-warning-text); border-color: var(--status-warning-border); }
.zusage-btn-maybe:hover { background: var(--status-warning-solid); color: #fff; border-color: var(--status-warning-solid); box-shadow: 0 2px 8px rgba(202,138,4,.25); }
.zusage-btn-no    { background: var(--status-danger-bg); color: var(--status-danger-text); border-color: var(--status-danger-border); }
.zusage-btn-no:hover    { background: var(--status-danger-solid); color: #fff; border-color: var(--status-danger-solid); box-shadow: 0 2px 8px rgba(220,38,38,.25); }

/* Nur der Nicht-Ampel-Zustand braucht eine eigene Dark-Mode-Regel — die
   Farbzustaende ziehen ihre Werte aus den --status-*-Tokens. */
[data-theme="dark"] .zusage-state-na    { background: rgba(255,255,255,.05); color: var(--t4); border-color: rgba(255,255,255,.08); }

/* Next-event banner */
/* Liegt als Geschwister von .content direkt unter der Topbar (siehe base.html),
   damit der Rollbereich .content nicht um die Bannerhöhe überläuft. Als
   Flex-Element von .app-main darf es deshalb nicht schrumpfen. */
.termin-banner[hidden] { display: none; }
.termin-banner {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 10px 14px;
    background: var(--brand-light);
    border: 1px solid var(--brand-ring);
    border-left: 4px solid var(--brand);
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
}
.termin-banner-main {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1 1 auto;
    min-width: 0;
    text-decoration: none;
    color: inherit;
}
.termin-banner-icon {
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--brand);
}
.termin-banner-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.termin-banner-line1 {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
}
.termin-banner-countdown {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: calc(13rem / 14);
    font-weight: 700;
    color: var(--brand);
    white-space: nowrap;
}
.termin-banner-titel {
    font-size: calc(14rem / 14);
    font-weight: 600;
    color: var(--t1);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.termin-banner-tag {
    font-size: calc(11rem / 14);
    font-weight: 600;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--brand);
    color: #fff;
    white-space: nowrap;
}
.termin-banner-line2 {
    font-size: calc(12rem / 14);
    color: var(--t3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.termin-banner-main:hover .termin-banner-titel { text-decoration: underline; }
.termin-banner-zusage { flex: 0 0 auto; }
.termin-banner-dismiss {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px;
    border: none;
    background: transparent;
    color: var(--t4);
    cursor: pointer;
    border-radius: var(--r-sm);
    transition: background var(--ease), color var(--ease);
}
.termin-banner-dismiss:hover { background: var(--bg-row-hover); color: var(--t2); }

@media (max-width: 640px) {
    /* Only the three answer buttons need a row of their own; then the dismiss
       button stays pinned to the top right corner instead of flowing into yet
       another row, and the text reserves space for it. The answered state is one
       narrow pill and keeps the banner a single row — a second row would make it
       tower over the page. */
    .termin-banner:has(.zusage-actions) { flex-wrap: wrap; gap: 10px; position: relative; }
    .termin-banner:has(.zusage-actions) .termin-banner-main { flex: 1 1 100%; order: 1; padding-right: 28px; }
    .termin-banner:has(.zusage-actions) .termin-banner-zusage { order: 2; flex: 1 1 100%; }
    .termin-banner:has(.zusage-actions) .termin-banner-dismiss {
        position: absolute;
        top: 6px;
        right: 6px;
    }
    .termin-banner { gap: 10px; }
}

@media (max-width: 480px) {
    /* Before it gets tight the pill drops its label and shows the check alone. */
    .termin-banner .zusage-state-text { display: none; }
    .termin-banner .zusage-state-badge { gap: 0; padding: 4px; border-radius: 999px; }
}

/* Invite list */
.invite-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.invite-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 0;
    font-size: calc(13rem / 14);
    border-bottom: 1px solid var(--bg-row-hover);
}
.invite-row:last-child { border-bottom: none; }

/* Form actions */
.form-actions {
    display: flex;
    gap: 10px;
    padding: 16px 0;
}

/* Form field with inline action button (e.g. "+Ort" next to dropdown) */
.form-field-with-action {
    display: flex;
    gap: 8px;
    align-items: center;
}
.form-field-with-action select {
    flex: 1;
}
.form-field-with-action .btn-sm {
    flex-shrink: 0;
    padding: 6px 12px;
    font-size: 0.85rem;
}

/* Search-select (pill-style input with hidden select) */
.search-select-wrap {
    position: relative;
    display: flex;
    align-items: center;
    gap: 6px;
}
.search-select-icon {
    position: absolute;
    left: 9px;
    width: 14px;
    height: 14px;
    color: var(--t4);
    pointer-events: none;
    stroke: currentColor;
    transition: color var(--ease);
}
.search-select-input {
    width: 100%;
    height: 34px;
    font-family: var(--font);
    font-size: 0.95rem;
    color: var(--t1);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 0 10px 0 30px;
    outline: none;
    box-sizing: border-box;
    transition: border-color var(--ease), box-shadow var(--ease);
}
.search-select-input:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}
.search-select-wrap:focus-within .search-select-icon {
    color: var(--brand);
}
.search-select-input::placeholder {
    color: var(--t4);
}
.search-select-input::-webkit-search-cancel-button {
    cursor: pointer;
}
.search-select-add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--r-sm);
    background: var(--bg-row-hover);
    color: var(--t2);
    text-decoration: none;
    font-size: 1.1rem;
    font-weight: 600;
    flex-shrink: 0;
    transition: background var(--ease), color var(--ease);
}
.search-select-add:hover {
    background: var(--brand);
    color: #fff;
}
.search-select-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 40px;
    z-index: 600;
    max-height: 200px;
    overflow-y: auto;
    padding: 4px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
    display: none;
    margin-top: 2px;
}
.search-select-dropdown.active {
    display: block;
}
.search-select-item {
    display: block;
    width: 100%;
    padding: 7px 12px;
    background: transparent;
    color: var(--t1);
    border: none;
    border-radius: var(--r-sm);
    text-align: left;
    font-size: calc(13rem / 14);
    font-weight: 400;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.search-select-item:hover,
.search-select-item.selected {
    background: var(--bg-row-hover);
    color: var(--t1);
}

/* Checkbox row in forms */
.checkbox-group label,
.checkbox-row label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: calc(13rem / 14);
    font-weight: 400;
    color: var(--t2);
    margin-right: 16px;
    cursor: pointer;
}
.checkbox-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    padding-top: 4px;
}

/* Single-column cards on small screens */
@media (max-width: 768px) {
    .detail-cards { grid-template-columns: 1fr; }
    .attendance-single { display: none; }
    .attendance-split { display: block; }
}

[data-theme="dark"] .detail-icon { background: color-mix(in srgb, var(--brand) 15%, transparent); }
[data-theme="dark"] .detail-card-danger { border-color: #7f1d1d; }
[data-theme="dark"] .detail-card-danger h3 { color: #fca5a5; border-bottom-color: #7f1d1d; }
[data-theme="dark"] .badge-primary { background: color-mix(in srgb, var(--brand) 20%, transparent); }
[data-theme="dark"] .tag-active { background: color-mix(in srgb, var(--brand) 15%, transparent); }
[data-theme="dark"] .detail-card-row { border-bottom-color: rgba(255,255,255,0.05); }
[data-theme="dark"] .media-row { border-bottom-color: rgba(255,255,255,0.05); }
[data-theme="dark"] .invite-row { border-bottom-color: rgba(255,255,255,0.05); }

/* =================================================== */
/* Wiki / Articles                                     */
/* =================================================== */
.wiki {
    font-family: var(--font);
    font-size: calc(14rem / 14);
    line-height: 1.75;
    color: var(--t2);
    padding: 20px 24px;
    height: 100%;
    display: flex;
    flex-direction: column;
}

.wiki h1 {
    font-size: 1.45em;
    color: var(--brand-text);
    border-bottom: 2px solid var(--brand);
    padding-bottom: 0.3em;
    margin-bottom: 0.9em;
}

.wiki h2 {
    font-size: 1.2em;
    color: var(--brand-text);
    margin-top: 1.5em;
}

.wiki h3 {
    font-size: 1.05em;
    color: var(--t1);
    margin-top: 1.2em;
}

.wiki p { margin-bottom: 1em; }

.wiki a { color: var(--brand); }
.wiki a:hover { text-decoration: underline; }

.wiki strong { font-weight: 600; }

.datei-preview {
    max-width: 200px;
    max-height: 200px;
    border: 1px solid var(--border);
    border-radius: 4px;
    vertical-align: middle;
}

/* View context uses block layout so float works (text wraps around figures). */
/* The flex column on .wiki is only needed in the editor so the textarea fills height. */
.wiki-page .wiki {
    display: block;
    height: auto;
}

/* ── Right-floated file thumbnails ────────────────── */
.wiki-page .wiki .wiki-figure {
    float: right;
    clear: right;
    margin: 0.2em 0 0.8em 1.2em;
    max-width: 220px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 6px;
    box-shadow: var(--shadow-sm);
    text-align: center;
}

.wiki-page .wiki .wiki-figure img {
    display: block;
    max-width: 100%;
    height: auto;
    border-radius: var(--r-sm);
    margin: 0;
    box-shadow: none;
}

.wiki-page .wiki .wiki-figure figcaption {
    font-size: calc(11.5rem / 14);
    color: var(--t3);
    margin-top: 6px;
    line-height: 1.35;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wiki-page .wiki .wiki-figure a {
    border-bottom: none;
}
.wiki-page .wiki .wiki-figure a:hover {
    border-bottom: none;
}

/* Audio: das Noten-Symbol an der Stelle des Vorschaubilds; ein Klick darauf
   startet den Mini-Player (intern.js). */
.wiki-page .wiki .wiki-audio-start {
    display: block;
    padding: 12px 24px 6px;
    color: var(--brand-text);
}
.wiki-page .wiki .wiki-audio-start svg {
    display: block;
    width: 48px;
    height: 48px;
    margin: 0 auto;
}
.wiki-page .wiki .wiki-audio-start:hover { color: var(--t1); }
/* Dateiname und Download-Knopf in einer Zeile; gekürzt wird nur der Name. */
.wiki-page .wiki .wiki-audio figcaption {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.wiki-page .wiki .wiki-audio-name {
    overflow: hidden;
    text-overflow: ellipsis;
}
.wiki-page .wiki .wiki-audio .wp-download {
    display: inline-flex;
    flex-shrink: 0;
    color: var(--t3);
}
.wiki-page .wiki .wiki-audio .wp-download:hover { color: var(--t1); }

/* Mobile: floaten aufheben, damit der Text lesbar bleibt */
@media (max-width: 768px) {
    .wiki-page .wiki .wiki-figure {
        float: none;
        clear: none;
        margin: 1em auto;
        max-width: 100%;
    }
}

[data-theme="dark"] .wiki-page .wiki .wiki-figure {
    background: var(--bg-card);
    border-color: rgba(255, 255, 255, 0.07);
}

.wiki pre {
    background: var(--pre-bg);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 14px 16px;
    font-family: var(--mono);
    font-size: calc(12.5rem / 14);
    line-height: 1.6;
    margin: 1em 0;
    position: relative;
}

.wiki-copy-btn {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 28px;
    height: 28px;
    padding: 5px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    color: var(--muted);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, color 0.15s, border-color 0.15s;
}
.wiki-copy-btn svg { width: 100%; height: 100%; }
.wiki pre:hover .wiki-copy-btn { opacity: 1; }
.wiki-copy-btn:hover { color: var(--text); border-color: var(--border); }
.wiki-copy-btn--done { color: var(--brand) !important; opacity: 1 !important; }

.wiki textarea {
    width: 100%;
    flex: 1;
    box-sizing: border-box;
    min-height: 100px;
    font-family: var(--mono);
    font-size: calc(13rem / 14);
    border: 1px solid var(--border-dark);
    border-radius: var(--r-sm);
    padding: 10px;
    resize: vertical;
}

.wiki .wiki {
    border-left: 3px solid var(--brand);
    padding-left: 12px;
}

.wiki span.title {
    font-style: italic;
    color: var(--t3);
}

span.not_found {
    background: #fef9c3;
    border-radius: 2px;
    padding: 0 2px;
}

/* =================================================== */
/* Article editor                                     */
/* =================================================== */
.article-editor {
    height: 100%;
    display: flex;
    flex-direction: column;
    background: var(--bg-app);
}

/* Top / bottom action bars */
.ae-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 20px;
    background: var(--bg-card);
    flex-shrink: 0;
}
.ae-bar-top { border-bottom: 1px solid var(--border); }
.ae-bar-foot { border-top: 1px solid var(--border); }

/* Identity block — which article is being edited */
.ae-ident {
    display: flex;
    align-items: center;
    gap: 11px;
    min-width: 0;
}
.ae-ident-icon {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    padding: 8px;
    box-sizing: border-box;
    color: var(--brand);
    background: var(--brand-light);
    border-radius: var(--r);
}
.ae-ident-text { min-width: 0; }
.ae-name {
    font-size: calc(15rem / 14);
    font-weight: 600;
    color: var(--t1);
    line-height: 1.35;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ae-base {
    font-size: calc(12rem / 14);
    color: var(--t3);
}
.ae-base-new {
    color: var(--brand);
    font-weight: 500;
}

/* Abgewiesenes Speichern: die Abstimmung ohne Ende, Zeile fuer Zeile */
.ae-fehler {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin: 12px 20px 0;
    padding: 12px 16px;
    background: var(--warn-bg);
    border: 1px solid var(--warn-border);
    border-radius: var(--r-lg);
    font-size: calc(12.5rem / 14);
    color: var(--warn-text);
    flex-shrink: 0;
}
.ae-fehler > svg {
    flex-shrink: 0;
    color: var(--warn-icon);
}
.ae-fehler strong {
    display: block;
    color: var(--warn-strong);
    margin-bottom: 2px;
}
.ae-fehler code {
    font-family: var(--mono);
    font-size: calc(11.5rem / 14);
    word-break: break-all;
}
.ae-fehler-zeilen {
    list-style: none;
    margin: 6px 0 0;
    padding: 0;
}
.ae-fehler-zeilen li {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    margin-top: 3px;
}
.ae-fehler-nr {
    font-weight: 500;
    white-space: nowrap;
}

/* Collapsible syntax cheat-sheet */
.ae-help {
    background: var(--bg-card);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.ae-help > summary {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 9px 20px;
    font-size: calc(12rem / 14);
    font-weight: 500;
    color: var(--t3);
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.ae-help > summary::-webkit-details-marker { display: none; }
.ae-help > summary::before {
    content: "";
    width: 0;
    height: 0;
    border-left: 4px solid currentColor;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    transition: transform var(--ease);
}
.ae-help[open] > summary::before { transform: rotate(90deg); }
.ae-help > summary:hover { color: var(--brand); }

.ae-cheats {
    display: flex;
    flex-wrap: wrap;
    gap: 7px 14px;
    padding: 2px 20px 14px;
}
/* Ein Knopf, kein Text: der Klick fuegt das Muster ein (wiki-einfuegen.js) */
.ae-cheat {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font: inherit;
    font-size: calc(11.5rem / 14);
    color: var(--t3);
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    text-align: left;
    cursor: pointer;
    border-radius: var(--r-sm);
}
.ae-cheat:hover { color: var(--brand-text); }
.ae-cheat:focus-visible {
    outline: 2px solid var(--brand-dark);
    outline-offset: 2px;
}
.ae-cheat code {
    font-family: var(--mono);
    font-size: calc(11rem / 14);
    background: var(--pre-bg);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 2px 6px;
    color: var(--t1);
    white-space: nowrap;
    transition: border-color var(--ease), background var(--ease);
}
.ae-cheat:hover code {
    border-color: var(--brand-dark);
    background: var(--code-bg);
}
.ae-cheat:active code { transform: translateY(1px); }

/* Editor body — textarea fills remaining height */
.ae-body {
    flex: 1;
    min-height: 0;
    display: flex;
    padding: 16px 20px;
}
.article-editor .wiki {
    padding: 0;
    flex: 1;
    min-height: 0;
}
.article-editor .wiki textarea {
    min-height: 0;
    resize: none;
    background: var(--bg-card);
    color: var(--t1);
    line-height: 1.7;
    padding: 16px 18px;
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
    transition: border-color var(--ease), box-shadow var(--ease);
}
.article-editor .wiki textarea:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

/* Footer change-summary input */
.ae-comment {
    flex: 1;
    min-width: 0;
}

@media (max-width: 768px) {
    .ae-bar { padding: 10px 14px; }
    .ae-body { padding: 12px 14px; }
    .ae-help > summary,
    .ae-cheats { padding-left: 14px; padding-right: 14px; }
}

/* === Wiki Tables === */
.wiki-table {
    border-collapse: collapse;
    margin: 1.2em 0;
    width: 100%;
    font-size: 0.9em;
    border-radius: var(--r);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
}

.wiki-table th,
.wiki-table td {
    padding: 8px 14px;
    border: 1px solid var(--border);
    vertical-align: top;
    text-align: left;
}

.wiki-table thead th {
    background: var(--brand);
    color: #fff;
    font-weight: 600;
    border-color: var(--brand-dark);
    border-top: none;
    letter-spacing: 0.02em;
}
.wiki-table thead th:first-child { border-left: none; }
.wiki-table thead th:last-child  { border-right: none; }
.wiki-table tbody tr:first-child td,
.wiki-table tbody tr:first-child th { border-top: none; }
.wiki-table tbody td:first-child,
.wiki-table tbody th:first-child    { border-left: none; }
.wiki-table tbody td:last-child,
.wiki-table tbody th:last-child     { border-right: none; }

.wiki-table tbody th {
    background: var(--brand-light);
    color: var(--brand-text);
    font-weight: 600;
    border-color: color-mix(in srgb, var(--brand) 18%, transparent);
    white-space: nowrap;
}

.wiki-table tbody tr:nth-child(even) td {
    background: var(--bg-app);
}

.wiki-table tbody tr:hover td,
.wiki-table tbody tr:hover th {
    background: var(--bg-row-hover);
    transition: background var(--ease);
}

[data-theme="dark"] .wiki-table th,
[data-theme="dark"] .wiki-table td {
    border-color: rgba(255, 255, 255, 0.07);
}

[data-theme="dark"] .wiki-table thead th {
    border-color: var(--brand-dark);
}

[data-theme="dark"] .wiki-table tbody th {
    background: color-mix(in srgb, var(--brand) 14%, transparent);
    color: var(--brand-text);
    border-color: color-mix(in srgb, var(--brand) 20%, transparent);
}

[data-theme="dark"] .wiki-table tbody tr:nth-child(even) td {
    background: rgba(255, 255, 255, 0.025);
}

/* =================================================== */
/* Wiki Page — document card layout                    */
/* =================================================== */
.wiki-page {
    background: var(--bg-card);
    min-height: 100%;
    padding: 28px 0 48px;
}

.wiki-page .version-banner {
    margin: 0 52px 28px;
}

.wiki-page .wiki {
    height: auto;
    padding: 0 52px;
    font-size: calc(15rem / 14);
    line-height: 1.85;
}

/* ── Headings ─────────────────────────────────────── */
.wiki-page .wiki h1 {
    font-size: 1.8em;
    font-weight: 700;
    color: var(--t1);
    border: none;
    border-left: 4px solid var(--brand);
    padding: 0.1em 0 0.1em 16px;
    margin-bottom: 1.1em;
    line-height: 1.3;
}

.wiki-page .wiki h2 {
    font-size: 1.2em;
    color: var(--brand-text);
    border-bottom: 2px solid var(--brand);
    padding-bottom: 0.25em;
    margin: 2em 0 0.75em;
}

.wiki-page .wiki h3 {
    font-size: 1.05em;
    color: var(--t1);
    border-left: 3px solid color-mix(in srgb, var(--brand) 35%, transparent);
    padding-left: 10px;
    margin: 1.6em 0 0.5em;
}

.wiki-page .wiki h4 {
    font-size: 0.88em;
    color: var(--t3);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    margin: 1.4em 0 0.4em;
}

.wiki-page .wiki h5 {
    font-size: 0.88em;
    color: var(--t4);
    font-weight: 600;
    margin: 1.1em 0 0.3em;
}

/* ── Links ────────────────────────────────────────── */
.wiki-page .wiki a {
    color: var(--brand);
    text-decoration: none;
    border-bottom: 1px solid color-mix(in srgb, var(--brand) 28%, transparent);
    transition: border-color var(--ease), color var(--ease);
}
.wiki-page .wiki a:hover {
    text-decoration: none;
    border-bottom-color: var(--brand);
}

/* ── Lists ────────────────────────────────────────── */
.wiki-page .wiki ul {
    list-style: none;
    padding-left: 1.2em;
    margin: 0.5em 0 1em;
}
.wiki-page .wiki ul > li {
    position: relative;
    padding-left: 0.9em;
    margin-bottom: 0.2em;
}
.wiki-page .wiki ul > li::before {
    content: '›';
    position: absolute;
    left: -0.4em;
    color: var(--brand);
    font-weight: 700;
    font-size: 1.15em;
    line-height: 1.6;
}
.wiki-page .wiki ol {
    padding-left: 1.8em;
    margin: 0.5em 0 1em;
}
.wiki-page .wiki ol > li {
    margin-bottom: 0.2em;
}
.wiki-page .wiki ol > li::marker {
    color: var(--brand);
    font-weight: 600;
}

/* ── Block elements ───────────────────────────────── */
.wiki-page .wiki .citation {
    border-left: 4px solid var(--brand);
    background: var(--brand-light);
    padding: 10px 18px;
    margin: 1.4em 0;
    border-radius: 0 var(--r) var(--r) 0;
    color: var(--t2);
    font-style: italic;
    font-size: 0.97em;
}

.wiki-page .wiki .indent {
    padding-left: 1.4em;
    border-left: 2px solid var(--border-dark);
    color: var(--t3);
    margin: 0.3em 0 0.3em 0.5em;
}

.wiki-page .wiki .boxed {
    background: linear-gradient(135deg, color-mix(in srgb, var(--brand) 6%, transparent), color-mix(in srgb, var(--brand) 2%, transparent));
    border: 1px solid color-mix(in srgb, var(--brand) 22%, transparent);
    border-radius: var(--r);
    padding: 14px 18px;
    margin: 1.4em 0;
}

/* ── Code blocks — dark terminal ──────────────────── */
.wiki-page .wiki pre {
    background: var(--code-bg);
    color: var(--code-color);
    border: none;
    border-radius: var(--r);
    padding: 0;
    overflow: hidden;
    margin: 1.4em 0;
    box-shadow: var(--shadow-sm);
}
.wiki-page .wiki pre::before {
    content: '⬤  ⬤  ⬤';
    display: block;
    background: var(--code-bar-bg);
    border-bottom: 1px solid var(--border);
    padding: 7px 14px;
    font-size: calc(7rem / 14);
    color: var(--code-bar-dots);
    letter-spacing: 4px;
}
.wiki-page .wiki pre code {
    display: block;
    padding: 16px 20px;
    font-size: calc(12.5rem / 14);
    line-height: 1.7;
    font-family: var(--mono);
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── Media ────────────────────────────────────────── */
.wiki-page .wiki img:not([style*="width"]) {
    max-width: 100%;
    border-radius: var(--r-sm);
    box-shadow: var(--shadow-sm);
    margin: 0.4em 0;
}
.wiki-page .wiki audio,
.wiki-page .wiki video {
    width: 100%;
    border-radius: var(--r-sm);
    margin: 0.6em 0;
}

/* ── Mentions ─────────────────────────────────────── */
.wiki-page .wiki .mention {
    background: color-mix(in srgb, var(--brand) 10%, transparent);
    border-color: color-mix(in srgb, var(--brand) 25%, transparent);
    color: var(--brand-text);
    border-radius: 99px;
}

/* ── Footer ───────────────────────────────────────── */
.wiki-page .wiki #footer {
    margin-top: 2.5em;
    padding-top: 1.2em;
    border-top: 1px solid var(--border);
    justify-content: center;
    font-size: calc(11rem / 14);
    gap: 5px;
    opacity: 0.5;
}

/* ── Mobile ───────────────────────────────────────── */
@media (max-width: 768px) {
    .wiki-page {
        padding: 16px 0 24px;
    }
    .wiki-page .wiki {
        padding: 0 18px;
        font-size: calc(14.5rem / 14);
    }
    .wiki-page .version-banner {
        margin: 0 12px 18px;
    }
    .wiki-page .wiki h1 { font-size: 1.45em; }
}

/* ── Dark mode ────────────────────────────────────── */
[data-theme="dark"] .wiki-page .wiki .citation {
    background: color-mix(in srgb, var(--brand) 12%, transparent);
}
[data-theme="dark"] .wiki-page .wiki .boxed {
    background: color-mix(in srgb, var(--brand) 7%, transparent);
    border-color: color-mix(in srgb, var(--brand) 18%, transparent);
}
[data-theme="dark"] .wiki-page .wiki .mention {
    background: color-mix(in srgb, var(--brand) 15%, transparent);
    color: var(--brand-text);
    border-color: color-mix(in srgb, var(--brand) 25%, transparent);
}

/* =================================================== */
/* Password Strength                                   */
/* =================================================== */
.pw-strength {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
}

/* In a .form-grid the surrounding .form-group is display:contents, so the
   injected meter would otherwise land in its own grid cell and shove the
   following field sideways. Span the full width so it sits on its own row. */
.form-grid .pw-strength {
    grid-column: 1 / -1;
    margin-top: 0;
}

.pw-strength-track {
    flex: 1;
    height: 6px;
    border-radius: 3px;
    background: var(--border);
    overflow: hidden;
}

.pw-strength-bar {
    height: 100%;
    width: 0;
    border-radius: 3px;
    background: var(--strength-0);
    transition: width 0.25s ease, background 0.25s ease;
}

.pw-strength-label {
    font-size: calc(12rem / 14);
    color: var(--t3);
    white-space: nowrap;
}

.pw-strength[data-score="0"] .pw-strength-bar { background: var(--strength-0); }
.pw-strength[data-score="1"] .pw-strength-bar { background: var(--strength-1); }
.pw-strength[data-score="2"] .pw-strength-bar { background: var(--strength-2); }
.pw-strength[data-score="3"] .pw-strength-bar { background: var(--strength-3); }
.pw-strength[data-score="4"] .pw-strength-bar { background: var(--strength-4); }

.pw-widget {
    margin: 8px 0 4px;
}

.pw-match {
    display: flex;
    align-items: center;
    font-size: calc(12rem / 14);
    margin-top: 5px;
}

.pw-match[data-match="yes"] { color: var(--strength-4); }
.pw-match[data-match="no"]  { color: var(--strength-0); }

/* =================================================== */
/* Misc                                                */
/* =================================================== */
.container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
}

#footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    font-size: calc(12rem / 14);
    font-weight: 600;
    padding: 8px 12px;
    color: var(--t3);
}

/* =================================================== */
/* Audio buttons (Repertoire table + Titel detail)     */
/* =================================================== */
.audio-cell {
    white-space: nowrap;
    padding-top: 5px;
    padding-bottom: 5px;
    font-size: 0;  /* eliminate inline-button whitespace gaps */
}
.audio-cell-head { width: 1%; }
.audio-cell .audio-btn + .audio-btn { margin-left: 4px; }

.audio-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    height: 24px;
    min-width: 24px;
    padding: 0 6px;
    border: 1px solid transparent;
    border-radius: 999px;
    background: transparent;
    color: var(--t3);
    font: inherit;
    font-size: calc(10rem / 14);
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    vertical-align: middle;
    transition: background var(--ease), color var(--ease), border-color var(--ease), transform var(--ease);
}
.audio-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--brand-ring);
}
.audio-btn:active { transform: scale(0.94); }

.audio-btn-icon {
    flex: 0 0 auto;
    transform: translateX(0.5px);  /* optical centering of play triangle */
}
.audio-btn-logo {
    display: block;
    height: 14px;
    width: 14px;
    flex: 0 0 auto;
}

/* Original = outline / quiet */
.audio-btn--original {
    border-color: var(--border-dark);
    color: var(--t3);
}
.audio-btn--original:hover,
.audio-btn--original.playing {
    border-color: var(--brand);
    color: var(--brand);
    background: var(--brand-light);
}

/* JG Aufnahme = tinted / subdued */
.audio-btn--jg {
    background: var(--brand-light);
    border-color: var(--brand);
    color: var(--brand);
}
.audio-btn--jg:hover {
    background: color-mix(in srgb, var(--brand) 20%, transparent);
    border-color: var(--brand-dark);
    color: var(--brand-text);
}
.audio-btn--jg.playing {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
    box-shadow: 0 0 0 3px var(--brand-ring);
}
[data-theme="dark"] .audio-btn--jg {
    background: color-mix(in srgb, var(--brand) 15%, transparent);
    border-color: color-mix(in srgb, var(--brand) 40%, transparent);
    color: var(--brand-text);
}
[data-theme="dark"] .audio-btn--jg:hover {
    background: color-mix(in srgb, var(--brand) 28%, transparent);
    border-color: color-mix(in srgb, var(--brand) 60%, transparent);
    color: var(--brand-text);
}
[data-theme="dark"] .audio-btn--jg.playing {
    background: color-mix(in srgb, var(--brand) 55%, transparent);
    border-color: var(--brand);
    color: #fff;
}

/* Pulse while playing */
@keyframes audioPulse {
    0%, 100% { box-shadow: 0 0 0 0 var(--brand-ring); }
    50%      { box-shadow: 0 0 0 4px var(--brand-ring); }
}
.audio-btn.playing { animation: audioPulse 1.6s ease-in-out infinite; }

/* =================================================== */
/* File-icon links (PDF / Notensatz in Repertoire)     */
/* =================================================== */
.file-icon-cell {
    white-space: nowrap;
    text-align: center;
    padding-top: 5px;
    padding-bottom: 5px;
}
.file-icon-cell-head { width: 1%; text-align: center; }

.file-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 26px;
    border-radius: var(--r-sm);
    color: var(--t3);
    text-decoration: none;
    transition: background var(--ease), color var(--ease);
}
.file-icon-btn:hover {
    background: var(--brand-light);
    color: var(--brand);
}
.file-icon-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--brand-ring);
}
.file-icon-btn--pdf:hover  { color: var(--brand); }
.file-icon-btn--notes:hover { color: var(--brand); }

/* =================================================== */
/* Eigenschaften chips (Repertoire table + Titel)      */
/* =================================================== */
.eig-cell {
    white-space: nowrap;
    padding-top: 5px;
    padding-bottom: 5px;
    font-size: 0;  /* collapse whitespace between inline chips */
}
.eig-cell-head { width: 1%; }
.eig-cell .eig-chip + .eig-chip { margin-left: 4px; }

.eig-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    padding: 0 4px;
    border-radius: 999px;
    color: var(--t2);
    font-size: calc(12rem / 14);
    line-height: 1;
    vertical-align: middle;
    transition: color var(--ease), background var(--ease);
}
.eig-chip:hover { color: var(--brand); background: var(--brand-light); }
.eig-chip--dot:hover,
.eig-chip--beats:hover { background: transparent; }

/* Aktiv: status dot */
.eig-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    box-sizing: border-box;
}
.eig-dot--on  { background: #10b981; }
.eig-dot--off { background: transparent; border: 1.5px solid var(--t4); }

/* Beats: encircled number */
.eig-beats {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 22px;
    padding: 0 2px;
    border: 1.5px solid var(--border-dark);
    border-radius: 999px;
    font: 700 calc(9.5rem / 14) var(--mono);
    font-variant-numeric: tabular-nums;
    color: var(--t2);
    letter-spacing: -0.02em;
}
.eig-chip--beats { padding: 0; min-width: 24px; }

/* Tempo: 1/2/3 chevrons */
.eig-tempo {
    display: inline-block;
    color: var(--brand);
    font: 800 calc(14rem / 14) var(--font-sans);
    letter-spacing: -2.5px;
    line-height: 1;
    padding-right: 2px;  /* compensate negative letter-spacing on last glyph */
}

/* Tonart: plain text label — no border/background */
.eig-tonart {
    display: inline-block;
    font: 600 calc(11rem / 14) var(--font-sans);
    color: var(--t2);
    line-height: calc(22rem / 14);
    vertical-align: middle;
}
.eig-cell .eig-chip + .eig-tonart,
.eig-cell .eig-tonart + .eig-chip { margin-left: 4px; }

/* Dark-mode tweaks */
[data-theme="dark"] .eig-dot--on  { background: #34d399; }
[data-theme="dark"] .eig-beats    { border-color: rgba(255,255,255,0.18); color: var(--t1); }
[data-theme="dark"] .eig-chip:hover { background: color-mix(in srgb, var(--brand) 18%, transparent); }

/* Aktiv/Inaktiv status dot — used in member tables */
.status-dot {
    display: inline-block;
    width: 11px;
    height: 11px;
    border-radius: 50%;
    box-sizing: border-box;
    border: 1.5px solid var(--border-dark);
    vertical-align: middle;
}
.status-dot--on  { background: #22c55e; border-color: #16a34a; }
.status-dot--off { background: #ef4444; border-color: #dc2626; }
[data-theme="dark"] .status-dot--on  { background: #16a34a; border-color: #22c55e; }
[data-theme="dark"] .status-dot--off { background: #dc2626; border-color: #ef4444; }

/* =================================================== */
/* Floating mini audio player                          */
/* =================================================== */
.mini-player {
    position: fixed;
    left: 50%;
    bottom: calc(16px + env(safe-area-inset-bottom));
    transform: translate(-50%, calc(100% + 32px));
    width: min(520px, calc(100vw - 24px));
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-md);
    padding: 10px 14px 12px;
    z-index: 1100;
    opacity: 0;
    pointer-events: none;
    transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1),
                opacity 0.18s ease;
}
.mini-player.open {
    transform: translate(-50%, 0);
    opacity: 1;
    pointer-events: auto;
}

.mp-info {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
    color: var(--t2);
    font-size: calc(13rem / 14);
    min-width: 0;
}
.mp-info-icon {
    flex: 0 0 auto;
    color: var(--brand);
    display: inline-flex;
}
.mp-meta {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.mp-title {
    font-weight: 600;
    color: var(--t1);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mp-composer {
    font-size: calc(11rem / 14);
    color: var(--t3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: none;
}
.mp-composer:not(:empty) { display: block; }
.mp-type {
    flex: 0 0 auto;
    font-size: calc(10.5rem / 14);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--brand);
    background: var(--brand-light);
    padding: 2px 8px;
    border-radius: 999px;
}

.mp-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}

.mp-play,
.mp-prev,
.mp-next,
.mp-close,
.wp-download {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    color: var(--t2);
    cursor: pointer;
    padding: 0;
    border-radius: 50%;
    transition: background var(--ease), color var(--ease);
}
.mp-play {
    width: 34px;
    height: 34px;
    background: var(--brand);
    color: #fff;
    flex: 0 0 auto;
}
.mp-play:hover { background: var(--brand-dark); }
.mp-play:focus-visible,
.mp-prev:focus-visible,
.mp-next:focus-visible,
.mp-close:focus-visible,
.wp-download:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--brand-ring);
}

.mp-prev,
.mp-next {
    width: 28px;
    height: 28px;
    color: var(--t3);
    flex: 0 0 auto;
}
.mp-prev:hover:not(:disabled),
.mp-next:hover:not(:disabled) { background: var(--hover-bg); color: var(--t1); }
.mp-prev:disabled,
.mp-next:disabled { opacity: 0.3; cursor: default; }

/* Der Download-Link der Inline-Leiste sitzt im selben Slot wie das Schließen-
   Kreuz des schwebenden Players und sieht deshalb genauso aus. */
.mp-close,
.wp-download {
    width: 28px;
    height: 28px;
    font-size: calc(16rem / 14);
    line-height: 1;
    color: var(--t3);
    flex: 0 0 auto;
}
.mp-close:hover,
.wp-download:hover { background: var(--hover-bg); color: var(--t1); }

.mp-time {
    font-variant-numeric: tabular-nums;
    font-size: calc(11.5rem / 14);
    color: var(--t3);
    flex: 0 0 auto;
    min-width: 34px;
    text-align: center;
}

.mp-progress {
    flex: 1 1 auto;
    height: 16px;
    position: relative;
    cursor: pointer;
    display: flex;
    align-items: center;
}
.mp-progress::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 4px;
    background: var(--border);
    border-radius: 2px;
}
.mp-progress-bar {
    position: absolute;
    left: 0;
    height: 4px;
    width: 0;
    background: var(--brand);
    border-radius: 2px;
    transition: width 0.08s linear;
    pointer-events: none;
}
.mp-progress:hover::before { background: var(--border-dark); }

@media (max-width: 768px) {
    .mini-player {
        left: 8px;
        right: 8px;
        bottom: 8px;
        transform: translate(0, calc(100% + 24px));
        width: auto;
    }
    .mini-player.open { transform: translate(0, 0); }
}

/* =================================================== */
/* Inline-Medienleiste im Wikitext                     */
/* =================================================== */
/* Teilt sich die .mp-*-Innereien mit .mini-player — die sind bewusst ohne
   .mini-player-Vorfahren definiert, nur die Positionierung steckt dort. Diese
   Leiste ist die zweite Anzeige derselben Wiedergabe-Engine (intern.js).
   Sie ist ausdrücklich keine .wiki-figure und erbt daher weder float: right
   noch max-width: 220px. */
.wiki-player {
    display: flex;
    flex-direction: column;
    max-width: 520px;
    margin: 1em 0;
    padding: 10px 14px 12px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-sm);
    clear: right;  /* nicht neben eine gefloatete .wiki-figure rutschen */
}
/* Kein gap: .mp-info bringt sein margin-bottom schon mit. */
.wiki-player--video { max-width: 640px; }
.wiki-player.playing {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

.wp-video {
    display: block;
    width: 100%;
    max-height: 60vh;
    margin-bottom: 8px;
    border-radius: var(--r-sm);
    background: var(--video-bg);
}

/* .wiki a ist markenfarben und unterstrichen — der Download ist ein Icon-Knopf. */
.wiki-player a,
.wiki-player a:hover {
    color: var(--t3);
    text-decoration: none;
    border-bottom: none;
}
.wiki-player a:hover { color: var(--t1); }

[data-theme="dark"] .wiki-player { border-color: rgba(255, 255, 255, 0.07); }

@media (max-width: 768px) {
    .wiki-player { max-width: 100%; }
}

.text-center { text-align: center; }


/* =================================================== */
/* Sidebar Overlay (mobile)                            */
/* =================================================== */
.sidebar-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.45);
    z-index: 750;
}

/* =================================================== */
/* Responsive                                          */
/* =================================================== */
@media (max-width: 768px) {
    .sidebar {
        position: fixed;
        left: 0;
        top: 0;
        height: 100vh;
        height: 100dvh;
        width: var(--sb-width) !important;
        transform: translateX(-100%);
        z-index: 800;
    }

    .sidebar.active {
        transform: translateX(0);
        box-shadow: var(--shadow-md);
    }

    .sidebar-overlay.active {
        display: block;
    }

    .hamburger {
        display: flex !important;
        flex-shrink: 0;
    }

    .topbar-search input[type="search"] { width: 108px; }
    .topbar-search input[type="search"]:focus { width: 148px; }

    .form-grid {
        grid-template-columns: 1fr;
    }

    #AddPanel {
        width: 100vw;
    }
}

@media (min-width: 769px) {
    .hamburger { display: none !important; }
}

/* ── Folder drag-and-drop ─────────────────────────────── */
.table-container tbody tr[draggable="true"] { cursor: grab; }
.table-container tbody tr[draggable="true"]:active { cursor: grabbing; }

.dnd-dragging {
    opacity: 0.35;
}

.dnd-over td {
    background: var(--brand-light) !important;
    outline: 2px solid var(--brand);
    outline-offset: -2px;
}

.dnd-file-over td {
    background: rgba(34, 197, 94, 0.10) !important;
    outline: 2px solid #22c55e;
    outline-offset: -2px;
}

/* ── Outdated version banner + version navigator ──────── */
.version-banner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    margin: 12px 16px;
    padding: 14px 18px;
    background: var(--warn-bg);
    border: 1px solid var(--warn-border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-xs);
}

.version-banner-msg {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}
.version-banner-msg > svg {
    flex-shrink: 0;
    color: var(--warn-icon);
}
.version-banner-msg strong {
    display: block;
    color: var(--warn-strong);
    font-size: calc(12rem / 14);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.version-banner-msg span {
    color: var(--warn-text);
    font-size: calc(13rem / 14);
}

/* Version stepper */
.version-nav {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}
.version-step {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 6px 10px;
    font-size: calc(12.5rem / 14);
    font-weight: 600;
    color: var(--warn-strong);
    background: var(--bg-card);
    border: 1px solid var(--warn-border);
    border-radius: var(--r-sm);
    text-decoration: none;
    transition: background var(--ease), border-color var(--ease), color var(--ease);
}
.version-step:hover {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
    text-decoration: none;
}
.version-step svg { flex-shrink: 0; }
.version-step-disabled,
.version-step-disabled:hover {
    opacity: 0.45;
    background: var(--bg-card);
    border-color: var(--warn-border);
    color: var(--warn-strong);
    cursor: default;
}

.version-current {
    font-size: calc(12.5rem / 14);
    font-weight: 700;
    color: var(--warn-text);
    padding: 0 4px;
    font-variant-numeric: tabular-nums;
}

.version-latest {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-left: 6px;
    padding: 6px 12px;
    font-size: calc(12.5rem / 14);
    font-weight: 600;
    color: #fff;
    background: var(--brand);
    border: 1px solid var(--brand);
    border-radius: var(--r-sm);
    text-decoration: none;
    transition: background var(--ease);
}
.version-latest:hover {
    background: var(--brand-dark);
    text-decoration: none;
}

@media (max-width: 768px) {
    .version-banner { gap: 12px; }
    .version-nav { width: 100%; flex-wrap: wrap; }
}

/* ── Article history ──────────────────────────────────── */
.history-view {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}

.history-view form {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}

.history-toolbar {
    flex-shrink: 0;
    padding: 10px 16px;
    background: var(--bg-thead);
    border-bottom: 1px solid var(--border);
}

.history-table-wrap {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

.history-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.history-table th,
.history-table td {
    padding: 7px 10px;
    border-bottom: 1px solid var(--border);
    text-align: left;
    vertical-align: top;
}

.history-table thead th {
    background: var(--bg-thead);
    font-weight: 600;
    font-size: 0.8rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    position: sticky;
    top: 0;
    z-index: 1;
}

.history-table tbody tr:hover td {
    background: var(--bg-row-hover);
}

.radio-cell {
    width: 32px;
    text-align: center;
}

.history-table .nowrap { white-space: nowrap; }

.history-table .comment { color: var(--text-muted); font-style: italic; }

.diff-size { white-space: nowrap; }
.diff-size .added  { color: #16a34a; font-weight: 600; margin-right: 4px; }
.diff-size .removed { color: #dc2626; font-weight: 600; }
.diff-size .muted   { color: var(--text-muted); }

/* ── Article diff ─────────────────────────────────────── */
.diff-view {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}

.diff-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-app);
    flex-shrink: 0;
}

.diff-meta-versions {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: 0.875rem;
}

.diff-old  { color: #b91c1c; }
.diff-new  { color: #15803d; }
.diff-arrow { color: var(--text-muted); }

.diff-mode-toggle {
    display: flex;
    gap: 6px;
}

.diff-empty {
    padding: 32px 16px;
    text-align: center;
    color: var(--text-muted);
    font-style: italic;
}

/* Unified diff */
.diff-unified-wrap {
    flex: 1;
    overflow: auto;
    min-height: 0;
}

.diff-unified {
    width: 100%;
    border-collapse: collapse;
    font-family: ui-monospace, "Cascadia Code", "Fira Code", Consolas, "Courier New", monospace;
    font-size: 0.8125rem;
    tab-size: 4;
}

.diff-unified td {
    padding: 1px 8px;
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-all;
}

.diff-gutter {
    width: 24px;
    text-align: center;
    user-select: none;
    color: var(--text-muted);
    border-right: 1px solid var(--border);
    flex-shrink: 0;
}

.diff-add  { background: #f0fdf4; }
.diff-add .diff-gutter  { background: #bbf7d0; color: #15803d; border-color: #86efac; }
.diff-add .diff-code    { color: #15803d; }

.diff-del  { background: #fef2f2; }
.diff-del .diff-gutter  { background: #fecaca; color: #b91c1c; border-color: #fca5a5; }
.diff-del .diff-code    { color: #b91c1c; }

.diff-hunk { background: #eff6ff; }
.diff-hunk-label {
    padding: 3px 10px;
    color: #1d4ed8;
    font-family: ui-monospace, Consolas, monospace;
    font-size: 0.8rem;
    border-top: 1px solid #bfdbfe;
    border-bottom: 1px solid #bfdbfe;
}

/* Side-by-side (difflib.HtmlDiff output) */
.diff-side-wrap {
    flex: 1;
    overflow: auto;
    min-height: 0;
    padding: 0;
}

.diff-side-wrap table.diff {
    width: 100%;
    border-collapse: collapse;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 0.8125rem;
}

.diff-side-wrap table.diff td,
.diff-side-wrap table.diff th {
    padding: 2px 8px;
    white-space: pre-wrap;
    word-break: break-all;
    line-height: 1.6;
}

.diff-side-wrap table.diff th {
    background: var(--bg-thead);
    font-family: var(--font-sans);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    border-bottom: 2px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 1;
}

.diff-side-wrap td.diff_header { color: var(--text-muted); user-select: none; width: 3em; text-align: right; }
.diff-side-wrap td.diff_next,
.diff-side-wrap th.diff_next   { display: none; }

.diff-side-wrap tr.diff_add td { background: #f0fdf4; }
.diff-side-wrap tr.diff_chg td { background: #fefce8; }
.diff-side-wrap tr.diff_sub td { background: #fef2f2; }

.diff-side-wrap span.diff_add { background: #bbf7d0; }
.diff-side-wrap span.diff_chg { background: #fde68a; }
.diff-side-wrap span.diff_sub { background: #fecaca; }

/* =================================================== */
/* iCal subscription block                             */
/* =================================================== */
.ical-subscribe {
    position: relative;
    margin-top: 24px;
    padding: 16px 18px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    font-size: calc(13rem / 14);
    color: var(--t2);
}
.ical-subscribe .ical-close {
    position: absolute;
    top: 6px;
    right: 8px;
    width: 28px;
    height: 28px;
    padding: 0;
    background: transparent;
    color: var(--t3);
    border: none;
    border-radius: var(--r-sm);
    font-size: calc(20rem / 14);
    line-height: 1;
    cursor: pointer;
    box-shadow: none;
}
.ical-subscribe .ical-close:hover {
    background: var(--bg-app);
    color: var(--t1);
    box-shadow: none;
}
.ical-subscribe h3 {
    margin: 0 0 8px;
    font-size: calc(14rem / 14);
    color: var(--t1);
}
.ical-subscribe .ical-url-row {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.ical-subscribe code {
    flex: 1 1 320px;
    padding: 6px 10px;
    background: var(--bg-app);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    font-size: calc(12rem / 14);
    color: var(--t1);
    word-break: break-all;
    user-select: all;
}
.ical-subscribe ul {
    margin: 0;
    padding-left: 18px;
    color: var(--t3);
    font-size: calc(12rem / 14);
    line-height: 1.5;
}

/* =================================================== */
/* Row context menu                                    */
/* =================================================== */
/* Metrik und Farben folgen den Aktions-Buttons im Auswahl-Panel (.action-btn),
   damit Rechtsklick-Menü und Off-Canvas dieselbe Sprache sprechen. */
.context-menu {
    position: fixed;
    z-index: 1000;
    min-width: 220px;
    padding: 6px;
    background: var(--bg-card);
    border: 1px solid var(--border-dark);
    border-radius: var(--r);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    font-size: calc(13rem / 14);
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.context-menu-header {
    max-width: 280px;
    padding: 2px 4px 6px;
    margin-bottom: 2px;
    border-bottom: 1px solid var(--border);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.context-menu-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 10px;
    background: transparent;
    color: var(--t1);
    border: none;
    border-radius: var(--r-sm);
    text-align: left;
    font-size: calc(13rem / 14);
    font-weight: 400;
    cursor: pointer;
    box-shadow: none;
    white-space: nowrap;
}
.context-menu-item svg {
    flex: 0 0 auto;
    color: var(--t3);
}
.context-menu-item:hover {
    background: var(--bg-row-hover);
    box-shadow: none;
    color: var(--t1);
}
.context-menu-item:hover svg { color: currentColor; }
.context-menu-item.danger,
.context-menu-item.danger svg {
    color: #c53030;
}
.context-menu-item.danger:hover {
    background: rgba(197, 48, 48, 0.10);
    color: #9b2c2c;
}
/* Als Textfarbe braucht Rot auf dunklem Grund mehr Helligkeit als der
   Button-Ton #c53030 (gleiche Aufhellung wie bei .dl-icon-pdf). */
[data-theme="dark"] .context-menu-item.danger,
[data-theme="dark"] .context-menu-item.danger svg {
    color: #f87171;
}
[data-theme="dark"] .context-menu-item.danger:hover {
    background: rgba(248, 113, 113, 0.14);
    color: #fca5a5;
}
.context-menu-sep {
    height: 1px;
    margin: 4px 6px;
    background: var(--border);
}
/* Auswahlliste im Kontextmenü (Zielordner einer Referenz im Artikel):
   bei vielen Ordnern scrollt die Liste, nicht die Seite. */
.context-menu-liste {
    max-height: min(60vh, 420px);
    overflow-y: auto;
}

/* Die Zeile, zu der das Datei-Menü eines Artikels gesprungen ist. Steht nach
   Zebra und Hover und schlaegt beide bei gleicher Spezifitaet. */
tbody tr.zeile-markiert td {
    background: var(--brand-light);
}
tbody tr.zeile-markiert td:first-child {
    box-shadow: inset 3px 0 0 var(--brand-dark);
}
.rename-input {
    width: 100%;
    min-width: 120px;
    padding: 2px 6px;
    font-size: inherit;
    font-family: inherit;
    background: var(--bg-app);
    color: var(--t1);
    border: 1px solid var(--brand);
    border-radius: var(--r-sm);
    box-sizing: border-box;
}

/* =================================================== */
/* Wiki file-name autocomplete                         */
/* =================================================== */
.wiki-autocomplete {
    position: fixed;
    z-index: 1000;
    min-width: 260px;
    max-width: 420px;
    max-height: 220px;
    overflow-y: auto;
    padding: 4px;
    background: var(--bg-card);
    border: 1px solid var(--border-dark);
    border-radius: var(--r-sm);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    font-size: calc(13rem / 14);
    display: none;
}
.wiki-autocomplete.active {
    display: block;
}
.wiki-autocomplete-item {
    display: block;
    width: 100%;
    padding: 7px 12px;
    background: transparent;
    color: var(--t1);
    border: none;
    border-radius: var(--r-sm);
    text-align: left;
    font-size: calc(13rem / 14);
    font-weight: 400;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.wiki-autocomplete-item:hover,
.wiki-autocomplete-item.selected {
    background: var(--bg-row-hover);
    color: var(--t1);
}

/* Live syntax guide for the {abstimmung:...} editor helper */
.wiki-hint {
    position: fixed;
    z-index: 1000;
    max-width: 360px;
    padding: 6px 10px;
    background: var(--bg-card);
    border: 1px solid var(--border-dark);
    border-radius: var(--r-sm);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    font-size: calc(12rem / 14);
    line-height: 1.4;
    color: var(--t2);
    pointer-events: none;
    display: none;
}
.wiki-hint.active {
    display: block;
}
.wiki-hint strong {
    color: var(--t1);
}

/* =================================================== */
/* Karte (Map page)                                    */
/* =================================================== */

/* Full-bleed map container — fills .content exactly */
.karte-wrap {
    position: absolute;
    inset: 0;
    overflow: hidden;
}
#map {
    width: 100%;
    height: 100%;
}

/* ── Floating legend panel ── */
.karte-legend {
    position: absolute;
    top: 14px;
    right: 14px;
    z-index: 500;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r);
    box-shadow: 0 4px 16px rgba(0,0,0,.14);
    padding: 12px 14px;
    min-width: 190px;
    font-size: calc(13rem / 14);
    color: var(--t1);
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.karte-legend-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
    font-size: calc(13rem / 14);
    color: var(--brand);
    letter-spacing: 0.02em;
}
.karte-legend-title > span {
    flex: 1;
    transition: opacity .15s ease, max-width .2s ease;
}
.karte-legend-collapsed .karte-legend-title > span {
    opacity: 0;
    max-width: 0;
    overflow: hidden;
}
.karte-legend-collapsed {
    padding: 5px 7px;
    gap: 0;
    min-width: 0;
    width: auto;
}

.karte-legend-collapse {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border: none;
    background: transparent;
    color: var(--t3);
    cursor: pointer;
    border-radius: var(--r-sm);
    padding: 0;
    transition: color var(--ease), background var(--ease);
    flex-shrink: 0;
}
.karte-legend-collapse:hover { color: var(--brand); background: var(--bg-row-hover); }
.karte-legend-collapse svg { transition: transform .2s ease; }
.karte-legend-collapsed .karte-legend-collapse svg { transform: rotate(180deg); }

.karte-legend-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow: hidden;
    max-height: 400px;
    transition: max-height .25s ease, opacity .2s ease;
    opacity: 1;
}
.karte-legend-collapsed .karte-legend-body {
    max-height: 0;
    opacity: 0;
}

.karte-legend-section {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.karte-legend-divider {
    height: 1px;
    background: var(--border);
    margin: 2px 0;
}

/* ── Layer toggle rows ── */
.karte-toggle-row {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    user-select: none;
}
.karte-toggle-row:hover .karte-toggle-label {
    color: var(--brand);
}
.karte-toggle-label {
    flex: 1;
    font-size: calc(12.5rem / 14);
    transition: color var(--ease);
}

/* Color legend dots */
.karte-dot {
    width: 11px;
    height: 11px;
    border-radius: 50%;
    flex-shrink: 0;
    border: 2px solid rgba(0,0,0,.15);
}
.karte-dot-ort    { background: #4b80c0; }
.karte-dot-member { background: var(--brand); }
.karte-dot-live   { background: #e63946; }

/* Icon placeholders for indented toggle rows (locate/share) */
.karte-locate-icon-wrap,
.karte-share-icon-wrap {
    width: 11px;
    height: 11px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--t3);
}
.karte-locate-icon-wrap svg,
.karte-share-icon-wrap svg {
    width: 14px;
    height: 14px;
}

/* Toggle switch */
.karte-toggle-switch {
    position: relative;
    display: inline-block;
    width: 32px;
    height: 18px;
    flex-shrink: 0;
}
.karte-toggle-switch input {
    opacity: 0;
    width: 0;
    height: 0;
    position: absolute;
}
.karte-switch-track {
    position: absolute;
    inset: 0;
    background: var(--border-dark);
    border-radius: 9px;
    transition: background var(--ease);
    cursor: pointer;
}
.karte-switch-track::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #fff;
    transition: transform var(--ease);
    box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
.karte-toggle-switch input:checked + .karte-switch-track {
    background: var(--brand);
}
.karte-toggle-switch input:checked + .karte-switch-track::after {
    transform: translateX(14px);
}

/* ── Action buttons ── */
.karte-action-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: var(--r-sm);
    border: 1.5px solid transparent;
    font-size: calc(12.5rem / 14);
    font-weight: 500;
    font-family: var(--font);
    cursor: pointer;
    transition: background var(--ease), border-color var(--ease), color var(--ease), box-shadow var(--ease);
    line-height: 1.4;
    width: 100%;
    background: transparent;
    color: var(--t2);
}
.karte-btn-add {
    border-color: var(--border-dark);
    color: var(--t2);
}
.karte-btn-add:hover {
    background: #4b80c0;
    border-color: #4b80c0;
    color: #fff;
    box-shadow: 0 2px 8px rgba(75,128,192,.25);
}

/* ── Toast notifications ── */
.karte-toast {
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%) translateY(10px);
    z-index: 600;
    padding: 8px 18px;
    border-radius: 20px;
    font-size: calc(13rem / 14);
    font-weight: 500;
    background: var(--bg-card);
    color: var(--t1);
    border: 1px solid var(--border);
    box-shadow: 0 4px 16px rgba(0,0,0,.15);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease, transform .25s ease;
    white-space: nowrap;
}
.karte-toast.karte-toast-show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}
.karte-toast-ok    { background: #dcfce7; color: #166534; border-color: #bbf7d0; }
.karte-toast-error { background: #fee2e2; color: #991b1b; border-color: #fecaca; }
.karte-toast-info  { background: var(--bg-card); color: var(--t1); border-color: var(--border); }

/* ── Custom Leaflet markers ── */
.karte-pin {
    width: 28px;
    height: 36px;
    background: var(--pin-color, var(--brand));
    border-radius: 14px 14px 4px 4px;
    clip-path: polygon(50% 100%, 0% 30%, 0% 0%, 100% 0%, 100% 30%);
    display: flex;
    align-items: 38%;
    justify-content: center;
    padding-top: 6px;
    box-shadow: 0 2px 6px rgba(0,0,0,.3);
}

.karte-live-dot {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #e63946;
    border: 2.5px solid #fff;
    box-shadow: 0 0 0 0 rgba(230,57,70,.5);
    animation: karte-pulse 2s infinite;
}
.karte-live-dot-me {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #2e9e4f;
    border: 2.5px solid #fff;
    box-shadow: 0 0 0 0 rgba(46,158,79,.5);
    animation: karte-pulse-me 2s infinite;
}

@keyframes karte-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(230,57,70,.5); }
    70%  { box-shadow: 0 0 0 8px rgba(230,57,70,0); }
    100% { box-shadow: 0 0 0 0 rgba(230,57,70,0); }
}
@keyframes karte-pulse-me {
    0%   { box-shadow: 0 0 0 0 rgba(46,158,79,.5); }
    70%  { box-shadow: 0 0 0 8px rgba(46,158,79,0); }
    100% { box-shadow: 0 0 0 0 rgba(46,158,79,0); }
}

/* ── Coord hint in dialog ── */
.karte-coord-hint {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: calc(12rem / 14);
    color: var(--t4);
    padding: 6px 10px;
    border-radius: var(--r-sm);
    background: var(--bg-row-hover);
    border: 1px solid var(--border);
    margin-bottom: 4px;
    transition: background var(--ease), color var(--ease), border-color var(--ease);
}
.karte-coord-hint-active {
    background: color-mix(in srgb, var(--brand) 8%, transparent);
    color: var(--brand);
    border-color: var(--brand);
    font-weight: 500;
}
.karte-coord-hint svg {
    flex-shrink: 0;
}

/* ── Karte search autocomplete ── */
.karte-search-results {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    width: 250px;
    max-height: 320px;
    overflow-y: auto;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    box-shadow: 0 6px 24px rgba(0,0,0,.18);
    z-index: 700;
    padding: 4px;
    display: none;
}
.karte-search-results.karte-search-open {
    display: block;
}
.karte-search-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 8px;
    border-radius: var(--r-sm);
    cursor: pointer;
    font-size: calc(13rem / 14);
    color: var(--t1);
    transition: background var(--ease);
}
.karte-search-item:hover,
.karte-search-item.karte-search-active {
    background: var(--bg-row-hover);
}
.karte-search-item-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
}
.karte-search-item-sub {
    font-size: calc(11rem / 14);
    color: var(--t4);
}
.karte-search-empty {
    padding: 8px;
    font-size: calc(12.5rem / 14);
    color: var(--t4);
    text-align: center;
}

/* ── Ort dialog sizing ── */
.karte-ort-dialog {
    width: min(420px, 95vw);
}

/* Anchor the ort dialog to top-left instead of center */
.karte-ort-dialog[open] {
    align-self: flex-start;
    justify-self: flex-start;
    margin-top: 10px;
    margin-left: 10px;
}

/* Indented toggle rows under Live-Standorte */
.karte-row-indent {
    padding-left: 20px;
}

/* Active icon state for locate/share toggles */
.karte-icon-active svg {
    color: var(--brand);
}

/* ── Dialog form fields (no display:contents, unlike .form-grid) ── */
.dialog-field {
    margin-bottom: 12px;
}
.dialog-field label {
    display: block;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--t3);
    margin-bottom: 3px;
}
.dialog-field input {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border-dark);
    border-radius: var(--r-sm);
    font-size: 0.9375rem;
    font-family: var(--font);
    outline: none;
    box-sizing: border-box;
    margin-bottom: 0;
}
.dialog-field input:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}
.dialog-row {
    display: flex;
    gap: 10px;
    margin-bottom: 12px;
}
.dialog-field-grow { flex: 1; }
.dialog-field-shrink { flex: 0 0 80px; }

[data-theme="dark"] .dialog-field label {
    color: var(--t3);
}
[data-theme="dark"] .dialog-field input {
    background: var(--bg-card);
    border-color: var(--border-dark);
    color: var(--t1);
}

/* ── Geocode button ── */
.karte-geocode-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    margin-bottom: 8px;
    border-radius: var(--r-sm);
    border: 1.5px solid var(--border-dark);
    background: transparent;
    color: var(--t2);
    font-size: calc(12rem / 14);
    font-weight: 500;
    font-family: var(--font);
    cursor: pointer;
    transition: background var(--ease), border-color var(--ease), color var(--ease);
}
.karte-geocode-btn:hover {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
}

/* ── Popup extras ── */
.karte-popup-addr {
    font-size: calc(11rem / 14);
    color: #888;
}
.karte-popup-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 6px;
    padding: 3px 9px;
    border-radius: var(--r-sm);
    border: 1.5px solid var(--border-dark, #ccc);
    background: transparent;
    color: var(--brand);
    font-size: calc(11.5rem / 14);
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background .15s, color .15s;
}
.karte-popup-btn:hover {
    background: var(--brand);
    color: #fff;
    border-color: var(--brand);
}
.karte-popup-link {
    display: inline-block;
    margin-top: 5px;
    font-size: calc(11.5rem / 14);
    color: #4b80c0;
    text-decoration: none;
}
.karte-popup-link:hover { text-decoration: underline; }

/* ── Dark mode ── */
[data-theme="dark"] .karte-legend {
    box-shadow: 0 4px 20px rgba(0,0,0,.4);
}
[data-theme="dark"] .karte-toast-ok {
    background: rgba(22,101,52,.25);
    color: #86efac;
    border-color: rgba(22,101,52,.4);
}
[data-theme="dark"] .karte-toast-error {
    background: rgba(153,27,27,.25);
    color: #fca5a5;
    border-color: rgba(153,27,27,.4);
}
[data-theme="dark"] .karte-live-dot,
[data-theme="dark"] .karte-live-dot-me {
    border-color: var(--bg-card);
}
[data-theme="dark"] .karte-pin {
    box-shadow: 0 2px 8px rgba(0,0,0,.5);
}
[data-theme="dark"] .karte-coord-hint-active {
    background: color-mix(in srgb, var(--brand) 15%, transparent);
}

/* Abstimmung (poll widget in articles) */
.abstimmung {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r);
    padding: 16px 20px;
    margin: 16px 0;
}
.abstimmung-title {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--brand-text);
    border-bottom: 2px solid var(--brand);
    padding-bottom: 6px;
    margin: 0 0 12px;
}
.abstimmung-countdown {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 600;
    font-size: calc(11rem / 14);
    color: var(--t3);
    white-space: nowrap;
}
.abstimmung-options {
    list-style: none;
    margin: 0;
    padding: 0;
}
.abstimmung-option {
    padding: 6px 0;
    border-bottom: 1px solid var(--border);
}
.abstimmung-option:last-child {
    border-bottom: none;
}
.abstimmung-option.is-mine {
    background: var(--brand-light);
}
.abstimmung-choice {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    color: var(--t1);
}
.abstimmung-choice input[type="checkbox"]:disabled {
    cursor: not-allowed;
}
.abstimmung-choice input[type="checkbox"]:disabled + .abstimmung-label {
    color: var(--t3);
}
.abstimmung-result {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 4px 0 2px 24px;
}
.abstimmung-count {
    display: inline-block;
    font-weight: 700;
    min-width: 16px;
    text-align: center;
    padding: 0 5px;
    border-radius: 8px;
    font-size: calc(11rem / 14);
    line-height: calc(18rem / 14);
    background: var(--brand-light);
    color: var(--brand);
}
.abstimmung-bar {
    flex: 1;
    height: 8px;
    background: var(--bg-row-hover);
    border-radius: 4px;
    overflow: hidden;
}
.abstimmung-bar span {
    display: block;
    height: 100%;
    background: var(--brand);
    border-radius: 4px;
}
.abstimmung-voters {
    font-size: calc(11rem / 14);
    color: var(--t3);
    flex: 2;
}
.abstimmung-footer {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 12px;
}
.abstimmung-limit {
    font-size: calc(12rem / 14);
    color: var(--t3);
}
.abstimmung-counter {
    font-weight: 700;
    color: var(--brand);
}
.abstimmung-toggle-form {
    margin-top: 8px;
}
.abstimmung-locked {
    margin: 10px 0 0;
    font-size: calc(12rem / 14);
    color: var(--t3);
}
.abstimmung-readonly .abstimmung-label {
    color: var(--t1);
    font-weight: 500;
}
.abstimmung-readonly .abstimmung-result {
    margin-left: 0;
}

/* === Konzert Download Menu === */
.dl-trigger {
    position: relative;
    display: inline-flex;
}
.dl-trigger-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 7px;
    border-radius: var(--r-sm);
    background: none;
    border: none;
    cursor: pointer;
    color: var(--tb-icon);
    transition: background var(--ease);
}
.dl-trigger-btn:hover {
    background: var(--hover-icon-bg);
}
.dl-trigger-btn .toolicon {
    /* inherit toolicon sizing — no extra margin needed */
    display: block;
}
.dl-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 270px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-md);
    padding: 8px;
    z-index: 200;
    opacity: 0;
    pointer-events: none;
    transform: translateY(-6px);
    transition: opacity var(--ease), transform var(--ease);
}
.dl-menu.open {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}
.dl-menu-header {
    font-size: calc(11rem / 14);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--t4);
    padding: 4px 8px 8px;
}
.dl-group-label {
    font-size: calc(11rem / 14);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--t4);
    padding: 8px 8px 4px;
    margin-top: 4px;
}
.dl-group-label:not(:first-of-type) {
    border-top: 1px solid var(--border);
}
.dl-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 10px;
    border-radius: var(--r-sm);
    text-decoration: none;
    color: var(--t1);
    transition: background var(--ease);
}
.dl-item:hover {
    background: var(--hover-bg);
}
.dl-item:hover .dl-item-title {
    color: var(--brand);
}
.dl-item-icon {
    width: 36px;
    height: 36px;
    border-radius: var(--r-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.dl-icon-word  { background: #eff6ff; color: #2563eb; }
.dl-icon-pdf   { background: #fef2f2; color: #dc2626; }
.dl-icon-noten { background: #f0fdf4; color: #16a34a; }
.dl-icon-audio { background: var(--brand-light); color: var(--brand); }
.dl-item-body {
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.dl-item-title {
    font-size: 0.88rem;
    font-weight: 500;
    color: var(--t1);
    transition: color var(--ease);
}
.dl-item-sub {
    font-size: 0.78rem;
    color: var(--t3);
}
[data-theme="dark"] .dl-icon-word  { background: rgba(37,99,235,0.15);  color: #60a5fa; }
[data-theme="dark"] .dl-icon-pdf   { background: rgba(220,38,38,0.15);  color: #f87171; }
[data-theme="dark"] .dl-icon-audio { background: color-mix(in srgb, var(--brand) 15%, transparent); color: var(--brand); }

.dl-context-menu {
    position: fixed !important;
    top: 0;
    left: 0;
    right: auto;
    min-width: 250px;
    z-index: 1001;
}

/* === 404 Error Page === */
.error-standalone {
    min-height: 100vh;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    background: var(--bg-app);
}

.error-brand {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    text-decoration: none;
    margin-bottom: 2rem;
}
.error-brand img {
    width: 36px;
    height: 36px;
}
.error-brand span {
    font-size: 1rem;
    font-weight: 600;
    color: var(--brand);
}

.error-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-md);
    padding: 3rem 3.5rem;
    text-align: center;
    max-width: 480px;
    width: 100%;
}

.error-note {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: var(--brand-light);
    margin-bottom: 1.25rem;
    animation: error-float 3s ease-in-out infinite;
}

.error-note svg {
    width: 40px;
    height: 40px;
}

@keyframes error-float {
    0%, 100% { transform: translateY(0); }
    50%       { transform: translateY(-8px); }
}

.error-code {
    font-size: 7rem;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.04em;
    background: linear-gradient(135deg, var(--brand) 0%, var(--brand-dark) 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    margin-bottom: 0.75rem;
}

.error-title {
    font-size: 1.4rem;
    font-weight: 600;
    color: var(--t1);
    margin: 0 0 0.75rem;
}

.error-message {
    font-size: 0.95rem;
    color: var(--t3);
    line-height: 1.7;
    margin: 0 0 2rem;
}

.error-actions {
    display: flex;
    gap: 0.75rem;
    justify-content: center;
    flex-wrap: wrap;
}

.error-btn-primary {
    display: inline-block;
    background: var(--brand);
    color: #fff;
    border: none;
    padding: 0.65rem 1.5rem;
    border-radius: var(--r);
    font-size: 0.95rem;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.15s;
}
.error-btn-primary:hover {
    background: var(--brand-dark);
    color: #fff;
    text-decoration: none;
}

.error-btn-secondary {
    display: inline-block;
    background: transparent;
    color: var(--t2);
    border: 1px solid var(--border-dark);
    padding: 0.65rem 1.5rem;
    border-radius: var(--r);
    font-size: 0.95rem;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.error-btn-secondary:hover {
    background: var(--brand-light);
    border-color: var(--brand);
    color: var(--brand);
    text-decoration: none;
}

.error-path {
    font-size: 0.78rem;
    font-family: var(--mono);
    color: var(--t4);
    margin: 1.5rem 0 0;
    padding-top: 1.25rem;
    border-top: 1px solid var(--border);
    word-break: break-all;
}

@media (max-width: 480px) {
    .error-card {
        padding: 2rem 1.5rem;
    }
    .error-code {
        font-size: 5rem;
    }
}
[data-theme="dark"] .dl-icon-noten { background: rgba(22,163,74,0.15);  color: #4ade80; }

/* ChangeLog audit view */
.change-row { margin-bottom: 0.2rem; font-size: 0.875rem; }
.change-field { font-weight: 600; color: var(--text); }
.change-old { color: var(--text-muted); text-decoration: line-through; }
.change-new { color: var(--text); }
.nowrap { white-space: nowrap; }
.changelog-model { font-weight: 600; color: var(--primary); }

#changelog-sentinel,
.table-sentinel {
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 0.875rem;
}
#changelog-sentinel.loading::after,
.table-sentinel.loading::after {
  content: "Lade \2026";
}

/* ── Site-wide notification bubbles (ChangeLog-based) ── */
.notify-stack {
    position: fixed;
    bottom: 20px;
    right: 20px;
    display: flex;
    flex-direction: column-reverse;
    gap: 8px;
    z-index: 700;
    pointer-events: none;
    max-width: 360px;
}
.notify-bubble {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 8px;
    background: var(--bg-card);
    color: var(--t1);
    border: 1px solid var(--border);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
    text-decoration: none;
    pointer-events: auto;
    cursor: pointer;
    animation: notify-slide-in 0.3s ease forwards;
    transition: opacity 0.25s ease, transform 0.25s ease;
}
.notify-bubble:hover {
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
}
.notify-bubble-out {
    opacity: 0;
    transform: translateX(30px);
}
.notify-icon {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    color: var(--primary);
    background: color-mix(in srgb, var(--brand) 8%, transparent);
}
.notify-icon svg {
    width: 16px;
    height: 16px;
}
.notify-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}
.notify-body {
    min-width: 0;
    flex: 1;
}
.notify-header {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-bottom: 2px;
}
.notify-header strong {
    font-size: 0.85rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.notify-meta {
    font-size: 0.75rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.notify-snippet {
    font-size: 0.8rem;
    color: var(--text-muted);
    line-height: 1.3;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.notify-who {
    font-size: 0.7rem;
    color: var(--text-muted);
    margin-top: 1px;
}
@keyframes notify-slide-in {
    from {
        opacity: 0;
        transform: translateX(30px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}
@media (max-width: 480px) {
    .notify-stack {
        left: 10px;
        right: 10px;
        bottom: 10px;
        max-width: none;
    }
}

/* ── Folder table live-refresh row highlight ── */
@keyframes row-fresh-in {
    from { background: var(--brand-light); }
    to   { background: transparent; }
}
tr.row-fresh td {
    animation: row-fresh-in 0.6s ease-out forwards;
}

/* ── Terminliste: Termin ohne eigene Antwort ──
   Nur der Terminname trägt den Rahmen, nicht die Zeile: gemeint ist der Termin, nicht
   seine Datums- und Aufstellungszellen. inline-block, damit ein umbrechender Titel
   einen Kasten behält statt zerhackter Zeilenboxen; dieselbe ``offen-puls``-Animation
   wie das eigene Kästchen der Aufstellung, also gleicher Takt.
   **Kein Padding**: es rückte den Namen aus der Fluchtlinie der übrigen Termine. Der
   Rahmen liegt stattdessen per outline-offset außerhalb des Textes und reicht in das
   Zellenpolster hinein. */
.termin-offen {
    display: inline-block;
    border-radius: 3px;
    outline: 1.5px solid var(--brand);
    outline-offset: 1px;
    animation: offen-puls 1.6s ease-in-out infinite;
}

/* Wer Bewegung reduziert haben will, bekommt den Rahmen stehend statt blinkend. */
@media (prefers-reduced-motion: reduce) {
    .aufst-ich.aufst-na,
    .aufst-ich.aufst-maybe,
    .termin-offen { animation: none; }
}

/* ── Terminliste: Markerspalten zwischen Datum und Termin ──
   Zwei sehr schmale Spalten, getrennt geführt, damit Mikrofon und Pille über die
   Zeilen hinweg in derselben Flucht stehen. Das Mikrofon markiert einen öffentlich
   angekündigten Auftritt (rohes ``Termin.extern`` — dasselbe Kriterium, nach dem
   die Startseite listet), die Pille nennt die Zahl der Lieder im Ablauf.
   ``width: 1%`` ist die Projektkonvention für „so breit wie ihr Inhalt"; die Größe
   des Icons kommt als SVG-Attribut mit. Die Farbe des Icons ist ``--brand-dark``,
   der Token für **Linien** (nicht ``--brand-text``, das für brandfarbene Lettern
   auf einer Fläche steht); gezeichnet wird mit ``currentColor``, also gilt sie in
   beiden Themes. Die Pille bringt ihre Farbe aus ``.badge`` mit. */
th.marker-cell-head { width: 1%; }
td.marker-cell {
    width: 1%;
    white-space: nowrap;
    text-align: center;
    /* Enger als die globalen ``9px 12px`` der Zellen: die beiden Markerspalten
       stehen nebeneinander, und ihr doppeltes Polster schob Mikrofon und Pille
       unnötig auseinander. 4px je Seite lässt 8px zwischen ihnen und hält
       trotzdem Abstand zu Datum und Terminnamen. */
    padding: 5px 4px;
}
.marker-icon {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
    color: var(--brand-dark);
}

/* ── Upload progress card ── */
.upload-card {
    position: fixed;
    bottom: 20px;
    right: 20px;
    width: 320px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-md);
    z-index: 600;
    font-size: calc(13rem / 14);
    overflow: hidden;
    transition: box-shadow 0.2s;
}
.upload-card[hidden] { display: none !important; }
.upload-card-header {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 12px;
    background: var(--bg-thead);
    border-bottom: 1px solid var(--border);
}
.upload-card-title {
    flex: 1;
    font-weight: 600;
    color: var(--t1);
    font-size: calc(12rem / 14);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.upload-card-toggle,
.upload-card-close {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--t3);
    padding: 2px 4px;
    border-radius: var(--r-sm);
    line-height: 1;
    font-size: calc(14rem / 14);
    transition: color 0.15s, background 0.15s;
}
.upload-card-toggle:hover,
.upload-card-close:hover {
    color: var(--t1);
    background: var(--bg-row-hover);
}
.upload-card-body {
    max-height: 240px;
    overflow-y: auto;
    padding: 8px 0;
}
.upload-card--collapsed .upload-card-body { display: none; }
.uc-row {
    display: grid;
    grid-template-columns: 1fr auto auto;
    align-items: center;
    gap: 8px;
    padding: 5px 12px;
}
.uc-name {
    color: var(--t2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.uc-bar-wrap {
    width: 60px;
    height: 4px;
    background: var(--border);
    border-radius: 2px;
    overflow: hidden;
}
.uc-bar {
    height: 100%;
    background: var(--brand);
    border-radius: 2px;
    transition: width 0.2s;
}
.uc-status {
    font-size: calc(11rem / 14);
    white-space: nowrap;
    color: var(--t3);
    min-width: 80px;
    text-align: right;
}
.uc-status.ok  { color: #16a34a; }
.uc-status.err { color: var(--brand); }
.uc-status.warn { color: var(--warn-text); white-space: normal; }
[data-theme="dark"] .uc-status.ok { color: #4ade80; }

/* =================================================== */
/* Öffentliches Beitritts-Formular (join pages)        */
/* =================================================== */

/* Standalone-Seiten laden intern.css ohne App-Shell — den globalen
   no-scroll/flex-Reset von html,body wieder aufheben, damit die Seite
   normal scrollt und der Inhalt zentriert. */
html.join-page,
body.join-page {
    height: auto;
    min-height: 100%;
    overflow: auto;
    /* Auch auf html, sonst zeigt sich unterhalb des kurzen body die
       --sb-bg des globalen Resets als sichtbare Kante. */
    background: var(--bg-app);
}
body.join-page {
    display: block;
}

.join-wrap {
    max-width: 480px;            /* schmal: Erfolg / ungültig */
    margin: 0 auto;
    padding: 32px 16px 48px;
}
.join-wrap.join-wide {
    max-width: 720px;            /* breit: Beitritts-Formular */
}

.join-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-sm);
    padding: 28px 28px 24px;
}

.join-header {
    text-align: center;
    margin-bottom: 24px;
}
.join-logo {
    width: 84px;
    height: auto;
    margin-bottom: 16px;
}
.join-header h1 {
    margin: 0 0 8px;
    font-size: 1.4rem;
    font-weight: 600;
    color: var(--t1);
}
.join-intro {
    margin: 0 auto;
    max-width: 48ch;
    color: var(--t3);
    font-size: 0.95rem;
    line-height: 1.55;
}
.join-email {
    display: inline-block;
    margin-top: 14px;
    padding: 6px 14px;
    border-radius: var(--r-sm);
    background: var(--brand-light);
    color: var(--brand);
    font-weight: 600;
    font-size: 0.9rem;
}

/* Form: Karten untereinander statt im 2-Spalten-Raster */
.join-form .detail-card {
    margin-bottom: 16px;
}
.join-hint {
    margin: -4px 0 10px;
    font-size: 0.8rem;
    color: var(--t3);
}
/* Fehlermeldungen über die volle Rasterbreite, damit sie das
   display:contents-Raster nicht verschieben (vgl. .pw-strength). */
.join-form .form-grid .invalid-feedback {
    grid-column: 1 / -1;
}
.req {
    color: var(--brand);
    margin-left: 2px;
}
.join-required-note {
    margin: 4px 2px 0;
    font-size: 0.8rem;
    color: var(--t3);
}

/* Honeypot: aus dem Sichtfeld geschoben statt display:none — Bots fuellen
   sichtbare Felder aus und ueberspringen versteckte. */
.hp-feld {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* Einwilligungen */
.join-consents {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-top: 4px;
}
.join-consent {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 0;
    font-weight: 400;
    font-size: 0.9rem;
    line-height: 1.45;
    color: var(--t2);
    cursor: pointer;
}
.join-consent input[type="checkbox"] {
    width: auto;
    margin: 2px 0 0;
    flex-shrink: 0;
}
.join-consent a {
    color: var(--brand);
    text-decoration: underline;
}

.join-actions {
    margin-top: 20px;
}
.join-actions .btn {
    width: 100%;
    justify-content: center;
    padding: 11px 14px;
    font-size: calc(14rem / 14);
}

/* Status-Seiten (Erfolg / ungültig) */
.join-status-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    margin: 0 auto 16px;
    border-radius: 50%;
}
.join-status-icon svg {
    width: 28px;
    height: 28px;
}
.join-status-ok {
    background: var(--brand-light);
    color: var(--brand);
}
.join-status-warn {
    background: var(--warn-bg);
    color: var(--warn-icon);
}
.join-message {
    color: var(--t2);
    font-size: 0.95rem;
    line-height: 1.6;
    text-align: center;
}
.join-message p {
    margin: 0 0 14px;
}
.join-message-muted {
    color: var(--t4);
    font-size: 0.85rem;
}

/* === Kalender === */
/* Kalenderseite füllt den Rest von .content: .cal-page ist das einzige Kind und
   trägt flex:1, damit das Monatsraster mitwächst statt .content zu überlaufen. */
.content:has(.cal-page) { display: flex; flex-direction: column; }
.cal-page {
    flex: 1;
    min-height: 0;
    box-sizing: border-box;
    padding: 12px 16px;
    display: flex;
    flex-direction: column;
}
.cal-wrap {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* Toolbar: Monatsnavigation + Legende */
.cal-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}
.cal-nav {
    display: flex;
    align-items: center;
    gap: 10px;
}
.cal-nav-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--bg-card);
    border: 1px solid var(--border-dark);
    color: var(--t2);
    cursor: pointer;
    transition: background var(--ease), color var(--ease), border-color var(--ease);
}
.cal-nav-btn:hover {
    background: var(--brand-light);
    border-color: var(--brand);
    color: var(--brand);
}
.cal-nav-btn svg { width: 18px; height: 18px; }
.cal-title {
    margin: 0;
    min-width: 168px;
    text-align: center;
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--t1);
    letter-spacing: -0.01em;
}
.cal-title-year {
    margin-left: 8px;
    font-weight: 400;
    color: var(--t3);
}
.cal-today-btn {
    margin-left: 4px;
    padding: 6px 13px;
    border-radius: 999px;
    background: var(--brand);
    color: #fff;
    font-size: calc(12.5rem / 14);
    font-weight: 600;
    text-decoration: none;
    transition: background var(--ease);
}
.cal-today-btn:hover { background: var(--brand-dark); color: #fff; text-decoration: none; }
.cal-legend {
    display: flex;
    gap: 16px;
    font-size: calc(12rem / 14);
    color: var(--t3);
}
.cal-legend-item { display: inline-flex; align-items: center; gap: 6px; }

/* Karte um das Raster – füllt den restlichen Platz */
.cal-card {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}

/* Wochentagskopf */
.cal-weekdays {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    background: var(--bg-thead);
    border-bottom: 1px solid var(--border);
}
.cal-weekday {
    padding: 9px 12px;
    font-size: calc(11rem / 14);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--t3);
    text-align: left;
}
.cal-weekday:nth-child(n+6) { color: var(--cal-weekend); }

/* Raster: 1px-Trennlinien, Zeilen füllen die Höhe gleichmäßig */
.cal-grid {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    grid-auto-rows: 1fr;
    gap: 1px;
    background: var(--border);
}
.cal-day {
    position: relative;
    overflow: hidden;
    min-height: 0;
    padding: 6px 8px 8px;
    background: var(--bg-card);
    display: flex;
    flex-direction: column;
    gap: 4px;
    transition: background var(--ease);
}
.cal-day.has-events { cursor: pointer; }
.cal-day.has-events:hover { background: var(--hover-bg); }
.cal-day.is-weekend { background: color-mix(in srgb, var(--bg-thead) 55%, var(--bg-card)); }
.cal-day.is-weekend.has-events:hover { background: var(--hover-bg); }
.cal-day.is-outside { background: var(--bg-app); }
.cal-day.is-outside .cal-daynum { opacity: 0.5; }
/* Wer Termine anlegen darf, öffnet jeden Tag – auch den leeren. */
.cal-can-add .cal-day { cursor: pointer; }
.cal-can-add .cal-day:hover { background: var(--hover-bg); }

.cal-daynum {
    align-self: flex-start;
    min-width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 6px;
    font-size: calc(12.5rem / 14);
    font-weight: 600;
    color: var(--t2);
    border-radius: 999px;
}
.cal-day.is-weekend .cal-daynum { color: var(--cal-weekend); }
.cal-day.is-today .cal-daynum {
    background: var(--brand);
    color: #fff;
    box-shadow: 0 2px 8px color-mix(in srgb, var(--brand) 35%, transparent);
}

/* Chips (Termine / Geburtstage) */
.cal-day-detail {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.cal-chip {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 3px 7px;
    border-radius: var(--r-sm);
    font-size: calc(12rem / 14);
    line-height: 1.3;
    text-decoration: none;
    min-width: 0;
    transition: filter var(--ease), transform var(--ease);
    border-left: 3px solid transparent;
}
.cal-chip:hover { text-decoration: none; filter: brightness(0.97); transform: translateX(1px); }
[data-theme="dark"] .cal-chip:hover { filter: brightness(1.15); }
.cal-chip-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1;
}
.cal-chip-time { font-weight: 700; font-variant-numeric: tabular-nums; opacity: 0.85; }
.cal-chip-icon { width: 13px; height: 13px; flex: none; }

.cal-chip--termin {
    background: var(--brand-light);
    color: var(--brand-text);
    border-left-color: var(--brand);
}
.cal-chip--termin.is-konzert {
    background: var(--brand);
    color: #fff;
    border-left-color: var(--brand-dark);
}
/* Die Termin- und die Konzert-Marke brauchen keine eigene Dunkelregel mehr:
   ``--brand-text`` ist im dunklen Thema der aufgehellte Ton, und das Konzert
   trägt ohnehin Weiß auf dem Vollton. */
.cal-chip--geb {
    background: var(--cal-geb-bg);
    color: var(--cal-geb);
    border-left-color: var(--cal-geb);
}

/* Mehrtägige Termine: durchgehender Balken über alle betroffenen Tage.
   Die Chips bluten in die Zellränder (padding 8px) und werden vom
   overflow:hidden der Zelle sauber beschnitten, sodass ein Band entsteht;
   nur Start-/Endtag werden abgerundet. */
.cal-chip.is-span {
    margin-left: -8px;
    margin-right: -8px;
    padding-left: 8px;
    padding-right: 8px;
    border-left: none;
    border-radius: 0;
}
.cal-chip.is-span-start {
    margin-left: 0;
    border-top-left-radius: var(--r-sm);
    border-bottom-left-radius: var(--r-sm);
    border-left: 3px solid var(--brand);
    padding-left: 7px;
}
.cal-chip.is-span-end {
    margin-right: 0;
    border-top-right-radius: var(--r-sm);
    border-bottom-right-radius: var(--r-sm);
}
.cal-chip-cont { font-weight: 700; opacity: 0.75; flex: none; }

/* In der Detailleiste keinen Balken/Bleed – dort steht jeder Tag für sich. */
.cal-panel-body .cal-chip.is-span {
    margin: 0;
    border-radius: var(--r);
    border-left: 3px solid var(--brand);
    padding-left: 14px;
}

/* Punkte (nur mobil sichtbar) */
.cal-dots { display: none; gap: 3px; flex-wrap: wrap; padding: 1px 2px; }
.cal-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.cal-dot--termin { background: var(--brand); }
.cal-dot--geb { background: var(--cal-geb); }
.cal-legend .cal-dot { width: 8px; height: 8px; }

/* Offcanvas-Tagesdetail (Desktop + Mobil): großer, lesbarer Bereich */
.cal-panel-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.35);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.25s ease, visibility 0.25s ease;
    z-index: 1099;
}
.cal-panel-overlay.open { opacity: 1; visibility: visible; }
.cal-panel {
    position: fixed;
    top: var(--tb-h);
    right: 0;
    height: calc(100% - var(--tb-h));
    width: 380px;
    max-width: 90vw;
    background: var(--bg-card);
    border-left: 1px solid var(--border);
    box-shadow: -10px 0 30px rgba(0, 0, 0, 0.18);
    transform: translateX(100%);
    transition: transform 0.28s ease;
    z-index: 1100;
    display: flex;
    flex-direction: column;
}
.cal-panel.open { transform: translateX(0); }
.cal-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border);
}
.cal-panel-date { margin: 0; font-size: 1.05rem; font-weight: 700; color: var(--t1); }
.cal-panel-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 40px;
    height: 40px;
    padding: 0;
    flex: none;
    border: none;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--t2);
    cursor: pointer;
    transition: background var(--ease), color var(--ease);
}
.cal-panel-close:hover { background: var(--hover-bg); color: var(--t1); }
.cal-panel-close svg { width: 26px; height: 26px; flex: none; }
/* Einträge und Anlege-Formular teilen sich einen Scrollbereich. */
.cal-panel-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}
.cal-panel-body {
    padding: 16px 20px;
    display: flex;
    flex-direction: column;
    gap: 9px;
}
.cal-panel-body .cal-chip {
    font-size: calc(14rem / 14);
    padding: 11px 14px;
    border-radius: var(--r);
    border-left-width: 4px;
    gap: 9px;
}
.cal-panel-body .cal-chip-text { white-space: normal; overflow: visible; }
.cal-panel-body .cal-chip-icon { width: 17px; height: 17px; }

/* Termin anlegen im Tagesdetail */
.cal-panel-add { padding: 16px 20px 20px; }
.cal-panel-body:not([hidden]) + .cal-panel-add { border-top: 1px solid var(--border); }
.cal-add-open {
    width: 100%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}
/* .btn setzt display, das schlägt sonst das hidden-Attribut, mit dem
   kalender.js zwischen Button und Formular umschaltet. */
.cal-add-open[hidden] { display: none; }
.cal-add-open svg { width: 17px; height: 17px; flex: none; }
.cal-add-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.cal-add-checks { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 2px; }

/* Mobil: kompaktes Raster mit Punkten, natürliche Höhe (scrollt) */
@media (max-width: 768px) {
    .cal-page { flex: none; min-height: 100%; padding: 12px 10px; }
    .cal-wrap, .cal-card { flex: none; }
    .cal-grid { flex: none; grid-auto-rows: auto; }
    .cal-toolbar { margin-bottom: 12px; }
    .cal-legend { width: 100%; order: 3; }
    .cal-weekday { padding: 7px 4px; text-align: center; font-size: calc(10rem / 14); }
    .cal-day {
        min-height: 58px;
        padding: 5px 3px;
        align-items: center;
        cursor: pointer;
    }
    .cal-daynum { align-self: center; font-size: calc(12rem / 14); }
    .cal-dots { display: flex; justify-content: center; }
    .cal-day-detail { display: none; }
}

/* === Dateidetail: Ablageorte und Versionen === */
.datei-vorschau {
    max-width: 100%;
    max-height: 64px;
    border-radius: 4px;
    object-fit: contain;
}

.datei-hinweis {
    margin: 0 0 10px;
    font-size: calc(13rem / 14);
    color: var(--text-muted);
}

.datei-orte {
    list-style: none;
    margin: 0;
    padding: 0;
}

.datei-orte li {
    padding: 6px 0;
    border-bottom: 1px solid var(--border);
    font-size: calc(14rem / 14);
}

.datei-orte li:last-child { border-bottom: none; }

.datei-ort-hier {
    margin-left: 8px;
    padding: 1px 6px;
    border-radius: 10px;
    background: var(--border);
    color: var(--text-muted);
    font-size: calc(11rem / 14);
}

.datei-version-tabelle {
    width: 100%;
    border-collapse: collapse;
    font-size: calc(14rem / 14);
}

.datei-version-tabelle td {
    padding: 7px 8px 7px 0;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.datei-version-tabelle tr:last-child td { border-bottom: none; }
.datei-version-tabelle .ist-aktuell td { font-weight: 600; }
.datei-version-tabelle .v-vorschau { width: 44px; padding-right: 12px; }

.datei-version-tabelle .v-vorschau img {
    display: block;
    width: 44px;
    height: 44px;
    object-fit: cover;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--bg-thead);
}

.datei-version-tabelle .v-nummer { width: 70px; color: var(--text-muted); }
.datei-version-tabelle .v-groesse { text-align: right; white-space: nowrap; }
.datei-version-tabelle .v-aktion { text-align: right; width: 1%; }
.datei-version-tabelle .v-aktion form { margin: 0; }
.datei-version-tabelle .keine-versionen td { color: var(--text-muted); }

.btn-klein {
    padding: 3px 10px;
    font-size: calc(12rem / 14);
}

@media (max-width: 640px) {
    .datei-version-tabelle .v-autor { display: none; }
    .datei-version-tabelle .v-vorschau { width: 32px; padding-right: 8px; }
    .datei-version-tabelle .v-vorschau img { width: 32px; height: 32px; }
}

/* === Dialog: brechende Verweise beim Löschen/Umbenennen === */
.verwendung-dialog {
    max-width: 520px;
    width: calc(100% - 32px);
    padding: 20px 22px;
    border: 1px solid var(--border-dark);
    border-radius: 10px;
    background: var(--bg-card);
    color: var(--text);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
}

.verwendung-dialog::backdrop {
    background: rgba(0, 0, 0, 0.45);
}

.verwendung-dialog h3 {
    margin: 0 0 8px;
    font-size: calc(17rem / 14);
}

.verwendung-hinweis {
    margin: 0 0 14px;
    font-size: calc(14rem / 14);
    color: var(--text-muted);
}

.verwendung-block {
    margin-bottom: 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border);
    font-size: calc(14rem / 14);
}

.verwendung-block:last-of-type {
    border-bottom: none;
}

.verwendung-block ul {
    margin: 4px 0 0;
    padding-left: 20px;
}

.verwendung-block li {
    padding: 2px 0;
    color: var(--text-muted);
}

.verwendung-buttons {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 16px;
}

/* „Für alle weiteren gleichen Fälle übernehmen" bei den Ablage-Rückfragen. */
.verwendung-auswahl {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: calc(13rem / 14);
    color: var(--text-muted);
    cursor: pointer;
}

/* =================================================== */
/* Chip-Multiselect                                    */
/* =================================================== */
/* Markup: _chip_multiselect.html, Verhalten: chip-multiselect.js.
   Das native <select> bekommt bewusst KEINE display-Regel -- das JS blendet es
   ueber das hidden-Attribut aus, ohne JS muss es sichtbar bleiben. Aus demselben
   Grund haengt .chip-ms-ui sein display an :not([hidden]). */

.chip-ms {
    width: 100%;
    min-width: 0;
}

.chip-ms-ui:not([hidden]) {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.chip-ms-legend {
    font-size: calc(11rem / 14);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--t4);
}

.chip-ms-list {
    list-style: none;
    margin: 0;
    padding: 4px;
    background: var(--bg-app);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    min-width: 0;
}

.chip-ms-list:empty::before {
    content: attr(data-leer);
    display: block;
    padding: 6px 5px;
    font-size: calc(12rem / 14);
    color: var(--t4);
}

/* Oben: die getroffene Auswahl als Chips */
.chip-ms-selected {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 4px;
    min-height: 34px;
}

/* Darunter: der scrollbare Vorrat als Zeilenliste */
.chip-ms-pool {
    max-height: 220px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.chip-ms-item {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    cursor: pointer;
    user-select: none;
    transition: background var(--ease), color var(--ease), border-color var(--ease);
}

.chip-ms-pool > .chip-ms-item {
    padding: 7px 9px;
    border-radius: var(--r-sm);
    font-size: calc(13rem / 14);
    color: var(--t1);
}

.chip-ms-pool > .chip-ms-item:hover {
    background: var(--brand-light);
}

.chip-ms-item.chip-ms-chip {
    padding: 3px 6px 3px 10px;
    border-radius: 999px;
    background: var(--brand-light);
    color: var(--brand);
    border: 1px solid transparent;
    font-size: calc(12.5rem / 14);
    line-height: 1.4;
}

.chip-ms-item.chip-ms-chip:hover {
    border-color: var(--brand);
}

.chip-ms-text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.chip-ms-aktion {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font-size: calc(14rem / 14);
    line-height: 1;
    opacity: 0.55;
    cursor: pointer;
}

.chip-ms-item:hover .chip-ms-aktion {
    opacity: 1;
}

.chip-ms-search {
    width: 100%;
    height: 32px;
    box-sizing: border-box;
    padding: 0 10px;
    font-family: var(--font);
    font-size: calc(13rem / 14);
    color: var(--t1);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    outline: none;
    transition: border-color var(--ease), box-shadow var(--ease);
}

.chip-ms-search:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

.chip-ms-search::placeholder {
    color: var(--t4);
}

/* Ziehen gibt es nur auf Zeigergeraeten -- siehe chip-multiselect.js */
@media (pointer: fine) {
    .chip-ms-item { cursor: grab; }
    .chip-ms-item:active { cursor: grabbing; }
}

.chip-ms-item.sortable-ghost { opacity: 0.4; }
.chip-ms-item.sortable-chosen { background: var(--brand); color: #fff; }

/* ── Ausschluss-Variante (Nicht in Gruppen) ── */
.chip-ms--exclude .chip-ms-item.chip-ms-chip {
    background: var(--status-danger-bg);
    color: var(--status-danger-text);
}

.chip-ms--exclude .chip-ms-item.chip-ms-chip:hover {
    border-color: var(--status-danger-border);
}

.chip-ms--exclude .chip-ms-pool > .chip-ms-item:hover {
    background: var(--status-danger-bg);
}

/* ── Ziel-Popover nach Long-Press ── */
/* position:fixed und rohe Viewport-Koordinaten, anders als .att-move-picker: die
   Offcanvas-Panels sind selbst fixed und scrollen intern. */
.chip-ms-picker {
    position: fixed;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 140px;
    padding: 6px;
    border-radius: 10px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-md);
}

.chip-ms-pick {
    padding: 8px 10px;
    border: 0;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--t1);
    font-size: calc(13rem / 14);
    text-align: left;
    cursor: pointer;
}

.chip-ms-pick:hover {
    background: var(--bg-row-hover);
}

/* =================================================== */
/* Farbwahl (Color Picker)                              */
/* =================================================== */
/* Markup: _color_picker.html, Verhalten: color-picker.js.
   Textfeld bleibt Quelle der Wahrheit; der native <input type="color"> dient
   als Picker UND Vorschau-Swatch in einem. */

.color-picker {
    display: flex;
    align-items: center;
    gap: 8px;
}

.color-picker-text {
    flex: 1;
    min-width: 0;
}

.color-picker-swatch {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 1px solid var(--border-dark);
    border-radius: 5px;
    background: var(--bg-card);
    cursor: pointer;
}

.color-picker-swatch::-webkit-color-swatch-wrapper { padding: 2px; }
.color-picker-swatch::-webkit-color-swatch { border: none; border-radius: 3px; }
.color-picker-swatch::-moz-color-swatch { border: none; border-radius: 3px; }

.color-picker-swatch:focus-visible {
    outline: 2px solid var(--brand-ring);
    outline-offset: 2px;
}

/* =================================================== */
/* Gruppen-Berechtigungen                              */
/* =================================================== */
/* Gemeinsam von folder_berechtigungen, artikel_berechtigungen und
   forum_zugriff genutzt; Verhalten in berechtigungen.js. */

.detail-card .radio-label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0;
    cursor: pointer;
    color: var(--t2);
    font-size: calc(14rem / 14);
}

.detail-card .gruppen-auswahl {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--bg-row-hover);
}

.detail-card .gruppen-auswahl[hidden] {
    display: none;
}

.members-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    margin-top: 0.5rem;
}

.members-chips[hidden] {
    display: none;
}

.member-chip {
    padding: 0.125rem 0.625rem;
    border-radius: 99px;
    background: var(--bg-row-hover);
    color: var(--t2);
    font-size: calc(12rem / 14);
    white-space: nowrap;
}

.detail-hint {
    margin-top: 0.75rem;
    font-size: calc(12rem / 14);
    color: var(--t3);
}

/* === Hilfe-Tooltip ===
   Info-Icon (_hilfe_icon.html) plus die eine geteilte Blase, die tooltip.js an
   den Body hängt. Der Text steht als help_text am Model, nie hier. */
.hilfe-icon {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
    padding: 0;
    border: 0;
    background: none;
    color: var(--t4);
    cursor: help;
    line-height: 0;
}
.hilfe-icon:hover,
.hilfe-icon:focus-visible {
    color: var(--brand);
}
.hilfe-icon:focus-visible {
    outline: 2px solid var(--brand-ring);
    outline-offset: 2px;
    border-radius: 50%;
}
/* Auslöser, die kein Icon sind (Chips, Spaltenköpfe) */
[data-hilfe]:not(.hilfe-icon) {
    cursor: help;
}

/* position: fixed ist Pflicht – .table-container und .cal-panel-scroll haben
   overflow-y:auto und würden eine absolut positionierte Blase abschneiden. */
.hilfe-bubble {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 9999;
    max-width: 300px;
    padding: 10px 14px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--bg-card);
    color: var(--t2);
    font-size: calc(12.5rem / 14);
    line-height: 1.45;
    box-shadow: var(--shadow-md);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s;
}
.hilfe-bubble.visible {
    opacity: 1;
}

/* Ohne dies reißt das margin-right der Checkbox-Labels eine Lücke zum Icon. */
.detail-card .checkbox-group label {
    margin-right: 0;
}
/* .checkbox-row bringt padding-top mit; im Kalender-Panel regelt der Spaltenabstand
   von .cal-add-checks den Abstand bereits. */
.cal-add-checks .checkbox-row {
    padding-top: 0;
}

/* =================================================== */
/* Konfiguration                                       */
/* =================================================== */
/* max-width ohne margin:auto — wie .detail-page.member-voice haelt der Deckel
   nur die Zeilenlaenge, die Karten bleiben aber linksbuendig wie ihre
   Geschwister und werden nicht zur zentrierten Insel. */
.kf-page {
    padding: 16px;
    padding-bottom: calc(var(--kf-bars-h, 0px) + 24px);
    max-width: 1100px;
}

/* Karte für neu angelegte Einträge — immer ganz oben, vor den Gruppen. */
.kf-neu {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
    margin-bottom: 12px;
    padding: 4px 16px;
}

/* Mängel-Banner ganz oben: Pflichtschlüssel ohne Wert. Warn-Töne, nicht
   Fehler-Töne — das Portal läuft, es fehlt nur die eigene Angabe. */
.kf-mangel {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    background: var(--warn-bg);
    border: 1px solid var(--warn-border);
    border-radius: var(--r);
    padding: 12px 16px;
    margin-bottom: 12px;
    color: var(--warn-text);
}
.kf-mangel-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    color: var(--warn-icon);
}
.kf-mangel-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1 1 260px;
}
.kf-mangel-titel {
    font-size: calc(14rem / 14);
    font-weight: 700;
    color: var(--warn-strong);
}
.kf-mangel-detail {
    font-size: calc(12rem / 14);
    line-height: 1.45;
}
.kf-mangel-detail code {
    font-family: var(--mono);
    font-size: calc(11rem / 14);
    color: var(--warn-strong);
}
/* Neutrale Tonlage: ein abgeschalteter Dienst ist kein Fehler, sondern eine
   Auskunft. Bewusst aus vorhandenen Tokens gebaut — für eine graue Zeile lohnt
   kein eigenes --info-Set, und diese vier haben ihre Dark-Mode-Werte schon. */
.kf-mangel--hinweis {
    background: var(--bg-thead);
    border-color: var(--border);
    color: var(--t2);
}
.kf-mangel--hinweis .kf-mangel-icon { color: var(--t3); }
.kf-mangel--hinweis .kf-mangel-detail code { color: var(--t2); }

/* Akkordeon-Karten im Stil von .detail-card, Marker-Rezept von .ae-help. */
.kf-gruppe {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
    margin-bottom: 12px;
}
.kf-gruppe > summary {
    display: flex;
    flex-wrap: wrap;  /* grosse Schrift: Zaehler und Hinweis rutschen in die naechste Zeile */
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    cursor: pointer;
    list-style: none;
    user-select: none;
    border-bottom: 1px solid transparent;
}
.kf-gruppe[open] > summary { border-bottom-color: var(--border); }
.kf-gruppe > summary::-webkit-details-marker { display: none; }
.kf-gruppe > summary::before {
    content: "";
    width: 0;
    height: 0;
    border-left: 4px solid var(--t3);
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    transition: transform var(--ease);
    flex-shrink: 0;
}
.kf-gruppe[open] > summary::before { transform: rotate(90deg); }
.kf-gruppe > summary:hover .kf-gruppen-titel { color: var(--brand); }
.kf-gruppen-titel {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--brand-text);
    transition: color var(--ease);
}
.kf-gruppen-count {
    font-size: calc(11rem / 14);
    font-weight: 700;
    color: var(--t3);
    background: var(--bg-thead);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 1px 8px;
    min-width: 22px;
    text-align: right;
    margin-left: auto;
    flex-shrink: 0;
}
.kf-gruppen-hinweis {
    font-size: calc(12rem / 14);
    color: var(--t4);
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
}
.kf-gruppe-body { padding: 4px 16px; }

/* Eintrag als Grid mit benannten Bereichen — DOM-Reihenfolge Key → Wert →
   Beschreibung stimmt in beiden Layouts, die Media Query schaltet nur um. */
.kf-eintrag {
    display: grid;
    grid-template-columns: minmax(180px, 1fr) minmax(0, 1.5fr);
    grid-template-areas: "key  wert"
                         "desc wert";
    column-gap: 16px;
    row-gap: 4px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
}
.kf-eintrag:last-child { border-bottom: none; }
.kf-key { grid-area: key; align-self: start; display: flex; align-items: center; gap: 8px; }
.kf-desc { grid-area: desc; align-self: start; }
.kf-wert { grid-area: wert; }

.kf-key code {
    font-family: var(--mono);
    font-size: calc(12rem / 14);
    font-weight: 600;
    color: var(--t3);
    overflow-wrap: anywhere;
}

/* Wert steht immer in einem sichtbaren Feld (kein Edit-Modus mehr). */
.kf-eintrag .inline-input {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: 5px 9px;
    border: 1px solid var(--border-dark);
    border-radius: 5px;
    background: var(--bg-card);
    color: var(--t1);
    font-size: calc(13rem / 14);
    font-family: var(--font);
    resize: none;
    min-height: 32px;
    line-height: 1.45;
    transition: border-color var(--ease), box-shadow var(--ease);
}
.kf-eintrag textarea.inline-input { overflow: hidden; }
.kf-eintrag .inline-input:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 2px var(--brand-light);
    background: var(--bg-card);
}
/* Textfelder füllen die volle Höhe der wert-Zelle (auf Desktop key+desc-Zeilen)
   und stehen nie unter 4 Zeilen. height:100% greift, weil .kf-wert als Grid-
   Eintrag eine definite Höhe hat; autogrow setzt min-height auf den Inhalt. */
.kf-eintrag[data-typ="text"] textarea.kf-value-input {
    height: 100%;
    min-height: calc(1.45em * 4 + 10px);
}
/* Number-Input: Spinner bleibt (Port/Zoom/Tage), kein min/max/step — die
   Wertefunktion wird nicht eingeengt (z.B. leere Datei-ID möglich). */
.kf-eintrag input[type="number"].inline-input { width: 100%; }

/* Boolean als Toggle-Switch — die Checkbox trägt bewusst nicht .inline-input,
   sondern wird hier eigens gestylt. Gespeichert bleibt "1"/"0" als Zeichenkette. */
.kf-bool {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    user-select: none;
    padding: 4px 0;
}
.kf-bool input {
    appearance: none;
    -webkit-appearance: none;
    width: 40px;
    height: 22px;
    border-radius: 11px;
    background: var(--border-dark);
    position: relative;
    cursor: pointer;
    flex-shrink: 0;
    margin: 0;
    transition: background var(--ease);
}
.kf-bool input::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--bg-card);
    box-shadow: var(--shadow-xs);
    transition: transform var(--ease);
}
.kf-bool input:checked { background: var(--brand); }
.kf-bool input:checked::after { transform: translateX(18px); }
.kf-bool input:focus-visible { outline: 2px solid var(--brand-ring); outline-offset: 2px; }
.kf-bool-state { font-size: calc(12rem / 14); color: var(--t3); }
.kf-bool input:not(:checked) ~ .kf-bool-state::before { content: "Aus"; }
.kf-bool input:checked ~ .kf-bool-state::before { content: "An"; color: var(--brand); }

/* Löschen-Button immer sichtbar (kein Edit-Modus, an den er sich hängen könnte),
   dezent über --t4, rot bei Hover. Auf Touch die einzige erreichbare Variante. */
.kf-del-btn {
    margin-left: auto;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--t4);
    padding: 4px;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color var(--ease), background var(--ease);
}
.kf-del-btn:hover { color: var(--error-solid); background: var(--error-bg); }
.kf-eintrag.to-delete { opacity: 0.45; }
.kf-eintrag.to-delete .kf-key code,
.kf-eintrag.to-delete .kf-desc-text { text-decoration: line-through; }

/* Ungespeicherte Änderung — Warnfarbe statt Marken-Blau, damit sie sich von
   :focus unterscheidet und auch ungefokussiert auffällt. Nur am tatsächlich
   geänderten Teil (Wert und/oder Beschreibung getrennt geprüft in konfiguration.js). */
.kf-wert.kf-geaendert .inline-input {
    border-color: var(--warn-icon);
    box-shadow: 0 0 0 2px var(--warn-border);
}
.kf-wert.kf-geaendert .kf-bool-state { color: var(--warn-icon); font-weight: 600; }
.kf-desc.kf-geaendert .kf-desc-text { color: var(--warn-strong); font-weight: 600; }

/* Beschreibung: Klick auf Text oder Stift schaltet zum Eingabefeld. */
.kf-desc { display: flex; align-items: flex-start; gap: 6px; }
.kf-desc-text {
    flex: 1;
    font-size: calc(12rem / 14);
    color: var(--t3);
    line-height: 1.4;
    cursor: pointer;
    word-break: break-word;
    min-height: 18px;
}
.kf-desc-text:empty::before {
    content: "Beschreibung hinzufügen";
    color: var(--t4);
    font-style: italic;
}
.kf-desc-edit {
    flex-shrink: 0;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--t4);
    padding: 2px;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    transition: color var(--ease);
}
.kf-desc-edit:hover { color: var(--brand); }
/* .kf-desc-input darf KEIN eigenes display bekommen — das hidden-Attribut muss
   wirken, display:grid/flex gewinnt sonst dagegen. */
.kf-desc-input { width: 100%; box-sizing: border-box; }

.kf-leer { text-align: center; color: var(--t4); padding: 32px 0; font-size: calc(14rem / 14); }

/* Fokus-Freiraum statt gestrichelter Scroll-Nachführung. */
.kf-eintrag textarea,
.kf-eintrag input {
    scroll-margin-bottom: calc(var(--kf-bars-h, 0px) + 24px);
}

/* hidden braucht überall eine explizite Regel — intern.css hat keine globale
   [hidden]-Regel, und display:grid/flex gewinnt sonst gegen das Attribut. */
.kf-eintrag[hidden],
.kf-gruppe[hidden],
.kf-neu[hidden],
.kf-desc-input[hidden],
.kf-leer[hidden] { display: none; }

/* Markup-Legende für MAIL_*-Felder — hängt am Fokus, nicht mehr am Edit-Modus. */
.konfig-mailhelp {
    position: fixed;
    bottom: var(--kf-applybar-h, 0px);
    left: var(--sb-width);
    right: 0;
    z-index: 99;
    display: none;
    flex-wrap: wrap;
    gap: 6px 14px;
    align-items: center;
    padding: 10px 28px;
    padding-bottom: calc(10px + env(safe-area-inset-bottom));
    background: var(--bg-card);
    border-top: 1px solid var(--border);
    font-size: calc(12rem / 14);
    color: var(--t3);
}
.konfig-mailhelp.visible { display: flex; }
.konfig-mailhelp code {
    font-family: var(--mono);
    font-size: calc(11rem / 14);
    background: var(--bg-thead);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 1px 5px;
    color: var(--t1);
}
.konfig-mailhelp .konfig-mailhelp-title {
    font-weight: 700;
    color: var(--brand);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: calc(11rem / 14);
}

/* Apply-Bar — IDs bleiben, damit das übernommene JS unverändert greift. */
.konfig-apply-bar {
    position: fixed;
    bottom: 0;
    left: var(--sb-width);
    right: 0;
    padding: 14px 28px;
    padding-bottom: calc(14px + env(safe-area-inset-bottom));
    background: var(--bg-card);
    border-top: 1px solid var(--border);
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 16px;
    transform: translateY(100%);
    transition: transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
    z-index: 100;
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.08);
}
.konfig-apply-bar.visible { transform: translateY(0); }
.konfig-change-summary { font-size: calc(13rem / 14); color: var(--t3); }

[data-theme="dark"] .kf-eintrag .inline-input {
    background: var(--bg-app);
    border-color: rgba(255, 255, 255, 0.12);
}
[data-theme="dark"] .kf-bool input { background: rgba(255, 255, 255, 0.18); }
[data-theme="dark"] .kf-bool input::after { background: var(--t1); }
[data-theme="dark"] .konfig-apply-bar { box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.35); }

@media (max-width: 768px) {
    .kf-eintrag {
        grid-template-columns: 1fr;
        grid-template-areas: "key" "wert" "desc";
    }
    .konfig-apply-bar { left: 0; }
    .konfig-mailhelp {
        left: 0;
        flex-wrap: nowrap;
        overflow-x: auto;
    }
}

/* =================================================== */
/* Auslieferungen (Seite „Änderungen")                 */
/* =================================================== */
/* Die Release-Notizen aus CHANGELOG.md, aufbereitet von intern/auslieferungen.py:
   eine Folge kurzer Karten, kein langer Textblock. Deshalb trägt jede
   Auslieferung ihren eigenen Kasten — beim Scrollen kommt die Kante wieder ins
   Bild. Ein einzelner, viele Seiten langer Kasten hätte Ober- und Unterkante nie
   gleichzeitig auf dem Schirm, genau der Grund, aus dem die Mitgliedskarte 2026
   ihren Kasten verloren hat (siehe docs/frontend.md).

   Der Kasten ist gepolstert wie seine Geschwister (.detail-page, 20/24 px) und
   trägt einen Deckel von 1280 px — ohne ``margin: 0 auto``: der Deckel hält die
   Zeilenlänge im Lesbaren, aber die Seite bleibt linksbündig wie ihre Geschwister
   und wird nicht wieder zur zentrierten Insel (dieselbe Begründung wie bei
   .detail-page.member-voice). ``box-sizing: border-box`` gilt global (Reset), der
   Deckel schließt das Polster also ein: die Karten messen höchstens 1232 px.

   Die Abschnitte tragen eine eigene Kopfzeile statt .detail-card h3 („Auslieferung"
   statt „Detailkarte"): dessen text-transform: uppercase machte aus der Kennung
   V1.0.0-RC4. */

.auslieferungen {
    max-width: 1280px;
    /* Unten mehr als oben: die letzte Karte soll nicht am Fensterrand kleben. */
    padding: 20px 24px 40px;
}

.auslieferungen-intro,
.auslieferungen-leer {
    margin: 0;
    color: var(--t3);
    font-size: calc(13rem / 14);
}

.auslieferungen-intro { margin-bottom: 18px; }

/* Der Abstand sitzt zwischen den Karten, nicht in ihnen — so bleibt die Kante
   jeder Karte an allen vier Seiten sichtbar. */
.auslieferungen-liste {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.auslieferung {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
    padding: 16px 20px;
    /* Flex-Kinder schrumpfen sonst nicht unter ihre Inhaltsbreite, und lange
       Bezeichner wie --status-success-border ragen sonst aus dem Bild. */
    min-width: 0;
    overflow-wrap: anywhere;
}

/* Die laufende Version trägt links eine 3-px-Kante in der Akzentfarbe — dieselbe
   Aussage wie die Stimmenkante der Mitgliedskarte, eine Ebene tiefer (dort die
   Seite, hier die Karte). Auf der Kante steht kein Text, sie darf deshalb den
   Vollton tragen; eine Volltonfläche MIT Text wäre auf mehreren Stimmenfarben
   unlesbar, das ist im Haus so entschieden (siehe docs/frontend.md).

   Das Innenpolster links ist 18 statt 20 px, damit der Text der Karten in
   derselben Fluchtlinie bleibt: 3 px Kante + 18 px = 21 px, die Nachbarkarte
   kommt über ihre 1 px Kante + 20 px Polster auf dieselben 21 px. (Die
   Kantenbreite allein abzuziehen ergäbe 17 px und damit einen um 1 px
   verschobenen Text — sichtbar erst im gerenderten Vergleich, siehe
   .auslieferungen weiter oben.) */
.auslieferung--laufend {
    border-left: 3px solid var(--brand);
    padding-left: 18px;
}

/* Eigene Kopfzeile statt .detail-card h3: dessen text-transform: uppercase
   machte aus der Kennung V1.0.0-RC4. Der Nachfahren-Selektor ist nötig, nicht
   kosmetisch: ``.content header`` (Grundgerüst) setzt genau diesem Element
   Hintergrund und ``padding: 12px 20px`` und trägt eine Klasse mehr als
   ``.auslieferung-kopf`` allein — die Padding-Seiten sind deshalb alle vier
   ausgeschrieben, sonst blieben oben/rechts/links die 12 bzw. 20 px stehen. */
.auslieferung .auslieferung-kopf {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 10px;
    margin: 0 0 12px;
    padding: 0 0 10px;
    background: none;
    border-bottom: 1px solid var(--border);
}

/* Aus demselben Grund mit .auslieferung davor: ``.content h2`` setzt jedem h2
   im Rollbereich font-size: 1.2rem und schlägt eine einzelne Klasse. */
.auslieferung .auslieferung-version {
    margin: 0;
    min-width: 0;
    font-size: calc(15rem / 14);
    font-weight: 700;
    color: var(--t1);
}

.auslieferung-datum {
    font-size: calc(12rem / 14);
    color: var(--t3);
    font-variant-numeric: tabular-nums;
}

/* Nur der Abstand nach rechts; Farbe und Dark-Mode-Wert bringt
   .badge.badge-primary mit. Bei schmaler Breite darf die Marke umbrechen. */
.auslieferung-marke {
    margin-left: auto;
}

/* Die Gruppenüberschrift („Hinzugefügt", „Behoben", „Entfernt") — das Hausrezept
   für eine Zwischenüberschrift in einer Karte, wie .kf-gruppen-titel und
   .detail-card h3. Uppercase ist hier richtig: es ist eine Beschriftung, keine
   Kennung. Die Versionszeile darüber bleibt klein, siehe .auslieferung-version.

   Eine einzelne Klasse genügt — anders als beim Kartenkopf. Nachgemessen im
   Browser: ``.content h3`` gibt es nicht, es greifen nur ``.content h2`` (anderes
   Element) und ``.content header`` (Vorfahre, Hintergrund/Polster), und beide
   schlagen ein ``<h3>`` nicht. Zu schlagen sind allein die Vorgaben des Browsers
   (``margin: 1em 0``, ``font-size: 1.17em``); eine Klasse tut das.

   Die Abstände tragen den Rhythmus der Karte: 18 px Luft vor der Überschrift,
   8 px bis zu ihrer Liste. Die 18 px gelten auch für die erste Gruppe, denn der
   ``margin-bottom`` des Kartenkopfs (12 px) und dieses ``margin-top`` fallen
   zusammen und der Randzusammenfall nimmt den größeren — die erste Überschrift
   bekommt also weder 12 + 18 noch das Doppelte einer mittleren. Steht gar keine
   Überschrift (Gruppe ohne Namen), folgt die Liste direkt und mit den 12 px des
   Kopfes; dort fehlt nichts, was abgesetzt werden müsste. */
.auslieferung-gruppe {
    margin: 18px 0 8px;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--brand-text);
}

/* Die Schriftfarbe kommt aus ``--brand-text`` — im hellen Thema die abgedunkelte
   Marke, im dunklen die aufgehellte (5,8:1 auf ``--bg-card`` statt 2,7:1). Die
   beiden Rollen der Markenfarbe stehen bei ``--brand-text`` in ``:root`` und im
   Dark-Block erklärt; hier ist deshalb keine eigene Dunkelregel nötig. */

.auslieferung-liste {
    margin: 0;
    padding-left: 20px;
    font-size: calc(14rem / 14);
    line-height: 1.65;
    color: var(--t2);
}

/* Ein Punkt kann mehrere Absätze haben (der nächste Punkt beginnt erst mit dem
   nächsten <li>): der Abstand zwischen zwei Punkten bleibt größer als der
   zwischen zwei Absätzen desselben Punktes. */
.auslieferung-liste li + li { margin-top: 12px; }
.auslieferung-liste li p { margin: 0; }
.auslieferung-liste li p + p { margin-top: 5px; }

/* Inline-Auszeichnung des Absatzes (`code`, **fett**, *kursiv*) — die Betonungen
   erben ihre Schrift vom Fließtext, nur der Code tritt heraus. */
.auslieferung-liste code {
    font-family: var(--mono);
    font-size: calc(13rem / 14);
    background: var(--code-bg);
    color: var(--code-color);
    border-radius: var(--r-sm);
    padding: 1px 5px;
}

/* === Rechte-Hilfe-Dialog (Gruppen-Seite und eigenes Profil) === */
.perm-hilfe {
    width: min(640px, calc(100vw - 32px));
    max-height: calc(100vh - 48px);
    overflow-y: auto;
    background: var(--bg-card);
    color: var(--t1);
    white-space: normal;
}
.perm-hilfe h3 { padding-right: 24px; }
.perm-hilfe-kurz {
    margin: -6px 0 16px;
    font-size: calc(13rem / 14);
    line-height: 1.5;
    color: var(--t2);
}
.perm-hilfe h4 {
    margin: 18px 0 8px;
    font-size: calc(11rem / 14);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--t4);
}
.perm-hilfe-stellen {
    margin: 0;
    padding-left: 18px;
    font-size: calc(13rem / 14);
    line-height: 1.5;
}
.perm-hilfe-stellen li { margin-bottom: 8px; }
.perm-hilfe-ort { font-weight: 600; color: var(--t1); }
.perm-hilfe-text { color: var(--t2); }
.perm-hilfe-mit {
    display: block;
    margin-top: 2px;
    font-size: calc(12rem / 14);
    color: var(--brand-text);
}
.perm-hilfe-quelle { margin-bottom: 10px; }
.perm-hilfe-quelle-name {
    font-size: calc(12.5rem / 14);
    font-weight: 600;
    color: var(--t2);
    margin-bottom: 3px;
}
.perm-hilfe-leer {
    font-size: calc(12.5rem / 14);
    color: var(--t4);
}
.perm-hilfe .member-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 2px;
}
.perm-hilfe .member-chip {
    background: var(--bg-row-hover);
    color: var(--t1);
    border-radius: 99px;
    padding: 1px 8px;
    font-size: calc(11.5rem / 14);
    white-space: nowrap;
}

/* Profil „Meine Rechte“: ein Tag je Recht, öffnet den Hilfe-Dialog */
button.tag {
    border: none;
    font-family: inherit;
    cursor: pointer;
}
/* Gegen das globale button:hover (Markenfarbe als Flaeche) — wie .tag-active */
button.tag:hover,
button.tag:focus-visible {
    background: var(--brand-light);
    color: var(--brand-text);
    box-shadow: none;
}
