/* ══════════════════════════════════════════════
   Schuhspiel Design System
   ══════════════════════════════════════════════ */

/* Display-Schrift (Fragen/Headlines, #113): Josefin Sans, serifenlos, OFL,
   lokal gehostet (kein Font-CDN → CSP font-src 'self'). Eine variable woff2
   (wght-Achse 100–700, latin-Subset inkl. ä/ö/ü/ß und „"), daher font-weight
   als Bereich – kein Faux-Bold bei den 600er-Frage-Headings. font-display:swap
   + size-adjust hält den Swap-Shift klein. Nur Display-Ebene; Fließtext bleibt
   system-ui. Lizenz: fonts/josefin-sans/OFL.txt. */
@font-face {
    font-family: "Josefin Sans";
    font-style: normal;
    font-weight: 100 700;
    font-display: swap;
    src: url("../fonts/josefin-sans/josefin-sans-latin.woff2") format("woff2");
    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;
    /* Josefin hat eine kleine x-Höhe → an system-ui-Fallbackmetriken angleichen,
       damit der Wechsel Fallback→Josefin auf der Frage-Ansicht kaum springt. */
    size-adjust: 106%;
    ascent-override: 90%;
    descent-override: 22%;
}

:root {
    /* ── Backgrounds ── */
    --ss-bg:               #faf7f2;
    --ss-bg-soft:          #f5f0e9;
    --ss-bg-warm-highlight: rgba(255, 231, 184, 0.22);

    /* ── Surfaces ── */
    --ss-surface:          #ffffff;
    --ss-surface-strong:   #faf8f5;
    --ss-surface-muted:    #f3efe8;

    /* ── Borders ── */
    --ss-border:           #e4ddd3;
    --ss-border-light:     #ede8e0;

    /* ── Text ── */
    --ss-text:             #2c3642;
    --ss-text-secondary:   #5e6878;
    /* Kontrast-Audit (#175 P3.4): #8b95a3 erreichte auf den Glas-Karten nur ~2,8:1 und
       verfehlte WCAG 1.4.3 (AA) deutlich – jetzt ≥ 4,7:1 auf allen hellen Flächen. */
    --ss-muted:            #626b78;

    /* ── Primary (muted blue) ── */
    --ss-primary:          #3b6d9c;
    --ss-primary-hover:    #2d5a84;
    --ss-primary-soft:     #e8f0f8;
    --ss-primary-text:     #ffffff;

    /* ── Accent (champagne/gold) ── */
    --ss-accent:           #c4a265;
    --ss-accent-hover:     #b08e52;
    --ss-accent-soft:      rgba(196, 162, 101, 0.12);
    --ss-accent-ghost:     rgba(196, 162, 101, 0.5);  /* Ghost-Ziffern-Kontur (#114) */

    /* ── Semantic ── */
    --ss-success:          #3a8a5c;
    --ss-success-soft:     #e8f5ed;
    --ss-danger:           #c4493a;
    --ss-danger-soft:      #fdf0ee;
    --ss-warning:          #c49036;
    --ss-warning-soft:     #fef8ec;
    --ss-info:             #3b7ea8;
    --ss-info-soft:        #ebf4fa;

    /* ── Reaktions-Töne (#201) ──
       Bewusst keine neuen Farben: die vier Reaktionen greifen die bestehenden Semantikfarben
       auf, damit das Feature wie ein Teil der Marke wirkt und nicht wie ein Fremdkörper.
       --ss-reaction-caught ist der einzige eigene Wert: Gold trägt als Fläche, aber nicht als
       Text (siehe Kontrast-Audit unten), und die Balken tragen hier ihre Beschriftung. */
    --ss-reaction-sweet:     #c4493a;
    --ss-reaction-caught:    #a97e2f;
    --ss-reaction-surprising:#3b7ea8;
    --ss-reaction-unity:     #3a8a5c;

    /* ── Text-/Flächen-Varianten der Akzent- und Semantikfarben (Kontrast-Audit #175 P3.4) ──
       Champagner-Gold und das helle Warngelb tragen als *Fläche*, aber nicht als *Text*:
       Bootstraps .text-warning (#ffc107) kam auf 1,6:1, Gold als Schrift auf 3,1:1. Statt die
       Marken-Token zu verbiegen (sie sind als Hintergrund korrekt), gibt es eigene Token für
       Text, Icons und gefüllte Knöpfe. Alle ≥ 4,5:1 auf jeder hellen Fläche der Gast-Routen. */
    --ss-warning-text:     #8a5f16;
    --ss-success-text:     #2f7a4f;
    --ss-danger-text:      #b83f31;
    --ss-info-text:        #2b6c92;
    --ss-accent-text:      #7f6229;
    /* Gefüllter Gold-Knopf (Account-CTA): hell = tiefes Antikgold mit weißer Schrift. */
    --ss-accent-btn-bg:       #7f6229;
    --ss-accent-btn-bg-hover: #6d5323;
    --ss-accent-btn-text:     #ffffff;
    /* Countdown-Balken: als Grafik ≥ 3:1 gegen die Bahn (WCAG 1.4.11). */
    --ss-countdown-late:   #b8551a;

    /* ── Radii ── */
    --ss-radius-sm:        0.45rem;
    --ss-radius-md:        0.75rem;
    --ss-radius-lg:        1.15rem;

    /* ── Shadows ── */
    --ss-shadow-sm:        0 1px 3px rgba(45, 30, 15, 0.06), 0 1px 2px rgba(45, 30, 15, 0.04);
    --ss-shadow-md:        0 4px 16px rgba(45, 30, 15, 0.08), 0 1px 4px rgba(45, 30, 15, 0.04);
    --ss-shadow-lg:        0 12px 36px rgba(45, 30, 15, 0.12), 0 2px 8px rgba(45, 30, 15, 0.06);

    /* ── Focus ── */
    --ss-focus-ring:       0 0 0 0.18rem rgba(59, 109, 156, 0.35);

    /* ── Glass (frosted) – Rezeptur des Splash-Panels, zentral als Tokens.
       Fallbacks (kein backdrop-filter, prefers-reduced-transparency, Druck)
       laufen zentral über Token-Redefinition in Sektion 19 – Komponenten
       brauchen keine eigenen Fallback-Blöcke. ── */
    --ss-glass-blur:        9px;
    --ss-glass-blur-soft:   6px;
    --ss-glass-saturate:    110%;
    --ss-glass-filter:      blur(var(--ss-glass-blur)) saturate(var(--ss-glass-saturate));
    --ss-glass-filter-soft: blur(var(--ss-glass-blur-soft)) saturate(var(--ss-glass-saturate));
    --ss-glass-bg:          linear-gradient(165deg, rgba(255, 255, 255, 0.72) 0%, rgba(255, 255, 255, 0.48) 100%);
    --ss-glass-bg-fallback: rgba(255, 255, 255, 0.9);
    --ss-glass-border:      rgba(255, 255, 255, 0.62);
    --ss-glass-highlight:   inset 0 1px 0 rgba(255, 255, 255, 0.65);
    --ss-glass-shadow:      0 16px 40px rgba(58, 34, 16, 0.15);
    /* Helle Overlay-Fläche (Dropdown/Modal/Update-Chip) – hohe Deckung für Lesbarkeit */
    --ss-glass-surface:     rgba(255, 255, 255, 0.86);
    /* Dunkle Variante (Navbar/Update-Banner) auf Basis von --ss-nav-bg */
    --ss-glass-dark-bg:        rgba(44, 54, 66, 0.88);
    --ss-glass-dark-bg-accent: rgba(55, 69, 88, 0.88);

    /* ── Nav ── */
    --ss-nav-bg:           #2c3642;
    --ss-nav-text:         #c8cdd4;
    --ss-nav-active:       #ffffff;
    --ss-nav-hover:        #e8dcc8;

    /* ── Footer ── */
    --ss-footer-bg:        #2c3642;

    /* ── Display-Schrift (#113) ── */
    --ss-font-display:     "Josefin Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* ══════════════════════════════════════════════
   1. Typography & Base
   ══════════════════════════════════════════════ */

html, body {
    font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: var(--ss-text);
    background-color: var(--ss-bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    line-height: 1.6;
}

/* Subtle warm radial highlights on the body – mirrors Splash but much lighter */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: -1;
    background:
        radial-gradient(80% 50% at 5% 4%, rgba(255, 231, 184, 0.18) 0%, transparent 60%),
        radial-gradient(70% 45% at 92% 10%, rgba(255, 211, 156, 0.1) 0%, transparent 55%);
}

/* Hauchfeine Papierkorn-Textur (#114) als eigene Ebene über den Radials: eine
   einzige statische feTurbulence-SVG (Data-URI, CSP-safe via img-src data:) mit
   fest eingebackener Alpha-Slope ≈ 0.05, damit die Cremefläche „gedruckt" statt
   steril wirkt. Statische, gekachelte fixed-Ebene → kein GPU-Zuwachs beim
   Scrollen. Als separates ::after abschaltbar per display:none in Druck +
   prefers-reduced-transparency (Sektion 19), ohne die Radials zu duplizieren. */
body::after {
    content: "";
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: -1;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.05'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
    background-size: 160px 160px;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    color: var(--ss-text);
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.3;
}

h1:focus {
    outline: none;
}

/* Display-Ebene (#113): Fragen-Text und große Display-Zahlen heben sich mit der
   Josefin-Sans-Schrift vom system-ui-Fließtext ab. Bewusst NUR punktuell auf
   Frage-/Ergebnis-Elemente setzen (kleine Headings tragen Josefins niedrige
   x-Höhe schlecht). letter-spacing gleicht offen für die Display-Wirkung. */
.ss-display {
    font-family: var(--ss-font-display);
    letter-spacing: 0.005em;
}

/* Ghost-Ziffern (#114): riesige Outline-Ziffer in Akzent-Gold als Plakatmotiv
   hinter dem Inhalt. Rein dekorativ (aria-hidden + user-select:none am Element).
   `.ss-ghost-host` kapselt das Rezept: es klippt die Ziffer (overflow:hidden) und
   hebt jeden Nicht-Ghost-Inhalt automatisch über die Ziffer (z-index) – so bleibt
   der Vordergrund-Kontrast unberührt, ohne jedes Kind einzeln anzufassen. */
.ss-ghost-host {
    position: relative;
    overflow: hidden;
}

.ss-ghost-host > :not(.ss-ghost-number) {
    position: relative;
    z-index: 1;
}

.ss-ghost-number {
    position: absolute;
    top: 50%;
    right: 0.25em;
    transform: translateY(-50%);
    z-index: 0;
    margin: 0;
    font-family: var(--ss-font-display);
    font-weight: 700;
    line-height: 0.8;
    /* Deutlich kleiner als früher (war clamp(6rem, 22vw, 13rem)): auf 320 px reichte die
       Ziffer sonst bis über Prozentwert und Text (#330). */
    font-size: clamp(4rem, 18vw, 10rem);
    /* Outline-Gold; Füllung transparent. -webkit-text-fill-color (nicht color),
       damit die Stroke-Kontur sichtbar bleibt (Chromium, Safari, Firefox). */
    color: var(--ss-accent);
    -webkit-text-fill-color: transparent;
    -webkit-text-stroke: 2px var(--ss-accent-ghost);
    pointer-events: none;
    user-select: none;
}

/* Fallback ohne text-stroke: keine Kontur, sondern zart gefüllte Goldziffer. */
@supports not ((-webkit-text-stroke: 2px black)) {
    .ss-ghost-number {
        -webkit-text-fill-color: var(--ss-accent-soft);
        color: var(--ss-accent-soft);
    }
}

/* A+ (große Gastschrift): Der Vordergrundtext wächst, die dekorative Geisterziffer nicht –
   bei aktiver großer Schrift würde sie neben Prozentwert/Text eng. Dann ganz ausblenden;
   die Ergebniswerte bleiben unberührt (#330). */
html.ss-guest-lg .ss-ghost-number {
    display: none;
}

/* Eintritts-Reveal (Gäste): Karten/Elemente gleiten gestaffelt weich herein. Der
   Versatz kommt per inline `animation-delay` (GuestResultsView bei Ergebnis-Freigabe;
   Play.razor beim Phasen-/Neue-Frage-Eintritt, #140). `both` sorgt dafür, dass das
   Element während seiner Verzögerung noch unsichtbar bleibt. Bei reduzierter Bewegung
   greift der Guard unten (`animation: none`) → alles sofort und voll sichtbar; das
   inline `animation-delay` überschreibt nur den Delay, nicht den animation-name. */
.ss-reveal-item {
    animation: ss-reveal-in 0.55s ease-out both;
}

/* Der Endzustand hält die Ensemble-Neigung (#116) statt sie auf `none` zu setzen: das
   `both` des Fill-Modes friert den to-Zustand dauerhaft ein, und `transform: none` hat
   damit die rotate()-Neigung von `.ss-card-ensemble > .card` still überschrieben – die
   Ergebniskarten lagen schnurgerade statt „wie auf den Tisch gelegte Einladungen".
   Für alle Elemente außerhalb des Ensembles ist die Variable leer → 0deg → wie vorher. */
@keyframes ss-reveal-in {
    from {
        opacity: 0;
        transform: translateY(16px) rotate(var(--ss-ensemble-tilt, 0deg));
    }
    to {
        opacity: 1;
        transform: rotate(var(--ss-ensemble-tilt, 0deg));
    }
}

@media (prefers-reduced-motion: reduce) {
    .ss-reveal-item {
        animation: none;
    }
}

/* Reveal, der dem Blick folgt (#179): für Karten, die beim Freigeben der Ergebnisse
   unter der Falz liegen. `ss-reveal-item` würde seine Animation dort ungesehen
   verbrauchen – diese Karten ziehen stattdessen erst ein, wenn sie ins Sichtfeld
   scrollen. Den Takt gibt resultReveal.js (Verzögerung inline je Karte).

   Reihenfolge der Klassen ist Absicht:
     .ss-reveal-on-view  ist nur ein Marker und bleibt OHNE Wirkung sichtbar,
     .ss-reveal-armed    setzt JS – erst damit wird die Karte zurückgenommen,
     .ss-revealed        setzt der IntersectionObserver, wenn sie ins Bild kommt.
   Bleibt das Interop aus (JS-Fehler, kein IntersectionObserver), wird nie gespannt
   und die Ergebnisse stehen einfach unanimiert da. Eine Karte, die auf eine Animation
   wartet, die nie kommt, wäre der schlimmere Fehler. */
.ss-reveal-armed {
    opacity: 0;
}

.ss-reveal-armed.ss-revealed {
    animation: ss-reveal-in 0.65s ease-out both;
}

@media (prefers-reduced-motion: reduce) {
    .ss-reveal-armed {
        opacity: 1;
    }

    .ss-reveal-armed.ss-revealed {
        animation: none;
    }
}

/* ── Gemeinsames Bewegungs-Vokabular für die Gäste-Ansicht (#137) ──
   Vier Primitive: Eintritt (`ss-reveal-item`, oben), Bestätigung (`ss-confirm-pop`
   + Haken-Draw), Füllen (`ss-fill-bar`). Alle CSS-only, alle mit reduced-motion-
   Guard weiter unten. Bewusst zurückhaltend, da sich diese Momente jede Runde
   wiederholen. */

/* Press-Feedback beim Tippen einer Antwort – reaktiv auch bei langsamer Verbindung. */
.ss-press {
    transition: transform 0.1s ease;
}
.ss-press:active {
    transform: scale(0.97);
}

/* Bestätigung: die gewählte Person „poppt" sanft. Auch als verzögerter Stempel
   (`ss-stamp`) für das einig/uneinig-Badge im Zwischenstand genutzt. */
.ss-confirm-pop {
    animation: ss-confirm-pop 0.5s cubic-bezier(0.2, 0.7, 0.3, 1.2) both;
}
.ss-stamp {
    animation: ss-confirm-pop 0.55s cubic-bezier(0.2, 0.7, 0.3, 1.25) 0.6s both;
}

@keyframes ss-confirm-pop {
    0% {
        opacity: 0;
        transform: scale(0.82);
    }
    60% {
        opacity: 1;
        transform: scale(1.04);
    }
    100% {
        opacity: 1;
        transform: scale(1);
    }
}

/* Haken-Badge an der gewählten Person: der Kreis erscheint sofort, die Kontur
   zeichnet sich per stroke-dashoffset. Der 2px-Separations-Ring in Flächenfarbe
   trägt die Badge-Kante füllungs-unabhängig (#187-Folge): der Kreis darunter ist
   in jeder Palettenfarbe füllbar – inkl. „Grün", das mit dem Badge farbidentisch
   wäre (1,0:1). Ring ↔ Badge liegt konstant ≥ 4,5:1 (Tag wie Abend). */
.ss-confirm-check {
    position: absolute;
    top: -4px;
    right: -4px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--bs-success, #198754);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 0 2px var(--ss-surface), 0 1px 3px rgba(0, 0, 0, 0.25);
}
.ss-confirm-check svg {
    width: 15px;
    height: 15px;
}
.ss-confirm-check path {
    fill: none;
    stroke: #fff;
    stroke-width: 3;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 20;
    stroke-dashoffset: 20;
    animation: ss-check-draw 0.35s ease-out 0.25s forwards;
}

@keyframes ss-check-draw {
    to {
        stroke-dashoffset: 0;
    }
}

/* Füllen: Stimmen-Balken wachsen von 0 auf ihre Zielbreite. Die Zielbreite kommt
   als `--ss-fill-w` per inline-Style; die Basisregel setzt sie auch als Endwert,
   damit ohne Animation (reduced motion) direkt die volle Breite steht. */
.ss-fill-bar {
    width: var(--ss-fill-w, 0);
    animation: ss-fill 0.85s ease-out both;
}

@keyframes ss-fill {
    from {
        width: 0;
    }
    to {
        width: var(--ss-fill-w, 0);
    }
}

/* ── Tier-3 Feinschliff-Momente (#141) ──
   Kleine, bewusst zurückhaltende Politur-Effekte über die Gäste-Reise. „Feiern"
   (aufsteigende Herzen) bleibt exklusiv dem End-Ergebnis vorbehalten. Alle CSS-only,
   nur transform/opacity, jeweils mit reduced-motion-Guard weiter unten. */

/* 1 · Countdown-Puls: das Zeit-Badge pulsiert dezent in den letzten 10 s. */
.ss-pulse {
    animation: ss-pulse 1s ease-in-out infinite;
}

@keyframes ss-pulse {
    0%, 100% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.08);
    }
}

/* 2 · Fortschritts-Punkt-Pop: der neu erreichte Punkt „poppt" einmalig beim
   Weiterrücken (Auslösung per @key an der aktuellen Perle). Nur in der Gast-Variante –
   dort ist der aktive Punkt statisch scale(1.2) und pulslos; der Pop schwingt über und
   klingt bei genau dieser Ruhegröße aus (kein Schrumpfen, kein Überschreiben des
   Moderations-Pulses). Höhere Spezifität als `.is-current`, damit er greift. */
.ss-progress-dots--guest .ss-progress-dot.is-current.ss-dot-pop {
    animation: ss-dot-pop 0.5s cubic-bezier(0.2, 0.7, 0.3, 1.2) both;
}

@keyframes ss-dot-pop {
    0% {
        transform: scale(0.6);
    }
    55% {
        transform: scale(1.4);
    }
    100% {
        transform: scale(1.2);
    }
}

/* 3 · Icon-Pop: das „Spiel beendet"-Icon tritt kurz gedämpft auf (kein Konfetti). */
.ss-icon-pop {
    display: inline-block;
    animation: ss-icon-pop 0.55s cubic-bezier(0.2, 0.7, 0.3, 1.2) both;
}

