@import url("https://fonts.googleapis.com/css?family=Rubik+Mono+One|Roboto+Mono:400,700&display=swap");
/* CSS Document */
/*body{
	margin: 0;
	padding: 0;
}*/

/* unvisited link 
a:link {
color: white;
}*/
/* visited link 
a:visited {
color: white;
}*/
/* mouse over link 
a:hover {
color: orange;
} */
/* selected link
a:active {
color: black;
}*/

/* No underlines on links, anywhere (style guide, 23 Sept). Links are
   told apart by colour and weight instead (red, bold). !important so it
   also beats the ~20 older per-page rules and inline styles that set
   underline on specific links and link-style buttons — one rule here
   rather than hunting each one down. Covers <button>s too, since several
   "Click > here <" links are really buttons styled as text. */
a, a:link, a:visited, a:hover, a:focus, a:active,
button, button:hover, button:focus {
    text-decoration: none !important;
}

html, body {
    height: 100%;
    overflow-x: hidden;
}
/* Phones: the body is the page's scroller, so the browser's address/tool
   bar never slides away while you scroll. 100% is the page height with
   those bars hidden, which left the bottom of every long page stuck
   behind the bar and out of reach (Schedule was fine because it scrolls
   inside its own box). 100dvh is the height you can actually see right
   now, so the last options come up clear of the footer. (23 Sept) */
@supports (height: 100dvh) {
    html, body {
        height: 100dvh;
    }
}

*, *::before, *::after {
    box-sizing: border-box;
}

.hero-tab {
    display: none;
}

.hero-tab.active {
    display: block;
}

.page-container,
.iwpdata-container
.site-page {
    padding: 0 1rem;
    max-width: 100%;
}

input,
textarea,
select {
    font-family: var(--font-family-primary);
}

body {
	margin: 0;
	padding: 0;
	display:flex;
	flex-direction: column;
}
/* Keeps the end of every page clear of the fixed footer: a real spacer as
   the body's last item, as tall as the footer (footer-widget.js keeps
   --footer-height up to date as it expands/collapses and the cookie
   banner comes and goes). This used to be padding-bottom on the body,
   but the body is the page's scroller, and Safari (every browser on an
   iPhone) leaves a scroller's bottom padding out of how far you can
   scroll, so the last options on long pages stayed stuck behind the
   footer. Schedule never showed it because it scrolls inside its own
   box. (23 Sept) */
body::after {
	content: "";
	display: block;
	flex: 0 0 var(--footer-height);
	transition: flex-basis 0.35s ease;
}

.site-page {
    flex: 1;
    /* Was align-self:flex-start (only take the height its own content
       needs) + display:block, which is why only livestream.php's grey
       panel (a completely separate flex mechanism, #livestream-page/
       #livestream-panel) ever filled the space down to the footer —
       every other page's grey box just stopped wherever its content
       ended, leaving bare white space below it. Stretching this to
       #content's full height, then letting its grey child grow into
       that space (see .site-page > .MixcloudSpacing below), gives every
       page the same consistently-filled look. */
    align-self: stretch;
    display: flex;
    flex-direction: column;
    margin: 0 auto;
    max-width: 45rem;
}

.site-page > .MixcloudSpacing {
    flex: 1;
}

content{
	/*
	Flex: 1;
	min-height: 0;	*/
	display:block;
}

.cookie-banner {
  display: none;   /* shown via .is-visible, toggled by JS after checking consent cookie */
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  background: #333;
  color: #fff;
  padding: 1rem;
  text-align: center;
  z-index: 9999;
}

.cookie-banner.is-visible {
  display: block;
}

.cookie-banner button {
  margin: 0 0.25rem;
}

/* Main site (22 Sept): the banner sits INSIDE <footer>, stacked directly
   on top of the black bar (see includes/footer.php) — black like the bar,
   only as tall as its own content, with the ON AIR pill poking up above it the
   same way it pokes above the bar. position:relative (not static) so it
   paints over the pill's lower half, exactly as .footer-bar does.
   The site gate and mymix pages keep the plain fixed bottom banner. */
footer .cookie-banner {
  position: relative;
  bottom: auto;
  left: auto;
  z-index: auto;
  background: #000;
  box-sizing: border-box;
  padding: 10px 16px 6px; /* hugs its content now it's stacked on the bar — no fixed bar-height any more */
  border-bottom: 1px solid #222;
}
footer .cookie-banner.is-visible {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px 12px;
}
footer .cookie-banner p {
  margin: 0;
  color: #fff;
  font-size: 13px;
}
/* Accept and Reject deliberately identical — the ICO expects rejecting
   to be as easy and as visible as accepting. */
footer .cookie-banner #accept-cookies,
footer .cookie-banner #reject-cookies {
  margin: 0;
  min-height: 34px;
  padding: 0 18px;
  border: 1px solid #fff;
  border-radius: 999px;
  background: #fff;
  color: #000;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
footer .cookie-banner #accept-cookies:hover,
footer .cookie-banner #reject-cookies:hover {
  color: #CF1F1F;
}
footer .cookie-banner #cookie-banner-settings {
  margin: 0;
  background: none;
  border: none;
  padding: 0;
  color: #fff;
  font-size: 13px;
  text-decoration: underline;
  cursor: pointer;
}
footer .cookie-banner #cookie-banner-settings:hover {
  color: #CF1F1F;
}

.main_bold_font_red_medium {
    font-family: "Rubik Mono One", sans-serif;
    font-size: 14px;
    color: #000000 !important;
}

.schedule{
	
	height: 100vh;
}
/*
.pushdown{
    padding-top: 1rem !important;
}*/

/* 1. Stop margin collapse on all forms */
.form {
    padding-bottom: 1rem;
}

/* 2. Give every field row the SAME spacing */
.form .dj_row {
    margin-bottom: 1rem;
}

.dj_row {
    margin-bottom: 1rem; /* or 16px if you prefer */
}
.form .dj_row {
  margin-bottom: 1rem;
}

.form .dj_two-col {
  margin-bottom: 1rem; /* ensure the two-column row has the same gap */
}

.form .pushdown {
  padding-top: 1rem;   /* controlled gap above the button */
}


/* 3. Give every submit button the SAME spacing above */
.form .form-button {
    margin-top: 1rem !important;
}

/* For checkbox used throughout website */
.styled-checkbox {
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    width: 20px !important;
    height: 20px !important;
    min-width: 20px;
    max-width: 20px;
    padding: 0 !important;
    margin: 0 !important;
    border: 1px solid #ccc !important;
    background-color: #ffffff !important;
    border-radius: 3px;
    position: relative;
    cursor: pointer;
    flex-shrink: 0;
    box-sizing: border-box;
}

.styled-checkbox:checked::after {
    content: "";
    position: absolute;
    left: 7px;
    top: 3px;
    width: 5px;
    height: 10px;
    border: solid black;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

/* For radio button used throughout website */
.styled-radio {
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    width: 20px !important;
    height: 20px !important;
    min-width: 20px;
    max-width: 20px;
    padding: 0 !important;
    margin: 0 !important;
    border: 1px solid #ccc !important;
    background-color: #ffffff !important;
    border-radius: 50%;
    position: relative;
    cursor: pointer;
    flex-shrink: 0;
    box-sizing: border-box;
}

.styled-radio:checked::after {
    content: "";
    position: absolute;
    top: 4px;
    left: 4px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: black;
}

/* ===================================================================
   Persistent footer widget

   Previously `footer{}` had no `position` set, so it just sat at the
   end of whatever page content, pushed down by `.footer{margin-top:auto}`
   only on short pages (the flexbox sticky-footer trick) — it scrolled
   away like ordinary content rather than staying visible. That's the
   dimension bug: it was never actually anchored to the viewport.

   Now it's position:fixed, permanently pinned to the bottom of the
   screen, in two states:
     - collapsed (default): just the bar + the raised ON AIR/play-pause
       pill poking up out of the middle
     - expanded: the bar stays, plus a panel drops in below it holding
       socials / support links / cookie settings / the site credit

   `--footer-height` is kept in sync with whichever state is active by
   footer-widget.js, and body's padding-bottom (below) uses it so page
   content is pushed up rather than hidden behind the fixed footer.
   =================================================================== */

:root {
	--footer-height: 104px;
	--footer-bar-height: 78px;
}

footer {
	display: block;
	position: fixed;
	bottom: 0;
	left: 0;
	width: 100%;
	z-index: 999;
	transition: opacity 0.3s ease;
}

.footer-hidden {
	opacity: 0;
	pointer-events: none;
}

.footer-bar {
	position: relative;
	height: var(--footer-bar-height);
	overflow: hidden;
	background: #000000;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 0 1.25rem;
	box-sizing: border-box;
	box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.35); /* one shadow across the whole footer, was previously just around .footer-onair */
}

/* Real Now Playing text (station + track title) — see footer.php's
   comment: these two lines double for now as what the future Show tile
   in the Show/Chat/Schedule rotation will use. */
.footer-rotation {
	color: #ffffff;
	font-family: "Roboto Mono", monospace;
	flex: 1;
	min-width: 0;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	justify-content: center;
	line-height: 1.3;
	cursor: pointer;
	position: relative;
}

.footer-slide {
	display: none;
}

.footer-slide-active {
	display: block;
}

