/*
 * BandSet – canonical shared application components
 *
 * This file owns the visual base for reusable controls in the authenticated
 * application. Feature CSS may define layouts, but must not redefine these
 * component foundations.
 */

/* K3/K8: Buttons und Ueberschriften erben die Skala nicht von selbst.
   Ohne diese Regeln greift die Browser-Vorgabe - 13,33px bei Schaltflaechen
   und bei jeder Ueberschrift ohne eigene Klasse. */
.modal h4:not([class]),
.modal-content h4:not([class]),
[id$="View"] h4:not([class]) {
    font-size: var(--font-card-title-size);
    line-height: var(--font-card-title-line);
}
/* K3: Buttons erben die Schriftskala nicht von selbst - ohne diese Regel
   greift die Browser-Vorgabe von 13,33px, und 147 Schaltflaechen standen
   damit ausserhalb der Skala. */
button,
input,
select,
textarea {
    font-size: var(--font-button-size);
    line-height: var(--font-button-line);
}

/* Touch-Geraete: Eingabefelder duerfen NIE unter 16px liegen.
   Darunter zoomt iOS (Safari wie WKWebView) beim Fokussieren automatisch in
   die Seite - das Layout verrutscht und der Nutzer muss von Hand zurueck.
   Das ist ein Browser-Verhalten, kein App-Verhalten, deshalb `pointer: coarse`
   und nicht `html.native-shell`; diese Datei laedt sowohl index.html als auch
   html/app.html, die Regel gilt also auch fuer Login/Registrierung.
   Am Desktop (pointer: fine) passiert nichts - dort gibt es den Zoom nicht.
   Siehe docs/MOBILE_UI_STANDARDS.md, Abschnitt 3.5. */
@media (pointer: coarse) {
    input,
    select,
    textarea {
        font-size: max(16px, var(--font-button-size, 16px));
    }
}

/* Kein blauer Aufblitzen beim Antippen - der wichtigste Einzelunterschied
   zwischen "fuehlt sich nach Website an" und "fuehlt sich nach App an".
   Stand bisher nur verstreut in einzelnen Feature-Dateien. */
@media (pointer: coarse) {
    * {
        -webkit-tap-highlight-color: transparent;
    }

    /* Primaerer CTA hoeher als die Eingabefelder darueber (48px). Vorher war
       der Anmelden-Button mit 44px NIEDRIGER als die Felder - die Hierarchie
       stand damit auf dem Kopf und liess die Felder klobig wirken.
       iOS setzt fuer grosse CTAs 50pt an, Material 3 Expressive "M" = 56dp. */
    .btn-primary,
    .btn.btn-primary {
        min-height: 52px;
    }

    /* Ohne Zeigegeraet gibt es kein Hover - stattdessen braucht jeder Button
       eine spuerbare Antwort auf den Fingerdruck (< 100ms, siehe Abschnitt 10). */
    .btn:active:not(:disabled):not([aria-disabled="true"]) {
        transform: scale(0.97);
    }
}


:where(body:not(.landing-active)),
:where(body:not(.landing-active) *),
:where(body:not(.landing-active) *::before),
:where(body:not(.landing-active) *::after) {
    box-sizing: border-box;
}

/*
 * The `hidden` attribute is the app's primary show/hide mechanism in JS
 * (`el.hidden = true`). Its `display: none` comes from the browser's own
 * stylesheet, so ANY author rule that sets `display` on the same element wins
 * and the element stays visible — most often a layout rule inside a responsive
 * media query, which is why this failed on mobile only. That footgun has been
 * patched one selector at a time across several files; this makes it
 * structurally impossible instead.
 */
body:not(.landing-active) [hidden] {
    display: none !important;
}

body:not(.landing-active) {
    font-family: var(--font-sans);
    font-size: var(--font-body-size);
    line-height: var(--font-body-line);
    color: var(--app-ink);
}

body:not(.landing-active) h1,
body:not(.landing-active) h2,
body:not(.landing-active) h3,
body:not(.landing-active) h4,
body:not(.landing-active) h5,
body:not(.landing-active) h6 {
    margin: 0;
    color: var(--app-ink);
    font-weight: 600;
    letter-spacing: -0.02em;
}

body:not(.landing-active) h1 {
    font-size: var(--font-page-title-size);
    line-height: var(--font-page-title-line);
}

body:not(.landing-active) h2 {
    font-size: var(--font-section-title-size);
    line-height: var(--font-section-title-line);
}

body:not(.landing-active) h3,
body:not(.landing-active) h4 {
    font-size: var(--font-card-title-size);
    line-height: var(--font-card-title-line);
}

body:not(.landing-active) p {
    color: var(--app-body);
}

body:not(.landing-active) small {
    color: var(--app-muted);
    font-size: var(--font-meta-size);
    line-height: var(--font-meta-line);
}

/* Buttons and text actions */
.btn {
    /* Fallback, weil index.html (Landingpage + Login) app-tokens.css nicht
       laedt - ohne ihn kippt min-height dort auf den Browser-Standard. */
    min-height: var(--app-control-height, 48px);
    max-width: 100%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 0 var(--space-4);
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    font: 600 var(--font-button-size)/var(--font-button-line) var(--font-sans);
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    touch-action: manipulation;
    transition:
        color var(--motion-base),
        background-color var(--motion-base),
        border-color var(--motion-base),
        box-shadow var(--motion-base),
        transform var(--motion-fast);
}

.btn:hover {
    text-decoration: none;
}

.btn:active:not(:disabled):not([aria-disabled="true"]) {
    transform: translateY(1px);
}

.btn:focus-visible,
.btn-icon:focus-visible,
.btn-icon-only:focus-visible,
.modal-close:focus-visible,
.btn-text:focus-visible,
.btn-link:focus-visible,
.link-button:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.btn:disabled,
.btn[aria-disabled="true"],
.btn.is-disabled {
    opacity: 0.48;
    cursor: not-allowed;
    pointer-events: none;
    transform: none;
    box-shadow: none;
}

.btn-primary {
    color: var(--app-on-accent);
    background: var(--app-accent);
    border-color: var(--app-accent);
    box-shadow: var(--shadow-subtle);
}

.btn-primary:hover:not(:disabled):not([aria-disabled="true"]) {
    color: var(--app-on-accent);
    background: var(--app-accent-hover);
    border-color: var(--app-accent-hover);
    box-shadow: var(--shadow-raised);
}

.btn-secondary {
    color: var(--app-ink);
    background: var(--app-surface-raised);
    border-color: var(--app-border);
    box-shadow: var(--shadow-subtle);
}

.btn-secondary:hover:not(:disabled):not([aria-disabled="true"]) {
    color: var(--app-ink);
    background: var(--app-surface-soft);
    border-color: var(--app-border-strong);
}

.btn-ghost,
.btn-text,
.btn-link,
.link-button {
    color: var(--app-accent);
    background: transparent;
    border-color: transparent;
    box-shadow: none;
}

.btn-ghost:hover:not(:disabled),
.btn-text:hover:not(:disabled),
.btn-link:hover:not(:disabled),
.link-button:hover:not(:disabled) {
    color: var(--app-accent-hover);
    background: var(--app-accent-soft);
}

.btn-danger,
.btn-danger-soft {
    color: var(--app-danger);
    background: var(--app-danger-soft);
    border-color: var(--app-danger-border);
    box-shadow: none;
}

.btn-danger:hover:not(:disabled):not([aria-disabled="true"]),
.btn-danger-soft:hover:not(:disabled):not([aria-disabled="true"]) {
    color: var(--app-on-danger);
    background: var(--app-danger);
    border-color: var(--app-danger);
}

.btn-warning {
    color: var(--app-warning);
    background: var(--app-warning-soft);
    border-color: var(--app-warning-border);
}

.btn-sm {
    min-height: 36px;
    padding-inline: var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--font-meta-size);
}

.btn-lg {
    min-height: 52px;
    padding-inline: var(--space-5);
}

.btn-block,
.btn-full,
.w-full {
    width: 100%;
}

