* { margin: 0; padding: 0; box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; overflow-x: hidden; }

/* Radio Dial. A monochrome base with type doing the hierarchy; the accent
   is reserved for what is live or playable (play controls, the needle,
   on-air state) so it always means "you can listen to this". */
:root {
  --bg: #efeeea;
  --surface: #e5e3de;
  --text: #151517;
  --text-2: #3a3936;
  --muted: #5f5e5a;
  --faint: #a3a19b;
  --rule: #d6d4ce;
  --tick: #bdbbb5;
  --field: #83817b;                /* outlines of inputs and other controls: 3:1 on bg and surface */
  --accent: #5326f8;
  --on-accent: #ffffff;
  --logo-filter: brightness(0.15);
  --font-display: 'Josefin Sans', Futura, 'Century Gothic', sans-serif;
  --font-body: 'IBM Plex Sans', 'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, Menlo, Consolas, monospace;
  /* Content sits in a 1312px measure; the gutter grows past that width. */
  --gutter: max(64px, calc((100% - 1312px) / 2));
}

/* Dark theme is built on the brand blue rather than a neutral black: the
   background is a deep #5326F8, and every surface, rule and tick carries
   the same hue so nothing reads as grey on top of it. The accent is the
   same blue lifted until it clearly separates from that background
   (6.45:1) — the old #8b6fff would have sat at 4.71:1 and gone flat. */
body.dark {
  --bg: #1b1640;
  --surface: #241e57;
  --text: #ece9f7;
  --text-2: #c3c1d6;
  --muted: #9793b5;
  --faint: #565080;
  --rule: #2e2766;
  --tick: #3b3478;
  --field: #716c91;
  --accent: #a58fff;
  --on-accent: #140f33;
  --logo-filter: none;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  min-height: 100vh;
}

a { color: inherit; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--text); outline-offset: 3px; }

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
@keyframes blink { 50% { opacity: 0; } }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* --- Navigation --- */
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 32px;
  height: 88px;
  padding: 0 var(--gutter);
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
}

.nav-home-link {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  margin-right: auto;
  color: var(--text);
  text-decoration: none;
  flex-shrink: 0;
}

.nav-logo { width: 28px; height: 28px; filter: var(--logo-filter); }

.nav-brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.nav-links { display: contents; }

.nav a.nav-link {
  flex-shrink: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  padding: 6px 0;
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease;
}

.nav a.nav-link:hover { color: var(--text); }
.nav a.nav-link.active { color: var(--text); border-bottom-color: var(--text); }

.theme-toggle {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: none;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.theme-toggle:hover { color: var(--text); border-color: var(--text); }

.theme-icon.sun { display: none; }
.theme-icon.moon { display: block; }
body.dark .theme-icon.sun { display: block; }
body.dark .theme-icon.moon { display: none; }

.nav-hamburger {
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  color: var(--text);
  cursor: pointer;
}

/* The full bar needs ~966px in Josefin caps (brand, six links, toggle,
   gaps, gutters), so the menu collapses a little above that. */
@media (max-width: 980px) {
  .nav { height: 64px; }
  .nav-hamburger { display: flex; }
  .nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    padding: 12px var(--gutter) 20px;
    background: var(--bg);
    border-bottom: 1px solid var(--rule);
  }
  .nav-links.open { display: flex; }
  .nav a.nav-link { font-size: 17px; letter-spacing: 0.12em; padding: 10px 0; }
  .theme-toggle { margin-top: 8px; }
}

/* --- Pages --- */
.page { display: none; padding: 0 var(--gutter) 140px; }
.page.active { display: block; }

/* --- Home: hero --- */
.hero {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 64px;
  padding-top: 88px;
}

/* flex-shrink 0: if the numbers are ever off, the player gives way rather
   than the wordmark being silently clipped under it. */
.hero-id { display: flex; flex-direction: column; gap: 24px; flex-shrink: 0; }

