/* The game picker (the home screen). Layers, bottom to top: two still canvases (a full-resolution
   frame of the preview that was just on screen, or poster art for a game without a preview), the
   WebGL canvas with the live preview, then the picker: a soft white wash on the left (Sunny Sports is
   a light theme, so text is dark on a bright sky), the hero text, the join box and the card strip. The shell sets the layers' opacity and fades inline, so the hero always goes
   from one sharp picture to the next.
   2020 TVs run roughly Chrome 68: no `inset`, no flex `gap`, no `aspect-ratio`, and a plain
   declaration before every clamp(). */

#hero-bg { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: linear-gradient(180deg, #9fd4ff 0%, #dff1ff 55%, #f6fbff 100%); }
#hero-bg canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; }
body:not([data-phase="home"]) #hero-bg { display: none; }
/* Hidden until the first preview has drawn (the canvas may still hold the last game's frame). */
body[data-phase="home"] #gl { opacity: 0; }
body[data-phase="home"] #overlay { padding: 0; background: none; overflow: hidden; }

.picker {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  font-size: 18px;
  font-size: clamp(14px, 1.05vw, 22px);
}
/* Wash the left in white (behind the text, firmly, so any preview stays readable) and the bottom
   (behind the strip); the right stays the show. */
.picker::before {
  content: "";
  position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(246, 251, 255, 0.95) 0%, rgba(246, 251, 255, 0.88) 32%, rgba(246, 251, 255, 0.6) 46%, rgba(246, 251, 255, 0.18) 58%, rgba(246, 251, 255, 0) 70%),
    linear-gradient(0deg, rgba(246, 251, 255, 0.97) 0%, rgba(246, 251, 255, 0.72) 22%, rgba(246, 251, 255, 0) 48%);
}
.brand {
  position: absolute; top: 5vh; left: 5vw;
  display: flex; align-items: center;
  font: 800 1.5em/1 var(--font-display);
  color: var(--ink);
}
.brand b { margin-right: 0.25em; color: var(--amber); }
.brand i {
  width: 1.3em; height: 1.3em; margin-right: 0.45em; border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #ffe08a, #ffb020 70%);
  box-shadow: 0 0 0 0.25em rgba(255, 176, 32, 0.22);
}