.footer-np-station {
	font-size: 11px;
	opacity: 0.7;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.footer-np-title {
	font-size: 13px;
	font-weight: 600;
	line-height: 1.25;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* The raised centre pill housing ON AIR/LIVE NOW + play/pause.
   Deliberately a SIBLING of .footer-bar, placed BEFORE it in the markup
   (see footer.php) rather than nested inside it — that's what makes it
   sit visually *behind* the bar: .footer-bar comes later in the DOM and
   has its own opaque black background, so it naturally paints over
   whatever part of this pill falls within the bar's own height,
   leaving only the portion above the bar's top edge exposed.
   Positioned relative to <footer> itself (position:fixed, so it's
   already a containing block for this).

   Sized via explicit height/min-width (not padding-driven) so it's
   predictable: height is ~50% taller and min-width ~100% wider than
   the first version. align-items switched from center to flex-start
   (+ padding-top) because centering pulled the content down into the
   hidden-behind-the-bar half — flex-start keeps it up in the visible
   portion instead.

   Tuning knobs if this needs adjusting further:
     - `top` controls how far it pokes above the bar (more negative = more exposed)
     - `height` / `padding-top` control how much of that visible area the content sits in
     - total height must stay comfortably less than --footer-bar-height (78px)
       below the `top` offset, or it'll poke out the bottom of the bar */
.footer-onair {
	position: absolute;
	top: -40px;
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	align-items: flex-start;
	justify-content: center;
	gap: 14px;
	background: #000000;
	border-radius: 8px; /* matches .schedule-modal-inner */
	height: 100px; /* ~50% taller than before */
	min-width: 260px; /* ~100% wider than before */
	padding: 16px 40px 0;
	/* shadow moved to .footer-bar so it reads as one shadow across the
	   whole footer, rather than a blob just around this pill */
}

.onair-badge {
	font-family: "Rubik Mono One", sans-serif;
	font-size: 18px; /* up from 15px */
	color: #CF1F1F;
	letter-spacing: 0.5px;
	margin-top: -5px; /* lifted slightly per feedback, then another 2px to line up with the play/pause button */
	background: none;
	border: none;
	padding: 0;
	cursor: pointer;
}

.footer-play-pause {
	background: none;
	border: none;
	padding: 0;
	cursor: pointer;
	display: flex;
	align-items: center;
	line-height: 0;
	margin-top: -10px; /* lifted per feedback */
}

.footer-play-pause-icon {
	width: 28px;
	height: 28px;
}

.footer-toggle {
	background: none;
	border: none;
	cursor: pointer;
	padding: 0.5rem;
	flex-shrink: 0;
}

.footer-chevron {
	display: block;
	width: 12px;
	height: 12px;
	border-right: 2px solid #ffffff;
	border-bottom: 2px solid #ffffff;
	transform: rotate(45deg);
	transition: transform 0.3s ease;
}

/* Chevron flips to point down->up when expanded (JS toggles this class) */
.footer-toggle[aria-expanded="true"] .footer-chevron {
	transform: rotate(-135deg);
}

.footer-expanded {
	background: #000000;
	max-height: 0;
	overflow: hidden;
	transition: max-height 0.35s ease;
}

.footer-expanded-inner {
	padding: 1.25rem;
	display: flex;
	flex-direction: column;
	gap: 1rem;
	color: #ffffff;
	font-family: "Roboto Mono", monospace;
	font-size: 13px;
	text-align: center;
}

.footer-socials {
	display: flex;
	justify-content: center;
	gap: 1rem;
}

.footer-social-link {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 4px;
	opacity: 0.85;
	transition: opacity 0.15s ease;
}

.footer-social-link:hover {
	opacity: 1;
}

.footer-social-icon {
	height: 22px;
	width: auto;
}

/* Carousel arrows — same promote/demote mechanic as tapping a footer
   item (see footer-widget-state-model.md), used identically on
   livestream.php, chat.php, and schedule.php since all three are
   "main body" views of the same Show/Chat/Schedule rotation. Shared
   here rather than duplicated per page since it's pixel-identical on
   all three. */
/* Carousel — a layered "card stack": the Show/Chat/Schedule card floats
   in front (solid background + shadow, reads as elevated/closer), and
   the other two pages peek out from behind as vertical side tabs,
   shorter than the card so they visibly poke out top and bottom too.
   Tab labels are set by routing.js (updateCarouselTabs) since which
   page is "left"/"right" depends on where you currently are in the
   Show→Chat→Schedule cycle, not something fixed per page. */
.hero-carousel {
	position: relative;
	display: flex;
	/* Stretch is the right default here — this is the real Show/Chat/
	   Schedule carousel (livestream.php/chat.php/schedule.php), and each
	   of those cards' own content (the Now Playing panel, the chat
	   iframe, the schedule grid) is specifically built to grow and fill
	   whatever height it's given, same as it always has. */
	align-items: stretch;
	min-height: 220px;
}

/* Fork pages (Terms, Privacy, Events, DJ Directory, Home, the admin
   dashboards, Settings) are a different case — with .MixcloudSpacing now
   filling down to the footer (see that rule further down), stretch here
   would drag the white card down to match, reading as one giant white
   box rather than a card sitting inside a grey one. flex-start keeps the
   card at its own natural content height instead; the now-tall
   .hero-carousel itself has no background of its own, so
   .MixcloudSpacing's grey shows through in whatever's left below/around
   the card — which is the actual thing that was asked to fill, not the
   card. */
.hero-carousel.hero-fork-carousel {
	align-items: flex-start;
}

/* Schedule specifically (not Chat, not DJ Directory — see the long
   comment where this class is added in schedule.php for why those two
   are different) — Day view is always exactly 24 hours, a fixed amount
   of content that never grows just because the viewport is taller, so
   stretching the card to fill available height (the base .hero-carousel
   rule above) only ever produces a dead, unstyled blank patch below the
   last hour row, never more useful content. Same flex-start treatment
   as .hero-fork-carousel above, just under its own name since it's not
   a fork page and doesn't need routing.js's FORK_PAGES config. */
.hero-carousel.hero-carousel-natural {
	align-items: flex-start;
}

.hero-carousel-card {
	position: relative;
	/* NOTE: was bumped to 1500 to fix the Add/Edit Event modal getting
	   trapped below the footer/open-menu header (position:relative + a
	   z-index here creates a stacking context, so a modal nested inside
	   it — even position:fixed — only ever competes using THIS number
	   against things outside the card, regardless of the modal's own
	   much bigger z-index). That fixed the modal, but broke everything
	   ELSE about this card: it made every page's whole card render
	   above the footer (999) and the open hamburger menu (1002) too,
	   since this class wraps every page's content, not just Events.
	   Reverted to a low, safe value — the actual fix now lives with the
	   modal itself (see admin-events.js: it gets moved to be a direct
	   child of <body> at runtime, escaping this stacking context
	   entirely, rather than this card being raised to accommodate it). */
	z-index: 2;
	flex: 1;
	min-width: 0;
	background: #ffffff;
	border: 1px solid #e5e5e5;
	border-radius: 10px;
	box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
	padding: 4px;
	/* Lets a child that opts in (flex:1 — e.g. the Chat iframe) grow to
	   fill whatever height this card ends up with, instead of only ever
	   being as tall as its own natural content. Column direction keeps
	   everything else stacking exactly as it did under normal block
	   flow, so this is a safe default for every page that uses this
	   class, not just Chat's. */
	display: flex;
	flex-direction: column;
	/* Floored so a sparse page (Cookies, a fresh Contact form, etc.)
	   reads as a similarly-proportioned card instead of a visibly
	   smaller one, and never reads as smaller than the tabs framing it
	   either. Tied to the tab dimensions below (tab height + 2x tab
	   width) rather than a standalone number, so the two stay in
	   proportion if the tabs are ever resized. */
	min-height: calc(var(--hero-carousel-tab-height) + (2 * var(--hero-carousel-tab-width)));
}

:root {
	/* Single tunable spot for every side tab's height — was previously a
	   180px floor that let each tab grow to fit its own label (so a page
	   with a short label got a short tab and a page with a long one, e.g.
	   Home's "Let's Go Party People...", got a tall one). Fixed at one
	   value instead so every tab across the site is the same height
	   regardless of label length. If a future label still doesn't fit,
	   bump this one number rather than hunting for it. */
	--hero-carousel-tab-height: 300px;
	--hero-carousel-tab-width: 30px;
}

.hero-carousel-tab {
	position: sticky;
	top: 16px;
	margin-top: 30px; /* drops it below the card's top corner radius, so the rounded corner isn't fighting a flush-edge tab right beside it */
	align-self: flex-start; /* don't stretch to match the card's height as a flex item */
	height: var(--hero-carousel-tab-height);
	width: var(--hero-carousel-tab-width);
	z-index: 1;
	background: #CF1F1F;
	border: 1px solid rgba(255, 255, 255, 0.25);
	color: #fff;
	text-decoration: none; /* the left tab is a real <a> on Home (logged-in "I'm Outta Here" link) — every other tab is a <button>/<span>, so this was the one place a browser's default link underline was showing through */
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: flex-start;
	padding-top: 16px;
	font-family: "Rubik Mono One", sans-serif; /* matches .main_bold_font_red_large, the heading style used above the carousel */
	font-size: 12px;
	letter-spacing: 1px;
	writing-mode: vertical-rl;
	white-space: nowrap; /* without this, a label too tall for the tab's fixed height wraps into a second vertical column instead of just running past the bottom — the "PEOPLE..." on its own garbled second line seen on Home's long label. One continuous line that overflows visibly if it must is far more readable than a wrapped one squeezed into a 30px-wide box. */
	overflow: visible;
	transition: background 0.15s ease, color 0.15s ease;
}

.hero-carousel-tab:hover {
	background: #a81818;
	color: #fff;
}

/* Mirrors the page headings' "Label..." pattern (black text + red dots)
   but inverted, since tabs sit on a red background: white label text,
   black dots. Set via routing.js's shared IWP_setTabLabel helper rather
   than hardcoded per label, so it's automatic wherever a tab label is
   set — carousel or fork, static or JS-driven. */
.hero-carousel-tab-dots {
	color: #000;
}

.hero-carousel-tab-left {
	border-radius: 0 8px 8px 0; /* swapped vs. the visual intent — the 180deg rotation below flips which side this renders on */
	transform: rotate(180deg); /* reads bottom-to-top, matches the sketch */
}

.hero-carousel-tab-right {
	border-radius: 0 8px 8px 0;
}

/* "The End" — a page with nowhere further to go (yet). Same tab, same
   position, just black and inert, so every page still shows exactly two
   tabs rather than the right one disappearing and looking unfinished.
   Repointing it later is a one-line change in routing.js's fork-tab
   config, nothing to do with this page's own markup. */
.hero-carousel-tab-end,
.hero-carousel-tab-end:hover {
	background: #000;
	cursor: default;
}

/* The shared .hero-carousel-tab-dots rule is black — right for the red
   tab background, invisible against this one's black background. */
.hero-carousel-tab-end .hero-carousel-tab-dots {
	color: #CF1F1F;
}

/* Support/legal pages etc. reuse the carousel's card-stack look but don't
   need its 220px min-height — their content is usually taller than that
   anyway, and forcing it just adds dead space under short pages. */
.hero-fork-carousel {
	min-height: 0;
}

.hero-fork-card {
	padding: 20px;
	/* The 500px card floor (.hero-carousel-card, above) means a page
	   whose real content is much shorter than that leaves a solid block
	   of plain white at the bottom — reads as an obvious, unintentional
	   gap rather than a deliberately-sized card. Fading the last
	   stretch of it to the grey panel's own background colour (#f7f7f7,
	   see .MixcloudSpacing) instead lets it trail off into the page
	   rather than stopping dead. Content taller than ~350px never
	   reaches the fade at all, so a genuinely full page (Terms, Privacy)
	   looks exactly as it did before — this only affects the sparse
	   ones the 500px floor is actually padding out.
	   Scoped to .hero-fork-card specifically, NOT the shared
	   .hero-carousel-card rule above — the real Show/Chat/Directory/
	   Schedule carousel cards stretch to fill genuinely varying heights
	   (a tall Schedule grid, a short one), and this gradient's fixed
	   pixel stops would put a visible grey band partway down one of
	   those instead of at its actual bottom. */
	background: linear-gradient(to bottom, #ffffff 0%, #ffffff 350px, #f7f7f7 500px);
}

@media (max-width: 600px) {
	.hero-fork-card {
		padding: 16px 14px;
	}
}

/* Slide transition for the carousel — see routing.js's
   IWP_navigateWithSlide for how these classes get applied/removed. */
.page-slide-overlay {
	position: fixed;
	z-index: 500; /* above normal page content, below the footer (999) and modals */
	overflow: hidden;
	transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1);
	will-change: transform;
	pointer-events: none;
}

#content.page-slide-active {
	transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1);
	will-change: transform;
}

.page-slide-start-right { transform: translateX(100%); }
.page-slide-start-left { transform: translateX(-100%); }
.page-slide-exit-left { transform: translateX(-100%); }
.page-slide-exit-right { transform: translateX(100%); }
.page-slide-settled { transform: translateX(0); }

.footer-support-links {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.5rem 1.25rem;
}

.footer-support-links a,
.footer-link-button {
	color: #ffffff;
	text-decoration: none;
	background: none;
	border: none;
	font-family: "Roboto Mono", monospace;
	font-size: 13px;
	cursor: pointer;
	padding: 0;
}

.footer-support-links a:hover,
.footer-link-button:hover {
	color: #CF1F1F;
}

.footer-credit {
	opacity: 0.6;
	font-size: 11px;
}

.footer-credit a {
	color: #ffffff;
	text-decoration: none;
}

.footer-credit a:hover {
	color: #CF1F1F;
}

.cookie-pref-row {
	text-align: left;
	margin-bottom: 1rem;
}

.cookie-pref-row label {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	font-weight: bold;
}

