/* =============================================================================
   RADIONL — PAGES
   Layouts that belong to one route: Gemist, Programma's, Luisteren, RADIONL TV,
   Nieuws and the article body.
   ========================================================================== */

/* ============================ 1. Tabs & pickers =========================== */
/* Gemist RADIONL / Gemist RADIONL TV. */
.tabs {
  display: flex;
  gap: 12px;
  margin-bottom: 22px;
}

.tabs__tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex: 1 1 0;
  padding: 14px 18px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--color-border);
  background: var(--color-card);
  color: var(--color-navy);
  font-size: 15px;
  font-weight: 700;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.tabs__tab .icon { width: 19px; height: 19px; color: var(--color-red); }
.tabs__tab:hover { border-color: var(--color-blue); color: var(--color-blue); }

.tabs__tab[aria-current="page"] {
  background: var(--color-red);
  border-color: var(--color-red);
  color: var(--color-white);
}
.tabs__tab[aria-current="page"] .icon { color: var(--color-white); }

/* ── Day picker: 14 days, arrows either side ─────────────────────────────── */
.daypicker {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) 40px;
  gap: 10px;
  align-items: center;
  margin-bottom: 22px;
}

.daypicker__track {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding: 3px;
}
.daypicker__track::-webkit-scrollbar { display: none; }

.daypicker__day {
  flex: 1 0 74px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 11px 6px 12px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--color-border);
  background: var(--color-card);
  color: var(--color-navy);
  text-align: center;
  transition: border-color .18s ease, background-color .18s ease, color .18s ease;
}
.daypicker__day:hover { border-color: var(--color-blue); }

.daypicker__weekday {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--color-ink-soft);
}
.daypicker__number { font-size: 22px; font-weight: 700; line-height: 1.1; color: var(--color-blue); }
.daypicker__month  { font-size: 11.5px; color: var(--color-ink-soft); }
.daypicker__today  { font-size: 11px; font-weight: 700; }

.daypicker__day[aria-current="date"] {
  background: var(--color-red);
  border-color: var(--color-red);
  color: var(--color-white);
}
.daypicker__day[aria-current="date"] .daypicker__weekday,
.daypicker__day[aria-current="date"] .daypicker__number,
.daypicker__day[aria-current="date"] .daypicker__month { color: var(--color-white); }

.daypicker__arrow {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1.5px solid var(--color-border);
  background: var(--color-card);
  color: var(--color-red);
  font-size: 17px;
}
.daypicker__arrow:hover { border-color: var(--color-red); background: var(--color-ice); }
.daypicker__arrow[disabled] { opacity: .35; cursor: not-allowed; }

/* ============================== 2. Gemist ================================= */
.gemist__daytitle {
  margin: 26px 0 14px;
  font-size: 20px;
  font-weight: 700;
  color: var(--color-navy);
}

/* One programme: a fixed identity column, then its fragments. */
.showrow {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-divider);
  background: var(--color-card);
  overflow: hidden;
}

.showrow__ident {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 18px;
  border-right: 1px solid var(--color-divider);
  background: var(--gradient-surface);
}

.showrow__avatar {
  width: 62px;
  height: 62px;
  margin-bottom: 6px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--color-mist);
}
.showrow__name { font-size: 17px; font-weight: 700; color: var(--color-navy); line-height: 1.2; }
.showrow__host { font-size: 13px; color: var(--color-ink-soft); }
.showrow__time { font-size: 13.5px; font-weight: 600; color: var(--color-blue); font-variant-numeric: tabular-nums; }

.showrow__body { padding: 16px 18px 18px; min-width: 0; }

.showrow__head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
  font-size: 14px;
  font-weight: 600;
  color: var(--color-blue);
}
.showrow__head .panel__more { margin-left: auto; }

/* Audio fragments are a list, video fragments a grid — as drawn. */
.fragments { display: flex; flex-direction: column; gap: 4px; }

.fragment {
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
  padding: 9px 12px;
  border-radius: var(--radius-md);
  background: var(--color-ice);
  transition: background-color .18s ease;
}
.fragment:hover { background: var(--color-mist); }

