/* =====================================================================
 * HOERPROBEN-RASTER: PLAYLIST-KARTEN, KARUSSELL UND REITER
 *
 * Optik des Rasters aus includes/hoerproben-raster.php, bedient von
 * assets/js/raster.js. Gebraucht auf jeder Seite, die Hoerproben zeigt:
 * Paketshop, Startseite, saunamusik.php.
 *
 * Wird NACH carousel.css geladen ($pageStyleDeps = ['carousel', 'raster']),
 * denn die Regeln hier sind die engeren: Sie ueberschreiben die Mechanik
 * des Karussells bei gleicher Spezifitaet.
 *
 * Was nur der Paketshop hat (Referenzen, Individualauftrag, Formular,
 * Kopfbereich), steht in pages/pakete.css.
 * ===================================================================== */

/*
 * pakete.css · v3.2.1 · 30.08.2026
 * Änderung: Rabattzeile im Dialog, Anfragekorb über die Navigation gehoben
 * (z-index), Drawer auf dem Smartphone mit Backdrop-Streifen zum Schließen.
 */

/* Pakete & Preise */

/*
 * WICHTIG: Diese Seite nutzt bewusst dieselben Karussell-Klassen wie
 * Lets_DJ (.dj-tile, .dj-track, .dj-stage, .dj-peek, .dj-dot) - eine
 * Zuständigkeit, eine Quelle, statt einer zweiten Karussell-Implementierung
 * mit anderem Namen.
 *
 * Seit 3.2.5-p21 kommt davon nur noch die MECHANIK aus einer gemeinsamen
 * Datei: assets/css/pages/carousel.css, eingebunden über
 * $pageStyleDeps = ['carousel'] in pakete.php. lets-dj.css wird hier NICHT
 * mehr geladen.
 *
 * Daraus folgt die Regel für diese Datei: Alles, was die Kacheln GRÖSSE,
 * FORM oder BILDAUSSCHNITT gibt, steht hier - nie in carousel.css.
 */

/*
 * "Vor dem Kauf" nutzt jetzt .keyword-grid/.keyword-card aus components.css
 * (dasselbe Schlagwort-Kacheln-Muster wie Lets_DJ "Entstehung unserer
 * Musik") statt einer eigenen, seitenspezifischen Trust-Box - eine
 * Zuständigkeit, eine Quelle.
 */

.pakete-tabs {
    display: flex;
    justify-content: center;
    gap: 10px;
    flex-wrap: wrap;
    /* Abstaende wachsen mit der Fensterbreite (siehe #produkte weiter unten). */
    margin-top: clamp(8px, 2vw, 24px);
    margin-bottom: clamp(26px, 4vw, 44px);
}

/*
 * B2 (30.08.2026) - Bühne in drei Betriebsmodi:
 * Desktop bricht aus dem zentralen Wrapper aus (width:100vw-Breakout) und
 * zentriert sich in einem eigenen Maximalrahmen - die Spaltenzahl rechnet
 * pakete.js aus der echten Fensterbreite (productItemsPerView). Tablet
 * behält die bisherige Bühne, Smartphone zeigt statt des Karussells die
 * flache Liste (kein Über-den-Rand-Wischen mehr möglich).
 */

/*
 * HISTORISCHER HINWEIS (p12, ueberholt seit 3.2.5-p21):
 *
 * Diese Breitenangaben entstanden als Gegenwehr gegen eine geerbte Regel.
 * Der Paketshop lud damals lets-dj.css mit, und deren
 * .dj-stage { width: min(36%, 380px) } sperrte die Buehne in eine
 * sichtbare 380px-Kachel (Beobachtung Lars, Dunkelmodus) - die
 * Spaltenformel konnte nie greifen.
 *
 * Seit p21 laedt der Paketshop nur noch carousel.css, und die regelt
 * ausdruecklich keine Form. Die Erbschaft gibt es nicht mehr. Die Angaben
 * hier stehen aus eigenem Recht und beschreiben, wie breit die Buehne sein
 * SOLL - nicht mehr, wogegen sie sich wehrt.
 */

/*
 * TABLET UND DESKTOP: Kacheln bis zum Fensterrand (Wunsch Lars, 02.09.2026).
 * Der Textkopf und die Kategorie-Knoepfe bleiben im zentrierten Bereich -
 * nur die Buehne laeuft breiter, damit rechts eine angeschnittene Kachel
 * sichtbar bleibt und klar ist, dass es dort weitergeht.
 */

@media (min-width: 651px) and (max-width: 1000px) {
#paketeProductArea > .dj-stage {
        width: 96vw;
        max-width: 96vw;
        margin-left: 50%;
        transform: translateX(-50%);
    }
}

@media (min-width: 651px) {
.pakete-product-stage {
        width: 100%;
    }
}

@media (min-width: 1001px) {
/*
     * p19: ID-Spezifität! Der bisherige Klassen-Override stand am
     * Dateianfang und verlor bei gleicher Spezifität gegen die spätere
     * Basis-Regel .pakete-product-carousel{max-width:1100px} (Zeile ~225)
     * - die Bühne klebte deshalb weiter bei 1100px ("die Kachel" auf
     * 21:9). Dritter Fall dieser Fallenart (Geister-Pfeile p16, width-
     * Falle p17) -> neue Hausregel im BACKLOG: Overrides gegen spätere
     * Regeln IMMER mit ID-Spezifität ankern.
     */
#paketeProductArea {
        max-width: none;
    }
