/*
 * Hello TV — companion.
 *
 * The palette is sampled from the mark itself, not chosen: the ring of the TV body sweeps
 * cyan → blue → violet → magenta → orange → yellow, and those are the literal pixel values
 * out of assets/logo/icon.png.
 *
 * The logo's composition is the design rule too. It is one bright object on near-black,
 * and everything else is dark and quiet. So colour here is earned — the primary action,
 * the current selection, the pairing code — and nothing else gets any. A neon accent on
 * every surface would read as noise and make the one thing that matters on each screen
 * harder to find, which is the opposite of what the mark does.
 */

:root {
  /* Sampled from the ring of the TV body. */
  --brand-cyan: #00d3ff;
  --brand-blue: #145df6;
  --brand-violet: #8925fd;
  --brand-magenta: #ff3eb5;
  --brand-orange: #fdb92a;

  /* The sweep, in the order it runs around the mark. */
  --grad: linear-gradient(100deg,
    var(--brand-cyan) 0%,
    var(--brand-blue) 26%,
    var(--brand-violet) 48%,
    var(--brand-magenta) 72%,
    var(--brand-orange) 100%);

  /* The art's own ground, so the page and the icon sit on the same black. */
  --bg: #010412;
  --surface: #0b1022;
  --surface-2: #131a2e;
  --border: #1e2740;
  --border-lit: #2b3757;

  --text: #eef1f8;
  --muted: #8f98ad;
  --ok: #3ddc97;
  --danger: #ff5d6c;

  --radius: 14px;
  --radius-lg: 20px;
}

* { box-sizing: border-box; }

/*
 * The `hidden` attribute has to win.
 *
 * `hidden` is only `display: none` from the UA stylesheet, so any author rule that sets
 * `display` beats it — and this file sets `display: flex` on `header` and `.stack`. The
 * result was the signed-in header showing over the sign-in screen and both phone forms
 * rendering at once, with the markup perfectly correct.
 */
[hidden] { display: none !important; }

body {
  margin: 0;
  color: var(--text);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  /*
   * The halo. The mark glows into its own background, and two very dilute radial washes
   * reproduce that without tinting anything readable. Fixed, so it behaves like a backdrop
   * rather than sliding away as content scrolls.
   */
  background-image:
    radial-gradient(58rem 34rem at 12% -8%, rgba(0, 211, 255, 0.10), transparent 60%),
    radial-gradient(52rem 32rem at 92% 4%, rgba(255, 62, 181, 0.09), transparent 62%);
  background-attachment: fixed;
  min-height: 100vh;
  /* Installed to a home screen, so it runs under the notch and the home indicator. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
}

main { max-width: 560px; margin: 0 auto; padding: 24px 20px 64px; }
main.wide { max-width: 1100px; }

h1 { font-size: 26px; line-height: 1.2; margin: 0 0 8px; letter-spacing: -0.01em; }
h2 { font-size: 15px; margin: 0 0 6px; }
.lede { color: var(--muted); margin: 0 0 28px; }
.muted { color: var(--muted); font-size: 14px; }

header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 14px 20px;
  max-width: 560px; margin: 0 auto;
  border-bottom: 1px solid var(--border);
}
.brand { font-weight: 700; letter-spacing: .04em; font-size: 14px; color: var(--muted); }
.brand-mark { display: block; width: 104px; height: auto; }
nav { display: flex; gap: 14px; flex-wrap: wrap; }

/* The mark. An explicit width attribute in the HTML plus height:auto means the browser
   reserves the right box before the image loads, so the sign-in screen does not jump. */
.wordmark {
  display: block; width: 360px; max-width: 78%; height: auto;
  margin: 9vh 0 22px;
  /* The mark carries its own glow; this lifts it off the page the way it sits on its own
     artwork, rather than looking pasted on. */
  filter: drop-shadow(0 6px 26px rgba(137, 37, 253, 0.34));
}

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

.stack { display: flex; flex-direction: column; gap: 12px; }
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--muted); }
label.check { flex-direction: row; align-items: center; gap: 8px; }

