/* =============================================================================
   RADIONL — COMPONENTS
   Header, buttons, badges, hero, cards, the live rail and the footer.

   Colour rules from the handbook, applied consistently below:
     header / nav   white surface, blue text, red for the active item
     footer         Deep Blue gradient, white text
     primary CTA    red on white text
     secondary CTA  blue on white text
     card           white surface, antraciet text, blue accents
     hero           Primary Brand gradient, white text, red LIVE badge
   ========================================================================== */

/* ============================== 1. Buttons ================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 13px 24px;
  border-radius: var(--radius-pill);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.1;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease, box-shadow .18s ease,
              border-color .18s ease, transform .18s ease;
}
.btn .icon { width: 1.15em; height: 1.15em; }
.btn:active { transform: translateY(1px); }

/* Primary — reserved for "listen now" and equivalents. */
.btn--red {
  background: var(--color-red);
  color: var(--color-white);
}
.btn--red:hover { background: #c30a15; box-shadow: var(--glow-red); }

/* Secondary. */
.btn--blue {
  background: var(--color-blue);
  color: var(--color-white);
}
.btn--blue:hover { background: var(--color-blue-hover); box-shadow: var(--glow-blue); }
.btn--blue:active { background: var(--color-blue-active); }

/* Ghost — blue text, blue hairline. Used on light surfaces. */
.btn--ghost {
  background: var(--color-card);
  color: var(--color-blue);
  border: 1.5px solid var(--color-border);
}
.btn--ghost:hover {
  border-color: var(--color-blue);
  background: var(--color-ice);
}

/*
 * Ghost on the hero gradient.
 *
 * Carries a faint dark fill rather than being fully transparent: the hero's
 * gradient lightens towards its bottom-right, and an outline-only button lands
 * on the light end at about 4:1 — under AA. The fill costs nothing visually and
 * buys the label its contrast wherever the button sits.
 */
.btn--on-dark {
  background: rgba(18, 52, 91, .26);
  color: var(--color-white);
  border: 1.5px solid rgba(255, 255, 255, .55);
}
.btn--on-dark:hover {
  border-color: var(--color-white);
  background: rgba(255, 255, 255, .14);
}

.btn--sm { padding: 9px 16px; font-size: 13.5px; }
.btn--lg { padding: 16px 30px; font-size: 16.5px; }
.btn--block { display: flex; width: 100%; }

/* Circular icon-only button. */
.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1.5px solid var(--color-border);
  background: var(--color-card);
  color: var(--color-blue);
  font-size: 19px;
  transition: border-color .18s ease, background-color .18s ease, box-shadow .18s ease;
}
.icon-btn:hover { border-color: var(--color-blue); background: var(--color-ice); }
.icon-btn:focus-visible { box-shadow: var(--glow-blue); }

/* ============================== 2. Badges ================================= */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1;
}

/*
 * LIVE always carries the word as well as the colour.
 *
 * Solid brand red rather than the Live gradient: white on #DD0B18 is the 5.1:1
 * pairing the handbook itself certifies, while the gradient's far end (#F33644)
 * drops to 3.4:1 — fine behind a headline, not behind an 12px label. The
 * gradient stays available as --gradient-live for larger surfaces.
 */
.badge--live {
  background: var(--color-red);
  color: var(--color-white);
}
.badge--blue { background: var(--color-blue); color: var(--color-white); }
.badge--white { background: var(--color-white); color: var(--color-blue); }
.badge--soft { background: var(--color-ice); color: var(--color-blue); }