/*
     * Korrektur 31.08.2026 (Wunsch Lars, Bugfix): max-width: 2200px hier
     * entfernt - lief unabhaengig vom Wrapper-Deckel oben (96vw) und
     * driftete davon ab, sobald der Wrapper-Deckel geaendert wurde (siehe
     * Kommentar bei #produkte > .wrapper). Jetzt width:100%, keine eigene
     * Obergrenze mehr - der Wrapper (96vw) ist die EINZIGE Quelle fuer die
     * maximale Buehnenbreite, die JS-Formel in pakete.js rechnet mit
     * demselben Faktor.
     */
#paketeProductArea > .dj-stage {
        width: 100%;
        max-width: none;
        margin-inline: auto;
    }
}

@media (max-width: 650px) {
/*
     * p16: #paketeProductArea-Präfix vor den Pfeilen - die Basis-Regel
     * .pakete-product-arrow (display:grid) steht SPÄTER in dieser Datei
     * und gewann bei gleicher Spezifität durch die Reihenfolge. Deshalb
     * blieben die alten Wisch-Pfeile auf dem iPhone sichtbar (auf Höhe
     * des Modus-Schalters). ID schlägt Klasse, Reihenfolge egal.
     */
/* Buehne nutzt die volle Fensterbreite - die Kacheln sollen bis zum Rand
       laufen, nicht im zentrierten Textbereich stecken. */
#paketeProductArea > .dj-stage {
        width: 100vw;
        max-width: 100vw;
        margin-left: 50%;
        transform: translateX(-50%);
    }
}

/* Auf-/Zuklappen wie beim index-Hörproben-Player */

/*
 * Gestapelte Karten einzeln bedienbar (B2): der zentrale .dj-tile:hover-
 * Scale (lets-dj.css) hob den PAAR-Wrapper an - beide Karten wackelten
 * gemeinsam. Auf dem Produktraster deshalb neutralisiert; die einzelne
 * Karte reagiert stattdessen selbst, nur mit Randfarbe (Designformel:
 * Farbe statt Bewegung auf Glas).
 */

@media (hover: hover) and (pointer: fine) {
#productGrid .dj-tile:hover {
        transform: none;
    }
/* p13: Hover deutlich spürbarer - Rand + weicher Glow, weiterhin ohne
       Bewegung (Designformel). */
#productGrid .product-card:hover {
        outline: 2px solid var(--orange);
        outline-offset: -2px;
        box-shadow: 0 0 22px color-mix(in srgb, var(--orange) 35%, transparent);
    }
}

/* Spielende Karte: Umrandung in der Hauptfarbe ihres Covers (JS ermittelt
   sie per Canvas, Fallback Orange) mit pulsierendem Glow - Farbe animiert,
   nichts bewegt sich (Designformel).

   DIE FARBE WIRD ZU 50 % MIT WEISS GEMISCHT. Der Durchschnitt eines dunklen
   Covers ist fast schwarz (z. B. rgb(35 1 0) bei Tango Nights): Der Rahmen
   verschwand dann auf der Karte, und man sah nicht, was gerade laeuft. Mit
   dem Weiss bleibt der Ton des Covers erkennbar und der Rahmen sichtbar. */

#productGrid .product-card.is-playing {
    outline: 3px solid color-mix(in srgb, var(--cover-accent, var(--orange)) 50%, #fff);
    outline-offset: -3px;
    animation: pakete-cover-pulse 2.2s ease-in-out infinite;
}

@keyframes pakete-cover-pulse {
    0%, 100% { box-shadow: 0 0 0 0 transparent; }
    50% { box-shadow: 0 0 26px 4px color-mix(in srgb, color-mix(in srgb, var(--cover-accent, var(--orange)) 50%, #fff) 70%, transparent); }
}

/* Dazu dieselben Tonbalken wie in der Playlist-Liste des Popups (Keyframes
   in shop.css): vor dem Titel der spielenden Karte. */

#productGrid .product-card.is-playing .product-card-title::before {
    content: "";
    display: inline-block;
    width: 16px;
    height: 14px;
    margin-right: 8px;
    vertical-align: -1px;
    color: #fff;
    background:
        linear-gradient(currentColor, currentColor) 0 100% / 4px 60% no-repeat,
        linear-gradient(currentColor, currentColor) 6px 100% / 4px 100% no-repeat,
        linear-gradient(currentColor, currentColor) 12px 100% / 4px 40% no-repeat;
    animation: playlist-ton 1s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
#productGrid .product-card.is-playing {
        animation: none;
        box-shadow: 0 0 18px 2px color-mix(in srgb, color-mix(in srgb, var(--cover-accent, var(--orange)) 50%, #fff) 60%, transparent);
    }
#productGrid .product-card.is-playing .product-card-title::before {
        animation: none;
    }
}

.pakete-tab {
    /*
     * Kategorie-Schaltflächen als Glaskachel (Lars, 31.08.2026): heller
     * Lichtsaum an der Oberkante, dunklere Unterkante und ein weicher
     * Schlagschatten simulieren Materialstärke - dadurch kommt die Farbe des
     * aktiven Knopfes (Wellness Blau / Event Orange) plastisch zur Geltung
     * statt flach aufzuliegen. Kein transform beim Hover (Designformel:
     * Bewegung auf Glas nur über Farbe).
     */
    position: relative;
    backdrop-filter: blur(16px) saturate(165%);
    -webkit-backdrop-filter: blur(16px) saturate(165%);
    box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 85%, transparent),
        inset 0 -2px 4px rgba(16, 20, 25, .10),
        0 8px 20px rgba(16, 20, 25, .12);
    padding: 11px 20px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink);
    font-weight: 800;
    cursor: pointer;
    transition: box-shadow .3s ease, border-color .3s ease;
}

