@font-face {
  font-family: "Titan One";
  src: url("../assets/fonts/titan-one.woff2") format("woff2");
  font-display: swap;
}
@font-face {
  font-family: "Luckiest Guy";
  src: url("../assets/fonts/luckiest-guy.woff2") format("woff2");
  font-display: block;
}
@font-face {
  font-family: "Fredoka";
  src: url("../assets/fonts/fredoka.woff2") format("woff2");
  font-weight: 300 700;
  font-display: swap;
}

:root {
  --ink: #2a1a10;
  --paper: #f4ead3;
  --paper-2: #eadcbc;
  --mustard: #e0a33a;
  --sun: #f2b33d;
  --orange: #c8612b;
  --teal: #2f7f7a;
  --wood: #3b2416;
  --glow: #9fd0ff;
  --phosphor: #8dffb0;
  --display: "Titan One", "Arial Rounded MT Bold", system-ui, sans-serif;
  --body: "Fredoka", ui-rounded, system-ui, sans-serif;
}

* { box-sizing: border-box; }
html { background: var(--wood); }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1.125rem;
  line-height: 1.5;
}
button { font: inherit; color: inherit; }
:focus-visible { outline: 3px solid var(--sun); outline-offset: 3px; }

/* ---------- The room ---------- */

.hero {
  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 520px;
  overflow: hidden;
  background: var(--wood);
  container-type: size;
}
/* The room's dim corners follow the window, however much of the room it shows. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: radial-gradient(75% 75% at 50% 40%, rgba(28, 14, 6, 0) 45%, rgba(28, 14, 6, .62));
  pointer-events: none;
}

/* The room is drawn 2400 x 1000 with the TV in the middle (x -400 to 2000 in
   the SVG). The stage fills the window's height and the sides crop away, so a
   phone sees the TV and the kids and a wide screen sees more of the room.
   Past 2.4:1 it fills the width and crops top and bottom instead. */
.stage {
  position: absolute;
  left: 50%;
  top: 45%;
  width: max(100cqw, 240cqh);
  aspect-ratio: 24 / 10;
  transform: translate(-50%, -45%);
}
.room { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* The logo, and its sun rays as a separate layer behind it: the rays blend with
   the room, so each one lights up whatever it falls on (wall, wood or TV). */
.wordmark,
.logo-rays {
  position: absolute;
  top: max(10px, env(safe-area-inset-top));
  left: max(12px, env(safe-area-inset-left));
  width: 130px;
}
.wordmark { z-index: 3; display: block; line-height: 0; border-radius: 12px; }
.logo { display: block; width: 100%; height: auto; overflow: visible; }
.logo-rays { display: block; height: auto; }
.logo-rays { z-index: 2; pointer-events: none; mix-blend-mode: screen; }

.to-guide {
  position: absolute;
  z-index: 3;
  right: max(16px, env(safe-area-inset-right));
  bottom: max(16px, env(safe-area-inset-bottom));
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 20px;
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--display);
  text-decoration: none;
  box-shadow: 0 3px 0 #b9824a;
}