.station-name {
  font-family: var(--font-display);
  font-weight: 700;
  /* "BRENNPUNKT" in Josefin Sans 700 measures ~7.44em. Beside the player
     the column gets roughly (viewport - gutters - gap - player), so the
     size divides that by 7.6 for a little slack. */
  font-size: clamp(48px, calc((100vw - 600px) / 7.6), 112px);
  line-height: 0.92;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.station-tagline {
  font-style: italic;
  font-size: clamp(17px, 1.6vw, 22px);
  color: var(--muted);
  min-height: 1.5em;
}

.station-tagline .cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-left: 3px;
  vertical-align: -0.15em;
  background: currentColor;
  animation: blink 0.6s step-end infinite;
}

/* --- Home: now playing --- */
.player {
  flex: 0 1 470px;
  min-width: 340px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding-bottom: 8px;
}

.status {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 20px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.18em;
  color: var(--muted);
}

.status:has(.status-dot.live) { color: var(--accent); }

.status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--faint); }

.status-dot.live {
  background: var(--accent);
  box-shadow: 0 0 12px var(--accent);
  animation: pulse 2s ease-in-out infinite;
}

.visualizer-dots { display: flex; align-items: flex-end; gap: 2px; height: 20px; }
.visualizer-dots .bar { width: 2px; background: var(--accent); transition: height 0.15s ease; }
.visualizer-dots.idle { display: none; }

.track-info { display: flex; gap: 22px; align-items: center; min-width: 0; }

.track-art {
  width: 120px;
  height: 120px;
  flex-shrink: 0;
  object-fit: cover;
  border-radius: 2px;
  background: var(--surface);
}

.track-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.track-line { overflow: hidden; white-space: nowrap; }
.track-line .scroll-inner { display: inline-block; white-space: nowrap; }
.track-line.scrolling .scroll-inner { animation: marquee var(--duration, 12s) linear infinite; }
.track-title { font-size: 30px; font-weight: 500; line-height: 1.15; }
.track-artist { font-size: 16px; color: var(--text-2); }

.track-album {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.voting { display: flex; align-items: center; gap: 6px; }

.vote-label {
  margin-right: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.star-rating { display: flex; align-items: center; }

.star-btn {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--muted);
}

.star-btn svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linejoin: round;
  transition: fill 0.15s ease;
}

.star-btn:hover, .star-btn.hovered { color: var(--text); }
.star-btn.hovered svg { fill: var(--tick); }
.star-btn.filled { color: var(--text); }
.star-btn.filled svg { fill: currentColor; }

.star-avg { margin-left: 8px; font-family: var(--font-mono); font-size: 12px; color: var(--muted); }

/* --- Home: the dial (play control + progress as a tuning scale) --- */
.dial { display: flex; align-items: center; gap: 32px; margin-top: 80px; }
.controls { flex-shrink: 0; }

.play-btn {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  border: 2px solid transparent;
  background: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.2s ease;
}

.play-btn:hover {
  transform: scale(1.04);
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 20%, transparent);
}

.icon-play, .icon-pause { fill: var(--on-accent); }
.icon-play { margin-left: 4px; }
.icon-pause { display: none; }
.play-btn.playing .icon-play { display: none; }
.play-btn.playing .icon-pause { display: block; }

.play-btn.loading {
  background: transparent;
  border-color: var(--rule);
  border-top-color: var(--accent);
  animation: spin 0.8s linear infinite;
  pointer-events: none;
}

.play-btn.loading svg { display: none; }

.dial-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.dial-scale { position: relative; height: 68px; }

.dial-minor {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 18px;
  background: repeating-linear-gradient(to right, var(--tick) 0 1px, transparent 1px 18px);
}

.dial-scale::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--rule);
}

/* progressFill: the ticks already played, drawn in the accent. It shares
   the minor ticks' origin and period, so the two line up exactly. */
.progress-bar-fill {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 18px;
  width: 0%;
  background: repeating-linear-gradient(to right, var(--accent) 0 1px, transparent 1px 18px);
  transition: width 0.4s linear;
}

#dialMajors { position: absolute; inset: 0; }

.dial-major { position: absolute; bottom: 0; width: 1px; height: 36px; background: var(--muted); }
.dial-major-start { left: 0; }
.dial-major-end { right: 0; }

.dial-needle {
  position: absolute;
  left: 0%;
  bottom: 0;
  width: 2px;
  height: 100%;
  margin-left: -1px;
  background: var(--accent);
  transition: left 0.4s linear;
}