/* Dunkelmodus: dunklerer Schatten statt des hellen Lichtsaums. Steht seit
   3.5.1-p15 hier bei den uebrigen Reiter-Regeln statt am Dateianfang. */

html[data-theme=dark] .pakete-tab {
    box-shadow:
        inset 0 1px 0 color-mix(in srgb, #fff 16%, transparent),
        inset 0 -2px 4px rgba(0, 0, 0, .35),
        0 8px 20px rgba(0, 5, 12, .3);
}

.pakete-tab.active {
    box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent),
        inset 0 -3px 6px rgba(0, 0, 0, .18),
        0 12px 26px color-mix(in srgb, var(--orange) 32%, transparent);
    background: var(--ink);
    border-color: var(--ink);
    color: var(--page);
}

/*
 * Absprache 31.08.2026 (ersetzt die vom 30.08.): Kategoriefarben sind
 * jetzt durchgängig - Wellness Musik = Blau, Event Musik = Orange, an
 * jeder Stelle, die eine Kategorie anzeigt (Haupt-Tabs hier, Umschalter
 * und Kicker im Produktdialog, mobile Kategorie-Tabs). Individualauftrag
 * bleibt beim neutralen .pakete-tab.active-Look. Das --gold-Token bleibt
 * weiterhin ausschließlich "Audio spielt gerade" (lets-dj.css).
 */

.pakete-tab[data-category="wellness"].active {
    box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent),
        inset 0 -3px 6px rgba(0, 0, 0, .18),
        0 12px 26px color-mix(in srgb, var(--blue) 32%, transparent);
    background: var(--blue);
    border-color: var(--blue);
    color: #fff;
}

.pakete-tab[data-category="event"].active {
    background: var(--orange);
    border-color: var(--orange);
    color: #fff;
}

/*
 * Verspieltes Antipp-Feedback: kurzes Aufleuchten für 2 Sekunden, unabhängig
 * vom eigentlichen aktiven Zustand (.active) - reine Spielerei, siehe
 * pakete.js (Klasse wird per JS gesetzt und nach 2s wieder entfernt).
 */

.pakete-tab.is-tapped {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--orange) 55%, transparent), 0 0 24px color-mix(in srgb, var(--orange) 45%, transparent);
    border-color: var(--orange);
}

/* Auf dem Handy: 2 Tabs nebeneinander, ein dritter (Individualauftrag) zentriert darunter statt gequetscht in einer Reihe oder einzeln gestapelt. */

@media (max-width: 650px) {
.pakete-tabs {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        justify-items: stretch;
    }
.pakete-tab {
        text-align: center;
    }
.pakete-tab:nth-child(3):last-child {
        grid-column: 1 / -1;
        justify-self: center;
        min-width: 55%;
    }
}

/*
 * Produkt-Karussell: nutzt dieselbe zentrale Karussell-Engine wie Lets_DJ/
 * Playlist-Auswahl (createTileCarousel), nur mit itemsPerView>1 auf Tablet/
 * Desktop (siehe pakete.js initProductCarousel()) - eine Implementierung
 * statt einer dritten, eigenen Karussell-Logik. .dj-stage ist für ein
 * einzelnes Cover ausgelegt (schmal); hier breiter, damit mehrere Karten
 * nebeneinander passen.
 */

/*
 * Wrapper jetzt breiter als die Bühne (980px) und mit seitlichem Freiraum
 * (padding) - die Pfeile stehen darin AUSSERHALB der Karten, statt wie
 * zuvor direkt auf deren Rand zu liegen. Auf schmalen Bildschirmen
 * (Tablet/Handy) schrumpft der Freiraum wieder, siehe Media Query weiter
 * unten - dort ist kein Platz für einen großen Gutter.
 */

/*
 * GEZIELTE ACHSENSPERRE. Die Vorschau-Kacheln (.dj-peek) sitzen
 * ausserhalb der Buehne, rechts bei calc(100% + 8px). Auf dem Handy
 * stehen sie damit ueber den Rand und die Seite liesse sich seitlich
 * schieben. "clip" statt "hidden": hidden wuerde den Abschnitt zum
 * Scroll-Container machen (klebende Elemente, Ankersprünge). Gesperrt wird
 * dort, wo der Ausbruch stattfindet: im Abschnitt, der das Raster traegt.
 * Gilt fuer Start, Saunamusik und Pakete.
 */
