html, body { height: 100%; }
body { display: flex; flex-direction: column; min-height: 100vh; }
main { flex: 1 0 auto; padding-top: 1rem; }
footer { flex-shrink: 0; }

/* ── Global responsive foundation (mobile-first) ─────────────────────────
   Goal: no page ever needs a horizontal scrollbar. We fix the ROOT causes
   (wide flex rows, full-width buttons next to siblings, fixed-width media)
   rather than clipping. A single `overflow-x: clip` on <body> remains as a
   last-resort guardrail only — the layout is built not to rely on it. */
*, *::before, *::after { box-sizing: border-box; }
body { overflow-x: clip; }

/* ══════════════════════════════════════════════════════════════════════════
   THEME SYSTEM
   Five selectable looks for a modern choir, chosen with the SITE_THEME env var
   (warm | forest | navy | mono | plum) which sets <html data-theme="…">. Each
   theme is just a palette + font pairing in CSS variables; a single component
   layer below maps those variables onto Bootstrap so no templates change.
   ────────────────────────────────────────────────────────────────────────── */

/* Font stacks (families loaded in base.html.twig; graceful serif/sans fallbacks). */
:root {
    --font-cormorant: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
    --font-fraunces:  'Fraunces', Georgia, 'Times New Roman', serif;
    --font-inter:     'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

/* ── warm — Burgundy & Gold (default): classic choir elegance, serif headings */
:root, [data-theme="warm"] {
    --site-bg: #faf6ef;   --site-surface: #ffffff;  --site-surface-2: #f3ece0;
    --site-ink: #2b2422;  --site-muted: #6f645d;    --site-border: #e7ddcf;
    --site-primary: #7a1f2b;  --site-primary-rgb: 122,31,43;  --site-primary-hover: #641823;  --site-on-primary: #ffffff;
    --site-accent: #c8a24a;   --site-accent-rgb: 200,162,74;  --site-accent-ink: #4a3a12;
    --site-navbar-bg: #2a2020;  --site-navbar-ink: #f3e9e0;  --site-member-bg: #382a2a;  --site-footer-bg: #241b1b;
    --site-head-font: var(--font-cormorant);  --site-head-weight: 700;  --site-head-spacing: .01em;
    --site-body-font: var(--font-inter);
    --site-hero: linear-gradient(135deg, #2a2020 0%, #4a2530 55%, #7a1f2b 100%);
}
/* ── forest — Forest Green & Amber: fresh, contemporary, clean sans */
[data-theme="forest"] {
    --site-bg: #f7f5f0;   --site-surface: #ffffff;  --site-surface-2: #eef1ea;
    --site-ink: #22302a;  --site-muted: #5c6b62;    --site-border: #e0e4dc;
    --site-primary: #2f6b4f;  --site-primary-rgb: 47,107,79;  --site-primary-hover: #245840;  --site-on-primary: #ffffff;
    --site-accent: #d9a441;   --site-accent-rgb: 217,164,65;  --site-accent-ink: #4a3410;
    --site-navbar-bg: #1e2b24;  --site-navbar-ink: #eaf1ea;  --site-member-bg: #26362d;  --site-footer-bg: #1a251f;
    --site-head-font: var(--font-inter);  --site-head-weight: 700;  --site-head-spacing: -.015em;
    --site-body-font: var(--font-inter);
    --site-hero: linear-gradient(135deg, #1e2b24 0%, #2f6b4f 100%);
}
/* ── navy — Deep Navy & Gold: refined concert-hall blue, serif headings */
[data-theme="navy"] {
    --site-bg: #f4f6fa;   --site-surface: #ffffff;  --site-surface-2: #e9eef6;
    --site-ink: #1c2430;  --site-muted: #5a6572;    --site-border: #dbe1ea;
    --site-primary: #1f3a5f;  --site-primary-rgb: 31,58,95;  --site-primary-hover: #172e4c;  --site-on-primary: #ffffff;
    --site-accent: #c6a24a;   --site-accent-rgb: 198,162,74;  --site-accent-ink: #3a2f12;
    --site-navbar-bg: #14243a;  --site-navbar-ink: #e7edf6;  --site-member-bg: #1c3149;  --site-footer-bg: #101d2e;
    --site-head-font: var(--font-cormorant);  --site-head-weight: 700;  --site-head-spacing: .01em;
    --site-body-font: var(--font-inter);
    --site-hero: linear-gradient(135deg, #14243a 0%, #1f3a5f 100%);
}
/* ── mono — Graphite & Gold: understated, timeless, modern serif headings */
[data-theme="mono"] {
    --site-bg: #f6f4f1;   --site-surface: #ffffff;  --site-surface-2: #edeae5;
    --site-ink: #1e1c1a;  --site-muted: #6b665f;    --site-border: #e4e0da;
    --site-primary: #33312e;  --site-primary-rgb: 51,49,46;  --site-primary-hover: #201f1d;  --site-on-primary: #ffffff;
    --site-accent: #b58a3c;   --site-accent-rgb: 181,138,60;  --site-accent-ink: #3a2c12;
    --site-navbar-bg: #1b1a18;  --site-navbar-ink: #ece9e4;  --site-member-bg: #2a2825;  --site-footer-bg: #161513;
    --site-head-font: var(--font-fraunces);  --site-head-weight: 600;  --site-head-spacing: .005em;
    --site-body-font: var(--font-inter);
    --site-hero: linear-gradient(135deg, #1b1a18 0%, #3a3733 100%);
}
/* ── plum — Plum & Copper: warm contemporary, modern serif headings */
[data-theme="plum"] {
    --site-bg: #f9f5f6;   --site-surface: #ffffff;  --site-surface-2: #f0e7ea;
    --site-ink: #2c2028;  --site-muted: #6d5f66;    --site-border: #ebe0e5;
    --site-primary: #6a2c4f;  --site-primary-rgb: 106,44,79;  --site-primary-hover: #571f40;  --site-on-primary: #ffffff;
    --site-accent: #b5763f;   --site-accent-rgb: 181,118,63;  --site-accent-ink: #ffffff;
    --site-navbar-bg: #241820;  --site-navbar-ink: #f2e6ec;  --site-member-bg: #34222c;  --site-footer-bg: #1f141b;
    --site-head-font: var(--font-fraunces);  --site-head-weight: 600;  --site-head-spacing: .005em;
    --site-body-font: var(--font-inter);
    --site-hero: linear-gradient(135deg, #241820 0%, #6a2c4f 100%);
}

/* ── Seasonal themes: each pairs a palette with a hero illustration (SVG in
      public/images/themes/) blending the season with musical motifs — staves,
      notes, blossoms/leaves/snowflakes. The illustration layers over a seasonal
      gradient; motifs hug the edges so centred hero text stays legible. ─────── */
[data-theme="spring"] {
    --site-bg: #f3f8f3;   --site-surface: #ffffff;  --site-surface-2: #e8f1e8;
    --site-ink: #1f2a22;  --site-muted: #5d6b60;    --site-border: #dde7dc;
    --site-primary: #47895a;  --site-primary-rgb: 71,137,90;  --site-primary-hover: #3a7449;  --site-on-primary: #ffffff;
    --site-accent: #d97a97;   --site-accent-rgb: 217,122,151;  --site-accent-ink: #4a1f2c;
    --site-navbar-bg: #24402e;  --site-navbar-ink: #eaf3ea;  --site-member-bg: #2c4d38;  --site-footer-bg: #1c3324;
    --site-head-font: var(--font-cormorant);  --site-head-weight: 700;  --site-head-spacing: .01em;
    --site-body-font: var(--font-inter);
    --site-hero: url('/images/themes/spring.svg?v=3') center/cover no-repeat,
                 linear-gradient(135deg, #2e5a3b 0%, #47895a 100%);
}
[data-theme="summer"] {
    --site-bg: #f4f8fb;   --site-surface: #ffffff;  --site-surface-2: #e6f0f5;
    --site-ink: #16262d;  --site-muted: #566670;    --site-border: #dde6ec;
    --site-primary: #1f7f9e;  --site-primary-rgb: 31,127,158;  --site-primary-hover: #196a85;  --site-on-primary: #ffffff;
    --site-accent: #edb63a;   --site-accent-rgb: 237,182,58;  --site-accent-ink: #4a3410;
    --site-navbar-bg: #123c4b;  --site-navbar-ink: #e6f2f6;  --site-member-bg: #17505f;  --site-footer-bg: #0e2f3b;
    --site-head-font: var(--font-fraunces);  --site-head-weight: 600;  --site-head-spacing: .005em;
    --site-body-font: var(--font-inter);
    --site-hero: url('/images/themes/summer.svg?v=2') center/cover no-repeat,
                 linear-gradient(135deg, #185f78 0%, #2f8fb0 100%);
}
[data-theme="autumn"] {
    --site-bg: #faf4ec;   --site-surface: #ffffff;  --site-surface-2: #f2e7d7;
    --site-ink: #2a1c14;  --site-muted: #6b5c50;    --site-border: #ece1d2;
    --site-primary: #a8481f;  --site-primary-rgb: 168,72,31;  --site-primary-hover: #8c3a16;  --site-on-primary: #ffffff;
    --site-accent: #d98a2b;   --site-accent-rgb: 217,138,43;  --site-accent-ink: #3a2410;
    --site-navbar-bg: #3a1c10;  --site-navbar-ink: #f4e7da;  --site-member-bg: #4d2717;  --site-footer-bg: #2a140b;
    --site-head-font: var(--font-cormorant);  --site-head-weight: 700;  --site-head-spacing: .01em;
    --site-body-font: var(--font-inter);
    --site-hero: url('/images/themes/autumn.svg?v=2') center/cover no-repeat,
                 linear-gradient(135deg, #6e2f14 0%, #a8481f 100%);
}
[data-theme="winter"] {
    --site-bg: #f1f4f8;   --site-surface: #ffffff;  --site-surface-2: #e6ecf3;
    --site-ink: #1a2230;  --site-muted: #5a6572;    --site-border: #dde3ec;
    --site-primary: #294060;  --site-primary-rgb: 41,64,96;  --site-primary-hover: #20334d;  --site-on-primary: #ffffff;
    --site-accent: #6ea3c4;   --site-accent-rgb: 110,163,196;  --site-accent-ink: #10222f;
    --site-navbar-bg: #182740;  --site-navbar-ink: #e6edf6;  --site-member-bg: #223252;  --site-footer-bg: #101a2e;
    --site-head-font: var(--font-fraunces);  --site-head-weight: 600;  --site-head-spacing: .005em;
    --site-body-font: var(--font-inter);
    --site-hero: url('/images/themes/winter.svg?v=2') center/cover no-repeat,
                 linear-gradient(135deg, #1c2c40 0%, #33506f 100%);
}

/* ── Component layer: map the theme variables onto Bootstrap + base elements ── */
:root {
    --bs-primary: var(--site-primary);
    --bs-primary-rgb: var(--site-primary-rgb);
    --bs-link-color: var(--site-primary);
    --bs-link-color-rgb: var(--site-primary-rgb);
    --bs-link-hover-color: var(--site-primary-hover);
    --bs-body-bg: var(--site-bg);
    --bs-body-color: var(--site-ink);
    --bs-border-color: var(--site-border);
}
body {
    background-color: var(--site-bg);
    color: var(--site-ink);
    font-family: var(--site-body-font);
}
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--site-head-font);
    font-weight: var(--site-head-weight);
    letter-spacing: var(--site-head-spacing);
    /* Colour is inherited (Bootstrap default), so headings are dark on the page
       body yet stay light inside dark/coloured contexts (e.g. .text-white card
       headers). Don't force a colour here or those become dark-on-dark. */
}
.navbar-brand {
    font-family: var(--site-head-font);
    font-weight: var(--site-head-weight);
    letter-spacing: .02em;
    font-size: 1.4rem;
}
a { color: var(--site-primary); text-underline-offset: .15em; }
a:hover { color: var(--site-primary-hover); }
.lead { color: var(--site-muted); font-weight: 400; }
.text-primary { color: var(--site-primary) !important; }
.bg-primary { background-color: var(--site-primary) !important; }
.border-primary { border-color: var(--site-primary) !important; }

/* Buttons — primary */
.btn-primary {
    --bs-btn-bg: var(--site-primary);              --bs-btn-border-color: var(--site-primary);
    --bs-btn-hover-bg: var(--site-primary-hover);  --bs-btn-hover-border-color: var(--site-primary-hover);
    --bs-btn-active-bg: var(--site-primary-hover);  --bs-btn-active-border-color: var(--site-primary-hover);
    --bs-btn-disabled-bg: var(--site-primary);     --bs-btn-disabled-border-color: var(--site-primary);
    --bs-btn-color: var(--site-on-primary);        --bs-btn-hover-color: var(--site-on-primary);
    --bs-btn-active-color: var(--site-on-primary);  --bs-btn-disabled-color: var(--site-on-primary);
}
.btn-outline-primary {
    --bs-btn-color: var(--site-primary);           --bs-btn-border-color: var(--site-primary);
    --bs-btn-hover-bg: var(--site-primary);        --bs-btn-hover-border-color: var(--site-primary);
    --bs-btn-hover-color: var(--site-on-primary);
    --bs-btn-active-bg: var(--site-primary);       --bs-btn-active-border-color: var(--site-primary);
    --bs-btn-active-color: var(--site-on-primary);
}
.btn { border-radius: .5rem; }
.btn-sm { border-radius: .4rem; }

/* Accent = the theme's gold/amber/copper. Bootstrap's "warning" role (member nav
   highlight, logout, LiederListe) is re-tinted to the accent so it stays on-theme. */
.text-warning { color: var(--site-accent) !important; }
.btn-warning {
    --bs-btn-bg: var(--site-accent);        --bs-btn-border-color: var(--site-accent);
    --bs-btn-hover-bg: var(--site-accent);  --bs-btn-hover-border-color: var(--site-accent);
    --bs-btn-color: var(--site-accent-ink);  --bs-btn-hover-color: var(--site-accent-ink);
    --bs-btn-active-color: var(--site-accent-ink);
    filter: none;
}
.btn-outline-warning {
    --bs-btn-color: var(--site-accent);        --bs-btn-border-color: var(--site-accent);
    --bs-btn-hover-bg: var(--site-accent);     --bs-btn-hover-border-color: var(--site-accent);
    --bs-btn-hover-color: var(--site-accent-ink);
    --bs-btn-active-bg: var(--site-accent);    --bs-btn-active-color: var(--site-accent-ink);
}

/* Cards & surfaces */
.card {
    --bs-card-bg: var(--site-surface);
    --bs-card-border-color: var(--site-border);
    border-radius: .75rem;
    box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 6px 20px rgba(0,0,0,.05);
}
.card-title { font-family: var(--site-head-font); font-weight: var(--site-head-weight); }

/* Navbars & footer */
.navbar.bg-dark { background-color: var(--site-navbar-bg) !important; }
.navbar.member-nav {
    background-color: var(--site-member-bg);
    border-top: 2px solid var(--site-accent);
}
.navbar .nav-link.active,
.navbar .nav-link:hover { color: var(--site-accent) !important; }
footer.bg-dark { background-color: var(--site-footer-bg) !important; }

/* Form focus ring picks up the theme colour */
.form-control:focus, .form-select:focus, .form-check-input:focus {
    border-color: var(--site-primary);
    box-shadow: 0 0 0 .2rem rgba(var(--site-primary-rgb), .25);
}
.form-check-input:checked { background-color: var(--site-primary); border-color: var(--site-primary); }

/* Homepage / section hero: a full-width themed band. Any <h1> that opens a page
   container gets the display treatment; add .site-hero for the coloured band. */
.site-hero {
    background: var(--site-hero);
    background-size: cover;
    background-position: center;
    color: #fff;
    border-radius: 1rem;
    padding: clamp(1.75rem, 4vw, 3rem) clamp(1.25rem, 5vw, 3rem);
    /* Scale the band's height with its width so the illustrated hero keeps close
       to the artwork's proportions — otherwise a wide screen makes a short, very
       letterboxed band and `cover` crops the top/bottom motifs (sun, notes) away.
       Centre the text so it stays balanced as the band grows. */
    min-height: clamp(240px, 26vw, 400px);
    display: flex;
    flex-direction: column;
    justify-content: center;
    margin-bottom: 2rem;
    box-shadow: 0 10px 30px rgba(0,0,0,.12);
}
.site-hero h1, .site-hero .h1 { color: #fff; margin-bottom: .5rem; }
.site-hero .lead { color: rgba(255,255,255,.85); }
.site-hero::after {
    content: ""; display: block; width: 3.5rem; height: 3px;
    background: var(--site-accent); margin-top: 1.25rem; border-radius: 2px;
}
/* On phones the near-square hero crops the illustration's sides (cover). Anchor
   the summer art to the right so its top-right sun stays on screen instead of
   being cropped away with the reeds on the left; and ease the hero title down a
   size so it no longer fills the whole band and overlaps the sun. */
@media (max-width: 575.98px) {
    .site-hero h1, .site-hero .h1 { font-size: 1.4rem; line-height: 1.2; }
    .site-hero .lead { font-size: .95rem; }
    /* Summer's sun sits in the top-right, so on phones lay the text into a left
       column and anchor the art to the right — the title stays clear of the sun
       instead of running underneath it. */
    [data-theme="summer"] .site-hero {
        background-position: right center;
        align-items: flex-start;
        text-align: left !important;
    }
    [data-theme="summer"] .site-hero > * { max-width: 64%; }
}
/* END THEME SYSTEM ═════════════════════════════════════════════════════════ */

/* On a PC the Partitur modal uses most of the screen width (mobile stays
   fullscreen via modal-fullscreen-lg-down) so more of the horizontal score is
   visible without scrolling. The #id beats Bootstrap's .modal-xl max-width. */
@media (min-width: 992px) {
    #partiturModal .modal-dialog { max-width: 92vw; }
}

/* ── Partitur: immersive full-screen score view. The presentation follows the
   device's real orientation (JS: applyOrientationMode):
     • .osmd-immersive            → full-screen overlay, upright (phone already
                                     held in landscape — "natural fill").
     • .osmd-immersive.osmd-rotated → additionally turned 90° so the wide score
                                     fills a phone held in portrait. The 100vh/100vw
                                     swap maps the element's width onto the screen
                                     height and vice-versa. */
body.osmd-landscape-active { overflow: hidden; }
.osmd-viewer.osmd-immersive {
    /* !important beats Bootstrap's .position-relative utility on the wrapper. */
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    width: 100vw;
    height: 100vh;
    margin: 0;
    z-index: 2000;
    background: #fff;
    display: flex;
    flex-direction: column;
}
.osmd-viewer.osmd-immersive.osmd-rotated {
    width: 100vh;
    height: 100vw;
    transform-origin: top left;
    transform: rotate(90deg) translateY(-100%);
}
/* Controls bar stays a compact strip along the top edge; the score takes the rest. */
.osmd-viewer.osmd-immersive .osmd-controls-bar {
    flex: 0 0 auto;
    margin: 0;
    padding: .5rem .75rem;
    background: #fff;
    border-bottom: 1px solid #dee2e6;
}
.osmd-viewer.osmd-immersive .osmd-score-wrap {
    flex: 1 1 auto;
    min-height: 0;
}
.osmd-viewer.osmd-immersive .osmd-scroll {
    max-height: none !important;
    height: 100% !important;
    border-radius: 0 !important;
    /* No flex-centring here: align-items:center makes overflow unreachable by
       scrollTop, which would break scrollStaffIntoCenter (selecting a voice).
       The fit-zoom already sizes the staff to roughly fill, so top-aligned is
       fine and vertical scroll-to-voice keeps working. */
}

/* The single landscape toggle button swaps its label between "Querformat"
   (enter) and "Hochformat" (exit) depending on the immersive state. */
.osmd-toggle-exit { display: none; }
.osmd-viewer.osmd-immersive .osmd-toggle-enter { display: none !important; }
.osmd-viewer.osmd-immersive .osmd-toggle-exit { display: inline-block; }

/* All replaced/embedded media shrinks to fit its container */
img, canvas, video, iframe, svg { max-width: 100%; }
img { height: auto !important; }

/* …except the OSMD Partitur score, which is one very wide SVG that must scroll
   horizontally (renderSingleHorizontalStaffline). Exempt it from the guard above. */
[data-osmd-target="container"] svg { max-width: none; }

/* Constrain inline-block wrappers (used for rotated post images) */
div[style*="inline-block"] { max-width: 100%; }

/* Long words / URLs in content must wrap instead of forcing width. break-word
   wraps at spaces first and only splits a word when it alone is too wide — far
   tidier than `anywhere`, which breaks greedily mid-word inside narrow cells. */
.post-paragraph, .card-text, .ksl-title, .accordion-button,
td, th, .breadcrumb-item, .form-check-label { overflow-wrap: break-word; }

/* Flex children default to min-width:auto and refuse to shrink below their
   content, which is the #1 cause of horizontal overflow. This utility lets a
   flex item shrink past its content width (pair with text-truncate where wanted). */
.minw-0 { min-width: 0 !important; }

/* Song-browser row layout (Noten / Aktuelle Proben) is defined below — see ".song-row". */

/* Hide empty paragraphs from Quill editor output (outside the editor and post content) */
/* Rules are split so p:empty works even in browsers without :has() (Safari < 15.4) */
p:empty { display: none; }
p:has(br:only-child) { display: none; }

/* Keep Quill editor paragraphs visible (it uses <p><br></p> for blank lines and cursor) */
.ql-editor p:empty { display: block !important; }
.ql-editor p:has(br:only-child) { display: block !important; }

/* Quill paragraph content: <p> blocks act as single line breaks */
.post-paragraph p { margin: 0; }
/* Quill alignment classes outside the editor (öffentliche Seiten) */
.post-paragraph .ql-align-center  { text-align: center; }
.post-paragraph .ql-align-right   { text-align: right; }
.post-paragraph .ql-align-justify { text-align: justify; }
/* Allow empty <p><br></p> to show as blank lines inside post content */
.post-paragraph p:empty { display: block; }
.post-paragraph p:has(br:only-child) { display: block; }

/* Lightbox overlay for post images */
#lightbox-overlay {
    display: none;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background: rgba(0, 0, 0, 0.88);
    z-index: 9999;
    cursor: zoom-out;
    align-items: center;
    justify-content: center;
}
#lightbox-overlay.active { display: flex; }
#lightbox-overlay img {
    max-width: 92vw;
    max-height: 92vh;
    object-fit: contain;
    box-shadow: 0 0 40px rgba(0,0,0,0.6);
}

/* Pin the expand chevron to the right edge so it stays vertically aligned
   across rows regardless of genre/file-badge width (esp. on mobile). */
.accordion-btn-files { position: relative; padding-right: 3rem; text-align: left; }
/* When expanded, give the whole row (header columns + body) a light grey
   background instead of Bootstrap's blue tint. The toggle button itself goes
   transparent so the header's Etikett/title/genres/admin columns all share the
   single light background painted on the header row and the collapse panel. */
.accordion-btn-files:not(.collapsed) {
    background-color: transparent;
}
.song-row:has(> .accordion-btn-files:not(.collapsed)),
.accordion-collapse.show,
.accordion-collapse.collapsing {
    background-color: var(--bs-tertiary-bg, #f4f6f8);
}
/* No blue focus ring / active border on the song-row toggles, in any state. */
.accordion-btn-files,
.accordion-btn-files:focus,
.accordion-btn-files:focus-visible,
.accordion-btn-files:not(.collapsed) {
    box-shadow: none;
    outline: none;
    border-color: transparent;
}
.accordion-btn-files::after {
    position: absolute;
    right: 1.25rem;
    top: 50%;
    margin: -0.625rem 0 0 0; /* vertical centering without touching transform (Bootstrap rotates ::after) */
}

/* ── Song-browser rows (Noten / Aktuelle Proben) ─────────────────────────────
   Each accordion header is a grid with FIXED side tracks so every row aligns
   the same way no matter how long the Etikett is or how many genres a song has:
       [ Etikett | toggle (icon · title · genres) | admin controls ]
   The toggle is itself a 3-track grid, so the genre badges form their own
   aligned column on the right and the title takes the flexible middle space. */
/* Desktop: a single row — Etikett | toggle | admin controls (beside the chevron). */
.song-row {
    display: grid;
    grid-template-columns:
        [etikett] var(--song-etikett-w, 8rem)
        [main]    minmax(0, 1fr)
        [ctrl]    auto;
    grid-template-areas: "etikett main ctrl";
    align-items: center;
    column-gap: .25rem;
}
.song-row > .editable-etikett,
.song-row > .song-etikett-col {
    grid-area: etikett;
    align-self: center;
    min-width: 0;
    text-align: right;
}
/* Long Etiketts wrap (at spaces/hyphens first) inside the fixed column
   instead of widening it or breaking mid-word. */
.song-row > .song-etikett-col .badge,
.song-row > .editable-etikett .display-val .badge {
    white-space: normal;
    overflow-wrap: break-word;
    text-align: left;
}
.song-row > .song-ctrl {
    grid-area: ctrl;
    display: flex;
    align-items: center;
    gap: .25rem;
}

/* Toggle button: icon | title | genres (chevron is pinned right, above). */
.song-row > .accordion-btn-files {
    grid-area: main;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) var(--song-genres-w, 12rem);
    align-items: center;
    column-gap: .5rem;
}
.song-row > .accordion-btn-files > .accordion-btn-badges {
    flex-wrap: wrap;
    justify-content: flex-end;
    min-width: 0;
    margin: 0 !important;   /* the grid gap handles spacing; drop ps-3/me-3 */
    padding: 0 !important;
}
/* The PDF/audio count badges are a nested flex unit; on a narrow genres column
   (phones) the pair is wider than the column and would spill left over the title.
   Cap it to the column and let the two counts wrap/stack so they stay aligned. */
.song-row > .accordion-btn-files > .accordion-btn-badges .file-count-badges {
    flex-wrap: wrap;
    justify-content: flex-end;
    max-width: 100%;
}

/* Narrow phones: drop to two rows so the admin controls tuck UNDER the chevron
   (freeing the full width for the title), and tighten the side columns. */
@media (max-width: 575.98px) {
    .song-row {
        grid-template-columns: [etikett] var(--song-etikett-w) [main] minmax(0, 1fr);
        grid-template-areas:
            "etikett main"
            "etikett ctrl";
        align-items: start;
        row-gap: .1rem;
        --song-etikett-w: 4.5rem;
        column-gap: .1rem;
    }
    .song-row > .accordion-btn-files {
        grid-template-columns: auto minmax(0, 1fr);   /* icon | title only */
        padding-right: 1.9rem;       /* room for the chevron at the top-right */
        column-gap: .2rem;
    }
    /* Chevron pinned to the top-right, level with the title's first line. */
    .song-row > .accordion-btn-files::after { right: .55rem; top: 1.7rem; }
    /* Genres, "Sätze" and file-type badges drop to a full-width row tucked
       UNDER the chevron (right-aligned) instead of a separate right-hand column. */
    .song-row > .accordion-btn-files > .accordion-btn-badges {
        grid-column: 1 / -1;
        flex-flow: row wrap;
        justify-content: flex-end;
        align-items: center;
        gap: .25rem;
        margin-top: .35rem !important;
    }
    /* Admin action buttons sit side by side on one line, tucked UNDER the chevron. */
    .song-row > .song-ctrl {
        flex-direction: row;
        justify-self: end;
        align-items: center;
        gap: .3rem;
        padding-right: .35rem;
        padding-bottom: .35rem;
    }
    /* Folder icon hugs the title on phones to save horizontal space. */
    .song-row > .accordion-btn-files > .bi { margin-right: .3rem !important; }
}