/* The eyebrow above a panel heading on the Luisteren page. */
.eyebrow {
  display: inline-block;
  padding: 6px 13px;
  border-radius: var(--radius-pill);
  background: var(--color-navy);
  color: var(--color-white);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* Duration chip in the corner of a video thumbnail. */
.duration {
  position: absolute;
  right: 10px;
  bottom: 10px;
  padding: 4px 8px;
  border-radius: 6px;
  background: rgba(18, 52, 91, .82);
  color: var(--color-white);
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* On the TV page it sits bottom-left, opposite the centred play button. */
.duration--left { right: auto; left: 10px; }

/* ============================== 3. Header ================================= */
.site-header {
  position: sticky;
  top: 0;
  z-index: 120;
  background: var(--gradient-glass);
  backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--color-divider);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 22px;
  min-height: var(--header-height);
}

.logo { flex: none; display: block; }
.logo img { width: 168px; height: auto; }

.nav { flex: 1; min-width: 0; }

.nav__list {
  display: flex;
  align-items: center;
  gap: 26px;
}

.nav__item { position: relative; }

.nav__item > a {
  position: relative;
  display: block;
  padding: 8px 2px;
  color: var(--color-blue);
  font-size: 15.5px;
  font-weight: 600;
  white-space: nowrap;
  transition: color .16s ease;
}
.nav__item > a:hover { color: var(--color-blue-hover); }

/*
 * Active state: red text plus a red underline. Two signals rather than one,
 * so it does not depend on distinguishing red from blue.
 */
.nav__item > a[aria-current="page"] { color: var(--color-red); }
.nav__item > a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 3px;
  border-radius: 2px;
  background: var(--color-red);
}

/* Dropdowns, for menus deeper than the design's six items. */
.nav__submenu {
  position: absolute;
  top: calc(100% + 10px);
  left: -14px;
  min-width: 230px;
  padding: 8px;
  border-radius: var(--radius-lg);
  background: var(--color-card);
  border: 1px solid var(--color-divider);
  box-shadow: var(--shadow-medium);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-6px);
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
}
.nav__item--parent:hover > .nav__submenu,
.nav__item--parent:focus-within > .nav__submenu {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
}
.nav__submenu a {
  display: block;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  color: var(--color-navy);
  font-size: 14.5px;
  font-weight: 600;
}
.nav__submenu a:hover { background: var(--color-ice); color: var(--color-blue); }

.site-header__actions {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
}

.icon-btn--menu { display: none; }

/* ============================== 4. Hero =================================== */
/*
 * The Primary Brand gradient, with the station's line-art doodles at low
 * opacity behind the copy. The presenter cut-out sits between the two columns.
 *
 * ── Why the copy sits on overlays ──
 * The official gradient ends at #8FC5FF, and white on that is 1.8:1 — nowhere
 * near the 4.5:1 the handbook's own accessibility page requires, and no choice
 * of stops fixes it, because 12px white text needs a background darker than
 * roughly #2472DD. So the gradient stays exactly as specified and the text is
 * lifted onto the handbook's own overlays instead:
 *
 *   left column     a soft dark wash that fades out before the presenter
 *   schedule column the Glass Surface treatment — a translucent dark panel,
 *                   which also replaces the hairline divider in the design
 *
 * Both are verified by sampling the rendered background behind every text box;
 * the tightest measured pair is ~4.7:1.
 *
 * Layer order, all beneath the content:
 *   element background  the Primary Brand gradient
 *   ::before  z-index -3  line-art doodles
 *   ::after   z-index -2  the left-hand wash
 *   portrait  z-index -1  the presenter, above the wash so they stay bright
 */
.hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 268px;
  gap: 24px;
  min-height: 470px;
  padding: 30px;
  border-radius: var(--radius-xl);
  background: var(--gradient-brand);
  color: var(--color-white);
  overflow: hidden;
  isolation: isolate;
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url("/assets/theme/radionl-2026/doodles.svg") center / cover no-repeat;
  /* Visible as texture, never as something competing with the copy. The scrim
     above this layer damps it further where the text actually sits. */
  opacity: .38;
  z-index: -3;
  pointer-events: none;
}

