/* ============================================================
   FM Studio — public station website
   Neutral greyscale surfaces so the ONE colour on the page is the station's
   own accent (--sx-primary, injected per station in the layout). No gradients
   and no decorative colour: a station's brand should be the only hue a
   listener sees. One stylesheet serves every tenant.
   ============================================================ */

:root {
    --sx-primary: #171717;
    --sx-secondary: #171717;
    --sx-font: "Inter", -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --sx-radius: 3px;
    --sx-player-h: 76px;
}

/* The single state colour on the public site. Everything else is the
   station's own accent or greyscale. */
:root { --sx-live: #4ec27f; }

[data-bs-theme="dark"] {
    --sx-bg: #0a0a0a;
    --sx-surface: #121212;
    --sx-text: #f4f4f4;
    --sx-muted: #9a9a9a;
    --sx-border: #232323;
}
[data-bs-theme="light"] {
    --sx-bg: #fafafa;
    --sx-surface: #ffffff;
    --sx-text: #121212;
    --sx-muted: #565656;
    --sx-border: #d9d9d9;
}

.sx-body {
    font-family: var(--sx-font);
    background: var(--sx-bg);
    color: var(--sx-text);
    /* room for the sticky player */
    padding-bottom: calc(var(--sx-player-h) + 12px);
    letter-spacing: -.01em;
}

a { color: var(--sx-primary); }
a:hover { color: var(--sx-primary); text-decoration: underline; }

/* ---------- Header / nav ---------- */
.sx-header {
    background: var(--sx-surface);
    border-bottom: 1px solid var(--sx-border);
    position: sticky; top: 0; z-index: 1020;
}
.sx-brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; color: var(--sx-text); }
.sx-brand-name { font-weight: 600; font-size: 1.05rem; letter-spacing: -.02em; }
.sx-logo { height: 40px; width: auto; max-width: 160px; object-fit: contain; }
/* The embed is narrow, so the mark gets a little more room but a hard ceiling */
.sx-logo-embed { height: auto; max-height: 56px; max-width: 70%; display: block; margin: 0 auto; }
.sx-logo-fallback {
    width: 36px; height: 36px; border-radius: 3px; color: var(--sx-on-primary);
    display: flex; align-items: center; justify-content: center; font-size: 1.15rem;
    background: var(--sx-primary);
}
.sx-nav { display: flex; gap: 1.25rem; }
.sx-nav a {
    color: var(--sx-muted); text-decoration: none; font-size: .93rem; font-weight: 500;
    padding: .25rem 0; border-bottom: 2px solid transparent;
}
.sx-nav a:hover { color: var(--sx-primary); border-bottom-color: var(--sx-primary); }
.sx-nav-toggle { color: var(--sx-text); border: 1px solid var(--sx-border); }
@media (max-width: 991.98px) {
    .sx-nav { flex-direction: column; gap: .4rem; width: 100%; padding-top: .75rem; }
}

/* ---------- Now-playing centrepiece ---------- */
/* The page's primary surface. A listener came to listen, so the track title is
   the largest thing here and there is exactly one primary control. */
.sx-np {
    position: relative;
    padding: clamp(2.5rem, 7vw, 4.5rem) 0;
    background-color: var(--sx-surface);
    background-size: cover; background-position: center;
    border-bottom: 1px solid var(--sx-border);
    text-align: center;
}
/* A banner is decoration; it must never fight the title for legibility.
   Keyed off .has-banner, set by the view. The old selector matched a `style`
   ATTRIBUTE, but the image came from a <style> block, so this never applied. */
.sx-np.has-banner::before {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--sx-bg) 62%, transparent),
        color-mix(in srgb, var(--sx-bg) 88%, transparent));
}
.sx-np > .container { position: relative; z-index: 1; }
.sx-np-inner { max-width: 34rem; margin: 0 auto; }

/* The cover is context, not the headline — the track title is. 34vw made it
   dominate a phone screen and push the title and play control below the fold.
   Scales with the viewport but stays modest at both ends. */
