diff --git a/app.css b/app.css index 30f4d3d..05be480 100644 --- a/app.css +++ b/app.css @@ -1113,6 +1113,133 @@ textarea.inline-edit { .streaming-info-num { font-size: 1.1rem; } } +/* ── Per-type bespoke: MusicGroup (artist/band hero page) ── */ +.card.artist-hero { overflow: hidden; } +.card.artist-hero .hd.hidden { display: none; } + +.artist-banner { + position: relative; + width: 100%; + height: 400px; + overflow: hidden; +} +.artist-banner-img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + filter: brightness(.75) saturate(1.1); + transition: transform .6s cubic-bezier(.16,1,.3,1), filter .4s; +} +.artist-banner:hover .artist-banner-img { + transform: scale(1.04); + filter: brightness(.85) saturate(1.15); +} +.artist-scrim { + position: absolute; + inset: 0; + background: + linear-gradient(180deg, + rgba(0,0,0,.3) 0%, + rgba(0,0,0,.1) 25%, + rgba(0,0,0,.55) 70%, + rgba(0,0,0,.92) 100%); +} +.artist-overlay { + position: absolute; + bottom: 0; left: 0; right: 0; + padding: 1.5rem 2.5rem 2rem; + color: #fff; +} + +/* Genre chips */ +.artist-genre-row { + display: flex; + flex-wrap: wrap; + gap: .35rem; + margin-bottom: .75rem; +} +.artist-genre-chip { + padding: .25rem .65rem; + border-radius: 100px; + background: rgba(255,255,255,.15); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + border: 1px solid rgba(255,255,255,.15); + font-size: .65rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: .06em; + color: rgba(255,255,255,.85); +} + +/* Band name */ +.artist-name { + margin: 0; + font-size: 3rem; + font-weight: 900; + letter-spacing: -.04em; + line-height: 1; + text-shadow: 0 2px 16px rgba(0,0,0,.5); +} + +/* Meta */ +.artist-meta { + font-size: .88rem; + font-weight: 600; + color: rgba(255,255,255,.65); + margin-top: .4rem; + letter-spacing: .04em; + text-transform: uppercase; +} + +/* Listen button */ +.artist-listen-btn { + display: inline-flex; + align-items: center; + gap: .4rem; + margin-top: 1rem; + padding: .6rem 1.5rem; + border-radius: 100px; + background: var(--accent); + color: #fff; + font-size: .88rem; + font-weight: 700; + text-decoration: none; + transition: transform .2s, box-shadow .2s, opacity .2s; + box-shadow: 0 4px 16px color-mix(in oklab, var(--accent) 40%, transparent); +} +.artist-listen-btn:hover { + transform: scale(1.04); + box-shadow: 0 6px 24px color-mix(in oklab, var(--accent) 50%, transparent); + opacity: .95; +} +.artist-listen-btn:active { + transform: scale(1); +} + +/* Body */ +.card.artist-hero .bd { + padding: 1.75rem 2.5rem 2.5rem; +} +.card.artist-hero .bd::before { display: none; } + +/* Bio */ +.artist-bio { + font-size: .92rem; + line-height: 1.75; + color: var(--ink-2); + max-width: 620px; +} + +@media (max-width: 600px) { + .artist-banner { height: 300px; } + .artist-overlay { padding: 1rem 1.25rem 1.25rem; } + .artist-name { font-size: 2rem; } + .artist-genre-chip { font-size: .58rem; padding: .2rem .5rem; } + .card.artist-hero .bd { padding: 1.25rem 1.5rem 2rem; } +} + /* ── Per-type bespoke: Map (stylish wayfinding card) ── */ .card.wayfinding { overflow: hidden; } .card.wayfinding .hd.hidden { display: none; } diff --git a/app.js b/app.js index 73f08d7..dc27e0a 100644 --- a/app.js +++ b/app.js @@ -721,6 +721,109 @@ } } + // ── MUSICGROUP (artist/band hero page) ── + if (cfg.type === "MusicGroup") { + const card = document.querySelector(".card"); + if (card) card.classList.add("artist-hero"); + + const heroMount = document.getElementById("hero-mount"); + const typeLabel = document.getElementById("type-label"); + + // Remove generic hero + heroMount.querySelector(".hero")?.remove(); + + // ── Big banner hero ── + var imageData = data["image"]; + var bandName = data["name"] || ""; + + var hero = document.createElement("div"); + hero.className = "artist-banner"; + + if (imageData) { + var img = document.createElement("img"); + img.className = "artist-banner-img"; + img.src = imageData; + img.alt = bandName; + img.loading = "lazy"; + hero.appendChild(img); + } + + // Scrim + var scrim = document.createElement("div"); + scrim.className = "artist-scrim"; + hero.appendChild(scrim); + + // Overlay content + var overlay = document.createElement("div"); + overlay.className = "artist-overlay"; + + // Genre badge row at top + var genre = data["genre"]; + if (genre) { + var genreRow = document.createElement("div"); + genreRow.className = "artist-genre-row"; + genre.split(",").forEach(function(g) { + var chip = document.createElement("span"); + chip.className = "artist-genre-chip"; + chip.textContent = g.trim(); + genreRow.appendChild(chip); + }); + overlay.appendChild(genreRow); + } + + // Band name HUGE + var h1 = document.createElement("h1"); + h1.className = "artist-name"; + h1.textContent = bandName; + overlay.appendChild(h1); + + // Founding year + var founded = data["foundingDate"]; + if (founded) { + var meta = document.createElement("div"); + meta.className = "artist-meta"; + var yr = founded.match(/(\d{4})/); + meta.textContent = yr ? "Est. " + yr[1] : founded; + overlay.appendChild(meta); + } + + // Listen CTA + var url = data["url"]; + if (url) { + var cta = document.createElement("a"); + cta.className = "artist-listen-btn"; + cta.href = url; + cta.target = "_blank"; + cta.rel = "noopener"; + cta.innerHTML = "\u{1F3B5} Listen"; + overlay.appendChild(cta); + } + + hero.appendChild(overlay); + heroMount.appendChild(hero); + + // Hide normal header + var hd = document.querySelector(".hd"); + if (hd) hd.classList.add("hidden"); + + // Mark handled props + handled.add("name"); + handled.add("image"); + handled.add("genre"); + handled.add("foundingDate"); + handled.add("url"); + + // ── Body: bio ── + var desc = data["description"]; + if (desc) { + var bio = document.createElement("div"); + bio.className = "artist-bio"; + bio.textContent = desc; + view.appendChild(bio); + handled.add("description"); + } + } + // ── MAP (stylish wayfinding card) ── if (cfg.type === "Map") { const card = document.querySelector(".card");