Book a callGitHub10
Show art: a studio microphone close-up

Podcast · weekly

The Long Table

128 episodes · newest first

  1. NewThu 16 Oct48 min

    What bakers know about patience

    Ilka Ferenczi has run a night bakery for thirty years. We talk sourdough, broken sleep and why the best loaves take two days.

  2. Thu 9 Oct52 min

    A night shift at the river port

    Crane drivers, a ship's cook and the woman who checks every container seal. What a port sounds like at three in the morning.

  3. Thu 2 Oct39 min

    Learning Portuguese at sixty

    Joaquim Teles moved back to his mother's village and found he had forgotten the language. A year of flashcards, market chats and one very patient neighbour.

  4. Thu 25 Sep44 min

    The town that rebuilt its cinema

    When the last screen closed, four hundred neighbours bought it back, one seat at a time.

    Played

It is live: hover, focus and its own controls respond. Actions that would change data (approve, send, delete) are for your app to wire. The width is a real 390 px, 768 px or 1280 px box, shrunk to fit your screen.

Source
<!-- Icons: Lucide (lucide.dev), ISC licence -->
<style>
.odl-podcast-episodes { box-sizing: border-box; inline-size: 100%; max-inline-size: 46rem; margin-inline: auto; container-type: inline-size; color: var(--ds-color-text-primary); font: var(--ds-text-body-md); text-wrap: pretty; }
.odl-podcast-episodes *, .odl-podcast-episodes *::before, .odl-podcast-episodes *::after { box-sizing: border-box; }
.odl-podcast-episodes .odl-card { display: grid; gap: var(--ds-space-stack-lg); padding: var(--ds-space-inset-lg); background: var(--ds-color-surface-raised);
  border: var(--ds-border-width-default) solid var(--ds-color-border-subtle); border-radius: var(--ds-radius-container); box-shadow: var(--ds-elevation-raised); }
.odl-podcast-episodes .odl-head { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--ds-space-inline-md) var(--ds-space-inset-lg); }
.odl-podcast-episodes .odl-art { display: block; inline-size: calc(var(--ds-size-control-lg) * 2); block-size: auto; aspect-ratio: 1; object-fit: cover; border-radius: var(--ds-radius-nested); box-shadow: var(--ds-elevation-raised); background: var(--ds-color-bg-neutral-subtle); }
.odl-podcast-episodes .odl-about { display: grid; gap: var(--ds-space-stack-xs); min-inline-size: 0; }
.odl-podcast-episodes .odl-show { margin: 0; color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); letter-spacing: var(--ds-text-label-md-tracking); }
.odl-podcast-episodes h3 { margin: 0; font: var(--ds-text-title-lg); text-wrap: balance; }
.odl-podcast-episodes .odl-count { margin: 0; color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); }
.odl-podcast-episodes ol { display: grid; margin: 0; padding: 0; list-style: none; }
.odl-podcast-episodes li { display: grid; gap: var(--ds-space-stack-xs); padding-block: var(--ds-space-stack-lg); border-block-start: var(--ds-border-width-default) solid var(--ds-color-border-separator); }
.odl-podcast-episodes li:last-child { padding-block-end: 0; }
.odl-podcast-episodes .odl-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-space-stack-xs) var(--ds-space-inline-sm); margin: 0; color: var(--ds-color-text-tertiary); font: var(--ds-text-label-md); font-variant-numeric: tabular-nums; }
.odl-podcast-episodes .odl-new { padding: var(--ds-space-2) var(--ds-space-inline-sm); border-radius: var(--ds-radius-control-sm); background: var(--ds-color-bg-neutral-subtle); color: var(--ds-color-text-primary); font: var(--ds-text-label-sm); }
.odl-podcast-episodes h4 { margin: 0; font: var(--ds-text-title-sm); }
.odl-podcast-episodes .odl-desc { display: -webkit-box; margin: var(--ds-space-stack-xs) 0 0; overflow: hidden; color: var(--ds-color-text-secondary); font: var(--ds-text-body-md); -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.odl-podcast-episodes .odl-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-space-inline-sm); margin-block-start: var(--ds-space-stack-sm); }
.odl-podcast-episodes button { display: inline-flex; align-items: center; justify-content: center; gap: var(--ds-space-inline-sm); min-inline-size: max(var(--ds-size-control-md), var(--ds-size-target-min));
  min-block-size: max(var(--ds-size-control-md), var(--ds-size-target-min)); padding: 0; border: 0; border-radius: var(--ds-radius-full); background: transparent; color: var(--ds-color-text-secondary);
  font: var(--ds-text-label-lg); cursor: pointer; transition: background-color var(--ds-motion-duration-short) var(--ds-motion-easing-standard), color var(--ds-motion-duration-short) var(--ds-motion-easing-standard); }