.cookie-pref-desc {
	margin: 0.25rem 0 0 28px;
	font-size: 12px;
	color: #555;
}

.iwppage-container {
    max-width: 900px;
    margin: 0 auto;
    /*padding: 20px;*/
    padding: 0 1rem;
    /* Home is the one page using this wrapper instead of .site-page, so
       it was missed entirely by that class's fill-to-the-footer
       treatment (see .site-page above) — same fix, mirrored here. */
    flex: 1;
    align-self: stretch;
    display: flex;
    flex-direction: column;
}
.iwppage-container > .MixcloudSpacing {
    flex: 1;
    min-height: 0;
}

.section-title {
    font-family: 'Trebuchet MS', Arial, sans-serif;
    font-size: 28px;
    font-weight: 600;
    margin-bottom: 20px;
    color: #000;
}

.red-arrows {
    color: #CF1F1F;
}

/* Chatroom (loaded via iframe on the livestream page) */
#chat-wrap {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 10px;
    box-sizing: border-box;
    min-height: 0;
}

.form-button {
  background-color: #bbbbbb !important;
  color: #000 !important;
  border: 1px solid #bebebe !important;
  border-radius: 5px !important;
  padding: 0.5rem 1rem;
  font-family: var(--font-family-primary);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: color 0.2s ease;
  margin: 0 !important;
}

#messages {
    background: #fff;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 10px;
    border-radius: 6px;
    border: 1px solid #ddd;
    font-family: "Roboto Mono", monospace;
    font-size: 12px;
}

/*.message {
    display: flex;
    align-items: baseline;
    margin-bottom: 6px;
    padding: 4px 10px;
    border-bottom: 1px solid #eee;
}

.message .meta {
    flex: 0 0 auto;
    white-space: nowrap;
    font-weight: bold;
    color: #CF1F1F;
    margin-right: 8px;
}

.message .text {
    flex: 1 1 auto;
    min-width: 0;
    word-wrap: break-word;
    color: #000;
}*/

.message {
    display: flex;
    flex-direction: column;
    margin-bottom: 6px;
    padding: 4px 10px;
    border-bottom: 1px solid #eee;
}

.message .meta {
    font-weight: bold;
    font-size: 11px;
    color: #CF1F1F;
    margin-bottom: 2px;
}

.message .text {
    font-size: 13px;
    word-wrap: break-word;
    color: #000;
}

.message.system {
    color: #888;
    font-style: italic;
}

#chat-input {
    display: flex;
    gap: 6px;
    margin-top: 8px;
}

#message-input {
    flex: 1;
    padding: 8px;
    border-radius: 4px;
    border: 1px solid #ccc;
    font-family: "Roboto Mono", monospace;
}

#send-btn {
    padding: 8px 16px;
    border: none;
    border-radius: 4px;
    background: #CF1F1F;
    color: #fff;
    cursor: pointer;
    font-family: "Roboto Mono", monospace;
}

/* (#dj-panel's old boxed look went 23 Sept — Chat Management is a drawer
   now, styled in chat.php to the style guide.) */

#status {
    font-size: 12px;
    color: #888;
    margin-bottom: 4px;
    font-family: "Roboto Mono", monospace;
}

#status .status-user {
    color: #CF1F1F;
    font-weight: bold;
}

#audio-player button {
	position: fixed;
	display: block;
	top: 0;
	left: 0;
	background: none;
	border: none;
	padding: 0;
	cursor: pointer;
	z-index: 998;
}

#playPauseIcon{
	width: 40px;
	height: 40px;
}

/* .footer (the old wrapping div's class) is no longer used now that the
   footer is position:fixed — the flexbox "margin-top:auto" sticky-footer
   trick isn't needed when the element is out of normal flow. Left as a
   comment rather than deleted in case something else still references it. */

/* Style for each iframe */
.iframe-item {		
	height: 120px; /* Set the height of each iframe */
	margin-bottom: 0px; /* Add spacing between iframes */
	border: none; /* Remove iframe borders */
	box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); /* Optional shadow for better visuals */
}

.wny-image {
  max-width: 100%;
  max-height: 283px;
}

header .top_div {
	height:auto;
	width:100%;
	display: flex;
	justify-content: center;
	align-items: center;
	padding: 0%;
	border: none;
}

header .top_div img{	
	/*flex-shrink: 0;
	display: block;	*/
	max-width: 720px;   /* match your section width */
    width: 100%;
    height: auto;
    display: block;
    margin: 0 auto;
}

.iwp-image {
    width: 100%;
    max-height: 120px;
    height: auto;
}

header {
    position: relative; /* so z-index applies and the shadow paints over the page below */
    z-index: 500;
    background-color: #000000;
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); /* same shadow as the top traffic-light pill hanging under it (22 Sept) */
}

/* While the nav menu is open, let it fully take over the screen: hide the
   header's own background/logo/login icon so nothing paints over the
   overlay, but still let the header (and the close/X icon inside it)
   rise above the overlay so the same hamburger-turned-X stays visible
   and clickable to close the menu. */
body:has(#main-navigation-toggle:checked) header {
    z-index: 1002;
    background-color: transparent;
    box-shadow: none;
}
body:has(#main-navigation-toggle:checked) .iwp-logo,
body:has(#main-navigation-toggle:checked) .iwp-filler.right {
    visibility: hidden;
}
body:has(#main-navigation-toggle:checked) .iwp-filler.left {
    background-image: none;
}
/* The "?" tour button floats at z-index 9500, well above the open menu
   overlay (1002) — deliberate everywhere else, but it meant it kept
   floating visibly over the fullscreen nav while it was open, which
   just looks like a stray leftover control on top of the menu. Hidden
   for the duration the menu is open; still there the moment it closes. */
body:has(#main-navigation-toggle:checked) #iwp-help-btn {
    display: none;
}

.iwp-banner {
    display: flex;
    width: 100%;
    align-items: stretch;   /* fillers match logo height */
}

.iwp-filler.left,
.iwp-filler.right {
    display: flex;
    align-items: flex-start;
    padding-top: 1rem;
    flex: 1 1 0; /* equal-width zones either side of the logo, so it sits
                    exactly centred regardless of the hamburger/login
                    icon's own width */
    min-width: 0;
}

.iwp-filler.left {
    justify-content: flex-start;
    padding-left: 1rem;
}

.iwp-filler.right {
    justify-content: flex-end;
    padding-right: 1rem;
}

.iwp-login-icon {
    color: var(--color-dark, #FFFFFF);
    font-size: 1.75rem;
    text-decoration: none;
    line-height: 1;
    cursor: pointer;
    display: inline-flex; /* so the image sits centered on the link's own line-height */
    align-items: center;
}
.iwp-login-icon-img {
    height: 1.75rem;
    width: 1.75rem;
    display: block;
}

.iwp-logo {
    max-height: 250px;      /* cap height */
	max-width: 100%;
    height: auto;           /* allow shrinking */
    width: auto;            /* maintain aspect ratio */
    flex-shrink: 1;         /* KEY: allow shrinking */
    flex-grow: 0;           /* do not stretch horizontally */
    min-width: 0;           /* same flexbox gotcha documented elsewhere in this
                               file: without this, a flex item won't shrink
                               below its own natural width no matter what
                               flex-shrink says — the logo was overflowing the
                               row on narrow screens, pushing the login icon
                               off past the right edge of the viewport where
                               overflow-x:hidden clips it invisible */
    display: block;
}

.iwp-filler {
    flex-grow: 1;           /* stretch horizontally */
    flex-shrink: 1;         /* shrink when needed */
	min-width: 1px;
    background-size: auto 100%; /* match logo height */
    background-repeat: repeat-x;
    background-position: center;
}

.iwp-filler.left {
    background-image: url('../images/logo_filler.png');
}

.iwp-filler.right {
    background-image: url('../images/logo_filler.png');
}

.player {
	border: 2px solid rgb(23, 22, 22);
	padding: 10px;
	background-color: #ffffff;
	width: 600px;
	height: auto;
}	

.form_a{
	margin:auto;	
	padding:40px;	
}

.bigLabel{
	font-family: "Rubik Mono One", sans-serif;
	font-size: 24px; 
	color: #Cf1F1F;
}

.field-label{
	color: #000000;

}

.advert_top{
	width: 100%;
	text-align: center;
	text-justify: auto;
}

.advert_bottom{
	width: 100%;
	text-align: center;
	text-justify: auto;
}

.MixcloudSpacing{	
	max-width: 720px;
    width: 100%;
    margin: 15px auto;       /* spacing between sections */
    padding: 20px;           /* equal internal boundaries */
    background-color: #f7f7f7;
    color: #000;
    border: 3px solid #ffffff;
    border-radius: 10px;     /* matches .hero-carousel-card's rounding, so the outer panel and the inner card read as the same visual family */
    font-size: 16px;         /* slightly bigger default font */
    box-sizing: border-box;
    /* Site-wide fill (see .site-page in this file) makes this box tall
       enough to reach the footer — but a normal block child only ever
       takes the height its own content needs, so a short page left dead
       space below it instead of actually using that height. Flexing
       .hero-carousel into that space (see below) fills it with grey,
       which is the actual thing that was asked to fill — the white card
       inside stays its own natural height regardless (see .hero-carousel's
       align-items in this file for why), it doesn't get stretched along
       with it. */
    display: flex;
    flex-direction: column;
}
.MixcloudSpacing > .hero-carousel {
    flex: 1;
    min-height: 0;
}
/* Settings is the one page whose card sits directly in MixcloudSpacing
   with no .hero-carousel wrapper around it (no tabs either side) — kept
   at its own natural height, same reasoning as every other page's card,
   rather than stretching to fill like it briefly did. */
.MixcloudSpacing > .hero-carousel-card {
    flex: 0 1 auto;
}

/* Hide a native file input visually while keeping it functional and
   accessible — pair with a <label for="..."> styled as a button, which
   opens the picker on click. Was previously only defined inside
   settings.php's own <style> block (worked for the avatar/mugshot
   uploads there), so any other page using the same pattern — e.g.
   Footer Tips' image upload — got the unstyled native file input AND
   the custom label both rendering side by side. Moved here so it's
   available everywhere this pattern is used, not just Settings. */
.visually-hidden-file {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* Site announcement banner — a public status/outage notice, rendered once
   in index.php's persistent shell (outside #content) so it's visible on
   every page and survives SPA navigation, rather than living inside any
   one page's own markup (moved here from livestream.php, which used to be
   the only page that ever rendered it). */
.announcement-banner {
    width: 100%; /* explicit rather than relying on default block/flex
                    stretch behaviour — belt and braces alongside max-width */
    max-width: 720px; /* matches .MixcloudSpacing's grey panel width so the
                          banner lines up with the page content underneath
                          instead of running wider than it */
    margin: 0 auto;
    padding: 0 1rem;
    box-sizing: border-box;
}
.announcement-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
    box-sizing: border-box;
    background: #d6e9ff;
    border-left: 4px solid #0d6efd;
    padding: 10px 16px;
    margin-top: 10px;
    font-size: 14px;
}
/* Colour by level — General keeps the original blue as the default/
   fallback look (also what any pre-existing announcement gets, since
   the level column defaults to 'general'). Same four levels as the
   admin page's pills (see $announcementLevels in admin-announcements.php)
   — keep the two in sync if a colour or level ever changes.
   Icon prefix per level, same idea as the status-message popup's
   warning icon — a quick glance tells you severe/warning/good/general
   without reading the text first. */
.announcement-item.announcement-level-severe {
    background: #fbdcdc;
    border-left-color: #CF1F1F;
}
.announcement-item.announcement-level-severe .announcement-text {
    color: #7a0000;
}
.announcement-item.announcement-level-severe .announcement-text::before {
    content: "\2716\00A0\00A0"; /* ✕ */
}
.announcement-item.announcement-level-warning {
    background: #fff3cd;
    border-left-color: #e6a800;
}
.announcement-item.announcement-level-warning .announcement-text {
    color: #6b5200;
}
.announcement-item.announcement-level-warning .announcement-text::before {
    content: "\26A0\00A0\00A0"; /* ⚠ */
}
.announcement-item.announcement-level-good {
    background: #dcf5dc;
    border-left-color: #2a7d2a;
}
.announcement-item.announcement-level-good .announcement-text {
    color: #1a4f1a;
}
.announcement-item.announcement-level-good .announcement-text::before {
    content: "\2713\00A0\00A0"; /* ✓ */
}
.announcement-text::before {
    content: "\2139\00A0\00A0"; /* ℹ — fallback for General / any level without its own icon rule above (severe/warning/good override this via higher specificity) */
}
.announcement-text {
    color: #003a75;
    font-weight: 600;
    font-size: 14px;
}
.announcement-close {
    flex-shrink: 0;
    background: #888;
    color: #fff;
    border: none;
    border-radius: 4px;
    padding: 4px 12px;
    font-size: 12px;
    cursor: pointer;
}
.announcement-close:hover {
    background: #CF1F1F;
}
.announcement-view-details {
    flex-shrink: 0;
    background: #003a75;
    color: #fff;
    border: none;
    border-radius: 4px;
    padding: 4px 12px;
    font-size: 12px;
    cursor: pointer;
}
.announcement-view-details:hover {
    background: #00509e;
}
.announcement-for-pill {
    flex-shrink: 0;
    background: #1a6fb0;
    color: #fff;
    border-radius: 10px;
    padding: 2px 10px;
    font-size: 11px;
    font-weight: 600;
}

/* Fixed-height scrollable list panel (16 Sep) — for any admin list that
   can grow long (Users, DJ Moderation, Show Requests, Announcements):
   keeps the page itself a fixed, predictable height regardless of list
   length, while each row inside can still expand in place via the
   existing .list-accordion-toggle/.list-accordion-body behaviour —
   expanding a row just makes the PANEL'S scroll content taller, it
   doesn't reflow the surrounding page. Shared here (not duplicated in
   each page's own <style> block like .admin-card/.admin-card-header
   currently are) since it's one visual idea reused identically
   everywhere, not something any single page customises. */
.admin-scroll-list {
    max-height: min(560px, 65vh);
    overflow-y: auto;
    overflow-x: hidden;
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    background: #f7f7f7;
    padding: 10px;
}
/* Rows keep their own bottom margin (set per-page alongside .admin-card)
   for spacing between cards — the last one doesn't need trailing space
   the panel's own padding already provides. */
.admin-scroll-list > *:last-child {
    margin-bottom: 0 !important;
}

/* Small round (i)/? info-reveal button (16 Sep) — was previously only
   styled when inside a .form element (see settings.php's own <style>
   block), which meant it looked unstyled on any page loaded outside
   that specific context (e.g. admin-users.php's "Block" section, which
   replaces settings.php's content in #content entirely rather than
   nesting inside it). Moved here, unscoped, so it looks right wherever
   it's used — settings.php's own .form-scoped rule still wins there via
   specificity, so nothing changes for the fields that already use it. */
.field-help-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    box-sizing: border-box;
    width: 18px;
    height: 18px;
    min-width: 18px;
    min-height: 18px;
    border-radius: 50%;
    border: 1px solid #999;
    background: #fff;
    color: #666;
    font-size: 11px;
    font-weight: 700;
    line-height: 16px;
    padding: 0;
    margin: 0;
    cursor: pointer;
}
.field-help-btn:hover {
    border-color: #CF1F1F;
    color: #CF1F1F;
}

