/*
	Garcia Project — Jerry Garcia Band Radio (web)

	Layout and styling follow the current iOS RadioView.swift. Values are taken from the
	SwiftUI source rather than invented:

		radioPurple  Color(red: 0.10, green: 0.05, blue: 0.16)  -> #1a0d29
		radioPanel   Color(red: 0.19, green: 0.11, blue: 0.28)  -> #301c47
		radioGold    Color(red: 0.86, green: 0.67, blue: 0.33)  -> #dbab54

	RadioView.body is a ScrollView over a VStack(spacing: 16) with .padding(16), so the page
	is a single column of cards separated by 16px. Cards use cornerRadius 20; GoldButtonStyle
	buttons use cornerRadius 10.
*/

:root {
	color-scheme: dark;
	--radio-purple: #1a0d29;
	--radio-panel: #301c47;
	--radio-gold: #dbab54;
	--ink: #ffffff;
	--muted: rgba(255, 255, 255, .8);
	--dim: rgba(255, 255, 255, .6);
	--faint: rgba(255, 255, 255, .45);
	--card-radius: 20px;
	--button-radius: 10px;
	--stack-gap: 16px;
	--page-pad: 16px;
}

* {
	box-sizing: border-box;
}

html {
	scroll-behavior: smooth;
	/* iOS keeps the safe area clear; the web equivalent is the page padding. */
	-webkit-text-size-adjust: 100%;
}

body {
	margin: 0;
	background: var(--radio-purple);
	color: var(--ink);
	font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	-webkit-font-smoothing: antialiased;
}

button,
a {
	touch-action: manipulation;
}

a {
	color: var(--radio-gold);
}

button {
	font: inherit;
	color: inherit;
	cursor: pointer;
	border: 0;
	background: none;
}

button:disabled {
	cursor: not-allowed;
	opacity: .45;
}

button:focus-visible,
a:focus-visible,
.radio-dial-face:focus-visible {
	outline: 3px solid var(--radio-gold);
	outline-offset: 3px;
	border-radius: 6px;
}

.radio-app {
	min-height: 100vh;
	overflow: hidden;
}

/* ------------------------------------------------------------------ header */

/* RadioView.header: BrandLogo scaledToFit, maxHeight 90, full width, centred, then a
   centred HStack of gold links separated by a dim pipe. */
/* The banner is pulled up so the crest breaks through the top of the chassis, which is why the
   header's bottom padding is large: the card's own top edge sits far below the nav, but the
   artwork rides up over it, so the perceived gap is nav -> crest, not nav -> card. */
.radio-header {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
	padding: 16px 16px 24px;
	text-align: center;
}

.radio-wordmark {
	display: block;
	width: 100%;
	line-height: 0;
}

.radio-wordmark .radio-brand-logo {
	display: block;
	width: 100%;
	max-width: 100%;
	max-height: 90px;
	height: auto;
	margin: 0 auto;
	object-fit: contain;
}

.radio-header-links {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	font: 700 15px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.radio-header-links a {
	color: var(--radio-gold);
	text-decoration: none;
}

.radio-header-links span {
	color: rgba(255, 255, 255, .55);
}

/* ------------------------------------------------------------------- stack */

/* VStack(alignment: .leading, spacing: 16) + .padding(16) */
.radio-stack {
	display: flex;
	flex-direction: column;
	gap: var(--stack-gap);
	max-width: 620px;
	margin: 0 auto;
	padding: 0 var(--page-pad) 32px;
}

.radio-card {
	background: var(--radio-panel);
	border-radius: var(--card-radius);
	padding: 16px;
}

/* The banner sits hard against the top of the card so the chassis reads as starting at the
   artwork rather than as an empty panel with a logo floating in the middle of it. Sides and
   bottom stay at 14px so every control below keeps the inset it had. overflow must stay visible
   so the overlapped banner is not clipped by the rounded corners. The gold hairline moved to
   ::before because the original single inset box-shadow painted an unbroken top edge that
   showed through the banner's transparent top margin as a stray line above the crest. The
   ::before renders the same hairline minus its top edge (the banner itself covers that edge),
   and sits under the banner's z-index so the artwork always wins. */
.radio-dials-card {
	padding: 12px 14px 14px;
	overflow: visible;
	position: relative;
}

.radio-dials-card::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	border-radius: var(--card-radius);
	/* RadioView.dials carries a gold hairline overlay; playerPanel does not. The 3px top clip
	   removes the top edge so nothing shows behind the banner; sides and the lower outline stay.
	   `round` keeps the clipped ring's corners on the same radius as the card. */
	box-shadow: inset 0 0 0 1px rgba(219, 171, 84, .6);
	clip-path: inset(3px 0 0 0 round var(--card-radius));
	pointer-events: none;
}

/* .caption.bold().tracking(2) in radioGold */
.radio-card-label {
	margin: 0;
	font: 700 12px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 2px;
	color: var(--radio-gold);
	text-transform: uppercase;
}

.radio-muted {
	color: var(--dim);
}

/* ------------------------------------------------------------------- dials */

/* .system(size: 27, weight: .black, design: .serif), centred */
/* The card heading is the supplied 3:1 logo. The <h1> stays as the page's single heading and
   carries the accessible name through the image alt, so the old display typography is gone and
   the card keeps its existing rhythm.

   The negative top margin is the intentional overlap: it lifts the crest through the card's top
   border so the chassis reads as sitting behind the banner. Because the margin is negative, the
   card's flow height shrinks by exactly the same amount, which is what pulls the dials up and
   leaves no blank gap where the banner used to sit. position/z-index keep the artwork above the
   card's inset gold hairline. Per-breakpoint values live in radio-refinement.css. */
.radio-dials-title {
	margin: -25px 0 0;
	position: relative;
	z-index: 2;
	overflow: visible;
	text-align: center;
}

/* <picture> is inline by default, which would leave the block image resolving against an
   anonymous line box instead of the card. */
.radio-dials-title picture {
	display: block;
}

/* The banner breaks out of the card on all four sides so the chassis reads as sitting behind
   the artwork. The card's side padding is 14px and the artwork adds a ~1% transparent margin of
   its own, so a 22px negative margin is what actually pushes the *visible* artwork past the
   card's border (by 1.8px on tablet, 4.4px on a phone) instead of only reaching it.
   Desktop widens this further in radio-refinement.css.

   Height is auto and object-fit is contain, so the 3:1 artwork is never cropped or distorted,
   and equal negative margins keep it exactly centred. max-width must be released, otherwise
   the 100% cap would fight the wider box. The delivered image is 1560px wide, which covers the
   widest rendered banner (756px) at over 2x. */
.radio-dials-logo {
	display: block;
	width: calc(100% + 44px);
	max-width: none;
	height: auto;
	margin: 0 -22px;
	object-fit: contain;
}

/* HStack(alignment: .top, spacing: 16) */
.radio-dials {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	margin-top: 15px;
}

