/* =============================================================================
   RADIONL — the player bar

   The bar and the shape of the page around it. Loaded on every page while the
   live-player plugin is on, after the theme's own stylesheets, so what it says
   about `html`/`body` wins.

   The page used to be an iframe in a separate shell document; the bar was the
   shell's. It is markup in the page now — the last child of <body>, a sibling
   of the scrolling column — which is what let the article's own HTML ship in
   the response instead of behind a frame. The geometry below is unchanged: the
   same flex column, with a scrolling <div> where the <iframe> used to be.

   Colours come from the theme's tokens.css. The fallbacks after each var() are
   for a theme that declares none.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  /*
   * `dvh`, not `%`. On a phone `height: 100%` resolves against the viewport you
   * get with the address bar hidden — and since this element never scrolls,
   * the address bar never hides, so the last stripe of it is unreachable.
   */
  height: 100%;
  height: 100dvh;
  /*
   * `clip`, not `hidden`. Both stop the element scrolling, but `hidden` makes
   * it a scroll container — and the theme asks for `scrollbar-gutter: stable`,
   * so <html> then reserved a scrollbar column it can never use. That is 15px
   * off the width of every page, on top of the 15px the column below reserves
   * for the scrollbar it actually has.
   */
  overflow: clip;
}

/* Belt and braces: the gutter belongs to the element that really scrolls. */
html { scrollbar-gutter: auto; }

/* The bar's resting height per breakpoint — a floor for the row, not a number
   anything else has to agree with. See .player-bar. */
:root { --player-h: 108px; }

/*
 * Two rows: the page, then the bar. The bar's height is whatever the bar needs
 * and the column above takes the rest.
 *
 * This used to be arithmetic — the content was `calc(100% - 108px)` and the bar
 * was fixed over the bottom — and arithmetic is what broke it. Getting the
 * height right meant every one of these being true at once: the bar is exactly
 * the height the constant claims, the box above is `display: block` so the
 * newlines around it collapse away, and no line box appears above or below it.
 * On at least one real desktop they were not: it sat 36px down the page and ran
 * 72px past the top of the bar, taking the footer with it, while the same build
 * measured perfectly everywhere I could test.
 *
 * A flex column cannot get this wrong. Whitespace-only text between flex items
 * generates no boxes at all, the column is sized by what is left rather than by
 * a number written down somewhere else, and the bar is a sibling of it rather
 * than a layer on top — so it can no longer cover anything.
 */
body.has-player {
  display: flex;
  flex-direction: column;
}

.has-player .app__scroll {
  flex: 1 1 auto;
  /* Without this a flex item refuses to shrink below its content. */
  min-height: 0;
  overflow-y: auto;
  /*
   * Nothing drags sideways. The layout has no horizontal scroll by design, so
   * any that appears is a defect — an editor's long URL, a pasted embed, a
   * table wider than the phone.
   */
  overflow-x: hidden;
  /* Reserve the scrollbar's column here rather than on <html>, which no longer
     scrolls: without it, moving between a page that scrolls and one that does
     not shifts the layout sideways on every navigation. */
  scrollbar-gutter: stable;
}

/*
 * Chrome that is fixed to the viewport has to stop where the bar starts.
 *
 * Inside the old iframe the viewport *was* the area above the bar, so this came
 * for free. In one document it does not: a scrim with `inset: 0` would dim the
 * player, and the mobile menu sheet would run behind it. Both are scoped to
 * .has-player, so a site without the plugin keeps the theme's own values.
 */
.has-player .scrim { bottom: var(--player-h); }

/* Matches the breakpoint where components.css turns the nav into a sheet. */
@media (max-width: 980px) {
  .has-player .nav { max-height: calc(100dvh - var(--header-height) - var(--player-h)); }
}

/* ─── The bar ───────────────────────────────────────────────────────────── */
/*
 * A band across the full width, not a card floating over one.
 *
 * It holds the audio element the entire site is built around and it never goes
 * away, so it belongs to the frame rather than to the page — edge to edge, with
 * a top border and a shadow that falls upward onto the content it sits under.
 * The row inside still lines up with the page's own container so the logo
 * starts where the header's logo starts.
 */
