/* Feed card chrome — the episode card and everything that hangs off it.
 *
 * EXTRACTED FROM index.html's inline <style>, where it lived until /episode/
 * pages needed the same cards. It is not homepage-specific: the card is built
 * by assets/js/feeds-podcasts.js, which now renders on two surfaces — the
 * Episodes and Songs feeds, and the "Other Episodes This Community
 * Boosts" section of an episode page. One definition rather than a restatement,
 * because this is 370 lines rather than the one control show-page.css carries.
 *
 * What is in here: the range/sort controls (feed-controls.js), the card and its
 * media / body / rank / subscribe menu, the boost drawer and the inline boost
 * thread under it, the copy toast, and the two shared bits of feed furniture
 * every list uses (.ob-stats-label, .feed-placeholder).
 *
 * What is NOT: the Shows and Boosts feeds' own card variants, which build on
 * .pcast-card but only exist on the homepage, and so stay inline there.
 *
 * ⚠️ Every rule reads --accent / --accent-d / --tint. index.html supplies those
 * per feed off body[data-active-feed]; a page that links this file has to
 * supply them too (episode-page.css does it on .show-main, the same way
 * show-page.css does).
 */

/* ── Shared feed furniture ────────────────────────────────────────── */
/* "Nostr Stats:" / "Nostr Boosts:" — the two-word qualifier that
   replaced the scope-note paragraph at the head of these panels. Quiet
   enough to read as a label rather than a figure. */
.ob-stats-label { color: var(--muted); font-weight: 600; }

.feed-placeholder {
  background: var(--white);
  border: 1px dashed var(--border);
  border-radius: 12px;
  padding: 2.25rem 1.5rem;
  text-align: center;
  color: var(--muted);
}
.feed-placeholder strong {
  display: block;
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 1.1rem;
  color: var(--accent-d);
  margin-bottom: 0.35rem;
}

/* ── Podcast Boosts cards ─────────────────────────────────────────
   Episodes the community has boosted on Nostr. The card head shows the
   art, show name, the episode title (a link to the Fountain episode), a
   meta row of booster avatars / recency / sats, and a ⋮ menu of
   show-level subscribe links. A low-profile drawer bar under the head
   toggles the inline boost thread. Rendered by feeds-podcasts.js. */
/* Range buttons + language menu + sort dropdown, as mounted into the feed bar's
   slot, in that order: the two filters that narrow the ranked corpus, then the
   sort that only arranges what survives.

   ⚠️ IT WRAPS, and it has to. Four range segments (~128px), the language pill
   and the sort pill run to ~360px against the 335px a 375px phone leaves inside
   the bar's padding, so the group is wider than the line it sits on the moment a
   feed carries all three. The bar itself already wraps, which puts this group on
   its own line but cannot break it up. Wrapping to the right keeps the sort pill
   under the controls it belongs with rather than stranded against the menus.
   The ranked feeds are the ones that reach three; the Boosts note feed carries
   two and never wraps. */
.pcast-controls {
  display: flex; align-items: center; gap: 0.5rem;
  flex-wrap: wrap; justify-content: flex-end;
  flex-shrink: 0; align-self: center;
}
/* 1W / 1M / All — deliberately borderless and touching: the faint tint on
   the selected segment is the only chrome, and it's what reveals that the
   neighbours are buttons with the same footprint. */