.radio-dial-cell {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	flex: 1 1 0;
	min-width: 0;
}

.radio-dial-label {
	font: 700 12px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 2px;
	color: var(--radio-gold);
	text-align: center;
}

/* RotaryDial is .frame(maxWidth: 160).frame(height: 160). The redesign reads as an antique
   instrument gauge screwed into the console: a mottled aged-brass rim (a conic sweep so the
   metal reads as cast rather than flat), a deeply recessed dark face, engraved ticks near the
   rim, a thinner tapered needle, and a machined hub. Sizes and stacking order match the old
   geometry — bezel outside, face at inset 5px, ticks at inset 7px — so responsive widths in
   radio-refinement.css and the rotation math keep working unchanged. */
.radio-dial-bezel {
	position: relative;
	width: min(160px, 100%);
	aspect-ratio: 1;
	border-radius: 50%;
	/* Aged brass: a warm top sheen over a conic sweep that varies the rim's tint like worn,
	   unpolished metal. The layered inset shadows model the rim's bevel: a lit lip at the top,
	   a dark drop toward the face, and deep ambient shadow under the whole gauge. */
	background:
		radial-gradient(circle at 50% 26%, rgba(255, 238, 196, .38) 0%, rgba(255, 238, 196, 0) 50%),
		/* Patina mottling: faint cool verdigris and dark oxide blooms, far below readability
		   concern and only on the metal ring itself. */
		radial-gradient(circle at 70% 76%, rgba(108, 126, 110, .16) 0%, rgba(108, 126, 110, 0) 26%),
		radial-gradient(circle at 22% 72%, rgba(56, 36, 16, .3) 0%, rgba(56, 36, 16, 0) 24%),
		radial-gradient(circle at 40% 12%, rgba(46, 60, 58, .14) 0%, rgba(46, 60, 58, 0) 20%),
		radial-gradient(circle at 86% 30%, rgba(232, 196, 130, .18) 0%, rgba(232, 196, 130, 0) 22%),
		conic-gradient(
			from 15deg,
			#a8853f 0deg, #7e5220 28deg, #5c3a15 62deg, #97723a 112deg,
			#c8a254 168deg, #83551f 214deg, #63401a 262deg, #9a7a3a 308deg,
			#c09a4a 340deg, #a8853f 360deg
		);
	box-shadow:
		0 14px 12px rgba(0, 0, 0, .72),
		0 5px 5px rgba(0, 0, 0, .55),
		inset 0 2px 2px rgba(255, 240, 205, .55),
		inset 0 -3px 4px rgba(38, 20, 8, .85),
		inset 0 0 0 1px rgba(60, 34, 14, .8);
}

