/*
 * styles.css — mirrors the tokens in src/theme.ts so the web surface reads as
 * the same product as the app. The app's accent is gold; text on a gold fill is
 * deep navy (contrast), which is why .btn-primary is dark-on-gold.
 */
:root {
  /* Navy environment, matching C.bg / C.surface / C.elevated in src/theme.ts. */
  --bg: #0E192B;
  --bg-deep: #091321;
  --surface: #151D29;
  --surface2: #1B2533;
  --interactive: #202B3A;
  --border: #293647;
  --border2: #3D4E66;
  /* Up Next electric blue. Token names kept from earlier palettes so the ~60
     references here convert by value. Blue takes DEEP NAVY on top so the neon
     fill reads electric — mirrors C.accent / C.onAccent in src/theme.ts. */
  --gold: #2F86FF;       /* brand / audio / active — not decoration */
  --gold2: #57B0FF;      /* the primary action */
  --gold-dim: rgba(47, 134, 255, 0.14);
  --on-accent: #04101F;
  /* Retuned from #E5484D, which measures 3.95–4.50:1 on these navies. */
  --red: #F2555A;
  --green: #82C65B;
  --text: #F7F3E8;
  --text2: #A1ADBD;
  /* Retuned from #69788D, which fails 4.5:1 on every navy surface. */
  --text3: #8494AA;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* A phone-width column: this surface is opened on a phone, from a text or an
   email, essentially every time. */
.wrap {
  max-width: 520px;
  margin: 0 auto;
  padding: 28px 20px 64px;
}
/* with the shared site chrome above it, the reading column no longer needs
   to supply its own top gap */
.site-nav + .wrap { padding-top: 34px; }

/* ── SHARED SITE CHROME ──────────────────────────────────────────────────────
 * The same sticky header and footer as the landing page, so /contact,
 * /privacy and /terms read as the same site instead of bare documents.
 *
 * These deliberately do NOT reuse .wrap: here that is the 520px reading
 * column, while the chrome needs the landing page's 1140px container. Hence
 * .site-wrap, and .site-* names throughout — nothing below collides with the
 * legal-page styles above.
 *
 * The landing page keeps its own copy of these rules in its inline <style>;
 * it is a single self-contained file on purpose. The values here mirror it.
 */
:root {
  /* the marketing surface's cyan→lime system, which the app-blue tokens
     above do not cover */
  --site-grad: linear-gradient(90deg, #37DBFF 0%, #25E4C6 48%, #B9F24A 100%);
  --site-cyan: #25E4C6;
  --site-on-cyan: #04141F;
}
.site-wrap { max-width: 1140px; margin: 0 auto; padding: 0 24px; }
/* On a short page (/contact-sent.html) the footer would otherwise float
   halfway up. Scoped with :has() so join.html, which shares this stylesheet
   and has no site chrome, keeps its own layout. Browsers without :has() just
   get the un-pinned footer. */
body:has(> .site-foot) { display: flex; flex-direction: column; min-height: 100vh; }
body:has(> .site-foot) .site-foot { margin-top: auto; }

.site-nav {
  position: sticky; top: 0; z-index: 50;
  backdrop-filter: blur(14px);
  background: rgba(5, 6, 8, 0.72);
  border-bottom: 1px solid var(--border);
}
.site-nav-in {
  display: flex; align-items: center; justify-content: space-between;
  height: 58px;
}
.site-brand { display: flex; align-items: center; gap: 10px; }
.site-brand img { display: block; width: 186px; height: auto; }
@media (max-width: 520px) { .site-brand img { width: 150px; } }
.site-links { display: flex; gap: 28px; align-items: center; }
.site-links a { color: var(--text2); font-weight: 600; font-size: 14px; text-decoration: none; }
.site-links a:hover { color: var(--text); }
@media (max-width: 800px) { .site-links a:not(.site-cta) { display: none; } }
/* sized as a nav item, matching the landing page: 38px in a 58px bar */
.site-cta {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--site-grad); color: var(--site-on-cyan);
  font-size: 13.5px; font-weight: 800; line-height: 1.5;
  padding: 8px 16px; border-radius: 10px;
  border: 1px solid transparent; white-space: nowrap;
  box-shadow: 0 4px 14px -6px rgba(37, 228, 198, 0.5);
  transition: 0.2s;
}
.site-links a.site-cta, .site-links a.site-cta:hover { color: var(--site-on-cyan); }
.site-cta:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 20px -8px rgba(37, 228, 198, 0.62);
}