.section:has(.pakete-product-carousel) {
    overflow-x: clip;
}

.pakete-product-carousel {
    position: relative;
    width: 100%;
    max-width: 1100px;
    margin-inline: auto;
    margin-top: clamp(8px, 2vw, 20px);
    padding: 0 60px;
    background: transparent;
}

@media (max-width: 1100px) {
.pakete-product-carousel {
        padding: 0 6px;
    }
}

/* Bugfix: hidden-Attribut wurde ohne diese Regel vom unbedingt gesetzten display:flex überschrieben - gleiches Muster wie bei .pakete-individual, siehe dortigen Kommentar. */

.pakete-product-carousel[hidden] {
    display: none;
}

/*
 * Eigene, sichtbare Pfeil-Klasse statt .dj-carousel-arrow - die ist seitenweit
 * auf display:none gesetzt (Lets_DJ/Playlist-Dialog navigieren stattdessen
 * über Cover-Zonen bzw. Wisch-Geste). Das Produkt-Karussell hat keine
 * vergleichbare Cover-Zone für Vor/Zurück, deshalb braucht es hier
 * eigenständige, sichtbare Pfeile.
 *
 * Als Glas-Overlay DIREKT auf den Kacheln statt außen flankierend - vermeidet
 * das vorherige Überlauf-Risiko (Pfeile fielen bei bestimmten Breiten aus
 * dem sichtbaren Bereich) und liest sich wie die übrige Liquid-Glass-
 * Bedienung der Seite. Symbolfarbe Orange statt neutralem Grau/Weiß.
 */

.pakete-product-arrow {
    position: absolute;
    top: 50%;
    z-index: 6;
    transform: translateY(-50%);
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--orange) 78%, transparent);
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
    border: 1px solid #ff8666;
    box-shadow: 0 10px 24px rgba(236, 88, 48, .38), inset 0 1px 0 rgba(255, 255, 255, .3);
    color: #fff;
    font-size: 1.6rem;
    font-weight: 800;
    cursor: pointer;
    transition: background .18s ease, transform .18s ease;
}

/*
 * Pfeile nach innen gerueckt (p18, Wunsch Lars): Sie standen buendig am
 * Buehnenrand und wirkten dadurch losgeloest vom Inhalt. Der Abstand waechst
 * mit der Fensterbreite - auf dem Smartphone bleibt es knapp, damit die
 * Kachel Platz behaelt, auf grossen Bildschirmen ruecken sie deutlich ein.
 */

.pakete-product-arrow-prev {
    left: clamp(6px, 3vw, 56px);
}

.pakete-product-arrow-next {
    right: clamp(6px, 3vw, 56px);
}

.pakete-product-arrow[hidden] {
    visibility: hidden;
}

/* Kein Rundlauf mehr im Mehrfach-Modus - am jeweiligen Rand ausgegraut statt weiterhin aktiv anklickbar zu wirken. */

.pakete-product-arrow:disabled {
    opacity: .35;
    cursor: default;
    box-shadow: none;
}

@media (hover: hover) and (pointer: fine) {
.pakete-product-arrow:hover {
        background: color-mix(in srgb, var(--orange) 92%, transparent);
        transform: translateY(-50%) scale(1.06);
    }
}

.pakete-product-stage {
    width: 100%;
    max-width: 980px;
    margin-inline: auto;
    /* Bewusste Glas-Optik statt weiter gegen einen nicht auffindbaren weißen Hintergrund zu kämpfen - passt zur übrigen Liquid-Glass-Sprache der Seite. */
    padding: 20px;
    border-radius: 24px;
    background: color-mix(in srgb, #fff 12%, transparent);
    backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, .3);
}