.radio-dial-face {
	position: absolute;
	inset: 5px;
	border-radius: 50%;
	/* Dark recessed face: a near-black umber dish sitting below the rim. The inner shadows push
	   it down into the bezel: a wide dark upper shadow, a soft contact ring, and a faint brass
	   hairline where the face meets the metal. The two whisper-faint rings near the middle give
	   the face an etched, machined instrument detail that stays well below the tick band in
	   brightness and leaves the reading area between needle and hub uncluttered. */
	background:
		radial-gradient(circle, transparent 0 57%, rgba(219, 171, 84, .085) 57% 58.5%, transparent 60%),
		radial-gradient(circle, transparent 0 52%, rgba(219, 171, 84, .05) 52% 54%, transparent 55%),
		radial-gradient(circle at 50% 40%, #2b1b2c 0%, #150c20 58%, #0c0713 100%);
	box-shadow:
		inset 0 4px 9px rgba(0, 0, 0, .9),
		inset 0 -2px 5px rgba(0, 0, 0, .6),
		inset 0 0 0 1px rgba(219, 171, 84, .3);
	cursor: grab;
	touch-action: none;
	user-select: none;
	-webkit-user-select: none;
}

/* Glass cover. The hairline that used to live here is now part of the face's inset shadows, so
   this pseudo paints only a soft curved reflection that falls off before the middle of the dial,
   like light on an antique bevel-glass cover. */
.radio-dial-face::after {
	content: "";
	position: absolute;
	inset: 2px;
	border-radius: 50%;
	background: linear-gradient(
		155deg,
		rgba(255, 255, 255, .14) 0%,
		rgba(255, 255, 255, .06) 24%,
		rgba(255, 255, 255, 0) 40%
	);
	pointer-events: none;
}

.radio-dial-face:active {
	cursor: grabbing;
}

.radio-dial-face[aria-disabled="true"] {
	cursor: not-allowed;
}

/* The disabled date dial must not fade the face itself: a translucent face over the bright
   bezel reads as a solid brass disc. The recess stays opaque; only what is printed on the face
   (ticks, needle, readout) dims. */
.radio-dial-face[aria-disabled="true"]::before,
.radio-dial-face[aria-disabled="true"] > * {
	opacity: .45;
}

/* RotaryDial draws 21 ticks at offset(y: -side * 0.38) rotated -135 + 270 * tick/20, i.e. a
   13.5 degree step across a 270 degree sweep. The engraved look comes from a dim brass tick
   body plus a brighter butt on every sixth tick, and the tick band hugs the rim so the middle
   of the face stays clear for the needle and the readout. */
.radio-dial-face::before {
	content: "";
	position: absolute;
	inset: 7px;
	border-radius: 50%;
	background: repeating-conic-gradient(
		from -135deg,
		rgba(224, 182, 106, .78) 0deg 1.1deg,
		transparent 1.1deg 12.75deg,
		rgba(235, 198, 124, 1) 12.75deg 13.5deg,
		transparent 13.5deg 13.5deg
	);
	-webkit-mask: radial-gradient(transparent 0 73%, #000 74% 88%, transparent 89%);
	mask: radial-gradient(transparent 0 73%, #000 74% 88%, transparent 89%);
	pointer-events: none;
}

.radio-dial-face > * {
	pointer-events: none;
}

/* RotaryDial bolts sit at offset(y: -side * 0.46), outside the tick band. They read as slotted
   screws: a turned brass head with a dark slot. Alternate screws tilt their slot, the way a
   real chassis is tightened down. */
.radio-dial-bolts {
	position: absolute;
	inset: 7px;
	border-radius: 50%;
}

.radio-dial-bolts i {
	position: absolute;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background:
		linear-gradient(90deg, rgba(24, 12, 5, .9), rgba(24, 12, 5, .9)) 50% 50% / 4.2px 1.2px no-repeat,
		radial-gradient(circle at 50% 30%, #dfb46e 0%, #8a5b26 70%, #5f3c18 100%);
	box-shadow: 0 0 0 .8px rgba(40, 24, 10, .75), 0 1px 1px rgba(0, 0, 0, .7);
}

.radio-dial-bolts i:nth-child(even) {
	transform: rotate(35deg);
}

.radio-dial-bolts i:nth-child(1) {
	top: 2%;
	left: 2%;
}

.radio-dial-bolts i:nth-child(2) {
	top: 2%;
	right: 2%;
}

.radio-dial-bolts i:nth-child(3) {
	bottom: 2%;
	left: 2%;
}

.radio-dial-bolts i:nth-child(4) {
	bottom: 2%;
	right: 2%;
}

/* Capsule().frame(width: side * 0.35, height: 5) with .offset(x: side * 0.17) and
   .rotationEffect(angle). SwiftUI pivots the bar just off centre and sweeps -135 to +135
   degrees; a bar anchored at the centre reaching outward lands in the same place. The
   mechanical look comes from a thinner, tapered blade with a brass body and a bright tip,
   dropping a small shadow onto the face like a real pointer lifts off the dial. */
.radio-dial-hand {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 36%;
	height: 3px;
	margin-top: -1.5px;
	clip-path: polygon(0 50%, 4% 0, 88% 32%, 100% 50%, 88% 68%, 4% 100%);
	/* Brass body with a brighter metallic tip; the faint centre ridge reads as a folded /
	   dimensional blade edge. The rotation transform is untouched. */
	background:
		linear-gradient(90deg, rgba(255, 255, 255, 0) 62%, rgba(255, 244, 214, .55) 88%, rgba(255, 250, 230, .85) 100%),
		linear-gradient(90deg, rgba(0, 0, 0, 0) 30%, rgba(255, 255, 255, .18) 49%, rgba(0, 0, 0, .22) 52%, rgba(0, 0, 0, 0) 70%),
		linear-gradient(180deg, #eec987 0%, #c59a52 48%, #7a4c1e 100%);
	box-shadow: 0 1px 3px rgba(0, 0, 0, .8);
	transform-origin: 0 50%;
	transform: rotate(var(--dial-angle, -135deg));
}

.radio-date-dial .radio-dial-hand {
	transform: rotate(var(--date-angle, -135deg));
}

/* Circle().fill(radioGold).frame(14) with a dark 2pt ring, centred on the dial. Now a machined
   brass hub: a domed radial top, a soft specular edge, a dark seat ring that locks it to the
   needle end, a fine inner rim shadow for depth, and a screwdriver slot across the centre. */
.radio-dial-pin {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 15px;
	height: 15px;
	margin: -7.5px 0 0 -7.5px;
	border-radius: 50%;
	background:
		linear-gradient(90deg, rgba(24, 12, 5, .85), rgba(24, 12, 5, .85)) 50% 50% / 8px 1.6px no-repeat,
		radial-gradient(circle at 44% 8%, rgba(255, 246, 214, .5) 0%, rgba(255, 246, 214, 0) 55%),
		radial-gradient(circle at 50% 32%, #f2d494 0%, #c59a52 42%, #997334 70%, #6f451c 100%);
	box-shadow:
		0 0 0 2px #2a1810,
		0 0 0 3px rgba(219, 171, 84, .45),
		0 2px 3px rgba(0, 0, 0, .85),
		inset 0 1px 1px rgba(255, 240, 200, .5),
		inset 0 -1px 1px rgba(40, 22, 10, .8);
}

/* detail (14 black monospaced) over title (8 bold), offset(y: side * 0.25). The block was
   lifted from 77% to 72% and given a taller gap so the subtitle sits clearly inside the dark
   face: on the iPhone's 160px dial the old position put "Recorded show date" against the
   inner brass ring. Both dials share this block, so YEAR and RECORDED DATE stay consistent. */
.radio-dial-center {
	position: absolute;
	top: 72%;
	left: 50%;
	transform: translate(-50%, 0);
	width: 76%;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 5px;
	color: var(--radio-gold);
	text-align: center;
}

.radio-dial-center span {
	font: 900 14px/1.1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	letter-spacing: .02em;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* One size up (8px -> 9px) and a calmer brass tone: gold-on-dark at 8px was the part that
   read faintly, especially over the ring at the old position. */
.radio-dial-center small {
	font: 700 9px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: .05em;
	white-space: nowrap;
	color: #dcb875;
	opacity: .95;
}

/* selected date block */
.radio-selected {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 3px;
	margin-top: 15px;
	text-align: center;
	min-height: 34px;
}

.radio-selected strong {
	font: 700 15px/1.25 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--radio-gold);
}

.radio-selected > span {
	font: 400 12px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--muted);
	max-width: 100%;
}

.radio-selected-count {
	font: 600 11px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
	color: var(--faint) !important;
}

.radio-selected-count[hidden] {
	display: none;
}

/* ----------------------------------------------------------------- buttons */

/* GoldButtonStyle: subheadline bold, full width, v10 h8, purple on gold, radius 10. */
.radio-gold-button {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 44px;
	padding: 10px 8px;
	border-radius: var(--button-radius);
	background: var(--radio-gold);
	color: var(--radio-purple);
	font: 700 15px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	text-align: center;
	text-decoration: none;
	transition: background .15s ease, transform .1s ease;
}

.radio-gold-button:hover:not(:disabled) {
	background: #e5bc6c;
}

.radio-gold-button:active:not(:disabled) {
	transform: scale(.985);
}

.radio-tune-in {
	margin-top: 14px;
	font-size: 17px;
	padding: 12px 8px;
}

/* HStack(spacing: 10) of caption buttons */
.radio-discovery {
	display: flex;
	gap: 10px;
}

.radio-discovery .radio-gold-button {
	font-size: 13px;
	padding: 9px 6px;
}

/* ------------------------------------------------------------------ player */

.radio-player-card {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

/* date · venue as .title2.bold */
.radio-now-show {
	margin: 0;
	font: 700 22px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--ink);
}

.radio-now-place {
	margin: 0;
	font: 400 17px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--muted);
}

.radio-now-place:empty,
.radio-now-track:empty {
	display: none;
}

/* track title as .headline in gold */
.radio-now-track {
	margin: 0;
	font: 600 17px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--radio-gold);
}

.radio-status {
	margin: 0;
	font: 400 15px/1.35 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--muted);
	min-height: 20px;
}

.radio-loading {
	display: inline-block;
	width: 15px;
	height: 15px;
	border: 2px solid rgba(219, 171, 84, .3);
	border-top-color: var(--radio-gold);
	border-radius: 50%;
	animation: radio-spin .8s linear infinite;
}

.radio-loading[hidden] {
	display: none;
}

@keyframes radio-spin {
	to {
		transform: rotate(360deg);
	}
}

/* ------------------------------------------------- stereo meters (Web Audio) */

/* StereoAmplifierView: HStack(spacing: 6) of two 13x93 rack handles around the meter pair,
   v12 h8 padding, cornerRadius 7, brushed-metal gradient. Meters are driven by real Web
   Audio analysis in radio.js -- the blue backlight only changes brightness. */
.radio-stereo {
	position: relative;
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 12px 8px;
	border-radius: 7px;
	background: linear-gradient(135deg, #C9CFD1 0%, #828A92 48%, #B8BEC2 100%);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .65), 0 6px 16px rgba(0, 0, 0, .5);
}

.radio-rack-handle {
	flex: 0 0 13px;
	width: 13px;
	height: 93px;
	border-radius: 4px;
	background: linear-gradient(90deg, rgba(255, 255, 255, .95) 0%, #666E75 50%, rgba(255, 255, 255, .7) 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .55), 3px 3px 3px rgba(0, 0, 0, .65);
}

.radio-vu-pair {
	display: flex;
	align-items: flex-start;
	gap: 7px;
	flex: 1 1 auto;
	min-width: 0;
}

.radio-vu {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	flex: 1 1 0;
	min-width: 0;
}

.radio-vu-window {
	position: relative;
	height: 70px;
	padding: 5px;
	border: 2px solid #000;
	border-radius: 3px;
	background: #060910;
	overflow: hidden;
}

.radio-vu-backlight {
	position: absolute;
	inset: 5px;
	border-radius: 2px;
	background: linear-gradient(#05337F 0%, #11AEF7 55%, #0D6BBD 100%);
	opacity: .55;
	transition: opacity .25s ease;
}

/* lit only while audio is actually playing */
.radio-stereo.is-live .radio-vu-backlight {
	opacity: 1;
	box-shadow: 0 0 8px rgba(0, 132, 255, .75);
	animation: radio-vu-glow 2.6s ease-in-out infinite alternate;
}

@keyframes radio-vu-glow {
	from {
		opacity: .8;
	}

	to {
		opacity: 1;
	}
}

/* tick geometry from StereoAmplifierView.amplifierMeter */
.radio-vu-scale {
	position: absolute;
	inset: 5px;
	pointer-events: none;
}

.radio-vu-scale i {
	position: absolute;
	width: 1px;
	background: rgba(0, 0, 0, .7);
}

/* pivot at (50%, 91%), length 67%, angle -55deg + level * 110deg */
.radio-vu-needle {
	position: absolute;
	left: 50%;
	bottom: 9%;
	width: 1.7px;
	height: 67%;
	border-radius: 1px;
	background: #141A24;
	transform-origin: 50% 100%;
	transform: rotate(calc(-55deg + var(--vu, 0) * 110deg));
	transition: transform 50ms linear;
	z-index: 3;
}

.radio-vu-mark {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 1px;
	text-align: center;
	font: 600 8px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
	color: rgba(0, 0, 0, .65);
	z-index: 2;
}

.radio-vu strong {
	display: block;
	margin-top: 2px;
	text-align: center;
	font: 900 9px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
	letter-spacing: 2px;
	color: rgba(0, 0, 0, .8);
}

.radio-vu-unavailable {
	position: absolute;
	right: 10px;
	bottom: 6px;
	padding: 3px 6px;
	border-radius: 4px;
	background: rgba(240, 205, 140, .8);
	color: #3A2A10;
	font: 800 10px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: .1em;
	text-transform: uppercase;
}

.radio-vu-unavailable[hidden] {
	display: none;
}

/* --------------------------------------------------------------- transport */

/* HStack(spacing: 24) of gobackward.15 / backward / play / forward / goforward.15,
   .font(.title2) in gold, play at 54pt. */
.radio-transport {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	width: 100%;
	color: var(--radio-gold);
}

.radio-transport button {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 1px;
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	color: var(--radio-gold);
	transition: transform .1s ease, background .15s ease;
}

.radio-transport button:hover:not(:disabled) {
	background: rgba(219, 171, 84, .12);
}

.radio-transport button:active:not(:disabled) {
	transform: scale(.92);
}

.radio-transport svg {
	width: 22px;
	height: 22px;
	fill: currentColor;
}

.radio-transport-skip svg {
	width: 24px;
	height: 24px;
}

.radio-transport-skip span {
	font: 700 9px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
	letter-spacing: .04em;
}

/* 54pt circle */
.radio-transport-play {
	width: 54px !important;
	height: 54px !important;
}

.radio-transport-play svg {
	width: 54px;
	height: 54px;
}

.radio-transport-play .radio-icon-pause {
	display: none;
}

.radio-transport-play[aria-label="Pause"] .radio-icon-play {
	display: none;
}

.radio-transport-play[aria-label="Pause"] .radio-icon-pause {
	display: block;
}

/* Song position: elapsed time, a thin seekable bar, then total duration. It sits with the
   transport rather than the VU/EQ rack, and reuses the same gold as the transport glyphs so it
   reads as part of the playback row instead of another instrument module. */
.radio-progress {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
}

.radio-progress-time {
	flex: 0 0 auto;
	min-width: 3.2em;
	font: 600 12px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
	font-variant-numeric: tabular-nums;
	letter-spacing: .02em;
	color: var(--radio-gold);
	opacity: .9;
	text-align: center;
}

.radio-progress-time:last-of-type {
	text-align: right;
}

/* The bar is deliberately short. It carries a transparent padding box so the touch target is a
   comfortable 24px tall even though the visible rail is only 4px, which matters on iPhone. */
.radio-progress-track {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
	height: 4px;
	padding: 10px 0;
	background-clip: content-box;
	background-color: rgba(219, 171, 84, .22);
	border-radius: 999px;
	cursor: pointer;
	touch-action: none;
}

.radio-progress-track:focus-visible {
	outline: 2px solid var(--radio-gold);
	outline-offset: 3px;
}

/* The fill carries the playhead dot at its trailing edge, so the head always sits exactly at the
   reported position even when the rail is empty and the dot is all that is visible. */
.radio-progress-played {
	position: absolute;
	top: 50%;
	left: 0;
	height: 4px;
	width: 0;
	margin-top: -2px;
	border-radius: 999px;
	background: linear-gradient(90deg, rgba(219, 171, 84, .55), var(--radio-gold));
	pointer-events: none;
}

.radio-progress-played::after {
	content: "";
	position: absolute;
	top: 50%;
	right: 0;
	width: 8px;
	height: 8px;
	margin-top: -4px;
	margin-right: -4px;
	border-radius: 50%;
	background: var(--radio-gold);
	box-shadow: 0 0 0 2px rgba(26, 13, 41, .9);
}

/* Until metadata arrives there is nothing to seek within, so the row reads as inert rather than
   as a control that silently refuses input. */
.radio-progress[data-ready="false"] .radio-progress-track {
	cursor: default;
	opacity: .45;
}

.radio-progress[data-ready="false"] .radio-progress-played::after {
	display: none;
}

.radio-show-nav {
	display: flex;
	gap: 10px;
}

.radio-divider {
	width: 100%;
	height: 1px;
	margin: 4px 0;
	border: 0;
	background: rgba(219, 171, 84, .4);
}

/* ------------------------------------------------------------- recordings */

/* Integrated into the player card: a compact selector rather than a separate panel. */
.radio-source-panel[hidden] {
	display: none;
}

.radio-source-current {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
}

.radio-source-badge {
	padding: 2px 8px;
	border-radius: 999px;
	background: var(--radio-gold);
	color: var(--radio-purple);
	font: 800 10px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: .08em;
	text-transform: uppercase;
}

.radio-source-meta {
	font: 400 12px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--dim);
}

.radio-source-list {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin-top: 4px;
}

.radio-source-row {
	padding: 10px 12px;
	border-radius: var(--button-radius);
	background: rgba(255, 255, 255, .06);
}

.radio-source-row.is-selected {
	box-shadow: inset 0 0 0 1px rgba(219, 171, 84, .8);
	background: rgba(219, 171, 84, .12);
}

.radio-source-head {
	display: flex;
	align-items: center;
	gap: 8px;
	justify-content: space-between;
}

.radio-source-name {
	font: 700 13px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--ink);
}

.radio-source-select {
	flex: 0 0 auto;
	padding: 5px 10px;
	border-radius: 8px;
	background: var(--radio-gold);
	color: var(--radio-purple);
	font: 700 11px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.radio-source-description {
	display: block;
	margin-top: 4px;
	font: 400 12px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--muted);
}

/* Extracted from the Archive.org description: provenance first, then the notes a listener
   actually wants, both hidden behind one disclosure so a long source list stays tidy. */
.radio-source-description > summary {
	cursor: pointer;
	color: var(--radio-gold);
	font-weight: 700;
}

.radio-source-facts {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 2px 8px;
	margin: 6px 0 0;
}

.radio-source-facts dt {
	color: var(--faint);
}

.radio-source-facts dd {
	margin: 0;
	color: var(--muted);
	overflow-wrap: anywhere;
}

.radio-source-notes {
	margin: 6px 0 0;
	padding-left: 16px;
}

.radio-source-notes li {
	margin: 0 0 3px;
	color: var(--muted);
}

/* ------------------------------------------------------------------ tracks */

.radio-tracks {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.radio-tracks .radio-empty {
	font: 400 13px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--faint);
}

.radio-tracks button {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 7px 8px;
	border-radius: 8px;
	text-align: left;
	font: 400 15px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--ink);
	transition: background .12s ease;
}

.radio-tracks button:hover {
	background: rgba(255, 255, 255, .06);
}

.radio-tracks button.is-current {
	background: rgba(219, 171, 84, .14);
}

.radio-track-number {
	flex: 0 0 auto;
	font: 700 13px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
	color: var(--radio-gold);
}

.radio-tracks button strong {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-weight: 400;
}

.radio-tracks button.is-current strong {
	color: var(--radio-gold);
	font-weight: 600;
}

.radio-track-length {
	flex: 0 0 auto;
	font-size: 13px;
	color: rgba(255, 255, 255, .55);
	font-variant-numeric: tabular-nums;
}

/* radioPurple pill, cornerRadius 10 */
.radio-recreated {
	margin: 0;
	padding: 10px 12px;
	border-radius: var(--button-radius);
	background: var(--radio-purple);
	color: var(--ink);
	font: 700 15px/1.35 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	text-align: center;
}

.radio-recreated[hidden] {
	display: none;
}

/* ----------------------------------------------------------- archive links */

/* RadioView.archiveLinks sits last, after the site's own sections. */
.radio-archive-links {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
	padding: 0 var(--page-pad);
	max-width: 620px;
	margin: 0 auto;
}

/* Same treatment as the band's photo, and square rather than circular so the artwork keeps
   its own shape inside the reserved slot. */
.radio-archive-thumb {
	flex: 0 0 auto;
	width: 76px;
	height: 76px;
	object-fit: contain;
	border-radius: 0;
}

.radio-archive-nav {
	display: flex;
	flex-direction: column;
	gap: 8px;
	font: 400 15px/1.35 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.radio-archive-nav a {
	color: var(--radio-gold);
	text-decoration: none;
}

.radio-archive-nav a:hover {
	text-decoration: underline;
}

.radio-archive-note {
	flex: 1 1 100%;
	margin: 0;
	font: 400 12px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--dim);
}

.radio-archive-link {
	flex: 1 1 100%;
	font-size: 12px;
	color: var(--radio-gold);
}

.radio-archive-link[hidden] {
	display: none;
}

/* -------------------------------------------------------------- disclaimer */

/* Identity/legal clarification, not marketing and not a warning. It sits in the existing
   footer at the same 12px scale as the archive note, in dim text so it reads as quieter than
   the gold navigation links, and it uses a native <details> so there is no JavaScript, no modal
   focus trap and no extra card in the main radio column. */
.radio-disclaimer {
	flex: 1 1 100%;
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 2px 6px;
}

.radio-disclaimer-note {
	margin: 0;
	font: 400 12px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--dim);
}

/* The note wraps to fill the row, so the trigger lands on the line directly beneath it, left
   aligned with the rest of the footer content. Open, the details claims a full row for the
   body text. */
.radio-disclaimer-details {
	flex: 0 0 auto;
}

.radio-disclaimer-details[open] {
	flex: 1 1 100%;
	margin-top: 8px;
}

/* The default disclosure triangle is dropped so this looks like the other footer links rather
   than a widget, and the marker is hidden explicitly for WebKit. */
.radio-disclaimer-summary {
	display: inline-block;
	font: 400 12px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--radio-gold);
	cursor: pointer;
	list-style: none;
}