.pcast-range { display: flex; flex-shrink: 0; }
.pcast-range-btn {
  /* Near-square: the min-width and the vertical padding are tuned to land
     the box at roughly 32x30, so the row reads as one tight block. Four
     segments on the ranked feeds (1W/1M/1Y/All), three on the Boosts note
     feed — ~128px either way, which still leaves the sort pill beside it on
     a 375px phone once the group has wrapped onto its own line. */
  min-width: 2rem; padding: 0.5rem 0.35rem;
  font: inherit; font-size: 0.72rem; font-weight: 700; line-height: 1.2;
  color: var(--muted); background: transparent;
  border: none; border-radius: 6px; cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
/* Tint of the active feed's accent. The solid --tint is the fallback for
   engines without color-mix; it lands in the same place visually. */
.pcast-range-btn:hover {
  color: var(--accent-d);
  background: var(--tint);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
.pcast-range-btn.is-active {
  color: var(--accent-d);
  background: var(--tint);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}

.pcast-sort { position: relative; flex-shrink: 0; align-self: center; }
.pcast-sort-btn {
  display: inline-flex; align-items: center; gap: 0.25rem;
  padding: 0.3rem 0.7rem; font: inherit; font-size: 0.78rem; font-weight: 600;
  color: var(--text); background: var(--white);
  border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
  white-space: nowrap; transition: border-color 0.12s, background 0.12s;
}
.pcast-sort-btn:hover { border-color: var(--accent); background: var(--tint); }
.pcast-sort-tag { color: var(--muted); }
.pcast-sort-cur { color: var(--accent-d); font-weight: 700; }
.pcast-sort-caret { color: var(--muted); font-size: 0.85em; }
.pcast-sort-menu {
  position: absolute; top: calc(100% + 4px); right: 0; z-index: 6;
  min-width: 175px; background: var(--white);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.18); padding: 0.35rem;
}
.pcast-sort-menu[hidden] { display: none; }
.pcast-sort-item {
  display: block; width: 100%; text-align: left;
  padding: 0.45rem 0.6rem; font: inherit; font-size: 0.85rem; font-weight: 600;
  color: var(--text); background: transparent; border: none; border-radius: 6px; cursor: pointer;
}
.pcast-sort-item:hover { background: var(--tint); color: var(--accent-d); }
.pcast-sort-item.is-active { color: var(--accent-d); background: var(--tint); }
.pcast-sort-item.is-active::after { content: ' ✓'; float: right; }
/* The language menu is the sort pill exactly, with one difference: its LENGTH IS
   DATA. The index describes 19 languages on the podcast side and gains a row the
   first time anyone boosts a show in a new one, where every sort menu on the
   site is a fixed five or six. Twenty rows is ~600px, which overruns a phone
   entirely, so this one scrolls. A floor on the menu would have been the other
   fix and is deliberately not taken — ten of those languages are a single show,
   and hiding them makes those shows unfindable by the axis the control is for. */
.pcast-lang .pcast-sort-menu {
  max-height: min(60vh, 21rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* The colon is CSS rather than part of the tag text, so the narrow-viewport
   rule below can drop it and leave "Language" instead of "Language:". */
.pcast-lang .pcast-sort-tag::after { content: ':'; }
/* The subtag form ("DE"), for the phone rule below. Off entirely on desktop,
   where the pill has room for the language's name. */
.pcast-lang-short { display: none; }

/* ── The bar on a phone ──
   Three controls do not fit on a 375px screen: the range is 128px, and
   "Language: All ▾" and "Sort: Most boosts ▾" are 124px and 153px against the
   335px inside the bar's padding. The group wrapped to a second line, which put
   the sticky chrome at three rows and 200px with the nav — 30% of a 667px
   screen before a single card.

   The TAGS are the fat, and they say what the value already implies. Dropping
   them here takes the group to ~330px and the bar back to two rows, with every
   active filter still legible, which is the whole reason these are sticky
   rather than in the panel. Desktop is untouched: there is room for the tags
   there, and "Sort: X ▾" is a pattern the detail pages share. */
@media (max-width: 640px) {
  .pcast-sort:not(.pcast-lang) .pcast-sort-tag { display: none; }

  /* ⚠️ THE LANGUAGE PILL IS THE OTHER WAY AROUND WHEN NOTHING IS PICKED. A bare
     "All" would sit inches from the range's own All button and mean something
     entirely different, so the unset pill names its AXIS and the picked one
     names its VALUE — a language is self-identifying and needs no tag. */
  .pcast-lang[data-lang="all"] .pcast-sort-cur { display: none; }
  .pcast-lang[data-lang="all"] .pcast-sort-tag::after { content: none; }
  .pcast-lang[data-lang="all"] .pcast-sort-tag { color: var(--accent-d); font-weight: 700; }
  .pcast-lang:not([data-lang="all"]) .pcast-sort-tag { display: none; }

  /* ⚠️ AND A PICKED LANGUAGE SHOWS ITS SUBTAG, WHICH IS WHAT ACTUALLY MAKES
     THREE CONTROLS FIT. With the name in the pill only 58 of the 120 sort x
     language combinations fit on one line: "Norwegian Bokmål" is 141px and
     "Recently boosted" another 141px, against 335px inside the bar. "DE" is
     48px and takes every picked state under the line. The name is still the
     menu row it was picked from, and the button's tooltip. */
  .pcast-lang:not([data-lang="all"]) .pcast-sort-cur { display: none; }
  .pcast-lang:not([data-lang="all"]) .pcast-lang-short {
    display: inline; color: var(--accent-d); font-weight: 700;
  }

  /* The last ~15px, taken off the padding rather than the type: shrinking the
     label is what makes a control look like a different control. */
  .pcast-range-btn { min-width: 1.85rem; }
  .pcast-sort-btn { padding-left: 0.55rem; padding-right: 0.55rem; }
}

/* Events type dropdown — squarer corners than the podcast sort pill. */
.feed-type-sort .pcast-sort-btn { border-radius: 7px; }
.feed-type-sort .pcast-sort-menu { border-radius: 8px; }

/* minmax(0,1fr) — without the 0 min, a grid item's min-width is its
   content, so long shownotes/URLs would blow the column (and card) far
   wider than the container. */
.pcast-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.6rem; }
.pcast-card {
  min-width: 0;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
  /* No overflow:hidden here — it would clip the ⋮ subscribe dropdown when
     it opens past the bottom of the card. The media clips its own corners,
     and the drawer rounds its bottom corners when it's the last child. */
  transition: box-shadow 0.12s, border-color 0.12s;
}
.pcast-card:hover { box-shadow: 0 6px 18px rgba(0,0,0,0.08); }
/* `.is-open` has no emitter any more — the drawer is a <details> and the open
   state is read off it directly, further down this file. Kept because a reader
   holding a cached page that still adds the class gets the same highlight. */
.pcast-card.is-open { border-color: var(--accent); box-shadow: 0 6px 18px rgba(0,0,0,0.10); }
.pcast-card-head {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  /* tight right padding so the ⋮ menu hugs the corner */
  padding: 0.7rem 0.4rem 0.5rem 0.7rem;
}
.pcast-card-media {
  display: block; /* also correct when the media is an <a> link */
  flex-shrink: 0;
  width: 68px; height: 68px;
  border-radius: 8px; overflow: hidden;
  background: var(--tint);
}
a.pcast-card-media { cursor: pointer; }
/* --podcasts-accent until now, which was never defined — the token has
   always been --pg-/--eg-accent, so the whole declaration was invalid at
   computed-value time and the hover did nothing. --accent is the active
   feed's, which is what it was reaching for. */
a.pcast-card-media:hover { box-shadow: 0 0 0 2px var(--accent); }
.pcast-card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pcast-card-media--none {
  display: flex; align-items: center; justify-content: center;
  font-size: 1.7rem; opacity: 0.55;
}
.pcast-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; justify-content: center; }

/* The compact layout's right rail — the boost pill, and nothing else.
 *
 * `align-self: stretch` makes the rail as tall as the card head whatever drives
 * that height (the artwork on a short card, the body on a long one), and
 * `align-items: center` then puts the pill at its vertical middle. That is the
 * whole trick: the pill used to be the last thing on the last line of the body,
 * so on a card with no player it sat against the drawer's top edge.
 *
 * ⚠️ IT OCCUPIES THE ⋮ SUBSCRIBE MENU'S EDGE, which is why the compact layout
 * drops that menu rather than keeping both. A menu pinned to the top of the head
 * and a pill centred in it overlap on a short card, and a card in this container
 * is short by design. See CARD_PARTS in episode-card.js.
 *
 * The pill keeps its own `margin-left: auto` from theme.css, which is a no-op in
 * a one-child row and correct if anything is ever added beside it. */
.pcast-card-rail {
  display: flex;
  align-items: center;
  align-self: stretch;
  flex-shrink: 0;
  padding-left: 0.2rem;
}
.pcast-show {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.02em;
  text-transform: uppercase; color: var(--accent-d);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
a.pcast-show-link { text-decoration: none; cursor: pointer; display: block; }
a.pcast-show-link:hover { text-decoration: underline; }
.pcast-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 0.98rem; font-weight: 700; line-height: 1.25; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pcast-meta {
  display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap;
  margin-top: 0.25rem; font-size: 0.78rem; color: var(--muted);
}

/* Shownotes teaser (first ~2 lines) + a links row ("see full description"
   and a compact "Listen on Fountain") beneath it. */
.pcast-desc {
  margin: 0.35rem 0 0; font-size: 0.82rem; line-height: 1.4; color: var(--muted);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  overflow-wrap: anywhere; word-break: break-word;
}
.pcast-links { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin-top: 0.35rem; }
/* The episode card's "Nostr Stats:" line, directly under the Fountain
   link. Inherits .pcast-meta; tabular figures so the counts line up
   down a column of cards. */
.pcast-nstats { font-variant-numeric: tabular-nums; margin-top: 0.35rem; }
.pcast-fountain-link {
  font-size: 0.78rem; font-weight: 700; color: var(--accent-d); text-decoration: none; white-space: nowrap;
}
.pcast-fountain-link:hover { text-decoration: underline; }

/* The episode page's hero player (episode-page.css scopes it under
   .ep-player-row). The feed card carried one too, in a `.pcast-player-row`,
   until 2026-09-03; see the note in episode-card.js. */
.pcast-player { width: 100%; display: block; }

/* The card action row (a pill Boost button beside "↓ Download MP3") is
   gone. Boost is now the .ob-boost-pill at the right end of the Nostr
   Stats line — defined in theme.css, since the show pages use the same
   one — and the download duplicated what the audio element's own ⋮ menu
   already offers. That row cost a full band of card height for two
   controls, which is the whole argument on a phone. */
.pcast-dot { opacity: 0.6; }
.pcast-sats { font-weight: 700; color: var(--accent-d); white-space: nowrap; }
.pcast-bolt { font-size: 0.85em; }

/* Avatars — stacked on cards, single on modal rows. Size via --pcast-av. */
.pcast-avatars { display: inline-flex; align-items: center; }
.pcast-avatars .pcast-avatar + .pcast-avatar { margin-left: -8px; }
.pcast-avatar {
  width: var(--pcast-av, 26px); height: var(--pcast-av, 26px);
  border-radius: 50%; object-fit: cover; flex-shrink: 0;
  border: 2px solid var(--white); background: var(--tint);
  box-sizing: border-box;
}
.pcast-avatar--none {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--cream-d); color: var(--muted);
  font-size: 0.6rem; font-weight: 700;
}
.pcast-avatar.is-interactive { cursor: pointer; }
.pcast-avatar.is-interactive:hover { border-color: var(--accent); }
.pcast-avatar.is-interactive:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* The link wrapper an interactive avatar sits in since those faces started
   pointing at /booster/<npub>. It carries the href and nothing else: the
   `.pcast-avatar` inside it is still what has the size, the border and the
   radius, so this must add no box of its own. The hover is delegated inward
   because the wrapper is the element the pointer is actually over. */
.pcast-avatar-link { display: inline-flex; flex-shrink: 0; line-height: 0; }
.pcast-avatar-link:hover .pcast-avatar { border-color: var(--accent); }

.pcast-more-wrap { display: flex; justify-content: center; margin-top: 1.1rem; }
.pcast-more-group { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; }
.pcast-more-count { font-size: 0.75rem; color: var(--muted); }
.pcast-showmore {
  padding: 0.5rem 1.4rem;
  font: inherit; font-size: 0.85rem; font-weight: 700;
  color: var(--accent-d); background: var(--white);
  border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.pcast-showmore:hover { background: var(--tint); border-color: var(--accent); }

/* Episode title links out to the Fountain episode. */
.pcast-title-link { color: var(--text); text-decoration: none; }
.pcast-title-link:hover { color: var(--accent-d); text-decoration: underline; }

/* Media column: episode art with the air date tucked directly beneath it. */
.pcast-media-col { display: flex; flex-direction: column; align-items: center; gap: 0.25rem; flex-shrink: 0; }
.pcast-card-aired { font-size: 0.66rem; color: var(--muted); white-space: nowrap; text-align: center; }

/* ⋮ subscribe menu on the card head (top-right) — show-level app links. */
.pcast-cardmenu { position: relative; flex-shrink: 0; align-self: flex-start; }
.pcast-cardmenu-btn {
  width: 30px; height: 30px; border-radius: 50%;
  border: none; background: transparent; color: var(--muted); cursor: pointer;
  font-size: 1.2rem; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.pcast-cardmenu-btn:hover { background: var(--tint); color: var(--text); }
.pcast-cardmenu-menu {
  position: absolute; top: 34px; right: 0; z-index: 6;
  min-width: 190px;
  background: var(--white);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.18);
  padding: 0.35rem;
}
.pcast-cardmenu-menu[hidden] { display: none; }
.pcast-cardmenu-label {
  padding: 0.4rem 0.6rem 0.25rem;
  font-size: 0.66rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--muted);
}
.pcast-cardmenu-item {
  display: block; padding: 0.45rem 0.6rem;
  font-size: 0.85rem; font-weight: 600; color: var(--text);
  text-decoration: none; border-radius: 6px;
}
.pcast-cardmenu-item:hover { background: var(--tint); color: var(--accent-d); }

/* Rank badge — only rendered on the quantitative sorts (most boosters /
   boosts / sats), where position is a ranking rather than chronology.
   Tabular figures keep the column steady from 1 to 999. */
/* ⚠️ THE MIN-WIDTH IS AN ALIGNMENT FLOOR, NOT DECORATION. Each card is its own
   flex row, so a wider numeral pushes that card's artwork right and the run of
   cards stops lining up. `T` costs roughly one character, which is what took
   this from 1.6rem: it holds "T99" and "999" at this size, covering what a
   reader sees before they have paged deep enough for four digits. A rank wider
   than the floor still grows the column — the floor buys alignment for the
   common case rather than clipping the uncommon one. */
.pcast-rank {
  flex: 0 0 auto;
  align-self: flex-start;
  min-width: 2.3rem;
  padding-top: 0.15rem;
  font-family: 'Playfair Display', Georgia, serif;
  font-weight: 700;
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
  color: var(--accent);
  text-align: right;
}
@media (max-width: 640px) {
  .pcast-rank { min-width: 1.8rem; font-size: 0.95rem; }
}

/* ── Boost drawer — a low-profile full-width toggle under the head. ──

   ⚠️ IT IS A <summary> INSIDE A <details> NOW, not a <button> beside a hidden
   <div>. The boost notes it opens onto are FACTS and are server-rendered into
   the document, so a control only JavaScript could open would leave them
   unreachable — which is the whole shape the rendering rule exists to remove.
   <details> opens on its own, and it is the same idiom .ep-drawer uses on /show
   and /episode, so a reader who has opened one has already learned this one.

   The classes, the children and every declaration below are unchanged; the two
   rules that follow are the entire delta. A <summary> paints a disclosure
   triangle by default, which would sit beside the caret this design already
   draws — `list-style` kills it everywhere except WebKit, which needs the
   pseudo-element. */
.pcast-card-details > .pcast-drawer { list-style: none; }
.pcast-card-details > .pcast-drawer::-webkit-details-marker { display: none; }
.pcast-drawer {
  display: flex; align-items: center; gap: 0.4rem; width: 100%;
  padding: 0.45rem 0.7rem 0.5rem;
  font: inherit; font-size: 0.78rem; font-weight: 600;
  color: var(--muted); background: transparent;
  border: none; border-top: 1px solid var(--border);
  cursor: pointer; text-align: left;
  transition: color 0.12s, background 0.12s;
}
.pcast-drawer:hover { color: var(--accent-d); background: rgba(0,0,0,0.02); }
.pcast-drawer:last-child { border-radius: 0 0 10px 10px; }
.pcast-drawer-caret { font-size: 0.85em; flex-shrink: 0; transition: transform 0.18s; }
.pcast-drawer-label { flex-shrink: 0; }
/* Booster faces + total sats, sitting just after the "N boosts" label.
   The faces are the only part of the bar allowed to shrink: the label and
   the sats total are the information, the stack is decoration, and it is
   the one child whose width grows with the data. Without this the row
   overflows the card on a heavily boosted episode and the whole feed
   column gets a horizontal scrollbar. MAX_FACES in feeds-podcasts.js caps
   the stack so the clip below is insurance rather than the usual case. */
.pcast-drawer-meta { display: inline-flex; align-items: center; gap: 0.5rem; min-width: 0; }
.pcast-drawer-meta .pcast-avatars { min-width: 0; overflow: hidden; }
.pcast-drawer-meta .pcast-sats { flex-shrink: 0; font-weight: 700; color: var(--accent-d); white-space: nowrap; }
/* Narrow viewports have room for far fewer faces than the DOM cap. The
   drawer label states the real booster count, so trimming the stack loses
   nothing. */
@media (max-width: 560px) {
  .pcast-avatars .pcast-avatar:nth-child(n+6) { display: none; }
}
/* Open state, off the <details> rather than off a class JavaScript added. The
   :has() is what lets the CARD react to a descendant opening; browsers without
   it lose a border highlight and nothing else, which is why the caret rotation
   is written as a plain descendant rule rather than folded into it. */
.pcast-card-details[open] > .pcast-drawer > .pcast-drawer-caret { transform: rotate(180deg); }
.pcast-card:has(> .pcast-card-details[open]) {
  border-color: var(--accent);
  box-shadow: 0 6px 18px rgba(0,0,0,0.10);
}

/* "Hide boosts" control at the bottom of a card's thread. */
.pcast-drawer-close {
  justify-self: start;
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.35rem 0;
  font: inherit; font-size: 0.8rem; font-weight: 700;
  color: var(--muted); background: transparent; border: none; cursor: pointer;
}
.pcast-drawer-close:hover { text-decoration: underline; color: var(--accent-d); }

/* Thread footer: "see all boosts" (Boost Me Bitch) on the left, hide on the right. */
.pcast-details-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; flex-wrap: wrap;
}
.pcast-seeall {
  font-size: 0.8rem; font-weight: 700; color: var(--accent-d); text-decoration: none;
}
.pcast-seeall:hover { text-decoration: underline; }