.fragment__play {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1.5px solid var(--color-blue);
  background: var(--color-card);
  color: var(--color-blue);
  font-size: 15px;
}
.fragment__play:hover { background: var(--color-blue); color: var(--color-white); }

.fragment__title { font-size: 15px; font-weight: 600; color: var(--color-navy); line-height: 1.25; }
.fragment__time  { font-size: 12.5px; color: var(--color-ink-soft); font-variant-numeric: tabular-nums; }
.fragment__duration {
  font-size: 14px;
  font-weight: 600;
  color: var(--color-navy);
  font-variant-numeric: tabular-nums;
}

/* ============================ 3. Programma's ============================== */
.weekdays {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 20px;
}

.weekdays__day {
  flex: 1 1 96px;
  padding: 11px 12px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--color-border);
  background: var(--color-card);
  color: var(--color-navy);
  font-size: 14.5px;
  font-weight: 600;
  text-align: center;
  transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}
.weekdays__day:hover { border-color: var(--color-blue); color: var(--color-blue); }
.weekdays__day[aria-current="page"] {
  background: var(--color-red);
  border-color: var(--color-red);
  color: var(--color-white);
}

/* One row of the weekly grid: title block, presenter photo, times. */
.slot {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 218px 128px;
  align-items: stretch;
  border-radius: var(--radius-lg);
  background: var(--color-card);
  border: 1px solid var(--color-divider);
  overflow: hidden;
  transition: box-shadow .2s ease, transform .2s ease;
}
.slot:hover { box-shadow: var(--shadow-light); transform: translateY(-1px); }

/* The title remains the semantic link, while its overlay makes every visible
   part of a linked programme card one pointer target. */
.slot__title a { color: inherit; text-decoration: none; }
.slot__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: var(--radius-lg);
}
.slot__title a:focus-visible { outline: none; }
.slot__title a:focus-visible::after {
  outline: 3px solid var(--color-blue);
  outline-offset: -3px;
}
.slot--current .slot__title a:focus-visible::after {
  outline-color: var(--color-white);
}

/*
 * The design puts an audio trace at the right-hand end of every programme
 * block. It is a background rather than an <img> so it can never be read out,
 * selected or tabbed to — it says nothing the row does not already say.
 */
.slot__info {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 20px;
  background: var(--gradient-soft);
}

.slot__info::after {
  content: "";
  position: absolute;
  right: 16px;
  top: 50%;
  width: 72px;
  height: 34px;
  transform: translateY(-50%);
  background: url("/assets/theme/radionl-2026/waveform.svg") right center / contain no-repeat;
  /* Steel blue on the light rows, white on the blue ones. */
  opacity: .28;
  filter: invert(28%) sepia(28%) saturate(900%) hue-rotate(178deg);
  pointer-events: none;
}

.slot--current .slot__info::after,
.slot--nonstop .slot__info::after { opacity: .45; filter: none; }

/*
 * The programme that is on air right now.
 *
 * Solid brand blue rather than the Secondary Blue gradient: the gradient's far
 * end is #2E86FF, where white text falls to about 4.2:1. #0A5FCC is the 6:1
 * pairing the handbook certifies and looks the same at a glance.
 */
.slot--current .slot__info { background: var(--color-blue); }
.slot--current .slot__title,
.slot--current .slot__title a,
.slot--current .slot__host { color: var(--color-white); }

/* A translucent white pill would sit at ~4.3:1; a solid one is 6:1. */
.slot--current .slot__badge { background: var(--color-white); color: var(--color-blue); }

/* Kept clear of the audio trace at the right-hand edge: a glyph sitting on one
   of those bars loses about half its contrast. */
.slot__title,
.slot__host,
.slot__badge { max-width: calc(100% - 96px); }

.slot__title { font-size: 20px; font-weight: 700; color: var(--color-navy); line-height: 1.2; }
.slot__host  { font-size: 14.5px; color: var(--color-ink-soft); }

.slot__badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  align-self: flex-start;
  margin-top: 6px;
  padding: 6px 13px;
  border-radius: var(--radius-pill);
  background: var(--color-card);
  color: var(--color-blue);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.slot__badge .icon { width: 15px; height: 15px; }