/* Shared help-modal shell (16 Sep) — previously duplicated in each of
   djdirectory.php/djform-modal.php/djform.php/settings.php's own <style>
   blocks; moved here so a page like admin-users.php (below) that also
   wants a .field-help-btn info reveal doesn't need a 5th copy. The
   trigger is any .field-help-btn/.profile-section-help click (see
   profile.js, loaded site-wide) — the markup itself (#profile-help-
   modal-overlay etc.) still needs to exist on whichever page uses it. */
.profile-help-modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.6);
    z-index: 1000;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.profile-help-modal-overlay.open {
    display: flex;
}
.profile-help-modal {
    background: #fff;
    border-radius: 8px;
    max-width: 440px;
    width: 100%;
    padding: 24px;
    position: relative;
    max-height: 80vh;
    overflow-y: auto;
}
.profile-help-modal h4 {
    color: #CF1F1F;
    margin: 0 0 12px;
    padding-right: 24px;
}
.profile-help-modal p {
    color: #000;
    font-size: 14px;
    line-height: 1.5;
    margin: 0 0 10px;
}
.profile-help-modal-close {
    position: absolute;
    top: 16px;
    right: 16px;
    background: none;
    border: none;
    font-size: 22px;
    line-height: 1;
    color: #666;
    cursor: pointer;
}
.profile-help-modal-close:hover {
    color: #CF1F1F;
}


.main_bold_font_red_large{	
	font-family: "Rubik Mono One", sans-serif;
	font-size: 15px; 	
	color: #000000 !important;
}

.main_bold_font_red{
	font-family: "Rubik Mono One", sans-serif;
	font-size: 12px; 	
	color: #000000 !important;
}

.main_bold_font_red a{
	
	text-align: center;
	color: #000000;
	text-decoration: none;
}

.main_bold_font_red a:link {
	
	color: #000000;
}

/* visited link */
.main_bold_font_red a:visited {

	color: #CF1F1F;
}

/* mouse over link */
.main_bold_font_red a:hover {

	color: #000000;
}

/* selected link */
.main_bold_font_red a:active {
	color: #CF1F1F;
}

.dj_play{
	position: absolute;
	top: 0;
	left: 0;
}

.h2_heading {
	font-weight: 900;
	font-size: xx-large;
	color:#000000;
	padding-top: 20px;
	padding-bottom: 20px;
}

#dj_form {
    max-width: 800px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.dj_row {
    display: flex;
    flex-direction: column;
}

.dj_two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

/* Grid items default to min-width:auto, meaning a child (an <input>,
   <select>, etc.) refuses to shrink below its own content's natural
   minimum width even when 1fr would otherwise allocate less — the
   classic CSS Grid overflow gotcha. Without this, a .dj_two-col row
   with real form fields inside quietly forces the whole page wider than
   intended, showing up as a horizontal scrollbar that doesn't scale
   normally with window width the way a simple padding/box-sizing
   mismatch would. */
.dj_two-col > .dj_col {
    min-width: 0;
}

.dj_label {
	color:#CF1F1F !important;
    font-weight: 600;
    margin-bottom: 6px;
}

:root {
	/* Single tunable spot for every text input / textarea / select
	   box's outline colour and corner radius site-wide — change the
	   look of form fields everywhere by editing these two values
	   rather than hunting through each page's own CSS. */
	--iwp-field-border-color: #ccc;
	--iwp-field-radius: 6px;
}

input[type="password"],
input[type="text"],
input[type="email"],
input[type="url"],
input[type="number"],
input[type="tel"],
input[type="search"],
textarea,
select {
    width: 100%;
    padding: 10px;
    border-radius: var(--iwp-field-radius);
    border: 1px solid var(--iwp-field-border-color);
    font-size: 16px;
    box-sizing: border-box;
}

textarea {
    resize: none; /* fixed size — no user drag-resize handle, matches every other field being a fixed box */
}

.contactTextArea{
	height: 150px !important; /* the one thing still worth a page-specific override — a taller fixed box for a longer message */
}


.dj_genres {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px 10px;
}

.dj-callout {
    font-size: 16px;
    margin-top: 20px;
}


.dj_genre_item{
	display: flex;
	align-items: center;
	gap: 6px;
	width: 100%;
}

/* Genre checkbox labels have no class of their own, so they inherit the
   menu stylesheet's body{color:white} rule and go invisible on light
   backgrounds. Applies globally (djform, Profile tab, DJ Directory). */
.dj_genre_item label {
    color: #000;
    font-size: 0.9rem;
    cursor: pointer;
}

/* .dj_label doubles as both a standalone field label ("DJ Name", bold
   red, larger — fine as-is) and, wrapped around a checkbox/radio plus
   its confirmation text ("I confirm I've shared this..."), a form
   control. The second usage was inheriting the field-label sizing too,
   making checkbox text noticeably bigger than the auth-note text
   around it. :has() distinguishes the two without touching markup in
   every form that uses this pattern. */
label.dj_label:has(input[type="checkbox"]),
label.dj_label:has(input[type="radio"]) {
    font-size: 0.9rem;
}

/* Same root cause, wider net: every other unclassed checkbox/radio label
   sitting on a light background (claim modal, edit-show modal, Settings
   tab) inherits the same white body text and goes invisible. Rather than
   patching each inline style individually, this covers every label inside
   those light-background containers in one place. */
.schedule-modal-inner label,
.show-edit-modal-inner label,
#hero-tab-profile .profile-section-body label {
    color: #000;
}

button {
    padding: 1px 1px;
    font-size: 18px;
    border: none;
    background: #333;
    color: white;
    border-radius: 6px;
    cursor: pointer;
}

.nowplaying-box {
    display: grid;
    grid-template-columns: auto 1fr auto 60px; /* 4 columns */
    grid-template-rows: auto auto auto auto auto; /* 5 rows */
    grid-gap: 10px;
    max-width: 720px;
    width: 100%;
	border-radius: 12px;
	padding-bottom: 6px;
}

/* Row 1, Col 1 */
.np-station {
    grid-column: 1 / span 3; /* columns 1,2,3 */
    grid-row: 1;
	font-family: "Rubik Mono One", sans-serif;
	font-size: 12px; 	
    color: #000;
	padding-left: 12px;
}

/* Now Playing tab on livestream.php: description sits full-width, centred, no offset */
#hero-tab-meta .np-station {
    padding-left: 0;
    font-size: 0.9rem;
}

/* Row 1, Col 2 */
.np-playbtn {
    grid-column: 4;
    grid-row: 1;
    width: 40px;
    height: 40px;
    background: #000;
    color: #fff;
    border-radius: 50%;
    border: none;
    font-size: 20px;
	justify-self: start;
    cursor: pointer;
}
.np-playbtn img{
	max-width: 40px;
    max-height: 40px;
}

.nowplaying-details {
    display: grid;
    grid-template-rows: repeat(5, auto);
    row-gap: 4px;
}

.np-col {
    display: flex;
    flex-direction: column;
}

.np-row {
    font-size: 16px;
    font-weight: 600;
    color: #000;
	padding: 4px 12px;
}

/* Artwork spans rows 2–5 */
.np-art {
    grid-column: 1;
    grid-row: 2 / span 4; /* rows 2,3,4,5 */
    width: 150px;
    height: 150px;
    object-fit: cover;
	margin-left: 12px;
    border-radius: 8px;
}

/* Track info spans rows 2–5 */
.np-info {
    grid-column: 2 / span 3; /* columns 2,3,4 */
    grid-row: 2 / span 4;    /* rows 2,3,4,5 */
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.andBreathe{
	margin-bottom: 14px;
}

.np-loader {
    width: 120px;
    height: 14px;
    background: #333;
    border-radius: 6px;
    animation: npPulse 1.2s infinite ease-in-out;
    margin-bottom: 10px;
}

#nowplaying-wrapper {
    position: relative;
    min-height: 40px;
}