.btn[aria-busy="true"],
.btn.is-loading {
    position: relative;
    cursor: wait;
    pointer-events: none;
}

.btn[aria-busy="true"]::before,
.btn.is-loading::before {
    width: 1rem;
    height: 1rem;
    flex: 0 0 auto;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: var(--radius-full);
    content: "";
    animation: app-component-spin 720ms linear infinite;
}

.btn-icon,
.btn-icon-only,
.modal-close {
    width: var(--app-control-height);
    min-width: var(--app-control-height);
    height: var(--app-control-height);
    min-height: var(--app-control-height);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--app-border);
    border-radius: var(--radius-md);
    color: var(--app-body);
    background: var(--app-surface-raised);
    box-shadow: var(--shadow-subtle);
    line-height: 0;
    cursor: pointer;
    touch-action: manipulation;
    transition:
        color var(--motion-base),
        background-color var(--motion-base),
        border-color var(--motion-base),
        box-shadow var(--motion-base),
        transform var(--motion-fast);
}

.btn-icon:hover:not(:disabled),
.btn-icon-only:hover:not(:disabled),
.modal-close:hover:not(:disabled) {
    color: var(--app-accent);
    background: var(--app-accent-soft);
    border-color: color-mix(in srgb, var(--app-accent) 34%, var(--app-border));
}

.btn-icon:active:not(:disabled),
.btn-icon-only:active:not(:disabled),
.modal-close:active:not(:disabled) {
    transform: translateY(1px);
}

.btn-icon svg,
.btn-icon-only svg,
.modal-close svg {
    width: 18px;
    height: 18px;
    display: block;
    stroke-width: 1.8;
}

.btn-icon.btn-sm,
.btn-icon-only.btn-sm {
    width: 36px;
    min-width: 36px;
    height: 36px;
    min-height: 36px;
}

.btn-icon.btn-danger,
.btn-icon.btn-danger-soft,
.btn-icon-only.btn-danger,
.btn-icon-only.btn-danger-soft {
    color: var(--app-danger);
    background: var(--app-danger-soft);
    border-color: var(--app-danger-border);
}

.btn-icon.btn-danger:hover:not(:disabled),
.btn-icon.btn-danger-soft:hover:not(:disabled),
.btn-icon-only.btn-danger:hover:not(:disabled),
.btn-icon-only.btn-danger-soft:hover:not(:disabled) {
    color: var(--app-on-danger);
    background: var(--app-danger);
    border-color: var(--app-danger);
}

/* Form controls */
.form-group {
    min-width: 0;
    margin-bottom: var(--space-4);
}

.form-group.full-width {
    grid-column: 1 / -1;
}

.form-label,
.form-group > label:not(.toggle-switch):not(.switch),
.field-label {
    display: block;
    margin-bottom: var(--space-2);
    color: var(--app-body);
    font-size: var(--font-label-size);
    font-weight: 600;
    line-height: var(--font-label-line);
}

.form-input,
.profile-form-input,
.form-select,
.form-textarea,
.form-control,
.search-field-input,
.modern-search-input {
    width: 100%;
    min-height: var(--app-control-height);
    padding: 10px 12px;
    border: 1px solid var(--app-input-border);
    border-radius: var(--radius-md);
    color: var(--app-ink);
    background: var(--app-surface-soft);
    box-shadow: none;
    font: 400 var(--font-body-size)/var(--font-body-line) var(--font-sans);
    transition:
        color var(--motion-base),
        background-color var(--motion-base),
        border-color var(--motion-base),
        box-shadow var(--motion-base);
}

.form-input:hover:not(:disabled),
.profile-form-input:hover:not(:disabled),
.form-select:hover:not(:disabled),
.form-textarea:hover:not(:disabled),
.form-control:hover:not(:disabled) {
    border-color: var(--app-border-strong);
}

.form-input:focus,
.profile-form-input:focus,
.form-select:focus,
.form-textarea:focus,
.form-control:focus,
.search-field-input:focus,
.modern-search-input:focus {
    outline: none;
    border-color: var(--app-focus);
    background: var(--app-surface-raised);
    box-shadow: var(--focus-ring);
}

.form-input::placeholder,
.profile-form-input::placeholder,
.form-textarea::placeholder,
.form-control::placeholder,
.search-field-input::placeholder,
.modern-search-input::placeholder {
    color: var(--app-subtle);
    opacity: 1;
}

.form-input:disabled,
.profile-form-input:disabled,
.form-select:disabled,
.form-textarea:disabled,
.form-control:disabled {
    color: var(--app-subtle);
    background: var(--app-surface-strong);
    border-color: var(--app-border);
    opacity: 0.66;
    cursor: not-allowed;
}

.form-textarea,
textarea.form-input,
textarea.profile-form-input,
textarea.form-control {
    min-height: 112px;
    resize: vertical;
}

select.form-input,
select.profile-form-input,
.form-select,
select.form-control {
    padding-right: 40px;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23918a99' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 18px;
}

select[multiple].form-input,
select[multiple].profile-form-input,
select[multiple].form-select,
select[multiple].form-control {
    min-height: 128px;
    padding: var(--space-2);
    appearance: auto;
    background-image: none;
}

select[multiple] option {
    margin-bottom: 2px;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
}

/* Baseline for ANY select that hasn't opted into one of the canonical form
   classes above — closes the gap where a dropdown falls back to the raw
   OS/browser arrow instead of the app's chevron. Purely cosmetic (appearance
   + background-image), so it's safe to apply broadly; any select that already
   defines its own appearance/background-image (more specific selector) keeps
   winning as normal. Excludes the Quill rich-text toolbar, which intentionally
   keeps its own third-party control styling. */
select:not(.ql-header):not([multiple]) {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23918a99' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 18px;
    padding-right: 40px;
}

/* Baseline number-input spinner removal — the app doesn't use native
   increment/decrement arrows anywhere else, so a bare number input showing
   them (e.g. Betrag/BPM fields) reads as a foreign control. */
input[type="number"] {
    appearance: textfield;
    -moz-appearance: textfield;
}

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
}

.search-field-input,
.modern-search-input {
    padding-left: 44px;
    border-radius: var(--radius-full);
}

.search-field-container,
.search-container {
    position: relative;
    width: 100%;
}

.search-field-icon,
.search-icon {
    position: absolute;
    z-index: 1;
    left: 14px;
    top: 50%;
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--app-muted);
    pointer-events: none;
    transform: translateY(-50%);
}

.form-input[aria-invalid="true"],
.profile-form-input[aria-invalid="true"],
.form-select[aria-invalid="true"],
.form-textarea[aria-invalid="true"],
.form-control[aria-invalid="true"],
body:not(.landing-active) input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):user-invalid,
body:not(.landing-active) select:user-invalid,
body:not(.landing-active) textarea:user-invalid,
.is-invalid {
    border-color: var(--app-danger);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--app-danger) 18%, transparent);
}

.field-error,
.validation-message,
.form-error {
    display: block;
    margin-top: var(--space-2);
    color: var(--app-danger);
    font-size: var(--font-meta-size);
    line-height: var(--font-meta-line);
}

.field-success,
.form-success {
    display: block;
    margin-top: var(--space-2);
    color: var(--app-success);
    font-size: var(--font-meta-size);
}

.help-text,
.field-hint,
.form-hint {
    color: var(--app-muted);
    font-size: var(--font-meta-size);
    line-height: var(--font-meta-line);
}

.form-checkbox,
.form-radio,
input[type="checkbox"],
input[type="radio"] {
    accent-color: var(--app-accent);
}

.form-checkbox,
.form-radio {
    width: 20px;
    height: 20px;
    flex: 0 0 20px;
    cursor: pointer;
}

.form-checkbox:focus-visible,
.form-radio:focus-visible,
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
    outline: 3px solid color-mix(in srgb, var(--app-focus) 24%, transparent);
    outline-offset: 2px;
}

.toggle-switch,
.switch {
    position: relative;
    flex: 0 0 auto;
}

.toggle-switch {
    min-width: 46px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
}

.switch {
    width: 48px;
    height: 44px;
    display: inline-flex;
    align-items: center;
}