/*
 * The presenter, cut out rather than cropped.
 *
 * These are the same `hero-` images the hero at the top of every page uses:
 * transparent PNGs with the background removed. That means no grey plate behind
 * them and no `cover` — cover would crop a standing figure to a slice of torso.
 * They stand on the bottom edge of the row, as they do in the hero.
 */
.slot__photo {
  position: relative;
  overflow: hidden;
  /* The card's own background continues behind the cut-out. A white plate here
     would put a hard seam down the middle of the row, which is exactly what the
     transparent PNGs are there to avoid. */
  background: var(--gradient-soft);
}

/* On air: the presenter stands on the same blue as the panel beside them, so
   the live row reads as one band — the hero at the top of the page, in little. */
.slot--current .slot__photo { background: var(--color-blue); }
.slot__photo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: bottom center;
  /* Bleeding a little past the row's padding is what makes them read as
     standing in it rather than as being pasted into a box. */
  padding-top: 6px;
}

.slot__time {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  padding: 14px;
  background: var(--color-card);
  color: var(--color-navy);
  font-size: 20px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
/* The dash between the two times. Muted, but still text — Donkergrijs rather
   than Placeholder, which is a 3.6:1 pairing. */
.slot__time span:nth-child(2) { color: var(--color-ink-soft); font-weight: 500; }

/* A block with no presenter — "Nonstop" in the design, where the trace runs
   across the whole row instead of sitting in the corner. */
.slot--nonstop { grid-template-columns: minmax(0, 1fr) 128px; }
.slot--nonstop .slot__info::after {
  right: 6%;
  width: 46%;
  height: 54px;
  background-position: center;
}
.slot--nonstop .slot__info { background: var(--color-blue); }
.slot--nonstop .slot__title { color: var(--color-white); }
.slot--nonstop .slot__badge { background: var(--color-white); color: var(--color-blue); }

/* ============================== 4. Luisteren ============================== */
.listen-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
}

.listen-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 22px;
  border-radius: var(--radius-lg);
  background: var(--gradient-surface);
  border: 1px solid var(--color-divider);
}

.listen-card__title { font-size: 22px; font-weight: 700; color: var(--color-blue); }
.listen-card__text  { color: var(--color-ink-soft); font-size: 15px; line-height: 1.65; }

.listen-card__mark {
  display: inline-grid;
  place-items: center;
  min-width: 62px;
  height: 52px;
  margin-top: auto;
  padding-inline: 14px;
  border-radius: var(--radius-md);
  background: var(--color-blue);
  color: var(--color-white);
  font-size: 22px;
  font-weight: 800;
  letter-spacing: .02em;
}
/*
 * DAB+ gets Donkerblauw rather than the Success green: white on #2DBE8A is
 * 2.4:1. Green is a status colour in this palette anyway — reserved for "it
 * worked", not for labelling a broadcast standard.
 */
.listen-card__mark--dab { background: var(--color-navy); }

/* The wide app card, with the phone mockup on the right. */
.listen-app {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 24px;
  align-items: center;
}
.listen-app--text-only { grid-template-columns: minmax(0, 1fr); }
.listen-app__art img { width: 100%; height: auto; }

.appstores { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 20px; }
.appstores .icon { width: 22px; height: 22px; }

/* The "Luisteren digitaal" heading sits beside its explanation, not above it. */
.listen-split {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: 12px 32px;
  align-items: start;
  margin-bottom: 6px;
}

/* ── Reception picker ────────────────────────────────────────────────────── */
.reception {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  padding: 16px 20px;
  border-radius: var(--radius-lg);
  background: var(--color-card);
  border: 1px solid var(--color-divider);
}

.reception__label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 16px;
  font-weight: 600;
  color: var(--color-navy);
}
.reception__label .icon { width: 22px; height: 22px; color: var(--color-blue); }

.reception__select {
  margin-left: auto;
  min-width: 190px;
  padding: 11px 16px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--color-border);
  background: var(--color-card);
  color: var(--color-navy);
  font-size: 14.5px;
  font-weight: 600;
}

.reception__result {
  flex: 1 1 100%;
  padding-top: 4px;
  color: var(--color-ink-soft);
  font-size: 15px;
}
.reception__result strong { color: var(--color-navy); }
.reception__result[hidden] { display: none; }