.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  /*
   * One smooth wash from the left, gone by the time it reaches the presenter.
   * Angled rather than horizontal so it follows the brand gradient's own
   * diagonal instead of cutting across it.
   */
  background: linear-gradient(
    108deg,
    rgba(18, 52, 91, .40) 0%,
    rgba(18, 52, 91, .36) 38%,
    rgba(18, 52, 91, .13) 56%,
    rgba(18, 52, 91, 0) 72%
  );
}

/* The presenter photo, anchored to the bottom edge between the columns. */
.hero__portrait {
  position: absolute;
  bottom: 0;
  left: 46%;
  width: 400px;
  max-width: 46%;
  transform: translateX(-44%);
  z-index: -1;
  object-fit: contain;
  object-position: bottom center;
  filter: drop-shadow(0 18px 34px rgba(18, 52, 91, .28));
  pointer-events: none;
}

.hero__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  max-width: 460px;
}

.hero__title {
  color: var(--color-white);
  font-size: clamp(30px, 3.4vw, 50px);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -.02em;
  text-wrap: balance;
}

.hero__host {
  font-size: clamp(17px, 1.5vw, 23px);
  font-weight: 500;
}

.hero__time {
  font-size: clamp(17px, 1.5vw, 23px);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.hero__lead {
  max-width: 34ch;
  font-size: 16px;
  color: rgba(255, 255, 255, .92);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: auto;
  padding-top: 18px;
}

/* Inside the hero, the deep blue reads as the primary action against the
   lighter gradient, so the red CTA is not repeated here. */
.hero__actions .btn--blue { background: var(--color-blue); }
.hero__actions .btn--blue:hover { background: var(--color-blue-active); }

/* ── Today's schedule, the hero's right-hand column ─────────────────────────
   Glass Surface: the handbook's recipe for a panel floating over a coloured
   field. It carries the schedule's small text at an accessible contrast, and
   reads as the divider the design draws between the two halves. */
.onair {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 20px;
  border-radius: var(--radius-lg);
  background: rgba(18, 52, 91, .52);
  backdrop-filter: blur(3px);
  border: 1px solid rgba(255, 255, 255, .16);
}

.onair__title {
  color: var(--color-white);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.onair__list {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.onair__item {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr);
  column-gap: 12px;
  align-items: center;
}

.onair__avatar {
  grid-row: 1 / 4;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  object-fit: cover;
  background: rgba(255, 255, 255, .18);
}

.onair__time  { font-size: 12.5px; color: rgba(255, 255, 255, .85); font-variant-numeric: tabular-nums; }
.onair__show  { font-size: 15.5px; font-weight: 700; line-height: 1.25; }
.onair__host  { font-size: 13px; color: rgba(255, 255, 255, .85); }

.onair__more { margin-top: auto; }

/* ============================= 5. Panels ================================== */
/* A white card holding one section of the page. */
.panel {
  padding: 20px;
  border-radius: var(--radius-lg);
  background: var(--color-card);
  box-shadow: var(--shadow-light);
}

.panel--soft { background: var(--gradient-soft); box-shadow: none; }
.panel--flat { box-shadow: none; border: 1px solid var(--color-divider); }

.panel__head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-bottom: 16px;
}

.panel__title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: clamp(19px, 1.7vw, 24px);
  font-weight: 700;
  color: var(--color-navy);
}

/* Section icons are red in the design — one accent per component. */
.panel__title .icon { width: 26px; height: 26px; color: var(--color-red); }

/*
 * `nowrap` keeps "Bekijk alle 12 fragmenten →" on one line, which is right
 * until the line is wider than the phone holding it — this link was the single
 * reason the homepage could be dragged sideways. It keeps the nowrap and gets
 * permission to drop onto its own row instead, via the wrap on .panel__head.
 */
.panel__more {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  color: var(--color-blue);
  font-size: 14.5px;
  font-weight: 600;
  white-space: nowrap;
}
.panel__more:hover { color: var(--color-blue-hover); text-decoration: underline; }
.panel__more .icon { width: 17px; height: 17px; }

.panel__lead { color: var(--color-ink-soft); margin-bottom: 16px; }