.toggle-switch input,
.switch input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.toggle-slider,
.switch-slider {
    position: relative;
    width: 46px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    padding: 3px;
    border: 1px solid var(--app-border-strong);
    border-radius: var(--radius-full);
    background: var(--app-surface-strong);
    cursor: pointer;
    transition: background-color var(--motion-base), border-color var(--motion-base), box-shadow var(--motion-base);
}

.switch .slider {
    position: absolute;
    inset: 50% 0 auto;
    height: 26px;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    padding: 3px;
    border: 1px solid var(--app-border-strong);
    border-radius: var(--radius-full);
    background: var(--app-surface-strong);
    cursor: pointer;
    transition: background-color var(--motion-base), border-color var(--motion-base), box-shadow var(--motion-base);
}

.toggle-slider::before,
.switch .slider::before,
.switch-slider::before {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--app-surface-raised);
    box-shadow: var(--shadow-subtle);
    content: "";
    transition: transform var(--motion-base), background-color var(--motion-base);
}

.toggle-switch input:checked + .toggle-slider,
.switch input:checked + .slider,
.switch input:checked + .switch-slider {
    border-color: var(--app-accent);
    background: var(--app-accent);
}

.toggle-switch input:checked + .toggle-slider::before,
.switch input:checked + .slider::before,
.switch input:checked + .switch-slider::before {
    transform: translateX(20px);
    background: var(--app-on-accent);
}

.toggle-switch input:focus-visible + .toggle-slider,
.switch input:focus-visible + .slider,
.switch input:focus-visible + .switch-slider,
.toggle-switch[role="switch"]:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

/* Cards, panels and states */
.card,
.panel,
.page-section-card,
.page-overview-card {
    border: 1px solid var(--app-border);
    border-radius: var(--radius-lg);
    background: var(--app-surface-raised);
    box-shadow: var(--shadow-subtle);
}

.badge,
.chip,
.status-pill,
.role-badge {
    min-height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    padding: 3px var(--space-2);
    border: 1px solid var(--app-border);
    border-radius: var(--radius-full);
    color: var(--app-body);
    background: var(--app-surface-soft);
    font-size: var(--font-meta-size);
    font-weight: 600;
    line-height: 1.2;
}

.badge-success,
.status-success {
    color: var(--app-success);
    background: var(--app-success-soft);
    border-color: var(--app-success-border);
}

.badge-warning,
.status-warning {
    color: var(--app-warning);
    background: var(--app-warning-soft);
    border-color: var(--app-warning-border);
}

.badge-danger,
.status-danger,
.badge-error,
.status-error {
    color: var(--app-danger);
    background: var(--app-danger-soft);
    border-color: var(--app-danger-border);
}

.badge-info,
.status-info,
.badge-primary {
    color: var(--app-accent);
    background: var(--app-accent-soft);
    border-color: color-mix(in srgb, var(--app-accent) 30%, var(--app-border));
}

.avatar,
.avatar-img,
.user-avatar,
.member-avatar {
    flex: 0 0 auto;
    border-radius: 50%;
    object-fit: cover;
}

.empty-state,
.empty-state-compact,
.error-state,
.loading-state {
    width: 100%;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    padding: var(--space-6) var(--space-5);
    border: 1px dashed var(--app-border);
    border-radius: var(--radius-lg);
    color: var(--app-muted);
    background: var(--app-surface-soft);
    text-align: center;
}

.empty-state-compact,
.loading-state-sm {
    min-height: 88px;
    padding: var(--space-4);
}

.empty-state p,
.empty-state-compact p,
.error-state p,
.loading-state p {
    max-width: 54ch;
    margin: 0;
    color: inherit;
}

.empty-state-compact-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border: 1px solid color-mix(in srgb, var(--app-accent) 24%, var(--app-border));
    border-radius: 0.75rem;
    background: var(--app-accent-soft);
    color: var(--app-accent);
}

.empty-state-compact-icon svg {
    width: 1.2rem;
    height: 1.2rem;
}

.error-state {
    color: var(--app-danger);
    background: var(--app-danger-soft);
    border-color: var(--app-danger-border);
}

.spinner,
.loading-spinner,
.loading-spinner-circle,
.spinner-border,
.spinner-border-sm {
    width: 24px;
    height: 24px;
    display: inline-block;
    flex: 0 0 auto;
    border: 2px solid color-mix(in srgb, var(--app-accent) 24%, transparent);
    border-top-color: var(--app-accent);
    border-radius: 50%;
    animation: app-component-spin 720ms linear infinite;
}

.spinner-sm,
.spinner-border-sm {
    width: 16px;
    height: 16px;
}

.skeleton,
.skeleton-line,
.skeleton-card {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-sm);
    background: var(--app-surface-strong);
}

.skeleton::after,
.skeleton-line::after,
.skeleton-card::after {
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--app-ink) 8%, transparent), transparent);
    content: "";
    transform: translateX(-100%);
    animation: app-component-skeleton 1.35s ease-in-out infinite;
}

/* Tabs, tables and uploads */
.tab-nav,
.modal-tabs,
.settings-tabs,
.schedule-tabs,
#bandModalTabs,
#orgModalTabs,
.segmented-control {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1);
    border: 1px solid var(--app-border);
    border-radius: var(--radius-md);
    background: var(--app-surface-soft);
}

.tab-btn,
.settings-tab-btn,
.schedule-tab-btn,
.segmented-control > button {
    min-height: 38px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 0 var(--space-3);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--app-muted);
    background: transparent;
    font: 600 var(--font-meta-size)/1.3 var(--font-sans);
    cursor: pointer;
    transition: color var(--motion-base), background-color var(--motion-base), border-color var(--motion-base), box-shadow var(--motion-base);
}

.tab-btn:hover,
.settings-tab-btn:hover,
.schedule-tab-btn:hover,
.segmented-control > button:hover {
    color: var(--app-ink);
    background: var(--app-surface-raised);
}

.tab-btn.active,
.tab-btn[aria-selected="true"],
.settings-tab-btn.active,
.settings-tab-btn[aria-selected="true"],
.schedule-tab-btn.active,
.schedule-tab-btn[aria-selected="true"],
.segmented-control > button.active,
.segmented-control > button[aria-pressed="true"] {
    color: var(--app-accent);
    background: var(--app-surface-raised);
    border-color: var(--app-border);
    box-shadow: var(--shadow-subtle);
}

.tab-btn:focus-visible,
.settings-tab-btn:focus-visible,
.schedule-tab-btn:focus-visible,
.segmented-control > button:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.table-wrapper,
.table-responsive {
    width: 100%;
    overflow-x: auto;
    border: 1px solid var(--app-border);
    border-radius: var(--radius-lg);
    background: var(--app-surface-raised);
    -webkit-overflow-scrolling: touch;
}

.table,
table.app-table {
    width: 100%;
    border-collapse: collapse;
    color: var(--app-body);
    font-size: var(--font-body-size);
}

.table th,
.table td,
table.app-table th,
table.app-table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--app-border);
    text-align: left;
    vertical-align: middle;
}

.table th,
table.app-table th {
    color: var(--app-muted);
    background: var(--app-surface-soft);
    font-size: var(--font-meta-size);
    font-weight: 600;
}

.table tbody tr:last-child td,
table.app-table tbody tr:last-child td {
    border-bottom: 0;
}

.file-upload-wrapper,
.upload-dropzone {
    position: relative;
    width: 100%;
    min-height: 132px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    padding: var(--space-5);
    border: 1px dashed var(--app-border-strong);
    border-radius: var(--radius-lg);
    color: var(--app-muted);
    background: var(--app-surface-soft);
    text-align: center;
    transition: color var(--motion-base), background-color var(--motion-base), border-color var(--motion-base), box-shadow var(--motion-base);
}

.file-upload-wrapper:hover,
.upload-dropzone:hover,
.upload-dropzone.drag-over {
    color: var(--app-accent);
    background: var(--app-accent-soft);
    border-color: var(--app-accent);
}

.file-upload-wrapper:focus-within,
.upload-dropzone:focus-within {
    box-shadow: var(--focus-ring);
}