.site-foot {
  border-top: 1px solid var(--border);
  padding: 40px 0 34px;
  color: var(--text3); font-size: 13px;
}
.site-foot-in {
  display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap; gap: 16px;
}
.site-foot-in a { color: var(--text3); text-decoration: none; }
.site-foot-in a:hover { color: var(--text); }
.site-foot-links { display: flex; gap: 22px; flex-wrap: wrap; }
.site-tagline {
  text-align: center; padding: 26px 24px 0;
  color: var(--text3); font-weight: 800; font-size: 12px; letter-spacing: 0.3em;
}
/* the footer brand lockup is the wordmark image, like the landing page */
.site-foot .site-brand img { width: 150px; }

h1 { font-size: 25px; line-height: 1.22; font-weight: 800; letter-spacing: -0.5px; margin: 0 0 10px; }
h2 { font-size: 15px; font-weight: 700; margin: 26px 0 10px; }
p  { color: var(--text2); font-size: 15px; line-height: 1.5; margin: 0 0 14px; }
.muted  { color: var(--text3); font-size: 13px; line-height: 1.5; }
.center { text-align: center; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 16px;
  margin: 16px 0;
}

.row { display: flex; align-items: center; gap: 10px; padding: 9px 0; }
.row + .row { border-top: 1px solid var(--border); }
.row-text { flex: 1; font-size: 14px; }
.tick { color: var(--green); font-weight: 700; }

label { display: block; font-size: 14px; font-weight: 700; margin: 16px 0 7px; }

/* password included: /auth/action's reset form uses it, and without it the
   field falls back to a tiny unstyled native input */
input[type="email"], input[type="text"], input[type="search"], input[type="number"],
input[type="password"] {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: 13px;
  color: var(--text);
  font-size: 16px; /* 16px keeps iOS Safari from zooming on focus */
  font-family: inherit;
}
input:focus { outline: none; border-color: var(--gold); }

/* Contact form. textarea/select were never styled here because no page had
   them; they inherit the input treatment so /contact.html needs no CSS of
   its own. */
textarea, select {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: 13px;
  color: var(--text);
  font-size: 16px; /* 16px keeps iOS Safari from zooming on focus */
  font-family: inherit;
}
textarea { min-height: 148px; resize: vertical; line-height: 1.5; }
textarea:focus, select:focus { outline: none; border-color: var(--gold); }
select {
  appearance: none; -webkit-appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text2) 50%),
                    linear-gradient(135deg, var(--text2) 50%, transparent 50%);
  background-position: calc(100% - 20px) 52%, calc(100% - 14px) 52%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 38px;
}
/* the honeypot: a real field, kept out of sight and out of the tab order */
.hp { position: absolute; left: -9999px; opacity: 0; }
label .opt { font-weight: 500; color: var(--text3); }
/* submit result, announced to screen readers via aria-live */
.formnote { margin-top: 14px; font-size: 14px; line-height: 1.5; border-radius: 11px; padding: 13px; }
.formnote.ok  { background: rgba(130,198,91,.12); border: 1px solid rgba(130,198,91,.4); color: var(--text); }
.formnote.err { background: rgba(242,85,90,.1);  border: 1px solid rgba(242,85,90,.4);  color: var(--text); }
.formnote:empty { display: none; }
/* the "send it the direct way" fallback inside an error note: a button, but
   it should read as the link it behaves like */
/* ── Firebase email action handler (/auth/action) ───────────────────────────── */
.auth-badge {
  width: 64px; height: 64px; border-radius: 50%;
  display: grid; place-items: center; margin: 0 0 20px;
  font-size: 30px; line-height: 1;
}
.auth-badge.ok   { background: rgba(130,198,91,.14); border: 1px solid rgba(130,198,91,.45); }
.auth-badge.bad  { background: rgba(242,85,90,.12);  border: 1px solid rgba(242,85,90,.45); }
.auth-badge.wait { background: var(--gold-dim);      border: 1px solid var(--border2); }
/* the spinner shown while the code is being applied */
.auth-spin {
  width: 26px; height: 26px; border-radius: 50%;
  border: 2.5px solid var(--border2); border-top-color: var(--gold2);
  animation: authspin .8s linear infinite;
}
@keyframes authspin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .auth-spin { animation-duration: 2.4s; } }
/* the small print under an action result */
.auth-note { color: var(--text3); font-size: 13px; line-height: 1.55; margin-top: 18px; }
.auth-note code {
  background: var(--surface2); border: 1px solid var(--border);
  border-radius: 5px; padding: 1px 5px; font-size: 12px;
}
.auth-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 24px; }
.auth-actions .btn { margin-top: 0; }
[hidden] { display: none !important; }