/* ── Provider logos ──────────────────────────────────────────────────────── */
.providers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 18px 12px;
  margin: 22px 0 18px;
}

.provider {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
}
.provider img { height: 34px; width: auto; object-fit: contain; }
.provider__name { font-size: 16px; font-weight: 700; color: var(--color-navy); }
.provider__channel {
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--color-blue);
}

/* ============================= 5. RADIONL TV ============================== */
.tvplayer {
  position: relative;
  aspect-ratio: 16 / 9;
  /*
   * The header is sticky, so scrolling the player to the top of the viewport
   * puts its first 76px underneath it — the "NU LIVE" badge and the top of the
   * picture. Reserving the header's own height, plus a little air, is what
   * makes scrollIntoView land the whole frame in view.
   */
  scroll-margin-top: calc(var(--header-height) + 14px);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-navy);
}
/* The corner logo is also an <img> inside .tvplayer, so it is excluded here —
   otherwise it stretches to fill the whole frame. */
.tvplayer video,
.tvplayer iframe,
.tvplayer > img:not(.tvplayer__logo) {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border: 0;
}

/* The badges sit on live video, which can be any colour from one second to the
   next, so they carry their own scrim rather than trusting the picture. */
.tvplayer__badges {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px;
  color: var(--color-white);
  font-size: 14px;
  font-weight: 600;
  text-shadow: 0 1px 6px rgba(18, 52, 91, .7);
  background: linear-gradient(180deg, rgba(18, 52, 91, .55) 0%, rgba(18, 52, 91, 0) 100%);
  pointer-events: none;
}

.tvplayer__logo {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  width: 120px;
  height: auto;
  filter: drop-shadow(0 2px 8px rgba(18, 52, 91, .35));
}

/* The <video> element's own fallback, for a browser that cannot render one at
   all. It sits on the player's dark ground, so it needs its own colour. */
.tvplayer video { color: var(--color-white); }

/* Shown when no stream is configured yet. */
.tvplayer__placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 14px;
  padding: 24px;
  text-align: center;
  background: var(--gradient-deep);
  color: var(--color-white);
}
.tvplayer__placeholder .icon { width: 46px; height: 46px; opacity: .8; }
.tvplayer__placeholder p { max-width: 42ch; color: rgba(255, 255, 255, .88); }

/* ============================== 6. Nieuws ================================= */
.news-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-card);
  box-shadow: var(--shadow-light);
}
.news-hero__media { position: relative; aspect-ratio: 16 / 9; background: var(--color-mist); }
.news-hero__media img { width: 100%; height: 100%; object-fit: cover; }
.news-hero__body { padding: 22px; display: flex; flex-direction: column; gap: 10px; }
.news-hero__title { font-size: clamp(23px, 2.4vw, 32px); font-weight: 700; color: var(--color-navy); }

.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 6px;
}
.pagination a, .pagination span {
  min-width: 42px;
  padding: 10px 14px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--color-border);
  background: var(--color-card);
  color: var(--color-blue);
  font-weight: 600;
  text-align: center;
}
.pagination a:hover { border-color: var(--color-blue); background: var(--color-ice); }
.pagination [aria-current="page"] {
  background: var(--color-blue);
  border-color: var(--color-blue);
  color: var(--color-white);
}

/* ======================= 7. Article and rich text ========================= */
/*
 * One measure for the whole article.
 *
 * Applying it to the header and the photograph as well as the body is what
 * turns three separately-aligned blocks into a column. Centred rather than
 * flush left, because the panel is as wide as the page allows and a line of
 * text that long is tiring to read.
 *
 * In `rem`, not `ch`. `ch` resolves against each element's *own* font size, so
 * the same "74ch" gave the body at 17.5px a column 71px wider than the header
 * at 16px — three blocks meant to share an edge, each ending somewhere else.
 * 52rem is that body measure, now stated once.
 */
.article {
  --article-measure: 52rem;
}

.article > * {
  max-width: var(--article-measure);
  margin-inline: auto;
}

/* `.prose` carries its own 74ch for bodies rendered outside an article; inside
   one, the shared measure has to win. */
.article > .prose {
  max-width: var(--article-measure);
}

.article__header {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 26px;
}

.article__cats { display: flex; flex-wrap: wrap; gap: 6px; }
.article__cats .badge:hover { text-decoration: underline; }

