/* css/layout.css
   Aufbau der Seite: Header, die drei Sektionen (Musik, Konzerte, Kontakt),
   Alben, Tickets, Player-Leiste und Footer.
   Semantische Klassen ohne Präfix, weil es das Seitengerüst ist und kein
   isoliertes Animations-Cluster (die Cluster bleiben mit Präfix
   selbstständig: .parallax-…, .birds-…, .waves-…, .palms-…). */

/* ============================= Header ================================== */

/* Fixiert über der Wellenlandschaft, zentriertes Logo. Es bleibt dauerhaft
   am oberen Rand – auf derselben Höhe wie der Player (12 px). Nur die
   Skalierung läuft beim Scrollen von 45 % auf ca. 20 % Breite; der
   vertikale Offset ist konstant und hängt nicht mehr von der Fensterbreite
   ab (Aufgabe 40). */
.site-header {
    --header-offset: 12px; /* gleiche Oberkante wie der Player */
    --logo-scale: 1;       /* Parallax: 1 → 0.44 (altes 45 % → 20 %) */
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 20;
    pointer-events: none; /* reine Schicht, darf Klicks nicht schlucken */
    transform: translateY(var(--header-offset));
}

/* Logo: 800×406 px intrinsic (width/height im HTML gegen Layout-Shift).
   Vorlage: width 45 % des vollflächigen Headers; vw ist vorhersagbarer.
   Das SVG erbt den weichen Schatten des Originalbilds per drop-shadow. */
.site-logo {
    display: block;
    margin: 0 auto;
    height: auto;
    width: 45vw;
    /* Von der Oberkante aus skalieren: So bleibt der sichtbare Abstand
       zum oberen Rand beim Schrumpfen konstant (Aufgabe 43). */
    transform: scale(var(--logo-scale));
    transform-origin: 50% 0;
    filter: drop-shadow(1px 2px 2px rgba(0, 0, 0, 0.32));
}

/* ======================= Scroll-Indikator ============================== */

/* Fixiert unter Bildschirmmitte – wie die Vorlage:
   28 px, weiß, bottom 9px, z-index 20. Standardmäßig unsichtbar;
   JS hängt .is-visible an, solange die Seite ganz oben steht
   (Aufgabe 14 blendet ihn nach dem ersten Scroll aus).
   Inline-SVG statt FontAwesome (Zeichnung: Aufgabe 31). */
.scroll-indicator {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 9px;
    z-index: 20;
    width: 28px;
    height: 28px;
    margin: 0 auto;
    padding: 0;
    border: none;
    background: none;
    color: #ffffff;
    cursor: pointer;
    display: none; /* erst .is-visible macht ihn sichtbar */
}

.scroll-indicator.is-visible {
    display: block;
    /* Wie die Vorlage: 1 s Bounce, 5 s Verzögerung, einmalig.
       Die Keyframes sind die originalen (nur translate3d). */
    animation: scroll-bounce 1s 5s 1 both;
}

.scroll-indicator svg {
    display: block;
    width: 100%;
    height: 100%;
}

/* Kopie des Vorlagen-Keyframes „bounce“: einmaliger Hüpf-Vorgang,
   pro Keyframe-Teil eigenes Easing, reines transform. */