.linkish {
  background: none; border: 0; padding: 0; margin: 0;
  color: var(--gold2); font: inherit; font-weight: 700;
  cursor: pointer; text-decoration: underline;
}

.btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%;
  border: 0; border-radius: 12px;
  padding: 15px;
  font-size: 16px; font-weight: 700; font-family: inherit;
  cursor: pointer;
  margin-top: 14px;
  text-decoration: none;
}
.btn-primary { background: var(--gold); color: var(--on-accent); }
.btn-primary:disabled { opacity: 0.45; cursor: default; }
.btn-secondary {
  background: transparent; color: var(--text);
  border: 1px solid var(--border2);
}
.btn-text { background: none; color: var(--text2); font-weight: 600; padding: 12px; }
.btn-danger { background: none; color: var(--red); font-weight: 600; }

.pill {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--gold-dim); color: var(--gold2);
  border-radius: 999px; padding: 5px 11px;
  font-size: 12px; font-weight: 700;
}

/* ── Photo ── */
.photo-slot {
  width: 128px; height: 128px;
  border-radius: 64px;
  background: var(--surface2);
  border: 1px dashed var(--border2);
  display: grid; place-items: center;
  margin: 0 auto 12px;
  overflow: hidden;
  transition: border-color 0.15s ease;
}
.photo-slot:has(img) { border-style: solid; border-color: var(--border); }
.photo-slot img { width: 100%; height: 100%; object-fit: cover; }

/* ── Busy states ────────────────────────────────────────────────────────────
   Uploading a phone photo takes 4–6s: read the file, base64 it, send it, and
   re-encode it server-side through sharp to strip EXIF. The page did say
   "Uploading photo…" — but in #msg, which sits above the Photo heading, so on
   a phone the parent had scrolled past it and saw nothing move at all.

   Progress belongs on the thing being changed. The slot dims and spins over
   the parent's own photo (shown immediately from the local file, before the
   upload finishes), so the wait reads as "saving this" rather than "nothing
   happened". */
