<!-- source-hash: 882a2c614fa33ecfd7b3ef948ea40a94 -->
Brief overview of the `program-card.tsx` component — a pure presentational card for displaying podcasts, webinars, and events with two density modes.

## Key Components

### Exports

| Export | Type | Description |
|--------|------|-------------|
| `ProgramCardSkeleton` | Component | Loading placeholder supporting `default` and `sm` sizes |
| `ProgramCard<T>` | Generic Component | Main card component, typed against `BaseProgramItem` |
| `ProgramCardProps<T>` | Interface | Props contract for `ProgramCard` |

### Internal Helpers

- **`getHosts()`** — Normalizes host data from either a typed array or a JSON string
- **`MediaGallery`** — Scrollable thumbnail strip with `ImageGalleryModal` lightbox integration

### Card Sizes (`CardSize`)

| Size | Layout | Use Case |
|------|--------|----------|
| `default` | Vertical, full detail | Standalone page/feed cards |
| `sm` | Compact horizontal | Chat-inline embeds |

### Type-Aware Metadata

The card adapts displayed metadata based on `config.type`:

- **`podcast`** → Duration via `formatDurationCompact`
- **`event`** → Location name
- **`webinar`** → Start time + duration via `formatTimeWithTimezone` / `formatDurationFromRange`

## Usage Example

```typescript
import { ProgramCard } from './program-card'

// Default (vertical) layout
<ProgramCard
  config={{ type: 'podcast', labels: { singular: 'Episode' } }}
  item={episode}
  href="/podcasts/ep-42"
  size="default"
/>

// Compact inline variant (e.g., inside chat)
<ProgramCard
  config={{ type: 'webinar', labels: { singular: 'Webinar' } }}
  item={webinarItem}
  href="https://external.com/webinar"
  target="_blank"
  rel="noopener noreferrer"
  size="sm"
  placeholderUrl="https://cdn.example.com/og-fallback.png"
/>
```

> **Note:** `ProgramCard` is purely presentational — it owns no navigation logic. Callers are responsible for computing and passing `href` and `target`.