.file-upload-hint {
    margin: 0;
    color: var(--app-muted);
    font-size: var(--font-meta-size);
}

/* Tooltips */
[data-tooltip] {
    position: relative;
}

[data-tooltip]::after {
    position: absolute;
    z-index: 1200;
    left: 50%;
    bottom: calc(100% + var(--space-2));
    max-width: min(280px, calc(100vw - 32px));
    padding: 7px 9px;
    border: 1px solid var(--app-border);
    border-radius: var(--radius-sm);
    color: var(--app-ink);
    background: var(--app-surface-raised);
    box-shadow: var(--shadow-raised);
    content: attr(data-tooltip);
    font-size: var(--font-meta-size);
    line-height: var(--font-meta-line);
    white-space: normal;
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, 4px);
    transition: opacity var(--motion-fast), transform var(--motion-fast);
}

[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after {
    opacity: 1;
    transform: translate(-50%, 0);
}

/* Dialog and modal structure */
html.modal-open,
body.modal-open {
    overflow: hidden;
    overscroll-behavior: none;
}

.modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    background: var(--app-overlay);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

.modal.active {
    display: flex;
}

.modal-content {
    max-height: min(90vh, 900px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--app-border);
    border-radius: var(--dialog-radius);
    color: var(--app-ink);
    background: var(--app-surface-raised);
    box-shadow: var(--shadow-overlay);
}

.modal-header {
    min-height: 68px;
    /* Nie zusammenstauchen: .modal-content ist ein hoehenbegrenzter
       Flex-Container. Auf niedrigen Viewports (Handy quer, kurzes Fenster)
       schrumpfte der Kopf sonst unter seine Inhaltshoehe - der mehrzeilige
       Titel + Untertitel liefen dann aus dem Kopf heraus und lagen vor dem
       Scroll-Inhalt (z. B. der Stepper im "Song hinzufuegen"-Fenster).
       Nur der scrollbare Mittelteil darf flexen. 2026-09-09. */
    flex-shrink: 0;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--dialog-head-pad);
    border-bottom: 1px solid var(--app-border);
    background: var(--app-surface-raised);
}

.modal-title-copy {
    min-width: 0;
    display: grid;
    gap: var(--space-1);
}

.modal-kicker {
    color: var(--app-accent);
    font-size: var(--font-meta-size);
    font-weight: 600;
    letter-spacing: 0.08em;
    line-height: 1.3;
    text-transform: uppercase;
}

.modal-header h2 {
    margin: 0;
    overflow-wrap: anywhere;
}

.modal-body {
    min-height: 0;
    padding: var(--dialog-pad);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* K4: Eine Regel fuer alle Fenster-Fusszeilen.
   Vorher gab es vier verschiedene Ausrichtungen fuer dieselbe Zeile
   (flex-end, center, space-between, stretch) - je nach Fenster sass der
   Abbrechen-Knopf woanders. */
.modal-actions,
.modal-footer {
    min-height: 72px;
    /* Fusszeile bleibt wie der Kopf immer voll sichtbar - nur der Mittelteil
       flext (siehe .modal-header). */
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-5);
    border-top: 1px solid var(--app-border);
    background: var(--app-surface-raised);
}

/* Abbrechen bzw. Schliessen steht immer links, die Primaeraktion rechts.
   Das Markup fuehrt die Abbrechen-Schaltflaeche durchgaengig zuerst.

   Bewusst ueber margin-right statt space-between: Bei nur EINER Schaltflaeche
   wuerde space-between sie nach links schieben, was falsch waere. Die
   :has()-Bedingung greift deshalb erst ab zwei Elementen. */
.modal-actions,
.modal-footer,
.modal [class*="modal-actions"],
.modal [class*="-modal-actions"],
.modal .pdf-preview-footer {
    justify-content: flex-end;
}

.modal-actions:has(> :nth-child(2)) > :first-child,
.modal-footer:has(> :nth-child(2)) > :first-child,
.modal [class*="modal-actions"]:has(> :nth-child(2)) > :first-child,
.modal .pdf-preview-footer:has(> :nth-child(2)) > :first-child {
    margin-right: auto;
}

.modal-actions-right {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-3);
    margin-left: auto;
}

.modal-close {
    flex: 0 0 var(--app-control-height);
}

.app-dialog-content {
    width: min(100%, 480px);
}

.app-dialog-message {
    margin: 0;
    color: var(--app-body);
    white-space: pre-line;
}

.app-dialog-heading {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.app-dialog-icon {
    width: 36px;
    height: 36px;
    display: inline-flex;
    flex: 0 0 36px;
    align-items: center;
    justify-content: center;
    border: 1px solid color-mix(in srgb, var(--app-accent) 28%, var(--app-border));
    border-radius: var(--radius-md);
    color: var(--app-accent);
    background: var(--app-accent-soft);
}

.app-dialog-icon svg {
    width: 18px;
    height: 18px;
}

.app-prompt-form {
    display: grid;
    gap: var(--space-4);
}

.app-loading-message {
    margin: 0;
    color: var(--app-ink);
    font-weight: 600;
}

.pdf-preview-container,
.preview-container,
.document-preview-surface {
    min-width: 0;
    overflow: auto;
    border: 1px solid var(--app-border);
    border-radius: var(--radius-lg);
    background: var(--app-surface-soft);
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--app-ink) 4%, transparent);
}

@keyframes app-component-spin {
    to {
        transform: rotate(360deg);
    }
}

@keyframes app-component-skeleton {
    to {
        transform: translateX(100%);
    }
}

@media (max-width: 820px), (max-width: 900px) and (max-height: 500px) {
    .btn {
        min-width: 44px;
        min-height: 44px;
    }

    .btn-icon,
    .btn-icon-only,
    .modal-close {
        width: 44px;
        min-width: 44px;
        height: 44px;
        min-height: 44px;
    }

    .form-input,
    .profile-form-input,
    .form-select,
    .form-textarea,
    .form-control,
    .search-field-input,
    .modern-search-input {
        min-height: 46px;
        font-size: var(--font-card-title-size);
    }

    /* K2: Fenster stehen auch auf dem Handy mittig.
       Vorher zog diese Regel global jedes Fenster an den unteren Rand,
       waehrend neun andere Regeln es mittig setzen wollten - wer gewann,
       entschied die Ladereihenfolge. Ein Sheet von unten ist weiterhin
       moeglich, aber nur mit der Klasse .modal-sheet am Fenster. */
    .modal {
        align-items: center;
        padding: max(var(--space-2), env(safe-area-inset-top)) max(var(--space-2), env(safe-area-inset-right)) max(var(--space-2), env(safe-area-inset-bottom)) max(var(--space-2), env(safe-area-inset-left));
    }

    /* Ausdruecklich als Sheet gewuenscht - faehrt von unten ein. */
    .modal.modal-sheet {
        align-items: flex-end;
    }

    .modal-content,
    .modal-large,
    .modal-lg,
    .modal-xl {
        max-height: calc(100dvh - max(16px, env(safe-area-inset-top)) - max(16px, env(safe-area-inset-bottom)));
        border-radius: var(--dialog-radius);
    }

    .modal-header {
        min-height: 64px;
        padding: var(--dialog-head-pad);
    }

    .modal-body {
        padding: var(--dialog-pad);
    }

    .modal-actions,
    .modal-footer {
        position: sticky;
        bottom: 0;
        min-height: 72px;
        padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom));
    }

    .modal-actions > .btn,
    .modal-footer > .btn,
    .modal-actions-right > .btn {
        flex: 1 1 0;
        min-width: 0;
    }

    .tab-nav,
    .modal-tabs,
    .settings-tabs,
    .schedule-tabs,
    #bandModalTabs,
    #orgModalTabs,
    .segmented-control {
        max-width: 100%;
        overflow-x: auto;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }

    .tab-nav::-webkit-scrollbar,
    .modal-tabs::-webkit-scrollbar,
    .settings-tabs::-webkit-scrollbar,
    .schedule-tabs::-webkit-scrollbar,
    #bandModalTabs::-webkit-scrollbar,
    #orgModalTabs::-webkit-scrollbar,
    .segmented-control::-webkit-scrollbar {
        display: none;
    }

    .tab-btn,
    .settings-tab-btn,
    .schedule-tab-btn,
    .segmented-control > button {
        flex: 0 0 auto;
        min-height: 44px;
        white-space: nowrap;
    }

    body:not(.landing-active) label:has(> .form-checkbox),
    body:not(.landing-active) label:has(> .form-radio) {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        gap: var(--space-2);
        cursor: pointer;
    }

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

    /* .finance-table is deliberately NOT included here (it used to be) - it
       already has its own dedicated, complete horizontal-scroll wrapper
       (.finance-table-scroll-shell/.finance-table-scroll-frame in
       finances.css, with its own hint banner and custom scrollbar). Giving
       the <table> element itself `overflow-x: auto` too made it a SECOND,
       independently-scrollable container nested inside that wrapper - the
       cause of the double-scrollbar "first swipe moves a little, second
       swipe moves the rest" bug: a real, measured 300px scroll range on the
       table itself, nested inside the wrapper's real 571px range, verified
       via scrollWidth/clientWidth on both in the live DOM (not just
       visually - see the CSS Overflow spec quirk fixed elsewhere in this
       file's history for why that visual-only check missed it before).
       This rule now only covers .table/table.app-table, which - unlike
       .finance-table - have no wrapper of their own and need the table
       itself to become the scroll container. */
    .table,
    table.app-table {
        display: block;
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}