input, select {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--border-lit);
  border-radius: 10px;
  padding: 13px 14px;
  color: var(--text);
  font: inherit;
  /* 16px minimum, or iOS Safari zooms the page when the field takes focus. */
  font-size: 16px;
  transition: border-color .15s, box-shadow .15s;
}
input::placeholder { color: #5b6478; }
input:focus, select:focus {
  outline: none;
  border-color: var(--brand-cyan);
  box-shadow: 0 0 0 3px rgba(0, 211, 255, 0.16);
}

/*
 * The pairing code — the app's signature moment, and the one field anyone actually types
 * into. Given the room and the glow the primary button gets, because reading eight
 * characters off a television and typing them here is the whole product.
 */
.code-input {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 28px; letter-spacing: .3em; text-align: center; text-transform: uppercase;
  padding: 16px 14px;
  /* Offsets the trailing letter-space so the text sits optically centred. */
  text-indent: .3em;
}
.code-input:focus {
  border-color: transparent;
  box-shadow: 0 0 0 2px var(--brand-violet), 0 0 26px rgba(137, 37, 253, 0.30);
}

button {
  font: inherit; border: 0; border-radius: 12px; cursor: pointer;
  /* 44px minimum touch target. */
  padding: 13px 22px; min-height: 44px;
  transition: transform .12s, box-shadow .2s;
}
button:active { transform: translateY(1px); }

.primary {
  background: var(--grad);
  /* Near-black on a saturated gradient is the only text colour that stays legible across
     all of cyan, magenta and orange. White fails at the warm end. */
  color: #04060f;
  font-weight: 700;
  box-shadow: 0 6px 22px rgba(137, 37, 253, 0.32);
}
.primary:hover { box-shadow: 0 8px 28px rgba(137, 37, 253, 0.44); }

.secondary {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border-lit);
}
.secondary:hover { border-color: #3b496e; }

.linkish { background: none; color: var(--muted); padding: 6px 2px; min-height: 0; }
.linkish:hover { color: var(--text); }
.linkish.danger { color: var(--danger); }
.warn { background: var(--brand-orange); color: #04060f; font-weight: 600; }
button.danger { background: var(--danger); color: #fff; font-weight: 600; }

/* Keyboard focus, everywhere — distinct from hover and pressed, so tabbing through the
   page is legible without a mouse. */
:focus-visible { outline: 2px solid var(--brand-cyan); outline-offset: 2px; }

.divider {
  display: flex; align-items: center; gap: 12px;
  color: var(--muted); font-size: 12px; letter-spacing: .08em; text-transform: uppercase;
  margin: 24px 0;
}
.divider::before, .divider::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, transparent, var(--border-lit), transparent);
}

.list { list-style: none; padding: 0; margin: 0; }
.list li {
  display: flex; align-items: center; gap: 12px;
  padding: 15px 0; border-bottom: 1px solid var(--border);
}
.list li .device-name { flex: 1; }
.device-name { font-weight: 600; }

.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.chip {
  background: var(--surface-2); border: 1px solid var(--border-lit);
  color: var(--muted); border-radius: 999px; padding: 9px 16px; min-height: 0;
  font-size: 14px;
}
/* Selection is a real toggle, so it is announced as one rather than only coloured. */
.chip[aria-pressed="true"] {
  background: var(--grad);
  color: #04060f;
  border-color: transparent;
  font-weight: 700;
  box-shadow: 0 3px 14px rgba(137, 37, 253, 0.28);
}

.error { color: var(--danger); }
.ok { color: var(--ok); }

.spinner {
  width: 30px; height: 30px; margin: 26vh auto 0;
  border-radius: 50%;
  /* A conic sweep of the brand gradient rather than a single-colour arc: the same idea as
     the ring in the mark. The mask is what leaves a ring instead of a filled disc. */
  background: conic-gradient(from 0deg, transparent 0deg, var(--brand-cyan) 90deg,
              var(--brand-violet) 200deg, var(--brand-magenta) 300deg, transparent 360deg);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
  animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 3s; }
  button { transition: none; }
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* reCAPTCHA is invisible in the normal case; this keeps its badge from shifting layout. */
#recaptcha { margin-top: 8px; }

/* The uid is copied out of here into the Firebase console, so make selecting it easy
   rather than a careful drag across 28 characters. */
.selectable {
  user-select: all;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  color: var(--text);
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px 6px;
}

/* ── Toasts ──────────────────────────────────────────────────────────────── */

.toast-region {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  /* Bottom on a phone, where the thumb is, and clear of the home indicator. */
  bottom: calc(20px + env(safe-area-inset-bottom));
  z-index: 100;
  display: flex; flex-direction: column; gap: 8px; align-items: center;
  width: max-content; max-width: min(92vw, 460px);
  /* The region spans the screen but must never swallow taps meant for the page beneath;
     each toast re-enables pointer events for itself. */
  pointer-events: none;
}

.toast {
  pointer-events: auto;
  cursor: pointer;
  background: var(--surface-2);
  border: 1px solid var(--border-lit);
  color: var(--text);
  border-radius: 12px;
  padding: 13px 18px;
  font-size: 14px; line-height: 1.4;
  box-shadow: 0 10px 34px rgba(0, 0, 0, .55);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .2s ease, transform .2s ease;
}
.toast-in { opacity: 1; transform: translateY(0); }
.toast-leaving { opacity: 0; transform: translateY(6px); }

/* A hairline of colour rather than a coloured slab: the message is the content, and a
   fully tinted panel competes with the gradient the primary action already owns. */
.toast-ok { border-left: 3px solid var(--ok); }
.toast-error { border-left: 3px solid var(--danger); }
.toast-info { border-left: 3px solid var(--brand-cyan); }

@media (prefers-reduced-motion: reduce) {
  .toast { transition: opacity .2s ease; transform: none; }
  .toast-in, .toast-leaving { transform: none; }
}

/* ── Switch ──────────────────────────────────────────────────────────────── */

/*
 * A real switch, not a bare checkbox.
 *
 * The input stays in the DOM and keeps doing the work — it is focusable, it is in the tab
 * order, and `role="switch"` makes a screen reader say "on/off" rather than
 * "checked/unchecked", which is the right vocabulary for a setting that takes effect
 * immediately. Only its appearance is replaced.
 */
.switch { display: inline-flex; align-items: center; cursor: pointer; }
.switch input {
  /* Not display:none, which would remove it from the accessibility tree and the tab
     order. Kept in place, sized to the track, and made invisible. */
  position: absolute; opacity: 0; width: 44px; height: 26px; margin: 0; cursor: pointer;
}
.switch .track {
  position: relative; display: block;
  width: 44px; height: 26px; border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border-lit);
  transition: background .18s, border-color .18s;
}
.switch .thumb {
  position: absolute; top: 3px; left: 3px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--muted);
  transition: transform .18s, background .18s;
}
.switch input:checked + .track {
  background: var(--grad);
  border-color: transparent;
}
.switch input:checked + .track .thumb {
  transform: translateX(18px);
  background: #04060f;
}
.switch input:focus-visible + .track {
  outline: 2px solid var(--brand-cyan);
  outline-offset: 2px;
}
.switch input:disabled + .track { opacity: .5; cursor: not-allowed; }