/* ── Inline boost details — indented under the card like a child/thread,
   marked by a left accent rule and kept tight vertically. ── */
.pcast-details {
  display: grid; gap: 0.6rem;
  margin: 0 0.7rem 0.85rem 3.3rem;
  padding: 0.15rem 0 0.15rem 0.95rem;
  border-left: 2px solid var(--accent);
}
.pcast-details[hidden] { display: none; }
/* A lazy drawer's one line while its rows are fetched, or after the fetch
   failed (episode-card-actions.js#fillLazyDrawer). Set like the row's timestamp
   so it reads as part of the thread and not as a banner over it. */
.pcast-boosts-status { font-size: 0.8rem; color: var(--muted); padding: 0.1rem 0; }
.pcast-boost { border-top: 1px solid var(--border); padding-top: 0.6rem; }
.pcast-boost:first-child { border-top: none; padding-top: 0; }
.pcast-boost-head { display: flex; align-items: center; gap: 0.55rem; }
.pcast-boost-who { min-width: 0; flex: 1; display: flex; flex-direction: column; }
/* Was a <button> that copied the npub; now an <a> to /booster/<npub>. The
   declarations below were already neutralising the button chrome, so they carry
   over to an anchor unchanged — `text-decoration: none` is the one addition,
   since the underline is meant to arrive on hover and not before. */