.np-loader {
    width: 120px;
    height: 14px;
    background: #333;
    border-radius: 6px;
    animation: npPulse 1.2s infinite ease-in-out;
}

@keyframes npPulse {
    0% { opacity: 0.3; }
    50% { opacity: 1; }
    100% { opacity: 0.3; }
}

.np-text {
    font-size: 18px;
    font-weight: 600;
    color: #fff;
    transition: opacity 0.4s ease;
}

/* Tabs */
#hero-tabs {
    display: flex;
    gap: 0px;
    margin-bottom: 20px;
}

#hero-tabs button {
    padding: 10px 15px;
    border: none;
    background: #333;
    color: #fff;
    cursor: pointer;
    border-radius: 6px;
}

.hero-tab {
  display: none;        /* hide all panels by default */
}

.hero-tab.active {
  display: block;       /* only show the active one */
  flex: 1;
  min-width: 0;          /* flex items refuse to shrink below their content's
                            natural width by default — without this, the
                            whole panel (not just one element inside it)
                            can force itself wider than the space actually
                            available, which is what was causing the
                            horizontal scrollbar */
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Belt-and-braces on top of the rule above: whatever the exact chain of
   flex/grid min-width defaults turns out to be, this ID-scoped rule
   guarantees nothing inside the Settings/Profile tab can ever force a
   horizontal scrollbar, full stop — any content that's genuinely too
   wide gets clipped rather than pushing the panel wider. */
#hero-tab-profile {
  overflow-x: hidden !important;
}

#hero-tab-chat.active #chat-frame {
    height: 100%;
    display: block;
}

/* Livestream page: let height flow down from page-container to hero-player,
   so hero-player fills exactly the space available between the banner and
   footer instead of a guessed fixed height. Scoped to this page only. */
#livestream-page {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

#livestream-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Hero layout */
#hero-player {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    padding: 0px;
}

.hero-artwork img {
    width: 100%;
    max-width: 400px;
    height: auto;
    border-radius: 12px;
    display: block;
    margin: 0 auto;
}

.hero-row {
    text-align: center;
    font-size: 1.4rem;
    margin-bottom: 10px;
    color: #000;
}

.hero-controls {
    display: flex;
    justify-content: center;
}

#hero-playbtn {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    font-size: 2rem;
    border: none;
    background: #ff0066;
    color: white;
    cursor: pointer;
}

/* Make headings black — also resets the browser's own large default h2
   margin, which was the main source of the big gap between the heading
   and the note/form right after it. */
#auth-wrapper h2.auth-heading {
    color: #000;
    margin: 0 0 6px;
}

/* Friendly micro-copy */
.auth-note {
    color: #444;
    font-size: 0.9rem;
    margin-bottom: 10px;
}

/* OR separator */
.auth-or {
    text-align: center;
    font-weight: bold;
    color: #555;
    margin: 25px 0 10px;
}

#auth-wrapper .form input,
#auth-wrapper .form button,
#auth-wrapper .form input[type="submit"] {
  margin-bottom: 0;   /* remove random gaps */
}

#auth-wrapper .form .form-button {
  margin-top: 1rem;   /* consistent gap above buttons */
}

.tabs {
  display: flex;
  gap: 0;
  padding-bottom: 20px;
  width: 100%;                  /* make sure it stretches full width */
}

.tabs-button {
  background-color: #e6e6e6 !important;   /* match your grey div */
  color: #000 !important;     /* default black text */
  border: 1px solid #bebebe !important;
  border-radius: 5px 5px 0 0 !important;
  padding: 0.5rem 1rem;
  font-family: var(--font-family-primary);
  cursor: pointer;
  transition: color 0.2s ease;
  margin: 0 !important;
  margin-right: -1px;
}

.tabs-button.active {
  background-color: #f6f6f6 !important;   /* match your grey div */
  color: #CF1F1F !important;           /* red for selected tab */
  border-bottom: none !important;
  font-weight: bold;
}

.tabs-button:hover {
  color: #CF1F1F;           /* red on hover */
}

input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
    -webkit-box-shadow: 0 0 0 1000px #ffffff inset !important;
    -webkit-text-fill-color: #000 !important;
    font-family: var(--font-family-primary) !important;
    transition: background-color 5000s ease-in-out 0s;
}

.auth-note h3 {
    color: #CF1F1F;
}

.auth-note a {
    color: #CF1F1F;
    text-decoration: none;
}
.auth-note a:hover {
    color: black;
}

/* Reusable red-link/black-hover treatment for plain inline links outside
   .auth-note's scope (e.g. DJ application review's Mixcloud/SoundCloud/
   Instagram links) — same visual pattern, without pulling in .auth-note's
   own font-size/color changes to the surrounding text. */
.social-link {
    color: #CF1F1F;
    text-decoration: none;
}
.social-link:hover {
    color: #000;
    text-decoration: underline;
}

.form-button {
  background-color: #bbbbbb !important;   /* match your grey div */
  color: #000 !important;     /* default black text */
  border: 1px solid #bebebe !important;
  border-radius: 5px !important;
  padding: 0.5rem 1rem;
  font-family: var(--font-family-primary);
  font-weight: 600;
  cursor: pointer;
  transition: color 0.2s ease;
  margin: 0 !important;
}

.form-button.active {
  background-color: #EBEBEB !important;   /* match your grey div */
  color: #CF1F1F !important;           /* red for selected tab */
  font-weight: bold;
}

.form-button:hover {
  color: #CF1F1F !important;           /* red on hover */
}


/* .cookie-banner rules consolidated up near the top of this file, next to the
   footer widget CSS — this duplicate removed so there's one source of truth */

.form button,
.form input[type="submit"] {
  display: block;
  width: 100% !important;   /* stretches to parent width */
}

.form {
  padding-bottom: 1rem; /* prevents child margins from collapsing into footer */
}

.form {
  overflow: auto; /* or hidden */
}

.form button {
  margin-top: 1rem;   /* add a uniform gap above buttons */
}

.auth-errors {
    margin-bottom: 20px;
}

.error-message {
    background: #ffdddd;
    border-left: 4px solid #cf1f1f;
    padding: 10px;
    margin-bottom: 8px;
    font-size: 14px;
}

/* Deliberate, scoped exception to the site's red/black/grey/white
   palette — reserved purely for transient success confirmations
   (saved, connected, uploaded), never for ongoing status categories.
   Those keep using the black/grey/red system elsewhere (schedule grid,
   My Shows, admin status pills etc.) — this is a different kind of
   signal, a moment of feedback rather than a state to track. */
:root {
	/* Shared Severe/Warning/General/Good severity colours -- used
	   across Site Announcements, public status messages, and .auth-
	   success -- one source of truth rather than each place picking
	   its own shade. */
	--iwp-severity-severe: #CF1F1F;
	--iwp-severity-warning: #e6a800;
	--iwp-severity-general: #0d6efd;
	--iwp-severity-good: #2a7d2a;
}

.auth-success {
    background: #e5f6ec;
    border-left: 4px solid var(--iwp-severity-good);
    color: #1a4f1a;
    padding: 10px;
    margin-bottom: 8px;
    font-size: 14px;
}

/* Warning banner — same shape as .auth-success, but purple with a leading
   exclamation mark, for messages that need to stand out as "something's
   wrong, worth noticing" without being a hard red error. */
.auth-warning {
    background: #f1e9fb;
    border-left: 4px solid #6b21a8;
    color: #4c1580;
    padding: 10px 10px 10px 12px;
    margin-bottom: 8px;
    font-size: 14px;
    display: flex;
    align-items: flex-start;
    gap: 8px;
}
.auth-warning::before {
    content: "!";
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #6b21a8;
    color: #fff;
    font-weight: 700;
    font-size: 12px;
    line-height: 18px;
    text-align: center;
}

/* Shared upload UI — used anywhere a file gets picked/uploaded across
   the site (show artwork, mix uploads, etc.) so every upload looks and
   behaves the same, and any future tweak only needs changing here. */
.upload-filename-display {
    text-align: left;
    margin: 4px 0 0 !important;
    font-size: 13px;
    color: #666;
    display: none;
}
.upload-progress-wrap {
    display: none;
    align-items: center;
    gap: 10px;
    margin-top: 8px;
}
.upload-progress-bar {
    flex: 1;
    height: 8px;
    background: #eee;
    border-radius: 4px;
    overflow: hidden;
}
.upload-progress-fill {
    height: 100%;
    width: 0%;
    background: #1a1a1a;
    transition: width 0.2s ease;
}
.upload-progress-pct {
    font-size: 12px;
    color: #666;
    min-width: 34px;
    text-align: right;
}

#forgot-password-link {
    color: #cf1f1f;
    text-decoration: none;
}

#forgot-password-link:hover {
    color: black;
}

#guidelines_form input[type="checkbox"] {
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    width: 20px !important;
    height: 20px !important;
    min-width: 20px;
    max-width: 20px;
    padding: 0 !important;
    margin: 0 !important;
    border: 2px solid #333 !important;
    background-color: #ffffff !important;
    border-radius: 3px;
    position: relative;
    cursor: pointer;
    flex-shrink: 0;
    box-sizing: border-box;
}

#guidelines_form input[type="checkbox"]:checked::after {
    content: "";
    position: absolute;
    left: 6px;
    top: 2px;
    width: 5px;
    height: 10px;
    border: solid black;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

/* Cancel link — match the forgot-password link colours */
#cancel-registration-link {
    color: #CF1F1F;
    text-decoration: none;
}

#cancel-registration-link:hover {
    color: black;
}


@keyframes spin{
	to { transform: rotate(360deg);}
}

@media screen and (max-width: 767px) {	
	
	.iwp-image {	  
	    width: 800px;
		max-width: none;
	}
	
	.player {
		width: 720px;
		max-width: none;
	}
	
	.MixcloudSpacing{	
		padding: 10px;	
		max-width: 720px; 		
	}
	
	.form_a{
		margin:auto;	
		padding:40px;	
	}
		
	.bigLabel{
		font-family: "Rubik Mono One", sans-serif;
		font-size: 24px; 	
	}
	#dj-form {
    
			max-width: 720px;
	}
}

@media screen and (max-width: 480px) {
	
	.iwp_image {	
		
		
		width: 480px;
		max-width: none;
		height: 100px;		
	}	
	
	.player {
		width: 400px;
		max-width: none;		
		border: 2px solid white;
		padding: 0px;
	}
	
	.MixcloudSpacing{	
	
		
		padding: 10px;
    	max-width: 400px; /* Set a fixed width */
	}

	#dj-form {
    
			max-width: 480px;
	}

	#playPauseIcon{
		width: 40px;
		height: 40px;
	}
}
/* ==========================================================================
   Shared accordion (.profile-section*)
   Originally only in livestream.php's own <style> block (the Profile tab),
   duplicated by hand into every page that reuses the same look since —
   consolidated here as the single source. Any page using this pattern
   should link to this, not carry its own copy.
   ========================================================================== */