.dial-elapsed {
  position: absolute;
  top: 0;
  left: 0%;
  margin-left: 12px;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--accent);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  transition: left 0.4s linear;
}

.dial-elapsed.flip { transform: translateX(calc(-100% - 24px)); }

.dial-scale.no-anim .progress-bar-fill,
.dial-scale.no-anim .dial-needle,
.dial-scale.no-anim .dial-elapsed,
.mini-progress.no-anim .mini-progress-fill { transition: none; }

.dial-labels {
  position: relative;
  height: 16px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

#dialLabels { position: absolute; inset: 0; }
.dial-label { position: absolute; top: 0; transform: translateX(-50%); }
.dial-end { position: absolute; top: 0; left: 0; }
.dial-end-right { left: auto; right: 0; }

/* --- Home: latest episodes --- */
.home-shows { margin-top: 104px; }

.section-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--text);
}

.home-shows-title {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.home-shows-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text);
  text-decoration: none;
}

.home-shows-link:hover { text-decoration: underline; text-underline-offset: 4px; }

.latest-list, .episodes-list { display: flex; flex-direction: column; }

/* Episode rows (home and show pages): rules, not cards. */
.episode-card {
  display: flex;
  align-items: center;
  gap: 32px;
  padding: 24px 0;
  border-bottom: 1px solid var(--rule);
}

.episode-index { width: 32px; flex-shrink: 0; font-family: var(--font-mono); font-size: 13px; color: var(--muted); }

.episode-date {
  width: 132px;
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 13px;
  text-transform: uppercase;
  color: var(--muted);
}

.episode-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.episode-title { font-size: 28px; line-height: 1.15; overflow-wrap: anywhere; }
.episode-show { font-size: 14px; color: var(--muted); }

.episode-meta {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 13px;
  text-transform: uppercase;
  color: var(--muted);
}

.episode-play-btn {
  width: 48px;
  height: 48px;
  flex-shrink: 0;
  padding-left: 3px;
  border-radius: 50%;
  border: 1px solid var(--accent);
  background: transparent;
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.episode-play-btn:hover, .episode-play-btn.active { background: var(--accent); color: var(--on-accent); }

.episodes-loading, .chart-empty, .featured-loading {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  padding: 48px 0;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.spinner {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid var(--rule);
  border-top-color: var(--text);
  animation: spin 0.8s linear infinite;
}

/* --- Home: footer row + recently played --- */
.home-foot { margin-top: 72px; }

.home-foot-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.history-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.history-toggle:hover { color: var(--text); }
.history-toggle svg { width: 14px; height: 14px; transition: transform 0.2s ease; }
.history-toggle.open svg { transform: rotate(180deg); }

.history-list {
  display: none;
  margin-top: 12px;
  max-height: 360px;
  overflow-y: auto;
  border-top: 1px solid var(--text);
}

.history-list.open { display: block; }

.history-item { display: flex; align-items: center; gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--rule); }

.history-item-art {
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  border-radius: 2px;
  object-fit: cover;
  background: var(--surface);
}

.history-item-info { flex: 1; min-width: 0; }
.history-item-title { font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.history-item-artist { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.history-item-time { flex-shrink: 0; font-family: var(--font-mono); font-size: 11px; color: var(--muted); }

.cc4ap-badge {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
}

.cc4ap-badge:hover { color: var(--text); }
.cc4ap-logo svg { width: 40px; height: auto; display: block; }

/* --- Sponsors ---------------------------------------------------------- */
.home-credits {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 24px 32px;
  margin-top: 56px;
  padding-top: 24px;
  border-top: 1px solid var(--rule);
}

.sponsors-title {
  margin: 0 0 20px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.sponsors-logos {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 24px 48px;
}

.sponsor { display: block; opacity: 0.85; transition: opacity 0.2s ease; }
.sponsor:hover, .sponsor:focus-visible { opacity: 1; }
.sponsor img { display: block; width: auto; height: 72px; }
.sponsor-shunpike img { height: 84px; }   /* the round badge reads smaller at equal height */

/* One logo per theme */
.sponsor .on-dark { display: none; }
body.dark .sponsor .on-light { display: none; }
body.dark .sponsor .on-dark { display: block; }

/* --- Page headers (Shows, Featured, Chart, About, Submit, show pages) --- */
.shows-header, .featured-header, .chart-header, .about-header, .submit-header, .show-detail-header, .notfound-header {
  padding: 72px 0 32px;
  border-bottom: 1px solid var(--text);
}

.shows-header h2, .featured-header h2, .chart-header h2, .about-header h2, .submit-header h2, .show-detail-header h2, .notfound-header h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(44px, 6vw, 88px);
  line-height: 0.95;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.shows-header p, .featured-header p, .chart-header p, .about-header p, .submit-header p, .show-detail-sub, .notfound-header p {
  margin-top: 16px;
  font-style: italic;
  font-size: 20px;
  color: var(--muted);
}

.show-detail-desc { margin-top: 16px; max-width: 60ch; font-size: 18px; line-height: 1.65; color: var(--text-2); }

.show-detail-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin-bottom: 16px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
}

.show-detail-back:hover { color: var(--text); }

/* --- Shows --- */
.shows-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 32px; padding: 28px 0 40px; }

.shows-search {
  width: 320px;
  max-width: 100%;
  min-height: 44px;
  padding: 10px 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--field);
  border-radius: 0;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  outline: none;
}

.shows-search::placeholder { color: var(--muted); }
.shows-search:focus { border-bottom-color: var(--text); }

.shows-tags { display: flex; flex-wrap: wrap; gap: 8px; }

.shows-tag {
  min-height: 40px;
  padding: 0 14px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.15s ease, border-color 0.15s ease;
}

.shows-tag:hover { color: var(--text); border-color: var(--text); }
.shows-tag.active { background: var(--text); border-color: var(--text); color: var(--bg); }

.shows-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 48px 28px; }
.show-card { display: block; color: inherit; text-decoration: none; }