.article__title {
  font-size: clamp(28px, 3.2vw, 42px);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--color-navy);
}

/* The standfirst: bigger than the body and quieter than the headline, so the
   eye goes title → lead → text rather than title → text → back up. */
.article__lead {
  font-size: 19px;
  line-height: 1.6;
  color: var(--color-ink-soft);
}

.article__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding-top: 4px;
  border-top: 1px solid var(--color-divider);
  margin-top: 2px;
  color: var(--color-ink-soft);
  font-size: 14.5px;
}
.article__dot { color: var(--color-placeholder); }

/*
 * The photograph.
 *
 * A fixed 16:9 with `cover`, because the source is whatever the newsroom had —
 * a square press photo, a phone snap, a wide still — and an article page that
 * changes shape with each one does not read as a publication. Without this the
 * image sat at its natural width inside a full-width figure and left a strip of
 * --color-mist down the right-hand side, which is what the background was for.
 */
.article__media {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: 26px;
  background: var(--color-mist);
}

.article__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Faces are near the top of a press photo far more often than the bottom. */
  object-position: center 40%;
}

@media (max-width: 720px) {
  .article__lead { font-size: 17.5px; }
  .article__media { aspect-ratio: 4 / 3; margin-bottom: 20px; }
}

.prose { color: var(--color-ink); font-size: 17.5px; line-height: 1.75; max-width: 74ch; }
.prose > * + * { margin-top: 1.05em; }
.prose h2 { font-size: 26px; margin-top: 1.6em; }
.prose h3 { font-size: 21px; margin-top: 1.4em; }
.prose ul, .prose ol { padding-left: 1.3em; }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li + li { margin-top: .4em; }
.prose img, .prose figure img { border-radius: var(--radius-md); }
.prose figcaption { margin-top: .5em; font-size: 14px; color: var(--color-ink-soft); }

.prose blockquote {
  padding: 4px 0 4px 20px;
  border-left: 4px solid var(--color-red);
  font-size: 19px;
  color: var(--color-navy);
}

.prose hr { height: 1px; margin: 2em 0; border: 0; background: var(--color-border); }

/* ============================== 8. Agenda ================================= */
.event {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr);
  gap: 18px;
  align-items: center;
  padding: 16px;
  border-radius: var(--radius-lg);
  background: var(--color-card);
  border: 1px solid var(--color-divider);
}

.event__date {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 12px 6px;
  border-radius: var(--radius-md);
  background: var(--gradient-blue);
  color: var(--color-white);
}
.event__day { font-size: 27px; font-weight: 800; line-height: 1; }
.event__month { font-size: 12.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }

.event__title { font-size: 19px; font-weight: 700; color: var(--color-navy); }
.event__meta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 4px; color: var(--color-ink-soft); font-size: 14px; }
.event__meta .icon { width: 15px; height: 15px; color: var(--color-blue); }

/* ============================== 9. Playlist =============================== */
.playlist { display: flex; flex-direction: column; gap: 2px; }

.playlist__row {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr) auto;
  gap: 16px;
  align-items: center;
  padding: 10px 12px;
  border-radius: var(--radius-md);
}
.playlist__row:nth-child(odd) { background: var(--color-ice); }
.playlist__cover { width: 58px; height: 58px; border-radius: var(--radius-sm); object-fit: cover; background: var(--color-mist); }
.playlist__title { font-size: 16px; font-weight: 700; color: var(--color-navy); }
.playlist__artist { font-size: 14.5px; color: var(--color-ink-soft); }
.playlist__time { font-size: 15px; font-weight: 700; color: var(--color-blue); font-variant-numeric: tabular-nums; }

/*
 * A plugin block embedded in a body.
 *
 * Blocks are written to be page sections, where a `.panel` — white card, shadow,
 * padding — is exactly right. Dropped into an article or a page's rich text they
 * land inside that body's own card, and the panel becomes a second box drawn
 * inside the first. Sitting flush is what an embedded block should do; only the
 * spacing above and below is kept.
 */