html[data-theme=dark] .pakete-product-stage {
    background: color-mix(in srgb, #fff 6%, transparent);
    border-color: rgba(255, 255, 255, .14);
}

/*
 * Karte = .dj-tile, komplett vom Cover ausgefüllt (statt nur oberer
 * Streifen wie zuvor) - Text liegt als Liquid-Glass-Label über dem Bild.
 */

.product-card {
    overflow: hidden;
    cursor: pointer;
}

/*
 * Paar-Wrapper: übernimmt jetzt die Rolle, die vorher .dj-tile direkt für
 * eine einzelne Karte hatte (Breite/Scroll-Snap kommt weiterhin von
 * .dj-tile, siehe layoutMultiTrack() in carousel.js). Enthält 1-2 Playlist-
 * Karten übereinander gestapelt statt einer einzelnen Karte nebeneinander -
 * dadurch bleiben die Karten breit genug, auch wenn mehr Playlists
 * gleichzeitig sichtbar sind.
 */

.dj-track-multi .product-card-pair {
    display: flex;
    flex-direction: column;
    gap: 14px;
    aspect-ratio: unset;
    height: auto;}

/* Im Einzel-Modus (Handy) ist der Paar-Wrapper selbst die .dj-tile (position:absolute;inset:0 von der Basisregel) - die einzelne enthaltene Karte füllt ihn komplett aus statt sich nur an aspect-ratio zu orientieren, ohne Bezugsgröße zu haben. */

.dj-track:not(.dj-track-multi) .product-card-pair .product-card {
    width: 100%;
    height: 100%;
}

/* Referenzen ohne eigenes Cover (z. B. noch nicht hochgeladen) - Verlauf in den Website-Akzenten statt leerer, dunkler Fläche. */

/*
 * AUSLAUF NUR BIS ZUM PFEIL (3.2.5-p23, Wunsch Lars).
 *
 * "Der weisse Schleier darf nur auf einer Kachel ankommen, wenn diese
 * inaktiv ist. Sobald sie aktiv und nutzbar ist, muss sie glasklar
 * dargestellt werden - am besten immer da, wo der Pfeil ist, wird
 * Auslaufen angewendet, innerhalb der Pfeile nicht."
 *
 * Die Strecke ist deshalb an den Pfeilen ausgerichtet statt an der
 * Trackbreite: Abstand des Pfeils vom Rand plus seine eigene Breite,
 * beides aus .pakete-product-arrow / -prev / -next. Ab der Innenkante des
 * Pfeils ist die Flaeche unangetastet, bei jeder Fensterbreite.
 *
 * Wer die Pfeile verschiebt oder ihre Groesse aendert, aendert hier mit.
 *
 * Nur am Produktkarussell: Das Referenzkarussell hat keine Pfeile und
 * setzt die Klasse .dj-track-overflow bei zwei Eintraegen ohnehin nicht.
 */

#productGrid {
    --anschnitt-schleier: calc(clamp(6px, 3vw, 56px) + 52px);
}

/*
 * KACHELFORM, SEITENSPEZIFISCH (3.2.5-p21).
 *
 * Bis p20 hat der Paketshop Radius, Hintergrund und Schatten der Kachel
 * unausgesprochen aus lets-dj.css geerbt ($pageStyleDeps). Seit dem
 * Umbau laedt er nur noch carousel.css - und die regelt ausdruecklich
 * KEINE Form. Die Werte stehen deshalb hier, unveraendert uebernommen:
 * Der Umbau soll nichts am Aussehen aendern.
 */

.dj-tile {
    border-radius: 30px;
    background: #0b1622;
    box-shadow: 0 10px 26px rgba(0, 0, 0, .28);
}

@media (max-width: 1000px) {
.dj-tile {
        border-radius: 28px;
    }
}

/*
 * REFERENZKACHELN BLEIBEN QUADRATISCH.
 *
 * Sie sind selbst die .dj-tile (siehe renderReferenceCard() in pakete.js)
 * und haben - anders als die Paar-Wrapper und die inneren Playlist-Karten -
 * nie ein eigenes Seitenverhaeltnis getragen. Sie hingen an der zentralen
 * Regel .dj-track.dj-track-multi .dj-tile { aspect-ratio: 1/1 } in
 * lets-dj.css, die mit p21 ersatzlos entfaellt.
 */

.dj-tile.product-card-reference {
    aspect-ratio: 1 / 1;
}

/*
 * DIE p20-REGEL IST ENTFALLEN.
 *
 * #productGrid .dj-tile.product-card-pair { aspect-ratio: unset }
 * musste mit ID-Spezifitaet (1-2-0) gegen das zentrale Quadrat
 * (0-3-0) anschreiben. Das Quadrat gibt es nicht mehr - die Aufhebung
 * bei .dj-track-multi .product-card-pair weiter oben genuegt, und der
 * Sonderfall verschwindet mitsamt seiner Ursache.
 */

