First commit. Again. Yo ho. Again

This commit is contained in:
2026-04-01 17:29:47 +02:00
commit 6271ea7576
8 changed files with 3671 additions and 0 deletions

577
_playlist-template.html Normal file
View File

@@ -0,0 +1,577 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Eclectica Experimenti | PLAYLISTS</title>
<link href="https://fonts.googleapis.com/css2?family=Ribeye+Marrow&family=Rambla:wght@400;700&family=Share+Tech+Mono&display=swap" rel="stylesheet">
<style>
:root {
--bg-void: #04060b;
--text-warm: #e8d5b8;
--text-muted: #7a6f5e;
--ff-primary: #a855f7;
--ff-bright: #c084fc;
--ff-deep: #6d28d9;
--ff-glow: rgba(168, 85, 247, 0.18);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-void);
color: var(--text-warm);
font-family: 'Rambla', sans-serif;
line-height: 1.5;
min-height: 100vh;
}
/* Sticky Header */
header {
position: sticky;
top: 0;
z-index: 100;
background-color: var(--bg-void);
border-bottom: 1px solid var(--ff-deep);
padding: 1rem 2rem;
display: flex;
align-items: center;
justify-content: space-between;
gap: 2rem;
}
.header-main {
display: flex;
align-items: baseline;
gap: 1.5rem;
flex-grow: 1;
min-width: 0;
}
header h1 {
font-family: 'Ribeye Marrow', cursive;
color: var(--ff-primary);
font-size: 2rem;
font-weight: normal;
margin: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.header-meta {
font-family: 'Share Tech Mono', monospace;
color: var(--text-muted);
font-size: 0.9rem;
text-transform: uppercase;
white-space: nowrap;
}
.nav-links {
display: flex;
gap: 1.5rem;
}
.back-to-hub {
font-family: 'Share Tech Mono', monospace;
color: var(--ff-primary);
text-decoration: none;
font-size: 1rem;
white-space: nowrap;
transition: color 100ms ease;
}
.back-to-hub:hover {
color: var(--ff-bright);
}
/* Mobile Menu */
.menu-toggle {
display: none;
background: none;
border: 1px solid var(--ff-primary);
color: var(--ff-primary);
padding: 0.5rem;
font-family: 'Share Tech Mono', monospace;
cursor: pointer;
font-size: 1.2rem;
}
@media (max-width: 640px) {
header {
padding: 1rem;
}
.nav-links {
display: none;
position: absolute;
top: 100%;
left: 0;
right: 0;
background: var(--bg-void);
flex-direction: column;
padding: 1rem;
border-bottom: 1px solid var(--ff-deep);
}
.nav-links.open {
display: flex;
}
.menu-toggle {
display: block;
}
header h1 {
font-size: 1.5rem;
}
}
/* Track List */
.track-list {
max-width: 1000px;
margin: 2rem auto;
padding: 0 1rem 5rem;
}
.track-card {
display: flex;
flex-direction: column;
border-left: 1px solid var(--ff-deep);
background: transparent;
margin-bottom: 0.5rem;
transition: background 100ms ease, border-color 100ms ease;
position: relative;
}
.track-card:hover {
background: var(--ff-glow);
border-color: var(--ff-primary);
}
.track-card::after {
content: '';
position: absolute;
bottom: -0.25rem;
left: 0;
right: 0;
height: 1px;
background-color: var(--ff-deep);
opacity: 0.1;
}
.track-main-row {
display: flex;
padding: 1.5rem;
gap: 1.5rem;
align-items: flex-start;
}
/* Zones */
.zone-meta {
width: 80px;
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 0.75rem;
}
.track-num {
font-family: 'Share Tech Mono', monospace;
color: var(--text-muted);
font-size: 1.1rem;
}
.album-art {
width: 64px;
height: 64px;
background-color: #111;
object-fit: cover;
border: 1px solid rgba(255,255,255,0.05);
}
.zone-info {
flex-grow: 1;
min-width: 0;
}
.track-name {
font-family: 'Rambla', sans-serif;
font-weight: 700;
font-size: 1.1rem;
color: var(--text-warm);
margin-bottom: 0.25rem;
}
.artist-name {
font-family: 'Rambla', sans-serif;
font-size: 0.95rem;
color: var(--ff-bright);
margin-bottom: 0.5rem;
}
.album-meta {
font-family: 'Share Tech Mono', monospace;
font-size: 0.75rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* Links Row */
.links-row {
margin-top: 1rem;
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.track-link {
font-family: 'Share Tech Mono', monospace;
font-size: 0.75rem;
color: var(--ff-primary);
text-decoration: none;
transition: color 100ms ease;
cursor: pointer;
background: none;
border: none;
padding: 0;
}
.track-link:hover {
color: var(--ff-bright);
}
.track-link[data-available="false"] {
color: var(--text-muted);
cursor: not-allowed;
pointer-events: none;
}
/* Embed Area */
.embed-container {
display: none;
width: 100%;
background: var(--ff-glow);
border-top: 1px solid var(--ff-deep);
padding: 1rem;
}
.video-wrapper {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
height: 0;
overflow: hidden;
}
.video-wrapper iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
.track-card.active {
border-color: var(--ff-primary);
}
.track-card.active .embed-container {
display: block;
}
@media (max-width: 480px) {
.track-main-row {
padding: 1rem;
gap: 1rem;
}
.zone-meta {
width: 64px;
}
.album-art {
width: 48px;
height: 48px;
}
}
</style>
</head>
<body>
<header>
<div class="header-main">
<h1>Eclectica Experimenti</h1>
<span class="header-meta">92 TRACKS &bull; 6:42:15</span>
</div>
<button class="menu-toggle" id="menuToggle"></button>
<nav class="nav-links" id="navLinks">
<a href="playlists.html" class="back-to-hub">← Playlists</a>
</nav>
</header>
<main class="track-list">
<!-- Track 1: Full Embed -->
<article class="track-card">
<div class="track-main-row">
<div class="zone-meta">
<span class="track-num">01</span>
<img class="album-art"
src=""
data-src="https://i.scdn.co/image/ab67616d0000b273b40049962a93144df36ca024"
alt="Album Art"
loading="lazy">
</div>
<div class="zone-info">
<div class="track-name">Midnight City</div>
<div class="artist-name">M83</div>
<div class="album-meta">Hurry Up, We're Dreaming &bull; 2011</div>
<div class="links-row">
<a href="https://open.spotify.com/track/1eyzqe2QqGZUmfc2NWm1vI" class="track-link" target="_blank">[SPOTIFY]</a>
<a href="https://musicbrainz.org/recording/86c62c93-9c8e-4903-8874-9b5753909796" class="track-link" target="_blank">[MUSICBRAINZ]</a>
<button class="track-link youtube-toggle" data-video-id="dX3k_LHnn28">[YOUTUBE]</button>
<a href="https://ilovem83.com" class="track-link" target="_blank">[ARTIST]</a>
</div>
</div>
</div>
<div class="embed-container">
<div class="video-wrapper">
<iframe src=""
data-src="https://www.youtube.com/embed/dX3k_LHnn28"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe>
</div>
</div>
</article>
<!-- Track 2: No Artist Link -->
<article class="track-card">
<div class="track-main-row">
<div class="zone-meta">
<span class="track-num">02</span>
<img class="album-art"
src=""
data-src="https://i.scdn.co/image/ab67616d0000b2737604f56f34582f3a479a4055"
alt="Album Art"
loading="lazy">
</div>
<div class="zone-info">
<div class="track-name">Nightcall</div>
<div class="artist-name">Kavinsky</div>
<div class="album-meta">OutRun &bull; 2013</div>
<div class="links-row">
<a href="#" class="track-link" target="_blank">[SPOTIFY]</a>
<a href="#" class="track-link" target="_blank">[MUSICBRAINZ]</a>
<button class="track-link youtube-toggle" data-video-id="MV_3Dpw-BRY">[YOUTUBE]</button>
<span class="track-link" data-available="false">[ARTIST]</span>
</div>
</div>
</div>
<div class="embed-container">
<div class="video-wrapper">
<iframe src=""
data-src="https://www.youtube.com/embed/MV_3Dpw-BRY"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe>
</div>
</div>
</article>
<!-- Track 3: YouTube Search only -->
<article class="track-card">
<div class="track-main-row">
<div class="zone-meta">
<span class="track-num">03</span>
<img class="album-art"
src=""
data-src="https://i.scdn.co/image/ab67616d0000b273413554e19576189b884d5098"
alt="Album Art"
loading="lazy">
</div>
<div class="zone-info">
<div class="track-name">Genesis</div>
<div class="artist-name">Grimes</div>
<div class="album-meta">Visions &bull; 2012</div>
<div class="links-row">
<a href="#" class="track-link" target="_blank">[SPOTIFY]</a>
<a href="#" class="track-link" target="_blank">[MUSICBRAINZ]</a>
<a href="https://www.youtube.com/results?search_query=Grimes+Genesis" class="track-link" target="_blank">[YOUTUBE]</a>
<a href="#" class="track-link" target="_blank">[ARTIST]</a>
</div>
</div>
</div>
</article>
<!-- Track 4: Another example -->
<article class="track-card">
<div class="track-main-row">
<div class="zone-meta">
<span class="track-num">04</span>
<img class="album-art"
src=""
data-src="https://i.scdn.co/image/ab67616d0000b2731885440620ef0d18d45543c8"
alt="Album Art"
loading="lazy">
</div>
<div class="zone-info">
<div class="track-name">Loro</div>
<div class="artist-name">Pinback</div>
<div class="album-meta">Pinback &bull; 1999</div>
<div class="links-row">
<a href="#" class="track-link" target="_blank">[SPOTIFY]</a>
<a href="#" class="track-link" target="_blank">[MUSICBRAINZ]</a>
<button class="track-link youtube-toggle" data-video-id="46_l1n6_q60">[YOUTUBE]</button>
<a href="#" class="track-link" target="_blank">[ARTIST]</a>
</div>
</div>
</div>
<div class="embed-container">
<div class="video-wrapper">
<iframe src=""
data-src="https://www.youtube.com/embed/46_l1n6_q60"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe>
</div>
</div>
</article>
<!-- Track 5: Deep vibes -->
<article class="track-card">
<div class="track-main-row">
<div class="zone-meta">
<span class="track-num">05</span>
<img class="album-art"
src=""
data-src="https://i.scdn.co/image/ab67616d0000b273fc61f1c2b535d8da951a808f"
alt="Album Art"
loading="lazy">
</div>
<div class="zone-info">
<div class="track-name">Small Memory</div>
<div class="artist-name">Jon Hopkins</div>
<div class="album-meta">Insides &bull; 2009</div>
<div class="links-row">
<a href="#" class="track-link" target="_blank">[SPOTIFY]</a>
<a href="#" class="track-link" target="_blank">[MUSICBRAINZ]</a>
<button class="track-link youtube-toggle" data-video-id="xSls68pX-94">[YOUTUBE]</button>
<a href="#" class="track-link" target="_blank">[ARTIST]</a>
</div>
</div>
</div>
<div class="embed-container">
<div class="video-wrapper">
<iframe src=""
data-src="https://www.youtube.com/embed/xSls68pX-94"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe>
</div>
</div>
</article>
<!-- Track 6: Classics -->
<article class="track-card">
<div class="track-main-row">
<div class="zone-meta">
<span class="track-num">06</span>
<img class="album-art"
src=""
data-src="https://i.scdn.co/image/ab67616d0000b27376696706e57f12a233604f37"
alt="Album Art"
loading="lazy">
</div>
<div class="zone-info">
<div class="track-name">Teardrop</div>
<div class="artist-name">Massive Attack</div>
<div class="album-meta">Mezzanine &bull; 1998</div>
<div class="links-row">
<a href="#" class="track-link" target="_blank">[SPOTIFY]</a>
<a href="#" class="track-link" target="_blank">[MUSICBRAINZ]</a>
<button class="track-link youtube-toggle" data-video-id="u7K72X4eo_s">[YOUTUBE]</button>
<a href="#" class="track-link" target="_blank">[ARTIST]</a>
</div>
</div>
</div>
<div class="embed-container">
<div class="video-wrapper">
<iframe src=""
data-src="https://www.youtube.com/embed/u7K72X4eo_s"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe>
</div>
</div>
</article>
</main>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Mobile menu toggle
const menuToggle = document.getElementById('menuToggle');
const navLinks = document.getElementById('navLinks');
menuToggle.addEventListener('click', () => {
navLinks.classList.toggle('open');
menuToggle.textContent = navLinks.classList.contains('open') ? '✕' : '☰';
});
// Intersection Observer for lazy loading images
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
}, { rootMargin: '300px' });
document.querySelectorAll('.album-art').forEach(img => {
imageObserver.observe(img);
});
// YouTube Toggle and Lazy Loading
const youtubeToggles = document.querySelectorAll('.youtube-toggle');
const videoObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
const card = entry.target;
const iframe = card.querySelector('iframe');
if (entry.isIntersecting && card.classList.contains('active')) {
if (iframe && !iframe.src) {
iframe.src = iframe.dataset.src;
}
}
});
}, { rootMargin: '200px' });
youtubeToggles.forEach(toggle => {
toggle.addEventListener('click', () => {
const card = toggle.closest('.track-card');
const iframe = card.querySelector('iframe');
card.classList.toggle('active');
// If opening, check if we need to load the iframe
if (card.classList.contains('active')) {
videoObserver.observe(card);
// Force check immediate visibility
if (iframe && !iframe.src) {
iframe.src = iframe.dataset.src;
}
}
});
});
});
</script>
</body>
</html>