/* FWG Naila e.V. — eigenes Stylesheet (ergänzt Bootstrap 5)
   „App-Look": moderne, App-artige Oberfläche in den Freie-Wähler-Farben
   (Orange) mit Frankenwald-Grün und Petrol. Token-basiert: Farben, Flächen,
   Radien und Schatten hängen an CSS-Variablen, der Dark Mode tauscht nur
   die Token — nicht die Komponenten. */

/* Hausschrift Figtree (selbst gehostet, kein CDN) */
@font-face {
    font-family: 'Figtree';
    src: url('../fonts/figtree-latin.woff2') format('woff2');
    font-weight: 300 900;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Figtree';
    src: url('../fonts/figtree-latin-ext.woff2') format('woff2');
    font-weight: 300 900;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    --fwg-orange: #f18700;
    --fwg-orange-dark: #d97600;
    --fwg-orange-soft: #fff1dd;
    --fwg-green: #2c5f2d;
    --fwg-green-dark: #1e4620;
    --fwg-petrol: #0b2c31;
    --fwg-petrol-2: #14424a;
    --fwg-ink: #1c2a33;
    /* Überschriften: mittleres Petrol statt Schwarz (weicher, markentreu;
       #123f47 war Dominik noch zu dunkel → aufgehellt, Kontrast auf Weiß
       weiterhin ~7:1). Im Dark-Mode = --fwg-ink (hell). Dunkle Flächen
       überschreiben das Token lokal auf Weiß (Hero, Footer, Gruß, Flyer). */
    --fwg-heading: #17606e;
    --fwg-bg: #f4f4ef;
    --fwg-surface: #ffffff;
    --fwg-surface-2: #ecebe4;
    --fwg-border: #e6e4db;
    /* Vier Radius-Stufen — eine Quelle, keine Ad-hoc-Werte mehr:
       -pill = voll rund (Badges, Buttons, Pillen), -lg = große Flächen,
       (Basis) = Karten, -sm = Formulare/kleine Elemente. */
    --fwg-radius-pill: 999px;   /* voll rund (Badges, Buttons, Chips) */
    --fwg-radius: 1.25rem;      /* Karten */
    --fwg-radius-lg: 1.5rem;    /* große Flächen (Hero, Sidebar, Footer) */
    --fwg-radius-sm: 0.75rem;   /* Formulare, kleine Elemente */
    --fwg-shadow: 0 2px 4px rgba(12, 42, 49, 0.04), 0 10px 30px rgba(12, 42, 49, 0.08);
    --fwg-shadow-hover: 0 4px 8px rgba(12, 42, 49, 0.06), 0 18px 44px rgba(12, 42, 49, 0.14);
}

/* Im Portal wirken die großen Marketing-Radien zu „bubbly" — dort etwas
   sachlicher. Nur die Karten-/Großflächen-Stufen; -sm und -pill bleiben.
   Der öffentliche Bereich (body ohne .portal) behält die großzügige Optik. */
body.portal {
    --fwg-radius: 0.85rem;
    --fwg-radius-lg: 1.1rem;
}

body {
    background-color: var(--fwg-bg);
    color: var(--fwg-ink);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    font-family: 'Figtree', system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
}

main {
    flex: 1 0 auto;
}

h1, h2, h3, h4, h5, .navbar-brand {
    font-weight: 700;
    letter-spacing: -0.015em;
}

h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6,
.card-title { /* Bootstrap färbt .card-title per Klassen-Regel — mitziehen */
    color: var(--fwg-heading);
}

/* Dunkle Flächen: Überschriften bleiben dort weiß (Token-Override statt
   Spezifitäts-Kampf — gilt automatisch für alle Ebenen darin). */
.hero, .dash-greet-hero, .dash-hero, .event-flyer-hero {
    --fwg-heading: #fff;
}

h1, .h1, h2, .h2 { font-weight: 800; }

/* Abschnitts-Überschriften mit orangem Akzent */
.section-title {
    position: relative;
    padding-bottom: 0.6rem;
}

.section-title::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 56px;
    height: 4px;
    border-radius: var(--fwg-radius-pill);
    background: linear-gradient(90deg, var(--fwg-orange), #ffb85c);
}

/* Navigation: Glas-Leiste; im öffentlichen Bereich (Container statt fluid)
   als schwebende Pille im App-Stil. */
.navbar-fwg {
    /* Glas-Optik („Glass Surface"): durchscheinende Fläche, kräftiger Blur mit
       Farbsättigung (dahinter Scrollendes schimmert lebendig durch) und eine
       zarte Lichtkante oben — wie Milchglas. Fallback ohne backdrop-filter
       unten (@supports): fast deckend, damit Text lesbar bleibt. */
    background-color: color-mix(in srgb, var(--fwg-surface) 62%, transparent);
    backdrop-filter: blur(24px) saturate(1.7);
    -webkit-backdrop-filter: blur(24px) saturate(1.7);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45);
    border-bottom: 1px solid color-mix(in srgb, var(--fwg-border) 75%, transparent);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .navbar-fwg { background-color: color-mix(in srgb, var(--fwg-surface) 96%, transparent); }
}

.navbar-fwg .nav-link {
    font-weight: 600;
    font-size: 0.92rem;
    color: var(--fwg-ink);
    border-radius: var(--fwg-radius-pill);
    padding-inline: 0.85rem;
    transition: color 0.15s ease, background-color 0.15s ease;
}

.navbar-fwg .nav-link.active,
.navbar-fwg .nav-link:hover {
    color: var(--fwg-orange-dark);
    background-color: var(--fwg-orange-soft);
}

/* Öffentliche Seite: schwebende Pill-Navbar */
.navbar-fwg:has(> .container) {
    background: transparent;
    border-bottom: 0;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding: 0.7rem 0.9rem 0;
}
.navbar-fwg > .container {
    background: color-mix(in srgb, var(--fwg-surface) 62%, transparent);
    backdrop-filter: blur(24px) saturate(1.7);
    -webkit-backdrop-filter: blur(24px) saturate(1.7);
    border: 1px solid color-mix(in srgb, var(--fwg-border) 75%, transparent);
    border-radius: var(--fwg-radius-lg);
    box-shadow: var(--fwg-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.45);
    padding: 0.45rem 1rem;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .navbar-fwg > .container { background: color-mix(in srgb, var(--fwg-surface) 96%, transparent); }
}

.brand-title {
    font-weight: 800;
    line-height: 1.05;
}

.brand-sub {
    font-size: 0.72rem;
    color: var(--fwg-orange-dark);
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

/* Vereins-Logo (Sonne über den Frankenwald-Hügeln): Sonne bleibt orange,
   Wortmarke folgt currentColor, Hügel-Grün über CSS-Variablen themefähig. */
:root {
    --logo-hill-1: #2c5f2d;
    --logo-hill-2: #1e4620;
}
[data-bs-theme="dark"] {
    /* dunkles Hügel-Grün säuft auf Petrol ab -> aufhellen */
    --logo-hill-1: #6fae70;
    --logo-hill-2: #4c8a4e;
}
.brand-logo {
    height: 44px;
    width: auto;
    display: block;
    color: #2c5f2d; /* Wortmarke im Vereins-Grün */
}
.brand-sun {
    height: 38px;
    width: auto;
    display: block;
    flex: 0 0 auto;
}
[data-bs-theme="dark"] .brand-logo {
    color: #eef4f4;
}

img.brand-sun { object-fit: contain; }
/* Logo-Bilder passen sich per prefers-color-scheme selbst an (SVG), daher hier
   keine Theme-Umschaltung mehr nötig. */
@media (max-width: 575.98px) {
    .brand-logo { height: 36px; }
}

.dropdown-menu {
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius-sm);
    box-shadow: var(--fwg-shadow-hover);
    overflow: hidden;
}

.dropdown-item {
    padding: 0.55rem 1.1rem;
}

.dropdown-item:hover {
    background-color: var(--fwg-orange-soft);
    color: var(--fwg-orange-dark);
}

/* Hero — Naila-Foto mit Petrol/Teal-Overlay (Logo-Türkis) und Sonne,
   abgerundet wie eine App-Karte.
   Ebenen (oben zuerst gemalt): Sonnen-Glow → dunkles Petrol-Overlay →
   Foto → als background-color der bisherige Petrol-Verlauf ist NICHT
   möglich (color ist einfarbig), daher liegt der Verlauf als UNTERSTE
   background-Ebene: fehlt das Foto (Datei nicht vorhanden), lädt der
   Foto-Layer einfach nicht und Overlay+Sonne liegen auf dem Verlauf →
   sieht praktisch aus wie vorher. Das Overlay hält den weißen Text lesbar
   (das Foto ist hell). */