@keyframes scroll-bounce {
    from,
    20%,
    53%,
    80%,
    to {
        animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
        transform: translate3d(0, 0, 0);
    }
    40%,
    43% {
        animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
        transform: translate3d(0, -30px, 0);
    }
    70% {
        animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
        transform: translate3d(0, -15px, 0);
    }
    90% {
        transform: translate3d(0, -4px, 0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .scroll-indicator.is-visible {
        animation: none; /* statischer Zeiger, kein Bounce */
    }
}

/* ============================ Content ================================= */

/* Hält die drei Sektionen. position/z-index wie die Vorlage, damit der
   Inhalt vor der Parallax-Schicht (z-index 0) liegt.
   Die Vorlage hielt 900 px für das Strand-Szene frei; das wird fluid:
   Die Szene soll etwa einen Bildschirm einnehmen, aber auf kleinen
   Displays nicht die halbe Seite fressen. (Fallszeile zuerst für
   Browser ohne dvh-Unterstützung.) */
.content {
    position: relative;
    z-index: 10;
    padding-top: 900px;
    padding-top: clamp(500px, 95dvh, 950px);
}

/* Sektionen als „Kacheln“ – Look 1:1 aus der Vorlage: diagonaler
   Zuschnitt, Papierfaser-Kachelmuster über dem Grundton.
   Clip-Path bleibt der alte Polygon (Steigung 80 px auf 2600 px ist
   gestalterisch so gewollt). Paddings und Strand-Abstände werden
   fluid per clamp() statt 80/30 und 450 px fix; ab ~960 px breit
   übernimmt calc(50% − 450 px) wie in der Vorlage ab 930 px,
   damit der Textblock mittig 900 px breit bleibt. */
.container {
    /* Einheitlicher seitlicher Rand des zentrierten Textblocks. Der
       Prozentwert löst sich erst in .container__body gegen die volle
       Sektionsbreite auf (Aufgabe 60). */
    --container-gutter: max(clamp(16px, 4vw, 30px), calc(50% - 450px));
    margin-bottom: 450px;
    margin-bottom: clamp(240px, 48dvh, 450px);
    /* Kein seitliches Padding mehr: Textblock und Carousels setzen ihre
       Innenabstände selbst. So können die Kartenreihen über die volle
       Breite laufen, während der Text zentriert bleibt.
       Oben mindestens 76 px: Der clip-path beginnt links bei 80 px, und
       die um −3° gedrehte Überschrift ragt mit ihrer rechten oberen Ecke
       darüber hinaus. Mit weniger Padding wurde sie gekappt. */
    padding: clamp(76px, 8vw, 80px) 0;
    color: var(--color-text);
    /* Die rechte Kante muss bei sehr breiten Displays mitwachsen:
       2600 px fest schnitt den Hintergrund ab 3440 px rechts ab.
       max() lässt die Diagonale auf normalen Displays unverändert und
       zieht die Kachel auf Ultrawide-Bildschirmen bis zum Rand. */
    clip-path: polygon(0 80px, max(2600px, 100%) 0, max(2600px, 100%) 100%, 0 calc(100% - 40px));
    background-image: url(../assets/background1.webp);
    background-size: 450px;
    background-blend-mode: overlay; /* Körnung über den Grundton legen */
}

/* Zentrierter Textblock (Überschriften, Kontakt). Die Carousels liegen
   bewusst außerhalb und nutzen die volle Sektionsbreite (Aufgabe 60). */
.container__body {
    padding-inline: var(--container-gutter);
}

/* Die drei Sektionsfarben (Vorlage: nth-child 1–3) */
.container--music    { background-color: var(--color-music); }
.container--concerts { background-color: var(--color-concerts); }
.container--contact  { background-color: var(--color-contact); }

/* Sektionsüberschriften leicht gekippt (Vorlage 1:1) */
.container__heading {
    width: 90%;
    transform: rotate(-3deg);
    transform-origin: 0 0;
    margin-top: 0.5em;
    margin-bottom: 0;
}

/* ============================ Alben =================================== */

/* Kartenlook 1:1: 270×270 px, das Cover füllt die Karte (max-width
   aus base.css), hinter ihr die Vinylscheibe (z −1). Die Scheibe saß
   im Ruhezustand komplett hinter dem Cover; bei Hover schiebt sie sich
   rechts darunter heraus. Beim Abspielen blendet sie nur noch aus
   (Aufgabe 94).
   Die Vorlage fuhr die Scheibe über `left` – identische Bewegung
   hier über transform, damit nur transform animiert wird.
   (Klick verhält sich wie die Vorlage: Album ab der ersten Titeln
   spielen – JS in Aufgabe 13.) */
.album {
    /* Größe und alle davon abhängigen Maße (Vinylscheibe, Hover-Weg)
       laufen über eine Variable. So kann responsive.css auf Smartphones
       die ganze Karte verkleinern, ohne die Einzelwerte zu duplizieren.
       Basis bleibt die Vorlagenbreite 270 px. */
    --album-size: 270px;
    --album-disc-inset: calc(var(--album-size) * 10 / 270);
    --album-disc-size: calc(var(--album-size) * 243 / 270);
    --album-hover-shift: calc(var(--album-size) * 50 / 270);
    margin: 18px 9px;
    width: var(--album-size);
    height: var(--album-size);
    position: relative;
    box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
    cursor: pointer;
    transition: transform 0.25s ease; /* Vorlage: all 0.25s ease */
}

/* Das Cover füllt die 270er-Karte, ohne verzerrt zu werden: object-fit
   „contain“ hält das Seitenverhältnis und schneidet nichts ab. Ohne die
   explizite Höhe würden die width/height-Attribute der Bilder (700/715 px)
   als CSS-Höhe stehen bleiben und das Cover auf 270×700 px stauchen. */
.album__background {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Die Titel sind reine Daten (display: none wie in der Vorlage):
   das Abspielen steuert der Klick auf die Karte, die Spur-Wechsel
   laufen über die Player-Leiste. */
.album__track {
    display: none;
}

/* Mehr-Song-Cover bekommen per js/main.js einen dezenten Zähler. Die
   dunkle, leicht transparente Plakette bleibt lesbar, ohne das Cover
   wesentlich zu verdecken; Singles behalten die unveränderte Optik. */
.album__track-count {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 1;
    padding: 4px 7px;
    border: 1px solid rgba(247, 245, 234, 0.38);
    border-radius: 3px;
    background: rgba(28, 29, 27, 0.78);
    color: #f7f5ea;
    font-family: var(--font-mono);
    font-size: 12px;
    line-height: 1.2;
    letter-spacing: 0.02em;
    pointer-events: none;
}

/* Die Vinylscheibe: 243 px bei 140 px Radius – die Karte hat 90 °
   Ecken, die Scheibe wird an den Ecken daraus freigelegt.
   Ebenen wie in der Vorlage: schwarzer Schimmer von links,
   orange Label in der Mitte, bläuliche Reflexion von unten. */
.album::after {
    content: "";
    position: absolute;
    top: var(--album-disc-inset);
    left: var(--album-disc-inset);
    z-index: -1;
    display: block;
    width: var(--album-disc-size);
    height: var(--album-disc-size);
    border-radius: 50%;
    background: #222444;
    background-image:
        linear-gradient(90deg, black, transparent 80%),
        radial-gradient(darkorange 30%, transparent 30%),
        linear-gradient(0deg, transparent 30%, rgba(216, 220, 255, 0.2) 50%, transparent 70%);
    transition: transform 0.25s ease; /* Vorlage: all 0.25s ease */
}

/* Vorlage: Hover kippt die Karte −1°, die Scheibe rückt von
   left 10 px auf 60 px → 50 px nach rechts. */
.album:hover {
    transform: rotate(-1deg);
}

.album:hover::after {
    transform: translateX(var(--album-hover-shift));
}

/* Abspielend: −3° statt −1°; die Karte liegt dabei über den Nachbarn.
   (is-playing steht hinter hover, damit es den Hover übertrumpft.) */
.album.is-playing {
    position: relative;
    z-index: 3;
    transform: rotate(-3deg);
}

/* Beim Start bleibt die Scheibe an ihrer Position und blendet nur aus
   (Aufgabe 94). Kein Wegfliegen, keine Drehung – der Player oben ist
   danach die sichtbare „Platte“. */
.album.is-playing::after {
    animation: album-fade 0.9s ease forwards;
}

@keyframes album-fade {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Horizontale Cover-Reihe: natives Touch-Scrolling mit Snapping; wenn
   nicht alle Karten in den Viewport passen, bleibt die Reihe wischbar.
   Der Abstand ist doppelt so groß wie früher, damit die Schallplatte
   beim Hover zwischen zwei Covern sichtbar wird (Aufgabe 38). */
.albums {
    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
    gap: 32px;
    overflow-x: auto;
    overflow-y: hidden;
    padding-block: 8px 18px;
    /* Volle Sektionsbreite: nur ein kleiner Rand, damit die Karten nicht
       am Bildschirmrand kleben (Aufgabe 60). */
    padding-inline: clamp(16px, 4vw, 30px);
    scroll-snap-type: x mandatory;
    scroll-padding-inline: clamp(16px, 4vw, 30px);
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x pan-y;
}

.albums .album {
    flex: 0 0 var(--album-size);
    margin: 0;
    scroll-snap-align: start;
}

/* Passen alle Cover hinein, teilen die Auto-Ränder den Rest gleichmäßig
   auf und die Reihe bleibt mittig. Bei Überlauf werden sie zu 0, damit
   das erste Cover vollständig erreichbar bleibt. */
.albums > .album:first-child { margin-inline-start: auto; }
.albums > .album:last-child  { margin-inline-end: auto; }

.albums--mouse-drag {
    cursor: grab;
    user-select: none;
}

.albums--mouse-drag.albums--is-dragging {
    cursor: grabbing;
    scroll-snap-type: none;
}

/* ============================ Tickets ================================= */

/* Konzertkarten, Look 1:1 aus der Vorlage: 200 px hoch, Mono-Schrift
   (Cutive Mono, fett), papierfarben mit radialer Schattierung in der
   Ecke und Welle-Logo mittig (dritte Schicht des Hintergrund-
   Kurzschreibweises; `assets/logo_live.webp`). Die Vorlage animierte
   alle Eigenschaften – hier nur
   transform, damit der Hover (Aufgabe 12) GPU-freundlich bleibt. */
.ticket {
    /* Breite als Variable, damit responsive.css die Karte auf dem
       Smartphone verkleinern kann, ohne das Innenlayout zu duplizieren. */
    --ticket-width: 360px;
    margin: 18px;
    height: 200px;
    position: relative;
    overflow: hidden; /* schneidet den geneigten Stempel am Rand ab */
    display: block;
    font-family: var(--font-mono);
    font-weight: bold;
    background:
        radial-gradient(ellipse farthest-corner at 45px 45px, rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.2)),
        url(../assets/logo_live.webp) center / 150px no-repeat,
        var(--color-ticket);
    color: var(--color-ticket-text);
    padding: 9px;
    box-shadow: 0 0 30px rgba(0, 0, 0, 0.3);
    transition: transform 0.25s ease;
}

/* Textblock: Datum unten links und Adresse unten rechts hängen
   absolut an den Ecken, der Name steht oben in der Display-Schrift. */
.ticket__content {
    font-weight: normal;
    height: 100%;
    padding: 9px;
    position: relative;
}

.ticket__location {
    font-family: var(--font-display);
    font-size: 25px;
    text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);
}

.ticket__date,
.ticket__address {
    font-size: 20px;
    line-height: 20px;
    position: absolute;
    bottom: 9px;
}

.ticket__date    { left: 9px;  text-align: left; }
.ticket__address { right: 9px; text-align: right; }

/* „SOLD OUT“ für abgelaufene Konzerte (Vorlagen-Klasse:
   ticket--validated). Maße 1:1: 280×110 px, 9 px-Rahmen, 60 px
   Schrift, mix-blend-mode multiply „drückt“ den Stempel ins Papier.
   Zentrierung läuft über transform statt negativer Margen –
   identischer Look, nur transform animierbar. */
.ticket--soldout::after {
    content: "SOLD OUT";
    position: absolute;
    display: block;
    left: 50%;
    top: 50%;
    width: 280px;
    height: 110px;
    overflow: hidden;
    color: #900;
    border: solid 9px #900;
    padding: 9px;
    text-align: center;
    font-family: var(--font-mono);
    font-size: 60px;
    transform: translate(-50%, -50%) rotate(-40deg);
    mix-blend-mode: multiply;
}

/* Hover: −2° wie in der Vorlage (reines transform). */
.ticket:hover {
    transform: rotate(-2deg);
}

/* Horizontale Ticket-Reihe: natives Touch-Scrolling mit Snapping.
   Die Vorlagen-Tickets hatten keine eigene Breite – die gab der
   Slider-Slide vor. Hier: 360 px, weil unten links das
   Datum und unten rechts die Adresse in denselben Zeilen stehen –
   zusammen mit den längsten Dummy-Daten („Lennepromenade 7“ +
   Datum) brauchen sie ~315 px plus Padding, gemessen mit der
   echten Schrift 316 px. */
.tickets {
    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
    gap: 16px;
    overflow-x: auto;
    overflow-y: hidden;
    padding-block: 8px 18px;
    /* Wie die Alben: volle Sektionsbreite mit kleinem Rand (Aufgabe 60). */
    padding-inline: clamp(16px, 4vw, 30px);
    scroll-snap-type: x mandatory;
    scroll-padding-inline: clamp(16px, 4vw, 30px);
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x pan-y;
}

.tickets .ticket {
    flex: 0 0 var(--ticket-width);
    width: var(--ticket-width);
    margin: 0; /* der alte 18 px-Rand macht das Gap überfällig */
    scroll-snap-align: start;
}

/* Zentrierung wie bei den Alben, solange alle Tickets hineinpassen.
   :first-of-type/:last-of-type statt :first-child/:last-child: Der
   Leerzustand-Stempel bleibt als letztes Element im DOM (nur display:none).
   Mit :last-child bekäme das letzte Ticket keinen Auto-Rand und die Reihe
   würde nach rechts rutschen. */
.tickets > .ticket:first-of-type { margin-inline-start: auto; }
.tickets > .ticket:last-of-type  { margin-inline-end: auto; }

/* Leerzustand: Solange kein echtes .ticket im HTML steht, zeigt die
   Reihe einen Stempel direkt auf dem Sektionshintergrund. :has(.ticket)
   prüft den tatsächlichen Inhalt – auskommentierte Tickets zählen nicht.
   Sobald ein Ticket eingefügt wird, verschwindet der Stempel ohne JS. */
.tickets__empty {
    flex: 1;
    display: grid;
    place-items: center;
    min-height: clamp(200px, 22vw, 260px);
    margin: 0;
}

.tickets__stamp {
    display: inline-block;
    padding: clamp(12px, 2.4vw, 18px) clamp(18px, 4vw, 36px);
    border: clamp(4px, 0.7vw, 7px) solid currentColor;
    outline: 2px solid currentColor;
    outline-offset: 5px;
    color: #f7f5ea;
    font-family: var(--font-mono);
    font-size: clamp(18px, 3.4vw, 42px);
    font-weight: bold;
    line-height: 1;
    letter-spacing: 0.06em;
    white-space: nowrap;
    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.18);
    transform: rotate(-7deg);
    opacity: 0.86;
}

.tickets:has(.ticket) .tickets__empty {
    display: none;
}

.tickets--mouse-drag {
    cursor: grab;
    user-select: none;
}

.tickets--mouse-drag.tickets--is-dragging {
    cursor: grabbing;
    scroll-snap-type: none;
}

/* Scrollbalken der beiden Kartenreihen (Aufgabe 92): Der native Balken
   wirkte wie ein Fremdkörper. Stattdessen ein schlanker, abgerundeter
   Daumen in Papierfarbe auf einem dunklen, leicht durchscheinenden
   Track – passend zu den dunklen Sektionen. Firefox nutzt die
   Standard-Eigenschaften, WebKit/Blink die Pseudo-Elemente.
   Auf Touch-Geräten bleibt der Overlay-Balken des Systems erhalten. */
.albums,
.tickets {
    scrollbar-width: thin;
    scrollbar-color: rgba(247, 245, 234, 0.45) rgba(0, 0, 0, 0.18);
}

.albums::-webkit-scrollbar,
.tickets::-webkit-scrollbar {
    height: 8px;
}

.albums::-webkit-scrollbar-track,
.tickets::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0.18);
    border-radius: 999px;
}