.player-bar {
  flex: none;
  /* A floor, not a ceiling: if the content ever needs more, the row grows and
     the frame above it gives up exactly that much. Nothing to keep in step. */
  min-height: var(--player-h);
  padding-block: 8px;
  display: flex;
  align-items: center;
  background: var(--gradient-glass, linear-gradient(180deg, rgba(255,255,255,.95), rgba(244,247,254,.95)));
  border-top: 1px solid var(--color-divider, #e8eef8);
  box-shadow: 0 -8px 30px rgba(18, 52, 91, .10);
  backdrop-filter: saturate(1.4) blur(12px);
  animation: bar-rise .45s cubic-bezier(.2, .8, .3, 1) .2s both;
}

/* Unchanged: `transform` moves the bar without moving the layout, and `body`
   clips it on the way in, so the rise reads exactly as it did before. */
@keyframes bar-rise { from { transform: translateY(100%); } to { transform: none; } }

.player-bar__inner {
  display: flex;
  align-items: center;
  gap: 20px;
  width: min(100% - 32px, var(--container, 1400px));
  margin-inline: auto;
}

/* ─── The presenter ─── */
/*
 * The same photo, at the same size, as "Daarna op RADIONL" further along the
 * row — so the two presenters in the bar are shown the same way rather than one
 * as a cut-out standing in it and the other as a portrait in a box.
 *
 * `object-position: top center` because these are half-length photographs: a
 * centred crop of one at 52px is a square of shirt.
 */
.player-bar__dj-slot { display: contents; }

.player-bar__dj {
  width: 52px;
  height: 52px;
  flex: none;
  border-radius: 8px;
  object-fit: cover;
  object-position: top center;
  background: var(--color-mist, #dce8fa);
}

/* ─── Logo ─── */
.player-bar__logo { flex: none; display: block; }
.player-bar__logo img { display: block; width: 128px; height: auto; }

/* ─── What is on air ─── */
.player-bar__show {
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.player-bar__show-title,
.player-bar__show-host,
.player-bar__show-time {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.player-bar__show-title { font-size: 15.5px; font-weight: 700; color: var(--color-blue, #0a5fcc); }
.player-bar__show-host  { font-size: 14px; color: var(--color-navy, #12345b); }
.player-bar__show-time  { font-size: 14px; color: var(--color-navy, #12345b); font-variant-numeric: tabular-nums; }

/* ─── LIVE pill ───
   Red text on white rather than the solid red badge used inside the page: on
   this light bar the outline reads as a status, not as a second call to
   action competing with play. */
.player-bar__live {
  flex: none;
  padding: 7px 15px;
  border-radius: 999px;
  border: 1.5px solid var(--color-red, #dd0b18);
  background: #fff;
  color: var(--color-red, #dd0b18);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1;
}

/* ─── Play / pause ─── */
.player-bar__play {
  flex: none;
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--color-blue, #0a5fcc);
  color: #fff;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(10, 95, 204, .32);
  transition: background-color .18s ease, transform .12s ease, box-shadow .18s ease;
}
.player-bar__play:hover { background: var(--color-blue-hover, #084fb0); }
.player-bar__play:active { transform: scale(.95); }
.player-bar__play svg { width: 24px; height: 24px; fill: currentColor; }

/* One pulse on press, so the control feels answered before the audio starts. */
.player-bar__play.play-btn--pulse { animation: play-pulse .45s ease-out; }
@keyframes play-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(10, 95, 204, .45); }
  100% { box-shadow: 0 0 0 18px rgba(10, 95, 204, 0); }
}

/* ─── Volume ─── */
.player-bar__volume-wrap {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  max-width: 220px;
  color: var(--color-blue, #0a5fcc);
}
.player-bar__volume-icon { width: 24px; height: 24px; flex: none; }

.player-bar__volume {
  flex: 1;
  min-width: 60px;
  height: 6px;
  appearance: none;
  -webkit-appearance: none;
  border-radius: 999px;
  background: var(--color-mist, #dce8fa);
  cursor: pointer;
}
.player-bar__volume::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 17px;
  height: 17px;
  border: 0;
  border-radius: 50%;
  background: var(--color-blue, #0a5fcc);
}
.player-bar__volume::-moz-range-thumb {
  width: 17px;
  height: 17px;
  border: 0;
  border-radius: 50%;
  background: var(--color-blue, #0a5fcc);
}
/* The filled portion, painted by player.js into --volume-fill. */
.player-bar__volume {
  background-image: linear-gradient(var(--color-blue, #0a5fcc), var(--color-blue, #0a5fcc));
  background-size: var(--volume-fill, 80%) 100%;
  background-repeat: no-repeat;
}

/* ─── What is on next ─── */
.player-bar__next {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-left: auto;
}

.player-bar__next-photo {
  width: 52px;
  height: 52px;
  flex: none;
  border-radius: 8px;
  object-fit: cover;
  object-position: top center;
  background: var(--color-mist, #dce8fa);
}

.player-bar__next-text { display: flex; flex-direction: column; gap: 0; min-width: 0; }
.player-bar__next-label { font-size: 13px; color: var(--color-navy, #12345b); }
.player-bar__next-show  { font-size: 13.5px; font-weight: 700; color: var(--color-navy, #12345b); }
.player-bar__next-host  { font-size: 13px; color: var(--color-navy, #12345b); }
.player-bar__next-time  { font-size: 13px; color: var(--color-navy, #12345b); font-variant-numeric: tabular-nums; }

/* ─── The track ─── */
/*
 * Deliberately quieter than the programme block beside the play button: the
 * programme is what you tuned in for, the track is what happens to be on. The
 * artwork is what makes it readable at a glance, so it keeps its full size even
 * where the text around it is trimmed.
 */
.player-bar__track {
  flex: 0 1 auto;
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  max-width: 300px;
  padding-left: 20px;
  border-left: 1px solid var(--color-divider, #e8eef8);
}

.player-bar__track-art {
  width: 48px;
  height: 48px;
  flex: none;
  border-radius: 8px;
  object-fit: cover;
  background: var(--color-mist, #dce8fa);
}
.player-bar__track-art[hidden] { display: none; }

.player-bar__track-text { display: flex; flex-direction: column; min-width: 0; }

.player-bar__track-label,
.player-bar__track-title,
.player-bar__track-artist {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.player-bar__track-label {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--color-red, #dd0b18);
}
.player-bar__track-title  { font-size: 14.5px; font-weight: 700; color: var(--color-navy, #12345b); }
.player-bar__track-artist { font-size: 13.5px; color: var(--color-ink-soft, #4a5a6e); }

/* ─── CTA ─── */
.player-bar__cta {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 13px 22px;
  border-radius: 999px;
  border: 1.5px solid var(--color-border, #d9e2f2);
  background: #fff;
  color: var(--color-blue, #0a5fcc);
  font-size: 14.5px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: border-color .18s ease, background-color .18s ease;
}
.player-bar__cta:hover { border-color: var(--color-blue, #0a5fcc); background: var(--color-ice, #edf4ff); }
.player-bar__cta svg { width: 17px; height: 17px; }

.player-bar__play:focus-visible,
.player-bar__volume:focus-visible,
.player-bar__cta:focus-visible,
.player-bar__logo:focus-visible {
  outline: 3px solid var(--color-blue, #0a5fcc);
  outline-offset: 2px;
}

/* ─── Responsive ───
   Things drop in reverse order of usefulness. What is on next goes first: it is
   the nicest to have and the least needed. Volume goes next, because a phone has
   hardware buttons for it. What survives to the narrowest width is the logo, the
   programme name and play. */
@media (max-width: 1240px) {
  .player-bar__cta { display: none; }
}

@media (max-width: 1080px) {
  .player-bar__next-host,
  .player-bar__next-time { display: none; }
}

/* The presenter goes first: the only purely decorative thing in the row. */
@media (max-width: 760px) {
  .player-bar__dj { display: none; }
}

@media (max-width: 900px) {
  :root { --player-h: 92px; }
  .player-bar__next { display: none; }
  .player-bar__volume-wrap { max-width: 160px; margin-left: auto; }
  .player-bar__inner { gap: 14px; }
}

/*
 * Phones: the track, and a way to start it.
 *
 * The programme block goes and the track takes its place. On a screen this size
 * there is room for one of them, and the one worth keeping is the one that
 * changes every three minutes — the programme is in the hero of the page behind
 * this bar, and on /programma, whereas the track is nowhere else once the
 * sidebar has scrolled away.
 */
@media (max-width: 640px) {
  :root { --player-h: 86px; }
  .has-player #CookiebotWidget {
    top: auto !important;
    bottom: calc(var(--player-h) + 12px) !important;
  }
  .player-bar__inner { width: calc(100% - 28px); gap: 12px; }
  .player-bar__logo img { width: 92px; }
  .player-bar__volume-wrap { display: none; }
  .player-bar__live { display: none; }
  .player-bar__show { display: none; }
  .player-bar__play { width: 52px; height: 52px; margin-left: auto; }
  .player-bar__play svg { width: 20px; height: 20px; }

  .player-bar__track {
    /* Before the play button, so the row reads artwork → track → action and the
       button lands bottom-right, where a thumb already is. */
    order: -1;
    flex: 1 1 auto;
    max-width: none;
    padding-left: 0;
    border-left: 0;
  }
}

/* Smallest phones: the logo is the one thing here that says nothing new — the
   header three centimetres above it is the same logo. */
@media (max-width: 400px) {
  .player-bar__logo { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .player-bar { animation: none; }
  .player-bar__play.play-btn--pulse { animation: none; }
}