@keyframes ss-icon-pop {
    0% {
        opacity: 0;
        transform: scale(0.6);
    }
    70% {
        opacity: 1;
        transform: scale(1.1);
    }
    100% {
        opacity: 1;
        transform: scale(1);
    }
}

/* 4 + 5 · Herz-Motiv: sanfter Herzschlag für beide „Danke"-Momente (Feedback-Dank
   und Fragen-Bewerten). Bewusst kein Aufsteigen – die Finale-Herzen bleiben exklusiv. */
.ss-heart-in {
    display: inline-block;
    color: var(--ss-accent);
    animation: ss-heart-in 0.72s cubic-bezier(0.2, 0.7, 0.3, 1.3) both;
}

@keyframes ss-heart-in {
    0% {
        opacity: 0;
        transform: scale(0.5);
    }
    45% {
        opacity: 1;
        transform: scale(1.22);
    }
    70% {
        transform: scale(0.98);
    }
    85% {
        transform: scale(1.06);
    }
    100% {
        transform: scale(1);
    }
}

/* 5 · Tap-Pop: der gewählte Bewerten-Button quittiert den Tap mit einem kleinen Nicken. */
.ss-tap-pop {
    animation: ss-tap-pop 0.35s ease-out both;
}

@keyframes ss-tap-pop {
    0%, 100% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.06);
    }
}

@media (prefers-reduced-motion: reduce) {
    .ss-pulse,
    .ss-icon-pop,
    .ss-heart-in,
    .ss-tap-pop {
        animation: none;
    }
    /* Gleiche Spezifität wie die Pop-Regel oben, sonst würde `animation: none` nicht greifen. */
    .ss-progress-dots--guest .ss-progress-dot.is-current.ss-dot-pop {
        animation: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .ss-confirm-pop,
    .ss-stamp,
    .ss-fill-bar {
        animation: none;
    }
    .ss-confirm-check path {
        animation: none;
        stroke-dashoffset: 0;
    }
    .ss-press {
        transition: none;
    }
}

a, .btn-link {
    color: var(--ss-primary);
    transition: color 0.15s ease;
}

a:hover, .btn-link:hover {
    color: var(--ss-primary-hover);
}

code {
    color: var(--ss-accent-hover);
    background: var(--ss-accent-soft);
    padding: 0.15em 0.35em;
    border-radius: var(--ss-radius-sm);
    font-size: 0.875em;
}

.text-muted {
    color: var(--ss-text-secondary) !important;
}

/* Kontrast-Audit (#175 P3.4): Bootstraps Semantik-Utilities sind für Flächen gedacht und
   fallen als Schrift durch WCAG 1.4.3 (.text-warning #ffc107 = 1,6:1 auf Weiß) – sie tragen
   im Gäste-UI aber echten Fließtext (WLAN-Hinweis, Sync-Warnung, Trefferquote). Deshalb
   zentral auf die Text-Token umbiegen; im Abendmodus zeigen dieselben Token auf die
   angehobenen Warmwerte, sodass beide Modi ohne Sonderregeln bestehen. */
.text-warning {
    color: var(--ss-warning-text) !important;
}

.text-success {
    color: var(--ss-success-text) !important;
}

.text-danger {
    color: var(--ss-danger-text) !important;
}

.text-info {
    color: var(--ss-info-text) !important;
}

small, .small {
    color: var(--ss-text-secondary);
}

.content {
    padding-top: 1.1rem;
}

/* ══════════════════════════════════════════════
   2. Buttons
   ══════════════════════════════════════════════ */

.btn {
    border-radius: var(--ss-radius-sm);
    font-weight: 500;
    transition: all 0.18s ease;
    min-height: 2.35rem;
    border-width: 1px;
    letter-spacing: 0.005em;
}

.btn-sm {
    min-height: 2rem;
    border-radius: var(--ss-radius-sm);
}

/* Mindest-Touch-Ziel (44 px) für kompakte Aktionen, die auch am Spieltag auf dem Handy
   getroffen werden müssen — überschreibt bewusst die kleinere .btn-sm-Höhe. */
.ss-touch-target {
    min-height: 44px;
}

.btn-lg {
    border-radius: var(--ss-radius-md);
}

.btn-primary {
    color: var(--ss-primary-text);
    background-color: var(--ss-primary);
    border-color: var(--ss-primary);
    box-shadow: var(--ss-shadow-sm);
}

.btn-primary:hover,
.btn-primary:active {
    background-color: var(--ss-primary-hover);
    border-color: var(--ss-primary-hover);
    box-shadow: var(--ss-shadow-md);
}

.btn-outline-primary {
    color: var(--ss-primary);
    border-color: var(--ss-primary);
    background: transparent;
}

.btn-outline-primary:hover,
.btn-outline-primary:active {
    color: var(--ss-primary-text);
    background-color: var(--ss-primary);
    border-color: var(--ss-primary);
}

/* ── Champagner-Gold als zweite Antwortfarbe (#142/A3) ──
   Gold statt Rot für „Option 2": festlich und wertfrei statt „falsch/Gefahr".
   Token-basiert, damit es mit dem Kerzenlicht-Modus (#115) komponiert. Die Schrift trägt
   das Text-Token: Der Name auf dem Antwort-Knopf ist Fließtext und muss AA erfüllen –
   die frühere Gold-Stufe kam auf 3,1:1 (Kontrast-Audit #175 P3.4). Der Rand bleibt Gold. */
.btn-outline-accent {
    color: var(--ss-accent-text);
    border-color: var(--ss-accent);
    background: transparent;
}

.btn-outline-accent:hover,
.btn-outline-accent:active {
    color: var(--ss-accent-btn-text);
    background-color: var(--ss-accent-btn-bg);
    border-color: var(--ss-accent-btn-bg);
}

.bg-ss-accent {
    background-color: var(--ss-accent) !important;
}

.bg-ss-accent-soft {
    background-color: var(--ss-accent-soft) !important;
}

.text-ss-accent {
    color: var(--ss-accent) !important;
}

/* ── Ruhige Statuszeile & Warte-Punkte (#142/C1, C2) ──
   Leiser „Verbunden · Details"-Pill mit sanft pulsierendem Live-Punkt; im
   Lobby-Warten drei ruhige Punkte statt Warn-Optik. Beide reduced-motion-gated. */
.ss-status-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.3rem 0.65rem;
    border: 1px solid var(--ss-border);
    border-radius: 999px;
    background: var(--ss-surface);
    box-shadow: var(--ss-shadow-sm);
    color: var(--ss-text-secondary);
    font-family: inherit;
    font-size: 0.74rem;
    line-height: 1.3;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.ss-status-chip:hover,
.ss-status-chip:focus-visible {
    background: var(--ss-surface-muted);
    border-color: var(--ss-border);
    color: var(--ss-text);
}

.ss-status-chip-more {
    color: var(--ss-muted);
}

/* Der Puls-Ring wird aus --ss-success gemischt statt fest verdrahtet: im Kerzenschein
   ist das Grün ein anderes (#6cc48f), ein hart kodiertes rgba(58,138,92,…) läge dort
   neben der Farbe des Punkts. */
.ss-live-dot {
    --ss-live-ring: color-mix(in srgb, var(--ss-success) 45%, transparent);
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--ss-success);
    box-shadow: 0 0 0 0 var(--ss-live-ring);
    animation: ss-live-pulse 2.4s ease-out infinite;
}

@keyframes ss-live-pulse {
    0% { box-shadow: 0 0 0 0 var(--ss-live-ring); }
    70% { box-shadow: 0 0 0 6px transparent; }
    100% { box-shadow: 0 0 0 0 transparent; }
}

/* Live-Signal mit Wort (#178): in der Moderation reicht der nackte Punkt nicht –
   dort wird unter Zeitdruck abgelesen, ob die Verbindung steht. Grün + Puls + „Live".

   Das Wort steht bewusst in der Textfarbe, nicht in --ss-success: das Grün (#3a8a5c) käme
   auf hellem Grund nur auf ~4,0:1 und verfehlte damit für 14-px-Text die 4,5:1 aus WCAG AA.
   Die Signalfarbe trägt der Punkt – der ist nicht-textuell und darf grün bleiben. */
.ss-live-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--ss-text);
    font-weight: 600;
}

/* .ss-calm-dots ist mit #181 entfallen: Die einzige Nutzung (Lobby-Wartescreen) doppelte
   die Ladepunkte der WaitingSplashAnimation, die direkt darüber steht. Die Punkte der
   Splash-Animation liegen in den .splash-loader-Regeln (Sektion „Warte-Animation"). */

@media (prefers-reduced-motion: reduce) {
    .ss-live-dot {
        animation: none;
    }
}

.btn-secondary,
.btn-outline-secondary {
    border-color: var(--ss-border);
    color: var(--ss-text-secondary);
}

.btn-secondary {
    background-color: var(--ss-surface-muted);
}

.btn-secondary:hover {
    background-color: var(--ss-border-light);
    color: var(--ss-text);
}

.btn-outline-secondary:hover {
    background-color: var(--ss-surface-muted);
    border-color: var(--ss-border);
    color: var(--ss-text);
}

.btn-success {
    background-color: var(--ss-success);
    border-color: var(--ss-success);
}

.btn-success:hover {
    background-color: #2f7a4e;
    border-color: #2f7a4e;
}

.btn-danger {
    background-color: var(--ss-danger);
    border-color: var(--ss-danger);
}

.btn-danger:hover {
    background-color: #ab3d30;
    border-color: #ab3d30;
}

.btn-outline-danger {
    color: var(--ss-danger);
    border-color: var(--ss-danger);
}

.btn-outline-danger:hover {
    background-color: var(--ss-danger);
    border-color: var(--ss-danger);
    color: #fff;
}

.btn-warning {
    background-color: var(--ss-warning);
    border-color: var(--ss-warning);
    color: #fff;
}

.btn-outline-light {
    border-color: rgba(255,255,255,0.35);
    color: rgba(255,255,255,0.9);
}

.btn-outline-light:hover {
    background-color: rgba(255,255,255,0.12);
    border-color: rgba(255,255,255,0.5);
    color: #fff;
}

.btn-light {
    background-color: rgba(255,255,255,0.92);
    border-color: rgba(255,255,255,0.6);
    color: var(--ss-text);
}

/* Focus ring – all interactive */
.btn:focus, .btn:active:focus,
.btn-link.nav-link:focus,
.form-control:focus,
.form-select:focus,
.form-check-input:focus {
    box-shadow: var(--ss-focus-ring);
    outline: none;
}

.btn:disabled, .btn.disabled {
    opacity: 0.55;
}

/* ══════════════════════════════════════════════
   3. Cards & Panels
   ══════════════════════════════════════════════ */

.card {
    background-color: var(--ss-surface);
    border: 1px solid var(--ss-border-light);
    border-radius: var(--ss-radius-lg);
    box-shadow: var(--ss-shadow-sm);
    transition: box-shadow 0.2s ease;
}

.card.shadow-sm {
    box-shadow: var(--ss-shadow-md) !important;
}

.card-body {
    padding: 1.25rem;
}

.card-header {
    background-color: var(--ss-surface-strong);
    border-bottom: 1px solid var(--ss-border-light);
    border-radius: var(--ss-radius-lg) var(--ss-radius-lg) 0 0 !important;
    font-weight: 600;
}

.card-footer {
    background-color: var(--ss-surface-strong);
    border-top: 1px solid var(--ss-border-light);
}

/* ══════════════════════════════════════════════
   4. Forms
   ══════════════════════════════════════════════ */

.form-control,
.form-select {
    border: 1px solid var(--ss-border);
    border-radius: var(--ss-radius-sm);
    background-color: var(--ss-surface);
    color: var(--ss-text);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
    min-height: 2.5rem;
}

.form-control:focus,
.form-select:focus {
    border-color: var(--ss-primary);
    box-shadow: var(--ss-focus-ring);
    background-color: var(--ss-surface);
}

.form-control::placeholder {
    color: var(--ss-muted);
}

.form-label {
    font-weight: 500;
    color: var(--ss-text);
    margin-bottom: 0.35rem;
    font-size: 0.9rem;
}

.form-text {
    color: var(--ss-muted);
}

.form-check-input {
    border-color: var(--ss-border);
}

.form-check-input:checked {
    background-color: var(--ss-primary);
    border-color: var(--ss-primary);
}

.input-group-text {
    background-color: var(--ss-surface-muted);
    border-color: var(--ss-border);
    color: var(--ss-text-secondary);
}

/* Validation states – clear but not aggressive */
.valid.modified:not([type=checkbox]) {
    outline: none;
    border-color: var(--ss-success);
}

.invalid {
    outline: none;
    border-color: var(--ss-danger);
}

.validation-message {
    color: var(--ss-danger);
    font-size: 0.85rem;
    margin-top: 0.25rem;
}