.odl-podcast-episodes button:hover { background: var(--ds-color-bg-neutral-subtle); color: var(--ds-color-text-primary); }
.odl-podcast-episodes .odl-i { display: block; flex: none; inline-size: var(--ds-size-icon-md); block-size: var(--ds-size-icon-md); stroke-width: var(--ds-icon-stroke-md); }
.odl-podcast-episodes button:focus-visible { outline: var(--ds-focus-ring-width) solid var(--ds-color-border-focus); outline-offset: var(--ds-focus-ring-offset); }
.odl-podcast-episodes .odl-play { padding-inline: var(--ds-space-inset-md) var(--ds-space-inset-lg); border-radius: var(--ds-radius-control); background: var(--ds-color-bg-accent-subtle); color: var(--ds-color-text-accent);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.odl-podcast-episodes .odl-play:hover { background: var(--ds-color-bg-accent-subtle-hover); color: var(--ds-color-text-accent); }
.odl-podcast-episodes .odl-play .odl-i { inline-size: var(--ds-size-icon-sm); block-size: var(--ds-size-icon-sm); fill: currentColor; }
.odl-podcast-episodes .odl-play .odl-i-pause, .odl-podcast-episodes .is-playing .odl-play .odl-i-play { display: none; }
.odl-podcast-episodes .is-playing .odl-play .odl-i-pause { display: block; }
.odl-podcast-episodes .is-playing .odl-play, .odl-podcast-episodes .is-playing .odl-play:hover { background: var(--ds-color-bg-accent-bold); color: var(--ds-color-text-on-accent); }
.odl-podcast-episodes .odl-bar { flex: none; inline-size: var(--ds-space-32); block-size: var(--ds-space-4); border-radius: var(--ds-radius-full); background: var(--ds-color-border-default); overflow: hidden; }
.odl-podcast-episodes .odl-bar i { display: block; inline-size: var(--w); block-size: 100%; border-radius: var(--ds-radius-full); background: currentColor; }
.odl-podcast-episodes .is-playing .odl-bar { background: var(--ds-color-neutral-alpha-dark-6); }
.odl-podcast-episodes .odl-played { display: inline-flex; align-items: center; gap: var(--ds-space-inline-xs); margin-inline-start: var(--ds-space-inline-xs); color: var(--ds-color-text-tertiary); font: var(--ds-text-label-md); }
.odl-podcast-episodes .odl-played .odl-i { inline-size: var(--ds-size-icon-sm); block-size: var(--ds-size-icon-sm); }
.odl-podcast-episodes .odl-dl { margin-inline-start: auto; }
.odl-podcast-episodes .odl-dl .odl-ring { position: relative; display: none; inline-size: var(--ds-size-icon-md); block-size: var(--ds-size-icon-md); border-radius: var(--ds-radius-full);
  background: conic-gradient(var(--ds-color-icon-accent) var(--d, 0%), var(--ds-color-border-default) 0); }
.odl-podcast-episodes .odl-dl .odl-ring::after { content: ""; position: absolute; inset: var(--ds-border-width-emphasis); border-radius: var(--ds-radius-full); background: var(--ds-color-surface-raised); }
.odl-podcast-episodes .odl-dl .odl-ring b { position: absolute; inset: 34%; z-index: 1; border-radius: var(--ds-radius-2); background: var(--ds-color-icon-accent); }
.odl-podcast-episodes .odl-dl .is-done, .odl-podcast-episodes .odl-dl[data-state="loading"] .is-idle, .odl-podcast-episodes .odl-dl[data-state="done"] .is-idle { display: none; }
.odl-podcast-episodes .odl-dl[data-state="loading"] .odl-ring { display: block; }
.odl-podcast-episodes .odl-dl[data-state="done"] .is-done { display: block; color: var(--ds-color-text-primary); }
@container (min-width: 36rem) {
  .odl-podcast-episodes .odl-card { padding: var(--ds-space-inset-xl); }
  .odl-podcast-episodes .odl-art { inline-size: calc(var(--ds-size-control-lg) * 2.5); }
}
@media (prefers-reduced-motion: reduce) { .odl-podcast-episodes, .odl-podcast-episodes *, .odl-podcast-episodes *::before, .odl-podcast-episodes *::after { transition: none !important; animation: none !important; } }
</style>
<section class="odl-podcast-episodes" aria-labelledby="odl-pe-title">
  <div class="odl-card">
    <header class="odl-head">
      <img class="odl-art" src="https://images.unsplash.com/photo-1478737270239-2f02b77fc618?w=240&h=240&fit=crop&auto=format&q=70" alt="Show art: a studio microphone close-up" width="120" height="120" loading="lazy" decoding="async">
      <div class="odl-about">
        <p class="odl-show">Podcast · weekly</p>
        <h3 id="odl-pe-title">The Long Table</h3>
        <p class="odl-count">128 episodes · newest first</p>
      </div>
    </header>
    <ol aria-label="Episodes">
      <li>
        <p class="odl-meta"><span class="odl-new">New</span><span>Thu 16 Oct</span><span aria-hidden="true">·</span><span>48 min</span></p>
        <h4>What bakers know about patience</h4>
        <p class="odl-desc">Ilka Ferenczi has run a night bakery for thirty years. We talk sourdough, broken sleep and why the best loaves take two days.</p>
        <div class="odl-row">
          <button type="button" class="odl-play" aria-label="Play What bakers know about patience, 48 minutes"><svg class="odl-i odl-i-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="6 3 20 12 6 21 6 3"/></svg><svg class="odl-i odl-i-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="14" y="4" width="4" height="16" rx="1"/><rect x="6" y="4" width="4" height="16" rx="1"/></svg><span>48 min</span></button>
          <button type="button" class="odl-dl" data-state="idle" aria-label="Download What bakers know about patience"><svg class="odl-i odl-i-dl is-idle" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 8v8"/><path d="m8 12 4 4 4-4"/></svg><span class="odl-ring" aria-hidden="true"><b></b></span><svg class="odl-i odl-i-done is-done" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg></button>
          <button type="button" class="odl-more" aria-label="More for What bakers know about patience"><svg class="odl-i odl-i-more" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg></button>
        </div>
      </li>
      <li>
        <p class="odl-meta"><span>Thu 9 Oct</span><span aria-hidden="true">·</span><span>52 min</span></p>
        <h4>A night shift at the river port</h4>
        <p class="odl-desc">Crane drivers, a ship's cook and the woman who checks every container seal. What a port sounds like at three in the morning.</p>
        <div class="odl-row">
          <button type="button" class="odl-play" aria-label="Resume A night shift at the river port, 18 minutes left"><svg class="odl-i odl-i-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="6 3 20 12 6 21 6 3"/></svg><svg class="odl-i odl-i-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="14" y="4" width="4" height="16" rx="1"/><rect x="6" y="4" width="4" height="16" rx="1"/></svg><span class="odl-bar" aria-hidden="true"><i style="--w: 65%"></i></span><span>18 min left</span></button>
          <button type="button" class="odl-dl" data-state="done" aria-label="Downloaded. Remove download of A night shift at the river port"><svg class="odl-i odl-i-dl is-idle" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 8v8"/><path d="m8 12 4 4 4-4"/></svg><span class="odl-ring" aria-hidden="true"><b></b></span><svg class="odl-i odl-i-done is-done" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg></button>
          <button type="button" class="odl-more" aria-label="More for A night shift at the river port"><svg class="odl-i odl-i-more" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg></button>
        </div>
      </li>
      <li>
        <p class="odl-meta"><span>Thu 2 Oct</span><span aria-hidden="true">·</span><span>39 min</span></p>
        <h4>Learning Portuguese at sixty</h4>
        <p class="odl-desc">Joaquim Teles moved back to his mother's village and found he had forgotten the language. A year of flashcards, market chats and one very patient neighbour.</p>
        <div class="odl-row">
          <button type="button" class="odl-play" aria-label="Play Learning Portuguese at sixty, 39 minutes"><svg class="odl-i odl-i-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="6 3 20 12 6 21 6 3"/></svg><svg class="odl-i odl-i-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="14" y="4" width="4" height="16" rx="1"/><rect x="6" y="4" width="4" height="16" rx="1"/></svg><span>39 min</span></button>
          <button type="button" class="odl-dl" data-state="loading" data-done="60" style="--d: 60%" aria-label="Downloading, 60%. Cancel download of Learning Portuguese at sixty"><svg class="odl-i odl-i-dl is-idle" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 8v8"/><path d="m8 12 4 4 4-4"/></svg><span class="odl-ring" aria-hidden="true"><b></b></span><svg class="odl-i odl-i-done is-done" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg></button>
          <button type="button" class="odl-more" aria-label="More for Learning Portuguese at sixty"><svg class="odl-i odl-i-more" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg></button>
        </div>
      </li>
      <li>
        <p class="odl-meta"><span>Thu 25 Sep</span><span aria-hidden="true">·</span><span>44 min</span></p>
        <h4>The town that rebuilt its cinema</h4>
        <p class="odl-desc">When the last screen closed, four hundred neighbours bought it back, one seat at a time.</p>
        <div class="odl-row">
          <button type="button" class="odl-play" aria-label="Play again: The town that rebuilt its cinema, 44 minutes"><svg class="odl-i odl-i-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="6 3 20 12 6 21 6 3"/></svg><svg class="odl-i odl-i-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="14" y="4" width="4" height="16" rx="1"/><rect x="6" y="4" width="4" height="16" rx="1"/></svg><span>44 min</span></button>
          <span class="odl-played"><svg class="odl-i odl-i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>Played</span><button type="button" class="odl-dl" data-state="idle" aria-label="Download The town that rebuilt its cinema"><svg class="odl-i odl-i-dl is-idle" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 8v8"/><path d="m8 12 4 4 4-4"/></svg><span class="odl-ring" aria-hidden="true"><b></b></span><svg class="odl-i odl-i-done is-done" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg></button>
          <button type="button" class="odl-more" aria-label="More for The town that rebuilt its cinema"><svg class="odl-i odl-i-more" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg></button>
        </div>
      </li>
    </ol>
  </div>
</section>
<script>
document.querySelectorAll(".odl-podcast-episodes").forEach((root) => {
  if (root.dataset.odlReady) return; // wire once, even if the file is pasted twice
  root.dataset.odlReady = "1";
  const items = [...root.querySelectorAll("li")];
  items.forEach((li) => {
    const title = li.querySelector("h4").textContent, play = li.querySelector(".odl-play"), first = play.getAttribute("aria-label");
    play.addEventListener("click", () => {
      const on = !li.classList.contains("is-playing");
      items.forEach((o) => { o.classList.remove("is-playing"); const b = o.querySelector(".odl-play"); b.setAttribute("aria-label", b.dataset.label || b.getAttribute("aria-label")); });
      play.dataset.label = first;
      li.classList.toggle("is-playing", on);
      play.setAttribute("aria-label", on ? `Pause ${title}` : first);
    });
    const dl = li.querySelector(".odl-dl");
    let timer = null;
    const set = (state, pct) => {
      dl.dataset.state = state;
      dl.style.setProperty("--d", (pct || 0) + "%");
      dl.setAttribute("aria-label", state === "done" ? `Downloaded. Remove download of ${title}` : state === "loading" ? `Downloading, ${pct}%. Cancel download of ${title}` : `Download ${title}`);
    };
    const run = (from) => {
      let pct = from;
      clearInterval(timer);
      timer = setInterval(() => { pct = Math.min(100, pct + 4); if (pct >= 100) { clearInterval(timer); timer = null; set("done"); } else set("loading", pct); }, 900);
    };
    dl.addEventListener("click", () => {
      if (dl.dataset.state === "idle") { set("loading", 0); run(0); }
      else { clearInterval(timer); timer = null; set("idle"); }
    });
    if (dl.dataset.state === "loading") run(Number(dl.dataset.done || 0));
  });
});
</script>

More like this

ConsumerFriendly · Social

Social post

A feed post: the author's photo with a follow button, a photo, like, comment, share and save, a like count that changes, a caption that opens with "more" and the top comment.

ConsumerFriendly · Media

Track list

An album or playlist: a cover photo, title and artist, play, shuffle and save, then numbered tracks with their length, an explicit tag, a like heart and the playing one marked.

ConsumerFriendly · Social

Chat thread

A one-to-one message thread with the other person's photo: bubbles on both sides grouped into runs, a quoted reply, a heart reaction, a read receipt, a typing indicator and a composer with attach and send that adds your message.

Your kit

Nothing here yet. Add parts with Add to kit, and a look if you want the whole system.

    Parts
    0
    Files to fetch
    0 KB
    Licence
    MIT
    Total
    Free, now and later

    How do you want it?

    Your prompt

    No sign-up. Nothing leaves your browser until you paste it.

    Free