@media (max-width: 430px) {
    .modal-actions,
    .modal-footer,
    .modal-actions-right {
        gap: var(--space-2);
    }

    .modal-actions .btn,
    .modal-footer .btn {
        padding-inline: var(--space-3);
        white-space: normal;
    }
}

@media (prefers-reduced-motion: reduce) {
    .btn,
    .btn-icon,
    .btn-icon-only,
    .modal-close,
    .form-input,
    .profile-form-input,
    .form-select,
    .form-textarea,
    .form-control,
    .toggle-slider,
    .switch .slider,
    .switch-slider {
        transition: none;
    }

    .spinner,
    .loading-spinner,
    .loading-spinner-circle,
    .spinner-border,
    .spinner-border-sm,
    .btn[aria-busy="true"]::before,
    .btn.is-loading::before,
    .skeleton::after,
    .skeleton-line::after,
    .skeleton-card::after {
        animation-duration: 1.5s;
    }
}

/* Shared member-role editor */

.role-edit-modal .role-edit-modal-content {
    background:
        linear-gradient(180deg, color-mix(in srgb, var(--app-accent-soft) 36%, transparent), transparent 180px),
        var(--app-surface-raised);
}

.role-edit-modal .role-edit-modal-header {
    background: color-mix(in srgb, var(--app-surface-raised) 84%, var(--app-accent-soft));
}

.role-edit-modal-subtitle {
    max-width: 34rem;
    margin: 0;
    color: var(--app-body);
    font-size: var(--font-body-size);
    line-height: var(--font-body-line);
}

.role-edit-modal .role-edit-modal-body {
    display: grid;
    gap: var(--space-3);
}

.role-edit-summary-card,
.role-edit-section,
.role-edit-danger-card {
    border: 1px solid var(--app-border);
    border-radius: var(--radius-md);
    background: var(--app-surface-soft);
    box-shadow: var(--shadow-subtle);
}

#editRoleModal .role-edit-section[hidden],
#editRoleModal .role-option-card[hidden],
#editOrgRoleModal .role-option-card[hidden],
#editRoleModal .role-edit-danger-card[hidden],
#editRoleModal #saveEditRoleBtn[hidden] {
    display: none !important;
}

.role-edit-summary-card {
    min-height: 56px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
}

.role-edit-summary-label,
.role-edit-section-head > span {
    color: var(--app-ink);
    font-size: var(--font-meta-size);
    font-weight: 700;
    letter-spacing: 0.08em;
    line-height: var(--font-meta-line);
    text-transform: uppercase;
}

.role-edit-section {
    display: grid;
    gap: var(--space-3);
    padding: var(--space-4);
}

.role-edit-section-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-4);
}

.role-edit-section-head small {
    max-width: 18rem;
    color: var(--app-muted);
    font-size: var(--font-meta-size);
    font-weight: 500;
    line-height: var(--font-meta-line);
    text-align: right;
}

.role-edit-native-select {
    position: absolute;
    width: 1px !important;
    min-width: 1px !important;
    height: 1px !important;
    min-height: 1px;
    padding: 0;
    opacity: 0 !important;
    pointer-events: none !important;
}

.role-option-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-2);
}

.role-option-card {
    position: relative;
    width: 100%;
    min-width: 0;
    min-height: 76px;
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr) 24px;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    overflow: hidden;
    border: 1px solid var(--app-border);
    border-radius: var(--radius-md);
    color: var(--app-ink);
    background: var(--app-surface-raised);
    cursor: pointer;
    touch-action: manipulation;
    transition:
        transform var(--motion-fast),
        border-color var(--motion-base),
        background-color var(--motion-base),
        box-shadow var(--motion-base);
}

.role-option-card:hover {
    transform: translateY(-1px);
    border-color: var(--app-border-strong);
    background: var(--app-accent-soft);
}

.role-option-card:focus-within {
    outline: 2px solid var(--app-accent);
    outline-offset: 2px;
}

.role-option-card.is-selected {
    border-color: var(--app-accent);
    background: var(--app-accent-soft);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--app-accent) 22%, transparent);
}

.role-option-card input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.role-option-icon,
.role-option-check {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
}

.role-option-icon {
    width: 40px;
    height: 40px;
    border: 1px solid color-mix(in srgb, var(--app-accent) 28%, var(--app-border));
    border-radius: var(--radius-md);
    color: var(--app-accent);
    background: var(--app-accent-soft);
}

.role-option-icon svg {
    width: 20px;
    height: 20px;
}

.role-option-check {
    justify-self: end;
    width: 24px;
    height: 24px;
    border: 1px solid var(--app-border-strong);
    border-radius: var(--radius-full);
    color: transparent;
    background: var(--app-surface-raised);
}

.role-option-check svg {
    width: 15px;
    height: 15px;
}

.role-option-card.is-selected .role-option-check {
    border-color: var(--app-accent);
    color: var(--app-on-accent);
    background: var(--app-accent);
}

.role-option-copy {
    min-width: 0;
    display: grid;
    gap: var(--space-1);
    overflow: hidden;
}

.role-option-copy strong,
.role-option-copy small {
    display: block;
    min-width: 0;
    overflow-wrap: anywhere;
}

.role-option-copy strong {
    color: var(--app-ink);
    font-size: var(--font-label-size);
    font-weight: 700;
    line-height: var(--font-label-line);
}

.role-option-copy small {
    color: var(--app-body);
    font-size: var(--font-meta-size);
    line-height: var(--font-meta-line);
}

.role-edit-danger-card {
    min-height: 72px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-4);
    border-color: var(--app-danger-border);
    background: var(--app-danger-soft);
}

.role-edit-danger-copy {
    min-width: 0;
    display: grid;
    gap: var(--space-1);
}

.role-edit-danger-copy strong {
    color: var(--app-ink);
    font-size: var(--font-label-size);
    line-height: var(--font-label-line);
}

.role-edit-danger-copy span {
    color: var(--app-body);
    font-size: var(--font-meta-size);
    line-height: var(--font-meta-line);
}

.role-edit-danger-action {
    min-height: var(--app-control-height);
    flex: 0 0 auto;
}

.role-edit-actions {
    gap: var(--space-3);
}

.role-edit-actions .btn {
    min-width: 124px;
}

.role-edit-actions svg,
.role-edit-danger-action svg {
    width: 17px;
    height: 17px;
}

@media (min-width: 821px) {
    #editRoleModal .role-edit-actions {
        justify-content: space-between;
    }
}