/* Floating label overrides */
.form-floating > .form-control-plaintext::placeholder,
.form-floating > .form-control::placeholder {
    color: var(--ss-muted);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder,
.form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ══════════════════════════════════════════════
   5. Alerts
   ══════════════════════════════════════════════ */

.alert {
    border-radius: var(--ss-radius-md);
    border-width: 1px;
    font-size: 0.92rem;
}

.alert-danger {
    background-color: var(--ss-danger-soft);
    border-color: rgba(196, 73, 58, 0.2);
    color: #8b2e22;
}

.alert-success {
    background-color: var(--ss-success-soft);
    border-color: rgba(58, 138, 92, 0.2);
    color: #245838;
}

.alert-warning {
    background-color: var(--ss-warning-soft);
    border-color: rgba(196, 144, 54, 0.2);
    color: #7a5820;
}

.alert-info {
    background-color: var(--ss-info-soft);
    border-color: rgba(59, 126, 168, 0.2);
    color: #254f6a;
}

.alert-light {
    background-color: var(--ss-surface-strong);
    border-color: var(--ss-border-light);
    color: var(--ss-text);
}

/* ══════════════════════════════════════════════
   6. Badges
   ══════════════════════════════════════════════ */

.badge {
    border-radius: var(--ss-radius-sm);
    font-weight: 500;
    letter-spacing: 0.01em;
    padding: 0.3em 0.6em;
}

.text-bg-primary,
.badge.text-bg-primary {
    background-color: var(--ss-primary) !important;
}

.text-bg-secondary,
.badge.text-bg-secondary {
    background-color: var(--ss-text-secondary) !important;
}

.text-bg-success,
.badge.text-bg-success {
    background-color: var(--ss-success) !important;
}

.text-bg-danger,
.badge.text-bg-danger {
    background-color: var(--ss-danger) !important;
}

.text-bg-warning,
.badge.text-bg-warning {
    background-color: var(--ss-warning) !important;
    color: #fff !important;
}

.text-bg-info,
.badge.text-bg-info {
    background-color: var(--ss-info) !important;
    color: #fff !important;
}

.text-bg-light,
.badge.text-bg-light {
    background-color: var(--ss-surface-muted) !important;
    color: var(--ss-text) !important;
    border: 1px solid var(--ss-border-light);
}

/* ══════════════════════════════════════════════
   7. Tables
   ══════════════════════════════════════════════ */

.table {
    --bs-table-bg: transparent;
    --bs-table-hover-bg: var(--ss-accent-soft);
    border-color: var(--ss-border-light);
    font-size: 0.92rem;
}

.table > thead {
    border-bottom-width: 2px;
    border-bottom-color: var(--ss-border);
}

.table-light,
.table > thead.table-light > tr > th {
    --bs-table-bg: var(--ss-surface-strong);
    --bs-table-border-color: var(--ss-border-light);
    color: var(--ss-text-secondary);
    font-weight: 600;
    font-size: 0.84rem;
    text-transform: none;
    letter-spacing: 0.01em;
}

.table > tbody > tr {
    transition: background-color 0.12s ease;
}

.table-success {
    --bs-table-bg: var(--ss-success-soft) !important;
}

.table-responsive {
    border-radius: var(--ss-radius-md);
}

/* ══════════════════════════════════════════════
   8. Navbar
   ══════════════════════════════════════════════ */

/* Dezentes dunkles Glas: die Navbar ist sticky-top, Inhalt scrollt darunter
   durch. Hohe Deckung (0.88), damit die Nav-Links AA-Kontrast behalten. */
.navbar.bg-dark {
    background-color: var(--ss-glass-dark-bg) !important;
    background-image: linear-gradient(180deg, rgba(255,255,255,0.03) 0%, transparent 100%);
    border-bottom: 1px solid rgba(255,255,255,0.08);
    backdrop-filter: var(--ss-glass-filter);
    -webkit-backdrop-filter: var(--ss-glass-filter);
}

.navbar .navbar-brand {
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
    color: #fff !important;
}

.navbar .navbar-brand img {
    border-radius: 10px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}

.navbar .nav-link {
    color: var(--ss-nav-text) !important;
    font-weight: 450;
    font-size: 0.9rem;
    padding: 0.5rem 0.75rem !important;
    border-radius: var(--ss-radius-sm);
    transition: color 0.15s ease, background 0.15s ease;
}

.navbar .nav-link:hover {
    color: var(--ss-nav-hover) !important;
    background: rgba(255,255,255,0.06);
}

.navbar .nav-link.active {
    color: var(--ss-nav-active) !important;
    font-weight: 600;
    background: rgba(255,255,255,0.08);
}

/* ══════════════════════════════════════════════
   9. Dropdowns
   ══════════════════════════════════════════════ */

/* Helles Glas mit hoher Deckung – schwebt über dem Inhalt */
.dropdown-menu {
    border: 1px solid var(--ss-border-light);
    border-radius: var(--ss-radius-md);
    box-shadow: var(--ss-shadow-lg);
    background-color: var(--ss-glass-surface);
    backdrop-filter: var(--ss-glass-filter-soft);
    -webkit-backdrop-filter: var(--ss-glass-filter-soft);
    padding: 0.35rem;
}

.dropdown-item {
    border-radius: var(--ss-radius-sm);
    font-size: 0.9rem;
    padding: 0.45rem 0.75rem;
    color: var(--ss-text);
    transition: background 0.12s ease;
}

.dropdown-item:hover,
.dropdown-item:focus {
    background-color: var(--ss-surface-muted);
    color: var(--ss-text);
}

.dropdown-item.active,
.dropdown-item:active {
    background-color: var(--ss-primary-soft);
    color: var(--ss-primary);
}

/* ══════════════════════════════════════════════
   10. Modals
   ══════════════════════════════════════════════ */

/* Helles Glas über dem abgedunkelten Backdrop; hohe Deckung,
   da Modals auch Formulare/Texte tragen */
.modal-content {
    border: 1px solid var(--ss-glass-border);
    border-radius: var(--ss-radius-lg);
    box-shadow: var(--ss-shadow-lg), var(--ss-glass-highlight);
    background-color: var(--ss-glass-surface);
    backdrop-filter: var(--ss-glass-filter);
    -webkit-backdrop-filter: var(--ss-glass-filter);
}

.modal-header {
    border-bottom-color: var(--ss-border-light);
    padding: 1rem 1.25rem;
}

.modal-footer {
    border-top-color: var(--ss-border-light);
    padding: 0.85rem 1.25rem;
}

.modal-backdrop.show {
    background-color: rgba(30, 25, 18, 0.45);
}

/* ══════════════════════════════════════════════
   11. Progress bars
   ══════════════════════════════════════════════ */

.progress {
    background-color: var(--ss-surface-muted);
    border-radius: 999px;
    overflow: hidden;
}

.progress-bar {
    transition: width 0.4s ease;
}

.progress-bar.bg-primary,
.progress-bar:not([class*="bg-"]) {
    background-color: var(--ss-primary) !important;
}

.progress-bar.bg-success {
    background-color: var(--ss-success) !important;
}

.progress-bar.bg-info {
    background-color: var(--ss-info) !important;
}

/* ══════════════════════════════════════════════
   12. Spinners
   ══════════════════════════════════════════════ */

.spinner-border {
    color: var(--ss-primary);
}

.spinner-border.text-primary {
    color: var(--ss-primary) !important;
}

/* ══════════════════════════════════════════════
   13. Footer (global support)
   ══════════════════════════════════════════════ */

.bg-dark {
    background-color: var(--ss-nav-bg) !important;
}

/* ══════════════════════════════════════════════
   14. Breadcrumb nav refinements
   ══════════════════════════════════════════════ */

.breadcrumb {
    font-size: 0.85rem;
    background: transparent;
    padding: 0;
    margin-bottom: 0.75rem;
}

/* ══════════════════════════════════════════════
   15. List groups
   ══════════════════════════════════════════════ */

.list-group-item {
    border-color: var(--ss-border-light);
    color: var(--ss-text);
}

.list-group-item.active {
    background-color: var(--ss-primary);
    border-color: var(--ss-primary);
}

/* ══════════════════════════════════════════════
   16. UX Helper Components
   ══════════════════════════════════════════════ */

/* HelpDetails – collapsible help block */
.ss-help-details {
    font-size: 0.85rem;
}

.ss-help-summary {
    cursor: pointer;
    color: var(--ss-primary);
    font-weight: 500;
    padding: 0.3rem 0;
    list-style: none;
    user-select: none;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    transition: color 0.15s ease;
}

.ss-help-summary:hover {
    color: var(--ss-primary-hover);
}

.ss-help-summary::-webkit-details-marker {
    display: none;
}

.ss-help-summary::after {
    content: "▸";
    font-size: 0.7em;
    transition: transform 0.2s ease;
    margin-left: 0.15rem;
}

.ss-help-details[open] > .ss-help-summary::after {
    transform: rotate(90deg);
}

.ss-help-body {
    color: var(--ss-text-secondary);
    padding: 0.45rem 0 0.25rem 1.4rem;
    line-height: 1.55;
}

/* Abschnitts-Navigation (#412) – Anker-Chips über langen Formularseiten.
   Auf dem Handy horizontal scrollbar statt umbrechend: Drei Chip-Zeilen über der Hero-Karte
   kosteten mehr Platz, als die Navigation spart. Höhe 44 px = Mindest-Touch-Ziel. */
.ss-anchor-nav {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.4rem;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    padding-bottom: 0.2rem;
}

.ss-anchor-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    flex: 0 0 auto;
    min-height: 44px;
    padding: 0.35rem 0.8rem;
    border: 1px solid var(--ss-border);
    border-radius: 999px;
    background: var(--ss-surface);
    color: var(--ss-text-secondary);
    font-size: 0.82rem;
    line-height: 1.25;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.ss-anchor-chip:hover,
.ss-anchor-chip:focus-visible {
    background: var(--ss-surface-muted);
    border-color: var(--ss-primary);
    color: var(--ss-primary);
}

@media (min-width: 768px) {
    .ss-anchor-nav {
        flex-wrap: wrap;
        overflow-x: visible;
    }
}

/* Sprungziel: Die Navbar ist sticky-top, ohne Abstand verschwände der Abschnittsanfang
   darunter. Gilt auch für die Deep-Links aus dem Setup-Cockpit. */
.ss-anchor-target {
    scroll-margin-top: 4.5rem;
}

/* RecommendationCard – best-practice hint */
.ss-recommendation {
    background-color: var(--ss-accent-soft);
    border: 1px solid rgba(196, 162, 101, 0.18);
    border-left: 3px solid var(--ss-accent);
    border-radius: var(--ss-radius-sm);
    padding: 0.65rem 0.85rem;
    color: var(--ss-text);
}

.ss-recommendation-icon {
    color: var(--ss-accent);
    font-size: 1rem;
    flex-shrink: 0;
}

/* ── Setup-Cockpit & Runden-Hub (#411/#383) ──
   Touch-Ziel ≥44 px aus Zielbild 3.8: Bootstraps btn-sm liegt bei ~31 px und ist am Spieltag
   auf dem Handy zu klein. Gilt für alle Bedienelemente in Hub und Cockpit-Blöcken. */
.ss-touch-target {
    min-height: 44px;
    min-width: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Kebab-Menü ohne Bootstrap-JS: die Sichtbarkeit steuert Blazor, die Position dieses Regelpaar. */
.ss-hub-menu-host {
    position: relative;
}

.ss-hub-menu {
    position: absolute;
    top: calc(100% + 0.25rem);
    right: 0;
    z-index: 20;
    min-width: 12rem;
    /* #511 E: nie breiter als der Viewport — gleiche Kappung wie beim Runden-Wechsler. */
    max-width: calc(100vw - 1.5rem);
}

/* #511 E: Gleiche Konstruktion wie .ss-menu-host — `right: 0` meint die rechte Kante des
   KEBAB-BUTTONS. Auf dem Handy kann das Kebab nach dem Flex-Umbruch aber überall stehen:
   allein umgebrochen ganz links (dann liefe das 12rem-Menü links aus dem Bild) oder auf
   der geteilten Zeile ganz rechts (dann liefe ein linksbündiges Menü rechts hinaus —
   deshalb hier bewusst NICHT die Linksbündigkeit des Runden-Wechslers). Stattdessen ankert
   das Menü auf dem Handy an der Zeilenkarte (position-relative in RoundHubRowView.razor):
   die ist praktisch viewportbreit, das Menü passt in jeder Kebab-Position vollständig hinein. */
@media (max-width: 575.98px) {
    .ss-hub-menu-host {
        position: static;
    }

    .ss-hub-menu {
        min-width: 0;
        width: max-content;
    }
}

/* Klick daneben schließt (#511 E, Runden-Wechsler + Hub-Kebab): unsichtbarer Backdrop knapp
   unter dem Menü (z-index 20) — gleiches Muster wie .ss-help-backdrop im GuestHelpButton,
   nur ohne Abdunklung. Auf dem Handy gibt es kein Escape; der erste Tipp daneben schließt
   das Menü, erst der zweite bedient das Element darunter. */
.ss-menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: 19;
    background: transparent;
}

/* „Notfallmappe veraltet" braucht einen eigenen Stil (Zielbild 3.2) — sonst trägt sie dasselbe
   Warnbild wie „noch nicht gedruckt", obwohl der Handlungsdruck ein anderer ist. */
.ss-binder-outdated {
    color: var(--ss-warning-emphasis, #8a6100);
    text-decoration-style: dashed;
    text-underline-offset: 0.2em;
}

/* ══════════════════════════════════════════════
   17. Blazor Error UI
   ══════════════════════════════════════════════ */

#blazor-error-ui {
    color-scheme: light only;
    background: var(--ss-warning-soft);
    bottom: 0;
    box-shadow: 0 -1px 4px rgba(45, 30, 15, 0.1);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    color: var(--ss-text);
    border-top: 1px solid var(--ss-border);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA9NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, var(--ss-danger);
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
    border-radius: var(--ss-radius-md);
}

.blazor-error-boundary::after {
    content: "Es ist ein Fehler aufgetreten.";
}

/* ══════════════════════════════════════════════
   18. PWA Update Banner
   ══════════════════════════════════════════════ */

.pwa-update-banner {
    position: fixed;
    left: 1rem;
    right: 1rem;
    bottom: 1rem;
    z-index: 1100;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.85rem 1.15rem;
    border-radius: var(--ss-radius-lg);
    background: linear-gradient(135deg, var(--ss-glass-dark-bg) 0%, var(--ss-glass-dark-bg-accent) 100%);
    border: 1px solid rgba(255,255,255,0.1);
    color: #fff;
    box-shadow: var(--ss-shadow-lg);
    backdrop-filter: var(--ss-glass-filter-soft);
    -webkit-backdrop-filter: var(--ss-glass-filter-soft);
}

@media (min-width: 576px) {
    .pwa-update-banner {
        left: auto;
        right: 1rem;
        max-width: 26rem;
    }
}

.pwa-update-text {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.pwa-update-title {
    font-size: 0.92rem;
    font-weight: 500;
}

.pwa-update-subtitle {
    font-size: 0.78rem;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.72);
    line-height: 1.3;
}

.pwa-update-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex-shrink: 0;
}

.pwa-update-later {
    color: rgba(255, 255, 255, 0.78);
    text-decoration: none;
    padding-inline: 0.5rem;
}

.pwa-update-later:hover {
    color: #fff;
}

/* Dezenter Hinweis-Chip – erscheint während laufender Spiel-/Moderationsansichten
   sowie nach „Später", ohne vom Spiel abzulenken. */
.pwa-update-chip {
    position: fixed;
    right: 0.85rem;
    bottom: 0.85rem;
    z-index: 1090;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    max-width: calc(100vw - 1.7rem);
    padding: 0.3rem 0.6rem;
    border-radius: 999px;
    background: var(--ss-glass-surface);
    border: 1px solid var(--ss-border);
    color: var(--ss-muted);
    box-shadow: var(--ss-shadow-sm);
    backdrop-filter: var(--ss-glass-filter-soft);
    -webkit-backdrop-filter: var(--ss-glass-filter-soft);
    font-size: 0.74rem;
    line-height: 1.2;
    opacity: 0.9;
}

.pwa-update-chip i {
    font-size: 0.8rem;
    flex-shrink: 0;
}

.pwa-update-chip-text {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pwa-update-chip-action {
    padding: 0 0.15rem;
    font-size: 0.74rem;
    font-weight: 500;
    color: var(--ss-primary);
    text-decoration: none;
}

/* Der „Update bereit"/„Neue Version"-Hinweis ist ein fixiertes Overlay und wird
   sonst auf jeder Druckseite mitgedruckt (u. a. auf /join-print, #72). Global im
   Druck ausblenden – nicht nur auf einzelnen Seiten. */
@media print {
    .pwa-update-banner,
    .pwa-update-chip {
        display: none !important;
    }
}

/* ══════════════════════════════════════════════
   19. Glass utility (frosted)
   Kapselt das Splash-Glas-Rezept für Wiederverwendung.
   Bewusst sparsam einsetzen: backdrop-filter ist GPU-teuer –
   max. 1–2 geblurrte Ebenen pro Screen (Gäste-Handys!).
   Steht nach den Komponenten-Sektionen, damit es .card/.modal-content
   in der Kaskade übersteuert.
   Alle Fallbacks laufen zentral über die Token-Redefinitionen unten –
   neue Glas-Flächen erben sie automatisch, solange sie die
   --ss-glass-*-Tokens (statt Literale) verwenden.
   ══════════════════════════════════════════════ */

.ss-glass {
    border: 1px solid var(--ss-glass-border);
    background: var(--ss-glass-bg);
    box-shadow: var(--ss-glass-shadow), var(--ss-glass-highlight);
    backdrop-filter: var(--ss-glass-filter);
    -webkit-backdrop-filter: var(--ss-glass-filter);
}

/* Kein Blur-im-Blur: innerhalb einer .ss-glass-Fläche liegt der Frost bereits
   unter dem Panel; verschachtelte backdrop-filter (z. B. WaitingSplashAnimation
   in einer Glas-Karte) sampeln nur die Eltern-Ebene und kosten GPU.
   Transluzenz, Lichtkante und Schatten der inneren Panels bleiben erhalten. */
.ss-glass .splash-panel,
.ss-glass .splash-loader {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

/* Kein backdrop-filter verfügbar → deckende Flächen. Der or-Zweig ist wichtig:
   älteres iOS-Safari kann nur das geprefixte -webkit-backdrop-filter; ohne ihn
   fiele dort das Glas fälschlich auf die deckende Variante zurück. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    :root {
        --ss-glass-bg:             var(--ss-glass-bg-fallback);
        --ss-glass-surface:        var(--ss-surface);
        --ss-glass-dark-bg:        var(--ss-nav-bg);
        --ss-glass-dark-bg-accent: #374558;
    }

    /* Abendmodus (#115): eigener Zweig nötig, weil die html.ss-evening-Tokens aus
       Sektion 21 die :root-Redefinition oben sonst wieder überstimmen würden. Die
       doppelte Klasse hebt die Spezifität über Sektion 21 (die später im Stylesheet
       steht und bei gleicher Spezifität gewinnen würde). */
    html.ss-evening.ss-evening {
        --ss-glass-bg:      var(--ss-glass-bg-fallback);
        --ss-glass-surface: var(--ss-surface);
    }
}

/* Nutzerwunsch „weniger Transparenz": vollständig deckende, ruhige Flächen */
@media (prefers-reduced-transparency: reduce) {
    :root {
        --ss-glass-filter:         none;
        --ss-glass-filter-soft:    none;
        --ss-glass-bg:             var(--ss-surface);
        --ss-glass-bg-fallback:    var(--ss-surface);
        --ss-glass-surface:        var(--ss-surface);
        --ss-glass-dark-bg:        var(--ss-nav-bg);
        --ss-glass-dark-bg-accent: #374558;
    }

    /* Abendmodus (#115): siehe Hinweis im @supports-Block – deckende dunkle Flächen
       (doppelte Klasse schlägt die später stehende Sektion 21). */
    html.ss-evening.ss-evening {
        --ss-glass-bg:          var(--ss-surface);
        --ss-glass-bg-fallback: var(--ss-surface);
        --ss-glass-surface:     var(--ss-surface);
        --ss-glass-highlight:   inset 0 0 0 rgba(0, 0, 0, 0);
    }

    /* Nicht token-getrieben (bewusst eigene, hellere Rezeptur) → explizit */
    .splash-loader {
        background: var(--ss-surface);
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }

    .pwa-update-chip {
        opacity: 1;
    }

    /* Papierkorn ist eine Textur-/Transluzenz-Ebene → bei „weniger Transparenz"
       abschalten; die warmen Radials (body::before) bleiben. */
    body::after {
        display: none;
    }
}

/* Druck: Transluzenz/Blur drucken schlecht (graue Flächen) → deckend, flach */
@media print {
    :root {
        --ss-glass-filter:         none;
        --ss-glass-filter-soft:    none;
        --ss-glass-bg:             #fff;
        --ss-glass-bg-fallback:    #fff;
        --ss-glass-surface:        #fff;
        --ss-glass-dark-bg:        var(--ss-nav-bg);
        --ss-glass-dark-bg-accent: #374558;
        --ss-glass-border:         var(--ss-border-light);
        /* box-shadow-Listen erlauben kein "none" je Eintrag → transparente Nullschatten */
        --ss-glass-shadow:         0 0 0 rgba(0, 0, 0, 0);
        --ss-glass-highlight:      inset 0 0 0 rgba(0, 0, 0, 0);
    }

    /* Hintergrund-Ebenen (warme Radials + Papierkorn) nicht mitdrucken. */
    body::before,
    body::after {
        display: none;
    }

    /* App-Chrome (Navbar inkl. Login/Registrieren, Footer, Banner) nie mitdrucken (#310).
       Navbar und Footer sind in MainLayout Geschwister von .app-content; Modals
       (MfaStepUp, Problem melden) rendern außerhalb der Shell und brauchen die
       eigene Regel. */
    .app-shell > *:not(.app-content),
    .modal,
    .modal-backdrop {
        display: none !important;
    }

    .app-content {
        padding: 0 !important;
    }

    /* Seitenweite Opt-out-Klasse für nicht druckwürdige Blöcke (Feedback, CTAs, Toggles).
       JoinPrint/SessionResultExport definieren sie zusätzlich lokal — harmlos redundant. */
    .no-print {
        display: none !important;
    }

    /* Browser drucken keine box-shadows: Karten bekommen einen expliziten Rand,
       sonst stehen border-0-Karten als randlose weiße Blöcke auf dem Papier (#310).
       Farbe = bewusst abgedunkeltes --ss-border (#e4ddd3), damit der Rand auf
       Papier sichtbar bleibt; Literal statt Token, damit Dark-Mode-Tokenwerte
       nie in den Druck durchschlagen. */
    .card {
        border: 1px solid #c9c1b4 !important;
        box-shadow: none !important;
        break-inside: avoid;
    }

    /* Die dekorative Geisterziffer ist absolut positioniert (Größe via vw) und legt
       sich im Druck über den Kartentext (#308) → weglassen. */
    .ss-ghost-number {
        display: none !important;
    }

    /* Scroll-Reveal-Zustände (IntersectionObserver) dürfen im Druck nichts verstecken
       oder verschieben — unterhalb des Falzes wären Karten sonst leer/transparent (#308). */
    .ss-reveal-armed,
    .ss-reveal-item,
    .ss-reveal-on-view {
        /* animation: none, sonst friert der both-Fill-Mode den from-Zustand
           (opacity 0, translateY) ein, wenn die Animation nie lief. */
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
    }
}

/* ══════════════════════════════════════════════
   Splash Screen (preserved – uses shared tokens where safe)
   ══════════════════════════════════════════════ */

.splash {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background:
        radial-gradient(120% 70% at 10% 8%, rgba(255, 231, 184, 0.45) 0%, rgba(255, 231, 184, 0) 58%),
        radial-gradient(100% 65% at 88% 16%, rgba(255, 211, 156, 0.3) 0%, rgba(255, 211, 156, 0) 62%),
        linear-gradient(155deg, #fff6ea 0%, #fdf3e7 34%, #eef2fb 100%);
    color: var(--ss-text);
    z-index: 9999;
    overflow: hidden;
    gap: 1.25rem;
    padding: 1.5rem;
}

.splash::before,
.splash::after {
    content: "";
    position: absolute;
    pointer-events: none;
    border-radius: 999px;
    z-index: 0;
}

.splash::before {
    width: min(58vw, 23rem);
    height: min(58vw, 23rem);
    top: -12%;
    left: -10%;
    background: radial-gradient(circle, rgba(255, 221, 169, 0.28) 0%, rgba(255, 221, 169, 0) 72%);
}

.splash::after {
    width: min(56vw, 21rem);
    height: min(56vw, 21rem);
    bottom: -18%;
    right: -10%;
    background: radial-gradient(circle, rgba(81, 130, 189, 0.18) 0%, rgba(81, 130, 189, 0) 70%);
}

.splash-panel {
    position: relative;
    width: min(100%, 27rem);
    border-radius: var(--ss-radius-lg);
    border: 1px solid var(--ss-glass-border);
    background: var(--ss-glass-bg);
    box-shadow: var(--ss-glass-shadow), var(--ss-glass-highlight);
    backdrop-filter: var(--ss-glass-filter);
    -webkit-backdrop-filter: var(--ss-glass-filter);
    z-index: 1;
}

/* ── Brand block ── */
.splash-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.45rem;
    padding: 1.1rem 1rem 1rem;
    text-align: center;
}

.splash-logo {
    width: 72px;
    height: 72px;
    border-radius: 18px;
    border: 1px solid rgba(255, 255, 255, 0.9);
    box-shadow:
        0 10px 22px rgba(49, 33, 16, 0.2),
        0 2px 8px rgba(49, 33, 16, 0.12);
    margin-bottom: 0.35rem;
}

.splash-title {
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ss-primary);
}

.splash-slogan {
    font-size: 0.92rem;
    color: var(--ss-text-secondary);
    text-align: center;
    max-width: 21rem;
    line-height: 1.4;
}

.splash-questions-stage {
    width: min(100%, 29rem);
    padding: 0.55rem 0.6rem;
    overflow: hidden;
}

.splash-focus-line {
    position: absolute;
    left: 0.65rem;
    right: 0.65rem;
    top: calc(50% - 1.25rem);
    height: 2.5rem;
    border-radius: 999px;
    background: linear-gradient(90deg, rgba(255, 239, 208, 0.8), rgba(255, 250, 238, 0.9), rgba(255, 239, 208, 0.8));
    border: 1px solid rgba(222, 189, 126, 0.45);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.8),
        0 4px 12px rgba(124, 90, 43, 0.12);
    pointer-events: none;
    z-index: 1;
}