.pcast-boost-name {
  align-self: flex-start;
  font: inherit; font-size: 0.9rem; font-weight: 700; color: var(--text);
  background: transparent; border: none; padding: 0; cursor: pointer;
  text-decoration: none;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pcast-boost-name:hover { color: var(--accent-d); text-decoration: underline; }
.pcast-boost-name:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pcast-boost-when { font-size: 0.74rem; color: var(--muted); }
.pcast-boost-sats { flex-shrink: 0; font-size: 0.88rem; font-weight: 700; color: var(--accent-d); white-space: nowrap; }
.pcast-boost-msg {
  margin-top: 0.3rem; font-size: 0.88rem; line-height: 1.35; color: var(--text);
  white-space: pre-wrap; word-break: break-word;
}
.pcast-boost-msg a { color: var(--accent-d); }
/* Shared reply/repost/like/zap bar (boost-actions.css) under each comment —
   scoped-down here: no divider line, smaller + tighter than the boosts page. */
.pcast-boost .note-actions {
  margin-top: 0.15rem; padding-top: 0; border-top: none; gap: 0.05rem;
}
.pcast-boost .note-actions button { font-size: 0.72rem; padding: 0.2rem 0.4rem; gap: 0.25rem; }
.pcast-boost .note-actions .lb-icon { font-size: 0.82rem; }

/* Per-boost ⋮ overflow menu */
.pcast-more { position: relative; flex-shrink: 0; }
.pcast-more-btn {
  width: 30px; height: 30px; border-radius: 50%;
  border: none; background: transparent; color: var(--muted); cursor: pointer;
  font-size: 1.1rem; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.pcast-more-btn:hover { background: var(--tint); color: var(--text); }
.pcast-more-menu {
  position: absolute; top: 34px; right: 0; z-index: 5;
  min-width: 160px;
  background: var(--white);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.18);
  padding: 0.35rem;
}
.pcast-more-menu[hidden] { display: none; }
.pcast-more-item {
  display: block; width: 100%; box-sizing: border-box; text-align: left;
  padding: 0.45rem 0.6rem; font: inherit; font-size: 0.85rem; color: var(--text);
  background: transparent; border: none; border-radius: 6px; cursor: pointer;
}
.pcast-more-item:hover { background: var(--tint); }

/* Copy toast */
.pcast-toast {
  position: fixed; left: 50%; bottom: 1.5rem; transform: translate(-50%, 1rem);
  z-index: 1100;
  background: var(--text, #1e160a); color: #fff;
  padding: 0.55rem 1.1rem; border-radius: 999px;
  font-size: 0.85rem; font-weight: 600;
  box-shadow: 0 8px 24px rgba(0,0,0,0.25);
  opacity: 0; pointer-events: none;
  transition: opacity 0.18s, transform 0.18s;
}
.pcast-toast.is-visible { opacity: 1; transform: translate(-50%, 0); }
.pcast-toast.is-error { background: #9b2c2c; }

/* ── Dark mode ─────────────────────────────────────────────────────
   The toast inverts with the page: its fill is var(--text), which is
   light in dark mode, so the hardcoded white text flips to ink. The
   error toast keeps its dark red fill and therefore keeps white. */
:root[data-theme="dark"] .pcast-toast { color: #10202c; }
:root[data-theme="dark"] .pcast-toast.is-error { color: #fff; }