/* ---------- hero ---------- */
.hero {
  position: absolute;
  left: 5vw; bottom: 42%; /* the shell then anchors it just above the card strip */
  width: 46vw; max-width: 920px;
}
.hero.enter { animation: hero-in 0.3s ease both; }
@keyframes hero-in {
  from { opacity: 0.35; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
.hero .eyebrow { color: var(--muted); }
.hero-title {
  margin: 0.2em 0 0.3em;
  font: 800 104px/0.92 var(--font-display);
  font: 800 clamp(54px, 6.8vw, 156px)/0.92 var(--font-display);
  letter-spacing: -0.01em;
  color: var(--ink);
  text-shadow: 0 2px 24px rgba(255, 255, 255, 0.9);
}
.hero-title em { display: block; font-style: normal; color: var(--ac, var(--signal)); }
/* The description box: four lines (fewer when the column has to fit). Longer text scrolls inside it
   rather than ending in an ellipsis: the shell slides the inner line with a transform, and a mask
   softens whichever edge text is passing (only the bottom at the start, both while scrolling, only
   the top at the end). */
.hero-brief {
  margin: 0 0 1em; max-width: 46ch; max-height: 6.2em; overflow: hidden;
  font-size: 1.05em; line-height: 1.55; color: var(--ink); text-shadow: 0 1px 10px rgba(255, 255, 255, 0.95);
}
.hero-brief > span { display: block; }
.hero-brief { transition: opacity 0.3s ease; }
.hero-brief.overflows {
  -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0, #000 1em, #000 calc(100% - 1em), rgba(0, 0, 0, 0) 100%);
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: 100% calc(100% + 1em);
  -webkit-mask-position: 0 -1em;
  transition: opacity 0.3s ease, -webkit-mask-position 0.5s ease, -webkit-mask-size 0.5s ease;
}
.hero-brief.overflows > span { will-change: transform; }
.hero-brief.overflows.scrolling { -webkit-mask-size: 100% 100%; -webkit-mask-position: 0 0; }
.hero-brief.overflows.at-end { -webkit-mask-size: 100% calc(100% + 1em); -webkit-mask-position: 0 0; }
/* The description and the "How to play" view share one slot (the shell sizes it to the taller one);
   Down on the remote crossfades to the second view, Up back. */
.hero-swap { position: relative; }
.hero-howview { position: absolute; top: 0; left: 0; right: 0; opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0s linear 0.3s; }
.hero-swap.show-how .hero-howview { opacity: 1; visibility: visible; transition: opacity 0.3s ease; }
.hero-swap.show-how .hero-brief { opacity: 0; }
.hero-kb { margin: 0 0 1em; font-size: 0.72em; }
.hero-kb:empty { display: none; }
.hero-toggle { cursor: pointer; }
.hero-how { display: grid; grid-template-columns: auto minmax(0, 1fr); grid-gap: 0.35em 0.9em; gap: 0.35em 0.9em; margin: 0 0 0.8em; font-size: 0.82em; }
.hero-how dt { font: 800 0.95em/1.3 var(--font-display); color: var(--ac, var(--signal)); }
.hero-how dd { margin: 0; line-height: 1.4; color: var(--ink); }
.hero .prompt { text-shadow: 0 1px 8px rgba(255, 255, 255, 0.9); }
.hero-note { margin: 0.5em 0 0; font-size: 0.72em; }
.hero-note:empty { display: none; }
/* The column must clear the brand at the top: the shell steps it down until it does. fit-1: a
   smaller title; fit-2: a three-line description box (it scrolls, so nothing is lost); fit-3: a
   compact "How to play" list; fit-4: an even smaller title; fit-5: a two-line box. */
.hero.fit-1 .hero-title, .hero.fit-2 .hero-title, .hero.fit-3 .hero-title { font-size: 90px; font-size: clamp(48px, 5.8vw, 132px); }
.hero.fit-4 .hero-title, .hero.fit-5 .hero-title { font-size: 76px; font-size: clamp(42px, 4.9vw, 110px); }
.hero.fit-2 .hero-brief, .hero.fit-3 .hero-brief, .hero.fit-4 .hero-brief { max-height: 4.65em; }
.hero.fit-5 .hero-brief { max-height: 3.1em; }
/* fit-6: a small window (a laptop, not a TV): the description gives way to the title and the prompt. */
.hero.fit-6 .hero-title { font-size: 64px; font-size: clamp(36px, 4.4vw, 100px); }
.hero.fit-6 .hero-swap, .hero.fit-6 .hero-kb { display: none; }
.hero.fit-3 .hero-how, .hero.fit-4 .hero-how, .hero.fit-5 .hero-how { font-size: 0.74em; grid-gap: 0.15em 0.9em; gap: 0.15em 0.9em; }
/* Reduced motion: nothing scrolls. The whole description shows, a little smaller and across the
   column's full width, and the fit levels above make room for it. */
@media (prefers-reduced-motion: reduce) {
  .hero-brief, .hero.fit-2 .hero-brief, .hero.fit-3 .hero-brief, .hero.fit-4 .hero-brief, .hero.fit-5 .hero-brief { max-height: none; max-width: none; font-size: 0.9em; line-height: 1.45; }
  .hero.fit-5 .hero-brief { font-size: 0.8em; }
  .hero.enter { animation: none; }
}
.hero .note { margin-top: 0.6em; }

/* ---------- join box ---------- */
.join {
  position: absolute; top: 5vh; right: 5vw; /* inside the TV safe area */
  display: flex; align-items: flex-start;
  max-width: 30vw;
  padding: 0.85em;
  background: rgba(255, 255, 255, 0.94);
  border-radius: 24px;
  box-shadow: 0 12px 40px rgba(29, 42, 74, 0.16);
}
#qr { flex: none; width: 112px; width: clamp(88px, 6.6vw, 150px); height: auto; image-rendering: pixelated; background: var(--qr-light); border-radius: 10px; }
.join-info { min-width: 0; margin-left: 0.85em; }
.join .eyebrow { font-size: 0.66em; }
.join .code { margin: 0.1em 0 0.15em; font: 800 2.1em/1 var(--font-display); letter-spacing: 0.14em; color: var(--signal); }
.join-url { margin: 0 0 0.5em; font-size: 0.72em; line-height: 1.35; color: var(--muted); word-break: break-all; }
.roster { display: flex; flex-wrap: wrap; list-style: none; margin: 0 0 -0.3em; padding: 0; }
.roster li { display: flex; align-items: center; margin: 0 0.55em 0.3em 0; font-size: 0.72em; white-space: nowrap; }
.roster li i { width: 0.8em; height: 0.8em; margin-right: 0.3em; border-radius: 50%; background: var(--c); }
.roster li b { margin-right: 0.3em; font: 800 1em/1 var(--font-display); color: var(--muted); }
.roster li span { font: 800 1em/1 var(--font-display); }
.roster li.away { opacity: 0.45; }
.join-count { margin: 0.45em 0 0; font-size: 0.66em; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }

/* ---------- card strip ---------- */
/* Cards sit 8vh up, clear of the hints line. The generous top and bottom padding (offset in `bottom`)
   keeps the focused card's lift, focus ring and shadow inside the clip; 5vw at the sides is the safe
   area the shell scrolls the cards within. */
.shelf {
  position: absolute; left: 0; right: 0; bottom: calc(8vh - 50px);
  overflow: hidden;
  padding: 60px 5vw 50px;
}
.shelf-row { display: flex; transition: transform 0.35s ease; }
.gcard {
  flex: none;
  position: relative;
  width: 220px;
  width: clamp(170px, 14.5vw, 300px);
  margin-right: 1.1vw;
  padding: 0;
  text-align: left;
  font: inherit;
  color: var(--ink);
  background: #ffffff;
  border: 3px solid #ffffff;
  border-bottom: 6px solid var(--ac, var(--signal));
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 8px 22px rgba(29, 42, 74, 0.14);
  cursor: pointer;
  transform-origin: 50% 100%;
  transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
/* 16:9 thumbnail without aspect-ratio: the padding box sets the height. */
.gcard .thumb { position: relative; display: block; padding-top: 56.25%; overflow: hidden; }
.gcard canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: block; }
.gcard .ct { display: block; padding: 0.55em 0.75em 0.15em; font: 800 0.98em/1.15 var(--font-display); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gcard .cp { display: block; padding: 0 0.85em 0.6em; font-size: 0.68em; color: var(--muted); }
.gcard .votes { position: absolute; top: 6px; right: 6px; display: flex; }
.gcard .votes i { width: 14px; height: 14px; margin-left: 4px; border-radius: 50%; background: var(--c); border: 2px solid #fff; }
.gcard:hover { border-color: #f4f9ff; }
/* Plain :focus (remote users need it; old TVs drop :focus-visible). */
.gcard:focus {
  outline: none;
  z-index: 2;
  transform: translateY(-8px) scale(1.09);
  border-color: var(--amber);
  box-shadow: 0 16px 40px rgba(29, 42, 74, 0.28), 0 0 0 4px var(--amber);
}
.gcard:focus .ct { color: var(--ac, var(--signal)); }
.gcard.off { opacity: 0.5; }
.gcard.off:focus { opacity: 0.85; }
.picker-meta { position: absolute; left: 5vw; right: 5vw; bottom: 5vh; margin: 0; font-size: 0.68em; line-height: 1.6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.picker-meta span + span::before { content: " · "; }
.picker .shelf .brief { margin: 0; }