/* ── Questions preview ── */
.splash-questions {
    display: flex;
    gap: 0.35rem;
    height: 7.5rem;
    overflow: hidden;
    position: relative;
    z-index: 2;
    mask-image: linear-gradient(to bottom,
        rgba(0,0,0,0.1) 0%,
        rgba(0,0,0,0.5) 26%,
        black 36%,
        black 64%,
        rgba(0,0,0,0.5) 74%,
        rgba(0,0,0,0.1) 100%);
    -webkit-mask-image: linear-gradient(to bottom,
        rgba(0,0,0,0.1) 0%,
        rgba(0,0,0,0.5) 26%,
        black 36%,
        black 64%,
        rgba(0,0,0,0.5) 74%,
        rgba(0,0,0,0.1) 100%);
}

.splash-col {
    flex: 1;
    overflow: hidden;
    position: relative;
}

.splash-col-left {
    text-align: right;
}

.splash-col-right {
    text-align: left;
}

.splash-track {
    display: flex;
    flex-direction: column;
}

.splash-track span {
    display: block;
    height: 2.5rem;
    line-height: 2.5rem;
    font-size: 0.82rem;
    font-weight: 500;
    white-space: nowrap;
    color: var(--ss-text-secondary);
    padding: 0 0.3rem;
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.35);
}

.splash-col-left .splash-track span {
    color: var(--ss-primary);
    font-weight: 600;
}

/* ── Splash animation (unchanged) ── */
.splash-track-left {
    animation: splash-left 30s linear infinite;
}

.splash-track-right {
    animation: splash-right 30s linear infinite;
}

@keyframes splash-left {
    0%, 7%    { transform: translateY(0); }
    10%, 17%  { transform: translateY(-2.5rem); }
    20%, 27%  { transform: translateY(-5rem); }
    30%, 37%  { transform: translateY(-7.5rem); }
    40%, 47%  { transform: translateY(-10rem); }
    50%, 57%  { transform: translateY(-12.5rem); }
    60%, 67%  { transform: translateY(-15rem); }
    70%, 77%  { transform: translateY(-17.5rem); }
    80%, 87%  { transform: translateY(-20rem); }
    90%, 100% { transform: translateY(-22.5rem); }
}

@keyframes splash-right {
    0%, 7%    { transform: translateY(-22.5rem); }
    10%, 17%  { transform: translateY(-20rem); }
    20%, 27%  { transform: translateY(-17.5rem); }
    30%, 37%  { transform: translateY(-15rem); }
    40%, 47%  { transform: translateY(-12.5rem); }
    50%, 57%  { transform: translateY(-10rem); }
    60%, 67%  { transform: translateY(-7.5rem); }
    70%, 77%  { transform: translateY(-5rem); }
    80%, 87%  { transform: translateY(-2.5rem); }
    90%, 100% { transform: translateY(0); }
}

/* ── Reduced-motion: static display ── */
@media (prefers-reduced-motion: reduce) {
    .splash-track-left,
    .splash-track-right {
        animation: none;
    }

    .splash-questions {
        height: 2.5rem;
        mask-image: none;
        -webkit-mask-image: none;
    }

    .splash-track span {
        display: none;
    }

    .splash-col-left .splash-track span:nth-child(2) {
        display: block;
    }

    .splash-col-right .splash-track span:nth-child(11) {
        display: block;
    }
}

/* ── Loader dots ── */
.splash-loader {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.32rem;
    padding: 0.5rem 0.75rem;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.55);
    background: rgba(255, 255, 255, 0.58);
    box-shadow: 0 8px 20px rgba(49, 33, 16, 0.14);
    backdrop-filter: blur(var(--ss-glass-blur-soft));
    -webkit-backdrop-filter: blur(var(--ss-glass-blur-soft));
    z-index: 1;
}

.splash-loader-dot {
    width: 0.44rem;
    height: 0.44rem;
    border-radius: 50%;
    background: linear-gradient(160deg, var(--ss-accent), var(--ss-primary));
    opacity: 0.35;
    animation: splash-dot 1.35s ease-in-out infinite;
}

.splash-loader-dot:nth-child(1) { animation-delay: 0s; }
.splash-loader-dot:nth-child(2) { animation-delay: 0.2s; }
.splash-loader-dot:nth-child(3) { animation-delay: 0.4s; }

@keyframes splash-dot {
    0%, 80%, 100% {
        transform: translateY(0) scale(0.88);
        opacity: 0.32;
    }
    40% {
        transform: translateY(-3px) scale(1);
        opacity: 1;
    }
}

@media (prefers-reduced-motion: reduce) {
    .splash-loader-dot {
        animation: none;
        opacity: 0.6;
    }
}

/* ── Geduld-Hinweis bei langem Erstladen (#382) ──
   Beim Erstbesuch über schwaches Saal-WLAN dauert der WASM-Download spürbar.
   Der Hinweis liegt absolut am unteren Splash-Rand (beeinflusst das zentrierte
   Layout nicht) und blendet rein per animation-delay erst nach ~4,5 s ein –
   schnelle Verbindungen sehen den Splash exakt wie bisher. Nach ~18 s löst ein
   zweiter, beruhigender Text den ersten per Crossfade ab (beide Texte teilen
   sich dieselbe Grid-Zelle). Nur Opacity-Fades, keine Bewegung – deshalb
   bewusst KEIN prefers-reduced-motion-Sonderfall. */
.splash-patience {
    position: absolute;
    left: 1.5rem;
    right: 1.5rem;
    bottom: 1.1rem;
    bottom: max(1.1rem, env(safe-area-inset-bottom, 0px));
    display: grid;
    justify-items: center;
    row-gap: 0.55rem;
    z-index: 1;
    pointer-events: none;
    color: var(--ss-text-secondary);
}

.splash-patience-text {
    grid-row: 1;
    grid-column: 1;
    margin: 0;
    font-size: 0.82rem;
    line-height: 1.45;
    text-align: center;
    opacity: 0;
}

.splash-patience-text-1 {
    animation:
        splash-patience-in  0.9s ease 4.5s forwards,
        splash-patience-out 0.9s ease 18s  forwards;
}

.splash-patience-text-2 {
    animation: splash-patience-in 0.9s ease 18.5s forwards;
}

/* Fortschritt: blazor.webassembly.js meldet den Boot-Download über
   --blazor-load-percentage auf <html> (Anteil geladener Ressourcen nach Anzahl,
   nicht Bytes – springt daher leicht; die width-Transition glättet das).
   Fallback 0% zeigt bis zum ersten Progress-Event nur die leere Hairline.
   Der Farbverlauf ist die Rezeptur der .splash-loader-dots, damit der Balken
   kein Fremdkörper ist. Die Spur nimmt currentColor (= --ss-text-secondary)
   und folgt so auch dem Kerzenschein-Modus; das rgba ist der Fallback für
   Browser ohne color-mix. */
.splash-patience-bar {
    grid-row: 2;
    grid-column: 1;
    width: min(10rem, 56vw);
    height: 3px;
    border-radius: 999px;
    background: rgba(94, 104, 120, 0.22);
    background: color-mix(in srgb, currentColor 24%, transparent);
    overflow: hidden;
    opacity: 0;
    animation: splash-patience-in 0.9s ease 4.5s forwards;
}

.splash-patience-bar-fill {
    height: 100%;
    width: var(--blazor-load-percentage, 0%);
    border-radius: inherit;
    background: linear-gradient(90deg, var(--ss-accent), var(--ss-primary));
    transition: width 0.5s ease;
}

@keyframes splash-patience-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes splash-patience-out {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Sehr flache Viewports (Landscape-Handy): unten fehlt der Platz, der Hinweis
   liefe in die Ladepunkte → weglassen statt überlagern. */
@media (max-height: 520px) {
    .splash-patience {
        display: none;
    }
}

/* ── Responsive tweaks ── */
@media (max-width: 380px) {
    .splash {
        gap: 1rem;
        padding: 1rem;
    }

    .splash-panel {
        border-radius: 1.1rem;
    }

    .splash-logo {
        width: 56px;
        height: 56px;
        border-radius: 14px;
    }

    .splash-title {
        font-size: 1.35rem;
    }

    .splash-slogan {
        font-size: 0.84rem;
    }

    .splash-track span {
        font-size: 0.74rem;
    }

    .splash-patience-text {
        font-size: 0.76rem;
    }
}

/* ══════════════════════════════════════════════
   Wiederverwendbare Warte-Animation (WaitingSplashAnimation.razor)
   Nutzt die .splash-* Bausteine oben, ergänzt nur Layout + Bildunterschrift.
   ══════════════════════════════════════════════ */

.wait-splash {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 0.5rem 0;
}

.wait-splash .splash-questions-stage {
    margin: 0 auto;
}

.wait-splash-caption {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--ss-primary);
    text-align: center;
    max-width: 24rem;
}

.wait-splash-subcaption {
    margin: -0.4rem 0 0;
    font-size: 0.88rem;
    color: var(--ss-text-secondary);
    text-align: center;
    max-width: 24rem;
    line-height: 1.4;
}


/* ══════════════════════════════════════════════
   Fortschritts-Visualisierung (GameOverviewDots / QuestionPhaseStepper)
   Zwei Ebenen: Perlenkette „Spiel-Überblick" (ein Punkt je Frage) und
   Frage-Phasen-Stepper. Nur --ss-*-Tokens; Zustands-/Fensterlogik liegt
   testbar in SessionProgress.cs. Punkt-Geometrie (12px + 8px Lücke) muss
   zu SessionProgress.DotSizePx / GapPx passen (Filmstrip-Rechnung).
   ══════════════════════════════════════════════ */

/* ── Ebene 1: Perlenkette / Filmstrip ── */
.ss-progress-dots {
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 100%;
    margin-inline: auto;
}

/* Gefensterte Variante bei vielen Fragen: Ausschnitt + Verlaufskante.
   Breite (inline) und Transform (auf dem Track) kommen aus SessionProgress. */
.ss-progress-dots--windowed {
    justify-content: flex-start;
    overflow: hidden;
}

.ss-progress-track {
    display: flex;
    align-items: center;
    gap: 8px;
    width: max-content;
    padding: 4px 0;
    transition: transform 0.3s ease;
}

.ss-progress-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--ss-surface-muted);
    border: 1.5px solid var(--ss-border);
    flex: 0 0 auto;
    position: relative;
    transition: transform 0.2s ease;
}

.ss-progress-dot.is-done {
    background: var(--ss-primary);
    border-color: transparent;
}

/* Häkchen als zusätzliche, nicht-farbliche Unterscheidung „erledigt" */
.ss-progress-dot.is-done::after {
    content: "";
    position: absolute;
    inset: 0;
    margin: auto;
    width: 4px;
    height: 7px;
    border: solid var(--ss-primary-text);
    border-width: 0 1.5px 1.5px 0;
    transform: translateY(-1px) rotate(45deg);
}

.ss-progress-dot.is-current {
    background: var(--ss-accent);
    border-color: transparent;
    transform: scale(1.25);
    box-shadow: 0 0 0 4px var(--ss-accent-soft);
    animation: ss-progress-pulse 2s ease-in-out infinite;
}

@keyframes ss-progress-pulse {
    0%, 100% { box-shadow: 0 0 0 4px var(--ss-accent-soft); }
    50%      { box-shadow: 0 0 0 7px var(--ss-accent-soft); }
}

/* Gast-Variante: bewusst ruhiger – kein Puls, entsättigt, ohne Häkchen
   (erledigt = gefüllte Scheibe, offen = hohle Scheibe → Form als Cue). */
.ss-progress-dots--guest .ss-progress-dot.is-done {
    opacity: 0.85;
}

.ss-progress-dots--guest .ss-progress-dot.is-done::after {
    display: none;
}

.ss-progress-dots--guest .ss-progress-dot.is-current {
    animation: none;
    transform: scale(1.2);
    box-shadow: 0 0 0 3px var(--ss-accent-soft);
}

/* Verlaufskanten (Filmstrip): schwarz/transparent nur als Masken-Alpha, keine Farbe. */
.ss-progress-dots--fade-both {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 20%, #000 80%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 20%, #000 80%, transparent 100%);
}

.ss-progress-dots--fade-left {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 22%, #000 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 22%, #000 100%);
}

.ss-progress-dots--fade-right {
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 78%, transparent 100%);
            mask-image: linear-gradient(90deg, #000 0, #000 78%, transparent 100%);
}

/* ── Ebene 2: Frage-Phasen-Stepper (nur Moderation) ── */
.ss-progress-phase {
    margin-bottom: 1rem;
}

.ss-progress-stepper {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    position: relative;
    list-style: none;
    margin: 0;
    padding: 0;
}

.ss-progress-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 1;
    min-width: 0;
    position: relative;
    text-align: center;
}

.ss-progress-step-node {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--ss-surface-muted);
    border: 1.5px solid var(--ss-border);
    color: var(--ss-muted);
    font-size: 0.9rem;
    position: relative;
    z-index: 1;
    transition: all 0.25s ease;
}

.ss-progress-step-label {
    font-size: 0.74rem;
    margin-top: 0.5rem;
    color: var(--ss-muted);
    font-weight: 500;
    max-width: 7rem;
}

.ss-progress-step-sub {
    font-size: 0.66rem;
    color: var(--ss-muted);
    margin-top: 0.1rem;
}

/* Verbindungslinie zwischen den Knoten */
.ss-progress-step:not(:last-child)::after {
    content: "";
    position: absolute;
    top: 17px;
    left: 50%;
    width: 100%;
    height: 2px;
    background: var(--ss-border);
    z-index: 0;
}

.ss-progress-step.is-done .ss-progress-step-node {
    background: var(--ss-primary);
    border-color: transparent;
    color: var(--ss-primary-text);
}

.ss-progress-step.is-done::after {
    background: var(--ss-primary);
}

.ss-progress-step.is-done .ss-progress-step-label {
    color: var(--ss-text-secondary);
}

.ss-progress-step.is-current .ss-progress-step-node {
    background: var(--ss-accent);
    border-color: transparent;
    color: var(--ss-primary-text);
    box-shadow: 0 0 0 5px var(--ss-accent-soft);
    animation: ss-progress-pulse-node 2s ease-in-out infinite;
}

.ss-progress-step.is-current .ss-progress-step-label {
    color: var(--ss-accent-hover);
    font-weight: 700;
}

.ss-progress-step.is-current .ss-progress-step-sub {
    color: var(--ss-accent-hover);
}

@keyframes ss-progress-pulse-node {
    0%, 100% { box-shadow: 0 0 0 5px var(--ss-accent-soft); }
    50%      { box-shadow: 0 0 0 8px var(--ss-accent-soft); }
}

/* Kompakter Fallback (Beads) – per Breakpoint statt JS. */
.ss-progress-beads {
    display: none;
    align-items: center;
    gap: 0.35rem;
    background: var(--ss-surface-muted);
    border: 1px solid var(--ss-border);
    border-radius: 999px;
    padding: 0.4rem 0.7rem;
    width: max-content;
    max-width: 100%;
}

.ss-progress-bead {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--ss-surface);
    border: 1px solid var(--ss-border);
    flex: 0 0 auto;
}

.ss-progress-bead.is-done {
    background: var(--ss-primary);
    border-color: transparent;
}

.ss-progress-bead.is-current {
    width: 11px;
    height: 11px;
    background: var(--ss-accent);
    border-color: transparent;
    box-shadow: 0 0 0 3px var(--ss-accent-soft);
}

.ss-progress-beads-text {
    font-size: 0.76rem;
    color: var(--ss-text-secondary);
    margin-left: 0.35rem;
    font-weight: 600;
    white-space: nowrap;
}

/* Stepper hat Vorrang; wird es zu eng, übernimmt die Beads-Variante. */
@media (max-width: 575.98px) {
    .ss-progress-stepper { display: none; }
    .ss-progress-beads { display: inline-flex; }
}

@media (prefers-reduced-motion: reduce) {
    .ss-progress-dot.is-current,
    .ss-progress-step.is-current .ss-progress-step-node {
        animation: none;
    }

    .ss-progress-dot.is-current {
        transform: scale(1.2);
    }

    .ss-progress-track {
        transition: none;
    }
}

/* ══════════════════════════════════════════════
   Karten-Ensemble – Ergebnis-Präsentation (#116)
   ══════════════════════════════════════════════ */

/* Etwas seitlicher Innenraum: die gedrehten Ecken und die weichen Schatten
   brauchen „Luft" zum Spaltenrand, sonst wirkt das schräge Ensemble gequetscht. */
.ss-card-ensemble {
    padding-inline: clamp(0.25rem, 2vw, 0.9rem);
}

/* Bei der Ergebnis-Präsentation liegen die Karten wie auf den Tisch gelegte
   Einladungskarten leicht schräg. Deterministische Mini-Rotation über nth-child
   (kein JS, kein Zufall → stabil über Rerenders). Bewusst dosiert: nur die
   Karten-Grids der Ergebnisansichten tragen die Klasse – Tabellen, Formulare und
   Admin-Listen bleiben unangetastet. */
.ss-card-ensemble > .card {
    transform: rotate(var(--ss-ensemble-tilt, 0deg));
    transform-origin: center center;
    /* Großzügigerer vertikaler Rhythmus als das Standard-mb: Rotation und weiche
       Schatten brauchen Abstand, damit jede Karte einzeln „aufliegt", statt sich mit
       den Nachbarn zu einem dichten Band zu überlagern. Schlägt Bootstraps .mb-* per
       !important – bewusst, analog zum Schatten unten. */
    margin-bottom: clamp(1.75rem, 4vw, 2.5rem) !important;
    /* Taktiler Schatten: nah + weich kombiniert, damit die Karte spürbar „aufliegt". */
    box-shadow:
        0 1px 2px rgba(45, 30, 15, 0.10),
        0 10px 28px rgba(45, 30, 15, 0.10) !important;
}

/* ca. −1,4° bis +0,8°, zyklisch über fünf Positionen. */
.ss-card-ensemble > .card:nth-child(5n + 1) { --ss-ensemble-tilt: -1.4deg; }
.ss-card-ensemble > .card:nth-child(5n + 2) { --ss-ensemble-tilt:  0.8deg; }
.ss-card-ensemble > .card:nth-child(5n + 3) { --ss-ensemble-tilt: -0.7deg; }
.ss-card-ensemble > .card:nth-child(5n + 4) { --ss-ensemble-tilt:  0.5deg; }
.ss-card-ensemble > .card:nth-child(5n + 5) { --ss-ensemble-tilt: -1.1deg; }

/* Aufricht-Bewegung nur, wenn Bewegung erwünscht ist: die fokussierte/aktive Karte
   richtet sich gerade auf und hebt sich leicht. */
@media (prefers-reduced-motion: no-preference) {
    .ss-card-ensemble > .card {
        transition: transform 0.28s ease, box-shadow 0.28s ease;
    }

    .ss-card-ensemble > .card:hover,
    .ss-card-ensemble > .card:focus-within {
        --ss-ensemble-tilt: 0deg;
        box-shadow:
            0 2px 4px rgba(45, 30, 15, 0.12),
            0 16px 40px rgba(45, 30, 15, 0.15) !important;
    }
}

/* prefers-reduced-motion: keine Aufricht-Animation, Rotation statisch belassen
   (rein dekorativ) – der no-preference-Block oben greift dann schlicht nicht. */

/* Druck-Fallback: Rotation und taktiler Schatten entfallen, damit sauber gedruckt wird. */
@media print {
    .ss-card-ensemble > .card {
        transform: none;
        box-shadow: none !important;
    }
}

/* ══════════════════════════════════════════════
   Gold-Wellenlinie – Abschnittstrenner (#116)
   ══════════════════════════════════════════════ */

/* Kurze, handgezogen wirkende Wellenlinie in --ss-accent als Abschnittstrenner
   unter Überschriften. Inline-SVG in currentColor, zwei Varianten gegen sichtbare
   Wiederholung. Rein dekorativ (aria-hidden). */