.photo-slot.is-busy { border-color: var(--accent); border-style: solid; }
.photo-slot.is-busy img { opacity: 0.45; filter: saturate(0.6); }
.photo-slot.is-busy::after {
  content: '';
  position: absolute;
  width: 30px; height: 30px;
  border: 3px solid rgba(255, 255, 255, 0.28);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
.photo-slot { position: relative; }

/* A spinner inside a secondary button, where --on-accent has no contrast. */
.spinner-dark {
  border-color: var(--border2);
  border-top-color: var(--text);
}
/* Keeps a button's label and spinner on one line without it jumping width. */
.btn-busy { display: inline-flex; align-items: center; justify-content: center; gap: 9px; }

/* ── Song search ── */
.results { margin-top: 10px; }
.result {
  display: flex; align-items: center; gap: 11px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 11px; padding: 10px;
  margin-bottom: 7px; cursor: pointer;
  width: 100%; text-align: left; font-family: inherit;
}
.result.on { border-color: var(--gold); }
.result img { width: 44px; height: 44px; border-radius: 7px; flex: none; background: var(--surface2); }
.result-meta { flex: 1; min-width: 0; }
.result-title {
  color: var(--text); font-size: 14px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.result-artist {
  color: var(--text3); font-size: 12.5px; margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.explicit {
  font-size: 9px; font-weight: 800; color: var(--text3);
  border: 1px solid var(--text3); border-radius: 3px;
  padding: 0 3px; margin-left: 5px; vertical-align: middle;
}

.banner {
  border-radius: 11px; padding: 12px 14px; margin: 14px 0;
  font-size: 13.5px; line-height: 1.45;
}
.banner-err  { background: rgba(220, 38, 38, 0.12); color: #fca5a5; }
.banner-ok   { background: rgba(22, 163, 74, 0.13); color: #86efac; }
.banner-info { background: var(--surface2); color: var(--text2); }

.spinner {
  width: 19px; height: 19px;
  border: 2px solid rgba(9, 19, 33, 0.3);
  border-top-color: var(--on-accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.hidden { display: none !important; }

/* ── Brand ─────────────────────────────────────────────────────────────────── */
/* The website header logo: the purpose-made horizontal wordmark, the same
   asset the marketing nav uses.
   This replaced an icon-mark + hand-set "Up <i>Next</i>" lockup, which printed
   the brand name TWICE — icon-mark.png is the app icon and already contains
   the words UP NEXT — in two typefaces and two different blues, with the
   icon's own wordmark reduced to an illegible smudge at 30px. */
.brand { display: inline-flex; align-items: center; margin-bottom: 22px; text-decoration: none; }
.brand-web { display: block; width: 150px; height: auto; }
.hero-logo { width: 230px; margin: 0 auto 22px; display: block; }

.slot-empty {
  color: var(--text3);
  font-size: 12.5px; font-weight: 700;
  letter-spacing: 0.2px;
}

/* ── Clip start ────────────────────────────────────────────────────────────── */
.start-row { display: flex; align-items: center; gap: 11px; }
.start-row input { flex: 1; }
.start-mmss {
  font-variant-numeric: tabular-nums;
  font-size: 19px; font-weight: 800;
  color: var(--gold2);
  min-width: 58px; text-align: right;
}

/* One tap to accept the recommendation — the number a parent cannot guess. */
.chip-rec {
  display: inline-flex; align-items: baseline; gap: 7px;
  margin-top: 11px;
  background: var(--gold-dim);
  border: 1px solid rgba(47, 134, 255, 0.35);
  border-radius: 999px;
  padding: 8px 14px;
  color: var(--gold2);
  font-size: 13.5px; font-weight: 800; font-family: inherit;
  cursor: pointer;
}
.chip-rec:hover { border-color: var(--gold); }
.chip-on { background: var(--gold); color: var(--on-accent); border-color: var(--gold); }
.chip-why { font-size: 11.5px; font-weight: 600; opacity: 0.75; }

/* ── Completion checklist ──────────────────────────────────────────────────── */
.checklist { display: flex; gap: 7px; margin: 4px 0 20px; }
.step {
  flex: 1;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 9px 8px;
  text-align: center;
}
.step-on { border-color: rgba(22, 163, 74, 0.5); background: rgba(22, 163, 74, 0.08); }
.step-icon { font-size: 15px; line-height: 1; }
.step-label {
  display: block; margin-top: 5px;
  font-size: 10.5px; font-weight: 800; letter-spacing: 0.3px;
  text-transform: uppercase; color: var(--text3);
}
.step-on .step-label { color: #86efac; }

/* Nudge the eye to what's left, without nagging. */
.all-done {
  background: rgba(22, 163, 74, 0.13);
  border: 1px solid rgba(22, 163, 74, 0.3);
  border-radius: 12px; padding: 14px;
  margin: 16px 0;
  color: #86efac; font-size: 14px; line-height: 1.5;
}

/* ── Child switcher (a parent with siblings on one team) ────────────────────── */
/* Scrolls sideways rather than dividing the width, because the number of
   children is not bounded. With `flex: 1` every tab took an equal share and
   ellipsised, so a parent with seven players got seven tabs reading "Pla…" —
   identical, and useless for choosing between them. Sizing to the name keeps
   every one legible at any count, and a strip that runs off the edge is the
   normal way to say "there are more". */
.switcher {
  display: flex; gap: 7px; margin-bottom: 18px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  /* The bar itself would sit on top of the tabs on a short strip. */
  scrollbar-width: none;
}
.switcher::-webkit-scrollbar { display: none; }
.switch-tab {
  /* Never squeezed: the name is the entire point of the control. */
  flex: 0 0 auto;
  scroll-snap-align: start;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 11px; padding: 11px 13px;
  color: var(--text2); font-size: 14px; font-weight: 700; font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
}
.switch-on {
  border-color: var(--gold); background: var(--gold-dim); color: var(--gold2);
  cursor: default;
}

/* ── Legal pages ────────────────────────────────────────────────────────────── */
/* Wider and looser than the app-like screens: these are read, not tapped. */
.legal { max-width: 680px; }
.legal h1 { font-size: 30px; margin-bottom: 6px; }
.legal h2 {
  font-size: 17px; font-weight: 800;
  margin: 30px 0 10px;
  color: var(--text);
}
.legal p, .legal li { color: var(--text2); font-size: 15.5px; line-height: 1.62; }
.legal ul { padding-left: 20px; margin: 0 0 14px; }
.legal li { margin-bottom: 7px; }
.legal strong { color: var(--text); }
.legal a { color: var(--gold2); }