.product-card-placeholder {
    background: linear-gradient(155deg, color-mix(in srgb, var(--blue) 55%, #0b1622), color-mix(in srgb, var(--orange) 45%, #0b1622));
}

/*
 * BUGFIX: position:relative war hier UNBEDINGT gesetzt und hat damit
 * position:absolute von .dj-tile überschrieben (gleiche Spezifität,
 * pakete.css lädt nach lets-dj.css) - im Einzel-Modus (Smartphone) braucht
 * .dj-tile aber zwingend position:absolute, um die Kacheln übereinander zu
 * stapeln. Ohne das fielen die Karten aus ihrem quadratischen Rahmen -
 * sichtbar als leere Fläche. Jetzt nur noch im Mehrfach-Modus gesetzt, wo
 * es tatsächlich gebraucht wird (siehe .dj-track-multi .dj-tile in
 * lets-dj.css, das setzt es dort bereits selbst - diese Regel doppelt es
 * nur für den spezielleren .product-card-Selektor ab, falls CSS-
 * Reihenfolge sich mal ändert).
 */

.dj-track-multi .product-card {
    position: relative;
}

/*
 * COVER FUELLT DIE KARTE (3.2.5-p37, Befund Lars).
 *
 * Vorher stand das Bild als einziges Kind IM FLUSS und trug
 * height: 100%. Eine Prozenthoehe braucht eine aufloesbare Bezugshoehe -
 * die Karte hat aber height: auto (ihre Hoehe kommt aus aspect-ratio bzw.
 * dem Inhalt). Die Angabe lief damit ins Leere, das Bild fiel auf seine
 * Eigenhoehe zurueck: bei 270px Breite genau 270px hoch. Ist die Karte
 * hoeher, blieb unten ein Streifen, in dem der dunkle Kachelhintergrund
 * (#0b1622) durchschien - sichtbar als dunkles Band unter den Chips.
 *
 * Absolut positioniert braucht das Bild keine Bezugshoehe mehr: inset: 0
 * spannt es ueber die gesamte Karte, gleich wie hoch sie ausfaellt.
 * object-fit: cover haelt das Seitenverhaeltnis; da die Cover quadratisch
 * sind (4:4) und die Karte es ebenfalls anstrebt, wird praktisch nichts
 * beschnitten.
 *
 * Unbedenklich, weil das Bild das EINZIGE Kind im Fluss war: Preview-
 * Reiter, die drei Wiedergabetasten, das Haekchen und das Glas-Label sind
 * bereits alle absolut. Es aendert sich also keine Stapelreihenfolge und
 * keine Position eines anderen Elements.
 */

.product-card img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    -webkit-user-drag: none;
    user-select: none;
}

/*
 * Bezugsrahmen fuer das absolut gesetzte Bild.
 *
 * Bewusst NUR an den Karten im Paar-Wrapper: Die Referenzkarten sind
 * selbst die .dj-tile und tragen ueber carousel.css bereits
 * position: absolute - sie sind damit ohnehin Bezugsrahmen. Eine Regel auf
 * blankem .product-card wuerde ihnen ihr absolutes Verhalten nehmen; genau
 * dieser Fehler ist im Kommentar zu .dj-track-multi .product-card weiter
 * oben dokumentiert.
 */

.product-card-pair .product-card {
    /* Innere Playlist-Karten bekommen jetzt selbst die quadratische Form, die vorher von .dj-tile kam (sie sind nicht mehr .dj-tile selbst, siehe renderPlaylistCard() in pakete.js). */
    width: 100%;
    aspect-ratio: 1 / 1;
    position: relative;
    /*
     * Hoehe fuer das Glas-Label MIT Auswahlknopf: Das Label ist rund 232 px
     * hoch (vorher 188). Die Mindesthoehe 330 px aus pages.css reichte dann
     * nicht mehr - das Label ueberdeckte die Abspieltasten. Bei 376 px
     * bleiben zwischen Preview-Reitern und Label 80 px fuer die Tasten.
     */
    min-height: 376px;
}

/*
 * Die drei Abspieltasten sitzen mittig in der freien Flaeche zwischen den
 * Preview-Reitern (unten bei 52 px) und dem Label (oben bei 132 px).
 */

.product-card-pair .product-card .product-card-play,
.product-card-pair .product-card .product-card-skip {
    top: 25%;
}

/*
 * Abdunkelnder Verlauf am unteren Rand, damit das helle Glas-Label auf
 * jedem Motiv lesbar bleibt, unabhängig davon, wie hell das Foto dort ist.
 */

.product-card::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(0, 0, 0, .55), transparent 55%);
    pointer-events: none;
    z-index: 1;
}

/* Sicherheitsnetz, falls fitReferenceTitles() (pakete.js) aus irgendeinem Grund nicht läuft - Text bricht dann sauber mit "..." nach 2 Zeilen ab, statt das feste Panel zu sprengen. */

.product-card-reference .product-card-title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.product-card-info {
    display: grid;
    gap: 4px;
}

/* Referenz-Karten (Individualauftrag: STERNAUTO/STARGAYTE) - Orange statt Blau, unterscheidet sie farblich von den Wellness-/Event-Produktkarten. */

[data-reference-index] .product-card-kicker {
    /* Helle Fassung, siehe .product-card-kicker oben. */
    color: var(--orange-auf-dunkel, #ec5830);
}

.product-card-story-close {
    position: absolute;
    top: -18px;
    right: -18px;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, .3);
    background: rgba(255, 255, 255, .12);
    color: #fff;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
}

.product-card-story-close:hover {
    background: rgba(255, 255, 255, .22);
}

/*
 * Referenz-Karten (STERNAUTO/STARGAYTE): Kicker + Titel zentriert statt
 * linksbündig, darunter zentral ein oranger "Mehr erfahren"-Hinweis statt
 * standardmäßig sichtbarem Vorschau-Text - hält beide Karten von Natur aus
 * gleich hoch (kein unterschiedlich langer Text mehr, der die Box streckt).
 * Klick auf den Hinweis blendet die volle story-Zeile ein, siehe pakete.js.
 */

.product-card-reference .product-card-label {
    /* Harte 50%-Obergrenze nur bei Referenz-Karten (dort ursprünglich gedacht, wegen des potenziell langen Zusammenarbeits-Textes) - normale Produktkarten brauchen mehr Raum für ihre 5 Content-Zeilen (Kicker/Titel/Preis/Bundle-Hinweis/Schlagwörter). */
    height: 150px;
    overflow: hidden;
    align-items: center;
    text-align: center;
    min-height: 92px;
    justify-content: center;
}