.ss-wave-divider {
    color: var(--ss-accent);
    line-height: 0;
    margin: 0.35rem 0 1rem;
}

.ss-wave-divider svg {
    display: block;
    width: clamp(56px, 20%, 96px);
    height: auto;
}

.ss-wave-divider--center {
    text-align: center;
}

.ss-wave-divider--center svg {
    margin-inline: auto;
}

/* Druck-Fallback: die dekorative Linie entfällt im Druck. */
@media print {
    .ss-wave-divider {
        display: none;
    }
}

/* ══════════════════════════════════════════════
   20. Gäste-Scope „Große Schrift, große Ziele" (Issue #174, M1)
   Eigener Scope für die Gast-Routen (/join/**): Basisschrift 18 px, Zeilenhöhe ≥ 1,5,
   kein inhaltstragender Text unter 16 px und Tippziele ≥ 48 × 48 px (WCAG 2.5.8).
   Bewusst NICHT global — Moderation/Admin bleiben kompakt. Die Klasse .ss-guest
   setzen Join/Lobby/Play auf ihrem äußersten Container; sie komponiert mit dem
   Abendmodus (#115), weil dieser nur Farb-Token neu belegt.
   ══════════════════════════════════════════════ */

.ss-guest {
    /* Schriftgrößen-Faktor des A/A+-Schalters (#175 P3.1). Alle festen Größen im Gast-Scope
       rechnen damit; außerhalb greift überall der Fallback 1, sodass Moderation/Admin und
       die restliche App unberührt bleiben — auch wenn die Klasse auf <html> stehen bleibt. */
    --ss-guest-scale: 1;
    font-size: calc(1.125rem * var(--ss-guest-scale));
    line-height: 1.6;
}

/* „small" bleibt nur für echte Fußnoten kleiner — inhaltstragender Text (Statuszeile,
   Hilfetexte, Gruppenhinweise) landet damit bei 16 px statt 12–15 px. */
.ss-guest small,
.ss-guest .small,
.ss-guest .form-text,
.ss-guest .form-label,
.ss-guest .badge {
    font-size: calc(1rem * var(--ss-guest-scale));
}

.ss-guest .form-label {
    font-weight: 600;
}

.ss-guest h1 {
    font-size: calc(1.6rem * var(--ss-guest-scale));
}

/* Bootstraps Überschriften-/Lead-Klassen tragen feste rem-Werte und würden sonst als
   einzige nicht mitwachsen. Die Werte entsprechen exakt den Bootstrap-Größen — bei
   Faktor 1 ändert sich also nichts. */
.ss-guest .h4 {
    font-size: calc(1.5rem * var(--ss-guest-scale));
}

.ss-guest .h5 {
    font-size: calc(1.25rem * var(--ss-guest-scale));
}

.ss-guest .h6 {
    font-size: calc(1rem * var(--ss-guest-scale));
}

.ss-guest .lead {
    font-size: calc(1.25rem * var(--ss-guest-scale));
}

/* Tippziele: 48 px Mindesthöhe für alles Interaktive — auch für die Textlinks
   (btn-link/btn-sm), die im Gast-Bereich echte Bedienelemente sind. */
.ss-guest .btn,
.ss-guest .btn-sm,
.ss-guest .form-control,
.ss-guest .form-select,
.ss-guest .ss-status-chip {
    min-height: calc(3rem * var(--ss-guest-scale));
    font-size: calc(1.0625rem * var(--ss-guest-scale));
}

.ss-guest .btn-lg {
    min-height: calc(3.5rem * var(--ss-guest-scale));
    font-size: calc(1.15rem * var(--ss-guest-scale));
}

.ss-guest .btn-link {
    padding: 0.6rem 0.35rem;
    text-decoration: underline;
}

.ss-guest .ss-status-chip {
    padding: 0.55rem 0.95rem;
    font-size: calc(1rem * var(--ss-guest-scale));
}

/* Deaktivierte Gäste-Primärbuttons eindeutig als deaktiviert lesbar (#333): Bootstrap senkt
   nur die Deckkraft, ein deaktivierter „Weiter"/„Mitspielen" wirkt dann farblich fast aktiv.
   Neutrale, klar abgesetzte Fläche mit lesbarem Sekundärtext und not-allowed-Cursor. */
.ss-guest .btn-primary:disabled,
.ss-guest .btn-primary.disabled {
    background-color: var(--ss-surface-muted);
    border-color: var(--ss-border);
    color: var(--ss-text-secondary);
    opacity: 1;
    box-shadow: none;
    cursor: not-allowed;
}

/* Checkbox/Radio: Bootstraps 1 em ist als Tippziel zu klein — Fläche über das
   Label mitnehmen, damit der ganze Zeilentext trifft. */
.ss-guest .form-check-input {
    width: 1.4em;
    height: 1.4em;
    margin-top: 0.18em;
}

.ss-guest .form-check-label {
    padding: 0.35rem 0;
    cursor: pointer;
}

/* AGB-Consent-Zeile (#225): ganze Zeile tippbar, Tippziel >= 48 px (WCAG 2.5.8),
   ohne den schlanken Identity-Schritt optisch aufzublähen. */
.ss-guest .ss-consent-check {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.75rem 0.5rem;
    margin-left: 0;
    border-radius: 0.75rem;
    min-height: calc(3rem * var(--ss-guest-scale, 1));
}

.ss-guest .ss-consent-check .form-check-input {
    flex-shrink: 0;
    width: 1.6em;
    height: 1.6em;
    margin: 0.1rem 0 0 0;
    float: none;
}

.ss-guest .ss-consent-check .form-check-label {
    flex: 1 1 auto;
    padding: 0.1rem 0;
    cursor: pointer;
}

/* ── Code-Eingabe (#174 M2) ──
   Groß, zentriert, mit Buchstabenabstand. Die Großschreibung ist rein visuell —
   der getippte Wert bleibt unverändert, autocapitalize/autocomplete greifen weiter. */
.ss-code-input.form-control {
    text-align: center;
    text-transform: uppercase;
    letter-spacing: 0.2em;
    font-weight: 600;
    font-size: calc(1.6rem * var(--ss-guest-scale, 1));
    min-height: calc(3.75rem * var(--ss-guest-scale, 1));
    /* Der Buchstabenabstand hängt rechts am letzten Zeichen — optisch ausgleichen. */
    text-indent: 0.2em;
}

.ss-code-input.form-control::placeholder {
    letter-spacing: normal;
    text-transform: none;
    font-size: calc(1.125rem * var(--ss-guest-scale, 1));
    font-weight: 400;
}

/* ── Ruhiger Countdown (#174 M3) ──
   Fortschrittsbalken grün → gelb → orange plus große Ziffern statt rot pulsierendem
   Mini-Badge. Zeitdruck-Panik verleitet gerade ältere Gäste zu Fehltipps. */
.ss-countdown-value {
    font-size: calc(1.25rem * var(--ss-guest-scale, 1));
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--ss-text);
}

.ss-countdown-bar {
    height: 10px;
    border-radius: 999px;
    background: var(--ss-surface-muted);
    overflow: hidden;
}

.ss-countdown-bar-fill {
    height: 100%;
    border-radius: 999px;
    transition: width 0.9s linear, background-color 0.6s ease;
}

/* Die Füllung ist eine Grafik und muss sich mit ≥ 3:1 von der Bahn abheben (WCAG 1.4.11);
   das helle Warngelb kam auf 2,5:1 (Kontrast-Audit #175 P3.4). Grün → Bernstein → Orange
   bleibt als Eskalation erhalten, nur eine Stufe tiefer. */
.ss-countdown-calm { background-color: var(--ss-success); }
.ss-countdown-mid  { background-color: var(--ss-warning-text); }
.ss-countdown-late { background-color: var(--ss-countdown-late); }

@media (prefers-reduced-motion: reduce) {
    .ss-countdown-bar-fill {
        transition: none;
    }
}

/* ── Antwort-Buttons (#174 M3) ──
   Nebeneinander wie bisher (Zwei-Personen-Anmutung), aber je ~50 % der Zeilenbreite
   und ≥ 96 px hoch; der Name wird prominenter als das Icon und darf umbrechen. */
.ss-answer-row {
    display: flex;
    gap: 0.6rem;
    align-items: stretch;
}

.ss-answer-col {
    flex: 1 1 0;
    min-width: 0;
}

.ss-answer-btn {
    flex: 1 1 auto;
    width: 100%;
    min-height: calc(96px * var(--ss-guest-scale, 1));
    padding: 1rem 0.5rem;
    border-radius: var(--ss-radius-md);
    /* Lange Anzeigenamen brechen um, statt den Button zu sprengen. */
    white-space: normal;
    overflow-wrap: anywhere;
}

.ss-answer-icon {
    width: calc(72px * var(--ss-guest-scale, 1));
    height: calc(72px * var(--ss-guest-scale, 1));
    font-size: calc(2.2rem * var(--ss-guest-scale, 1));
    flex: none;
}

/* Soft-Antwort-Kreis mit Identitätsfarbe (#187).
   --ss-id kommt per Inline-Style aus GuestAnswerVisuals (konfigurierte oder Slot-Standardfarbe).
   Die Tönung (12 % Alpha) und der Ring (30 %) mischen sich über den jeweils darunter
   liegenden – also theme-passenden – Button-Grund, brauchen daher keinen Abendmodus-Zweig.
   Die Glyphe dagegen muss je Modus abgedunkelt (heller Grund) bzw. aufgehellt (dunkler
   Grund) werden, damit sie den hellen/dunklen Soft-Grund mit ≥ 3,6:1 trägt (Herleitung in
   docs/webapp-auth-ui-notes.md). Fallback --ss-primary nur zur Sicherheit, --ss-id ist gesetzt. */
.ss-id-soft {
    background-color: color-mix(in srgb, var(--ss-id, var(--ss-primary)) 12%, transparent);
    box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--ss-id, var(--ss-primary)) 30%, transparent);
}

.ss-id-soft > i {
    color: color-mix(in srgb, var(--ss-id, var(--ss-primary)) 70%, #000);
}

.ss-answer-name {
    font-size: calc(1.15rem * var(--ss-guest-scale, 1));
    font-weight: 700;
    line-height: 1.25;
}

/* ── Schriftgrößen-Umschalter „A / A+" (#175 P3.1) ──
   Der Schalter setzt js/guestTextScale.js die Klasse ss-guest-lg auf <html>; wirksam wird
   sie ausschließlich im Gast-Scope, weil nur dort --ss-guest-scale ausgewertet wird.
   +18 % über alle Größen (Schrift UND Tippziele) — genug, damit es ohne Lesebrille
   funktioniert, wenig genug, damit die Antwort-Buttons nebeneinander bleiben. */
html.ss-guest-lg .ss-guest {
    --ss-guest-scale: 1.18;
}

/* Das „A+" ist die Beschriftung des Schalters selbst und darf deshalb nicht mitwachsen —
   sonst zeigt der Knopf im großen Zustand seine eigene Wirkung statt seiner Aktion. */
.ss-text-scale-icon {
    font-weight: 700;
    font-size: 1rem;
    line-height: 1;
    letter-spacing: 0.02em;
}

/* ── Hilfe-Zugang (#175 P3.4, kollisionsfrei überarbeitet mit #330) ──
   Früher ein schwebender Eckknopf (position:fixed unten rechts). Auf schmalen Gäste-Screens
   (320–430 px) und im A+-Modus lag er über Fragenbewertung, Ergebnisaktionen oder
   Ergebniskarten. Jetzt steht der Auslöser als ruhiger Chip IM FLUSS unter dem Inhalt –
   dieselbe Sprache wie die Statuszeile (.ss-status-chip) – und überlagert damit in keiner
   Phase etwas. Nur das auf Tippen geöffnete Panel legt sich bewusst als Dialog darüber. */
.ss-help {
    margin-top: 1.25rem;
    text-align: center;
}

.ss-help-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.9rem;
    border: 1px solid var(--ss-border);
    border-radius: 999px;
    background: var(--ss-surface);
    box-shadow: var(--ss-shadow-sm);
    color: var(--ss-text-secondary);
    font-family: inherit;
    line-height: 1.2;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.ss-help-chip:hover,
.ss-help-chip:focus-visible {
    color: var(--ss-primary);
    border-color: var(--ss-primary);
    background: var(--ss-surface-muted);
}

/* Reiner Glyph, kein Rahmenkreis: fällt die Icon-Font aus, rendert fa-question ein echtes
   „?"; fällt die ganze FA-CSS aus, trägt die sichtbare „Hilfe"-Beschriftung den Knopf. So
   entsteht nie ein „leerer Kreis". */
.ss-help-chip__icon {
    font-size: 1rem;
    line-height: 1;
}

.ss-help-backdrop {
    position: fixed;
    inset: 0;
    /* Über PWA-Update-Banner (1100), -Chip (1090) und Toasts (1080/1085): der Dialog ist
       aria-modal und muss zuoberst liegen — sonst überlagert der Update-Chip das Bottom-Sheet. */
    z-index: 1110;
    background: rgb(0 0 0 / 25%);
}

.ss-help-panel {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
    z-index: 1111;
    width: min(24rem, calc(100vw - 2rem));
    padding: 1rem 1.1rem;
    border-radius: var(--ss-radius-md);
    border: 1px solid var(--ss-border);
    background: var(--ss-surface);
    box-shadow: var(--ss-shadow-lg, 0 8px 24px rgb(0 0 0 / 20%));
    text-align: left;
}

.ss-help-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.75rem;
    padding: 0.4rem 0;
    border-top: 1px solid var(--ss-border);
}

.ss-help-label {
    color: var(--ss-text-secondary);
}

.ss-help-value {
    font-weight: 700;
    text-align: right;
    overflow-wrap: anywhere;
}

/* ── „So funktioniert's" in der Wartezeit (#175 P3.2) ──
   Drei Schritte mit Symbol; erklärt das Spiel in der erzwungenen Wartezeit, ohne einen
   zusätzlichen Tipp zu verlangen. Die Größen hängen wie alles im Gast-Scope am A/A+-Faktor. */
.ss-howto {
    border: 1px solid var(--ss-border);
    border-radius: var(--ss-radius-md);
    background: var(--ss-surface-muted);
    padding: 0.9rem 1rem;
}

.ss-howto-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.ss-howto-step {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.ss-howto-icon {
    flex: none;
    width: calc(2.75rem * var(--ss-guest-scale, 1));
    height: calc(2.75rem * var(--ss-guest-scale, 1));
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--ss-primary-soft);
    color: var(--ss-primary);
    font-size: calc(1.35rem * var(--ss-guest-scale, 1));
}

.ss-howto-no {
    font-weight: 700;
    color: var(--ss-primary);
    margin-right: 0.35rem;
}

/* ── Probetipp in der Lobby (#322) ──
   Gehört sichtbar zur Erklärung darüber, ist aber ein eigener Block: gleicher Rahmen wie
   „So funktioniert's", damit klar ist, dass hier noch nichts zählt. Die Antwort-Kreise
   darin sind unverändert die des Ernstfalls – hier keine eigene Optik nachbauen. */
.ss-practice {
    /* Grid mit einer Zeile nur fürs Ausblenden: 1fr → 0fr lässt die Auto-Höhe weich
       zusammenfalten, ohne die Höhe per JS messen zu müssen. Der Inhalt liegt dafür
       in genau einem Kind (.ss-practice__inner). */
    display: grid;
    grid-template-rows: 1fr;
    border: 1px solid var(--ss-border);
    border-radius: var(--ss-radius-md);
    background: var(--ss-surface-muted);
    padding: 0.9rem 1rem;
    /* Opacity bewusst kürzer: erst verblassen, dann fertig zusammenfalten – der Inhalt
       darunter rutscht weich nach, statt zu springen. Dauer + Puffer muss HideAnimation
       in LobbyPracticeQuestion.razor abdecken. */
    transition: grid-template-rows 0.45s ease, opacity 0.3s ease,
                padding 0.45s ease, margin-bottom 0.45s ease, border-width 0.45s ease;
}

.ss-practice__inner {
    overflow: hidden;
    min-height: 0;
}

/* Das Kennzeichnungs-Badge („Nur zum Ausprobieren — zählt nicht") ist länger als eine
   schmale Card-Breite: Bootstrap-Badges sind nowrap und liefen auf Mobilgeräten über
   den Kartenrand (#360). Umbruch erlauben, balance hält beide Zeilen ähnlich lang. */
.ss-practice .badge {
    white-space: normal;
    text-wrap: balance;
    line-height: 1.35;
}

.ss-practice--hiding {
    grid-template-rows: 0fr;
    opacity: 0;
    /* Unsichtbar heißt nicht untippbar: Während der Transition dürfen die
       Antwortknöpfe keine Taps mehr annehmen. */
    pointer-events: none;
    padding-top: 0;
    padding-bottom: 0;
    border-width: 0;
    /* !important, weil das mb-3 der Section (Bootstrap-Utility) sonst gewinnt. */
    margin-bottom: 0 !important;
}

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

/* ── Account-Benefit-Karte (#174 M5) ──
   Das Account-Angebot ist ein Geschäftsziel: farblich abgesetzt und auffällig, aber
   nie blockierend. Erscheint an drei Stellen (Beitritt, Wartezeit, Ergebnis). */
.ss-benefit-card {
    border: 2px solid var(--ss-accent);
    border-radius: var(--ss-radius-md);
    background: var(--ss-accent-soft);
    padding: 1rem 1.1rem;
    margin-top: 1rem;
    text-align: left;
}

.ss-benefit-title {
    font-weight: 800;
    font-size: calc(1.1rem * var(--ss-guest-scale, 1));
    color: var(--ss-text);
    margin-bottom: 0.25rem;
}

.ss-benefit-text {
    color: var(--ss-text-secondary);
}

/* ── Ergebnis-Schlagzeile (#174 M6) ──
   „Lag ich richtig?" ist die einzige Frage, die der Gast in zwei Sekunden beantwortet
   haben will. Ein großes Symbol plus ein Klartext-Satz; die Statistik folgt darunter,
   die vollständige Aufschlüsselung liegt einen Tipp entfernt. */
.ss-result-lead {
    text-align: center;
    padding: 1rem 0.75rem;
    border-radius: var(--ss-radius-md);
    margin-bottom: 1rem;
}

.ss-result-icon {
    font-size: calc(2.25rem * var(--ss-guest-scale, 1));
    line-height: 1.1;
    margin-bottom: 0.35rem;
}

.ss-result-headline {
    font-weight: 700;
    font-size: calc(1.3rem * var(--ss-guest-scale, 1));
    line-height: 1.25;
}

.ss-result-sub {
    color: var(--ss-text-secondary);
    margin-top: 0.25rem;
}

/* Die Symbole tragen die Aussage mit (Haken/Kreuz/Augen) und müssen sich auf ihrer weichen
   Fläche abheben – dafür die Text-Token statt der Flächen-Token (Kontrast-Audit #175 P3.4). */
.ss-result-lead--hit     { background: var(--ss-success-soft); }
.ss-result-lead--hit .ss-result-icon { color: var(--ss-success-text); }
.ss-result-lead--miss    { background: var(--ss-warning-soft); }
.ss-result-lead--miss .ss-result-icon { color: var(--ss-warning-text); }
.ss-result-lead--fun     { background: var(--ss-accent-soft); }
.ss-result-lead--fun .ss-result-icon { color: var(--ss-accent-text); }
.ss-result-lead--neutral { background: var(--ss-surface-muted); }
.ss-result-lead--neutral .ss-result-icon { color: var(--ss-muted); }