.albums::-webkit-scrollbar-thumb,
.tickets::-webkit-scrollbar-thumb {
    border: 2px solid transparent;
    border-radius: 999px;
    background: rgba(247, 245, 234, 0.45);
    background-clip: padding-box;
}

.albums::-webkit-scrollbar-thumb:hover,
.tickets::-webkit-scrollbar-thumb:hover,
.albums--is-dragging::-webkit-scrollbar-thumb,
.tickets--is-dragging::-webkit-scrollbar-thumb {
    background: rgba(247, 245, 234, 0.78);
    background-clip: padding-box;
}

/* ======================= Karussell-Scrollhinweis ====================== */

/* Auf Touch-Geräten zeigt der Browser für die horizontalen Reihen keinen
   dauerhaften Scrollbalken. Der Pfeil sitzt am rechten Rand der jeweiligen
   Reihe und bleibt stehen, während die Karten darunter wegscrollen.
   js/carousel-hints.js blendet ihn aus, sobald gescrollt wurde. */
.carousel {
    position: relative;
}

.carousel__hint {
    position: absolute;
    top: 50%;
    right: clamp(4px, 2vw, 10px);
    z-index: 2;
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    background: rgba(28, 29, 27, 0.76);
    color: #ffffff;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.34);
    cursor: pointer;
    transform: translateY(-50%);
    animation: carousel-hint-bounce 1.6s ease-in-out infinite;
}