/* ============================== 6. Cards ================================== */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: var(--gap);
}
.cards--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cards--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.card__media {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-mist);
}
.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .3s ease;
}
.card:hover .card__media img { transform: scale(1.04); }

.card__media--square { aspect-ratio: 1 / 1; }

/* A fragment with no thumbnail of its own. */
.card__media--blank { background: var(--gradient-soft); }
.card__blank {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--color-steel);
  opacity: .5;
}
.card__blank .icon { width: 46px; height: 46px; }

.card__title {
  font-size: 16.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-navy);
}
.card:hover .card__title { color: var(--color-blue); }

.card__meta {
  font-size: 13.5px;
  color: var(--color-ink-soft);
}
.card__excerpt {
  font-size: 14px;
  color: var(--color-ink-soft);
  line-height: 1.5;
}

/* The date/kicker line above a card title. */
.card__kicker {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 700;
  color: var(--color-blue);
}

/*
 * Play affordance on a video thumbnail.
 *
 * Two placements, both from the design: tucked into the bottom-left corner on
 * the rails, and large and centred on the RADIONL TV page.
 */
.play-dot {
  position: absolute;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  color: var(--color-blue);
  box-shadow: var(--shadow-light);
  transition: transform .2s ease, background-color .2s ease;
}

.play-dot--corner { left: 10px; bottom: 10px; width: 38px; height: 38px; font-size: 15px; }
.play-dot--centre { inset: 0; margin: auto; width: 58px; height: 58px; font-size: 23px; }

.card:hover .play-dot,
.tile:hover .play-dot { transform: scale(1.08); background: var(--color-white); }
.play-dot--centre { transform-origin: center; }

/* A numbered rank badge, for "Meest bekeken". A circle, as drawn. */
.rank {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-red);
  color: var(--color-white);
  font-size: 15px;
  font-weight: 800;
}

/* "Meest bekeken": ranking and title sit directly on the thumbnail. */
.tile {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-mist);
}
.tile img { width: 100%; height: 100%; object-fit: cover; transition: transform .3s ease; }
.tile:hover img { transform: scale(1.04); }
.tile__title {
  position: absolute;
  z-index: 1;
  top: 10px;
  right: 10px;
  left: 52px;
  display: -webkit-box;
  padding: 6px 8px;
  overflow: hidden;
  border-radius: 7px;
  background: rgba(18, 52, 91, .86);
  color: var(--color-white);
  font-size: 14px;
  font-weight: 750;
  line-height: 1.2;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .28);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  backdrop-filter: blur(4px);
}

/* RADIONL TV cards carry a broadcast time and an overflow affordance. */
.tvcard__head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
}
.tvcard__time {
  font-size: 14px;
  font-weight: 700;
  color: var(--color-blue);
  font-variant-numeric: tabular-nums;
}
.tvcard__more { margin-left: auto; color: var(--color-placeholder); }
.tvcard__more .icon { width: 18px; height: 18px; }

/* A pill sitting on top of a thumbnail ("NIEUWS", "ACTIE", "EVENT"). */
.card__tag {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 1;
}