/* Der Karten-Button trägt die Akzentfarbe – klar sekundär zum Mitspielen-Button,
   aber deutlich präsenter als ein Textlink. Weiß auf Champagner-Gold kam im Kontrast-Audit
   (#175 P3.4) nur auf 3,1:1 (hell) bzw. 2,0:1 (Abendmodus). Die Token drehen die Kombination
   deshalb pro Modus: hell tiefes Antikgold mit weißer Schrift, im Kerzenlicht helles Gold
   mit dunkler Schrift – die Gold-Anmutung bleibt, die Lesbarkeit stimmt in beiden. */
.btn-accent {
    color: var(--ss-accent-btn-text);
    background-color: var(--ss-accent-btn-bg);
    border-color: var(--ss-accent-btn-bg);
}

.btn-accent:hover,
.btn-accent:active,
.btn-accent:focus-visible {
    color: var(--ss-accent-btn-text);
    background-color: var(--ss-accent-btn-bg-hover);
    border-color: var(--ss-accent-btn-bg-hover);
}

/* ══════════════════════════════════════════════
   21. Abendmodus „Kerzenlicht" (Issue #115)
   Warmer Dunkelmodus für die Gäste-Seiten (/join/**). Reine Token-Redefinition
   auf <html class="ss-evening"> – die Klasse setzt js/eveningMode.js, gesteuert
   von den Join-Seiten anhand des effektiven Server-Flags (Setting UND Entitlement).
   Bewusst @media screen: Druck bleibt immer hell (die :root-Print-Werte in
   Sektion 19 greifen wieder, weil dieser Block im Druck nicht existiert).
   ══════════════════════════════════════════════ */