.carousel__hint[hidden] {
    display: none;
}

.carousel__hint-icon {
    width: 18px;
    height: 18px;
    /* Der Pfeil der Startseite zeigt nach unten; −90° macht daraus den
       Hinweis „weiter nach rechts“. */
    transform: rotate(-90deg);
}

@keyframes carousel-hint-bounce {
    0%,
    100% { transform: translateY(-50%) translateX(0); }
    50%  { transform: translateY(-50%) translateX(6px); }
}

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

/* ============================ Kontakt ================================= */

/* Zwei Spalten wie in der Vorlage (Flex, space-between); das alte
   margin-left wird zu gap. Basis + Wrap statt 768px-Media-Query:
   die Spalten stehen breit nebeneinander und stapeln sich schmal
   automatisch – mobile-first. */
.grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: clamp(18px, 4vw, 36px);
}

.grid__item {
    flex: 1 1 280px;
}

/* Kontakt-Zeilen im Rhythmus der Vorlagen-lead (20 px / 45 px). */
.lead {
    font-size: 20px;
    line-height: 45px;
    margin: 0;
}

.lead a,
.streaming a {
    display: inline-flex;
    align-items: center;
    gap: 0.45em;
}

.contact__icon {
    display: block;
    width: 1.15em;
    height: 1.15em;
    flex: none;
}