.product-card-reference .product-card-kicker {
    justify-self: center;
}

.product-card-story-cta {
    /* Helle Fassung - steht auf Cover-Glas (3.5.0-p23). */
    color: var(--orange-auf-dunkel, #ec5830);
    font-weight: 800;
    font-size: .82rem;
    cursor: pointer;
}

.product-card-mood {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: none;
}

.product-card-mood::-webkit-scrollbar {
    display: none;
}

.product-card-mood span {
    flex: 0 0 auto;
    padding: 3px 10px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--blue) 35%, rgba(8, 12, 18, .45));
    border: 1px solid color-mix(in srgb, var(--blue) 55%, transparent);
    color: #fff;
    font-size: .64rem;
    font-weight: 700;
    text-align: center;
    white-space: nowrap;
}

/*
 * Zwei breite Vorschau-Tabs oben ("Preview 1"/"Preview 2") - der Kunde kann
 * gezielt eine der beiden anhören. Zusätzlich ein zentraler Play/Pause-
 * Button, der die Wiedergabe steuert und dabei automatisch von Preview 1 zu
 * Preview 2 weiterläuft (feste Reihenfolge), während die Tabs einen
 * gezielten Sprung erlauben. Gleiche Glasoptik wie der Rest der Cover-
 * Bedienung.
 */

.product-card-preview-tabs {
    position: absolute;
    left: 12px;
    right: 58px;
    top: 12px;
    z-index: 2;
    display: flex;
    gap: 6px;
}