.profile-section {
    border: 1px solid var(--iwp-field-border-color); /* was hardcoded #ddd — a third near-duplicate grey alongside .admin-scroll-list's old #e0e0e0 and Beta Testers'/Cron Log's old #333, now all one value */
    border-radius: 6px;
    margin-bottom: 10px;
    overflow: hidden;
}
.profile-section-header {
    width: 100%;
    display: flex;
    align-items: stretch;
    background: #f7f7f7;
}
.profile-section.open .profile-section-header {
    background: #CF1F1F;
}
.profile-section-toggle {
    flex-grow: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: none;
    border: none;
    padding: 14px 16px;
    font-family: var(--font-family-primary);
    font-size: 16px;
    font-weight: 700;
    color: #000;
    cursor: pointer;
    text-align: left;
    text-decoration: none; /* the Admin/Event Management rows (.profile-section-link) are real <a> tags, not <button>s like every other accordion row — this was the browser's default link underline showing through on the label and the ">" both, since they're one and the same text node inside the anchor */
}
.profile-section.open .profile-section-toggle {
    color: #fff;
}
.profile-section-help {
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    align-self: center;
    margin-right: 14px;
    border-radius: 50%;
    border: 1px solid #999;
    background: #fff;
    color: #666;
    font-family: var(--font-family-primary);
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}
.profile-section.open .profile-section-help {
    border-color: #fff;
    color: #CF1F1F;
}
.profile-section-icon {
    font-size: 20px;
    line-height: 1;
    transition: transform 0.15s ease;
}
.profile-section.open .profile-section-icon {
    transform: rotate(45deg);
}
/* Groups a section's badge (if any) right next to its +/x toggle icon,
   both flush right — used where a toggle shows a live count (e.g. Admin
   -> All Users) instead of leaving the badge sitting inline after the
   title. Only two children expected: an optional .admin-badge and the
   .profile-section-icon. */
.profile-section-toggle-right {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: 12px;
}
.profile-section-body {
    display: none;
    padding: 16px;
}
.profile-section.open .profile-section-body {
    display: block;
}

/* ==========================================================================
   Shared modal shell (.schedule-modal*)
   Originally only in schedule.php's own <style> block, duplicated by hand
   into admin-events.php and mymix-upload.php since — consolidated here as
   the single source. schedule.php itself keeps one small override
   (.schedule-modal-inner text-align: center) since its claim modal's
   content is meant centered, unlike the form-based modals elsewhere.
   ========================================================================== */
.schedule-modal {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.55);
    z-index: 6000; /* raised well clear of the header/logo/nav-main and every other stacking layer on the page — a modal must always win regardless of what's sitting underneath it */
    display: flex;
    align-items: flex-start;
    justify-content: center;
    overflow-y: auto;
    padding: 30px 12px;
}
.schedule-modal-inner {
    background: #fff;
    border-radius: 8px;
    padding: 24px;
    max-width: 480px;
    width: 100%;
    position: relative;
}
/* DJ application modal (djform-modal.js) needs more room for its
   two-column name row and genre grid than the login/account modal does
   — toggled on/off by JS rather than raising the shared default, so
   login/account stay exactly as they were. */
.schedule-modal-inner.iwp-modal-wide {
    max-width: 640px;
}
/* New/Existing/Forgot/Logout account modal (#iwp-account-modal-overlay
   in index.php) — was an inline max-width:480px on that one div;
   pulled out into a real class so it's an explicit, named width
   rather than a copy-pasteable inline value, same reasoning as
   .iwp-modal-wide above. 480px happens to match the shared default
   already, so this is a no-op visually — just makes it robust against
   the shared default ever changing for other modals. */
.schedule-modal-inner.iwp-modal-auth {
    max-width: 480px;
}
.schedule-modal-close {
    position: absolute;
    top: 10px;
    right: 14px;
    background: none;
    border: none;
    font-size: 1.5em;
    line-height: 1;
    cursor: pointer;
    color: #888;
}
.schedule-modal-close:hover { color: #CF1F1F; }

/* Classic-Windows-form titlebar (14 Sept) — red bar, white bold title
   (same "Rubik Mono One" font as every page heading), close X on the
   same line rather than floating alone above a title on the row below.
   Bleeds to the edges of .schedule-modal-inner's own padding via
   negative margins rather than changing that padding globally (which
   would also push in every modal's ordinary content). Retrofit any
   modal still using the old bare "close button + h3" pattern by
   wrapping both in <div class="schedule-modal-titlebar">, title first
   then the close button — see admin-users.php's Filter/Invite modals
   for the reference markup. Not every modal needs a close button in
   the bar (e.g. a forced yes/no confirm step) — just omit it, the bar
   still centers/left-aligns the title correctly either way. */
.schedule-modal-titlebar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    background: #CF1F1F;
    margin: -24px -24px 16px -24px;
    padding: 10px 14px;
    border-radius: 8px 8px 0 0;
}
.schedule-modal-titlebar h3 {
    font-family: "Rubik Mono One", sans-serif;
    font-size: 14px;
    color: #ffffff;
    margin: 0;
}
.schedule-modal-titlebar .schedule-modal-close {
    position: static;
    color: #ffffff;
    font-size: 1.3em;
}
.schedule-modal-titlebar .schedule-modal-close:hover { color: #000000; }

/* The shared help modal (profile.js's openHelpModal — Settings, DJ
   Directory, Admin Users, DJ form). Its links were falling back to the
   browser's default blue; same red + bold as links everywhere else. Its
   title bar is the standard one above (23 Sept). */
.profile-help-modal a {
    color: #CF1F1F;
    font-weight: 700;
}
.profile-help-modal a:hover {
    color: #ff4d4d;
}

/* ==========================================================================
   Drawers (23 Sept) — render_drawer_start()/render_drawer_end() in
   partials/page-head.php, opened/closed by page-head.js. Right-hand side
   panel on desktop, bottom sheet on a phone — the same look as the DJ
   Directory's shortlist drawer (.listing-drawer in listing-tiles.php).
   Drawer = look at it while the page stays in view; Modal = needs an
   answer first. The body scrolls on its own, so a long panel never runs
   off the bottom of a phone screen.
   ========================================================================== */
/* The floating "?" tips button (z-index 9500) sits above a drawer and
   covered the bottom of it on a phone — hide it while any drawer is
   open, the same as the shortlist/profile/filter already do. */
body:has(.iwp-drawer.open) #iwp-help-btn {
    display: none;
}
.iwp-drawer-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 2900;
}
.iwp-drawer-backdrop.open {
    display: block;
}
.iwp-drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 360px;
    max-width: 100%;
    background: #fff;
    box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);
    z-index: 2950;
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    visibility: hidden;
    transition: transform 0.2s ease, visibility 0.2s ease;
    text-align: left;
    font-family: var(--font-family-primary, "Roboto Mono", monospace);
    color: #000;
}
.iwp-drawer.open {
    transform: translateX(0);
    visibility: visible;
}
@media (max-width: 600px) {
    .iwp-drawer {
        top: auto;
        left: 0;
        width: 100%;
        max-height: 80vh;
        max-height: 80dvh; /* the visible screen, not counting the phone's address bar */
        border-radius: 16px 16px 0 0;
        box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.15);
        transform: translateY(100%);
    }
    .iwp-drawer.open {
        transform: translateY(0);
    }
}
@media (prefers-reduced-motion: reduce) {
    .iwp-drawer { transition: none; }
}
/* Same red title bar as .schedule-modal-titlebar. */
.iwp-drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 14px;
    background: #CF1F1F;
    flex-shrink: 0;
}
@media (max-width: 600px) {
    .iwp-drawer-head {
        border-radius: 16px 16px 0 0;
    }
}
.iwp-drawer-title {
    font-family: "Rubik Mono One", sans-serif;
    font-size: 14px;
    font-weight: normal;
    color: #fff;
    margin: 0;
}
.iwp-drawer-close {
    background: none;
    border: none;
    padding: 0;
    color: #fff;
    font-size: 1.3em;
    line-height: 1;
    cursor: pointer;
}
.iwp-drawer-close:hover {
    color: #000;
}
.iwp-drawer-body {
    flex: 1;
    min-height: 60px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 14px 18px 18px;
}
.iwp-drawer-foot {
    flex-shrink: 0;
    padding: 14px 18px 18px;
    border-top: 1px solid #eee;
}
/* A grey "nothing here yet" line inside a drawer body. */
.iwp-drawer-empty {
    color: #777;
    font-size: 13px;
    margin: 4px 0;
}
/* Sections inside a drawer: .settings-subheading heading, then fields. */
.iwp-drawer-section + .iwp-drawer-section {
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px solid #eee;
}

/* ==========================================================================
   Chat's online-users list (chat.php / chatroom.js)
   #online-users-modal-overlay gets moved to a direct child of <body> at
   runtime (same reason as every other modal note in this file —
   .hero-carousel-card's stacking context traps a nested modal regardless
   of its own z-index) rather than left inside chat.php's markup. That
   relocation is what makes this CSS need to live here instead of in
   chat.php's own <style> block: a page-specific <style> tag only exists
   in the DOM while that page's fragment is loaded, but the relocated
   element itself persists as a sibling of #content across every later
   SPA navigation — without global CSS, once you navigate away from Chat
   the element is still sitting there, un-hidden (a plain <div> defaults
   to visible with nothing telling it otherwise), and dumps its raw
   content into whatever page you're now on. Learned this the hard way
   once already. #mod-sheet-overlay does NOT need this treatment — see
   its own CSS comment in chat.php for why it stays inside the card and
   its styling stays with it there.
   ========================================================================== */
#online-users-modal-overlay .schedule-modal-inner {
    text-align: left;
}
#online-users-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 50vh;
    overflow-y: auto;
}
.online-user-pill {
    background: #2c2c2c;
    color: #fff;
    font-size: 13px;
    padding: 6px 10px;
    border-radius: 6px;
}
.online-user-pill.is-you {
    background: #CF1F1F;
    font-weight: 700;
}

/* ==========================================================================
   Account modal (#iwp-account-modal-overlay / #iwp-account-modal-body)
   Header login icon opens this (see account-menu.js), which fetches
   /pages/login.php's raw HTML straight into #iwp-account-modal-body. It
   never had its own styling, so it was falling back to whatever login.php
   brought with it — the old .site-page/.MixcloudSpacing page wrapper
   (grey background, white border) left over from when login was a full
   standalone page. login.php no longer wraps its content in those, and
   this shell now mirrors .schedule-modal/.schedule-modal-inner exactly so
   every modal on the site (Edit Event, Edit Show, this one) looks and
   feels the same. Base display stays "none" — account-menu.js toggles it
   to "flex" via inline style when opening.
   ========================================================================== */
#iwp-account-modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.55);
    z-index: 6000; /* matches .schedule-modal — see that rule's comment */
    align-items: flex-start;
    justify-content: center;
    overflow-y: auto;
    padding: 30px 12px;
}
#iwp-account-modal-body {
    position: relative;
}
/* Account summary row (avatar + name + role/DJ-type) at the top of the
   logged-in account modal — see account-menu.js's openAccountModal(). */
.iwp-account-summary {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
}
.iwp-account-avatar {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    border: 1px solid #e5e5e5;
}
.iwp-account-name {
    font-weight: 700;
    color: #000;
    font-size: 1.05em;
}
.iwp-account-type {
    color: #666;
    font-size: 0.85em;
}
#iwp-account-modal-body label {
    color: #000;
}

/* Explicit colour on the cookie-preferences modal's own text — same
   white-on-white gotcha documented elsewhere in this file: unstyled
   headings/paragraphs can inherit an ancestor's white text colour and
   go invisible once they're sitting on this modal's white card. */
/* Sits above .cookie-banner (z-index: 9999) — otherwise the banner, if
   still showing, physically overlaps and blocks clicks on this modal's
   buttons even though the modal appears open. */
#cookie-preferences-modal {
    z-index: 10000;
}

/* ---- Onboarding tips ---------------------------------------------- */

/* Floating, unmissable, everywhere — sits just above the persistent
   footer (tracks --footer-height automatically as it expands/collapses)
   but below any open modal (9999), so a modal always wins if both are
   somehow on screen at once. The pulse is a slow, low-key "notice me"
   cue for a first-time visitor, not a persistent distraction. */