/* Streaming-Links ersetzen das alte Formular (Entscheidung Q4):
   schlichte Liste im gleichen Zeilenrhythmus wie die lead daneben. */
.streaming {
    list-style: none;
    margin: 0;
    padding: 0;
}

.streaming li {
    line-height: 45px;
}

/* ============================ Player ================================== */

/* Kompakter, oben links fixierter Player: Der dunkle Hintergrund ersetzt
   die frühere gelbe Vollbreitenleiste. Sichtbar erst bei laufender Auswahl. */
.player {
    display: none;
    position: fixed;
    top: 12px;
    left: 12px;
    z-index: 30;
    width: clamp(180px, 18vw, 230px);
    padding: 12px;
    gap: 8px;
    color: #ffffff;
    text-align: center;
    background: rgba(28, 29, 27, 0.9);
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: 6px;
    box-shadow: 0 5px 20px rgba(0, 0, 0, 0.32);
    backdrop-filter: blur(6px);
}

.player.is-visible {
    display: grid;
}

.player__artwork {
    position: relative;
    width: 86px;
    height: 72px;
    margin: 0 auto;
}

.player__cover {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    width: 64px;
    height: 64px;
    object-fit: cover;
    box-shadow: 0 2px 7px rgba(0, 0, 0, 0.42);
}