@media screen {
    html.ss-evening {
        color-scheme: dark;

        /* ── Backgrounds ── */
        --ss-bg:               #1f1a14;
        --ss-bg-soft:          #191410;
        --ss-bg-warm-highlight: rgba(214, 152, 66, 0.1);

        /* ── Surfaces ── */
        --ss-surface:          #2a2219;
        --ss-surface-strong:   #322820;
        --ss-surface-muted:    #241d16;

        /* ── Borders ── */
        --ss-border:           #3c3225;
        --ss-border-light:     #332a20;

        /* ── Text ── */
        --ss-text:             #f2e9db;
        --ss-text-secondary:   #c9bda8;
        --ss-muted:            #a99c86;

        /* ── Primary – für Warm-Dunkel angehoben (AA auf #1f1a14) ── */
        --ss-primary:          #7fb2e6;
        --ss-primary-hover:    #9cc4ee;
        --ss-primary-soft:     rgba(127, 178, 230, 0.15);
        --ss-primary-text:     #10202f;

        /* ── Accent – Champagner-Gold trägt auf warmem Dunkel weiter ── */
        --ss-accent-hover:     #d4b478;
        --ss-accent-soft:      rgba(196, 162, 101, 0.16);
        --ss-accent-ghost:     rgba(196, 162, 101, 0.4);

        /* ── Semantic – angehoben (AA auf #1f1a14) ── */
        --ss-success:          #6cc48f;
        --ss-success-soft:     rgba(108, 196, 143, 0.14);
        --ss-danger:           #eb8b73;
        --ss-danger-soft:      rgba(235, 139, 115, 0.14);
        --ss-warning:          #e6a34a;
        --ss-warning-soft:     rgba(230, 163, 74, 0.14);
        --ss-info:             #6bb0d8;
        --ss-info-soft:        rgba(107, 176, 216, 0.14);

        /* ── Text-/Flächen-Varianten (Kontrast-Audit #175 P3.4) ──
           Auf warmem Dunkel tragen die angehobenen Semantikfarben auch als Schrift
           (≥ 5:1 bis auf die hellste Glas-Fläche); der gefüllte Gold-Knopf dreht sich um:
           helles Gold mit dunklem Text (8,4:1) statt Weiß auf Gold (2,0:1). ── */
        --ss-warning-text:     #e6a34a;
        --ss-success-text:     #6cc48f;
        --ss-danger-text:      #eb8b73;
        --ss-info-text:        #6bb0d8;
        --ss-accent-text:      #d4b478;
        --ss-accent-btn-bg:       #d4b478;
        --ss-accent-btn-bg-hover: #c4a265;
        --ss-accent-btn-text:     #10202f;
        --ss-countdown-late:   #d97a2b;

        /* ── Shadows/Focus – schwarzbasiert bzw. gold statt blau ── */
        --ss-shadow-sm:        0 1px 3px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2);
        --ss-shadow-md:        0 4px 16px rgba(0, 0, 0, 0.35), 0 1px 4px rgba(0, 0, 0, 0.2);
        --ss-shadow-lg:        0 12px 36px rgba(0, 0, 0, 0.45), 0 2px 8px rgba(0, 0, 0, 0.25);
        --ss-focus-ring:       0 0 0 0.18rem rgba(196, 162, 101, 0.4);

        /* ── Glass für dunklen Grund ── */
        --ss-glass-bg:          linear-gradient(165deg, rgba(58, 48, 35, 0.78) 0%, rgba(38, 31, 22, 0.6) 100%);
        --ss-glass-bg-fallback: rgba(42, 34, 25, 0.94);
        --ss-glass-border:      rgba(214, 184, 132, 0.16);
        --ss-glass-highlight:   inset 0 1px 0 rgba(255, 236, 206, 0.07);
        --ss-glass-shadow:      0 16px 40px rgba(0, 0, 0, 0.5);
        --ss-glass-surface:     rgba(42, 34, 25, 0.9);

        /* ── Bootstrap-Variablen für nicht token-gemappte Utilities
             (bg-white/bg-light/bg-body-secondary/text-body-secondary,
             bg-*-Opacity-Mischungen, Inline-var(--bs-…)-Icon-Farben) ── */
        --bs-body-bg:          #1f1a14;
        --bs-body-color:       #f2e9db;
        --bs-body-color-rgb:   242, 233, 219;
        --bs-secondary-bg:     #322820;
        --bs-secondary-bg-rgb: 50, 40, 32;
        --bs-secondary-color:  #c9bda8;
        --bs-border-color:     #3c3225;
        --bs-primary:          #7fb2e6;
        --bs-secondary:        #c9bda8;
        --bs-success:          #6cc48f;
        --bs-danger:           #eb8b73;
        --bs-warning:          #e6a34a;
        --bs-info:             #6bb0d8;
        --bs-primary-rgb:      127, 178, 230;
        --bs-secondary-rgb:    201, 189, 168;
        --bs-success-rgb:      108, 196, 143;
        --bs-danger-rgb:       235, 139, 115;
        --bs-warning-rgb:      230, 163, 74;
        --bs-info-rgb:         107, 176, 216;
        --bs-light-rgb:        50, 40, 32;
        --bs-white-rgb:        42, 34, 25;
    }

    /* Ember-Glow statt heller Creme-Radials (eine ruhige Kerzenlicht-Geste). */
    html.ss-evening body::before {
        background:
            radial-gradient(58% 42% at 50% -4%, rgba(214, 152, 66, 0.16) 0%, transparent 62%),
            radial-gradient(40% 30% at 82% 8%, rgba(180, 120, 50, 0.08) 0%, transparent 60%);
    }

    /* Alert-Textfarben sind in Sektion 5 hart dunkel → auf warm-hell nachziehen. */
    html.ss-evening .alert-danger  { border-color: rgba(235, 139, 115, 0.3);  color: #f2b6a6; }
    html.ss-evening .alert-success { border-color: rgba(108, 196, 143, 0.3);  color: #a9dfbf; }
    html.ss-evening .alert-warning { border-color: rgba(230, 163, 74, 0.3);   color: #eec48c; }
    html.ss-evening .alert-info    { border-color: rgba(107, 176, 216, 0.3);  color: #accfe4; }

    /* Badges: die angehobenen Evening-Farben sind hell → dunkle Badge-Texte
       (weißer Bootstrap-Default fiele unter AA). */
    html.ss-evening .text-bg-primary,
    html.ss-evening .badge.text-bg-primary   { color: #10202f !important; }
    html.ss-evening .text-bg-secondary,
    html.ss-evening .badge.text-bg-secondary { color: #1f1a14 !important; }
    html.ss-evening .text-bg-success,
    html.ss-evening .badge.text-bg-success   { color: #082213 !important; }
    html.ss-evening .text-bg-danger,
    html.ss-evening .badge.text-bg-danger    { color: #2a0f08 !important; }
    html.ss-evening .text-bg-warning,
    html.ss-evening .badge.text-bg-warning   { color: #2a1c06 !important; }
    html.ss-evening .text-bg-info,
    html.ss-evening .badge.text-bg-info      { color: #08222f !important; }

    /* Bestätigungs-Haken (ss-confirm-check): der Badge-Grund ist var(--bs-success) und
       damit im Abendmodus das angehobene helle Grün → der weiße Strich fiele auf ~2:1.
       Dunkler Strich analog zu den Badge-Texten oben. */
    html.ss-evening .ss-confirm-check path { stroke: #082213; }

    /* Soft-Antwort-Glyphe (#187): auf dem dunklen Kerzenlicht-Grund wird die Identitätsfarbe
       aufgehellt statt abgedunkelt, damit sie ≥ 3,6:1 trägt. Tönung/Ring bleiben (mischen
       sich ohnehin über den dunklen Grund). */
    html.ss-evening .ss-id-soft > i {
        color: color-mix(in srgb, var(--ss-id, var(--ss-primary)) 62%, #fff);
    }

    /* Bootstrap bäckt den hellen Select-Pfeil als Variable in .form-select ein
       (dunkler Stroke #343a40) – auf dunklem Feld unsichtbar → heller Pfeil. */
    html.ss-evening .form-select {
        --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23c9bda8' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    }

    /* Bootstraps schwarzes Schließen-X ist auf dunklen Alerts unsichtbar –
       denselben Weiß-Filter anwenden, den Bootstrap unter data-bs-theme=dark nutzt. */
    html.ss-evening .btn-close {
        filter: var(--bs-btn-close-white-filter);
    }

    /* Boot-Splash (index.html) hat einen fest hellen Verlauf; beim Reload im dunklen
       Saal setzt js/eveningMode.js die Klasse bereits vor Blazor-Start → auch der
       Splash muss warm-dunkel können. */
    html.ss-evening .splash {
        background:
            radial-gradient(120% 70% at 10% 8%, rgba(214, 152, 66, 0.14) 0%, transparent 58%),
            radial-gradient(100% 65% at 88% 16%, rgba(180, 120, 50, 0.08) 0%, transparent 62%),
            linear-gradient(155deg, #241d16 0%, #1f1a14 34%, #191410 100%);
    }

    /* Warte-Splash: die zwei bewusst hell hartkodierten Rezepturen nachziehen. */
    html.ss-evening .splash-focus-line {
        background: linear-gradient(90deg, rgba(66, 53, 36, 0.85), rgba(80, 65, 44, 0.9), rgba(66, 53, 36, 0.85));
        border-color: rgba(214, 184, 132, 0.3);
        box-shadow:
            inset 0 1px 0 rgba(255, 236, 206, 0.08),
            0 4px 12px rgba(0, 0, 0, 0.3);
    }

    html.ss-evening .splash-loader {
        border-color: rgba(214, 184, 132, 0.2);
        background: rgba(42, 34, 25, 0.6);
        box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35);
    }

    /* ALTCHA-Widget (Register/Login, #188): das Custom Element bringt eine eigene helle
       Default-Palette mit – auf die Abend-Token mappen, damit es im Kerzenlicht nicht
       als weißer Kasten leuchtet (Custom Properties durchdringen das Shadow DOM). */
    html.ss-evening altcha-widget {
        --altcha-color-base: var(--ss-surface);
        --altcha-color-text: var(--ss-text);
        --altcha-color-border: var(--ss-border);
        --altcha-color-border-focus: var(--ss-accent-hover);
        --altcha-color-error-text: var(--ss-danger-text);
        --altcha-color-footer-bg: var(--ss-surface-muted);
    }
}

/* ══════════════════════════════════════════════
   22. Wortmarke „Schuhspiel.de" (Logo)
   Quelle: resources/Logo.svg. Die Zeichnung wird als Inline-SVG ausgeliefert
   (Components/BrandWordmark.razor bzw. im Boot-Splash direkt in index.html) und
   NICHT als <img> — nur inline greifen currentColor und die Farb-Tokens.

   Zwei Farbrollen statt zwei fixer Hex-Werte:
     .ss-logo-ink    → currentColor  (Wortmarke + High-Heel-i)
     .ss-logo-accent → --ss-accent   (".de", i-Punkt, Punkt im „l")
   Damit trägt eine Zeichnung alle drei Auftritte:
     hell        → --ss-primary (#3b6d9c), 6,6:1 auf --ss-bg
     Navbar      → weiß; die Navbar ist in BEIDEN Modi dunkel (#2c3642),
                   das Markenblau käme dort nur auf 2,2:1
     Kerzenschein→ --ss-text (#f2e9db); Blau bliebe bei 3,2:1 hängen
   Das Gold bleibt in allen Fällen unverändert (im Kerzenschein sogar 7,2:1).
   ══════════════════════════════════════════════ */

.ss-logo {
    display: block;
    height: 2rem;
    width: auto;
    /* Pflicht: ein Inline-<svg> mit width:auto fällt sonst auf die SVG-Defaultbreite
       von 300px zurück und zentriert die Zeichnung darin (preserveAspectRatio) –
       sichtbarer Leerraum links und rechts. */
    aspect-ratio: 402 / 78;
    flex: none;
    color: var(--ss-primary);
}

.ss-logo-ink    { fill: currentColor; }
.ss-logo-accent { fill: var(--ss-accent); }

/* Navbar: in beiden Modi dunkel → weiße Wortmarke. */
.navbar .ss-logo {
    height: 1.75rem;
    color: #fff;
}

/* Boot-Splash: große Markenbühne. */
.splash-brand .ss-logo {
    height: 2.4rem;
    margin-bottom: 0.1rem;
}

/* Startseite (#178). Die Wortmarke tritt zweimal auf und muss dabei eine klare
   Rangfolge halten – sonst konkurrieren zwei gleich große Schriftzüge auf einem Screen:
     .ss-logo-hero   → die Überschrift selbst, zentriert (.ss-logo ist display:block,
                       deshalb zentriert margin-inline und nicht text-align des Elternteils)
     .ss-logo-lockup → Briefkopf der Einladungs-Karte, links wie der Kartentext,
                       deutlich kleiner und damit erkennbar nachgeordnet */
.ss-logo-hero {
    height: 2.75rem;
    margin-inline: auto;
}

.ss-logo-lockup {
    height: 1.3rem;
}

/* Kerzenschein: Creme statt Blau (siehe Sektion 21). Bewusst @media screen –
   im Druck bleibt das Markenblau. */
@media screen {
    html.ss-evening .splash-brand .ss-logo {
        color: var(--ss-text);
    }
}

/* ══════════════════════════════════════════════
   23. Beameransicht „Präsentationsmodus" (Issue #197)
   Vollbild-Präsentationsseiten (/presentation/**, Moderationsvorschau). Eigener
   Scope .ss-presentation mit lokalen bm-Tokens: die Default-Werte entsprechen 1:1
   dem Kerzenlicht-Scope html.ss-evening (Sektion 21), hängen hier aber bewusst NICHT
   am Abendmodus-Schalter der Gäste-Ansicht — die Leinwand hat ihren eigenen Modus.
   Den setzt die Moderation: .bm-stage--light kippt die Tokens auf hell (heller Saal,
   schwacher Beamer). Deshalb steht die Modus-Klasse auf der Bühne und nicht auf
   .ss-presentation — nur die Bühne kennt den Präsentations-State.
   Verbindliche Vorlage: UX-Mock beamer-praesentationsmodus.html. 16:9-freundlich,
   aber Vollbild = ganzer Viewport (fixed inset 0 ≙ 100dvh), nicht letterboxed.
   ══════════════════════════════════════════════ */

.ss-presentation {
    /* ── Lokale Tokens (Werte aus html.ss-evening) ── */
    --bm-bg:             #1f1a14;
    --bm-bg-soft:        #191410;
    --bm-surface:        #2a2219;
    --bm-surface-strong: #322820;
    --bm-border:         #3c3225;
    --bm-text:           #f2e9db;
    --bm-text-secondary: #c9bda8;
    --bm-muted:          #a99c86;
    --bm-gold:           #d4b478;
    --bm-gold-hover:     #c4a265;
    --bm-gold-ink:       #10202f;
    /* Goldkontur für Chips und Fokus — als Token, weil der helle Modus ein anderes Gold trägt. */
    --bm-gold-soft:      rgba(212, 180, 120, 0.5);
    /* Untergrund der Eck-Hinweise (Testansicht/Verbindung): leicht abgesetzt, nie deckend. */
    --bm-overlay:        rgba(42, 34, 25, 0.8);
    --bm-success:        #6cc48f;
    --bm-warning:        #e6a34a;
    --bm-danger:         #eb8b73;
    --bm-radius:         1.15rem;
    --bm-font-display:   "Josefin Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
    --bm-font-sans:      system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

    position: fixed;
    inset: 0;
    z-index: 1050;
    overflow: auto;
    background: var(--bm-bg);
    color: var(--bm-text);
    font-family: var(--bm-font-display);
    color-scheme: dark;
}

/* Ember-Glow wie im Kerzenlicht-Scope — eine ruhige Geste, kein Effektfeuerwerk.

   Der Glow atmet langsam. Das ist kein Schmuck, sondern der Lebendigkeits-Nachweis der
   Leinwand: Zwischen zwei Moderationsaktionen steht der Screen sonst absolut still, und
   ein stillstehendes Bild liest der Saal als „hängt". Ein Puls über die ganze Fläche wirkt
   auf JEDEM Screen, ohne dass ein einzelner Screen etwas dafür tun muss.

   Bewusst nur opacity und bewusst flach (0.72–1 über 9 s): eine große, langsam animierte
   Verlaufsfläche ist genau der Fall, in dem lichtschwache Beamer Banding zeigen. Kein
   transform — das verschöbe die Gradient-Zentren sichtbar. */
.ss-presentation::before {
    content: "";
    position: fixed;
    inset: 0;
    pointer-events: none;
    background:
        radial-gradient(58% 42% at 50% -4%, rgba(214, 152, 66, 0.16) 0%, transparent 62%),
        radial-gradient(40% 30% at 82% 8%, rgba(180, 120, 50, 0.08) 0%, transparent 60%);
    animation: bm-ember-breathe 9s ease-in-out infinite alternate;
}

@keyframes bm-ember-breathe {
    from { opacity: 0.72; }
    to   { opacity: 1; }
}

/* ── Bühne & Screen-Gerüst ── */

.bm-stage {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    min-height: 100%;
}

/* Heller Leinwand-Modus (von der Moderation geschaltet). Reine Token-Umdefinition — kein
   einziger bm-Baustein unten kennt den Modus. Die Bühne trägt hier zusätzlich selbst den
   Hintergrund: .ss-presentation bleibt darunter dunkel, und der Ember-Glow (::before)
   verschwindet damit im hellen Modus von allein, ohne eigene Regel.

   Gold: im Hellen NICHT das Kerzen-Gold #d4b478 (auf hellem Grund nur ~2,2:1), sondern das
   dunklere --ss-accent-text #7f6229 aus Sektion 1 (5,3:1) — sonst wären Prozentzahl und
   „Schuhe hoch!" ausgerechnet im hellen Saal am schlechtesten lesbar. */
.bm-stage--light {
    --bm-bg:             #faf7f2;
    --bm-bg-soft:        #f5f0e9;
    --bm-surface:        #ffffff;
    --bm-surface-strong: #ece5da;
    --bm-border:         #e4ddd3;
    --bm-text:           #2c3642;
    --bm-text-secondary: #5e6878;
    --bm-muted:          #626b78;
    --bm-gold:           #7f6229;
    --bm-gold-hover:     #6d5323;
    --bm-gold-ink:       #ffffff;
    --bm-gold-soft:      rgba(127, 98, 41, 0.45);
    --bm-overlay:        rgba(255, 255, 255, 0.85);
    --bm-success:        #3a8a5c;
    --bm-warning:        #c49036;
    --bm-danger:         #c4493a;

    background: var(--bm-bg);
    color: var(--bm-text);
    color-scheme: light;
}

.bm-screen {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: clamp(20px, 3.2vw, 48px);
}

.bm-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    min-height: clamp(48px, 6vw, 92px);
    font-size: clamp(14px, 1.5vw, 22px);
    letter-spacing: 0.06em;
    color: var(--bm-text-secondary);
    font-family: var(--bm-font-sans);
}

/* Kopfzeile ohne zweiten Inhalt (Abschluss): die Wortmarke steht mittig als Signatur. */
.bm-top--center {
    justify-content: center;
}

/* Wortmarke auf der Leinwand (Sektion 22 liefert die Zeichnung). Statt des früheren
   Schriftzugs „Schuhspiel" jetzt das echte Logo — deshalb hier die Farbrollen an die
   bm-Tokens hängen: Schrift in Textfarbe (Creme bzw. dunkles Blaugrau), „.de"/i-Punkt im
   jeweiligen Gold. Ohne diese Regel zöge .ss-logo das helle --ss-primary und stünde im
   Kerzenlicht bei ~3:1. */
.ss-presentation .ss-logo {
    color: var(--bm-text);
}

.ss-presentation .ss-logo-accent {
    fill: var(--bm-gold);
}

.bm-logo {
    height: clamp(18px, 2vw, 30px);
}

/* Signatur unter dem Schlussbild und Markenkopf der Connect-Seite: bewusst größer. */
.bm-logo--finale {
    height: clamp(24px, 2.8vw, 44px);
}

.bm-logo--connect {
    height: clamp(26px, 3vw, 40px);
}

.bm-mid {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: clamp(10px, 2vw, 26px);
}

.bm-mid--wide-gap {
    gap: clamp(18px, 2.6vw, 40px);
}

.bm-mid--tight-gap {
    gap: clamp(12px, 2vw, 28px);
}

/* ── Typo-Bausteine ── */

.bm-q {
    font-size: clamp(28px, 4vw, 64px);
    font-weight: 500;
    line-height: 1.15;
    letter-spacing: 0.01em;
    max-width: 24ch;
    color: var(--bm-text);
    text-wrap: balance;
}

.bm-q--title {
    font-size: clamp(34px, 5vw, 80px);
    max-width: none;
}

.bm-q--small {
    font-size: clamp(22px, 3.3vw, 52px);
}

.bm-sub {
    font-size: clamp(15px, 1.7vw, 26px);
    color: var(--bm-text-secondary);
    letter-spacing: 0.05em;
    font-family: var(--bm-font-sans);
}

.bm-big {
    font-size: clamp(40px, 6.5vw, 110px);
    font-weight: 600;
    color: var(--bm-gold);
    letter-spacing: 0.02em;
    line-height: 1;
}

.bm-code {
    font-size: clamp(30px, 4.4vw, 72px);
    font-weight: 600;
    letter-spacing: 0.24em;
    color: var(--bm-text);
}

/* ── Antwort-Optionen (Karten & Chips) ── */

.bm-opts {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: clamp(12px, 2vw, 32px);
}

.bm-opt {
    display: flex;
    align-items: center;
    gap: clamp(10px, 1vw, 16px);
    padding: clamp(12px, 1.8vw, 28px) clamp(20px, 3vw, 48px);
    border-radius: var(--bm-radius);
    background: var(--bm-surface);
    border: 0.5px solid var(--bm-border);
    font-size: clamp(20px, 2.6vw, 42px);
    color: var(--bm-text);
}

.bm-opt i {
    font-size: 0.85em;
    color: var(--bm-text-secondary);
}

.bm-chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: clamp(10px, 1.4vw, 20px);
}

.bm-chip {
    display: flex;
    align-items: center;
    gap: 0.5em;
    padding: clamp(6px, 0.9vw, 12px) clamp(14px, 1.8vw, 28px);
    border-radius: 999px;
    background: var(--bm-surface);
    border: 0.5px solid var(--bm-border);
    font-size: clamp(15px, 1.8vw, 26px);
    color: var(--bm-text-secondary);
    font-family: var(--bm-font-sans);
}

.bm-chip i {
    font-size: 0.9em;
}

/* Uneinige Paarantworten: beide Nennungen tragen Gold, bleiben aber Chips. */
.bm-chip--gold {
    border-color: var(--bm-gold-soft);
    color: var(--bm-text);
    font-family: var(--bm-font-display);
    font-size: clamp(18px, 2.2vw, 34px);
}

/* ── Balken, Labels, Pill ── */

.bm-row {
    display: flex;
    flex-direction: column;
    gap: clamp(6px, 1vw, 14px);
    width: min(72%, 640px);
}

.bm-row--center {
    align-self: center;
}

.bm-lab {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    font-size: clamp(14px, 1.7vw, 24px);
    color: var(--bm-text-secondary);
    font-family: var(--bm-font-sans);
}

.bm-lab--muted {
    color: var(--bm-muted);
}

.bm-bar {
    width: 100%;
    height: clamp(12px, 1.6vw, 20px);
    background: var(--bm-surface-strong);
    border-radius: 999px;
    overflow: hidden;
}

.bm-fill {
    height: 100%;
    background: var(--bm-gold);
    border-radius: inherit;
    transition: width 0.6s ease;
}

.bm-fill--muted {
    background: var(--bm-muted);
}

.bm-pill {
    background: var(--bm-gold);
    color: var(--bm-gold-ink);
    font-size: clamp(14px, 1.8vw, 24px);
    font-weight: 500;
    padding: 0.35em 1em;
    border-radius: 999px;
    font-family: var(--bm-font-sans);
    white-space: nowrap;
}

/* ── QR, Gästezähler, Countdown-Ring ── */

.bm-qr {
    width: clamp(110px, 16vw, 220px);
    height: clamp(110px, 16vw, 220px);
    padding: clamp(6px, 0.8vw, 12px);
    background: #ffffff;
    border-radius: 0.75rem;
    image-rendering: pixelated;
}

.bm-dot {
    display: inline-block;
    width: clamp(9px, 0.8vw, 13px);
    height: clamp(9px, 0.8vw, 13px);
    border-radius: 50%;
    background: var(--bm-success);
    margin-right: 0.5em;
    vertical-align: middle;
}

.bm-ring {
    display: flex;
    align-items: center;
    justify-content: center;
    width: clamp(52px, 6vw, 92px);
    height: clamp(52px, 6vw, 92px);
    border-radius: 50%;
    border: 3px solid var(--bm-gold);
    font-size: clamp(17px, 2vw, 30px);
    font-weight: 500;
    color: var(--bm-text);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

/* ── Lobby: kompaktes 720p-Höhenbudget (#331) ──
   Befund aus dem Beamer-UX-Audit: die Lobby war bei 1280×720 rund 56 px zu hoch
   (scrollHeight 776 > clientHeight 720) und scrollte. Kompaktiert wird gezielt über
   Abstände, Marken-/Titel- und QR-Maße — NICHT über pauschales Herunterskalieren:
   QR-Code und Join-Code bleiben deutlich größer als Fließtext und aus Raumdistanz nutzbar.
   Bewusst bleibt sichtbare Luft unter den Beitritts-Elementen erhalten, damit das spätere
   Lobby-Vorspann-Band (#324) ins selbe Budget passt. Scope: nur die Lobby, die übrigen
   Phasen (offene Frage, Auflösung, Abschluss) behalten ihre großzügigere Maßstäblichkeit. */
.bm-screen--lobby {
    padding-top: clamp(14px, 1.8vw, 28px);
    padding-bottom: clamp(14px, 1.8vw, 28px);
}

.bm-screen--lobby .bm-top {
    min-height: clamp(34px, 3.6vw, 54px);
}

.bm-screen--lobby .bm-mid {
    gap: clamp(7px, 1.1vw, 16px);
}

/* Paarnamen tragen weiter die Begrüßung, nur etwas gebändigt gegenüber dem generischen Titel. */
.bm-screen--lobby .bm-q--title {
    font-size: clamp(28px, 3.6vw, 56px);
}

/* ── Beitrittsadresse in der Lobby (#334) ──
   Neben QR- und Join-Code eine ausgeschriebene Adresse, damit Gäste ohne funktionierende
   Kamera wissen, welche Seite sie öffnen sollen. Gold hervorgehoben und aus Raumdistanz lesbar. */
.bm-join-hint {
    max-width: 36ch;
    line-height: 1.4;
    text-wrap: balance;
}

.bm-join-url {
    color: var(--bm-gold);
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    /* Etwas größer als der umgebende Hinweis, damit die Adresse aus Raumdistanz trägt. */
    font-size: 1.12em;
}

/* ── Lobby-Vorspann (#324, Stufe 1.4) ──
   Zwei Elemente über der bestehenden Lobby: die Tageszeit-Begrüßung (E7) als ruhige Zeile über
   der Paar-Begrüßung und ein Ticker-Band unterhalb der Beitritts-Elemente. QR-Code und Join-Code
   bleiben in BEIDEN Phasen (Preparation/Lobby) unverändert stehen — kein Vollbild-Wechsel im Takt.
   Die Band-Höhe ist reserviert (min-height), damit der Zeilenwechsel den Join-Code darüber nicht
   verschiebt (auf der Leinwand ist jede Layout-Bewegung sichtbar). Typografie aus den bm-Tokens,
   NICHT die Handy-Variante hochskaliert. Verbindliche Vorlage: 324-lobby-vorspann-beamer-mockup.html. */

/* Tageszeit-Begrüßung: ein bm-sub-Geschwister, das die Paar-Namen bewusst nicht überstrahlt.
   Wechselt nur beim Rollover (der Server rendert sie bei jedem State neu), nie im Ticker-Takt. */
.bm-greet {
    color: var(--bm-gold);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-size: clamp(13px, 1.4vw, 21px);
}

.bm-ticker {
    margin-top: clamp(5px, 0.7vw, 12px);
    padding-top: clamp(5px, 0.7vw, 12px);
    border-top: 0.5px solid var(--bm-border);
    width: min(92%, 1000px);
    min-height: clamp(20px, 1.9vw, 34px);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Zeilenbreite in ch auf das Element mit der Schriftgröße begrenzen — nicht auf das Band, sonst
   rechnet ch gegen die geerbte Größe und das Band fällt viel zu schmal aus (Muster .bm-q). */
.bm-ticker__line {
    font-family: var(--bm-font-sans);
    font-size: clamp(13px, 1.45vw, 23px);
    line-height: 1.3;
    max-width: 52ch;
    color: var(--bm-text-secondary);
    text-wrap: balance;
    opacity: 1;
    transition: opacity 600ms ease;
}

.bm-ticker__line[data-fading="true"] {
    opacity: 0;
}

/* Die Kür ist die persönliche Zeile im Feld der Datenzeilen — hebt sich minimal ab: kein Kasten,
   keine Farbe, nur die Textfarbe eine Stufe heller. */
.bm-ticker__line[data-kind="custom"] {
    color: var(--bm-text);
}

/* Phase Lobby: das Band muss im 720p-Budget bezahlt werden (das Original füllt 16:9 bereits aus,
   #331). Zwei behutsame Hebel — engere bm-mid-Abstände und ein etwas kleinerer QR-Code —, beide
   ausdrücklich verhandelbar; die Existenz von QR und Join-Code ist es NICHT. Höhere Spezifität als
   die #331-Basisregeln, die für Preparation unberührt bleiben. */
.bm-screen--lobby[data-phase="lobby"] .bm-mid {
    gap: clamp(4px, 0.72vw, 10px);
}

.bm-screen--lobby[data-phase="lobby"] .bm-qr {
    width: clamp(110px, 9.6vw, 146px);
    height: clamp(110px, 9.6vw, 146px);
}

/* Phase Preparation (aufgetrennt von Lobby): es müssen noch keine Gäste beitreten, also darf der
   Vorspann breiter und größer laufen; QR und Code treten zurück — verschwinden aber NIE. */
.bm-screen--lobby[data-phase="preparation"] .bm-qr {
    width: clamp(104px, 9.5vw, 148px);
    height: clamp(104px, 9.5vw, 148px);
}

.bm-screen--lobby[data-phase="preparation"] .bm-code {
    font-size: clamp(24px, 3.4vw, 52px);
}

.bm-screen--lobby[data-phase="preparation"] .bm-ticker {
    width: min(94%, 1200px);
    min-height: clamp(40px, 4.4vw, 72px);
}

.bm-screen--lobby[data-phase="preparation"] .bm-ticker__line {
    font-size: clamp(18px, 2.2vw, 36px);
    max-width: 34ch;
    color: var(--bm-text);
}

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

/* ── „Zeit um" (#334) ──
   Der serverzeitbasierte Countdown hat 0 erreicht. Rein visuell: die Antwortflächen werden
   als geschlossen dargestellt, die Sessionphase bleibt QuestionOpen und es wird kein Ergebnis
   vor der Moderationsfreigabe gezeigt. Eine serverseitige Verlängerung hebt den Zustand auf. */
.bm-timeup {
    background: var(--bm-danger);
    color: var(--bm-gold-ink);
    font-size: clamp(15px, 1.9vw, 26px);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0.3em 1em;
    border-radius: 999px;
    font-family: var(--bm-font-sans);
    white-space: nowrap;
}

/* Geschlossene Antwortflächen: gedämpft, aber weiter lesbar — die Wahl bleibt sichtbar,
   ist aber erkennbar nicht mehr offen. */
.bm-opts--closed {
    opacity: 0.5;
    filter: grayscale(0.25);
}

.bm-lab--center {
    justify-content: center;
    text-align: center;
}

/* ── Leerzustand ohne Gästestimmen (#334) ──
   Bei 0 gültigen Gaststimmen ein ruhiger Klartext statt zweier bedeutungsloser 0-%-Balken. */
.bm-empty-votes {
    font-size: clamp(15px, 1.9vw, 27px);
    color: var(--bm-muted);
    letter-spacing: 0.04em;
    font-family: var(--bm-font-sans);
    text-wrap: balance;
}

/* ── „Schuhe hoch!"-Tafel ── */

.bm-plate {
    display: flex;
    align-items: center;
    gap: clamp(14px, 2.4vw, 36px);
}

.bm-rule {
    height: 1px;
    width: clamp(30px, 6vw, 120px);
    background: var(--bm-gold);
    opacity: 0.75;
}

/* Wartetafel („Die Ergebnisse werden ausgewertet"): Auf den Gästehandys dreht sich hier ein
   Spinner — die Leinwand braucht ein Pendant, sonst wirkt sie als Einzige eingefroren. Ein
   Spinner wäre der falsche Ton, der gehört ins UI und nicht auf eine Hochzeitsleinwand.

   Stattdessen atmen die beiden Linien: dieselbe Geste wie der Ember-Glow, damit der Screen
   eine Bewegungssprache spricht. Entscheidend ist `alternate` — die Bewegung kehrt um, statt
   neu zu starten, und kann deshalb GAR KEINE sichtbare Naht haben. Eine gerichtete Animation
   (Licht wandert von rechts nach links und beginnt wieder rechts) braucht dafür eine exakt
   periodische Musterung; ohne die schnappt sie bei jedem Zyklus zurück, und mit ease-in-out
   bremst sie davor auch noch sichtbar ab.

   transform statt width: verändert das Layout nicht, der Text steht absolut still. Der
   Ursprung liegt jeweils innen, die Linien öffnen sich also nach außen vom Text weg. */
.bm-plate--waiting .bm-rule {
    animation: bm-rule-breathe 5s ease-in-out infinite alternate;
}

.bm-plate--waiting .bm-rule:first-child {
    transform-origin: right center;
}

.bm-plate--waiting .bm-rule:last-child {
    transform-origin: left center;
}

@keyframes bm-rule-breathe {
    from { transform: scaleX(0.5); opacity: 0.4; }
    to   { transform: scaleX(1);   opacity: 0.85; }
}

.bm-hi {
    font-size: clamp(36px, 5.6vw, 96px);
    font-weight: 600;
    color: var(--bm-gold);
    letter-spacing: 0.06em;
    line-height: 1;
}

/* ── Abschluss-Karten ── */

.bm-cards {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: clamp(10px, 1.6vw, 24px);
    max-width: min(92%, 1100px);
}

.bm-card {
    background: var(--bm-surface);
    border: 0.5px solid var(--bm-border);
    border-radius: var(--bm-radius);
    padding: clamp(12px, 1.6vw, 24px) clamp(16px, 2vw, 30px);
    min-width: clamp(140px, 18vw, 260px);
    max-width: 34ch;
}

.bm-card__k {
    font-size: clamp(12px, 1.3vw, 17px);
    color: var(--bm-text-secondary);
    letter-spacing: 0.05em;
    margin-bottom: 0.3em;
    font-family: var(--bm-font-sans);
}

.bm-card__v {
    font-size: clamp(17px, 2.2vw, 30px);
    font-weight: 500;
    color: var(--bm-text);
}

.bm-card__v--question {
    font-size: clamp(15px, 1.7vw, 23px);
    line-height: 1.3;
}

.bm-card__s {
    margin-top: 0.35em;
    font-size: clamp(12px, 1.2vw, 16px);
    color: var(--bm-muted);
    font-family: var(--bm-font-sans);
}

/* ── Schlussbild (Abschluss) ── */

/* Trägt die letzte Einstellung des Abends. Ruhiger als die Karten darüber: die Namen groß
   im Display-Schnitt, darunter eine goldene Linie mit Raute und eine einzelne Zeile. */
.bm-finale {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(8px, 1.2vw, 18px);
    margin-top: clamp(6px, 1.4vw, 22px);
}

.bm-finale__names {
    font-size: clamp(26px, 3.6vw, 58px);
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: 0.02em;
    color: var(--bm-text);
    text-wrap: balance;
}

.bm-finale__rule {
    display: flex;
    align-items: center;
    gap: clamp(10px, 1.4vw, 20px);
}

/* Raute als gedrehtes Quadrat statt Zeichen/Icon: das FA-Kit ist ein Subset und die
   Display-Schrift führt kein Rauten-Glyph — beides ergäbe ein Tofu-Kästchen. */
.bm-finale__gem {
    width: clamp(6px, 0.7vw, 10px);
    height: clamp(6px, 0.7vw, 10px);
    background: var(--bm-gold);
    transform: rotate(45deg);
    flex: none;
}

.bm-finale__line {
    font-size: clamp(15px, 1.8vw, 27px);
    color: var(--bm-text-secondary);
    letter-spacing: 0.05em;
    font-family: var(--bm-font-sans);
    text-wrap: balance;
}

/* ── Gruppenstand-Zeile (Auswertung) ── */

.bm-standing {
    color: var(--bm-text-secondary);
}

/* ── Testansicht-Badge & Verbindungsindikator (dezent, Ecken) ── */

.bm-test-badge {
    position: absolute;
    top: clamp(10px, 1.2vw, 18px);
    right: clamp(10px, 1.2vw, 18px);
    padding: 0.3em 0.9em;
    border-radius: 999px;
    border: 0.5px solid var(--bm-border);
    background: var(--bm-overlay);
    color: var(--bm-muted);
    font-size: clamp(11px, 1vw, 14px);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-family: var(--bm-font-sans);
    pointer-events: none;
}

.bm-conn {
    position: absolute;
    bottom: clamp(10px, 1.2vw, 18px);
    left: clamp(10px, 1.2vw, 18px);
    display: flex;
    align-items: center;
    gap: 0.5em;
    padding: 0.3em 0.9em;
    border-radius: 999px;
    background: var(--bm-overlay);
    color: var(--bm-muted);
    font-size: clamp(11px, 1vw, 14px);
    font-family: var(--bm-font-sans);
    pointer-events: none;
}

.bm-conn__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--bm-warning);
    animation: bm-conn-pulse 1.6s ease-in-out infinite;
}

@keyframes bm-conn-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}

/* ── Reveal-Staffelung: weiches Einblenden nachgereichter Sektionen ── */

.bm-reveal-in {
    animation: bm-fade-up 0.6s ease both;
}

@keyframes bm-fade-up {
    from {
        opacity: 0;
        transform: translateY(10px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .bm-reveal-in {
        animation: none;
    }

    .bm-conn__dot {
        animation: none;
    }

    .bm-fill {
        transition: none;
    }

    /* Auch die Lebendigkeits-Signale stehen still — der Wunsch nach Ruhe wiegt schwerer als
       die Sorge, die Leinwand könnte eingefroren wirken. Der Glow bleibt auf voller Deckkraft
       stehen (nicht auf dem 0.72-Startwert), sonst wäre er dauerhaft zu blass. */
    .ss-presentation::before {
        animation: none;
        opacity: 1;
    }

    .bm-plate--waiting .bm-rule {
        animation: none;
        transform: none;
    }
}

/* ── Connect-Seite (/presentation/connect) ── */

.bm-connect {
    min-height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: clamp(18px, 3vw, 36px);
    padding: 2rem 1.25rem;
    text-align: center;
    position: relative;
}

.bm-connect__panel {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    width: 100%;
    max-width: 30rem;
    background: var(--bm-surface);
    border: 0.5px solid var(--bm-border);
    border-radius: var(--bm-radius);
    padding: clamp(24px, 4vw, 48px);
    margin: 0;
}

.bm-connect__title {
    font-size: clamp(20px, 2.4vw, 30px);
    font-weight: 500;
}

.bm-connect__hint {
    margin: 0;
    color: var(--bm-text-secondary);
    font-family: var(--bm-font-sans);
    font-size: 0.95rem;
    line-height: 1.6;
}

.bm-connect__input {
    width: 100%;
    text-align: center;
    letter-spacing: 0.35em;
    text-transform: uppercase;
    font-family: var(--bm-font-display);
    font-size: clamp(24px, 3vw, 36px);
    font-weight: 600;
    color: var(--bm-text);
    background: var(--bm-bg-soft);
    border: 1px solid var(--bm-border);
    border-radius: 0.75rem;
    padding: 0.5em 0.4em;
}

.bm-connect__input::placeholder {
    color: var(--bm-muted);
    opacity: 0.6;
}

.bm-connect__input:focus-visible {
    outline: none;
    border-color: var(--bm-gold);
    box-shadow: 0 0 0 0.18rem var(--bm-gold-soft);
}

.bm-connect__error {
    color: var(--bm-danger);
    font-family: var(--bm-font-sans);
    font-size: 0.95rem;
}

.bm-connect__btn {
    align-self: center;
    display: inline-block;
    background: var(--bm-gold);
    color: var(--bm-gold-ink);
    border: none;
    border-radius: 999px;
    padding: 0.7em 2em;
    font-family: var(--bm-font-sans);
    font-size: 1.05rem;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
}

.bm-connect__btn:hover,
.bm-connect__btn:focus-visible {
    background: var(--bm-gold-hover);
    color: var(--bm-gold-ink);
}

.bm-connect__btn:disabled {
    opacity: 0.55;
    cursor: default;
}

.bm-connect__link {
    background: none;
    border: none;
    padding: 0;
    color: var(--bm-text-secondary);
    font-family: var(--bm-font-sans);
    font-size: 0.9rem;
    text-decoration: underline;
    cursor: pointer;
}

.bm-connect__link:hover {
    color: var(--bm-text);
}

/* ── Moderationsvorschau (Hinweisleiste + eingebettete Bühne) ── */

.bm-preview {
    display: flex;
    flex-direction: column;
    min-height: 100%;
}

.bm-preview__bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 0.55rem 1rem;
    background: var(--bm-surface);
    border-bottom: 1px solid var(--bm-border);
    color: var(--bm-text-secondary);
    font-family: var(--bm-font-sans);
    font-size: 0.9rem;
}

.bm-preview__bar a {
    color: var(--bm-gold);
    text-decoration: underline;
    white-space: nowrap;
}

.bm-preview__bar a:hover {
    color: var(--bm-gold-hover);
}

.bm-preview__stage {
    flex: 1;
    display: flex;
}

.bm-preview__stage .bm-stage {
    flex: 1;
    min-height: 0;
}

.bm-preview__error {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1.25rem;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Sektion: Gäste-Reaktionen (#201)

   Drei Bühnen, eine Formsprache: Gäste-Handy (klein, vereinzelt, nur am unteren
   Rand), Beamer (großflächig) und Moderationsvorschau (dazwischen). Die Blasen
   erzeugt js/reactionBubbles.js; hier stehen nur Layout und Bewegung.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Genug Höhe, damit die Blasen einen sichtbaren Weg haben – ohne die Karte aufzublähen. */
.ss-reaction-section {
    min-height: 9.5rem;
    overflow: hidden;
}

.ss-reaction-layer {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 2;
}

/* Gäste-Variante: nur das untere Drittel, nach oben weich ausmaskiert. Die Blasen
   sollen die Frage begleiten, nie über sie hinweglaufen. */
.ss-reaction-layer--band {
    top: auto;
    height: 34%;
    -webkit-mask-image: linear-gradient(to top, #000 0%, #000 30%, transparent 100%);
    mask-image: linear-gradient(to top, #000 0%, #000 30%, transparent 100%);
}

.ss-reaction-bubble {
    position: absolute;
    bottom: -6%;
    left: var(--ss-x, 50%);
    transform: translateX(-50%);
    display: grid;
    place-items: center;
    line-height: 1;
    opacity: 0;
    will-change: transform, bottom, opacity;
    animation: ssReactionRise var(--ss-dur, 6s) cubic-bezier(.33, 0, .3, 1) forwards;
}

@keyframes ssReactionRise {
    0%   { opacity: 0; bottom: -6%; transform: translate(-50%, 0) scale(.72); }
    14%  { opacity: var(--ss-peak, .9); }
    68%  { opacity: var(--ss-peak, .9); }
    100% { opacity: 0; bottom: var(--ss-end, 70%); transform: translate(calc(-50% + var(--ss-drift, 0px)), 0) scale(1); }
}

/* ── Gäste-Handy: die vier Kacheln ── */
.ss-reaction-choices {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: .55rem;
}

.ss-reaction-btn {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* min-width: 0 lässt die vier Grid-Spalten unter ihre min-content-Breite schrumpfen —
       sonst diktiert das längste Label ("Überraschend") die Spaltenbreite und die Kacheln
       laufen auf 320-px-Handys (erst recht mit A+) horizontal über. */
    min-width: 0;
    gap: .35rem;
    padding: .75rem .25rem .55rem;
    border-radius: .75rem;
    border: 1.5px solid var(--ss-border);
    background: var(--ss-surface);
    cursor: pointer;
    transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), border-color .2s, background .2s, box-shadow .2s, opacity .25s;
}

.ss-reaction-btn__emoji {
    font-size: 1.6rem;
    line-height: 1;
    transition: transform .2s;
}

.ss-reaction-btn__label {
    /* Sichtbar und seniorentauglich (#333): war 0.66rem und skalierte nicht mit A+.
       Jetzt ~14 px als Ausgangspunkt und mitwachsend mit der Gastschrift. Die Emojis
       tragen die Grundbedeutung, darum reicht diese Größe – keine übergroße Beschriftung. */
    font-size: calc(0.875rem * var(--ss-guest-scale, 1));
    font-weight: 600;
    color: var(--ss-text-secondary);
    /* Lange Labels dürfen umbrechen statt die Kachel zu sprengen; Silbentrennung bevorzugt,
       harter Umbruch nur als letzter Ausweg. */
    max-width: 100%;
    hyphens: auto;
    overflow-wrap: anywhere;
    text-align: center;
}

.ss-reaction-btn:hover:not(:disabled) {
    transform: translateY(-3px);
    border-color: var(--ss-accent);
}

.ss-reaction-btn:hover:not(:disabled) .ss-reaction-btn__emoji {
    transform: scale(1.12);
}

.ss-reaction-btn:active:not(:disabled) {
    transform: translateY(-1px) scale(.96);
}

.ss-reaction-btn[aria-pressed="true"] {
    border-color: var(--ss-reaction-tint, var(--ss-primary));
    background: color-mix(in srgb, var(--ss-reaction-tint, var(--ss-primary)) 12%, var(--ss-surface));
    box-shadow: 0 8px 20px -12px var(--ss-reaction-tint, var(--ss-primary));
}

.ss-reaction-btn[aria-pressed="true"] .ss-reaction-btn__label {
    color: var(--ss-reaction-tint);
}

.ss-reaction-btn[aria-pressed="true"]::after {
    content: "✓";
    position: absolute;
    top: .35rem;
    right: .4rem;
    width: 1.05rem;
    height: 1.05rem;
    border-radius: 50%;
    background: var(--ss-reaction-tint);
    color: #fff;
    font-size: .68rem;
    display: grid;
    place-items: center;
    animation: ssReactionPop .3s cubic-bezier(.34, 1.56, .64, 1) both;
}

@keyframes ssReactionPop {
    from { transform: scale(0); }
    to   { transform: scale(1); }
}

/* Nach der eigenen Wahl treten die übrigen Kacheln zurück, statt zu verschwinden:
   der Gast soll sehen, wofür er sich entschieden hat. */
.ss-reaction-btn:disabled {
    cursor: default;
}

.ss-reaction-choices--locked .ss-reaction-btn:not([aria-pressed="true"]) {
    opacity: .45;
}

/* ── Beamer: aggregierte Live-Auswertung ── */
.ss-reaction-tally {
    display: flex;
    gap: clamp(.5rem, 1.6vw, 1.25rem);
    justify-content: center;
    flex-wrap: wrap;
}

.ss-reaction-tally__item {
    display: flex;
    align-items: center;
    gap: .55rem;
    background: rgba(255, 255, 255, .08);
    border: 1px solid rgba(196, 162, 101, .32);
    border-radius: .875rem;
    padding: .55rem clamp(.75rem, 1.6vw, 1.125rem);
    backdrop-filter: blur(4px);
}

.ss-reaction-tally__emoji {
    font-size: clamp(1.2rem, 2.6vw, 1.75rem);
}

.ss-reaction-tally__meta {
    display: flex;
    flex-direction: column;
    line-height: 1.05;
}

.ss-reaction-tally__count {
    font-weight: 700;
    font-size: clamp(1.1rem, 2.6vw, 1.875rem);
    font-variant-numeric: tabular-nums;
}

.ss-reaction-tally__name {
    font-size: clamp(.56rem, 1.2vw, .75rem);
    letter-spacing: .05em;
    color: rgba(255, 255, 255, .66);
}

/* ── Moderation: Balken je Reaktion ── */
.ss-reaction-bars {
    display: flex;
    flex-direction: column;
    gap: .65rem;
}

.ss-reaction-bar {
    display: grid;
    grid-template-columns: 1.6rem 1fr 2.75rem;
    align-items: center;
    gap: .7rem;
}

.ss-reaction-bar__emoji {
    font-size: 1.2rem;
}

.ss-reaction-bar__track {
    position: relative;
    height: 1.6rem;
    border-radius: .45rem;
    background: var(--ss-surface-muted);
    overflow: hidden;
}

.ss-reaction-bar__fill {
    position: absolute;
    inset: 0 auto 0 0;
    border-radius: .45rem;
    background: linear-gradient(90deg, color-mix(in srgb, var(--ss-reaction-tint) 68%, #fff), var(--ss-reaction-tint));
    transition: width .9s cubic-bezier(.33, 0, .3, 1);
}

.ss-reaction-bar__name {
    position: absolute;
    left: .7rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: .75rem;
    font-weight: 600;
    color: var(--ss-text);
}

.ss-reaction-bar__count {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    text-align: right;
    color: var(--ss-primary-hover);
}

@media (prefers-reduced-motion: reduce) {
    .ss-reaction-bubble,
    .ss-reaction-btn[aria-pressed="true"]::after {
        animation: none !important;
    }

    .ss-reaction-bar__fill {
        transition: none;
    }

    .ss-reaction-btn {
        transition: border-color .2s, background .2s;
    }

    .ss-reaction-btn:hover:not(:disabled),
    .ss-reaction-btn:active:not(:disabled) {
        transform: none;
    }

    .ss-reaction-btn:hover:not(:disabled) .ss-reaction-btn__emoji {
        transform: none;
    }
}

/* ── Beameransicht: Online-Punkt in der Geräteliste (#242) ─────────────────── */
/* Sanfter Puls signalisiert „gerade aktiv" — deutlich lebendiger als nur Text. */
.ss-presentation-online-dot {
    display: inline-block;
    width: .55rem;
    height: .55rem;
    border-radius: 50%;
    background: var(--bs-success);
    animation: ss-presentation-online-pulse 2s ease-in-out infinite;
}

@keyframes ss-presentation-online-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(25, 135, 84, .45); }
    50% { box-shadow: 0 0 0 .3rem rgba(25, 135, 84, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .ss-presentation-online-dot {
        animation: none;
    }
}

/* ══════════════════════════════════════════════
   24. Speichern-Leiste (Session-Vorbereitung)
   Fixierte Aktionsleiste am unteren Rand, die nur bei ungespeicherten Änderungen
   gerendert wird (siehe PreparationSaveBar.razor). Bewusst unter dem PWA-Update-Banner
   (z-index 1100) und unter den Toasts (1080/1085) einsortiert.
   ══════════════════════════════════════════════ */

.ss-save-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1030;
    background: var(--ss-surface);
    border-top: 1px solid var(--ss-border);
    box-shadow: var(--ss-shadow-lg);
    /* Home-Indicator/Gestenleiste auf iOS nicht überlagern. */
    padding: 0.6rem 0 calc(0.6rem + env(safe-area-inset-bottom, 0px));
}

.ss-save-bar-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

.ss-save-bar-status {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
    color: var(--ss-text);
}

/* Eigenes Token statt --bs-warning-*: der Abendmodus (html.ss-evening) redefiniert die
   ss-Tokens, die Bootstrap-Emphasis-Variablen dagegen nicht – dort stünde sonst ein
   dunkles Gelb auf dunklem Grund. */
.ss-save-bar-status > i {
    color: var(--ss-warning-text);
    flex-shrink: 0;
}

.ss-save-bar-text {
    min-width: 0;
}

.ss-save-bar-text > div {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ss-save-bar-action {
    flex-shrink: 0;
}

/* Auf schmalen Geräten trägt der Button die volle Breite; der Statustext rückt darüber. */
@media (max-width: 575.98px) {
    .ss-save-bar-inner {
        flex-direction: column;
        align-items: stretch;
        gap: 0.5rem;
    }

    .ss-save-bar-action {
        width: 100%;
    }
}

/* Freiraum, damit eine fixierte Leiste das letzte Bedienelement der Seite nicht verdeckt.
   Wann die Seite die Klasse setzt, entscheidet sie selbst: blendet sich die Leiste häufig
   ein und aus (Session-Vorbereitung), hängt der Freiraum am Editier-Zustand statt an der
   Leiste – sonst springt die Seite bei jedem Speichern um seine Höhe. */
.ss-fixed-bar-offset {
    padding-bottom: calc(6rem + env(safe-area-inset-bottom, 0px)) !important;
}

/* Variante für Leisten, die nur unterhalb des lg-Breakpoints existieren
   (SessionControl rendert ihre Primäraktions-Leiste als `fixed-bottom d-lg-none`). */
@media (max-width: 991.98px) {
    .ss-fixed-bar-offset-mobile {
        padding-bottom: calc(6rem + env(safe-area-inset-bottom, 0px)) !important;
    }

    /* Bei gestörter Live-Verbindung (#484) trägt dieselbe Leiste zusätzlich einen schmalen
       Warnstreifen. Ohne den größeren Freiraum verdeckte sie dann das letzte Bedienelement –
       genau der Zustand, in dem man am wenigsten sucht. */
    .ss-fixed-bar-offset-mobile-wide {
        padding-bottom: calc(9.5rem + env(safe-area-inset-bottom, 0px)) !important;
    }
}

/* ══════════════════════════════════════════════
   Runde vorbereiten – Cockpit kompakt (Variante D, Spec 2026-08-10)
   ══════════════════════════════════════════════ */

.ss-headbar {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    flex-wrap: wrap;
}

.ss-task-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.8rem;
    margin: 1rem 0;
}

@media (max-width: 860px) {
    .ss-task-grid { grid-template-columns: 1fr; }
}

.ss-task-card {
    background: var(--ss-surface);
    border: 1px solid var(--ss-border-light);
    border-radius: var(--ss-radius-md);
    box-shadow: var(--ss-shadow-sm);
    padding: 0.8rem 0.95rem;
    text-align: left;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.ss-task-card:hover { border-color: var(--ss-accent); }

.ss-task-card.active {
    border-color: var(--ss-accent);
    box-shadow: 0 0 0 3px var(--ss-accent-soft), var(--ss-shadow-sm);
}

.ss-task-card-kind {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
}

.ss-task-card-kind.must { color: var(--ss-danger-text); }
.ss-task-card-kind.should { color: var(--ss-accent-text); }
.ss-task-card-kind.may { color: var(--ss-muted); }

.ss-task-card-state {
    font-size: 0.78rem;
    color: var(--ss-text-secondary);
}

.ss-area-foot {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    margin-top: 1.1rem;
}

.ss-area-foot .ss-area-next { margin-left: auto; }

/* Dropdowns dieser Seite („Runde wechseln", „Mehr Wege") kommen ohne Bootstrap-JS aus: Blazor
   steuert die Sichtbarkeit, die Position steht hier. Ohne diese Regeln bleibt `dropdown-menu-end`
   wirkungslos (es setzt nur die Popper-Ausrichtung) und das Menü stünde linksbündig im Textfluss –
   es liefe über den rechten Rand hinaus. Gleiches Muster wie .ss-hub-menu-host. Der
   Runden-Wechsler stellt sich auf dem Handy zusätzlich linksbündig (.ss-round-switcher-menu
   unten, #511 E). */
.ss-menu-host {
    position: relative;
}

.ss-menu-host > .dropdown-menu {
    position: absolute;
    top: calc(100% + 0.25rem);
    right: 0;
    left: auto;
    z-index: 20;
    /* #511 E: nie breiter als der Viewport. */
    max-width: calc(100vw - 1.5rem);
}

/* #511 E: Die 16rem standen als Inline-style in der Komponente — inline schlüge die
   Media-Query darunter. Bewusst als eigene Klasse statt auf .ss-menu-host insgesamt:
   „Mehr Wege" (QuestionAddActionsPanel) nutzt denselben Host, sitzt aber oben rechts in
   seiner Karte — dort ist rechtsbündig auch auf dem Handy richtig, und linksbündig plus
   Mindestbreite liefe es rechts aus dem Bild (der gespiegelte Fehler). */
.ss-round-switcher-menu {
    min-width: 16rem;
}

/* #511 E: `right: 0` meint die rechte Kante des BUTTONS, nicht der Karte. In der umbrochenen
   Kopfzeile steht „Runde wechseln" auf dem Handy nahe am linken Rand — rechtsbündig plus
   16rem Mindestbreite schob die linke Menükante ins Negative (Beschriftungen vorn
   abgeschnitten: „ochzeit", „estrunde"). Deshalb dort linksbündig und nur so breit wie der
   Inhalt. */
@media (max-width: 575.98px) {
    .ss-menu-host > .ss-round-switcher-menu {
        right: auto;
        left: 0;
        min-width: 0;
        width: max-content;
    }
}