.radio-disclaimer-summary::-webkit-details-marker {
	display: none;
}

.radio-disclaimer-summary:hover {
	text-decoration: underline;
}

.radio-disclaimer-summary:focus-visible {
	outline: 3px solid var(--radio-gold);
	outline-offset: 3px;
	border-radius: 6px;
}

.radio-disclaimer-body {
	flex: 1 1 100%;
	margin-top: 8px;
	padding-left: 10px;
	border-left: 2px solid rgba(219, 171, 84, .35);
}

.radio-disclaimer-heading {
	margin: 0 0 6px;
	font: 700 12px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 2px;
	text-transform: uppercase;
	color: var(--radio-gold);
}

.radio-disclaimer-body p {
	margin: 0 0 8px;
	font: 400 12px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--muted);
}

.radio-disclaimer-body p:last-child {
	margin-bottom: 0;
}

/* ------------------------------------------------------------ graphic equalizer */

/* The compact module is the same rack hardware as .radio-stereo, so it borrows that brushed
   plate and chrome handles and only adds height. It is a real button, but it is dressed as a
   panel rather than a modern button: no border radius jump, no fill change on hover, only the
   engraved plate darkens slightly and the cursor plus focus ring signal that it is operable. */
.radio-eq-module {
	display: flex;
	align-items: center;
	gap: 6px;
	width: 100%;
	padding: 5px 8px;
	border: 0;
	border-radius: 7px;
	background: linear-gradient(135deg, #C9CFD1 0%, #828A92 48%, #B8BEC2 100%);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .65), 0 4px 12px rgba(0, 0, 0, .45);
	font: inherit;
	color: inherit;
	text-align: left;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
}

.radio-eq-module:hover .radio-eq-plate {
	background: linear-gradient(180deg, #26262A 0%, #141416 100%);
}

.radio-eq-module:focus-visible {
	outline: 3px solid var(--radio-gold);
	outline-offset: 3px;
}

/* radio-refinement.css restyles .radio-rack-handle inside media queries. Those rules tie on
   specificity but win by source order, so the short module handles need the extra class weight. */
.radio-eq-module .radio-rack-handle-eq {
	height: 30px;
}

/* Dark inset face with the engraved gold legend, so the module reads as a fitted panel. */
.radio-eq-plate {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 4px 9px;
	border-radius: 3px;
	background: linear-gradient(180deg, #26262A 0%, #141416 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .8), inset 0 1px 0 rgba(255, 255, 255, .12);
	transition: background .12s ease;
}

.radio-eq-screw {
	position: absolute;
	top: 50%;
	left: 3px;
	width: 4px;
	height: 4px;
	margin-top: -2px;
	border-radius: 50%;
	background: radial-gradient(circle at 35% 30%, #F2F4F5 0%, #7C848B 60%, #3C4247 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .5);
}

.radio-eq-screw-right {
	left: auto;
	right: 3px;
}

.radio-eq-brand {
	flex: 0 0 auto;
	font: 700 9px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 1.4px;
	color: var(--radio-gold);
	text-shadow: 0 1px 0 rgba(0, 0, 0, .8);
	white-space: nowrap;
}

/* Seven miniature faders that mirror the real gains. --eq is 0..1, written by radio.js. */
.radio-eq-mini {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 3px;
	height: 20px;
	padding: 0 1px;
}

.radio-eq-mini-band {
	position: relative;
	flex: 1 1 0;
	min-width: 0;
	max-width: 9px;
	height: 20px;
	border-radius: 1px;
	background: linear-gradient(180deg, #0B0B0D 0%, #171719 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .9);
}

.radio-eq-mini-band::after {
	/* 0 dB centre mark */
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 1px;
	background: rgba(219, 171, 84, .35);
}

.radio-eq-mini-slider {
	position: absolute;
	left: 0;
	right: 0;
	bottom: calc(var(--eq, .5) * 100%);
	height: 3px;
	margin-bottom: -1px;
	border-radius: 1px;
	background: linear-gradient(180deg, #F0DCAE 0%, var(--radio-gold) 55%, #9A7430 100%);
	box-shadow: 0 0 3px rgba(219, 171, 84, .55);
}

.radio-eq-state {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 4px;
	font: 700 9px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 1.2px;
	color: rgba(255, 255, 255, .78);
	white-space: nowrap;
}

.radio-eq-state::before {
	content: "";
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: #6E7480;
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .6);
}

.radio-eq-state.is-on::before {
	background: #6FD08C;
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .5), 0 0 5px rgba(111, 208, 140, .85);
}

/* ---------------------------------------------------------- expanded EQ overlay */

/* --- Personal Library (v0.4.5) ------------------------------------------------------
   A single compact control row inside the existing player card, plus one native dialog
   mirroring the EQ modal. Everything here is scoped to .radio-lib-* / .radio-library-*
   so the dials, rack geometry, transport, meters and recording selector are untouched. */

.radio-library-bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 10px;
	margin-bottom: 14px;
	padding-bottom: 14px;
	border-bottom: 1px solid rgba(255, 255, 255, .12);
}

.radio-lib-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	min-height: 40px;
	padding: 0 12px;
	border: 0;
	border-radius: 8px;
	background: rgba(255, 255, 255, .1);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
	color: var(--muted);
	font: 700 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 1.1px;
	white-space: nowrap;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
}

.radio-lib-btn:hover:not(:disabled) {
	color: var(--ink);
	background: rgba(255, 255, 255, .16);
}

.radio-lib-btn:disabled {
	opacity: .4;
	cursor: default;
}

.radio-lib-btn:focus-visible,
.radio-lib-star:focus-visible,
.radio-lib-input:focus-visible {
	outline: 2px solid var(--radio-gold);
	outline-offset: 2px;
}

/* The Library entry point is the one primary action in the row. */
.radio-lib-open {
	background: var(--radio-gold);
	box-shadow: none;
	color: var(--radio-purple);
}

.radio-lib-open:hover:not(:disabled) {
	background: #e5bc6c;
	color: var(--radio-purple);
}

.radio-lib-fav-icon {
	font-size: 15px;
	line-height: 1;
}

.radio-lib-fav.is-active {
	background: rgba(219, 171, 84, .22);
	box-shadow: inset 0 0 0 1px rgba(219, 171, 84, .7);
	color: var(--radio-gold);
}

.radio-lib-fav.is-active .radio-lib-fav-icon {
	color: var(--radio-gold);
}

.radio-lib-rating {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-width: 0;
}

.radio-lib-rating-label {
	color: var(--dim);
	font: 700 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 1.1px;
	white-space: nowrap;
}

/* 40px square touch targets, larger than the 44px minimum only where the row allows. */
.radio-lib-stars {
	display: inline-flex;
	align-items: center;
	gap: 2px;
}

.radio-lib-star {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 8px;
	background: transparent;
	color: rgba(255, 255, 255, .32);
	font-size: 26px;
	line-height: 1;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
	-webkit-tap-highlight-color: transparent;
}

.radio-lib-star.is-on {
	color: var(--radio-gold);
}

.radio-lib-star:hover:not(:disabled) {
	color: rgba(219, 171, 84, .8);
}

.radio-lib-star:disabled {
	cursor: default;
}

.radio-lib-warning {
	flex-basis: 100%;
	margin: 0;
	color: var(--faint);
	font: 400 12px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.radio-lib-dialog {
	width: min(640px, calc(100vw - 24px));
	max-width: calc(100vw - 24px);
	max-height: calc(100dvh - 32px);
	padding: 0;
	border: 0;
	border-radius: 14px;
	background: transparent;
	color: var(--ink);
	overflow: visible;
}

.radio-lib-dialog::backdrop {
	background: rgba(10, 5, 18, .74);
}

/* Same scroll-lock class pattern the EQ uses so the dials cannot move behind the overlay. */
html.radio-lib-open,
html.radio-lib-open body {
	overflow: hidden;
}

.radio-lib-panel {
	display: flex;
	flex-direction: column;
	gap: 18px;
	max-height: calc(100dvh - 40px);
	padding: 18px 16px;
	border-radius: 14px;
	background: linear-gradient(180deg, var(--radio-panel) 0%, var(--radio-purple) 100%);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14), 0 18px 44px rgba(0, 0, 0, .6);
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior: contain;
}

.radio-lib-head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
}

.radio-lib-title {
	margin: 0;
	font: 700 18px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 1.6px;
	color: var(--radio-gold);
}

.radio-lib-note {
	margin: 0;
	color: var(--faint);
	font: 400 12px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

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

.radio-lib-section-title {
	margin: 0;
	color: var(--muted);
	font: 700 12px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 1.4px;
}

.radio-lib-sort {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.radio-lib-sort-btn.is-active {
	background: rgba(219, 171, 84, .2);
	box-shadow: inset 0 0 0 1px rgba(219, 171, 84, .7);
	color: var(--radio-gold);
}

.radio-lib-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.radio-lib-row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: 6px 12px;
	align-items: center;
	padding: 11px 0;
	border-top: 1px solid rgba(255, 255, 255, .1);
}

.radio-lib-row:first-child {
	border-top: 0;
}

.radio-lib-row-text {
	min-width: 0;
}

/* overflow-wrap keeps a very long venue name from widening the dialog. */
.radio-lib-row-title {
	display: block;
	color: var(--ink);
	font: 700 14px/1.35 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	overflow-wrap: anywhere;
}

.radio-lib-row-sub {
	display: block;
	color: var(--dim);
	font: 400 12px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	overflow-wrap: anywhere;
}

.radio-lib-stars-display {
	display: inline-flex;
	gap: 1px;
	color: var(--radio-gold);
	font-size: 13px;
	letter-spacing: .5px;
}

.radio-lib-stars-display .is-off {
	color: rgba(255, 255, 255, .28);
}

/* Inline 1-5 rating inside a Library row: same control as the current-show row. */
.radio-lib-row-stars {
	display: inline-flex;
	gap: 2px;
}

.radio-lib-row-stars .radio-lib-star {
	width: 34px;
	height: 34px;
	font-size: 22px;
}

.radio-lib-row-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	justify-content: flex-end;
}

.radio-lib-row-actions .radio-lib-btn {
	min-height: 36px;
	padding: 0 10px;
	letter-spacing: .8px;
}

.radio-lib-row-tune {
	background: rgba(219, 171, 84, .2);
	box-shadow: inset 0 0 0 1px rgba(219, 171, 84, .7);
	color: var(--radio-gold);
}

.radio-lib-empty {
	margin: 0;
	color: var(--faint);
	font: italic 400 13px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.radio-lib-create {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}

.radio-lib-create-label {
	color: var(--dim);
	font: 700 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 1.1px;
}

/* min-width:0 keeps a long single-line name from forcing horizontal overflow. */
.radio-lib-input {
	flex: 1 1 160px;
	min-width: 0;
	min-height: 40px;
	padding: 0 10px;
	border: 0;
	border-radius: 8px;
	background: rgba(0, 0, 0, .34);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
	color: var(--ink);
	font: 400 15px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	-webkit-appearance: none;
	appearance: none;
}

.radio-lib-input::placeholder {
	color: var(--faint);
}

.radio-lib-playlists {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.radio-lib-playlist {
	min-width: 0;
	padding: 12px;
	border-radius: 10px;
	background: rgba(0, 0, 0, .22);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12);
}

.radio-lib-playlist-head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	margin-bottom: 4px;
}

/* Long playlist names truncate rather than stretching the dialog. */
.radio-lib-playlist-name {
	min-width: 0;
	margin: 0;
	color: var(--radio-gold);
	font: 700 14px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.radio-lib-playlist-head .radio-lib-btn {
	min-height: 32px;
	padding: 0 9px;
	font-size: 10px;
}

.radio-lib-playlist-rename {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 4px 0 8px;
}

.radio-lib-chooser {
	padding: 12px;
	border-radius: 10px;
	background: rgba(219, 171, 84, .12);
	box-shadow: inset 0 0 0 1px rgba(219, 171, 84, .4);
}

.radio-lib-chooser[hidden] {
	display: none;
}

.radio-lib-chooser-subject {
	margin: 0;
	color: var(--muted);
	font: 700 13px/1.35 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	overflow-wrap: anywhere;
}

@media (max-width: 560px) {
	.radio-lib-row {
		grid-template-columns: minmax(0, 1fr);
	}

	.radio-lib-row-actions {
		justify-content: flex-start;
	}

	/* Keep every star at a full 44px on touch-sized screens. */
	.radio-lib-star {
		width: 44px;
		height: 44px;
	}

	.radio-lib-panel {
		padding: 14px 12px;
	}

	.radio-lib-title {
		font-size: 16px;
	}
}

.radio-eq-dialog {
	width: min(620px, calc(100vw - 24px));
	max-width: calc(100vw - 24px);
	max-height: calc(100dvh - 32px);
	padding: 0;
	border: 0;
	border-radius: 14px;
	background: transparent;
	color: var(--ink);
	overflow: visible;
}

.radio-eq-dialog::backdrop {
	background: rgba(10, 5, 18, .74);
}

/* Native modal dialogs already trap focus and close on Escape; this only stops the page behind
   from scrolling so the dial cannot move while the EQ is open. */
html.radio-eq-open,
html.radio-eq-open body {
	overflow: hidden;
}

.radio-eq-rack {
	display: flex;
	align-items: stretch;
	gap: 8px;
	padding: 12px;
	border-radius: 14px;
	background: linear-gradient(135deg, #C9CFD1 0%, #828A92 48%, #B8BEC2 100%);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .6), 0 22px 60px rgba(0, 0, 0, .65);
}

.radio-eq-rack .radio-rack-handle {
	height: auto;
	align-self: stretch;
}

.radio-eq-panel {
	flex: 1 1 auto;
	min-width: 0;
	padding: 14px 14px 12px;
	border-radius: 6px;
	background: linear-gradient(180deg, #26262A 0%, #141416 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .8), inset 0 1px 0 rgba(255, 255, 255, .12);
}

.radio-eq-head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	margin-bottom: 12px;
}

.radio-eq-title {
	margin: 0;
	font: 700 13px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 2px;
	color: var(--radio-gold);
	text-shadow: 0 1px 0 rgba(0, 0, 0, .8);
}

.radio-eq-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.radio-eq-switch {
	min-height: 34px;
	padding: 0 12px;
	border: 0;
	border-radius: 5px;
	background: linear-gradient(180deg, #3A3A40 0%, #222226 100%);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .16), 0 2px 4px rgba(0, 0, 0, .5);
	color: var(--muted);
	font: 700 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: 1.2px;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
}

.radio-eq-switch:hover {
	color: var(--ink);
	background: linear-gradient(180deg, #46464E 0%, #2A2A30 100%);
}

.radio-eq-switch:focus-visible {
	outline: 3px solid var(--radio-gold);
	outline-offset: 2px;
}

.radio-eq-switch[aria-pressed="true"] {
	color: #12210F;
	background: linear-gradient(180deg, #8FE3A6 0%, #4FA96C 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .35), 0 0 10px rgba(111, 208, 140, .35);
}

.radio-eq-close {
	color: #2A1505;
	background: linear-gradient(180deg, #F0DCAE 0%, #C79A46 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .35), 0 2px 4px rgba(0, 0, 0, .5);
}

/* dB reference column beside the slider tracks. */
.radio-eq-scale {
	position: relative;
	flex: 0 0 auto;
	width: 26px;
	height: 200px;
}

.radio-eq-tick {
	position: absolute;
	left: 0;
	font: 700 9px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: .3px;
	color: var(--dim);
	white-space: nowrap;
}

.radio-eq-tick::after {
	content: "";
	position: absolute;
	top: 50%;
	left: calc(100% + 3px);
	width: 5px;
	height: 1px;
	background: rgba(219, 171, 84, .4);
}

.radio-eq-tick-top {
	top: 0;
	transform: translateY(-40%);
}

.radio-eq-tick-mid {
	top: 50%;
	transform: translateY(-50%);
	color: var(--radio-gold);
}

.radio-eq-tick-top::after,
.radio-eq-tick-bot::after {
	display: none;
}

.radio-eq-tick-bot {
	bottom: 0;
	transform: translateY(40%);
}

.radio-eq-bands {
	display: flex;
	align-items: flex-start;
	gap: 7px;
	padding: 8px 10px 6px;
	border-radius: 4px;
	background: linear-gradient(180deg, #0B0B0D 0%, #151517 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .9);
}

.radio-eq-track {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 2px;
}

.radio-eq-band {
	flex: 1 1 0;
	min-width: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
}

/* The input keeps a finger sized hit area (40px wide, 200px tall) while the painted track stays
   narrow, so seven bands fit a 320px phone without horizontal scrolling. */
.radio-eq-slider {
	-webkit-appearance: none;
	appearance: none;
	width: 100%;
	max-width: 40px;
	height: 200px;
	margin: 0;
	background: transparent;
	cursor: pointer;
	/* vertical-rl with rtl puts the maximum at the top, so dragging up adds gain */
	writing-mode: vertical-lr;
	direction: rtl;
}

.radio-eq-slider::-webkit-slider-runnable-track {
	width: 6px;
	border-radius: 3px;
	background: linear-gradient(180deg, #0A0A0C 0%, #1E1E22 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .9);
}

.radio-eq-slider::-moz-range-track {
	width: 6px;
	border-radius: 3px;
	background: linear-gradient(180deg, #0A0A0C 0%, #1E1E22 100%);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .9);
}

.radio-eq-slider::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	width: 30px;
	height: 11px;
	border-radius: 2px;
	background: linear-gradient(180deg, #F6E6C4 0%, var(--radio-gold) 48%, #8E6B2C 100%);
	box-shadow: 0 1px 3px rgba(0, 0, 0, .75), inset 0 0 0 1px rgba(255, 255, 255, .35);
}

.radio-eq-slider::-moz-range-thumb {
	width: 30px;
	height: 11px;
	border: 0;
	border-radius: 2px;
	background: linear-gradient(180deg, #F6E6C4 0%, var(--radio-gold) 48%, #8E6B2C 100%);
	box-shadow: 0 1px 3px rgba(0, 0, 0, .75), inset 0 0 0 1px rgba(255, 255, 255, .35);
}

.radio-eq-slider:focus-visible {
	outline: 3px solid var(--radio-gold);
	outline-offset: 2px;
	border-radius: 4px;
}

.radio-eq-label {
	font: 700 9px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	letter-spacing: .4px;
	color: var(--dim);
	white-space: nowrap;
}

.radio-eq-hint {
	margin: 10px 0 0;
	font: 400 11px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--dim);
}

/* Narrow phones: the decorative rack ears and generous panel padding are dropped so that all
   seven bands keep a 40px wide hit area inside a 320px screen without any sideways scrolling.
   The visible track stays narrow because only the painted track is 6px, not the input. */
@media (max-width: 600px) {
	.radio-eq-rack {
		gap: 0;
		padding: 8px;
	}

	.radio-eq-rack .radio-rack-handle {
		display: none;
	}

	.radio-eq-panel {
		padding: 8px 10px;
	}

	.radio-eq-bands {
		gap: 5px;
		padding: 6px 8px;
	}

	.radio-eq-scale {
		width: 18px;
	}

	.radio-eq-track {
		gap: 1px;
	}

	.radio-eq-slider {
		min-width: 40px;
		height: 168px;
	}

	.radio-eq-label {
		font-size: 8px;
		letter-spacing: 0;
	}
}

/* ------------------------------------------------------------- site cards */

.radio-site-card {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.radio-tour-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.radio-tour-list li {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
	padding: 10px 12px;
	border-radius: var(--button-radius);
	background: rgba(255, 255, 255, .06);
	font: 400 14px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.radio-tour-list time {
	flex: 0 0 auto;
	min-width: 96px;
	color: var(--radio-gold);
	font-weight: 700;
}

.radio-tour-list span {
	flex: 1 1 auto;
}

.radio-ticket-link {
	flex: 0 0 auto;
	padding: 5px 10px;
	border-radius: 8px;
	background: var(--radio-gold);
	color: var(--radio-purple) !important;
	font-weight: 700;
	font-size: 12px;
	text-decoration: none;
}

.radio-ticket-unavailable {
	flex: 0 0 auto;
	color: var(--faint);
	font-size: 12px;
}

/* iPhone only (the tablet sheet takes over at 600px). The row-plus-wrap layout above flows
   date, venue and button differently per card depending on how wide the content renders. On a
   phone every card gets one identical vertical structure instead — date row, venue/location
   row, buy-tickets row — left-aligned with even spacing. */
@media (max-width: 599px) {
	.radio-tour-list li {
		flex-direction: column;
		align-items: flex-start;
		gap: 4px;
	}

	.radio-tour-list time {
		min-width: 0;
	}

	.radio-tour-list span {
		flex: 0 1 auto;
	}
}

.radio-about-layout {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

/* The band's photo is shown in full: contain keeps every part of the frame visible and
   height:auto lets the browser hold the 960x675 ratio instead of cropping into a square. */
.radio-band-photo {
	display: block;
	width: 100%;
	height: auto;
	object-fit: contain;
	border-radius: var(--button-radius);
}

.radio-about-copy p {
	margin: 0 0 10px;
	font: 400 14px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--muted);
}

.radio-about-website {
	font: 600 14px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.radio-social-links {
	display: flex;
	gap: 14px;
	flex-wrap: wrap;
	margin-top: 12px;
	font-size: 13px;
}

.radio-patreon {
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding: 14px;
	border-radius: var(--button-radius);
	background: var(--radio-purple);
}

.radio-patreon h3 {
	margin: 0 0 4px;
	font-size: 15px;
	color: var(--radio-gold);
}

.radio-patreon p {
	margin: 0;
	font: 400 13px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	color: var(--muted);
}

.radio-patreon a {
	font-weight: 700;
	font-size: 13px;
}

@media (prefers-reduced-motion: reduce) {

	*,
	*::before,
	*::after {
		animation-duration: .001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .001ms !important;
		scroll-behavior: auto !important;
	}
}