/* SVG text */
.ch-led { font: 700 15px ui-monospace, Menlo, monospace; fill: #ff4b36; letter-spacing: 1px; }
.vcr-clock { font: 700 15px ui-monospace, Menlo, monospace; fill: #59e3a6; animation: blink 1s steps(1) infinite; }
.tv-label { font: 800 9px var(--body); letter-spacing: 1.5px; fill: #f6e6c0; }
.mute-led { fill: #3a1a14; }
.mute-led.on { fill: #ff4b36; }
.tv-brand { font: 700 12px var(--body); letter-spacing: 4px; fill: #b8b8c0; opacity: .8; }
.grain { opacity: .09; mix-blend-mode: overlay; pointer-events: none; }

/* ---------- Motion ---------- */

.room * { transform-box: view-box; }

.glow { animation: flicker 4.7s infinite; }
.shin-far { transform-origin: 398px 860px; animation: kick-far 2.9s ease-in-out infinite; }
.shin-near { transform-origin: 366px 880px; animation: kick-near 3.4s ease-in-out infinite; }
.head-lying { transform-origin: 692px 756px; animation: nod 9s ease-in-out infinite; }
.leg-up { transform-origin: 1226px 860px; animation: knee-sway 6s ease-in-out infinite; }
.foot { transform-origin: 1306px 878px; animation: tap 3.8s ease-in-out infinite; }
.head-sitting { transform-origin: 1180px 700px; animation: tilt 11s ease-in-out infinite; }
.knob-mark { transform-origin: 1144px 190px; transition: transform .25s cubic-bezier(.25, 1, .5, 1); }
.wisp { stroke-dasharray: 36 110; animation: rise 3.6s ease-out infinite; }
.wisp-2 { animation-duration: 4.4s; animation-delay: -1.6s; }
.wisp-3 { animation-duration: 5.1s; animation-delay: -3s; --o: .5; }
.dust circle { animation: mote var(--d, 12s) ease-in-out infinite; opacity: 0; }

@keyframes flicker {
  0%, 100% { opacity: .9; } 18% { opacity: .78; } 21% { opacity: .95; }
  47% { opacity: .84; } 63% { opacity: 1; } 80% { opacity: .82; }
}
@keyframes kick-far {
  0%, 100% { transform: rotate(-14deg); } 50% { transform: rotate(18deg); }
}
@keyframes kick-near {
  0%, 100% { transform: rotate(16deg); } 50% { transform: rotate(-20deg); }
}
@keyframes nod {
  0%, 70%, 100% { transform: rotate(0); } 78%, 90% { transform: rotate(4deg); }
}
@keyframes knee-sway {
  0%, 100% { transform: rotate(0); } 50% { transform: rotate(-5deg); }
}
@keyframes tap {
  0%, 60%, 100% { transform: rotate(0); }
  66% { transform: rotate(-14deg); } 72% { transform: rotate(0); }
  78% { transform: rotate(-14deg); } 84% { transform: rotate(0); }
}
@keyframes tilt {
  0%, 30%, 100% { transform: rotate(0); } 38%, 62% { transform: rotate(-7deg); } 70% { transform: rotate(0); }
}
@keyframes rise {
  0% { stroke-dashoffset: 30; opacity: 0; } 15% { opacity: var(--o, .7); } 60%, 100% { opacity: 0; } 100% { stroke-dashoffset: -110; }
}
@keyframes mote {
  0% { opacity: 0; transform: translate(0, 0); }
  30% { opacity: .85; }
  70% { opacity: .6; }
  100% { opacity: 0; transform: translate(var(--x), var(--y)); }
}
@keyframes blink { 50% { opacity: 0; } }

/* ---------- The screen ---------- */

/* Matches the glass in the SVG: x 500-1100, y 140-590 of the room's -400 to 2000. */
.screen {
  position: absolute;
  z-index: 2;
  left: 37.5%;
  top: 14%;
  width: 25%;
  height: 45%;
  border-radius: 6% / 8%;
  overflow: hidden;
  background: #050807;
  isolation: isolate;
}
.channel {
  position: absolute;
  inset: 0;
  visibility: hidden;
}
.channel.on { visibility: visible; }

.ident-sky {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  align-content: center;
  gap: .4em;
  background: linear-gradient(#58b6e6, #9fd8f2 60%, #f7d98a);
  text-align: center;
  container-type: inline-size;
}
.ident-sun { width: 18cqw; height: 18cqw; animation: spin 24s linear infinite; }
.ident-name {
  margin: 0;
  font-family: var(--display);
  font-size: 9cqw;
  line-height: .95;
  color: #fff7e2;
  text-shadow: 0 .5cqw 0 var(--orange), 0 1cqw 0 rgba(0, 0, 0, .2);
}
.ident-name span { color: var(--sun); font-size: .7em; }
.ident-tag { margin: 0; font-family: var(--display); font-size: 4cqw; color: var(--teal); }

.ch-bars { container-type: inline-size; }
.bars { position: absolute; inset: 0; display: flex; }
.bars i { flex: 1; }
.bars i:nth-child(1) { background: #c0c0c0; }
.bars i:nth-child(2) { background: #c0c000; }
.bars i:nth-child(3) { background: #00c0c0; }
.bars i:nth-child(4) { background: #00c000; }
.bars i:nth-child(5) { background: #c000c0; }
.bars i:nth-child(6) { background: #c00000; }
.bars i:nth-child(7) { background: #0000c0; }
.bars-card {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  padding: 2cqw 4cqw;
  background: #111;
  color: #f4f4f4;
  font-family: var(--display);
  font-size: 5cqw;
  line-height: 1.1;
  text-align: center;
  border: .6cqw solid #f4f4f4;
}

/* Coming up next: a ball bouncing across a sunny field under the title card.
   Transforms only (bounce, roll and travel are separate properties, so they
   stack), which the graphics chip runs on its own. */
.ch-next {
  container-type: inline-size;
  overflow: hidden;
  background: linear-gradient(#58b6e6, #9fd8f2 50%, #f7e3a0 60%);
}
.next-field {
  position: absolute;
  inset: 60% 0 0;
  background: repeating-linear-gradient(90deg, #6cb651 0 12.5%, #5ea846 12.5% 25%);
  box-shadow: inset 0 .8cqw 0 #4f973c;
}
.next-run {
  position: absolute;
  left: 0;
  bottom: 13%;
  width: 100%;
  animation: next-run 10s linear infinite;
}
.next-ball, .next-shadow { position: absolute; left: 0; bottom: 0; border-radius: 50%; }
.next-ball {
  width: 9cqw;
  height: 9cqw;
  background:
    radial-gradient(circle at 34% 30%, rgba(255, 255, 255, .55) 0 11%, transparent 12%),
    linear-gradient(transparent 42%, #ffd84a 42% 58%, transparent 58%),
    radial-gradient(circle at 40% 35%, #ff7a5c, #e0412c 60%, #a8281b);
  box-shadow: inset -.6cqw -.8cqw 0 rgba(0, 0, 0, .15);
  animation: next-bounce 1.1s infinite, next-roll 1.6s linear infinite;
}
.next-shadow {
  left: .5cqw;
  bottom: -1cqw;
  width: 8cqw;
  height: 2cqw;
  background: rgba(20, 60, 10, .35);
  animation: next-shadow 1.1s infinite;
}
@keyframes next-run { from { transform: translateX(-12%); } to { transform: translateX(100%); } }
@keyframes next-bounce {
  0%, 100% { translate: 0 0; animation-timing-function: cubic-bezier(.2, .6, .35, 1); }
  50% { translate: 0 -15cqw; animation-timing-function: cubic-bezier(.65, 0, .8, .4); }
}
@keyframes next-roll { to { rotate: 360deg; } }
@keyframes next-shadow {
  0%, 100% { scale: 1; opacity: 1; animation-timing-function: cubic-bezier(.2, .6, .35, 1); }
  50% { scale: .55; opacity: .45; animation-timing-function: cubic-bezier(.65, 0, .8, .4); }
}
.next-card {
  position: absolute;
  inset: 0 0 40%;
  display: grid;
  place-content: center;
  gap: 1.6cqw;
  text-align: center;
}
.next-bug {
  margin: 0 auto;
  padding: .5cqw 2.4cqw;
  border-radius: 99px;
  background: var(--teal);
  color: #fff7e2;
  font: 700 3.2cqw var(--body);
  letter-spacing: .14em;
  text-transform: uppercase;
}
.next-title {
  margin: 0;
  font-family: var(--display);
  font-size: 7.5cqw;
  line-height: .95;
  color: #fff7e2;
  text-shadow: 0 .5cqw 0 var(--orange), 0 1cqw 0 rgba(0, 0, 0, .2);
}

/* Shows rest while they're off the air: another channel, the screensaver, or the room scrolled away. */
.channel:not(.on) *, .saver-on .channel *, .off-screen .channel * { animation-play-state: paused; }

/* The screensaver: the logo in one colour on black, bouncing off the edges and
   changing colour each time it does, like a DVD player's. */
.saver { position: absolute; inset: 0; background: #000; cursor: pointer; }
.saver[hidden] { display: none; }
.saver-logo { position: absolute; left: 0; top: 0; width: 26%; height: auto; overflow: visible; will-change: transform; }
/* A hit right in a corner: the rays flash a rainbow and stretch out from the sun. */
.saver-rays { transform-origin: 180.9px 164.8px; transition: transform .3s cubic-bezier(.3, 1.6, .5, 1), opacity .3s; }
.saver-logo.corner .saver-rays { opacity: 1; transform: scale(1.3); }
.saver-logo.corner .saver-rays path { animation: rainbow .7s linear infinite; }
.saver-logo.corner .saver-rays path:nth-child(2) { animation-delay: -.1s; }
.saver-logo.corner .saver-rays path:nth-child(3) { animation-delay: -.2s; }
.saver-logo.corner .saver-rays path:nth-child(4) { animation-delay: -.3s; }
.saver-logo.corner .saver-rays path:nth-child(5) { animation-delay: -.4s; }
.saver-logo.corner .saver-rays path:nth-child(6) { animation-delay: -.5s; }
.saver-logo.corner .saver-rays path:nth-child(7) { animation-delay: -.6s; }
@keyframes rainbow {
  0%, 100% { fill: #ff4d4d; }
  16% { fill: #ff9a3d; }
  33% { fill: #ffe14a; }
  50% { fill: #5fd35f; }
  66% { fill: #4fa8ff; }
  83% { fill: #a77bff; }
}
/* The corner logo steps aside while it's bouncing about on the TV. */
.wordmark, .logo-rays { transition: opacity .6s, visibility .6s; }
.saver-on .wordmark, .saver-on .logo-rays { opacity: 0; visibility: hidden; }
/* The screensaver has the picture to itself: the controls go at once, even ones with focus. */
.saver-on .osd-ch, .saver-on .osd-bar, .saver-on .osd-channel { opacity: 0 !important; visibility: hidden !important; transition: none !important; }

.static {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
  opacity: 0;
  pointer-events: none;
}
.static.on { opacity: 1; }

.osd {
  position: absolute;
  z-index: 2;
  margin: 0;
  font: 700 clamp(14px, 2.4cqw, 30px) / 1 ui-monospace, Menlo, monospace;
  color: var(--phosphor);
  text-shadow: 0 0 6px rgba(141, 255, 176, .8), 2px 2px 0 #062;
  letter-spacing: .06em;
}
.screen { container-type: inline-size; }
.osd-channel {
  top: 7%;
  right: 7%;
  font-size: clamp(18px, 5cqw, 48px);
  opacity: 0;
  transition: opacity .2s;
}
.osd-channel.on { opacity: 1; }
/* A show's controls along the bottom of the picture: play, full screen and sound, in phosphor green. */
.osd-bar {
  position: absolute;
  z-index: 2;
  left: 4%;
  right: 4%;
  bottom: 3%;
  display: flex;
  gap: 6px;
  pointer-events: none;
}
.osd-bar[hidden] { display: none; }
.osd-gap { flex: 1; }
.osd-btn {
  position: static;
  min-height: 48px;
  min-width: 48px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 10px;
  background: rgba(0, 20, 8, .55);
  cursor: pointer;
  pointer-events: auto;
}
.osd-btn:hover { background: rgba(0, 40, 16, .75); }
.icon {
  width: 24px;
  height: 24px;
  background: currentColor;
  -webkit-mask: var(--m) center / contain no-repeat;
  mask: var(--m) center / contain no-repeat;
}

/* Channel arrows on the picture's sides, on every channel: a thin, tall tab
   against each edge. The button itself stays 48px wide for small fingers. */
.osd-ch {
  position: absolute;
  top: 50%;
  height: 40%;
  min-height: 72px;
  transform: translateY(-50%);
  isolation: isolate;
  background: none;
  justify-content: flex-start;
}
.osd-ch::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  left: 0;
  width: 30px;
  border-radius: 10px;
  background: rgba(0, 20, 8, .55);
}
.osd-ch:hover { background: none; }
.osd-ch:hover::before { background: rgba(0, 40, 16, .75); }
.osd-ch .icon { margin-left: 3px; }
.osd-ch-prev { left: 1.5%; }
.osd-ch-next { right: 1.5%; justify-content: flex-end; }
.osd-ch-next::before { left: auto; right: 0; }
.osd-ch-next .icon { margin: 0 3px 0 0; }
.icon-prev { --m: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 4l-8 8 8 8'/%3E%3C/svg%3E"); }
.icon-next { --m: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 4l8 8-8 8'/%3E%3C/svg%3E"); }
.icon-pause { --m: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='5' y='4' width='5' height='16' rx='1'/%3E%3Crect x='14' y='4' width='5' height='16' rx='1'/%3E%3C/svg%3E"); }
.icon-play { --m: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 4l14 8-14 8z'/%3E%3C/svg%3E"); }
.icon-full { --m: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9V3h6M15 3h6v6M21 15v6h-6M9 21H3v-6'/%3E%3C/svg%3E"); }
.icon-exit { --m: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 3v6H3M21 9h-6V3M15 21v-6h6M3 15h6v6'/%3E%3C/svg%3E"); }

/* The controls stay out of the picture until it's tapped (phones) or the mouse
   is over it (scene.js sets controls-on), or a key moves focus onto one. */
.hide-controls .osd-ch,
.hide-controls .osd-bar {
  opacity: 0;
  transition: opacity .25s, visibility .25s;
}
/* With a mouse they stay in the tab order; on phones a tap on a hidden button
   only brings the controls up. */
.tap-controls .osd-ch,
.tap-controls .osd-bar { visibility: hidden; }
.hide-controls.controls-on .osd-ch,
.hide-controls.controls-on .osd-bar,
.hide-controls:has(.osd :focus-visible, .osd:focus-visible) .osd-ch,
.hide-controls:has(.osd :focus-visible, .osd:focus-visible) .osd-bar { opacity: 1; visibility: visible; }

/* Full screen: just the picture, edge to edge. */
.screen:fullscreen { border-radius: 0; }
.screen:fullscreen .glass { display: none; }
.screen:fullscreen .osd-btn { min-width: 56px; min-height: 56px; }
.screen:fullscreen .osd-ch::before { width: 36px; }
.screen:fullscreen .osd-ch .icon { margin-left: 6px; }
.screen:fullscreen .osd-ch-next .icon { margin: 0 6px 0 0; }
.sound-icon {
  width: 24px;
  height: 24px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 9h4l5-4v14l-5-4H3z'/%3E%3Cpath d='M16 9l5 6m0-6l-5 6' stroke='black' stroke-width='2.4' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 9h4l5-4v14l-5-4H3z'/%3E%3Cpath d='M16 9l5 6m0-6l-5 6' stroke='black' stroke-width='2.4' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
}
.osd-sound[aria-pressed="true"] .sound-icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 9h4l5-4v14l-5-4H3z'/%3E%3Cpath d='M16 8.5c1.6 2 1.6 5 0 7M19 6c3 3.4 3 8.6 0 12' stroke='black' stroke-width='2.2' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 9h4l5-4v14l-5-4H3z'/%3E%3Cpath d='M16 8.5c1.6 2 1.6 5 0 7M19 6c3 3.4 3 8.6 0 12' stroke='black' stroke-width='2.2' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
}

@container (max-width: 420px) {
  .osd-bar { left: 2%; right: 2%; bottom: 1%; gap: 2px; }
  .osd-ch-prev { left: 1%; }
  .osd-ch-next { right: 1%; }
  .osd-ch::before { background: rgba(0, 20, 8, .7); }
  .osd-btn:not(.osd-ch) { background: rgba(0, 20, 8, .7); }
  .sound-icon, .icon { width: 22px; height: 22px; }
}

/* Scanlines, the bulge of the tube, and a glare on the glass */
.glass {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  border-radius: inherit;
  background:
    radial-gradient(ellipse 40% 30% at 22% 16%, rgba(255, 255, 255, .16), transparent 70%),
    radial-gradient(ellipse at 50% 50%, transparent 58%, rgba(0, 0, 0, .55) 100%),
    repeating-linear-gradient(0deg, rgba(0, 0, 0, .22) 0 1px, transparent 1px 3px);
  box-shadow: inset 0 0 24px rgba(0, 0, 0, .7);
  animation: roll 7s linear infinite;
}
/* The curve of the tube: a thin rim of light along the top and left of the glass */
.glass::after {
  content: "";
  position: absolute;
  inset: 2.5% 3%;
  border-radius: 18% / 22%;
  border-top: 2px solid rgba(255, 255, 255, .14);
  border-left: 2px solid rgba(255, 255, 255, .08);
  -webkit-mask-image: linear-gradient(135deg, #000 20%, transparent 60%);
  mask-image: linear-gradient(135deg, #000 20%, transparent 60%);
}
@keyframes roll {
  0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.04); }
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Invisible buttons over the dial and the remote */
.hotspot {
  position: absolute;
  z-index: 2;
  min-width: 48px;
  min-height: 48px;
  transform: translate(-50%, -50%);
  border: 0;
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
}
/* The dial (centred at 19%) and the mute button (23.8%) are closer than two 48px
   buttons, so they meet halfway (21.4%) instead of overlapping: the dial's button
   grows up from there and the mute's down, and a tap on either lands on its own. */
.hotspot-knob { left: 64.333%; top: 21.4%; width: 2.4%; aspect-ratio: 1; transform: translate(-50%, -100%); }
.hotspot-mute { left: 64.333%; top: 21.4%; width: 2.4%; height: 4.2%; border-radius: 8px; transform: translate(-50%, 0); }
/* The game pad: a little secret, it starts the TV's screensaver */
.hotspot-pad { left: 55.083%; top: 78.5%; width: 3.833%; height: 3%; border-radius: 12px; }
.gamepad > g { transition: transform .12s; }
.stage:has(#pad:active) .gamepad > g { transform: translate(80px, -141px); }
.hotspot-remote { left: 23.733%; top: 90%; width: 7.333%; height: 6%; border-radius: 12px; }
.hotspot-remote:hover::after, .hotspot-remote:focus-visible::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: inherit;
  box-shadow: 0 0 0 3px rgba(242, 179, 61, .8);
}
/* The dial and mute button get a ring drawn in the room, sized to the
   control itself; the button over it stays a full 48px to tap. */
.ring { fill: none; stroke: rgba(242, 179, 61, .8); stroke-width: 3.5; opacity: 0; }
.stage:has(#knob:hover, #knob:focus-visible) .ring-knob,
.stage:has(#mute:hover, #mute:focus-visible) .ring-mute { opacity: 1; }

.hint {
  position: absolute;
  z-index: 2;
  left: 66.133%;
  top: 17.4%;
  margin: 0;
  padding: 6px 14px 6px 12px;
  border-radius: 4px;
  background: #fff6c8;
  color: var(--ink);
  font: 600 clamp(12px, 1.1vw, 16px) var(--body);
  transform: rotate(-3deg);
  box-shadow: 0 2px 4px rgba(0, 0, 0, .3);
  pointer-events: none;
}
.hint::before {
  content: "";
  position: absolute;
  left: -7px;
  top: 8px;
  border: 7px solid transparent;
  border-left: 0;
  border-right-color: #fff6c8;
}
/* The sound note sits beside the mute button and goes once the sound is on. */
.hint-sound { top: 23%; transform: rotate(2deg); }
.hint-sound.gone { visibility: hidden; }
/* Cropped too close to fit beside the TV (scene.js checks): no note at all. */
.hint.no-room { visibility: hidden; }

/* Phones and tall windows: crop in on the TV and the kids */
@media (max-aspect-ratio: 1/1) {
  /* The room shows about 900 x 1000 of the drawing: the TV and the kids, with
     the logo over the top-left corner as on wider screens. */
  .hero { height: 110vw; min-height: 0; }
  .stage { top: 0; width: max(100cqw, 2.4 * 100cqh); transform: translateX(-50%); }
  .to-guide { display: none; }
}

/* Save-Data: no drifting dust, lava or film grain */
.save-data .dust, .save-data .grain { display: none; }
.save-data .lava-blob { animation: none; }

/* The lava lamp on the bottom shelf */
.lava-blob { animation: lava var(--d) ease-in-out infinite alternate; }
@keyframes lava { to { transform: translateY(var(--y)); } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .dust circle { opacity: .6; }
  /* The ball waits in the middle of the field. */
  .next-run { transform: translateX(45%); }
}

/* ---------- The listings ---------- */

.guide {
  background:
    radial-gradient(circle at 20% 10%, rgba(255, 255, 255, .5), transparent 40%),
    var(--paper);
  padding: 56px 16px 64px;
}
/* A page that is only the guide (privacy, contact, 404) fills the window, so no wood shows under short text. */
body > main.guide:first-child { min-height: 100vh; min-height: 100dvh; }
.guide-inner { max-width: 880px; margin: 0 auto; }
.guide-kicker {
  margin: 0 0 4px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: .85rem;
  color: var(--orange);
}
.guide h1 {
  margin: 0 0 24px;
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.4rem, 7vw, 4rem);
  line-height: 1;
  border-bottom: 6px double var(--ink);
  padding-bottom: 12px;
}
.listings { list-style: none; margin: 0; padding: 0; }
.listing {
  display: grid;
  grid-template-columns: 92px 1fr;
  gap: 20px;
  padding: 20px 0;
  border-bottom: 2px solid var(--ink);
}
.slot {
  margin: 0;
  font-family: var(--display);
  font-size: 1.6rem;
  line-height: 1;
}
.slot span {
  display: block;
  margin-bottom: 6px;
  font-family: var(--body);
  font-weight: 600;
  font-size: .8rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--teal);
}
.listing h2 {
  margin: 0 0 6px;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.6rem;
  line-height: 1.15;
}
.listing p { margin: 0 0 10px; max-width: 60ch; }
.listing-hit { background: linear-gradient(90deg, rgba(242, 179, 61, .22), transparent 70%); padding-left: 12px; margin-left: -12px; }
.badge {
  display: inline-block;
  vertical-align: middle;
  padding: 2px 10px;
  border-radius: 4px;
  background: var(--orange);
  color: #fff;
  font-size: .9rem;
  transform: rotate(-3deg);
}
.status { font-weight: 600; color: var(--teal); }
.watch {
  min-height: 48px;
  padding: 0 22px;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--display);
  font-size: 1rem;
  cursor: pointer;
  box-shadow: 0 3px 0 var(--orange);
}
.watch:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--orange); }
a.watch { display: inline-flex; align-items: center; text-decoration: none; }

.promise { margin-top: 48px; }
.promise h2 { font-family: var(--display); font-weight: 400; font-size: 1.8rem; margin: 0 0 16px; }
.promise-intro { margin: 0 0 20px; }
.promise ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* Six cards: three across, two across, or one, so the rows always come out even. */
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
@media (max-width: 860px) { .promise ul { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .promise ul { grid-template-columns: 1fr; } }
.promise li {
  padding: 18px 20px;
  border: 2px solid var(--ink);
  border-radius: 10px;
  background: #fbf4e2;
  box-shadow: 4px 4px 0 var(--ink);
}
.promise strong { display: block; font-family: var(--display); font-weight: 400; font-size: 1.15rem; margin-bottom: 4px; }

.footer { background: var(--wood); color: #f1e2c2; padding: 32px 16px calc(32px + env(safe-area-inset-bottom)); }
.footer-inner { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; }
.footer-name { margin: 0; display: flex; align-items: center; gap: 8px; font-family: var(--display); }
.footer-name svg { width: 28px; height: 28px; }
.footer nav { display: flex; gap: 8px; }
.footer a { color: #f1e2c2; min-height: 48px; display: inline-flex; align-items: center; padding: 0 8px; }
.footer-small { margin: 0 0 0 auto; font-size: .9rem; opacity: .7; }

@media (max-width: 560px) {
  .listing { grid-template-columns: 1fr; gap: 8px; }
  .footer-small { margin-left: 0; }
}

/* ---------- Plain pages ---------- */

.guide-kicker a { color: inherit; }
/* Privacy, contact and 404 lead with the logo, which goes back to the living room. */
.guide-logo { display: block; width: min(240px, 60vw); margin: -24px 0 16px -8px; line-height: 0; border-radius: 12px; }
.guide-logo svg { display: block; width: 100%; height: auto; overflow: visible; }

.prose h2 { font-family: var(--display); font-weight: 400; font-size: 1.4rem; margin: 32px 0 8px; }
.prose ul { padding-left: 1.2em; }
.prose li { margin-bottom: 6px; }
.prose a, .promise a { color: var(--teal); }

/* ---------- Contact form ---------- */

.contact { max-width: 36rem; margin: 28px 0 0; display: grid; gap: 6px; }
.contact label { font-family: var(--display); font-size: 1.1rem; margin-top: 14px; }
.contact label span { font-family: var(--body); font-size: .95rem; opacity: .7; }
.contact input, .contact textarea {
  width: 100%;
  min-height: 48px;
  padding: 10px 14px;
  border: 2px solid var(--ink);
  border-radius: 10px;
  background: #fbf4e2;
  color: var(--ink);
  font: inherit;
  box-shadow: 3px 3px 0 var(--ink);
}
.contact textarea { resize: vertical; min-height: 9rem; }
.contact-note { margin: 2px 0 0; font-size: .95rem; opacity: .75; }
.contact-trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.contact-check { margin-top: 18px; min-height: 65px; }
.contact .watch { justify-self: start; margin-top: 12px; }
.contact .watch:disabled { opacity: .6; cursor: progress; }
.contact-status { margin: 8px 0 0; min-height: 1.5em; font-weight: 600; }
.contact-status.is-ok { color: var(--teal); }
.contact-status.is-error { color: var(--orange); }
.contact[hidden], .contact-done[hidden] { display: none; }
.contact-done { max-width: 36rem; margin: 28px 0 0; animation: contact-done-in .4s ease-out; }
.contact-done-title { font-family: var(--display); font-size: 1.4rem; color: var(--teal); margin: 0 0 4px; outline: none; }
@keyframes contact-done-in { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .contact-done { animation: none; } }
.contact-small { margin: 32px 0 0; font-size: .95rem; opacity: .8; }
.contact-small a { color: var(--teal); }

/* The made-up shows: a short looping video each, filling the tube. Black until its poster arrives. */
.ch-show { background: #000; }
.ch-show video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* The note over the made-up shows: they're stand-ins until the real ones are out. Top right,
   clear of the channel arrows (the sides' middle) and of the logo on a phone; it steps aside
   while the channel number shows there after a change. */
.show-bug {
  position: absolute;
  z-index: 2;
  right: 7%;
  top: 7%;
  width: max-content;
  max-width: 58%;
  margin: 0;
  padding: .35em .8em;
  border-radius: .4em;
  background: rgba(0, 0, 0, .62);
  color: #fff;
  font: 600 clamp(10px, 2.6cqw, 22px) / 1.25 Fredoka, system-ui, sans-serif;
  text-align: right;
  pointer-events: none;
  visibility: hidden;
  transition: opacity .2s;
}
.screen:has(.osd-channel.on) .show-bug { opacity: 0; }
.show-bug b { color: #ffd84a; font-weight: 700; }
.ch-show.on ~ .show-bug { visibility: visible; }
.saver-on .show-bug { visibility: hidden; }