.sx-np-art {
    width: clamp(6.5rem, 20vw, 9.5rem); aspect-ratio: 1;
    margin: 0 auto 1.35rem;
    border: 1px solid var(--sx-border); border-radius: 3px;
    background: var(--sx-bg);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
.sx-np-art img { width: 100%; height: 100%; object-fit: cover; }
.sx-np-art-fallback { font-size: 1.9rem; color: var(--sx-muted); opacity: .45; }

.sx-np-status {
    font-size: .75rem; letter-spacing: .09em; text-transform: uppercase;
    color: var(--sx-muted); margin: 0 0 .9rem; font-weight: 500;
}
.sx-np-sep { margin: 0 .4rem; opacity: .5; }

.sx-np-title {
    font-size: clamp(1.5rem, 4.5vw, 2.25rem); font-weight: 600;
    letter-spacing: -.03em; line-height: 1.2; margin: 0 0 .4rem;
    overflow-wrap: anywhere;
}
.sx-np-artist { color: var(--sx-muted); font-size: 1rem; margin: 0 0 2rem; min-height: 1.5rem; }

.sx-np-controls { display: flex; align-items: center; justify-content: center; gap: 1.25rem; }
.sx-np-play {
    width: 64px; height: 64px; border-radius: 50%; border: 0; flex-shrink: 0;
    background: var(--sx-primary); color: var(--sx-on-primary);
    font-size: 1.6rem; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: transform .12s ease;
}
.sx-np-play:hover:not(:disabled) { transform: scale(1.04); }
.sx-np-play:disabled { opacity: .4; cursor: not-allowed; }
.sx-np-volume { display: flex; align-items: center; gap: .5rem; }
.sx-np-note { margin: 1.25rem 0 0; font-size: .82rem; color: var(--sx-muted); min-height: 1.2rem; }

@media (max-width: 575.98px) {
    .sx-np-volume { display: none; }   /* phones have hardware volume */
}

/* Live indicator — a state colour, not a decorative one */
.sx-live-dot {
    display: inline-block; width: .5rem; height: .5rem; border-radius: 50%;
    background: var(--sx-live); margin-right: .45rem; vertical-align: middle;
    animation: sxpulse 2s ease-in-out infinite;
}
@keyframes sxpulse { 0%,100% { opacity: 1 } 50% { opacity: .35 } }

.sx-spin { display: inline-block; animation: sxspin 1s linear infinite; }
@keyframes sxspin { to { transform: rotate(360deg) } }

/* A pulsing dot and a spinner are both vestibular triggers */
@media (prefers-reduced-motion: reduce) {
    .sx-live-dot, .sx-spin { animation: none; }
    .sx-np-play { transition: none; }
}

/* ---------- Cards & sections ---------- */
.sx-section { padding: 3rem 0; }
.sx-section h2 { font-size: 1.05rem; font-weight: 600; letter-spacing: -.02em; margin-bottom: 1.25rem; }
.sx-card {
    background: var(--sx-surface);
    border: 1px solid var(--sx-border);
    border-radius: var(--sx-radius);
    padding: 1.1rem;
    height: 100%;
}
.sx-muted { color: var(--sx-muted); }

.sx-track { display: flex; align-items: center; gap: .8rem; padding: .55rem 0; border-bottom: 1px solid var(--sx-border); }
.sx-track:last-child { border-bottom: 0; }
.sx-track-art {
    width: 42px; height: 42px; border-radius: 3px; object-fit: cover; flex-shrink: 0;
    background: color-mix(in srgb, var(--sx-primary) 14%, transparent);
    display: flex; align-items: center; justify-content: center; color: var(--sx-primary);
}

/* Foreground is computed from the station's accent (PublicStationResolver::
   readableOn) — assuming white made pale accents unreadable. */
.sx-btn {
    background: var(--sx-primary);
    color: var(--sx-on-primary); border: 0; border-radius: 3px;
    padding: .6rem 1.4rem; min-height: 44px;
    font-weight: 500; text-decoration: none;
    display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
}
.sx-btn:hover { color: var(--sx-on-primary); filter: brightness(1.08); }

/* Icon-only controls still need a 44px target even though the glyph is small */
.sx-icon-btn {
    background: none; border: 0; color: var(--sx-muted); cursor: pointer;
    width: 44px; height: 44px; border-radius: 3px; font-size: 1.05rem;
    display: inline-flex; align-items: center; justify-content: center;
}
.sx-icon-btn:hover { color: var(--sx-text); }

.sx-range { width: 110px; accent-color: var(--sx-primary); }

:where(a, button, input, select, textarea):focus-visible {
    outline: 2px solid var(--sx-primary);
    outline-offset: 2px;
}
.sx-btn-ghost {
    background: transparent; border: 1px solid var(--sx-border); color: var(--sx-text);
    border-radius: 3px; padding: .6rem 1.2rem; text-decoration: none;
    display: inline-flex; align-items: center; gap: .5rem;
}

/* ---------- Sticky player ---------- */
.sx-player {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 1040;
    background: color-mix(in srgb, var(--sx-surface) 92%, transparent);
    border-top: 1px solid var(--sx-border);
    backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
    transition: transform .22s ease, opacity .22s ease;
}
/* On the home page the bar waits until the centrepiece scrolls away, so the
   two are never both presenting as the primary control. */
.sx-player.is-deferred { transform: translateY(100%); opacity: 0; pointer-events: none; }
.sx-player.is-deferred.is-visible { transform: none; opacity: 1; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .sx-player { transition: none; } }
.sx-player-inner {
    display: flex; align-items: center; gap: 1rem;
    padding: .6rem 1rem; min-height: var(--sx-player-h);
    max-width: 1140px; margin: 0 auto;
}
.sx-player-volume { display: flex; align-items: center; gap: .4rem; }
.sx-play-btn {
    width: 44px; height: 44px; border-radius: 50%; border: 0; flex-shrink: 0;
    background: var(--sx-primary); color: var(--sx-on-primary);
    font-size: 1.15rem; display: flex; align-items: center; justify-content: center;
    cursor: pointer;
}
.sx-play-btn:disabled { opacity: .5; cursor: not-allowed; }
.sx-now { min-width: 0; flex: 1; }
.sx-now-title { font-weight: 600; font-size: .95rem; }
.sx-now-artist { font-size: .8rem; color: var(--sx-muted); }
.sx-now-art { width: 46px; height: 46px; border-radius: 3px; object-fit: cover; flex-shrink: 0; }
.sx-listeners { font-size: .8rem; color: var(--sx-muted); white-space: nowrap; }

@media (max-width: 575.98px) {
    .sx-player-volume, .sx-listeners { display: none; }
}

/* ---------- Off air ---------- */
.sx-offair {
    min-height: 70vh; display: flex; align-items: center; justify-content: center; text-align: center;
}
.sx-offair-icon { font-size: 3.4rem; color: var(--sx-muted); }

/* ---------- Footer ---------- */
.sx-footer { border-top: 1px solid var(--sx-border); background: var(--sx-surface); color: var(--sx-muted); }
.sx-social a { color: var(--sx-muted); font-size: 1.15rem; }
.sx-social a:hover { color: var(--sx-primary); }
.sx-powered { color: var(--sx-muted); opacity: .75; }
.sx-powered a { color: var(--sx-muted); text-decoration: underline; }

/* ---------- Podcast episode player ----------
   Same shape as the live now-playing block (.sx-np-*), deliberately: a listener
   should not feel they have moved to a different product. The one addition is a
   seek bar — a live stream has nothing to seek, an episode does. */
.sx-ep {
    position: relative;
    padding: clamp(2rem, 5vw, 3rem) 0;
    background-color: var(--sx-surface);
    border-bottom: 1px solid var(--sx-border);
    text-align: center;
}
.sx-ep-inner { max-width: 34rem; margin: 0 auto; }

.sx-ep-seek {
    display: flex; align-items: center; gap: .6rem;
    margin: 0 auto 1.25rem; max-width: 26rem;
}
.sx-ep-range { flex: 1; }
.sx-ep-time {
    font-size: .72rem; color: var(--sx-muted);
    font-variant-numeric: tabular-nums; min-width: 2.6rem;
}
.sx-ep-time:last-child { text-align: right; }

/* Row play button: a quiet circle until it is the one playing */
.sx-ep-play {
    width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
    border: 1px solid var(--sx-border); background: transparent;
    color: var(--sx-text); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: border-color .12s ease, color .12s ease;
}
.sx-ep-play:hover { border-color: var(--sx-primary); color: var(--sx-primary); }
.sx-ep-row.is-playing .sx-ep-play {
    background: var(--sx-primary); color: var(--sx-on-primary); border-color: var(--sx-primary);
}
.sx-ep-row.is-playing > .min-w-0 > .fw-semibold { color: var(--sx-primary); }

@media (prefers-reduced-motion: reduce) {
    .sx-ep-play { transition: none; }
}

/* ---------- Utilities ----------
   Not a Bootstrap class, but the public views and public.js use it to let a
   flex child shrink so `.text-truncate` can actually truncate. See app.css. */
.min-w-0 { min-width: 0 !important; }

/* ---------- Song request feedback ---------- */
#sxReqStatus { font-size: .82rem; color: var(--sx-muted); min-height: 1.2rem; margin-top: .5rem; }
#sxReqStatus.is-error { color: #e0645f; }