@media (prefers-reduced-motion: reduce) {
  .switch .track, .switch .thumb { transition: none; }
}

/* ── Form actions ────────────────────────────────────────────────────────── */

/*
 * The button that commits a form needs air above it. Without this the Save button sat
 * flush against the last field, reading as another row of the form rather than as the
 * action that ends it.
 */
.form-actions {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

/* ── Sign in ─────────────────────────────────────────────────────────────── */

/*
 * A centred column. The mark, the sentence under it and both buttons share one axis;
 * previously the wordmark and the Google button sat left while the phone form stretched
 * full width, so nothing lined up with anything.
 *
 * Only the block is centred - the form labels stay left-aligned, because centred label
 * text above a left-aligned field is harder to scan, not easier.
 */
.signin { display: flex; flex-direction: column; align-items: center; text-align: center; }
.signin .wordmark { margin-left: auto; margin-right: auto; }
.signin .lede { max-width: 34ch; }
.signin form { width: 100%; }
.signin form label { text-align: left; }
/* Both buttons full width, so the two ways in carry equal weight rather than one looking
   like the real option and the other like an afterthought. */
.signin > button, .signin form > button { width: 100%; }
.signin .divider { width: 100%; }

/*
 * Google's button, to their spec: white surface, #1f1f1f label, their grey border, and
 * the official mark at 18px. Deliberately not the house gradient - see the comment in
 * index.html.
 */
.btn-google {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  background: #fff;
  color: #1f1f1f;
  border: 1px solid #747775;
  border-radius: 12px;
  font-size: 15px; font-weight: 600;
  min-height: 48px;
}
.btn-google:hover { background: #f2f2f2; }
.btn-google .g-mark { width: 18px; height: 18px; flex: none; }