@media (max-width: 820px) {
    .role-edit-modal .role-edit-modal-content {
        max-height: calc(100dvh - max(16px, env(safe-area-inset-top)) - max(16px, env(safe-area-inset-bottom)));
    }

    .role-edit-modal .role-edit-modal-body {
        gap: var(--space-3);
    }

    .role-edit-section-head {
        align-items: flex-start;
        flex-direction: column;
        gap: var(--space-1);
    }

    .role-edit-section-head small {
        max-width: none;
        text-align: left;
    }

    .role-edit-danger-card {
        align-items: stretch;
        flex-direction: column;
    }

    .role-edit-danger-action {
        width: 100%;
    }

    .role-edit-actions {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }

    .role-edit-actions .btn {
        width: 100%;
        min-width: 0;
    }

    .role-edit-actions.is-single-action {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 430px) {
    .role-edit-summary-card,
    .role-edit-section,
    .role-edit-danger-card {
        padding: var(--space-3);
    }

    .role-option-card {
        min-height: 72px;
        grid-template-columns: 36px minmax(0, 1fr) 24px;
        gap: var(--space-2);
        padding: var(--space-2);
    }

    .role-option-icon {
        width: 36px;
        height: 36px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .role-option-card {
        transition: none;
    }
}

/* Dynamic selector cards must honor semantic hidden states. */
[data-song-selector-card][hidden] {
    display: none;
}

/* Shared segmented view switch used by Songpool and settings workspaces. */
.songpool-view-switch {
    display: flex;
    margin-right: 1rem;
    padding: 3px;
    border: 1px solid color-mix(in srgb, var(--border) 40%, transparent);
    border-radius: 20px;
    background: color-mix(in srgb, var(--surface-secondary) 40%, transparent);
}

.songpool-view-switch .switch-btn {
    min-height: 38px;
    padding: 6px 14px;
    border: 0;
    border-radius: 17px;
    background: transparent;
    color: var(--text-secondary);
    font: 500 0.85rem/1.2 var(--font-sans);
    cursor: pointer;
    transition:
        color var(--motion-fast),
        background-color var(--motion-fast),
        box-shadow var(--motion-fast);
}

.songpool-view-switch .switch-btn.active {
    background: var(--color-primary);
    color: #ffffff;
    box-shadow: 0 2px 8px color-mix(in srgb, var(--color-primary) 30%, transparent);
}

.songpool-view-switch .switch-btn:not(.active):hover {
    background: color-mix(in srgb, var(--surface-secondary) 60%, transparent);
    color: var(--text-primary);
}

.songpool-view-switch .switch-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--color-primary) 68%, transparent);
    outline-offset: 2px;
}

@media (max-width: 820px) {
    .songpool-view-switch {
        width: 100%;
        margin-right: 0;
        margin-bottom: 0.75rem;
        justify-content: center;
    }

    .songpool-view-switch .switch-btn {
        flex: 1 1 0;
        min-width: 0;
        min-height: 44px;
        text-align: center;
    }
}

/* Organisations-Wähler im privaten Songpool - nur sichtbar, wenn man in
   mehreren Organisationen ist und den "Organisation"-Tab betrachtet. */
.songpool-org-switch {
    display: inline-flex;
    margin-right: 1rem;
}

.songpool-org-switch-select {
    min-height: 40px;
    max-width: 220px;
    padding: 6px 40px 6px 12px;
    border: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
    border-radius: 12px;
    background-color: color-mix(in srgb, var(--surface-secondary) 40%, transparent);
    color: var(--text-primary);
    font: 500 0.85rem/1.2 var(--font-sans);
    cursor: pointer;
}

.songpool-org-switch-select:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--color-primary) 68%, transparent);
    outline-offset: 2px;
}

@media (max-width: 820px) {
    /* Umschalter + Organisations-Wähler sollen mobil untereinander stehen,
       nicht in einer Zeile zusammengequetscht werden. */
    .songpool-toolbar .band-setlist-toolbar-actions {
        flex-wrap: wrap;
    }

    .songpool-org-switch {
        order: 3;
        width: 100%;
        margin-right: 0;
        margin-bottom: 0.75rem;
    }

    .songpool-org-switch-select {
        width: 100%;
        max-width: none;
        min-height: 44px;
    }
}

/* Compact Offen/Abgestimmt/Fest switch for Auftritte + Proben, replacing the
   three large .schedule-status-card tiles (icon + eyebrow + big number +
   caption sentence each) with one segmented pill - same visual language as
   .songpool-view-switch above, plus a small count badge per option. The
   caption sentences aren't lost, they were already duplicated verbatim in
   each panel's own header text below (e.g. "Offene Auftritts-Anfragen" /
   "Hier siehst du alles, was noch auf Rückmeldungen wartet."). 2026-09-04. */
.schedule-status-switch {
    display: flex;
    align-self: flex-start;
    gap: 2px;
    padding: 3px;
    border: 1px solid color-mix(in srgb, var(--border) 40%, transparent);
    border-radius: 20px;
    background: color-mix(in srgb, var(--surface-secondary) 40%, transparent);
}

.schedule-status-switch-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    min-height: 38px;
    padding: 6px 14px;
    border: 0;
    border-radius: 17px;
    background: transparent;
    color: var(--text-secondary);
    font: 500 0.85rem/1.2 var(--font-sans);
    cursor: pointer;
    transition:
        color var(--motion-fast),
        background-color var(--motion-fast),
        box-shadow var(--motion-fast);
}

.schedule-status-switch-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--text-secondary) 16%, transparent);
    color: var(--text-primary);
    font-size: 0.72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    transition: background-color var(--motion-fast), color var(--motion-fast);
}

/* Schrift auf dem Akzent MUSS ueber --app-on-accent laufen, nicht ueber ein
   hartes #ffffff: im Dunkelmodus ist der Akzent das helle #a78bfa, weisse
   Schrift darauf ergibt nur 2.72:1 (WCAG verlangt 4.5:1). Das Token ist pro
   Thema richtig gesetzt - hell #ffffff, dunkel #171020 - und liefert so
   6.8:1. Gemessen im Kontrast-Audit am 09.09.2026,
   siehe docs/MOBILE_UI_STANDARDS.md, Abschnitt 9. */