.show-card .show-img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
  margin-bottom: 16px;
  border-radius: 2px;
  background: var(--surface);
  transition: opacity 0.2s ease;
}

.show-card:hover .show-img { opacity: 0.88; }

.show-card .show-tag-label {
  margin-bottom: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.show-card h3 { margin-bottom: 4px; font-size: 20px; font-weight: 500; line-height: 1.25; }
.show-card:hover h3 { text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px; }
.show-card .show-host { font-size: 14px; color: var(--muted); }

.show-card .show-desc {
  margin-top: 8px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.shows-no-results {
  grid-column: 1 / -1;
  padding: 48px 0;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* --- Featured --- */
.featured-card { padding-top: 48px; }

.featured-layout {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 64px;
  align-items: start;
}

.featured-cover {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
  border-radius: 2px;
  background: var(--surface);
}

.featured-info { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; min-width: 0; }

.featured-kicker {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.featured-info h3 { font-size: clamp(32px, 3.6vw, 52px); font-weight: 500; line-height: 1.08; overflow-wrap: anywhere; }
.featured-artist { font-size: 20px; color: var(--text-2); }

.featured-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text);
  text-decoration: none;
}

.featured-link:hover { text-decoration: underline; text-underline-offset: 4px; }

.featured-embed { width: 100%; margin-top: 12px; padding-top: 20px; border-top: 1px solid var(--rule); }
/* Tints Bandcamp's light player into the site palette (it can't be styled
   inside its iframe). Light: white panels -> #efefef, our paper tone.
   Dark: invert(1) turns its white panel black and its black text white,
   hue-rotate(180deg) restores the hues, and screen blending drops that now
   black panel into the page colour exactly — so the player carries the blue
   background instead of sitting on a grey block. */
.featured-embed iframe { width: 100%; border: 0; display: block; filter: brightness(0.937); }
body.dark .featured-embed iframe {
  filter: invert(1) hue-rotate(180deg);
  mix-blend-mode: screen;
}

/* --- Chart --- */
.chart-list { display: flex; flex-direction: column; }

.chart-entry { display: flex; align-items: center; gap: 28px; padding: 22px 0; border-bottom: 1px solid var(--rule); }

.chart-rank {
  width: 64px;
  flex-shrink: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 36px;
  line-height: 1;
  color: var(--muted);
}

.chart-entry.top-3 .chart-rank { color: var(--text); }

.chart-art { width: 52px; height: 52px; flex-shrink: 0; border-radius: 2px; object-fit: cover; background: var(--surface); }
.chart-info { flex: 1; min-width: 0; }
.chart-title { font-size: 22px; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chart-artist { margin-top: 2px; font-size: 14px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.chart-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
}

.chart-link:hover { border-bottom-color: var(--text); }

.chart-stats { display: flex; align-items: center; gap: 16px; flex-shrink: 0; }
.chart-stars { display: flex; gap: 2px; }
.chart-stars svg { width: 14px; height: 14px; }
.chart-stars .star-filled { fill: var(--text); }
.chart-stars .star-half { fill: var(--muted); }
.chart-stars .star-empty { fill: var(--field); }
.chart-rating-text { min-width: 2.5em; text-align: right; font-family: var(--font-mono); font-size: 13px; }

.chart-votes {
  min-width: 5.5em;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.back-to-top {
  position: fixed;
  right: 24px;
  bottom: 88px;
  z-index: 90;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: var(--bg);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

.back-to-top.visible { opacity: 1; pointer-events: auto; }

/* --- About --- */
.about-content { padding-top: 48px; }
.about-intro { display: flex; flex-direction: column; align-items: flex-start; gap: 24px; max-width: 760px; }
.about-intro .about-logo { width: 56px; height: 56px; filter: var(--logo-filter); }
.about-badges { display: flex; flex-wrap: wrap; gap: 8px; }

.about-badge {
  padding: 8px 12px;
  border: 1px solid var(--rule);
  border-radius: 2px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-2);
}

.about-intro p { max-width: 62ch; font-size: 19px; line-height: 1.7; color: var(--text-2); }

.about-intro a, .faq-a a, .about-org a, .submit-intro a {
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

.about-faq, .about-org { margin-top: 96px; }

.about-faq h3, .about-org h3 {
  padding-bottom: 20px;
  border-bottom: 1px solid var(--text);
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.faq-item {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 48px;
  padding: 28px 0;
  border-bottom: 1px solid var(--rule);
}

.faq-q { font-size: 20px; font-weight: 500; line-height: 1.35; }
.faq-a { font-size: 17px; line-height: 1.65; color: var(--text-2); }
.about-org p { margin-top: 28px; max-width: 62ch; font-size: 19px; line-height: 1.7; color: var(--text-2); }

/* --- Submit --- */
.submit-content {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 64px;
  align-items: start;
  padding-top: 48px;
}

.submit-intro { grid-row: span 2; display: flex; flex-direction: column; gap: 18px; font-size: 17px; line-height: 1.7; color: var(--text-2); }
.submit-form { display: flex; flex-direction: column; gap: 24px; }

.submit-form label {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.submit-form input, .submit-form textarea {
  min-height: 48px;
  padding: 12px 14px;
  background: transparent;
  border: 1px solid var(--field);
  border-radius: 2px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  letter-spacing: 0;
  text-transform: none;
  outline: none;
  transition: border-color 0.15s ease;
}

.submit-form input::placeholder, .submit-form textarea::placeholder { color: var(--muted); }
.submit-form input:focus, .submit-form textarea:focus { border-color: var(--text); }
.submit-form textarea { min-height: 160px; resize: vertical; }

.submit-btn {
  align-self: flex-start;
  min-height: 52px;
  padding: 0 32px;
  background: var(--text);
  color: var(--bg);
  border: 0;
  border-radius: 2px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.submit-btn:hover { opacity: 0.85; }
.submit-btn:disabled { opacity: 0.5; cursor: default; }

.submit-success {
  display: none;
  padding: 24px 0;
  border-top: 1px solid var(--text);
  border-bottom: 1px solid var(--text);
  font-size: 19px;
}

/* --- Mini player (every page except home) --- */
.mini-player {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 95;
  align-items: center;
  gap: 14px;
  padding: 10px var(--gutter);
  background: var(--surface);
  border-top: 1px solid var(--rule);
}

.mini-player.visible { display: flex; }

.mini-progress { position: absolute; top: -1px; left: 0; right: 0; height: 2px; overflow: hidden; pointer-events: none; }
.mini-progress-fill { height: 100%; width: 0%; background: var(--accent); transition: width 0.4s linear; }
.mini-player.episode-mode .mini-progress { display: none; }

.mini-status-dot { width: 6px; height: 6px; flex-shrink: 0; border-radius: 50%; background: var(--faint); }

.mini-status-dot.live {
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent);
  animation: pulse 2s ease-in-out infinite;
}

.mini-art { width: 40px; height: 40px; flex-shrink: 0; border-radius: 2px; object-fit: cover; background: var(--bg); }
.mini-track { flex: 1; min-width: 0; }
.mini-title { font-size: 14px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mini-artist { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.mini-play-btn {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid transparent;
  background: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.mini-play-btn svg { fill: var(--on-accent); }
.mini-icon-play { margin-left: 3px; }

.mini-play-btn.loading {
  background: transparent;
  border-color: var(--rule);
  border-top-color: var(--accent);
  animation: spin 0.8s linear infinite;
  pointer-events: none;
}

/* !important: updateMiniPlayState() writes inline display on these icons. */
.mini-play-btn.loading svg { display: none !important; }

.mini-close {
  display: none;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  background: none;
  border: 0;
  cursor: pointer;
  font-size: 22px;
  line-height: 1;
  color: var(--muted);
}

.mini-close:hover { color: var(--text); }
.mini-player.episode-mode .mini-close { display: block; }

/* Episode mode: the live-only dot goes, our seek bar and source link appear. */
.mini-player.episode-mode .mini-status-dot { display: none; }
.mini-player.episode-mode .mini-track { flex: 0 1 30%; }

.mini-seek { display: none; }

.mini-player.episode-mode .mini-seek {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1 1 40%;
  min-width: 0;
}

.mini-time {
  flex-shrink: 0;
  min-width: 3.2em;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.mini-time:last-child { text-align: right; }

.mini-seek-range {
  flex: 1;
  min-width: 0;
  height: 28px;
  accent-color: var(--accent);
  cursor: pointer;
}

.mini-source {
  display: none;
  align-items: center;
  gap: 4px;
  min-height: 44px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
}

.mini-source:hover { color: var(--text); }
.mini-player.episode-mode .mini-source { display: inline-flex; }

/* The Mixcloud widget is driven from the controls above; its iframe stays in
   the page (it does the playing) but out of sight. */
#mixcloudFrame {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 1px;
  height: 1px;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

/* --- Responsive --- */
@media (max-width: 1080px) {
  .hero { flex-direction: column; align-items: stretch; gap: 48px; }
  .station-name { font-size: clamp(40px, calc((100vw - 136px) / 8), 112px); }
  .player { flex: none; width: 100%; max-width: 560px; min-width: 0; }
  .shows-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  .featured-layout { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .submit-content { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .submit-intro { grid-row: auto; }
  .faq-item { grid-template-columns: minmax(0, 1fr); gap: 10px; }
}

@media (max-width: 700px) {
  :root { --gutter: 20px; }
  .page { padding-bottom: 120px; }
  .station-name { font-size: clamp(32px, calc((100vw - 48px) / 8), 112px); }
  .hero { padding-top: 40px; gap: 36px; }
  .track-art { width: 88px; height: 88px; }
  .track-title { font-size: 22px; }
  .dial { margin-top: 48px; gap: 16px; }
  .play-btn { width: 56px; height: 56px; }
  #dialLabels { display: none; }
  .home-shows { margin-top: 64px; }

  .episode-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) 48px;
    grid-template-areas: "info info play" "date dur play";
    column-gap: 16px;
    row-gap: 6px;
    padding: 18px 0;
  }

  .episode-index { display: none; }
  .episode-info { grid-area: info; }
  .episode-title { font-size: 20px; }
  .episode-date { grid-area: date; width: auto; font-size: 11px; }
  .episode-meta { grid-area: dur; font-size: 11px; }
  .episode-play-btn { grid-area: play; }

  .home-foot-row { flex-direction: column; align-items: flex-start; }
  .home-credits { flex-direction: column; align-items: flex-start; }

  .shows-header, .featured-header, .chart-header, .about-header, .submit-header, .show-detail-header, .notfound-header { padding-top: 40px; }
  .shows-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px 16px; }
  .show-card h3 { font-size: 17px; }

  .chart-entry { gap: 14px; }
  .chart-rank { width: 32px; font-size: 22px; }
  .chart-art { width: 40px; height: 40px; }
  .chart-title { font-size: 17px; }
  .chart-stars, .chart-votes { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .track-line.scrolling .scroll-inner { animation: none; }
  .station-tagline .cursor { display: none; }
}

/* Honeypot for the submission form: invisible to people and screen readers,
   but bots that fill every input fill this too (see HONEYPOT_FIELD in server.py). */
.hp-field { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

/* Skip link: hidden until a keyboard user tabs to it. */
.skip-link {
  position: absolute;
  left: 12px;
  top: -64px;
  z-index: 300;
  padding: 12px 16px;
  background: var(--text);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: 2px;
}

.skip-link:focus { top: 12px; }

/* Page headings receive focus after navigation (so screen readers announce the
   new page); they aren't controls, so no focus ring. */
.page h1[tabindex="-1"]:focus,
.page h2[tabindex="-1"]:focus { outline: none; }

.notfound-back { padding-top: 32px; }

@media (max-width: 700px) {
  /* Episode mode on phones: the seek bar takes its own row. */
  .mini-player.episode-mode { flex-wrap: wrap; row-gap: 6px; }
  .mini-player.episode-mode .mini-track { flex: 1 1 0; }
  .mini-player.episode-mode .mini-seek { order: 10; flex-basis: 100%; }
  .mini-source-label { display: none; }
}

/* Fallback for browsers that only let audio start from a click inside
   Mixcloud's own player (Safari, strict autoplay settings). If playback
   doesn't start when asked, that player appears in the bar for the one
   click, then hides again and our controls take over. */
.mini-hint { display: none; }

.mini-player.needs-tap .mini-hint {
  display: block;
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.mini-player.needs-tap .mini-seek,
.mini-player.needs-tap .mini-play-btn { display: none; }

.mini-player.needs-tap #mixcloudFrame {
  position: static;
  flex: 1 1 320px;
  min-width: 0;
  width: auto;
  height: 60px;
  opacity: 1;
  pointer-events: auto;
}

@media (max-width: 700px) {
  .mini-player.needs-tap .mini-hint { order: 10; flex-basis: 100%; }
  .mini-player.needs-tap #mixcloudFrame { order: 11; flex-basis: 100%; }
}

/* --- Poem: a line of the station's voice, written across the screen ------ */
.poem-overlay {
  position: fixed;
  inset: 0;
  z-index: 250;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--gutter);
  pointer-events: none;            /* never blocks the player or the menu */
  overflow: hidden;                /* the lines deliberately run off the edges */
  opacity: 0;
  transition: opacity 0.8s ease;
}

.poem-overlay.show { opacity: 1; }
.poem-overlay.leaving { opacity: 0; transition-duration: 1.6s; }

/* A soft haze behind the words in the page's own tone, so the script stays
   legible over whatever is underneath: dark behind white on the dark theme,
   paper behind dark ink on the light theme. */
.poem-overlay::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 80% 65% at 50% 50%, rgba(247, 246, 242, 0.86), rgba(247, 246, 242, 0) 78%);
}

body.dark .poem-overlay::before {
  background: radial-gradient(ellipse 80% 65% at 50% 50%, rgba(12, 9, 34, 0.7), rgba(12, 9, 34, 0) 78%);
}

/* Sized by app.js so the whole tilted, staggered composition fits the
   screen; tilted slightly so the writing sweeps across it. */
.poem {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: 'WindSong', 'Snell Roundhand', 'Apple Chancery', cursive;
  font-weight: 500;
  font-size: 7vw;
  line-height: 1.12;
  color: #151517;                  /* dark ink on the light theme */
  text-align: center;
  text-shadow: 0 1px 22px rgba(247, 246, 242, 0.9);
  transform: rotate(-4deg);
}

body.dark .poem {
  color: #fff;
  text-shadow: 0 2px 30px rgba(10, 8, 30, 0.55);
}

/* The lines are staggered left to right (set per line by app.js) so they
   read as one diagonal sweep. */
.poem-line {
  display: block;
  white-space: nowrap;
}

/* Each line is written by sliding a window open over it: .poem-clip moves
   right while .poem-ink moves left by the same amount, so the words stay put
   and only the window's soft right edge travels along them like a pen.
   Both are transforms, which the browser animates off the main thread, so
   the writing stays smooth. The padding gives the swashes and the glow
   around the letters room inside the window, so neither is cut off at its
   edges; the negative margins keep it from changing the layout. */
.poem-clip {
  --room: calc(0.5em + 36px);
  display: inline-block;
  vertical-align: top;
  overflow: hidden;
  padding: var(--room) calc(var(--room) + 0.9em) var(--room) calc(var(--room) + 0.3em);
  margin: calc(-1 * var(--room)) calc(-1 * var(--room) - 0.6em) calc(-1 * var(--room)) calc(-1 * var(--room));
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 0.6em), transparent);
          mask-image: linear-gradient(90deg, #000 calc(100% - 0.6em), transparent);
}

.poem-ink { display: inline-block; }

/* --- The O thief: after a while on the home page, a little burglar climbs
   out of the O of RADIO, stands up wearing it, and walks off with it; a
   minute later he brings it back and sinks into it again (app.js). Every
   moving part is an HTML layer moved by transform only, so the motion runs
   on the compositor and stays smooth. */
.wordmark-o.stolen { visibility: hidden; }

.thief-stage {
  position: absolute;
  left: 0;
  width: 100%;
  z-index: 80;                     /* over the page, under the header and player */
  overflow: hidden;                /* he walks in from, and off, the edge of the screen */
  pointer-events: none;
  --thief-ink: #151517;
}

/* All parts are laid out from the O's pen position on the baseline. */
.thief-actor,
.thief-unit,
.thief-inner,
.thief-leg { position: absolute; left: 0; top: 0; will-change: transform; }

.thief-clip { position: absolute; overflow: hidden; will-change: transform; }
.thief-clip.open { overflow: visible; }

.thief-art { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; }
.thief-art .outline { stroke: var(--text); stroke-linecap: round; stroke-linejoin: round; }
.thief-art .suit { fill: var(--accent); }
.thief-art .ink { fill: var(--thief-ink); }
.thief-art .stripe { stroke: var(--thief-ink); fill: none; }
.thief-art .limb { fill: none; stroke: var(--text); stroke-linecap: round; }
.thief-art .eye { fill: #fff; }
.thief-art .pupil { fill: var(--thief-ink); }
.thief-art .pupils { transition: transform 0.25s ease; }

.thief-ring {
  position: absolute;
  left: 0;
  top: 0;
  line-height: 1;
  white-space: nowrap;
  text-transform: uppercase;
}

.thief-hands { opacity: 0; transition: opacity 0.15s ease; }
.thief-actor.gripping .thief-hands { opacity: 1; }

.thief-leg { transform-origin: 0 0; }
.thief-actor.walking .thief-leg-l { animation: thief-step 0.16s ease-in-out infinite alternate; }
.thief-actor.walking .thief-leg-r { animation: thief-step 0.16s ease-in-out infinite alternate-reverse; }
.thief-actor.facing-right .thief-leg svg { transform: scaleX(-1); }
.thief-actor.walking .thief-unit { animation: thief-bob 0.08s ease-in-out infinite alternate; }

@keyframes thief-step {
  from { transform: rotate(20deg); }
  to   { transform: rotate(-20deg); }
}

@keyframes thief-bob {
  from { transform: translateY(0); }
  to   { transform: translateY(var(--thief-bob, -2px)); }
}

/* People who ask their system for more contrast get firmer lines and dots:
   dividers, dial ticks and the idle status dots move up to the 3:1 outline
   tone, and the faintest text tone to the muted one. */
@media (prefers-contrast: more) {
  body,
  body.dark {
    --rule: var(--field);
    --tick: var(--field);
    --faint: var(--muted);
  }
}