.prose .panel {
  padding: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/* The heading of an embedded block still needs to separate it from the text
   it follows, which the card's edge used to do. */
.prose .panel + .panel { margin-top: 2em; }

/* ── RADIONL TV: live and clip in one frame ──────────────────────────────── */
/*
 * The two stages fill the same box, so switching between them does not resize
 * the page under the reader. `[hidden]` needs the explicit rule because the
 * stage is a grid item.
 */
.tvplayer__stage {
  position: absolute;
  inset: 0;
}
.tvplayer__stage[hidden] { display: none; }

.tvplayer__stage video,
.tvplayer__stage iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  background: #000;
}

/*
 * "Geluid aan", over the picture.
 *
 * Big and central because it is the one thing standing between the reader and
 * the broadcast, and because a muted stream with no visible way to unmute it
 * reads as a broken one.
 */
.tvplayer__unmute {
  position: absolute;
  left: 50%;
  bottom: 18%;
  transform: translateX(-50%);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 24px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--color-red);
  color: var(--color-white);
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: var(--shadow-medium);
}
.tvplayer__unmute:hover { background: #b3121d; }
.tvplayer__unmute[hidden] { display: none; }
.tvplayer__unmute .icon { width: 20px; height: 20px; }

/* Heading beside the way back, so the button is where the title changed. */
.tvhead {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding-top: 16px;
}
.tvhead__back { flex: none; margin: 0; }
.tvhead__back button[hidden] { display: none; }

@media (max-width: 640px) {
  .tvhead { flex-direction: column; }
  .tvhead__back { width: 100%; }
  .tvhead__back .btn { width: 100%; justify-content: center; }
}

/* ── Playlist filters ────────────────────────────────────────────────────── */
/*
 * Two dropdowns and, for anyone without JavaScript, a button. `.js` is set on
 * <html> by script.js the moment it runs, so the button is hidden by the same
 * thing that makes it unnecessary — no flash of a control that then disappears.
 */
.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px 16px;
  padding: 16px;
  margin-bottom: 20px;
  border-radius: var(--radius-lg);
  background: var(--color-ice);
  border: 1px solid var(--color-divider);
}

.filters__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1 1 190px;
}

.filters__label {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}

.filters__select {
  width: 100%;
  padding: 11px 16px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--color-border);
  background: var(--color-card);
  color: var(--color-navy);
  font-size: 15px;
  font-weight: 600;
}
.filters__select:disabled { color: var(--color-ink-soft); background: var(--color-mist); }

.filters__go { flex: none; }
.js .filters__go { display: none; }

.filters__summary {
  margin-bottom: 14px;
  color: var(--color-ink-soft);
  font-size: 14.5px;
  font-weight: 600;
}

/* ── Playlist, grouped by the hour it was played in ──────────────────────── */
.playlist__more { margin-top: 18px; }

.playlist__hour + .playlist__hour { margin-top: 22px; }

.playlist__hourlabel {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--color-divider);
  color: var(--color-navy);
  font-size: 15px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.playlist__hourlabel .icon { width: 17px; height: 17px; color: var(--color-blue); }

/* ============================== 10. DJ grid =============================== */
.dj {
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: center;
}
.dj__photo {
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-mist);
}
.dj__photo img { width: 100%; height: 100%; object-fit: cover; }
.dj__name { font-size: 17px; font-weight: 700; color: var(--color-navy); }
.dj__role { font-size: 14px; color: var(--color-ink-soft); }

/* ============================= 11. Responsive ============================= */
@media (max-width: 1120px) {
  .slot { grid-template-columns: minmax(0, 1fr) 168px 108px; }
  .listen-app { grid-template-columns: minmax(0, 1fr) 220px; }
}

@media (max-width: 860px) {
  .listen-grid { grid-template-columns: minmax(0, 1fr); }
  .listen-split { grid-template-columns: minmax(0, 1fr); }
  .listen-app { grid-template-columns: minmax(0, 1fr); }
  .listen-app__art { order: -1; max-width: 320px; margin-inline: auto; }
  .showrow { grid-template-columns: minmax(0, 1fr); }
  .showrow__ident {
    flex-direction: row;
    align-items: center;
    gap: 12px;
    border-right: 0;
    border-bottom: 1px solid var(--color-divider);
  }
  .showrow__avatar { width: 48px; height: 48px; margin-bottom: 0; }
  .showrow__time { margin-left: auto; }
}