#iwp-help-btn {
    position: fixed;
    right: 16px;
    /* Anchored to --footer-chrome-height (the footer's own current
       height — bar plus expanded panel when open — NOT inflated by the
       ON AIR pill poking up on the LEFT side of it, and deliberately a
       different custom property from the fixed --footer-bar-height
       above, which sizes .footer-bar itself and must stay untouched)
       so this button's gap above the footer matches its 16px gap from
       the right edge, and actually moves when the footer expands. */
    bottom: calc(var(--footer-chrome-height) + 16px);
    z-index: 9500;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: #CF1F1F;
    color: #fff;
    border: none;
    font-family: "Rubik Mono One", sans-serif;
    font-size: 24px;
    line-height: 1;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
    transition: bottom 0.35s ease, background 0.15s ease, transform 0.15s ease;
    animation: iwp-help-pulse 2.5s ease-in-out infinite;
}
#iwp-help-btn:hover {
    background: #a81818;
    transform: scale(1.06);
}
@keyframes iwp-help-pulse {
    0%, 100% { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35), 0 0 0 0 rgba(207, 31, 31, 0.5); }
    50% { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35), 0 0 0 10px rgba(207, 31, 31, 0); }
}

.iwp-tip-scrim {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 10001;
}

/* An iframe's own contents can't rise above the scrim just by setting a
   z-index inside the iframe's document — that only competes within the
   iframe's own stacking context. For a frame-based tip step (chatroom.php,
   loaded into #chat-frame) the whole iframe element itself needs lifting
   instead, so whatever's highlighted inside it is actually visible over
   the dim rather than hidden underneath it. Applied/removed alongside the
   inner .iwp-tip-highlight class — see onboarding-tips.js. */
.iwp-tip-frame-elevated {
    position: relative;
    z-index: 10002;
}

/* Bumped above the scrim so the actual target visibly pops through the
   dim, rather than needing a true cutout mask cut into the scrim itself
   (fragile to build reliably across every possible target on the site). */
.iwp-tip-highlight {
    position: relative;
    z-index: 10002;
    outline: 3px solid #CF1F1F;
    outline-offset: 3px;
    border-radius: 6px;
    box-shadow: 0 0 0 6px rgba(207, 31, 31, 0.25);
}

.iwp-tip-popup {
    position: fixed;
    z-index: 10003;
    max-width: 280px;
    background: #fff;
    border-radius: 8px;
    padding: 14px 16px;
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.3);
    font-size: 14px;
    color: #1a1a1a;
}
.iwp-tip-count {
    display: block;
    font-family: "Rubik Mono One", sans-serif;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #ffffff;
    background: #CF1F1F;
    margin: -14px -16px 10px -16px;
    padding: 8px 12px;
    border-radius: 8px 8px 0 0;
}
.iwp-tip-text {
    margin-bottom: 10px;
    line-height: 1.4;
}
.iwp-tip-dontshow {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: #555;
    margin-bottom: 10px;
    cursor: pointer;
}
.iwp-tip-actions {
    display: flex;
    justify-content: space-between;
    gap: 8px;
}
.iwp-tip-btn {
    background: #CF1F1F;
    color: #fff;
    border: none;
    border-radius: 4px;
    padding: 6px 14px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
}
.iwp-tip-btn:hover {
    background: #a81818;
}
.iwp-tip-btn-secondary {
    background: none;
    color: #666;
    border: 1px solid #ccc;
}
.iwp-tip-btn-secondary:hover {
    border-color: #999;
    color: #333;
}

/* Settings' "Show tool tips automatically" toggle (onboarding-tips.js) —
   a generic on/off slider, not tied to anything tour-specific in its
   own styling, so it's reusable wherever else a simple toggle is
   needed later. */
.iwp-toggle-switch {
    position: relative;
    display: inline-block;
    width: 44px;
    height: 24px;
    vertical-align: middle;
}
.iwp-toggle-switch input {
    opacity: 0;
    width: 0;
    height: 0;
}
.iwp-toggle-slider {
    position: absolute;
    cursor: pointer;
    inset: 0;
    background-color: #ccc;
    transition: background-color 0.2s ease;
    border-radius: 24px;
}
.iwp-toggle-slider::before {
    content: "";
    position: absolute;
    height: 18px;
    width: 18px;
    left: 3px;
    bottom: 3px;
    background-color: #fff;
    transition: transform 0.2s ease;
    border-radius: 50%;
}
.iwp-toggle-switch input:checked + .iwp-toggle-slider {
    background-color: #CF1F1F;
}
.iwp-toggle-switch input:checked + .iwp-toggle-slider::before {
    transform: translateX(20px);
}

/* The one-off "want to sign in?" prompt at the end of the tour — same
   card look as a normal .iwp-tip-popup step, but centered on screen
   rather than positioned next to a target (it doesn't have one). */
.iwp-signup-prompt {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    max-width: 320px;
    text-align: left;
}

/* Public status message step (onboarding-tips.js) — same centered,
   targetless treatment as .iwp-signup-prompt above, kept as its own
   class since it's a semantically separate thing (an admin-set notice,
   not the end-of-tour signup nudge) even though the positioning is
   identical. */
.iwp-status-tip-popup {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    max-width: 320px;
    text-align: left;
    white-space: pre-line; /* login-digest-style multi-line messages use \n, not <br> */
}
.iwp-status-tip-heading {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: "Rubik Mono One", sans-serif;
    font-size: 15px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #ffffff;
    background: var(--iwp-severity-warning); /* default; severe/good override below */
    margin: -14px -16px 10px -16px;
    padding: 10px 14px;
    border-radius: 8px 8px 0 0;
}
.iwp-status-tip-icon {
    font-size: 18px;
    line-height: 1;
}
/* Same 3-tier severity palette as the internal admin/system banner
   (.announcement-item.announcement-level-*) — now carried as the
   titlebar's own background rather than a border/text colour, so the
   3-tier signal still reads clearly at a glance. */
.iwp-status-tip-level-severe .iwp-status-tip-heading {
    background: var(--iwp-severity-severe);
}
.iwp-status-tip-level-warning .iwp-status-tip-heading {
    background: var(--iwp-severity-warning);
}
.iwp-status-tip-level-good .iwp-status-tip-heading {
    background: var(--iwp-severity-good);
}

#cookie-preferences-modal .schedule-modal-titlebar h3 {
    color: #ffffff;
}
#cookie-preferences-modal p {
    color: #000;
}

/* ==========================================================================
   Shared "copy link" button (.copy-link-btn)
   Small outlined button that copies a link to the clipboard, with a brief
   "Copied!" confirmation state. First built for events.php's "Copy event
   link" (as .odn-copy-btn, page-scoped), promoted here so mymix-upload.php
   and anywhere else needing the same pattern can reuse it directly rather
   than duplicating it again.
   ========================================================================== */
.copy-link-btn {
    background: #fff;
    color: #CF1F1F;
    border: 1px solid #CF1F1F;
    border-radius: 4px;
    padding: 3px 10px;
    font-size: 0.8em;
    cursor: pointer;
    margin: 4px 0 8px;
}
.copy-link-btn:hover {
    background: #CF1F1F;
    color: #fff;
}
.copy-link-btn.copy-link-btn-copied {
    background: #CF1F1F;
    color: #fff;
}
/* Live page's read-only "DJ takes requests" prompt (song-request-banner.js)
   — Chat has the real submit UI, this just points there. */
#livestream-song-request-banner {
    margin-top: 12px;
    padding: 8px 12px;
    background: #f7f7f7;
    border-radius: 6px;
    font-size: 0.85em;
    color: #000;
    text-align: center;
}
#livestream-song-request-banner a {
    color: #CF1F1F;
    font-weight: 700;
    text-decoration: none;
}
#livestream-song-request-banner a:hover {
    text-decoration: underline;
}

/* Shared "list row" pattern — a faint separator between entries plus
   subtle odd/even shading, for any stacked list of records (admin
   tables reworked into <details> rows, activity logs, etc). Opt-in
   via .iwp-list-row on each row — apply to a page's own list rows
   whenever that page next gets touched, rather than all at once.
   One place to retune the shading/line if it ever needs adjusting. */
:root {
	--iwp-list-row-border: rgba(255, 255, 255, 0.08);
	--iwp-list-row-alt-bg: rgba(255, 255, 255, 0.03);
}

.iwp-list-row {
	border-bottom: 1px solid var(--iwp-list-row-border);
}
.iwp-list-row:nth-child(even) {
	background: var(--iwp-list-row-alt-bg);
}

/* ===== Global Settings/Form style guide (16 Sep) — apply to any
   admin/settings page as it's touched, per the annotated screenshot.
   Reuses existing site variables/classes rather than inventing new
   ones wherever one already existed. ===== */

/* 1+2 — sub heading (e.g. "Site Gate", "Beta Features") + tightened
   gap to the .auth-note description that follows it. Font-size/weight
   unchanged from the plain <h3> this replaces — colour + spacing only.
   A class, not a bare h3 rule, since Terms/Privacy/Cookies also use
   plain h3 and shouldn't turn red. */
.settings-subheading {
    color: #CF1F1F;
    font-weight: bold;
    font-size: 1.17em; /* matches the plain <h3> default this replaces, so applying it to a non-heading element (e.g. a <summary>'s label span) still lines up */
    margin-top: 0; /* the browser's default h3 top margin (~19px) was stacking on top of .hero-fork-card's own 20px padding wherever this is the first thing in the card (almost always, since it's usually "Details") — this was the oversized gap above every page's first heading. Anywhere a page needs real spacing before a LATER subheading, it already sets that via an inline margin-top, which still wins over this. */
    margin-bottom: 4px;
}
.settings-subheading + .auth-note {
    margin-top: 0;
}

/* 4/5 — "Status: <value>" row (was "Currently: ...") — value coloured
   red/bold, same treatment .dj_label already gets elsewhere. */
.settings-status-value {
    color: #CF1F1F;
    font-weight: bold;
}

/* 5 — a standalone .dj_label used as a plain label ABOVE an input
   (e.g. "Confirm your password to change this") was inheriting the
   full-size look meant for the bold red "DJ Name"-style field labels.
   The checkbox/radio-wrapped case already has its own :has() rule
   below this one in the file — this covers the missing case where
   dj_label wraps no input at all, just text before a separate field. */
label.dj_label:not(:has(input)) {
    font-size: 0.9rem;
}

/* 6 — one shared border colour for every bordered box/list panel.
   Inputs already use --iwp-field-border-color (#ccc); these two
   previously hardcoded their own separate colours, which is why the
   Beta list's border didn't match the Users/Cards/Schedule panels. */
.admin-scroll-list {
    border-color: var(--iwp-field-border-color);
}
.iwp-list-row {
    border-bottom-color: var(--iwp-field-border-color);
}

/* 7 — .form-button is already the sitewide standard (grey bg, red on
   hover, see rules above) — nothing new needed here, just make sure
   every button on every page actually carries that class. */

/* .admin-type-filter-options (16 Sep) — the checkbox-group rows inside
   every filter modal (Users, Cards, Genres, Show Requests, etc.) use
   this class, but it had no CSS anywhere on the site at all — each
   <label> just fell back to default inline flow, wrapping wherever it
   ran out of width rather than one per line. One shared fix here
   covers every filter modal on the site at once. */