.hero {
    color: #fff;
    background:
        radial-gradient(ellipse 60% 42% at 50% 0%, rgba(241, 135, 0, 0.5), transparent 68%),
        linear-gradient(160deg, rgba(8, 38, 45, 0.82) 0%, rgba(12, 52, 61, 0.72) 45%, rgba(21, 96, 110, 0.6) 100%),
        url('../img/naila-hero.jpg') center / cover no-repeat,
        linear-gradient(160deg, #0a2c33 0%, #0f3f49 45%, #15606e 100%);
    padding: 5.5rem 0 7.5rem;
    position: relative;
    overflow: hidden;
    margin: 0.9rem 0.9rem 0;
    border-radius: var(--fwg-radius-lg);
}

.hero::before {
    /* weiche Sonnenkugel oben in der Mitte */
    content: "";
    position: absolute;
    left: 50%;
    top: -90px;
    transform: translateX(-50%);
    width: 280px;
    height: 280px;
    border-radius: 50%;
    background: radial-gradient(circle, #ffb254, var(--fwg-orange) 55%, transparent 72%);
    filter: blur(2px);
    opacity: 0.9;
    pointer-events: none;
}

.hero::after {
    /* sanfte Hügelsilhouette am unteren Rand */
    content: "";
    position: absolute;
    inset: auto 0 -2px 0;
    height: 90px;
    background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 90" preserveAspectRatio="none"><path d="M0,64 C240,10 420,90 720,52 C1020,14 1200,80 1440,38 L1440,90 L0,90 Z" fill="%23f4f4ef"/></svg>') bottom / 100% 100% no-repeat;
}

.hero .motto {
    display: inline-block;
    /* Dunkle Petrol-Pille mit orangem Rand: hebt sich klar vom Sonnen-Glow ab
       (vorher helles, blasses Transparent auf Orange = kaum lesbar). */
    background: rgba(7, 34, 40, 0.6);
    border: 1px solid rgba(247, 154, 31, 0.7);
    color: #fff;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    font-size: 0.82rem;
    padding: 0.5rem 1.2rem;
    border-radius: var(--fwg-radius-pill);
    backdrop-filter: blur(6px);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
}

.hero h1 {
    font-weight: 800;
    text-wrap: balance;
    letter-spacing: -0.03em;
}

/* Buttons in Vereinsfarben */
.btn-fwg {
    background: linear-gradient(135deg, var(--fwg-orange), #e06d00);
    border: none;
    color: #fff;
    font-weight: 700;
    border-radius: var(--fwg-radius-pill);
    padding-inline: 1.4rem;
    box-shadow: 0 6px 18px rgba(241, 135, 0, 0.35);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.btn-fwg:hover, .btn-fwg:focus {
    background: linear-gradient(135deg, var(--fwg-orange-dark), #c86800);
    color: #fff;
    transform: translateY(-1px);
    box-shadow: 0 8px 22px rgba(241, 135, 0, 0.45);
}

.btn-outline-secondary {
    border-radius: var(--fwg-radius-pill);
}

.btn-outline-success, .btn-outline-danger, .btn-success {
    border-radius: var(--fwg-radius-pill);
}

.text-fwg { color: var(--fwg-orange-dark); }
.bg-fwg-green { background-color: var(--fwg-green); }
.border-fwg { border: 1.5px solid color-mix(in srgb, var(--fwg-orange) 45%, var(--fwg-border)) !important; }

/* Feature-Kacheln auf der Startseite — farbige Tints im App-Stil */
.feature-tile {
    background: var(--fwg-surface);
    border-radius: var(--fwg-radius);
    padding: 1.75rem;
    height: 100%;
    box-shadow: var(--fwg-shadow);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.feature-tile:hover {
    transform: translateY(-4px);
    box-shadow: var(--fwg-shadow-hover);
}

.feature-tile .icon-bubble {
    width: 54px;
    height: 54px;
    border-radius: var(--fwg-radius-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    color: var(--fwg-orange-dark);
    background: var(--fwg-orange-soft);
    margin-bottom: 0.9rem;
}

/* Tint-Verläufe subtiler: Surface hält länger (bis 40%), der Tint kommt
   abgeschwächt (color-mix mit Surface) — ruhigerer App-Look, Tint bleibt
   aber erkennbar. */
.feature-tile.tile-orange { background: linear-gradient(140deg, var(--fwg-surface) 40%, color-mix(in srgb, #fff1dd 55%, var(--fwg-surface))); }
.feature-tile.tile-orange .icon-bubble { background: var(--fwg-orange); color: #fff; }
/* Türkis = Farbe der Logo-Wortmarke (#0090AB) — genutzt für „Unabhängig" (bewusst kein Grün) */
.feature-tile.tile-tuerkis { background: linear-gradient(140deg, var(--fwg-surface) 40%, color-mix(in srgb, #ddf1f6 55%, var(--fwg-surface))); }
.feature-tile.tile-tuerkis .icon-bubble { background: #0090ab; color: #fff; }
/* Warmes Koralle fürs Herz („Engagiert") — klar unterscheidbar von Türkis/Petrol */
.feature-tile.tile-herz { background: linear-gradient(140deg, var(--fwg-surface) 40%, color-mix(in srgb, #fdeae7 55%, var(--fwg-surface))); }
.feature-tile.tile-herz .icon-bubble { background: #e2574c; color: #fff; }
[data-bs-theme="dark"] .feature-tile.tile-orange { background: linear-gradient(140deg, var(--fwg-surface) 40%, color-mix(in srgb, #3c2c12 55%, var(--fwg-surface))); }
[data-bs-theme="dark"] .feature-tile.tile-tuerkis { background: linear-gradient(140deg, var(--fwg-surface) 40%, color-mix(in srgb, #0c3a44 55%, var(--fwg-surface))); }
[data-bs-theme="dark"] .feature-tile.tile-herz { background: linear-gradient(140deg, var(--fwg-surface) 40%, color-mix(in srgb, #42201c 55%, var(--fwg-surface))); }

/* ---------------------------------------------------------------------------
   Termin-Flyer: Highlight-Karte (Startseite + öffentliche Termine-Seite).
   Petrol-Fläche mit orangem „Sonnenuntergangs"-Schein — greift die Farbwelt
   der Vereins-Flyer auf (Petrol/Türkis + Orange = vorhandene Tokens).
   Dunkle Fläche in Light UND Dark → keine getrennte Dark-Variante nötig.
--------------------------------------------------------------------------- */
.event-flyer-hero {
    display: flex;
    gap: 1.75rem;
    align-items: center;
    background:
        radial-gradient(closest-side at 82% 0%, rgba(241, 135, 0, 0.38), transparent 70%),
        linear-gradient(135deg, var(--fwg-petrol-2), var(--fwg-petrol) 65%);
    border-radius: var(--fwg-radius);
    box-shadow: var(--fwg-shadow);
    padding: 1.5rem;
    color: #f2f7f7;
    overflow: hidden;
}
.event-flyer-hero-img {
    flex: 0 0 auto;
    display: block;
    max-width: min(240px, 42%);
}
.event-flyer-hero-img img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: calc(var(--fwg-radius) - 6px);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.35);
    transition: transform 0.2s ease;
}
.event-flyer-hero-img:hover img { transform: scale(1.02); }
.event-flyer-hero-body { min-width: 0; }
.event-flyer-hero-body .rich-text p:last-child { margin-bottom: 0; }
.event-flyer-kicker {
    display: inline-block;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #ffb85c;
    margin-bottom: 0.35rem;
}
@media (max-width: 575.98px) {
    .event-flyer-hero {
        flex-direction: column;
        text-align: center;
        gap: 1rem;
    }
    .event-flyer-hero-img { max-width: 78%; }
}

/* Kleines Flyer-Thumbnail in der öffentlichen Termin-Liste */
.event-flyer-thumb {
    display: block;
    width: 74px;
}
.event-flyer-thumb img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 8px;
    border: 1px solid var(--bs-border-color);
    box-shadow: var(--fwg-shadow);
}

footer.site-footer {
    /* Dunkler, sich abhebender Footer (Tanja: „auffälliger und bissl
       abgehoben" — die helle Karten-Variante wirkte zu unscheinbar), aber
       heller als das ursprüngliche Tiefpetrol und bewusst BLAUER statt
       grünstichig („sieht so grün"). Oben die Orange→Türkis-Akzentlinie
       (Hintergrund-Streifen statt border-image → Rundung bleibt sauber). */
    background:
        linear-gradient(90deg, var(--fwg-orange), #0090ab) top / 100% 4px no-repeat,
        linear-gradient(180deg, #245a72, #1f4f63);
    color: rgba(255, 255, 255, 0.88);
    margin: 0 0.9rem 0.9rem;
    border-radius: var(--fwg-radius-lg);
}

footer.site-footer strong {
    color: #fff;
}

footer.site-footer a {
    color: #ffce8a;
    font-weight: 600;
    text-decoration: none;
}

footer.site-footer a:hover {
    text-decoration: underline;
}

/* Karten */
.card {
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius);
    box-shadow: var(--fwg-shadow);
}

a.card, .card:has(.stretched-link) {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:has(.stretched-link):hover {
    transform: translateY(-4px);
    box-shadow: var(--fwg-shadow-hover);
}

.card .card-title {
    font-weight: 700;
}

/* Getönte Karten (Dashboard-Bento) */
.card-tint-orange {
    background: linear-gradient(145deg, var(--fwg-surface) 40%, color-mix(in srgb, #ffe9cc 55%, var(--fwg-surface)));
    border-color: color-mix(in srgb, var(--fwg-orange) 30%, var(--fwg-border));
}
.card-tint-green {
    background: linear-gradient(145deg, var(--fwg-surface) 40%, color-mix(in srgb, #e2eedf 55%, var(--fwg-surface)));
    border-color: color-mix(in srgb, var(--fwg-green) 25%, var(--fwg-border));
}
[data-bs-theme="dark"] .card-tint-orange { background: linear-gradient(145deg, var(--fwg-surface) 40%, color-mix(in srgb, #42300f 55%, var(--fwg-surface))); }
[data-bs-theme="dark"] .card-tint-green { background: linear-gradient(145deg, var(--fwg-surface) 40%, color-mix(in srgb, #16391c 55%, var(--fwg-surface))); }

/* Hero-Karte im Dashboard („Nächste Sitzung"): Verlauf mit Sonnen-Glow */
.dash-hero {
    background:
        radial-gradient(circle at 100% 0%, rgba(255, 178, 84, 0.38), rgba(241, 135, 0, 0.16) 28%, transparent 52%),
        linear-gradient(150deg, var(--fwg-petrol), #103e47 55%, #15606e);
    border: none;
    color: #fff;
}
.dash-hero .card-title,
.dash-hero .text-fwg { color: #fff; }
.dash-hero .text-muted { color: rgba(255, 255, 255, 0.75) !important; }
.dash-hero a:not(.btn) { color: #ffd28a; }
.dash-hero .btn-outline-secondary {
    color: #fff;
    border-color: rgba(255, 255, 255, 0.45);
}

.list-group-item:first-child { border-top-left-radius: var(--fwg-radius); border-top-right-radius: var(--fwg-radius); }
.list-group-item:last-child { border-bottom-left-radius: var(--fwg-radius); border-bottom-right-radius: var(--fwg-radius); }

.badge {
    border-radius: var(--fwg-radius-pill);
    font-weight: 600;
}

/* Portal-Layout: Sidebar als schwebende Karte mit Pill-Navigation */
.portal-sidebar {
    background-color: transparent;
    border-right: none;
    min-height: 100%;
}

/* Innerer Nav-Container: hält die vertikalen Abstände zwischen den Gruppen
   (früher via .nav gap-1) — auch auf Mobil, wo #portal-nav nicht scrollt. */
.portal-sidebar .portal-nav-scroll {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

@media (min-width: 992px) {
    .portal-sidebar #portal-nav {
        background: var(--fwg-surface);
        border: 1px solid var(--fwg-border);
        border-radius: var(--fwg-radius-lg);
        box-shadow: var(--fwg-shadow);
        padding: 0.75rem 0.5rem 0.75rem 0.65rem;
        position: sticky;
        top: 84px;
        /* Nie über den Bildschirm hinaus wachsen: auf Viewport-Höhe begrenzen.
           Abzug = Navbar (84px) + py-lg-3-Innenabstände der Spalte (2rem), sonst
           wäre die Seite ~12px höher als der Viewport → unnötiger rechter
           Seiten-Scrollbalken trotz kurzem Inhalt. */
        max-height: calc(100vh - 84px - 2rem);
        display: flex;
        flex-direction: column;
        flex-wrap: nowrap;
        overflow: hidden; /* rundet die Ecken sauber ab, klippt die innere Scrollleiste */
    }
    /* Eigentlicher Scroll-Bereich — nach INNEN gesetzt, damit die Scrollleiste
       innerhalb der Karte liegt (nicht auf den runden Ecken) und die Chevron-Pfeile
       Abstand zum Rand haben. Scrollt bei langem Menü (aufgeklappter Baum) intern. */
    .portal-sidebar .portal-nav-scroll {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        padding-right: 0.3rem;
        scrollbar-width: thin;
        scrollbar-color: color-mix(in srgb, var(--bs-secondary-color) 45%, transparent) transparent;
    }
}

/* Dezenter, abgerundeter Scrollbalken (WebKit/Blink) — neutral wie der
   Seiten-Scrollbalken, schwebt dank transparentem Rand + background-clip. */
.portal-sidebar .portal-nav-scroll::-webkit-scrollbar { width: 10px; }
.portal-sidebar .portal-nav-scroll::-webkit-scrollbar-track { background: transparent; }
.portal-sidebar .portal-nav-scroll::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--bs-secondary-color) 38%, transparent);
    border-radius: var(--fwg-radius-pill);
    border: 3px solid transparent;
    background-clip: padding-box;
}
.portal-sidebar .portal-nav-scroll::-webkit-scrollbar-thumb:hover {
    background: color-mix(in srgb, var(--bs-secondary-color) 60%, transparent);
    background-clip: padding-box;
}

.portal-sidebar .nav-link {
    color: #45525e;
    border-radius: var(--fwg-radius-pill);
    font-weight: 600;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.portal-sidebar .nav-link.active {
    background: linear-gradient(135deg, var(--fwg-orange), #e06d00);
    color: #fff;
    box-shadow: 0 5px 16px rgba(241, 135, 0, 0.35);
}

.portal-sidebar .nav-link:hover:not(.active) {
    background-color: var(--fwg-orange-soft);
    color: var(--fwg-orange-dark);
}

.portal-sidebar .sidebar-heading {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    /* #9aa4ad war auf hellem Grund ~2.6:1 → unter WCAG AA. #5c6b74 ≈ 4.6:1. */
    color: #5c6b74;
    font-weight: 700;
}

/* Aufklappbare Sidebar-Gruppen */
.portal-sidebar .sidebar-links {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.portal-sidebar .sidebar-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    gap: 0.5rem;
    background: none;
    border: 0;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    padding: 0.35rem 0.75rem;
    margin-top: 0.75rem;
    border-radius: var(--fwg-radius-pill);
}
.portal-sidebar .sidebar-group:first-child .sidebar-toggle {
    margin-top: 0;
}
.portal-sidebar .sidebar-toggle:hover {
    background-color: var(--fwg-orange-soft);
    color: var(--fwg-orange-dark);
}
.portal-sidebar .sidebar-chevron {
    font-size: 0.7rem;
    transition: transform 0.2s ease;
    flex: 0 0 auto;
}
.portal-sidebar .sidebar-group.collapsed .sidebar-chevron {
    transform: rotate(-90deg);
}
.portal-sidebar .sidebar-group.collapsed .sidebar-links {
    display: none;
}

.portal-sidebar .sidebar-links .sidebar-group .nav-link {
    padding-left: 1.75rem;
    font-size: 0.95em;
}

/* Mobile Bottom-Tab-Bar im Portal (App-Gefühl): schwebende Glas-Leiste,
   nur unter lg sichtbar; liegt unter dem Offcanvas (z-index < 1045). */
.portal-tabbar {
    position: fixed;
    /* Breit: nur kleiner Rand seitlich -> Leiste ist BREITER als die Inhaltskarten
       (die haben ~0.75rem Rand). Unten aber GENUG Abstand halten (runde Ecken +
       Home-Indikator bei iPhone/Android) — nicht zu weit nach unten! */
    left: 0.4rem;
    right: 0.4rem;
    /* Unten mind. 1.5rem, auf Geräten mit Home-Indikator (iPhone) automatisch bis
       ÜBER die Safe-Area -> Leiste liegt nie im Bereich der runden Ecken/Gesten. */
    bottom: max(1.5rem, env(safe-area-inset-bottom));
    z-index: 1030;
    /* Glas-Optik: durchscheinend mit kräftigem Blur + Sättigung — der starke
       Blur trägt die Lesbarkeit, der Inhalt schimmert nur als Farbfläche durch */
    background: color-mix(in srgb, var(--fwg-surface) 68%, transparent);
    backdrop-filter: blur(26px) saturate(1.7);
    -webkit-backdrop-filter: blur(26px) saturate(1.7);
    border: 1px solid color-mix(in srgb, var(--fwg-border) 80%, transparent);
    border-radius: var(--fwg-radius-lg);
    /* Light: weicher, petrol-getönter Schwebeschatten (hebt Weiß-auf-Weiß sauber ab) */
    box-shadow:
        0 10px 30px rgba(16, 42, 48, 0.22),
        0 3px 10px rgba(16, 42, 48, 0.14),
        inset 0 1px 0 rgba(255, 255, 255, 0.5);
    /* keine innere Safe-Area-Polsterung mehr — die Leiste schwebt bereits über
       der Safe-Area (siehe bottom), sonst würde sie unnötig hoch/leer wirken */
    padding: 0.4rem 0.3rem;
    transition: transform 0.25s ease, opacity 0.2s ease;
}
/* Sanfter Verlauf zur Seitenfarbe UNTER der Leiste: verdeckt Inhalt, der sonst
   im Spalt zwischen schwebender Leiste und Bildschirmrand durchblitzt. */
.portal-tabbar::after {
    content: "";
    position: absolute;
    left: -0.4rem;
    right: -0.4rem;
    bottom: -3rem;
    height: 3.6rem;
    background: linear-gradient(to bottom, transparent, var(--fwg-bg) 65%);
    z-index: -1;
    pointer-events: none;
}
/* Dark Mode: leicht hellere, gehobene Oberfläche + kräftigerer Rand -> hebt sich
   deutlicher von den Karten/Seite ab als die fast gleichfarbige Karte. */
[data-bs-theme="dark"] .portal-tabbar {
    /* Dark: „flach" — KEIN Schatten (der wirkt auf dunklem Grund matschig).
       Die Leiste hebt sich allein durch die etwas hellere Fläche + klaren Rand
       + zarte obere Lichtkante ab. */
    background: color-mix(in srgb, var(--fwg-surface-2) 55%, transparent);
    border-color: color-mix(in srgb, var(--fwg-surface-2) 80%, #ffffff);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
}
/* Beim Tippen (Tastatur offen) rutscht die Leiste aus dem Bild — der Platz
   gehört dann dem Eingabefeld (Klasse setzt tabbar.js bei Fokus). */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .portal-tabbar { background: color-mix(in srgb, var(--fwg-surface) 97%, transparent); }
    [data-bs-theme="dark"] .portal-tabbar { background: color-mix(in srgb, var(--fwg-surface-2) 80%, var(--fwg-surface)); }
}
body.typing .portal-tabbar {
    transform: translateY(140%);
    opacity: 0;
    pointer-events: none;
}
.portal-tabbar .tabbar-inner {
    display: flex;
    align-items: stretch;
}
/* „Übersicht" links, „Mehr" rechts fest verankert (gleich breite Randplätze) */
.portal-tabbar > .tabbar-inner > .tab-edge {
    flex: 1 1 0;
    min-width: 0;
}
/* Mittelzone: 1–3 Favoriten in GLEICH BREITEN Spalten (flex 1 1 0) — nur so
   sitzen die Symbole in einem gleichmäßigen Raster. space-evenly verteilte
   früher bloß die Lücken gleich; unterschiedlich breite Beschriftungen
   („Problem melden" vs. „Chat") schoben die Symbole dann aus der Mitte. */
.portal-tabbar .tab-favs {
    flex: 3 1 0;
    min-width: 0;
    display: flex;
    align-items: stretch;
    justify-content: center;
}
.portal-tabbar .tab-favs .tab {
    flex: 1 1 0;
    min-width: 0;
    max-width: 33.34%;
}
/* Beschriftung: lange Namen werden gekürzt statt die Spalte zu sprengen */
.portal-tabbar .tab .tab-label {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 0 3px;
}
.portal-tabbar .tab {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.15rem;
    font-size: 0.67rem;
    font-weight: 700;
    color: var(--bs-secondary-color);
    text-decoration: none;
    position: relative;
    padding: 0.2rem 0;
    background: none;
    border: 0;
    font-family: inherit;
    cursor: pointer;
}
/* Nach dem Schließen des „Mehr"-Sheets springt der Fokus auf den Button zurück —
   der blaue Browser-Fokusrahmen sieht bei Touch/Maus unschön aus. Für Zeiger-
   Eingabe unterdrücken, für Tastatur-Navigation (Barrierefreiheit) sichtbar
   lassen: ein dezenter Ring am Icon-Feld statt eckigem Kasten. */
.portal-tabbar .tab:focus {
    outline: none;
    box-shadow: none;
}
.portal-tabbar .tab:focus-visible .tico {
    outline: 2px solid var(--fwg-orange);
    outline-offset: 2px;
}
.portal-tabbar .tab .tico {
    width: 46px;
    height: 30px;
    border-radius: var(--fwg-radius-pill);
    display: grid;
    place-items: center;
    font-size: 1.15rem;
    line-height: 1;
}
/* Bunte Bereichs-Icons: Icon nimmt die Bereichsfarbe (--tab-ico je Tab gesetzt),
   das Label bleibt dezent — so bleibt die Leiste ruhig, die Icons sind aber bunt. */
.portal-tabbar .tab .tico i { color: var(--tab-ico, currentColor); }
.portal-tabbar .tab.active { color: var(--fwg-orange-dark); }
.portal-tabbar .tab.active .tico { background: var(--fwg-orange-soft); }
/* Aktiver Tab: Icon immer im Orange (überschreibt die Bereichsfarbe) */
.portal-tabbar .tab.active .tico i { color: var(--fwg-orange-dark); }
.portal-tabbar .tab .tab-dot,
.more-tile .tab-dot {
    position: absolute;
    top: -1px;
    right: calc(50% - 22px);
    background: var(--bs-danger, #dc3545);
    color: #fff;
    font-size: 0.62rem;
    font-weight: 800;
    border-radius: var(--fwg-radius-pill);
    padding: 0.02rem 0.32rem;
    line-height: 1.3;
}
.more-tile .tab-dot { top: -4px; }
@media (min-width: 992px) {
    .portal-tabbar { display: none; }
}

/* „Mehr"-Bottom-Sheet: alle Bereiche als Kachel-Raster, Stern = Tab-Favorit */
.portal-more.offcanvas-bottom {
    height: auto;
    max-height: 82vh;
    border: 0;
    border-top-left-radius: var(--fwg-radius-lg);
    border-top-right-radius: var(--fwg-radius-lg);
    background: var(--fwg-surface);
    box-shadow: 0 -12px 48px rgba(12, 42, 49, 0.3);
    padding-bottom: env(safe-area-inset-bottom);
}
.portal-more::before {
    /* Grabber-Griff wie bei nativen Sheets */
    content: "";
    display: block;
    width: 44px;
    height: 5px;
    border-radius: var(--fwg-radius-pill);
    background: var(--fwg-border);
    margin: 0.6rem auto 0;
}
/* Kacheln im „Mehr"-Sheet per Gedrückt-Halten sortierbar: iOS-Link-Vorschau und
   Textauswahl unterdrücken, sonst stört der Long-Press. */
.more-tile {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}
.more-tile.tile-dragging {
    opacity: 0.9;
    transform: scale(1.06);
    box-shadow: 0 8px 22px rgba(0, 0, 0, .3);
    z-index: 5;
    cursor: grabbing;
}

.more-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.7rem;
    padding-bottom: 0.5rem;
}
@media (min-width: 480px) {
    .more-grid { grid-template-columns: repeat(4, 1fr); }
}
.more-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 0.9rem 0.4rem 0.7rem;
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius-sm);
    background: var(--fwg-bg);
    text-decoration: none;
    color: var(--fwg-ink);
    font-weight: 600;
    font-size: 0.78rem;
    text-align: center;
}
.more-tile.active {
    border-color: color-mix(in srgb, var(--fwg-orange) 55%, var(--fwg-border));
    background: var(--fwg-orange-soft);
}
.more-tile .more-ico {
    position: relative;
    width: 44px;
    height: 44px;
    border-radius: var(--fwg-radius-sm);
    display: grid;
    place-items: center;
    font-size: 1.25rem;
    /* bunte Bereichs-Kachel: zarter Farbwash + Icon in der Bereichsfarbe */
    background: color-mix(in srgb, var(--tab-ico, var(--fwg-orange)) 18%, transparent);
    color: var(--tab-ico, var(--fwg-orange-dark));
}
.more-tile .more-ico .tab-dot { right: -6px; }
.more-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}
.more-star {
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--bs-secondary-color);
    font-size: 0.95rem;
    display: grid;
    place-items: center;
    cursor: pointer;
}
.more-star.is-fav { color: var(--fwg-orange); }
[data-bs-theme="dark"] .more-tile { background: var(--fwg-surface-2); }
/* Platz für die Tab-Bar, damit sie keine Inhalte verdeckt; beim Tippen ist
   die Leiste ausgeblendet -> Platzhalter einklappen (Tastatur braucht Raum) */
@media (max-width: 991.98px) {
    body:has(.portal-tabbar) main.container-fluid,
    body:has(.portal-tabbar) > .container-fluid.flex-grow-1 {
        padding-bottom: 6.5rem;
    }
    body.typing:has(.portal-tabbar) main.container-fluid,
    body.typing:has(.portal-tabbar) > .container-fluid.flex-grow-1 {
        padding-bottom: 1rem;
    }
}

/* Amts-Hub-Kacheln (Übersichtsseiten Schriftführer/Kasse/Vorstand/Admin) */
.hub-tile {
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius);
    transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}
.hub-tile:hover {
    transform: translateY(-2px);
    border-color: var(--fwg-orange);
    box-shadow: 0 6px 18px rgba(20, 40, 45, 0.12);
}
.hub-tile__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: var(--fwg-radius-sm);
    background: var(--fwg-orange-soft);
    color: var(--fwg-orange-dark);
    font-size: 1.3rem;
}
[data-bs-theme="dark"] .hub-tile {
    border-color: rgba(255, 255, 255, 0.08);
}

/* Avatare */
.avatar-img {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    object-fit: cover;
}

.avatar-lg {
    width: 120px;
    height: 120px;
    border-radius: 50%;
    object-fit: cover;
    box-shadow: 0 0 0 4px var(--fwg-surface), var(--fwg-shadow);
}

.avatar-placeholder {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--fwg-green), var(--fwg-green-dark));
    color: #fff;
    font-weight: 700;
    border-radius: 50%;
    width: 40px;
    height: 40px;
}

.avatar-placeholder.avatar-lg-ph {
    width: 120px;
    height: 120px;
    font-size: 2.5rem;
    box-shadow: 0 0 0 4px var(--fwg-surface), var(--fwg-shadow);
}

/* Profilbild-Zuschnitt: quadratische Bühne mit runder Maske; touch-action:none,
   damit Ziehen/Pinchen nicht die Seite scrollt/zoomt. */
.avatar-crop-stage {
    position: relative;
    width: 100%;
    max-width: 240px;
    aspect-ratio: 1;
    margin: 0 auto;
    border-radius: var(--fwg-radius-sm);
    overflow: hidden;
    background: #111;
    touch-action: none;
    cursor: grab;
}

.avatar-crop-stage canvas {
    display: block;
    width: 100%;
    height: 100%;
}

.avatar-crop-mask {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(circle closest-side, transparent 0 97%, rgba(0, 0, 0, .55) 100%);
}

.avatar-crop-mask::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .85);
}

.notification-unread {
    border-left: 4px solid var(--fwg-orange);
    /* #fff8ec war auf weißer Fläche praktisch unsichtbar (~1.02:1). */
    background-color: var(--fwg-orange-soft);
}

/* Personen-Karten im öffentlichen Bereich */
.person-card .person-icon {
    font-size: 3rem;
    color: var(--fwg-green);
}

/* Formulare */
.form-control, .form-select {
    border-radius: var(--fwg-radius-sm);
}

.form-control:focus, .form-select:focus {
    border-color: var(--fwg-orange);
    box-shadow: 0 0 0 0.2rem rgba(241, 135, 0, 0.18);
}

/* Zahlen/Beträge fluchten spaltenweise (Kassenbuch, Berichte, Beiträge).
   Utility .num für Einzelwerte; die rechtsbündigen Zellen der Kasse-Tabellen
   bekommen es automatisch, damit Salden sauber untereinander stehen. */
.num,
.table td.text-end,
.table th.text-end {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* Tabellen luftiger */
.table > :not(caption) > * > * {
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
}

/* Bündig in einer Karte liegende Tabellen: die eckige Kopfzeile (und die untere
   Zeile) an die Kartenrundung anpassen — sonst ragen die eckigen Ecken sichtbar
   aus dem abgerundeten Kartenrahmen. Das Clipping stört den horizontalen Scroll
   der inneren .table-responsive nicht (die scrollt in ihrem eigenen Container). */
.card:has(> .table-responsive),
.card:has(> .table) {
    overflow: hidden;
}

/* Mobile: Portal-Navigation als Offcanvas, kompaktere Abstände */
#portalSidebar {
    --bs-offcanvas-width: 290px;
}

@media (max-width: 991.98px) {
    .hero {
        padding: 3.5rem 0 5.5rem;
        margin: 0.6rem 0.6rem 0;
        border-radius: var(--fwg-radius);
    }

    .portal-sidebar {
        border-right: none;
    }

    h1.h3 {
        font-size: 1.35rem;
    }
}

/* ---------------------------------------------------------------------------
   Dunkles Design — Petrol-Ton des Freie-Wähler-Logos, dunkler abgetönt.
   Bootstrap übernimmt via data-bs-theme="dark" Karten, Tabellen, Formulare;
   hier werden nur die Token getauscht + wenige Sonderfälle nachgezogen.
--------------------------------------------------------------------------- */
[data-bs-theme="dark"] {
    --fwg-bg: #07222a;             /* Seite: tiefes Petrol */
    --fwg-surface: #10383f;        /* Karten, Navigation, Sidebar */
    --fwg-surface-2: #155059;      /* Hover-Flächen */
    --fwg-border: #1d4d55;
    --fwg-ink: #dcebea;
    --fwg-heading: #dcebea;        /* Überschriften im Dark wie bisher hell */
    --fwg-orange: #f79a1f;         /* Akzent auf Dunkel leicht aufgehellt */
    --fwg-orange-dark: #ffb254;
    --fwg-orange-soft: rgba(247, 154, 31, 0.14);
    --fwg-shadow: 0 2px 4px rgba(0, 0, 0, 0.3), 0 10px 30px rgba(0, 0, 0, 0.35);
    --fwg-shadow-hover: 0 4px 8px rgba(0, 0, 0, 0.35), 0 18px 44px rgba(0, 0, 0, 0.5);
    --bs-body-bg: #07222a;
    --bs-body-color: #dcebea;
    --bs-secondary-color: #8fabad; /* .text-muted */
    --bs-border-color: #1d4d55;
}

[data-bs-theme="dark"] .navbar-fwg {
    background-color: color-mix(in srgb, var(--fwg-surface) 58%, transparent);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

[data-bs-theme="dark"] .navbar-fwg:has(> .container) {
    background: transparent;
}

[data-bs-theme="dark"] .navbar-fwg > .container {
    background: color-mix(in srgb, var(--fwg-surface) 58%, transparent);
    box-shadow: var(--fwg-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

[data-bs-theme="dark"] .navbar-fwg .nav-link {
    color: var(--fwg-ink);
}

[data-bs-theme="dark"] .navbar-fwg .nav-link.active,
[data-bs-theme="dark"] .navbar-fwg .nav-link:hover {
    color: var(--fwg-orange-dark);
    background-color: var(--fwg-orange-soft);
}

[data-bs-theme="dark"] .brand-title {
    color: #f2f7f7;
}

[data-bs-theme="dark"] .brand-sub {
    color: var(--fwg-orange);
}

[data-bs-theme="dark"] .card,
[data-bs-theme="dark"] .feature-tile,
[data-bs-theme="dark"] .dropdown-menu {
    background-color: var(--fwg-surface);
    color: var(--fwg-ink);
}

[data-bs-theme="dark"] .card { border-color: var(--fwg-border); }

[data-bs-theme="dark"] .dropdown-item {
    color: var(--fwg-ink);
}

[data-bs-theme="dark"] .dropdown-item:hover {
    background-color: var(--fwg-orange-soft);
    color: var(--fwg-orange-dark);
}

[data-bs-theme="dark"] .portal-sidebar #portal-nav {
    background-color: var(--fwg-surface);
    border-color: var(--fwg-border);
}

[data-bs-theme="dark"] .portal-sidebar .nav-link {
    color: #b9cdcf;
}

[data-bs-theme="dark"] .portal-sidebar .nav-link:hover:not(.active) {
    background-color: var(--fwg-orange-soft);
    color: var(--fwg-orange-dark);
}

[data-bs-theme="dark"] .portal-sidebar .sidebar-heading {
    color: #6f8f92;
}

[data-bs-theme="dark"] .offcanvas {
    background-color: var(--fwg-surface);
}

[data-bs-theme="dark"] .icon-bubble {
    background: var(--fwg-orange-soft);
    color: var(--fwg-orange-dark);
}

[data-bs-theme="dark"] .hero {
    /* Dark: Foto stärker abgedunkelt, damit es zum tiefen Petrol passt. */
    background:
        radial-gradient(ellipse 60% 42% at 50% 0%, rgba(247, 154, 31, 0.35), transparent 68%),
        linear-gradient(160deg, rgba(14, 52, 58, 0.9) 0%, rgba(11, 44, 49, 0.85) 50%, rgba(9, 34, 39, 0.82) 100%),
        url('../img/naila-hero.jpg') center / cover no-repeat,
        linear-gradient(160deg, #0e343a 0%, #0b2c31 50%, #092227 100%);
}

[data-bs-theme="dark"] .hero::after {
    background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 90" preserveAspectRatio="none"><path d="M0,64 C240,10 420,90 720,52 C1020,14 1200,80 1440,38 L1440,90 L0,90 Z" fill="%2307222a"/></svg>') bottom / 100% 100% no-repeat;
}

[data-bs-theme="dark"] footer.site-footer {
    /* Etwas heller als der tiefe Petrol-Seitenhintergrund (#07222a), damit sich
       der Footer abhebt; Akzentlinie oben bleibt wie im Light. */
    background:
        linear-gradient(90deg, var(--fwg-orange), #0090ab) top / 100% 4px no-repeat,
        linear-gradient(180deg, #0e3a43, #0e3a43);
}

[data-bs-theme="dark"] .notification-unread {
    background-color: rgba(247, 154, 31, 0.10);
}

[data-bs-theme="dark"] .list-group-item {
    background-color: transparent;
    color: var(--fwg-ink);
}

[data-bs-theme="dark"] .avatar-lg,
[data-bs-theme="dark"] .avatar-placeholder.avatar-lg-ph {
    box-shadow: 0 0 0 4px var(--fwg-surface), var(--fwg-shadow);
}

[data-bs-theme="dark"] .badge.bg-light {
    background-color: var(--fwg-surface-2) !important;
    color: var(--fwg-ink) !important;
    border-color: #1d4d55 !important;
}

[data-bs-theme="dark"] .person-card .person-icon {
    color: #7db87e;
}

[data-bs-theme="dark"] .text-fwg {
    color: var(--fwg-orange-dark);
}

.theme-toggle {
    color: inherit;
}

/* --- Quill-Editor (WYSIWYG) ------------------------------------------------ */
/* Quill setzt .ql-container auf height:100%, was in Bootstrap-Rows (Flex) zur
   Spaltenhöhe aufgelöst wird und den Editor über den Formular-Button laufen
   lässt -> auf auto zurücksetzen, Höhe über den Inhaltsbereich steuern. */
.quill-editor.ql-container {
    height: auto;
    font-size: 1rem;
    font-family: inherit;
}

.quill-editor .ql-editor {
    height: auto;
    min-height: 200px;
}

.ql-toolbar.ql-snow,
.ql-container.ql-snow {
    border-color: var(--bs-border-color);
    border-radius: 0;
}

.ql-toolbar.ql-snow {
    border-top-left-radius: var(--bs-border-radius);
    border-top-right-radius: var(--bs-border-radius);
}

.ql-container.ql-snow {
    border-bottom-left-radius: var(--bs-border-radius);
    border-bottom-right-radius: var(--bs-border-radius);
}

[data-bs-theme="dark"] .ql-toolbar.ql-snow,
[data-bs-theme="dark"] .ql-container.ql-snow {
    background-color: var(--fwg-surface);
    color: var(--fwg-ink);
}

[data-bs-theme="dark"] .ql-snow .ql-stroke {
    stroke: var(--fwg-ink);
}

[data-bs-theme="dark"] .ql-snow .ql-fill {
    fill: var(--fwg-ink);
}

[data-bs-theme="dark"] .ql-snow .ql-picker {
    color: var(--fwg-ink);
}

[data-bs-theme="dark"] .ql-snow .ql-picker-options {
    background-color: var(--fwg-surface-2);
}

[data-bs-theme="dark"] .ql-snow .ql-tooltip {
    background-color: var(--fwg-surface-2);
    color: var(--fwg-ink);
    box-shadow: none;
    border-color: var(--bs-border-color);
}

[data-bs-theme="dark"] .ql-snow .ql-tooltip input[type="text"] {
    background-color: var(--fwg-surface);
    color: var(--fwg-ink);
    border-color: var(--bs-border-color);
}

/* Rich-Text-Ausgabe (News, Einladungstexte) */
.rich-text img {
    max-width: 100%;
    height: auto;
}

/* Tabellen INNERHALB einer Karte im Dark Mode: Bootstrap setzt --bs-table-bg
   auf die Seitenfarbe (--bs-body-bg, tiefes Petrol). In einer Karte (heller
   --fwg-surface) wirken die Zellen dann dunkler als die Karte → die Zwischen-
   räume um die Zellen/Eingabefelder sehen aus wie „Löcher". Tabellen in Karten
   erben deshalb den Karten-Hintergrund, dann verschmelzen Zellen und Karte. */
[data-bs-theme="dark"] .card .table {
    --bs-table-bg: var(--fwg-surface);
}

/* Helle Bootstrap-Tabellenzeilen (z. B. Summen-tfoot) im Dark Mode anpassen,
   sonst bleibt der Balken weiß. */
[data-bs-theme="dark"] .table-light,
[data-bs-theme="dark"] .table-light > th,
[data-bs-theme="dark"] .table-light > td {
    --bs-table-bg: var(--fwg-surface-2);
    --bs-table-color: var(--fwg-ink);
    color: var(--fwg-ink);
}

/* Breite Tabellen auf schmalen Screens horizontal scrollen lassen, statt die
   inhaltsreichste Spalte zu quetschen (wirkt zusammen mit .table-responsive). */
.table-scroll {
    min-width: 720px;
}

/* ---------------------------------------------------------------------------
   News-Bilder & Slideshow (Aktuelles/Home/Detail)
   --------------------------------------------------------------------------- */
.news-card {
    overflow: hidden; /* Bild-Ecken an Card-Radius anpassen */
}
/* Ganze Kachel klickbar (stretched-link an der Überschrift): dezenter
   Hinweis beim Überfahren, dass der Beitrag sich öffnet. */
.news-card:hover .card-title a { text-decoration: underline; }
.news-media {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: #e9eef0;
}
.news-media > img,
.news-media .carousel-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.news-media.carousel .carousel-inner,
.news-media.carousel .carousel-item {
    height: 100%;
}
/* Große Galerie auf der Detailseite: ganzes Bild zeigen, nichts abschneiden */
.news-media-lg {
    border-radius: var(--fwg-radius);
    box-shadow: var(--fwg-shadow);
}
/* Einzelbild: natürliches Seitenverhältnis, komplett sichtbar (kein Crop) */
.news-media-lg:not(.carousel) {
    aspect-ratio: auto;
}
.news-media-lg:not(.carousel) > img {
    height: auto;
    object-fit: contain;
}
/* Mehrere Bilder (Carousel): fester Rahmen, aber ganzes Bild (ggf. mit Rand) */
.news-media-lg.carousel {
    aspect-ratio: 3 / 2;
}
.news-media-lg.carousel .carousel-item img {
    object-fit: contain;
}
/* Gebrandeter Platzhalter, falls ein (alter) Beitrag kein Bild hat */
.news-media-fallback {
    display: grid;
    place-items: center;
    background: linear-gradient(135deg, #fff2df 0%, #ffdcb8 100%);
}
[data-bs-theme="dark"] .news-media {
    background: #0e343a;
}
[data-bs-theme="dark"] .news-media-fallback {
    background: linear-gradient(135deg, #123c43 0%, #0e343a 100%);
}
.news-fallback-sun {
    height: 46%;
    width: auto;
    opacity: 0.92;
}
/* Carousel-Bedienelemente auf hellen Bildern sichtbar machen. z-index 2 hält
   Pfeile/Punkte über dem .stretched-link-Overlay (z-index 1) der klickbaren
   News-Kachel — so bedienen sie den Slider, ohne den Artikel zu öffnen. */
.news-media .carousel-control-prev,
.news-media .carousel-control-next {
    width: 14%;
    z-index: 2;
}
.news-media .carousel-indicators {
    z-index: 2;
}
.news-media .carousel-control-prev-icon,
.news-media .carousel-control-next-icon {
    background-color: rgba(20, 40, 45, 0.45);
    border-radius: 50%;
    padding: 0.85rem;
    background-size: 55%;
}
.news-media .carousel-indicators [data-bs-target] {
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

/* Sehr schmale Displays (iPhone & Co.): kompakte Portal-Navbar, damit
   Hamburger + Logo + Schriftzug + Icons nebeneinander passen und die
   Seite nicht horizontal scrollt. */
@media (max-width: 430px) {
    .navbar-fwg .container-fluid {
        padding-left: 0.5rem !important;
        padding-right: 0.5rem !important;
    }
    .navbar-fwg .navbar-nav .nav-link {
        padding-left: 0.3rem;
        padding-right: 0.3rem;
    }
    .navbar-fwg .navbar-nav {
        gap: 0 !important;
    }
    .navbar-fwg .avatar-img,
    .navbar-fwg .navbar-nav .avatar-placeholder {
        width: 32px;
        height: 32px;
        font-size: 0.8rem;
    }
    .navbar-fwg .brand-title {
        font-size: 0.85rem !important;
    }
}

/* --- Editierbare Website-Seiten: moderne Inhalts-Darstellung --- */
.page-content h2 { color: var(--fwg-ink); font-weight: 700; margin-top: 1.75rem; margin-bottom: 0.75rem; }
.page-content h2:first-child { margin-top: 0; }
.page-content h3 { color: var(--fwg-orange-dark); font-size: 1.15rem; font-weight: 700; margin-top: 1.5rem; }
[data-bs-theme="dark"] .page-content h2 { color: var(--bs-body-color); }

/* Chronik: alternierende Zeitleiste mit Jahrzehnt-Markern und Stationskarten.
   Desktop: mittige Linie, Karten wechseln links/rechts, je EIN Punkt auf der
   Linie (dockt den Eintrag an). Mobil: einspaltig mit Linie links. */
.chronik-alt { position: relative; margin-top: 1rem; }
.chronik-alt::before {
    content: ""; position: absolute; left: 50%; transform: translateX(-50%);
    top: .3rem; bottom: .3rem; width: 2px; border-radius: 2px;
    background: linear-gradient(var(--fwg-orange) 0%, var(--bs-border-color) 92%);
}
/* Jahrzehnt-Marker als Pille mittig auf der Linie */
.chronik-era { position: relative; text-align: center; margin: 1.8rem 0 1.3rem; }
.chronik-era:first-child { margin-top: 0; }
.chronik-era span {
    position: relative; z-index: 1; display: inline-block;
    font-size: 1.1rem; font-weight: 800; color: #fff; background: var(--fwg-orange);
    padding: .3rem 1.05rem; border-radius: var(--fwg-radius-pill); box-shadow: 0 4px 12px rgba(241, 135, 0, .3);
}
/* Station (halbe Breite, wechselnd) */
.chronik-item { position: relative; width: 50%; padding: 0 2rem; margin-bottom: 1rem; }
.chronik-item.ch-left { left: 0; text-align: right; }
.chronik-item.ch-right { left: 50%; text-align: left; }
/* EIN Punkt pro Eintrag, mittig auf der Linie */
.chronik-item::before {
    content: ""; position: absolute; top: 1.05rem; z-index: 1;
    width: 15px; height: 15px; border-radius: 50%;
    background: var(--fwg-orange); box-shadow: 0 0 0 4px var(--fwg-orange-soft);
}
.chronik-item.ch-left::before { right: -7.5px; }
.chronik-item.ch-right::before { left: -7.5px; }
.chronik-card {
    display: inline-block; text-align: left; max-width: 100%; border-radius: var(--fwg-radius-sm);
    padding: .75rem 1rem;
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.chronik-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 .5rem 1.4rem rgba(0, 0, 0, .1);
    border-color: var(--fwg-orange);
}
.chronik-date { font-weight: 700; font-size: .95rem; color: var(--fwg-orange-dark); margin-bottom: .1rem; }
.chronik-text { line-height: 1.5; font-size: .96rem; }
[data-bs-theme="dark"] .chronik-date { color: var(--fwg-orange); }
[data-bs-theme="dark"] .chronik-item::before { box-shadow: 0 0 0 4px rgba(241, 135, 0, .22); }
/* Mobil + kleine Tablets: einspaltig, Linie links */
@media (max-width: 767.98px) {
    .chronik-alt::before { left: 9px; transform: none; }
    .chronik-era { text-align: left; padding-left: 0; }
    .chronik-item,
    .chronik-item.ch-left,
    .chronik-item.ch-right { width: 100%; left: 0; text-align: left; padding: 0 0 0 2.4rem; }
    .chronik-item.ch-left::before,
    .chronik-item.ch-right::before { left: 2px; right: auto; }
}

/* „Mitmachen"-Karte auf Über uns */
.bg-fwg-light { background: var(--fwg-orange-soft); }
[data-bs-theme="dark"] .bg-fwg-light { background: rgba(241, 135, 0, 0.12); }

/* --- Mitglieder-Chat --- */
/* Konversations-Bildschirm: Desktop wie gehabt (Karte mit fester Höhe), auf
   Mobil füllt der Chat die komplette Fläche zwischen Navbar und Tab-Leiste —
   nur die Nachrichtenliste scrollt, die Eingabezeile klebt unten. --app-vh
   setzt tabbar.js aus visualViewport (Tastatur!), Fallback 100dvh. */
.chat-card { max-width: 800px; }
.chat-body { height: calc(100vh - 250px); min-height: 380px; }
.chat-back { color: var(--fwg-orange-dark); }
/* Sprachnachricht: Player braucht Breite, sonst wirkt die Blase gequetscht */
/* Eigener Sprachnachricht-Player (transparent in der Blase, WhatsApp-Stil) */
.chat-voice {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: min(260px, 62vw);
}
.chat-voice-play {
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border: 0;
    border-radius: 50%;
    display: grid;
    place-items: center;
    cursor: pointer;
    color: inherit;
    background: rgba(127, 127, 127, 0.22);
    font-size: 1.2rem;
    line-height: 1;
}
.chat-voice-play:hover { background: rgba(127, 127, 127, 0.32); }
.chat-voice-body { flex: 1 1 auto; min-width: 0; }
.chat-voice-track {
    height: 4px;
    border-radius: var(--fwg-radius-pill);
    background: rgba(127, 127, 127, 0.3);
    cursor: pointer;
    position: relative;
}
.chat-voice-bar {
    height: 100%;
    width: 0;
    border-radius: var(--fwg-radius-pill);
    background: currentColor;
    opacity: 0.85;
}
.chat-voice-time {
    display: block;
    font-size: 0.7rem;
    opacity: 0.7;
    margin-top: 0.3rem;
}
.chat-voice-play:disabled { opacity: 0.5; cursor: default; }
.chat-voice-error { opacity: 0.7; }
/* Mobil: Name des Chats mittig in der Glas-Navbar (statt eigener Kopfzeile) */
.nav-center-title {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    /* Mittig — aber die Breite muss an den Bedienelementen enden, sonst klebt
       ein langer Titel an der Lupe (Fund Dominik 08/2026, „1. Vorsitzende/r").
       Links das Logo (~4,5 rem), rechts Suche + Glocke + Profil (~9 rem). */
    max-width: min(55%, calc(100% - 15rem));
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 800;
    font-size: 1.02rem;
    pointer-events: none;
}
@media (min-width: 992px) {
    .nav-center-title { display: none; }
}
@media (max-width: 991.98px) {
    .has-nav-title .brand-title,
    .has-nav-title .brand-sub { display: none !important; }
    /* Im Chat darf NUR die Nachrichtenliste scrollen, nicht die Seite. Ohne das
       hier bleibt `body { min-height: 100vh }` stehen: 100vh ist auf iOS die
       VOLLE Viewporthöhe — sie schrumpft nicht mit der Tastatur und schließt in
       der installierten App sogar die Safe-Areas ein. Das Dokument war dadurch
       immer höher als der sichtbare Bereich (Scrollbalken am Rand), und iOS
       nutzte den Spielraum, um beim Tippen die Navbar aus dem Bild zu schieben.
       Bewusst nur min-height weg + overflow, KEINE feste Höhe: body ist eine
       Flex-Spalte, eine erzwungene Höhe würde bei Überlauf die Navbar stauchen
       und die Messung ins Schwanken bringen. So ist das Dokument genau so hoch
       wie sein Inhalt — und der ist die berechnete Chat-Höhe. */
    body:has(.chat-screen),
    html.chat-page body {
        min-height: 0;
        overflow: hidden;
    }
    html:has(.chat-screen),
    html.chat-page { overflow: hidden; }
    body:has(.chat-screen) > .container-fluid.flex-grow-1 { padding-bottom: 0 !important; }
    body:has(.chat-screen) .col-12.col-lg-10 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; }
    .chat-screen {
        display: flex;
        flex-direction: column;
        /* Oben: --chat-top MISST, wie viel Platz über dem Chat wirklich weg ist
           (Navbar, Banner, Meldungen, gescrollte Seite) — tabbar.js setzt es.
           Eine feste Zahl lag daneben, sobald etwas darüberstand, und schob die
           Eingabezeile unter die Tastatur.
           Unten: die Tab-Leiste ist auf der Chat-Seite ausgeblendet (der Chat
           füllt die GANZE Seite) -> der Hintergrund reicht bis an die Unterkante
           (kein Rand-Streifen); der Abstand für den Composer kommt als INNEN-
           Polster der .chat-body (siehe unten), damit nichts durchscheint. */
        --chat-bottom: 0px;
        height: calc(var(--app-vh, 100dvh) - var(--chat-top, 74px) - var(--chat-bottom));
        transition: height 0.15s ease;
    }
    body.typing .chat-screen { --chat-bottom: 6px; }
    /* iOS: über der Tastatur sitzt zusätzlich die Formular-Zubehörleiste
       („‹ › Fertig"). Sie steckt NICHT in der Höhe, die visualViewport meldet,
       und lässt sich aus dem Web nicht abschalten — also Platz dafür lassen.
       ~44 px ist die Standardhöhe im Hochformat; im Querformat ist sie
       flacher, dann bleibt etwas Luft übrig (besser als verdeckt).
       Nur iOS: Android/Chrome meldet die Tastatur korrekt, dort gäbe der
       Zuschlag eine sichtbare Lücke. */
    html.is-ios body.typing .chat-screen { --chat-bottom: 50px; }
    /* In der INSTALLIERTEN App (standalone) rechnet iOS die Zubehörleiste
       dagegen bereits selbst aus der visualViewport-Höhe heraus — der
       50-px-Zuschlag riss dort eine sichtbare Lücke über der Tastatur
       (auf dem Gerät bestätigt). Dort reicht ein Mini-Abstand. */
    @media (display-mode: standalone) {
        html.is-ios body.typing .chat-screen { --chat-bottom: 8px; }
    }
    /* Chat = GANZE Seite (WhatsApp-Look): Portal-Navbar UND Tab-Leiste weichen
       der eigenen Titelleiste (Zurück-Pfeil + Name im .chat-topbar), kein
       Karten-Rahmen, Inhalt bis an die Ränder. Zurück geht's über den Pfeil.
       --chat-top wird weiter GEMESSEN (tabbar.js) und landet dadurch
       automatisch bei ~0 (bzw. unter einem Banner darunter). */
    html.chat-page .navbar-fwg,
    body:has(.chat-screen) .navbar-fwg { display: none; }
    html.chat-page .portal-tabbar,
    body:has(.chat-screen) .portal-tabbar { display: none; }
    html.chat-page .col-12.col-lg-10,
    body:has(.chat-screen) .col-12.col-lg-10 {
        padding: 0 !important;
    }
    .chat-screen .chat-card {
        flex: 1 1 auto; min-height: 0; max-width: none;
        border: 0; border-radius: 0; box-shadow: none;
    }
    /* Kopfzeile im Titelleisten-Look: volle Breite (hebt das card-body-Padding
       p-2 auf), Navbar-Optik, Safe-Area der installierten App eingerechnet. */
    .chat-screen .chat-topbar {
        margin: -0.5rem -0.5rem 0.25rem;
        padding: 0.6rem 0.85rem;
        padding-top: calc(0.6rem + env(safe-area-inset-top, 0px));
        background-color: color-mix(in srgb, var(--fwg-surface) 92%, transparent);
        border-bottom: 1px solid var(--fwg-border) !important;
    }
    .chat-screen .chat-topbar strong { font-weight: 800; font-size: 1.02rem; }
    @media (min-width: 768px) {
        /* card-body hat ab md p-3 (0.75rem) — Kopfzeile bleibt randlos */
        .chat-screen .chat-topbar { margin: -0.75rem -0.75rem 0.25rem; }
    }
    .chat-screen .chat-body { height: auto; min-height: 0; flex: 1 1 auto; }
    /* Composer-Abstand als INNEN-Polster (statt Außenrand): der Chat-
       Hintergrund reicht bis an die Gerätekante, der [+]-Knopf bleibt aber
       über der Bildschirm-Rundung bzw. dem Home-Indikator. Beim Tippen sitzt
       die Zeile dicht über der Tastatur (Ecken spielen dann keine Rolle).
       !important: schlägt die Bootstrap-Utilities p-2/p-md-3 der card-body. */
    .chat-screen .chat-body { padding-bottom: max(calc(env(safe-area-inset-bottom, 0px) + 10px), 28px) !important; }
    body.typing .chat-screen .chat-body { padding-bottom: 8px !important; }
}
.chat-bubble {
    position: relative; max-width: 100%; padding: 0.45rem 0.7rem;
    border-radius: var(--fwg-radius-sm); font-size: 0.95rem;
}
.chat-mine { background: var(--fwg-orange-soft); border-bottom-right-radius: 0.3rem; }
.chat-theirs { background: var(--bs-secondary-bg); border-bottom-left-radius: 0.3rem; }
[data-bs-theme="dark"] .chat-mine { background: rgba(241, 135, 0, 0.22); }
/* Umbruch nur an Wortgrenzen (bei Bedarf lange Wörter/URLs). Bootstraps
   .text-break setzt word-break:break-word — das kollabiert die Blase auf
   Ein-Zeichen-Breite (min-content) und bricht dann MITTEN im Wort. Deshalb
   hier überschreiben: normale Wortumbrüche, nur überlange Wörter brechen. */
.chat-bubble .text-break {
    white-space: pre-wrap;
    word-break: normal !important;
    overflow-wrap: break-word !important;
}
.chat-sender { font-size: 0.75rem; font-weight: 700; color: var(--fwg-orange-dark); }
[data-bs-theme="dark"] .chat-sender { color: var(--fwg-orange); }
/* Uhrzeit + Häkchen dezent in der Ecke der Blase (WhatsApp-Stil), immer sichtbar. */
.chat-meta {
    display: block; text-align: right; white-space: nowrap;
    font-size: 0.64rem; line-height: 1; margin-top: 3px;
    color: var(--bs-secondary-color);
}
.chat-ticks { font-size: 0.8rem; vertical-align: -1px; margin-left: 0.2rem; }
.chat-ticks.chat-read { color: var(--fwg-green); }
[data-bs-theme="dark"] .chat-ticks.chat-read { color: #7dd87f; }
.chat-image { max-width: min(240px, 100%); max-height: 260px; object-fit: cover; display: block; }
.chat-bubble { cursor: default; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.chat-deleted { font-style: italic; opacity: 0.75; }
.chat-deleted-text { color: var(--bs-secondary-color); font-size: 0.9rem; }
.chat-shift { max-width: 82%; }

/* Composer im iPhone-Stil: runde Buttons ([+] und Mikro), Senden-Pfeil
   erscheint im Eingabefeld, sobald Text drinsteht (Toggle in chat.js). */
.chat-roundbtn {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    border: 1px solid var(--fwg-border);
    background: var(--fwg-surface-2);
    color: var(--fwg-ink);
    display: grid;
    place-items: center;
    font-size: 1.2rem;
    padding: 0;
    flex: none;
    cursor: pointer;
    transition: background-color 0.15s ease;
}
.chat-roundbtn:hover { background: var(--fwg-orange-soft); color: var(--fwg-orange-dark); }
.chat-inputwrap .chat-input {
    padding-right: 46px;
    /* FESTER Eckenradius = halbe Einzelzeilen-Höhe statt Pill (999px):
       bei einer Zeile sieht das exakt gleich aus, beim Mitwachsen entstehen
       aber gerade Kanten zwischen den runden Ecken (wie bei Messenger-Apps) —
       der Pill-Radius machte aus dem gewachsenen Feld riesige Halbkreise. */
    border-radius: 21px;
    min-height: 42px;
    /* Wächst beim Tippen mit (chat.js autoGrow), maximal ~4 Zeilen — danach
       scrollt der Text innen weiter. Mikro/Senden kleben unten (bottom: 5px). */
    max-height: 116px;
    overflow-y: auto;
}
.chat-send {
    position: absolute;
    right: 5px;
    bottom: 5px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 0;
    background: linear-gradient(135deg, var(--fwg-orange), #e06d00);
    color: #fff;
    display: grid;
    place-items: center;
    font-size: 1.05rem;
    cursor: pointer;
    box-shadow: 0 3px 10px rgba(241, 135, 0, 0.35);
}
/* Mikro im Eingabefeld (iPhone-Stil): weicht dem Senden-Pfeil, sobald Text da ist */
.chat-mic {
    position: absolute;
    right: 5px;
    bottom: 5px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 0;
    background: transparent;
    color: var(--bs-secondary-color);
    display: grid;
    place-items: center;
    font-size: 1.15rem;
    cursor: pointer;
}
.chat-mic:hover { color: var(--fwg-orange-dark); background: var(--fwg-orange-soft); }
.chat-filelink { color: inherit; font-weight: 600; }
/* Online-Punkt (aktive Sitzung in den letzten 5 Minuten) */
.online-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #2fbf4f;
    box-shadow: 0 0 0 2px color-mix(in srgb, #2fbf4f 25%, transparent);
    margin-left: 0.3rem;
    vertical-align: 2px;
}
.chat-filelink i { color: var(--fwg-orange-dark); }
[data-bs-theme="dark"] .chat-filelink i { color: var(--fwg-orange); }

/* "schreibt …"-Hinweis: schwebt oben über dem Nachrichtenbereich */
.chat-typing {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 3;
    padding: 0.25rem 0.75rem;
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
    background: linear-gradient(to bottom, var(--bs-body-bg) 60%, transparent);
    pointer-events: none;
}
.chat-typing-dots span {
    animation: chat-typing-blink 1.2s infinite both;
}
.chat-typing-dots span:nth-child(2) { animation-delay: 0.2s; }
.chat-typing-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes chat-typing-blink {
    0%, 60%, 100% { opacity: 0.25; }
    30% { opacity: 1; }
}
.chat-sound-toggle.active i { color: var(--fwg-orange-dark); }
[data-bs-theme="dark"] .chat-sound-toggle.active i { color: var(--fwg-orange); }

/* Echtzeit-Toasts: mobil OBEN (unter der Navbar, mittig), Desktop oben rechts —
   unten würden sie auf dem Handy mit Tab-Bar und Tastatur kollidieren. */
#fwg-toast-wrap {
    position: fixed;
    z-index: 1090;
    top: calc(env(safe-area-inset-top, 0px) + 4.75rem);
    left: 0.75rem;
    right: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    align-items: center;
    pointer-events: none;
}
@media (min-width: 992px) {
    #fwg-toast-wrap {
        top: 4.75rem;
        left: auto;
        right: 1rem;
        align-items: flex-end;
    }
}
.fwg-toast {
    pointer-events: auto;
    position: relative;
    width: 100%;
    max-width: 420px;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    border-left: 4px solid var(--fwg-orange);
    border-radius: var(--fwg-radius-sm);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    padding: 0.6rem 2rem 0.6rem 0.85rem;
    opacity: 0;
    transform: translateY(-12px);
    transition: opacity 0.25s ease, transform 0.25s ease;
}
.fwg-toast.show { opacity: 1; transform: none; }
.fwg-toast-link { cursor: pointer; }
.fwg-toast-title { font-weight: 600; font-size: 0.9rem; }
.fwg-toast-body {
    font-size: 0.82rem;
    color: var(--bs-secondary-color);
    margin-top: 0.1rem;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.fwg-toast-close {
    position: absolute;
    top: 0.2rem;
    right: 0.4rem;
    border: 0;
    background: transparent;
    font-size: 1.2rem;
    line-height: 1;
    color: var(--bs-secondary-color);
    cursor: pointer;
}

/* ---- Bild einfügen / Drag&Drop (paste-upload.js) ---------------------- */
.paste-upload-hint kbd {
    font-size: .72em;
    padding: .1em .35em;
}
.paste-upload-previews:empty { display: none !important; }
.paste-thumb {
    width: 72px;
    height: 72px;
    border-radius: var(--fwg-radius-sm);
    overflow: hidden;
    border: 1px solid var(--bs-border-color);
    background: var(--bs-tertiary-bg);
}
.paste-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.paste-thumb-del {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 20px;
    height: 20px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, .6);
    color: #fff;
    font-size: .8rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}
.paste-thumb-del:hover { background: rgba(0, 0, 0, .8); }
.paste-dropactive {
    outline: 2px dashed var(--fwg-orange, #f18700);
    outline-offset: 3px;
    border-radius: var(--bs-border-radius, .5rem);
}
input.paste-upload-flash {
    animation: paste-flash .6s ease;
}
@keyframes paste-flash {
    0% { box-shadow: 0 0 0 0 rgba(241, 135, 0, .5); }
    100% { box-shadow: 0 0 0 6px rgba(241, 135, 0, 0); }
}

/* ── Glocken-Popup (Benachrichtigungen) ───────────────────────────────── */
#notif-dd { position: relative; }

.notif-panel {
    position: absolute;
    top: 100%;
    right: 0;
    left: auto;
    margin-top: 0.4rem;
    width: 360px;
    max-width: calc(100vw - 1rem);
    max-height: min(70vh, 30rem);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--fwg-radius-sm);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
    overflow: hidden;
}
/* Nur im aufgeklappten Zustand sichtbar — sonst greift Bootstraps
   .dropdown-menu { display:none }. WICHTIG: kein display auf der Basis,
   sonst steht das Popup dauerhaft offen. */
.notif-panel.show {
    display: flex;
    flex-direction: column;
    animation: notif-pop 0.18s ease;
}
@keyframes notif-pop {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: none; }
}

/* Mobil: als volle Leiste unter der Navbar „reinschweben" statt schmales Dropdown */
@media (max-width: 575.98px) {
    .notif-panel.dropdown-menu {
        position: fixed !important;
        top: calc(env(safe-area-inset-top, 0px) + 3.75rem) !important;
        right: 0.5rem !important;
        left: 0.5rem !important;
        margin-top: 0;
        width: auto;
        max-width: none;
        max-height: 75vh;
    }
}

.notif-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.6rem 0.85rem;
    border-bottom: 1px solid var(--bs-border-color);
    font-size: 0.9rem;
}
.notif-readall { font-size: 0.78rem; color: var(--fwg-orange-dark); }

.notif-panel-body { overflow-y: auto; flex: 1 1 auto; }

.notif-item {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.6rem 0.85rem;
    border-bottom: 1px solid var(--bs-border-color);
    color: inherit;
    text-decoration: none;
    position: relative;
}
a.notif-item { cursor: pointer; }
a.notif-item:hover { background: var(--bs-tertiary-bg); }
.notif-item:last-child { border-bottom: 0; }
.notif-item.notif-unread { background-color: #fff8ec; }
[data-bs-theme="dark"] .notif-item.notif-unread { background-color: rgba(247, 154, 31, 0.10); }

.notif-ico {
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 0.95rem;
    background: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
}
.notif-main { min-width: 0; display: flex; flex-direction: column; flex: 1 1 auto; }
.notif-title {
    font-size: 0.86rem;
    font-weight: 500;
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.notif-unread .notif-title { font-weight: 600; }
.notif-body {
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
    margin-top: 0.1rem;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.notif-time { font-size: 0.72rem; color: var(--bs-secondary-color); margin-top: 0.15rem; }
.notif-dot {
    flex: 0 0 auto;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--fwg-orange);
    margin-top: 0.5rem;
}

/* Farbtöne je Kategorie */
.notif-tone-chat      { background: #e7f0ff; color: #1d4ed8; }
.notif-tone-meeting,
.notif-tone-calendar  { background: #e6f4ec; color: #1c7c46; }
.notif-tone-vote,
.notif-tone-poll      { background: #efe7ff; color: #6d28d9; }
.notif-tone-task      { background: #e6f6f4; color: #0f766e; }
.notif-tone-money     { background: #fdf0d6; color: #b45309; }
.notif-tone-doc       { background: #eef1f4; color: #475569; }
.notif-tone-inventory { background: #f0ece4; color: #7c5e2a; }
.notif-tone-photo     { background: #fde8f0; color: #be1d6a; }
.notif-tone-birthday  { background: #fdeaea; color: #c2410c; }
.notif-tone-feedback  { background: #fdeaea; color: #b91c1c; }
.notif-tone-members   { background: #e6f4ec; color: #1c7c46; }
.notif-tone-news      { background: #fdf0d6; color: #b45309; }
.notif-tone-fraktion  { background: #eef1f4; color: #475569; }
.notif-tone-default   { background: var(--fwg-orange-soft); color: var(--fwg-orange-dark); }

[data-bs-theme="dark"] .notif-tone-chat      { background: rgba(59,130,246,.18); color: #93c5fd; }
[data-bs-theme="dark"] .notif-tone-meeting,
[data-bs-theme="dark"] .notif-tone-calendar,
[data-bs-theme="dark"] .notif-tone-members   { background: rgba(34,197,94,.18); color: #86efac; }
[data-bs-theme="dark"] .notif-tone-vote,
[data-bs-theme="dark"] .notif-tone-poll      { background: rgba(139,92,246,.20); color: #c4b5fd; }
[data-bs-theme="dark"] .notif-tone-task      { background: rgba(20,184,166,.18); color: #5eead4; }
[data-bs-theme="dark"] .notif-tone-money,
[data-bs-theme="dark"] .notif-tone-news      { background: rgba(245,158,11,.18); color: #fcd34d; }
[data-bs-theme="dark"] .notif-tone-doc,
[data-bs-theme="dark"] .notif-tone-fraktion  { background: rgba(148,163,184,.20); color: #cbd5e1; }
[data-bs-theme="dark"] .notif-tone-inventory { background: rgba(180,140,60,.20); color: #e6c99a; }
[data-bs-theme="dark"] .notif-tone-photo     { background: rgba(236,72,153,.18); color: #f9a8d4; }
[data-bs-theme="dark"] .notif-tone-birthday,
[data-bs-theme="dark"] .notif-tone-feedback  { background: rgba(239,68,68,.18); color: #fca5a5; }

.notif-panel-foot {
    display: block;
    text-align: center;
    padding: 0.6rem;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--fwg-orange-dark);
    text-decoration: none;
    border-top: 1px solid var(--bs-border-color);
    background: var(--bs-tertiary-bg);
}
.notif-panel-foot:hover { color: var(--fwg-orange); background: var(--bs-secondary-bg); }

/* ── „Was ist neu"-Banner + Punkt ─────────────────────────────────────── */
.changelog-banner {
    background: var(--fwg-orange-soft);
    color: var(--fwg-orange-dark);
    border-bottom: 1px solid color-mix(in srgb, var(--fwg-orange) 35%, transparent);
}
.changelog-banner .bi-stars { color: var(--fwg-orange); }
.changelog-banner .alert-link { color: var(--fwg-orange-dark); font-weight: 600; }
[data-bs-theme="dark"] .changelog-banner {
    background: rgba(247, 154, 31, 0.12);
    color: #fcd34d;
}
[data-bs-theme="dark"] .changelog-banner .alert-link { color: #fcd34d; }

/* ── Verwaltungs-Baum in der Sidebar (Desktop) ────────────────────────── */
.nav-tree-parent { display: flex; align-items: center; }
.nav-tree-parent .nav-link { flex: 1 1 auto; min-width: 0; }
.nav-tree-toggle {
    flex: 0 0 auto;
    background: none;
    border: 0;
    color: inherit;
    padding: 0.3rem 0.45rem;
    opacity: 0.5;
    line-height: 1;
    border-radius: var(--fwg-radius-sm);
}
.nav-tree-toggle:hover { opacity: 1; background: var(--fwg-orange-soft); }
.nav-tree-toggle .bi { display: block; transition: transform 0.15s ease; }
.nav-tree.collapsed .nav-tree-toggle .bi { transform: rotate(-90deg); }
.nav-tree.collapsed .nav-tree-children { display: none; }
.nav-tree-children {
    margin: 0.05rem 0 0.35rem 1.15rem;
    padding-left: 0.4rem;
    border-left: 1px solid var(--bs-border-color);
}
.nav-tree-children .nav-link {
    font-size: 0.875rem;
    padding-top: 0.32rem;
    padding-bottom: 0.32rem;
}
.nav-tree-children .nav-link .bi { font-size: 0.92em; }

/* kleiner „neu"-Punkt an der Build-Zeile */
.changelog-dot {
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--fwg-orange);
    margin-left: 0.25rem;
    vertical-align: middle;
}

/* --- Nutzungs-Statistik (Admin): Heatmap + 30-Tage-Balken --- */
.usage-heatmap-wrap { overflow-x: auto; padding-bottom: 0.25rem; }
.usage-heatmap { display: flex; gap: 3px; min-width: max-content; }
.hm-days { display: flex; flex-direction: column; gap: 3px; margin-right: 4px; }
.hm-days span { height: 13px; line-height: 13px; font-size: 0.6rem; color: var(--bs-secondary-color); }
.hm-week { display: flex; flex-direction: column; gap: 3px; }
.hm-cell { width: 13px; height: 13px; border-radius: 3px; display: inline-block; background: var(--fwg-border); }
.hm-future { visibility: hidden; }
.hm-0 { background: var(--fwg-border); }
.hm-1 { background: rgba(241, 135, 0, 0.30); }
.hm-2 { background: rgba(241, 135, 0, 0.55); }
.hm-3 { background: rgba(241, 135, 0, 0.80); }
.hm-4 { background: var(--fwg-orange); }
.usage-legend { display: inline-flex; align-items: center; gap: 3px; }
.usage-legend .hm-cell { width: 12px; height: 12px; }

.usage-bars { display: flex; align-items: flex-end; gap: 3px; height: 120px; }
.usage-bar { flex: 1 1 0; min-width: 4px; height: 100%; display: flex; align-items: flex-end; }
.usage-bar > span { display: block; width: 100%; background: var(--fwg-orange); border-radius: 3px 3px 0 0; }

/* --- Hilfe: „?"-Icon in Überschriften + Anker-Ziele auf der Hilfeseite --- */
.help-hint { color: var(--bs-secondary-color); text-decoration: none; font-size: 0.8em; margin-left: 0.4rem; opacity: 0.75; vertical-align: middle; }
.help-hint:hover, .help-hint:focus { color: var(--fwg-orange); opacity: 1; }
.help-section { scroll-margin-top: 5rem; transition: box-shadow 0.4s ease; }
.help-section:target { box-shadow: 0 0 0 3px rgba(241, 135, 0, 0.55); }
.help-toc a { text-decoration: none; }

/* --- Live-Passwort-Prüfliste (Passwort ändern / Reset / Erst-Login) --- */
.password-policy-list { list-style: none; padding-left: 0; margin-bottom: 0; }
.password-policy-list li { color: var(--bs-secondary-color); line-height: 1.6; }
.password-policy-list li::before { content: "○"; display: inline-block; width: 1.3em; text-align: center; }
.password-policy-list li.is-ok { color: var(--bs-success); }
.password-policy-list li.is-ok::before { content: "✓"; font-weight: 700; }

/* === Kompakt-Modus (nur Portal) ====================================
   Umschalter im Profil-Menü (.dense-toggle, dense.js); Zustand pro Gerät
   in localStorage `fwg-dense`, Klasse .dense wird schon im <head> gesetzt
   (kein Aufblitzen). Reduziert gezielt die spürbaren Abstände, ohne die
   Lesbarkeit zu opfern. Greift nur im Portal, weil dense.js nur dort läuft;
   der öffentliche Bereich behält seine großzügige Optik.
   Trick: wir überschreiben Bootstraps Spacer-/Gutter-Variablen — dann
   ziehen Karten und Grids automatisch mit, ohne jede Regel einzeln zu jagen.
   Die Card-Spacer MÜSSEN im .card-Scope gesetzt werden: Bootstrap deklariert
   `--bs-card-spacer-y:1rem` direkt auf `.card`, das würde einen Wert auf
   html.dense überstimmen. Auf `html.dense .card` gewinnt unser Wert. */
html.dense .card {
    --bs-card-spacer-y: 0.7rem;
    --bs-card-spacer-x: 0.85rem;
}

/* Grid-Abstände (Bento/Kachel-Reihen) etwas enger:
   die üppigen g-4 (1.5rem) auf ~1rem, g-3 (1rem) auf ~0.65rem. */
html.dense .g-4,
html.dense .gy-4 { --bs-gutter-y: 1rem; }
html.dense .g-4,
html.dense .gx-4 { --bs-gutter-x: 1rem; }
html.dense .g-3,
html.dense .gy-3 { --bs-gutter-y: 0.65rem; }
html.dense .g-3,
html.dense .gx-3 { --bs-gutter-x: 0.65rem; }

/* Tabellen: Zeilen dichter (Kassenbuch, Mitgliederliste …) */
html.dense .table > :not(caption) > * > * {
    padding-top: 0.4rem;
    padding-bottom: 0.4rem;
}

/* Feature-/Dashboard-Kacheln: weniger Innenabstand */
html.dense .feature-tile { padding: 1.1rem; }
html.dense .feature-tile .icon-bubble { margin-bottom: 0.5rem; }

/* Große vertikale Abstände zwischen Abschnitten zusammenziehen.
   Nur die üppigen Utility-Stufen (mb-4/mb-5, py-4/py-5) im Portal-Main. */
html.dense main .mb-5 { margin-bottom: 1.5rem !important; }
html.dense main .mb-4 { margin-bottom: 1rem !important; }
html.dense main .py-5 { padding-top: 1.75rem !important; padding-bottom: 1.75rem !important; }
html.dense main .py-4 { padding-top: 1.1rem !important; padding-bottom: 1.1rem !important; }

/* Seiten-Überschrift und Karten-Titel etwas kompakter */
html.dense main h1 { margin-bottom: 0.65rem; }
html.dense .card .card-title { margin-bottom: 0.4rem; }

/* === XXL-Modus (Barrierefreiheit, nur Portal) ==========================
   Umschalter im Profil-Menü (.xxl-toggle, xxl.js); Zustand pro Gerät in
   localStorage `fwg-xxl`, Klasse .xxl wird schon im <head> gesetzt.
   Zielgruppe: ältere Mitglieder — deutlich größere Schrift, kräftigere
   Kontraste und größere Klick-/Touchflächen. Der Kern ist die root-
   Schriftgröße: fast alles im Portal ist in rem gesetzt (Bootstrap +
   custom.css) und wächst dadurch automatisch mit — inklusive Abstände.
   Funktioniert in allen Design-Themen, weil nur Größen/Deckkraft
   verändert werden, keine Themen-Farben. */
html.xxl { font-size: 115%; }
html.xxl body { line-height: 1.65; }

/* Gedämpfte Texte kräftiger: --bs-secondary-color speist .text-muted,
   .form-text & Co. — color-mix folgt automatisch Hell/Dunkel. `html.xxl`
   gewinnt gegen Bootstraps :root und [data-bs-theme] (beide liegen auf
   demselben <html>-Element, unsere Spezifität ist höher). */
html.xxl {
    --bs-secondary-color: color-mix(in srgb, var(--bs-body-color) 82%, transparent);
    --bs-tertiary-color:  color-mix(in srgb, var(--bs-body-color) 66%, transparent);
}

/* Bedienelemente: größere Flächen (Fitts' Law, zittrige Finger) */
html.xxl .btn { padding: 0.6rem 1.1rem; }
html.xxl .btn-sm { padding: 0.45rem 0.85rem; font-size: 0.95rem; }
html.xxl .form-control, html.xxl .form-select { padding: 0.55rem 0.8rem; }
html.xxl .form-check-input { width: 1.4em; height: 1.4em; margin-top: 0.1em; }
html.xxl .form-switch .form-check-input { width: 2.6em; }
html.xxl .dropdown-item { padding-top: 0.55rem; padding-bottom: 0.55rem; }
html.xxl .portal-sidebar .nav-link { padding-top: 0.55rem; padding-bottom: 0.55rem; }
html.xxl .nav-tree-children .nav-link { padding-top: 0.45rem; padding-bottom: 0.45rem; }

/* Tabellen: luftigere Zeilen, damit Zahlen/Namen klar getrennt bleiben */
html.xxl .table > :not(caption) > * > * {
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
}

/* Kleingedrucktes nicht unter die Lesbarkeitsgrenze fallen lassen */
html.xxl .small, html.xxl small { font-size: 0.92em; }

/* Mobile Tab-Bar: Beschriftung + Symbole mitwachsen lassen */
html.xxl .portal-tabbar .tab { font-size: 0.78rem; }
html.xxl .portal-tabbar .tico { font-size: 1.35rem; }

/* === Saisonale Akzente (partials/seasonal.php, Setting `seasonal_accents`) ===
   Dezente Deko-Ebene über den Hero-Bereichen: Schneeflocken im Dezember,
   pulsierender Sonnen-Glow im Juli. pointer-events:none — Klicks gehen
   durch; prefers-reduced-motion hält alles still. */
.has-season { position: relative; overflow: hidden; }
.season-layer {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    border-radius: inherit;
    z-index: 1;
}
.season-flake {
    position: absolute;
    top: -12%;
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.7);
    text-shadow: 0 0 6px rgba(255, 255, 255, 0.35);
    animation: fwg-snowfall linear infinite;
    will-change: top, transform;
}
@keyframes fwg-snowfall {
    0%   { top: -12%; transform: translateX(0) rotate(0deg); opacity: 0; }
    8%   { opacity: 1; }
    50%  { transform: translateX(9px) rotate(180deg); }
    92%  { opacity: 0.9; }
    100% { top: 112%; transform: translateX(-7px) rotate(360deg); opacity: 0; }
}
.season-sun {
    position: absolute;
    top: -70px;
    right: -50px;
    width: 240px;
    height: 240px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 205, 90, 0.55), rgba(241, 135, 0, 0.22) 45%, transparent 70%);
    animation: fwg-sunpulse 5.5s ease-in-out infinite alternate;
    will-change: transform, opacity;
}
/* Auf der öffentlichen Startseite sitzt die Sonnenkugel mittig — der
   saisonale Glow legt sich als warmes Pulsieren darüber (deutlich
   gedämpfter, die Hero-Sonne leuchtet ja schon von selbst). */
.hero .season-sun {
    left: 50%;
    right: auto;
    margin-left: -120px;
    top: -110px;
    background: radial-gradient(circle, rgba(255, 205, 90, 0.28), rgba(241, 135, 0, 0.1) 45%, transparent 70%);
}
@keyframes fwg-sunpulse {
    from { transform: scale(1);    opacity: 0.65; }
    to   { transform: scale(1.22); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .season-flake, .season-sun { animation: none; }
    .season-flake { top: 20%; opacity: 0.5; }
}

/* === Skeleton-Loading beim Seitenwechsel (page-loader.js) ==============
   Overlay mit Platzhalter-Balken statt weißer Fläche, wenn eine
   Navigation spürbar dauert (> ~220 ms). Farben hängen an den Tokens
   und funktionieren dadurch in Hell/Dunkel und allen Design-Themen. */
.page-loader {
    position: fixed;
    inset: 0;
    z-index: 2500;
    background: var(--fwg-bg, var(--bs-body-bg));
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease;
}
.page-loader.on {
    opacity: 1;
    pointer-events: auto;
}
.page-loader-inner {
    max-width: 1100px;
    margin: 0 auto;
    padding: 5.5rem 1.25rem 2rem;
}
.skel {
    position: relative;
    overflow: hidden;
    border-radius: var(--fwg-radius-sm, 0.5rem);
    background: color-mix(in srgb, var(--fwg-ink, var(--bs-body-color)) 9%, transparent);
}
.skel::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--fwg-surface, #fff) 60%, transparent), transparent);
    animation: fwg-shimmer 1.3s ease-in-out infinite;
}
.skel-title { height: 2.1rem; width: min(46%, 300px); margin-bottom: 0.9rem; }
.skel-line  { height: 1rem;   width: min(68%, 480px); margin-bottom: 1.6rem; }
.skel-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1.25rem;
    margin-bottom: 1.25rem;
}
.skel-card  { height: 9.5rem; border-radius: var(--fwg-radius, 1rem); }
.skel-block { height: 14rem;  border-radius: var(--fwg-radius, 1rem); }
@media (max-width: 767.98px) {
    .skel-grid { grid-template-columns: 1fr; }
    .skel-card { height: 6.5rem; }
}
@keyframes fwg-shimmer {
    to { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
    .skel::after { animation: none; }
}

/* === Mobile Kartenlisten: Tabellen unter 992px als gestapelte Karten =========
   Tabellen mit der Klasse .table-cards werden auf schmalen Bildschirmen nicht
   horizontal gescrollt, sondern Zeile für Zeile als Karte gestapelt. Jede Zelle
   trägt ein data-label; das erscheint links, der Wert rechts (WhatsApp-artige
   Zwei-Spalten-Zeile). Leere Zellen werden ausgeblendet — dadurch verschwinden
   im Kassenbuch automatisch die jeweils leere Einnahme- ODER Ausgabe-Spalte.
   Betrifft Kassenbuch, Beiträge, Inventar, Mitgliederliste. */
@media (max-width: 991.98px) {
    /* Der horizontale Scroll-Zwang entfällt im Kartenmodus */
    .table-cards.table-scroll,
    .table-cards { min-width: 0; }
    .card:has(> .table-responsive) .table-responsive:has(.table-cards) { overflow: visible; }

    /* Die UMGEBENDE Karte legt ihren Kartenlook ab, sonst liegt Karte auf Karte
       (im Dark-Modus fällt der fehlende Kontrast sonst unangenehm auf). Nur die
       einzelnen Zeilen erscheinen als Karten. */
    .card:has(> .table-responsive > .table-cards),
    .card:has(> .card-header + .table-responsive > .table-cards) {
        border: 0;
        box-shadow: none;
        background: transparent;
    }

    .table-cards thead { display: none; }

    .table-cards,
    .table-cards tbody,
    .table-cards tr,
    .table-cards td { display: block; width: auto; }

    /* Jede Datenzeile = eine Karte. Hebt sich über surface-2 (die hellere
       Flächenfarbe) klar vom Seitenhintergrund ab — im Light wie im Dark. */
    .table-cards tbody tr {
        border: 1px solid var(--fwg-border);
        border-radius: var(--fwg-radius-sm);
        padding: 0.6rem 0.85rem;
        margin: 0.6rem 0;
        background: var(--fwg-surface);
        box-shadow: var(--fwg-shadow);
    }
    [data-bs-theme="dark"] .table-cards tbody tr {
        background: var(--fwg-surface-2);
        border-color: color-mix(in srgb, var(--fwg-surface-2) 70%, #ffffff 30%);
    }
    /* Bootstrap-Zell-Rahmen/-Padding im Kartenmodus zurücknehmen.
       WICHTIG: Bootstrap malt auf jede td den Tabellen-Hintergrund
       (--bs-table-bg = Seitenfarbe) via background + inset-box-shadow.
       Das würde die hellere Zeilen-Karte übermalen (dunkle „Löcher" im
       Dark-Modus). Deshalb Zellen transparent + den box-shadow-Trick aus. */
    .table-cards tbody td {
        border: 0 !important;
        padding: 0.28rem 0 !important;
        text-align: left !important;
        white-space: normal !important;
        background-color: transparent !important;
        box-shadow: none !important;
    }

    /* Zelle = Label links / Wert rechts */
    .table-cards tbody td[data-label]::before {
        content: attr(data-label);
        display: inline-block;
        min-width: 40%;
        padding-right: 0.75rem;
        font-weight: 600;
        color: var(--bs-secondary-color);
    }
    .table-cards tbody td[data-label] {
        display: flex;
        /* Umbruch ist Pflicht: eine Zelle mit mehreren Badges (Rollen, Status)
           lief sonst über den Kartenrand hinaus und wurde rechts abgeschnitten
           (Fund Dominik 08/2026, „Stellv. Vorsitzende…" in der Mitgliederliste).
           Das Label schiebt sich per margin-right:auto nach links, die Werte
           sammeln sich rechts und rutschen bei Bedarf in die nächste Zeile. */
        flex-wrap: wrap;
        justify-content: flex-end;
        align-items: baseline;
        gap: 0.35rem 0.5rem;
    }
    .table-cards tbody td[data-label]::before { margin-right: auto; }
    /* Wert-Text darf umbrechen und bündig rechts stehen */
    .table-cards tbody td[data-label] > * { text-align: right; }

    /* Leere Zellen (z. B. die nicht-befüllte Einnahme/Ausgabe-Spalte) weg.
       :empty greift, weil die betroffenen td dann wirklich keinen Inhalt haben. */
    .table-cards tbody td:empty { display: none; }

    /* Zellen ohne Label (Avatar, Aktionsspalte): volle Breite, keine ::before-Zeile.
       Aktionen ans Ende, Buttons dürfen sich breit machen. */
    .table-cards tbody td.cell-actions {
        display: flex;
        flex-wrap: wrap;
        gap: 0.4rem;
        justify-content: flex-end;
        margin-top: 0.5rem;
        padding-top: 0.5rem !important;
        border-top: 1px solid var(--fwg-border) !important;
    }
    .table-cards tbody td.cell-actions form { margin: 0; }

    /* Deko-/Avatar-Zelle ohne data-label und ohne .cell-actions einfach zentriert */
    .table-cards tbody td.cell-avatar { text-align: center !important; }

    /* Summen-/Leerzeilen-Fußzeile bleibt einfache Zeile */
    .table-cards tfoot { display: block; }
    .table-cards tfoot tr { display: block; margin: 0.6rem 0.75rem; }
    .table-cards tfoot th { display: flex; justify-content: space-between; border: 0; }
}

/* === Befehlspalette (⌘/Strg+K) ============================================= */
.cmdk-overlay {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 12vh 1rem 1rem;
    background: rgba(7, 34, 40, 0.55);
    backdrop-filter: blur(3px);
}
body.cmdk-open { overflow: hidden; }

.cmdk-panel {
    width: 100%;
    max-width: 560px;
    background: var(--fwg-surface);
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius);
    box-shadow: var(--fwg-shadow-hover);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    max-height: 70vh;
}

.cmdk-search {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--fwg-border);
}
.cmdk-search .bi-search { color: var(--bs-secondary-color); font-size: 1.05rem; }
.cmdk-search input {
    flex: 1 1 auto;
    border: 0;
    background: transparent;
    color: var(--fwg-ink);
    font-size: 1.05rem;
    outline: none;
}
.cmdk-esc {
    font-size: 0.7rem;
    color: var(--bs-secondary-color);
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius-sm);
    padding: 0.1rem 0.4rem;
}

.cmdk-results {
    list-style: none;
    margin: 0;
    padding: 0.4rem;
    overflow-y: auto;
}
.cmdk-item {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.55rem 0.7rem;
    border-radius: var(--fwg-radius-sm);
    cursor: pointer;
}
.cmdk-item .bi { color: var(--fwg-orange-dark); width: 1.2rem; text-align: center; flex: 0 0 auto; }
.cmdk-item .cmdk-label { flex: 1 1 auto; font-weight: 600; }
.cmdk-item .cmdk-group { font-size: 0.8rem; color: var(--bs-secondary-color); }
.cmdk-item.is-active { background: var(--fwg-orange-soft); }
.cmdk-item.is-active .cmdk-label { color: var(--fwg-orange-dark); }

.cmdk-empty {
    padding: 1.2rem 1rem;
    text-align: center;
    color: var(--bs-secondary-color);
}

/* ---------------------------------------------------------------------------
   Portal-Design-Feinschliff („App-Look Stufe 2"): verbindet das Portal optisch
   mit der überarbeiteten Landingpage — Icon-Kacheln in Kartenköpfen, farbige
   Bereichs-Icons in der Sidebar (gleiche Farbquelle wie Tab-Bar/„Mehr"-Sheet),
   sichtbarer Suchen-Knopf (Befehlspalette), sanfte Einblend-Animation.
--------------------------------------------------------------------------- */

/* Suchen-Knopf in der Kopfleiste: sieht aus wie ein Eingabefeld, öffnet die
   Befehlspalette (⌘/Strg+K). Nur Desktop; mobil ein schlichtes Lupen-Icon. */
.nav-search-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    border: 1px solid var(--fwg-border);
    background: color-mix(in srgb, var(--fwg-surface-2) 55%, var(--fwg-surface));
    color: var(--bs-secondary-color);
    border-radius: var(--fwg-radius-pill);
    padding: 0.4rem 0.6rem 0.4rem 0.9rem;
    font-size: 0.88rem;
    font-weight: 600;
    min-width: 200px;
    transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}
.nav-search-btn:hover {
    border-color: color-mix(in srgb, var(--fwg-orange) 45%, var(--fwg-border));
    color: var(--fwg-ink);
    background: var(--fwg-surface);
}
.nav-search-btn span { flex: 1 1 auto; text-align: left; }
.nav-search-btn kbd {
    font-size: 0.72rem;
    background: var(--fwg-surface);
    color: var(--bs-secondary-color);
    border: 1px solid var(--fwg-border);
    border-radius: 0.45rem;
    padding: 0.1rem 0.4rem;
}

/* Sidebar: Bereichs-Icons als getönte Farb-Chips (--nav-ico kommt aus
   portal_tab_color() im Layout — dieselbe Farbwelt wie die mobilen Kacheln).
   Aktiver Punkt: weißes Icon auf halbtransparentem Weiß. */
.portal-sidebar .nav-link {
    display: flex;
    align-items: center;
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
}
.portal-sidebar .nav-link .bi {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.7rem;
    height: 1.7rem;
    flex: 0 0 auto;
    border-radius: 0.55rem;
    font-size: 0.92rem;
    background: color-mix(in srgb, var(--nav-ico, var(--fwg-orange)) 14%, var(--fwg-surface));
    color: var(--nav-ico, currentColor);
    transition: transform 0.15s ease;
}
.portal-sidebar .nav-link.active .bi {
    background: rgba(255, 255, 255, 0.22);
    color: #fff;
}
.portal-sidebar .nav-link:hover:not(.active) .bi { transform: scale(1.1); }
/* Unterpunkte im Verwaltungs-Baum: schlichte Glyphen (ruhigere Hierarchie) */
.portal-sidebar .nav-tree-children .nav-link .bi {
    width: auto;
    height: auto;
    background: transparent;
    border-radius: 0;
    color: var(--bs-secondary-color);
}
.portal-sidebar .nav-tree-children .nav-link.active .bi { color: #fff; }

/* Kartenköpfe: das führende Icon wird zur kleinen abgerundeten Kachel im
   App-Stil (wie „Mehr"-Sheet und Hub-Kacheln) — gilt portalweit, rein CSS.
   --tile (optional, z. B. im Dashboard gesetzt) färbt die Kachel je Bereich;
   ohne --tile bleibt das Brand-Orange. */
body.portal .card-title > .bi:first-child {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.05rem;
    height: 2.05rem;
    flex: 0 0 auto;
    border-radius: 0.65rem;
    background: color-mix(in srgb, var(--tile, var(--fwg-orange)) 14%, var(--fwg-surface));
    color: color-mix(in srgb, var(--tile, var(--fwg-orange-dark)) 82%, var(--fwg-ink)) !important; /* schlägt .text-fwg */
    font-size: 1rem;
    vertical-align: middle;
    margin-top: -0.2rem;
}
[data-bs-theme="dark"] body.portal .card-title > .bi:first-child {
    color: color-mix(in srgb, var(--tile, var(--fwg-orange-dark)) 70%, #fff) !important;
}
/* Auf der dunklen Hero-Karte („Nächste Sitzung") hell hinterlegen */
body.portal .dash-hero .card-title > .bi:first-child {
    background: rgba(255, 255, 255, 0.16);
    color: #ffd28a !important;
}

/* Begrüßung auf der Übersicht: Hero-Banner im Stil der Startseite —
   Petrol-Verlauf mit Sonnen-Glow, weißer Gruß + Datum, Info-Chips rechts. */
.dash-greet-hero {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 1.4rem 1.6rem;
    border-radius: var(--fwg-radius-lg);
    color: #fff;
    background:
        radial-gradient(circle at 88% -20%, rgba(255, 178, 84, 0.5), rgba(241, 135, 0, 0.18) 30%, transparent 55%),
        linear-gradient(150deg, var(--fwg-petrol), #103e47 55%, #15606e);
    box-shadow: var(--fwg-shadow);
}
.dash-greet-hero h1 { color: #fff; margin-bottom: 0.15rem; }
.dash-greet-hero .dash-date {
    font-weight: 600;
    color: rgba(255, 255, 255, 0.78);
}
.dash-greet-hero .dash-date .bi { color: #ffc06a; }
.dash-greet-hero .help-hint { color: rgba(255, 255, 255, 0.65); }
.dash-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}
.dash-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.42rem 0.9rem;
    border-radius: var(--fwg-radius-pill);
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.18);
    color: #fff;
    font-size: 0.86rem;
    font-weight: 600;
    text-decoration: none;
    transition: background-color 0.15s ease, transform 0.15s ease;
}
.dash-chip:hover {
    background: rgba(255, 255, 255, 0.22);
    color: #fff;
    transform: translateY(-1px);
}
.dash-chip .bi { color: #ffc06a; }

/* --- Übersicht: Aufbau-Varianten (dashboard_layouts) ---------------------
   Alle drei Varianten teilen sich diese Bausteine; die Farben kommen aus den
   Token, damit sie in jedem Design-Thema und in Hell/Dunkel sitzen. */

/* Abschnitts-Überschrift („Das erledigst du heute") — Text + feine Linie */
.dash-section {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    margin: 2rem 0 1rem;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.dash-section::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--fwg-border);
}

/* Aktionskarten: Symbol, Text, Handlung — genau ein Ziel je Karte */
.dash-actions {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 0.75rem;
}
.dash-action {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius);
    background: var(--fwg-surface);
    color: inherit;
    text-decoration: none;
    box-shadow: var(--fwg-shadow);
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.dash-action:hover {
    color: inherit;
    transform: translateY(-2px);
    box-shadow: var(--fwg-shadow-hover);
}
/* „hot" = drängt (überfällig, wartet auf Freigabe): zarter Orange-Ton */
.dash-action.is-hot {
    border-color: color-mix(in srgb, var(--fwg-orange) 42%, var(--fwg-border));
    background: linear-gradient(140deg, var(--fwg-surface) 45%, color-mix(in srgb, var(--fwg-orange) 9%, var(--fwg-surface)));
}
.dash-action-ico {
    flex: 0 0 auto;
    width: 2.2rem;
    height: 2.2rem;
    border-radius: var(--fwg-radius-sm);
    display: grid;
    place-items: center;
    font-size: 1.05rem;
    background: color-mix(in srgb, var(--tile, var(--fwg-orange)) 16%, transparent);
    color: var(--tile, var(--fwg-orange));
}
.dash-action-txt { flex: 1; min-width: 0; }
.dash-action-txt strong { display: block; font-size: 0.95rem; line-height: 1.3; }
.dash-action-txt span {
    display: block;
    font-size: 0.82rem;
    color: var(--bs-secondary-color);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dash-action-cta {
    flex: 0 0 auto;
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--fwg-orange);
    white-space: nowrap;
}
@media (max-width: 575.98px) {
    /* Am Handy zählt die Handlung, nicht das Wort dafür — Pfeil genügt */
    .dash-action-cta { font-size: 0; }
    .dash-action-cta .bi { font-size: 1rem; margin-left: 0 !important; }
}

/* Kennzahl-Kacheln */
.dash-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
    gap: 0.75rem;
}
.dash-stat {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.9rem 1rem;
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius);
    background: var(--fwg-surface);
    color: inherit;
    text-decoration: none;
    box-shadow: var(--fwg-shadow);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.dash-stat:hover { color: inherit; transform: translateY(-2px); box-shadow: var(--fwg-shadow-hover); }
.dash-stat-label {
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.dash-stat-value {
    font-size: 1.6rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
}
.dash-stat-value.tone-good { color: var(--bs-success-text-emphasis, #16a34a); }
.dash-stat-value.tone-warn { color: var(--bs-warning-text-emphasis, #b45309); }
.dash-stat-value.tone-bad  { color: var(--bs-danger-text-emphasis, #dc3545); }
.dash-stat-sub { font-size: 0.78rem; color: var(--bs-secondary-color); }
.dash-spark { display: block; width: 100%; height: 24px; margin: 0.15rem 0; }

/* Zeitstrahl */
.dash-timeline { position: relative; padding-left: 4.6rem; }
.dash-timeline::before {
    content: "";
    position: absolute;
    left: 3.65rem;
    top: 0.4rem;
    bottom: 0.4rem;
    width: 2px;
    background: var(--fwg-border);
}
.dash-tl-item { position: relative; padding-bottom: 1rem; }
.dash-tl-when {
    position: absolute;
    left: -4.6rem;
    top: 0.1rem;
    width: 3.2rem;
    text-align: right;
    font-size: 0.78rem;
    font-weight: 800;
    line-height: 1.25;
    color: var(--bs-secondary-color);
    font-variant-numeric: tabular-nums;
}
.dash-tl-when em {
    display: block;
    font-style: normal;
    font-size: 0.7rem;
    font-weight: 700;
    opacity: 0.75;
}
.dash-tl-item.is-today .dash-tl-when { color: var(--fwg-orange); }
.dash-tl-dot {
    position: absolute;
    left: -1.19rem;
    top: 0.45rem;
    width: 0.8rem;
    height: 0.8rem;
    border-radius: 50%;
    background: var(--tile, var(--fwg-orange));
    border: 3px solid var(--fwg-bg);
}
.dash-tl-box {
    display: block;
    padding: 0.7rem 0.95rem;
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius-sm);
    background: var(--fwg-surface);
    color: inherit;
    text-decoration: none;
}
a.dash-tl-box:hover { color: inherit; border-color: color-mix(in srgb, var(--fwg-orange) 45%, var(--fwg-border)); }
.dash-tl-box strong { display: block; font-size: 0.95rem; }
.dash-tl-box > span { font-size: 0.82rem; color: var(--bs-secondary-color); }
.dash-tl-item.is-quiet .dash-tl-box { background: transparent; border-style: dashed; }
.dash-tl-item.is-quiet .dash-tl-dot { background: var(--fwg-border); }
@media (max-width: 575.98px) {
    .dash-timeline { padding-left: 3.9rem; }
    .dash-timeline::before { left: 2.95rem; }
    .dash-tl-when { left: -3.9rem; width: 2.6rem; font-size: 0.72rem; }
}

/* Dunkles Design: kräftigeres Petrol mit weniger Orange-Schleier, sonst
   verschwimmt der Banner mit dem dunklen Seitenhintergrund (Olivstich). */
[data-bs-theme="dark"] .dash-greet-hero {
    background:
        radial-gradient(circle at 92% -30%, rgba(247, 154, 31, 0.22), rgba(241, 135, 0, 0.06) 28%, transparent 45%),
        linear-gradient(150deg, #0d3640, #124a54 60%, #17545f);
    border: 1px solid var(--fwg-border);
}

/* Portal-Hintergrund: statt flacher Fläche zwei sehr dezente Farb-Glows
   (Orange oben rechts, Petrol oben links) — hell wie dunkel über Token. */
body.portal {
    background:
        radial-gradient(58rem 30rem at 88% -6%, color-mix(in srgb, var(--fwg-orange) 7%, transparent), transparent 60%),
        radial-gradient(48rem 26rem at -8% -2%, color-mix(in srgb, #15606e 9%, transparent), transparent 55%),
        var(--fwg-bg);
    background-attachment: fixed;
}
/* Dunkel: Orange-Glow fast raus (wirkt sonst oliv), dafür mehr Petrol-Tiefe */
[data-bs-theme="dark"] body.portal {
    background:
        radial-gradient(58rem 30rem at 88% -6%, rgba(247, 154, 31, 0.05), transparent 60%),
        radial-gradient(48rem 26rem at -8% -2%, rgba(21, 96, 110, 0.3), transparent 55%),
        var(--fwg-bg);
    background-attachment: fixed;
}

/* Leerzustände (z. B. „keine Sitzung"): mittig, großes gedämpftes Icon */
.empty-state {
    text-align: center;
    padding: 1.6rem 0.5rem;
}
.empty-state .bi {
    display: block;
    font-size: 2rem;
    margin-bottom: 0.35rem;
    color: color-mix(in srgb, var(--bs-secondary-color) 55%, transparent);
}

/* Sanfte, gestaffelte Einblend-Animation für Karten-Raster (Dashboard, Hubs).
   Nur bei erlaubter Bewegung; ab dem 9. Element ohne Verzögerung. */
@media (prefers-reduced-motion: no-preference) {
    @keyframes fwg-rise {
        from { opacity: 0; transform: translateY(12px); }
        to { opacity: 1; transform: none; }
    }
    body.portal .row.g-4 > [class*="col"] {
        animation: fwg-rise 0.45s cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
    }
    body.portal .row.g-4 > [class*="col"]:nth-child(2) { animation-delay: 0.05s; }
    body.portal .row.g-4 > [class*="col"]:nth-child(3) { animation-delay: 0.10s; }
    body.portal .row.g-4 > [class*="col"]:nth-child(4) { animation-delay: 0.15s; }
    body.portal .row.g-4 > [class*="col"]:nth-child(5) { animation-delay: 0.20s; }
    body.portal .row.g-4 > [class*="col"]:nth-child(6) { animation-delay: 0.25s; }
    body.portal .row.g-4 > [class*="col"]:nth-child(7) { animation-delay: 0.30s; }
    body.portal .row.g-4 > [class*="col"]:nth-child(8) { animation-delay: 0.35s; }
}

/* Sekundär-Buttons („Zum Kalender", „Alle ansehen" …) als ruhige Ghost-Buttons
   in den Oberflächen-Tokens statt Bootstrap-Grau — hell wie dunkel stimmig. */
body.portal .btn-outline-secondary {
    --bs-btn-color: var(--fwg-ink);
    --bs-btn-border-color: var(--fwg-border);
    --bs-btn-bg: transparent;
    --bs-btn-hover-color: var(--fwg-ink);
    --bs-btn-hover-bg: var(--fwg-surface-2);
    --bs-btn-hover-border-color: var(--fwg-border);
    --bs-btn-active-color: var(--fwg-ink);
    --bs-btn-active-bg: var(--fwg-surface-2);
    --bs-btn-active-border-color: var(--fwg-border);
}
body.portal .dash-hero .btn-outline-secondary {
    --bs-btn-color: #fff;
    --bs-btn-border-color: rgba(255, 255, 255, 0.45);
    --bs-btn-hover-bg: rgba(255, 255, 255, 0.12);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-border-color: rgba(255, 255, 255, 0.6);
}

/* Listenzeilen in Karten: beim Überfahren dezent einrücken + orange tönen */
body.portal .list-group-item-action {
    transition: background-color 0.15s ease, padding-left 0.18s ease;
}
body.portal .list-group-item-action.px-0:hover {
    padding-left: 0.45rem !important; /* px-0 ist ein !important-Utility */
    background-color: color-mix(in srgb, var(--fwg-orange) 6%, transparent);
}

/* ---- Scroll-Reveal (öffentliche Seite, scroll-reveal.js) -------------------
   Die Klassen vergibt erst das Skript — ohne JS ist alles sofort sichtbar.
   Das Thema „Motion" (theme-motion.css) verstärkt die Bewegung. */
.sr {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 0.55s ease, transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
    transition-delay: var(--sr-delay, 0ms);
}
.sr-in {
    opacity: 1;
    transform: none;
}
@media (prefers-reduced-motion: reduce) {
    .sr { opacity: 1; transform: none; transition: none; }
}

/* ---- Amts-Postfach (IMAP-Ansicht) -----------------------------------------
   Ungelesene Zeilen kräftiger, und der Mail-Inhalt wird in .mail-body
   eingesperrt: fremdes HTML soll das Portal-Layout nicht sprengen (breite
   Tabellen scrollen in sich, Bilder skalieren mit). */
.mail-list .mail-unread {
    font-weight: 600;
    background-color: color-mix(in srgb, var(--fwg-orange) 5%, transparent);
}
.mail-body {
    overflow-x: auto;
    word-break: break-word;
    overflow-wrap: break-word;
}
.mail-body img {
    max-width: 100%;
    height: auto;
}
.mail-body table {
    max-width: 100%;
}
.mail-body blockquote {
    border-left: 3px solid var(--bs-border-color);
    padding-left: 0.9rem;
    margin-left: 0;
    color: var(--bs-secondary-color);
}
/* Aktiver Ordner in Vereinsfarbe statt Bootstrap-Blau */
.mail-folders .list-group-item.active {
    background-color: var(--fwg-orange);
    border-color: var(--fwg-orange);
    color: #fff;
}

/* Zurückgehaltene externe Bilder: Platzhalter statt Lücke */
.mail-body img[data-remote-src] {
    min-width: 2rem;
    min-height: 2rem;
    border: 1px dashed var(--bs-border-color);
    border-radius: 0.35rem;
}

/* Vorschauzeile in der Nachrichtenliste (erste Zeilen der Mail) */
.mail-preview {
    color: var(--bs-secondary-color);
    font-weight: 400;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
@media (max-width: 991.98px) {
    .mail-preview { -webkit-line-clamp: 2; }
}

/* Anhang-Knöpfe: lange Dateinamen dürfen die Zeile nicht sprengen */
.mail-attachment {
    max-width: min(100%, 18rem);
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}
.mail-attachment .mail-attachment-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---- Postfach am Handy: App-Bildschirm ------------------------------------
   Gleiches Muster wie der Chat (.chat-screen): Der Bereich füllt mobil die
   Fläche zwischen Navbar und Tab-Leiste, es scrollt nur EIN Kind (Liste,
   Mail-Text bzw. Editor) — Kopfzeile und Aktionen bleiben stehen. --app-vh
   (visualViewport, also Tastatur-bewusst) und body.typing setzt tabbar.js
   bereits global; hier wird nur die Höhe daraus abgeleitet. Desktop bleibt
   unverändert das normale Seiten-Layout. */
@media (max-width: 991.98px) {
    body:has(.mail-screen) > .container-fluid.flex-grow-1 { padding-bottom: 0 !important; }
    body:has(.mail-screen) .col-12.col-lg-10 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; }
    .mail-screen {
        display: flex;
        flex-direction: column;
        /* Platz für die schwebende Tab-Leiste (inkl. Home-Indikator). Die
           Oberkante wird gemessen (--mail-top, tabbar.js), nicht geraten:
           darüber können Banner, Meldungen oder der „Ansicht als"-Balken
           stehen — mit einer festen Rechnung würde die Seite zusätzlich zur
           Liste scrollen. Fallback ohne JS: Navbar + Tab-Leiste. */
        --mail-bottom: calc(78px + max(1.5rem, env(safe-area-inset-bottom, 0px)));
        height: calc(var(--app-vh, 100dvh) - var(--mail-top, 132px) - var(--mail-bottom));
        transition: height 0.15s ease;
    }
    /* Tastatur offen: die Tab-Leiste ist weg, also mehr Platz */
    body.typing .mail-screen { --mail-bottom: 22px; }
    .mail-screen .mail-scroll {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    .mail-screen .mail-fixed { flex: 0 0 auto; }
    .mail-screen .card { max-width: none; }

    /* Schreiben: Editor füllt den Rest der Höhe statt fester Zeilenzahl.
       min-height sorgt dafür, dass immer eine brauchbare Schreibfläche bleibt —
       vorher schrumpfte er zwischen Kopfzeilen und Anhang-Block auf ~1 Zeile. */
    .mail-screen .mail-editor { display: flex; flex-direction: column; min-height: 11rem; flex: 1 1 auto; }
    .mail-screen .mail-editor .ql-container { flex: 1 1 auto; min-height: 8rem; overflow-y: auto; }
    .mail-screen .mail-editor .ql-editor { min-height: 0; }
    /* Werkzeugleiste kompakt halten — sie fraß zwei Zeilen der Schreibfläche */
    .mail-screen .mail-editor .ql-toolbar { padding: 0.25rem 0.35rem; }
    .mail-screen .mail-editor .ql-toolbar button { width: 26px; height: 24px; padding: 2px; }
    .mail-screen .mail-editor .ql-toolbar .ql-picker-label { padding-inline: 2px; }

    /* SCHREIBEN ist bewusst KEIN App-Bildschirm (Fund Dominik 08/2026).
       Die Rechnung `--app-vh − --mail-top` funktioniert nur, solange die Seite
       NICHT scrollt: --mail-top ist eine Dokument-Koordinate (Muster Chat, gegen
       die Rückkopplungs-Schleife) und enthält damit Navbar, „Ansicht als"-Balken
       und Meldungen — auch dann noch, wenn iOS sie beim Öffnen der Tastatur aus
       dem Bild geschoben hat. Von der ohnehin geschrumpften Tastatur-Höhe blieb
       so ein Stummel übrig: Beim Tippen im Betreff verschwand das Schreibfeld
       ganz, darunter klaffte eine leere Fläche.
       Ein Formular braucht das Modell auch gar nicht — es SOLL scrollen, damit
       man an alle Felder kommt. Nur „Senden" bleibt griffbereit und klebt unter
       der Navbar (Höhe misst tabbar.js als --navbar-h). */
    .mail-screen.mail-compose {
        display: block;
        height: auto;
    }
    .mail-screen.mail-compose .mail-scroll { overflow: visible; }
    .mail-screen.mail-compose .mail-compose-bar {
        position: sticky;
        top: var(--navbar-h, 56px);
        z-index: 1020;
        padding: 0.4rem 0;
        margin-bottom: 0.25rem !important;
        background: var(--fwg-bg, var(--bs-body-bg));
    }
    /* Ohne feste Bildschirmhöhe darf der Editor wieder frei wachsen */
    .mail-screen.mail-compose .mail-editor { display: block; min-height: 0; }
    .mail-screen.mail-compose .mail-editor .ql-container { min-height: 11rem; }

    /* Schwebender Schreib-Knopf über der Tab-Leiste (wie in Mail-Apps) */
    .mail-fab {
        position: fixed;
        right: 1rem;
        bottom: calc(96px + max(1.5rem, env(safe-area-inset-bottom, 0px)));
        z-index: 1030;
        width: 3.25rem;
        height: 3.25rem;
        border-radius: 50%;
        display: grid;
        place-items: center;
        font-size: 1.35rem;
        box-shadow: var(--fwg-shadow-lg, 0 8px 24px rgba(0, 0, 0, 0.25));
    }
    body.typing .mail-fab { display: none; }
}

/* ---- Mail schreiben: Empfänger als Kacheln + kompakte Zeilen ---------------
   Eine Zeile = schmales Label links, Feld rechts (Mail-App-Konvention). Am
   Handy sparte das gegenüber gestapelten Labels mehrere Zeilen Höhe — die
   fehlten vorher dem Editor. */
.mail-row {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.35rem 0;
    border-bottom: 1px solid var(--fwg-border);
}
.mail-row-label {
    flex: 0 0 3.2rem;
    padding-top: 0.35rem;
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
}
.mail-row > .form-control {
    border: 0;
    padding-inline: 0.25rem;
    background: transparent;
}
.mail-row > .form-control:focus { box-shadow: none; }

/* Empfänger-Feld: Chips + Tippfeld teilen sich eine umbrechende Fläche */
.rcpt-box {
    flex: 1 1 auto;
    min-width: 0;
    position: relative;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0;
    cursor: text;
}
.rcpt-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    max-width: 100%;
    padding: 0.15rem 0.25rem 0.15rem 0.6rem;
    border-radius: var(--fwg-radius-pill, 999px);
    background: color-mix(in srgb, var(--fwg-petrol, #0090ab) 16%, var(--fwg-surface) 84%);
    border: 1px solid color-mix(in srgb, var(--fwg-petrol, #0090ab) 35%, transparent);
    font-size: 0.85rem;
    line-height: 1.35;
}
.rcpt-chip > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.rcpt-chip.is-invalid {
    background: color-mix(in srgb, var(--bs-danger, #dc3545) 14%, var(--fwg-surface) 86%);
    border-color: color-mix(in srgb, var(--bs-danger, #dc3545) 45%, transparent);
}
.rcpt-x {
    border: 0;
    background: transparent;
    color: inherit;
    opacity: 0.65;
    font-size: 1.05rem;
    line-height: 1;
    padding: 0 0.25rem;
    border-radius: 50%;
}
.rcpt-x:hover, .rcpt-x:focus-visible { opacity: 1; background: rgba(0, 0, 0, 0.12); }
.rcpt-input {
    flex: 1 1 6rem;
    min-width: 6rem;
    border: 0;
    outline: 0;
    background: transparent;
    color: inherit;
    padding: 0.3rem 0.15rem;
    font-size: 0.95rem;
}
/* iOS/Safari malen ein Feld, das sie für eine Kontakt-/Mailadresse halten,
   kräftig GELB („AutoFill"-Markierung, Fund Dominik 08/2026) — im dunklen
   Portal ein leuchtender Fremdkörper. Das Angebot selbst ist nützlich und
   bleibt; nur die Farbe wird auf die Themenfarben gezwungen. Der Umweg über
   einen riesigen inneren Schatten ist nötig, weil background-color bei
   :-webkit-autofill ignoriert wird. Gilt auch für die übrigen Adressfelder
   des Adressbuchs. */
.rcpt-input:-webkit-autofill,
.rcpt-input:-webkit-autofill:hover,
.rcpt-input:-webkit-autofill:focus,
.mail-row .form-control:-webkit-autofill,
.mail-row .form-control:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--bs-body-color);
    -webkit-box-shadow: 0 0 0 100vmax var(--fwg-surface, var(--bs-body-bg)) inset;
    box-shadow: 0 0 0 100vmax var(--fwg-surface, var(--bs-body-bg)) inset;
    caret-color: var(--bs-body-color);
    transition: background-color 9999s ease-out 0s; /* Safari-Klassiker: Farbe nie einblenden */
}
/* Vorschlagsliste (bereits genutzte Adressen, Mitglieder, Freunde & Helfer) */
.rcpt-menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1040;
    max-height: 15rem;
    overflow-y: auto;
    background: var(--fwg-surface);
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius-sm, 0.5rem);
    box-shadow: var(--fwg-shadow-lg, 0 8px 24px rgba(0, 0, 0, 0.25));
}
.rcpt-option {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem;
    width: 100%;
    border: 0;
    background: transparent;
    color: inherit;
    text-align: left;
    padding: 0.45rem 0.6rem;
}
.rcpt-option + .rcpt-option { border-top: 1px solid var(--fwg-border); }
.rcpt-option:hover, .rcpt-option.is-active { background: var(--fwg-surface-2); }
.rcpt-option .rcpt-mail { font-size: 0.82rem; color: var(--bs-secondary-color); }
.rcpt-option .rcpt-src {
    margin-left: auto;
    font-size: 0.72rem;
    color: var(--bs-secondary-color);
    white-space: nowrap;
}
/* CC/BCC-Aufklapper */
.mail-more > summary {
    cursor: pointer;
    font-size: 0.85rem;
    color: var(--bs-secondary-color);
    padding: 0.4rem 0;
    list-style: none;
}
.mail-more > summary::-webkit-details-marker { display: none; }
.mail-more > summary::before { content: '⌄ '; }
.mail-more[open] > summary::before { content: '⌃ '; }

/* Der Editor bekommt eine echte Schreibfläche (vorher sah man ~1 Zeile) */
.mail-editor { margin-top: 0.75rem; }
.mail-editor .ql-container { min-height: 14rem; }
.mail-editor .ql-editor { min-height: 14rem; }

/* Kopfzeile beim Schreiben klebt oben — „Senden" ist immer erreichbar,
   ohne an Empfänger, Betreff und Editor vorbeizuscrollen. */
.mail-compose-bar {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--bs-body-bg);
    padding-block: 0.5rem;
}

/* ---- Veranstaltungs-Planung ------------------------------------------------
   Jede Position ist am Desktop eine Zeile und auf dem Handy ein Block — die
   Listen werden unterwegs gepflegt (Einkauf im Laden, Verkaufszahlen am Stand),
   deshalb keine gequetschte Tabelle.
   Jede Position ist dabei ein abgesetzter Block: eine Liste aus lauter
   Eingabefeldern verschwimmt sonst zu einer Wand — besonders im Dark-Modus, wo
   eine dünne Trennlinie praktisch unsichtbar ist. Gleiches Muster wie die
   Zeilen-Karten von .table-cards, nur eine Ebene höher: hier liegt der Block IN
   einer Karte, deshalb die hellere Flächenfarbe surface-2 (hell wie dunkel
   abgesetzt). */
.plan-row {
    background: var(--fwg-surface-2);
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius-sm);
    padding: 0.7rem 0.85rem;
    margin-bottom: 0.6rem;
}
.plan-row:last-child { margin-bottom: 0; }
.plan-row.plan-done { opacity: 0.6; }
.plan-row.plan-done input[name="shop_label[]"] { text-decoration: line-through; }

/* ---- Admin-Einstellungen: Kategorien-Reiter --------------------------------
   Die Seite war ein langer Wolf aus einem Dutzend Gruppen; die Reiter zeigen
   pro Kategorie nur ihre Karten (ohne JS/unter Webdriver: alles klassisch
   untereinander). Optik wie die .plan-jump-Chips, mobil seitlich scrollbar. */
.settings-tabs {
    display: flex;
    gap: 0.4rem;
    overflow-x: auto;
    flex-wrap: nowrap;
    padding-bottom: 0.25rem;
    scrollbar-width: none;
}
.settings-tabs::-webkit-scrollbar { display: none; }
.settings-tabs .settings-tab {
    white-space: nowrap;
    font-size: 0.85rem;
    padding: 0.45rem 0.75rem;
    cursor: pointer;
}
.settings-tabs .settings-tab.active {
    background: var(--fwg-orange, #f18700) !important;
    border-color: var(--fwg-orange, #f18700) !important;
    color: #fff !important;
}

/* Notizen-Brett: Quill-HTML kompakt in der Liste (kein Absatz-Nachlauf) */
.plan-note-text p:last-child,
.plan-note-text ul:last-child,
.plan-note-text ol:last-child { margin-bottom: 0; }

/* Aufklappbare Abschnitte: die Kopfzeile bleibt eine Karten-Kopfzeile */
.plan-section > summary {
    cursor: pointer;
    list-style: none;
    font-weight: 600;
}
.plan-section > summary::-webkit-details-marker { display: none; }
.plan-section > summary::after {
    content: "\F282"; /* bi-chevron-down */
    font-family: bootstrap-icons;
    margin-left: auto;
    padding-left: 0.5rem;
    font-weight: 400;
    opacity: 0.6;
    transition: transform 0.15s ease;
}
.plan-section[open] > summary::after { transform: rotate(180deg); }

/* „Speichern" bleibt beim Tippen in Reichweite, statt am Listenende zu warten.
   Der Hintergrund muss die KARTEN-Farbe sein (nicht die der Seite) — die Leiste
   klebt innerhalb der Karte, sonst schiebt sich beim Scrollen ein dunklerer
   Balken über den helleren Karteninhalt. */
.plan-bar {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--fwg-surface);
    padding-block: 0.4rem;
}
@media (max-width: 575.98px) {
    .plan-row { padding: 0.85rem 0; }
    .plan-jump { position: sticky; top: 0; z-index: 4; background: var(--bs-body-bg); padding-block: 0.35rem; }
}

/* ==========================================================================
   App-Feeling-Paket (07/2026): View Transitions, Wisch-Gesten, Blitzsuche,
   Chat-Reaktionen/-Zitate, Bild-Viewer, Micro-Interactions, Pull-to-Refresh
   ========================================================================== */

/* --- Flüssige Seitenübergänge (View Transitions API, MPA) ---------------
   Moderne Browser blenden ganze Seitenwechsel sanft über; alte ignorieren
   die Regeln einfach. Navbar, Sidebar und Tab-Leiste bekommen einen eigenen
   view-transition-name und bleiben dadurch beim Übergang stehen. */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: reduce) {
    @view-transition { navigation: none; }
}
@media (prefers-reduced-motion: no-preference) {
    ::view-transition-old(root) { animation: fwg-vt-out 90ms ease-out both; }
    ::view-transition-new(root) { animation: fwg-vt-in 170ms ease-out both; }
    @keyframes fwg-vt-out { to { opacity: 0; } }
    /* Reines Überblenden OHNE Versatz: die 7px Aufwärtsbewegung las sich beim
       Umschalten von Filtern/Seiten als „Zucken" der Überschrift (Wunsch
       Dominik 08/2026 — nicht wieder einbauen). */
    @keyframes fwg-vt-in  { from { opacity: 0; } }
}
.portal .navbar-fwg   { view-transition-name: fwg-navbar; }
.portal-sidebar       { view-transition-name: fwg-sidebar; }
.portal-tabbar        { view-transition-name: fwg-tabbar; }

/* --- Wisch-Gesten in Listen (Postfach, Benachrichtigungen) --------------
   swipe-actions.js verschiebt das Element per Touch; darunter liegt die
   farbige Aktionsfläche mit Icon. */
.swipe-wrap { position: relative; overflow: hidden; }
.swipe-under {
    position: absolute; inset: 0;
    display: flex; align-items: center;
    font-size: 1.25rem; color: #fff;
    padding-inline: 1.1rem;
    opacity: 0;
}
.swipe-under.left  { justify-content: flex-end; background: var(--bs-danger); }
.swipe-under.right { justify-content: flex-start; background: var(--bs-success); }
.swipe-under.visible { opacity: 1; }
.swipe-item { position: relative; z-index: 1; background: var(--bs-body-bg); touch-action: pan-y; }
.swipe-item.swiping { transition: none; }
.swipe-item.snap { transition: transform 0.18s ease-out; }
.swipe-item.swipe-leave { transition: transform 0.2s ease-in, opacity 0.2s ease-in; opacity: 0; }

/* --- Pull-to-Refresh (nur installierte App) ----------------------------- */
.ptr-indicator {
    position: fixed; top: calc(env(safe-area-inset-top, 0px) + 8px); left: 50%;
    width: 38px; height: 38px; margin-left: -19px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: var(--fwg-surface, var(--bs-body-bg));
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
    color: var(--fwg-orange, #f18700);
    font-size: 1.15rem;
    z-index: 2000;
    transform: translateY(-64px);
    transition: transform 0.15s ease-out;
    pointer-events: none;
}
.ptr-indicator .bi-arrow-repeat { transition: transform 0.1s linear; }
.ptr-indicator.spinning .bi-arrow-repeat { animation: fwg-spin 0.8s linear infinite; }
@keyframes fwg-spin { to { transform: rotate(360deg); } }

/* --- Blitzsuche: Inhalts-Treffer in der Befehlspalette ------------------ */
.cmdk-section {
    padding: 0.45rem 0.9rem 0.2rem;
    font-size: 0.72rem; font-weight: 600; letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}
.cmdk-item .cmdk-sub {
    display: block;
    font-size: 0.75rem;
    color: var(--bs-secondary-color);
    margin-top: 1px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cmdk-item .cmdk-main { min-width: 0; flex-grow: 1; }
.cmdk-loading { padding: 0.6rem 0.9rem; color: var(--bs-secondary-color); font-size: 0.85rem; }

/* --- Chat: Reaktionen, Zitat-Antworten, Aktions-Menü -------------------- */
.chat-reacts {
    display: flex; gap: 0.25rem; flex-wrap: wrap;
    margin-top: 0.2rem;
}
.chat-react {
    display: inline-flex; align-items: center; gap: 0.2rem;
    font-size: 0.78rem; line-height: 1;
    padding: 0.18rem 0.45rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--bs-body-color) 8%, var(--bs-body-bg));
    border: 1px solid var(--bs-border-color);
    cursor: pointer; user-select: none;
}
.chat-react.mine {
    border-color: var(--fwg-orange, #f18700);
    background: color-mix(in srgb, var(--fwg-orange, #f18700) 14%, var(--bs-body-bg));
}
.chat-react .cnt { font-size: 0.72rem; color: var(--bs-secondary-color); }
.chat-quote {
    display: block;
    border-left: 3px solid var(--fwg-orange, #f18700);
    background: color-mix(in srgb, var(--bs-body-color) 7%, transparent);
    border-radius: 0.4rem;
    padding: 0.3rem 0.5rem;
    margin-bottom: 0.3rem;
    font-size: 0.8rem;
    cursor: pointer;
    max-width: 100%;
}
.chat-quote .chat-quote-name { display: block; font-weight: 600; font-size: 0.72rem; color: var(--fwg-orange, #f18700); }
.chat-quote .chat-quote-text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; color: var(--bs-secondary-color); }
.chat-bubble.chat-flash { animation: fwg-chat-flash 1.2s ease-out; }
@keyframes fwg-chat-flash {
    0%, 45% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--fwg-orange, #f18700) 55%, transparent); }
    100% { box-shadow: none; }
}
/* Zitat-Vorschau über dem Eingabefeld */
.chat-replybar {
    display: flex; align-items: center; gap: 0.5rem;
    border-left: 3px solid var(--fwg-orange, #f18700);
    background: color-mix(in srgb, var(--bs-body-color) 6%, transparent);
    border-radius: 0.4rem;
    padding: 0.3rem 0.5rem;
    margin-top: 0.5rem;
    font-size: 0.8rem;
}
.chat-replybar .grow { min-width: 0; flex-grow: 1; }
.chat-replybar .chat-quote-text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Aktions-Menü (langes Drücken auf eine Nachricht) */
.chat-actionbar {
    position: absolute;
    z-index: 30;
    display: flex; align-items: center; gap: 0.15rem;
    background: var(--fwg-surface, var(--bs-body-bg));
    border: 1px solid var(--bs-border-color);
    border-radius: 999px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22);
    padding: 0.2rem 0.35rem;
    animation: fwg-pop-in 0.14s ease-out;
}
@keyframes fwg-pop-in { from { opacity: 0; transform: scale(0.85); } }
.chat-actionbar button {
    border: 0; background: none;
    font-size: 1.15rem; line-height: 1;
    padding: 0.3rem 0.4rem;
    border-radius: 50%;
    cursor: pointer;
    color: var(--bs-body-color);
}
.chat-actionbar button:hover { background: color-mix(in srgb, var(--bs-body-color) 10%, transparent); }
.chat-actionbar button.danger { color: var(--bs-danger); }
.chat-swipe-hint { transition: transform 0.15s ease-out; }

/* --- Bild-Viewer (Chat-Fotos): Vollbild, Wischen, Pinch-Zoom ------------ */
.imgv-overlay {
    position: fixed; inset: 0; z-index: 3000;
    background: rgba(8, 12, 16, 0.94);
    display: flex; align-items: center; justify-content: center;
    touch-action: none;
    animation: fwg-fade-in 0.15s ease-out;
}
@keyframes fwg-fade-in { from { opacity: 0; } }
.imgv-stage { position: absolute; inset: 0; overflow: hidden; display: flex; align-items: center; justify-content: center; }
.imgv-stage img {
    max-width: 100%; max-height: 100%;
    user-select: none; -webkit-user-drag: none;
    will-change: transform;
}
.imgv-close, .imgv-prev, .imgv-next {
    position: absolute; z-index: 2;
    border: 0; border-radius: 50%;
    width: 42px; height: 42px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(255, 255, 255, 0.12);
    color: #fff; font-size: 1.3rem;
    cursor: pointer;
}
.imgv-close { top: calc(env(safe-area-inset-top, 0px) + 12px); right: 12px; }
.imgv-prev { left: 10px; top: 50%; transform: translateY(-50%); }
.imgv-next { right: 10px; top: 50%; transform: translateY(-50%); }
.imgv-count {
    position: absolute; top: calc(env(safe-area-inset-top, 0px) + 20px); left: 50%;
    transform: translateX(-50%);
    color: rgba(255, 255, 255, 0.85); font-size: 0.85rem;
    z-index: 2;
}
@media (max-width: 991.98px) { .imgv-prev, .imgv-next { display: none; } }

/* --- Micro-Interactions -------------------------------------------------- */
/* Glocke klingelt kurz bei neuer Benachrichtigung (realtime notify) */
@media (prefers-reduced-motion: no-preference) {
    #nav-bell .bi-bell.bell-ring { animation: fwg-bell-ring 0.9s ease-in-out; transform-origin: top center; display: inline-block; }
    @keyframes fwg-bell-ring {
        0% { transform: rotate(0); }
        15% { transform: rotate(18deg); }
        30% { transform: rotate(-14deg); }
        45% { transform: rotate(9deg); }
        60% { transform: rotate(-6deg); }
        75% { transform: rotate(3deg); }
        100% { transform: rotate(0); }
    }
    /* Häkchen-„Pop" beim Abhaken (Aufgaben, Einkaufsliste …) */
    .form-check-input:checked { animation: fwg-check-pop 0.25s ease-out; }
    @keyframes fwg-check-pop {
        0% { transform: scale(0.8); }
        55% { transform: scale(1.15); }
        100% { transform: scale(1); }
    }
}
/* Leerzustände: Icon in getönter Scheibe + freundlicher Zweizeiler */
.empty-state .empty-ico {
    display: inline-flex; align-items: center; justify-content: center;
    width: 3.4rem; height: 3.4rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--fwg-orange, #f18700) 12%, transparent);
    margin-bottom: 0.55rem;
}
.empty-state .empty-ico .bi {
    display: block; font-size: 1.5rem; margin: 0;
    color: var(--fwg-orange, #f18700);
}
.empty-state .empty-title { font-weight: 600; margin-bottom: 0.15rem; }
.empty-state .empty-text { color: var(--bs-secondary-color); font-size: 0.9rem; margin: 0 auto; max-width: 30rem; }
.chat-row.justify-content-end .chat-reacts { justify-content: flex-end; }

/* ==========================================================================
   Politur-Paket (Inspiration React Bits, 08/2026): Hero-Text-Reveal +
   Claim-Schimmer, Aurora-Glow, Masonry-Galerie.
   Alles in reinem CSS/Vanilla-JS nachgebaut (kein React, kein CDN) und mit
   prefers-reduced-motion-Wachen.
   (Die früheren Spotlight-Karten — maus-folgender Lichtschein auf Karten —
   wurden auf Dominiks Wunsch wieder entfernt: „zu viel des Guten"; der
   Hover-Lift der Karten bleibt.)
   ========================================================================== */

/* --- Aurora-Glow: zwei langsam wandernde Farbnebel (Orange + Petrol) hinter
   den Hero-Bereichen. Reines CSS; reduced-motion hält sie still. --- */
.fwg-aurora {
    position: absolute;
    inset: -30%;
    pointer-events: none;
    filter: blur(42px);
    opacity: 0.5;
    background:
        radial-gradient(30rem 17rem at 22% 32%, rgba(247, 154, 31, 0.4), transparent 62%),
        radial-gradient(34rem 20rem at 78% 62%, rgba(32, 156, 178, 0.45), transparent 62%),
        radial-gradient(24rem 14rem at 55% 88%, rgba(255, 178, 84, 0.22), transparent 60%);
}
@media (prefers-reduced-motion: no-preference) {
    .fwg-aurora { animation: fwg-aurora 22s ease-in-out infinite alternate; }
    @keyframes fwg-aurora {
        from { transform: translate3d(-3.5%, -2%, 0) rotate(-2deg) scale(1); }
        to   { transform: translate3d(3.5%, 2.5%, 0) rotate(2deg) scale(1.07); }
    }
}
/* Dashboard-Hero: Kinder über die Aurora heben (Ausnahme: absolut liegende
   Ebenen wie .season-layer, die ihre Positionierung behalten müssen) */
.dash-greet-hero { position: relative; overflow: hidden; }
.dash-greet-hero > :not(.fwg-aurora):not(.season-layer) { position: relative; z-index: 1; }
.dash-greet-hero .fwg-aurora { opacity: 0.4; }

/* Hero-Text-Reveal (hero-reveal.js) wurde 08/2026 ENTFERNT: das Skript zerlegte
   die bereits gezeichnete Überschrift in Wörter und blendete sie neu ein — bei
   JEDEM Seitenaufruf ein sichtbares Zucken. Nicht wieder einbauen. */

/* --- Claim-Schimmer: alle paar Sekunden läuft ein feiner Glanz über die
   „Stark für Naila!"-Pille im Hero. --- */
@media (prefers-reduced-motion: no-preference) {
    .hero .motto { position: relative; overflow: hidden; }
    .hero .motto::after {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, 0.28) 50%, transparent 58%);
        transform: translateX(-130%);
        animation: fwg-shine 6s ease-in-out 1.4s infinite;
        pointer-events: none;
    }
    @keyframes fwg-shine {
        0% { transform: translateX(-130%); }
        30% { transform: translateX(130%); }
        100% { transform: translateX(130%); }
    }
}

/* --- Masonry-Galerie (öffentliche Galerie): versetzte Foto-Spalten in
   natürlichen Bildhöhen statt gleich geschnittener 4:3-Kacheln. --- */
.masonry { columns: 2; column-gap: 0.75rem; }
@media (min-width: 768px) { .masonry { columns: 3; } }
@media (min-width: 992px) { .masonry { columns: 4; } }
.masonry .masonry-item {
    display: block;
    break-inside: avoid;
    margin-bottom: 0.75rem;
    text-decoration: none;
}
.masonry .masonry-item img {
    width: 100%;
    display: block;
    border-radius: var(--fwg-radius-sm);
    box-shadow: var(--fwg-shadow-sm, 0 1px 4px rgba(0, 0, 0, 0.12));
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
@media (hover: hover) {
    .masonry .masonry-item:hover img {
        transform: scale(1.015);
        box-shadow: var(--fwg-shadow, 0 6px 18px rgba(0, 0, 0, 0.18));
    }
}
.masonry .masonry-caption { line-height: 1.3; }

/* --- Mehrschritt-Formulare (form-stepper.js): Kopf mit Punkten + Schritte --- */
.form-step { border: 0; padding: 0; margin: 0; min-width: 0; }
.form-step > legend {
    float: none;
    width: auto;
    font-size: 1rem;
    font-weight: 700;
    margin-bottom: 0.6rem;
}
/* Der Assistent greift NUR mit JavaScript (html.js wird im <head> gesetzt,
   vor dem ersten Zeichnen — deshalb springt nichts). Ohne JS bleiben alle
   Abschnitte sichtbar und Kopfzeile/Weiter-Knöpfe verschwinden: man käme
   sonst nie über Schritt 1 hinaus. Gilt auch unter Playwright. */
html:not(.js) .stepper-head,
html:not(.js) .stepper-nav { display: none; }
html.js form[data-stepper] .form-step > legend { display: none; } /* Titel steht im Kopf */
html.js .form-step.step-hidden { display: none; }
.stepper-head {
    list-style: none;
    display: flex;
    padding: 0;
    margin: 0 0 1.25rem;
}
.stepper-head li {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    position: relative;
    color: var(--bs-secondary-color);
    font-size: 0.78rem;
    font-weight: 600;
    text-align: center;
}
/* Verbindungslinie zwischen den Punkten */
.stepper-head li + li::before {
    content: "";
    position: absolute;
    top: 0.85rem;
    right: 50%;
    width: 100%;
    height: 2px;
    background: var(--bs-border-color);
    z-index: 0;
}
.stepper-head li.done + li::before { background: var(--fwg-orange, #f18700); }
.step-dot {
    width: 1.7rem;
    height: 1.7rem;
    border-radius: 50%;
    border: 2px solid var(--bs-border-color);
    display: grid;
    place-items: center;
    background: var(--bs-body-bg);
    font-size: 0.8rem;
    font-weight: 700;
    position: relative;
    z-index: 1;
}
.stepper-head li.active { color: var(--fwg-orange-dark, #c96e00); }
.stepper-head li.active .step-dot {
    border-color: var(--fwg-orange, #f18700);
    background: var(--fwg-orange, #f18700);
    color: #fff;
}
.stepper-head li.done { cursor: pointer; }
.stepper-head li.done .step-dot {
    border-color: var(--fwg-orange, #f18700);
    color: var(--fwg-orange-dark, #c96e00);
}

/* --- Rotierender Begriff im Hero (rotate-text.js) --- */
.hero .hero-rotate { font-weight: 600; }
.hero .rotate-words { color: #ffc06a; font-weight: 800; }
.rotate-words.rotate-live {
    display: inline-block;
    transition: opacity 0.32s ease, transform 0.32s ease;
}
.rotate-words.rotate-live.out {
    opacity: 0;
    transform: translateY(0.4em);
}

/* --- Click-Spark (click-spark.js): Funken-Burst an der Klickstelle --- */
.click-spark {
    position: fixed;
    z-index: 4000;
    width: 0;
    height: 0;
    pointer-events: none;
}
.click-spark i {
    position: absolute;
    left: -2px;
    top: -5px;
    width: 4px;
    height: 10px;
    border-radius: 2px;
    background: var(--fwg-orange, #f18700);
    transform-origin: 2px 5px;
    transform: rotate(var(--sa)) translateY(-8px);
    animation: fwg-spark 0.55s ease-out forwards;
}
@keyframes fwg-spark {
    to {
        transform: rotate(var(--sa)) translateY(-28px) scale(0.3);
        opacity: 0;
    }
}
/* Schritt-Fieldsets im Kassenbuch: display:contents lässt die Spalten ohne
   Schalter exakt wie bisher im Formular-Grid fließen; der aktive Stepper
   blendet sie schrittweise ein (step-hidden = display:none gewinnt). */
.d-contents { display: contents; }
.row > .stepper-head,
.row > .stepper-nav {
    flex: 0 0 100%;
    max-width: 100%;
}

/* --- Mitfliegende Speichern-Leiste (save-bar.js, Einstellungs-Formulare) --- */
.save-bar {
    position: fixed;
    left: 50%;
    transform: translate(-50%, 120%);
    bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
    z-index: 1500;
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 0.55rem 0.7rem 0.55rem 1rem;
    border-radius: var(--fwg-radius-pill);
    background: color-mix(in srgb, var(--fwg-surface, var(--bs-body-bg)) 75%, transparent);
    backdrop-filter: blur(20px) saturate(1.6);
    -webkit-backdrop-filter: blur(20px) saturate(1.6);
    border: 1px solid var(--fwg-border, var(--bs-border-color));
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.35);
    transition: transform 0.25s ease;
    max-width: calc(100vw - 1.5rem);
}
.save-bar.show { transform: translate(-50%, 0); }
.save-bar .save-bar-text {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
    white-space: nowrap;
}
@media (max-width: 991.98px) {
    /* über der mobilen Tab-Leiste schweben */
    .save-bar { bottom: calc(var(--tabbar-h, 60px) + max(1.5rem, env(safe-area-inset-bottom, 0px)) + 12px); }
}
/* Tastatur offen (body.typing, gesetzt in tabbar.js): auf Touch-Geräten
   ausblenden — iOS verschiebt den sichtbaren Bereich unter der Tastatur und
   „fixed" klebt dann mitten im Inhalt statt unten. Muster Tab-Leiste; nach dem
   Schließen der Tastatur schwebt die Leiste wieder ein. Desktop unberührt. */
@media (pointer: coarse) {
    body.typing .save-bar,
    body.typing .save-bar.show {
        transform: translate(-50%, 160%);
        opacity: 0;
        pointer-events: none;
    }
    .save-bar { transition: transform 0.25s ease, opacity 0.2s ease; }
}

/* Automatisches Listen-Suchfeld (list-filter.js): über langen Tabellen/Listen.
   Eingeklappt ist es NUR eine Lupe (spart Höhe, besonders am Handy), ein Tipp
   klappt das Feld auf. Die Leiste klebt beim Scrollen oben — der Abstand zur
   Navbar kommt als --list-filter-top aus dem Skript. */
.list-filter-wrap {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-bottom: 0.35rem;
    position: sticky;
    top: var(--list-filter-top, 0.25rem);
    z-index: 3;
}
.list-filter-toggle {
    border: 0;
    background: transparent;
    color: var(--bs-secondary-color);
    padding: 0.2rem 0.45rem;
    border-radius: var(--fwg-radius-pill);
    line-height: 1;
    transition: color 0.15s ease, background-color 0.15s ease;
}
.list-filter-toggle:hover,
.list-filter-toggle:focus-visible {
    background: var(--fwg-surface-2);
    color: var(--fwg-ink);
}
.list-filter-wrap .list-filter {
    display: none;
    max-width: 320px;
}
.list-filter-wrap.is-open {
    background: var(--fwg-surface);
    border: 1px solid var(--fwg-border);
    border-radius: var(--fwg-radius-pill);
    padding: 0.25rem 0.4rem;
    box-shadow: var(--fwg-shadow);
}
.list-filter-wrap.is-open .list-filter { display: block; }
.list-filter-wrap.is-open .list-filter-toggle { color: var(--fwg-orange); }

/* Quill-Formate außerhalb des Editors (öffentliche Seite, Leseansichten,
   render_rich_text): Größen und Ausrichtung kommen als ql-*-Klassen */
.ql-size-small { font-size: 0.8em; }
.ql-size-large { font-size: 1.4em; }
.ql-size-huge  { font-size: 2em; }
.ql-align-center  { text-align: center; }
.ql-align-right   { text-align: right; }
.ql-align-justify { text-align: justify; }

/* Wahl-Countdown-Banner auf der Startseite (Wahljahr) */
.wahl-banner {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 1rem 1.25rem;
    border-radius: var(--fwg-radius, 1rem);
    background: linear-gradient(100deg, var(--fwg-petrol, #0090ab), var(--fwg-orange-dark, #e67823));
    color: #fff;
    text-decoration: none;
    box-shadow: var(--fwg-shadow-sm, 0 2px 10px rgba(0, 0, 0, .12));
}
.wahl-banner:hover { color: #fff; filter: brightness(1.05); }
.wahl-banner-ico { font-size: 1.8rem; line-height: 1; }
.wahl-banner-body { flex: 1 1 240px; }
.wahl-banner-body strong { display: block; font-size: 1.1rem; }
.wahl-banner-sub { opacity: .92; }
.wahl-banner-cta { white-space: nowrap; font-weight: 600; }

/* Wahlergebnis als Balken (kein Chart-Lib) */
.wahl-bar-row {
    display: grid;
    grid-template-columns: minmax(140px, 1fr) 3fr auto;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}
.wahl-bar-track {
    background: color-mix(in srgb, var(--bs-body-color) 10%, transparent);
    border-radius: 999px;
    height: 1.1rem;
    overflow: hidden;
}
.wahl-bar {
    height: 100%;
    border-radius: 999px;
    background: var(--fwg-petrol, #0090ab);
}
.wahl-bar.is-elected { background: var(--bs-success, #198754); }
.wahl-bar-value { font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 575.98px) {
    .wahl-bar-row { grid-template-columns: 1fr auto; }
    .wahl-bar-track { grid-column: 1 / -1; }
}