@media (max-width: 720px) {
  .tabs { flex-direction: column; }
  .daypicker { grid-template-columns: 34px minmax(0, 1fr) 34px; }
  .daypicker__day { flex: 0 0 64px; }
  .daypicker__arrow { width: 34px; height: 34px; font-size: 15px; }

  /* The photo column costs more than it gives on a phone. */
  .slot { grid-template-columns: minmax(0, 1fr) 92px; }
  .slot__photo { display: none; }
  .slot--nonstop { grid-template-columns: minmax(0, 1fr) 92px; }
  .slot__time { font-size: 16px; }
  .slot__title { font-size: 17.5px; }

  .fragment { grid-template-columns: 38px minmax(0, 1fr) auto; gap: 10px; }
  .fragment__play { width: 38px; height: 38px; }

  .event { grid-template-columns: 72px minmax(0, 1fr); gap: 14px; }
  .event__day { font-size: 23px; }

  .playlist__row { grid-template-columns: 46px minmax(0, 1fr) auto; gap: 12px; }
  .playlist__cover { width: 46px; height: 46px; }

  .prose { font-size: 16.5px; }
}

/* ========================= 12. RADIONL TV controls ========================
   The designed control bar. Only ever visible once video-player.js has taken
   over from the browser's native controls, so a reader without JavaScript keeps
   a working player rather than a decorative one.
   ======================================================================== */
.vctl {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 3;
  padding: 26px 16px 14px;
  background: linear-gradient(180deg, rgba(18, 52, 91, 0) 0%, rgba(9, 17, 28, .82) 55%);
  opacity: 1;
  transition: opacity .25s ease;
}
.vctl[hidden] { display: none; }

/* Out of the way while playing, back on any pointer or keyboard activity. */
.tvplayer.is-idle .vctl { opacity: 0; pointer-events: none; }

.vctl__track {
  height: 4px;
  margin-bottom: 14px;
  border-radius: 2px;
  background: rgba(255, 255, 255, .32);
  cursor: pointer;
}
.vctl__fill {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: 2px;
  background: var(--color-red);
  position: relative;
}
.vctl__fill::after {
  content: "";
  position: absolute;
  right: -5px;
  top: 50%;
  width: 11px;
  height: 11px;
  transform: translateY(-50%);
  border-radius: 50%;
  background: var(--color-red);
}

.vctl__row { display: flex; align-items: center; gap: 18px; }
.vctl__spacer { flex: 1; }

.vctl__btn {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  color: var(--color-white);
  font-size: 22px;
  transition: background-color .15s ease;
}
.vctl__btn:hover { background: rgba(255, 255, 255, .16); }
.vctl__btn[hidden] { display: none; }
.vctl__btn .icon { width: 24px; height: 24px; }

/* The live indicator carries the word as well as the red dot. */
.vctl__live {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  color: var(--color-white);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.vctl__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--color-red);
}
/* Behind the live edge, so the dot is not claiming something untrue. */
.vctl__live[aria-pressed="false"] .vctl__dot { background: rgba(255, 255, 255, .45); }

.vctl__menuwrap { position: relative; }
.vctl__menuwrap[hidden] { display: none; }

.vctl__menu {
  position: absolute;
  right: 0;
  bottom: calc(100% + 10px);
  min-width: 132px;
  padding: 6px;
  border-radius: var(--radius-md);
  background: rgba(9, 17, 28, .95);
  box-shadow: var(--shadow-medium);
}
.vctl__menu[hidden] { display: none; }

.vctl__menu button {
  display: block;
  width: 100%;
  padding: 8px 12px;
  border-radius: 6px;
  color: var(--color-white);
  font-size: 14px;
  text-align: left;
}
.vctl__menu button:hover { background: rgba(255, 255, 255, .14); }
.vctl__menu button[aria-current="true"] { color: var(--color-red-bright); font-weight: 700; }

@media (max-width: 640px) {
  .vctl { padding: 22px 10px 10px; }
  .vctl__row { gap: 10px; }
  .vctl__btn { width: 30px; height: 30px; }
  .vctl__btn .icon { width: 20px; height: 20px; }
  .vctl__live { font-size: 13px; }
}
