{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "podcast-audio-player",
  "title": "Podcast Audio Player",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/podcast-audio-player/PodcastAudioPlayer.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, onUnmounted, ref } from 'vue'\nimport {\n  Bookmark,\n  BookmarkCheck,\n  BookOpen,\n  Check,\n  Clock,\n  Copy,\n  Download,\n  ExternalLink,\n  FastForward,\n  Headphones,\n  Heart,\n  ListMusic,\n  Mic,\n  Pause,\n  Play,\n  Radio,\n  RotateCcw,\n  RotateCw,\n  Share2,\n  SkipBack,\n  SkipForward,\n  Volume1,\n  Volume2,\n  VolumeX,\n} from 'lucide-vue-next'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Progress } from '@/components/ui/progress'\nimport { Separator } from '@/components/ui/separator'\nimport { Slider } from '@/components/ui/slider'\n\n// Audio Playback State\nconst isPlaying = ref(false)\nconst currentTime = ref(860) // 14:20\nconst totalDuration = ref(2912) // 48:32\nconst volume = ref(80)\nconst isMuted = ref(false)\nconst playbackSpeed = ref(1.0)\nconst speedOptions = [1.0, 1.25, 1.5, 2.0]\nconst isBookmarked = ref(false)\nconst isLiked = ref(false)\nconst likeCount = ref(342)\nconst isCopied = ref(false)\nconst isDownloaded = ref(false)\nconst activeAccordionTab = ref('summary')\n\n// 32-bar visual audio waveform normalized heights (15% to 100%)\nconst waveformBars = [\n  32, 48, 65, 88, 60, 42, 75, 96, 85, 62, 50, 78, 92, 100, 84, 60, 38, 70, 88, 95, 80, 54, 42, 68, 85, 92, 76, 60, 46,\n  64, 82, 45,\n]\n\n// Chapters Data\ninterface Chapter {\n  id: number\n  title: string\n  subtitle: string\n  start: number\n  end: number\n  durationFormatted: string\n}\n\nconst chapters: Chapter[] = [\n  {\n    id: 1,\n    title: 'Intro & State of Tooling',\n    subtitle: 'Why traditional CSS workflows break at scale',\n    start: 0, // 00:00\n    end: 495, // 08:15\n    durationFormatted: '08:15',\n  },\n  {\n    id: 2,\n    title: 'The Monorepo Pivot',\n    subtitle: 'Moving away from monolithic npm component packages',\n    start: 495, // 08:15\n    end: 1360, // 22:40\n    durationFormatted: '14:25',\n  },\n  {\n    id: 3,\n    title: 'OKLCH Math & Contrast Engines',\n    subtitle: 'Perceptual uniformity, APCA contrast & wide-gamut P3',\n    start: 1360, // 22:40\n    end: 2290, // 38:10\n    durationFormatted: '15:30',\n  },\n  {\n    id: 4,\n    title: 'Q&A & Future Standards',\n    subtitle: 'Audience questions, migration playbooks & CSS Color 5',\n    start: 2290, // 38:10\n    end: 2912, // 48:32\n    durationFormatted: '10:22',\n  },\n]\n\n// Hosts & Guest Panelists\ninterface Person {\n  name: string\n  role: string\n  company: string\n  avatar: string\n  fallback: string\n  bio: string\n  handle: string\n}\n\nconst panelists: Person[] = [\n  {\n    name: 'Elena Rostova',\n    role: 'Staff Design Engineer',\n    company: 'Linear',\n    avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=150&auto=format&fit=crop&q=80',\n    fallback: 'ER',\n    bio: 'Pioneered Linear dark mode tokens, high-density keyboard workflows, and micro-interactions.',\n    handle: '@erostova',\n  },\n  {\n    name: 'Marcus Vance',\n    role: 'Head of UI Architecture',\n    company: 'Vercel',\n    avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&auto=format&fit=crop&q=80',\n    fallback: 'MV',\n    bio: 'Core architect on headless design systems, token compilers, and zero-runtime CSS workflows.',\n    handle: '@marcusvance',\n  },\n  {\n    name: 'Dr. Aris Thorne',\n    role: 'Color Science Lead',\n    company: 'W3C CSS Working Group',\n    avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=150&auto=format&fit=crop&q=80',\n    fallback: 'AT',\n    bio: 'Author on CSS Color Module 4 & 5, APCA contrast metric integration, and gamut mapping algorithms.',\n    handle: '@aristhorne',\n  },\n]\n\n// External Referenced Links\ninterface ReferenceLink {\n  title: string\n  description: string\n  url: string\n  tag: string\n}\n\nconst referenceLinks: ReferenceLink[] = [\n  {\n    title: 'OKLCH Color Space Visualizer',\n    description: 'Interactive gamut mapper, lightness ramp generator, and P3 inspector.',\n    url: 'https://oklch.com',\n    tag: 'Tooling',\n  },\n  {\n    title: 'W3C CSS Color Module Level 4',\n    description: 'Official W3C specification defining oklch(), oklab(), and wide-gamut coordinates.',\n    url: 'https://www.w3.org/TR/css-color-4/',\n    tag: 'Specification',\n  },\n  {\n    title: 'UIPKGE Component Registry Architecture',\n    description: 'The unbundled registry distribution model for Vue and React design systems.',\n    url: 'https://uipkge.dev',\n    tag: 'Architecture',\n  },\n  {\n    title: 'APCA Accessible Perceptual Contrast Algorithm',\n    description: 'Next-generation readability standard replacing legacy WCAG 2 ratio formulas.',\n    url: 'https://git.apcacontrast.com',\n    tag: 'Accessibility',\n  },\n]\n\n// Playback Timer\nlet playInterval: ReturnType<typeof setInterval> | null = null\n\nfunction togglePlay() {\n  isPlaying.value = !isPlaying.value\n  if (isPlaying.value) {\n    playInterval = setInterval(() => {\n      if (currentTime.value < totalDuration.value) {\n        currentTime.value += 1\n      } else {\n        isPlaying.value = false\n        if (playInterval) clearInterval(playInterval)\n      }\n    }, 1000 / playbackSpeed.value)\n  } else if (playInterval) {\n    clearInterval(playInterval)\n  }\n}\n\nonUnmounted(() => {\n  if (playInterval) clearInterval(playInterval)\n})\n\nfunction formatTime(seconds: number): string {\n  const m = Math.floor(seconds / 60)\n  const s = Math.floor(seconds % 60)\n  return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`\n}\n\nconst formattedCurrentTime = computed(() => formatTime(currentTime.value))\nconst formattedTotalTime = computed(() => formatTime(totalDuration.value))\nconst remainingTime = computed(() => `-${formatTime(totalDuration.value - currentTime.value)}`)\nconst progressPercent = computed(() => (currentTime.value / totalDuration.value) * 100)\n\nconst currentChapter = computed(() => {\n  return (\n    chapters.find((c) => currentTime.value >= c.start && currentTime.value < c.end) || chapters[chapters.length - 1]\n  )\n})\n\nconst currentChapterProgress = computed(() => {\n  const ch = currentChapter.value\n  const elapsed = currentTime.value - ch.start\n  const total = ch.end - ch.start\n  return Math.min(100, Math.max(0, (elapsed / total) * 100))\n})\n\nfunction seekTo(seconds: number) {\n  currentTime.value = Math.max(0, Math.min(seconds, totalDuration.value))\n}\n\nfunction handleWaveformClick(event: MouseEvent) {\n  const target = event.currentTarget as HTMLElement\n  const rect = target.getBoundingClientRect()\n  const clickX = event.clientX - rect.left\n  const ratio = Math.max(0, Math.min(1, clickX / rect.width))\n  seekTo(Math.round(ratio * totalDuration.value))\n}\n\nfunction skipSeconds(delta: number) {\n  seekTo(currentTime.value + delta)\n}\n\nfunction cycleSpeed() {\n  const currentIndex = speedOptions.indexOf(playbackSpeed.value)\n  const nextIndex = (currentIndex + 1) % speedOptions.length\n  playbackSpeed.value = speedOptions[nextIndex]\n  if (isPlaying.value) {\n    if (playInterval) clearInterval(playInterval)\n    playInterval = setInterval(() => {\n      if (currentTime.value < totalDuration.value) {\n        currentTime.value += 1\n      } else {\n        isPlaying.value = false\n        if (playInterval) clearInterval(playInterval)\n      }\n    }, 1000 / playbackSpeed.value)\n  }\n}\n\nfunction skipToNextChapter() {\n  const currentIndex = chapters.findIndex((c) => c.id === currentChapter.value.id)\n  if (currentIndex < chapters.length - 1) {\n    seekTo(chapters[currentIndex + 1].start)\n  }\n}\n\nfunction skipToPrevChapter() {\n  const ch = currentChapter.value\n  if (currentTime.value - ch.start > 4) {\n    seekTo(ch.start)\n  } else {\n    const currentIndex = chapters.findIndex((c) => c.id === ch.id)\n    if (currentIndex > 0) {\n      seekTo(chapters[currentIndex - 1].start)\n    } else {\n      seekTo(0)\n    }\n  }\n}\n\nfunction toggleMute() {\n  isMuted.value = !isMuted.value\n}\n\nfunction toggleLike() {\n  isLiked.value = !isLiked.value\n  likeCount.value += isLiked.value ? 1 : -1\n}\n\nfunction handleCopyLink() {\n  isCopied.value = true\n  setTimeout(() => {\n    isCopied.value = false\n  }, 2000)\n}\n\nfunction handleDownload() {\n  isDownloaded.value = true\n  setTimeout(() => {\n    isDownloaded.value = false\n  }, 3000)\n}\n</script>\n\n<template>\n  <div data-slot=\"podcast-audio-player\" class=\"bg-background text-foreground w-full space-y-6\">\n    <!-- EPISODE HERO CARD -->\n    <Card class=\"overflow-hidden border shadow-xs\">\n      <CardContent class=\"p-5 sm:p-7\">\n        <div class=\"flex flex-col gap-6 lg:flex-row lg:items-center lg:justify-between\">\n          <!-- Left Column: Cover Art & Episode Details -->\n          <div class=\"flex flex-col gap-5 sm:flex-row sm:items-center\">\n            <!-- Podcast Cover Artwork Thumbnail -->\n            <div\n              class=\"from-primary/20 via-primary/10 to-background ring-border/80 group relative flex size-28 shrink-0 items-center justify-center overflow-hidden rounded-2xl border bg-gradient-to-br shadow-md ring-1 sm:size-32\"\n            >\n              <!-- Animated Soundwave/Vinyl Graphic -->\n              <div\n                class=\"border-primary/30 absolute inset-2 rounded-xl border border-dashed opacity-60 transition-transform duration-700 group-hover:rotate-45\"\n              />\n              <div\n                class=\"bg-card/90 relative z-10 flex size-14 items-center justify-center rounded-xl border shadow-xs\"\n              >\n                <Radio class=\"text-primary size-7\" />\n              </div>\n              <div\n                class=\"bg-background/90 text-foreground absolute right-2 bottom-2 rounded-md px-1.5 py-0.5 font-mono text-xs font-semibold shadow-xs\"\n              >\n                EP #48\n              </div>\n            </div>\n\n            <!-- Episode Meta & Titles -->\n            <div class=\"space-y-2\">\n              <div class=\"flex flex-wrap items-center gap-2\">\n                <Badge variant=\"outline\" class=\"gap-1 text-xs font-semibold\">\n                  <Mic class=\"text-primary size-3\" />\n                  <span>The Design Systems Podcast</span>\n                </Badge>\n                <Badge variant=\"secondary\" class=\"font-mono text-xs\"> Season 4 · Episode #48 </Badge>\n                <Badge variant=\"outline\" class=\"border-success/30 bg-success/10 text-success font-mono text-xs\">\n                  Lossless 320kbps\n                </Badge>\n              </div>\n\n              <h1 class=\"text-foreground text-xl font-bold tracking-tight sm:text-2xl lg:text-3xl\">\n                Deconstructing OKLCH & Zero-Dependency Component Registries\n              </h1>\n\n              <div class=\"text-muted-foreground flex flex-wrap items-center gap-3 text-xs sm:text-sm\">\n                <!-- Hosts Avatars -->\n                <div class=\"flex items-center gap-2\">\n                  <div class=\"flex shrink-0 -space-x-2 overflow-hidden\">\n                    <Avatar class=\"border-background ring-border size-6 border-2 ring-1\">\n                      <AvatarImage :src=\"panelists[0].avatar\" :alt=\"panelists[0].name\" />\n                      <AvatarFallback>{{ panelists[0].fallback }}</AvatarFallback>\n                    </Avatar>\n                    <Avatar class=\"border-background ring-border size-6 border-2 ring-1\">\n                      <AvatarImage :src=\"panelists[1].avatar\" :alt=\"panelists[1].name\" />\n                      <AvatarFallback>{{ panelists[1].fallback }}</AvatarFallback>\n                    </Avatar>\n                    <Avatar class=\"border-background ring-border size-6 border-2 ring-1\">\n                      <AvatarImage :src=\"panelists[2].avatar\" :alt=\"panelists[2].name\" />\n                      <AvatarFallback>{{ panelists[2].fallback }}</AvatarFallback>\n                    </Avatar>\n                  </div>\n                  <span class=\"text-foreground font-medium\">Elena Rostova, Marcus Vance & Dr. Aris Thorne</span>\n                </div>\n                <span>·</span>\n                <div class=\"flex items-center gap-1 font-mono text-xs tabular-nums\">\n                  <Clock class=\"size-3.5\" />\n                  <span>48 mins</span>\n                </div>\n              </div>\n            </div>\n          </div>\n\n          <!-- Right Column: Primary Hero Actions -->\n          <div class=\"flex flex-wrap items-center gap-2 border-t pt-4 lg:border-t-0 lg:pt-0\">\n            <!-- Like Button -->\n            <Button\n              :variant=\"isLiked ? 'default' : 'outline'\"\n              size=\"sm\"\n              class=\"h-9 gap-1.5 text-xs font-semibold shadow-xs\"\n              @click=\"toggleLike\"\n            >\n              <Heart :class=\"['size-4', isLiked ? 'fill-current' : 'text-muted-foreground']\" />\n              <span class=\"font-mono tabular-nums\">{{ likeCount }}</span>\n            </Button>\n\n            <!-- Bookmark Button -->\n            <Button\n              variant=\"outline\"\n              size=\"icon\"\n              class=\"size-9 shadow-xs\"\n              :aria-label=\"isBookmarked ? 'Remove bookmark' : 'Bookmark episode'\"\n              @click=\"isBookmarked = !isBookmarked\"\n            >\n              <BookmarkCheck v-if=\"isBookmarked\" class=\"text-primary size-4\" />\n              <Bookmark v-else class=\"text-muted-foreground size-4\" />\n            </Button>\n\n            <!-- Share / Copy Link -->\n            <Button\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"h-9 gap-1.5 text-xs font-semibold shadow-xs\"\n              @click=\"handleCopyLink\"\n            >\n              <Check v-if=\"isCopied\" class=\"text-success size-4\" />\n              <Share2 v-else class=\"size-4\" />\n              <span>{{ isCopied ? 'Link Copied' : 'Share' }}</span>\n            </Button>\n\n            <!-- Download Episode -->\n            <Button\n              variant=\"outline\"\n              size=\"icon\"\n              class=\"size-9 shadow-xs\"\n              :aria-label=\"isDownloaded ? 'Downloaded' : 'Download episode'\"\n              @click=\"handleDownload\"\n            >\n              <Check v-if=\"isDownloaded\" class=\"text-success size-4\" />\n              <Download v-else class=\"size-4\" />\n            </Button>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- AUDIO PLAYER CONTROLS (CENTERPIECE) -->\n    <Card class=\"border shadow-xs\">\n      <CardContent class=\"space-y-6 p-5 sm:p-7\">\n        <!-- Currently Playing Chapter Header -->\n        <div class=\"flex flex-col justify-between gap-2 sm:flex-row sm:items-center\">\n          <div class=\"space-y-1\">\n            <div class=\"flex items-center gap-2\">\n              <span class=\"bg-primary size-2 animate-pulse rounded-full\" />\n              <span class=\"text-muted-foreground font-mono text-xs font-semibold tracking-wider uppercase\">\n                Now Playing · Chapter {{ currentChapter.id }} of {{ chapters.length }}\n              </span>\n            </div>\n            <h2 class=\"text-foreground text-base font-bold tracking-tight sm:text-lg\">\n              {{ currentChapter.title }}\n            </h2>\n            <p class=\"text-muted-foreground text-xs\">\n              {{ currentChapter.subtitle }}\n            </p>\n          </div>\n\n          <div class=\"flex items-center gap-2 self-start font-mono text-xs font-semibold tabular-nums sm:self-auto\">\n            <Badge variant=\"outline\" class=\"border-primary/30 bg-primary/5 gap-1 px-2.5 py-1\">\n              <span class=\"text-primary font-bold\">{{ formattedCurrentTime }}</span>\n              <span class=\"text-muted-foreground\">/</span>\n              <span class=\"text-muted-foreground\">{{ formattedTotalTime }}</span>\n            </Badge>\n            <span class=\"text-muted-foreground text-xs\">{{ remainingTime }}</span>\n          </div>\n        </div>\n\n        <!-- 32-BAR VISUAL SVG AUDIO WAVEFORM SCRUBBER -->\n        <div class=\"space-y-2\">\n          <div\n            class=\"group/wave bg-muted/30 hover:bg-muted/50 border-border/80 relative flex h-24 w-full cursor-pointer items-center justify-between rounded-xl border p-4 transition-colors select-none\"\n            role=\"slider\"\n            aria-label=\"Audio Waveform Scrubber\"\n            :aria-valuenow=\"currentTime\"\n            :aria-valuemin=\"0\"\n            :aria-valuemax=\"totalDuration\"\n            @click=\"handleWaveformClick\"\n          >\n            <!-- Background SVG Waveform Bars -->\n            <div class=\"flex h-full w-full items-center justify-between gap-1 sm:gap-1.5\">\n              <div\n                v-for=\"(barHeight, index) in waveformBars\"\n                :key=\"index\"\n                class=\"flex h-full flex-1 items-center justify-center\"\n              >\n                <!-- Single Audio Bar -->\n                <div\n                  :class=\"[\n                    'w-full max-w-[8px] rounded-full transition-[height] duration-150',\n                    (index / waveformBars.length) * 100 <= progressPercent\n                      ? 'bg-primary'\n                      : 'bg-muted-foreground/25 group-hover/wave:bg-muted-foreground/35',\n                    isPlaying && Math.floor((progressPercent / 100) * waveformBars.length) === index\n                      ? 'ring-primary/40 scale-y-110 ring-2'\n                      : '',\n                  ]\"\n                  :style=\"{\n                    height: `${barHeight}%`,\n                  }\"\n                />\n              </div>\n            </div>\n\n            <!-- Interactive Timeline Cursor Scrubber Line -->\n            <div\n              class=\"bg-foreground pointer-events-none absolute top-0 bottom-0 z-10 w-0.5 transition-colors\"\n              :style=\"{ left: `${progressPercent}%` }\"\n            >\n              <div\n                class=\"bg-primary ring-background absolute -top-1 left-1/2 size-3.5 -translate-x-1/2 rounded-full shadow-md ring-2 transition-transform group-hover/wave:scale-125\"\n              />\n            </div>\n\n            <!-- Chapter Notch Markers on Waveform Bottom -->\n            <div class=\"pointer-events-none absolute right-4 bottom-1.5 left-4 flex justify-between\">\n              <span\n                v-for=\"ch in chapters\"\n                :key=\"ch.id\"\n                class=\"absolute flex flex-col items-center\"\n                :style=\"{ left: `${(ch.start / totalDuration) * 100}%` }\"\n              >\n                <span class=\"bg-muted-foreground/50 h-2 w-0.5\" />\n              </span>\n            </div>\n          </div>\n\n          <!-- Bottom Time & Chapter Range Indicators -->\n          <div class=\"text-muted-foreground flex items-center justify-between font-mono text-xs tabular-nums\">\n            <div class=\"flex items-center gap-1.5\">\n              <span class=\"text-foreground font-semibold\">{{ formattedCurrentTime }}</span>\n              <span>(Chapter progress: {{ Math.round(currentChapterProgress) }}%)</span>\n            </div>\n            <span>{{ formattedTotalTime }}</span>\n          </div>\n        </div>\n\n        <!-- MAIN PLAYBACK CONTROLS BAR -->\n        <div class=\"flex flex-col items-center justify-between gap-4 pt-2 md:flex-row\">\n          <!-- Left: Secondary Tools (Speed & Chapter Navigation) -->\n          <div class=\"flex items-center gap-2\">\n            <!-- Speed Selector Button -->\n            <Button\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"hover:bg-accent h-9 gap-1 px-2.5 font-mono text-xs font-bold shadow-xs\"\n              aria-label=\"Cycle Playback Speed\"\n              @click=\"cycleSpeed\"\n            >\n              <FastForward class=\"text-primary size-3.5\" />\n              <span>{{ playbackSpeed.toFixed(playbackSpeed % 1 === 0 ? 1 : 2) }}x</span>\n            </Button>\n\n            <!-- Previous Chapter -->\n            <Button\n              variant=\"ghost\"\n              size=\"icon\"\n              class=\"text-muted-foreground hover:text-foreground size-9\"\n              aria-label=\"Previous Chapter\"\n              @click=\"skipToPrevChapter\"\n            >\n              <SkipBack class=\"size-4\" />\n            </Button>\n\n            <!-- Next Chapter -->\n            <Button\n              variant=\"ghost\"\n              size=\"icon\"\n              class=\"text-muted-foreground hover:text-foreground size-9\"\n              aria-label=\"Next Chapter\"\n              @click=\"skipToNextChapter\"\n            >\n              <SkipForward class=\"size-4\" />\n            </Button>\n          </div>\n\n          <!-- Center: Core Transport Buttons (15s Rewind, Play/Pause, 15s Fast Forward) -->\n          <div class=\"flex items-center gap-3\">\n            <!-- 15s Rewind -->\n            <Button\n              variant=\"outline\"\n              size=\"icon\"\n              class=\"size-10 rounded-full shadow-xs\"\n              aria-label=\"Rewind 15 seconds\"\n              @click=\"skipSeconds(-15)\"\n            >\n              <RotateCcw class=\"size-4.5\" />\n            </Button>\n\n            <!-- Primary Play / Pause Circle Button -->\n            <Button\n              variant=\"default\"\n              size=\"icon\"\n              class=\"bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-ring size-13 rounded-full shadow-lg transition-[color,background-color,border-color,box-shadow,opacity,transform,scale,translate,rotate] hover:scale-105 focus-visible:ring-2 active:scale-95\"\n              :aria-label=\"isPlaying ? 'Pause episode' : 'Play episode'\"\n              @click=\"togglePlay\"\n            >\n              <Pause v-if=\"isPlaying\" class=\"size-6 fill-current\" />\n              <Play v-else class=\"ml-0.5 size-6 fill-current\" />\n            </Button>\n\n            <!-- 15s Fast Forward -->\n            <Button\n              variant=\"outline\"\n              size=\"icon\"\n              class=\"size-10 rounded-full shadow-xs\"\n              aria-label=\"Fast forward 15 seconds\"\n              @click=\"skipSeconds(15)\"\n            >\n              <RotateCw class=\"size-4.5\" />\n            </Button>\n          </div>\n\n          <!-- Right: Volume Slider Controls -->\n          <div class=\"flex items-center gap-2.5\">\n            <Button\n              variant=\"ghost\"\n              size=\"icon\"\n              class=\"text-muted-foreground hover:text-foreground size-9\"\n              :aria-label=\"isMuted ? 'Unmute' : 'Mute'\"\n              @click=\"toggleMute\"\n            >\n              <VolumeX v-if=\"isMuted || volume === 0\" class=\"text-destructive size-4.5\" />\n              <Volume1 v-else-if=\"volume < 50\" class=\"size-4.5\" />\n              <Volume2 v-else class=\"size-4.5\" />\n            </Button>\n\n            <div class=\"w-24 sm:w-28\">\n              <Slider v-model=\"volume\" :min=\"0\" :max=\"100\" :step=\"1\" :disabled=\"isMuted\" class=\"cursor-pointer\" />\n            </div>\n            <span class=\"text-muted-foreground w-8 text-right font-mono text-xs tabular-nums\">\n              {{ isMuted ? '0%' : `${volume}%` }}\n            </span>\n          </div>\n        </div>\n\n        <Separator />\n\n        <!-- CHAPTER NAVIGATION BAR -->\n        <div class=\"space-y-3\">\n          <div class=\"flex items-center justify-between\">\n            <div class=\"flex items-center gap-2\">\n              <ListMusic class=\"text-primary size-4\" />\n              <h3 class=\"text-foreground text-xs font-bold tracking-tight uppercase\">Chapter Navigation</h3>\n            </div>\n            <span class=\"text-muted-foreground font-mono text-xs\"> 4 Chapters · 48m 32s Total </span>\n          </div>\n\n          <div class=\"grid grid-cols-1 gap-2.5 sm:grid-cols-2 lg:grid-cols-4\">\n            <div\n              v-for=\"ch in chapters\"\n              :key=\"ch.id\"\n              :class=\"[\n                'group flex cursor-pointer flex-col justify-between rounded-xl border p-3 text-xs transition-colors duration-200',\n                currentChapter.id === ch.id\n                  ? 'border-primary/50 bg-primary/5 ring-primary/20 shadow-xs ring-1'\n                  : 'bg-card hover:bg-muted/40 border-border/70',\n              ]\"\n              @click=\"seekTo(ch.start)\"\n            >\n              <div class=\"space-y-1\">\n                <div class=\"flex items-center justify-between\">\n                  <Badge\n                    :variant=\"currentChapter.id === ch.id ? 'default' : 'outline'\"\n                    class=\"h-5 px-1.5 font-mono text-xs font-semibold\"\n                  >\n                    CH {{ ch.id }}\n                  </Badge>\n                  <span class=\"text-muted-foreground font-mono text-xs tabular-nums\">\n                    {{ formatTime(ch.start) }}\n                  </span>\n                </div>\n                <div class=\"text-foreground line-clamp-1 font-semibold\">\n                  {{ ch.title }}\n                </div>\n                <div class=\"text-muted-foreground line-clamp-1 text-xs\">\n                  {{ ch.subtitle }}\n                </div>\n              </div>\n\n              <!-- Active Chapter Progress Mini Indicator -->\n              <div class=\"mt-2.5 pt-1\">\n                <Progress v-if=\"currentChapter.id === ch.id\" :model-value=\"currentChapterProgress\" class=\"h-1\" />\n                <div\n                  v-else\n                  :class=\"['h-1 w-full rounded-full', currentTime >= ch.end ? 'bg-primary/40' : 'bg-muted']\"\n                />\n              </div>\n            </div>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- EPISODE SHOW NOTES & GUEST LINKS ACCORDION -->\n    <Card class=\"border shadow-xs\">\n      <CardHeader class=\"pb-3\">\n        <div class=\"flex items-center justify-between\">\n          <div class=\"flex items-center gap-2\">\n            <BookOpen class=\"text-primary size-4\" />\n            <CardTitle class=\"text-base font-bold tracking-tight sm:text-lg\">\n              Episode Show Notes & Comprehensive Guide\n            </CardTitle>\n          </div>\n          <Badge variant=\"outline\" class=\"font-mono text-xs\"> Full Notes </Badge>\n        </div>\n        <CardDescription class=\"text-xs sm:text-sm\">\n          Deep dive references, color math formulas, guest bios, and resource bookmarks from this episode.\n        </CardDescription>\n      </CardHeader>\n\n      <CardContent class=\"pt-1\">\n        <Accordion type=\"single\" collapsible default-value=\"summary\" class=\"w-full\">\n          <!-- Accordion Item 1: Episode Summary -->\n          <AccordionItem value=\"summary\">\n            <AccordionTrigger class=\"text-xs font-semibold hover:no-underline sm:text-sm\">\n              <div class=\"flex items-center gap-2\">\n                <span\n                  class=\"bg-primary/10 text-primary flex size-5 items-center justify-center rounded-full text-xs font-bold\"\n                  >1</span\n                >\n                <span>Executive Summary & Key Takeaways</span>\n              </div>\n            </AccordionTrigger>\n            <AccordionContent class=\"space-y-3 pt-2 text-xs leading-relaxed\">\n              <p class=\"text-muted-foreground\">\n                In this episode, we break down why traditional HSL and sRGB color models fall short when building\n                modern, accessible multi-theme design systems. We explore how the OKLCH color space decouples perceptual\n                lightness from chroma and hue, eliminating contrast inversion bugs when shifting from light to OLED dark\n                mode.\n              </p>\n\n              <div class=\"grid grid-cols-1 gap-3 pt-1 sm:grid-cols-3\">\n                <div class=\"bg-muted/30 space-y-1 rounded-lg border p-3\">\n                  <div class=\"text-foreground font-semibold\">Perceptual Uniformity</div>\n                  <p class=\"text-muted-foreground text-xs\">\n                    Lightness (L) in OKLCH remains consistent regardless of hue angle, unlike HSL where yellow appears\n                    far brighter than blue.\n                  </p>\n                </div>\n\n                <div class=\"bg-muted/30 space-y-1 rounded-lg border p-3\">\n                  <div class=\"text-foreground font-semibold\">Zero-Dependency Registries</div>\n                  <p class=\"text-muted-foreground text-xs\">\n                    Unbundled component distribution gives engineering teams 100% source code ownership with zero\n                    semantic version drift.\n                  </p>\n                </div>\n\n                <div class=\"bg-muted/30 space-y-1 rounded-lg border p-3\">\n                  <div class=\"text-foreground font-semibold\">Tailwind v4 @theme</div>\n                  <p class=\"text-muted-foreground text-xs\">\n                    Direct CSS variable binding with OKLCH tokens unlocks dynamic color-mix tints without JavaScript\n                    runtime overhead.\n                  </p>\n                </div>\n              </div>\n            </AccordionContent>\n          </AccordionItem>\n\n          <!-- Accordion Item 2: Detailed Chapter Breakdown -->\n          <AccordionItem value=\"chapters\">\n            <AccordionTrigger class=\"text-xs font-semibold hover:no-underline sm:text-sm\">\n              <div class=\"flex items-center gap-2\">\n                <span\n                  class=\"bg-primary/10 text-primary flex size-5 items-center justify-center rounded-full text-xs font-bold\"\n                  >2</span\n                >\n                <span>Timestamped Chapter Breakdown & Discussion Topics</span>\n              </div>\n            </AccordionTrigger>\n            <AccordionContent class=\"space-y-2.5 pt-2 text-xs\">\n              <div\n                v-for=\"ch in chapters\"\n                :key=\"ch.id\"\n                class=\"bg-muted/20 hover:bg-muted/40 flex items-center justify-between rounded-lg border p-3 transition-colors\"\n              >\n                <div class=\"space-y-0.5\">\n                  <div class=\"flex items-center gap-2\">\n                    <span class=\"text-foreground font-semibold\">Chapter {{ ch.id }}: {{ ch.title }}</span>\n                  </div>\n                  <p class=\"text-muted-foreground text-xs\">{{ ch.subtitle }}</p>\n                </div>\n\n                <Button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  class=\"h-7 gap-1 px-2.5 font-mono text-xs font-bold tabular-nums\"\n                  @click=\"seekTo(ch.start)\"\n                >\n                  <Play class=\"text-primary size-2.5 fill-current\" />\n                  <span>{{ formatTime(ch.start) }}</span>\n                </Button>\n              </div>\n            </AccordionContent>\n          </AccordionItem>\n\n          <!-- Accordion Item 3: Featured Panelists & Guests -->\n          <AccordionItem value=\"panelists\">\n            <AccordionTrigger class=\"text-xs font-semibold hover:no-underline sm:text-sm\">\n              <div class=\"flex items-center gap-2\">\n                <span\n                  class=\"bg-primary/10 text-primary flex size-5 items-center justify-center rounded-full text-xs font-bold\"\n                  >3</span\n                >\n                <span>Featured Hosts & Guest Panel</span>\n              </div>\n            </AccordionTrigger>\n            <AccordionContent class=\"space-y-3 pt-2 text-xs\">\n              <div class=\"grid grid-cols-1 gap-3 md:grid-cols-3\">\n                <div\n                  v-for=\"person in panelists\"\n                  :key=\"person.name\"\n                  class=\"bg-muted/25 flex flex-col justify-between space-y-3 rounded-xl border p-3.5\"\n                >\n                  <div class=\"flex items-start gap-3\">\n                    <Avatar class=\"ring-border size-10 border ring-1\">\n                      <AvatarImage :src=\"person.avatar\" :alt=\"person.name\" />\n                      <AvatarFallback>{{ person.fallback }}</AvatarFallback>\n                    </Avatar>\n                    <div class=\"min-w-0 space-y-0.5\">\n                      <div class=\"text-foreground truncate font-bold\">{{ person.name }}</div>\n                      <div class=\"text-muted-foreground truncate text-xs\">{{ person.role }}</div>\n                      <Badge variant=\"secondary\" class=\"h-4 px-1 text-xs\">\n                        {{ person.company }}\n                      </Badge>\n                    </div>\n                  </div>\n                  <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                    {{ person.bio }}\n                  </p>\n                  <div class=\"text-primary font-mono text-xs\">\n                    {{ person.handle }}\n                  </div>\n                </div>\n              </div>\n            </AccordionContent>\n          </AccordionItem>\n\n          <!-- Accordion Item 4: Mentioned Resources & External Links -->\n          <AccordionItem value=\"resources\">\n            <AccordionTrigger class=\"text-xs font-semibold hover:no-underline sm:text-sm\">\n              <div class=\"flex items-center gap-2\">\n                <span\n                  class=\"bg-primary/10 text-primary flex size-5 items-center justify-center rounded-full text-xs font-bold\"\n                  >4</span\n                >\n                <span>Mentioned Resources & Specifications</span>\n              </div>\n            </AccordionTrigger>\n            <AccordionContent class=\"space-y-2.5 pt-2 text-xs\">\n              <div class=\"grid grid-cols-1 gap-2.5 sm:grid-cols-2\">\n                <a\n                  v-for=\"link in referenceLinks\"\n                  :key=\"link.title\"\n                  :href=\"link.url\"\n                  target=\"_blank\"\n                  rel=\"noreferrer\"\n                  class=\"bg-muted/25 hover:bg-muted/50 group flex flex-col justify-between rounded-xl border p-3.5 transition-colors\"\n                >\n                  <div class=\"space-y-1\">\n                    <div class=\"flex items-center justify-between\">\n                      <span\n                        class=\"text-foreground group-hover:text-primary flex items-center gap-1.5 font-semibold transition-colors\"\n                      >\n                        {{ link.title }}\n                        <ExternalLink class=\"text-muted-foreground group-hover:text-primary size-3 transition-colors\" />\n                      </span>\n                      <Badge variant=\"outline\" class=\"font-mono text-xs\">\n                        {{ link.tag }}\n                      </Badge>\n                    </div>\n                    <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                      {{ link.description }}\n                    </p>\n                  </div>\n                  <div class=\"text-muted-foreground pt-2 font-mono text-xs\">\n                    {{ link.url }}\n                  </div>\n                </a>\n              </div>\n            </AccordionContent>\n          </AccordionItem>\n        </Accordion>\n      </CardContent>\n\n      <CardFooter class=\"bg-muted/20 flex flex-wrap items-center justify-between gap-3 border-t p-4 text-xs\">\n        <div class=\"text-muted-foreground flex items-center gap-2\">\n          <Headphones class=\"text-primary size-4\" />\n          <span>Produced by The Design Systems Guild · All rights reserved</span>\n        </div>\n\n        <div class=\"flex items-center gap-2\">\n          <Button variant=\"ghost\" size=\"sm\" class=\"h-7 text-xs\" @click=\"handleCopyLink\">\n            <Copy class=\"mr-1 size-3.5\" />\n            <span>Copy Transcript Link</span>\n          </Button>\n        </div>\n      </CardFooter>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/PodcastAudioPlayer.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/accordion.json",
    "https://uipkge.dev/r/vue/avatar.json",
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/progress.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/slider.json"
  ],
  "description": "Spotify and Apple Podcasts style audio player with 32-bar visual SVG waveform scrubber, chapter markers, playback speed controls, and show notes accordion.",
  "categories": [
    "media",
    "app",
    "audio"
  ]
}