.admin-type-filter-options {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Shared accordion box (moved here from Cron Log's own page-local
   <style> block, 16 Sep) — a bordered, padded <details>/<summary>
   panel, one per collapsible item, group them with a shared
   name="..." attribute on the <details> tags for one-open-at-a-time
   behaviour (no JS needed). Originally Cron Log-only; now also used
   by Site Maintenance's two scopes. */
.cron-job-accordion {
    border: 1px solid var(--iwp-field-border-color);
    border-radius: 6px;
    margin: 16px 0;
    padding: 12px 16px;
}
.cron-job-accordion summary {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    cursor: pointer;
    list-style: none;
}
.cron-job-accordion summary::-webkit-details-marker {
    display: none;
}

/* ==========================================================================
   Top traffic-light pill (22 Sept) — partials/top-pill.php, rendered in
   index.php straight after the header.
   Sits just under the logo (under "PARTY") at the top of a page, then as
   you scroll it rides up with the logo until it reaches the top of the
   screen and sticks there, tight to the top edge — the ON AIR pill's
   mirror image — with the page scrolling on underneath it. (A thin black
   strip above it was tried and dropped, 22 Sept.)
   ========================================================================== */
:root {
  --top-pill-height: 40px;
  --top-pill-tuck: 2px; /* how far the pill reaches up into the bottom of the logo (over "PARTY") */
}
@media (min-width: 700px) {
  :root { --top-pill-height: 46px; --top-pill-tuck: 6px; }
}
.iwp-top-pill {
  position: sticky;
  top: 0;
  align-self: center; /* body is a flex column */
  margin: calc(-1 * var(--top-pill-tuck)) auto 6px; /* reaches up into the banner; also hides the hairline seam the logo's fractional height leaves at the join */
  flex-shrink: 0;
  height: calc(var(--top-pill-height) + var(--top-pill-tuck));
  min-width: 170px;
  padding: var(--top-pill-tuck) 22px 0; /* lights stay where they were, below the logo */
  box-sizing: border-box;
  background: #fff;
  border-radius: 0 0 8px 8px;
  clip-path: inset(0 -24px -24px -24px); /* nothing (shadow or glow) spills above the pill's top edge */
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 998; /* same layer as the footer (999): under modals, the open menu and the "?" button */
}
/* The pill's shadow lives on a layer that starts where the banner ends,
   so the part of the pill reaching up over "PARTY" has no shadowed edges
   and blends into the white of the logo. */
.iwp-top-pill::before {
  content: "";
  position: absolute;
  top: var(--top-pill-tuck);
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: 0 0 8px 8px;
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
  clip-path: inset(0 -24px -24px -24px);
  pointer-events: none;
}
.iwp-top-light {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #2b2b2b;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: "Rubik Mono One", sans-serif;
  font-size: 12px;
  line-height: 1;
  text-decoration: none;
  transition: box-shadow 0.15s ease, filter 0.15s ease;
}
.iwp-top-lights {
  display: flex;
  align-items: center;
  gap: 14px;
}
/* Menu + account shortcuts: folded away (no width) until the pill sticks,
   then they slide in at either end. Plain grey outlines, so the lit
   light stays the thing your eye goes to. */
.iwp-top-pill-icon {
  width: 0;
  height: 32px;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  color: #555;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  cursor: pointer;
  border-radius: 8px;
  transition: width 0.25s ease, margin 0.25s ease, opacity 0.2s ease, visibility 0s linear 0.25s;
}
.iwp-top-pill.is-stuck .iwp-top-pill-icon {
  width: 32px;
  opacity: 1;
  visibility: visible;
  transition: width 0.25s ease, margin 0.25s ease, opacity 0.2s ease 0.05s, visibility 0s;
}
.iwp-top-pill.is-stuck .iwp-top-pill-menu { margin: 0 14px 0 -10px; }
.iwp-top-pill.is-stuck .iwp-top-pill-account { margin: 0 -10px 0 14px; }
.iwp-top-pill-icon:hover,
.iwp-top-pill-icon:focus-visible { color: #000; }
@media (min-width: 700px) {
  .iwp-top-pill { min-width: 230px; }
  .iwp-top-lights { gap: 20px; }
  .iwp-top-light { width: 32px; height: 32px; font-size: 14px; }
  .iwp-top-pill.is-stuck .iwp-top-pill-menu { margin: 0 22px 0 -8px; }
  .iwp-top-pill.is-stuck .iwp-top-pill-account { margin: 0 -8px 0 22px; }
}
/* Dimmed: each light's own colour, turned right down. */
.iwp-top-light-i { color: #6b2a2a; }
.iwp-top-light-w { color: #6e5a2e; }
.iwp-top-light-p { color: #2f5a3a; }
/* Lit: the section you're in. */
.iwp-top-light-i.is-current { background: #111; color: #ff5a5a; box-shadow: 0 0 0 2px #CF1F1F, 0 0 12px rgba(255, 60, 60, 0.85); }
.iwp-top-light-w.is-current { background: #111; color: #F2A516; box-shadow: 0 0 0 2px #F2A516, 0 0 12px rgba(242, 165, 22, 0.85); }
.iwp-top-light-p.is-current { background: #111; color: #5BE37F; box-shadow: 0 0 0 2px #1E8A3C, 0 0 12px rgba(91, 227, 127, 0.8); }
a.iwp-top-light:not(.is-current):hover,
a.iwp-top-light:focus-visible {
  filter: brightness(1.8);
}
.iwp-top-light.is-soon {
  cursor: default;
  opacity: 0.75;
}
/* Out of the way while the full-screen menu is open (same as the "?" button). */
body:has(#main-navigation-toggle:checked) .iwp-top-pill {
  display: none;
}
/* ==========================================================================
   Phone layout (24 Sept)

   Found testing on an iPhone 17 Pro: at the phone's normal width (402px)
   pages were cramped, and with Safari's page zoom at 150% (which leaves
   ~270px to lay out in) they became unusable. The side tabs stay, as the
   site's main way around, but everything around them gives way:

   - The grey panel's padding/border and the page wrappers' 16px side
     padding are dropped, so the tabs sit flush against the screen edges
     and the white card gets the width in between.
   - The tabs themselves are a little slimmer and stick just below the
     top pill (they used to stick at 16px, underneath it), and they're
     never taller than the gap between the top pill and the footer.
   - The footer and its ON AIR pill are shorter/narrower, so the page has
     more height and the "?" button can sit beside the pill instead of on
     top of it.
   - Long words/URLs wrap instead of pushing the page wider than the
     screen (the Privacy page overflowed sideways).

   Tested at 402px (normal) and 268px (402px at 150% page zoom). Desktop
   and tablet (over 600px) are untouched.
   ========================================================================== */

/* Every width: #content is a flex container, so the page inside it
   defaulted to min-width:auto and refused to get narrower than its
   longest unbreakable word (e.g. "Mixcloud/SoundCloud/Instagram," on
   Privacy), pushing the page off the right of the screen. */
#content > * {
    min-width: 0;
}
.hero-carousel-card {
    overflow-wrap: break-word;
}

/* Every width: the "?" button was at z-index 9500, above every modal
   (6000), so it sat on top of the login modal's "Forgot your password?"
   link. 1000 keeps it above the footer (999) and the page but under the
   open menu (1002), drawers and modals. The tour still lifts it over the
   dim when it points at it (.iwp-tip-highlight). */
#iwp-help-btn {
    z-index: 1000;
}
#iwp-help-btn.iwp-tip-highlight {
    z-index: 10002;
}

/* Every width: the modal overlay's bottom padding clears the iPhone's
   home bar / Safari toolbar, so a long modal's last button can always
   be scrolled into view. */
.schedule-modal {
    padding-bottom: calc(30px + env(safe-area-inset-bottom, 0px));
}

@media (max-width: 600px) {

    :root {
        --hero-carousel-tab-width: 26px;
        --footer-bar-height: 60px;
    }

    /* --- Page wrappers: no side padding, no grey frame ----------------- */
    .page-container,
    .iwppage-container,
    .site-page {
        padding-left: 0;
        padding-right: 0;
    }
    .MixcloudSpacing {
        max-width: none;
        margin: 0 auto;
        padding: 10px 12px 12px;
        border: 0;
        border-radius: 0;
    }
    /* The carousel (tabs + card) reaches back out through the panel's
       12px padding to the screen edges; headings and page tools above it
       keep the 12px. */
    .MixcloudSpacing > .hero-carousel,
    .MixcloudSpacing > #hero-player {
        margin-left: -12px;
        margin-right: -12px;
    }

    /* --- Side tabs ----------------------------------------------------- */
    .hero-carousel-tab {
        /* Stick just below the top pill once it's stuck, not under it. */
        top: calc(var(--top-pill-height) + 10px);
        margin-top: 20px;
        /* Never taller than the gap between the stuck top pill and the
           footer, so the bottom of the tab is never hidden behind the
           footer on a short screen; 150px floor so a label still fits. */
        height: clamp(150px, calc(100dvh - var(--top-pill-height) - var(--footer-height) - 40px), var(--hero-carousel-tab-height));
        font-size: 10px;
        letter-spacing: 0.5px;
        padding-top: 12px;
    }
    .hero-carousel-card {
        min-height: 0;
    }

    /* --- White card ---------------------------------------------------- */
    .hero-fork-card {
        padding: 14px 10px;
    }

    /* --- Footer: shorter bar, narrower ON AIR pill ---------------------- */
    .footer-bar {
        padding: 0 10px 0 14px;
    }
    .footer-onair {
        top: -30px;
        height: 80px;
        min-width: 0;
        padding: 9px 22px 0;
        gap: 10px;
    }
    .onair-badge {
        font-size: 15px;
        margin-top: -2px;
        white-space: nowrap;
    }
    .footer-play-pause {
        margin-top: -6px;
    }
    .footer-play-pause-icon {
        width: 26px;
        height: 26px;
    }
    .footer-np-station { font-size: 10px; }
    .footer-np-title { font-size: 12px; }

    /* --- "?" button: smaller, beside the ON AIR pill -------------------- */
    #iwp-help-btn {
        right: 10px;
        bottom: calc(var(--footer-chrome-height) + 6px);
        width: 40px;
        height: 40px;
        font-size: 18px;
    }

    /* --- Modals: more room for the form ------------------------------- */
    .schedule-modal {
        padding-left: 8px;
        padding-right: 8px;
    }
    .schedule-modal-inner {
        padding: 16px;
    }
    .schedule-modal-titlebar {
        margin: -16px -16px 14px -16px;
    }
}

/* Very narrow (a small phone, or any phone with page zoom turned up):
   two-column form rows (e.g. Contact's First Name / Surname) stack. */
@media (max-width: 380px) {
    /* --- Header: menu + account icons live in the top pill ------------ */
    /* On a very narrow screen (a small phone, or 150% page zoom) the logo
       needs the full width, which left the header's own hamburger and
       account icons squeezed into a sliver of black. Normal phones keep
       the header icons and the slide-in when the pill sticks. Here the
       top pill's own menu and account buttons are shown all the time
       instead, so they're in the same place whether you're at the top
       of a page or scrolled down. The header's
       hamburger comes back while the menu is open, since it turns into
       the menu's close (X). */
    .iwp-top-pill .iwp-top-pill-icon {
        width: 32px;
        opacity: 1;
        visibility: visible;
    }
    .iwp-top-pill .iwp-top-pill-menu { margin: 0 14px 0 -10px; }
    .iwp-top-pill .iwp-top-pill-account { margin: 0 -10px 0 14px; }
    header .iwp-login-icon {
        visibility: hidden;
    }
    body:not(:has(#main-navigation-toggle:checked)) .iwp-filler.left label {
        visibility: hidden;
    }

    .dj_two-col {
        grid-template-columns: 1fr;
        gap: 0;
    }
    .dj_two-col > .dj_col + .dj_col {
        margin-top: 1rem;
    }
}