/* ============================== 7. Live rail ============================== */
.rail-card {
  padding: 20px;
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

/*
 * The rail's section labels are the one place red is used purely as a label
 * colour. They read as station idents ("NU OP RADIONL:"), which is why they
 * keep the colon and the caps from the design.
 */
.rail-card__label {
  margin-bottom: 14px;
  color: var(--color-red);
  font-size: 14px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.rail-card__title {
  margin-bottom: 6px;
  font-size: 21px;
  font-weight: 700;
  color: var(--color-blue);
}

.rail-card__text {
  color: var(--color-navy);
  font-size: 15px;
  line-height: 1.6;
}

.rail-card__divider {
  height: 1px;
  margin: 22px 0;
  background: var(--color-border);
}

/* ── Now playing ─────────────────────────────────────────────────────────── */
.nowplaying {
  display: grid;
  grid-template-columns: 148px minmax(0, 1fr);
  gap: 18px;
  align-items: center;
}

.nowplaying__cover {
  width: 148px;
  height: 148px;
  border-radius: var(--radius-md);
  object-fit: cover;
  background: var(--color-mist);
  box-shadow: var(--shadow-light);
}

.nowplaying__title {
  font-size: 17px;
  font-weight: 700;
  color: var(--color-blue);
  line-height: 1.3;
}
.nowplaying__artist {
  margin-top: 2px;
  font-size: 15.5px;
  color: var(--color-blue);
}
.nowplaying__action { margin-top: 14px; }
.nowplaying__action .icon-btn { width: 42px; height: 42px; background: transparent; }

/* ── Recently played ─────────────────────────────────────────────────────── */
.tracks { display: flex; flex-direction: column; gap: 16px; }

.track {
  display: grid;
  grid-template-columns: 54px minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
}

.track__cover {
  width: 54px;
  height: 54px;
  flex: none;
  border-radius: var(--radius-sm);
  object-fit: cover;
  background: var(--color-mist);
}

/* No artwork: a note on the mist tile rather than a broken-image icon. */
.track__cover--blank,
.nowplaying__cover--blank,
.playlist__cover--blank {
  display: grid;
  place-items: center;
  background: var(--gradient-soft);
  color: var(--color-steel);
}
.track__cover--blank .icon { width: 22px; height: 22px; opacity: .6; }
.playlist__cover--blank .icon { width: 24px; height: 24px; opacity: .6; }

.track__title {
  font-size: 15.5px;
  font-weight: 700;
  color: var(--color-blue);
  line-height: 1.25;
}
.track__artist { font-size: 14.5px; color: var(--color-blue); }
.track__time {
  font-size: 15px;
  font-weight: 700;
  color: var(--color-blue);
  font-variant-numeric: tabular-nums;
}

/* ── App and social panels ───────────────────────────────────────────────── */
/*
 * The app panel: copy on the left, handset on the right.
 *
 * The card reserves height for the phone rather than letting it hang out of the
 * bottom, and clips anyway so a taller uploaded render cannot break the layout.
 */
.apppanel {
  position: relative;
  min-height: 252px;
  overflow: hidden;
}
.apppanel__phone {
  position: absolute;
  top: 16px;
  right: 6px;
  width: 128px;
  pointer-events: none;
}
.apppanel__body { max-width: 58%; }

.storebadges {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 18px;
}
.storebadges img { height: 46px; width: auto; border-radius: 7px; }

.socials {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 18px;
}

.socials a {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--color-blue);
  color: var(--color-white);
  font-size: 22px;
  transition: transform .18s ease, box-shadow .18s ease;
}
.socials a:hover { transform: translateY(-2px); box-shadow: var(--shadow-light); }

/* Platform marks stay recognisable; the handbook's palette governs the
   station's own surfaces, not third-party logos. */
.socials a[data-social="facebook"] { background: #1877f2; }
.socials a[data-social="instagram"] {
  background: radial-gradient(circle at 30% 107%, #fdf497 0%, #fd5949 45%, #d6249f 60%, #285aeb 90%);
}
.socials a[data-social="tiktok"]   { background: #010101; }
.socials a[data-social="youtube"]  { background: #ff0000; }
.socials a[data-social="snapchat"] { background: #fffc00; color: #010101; }

/* ============================== 8. Footer ================================= */
.site-footer {
  background: var(--gradient-deep);
  color: var(--color-white);
}

.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px 34px;
  padding-block: 18px;
  font-size: 14.5px;
}

/*
 * Clearance under the last thing on the page.
 *
 * The player bar starts exactly where this frame ends, so without this the
 * footer's final line of text sits flush against it with nothing between them —
 * which reads as the footer having been cut off rather than having ended.
 */
.site-footer { padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px)); }

.site-footer a { color: var(--color-white); }
.site-footer a:hover { text-decoration: underline; text-underline-offset: 3px; }

.site-footer__copy { color: rgba(255, 255, 255, .9); }

/* ============================ 9. Search overlay =========================== */
/*
 * The dimmer, shared by the search overlay and the mobile menu sheet.
 *
 * It has to sit *below* the header (z-index 120), not above it. The mobile
 * sheet is a child of the header, and the header is a stacking context — a
 * sticky element with a z-index, blur or no blur — so nothing inside it can
 * ever paint above something with a higher z-index outside it, whatever the
 * child's own z-index says. A scrim above the header therefore covered the very
 * menu it was dimming *for*: blurred, and swallowing every tap.
 *
 * Below the header instead, the order is: page < scrim < header (and its sheet)
 * < search panel. The header goes undimmed, which is right in both cases — the
 * sheet hangs off it, and the search panel covers it.
 */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 110;
  background: var(--overlay-dark);
  backdrop-filter: blur(3px);
}
.scrim[hidden] { display: none; }

.search {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 150;
  padding: 26px 0 30px;
  background: var(--color-card);
  box-shadow: var(--shadow-heavy);
}
.search[hidden] { display: none; }

.search__form {
  display: flex;
  gap: 12px;
  align-items: center;
}

.search__input {
  flex: 1;
  min-width: 0;
  padding: 15px 20px;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-card);
  font-size: 17px;
}
.search__input::placeholder { color: var(--color-placeholder); }
.search__input:focus-visible { border-color: var(--color-blue); outline: none; box-shadow: var(--glow-blue); }

/* ============================= 10. Empty state ============================ */
.empty {
  padding: 34px 20px;
  border-radius: var(--radius-lg);
  border: 1.5px dashed var(--color-border);
  background: var(--color-ice);
  text-align: center;
  color: var(--color-ink-soft);
}
.empty strong { display: block; margin-bottom: 4px; color: var(--color-navy); font-size: 17px; }

/* ============================ 11. Breadcrumbs ============================= */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--color-ink-soft);
}
.crumbs a { color: var(--color-blue); }
.crumbs a:hover { text-decoration: underline; }
.crumbs .icon { width: 14px; height: 14px; color: var(--color-placeholder); }
.crumbs [aria-current] { color: var(--color-navy); font-weight: 600; }