.schedule-status-switch-btn.is-active {
    background: var(--color-primary);
    color: var(--app-on-accent, #ffffff);
    box-shadow: 0 2px 8px color-mix(in srgb, var(--color-primary) 30%, transparent);
}

.schedule-status-switch-btn.is-active .schedule-status-switch-count {
    background: color-mix(in srgb, var(--app-on-accent, #ffffff) 22%, transparent);
    color: var(--app-on-accent, #ffffff);
}

.schedule-status-switch-btn:not(.is-active):hover {
    background: color-mix(in srgb, var(--surface-secondary) 60%, transparent);
    color: var(--text-primary);
}

.schedule-status-switch-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--color-primary) 68%, transparent);
    outline-offset: 2px;
}

@media (max-width: 820px) {
    /* Auf Mobile bleibt die Filterleiste (Offen / Abgestimmt / Fest) beim
       Scrollen oben stehen - sonst muss man in einer langen Proben-/
       Auftrittsliste erst hochscrollen, um den Status zu wechseln
       (Notion-Wunsch). Deckender Hintergrund + z-index, damit die Liste
       sauber darunter durchlaeuft; die Listeninhalte liegen in derselben
       Spaltenbreite, es blitzt also nichts seitlich durch. Ein kleiner
       Schatten trennt sie optisch vom durchlaufenden Inhalt. */
    .schedule-status-switch {
        position: sticky;
        /* Buendig unter dem Kopf andocken: .app-main hat 16px padding-top,
           `top: -16px` zieht die Leiste in diese Zone hoch, das gleiche
           padding-top schiebt die Knoepfe wieder an ihren Platz. Sonst
           blitzt in dem 16px-Streifen scrollender Inhalt ueber der Leiste
           durch. */
        top: calc(var(--app-page-padding, 16px) * -1);
        z-index: 20;
        width: 100%;
        margin-top: calc(var(--app-page-padding, 16px) * -1);
        padding: calc(var(--app-page-padding, 16px) + 3px) 3px 3px;
        background: var(--app-surface-raised, var(--surface-primary));
        /* Obere Ecken sitzen unter dem Kopf, nur unten runden. Die durchlaufende
           Liste braucht eine sichtbare Kante: eine deckende 1px-Linie trennt
           immer (hell wie dunkel), der weiche Schatten legt sich nur zusaetzlich
           drueber. Der fruehere Schatten lief ueber --app-canvas und war im
           Hellmodus weiss-auf-weiss, also unsichtbar. */
        border-color: transparent;
        border-bottom: 1px solid var(--app-border, var(--border));
        border-radius: 0 0 20px 20px;
        box-shadow: 0 8px 16px -10px rgba(17, 12, 26, 0.55);
    }

    .schedule-status-switch-btn {
        flex: 1 1 0;
        min-width: 0;
        min-height: 44px;
    }
}

/* =========================================================================
   SONGPOOL-AUSWAHLLEISTE UND -TABELLE

   Bandpool, privater Songpool und Organisations-Songpool zeigen dieselbe
   Tabelle, waren aber dreimal getrennt umgesetzt: drei Klassensaetze, drei
   Regelbloecke, drei Ergebnisse. Die Kaestchen waren 18px (Band), 17px
   (Organisation) und 16px (privat) gross und liefen auf zwei verschiedenen
   Akzentfarben; die Auswahlleiste des privaten Songpools stand ausserdem auf
   `display: none` und konnte deshalb nie erscheinen - dort fehlten Loeschen
   und Herunterladen vollstaendig.

   Grundlage ist der Band-Stand: er war der einzige durchgehend an Tokens
   gebundene. Die drei alten Klassensaetze sind entfernt.
   ========================================================================= */

.songpool-bulkbar {
    display: flex;
    min-height: 60px;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid color-mix(in srgb, var(--app-accent) 30%, var(--app-border));
    border-radius: var(--radius-md);
    background: var(--app-accent-soft);
}

.songpool-bulkbar[hidden] {
    display: none;
}

.songpool-bulkinfo {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
}

.songpool-bulk-label {
    color: var(--app-muted);
    font-size: var(--font-meta-size);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.songpool-bulkinfo strong {
    color: var(--app-ink);
    font-size: var(--font-card-title-size);
}

.songpool-bulkactions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.songpool-bulkactions .btn {
    min-height: var(--app-control-height);
}

/* Ein Kaestchen, eine Groesse, eine Akzentfarbe - fuer alle drei Tabellen. */
.songpool-table input[type="checkbox"] {
    width: 18px;
    height: 18px;
    min-width: 18px;
    min-height: 18px;
    margin: 0;
    accent-color: var(--app-accent);
    cursor: pointer;
}

@media (max-width: 820px) {
    .songpool-bulkbar {
        align-items: stretch;
        flex-direction: column;
    }

    .songpool-bulkactions {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .songpool-bulkactions .btn {
        width: 100%;
    }
}

/* Menue hinter "Song hinzufügen" - identisch im privaten und im
   Organisations-Songpool. Vorher lag es unter `#songpoolView` und griff
   deshalb in der Organisation nicht; dort kamen ausserdem andere Symbole in
   anderer Groesse zum Einsatz. */
.songpool-add-menu {
    right: 0;
    min-width: 240px;
}

.songpool-add-menu-icon {
    width: 18px;
    height: 18px;
}

/* =========================================================================
   GEMEINSAME SONG-TABELLE (Aussehen)

   Bisher stand diese komplette Sektion nur unter `#songpoolView` - band-
   und Organisations-Tabelle liefen auf eigenen `.bandpool-*` /
   `.org-songpool-*` Klassen mit eigenen, fast identischen Regeln. Seit
   js/app.js:renderSongPoolTable() alle drei Kontexte mit denselben Klassen
   rendert, gilt hier eine Regel fuer alle drei - inklusive der
   Sortierkopf-Optik und der Spalten-Breitengriffe, die es fuer Band und
   Organisation vorher schlicht nicht gab (im DOM vorhanden, aber unstyled
   und damit unsichtbar).

   Was NICHT hier steht: Werkzeugleiste, Suchfeld, Kopfbereich, das
   "Song hinzufügen"-Menü und die (nur privat genutzte) synchronisierte
   Scrollleiste - die bleiben bewusst je Kontext eigenständig.
   ========================================================================= */

.band-setlist-table.songpool-table {
    table-layout: fixed;
}

.band-setlist-table-wrap {
    position: relative;
    overflow-x: auto;
    overflow-y: visible;
    max-height: none;
    border-radius: 18px;
    border: 1px solid var(--border);
    background: var(--surface);
    scrollbar-gutter: auto;
    overscroll-behavior-x: contain;
    overscroll-behavior-y: auto;
    scrollbar-width: thin;
    -ms-overflow-style: auto;
}

.songpool-table-shell {
    overflow-x: auto;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--surface);
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
}

.band-setlist-table {
    width: 100%;
    min-width: 1200px;
    margin-top: 0 !important;
    border: none;
    border-radius: 0;
    border-collapse: collapse;
}

.songpool-table-row {
    border-bottom: 1px solid var(--border);
    transition: background-color var(--transition-fast);
}

.songpool-table-row:last-child {
    border-bottom: none;
}

.songpool-table-row:hover {
    background: var(--surface-secondary);
}

.songpool-table-row.songpool-row-shared td {
    background: color-mix(in srgb, var(--surface-secondary) 80%, transparent);
}

.band-setlist-table thead th {
    position: sticky;
    top: 0;
    z-index: 4;
    background: color-mix(in srgb, var(--surface-secondary) 96%, var(--surface));
    box-shadow: 0 1px 0 var(--border), 0 10px 20px -18px rgba(2, 6, 23, 0.82);
}

.band-setlist-table th,
.band-setlist-table td {
    padding: 10px 9px !important;
}

.band-setlist-table th {
    font-size: var(--font-meta-size);
}

.band-setlist-table td {
    font-size: var(--font-meta-size);
    line-height: 1.42;
    vertical-align: top;
}

.band-setlist-table td[data-label="Infos"] {
    max-width: none;
    white-space: normal;
    color: var(--text-secondary);
}

.songpool-select-heading,
.songpool-select-cell,
.songpool-actions-heading,
.songpool-actions-cell,
.songpool-files-heading,
.songpool-files-cell {
    text-align: center;
}

/* Titel- und Interpret-Zelle koennen zweizeilig werden (Titel + Dateibadges);
   Auswahl/Aktionen/Dateien bleiben dabei immer einzeilig - ohne dies stehen
   sie am oberen statt am vertikalen Zentrum der Zeile. Ueber `.band-setlist-
   table` skaliert, weil `.band-setlist-table td { vertical-align: top }`
   sonst wegen hoeherer Spezifitaet (Klasse+Typ vs. nur Klasse) gewinnt. */
.band-setlist-table .songpool-select-cell,
.band-setlist-table .songpool-actions-cell,
.band-setlist-table .songpool-files-cell {
    vertical-align: middle;
}

.songpool-select-heading {
    width: 48px;
}

.songpool-actions-heading,
.songpool-actions-cell {
    width: 108px;
    min-width: 108px;
    white-space: nowrap;
}

.songpool-actions-cell > div {
    gap: 6px !important;
}

/* Sortierkopf */
.band-setlist-table .sortable-header {
    padding-right: 12px;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: background-color 0.2s ease;
}

.band-setlist-table .sortable-header::after {
    display: none;
}

.band-setlist-table .sortable-header-content {
    display: inline-flex;
    align-items: center;
    gap: 0.42rem;
    min-width: 0;
}

.band-setlist-table .sortable-header-label {
    display: inline-block;
}

.band-setlist-table .sortable-header-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.22rem;
    height: 1.22rem;
    flex: 0 0 1.22rem;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--color-border) 84%, transparent);
    background: color-mix(in srgb, var(--color-surface-hover) 38%, transparent);
    color: var(--color-text-secondary);
    font-size: var(--font-meta-size);
    font-weight: 800;
    line-height: 1;
    transition: all 0.2s ease;
}

