Podcast — Guest Spotlight
A dark, audio-first guest spotlight card featuring a full-bleed guest portrait, verified name and role, a two-line bio, and the exact episode where they appeared. A glowing gradient play button toggles an animated violet-to-cyan waveform, live elapsed time counts up, and follow plus social buttons give instant toast feedback. A rail of related guest chips lets you swap the spotlight in place, all keyboard accessible with visible focus rings.
MCP
Code
:root {
--bg: #0c0c10;
--surface: #15151c;
--surface-2: #1d1d27;
--violet: #8b5cf6;
--violet-d: #7c3aed;
--cyan: #22d3ee;
--pink: #f472b6;
--ink: #f4f4f8;
--muted: #9a9aab;
--line: rgba(255, 255, 255, 0.10);
--line-2: rgba(255, 255, 255, 0.18);
--white: #fff;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 20px;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
margin: 0;
min-height: 100vh;
font-family: "Inter", system-ui, -apple-system, sans-serif;
line-height: 1.5;
color: var(--ink);
background:
radial-gradient(900px 600px at 15% -10%, rgba(139, 92, 246, 0.22), transparent 60%),
radial-gradient(700px 500px at 100% 0%, rgba(34, 211, 238, 0.14), transparent 55%),
var(--bg);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
display: grid;
place-items: center;
padding: 32px 18px;
}
.stage { width: 100%; max-width: 460px; }
/* ---------- Card ---------- */
.spotlight {
position: relative;
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.03), transparent 40%),
var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 22px;
box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.7);
overflow: hidden;
}
.spotlight::before {
content: "";
position: absolute;
inset: 0 0 auto 0;
height: 3px;
background: linear-gradient(90deg, var(--violet), var(--cyan));
opacity: 0.9;
}
/* ---------- Head ---------- */
.spotlight__head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 18px;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--violet);
}
.eyebrow__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--cyan);
box-shadow: 0 0 10px 2px rgba(34, 211, 238, 0.7);
animation: blink 1.8s ease-in-out infinite;
}
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
.ep-count {
font-size: 12px;
font-weight: 600;
color: var(--muted);
background: var(--surface-2);
border: 1px solid var(--line);
padding: 4px 10px;
border-radius: 999px;
}
/* ---------- Hero ---------- */
.hero {
position: relative;
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 14px;
}
.hero__glow {
position: absolute;
left: -10px;
top: -10px;
width: 120px;
height: 120px;
border-radius: 50%;
background: radial-gradient(circle, rgba(139, 92, 246, 0.55), transparent 70%);
filter: blur(14px);
z-index: 0;
}
.hero__photo {
position: relative;
z-index: 1;
width: 96px;
height: 96px;
object-fit: cover;
border-radius: 18px;
border: 2px solid var(--line-2);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
flex: none;
transition: transform 0.4s ease, opacity 0.3s ease;
}
.hero__meta { position: relative; z-index: 1; min-width: 0; }
.hero__name {
display: flex;
align-items: center;
gap: 6px;
margin: 0 0 4px;
font-size: 22px;
font-weight: 800;
letter-spacing: -0.02em;
line-height: 1.15;
}
.verified {
width: 20px;
height: 20px;
flex: none;
color: var(--cyan);
filter: drop-shadow(0 0 6px rgba(34, 211, 238, 0.5));
}
.hero__role {
margin: 0;
font-size: 13px;
font-weight: 500;
color: var(--muted);
}
/* ---------- Bio ---------- */
.bio {
margin: 0 0 18px;
font-size: 14px;
color: #c9c9d6;
}
/* ---------- Episode ---------- */
.episode {
display: grid;
grid-template-columns: 56px 1fr auto;
align-items: center;
gap: 14px;
background: var(--surface-2);
border: 1px solid var(--line);
border-radius: var(--r-md);
padding: 12px;
margin-bottom: 18px;
}
.episode__art {
width: 56px;
height: 56px;
border-radius: 10px;
object-fit: cover;
border: 1px solid var(--line);
}
.episode__body { min-width: 0; }
.episode__tag {
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--pink);
}
.episode__title {
margin: 2px 0 8px;
font-size: 15px;
font-weight: 700;
letter-spacing: -0.01em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Waveform */
.wave {
display: flex;
align-items: flex-end;
gap: 3px;
height: 22px;
}
.wave span {
flex: 1;
min-width: 2px;
border-radius: 2px;
background: linear-gradient(180deg, var(--cyan), var(--violet));
height: 30%;
opacity: 0.55;
transform-origin: bottom;
}
.wave.is-playing span {
animation: bounce 1s ease-in-out infinite;
opacity: 1;
}
.wave.is-playing span:nth-child(2n) { animation-duration: 0.75s; }
.wave.is-playing span:nth-child(3n) { animation-duration: 1.2s; }
.wave.is-playing span:nth-child(4n) { animation-duration: 0.9s; }
.wave.is-playing span:nth-child(5n) { animation-duration: 1.35s; }
@keyframes bounce {
0%, 100% { height: 20%; }
50% { height: 100%; }
}
.episode__controls {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
.play {
width: 48px;
height: 48px;
border-radius: 50%;
border: none;
cursor: pointer;
display: grid;
place-items: center;
color: var(--white);
background: linear-gradient(135deg, var(--violet), var(--violet-d));
box-shadow: 0 6px 20px -4px rgba(139, 92, 246, 0.8), inset 0 1px 0 rgba(255, 255, 255, 0.25);
transition: transform 0.18s ease, box-shadow 0.25s ease;
}
.play:hover { transform: translateY(-2px) scale(1.05); }
.play:active { transform: scale(0.96); }
.play.is-playing {
background: linear-gradient(135deg, var(--cyan), var(--violet));
animation: glowPulse 1.6s ease-in-out infinite;
}
@keyframes glowPulse {
0%, 100% { box-shadow: 0 6px 20px -4px rgba(34, 211, 238, 0.7); }
50% { box-shadow: 0 6px 30px 2px rgba(139, 92, 246, 0.9); }
}
.play__icon { width: 22px; height: 22px; }
.play__icon--pause { display: none; }
.play.is-playing .play__icon--play { display: none; }
.play.is-playing .play__icon--pause { display: block; }
.episode__time {
font-size: 11px;
font-weight: 600;
color: var(--muted);
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
/* ---------- Actions ---------- */
.actions {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 20px;
}
.btn {
display: inline-flex;
align-items: center;
gap: 7px;
font-family: inherit;
font-size: 14px;
font-weight: 700;
cursor: pointer;
border-radius: 999px;
padding: 10px 18px;
transition: transform 0.15s ease, background 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}
.btn__ico { width: 16px; height: 16px; transition: transform 0.3s ease; }
.btn--follow {
color: var(--white);
background: linear-gradient(135deg, var(--violet), var(--violet-d));
border: 1px solid transparent;
}
.btn--follow:hover { transform: translateY(-1px); }
.btn--follow:active { transform: scale(0.97); }
.btn--follow[aria-pressed="true"] {
background: transparent;
border-color: var(--line-2);
color: var(--cyan);
}
.btn--follow[aria-pressed="true"] .btn__ico { transform: rotate(45deg); }
.socials { display: inline-flex; gap: 8px; }
.social {
width: 40px;
height: 40px;
display: grid;
place-items: center;
border-radius: 12px;
cursor: pointer;
color: var(--muted);
background: var(--surface-2);
border: 1px solid var(--line);
transition: transform 0.15s ease, color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.social svg { width: 18px; height: 18px; }
.social:hover {
color: var(--ink);
border-color: var(--violet);
background: rgba(139, 92, 246, 0.14);
transform: translateY(-2px);
}
.social:active { transform: scale(0.94); }
/* ---------- Related rail ---------- */
.related {
border-top: 1px solid var(--line);
padding-top: 16px;
}
.related__label {
display: block;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 10px;
}
.related__rail {
display: flex;
gap: 8px;
overflow-x: auto;
padding-bottom: 4px;
scrollbar-width: thin;
scrollbar-color: var(--line-2) transparent;
}
.related__rail::-webkit-scrollbar { height: 6px; }
.related__rail::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 999px; }
.chip {
display: inline-flex;
align-items: center;
gap: 8px;
flex: none;
padding: 6px 12px 6px 6px;
border-radius: 999px;
cursor: pointer;
background: var(--surface-2);
border: 1px solid var(--line);
color: var(--ink);
font-family: inherit;
font-size: 12.5px;
font-weight: 600;
transition: transform 0.15s ease, border-color 0.2s ease, background 0.2s ease;
}
.chip img {
width: 26px;
height: 26px;
border-radius: 50%;
object-fit: cover;
}
.chip:hover { transform: translateY(-2px); border-color: var(--line-2); }
.chip:active { transform: scale(0.96); }
.chip.is-active {
border-color: var(--violet);
background: rgba(139, 92, 246, 0.16);
color: var(--white);
}
/* ---------- Focus ---------- */
:focus-visible {
outline: 2px solid var(--cyan);
outline-offset: 2px;
border-radius: 6px;
}
/* ---------- Toast ---------- */
.toast {
position: fixed;
left: 50%;
bottom: 26px;
transform: translateX(-50%) translateY(20px);
background: var(--surface-2);
border: 1px solid var(--line-2);
color: var(--ink);
font-size: 13px;
font-weight: 600;
padding: 11px 18px;
border-radius: 999px;
box-shadow: 0 14px 34px rgba(0, 0, 0, 0.5);
opacity: 0;
pointer-events: none;
transition: opacity 0.28s ease, transform 0.28s ease;
z-index: 50;
}
.toast.is-show {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
/* ---------- Swap animation ---------- */
.is-swapping .hero__photo,
.is-swapping .hero__meta,
.is-swapping .bio,
.is-swapping .episode {
opacity: 0;
transform: translateY(6px);
}
.hero__meta, .bio, .episode {
transition: opacity 0.3s ease, transform 0.3s ease;
}
/* ---------- Responsive ---------- */
@media (max-width: 520px) {
body { padding: 18px 12px; }
.spotlight { padding: 18px; border-radius: var(--r-md); }
.hero__photo { width: 80px; height: 80px; }
.hero__name { font-size: 19px; }
.episode {
grid-template-columns: 48px 1fr;
row-gap: 12px;
}
.episode__art { width: 48px; height: 48px; }
.episode__controls {
grid-column: 1 / -1;
flex-direction: row;
justify-content: space-between;
width: 100%;
}
.actions { flex-wrap: wrap; }
.btn--follow { flex: 1; justify-content: center; }
}
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; transition: none !important; }
}(function () {
"use strict";
/* ---------- Data ---------- */
var GUESTS = [
{
id: "amara",
name: "Dr. Amara Osei",
role: "Neuroscientist · Author of “Signal & Noise”",
photo: "https://images.unsplash.com/photo-1573497019940-1c28c88b4f3e?auto=format&fit=crop&w=480&q=80",
bio: "Amara runs the Cognition Lab at Meridian University, where she studies how attention rewires under constant notification pressure — and what a focused mind actually costs.",
epNumber: "Episode 128",
epTag: "Season 4 · Featured",
epTitle: "The Cost of a Focused Mind",
epArt: "https://images.unsplash.com/photo-1478737270239-2f02b77fc618?auto=format&fit=crop&w=160&q=80",
duration: "42:18"
},
{
id: "renzo",
name: "Renzo Vidal",
role: "Founder of Cadence · Ex-Spotify",
photo: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&w=480&q=80",
bio: "Renzo built three audio startups before he turned thirty. He argues that the next platform war won’t be about content — it’ll be about who owns the quiet moments between tracks.",
epNumber: "Episode 126",
epTag: "Season 4 · Builders",
epTitle: "Designing for the In-Between",
epArt: "https://images.unsplash.com/photo-1511671782779-c97d3d27a1d4?auto=format&fit=crop&w=160&q=80",
duration: "51:04"
},
{
id: "mei",
name: "Mei-Lin Zhao",
role: "Climate journalist · Peabody winner",
photo: "https://images.unsplash.com/photo-1544005313-94ddf0286df2?auto=format&fit=crop&w=480&q=80",
bio: "Mei-Lin has reported from thirty-one countries on the human edge of the climate story. She joins us to unpack how a single field recording changed an entire policy debate.",
epNumber: "Episode 124",
epTag: "Season 4 · Field Notes",
epTitle: "The Sound of a Melting Coast",
epArt: "https://images.unsplash.com/photo-1470229722913-7c0e2dbbafd3?auto=format&fit=crop&w=160&q=80",
duration: "38:47"
},
{
id: "isa",
name: "Isa Marchetti",
role: "Composer · Grammy-nominated",
photo: "https://images.unsplash.com/photo-1580489944761-15a19d654956?auto=format&fit=crop&w=480&q=80",
bio: "Isa scores films by starting with silence and subtracting. On this episode she walks through the four-note motif that took her eleven months and one broken piano to find.",
epNumber: "Episode 121",
epTag: "Season 4 · Craft",
epTitle: "Writing With the Volume Off",
epArt: "https://images.unsplash.com/photo-1507838153414-b4b713384a76?auto=format&fit=crop&w=160&q=80",
duration: "46:33"
}
];
/* ---------- Elements ---------- */
var $ = function (id) { return document.getElementById(id); };
var photo = $("guestPhoto");
var nameEl = $("guestName");
var roleEl = $("guestRole");
var bioEl = $("guestBio");
var epCount = $("epCount");
var epTag = $("epTag");
var epTitle = $("epTitle");
var epArt = $("epArt");
var epTime = $("epTime");
var playBtn = $("playBtn");
var wave = $("wave");
var followBtn = $("followBtn");
var followLabel = $("followLabel");
var rail = $("rail");
var toastEl = $("toast");
var card = document.querySelector(".spotlight");
var current = 0;
var playing = false;
var elapsed = 0;
var timer = null;
/* ---------- Toast ---------- */
var toastTimer = null;
function toast(msg) {
toastEl.textContent = msg;
toastEl.classList.add("is-show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("is-show");
}, 2200);
}
/* ---------- Time helpers ---------- */
function durationToSeconds(str) {
var p = str.split(":");
return parseInt(p[0], 10) * 60 + parseInt(p[1], 10);
}
function fmt(sec) {
var m = Math.floor(sec / 60);
var s = sec % 60;
return (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
}
function renderTime() {
var g = GUESTS[current];
epTime.textContent = fmt(elapsed) + " / " + g.duration;
epTime.setAttribute("datetime", "PT" + elapsed + "S");
}
/* ---------- Playback ---------- */
function stop() {
playing = false;
clearInterval(timer);
timer = null;
playBtn.classList.remove("is-playing");
playBtn.setAttribute("aria-pressed", "false");
playBtn.setAttribute("aria-label", "Play episode");
wave.classList.remove("is-playing");
}
function play() {
playing = true;
playBtn.classList.add("is-playing");
playBtn.setAttribute("aria-pressed", "true");
playBtn.setAttribute("aria-label", "Pause episode");
wave.classList.add("is-playing");
var total = durationToSeconds(GUESTS[current].duration);
timer = setInterval(function () {
elapsed += 1;
if (elapsed >= total) {
elapsed = total;
renderTime();
stop();
toast("Episode finished — thanks for listening");
return;
}
renderTime();
}, 1000);
toast("Now playing · " + GUESTS[current].epTitle);
}
playBtn.addEventListener("click", function () {
if (playing) { stop(); } else { play(); }
});
/* ---------- Follow ---------- */
followBtn.addEventListener("click", function () {
var on = followBtn.getAttribute("aria-pressed") === "true";
on = !on;
followBtn.setAttribute("aria-pressed", String(on));
followLabel.textContent = on ? "Following" : "Follow";
toast(on ? "Following " + GUESTS[current].name : "Unfollowed " + GUESTS[current].name);
});
/* ---------- Socials ---------- */
document.querySelectorAll(".social").forEach(function (btn) {
btn.addEventListener("click", function () {
var net = btn.getAttribute("data-net");
toast("Opening " + GUESTS[current].name.split(" ")[0] + "’s " + net);
});
});
/* ---------- Render guest ---------- */
function renderGuest(swap) {
var g = GUESTS[current];
var apply = function () {
photo.src = g.photo;
photo.alt = "Portrait of " + g.name;
nameEl.childNodes[0].nodeValue = g.name + " ";
roleEl.innerHTML = g.role;
bioEl.textContent = g.bio;
epCount.textContent = g.epNumber;
epTag.textContent = g.epTag;
epTitle.textContent = g.epTitle;
epArt.src = g.epArt;
renderTime();
if (swap) {
requestAnimationFrame(function () { card.classList.remove("is-swapping"); });
}
};
if (swap) {
card.classList.add("is-swapping");
setTimeout(apply, 300);
} else {
apply();
}
}
function selectGuest(idx) {
if (idx === current) return;
current = idx;
stop();
elapsed = 0;
// reset follow state per guest
followBtn.setAttribute("aria-pressed", "false");
followLabel.textContent = "Follow";
renderGuest(true);
updateChips();
}
/* ---------- Related rail ---------- */
var chips = [];
function buildRail() {
GUESTS.forEach(function (g, i) {
var chip = document.createElement("button");
chip.type = "button";
chip.className = "chip";
chip.setAttribute("role", "option");
chip.setAttribute("aria-selected", i === current ? "true" : "false");
chip.innerHTML =
'<img src="' + g.photo + '" alt="" />' +
"<span>" + g.name + "</span>";
chip.addEventListener("click", function () { selectGuest(i); });
rail.appendChild(chip);
chips.push(chip);
});
}
function updateChips() {
chips.forEach(function (chip, i) {
var active = i === current;
chip.classList.toggle("is-active", active);
chip.setAttribute("aria-selected", active ? "true" : "false");
});
}
/* ---------- Init ---------- */
buildRail();
renderGuest(false);
updateChips();
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Guest Spotlight — Frequency Podcast</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<main class="stage">
<article class="spotlight" aria-labelledby="guestName">
<header class="spotlight__head">
<span class="eyebrow"><span class="eyebrow__dot" aria-hidden="true"></span> Guest Spotlight</span>
<span class="ep-count" id="epCount">Episode 128</span>
</header>
<div class="hero">
<div class="hero__glow" aria-hidden="true"></div>
<img class="hero__photo" id="guestPhoto"
src="https://images.unsplash.com/photo-1573497019940-1c28c88b4f3e?auto=format&fit=crop&w=480&q=80"
alt="Portrait of the featured guest" />
<div class="hero__meta">
<h1 class="hero__name" id="guestName">
Dr. Amara Osei
<svg class="verified" viewBox="0 0 24 24" aria-label="Verified guest" role="img">
<path d="M12 2l2.4 1.8 3 .1 1 2.8 2.3 1.9-1 2.8 1 2.8-2.3 1.9-1 2.8-3 .1L12 22l-2.4-1.8-3-.1-1-2.8L3.3 15.6l1-2.8-1-2.8L5.6 6.1l1-2.8 3-.1L12 2z" fill="currentColor"/>
<path d="M9.5 12.5l1.8 1.8L15 10.6" fill="none" stroke="#0c0c10" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</h1>
<p class="hero__role" id="guestRole">Neuroscientist · Author of “Signal & Noise”</p>
</div>
</div>
<p class="bio" id="guestBio">
Amara runs the Cognition Lab at Meridian University, where she studies how attention
rewires under constant notification pressure — and what a focused mind actually costs.
</p>
<section class="episode" aria-label="Featured episode">
<img class="episode__art" id="epArt"
src="https://images.unsplash.com/photo-1478737270239-2f02b77fc618?auto=format&fit=crop&w=160&q=80"
alt="Episode cover art" />
<div class="episode__body">
<span class="episode__tag" id="epTag">Season 4 · Featured</span>
<h2 class="episode__title" id="epTitle">The Cost of a Focused Mind</h2>
<div class="wave" id="wave" aria-hidden="true">
<span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span>
</div>
</div>
<div class="episode__controls">
<button class="play" id="playBtn" type="button" aria-pressed="false" aria-label="Play episode">
<svg class="play__icon play__icon--play" viewBox="0 0 24 24" aria-hidden="true"><path d="M8 5v14l11-7z" fill="currentColor"/></svg>
<svg class="play__icon play__icon--pause" viewBox="0 0 24 24" aria-hidden="true"><path d="M7 5h4v14H7zM13 5h4v14h-4z" fill="currentColor"/></svg>
</button>
<time class="episode__time" id="epTime" datetime="PT0S">00:00 / 42:18</time>
</div>
</section>
<div class="actions">
<button class="btn btn--follow" id="followBtn" type="button" aria-pressed="false">
<svg viewBox="0 0 24 24" aria-hidden="true" class="btn__ico"><path d="M12 5v14M5 12h14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
<span id="followLabel">Follow</span>
</button>
<div class="socials" role="group" aria-label="Guest social links">
<button class="social" type="button" data-net="Website" aria-label="Visit website">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3a9 9 0 100 18 9 9 0 000-18zm0 0c2.5 2.2 3.8 5.4 3.8 9s-1.3 6.8-3.8 9M12 3C9.5 5.2 8.2 8.4 8.2 12s1.3 6.8 3.8 9M3.4 9h17.2M3.4 15h17.2" fill="none" stroke="currentColor" stroke-width="1.8"/></svg>
</button>
<button class="social" type="button" data-net="X" aria-label="Open on X">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 4l7 8.5L4.4 20H7l5-5.8L16.8 20H20l-7.3-8.9L19.5 4H17l-4.6 5.3L8.1 4H4z" fill="currentColor"/></svg>
</button>
<button class="social" type="button" data-net="LinkedIn" aria-label="Open on LinkedIn">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4a2 2 0 100 4 2 2 0 000-4zM3.5 9.5h3V20h-3V9.5zM9 9.5h2.9v1.5h.05c.4-.75 1.4-1.6 3-1.6 3.2 0 3.8 2 3.8 4.7V20h-3v-4.7c0-1.1 0-2.6-1.6-2.6s-1.85 1.2-1.85 2.5V20H9V9.5z" fill="currentColor"/></svg>
</button>
</div>
</div>
<footer class="related">
<span class="related__label">More guests this season</span>
<div class="related__rail" id="rail" role="listbox" aria-label="Related guests"></div>
</footer>
</article>
</main>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>The Guest Spotlight card puts a single podcast guest center stage: a full-bleed portrait with a soft violet glow, a verified name badge, their role, and a tight two-line bio. Below the fold sits the episode they appeared on — cover art, episode number, title, and duration — paired with a glowing gradient play button that lifts on hover and pulses when active.
Pressing play flips the button state, animates a violet-to-cyan waveform, and starts a live elapsed timer that ticks up in real time. A follow button toggles between “Follow” and “Following”, and each social link (site, X, LinkedIn) fires a small toast so the interaction always feels acknowledged. Everything is reachable by keyboard with a clear focus ring.
A horizontal rail of related-guest chips lets you swap the entire spotlight without a page reload — click or press Enter and the portrait, bio, episode, and socials cross-fade to the new guest. The layout collapses to a single column below 520px, keeping the play button and metadata comfortably tappable on phones.