.player__record {
    position: absolute;
    top: 4px;
    left: 30px;
    width: 64px;
    height: 64px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 50%;
    background:
        radial-gradient(circle, #c96c16 0 4px, #161616 4.5px 8px, transparent 8.5px),
        repeating-radial-gradient(circle, #1a1a1a 0 2px, #303030 2.5px 3px);
    animation: player-record-spin 5s linear infinite;
}

/* Kratzer machen die Drehung sichtbar: radiale Linien, die sich mit
   der Platte drehen (Aufgabe 52). */
.player__record::before {
    content: "";
    position: absolute;
    inset: 6px;
    border-radius: 50%;
    background: repeating-conic-gradient(
        from 0deg,
        rgba(255, 255, 255, 0.16) 0deg 1.2deg,
        transparent 1.2deg 14deg
    );
    -webkit-mask: radial-gradient(circle, transparent 0 8px, #000 9px 30px, transparent 31px);
    mask: radial-gradient(circle, transparent 0 8px, #000 9px 30px, transparent 31px);
}

/* Noten hüpfen von der Platte nach rechts und verblassen. Sie laufen,
   solange der Player sichtbar und nicht pausiert ist. */
.player__note {
    position: absolute;
    top: 16px;
    left: 56px;
    font-size: 15px;
    line-height: 1;
    color: #ffffff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
    opacity: 0;
    animation: player-note 3.2s ease-out infinite;
    animation-delay: var(--note-delay, 0s);
}

.player.is-paused .player__note {
    animation-play-state: paused;
}

@keyframes player-note {
    0% { opacity: 0; transform: translate(0, 0) scale(0.6) rotate(0deg); }
    12% { opacity: 0.9; }
    28% { opacity: 0.9; transform: translate(16px, -14px) scale(1) rotate(-6deg); }
    46% { transform: translate(32px, -4px) rotate(4deg); }
    64% { transform: translate(48px, -18px) rotate(-3deg); }
    82% { opacity: 0.5; transform: translate(62px, -8px) rotate(5deg); }
    100% { opacity: 0; transform: translate(76px, -16px) scale(1.1) rotate(10deg); }
}

.player__record::after {
    content: "";
    position: absolute;
    inset: 50%;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #f6e9d3;
    transform: translate(-50%, -50%);
}

@keyframes player-record-spin {
    to { transform: rotate(360deg); }
}

.player__track {
    display: block;
    min-width: 0;
    margin: 0;
    font-size: clamp(12px, 1.05vw, 15px);
    line-height: 1.3;
    overflow-wrap: anywhere;
}

/* Position in der Trackliste, passend zum Mono-Schriftzug der Cover-Badges.
   Bei Singles bleibt das Element per hidden ganz aus dem Player. */
.player__position {
    justify-self: center;
    margin: -2px 0 0;
    padding: 0;
    color: rgba(255, 255, 255, 0.82);
    font-family: var(--font-mono);
    font-size: 11px;
    line-height: 1.2;
    letter-spacing: 0.03em;
}

.player__controls {
    display: flex;
    justify-content: center;
    gap: 8px;
}

.player__button {
    position: relative;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: #ffffff;
    color: #27251f;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.28);
    cursor: pointer;
    transition: transform 0.2s ease;
}

.player__button:hover {
    transform: translateY(-2px);
}

.player__button:focus-visible {
    outline: 2px solid #ffffff;
    outline-offset: 3px;
}

.player__button--prev::before,
.player__button--prev::after,
.player__button--next::before,
.player__button--next::after,
.player__button--play::after,
.player__button--pause::before,
.player__button--pause::after {
    content: "";
    position: absolute;
}

.player__button--prev::before,
.player__button--prev::after {
    top: 10px;
    border-top: 7px solid transparent;
    border-bottom: 7px solid transparent;
    border-left: 0;
    border-right: 11px solid currentColor;
}

.player__button--prev::before { right: 18px; }
.player__button--prev::after  { right: 9px; }

.player__button--next::before,
.player__button--next::after {
    top: 10px;
    border-top: 7px solid transparent;
    border-bottom: 7px solid transparent;
    border-right: 0;
    border-left: 11px solid currentColor;
}

.player__button--next::before { left: 18px; }
.player__button--next::after  { left: 9px; }

.player__button--play::after {
    top: 10px;
    left: 13px;
    border-top: 8px solid transparent;
    border-bottom: 8px solid transparent;
    border-left: 13px solid currentColor;
}

.player__button--pause::before,
.player__button--pause::after {
    top: 10px;
    width: 4px;
    height: 16px;
    background: currentColor;
}

.player__button--pause::before { left: 12px; }
.player__button--pause::after  { right: 12px; }

@media (prefers-reduced-motion: reduce) {
    .player__record { animation: none; }
    .album.is-playing::after { animation: none; }
}

/* ============================= Footer ================================== */

/* Dunkle Leiste wie in der Vorlage (16 px, rechtsbündig),
   Barhöhe fluid in dvh statt fix 10 px (Fallszeile zuerst). */
.footer {
    position: relative;
    z-index: 10;
    font-size: 16px;
    padding: 10px;
    padding: clamp(10px, 2.5dvh, 24px) 12px;
    text-align: right;
    background: var(--color-footer);
    color: var(--color-text);
}

/* „Impressum“-Schalter: Button statt span+jQuery wie in der Vorlage,
   Farbe und Schrift erbt aus der Leiste. */
.footer__toggle {
    background: none;
    border: none;
    padding: 0;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

/* Impressum-Block: wie die Vorlage linksbündig in 600 px Breite.
   [hidden] wird vom JS gesetzt; die Regel doppelt, damit kein
   Reset sie aufheben kann. */
.footer__content {
    text-align: left;
    margin: 0 auto;
    max-width: 600px;
    padding: 10px;
}

.footer__content[hidden] {
    display: none;
}