.product-card-preview-tab {
    flex: 1;
    display: grid;
    place-items: center;
    padding: 8px 6px;
    border: 1px solid rgba(255, 255, 255, .45);
    border-radius: 10px;
    background: color-mix(in srgb, #fff 8%, transparent);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    box-shadow: 0 6px 16px rgba(0, 0, 0, .26), inset 0 1px 0 rgba(255, 255, 255, .35);
    color: #fff;
    font-weight: 800;
    font-size: .74rem;
    white-space: nowrap;
    cursor: pointer;
    transition: transform .18s ease, background .18s ease, color .18s ease;
}

.product-card-preview-tab.active {
    background: color-mix(in srgb, var(--orange) 55%, transparent);
    border-color: #ff8666;
    color: #fff;
}

.product-card-preview-tab:active {
    transform: scale(.96);
}

.product-card-preview-tab:focus-visible {
    outline: 3px solid rgba(255, 255, 255, .8);
    outline-offset: 2px;
}

.product-card-play {
    position: absolute;
    left: 50%;
    top: 34%;
    transform: translate(-50%, -50%);
    z-index: 2;
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    border: 1px solid rgba(255, 255, 255, .45);
    border-radius: 50%;
    background: rgba(10, 14, 20, .55);
    box-shadow: 0 10px 26px rgba(0, 0, 0, .32), inset 0 1px 0 rgba(255, 255, 255, .18), 0 0 0 3px rgba(0, 0, 0, .22);
    /* Helle Fassung - die Taste sitzt auf rgba(10,14,20,.55) ueber dem
       Cover (3.5.0-p23). */
    color: var(--orange-auf-dunkel, #ec5830);
    font-size: 1.4rem;
    cursor: pointer;
    transition: transform .18s ease, background .18s ease;
}

[data-reference-index] .product-card-play {
    top: 27%;
}

.product-card-skip {
    position: absolute;
    top: 34%;
    transform: translate(-50%, -50%);
    z-index: 2;
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border: 1px solid rgba(255, 255, 255, .3);
    border-radius: 50%;
    background: color-mix(in srgb, #fff 6%, transparent);
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
    color: rgba(255, 255, 255, .85);
    font-size: .64rem;
    font-weight: 800;
    cursor: pointer;
    transition: background .18s ease;
}

.product-card-skip-back {
    left: calc(50% - 68px);
}

.product-card-skip-forward {
    left: calc(50% + 68px);
}

.product-card-play:active {
    transform: translate(-50%, -50%) scale(.94);
    background: color-mix(in srgb, #fff 16%, transparent);
}

.product-card-play:focus-visible {
    outline: 3px solid rgba(255, 255, 255, .8);
    outline-offset: 3px;
}

/*
 * AUSWAHL AUF DER KARTE: BESCHRIFTETER KNOPF
 *
 * Der Knopf steht als letzte Zeile im Glas-Label der Karte und sagt, was er
 * tut: "Zur Anfrage" (nicht gewaehlt) bzw. "In der Anfrage" (gewaehlt). Ein
 * blasses Haekchen in der Ecke liess offen, dass die Karte ueberhaupt
 * waehlbar ist. Die Beschriftung wechselt rein ueber den Zustand .checked,
 * das Skript setzt nur diese Klasse (updateGridCheckmarks).
 */

.product-card-check {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    margin-top: 4px;
    padding: 0 12px;
    white-space: nowrap;
    border-radius: 999px;
    background: color-mix(in srgb, #fff 14%, transparent);
    border: 1px solid rgba(255, 255, 255, .5);
    color: #fff;
    font-size: .9rem;
    font-weight: 850;
    line-height: 1;
    cursor: pointer;
    transition: background .18s ease, border-color .18s ease, box-shadow .18s ease;
}

.product-card-check-aus,
.product-card-check-an {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Schmale Karten (Handy bis 380 px Fensterbreite): kleinere Schrift, damit
   auch "Dans la demande" in einer Zeile bleibt. */

@media (max-width: 380px) {
.product-card-check {
        font-size: .8rem;
        padding: 0 8px;
    }
}

/* Kleinste Telefone (320 px): die Karte ist 208 px breit, "Dans la demande"
   braucht dort bei .8rem 131 px bei 124 px Platz. */

@media (max-width: 340px) {
.product-card-check {
        font-size: .74rem;
    }
}

/*
 * Die Sprungtasten (-15 / +15) sind 34 px gross. Die Trefferflaeche wird
 * unsichtbar auf 44 px erweitert, ohne dass sich das Aussehen aendert.
 */

.product-card-skip::after {
    content: "";
    position: absolute;
    inset: -5px;
}

.product-card-check-an {
    display: none;
}

.product-card-check.checked .product-card-check-aus {
    display: none;
}

.product-card-check.checked .product-card-check-an {
    display: inline-flex;
}

.product-card-check:focus-visible {
    outline: 3px solid rgba(255, 255, 255, .85);
    outline-offset: 2px;
}

.product-card-check:active {
    transform: translateY(1px);
}

/*
 * AUSGEWÄHLT-ZUSTAND deutlich verstärkt (F7, 01.09.2026).
 *
 * Befund Lars: Der Anfragekorb zählt hoch, aber auf der Karte war nicht zu
 * erkennen, dass sie gewählt ist. Ursache war nicht fehlende Logik - die
 * Klasse wurde gesetzt -, sondern zu wenig Unterschied: Das Häkchen ist auf
 * JEDER Karte sichtbar, und 55 % Orange auf dunklem Glas hebt sich davon
 * kaum ab.
 *
 * Jetzt drei Signale statt einem:
 *   1. Der Kreis ist voll orange statt halbtransparent
 *   2. Er bekommt einen Leuchtring, der ihn aus der Karte heraushebt
 *   3. Die ganze Karte trägt einen orangen Rahmen - sichtbar auch dann,
 *      wenn der Blick nicht auf der Ecke liegt
 *
 * Der unausgewählte Kreis wird zugleich zurückgenommen, damit der
 * Unterschied nicht nur "mehr", sondern "anders" ist.
 */

.product-card-check.checked {
    background: var(--orange);
    border-color: #fff;
    box-shadow: 0 6px 18px color-mix(in srgb, var(--orange) 55%, transparent);
}

/* Ganze Kachel markieren - der zuverlässigste Hinweis, weil er unabhängig
   davon wirkt, wo der Blick gerade liegt. */

.product-card:has(.product-card-check.checked) {
    outline: 3px solid var(--orange);
    outline-offset: -3px;
    border-radius: inherit;
}

@media (hover: hover) and (pointer: fine) {
.product-card-play:hover,
    .product-card-preview-tab:hover {
        background: color-mix(in srgb, #fff 24%, transparent);
    }
.product-card-check:hover {
        /* Dunkler statt heller: Weisse Schrift auf aufgehelltem Grund fiel auf
           hellen Covern unter 4,5 : 1. */
        background: color-mix(in srgb, #0d2438 82%, transparent);
        border-color: #fff;
    }
.product-card-check.checked:hover {
        background: color-mix(in srgb, var(--orange) 85%, #000);
    }
}

/*
 * ZAEHLER STATT PUNKTE AUF DEM HANDY
 *
 * Das Raster hat auf dem Handy eine Kachel je Playlist - 25 Punkte sind
 * zu klein zum Treffen und sagen nichts. Dort steht stattdessen "3 / 25".
 * Ab Tablet bleiben die Punkte, weil dort jeder Punkt eine Seite mit
 * mehreren Karten ist.
 */

.pakete-product-zaehler[hidden] {
    display: none !important;
}

.pakete-product-zaehler {
    display: none;
    margin-top: 10px;
    color: var(--muted);
    font-weight: 850;
    font-size: .95rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

@media (max-width: 650px) {
#productDots {
        display: none;
    }
.pakete-product-zaehler {
        display: block;
    }
}

/* ---------------------------------------------------------------------
   Empfehlung des Musikberaters (LDRaster.empfehlen): die besten Treffer
   tragen einen orangen Rahmen und einen Stern in der freien Ecke oben
   rechts, neben den Preview-Reitern. Laeuft die Karte, gewinnt der
   Wiedergabe-Rahmen (.is-playing steht weiter oben, gleiche Spezifitaet,
   deshalb hier ausdruecklich ausgenommen).
   --------------------------------------------------------------------- */

#productGrid .product-card.is-empfohlen:not(.is-playing) {
    outline: 3px solid var(--orange);
    outline-offset: -3px;
}

.product-card-empfohlen {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--orange);
    color: #fff;
    font-size: 1.05rem;
    box-shadow: 0 4px 14px color-mix(in srgb, var(--orange) 45%, transparent);
}