.band-setlist-table .sortable-header .sortable-header-icon::before {
    content: '';
    display: inline-block;
    width: 1.1em;
    height: 1.1em;
    background-color: currentColor;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 15 5 5 5-5'/%3E%3Cpath d='m7 9 5-5 5 5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 15 5 5 5-5'/%3E%3Cpath d='m7 9 5-5 5 5'/%3E%3C/svg%3E");
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
}

.band-setlist-table .sortable-header:hover .sortable-header-icon {
    color: var(--color-text);
    border-color: color-mix(in srgb, var(--color-primary) 20%, var(--color-border));
    background: color-mix(in srgb, var(--color-primary) 10%, var(--color-surface-hover));
}

.band-setlist-table .sortable-header:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--color-primary) 62%, transparent);
    outline-offset: -3px;
}

.band-setlist-table .sortable-header.sort-asc .sortable-header-icon,
.band-setlist-table .sortable-header.sort-desc .sortable-header-icon {
    color: var(--color-primary);
    border-color: color-mix(in srgb, var(--color-primary) 28%, var(--color-border));
    background: color-mix(in srgb, var(--color-primary) 14%, var(--color-surface-hover));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

.band-setlist-table .sortable-header.sort-asc .sortable-header-icon::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E");
}

.band-setlist-table .sortable-header.sort-desc .sortable-header-icon::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}

.band-setlist-table .sortable-col-title {
    min-width: 300px;
}

.band-setlist-table .sortable-col-artist {
    min-width: 180px;
}

.band-setlist-table .sortable-col-bpm,
.band-setlist-table .sortable-col-time,
.band-setlist-table .sortable-col-original-key,
.band-setlist-table .sortable-col-ccli {
    min-width: 88px;
}

.band-setlist-table .sortable-col-key,
.band-setlist-table .sortable-col-tracks {
    min-width: 108px;
}

.band-setlist-table .sortable-col-lead,
.band-setlist-table .sortable-col-language {
    min-width: 112px;
}

/* Spaltengriffe zum Verbreitern/Verschmälern */
.band-setlist-table .resizable-column-header {
    position: sticky;
    padding-right: 18px !important;
    user-select: none;
}

.band-setlist-table .column-resize-handle {
    position: absolute;
    top: 0;
    right: -5px;
    bottom: 0;
    z-index: 4;
    width: 10px;
    cursor: col-resize;
    touch-action: none;
}

.band-setlist-table .column-resize-handle::after {
    content: '';
    position: absolute;
    top: 22%;
    bottom: 22%;
    left: 4px;
    width: 2px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--color-primary) 70%, white 6%);
    opacity: 0;
    transform: scaleY(0.72);
    transition: opacity 0.16s ease, transform 0.16s ease, box-shadow 0.16s ease;
}

.band-setlist-table .resizable-column-header:hover .column-resize-handle::after,
.band-setlist-table .resizable-column-header.is-resizing .column-resize-handle::after {
    opacity: 1;
    transform: scaleY(1);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 16%, transparent);
}

.band-setlist-table.is-resizing-column,
body.is-resizing-song-column {
    cursor: col-resize;
    user-select: none;
}

/* Zeileninhalt */
.songpool-row-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}

.songpool-row-actions .btn-icon {
    width: 38px;
    height: 38px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    color: var(--text-secondary);
}

.songpool-row-actions .btn-icon:hover {
    border-color: color-mix(in srgb, var(--color-primary) 34%, var(--border));
    background: var(--surface-secondary);
    color: var(--color-primary);
}

.songpool-row-actions .btn-danger-ghost:hover {
    border-color: color-mix(in srgb, var(--color-danger) 38%, var(--border));
    background: color-mix(in srgb, var(--color-danger) 10%, var(--surface));
    color: var(--color-danger);
}

.songpool-title-cell {
    display: grid;
    gap: 0.38rem;
    min-width: 0;
}

.songpool-title-main {
    appearance: none;
    width: fit-content;
    max-width: 100%;
    padding: 0;
    border: 0;
    background: transparent;
    font-weight: 600;
    font: inherit;
    color: var(--text-primary);
    line-height: 1.35;
    text-align: left;
    word-break: break-word;
    cursor: pointer;
}

.songpool-title-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
}

.songpool-document-badge {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    padding: 0.18rem 0.58rem;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--color-primary) 18%, var(--border));
    background: color-mix(in srgb, var(--color-primary) 9%, transparent);
    color: var(--color-primary);
    font-size: var(--font-meta-size);
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
}

.songpool-document-badge.is-chordpro {
    border-color: color-mix(in srgb, #14b8a6 28%, var(--border));
    background: color-mix(in srgb, #14b8a6 12%, transparent);
    color: color-mix(in srgb, #14b8a6 82%, white 5%);
}

.songpool-readonly-cell {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 34px;
    color: var(--text-muted);
    font-weight: 700;
    cursor: help;
    opacity: 0.6;
}

.band-setlist-table .song-table-title-cell {
    min-width: 0;
    max-width: none;
    white-space: normal !important;
    vertical-align: middle;
}

.band-setlist-table .song-table-title-text {
    display: block !important;
    max-width: 100%;
    min-width: 0;
    white-space: normal !important;
    overflow-wrap: anywhere;
    word-break: normal;
    line-height: 1.35;
}

.band-setlist-table .song-table-artist-cell {
    min-width: 0;
    max-width: none;
    white-space: normal !important;
    vertical-align: middle;
}

.song-table-artist-badge {
    display: inline-block;
    max-width: 100%;
    width: fit-content;
    min-width: 0;
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: normal;
    color: var(--text-secondary);
    font-size: var(--font-meta-size);
    line-height: 1.32;
    text-align: left;
}

.songpool-meta-cell {
    color: var(--text-secondary);
    font-size: var(--font-meta-size);
}

.songpool-key-badge {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
    padding: 0.25rem 0.62rem;
    border: 1px solid color-mix(in srgb, var(--color-success) 28%, var(--border));
    border-radius: 8px;
    background: color-mix(in srgb, var(--color-success) 10%, transparent);
    color: var(--color-success);
    font-size: var(--font-meta-size);
    font-weight: 650;
}

.songpool-ccli-cell {
    color: var(--text-secondary);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
    font-size: var(--font-meta-size);
}

.songpool-empty-row td {
    padding: var(--spacing-xl) !important;
    color: var(--color-text-light);
    text-align: center;
}

@media (max-width: 768px) {
    .band-setlist-table.songpool-table {
        width: max-content !important;
        min-width: 100%;
        table-layout: auto;
    }

    .band-setlist-table.songpool-table th,
    .band-setlist-table.songpool-table td {
        white-space: nowrap !important;
    }

    .band-setlist-table.songpool-table th:last-child,
    .band-setlist-table.songpool-table td:last-child {
        width: 1% !important;
        padding-right: 14px;
    }

    .band-setlist-table .column-resize-handle {
        display: none;
    }

    .band-setlist-table .resizable-column-header {
        padding-right: 9px !important;
    }
}

@media (prefers-reduced-motion: reduce) {
    /* Stand bisher nur im Bandpool, wo die Zeile und der Spaltengriff
       tatsaechlich eine Transition hatten - jetzt fuer alle drei gleich. */
    .songpool-table-row,
    .band-setlist-table .column-resize-handle::after {
        transition: none;
    }
}

/* ===========================================================================
   Trefferflaechen-Nachzug (Audit 09.09.2026)
   ---------------------------------------------------------------------------
   Diese Komponenten hatten 44px fest verdrahtet - Apples Minimum, aber unter
   Materials 48dp. Auf Touch-Geraeten auf 48px angehoben, Desktop unberuehrt.
   Steht bewusst am DATEIENDE: die Ursprungsregeln stehen weiter oben bzw. in
   spaeteren Media-Bloecken, bei gleicher Spezifitaet gewinnt die letzte Regel.
   Siehe docs/MOBILE_UI_STANDARDS.md, Abschnitt 2.
   =========================================================================== */
@media (pointer: coarse) {
    .schedule-status-switch-btn {
        min-height: 48px;
    }
}