/* ============================ 12. Header mobile =========================== */
@media (max-width: 1180px) {
  .nav__list { gap: 18px; }
  .nav__item > a { font-size: 14.5px; }
  .logo img { width: 148px; }
  .btn--listen span { display: none; }
  .btn--listen { padding-inline: 16px; }
}

@media (max-width: 980px) {
  .icon-btn--menu { display: inline-grid; }

  /* The menu becomes a sheet under the header rather than a row. */
  .nav {
    position: fixed;
    inset: var(--header-height) 0 auto;
    z-index: 130;
    max-height: calc(100dvh - var(--header-height));
    overflow-y: auto;
    padding: 12px 16px 22px;
    background: var(--color-card);
    border-bottom: 1px solid var(--color-divider);
    box-shadow: var(--shadow-medium);
    transform: translateY(-12px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s ease, transform .2s ease, visibility .2s;
  }
  .nav[data-open="true"] { opacity: 1; visibility: visible; transform: none; }

  .nav__list { flex-direction: column; align-items: stretch; gap: 2px; }
  .nav__item > a { padding: 13px 8px; font-size: 17px; }
  .nav__item > a[aria-current="page"]::after { left: 8px; right: auto; width: 26px; bottom: 6px; }

  .nav__submenu {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    box-shadow: none;
    border: 0;
    padding: 0 0 6px 14px;
    min-width: 0;
  }

  .btn--watch span { display: none; }
  .btn--watch { padding-inline: 16px; }

  /* Out of flow now, so the actions have to be pushed to the right themselves. */
  .site-header__actions { margin-inline-start: auto; }
}

/*
 * Phones. Five controls at their desktop sizes need 401px of a 390px screen,
 * and the one that fell off the end was the menu button — the only way into the
 * navigation at this width.
 *
 * The logo comes down a size and the gaps tighten, and "Kijk live" goes: it is
 * the one action that is also a top-level item in the sheet directly below,
 * whereas Luister live starts the player that this whole shell exists for.
 */
@media (max-width: 560px) {
  .site-header__inner { gap: 10px; }
  .site-header__actions { gap: 8px; }
  .logo img { width: 116px; }
  .btn--watch { display: none; }
  .icon-btn { width: 42px; height: 42px; font-size: 17px; }
}

@media (max-width: 720px) {
  /*
   * Stacked, and trimmed: the desktop hero is 470px of a 900px viewport, but
   * the same content stacked is most of a phone screen. The portrait shrinks
   * and bleeds off the bottom edge, and the schedule loses its avatars —
   * everything that costs height without carrying information.
   */
  .hero {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
    padding: 20px;
    gap: 18px;
  }
  .hero__portrait {
    position: static;
    order: 2;
    width: 170px;
    max-width: 52%;
    margin: -8px auto -26px;
    transform: none;
  }
  .hero__intro { max-width: none; gap: 10px; }
  .hero__actions { padding-top: 8px; }

  /* Stacked, so the wash runs top-to-bottom instead of across. */
  .hero::after {
    background: linear-gradient(
      180deg,
      rgba(18, 52, 91, .30) 0%,
      rgba(18, 52, 91, .34) 60%,
      rgba(18, 52, 91, .40) 100%
    );
  }

  /*
   * The schedule panel goes on phones.
   *
   * Stacked under the hero copy it was another screenful before the reader
   * reached any of the page, for a list that has its own route — the hero's
   * "Bekijk de programmering" button, one tap away, and /programma in the menu.
   */
  .onair { display: none; }
  .cards--3, .cards--2 { grid-template-columns: minmax(0, 1fr); }
  .nowplaying { grid-template-columns: 112px minmax(0, 1fr); gap: 14px; }
  .nowplaying__cover { width: 112px; height: 112px; }
  .apppanel__body { max-width: 100%; }
  .apppanel { min-height: 0; }
  .apppanel__phone { display: none; }
  .panel { padding: 16px; }
  .rail-card { padding: 16px; }
}

@media (max-width: 480px) {
  .hero__actions .btn { flex: 1 1 100%; }
  .storebadges img { height: 42px; }
}

/* ========================== 13. Soft navigation ===========================
   Pages swap in place rather than reloading (assets/soft-nav.js). The swap is
   dressed with a crossfade and nothing else: opacity only, no movement, no
   View Transitions.

   That is a deliberate retreat. A View Transition captures the old column and
   the new one and morphs the first into the second — but these columns differ
   in height and in where they start (a hero on one page, none on the next), so
   the morph dragged the snapshot up and down the screen. Adding a few pixels of
   travel on top made it shake outright. Fading in place has no geometry to
   disagree about, so there is nothing left to shake.
   ======================================================================== */

.softnav-leaving,
.softnav-entering {
  opacity: 0;
}

.softnav-leaving { transition: opacity .11s ease-in; }
.softnav-entering { transition: opacity .2s ease-out; }

.softnav {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  z-index: 400;
  height: 3px;
  width: 0;
  background: var(--color-red);
  opacity: 0;
  pointer-events: none;
}

.softnav--on {
  width: 78%;
  opacity: 1;
  transition: width 1.8s cubic-bezier(.1, .8, .2, 1), opacity .15s ease;
}

.softnav--done {
  width: 100%;
  opacity: 0;
  transition: width .16s ease, opacity .3s ease .1s;
}

@media (prefers-reduced-motion: reduce) {
  .softnav-leaving,
  .softnav-entering { transition: none; opacity: 1; }
  .softnav { transition: none; }
}
