:root {
  /* FidFad's colour. It is the one thing in the app that is not the surf, so
     it is the one colour that is not the surf's blue. */
  --fidfad: #ff4d9d;
  /* Custom Stream. Purple because every other colour in the app is already
     spoken for: blue is the quality stream, green Growing Fast, pink FidFad,
     orange a television that still needs picking. */
  --customize: #8b5cf6;
  /* Nothing picked yet, and something needs doing. */
  --pick: #ff9f2e;
  --bg: #0b0b0d;
  --fg: #f2f2f4;
  --dim: #9a9aa2;
  --line: #232329;
  --accent: #2e78ff;
  /* The headings on the remote screen. Blue for what is playing and for
     Featured, green for Growing Fast. */
  --growing: #34c759;
  --featured: #2e78ff;
  --hot: #ff3b30;
  --panel: #141418;
  --safe: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* A rule like .chipRow { display: flex } beats the browser's own hidden rule,
   so hiding something by setting hidden quietly did nothing. This makes hidden
   mean hidden everywhere. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--fg);
  font: 15px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  overscroll-behavior: none;
}

#app {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

#stage {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  position: relative;
}
#player, #player iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

#attrib {
  padding: 6px 14px 0;
  color: var(--dim);
  font-size: 11px;
  letter-spacing: 0.02em;
}

#info {
  flex: 1;
  padding: 10px 14px 16px;
  touch-action: pan-y;
  user-select: none;
}

.chip {
  display: inline-block;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 10px;
}
.chip.tv { border-color: var(--accent); color: var(--accent); }

.title {
  display: block;
  color: var(--fg);
  text-decoration: none;
  font-size: 19px;
  font-weight: 650;
  line-height: 1.25;
}

.meta {
  margin-top: 8px;
  color: var(--dim);
  font-size: 13px;
}

.hint {
  margin-top: 18px;
  color: #56565e;
  font-size: 12px;
}

#dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 80;
  background: var(--bg);
  border-top: 1px solid var(--line);
  padding-bottom: var(--safe);
}

/* The control pad. Two rows of two, full width. Skip Ad and Tune are on top
   because they are looked at. Next and Hide are on the bottom row, twice the
   height, because they are pressed by feel. */
/* The playback bar. Three buttons, the ones touched constantly while
   watching, so they are the big reachable ones. Back was taken off. */
#strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
}

/* The steering bar. Used when shaping the surf rather than driving it, so it
   is quieter, shorter and visually a different thing. Darker, with the
   buttons separated as pills rather than filling the width edge to edge, so
   there is no mistaking it for the playback bar above. */
#shapeBar {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  padding: 6px 8px;
  background: #0a0a0e;
  border-top: 1px solid var(--line);
}
.shapeb {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: none;
  border: 1px solid #2c2c38;
  border-radius: 999px;
  color: var(--dim);
  padding: 7px 4px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  min-width: 0;
}
.shapeb em { font-style: normal; white-space: nowrap; }
.shapeb .shapeIcon {
  display: inline-flex;
  align-items: center;
  font-size: 15px;
  line-height: 1;
}
.shapeb:active { color: var(--accent); border-color: var(--accent); }
.shapeb.on { color: var(--accent); border-color: var(--accent); }

/* If the screen is short, the steering bar gives way first. The playback bar
   is never the thing that shrinks. */
@media (max-height: 700px) {
  #shapeBar { padding: 4px 8px; gap: 5px; }
  .shapeb { padding: 5px 3px; font-size: 11px; }
  .shapeb .shapeIcon { font-size: 13px; }
}
@media (max-height: 620px) {
  .shapeb em { display: none; }
  .shapeb { padding: 6px 3px; }
}

#nav {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  border-top: 1px solid var(--line);
}

.navb {
  background: var(--bg);
  border: 0;
  color: var(--dim);
  font: inherit;
  font-size: 12px;
  padding: 9px 4px 10px;
}
.navb:active { background: #1e1e24; color: var(--fg); }
.navb.on { color: var(--accent); }

/* No television picked yet.
   Orange and slowly pulsing, because until one is chosen the app cannot do
   the thing it is for, and nothing else on the screen says so. */
.navb.picktv { color: var(--pick); font-weight: 700; animation: pickPulse 2.8s ease-in-out infinite; }

/* Picked. Blue, still, and carrying the name. The pulse has done its job and
   an animation that never stops is an animation nobody can watch a video
   next to. */
.navb.chosen { color: var(--accent); font-weight: 600; }

@keyframes pickPulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

/* Somebody who has turned animation off on their phone has said they do not
   want this. They still get the orange, which is what carries the meaning;
   the pulse was only ever the emphasis. */
@media (prefers-reduced-motion: reduce) {
  .navb.picktv { animation: none; }
}

/* Keep content clear of the fixed pad. The height is measured at startup
   and on every rotation, so a taller pad never covers anything. */
#app { padding-bottom: calc(var(--dock, 250px) + 16px + var(--safe)); }
.toast { bottom: calc(var(--dock, 250px) + 30px + var(--safe)); }

.btn {
  background: var(--panel);
  border: 0;
  color: var(--fg);
  /* Every button identical. One row, five equal shares of the width. */
  padding: 18px 1px 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font: inherit;
  min-width: 0;
}
.btn span { font-size: 24px; line-height: 1; }

/* Custom Stream.
   An oval, the same shape as the Quality stream chip above the video, because
   it is about the same thing: what the stream is. Purple so it is nobody
   else's colour — blue is the quality stream, green is Growing Fast, pink is
   FidFad, orange means a television still needs picking.

   A button sitting in its share of the bar rather than filling it, so it reads
   as a thing to press rather than as a third panel. The cell keeps its full
   height so the row stays level and the two blind buttons either side are
   still the size a thumb expects. */
.btn.customize {
  /* The same panel colour as Next and Skip Ad either side.
     It was "none", which let the strip's own divider colour show through the
     whole cell, so the middle third of the bar sat a shade lighter than its
     neighbours and looked like a different surface. Only the oval is meant to
     stand out; the cell behind it is part of the same dark bar. */
  background: var(--panel);
  padding: 0;
  justify-content: center;
}
.btn.customize em {
  font-style: normal;
  display: block;
  padding: 9px 14px;
  background: var(--customize);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.01em;
  border-radius: 999px;
  white-space: nowrap;
}
.btn.customize:active em { background: #6b3fc4; }
.btn em {
  font-style: normal;
  font-size: 11px;
  color: var(--dim);
  white-space: nowrap;
}
/* The drawn icons match the emoji beside them. */
.btn .wheel svg { width: 24px; height: 24px; }

.btn.small, .btn.big { padding: 0; grid-column: auto; }
.btn:active { background: #1e1e24; }
.btn.on span, .btn.on em { color: var(--accent); }

.sheet {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.72);
  display: flex;
  align-items: flex-end;
  z-index: 50;
}
.sheet[hidden] { display: none; }

.sheetInner {
  width: 100%;
  max-height: 88vh;
  overflow-y: auto;
  background: var(--panel);
  border-top: 1px solid var(--line);
  border-radius: 18px 18px 0 0;
  padding-top: 18px;
  padding-left: 16px;
  padding-right: 16px;
  /* clears the fixed control strip, whose real height is measured on load */
  padding-bottom: calc(var(--dock, 100px) + 20px + var(--safe));
}

/* Action buttons ride at the bottom of the sheet and stay reachable */
.sheetActions {
  position: sticky;
  bottom: 0;
  background: var(--panel);
  padding-top: 10px;
  padding-bottom: 4px;
  box-shadow: 0 -10px 14px -6px var(--panel);
}

.sheetInner h2 { margin: 0 0 14px; font-size: 17px; }

.lbl {
  display: block;
  margin: 18px 0 7px;
  font-size: 13px;
  color: var(--dim);
}

.inp {
  width: 100%;
  background: #0b0b0d;
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 10px;
  padding: 11px 12px;
  font: inherit;
}
input[type=range] { padding: 0; accent-color: var(--accent); }

.row { display: flex; gap: 8px; margin-top: 12px; }

.wide {
  width: 100%;
  margin-top: 10px;
  background: #222229;
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 11px;
  padding: 13px;
  font: inherit;
  font-weight: 600;
}
.wide:active { background: #2c2c35; }
/* A link dressed as one of these buttons, like staging's Sign in now. */
a.wide { display: block; box-sizing: border-box; text-align: center; text-decoration: none; }
.wide.danger { color: #ff6b60; }
.wide.gray { background: #55555f; color: #f2f2f5; }

.note { margin-top: 8px; font-size: 12px; color: var(--dim); min-height: 15px; }

.laneRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 13px 2px;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
}
.laneRow button {
  background: none;
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  padding: 5px 13px;
  font: inherit;
  font-size: 12px;
}
.laneRow button.on { color: var(--accent); border-color: var(--accent); }

.pickRow {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  color: var(--fg);
  padding: 15px 2px;
  font: inherit;
  font-size: 16px;
}
.pickRow.cur { color: var(--accent); font-weight: 650; }
.pickRow small { color: var(--dim); font-size: 12px; }

.toast {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(86px + var(--safe));
  background: #26262e;
  border: 1px solid var(--line);
  color: var(--fg);
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 13px;
  z-index: 90;
  max-width: 84vw;
  text-align: center;
}
.toast[hidden] { display: none; }

/* Left over from the old TV only design, where picking a television turned the
   phone into a remote and the video was hidden completely.

   That is not how it works any more. The phone always plays. Choosing a
   television adds it on top, and the phone carries on showing the picture with
   its own sound muted. This rule was hiding the whole stage the moment a
   television was chosen, which is why the phone showed no video while
   insisting it was playing on both.

   Nothing styles the tvonly class now. The class itself is left in place in
   case anything else reads it. */

/* Remote mode. While a television is playing the video the phone does not
   play it, so the video area gives way to a small card saying what is on and
   the rest of the screen is left open.

   The player is moved off screen rather than removed, so it is ready the
   moment the video comes back to the phone. */
body.casting #stage {
  position: absolute;
  left: -9999px;
  top: 0;
  width: 320px;
  height: 180px;
  pointer-events: none;
}
body.casting #attrib,
body.casting #now { display: none; }

.castNow { padding: 16px 14px 10px; touch-action: pan-y; user-select: none; }
.tvStopBtn { display: block; margin: 6px auto 8px; background: none; border: 1px solid var(--line); border-radius: 999px;
  color: var(--fg); font: inherit; font-size: 13px; padding: 5px 14px; }
.castWhere {
  text-align: center;
  color: var(--accent);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  margin-bottom: 10px;
}
.castCard { display: flex; gap: 14px; align-items: center; }
.castThumb {
  position: relative;
  flex: 0 0 50%;
  aspect-ratio: 16 / 9;
  border-radius: 10px;
  overflow: hidden;
  background: #000;
}
.castThumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.castThumb .tapMark { width: 46px; height: 46px; margin: -23px 0 0 -23px; font-size: 19px; }
.castWords { flex: 1; min-width: 0; }
.castTitle {
  font-size: 18px;
  font-weight: 650;
  line-height: 1.25;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.castChannel { color: var(--dim); font-size: 14px; margin-top: 6px; }
/* Both headings sit under what they name: Featured under its card, Growing
   Fast under the scroll. */
.promoWhere { color: var(--featured); margin-top: 8px; text-align: center; font-size: 15px; }
.discoverWhere { margin: 10px 14px 12px; color: var(--growing); }
/* On the phone face the scroll is a compact strip under the playing video,
   so its heading is smaller and tighter to match. */
body:not(.casting) .discoverWhere { margin: 6px 14px 10px; font-size: 12px; }
.promoCard { margin-top: 22px; color: var(--fg); text-decoration: none; cursor: pointer; transition: opacity 350ms ease; }
.promoCard.fading { opacity: 0; }

/* The Featured label and the featured title flash together, a steady pulse
   between white and blue, so the eye goes to them. Held still for anyone
   whose phone asks for less motion. */
.promoCard .castTitle,
.promoWhere { animation: promoFlash 1.2s ease-in-out infinite; }
@keyframes promoFlash {
  0%, 100% { color: var(--fg); }
  50% { color: var(--featured); }
}
@media (prefers-reduced-motion: reduce) {
  .promoCard .castTitle,
  .promoWhere { animation: none; }
}

/* Remote screen */
.rTop {
  display: flex;
  gap: 10px;
  margin-bottom: 10px;
}

.rk {
  flex: 1;
  background: #22222a;
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 14px;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  padding: 18px 6px;
  min-height: 58px;
}
.rk:active { background: var(--accent); border-color: var(--accent); color: #fff; }

.rPad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 10px;
  margin: 6px 0 14px;
}
.rUp { grid-area: 1 / 2; }
.rLeft { grid-area: 2 / 1; }
.rOk { grid-area: 2 / 2; border-radius: 999px; font-size: 17px; }
.rRight { grid-area: 2 / 3; }
.rDown { grid-area: 3 / 2; }
.rPad .rk { min-height: 66px; }

#nav.noTv { grid-template-columns: repeat(2, 1fr); }

.prompt {
  margin: 14px 14px 0;
  padding: 12px 14px;
  background: #1b2338;
  border: 1px solid #2e78ff;
  border-radius: 12px;
  color: #cddcff;
  font-size: 13px;
  line-height: 1.45;
}
.prompt[hidden] { display: none; }

.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
textarea.inp { resize: vertical; line-height: 1.4; }
.laneRow .rowBtns { display: flex; gap: 8px; }
.laneRow em { font-style: normal; color: var(--dim); font-size: 11px; display: block; }

.seg { display: flex; gap: 8px; }
.seg button {
  flex: 1;
  background: #22222a;
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 11px;
  padding: 12px 4px;
  font: inherit;
  font-size: 13px;
}
.seg button.on { color: var(--accent); border-color: var(--accent); font-weight: 600; }

#topbar {
  display: flex;
  justify-content: flex-end;
  padding: 8px 14px 0;
}
.tvpick {
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  padding: 7px 14px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
}
.tvpick.set { color: var(--accent); border-color: var(--accent); }



.linkBtn {
  background: none;
  border: 0;
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  padding: 12px 0 4px;
  text-decoration: underline;
}



.resName { font-size: 22px; font-weight: 650; margin-top: 4px; }
.resDesc { color: var(--fg); font-size: 14px; margin-top: 6px; line-height: 1.45; }
.resStats { color: var(--dim); font-size: 12px; margin-top: 10px; }
.resItem {
  border-top: 1px solid var(--line);
  padding: 11px 0;
  font-size: 14px;
  line-height: 1.35;
}
.resItem small { display: block; color: var(--dim); font-size: 12px; margin-top: 3px; }

/* Round five: the lane name is a label now, not a control */


/* Browse rows indent by depth so the tree reads as a tree */
.treeRow { padding-left: 0; }
.treeRow.d1 { padding-left: 18px; }
.treeRow.d2 { padding-left: 36px; }
.treeRow.d3 { padding-left: 54px; }
.treeRow.d4 { padding-left: 72px; }
.treeRow small { color: var(--dim); font-size: 12px; }

/* Topic picker. Rows indent by depth and carry a checkbox on the right. */
.topRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 2px;
  border-bottom: 1px solid var(--line);
}
.topRow .nm { font-size: 15px; }
.nmBtn {
  flex: 1;
  text-align: left;
  background: none;
  border: 0;
  color: var(--fg);
  font: inherit;
  padding: 2px 0;
}
.nmBtn small { display: block; color: var(--dim); font-size: 12px; margin-top: 2px; }
.nmBtn.into .nm::after { content: "  \203A"; color: var(--dim); }
.topRow.group .nm { font-weight: 650; }
.topRow.league .nm { font-weight: 600; color: var(--fg); }
.topRow.team .nm { font-size: 14px; color: var(--dim); }

.ctrls { display: flex; gap: 8px; flex: 0 0 auto; }

.box {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: #0b0b0d;
  color: var(--dim);
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
}
.box.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.box.x { font-weight: 400; font-size: 13px; }
.box.dim { opacity: 0.35; }

/* Two plainly labelled buttons. No cycling, no hidden meanings. */
.pill {
  border-radius: 999px;
  border: 1px solid var(--line);
  background: #0b0b0d;
  color: var(--dim);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  padding: 9px 12px;
  min-width: 68px;
}
.pill.follow.on {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.pill.block.on {
  background: #3a1d1d;
  border-color: #ff6b60;
  color: #ff6b60;
}

.secLbl {
  margin: 18px 0 8px;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dim);
}



.topRow.off .nm { color: #5c5c64; text-decoration: line-through; }

.foldBtn {
  background: none;
  border: 0;
  color: var(--dim);
  font: inherit;
  font-size: 12px;
  padding: 4px 8px;
}

.chipRow { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.chip.refresh { font-weight: 500; color: var(--dim); }
.chip.refresh:active { color: var(--accent); border-color: var(--accent); }
.chip.refresh.busy { color: var(--accent); border-color: var(--accent); }

.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-bottom: 6px;
}
.crumb {
  background: none;
  border: 0;
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  padding: 6px 2px;
}
.crumb.cur { color: var(--fg); font-weight: 650; }
.crumbSep { color: var(--dim); font-size: 13px; }

.topRow.group .nm, .topRow.league .nm { font-weight: 600; }
.topRow { min-height: 54px; }

/* Add Me card */
.addThumb {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 12px;
  background: #000;
  margin-bottom: 12px;
}
.addName { font-size: 22px; font-weight: 650; line-height: 1.2; }
.addSub { color: var(--dim); font-size: 13px; margin-top: 6px; line-height: 1.45; }
.addItem {
  border-top: 1px solid var(--line);
  padding: 11px 0;
  font-size: 14px;
  line-height: 1.35;
}
.addItem small { display: block; color: var(--dim); font-size: 12px; margin-top: 3px; }

/* A lane that has not gathered enough channels to be worth opening yet */
.topRow.building .nm { color: #6a6a74; }
.topRow.building .buildNote { color: var(--accent); }
.topRow.building .pill.follow { opacity: 0.75; }

/* ---------- the surf screen ---------- */

.chipRow {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px 4px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.chipRow::-webkit-scrollbar { display: none; }

.chipList { display: flex; gap: 8px; }

.chipRow .chip {
  flex: 0 0 auto;
  margin-bottom: 0;
  white-space: nowrap;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  padding: 9px 15px;
  font-size: 14px;
  font-weight: 600;
}
.chipRow .chip.on {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.chipRow .chip.shuffle {
  border-style: dashed;
  border-color: #4a4a56;
  color: var(--fg);
}
.chipRow .chip.shuffle.on {
  border-style: solid;
  background: #2a2a34;
  border-color: var(--accent);
  color: var(--accent);
}
.chipRow .chip.add {
  font-size: 18px;
  font-weight: 400;
  padding: 7px 16px;
  color: var(--dim);
}
.chipRow .chip.removing {
  background: #3a1d1d;
  border-color: #ff6b60;
  color: #ff6b60;
}

.freshRow {
  display: flex;
  gap: 6px;
  padding: 8px 12px 10px;
  overflow-x: auto;
  scrollbar-width: none;
}
.freshRow::-webkit-scrollbar { display: none; }
.freshRow .fresh {
  flex: 0 0 auto;
  background: none;
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  padding: 6px 13px;
  font: inherit;
  font-size: 12px;
  white-space: nowrap;
}
.freshRow .fresh.on { color: var(--accent); border-color: var(--accent); font-weight: 600; }
.freshRow .fresh.custom::after { content: " \2022"; color: var(--accent); }

#now { padding: 12px 14px 16px; touch-action: pan-y; user-select: none; }

#now .tags {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.tag {
  font-size: 12px;
  border-radius: 999px;
  padding: 5px 11px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--dim);
  font-weight: 600;
  white-space: nowrap;
}
.tag.source { color: var(--accent); border-color: var(--accent); }

/* FidFad, in the row above the title. A button, not a label, so it is the one
   thing in that row that looks pressable: filled rather than outlined, which
   is what separates it from the two chips beside it. */
.tag.fidfad {
  background: var(--fidfad);
  border-color: var(--fidfad);
  color: #fff;
  font: inherit;
  font-size: 11px;
  font-weight: 700;
  padding: 4px 12px;
  cursor: pointer;
}
.tag.fidfad:active { background: #e03a86; border-color: #e03a86; }
.tag.tv { font: inherit; font-size: 12px; font-weight: 600; }
.tag.tv.set { color: var(--fg); }


.subjRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 2px;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
}
.subjRow small { display: block; color: var(--dim); font-size: 12px; margin-top: 2px; }
.subjRow button {
  flex: 0 0 auto;
  background: #22222a;
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 999px;
  padding: 8px 14px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
}
.subjRow button.have { color: var(--dim); border-color: var(--line); background: none; }

#strip .btn em { font-size: 10px; }
.undoToast { display: flex; align-items: center; gap: 12px; }
.undoToast button {
  background: none; border: 0; color: var(--accent);
  font: inherit; font-size: 13px; font-weight: 700; padding: 0;
}

/* Developer review mode. Never visible to a customer. */
.devPanel {
  margin-top: 14px;
  padding: 12px;
  background: #12121a;
  border: 1px solid #2a2a3a;
  border-radius: 12px;
}
.devStreams { display: flex; gap: 6px; margin-bottom: 10px; }
.devTab {
  flex: 1;
  background: none;
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  padding: 8px 6px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
}
.devTab.on { color: var(--accent); border-color: var(--accent); }
.devTab.alt { flex: 0 0 auto; padding: 8px 14px; }

.devVerdict { font-size: 13px; font-weight: 700; margin-bottom: 6px; }
.devVerdict.accepted { color: #4ade80; }
.devVerdict.rejected { color: #ff6b60; }

.devWhy {
  font-size: 12px;
  line-height: 1.5;
  color: var(--dim);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap;
}
.devActions { margin-top: 10px; }
.devRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 2px;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}
.devRow small { display: block; color: var(--dim); font-size: 11px; }
.devRow button {
  background: none; border: 1px solid var(--line); color: var(--dim);
  border-radius: 999px; padding: 6px 12px; font: inherit; font-size: 12px;
}

/* The steering menu. Broad choices first, specific ones last. */
.tuneRow {
  display: block;
  width: 100%;
  text-align: left;
  background: #1a1a22;
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 12px;
  padding: 14px 15px;
  margin-top: 9px;
  font: inherit;
  font-size: 15px;
  line-height: 1.3;
}
.tuneRow:active { border-color: var(--accent); }
.tuneRow small {
  display: block;
  margin-top: 4px;
  color: var(--dim);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.tuneRow.off { border-color: #5a2a2a; }
.tuneRow.off small { color: #ff6b60; }
.tuneLadder { margin-top: 4px; }

/* The Dev button. Plainly labelled, easy to find, easy to remove. */
.tag.dev {
  text-decoration: none;
  color: #8a8a96;
  border-style: dashed;
  border-color: #3a3a46;
  margin-left: auto;
}
.tag.dev:active { color: var(--accent); border-color: var(--accent); }

/* Evaluation mode. A separate page, so nothing here can leak into the
   customer screen by accident. */
.evalBar {
  display: flex;
  gap: 6px;
  padding: 10px 12px 4px;
}
.evalBar .devTab { flex: 1; }
.evalBar .devTab.return {
  flex: 0 0 auto;
  text-decoration: none;
  padding: 8px 14px;
  color: var(--fg);
  border-color: #3a3a46;
}
.evalpage #devPanel { display: block; }
.evalpage #strip { grid-template-columns: repeat(2, 1fr); }
.evalpage .btn { grid-column: auto; }

/* The first choice on every Tune menu. It does what the Keep button did. */
.tuneRow.keep {
  border-color: var(--accent);
}
.tuneRow.keep span { color: var(--accent); font-weight: 700; }

/* Steering. Not a search box, and it must not read like one. */
.steerBox {
  min-height: 84px;
  resize: none;
  line-height: 1.45;
}
.wide.go { background: var(--accent); color: #fff; border-color: var(--accent); }

.reqRow {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 10px 12px;
  margin-bottom: 8px;
  background: #12121a;
}
.reqHead {
  font-size: 13px;
  font-weight: 700;
  color: var(--fg);
  margin-bottom: 6px;
}

/* The ship's wheel takes the colour of the label around it. */
.wheel { display: inline-flex; color: var(--dim); }
.btn:active .wheel { color: var(--fg); }

/* The account, the subscription and the help page. */
.tag.help {
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  width: 26px;
  padding: 5px 0;
  text-align: center;
  color: var(--dim);
}
.tag.help:active { color: var(--accent); border-color: var(--accent); }

/* Obvious enough to find, quiet enough not to nag. */
.tag.sub {
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  border-color: var(--accent);
  background: rgba(46,120,255,0.10);
}
.tag.sub:active { background: var(--accent); color: #fff; }
.tag.sub.trial {
  color: var(--dim);
  border-color: var(--line);
  background: none;
  font-weight: 600;
}

.planBox {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  margin: 12px 0 16px;
  background: #12121a;
}
.planLine { font-size: 13px; margin-bottom: 4px; }
.planLine.top { margin-top: 14px; }

.wide.prov {
  font-weight: 600;
  margin-bottom: 8px;
}
.wide.prov.google { border-color: #4a4a58; }
.wide.prov.apple { border-color: #4a4a58; }

.orLine {
  text-align: center;
  color: var(--dim);
  font-size: 12px;
  margin: 16px 0 10px;
}

#helpSheet .note a { color: var(--accent); }
#helpSheet .secLbl { margin-top: 16px; }

/* The two prices. */
.wide.price {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 14px 16px;
  margin-bottom: 8px;
}
.wide.price b { font-size: 16px; }
.wide.price small { color: var(--dim); font-size: 12px; font-weight: 400; }
.wide.price:active { border-color: var(--accent); }

/* The dev phase switcher. Sits above the title on the customer screen so a
   layout can be approved without leaving the page. Dev only, and it goes
   with the rest of the dev tools under the one flag. */
.devPhases {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 10px;
  padding: 6px 8px;
  border: 1px dashed #3a3a46;
  border-radius: 10px;
}
.devPhasesLbl {
  font-size: 11px;
  color: #6e6e7a;
  margin-right: 2px;
}
.devPhases .phase {
  flex: 1;
  background: none;
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  padding: 6px 4px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
}
.devPhases .phase.on {
  color: var(--accent);
  border-color: var(--accent);
  background: rgba(46,120,255,0.10);
}

/* Up next. A light look down the queue, not a wall of thumbnails. The words
   lead and the picture is small enough to be a reminder rather than a hook. */
.tag.peek {
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--dim);
}
.tag.peek:active { color: var(--accent); border-color: var(--accent); }

.peekRow {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  padding: 12px 2px;
  font: inherit;
  color: var(--fg);
}
.peekRow:last-child { border-bottom: 0; }
.peekRow:active { background: #16161d; }

.peekBody { flex: 1; min-width: 0; }

.peekSignal {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.02em;
  margin-bottom: 3px;
}
.peekSignal.soft { color: var(--dim); font-weight: 600; }

.peekTitle {
  font-size: 14px;
  line-height: 1.35;
  margin-bottom: 3px;
}
.peekMeta { font-size: 12px; color: var(--dim); }

.peekPos {
  font-size: 11px;
  color: #5e5e6a;
  min-width: 16px;
  padding-top: 2px;
}

/* Deliberately small. This is a reminder of the video, not a shop window. */
.peekThumb {
  width: 52px;
  height: 30px;
  border-radius: 4px;
  object-fit: cover;
  background: #1a1a22;
  flex: 0 0 auto;
  margin-top: 2px;
}

/* The locked screen. It replaces the app entirely once the trial is over,
   because there is no half working version to fall back to. */
.locked {
  position: fixed;
  inset: 0;
  background: var(--bg, #0b0b0d);
  z-index: 80;
  overflow-y: auto;
  display: flex;
  align-items: center;
}
.locked[hidden] { display: none; }
.lockedInner {
  width: 100%;
  max-width: 30em;
  margin: 0 auto;
  padding: 32px 22px calc(32px + var(--safe));
}
.lockedInner h1 { font-size: 24px; margin: 0 0 10px; }
.lockedNote { color: var(--dim); font-size: 15px; line-height: 1.55; margin: 0 0 18px; }
.lockedBox {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  margin-bottom: 18px;
  background: #12121a;
}

/* The way out of the locked screen, for the owner only. */
.lockedDev { margin-top: 26px; }

/* The bottom row takes a fourth entry now that Up next has moved down. */
#nav.four { grid-template-columns: repeat(4, 1fr); }
#nav.four .navb { font-size: 12px; }

/* The top bar is gone, so the title sits straight under the video. */
#now .tags { display: none; }

/* The developer way in lives at the foot of Settings now, so there is
   nothing floating over the main screen. */
.devLink {
  display: block;
  text-align: center;
  text-decoration: none;
  color: var(--fg);
  border-style: dashed;
  border-color: #3a3a46;
  margin-bottom: 8px;
}
.devLink:active { color: var(--accent); border-color: var(--accent); }

/* On a narrow phone the longest label is Skip Ad, so the text shrinks a
   little rather than the row wrapping or a word being cut off. */
@media (max-width: 360px) {
  .btn em { font-size: 10px; }
  .btn span { font-size: 22px; }
  .btn .wheel svg { width: 22px; height: 22px; }
}

/* Nothing sits over the video any more. The badge that used to show which
   television was playing and offer a way back to the phone was clutter over
   the picture, and everything it did already lives in the Where to play
   sheet behind the TV button. */

/* ---------- the reel ---------- */
/*
   A slow horizontal drift of what is coming next. It exists to be glanced at,
   so it moves calmly rather than ticking along, and every card carries its
   title and channel. The whole point of this app is not judging a video by
   its thumbnail, so a thumbnail is never shown on its own.
*/
.reel {
  position: relative;
  overflow: hidden;
  background: #0d0d12;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
}
.reel[hidden] { display: none; }

.reelTrack {
  display: flex;
  gap: 8px;
  padding: 8px;
  will-change: transform;
}

.reelCard {
  position: relative;
  flex: 0 0 auto;
  border: 0;
  padding: 0;
  border-radius: 10px;
  overflow: hidden;
  background: #16161d;
  font: inherit;
  color: var(--fg);
  text-align: left;
}
.reelCard img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #1a1a22;
}
.reelCard:active { outline: 2px solid var(--accent); }

/* The words sit over the picture, always, never optional. */
.reelWords {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 16px 8px 7px;
  background: linear-gradient(to top, rgba(6,6,10,0.94) 42%, rgba(6,6,10,0));
}
.reelTitle {
  font-size: 12px;
  line-height: 1.25;
  font-weight: 600;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.reelChan {
  font-size: 10px;
  color: #9a9aa6;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Big, when a television is carrying the video and the phone is mostly a
   remote. The reel becomes the thing worth looking at. */
.reel.big .reelCard { width: 260px; height: 146px; }
.reel.big .reelTitle { font-size: 15px; }
.reel.big .reelChan { font-size: 12px; }

/* Small, when the phone is playing the video. A strip under it, not a rival
   to it. */
.reel.small .reelCard { width: 132px; height: 74px; }
.reel.small .reelTitle { font-size: 10px; -webkit-line-clamp: 2; }
.reel.small .reelChan { font-size: 9px; }
.reel.small .reelWords { padding: 12px 6px 5px; }

/* Held still while a finger is on it. */
.reel.held { box-shadow: inset 0 0 0 1px var(--growing); }

/* ---------- the comparison bench, dev only ---------- */
.benchpage { padding: 0 0 40px; }
.benchTop { padding: 20px 16px 8px; max-width: 1100px; margin: 0 auto; }
.benchTop h1 { font-size: 20px; margin: 0 0 8px; }
.benchIntro { color: var(--dim); font-size: 13px; line-height: 1.55; margin: 0 0 14px; max-width: 46em; }
.benchBar { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.benchBar .wide { width: auto; padding: 9px 14px; font-size: 13px; }
.benchBar a.linkish { text-decoration: none; text-align: center; color: var(--fg); }

.benchVerdict {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  background: #12121a;
  font-size: 13px;
  line-height: 1.6;
  white-space: pre-wrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--dim);
}

.benchActs { padding: 12px 16px; max-width: 1100px; margin: 0 auto; }
.benchActs .row { display: flex; gap: 8px; align-items: center; }
.benchActs .row .inp { flex: 1; margin: 0; }
.benchActs .row .wide { width: auto; padding: 10px 16px; }

.benchCols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  padding: 8px 16px;
  max-width: 1100px;
  margin: 0 auto;
}
@media (max-width: 760px) { .benchCols { grid-template-columns: 1fr; } }

.benchCol h2 { font-size: 16px; margin: 0 0 8px; }
.benchCol h2 small { color: var(--dim); font-weight: 400; font-size: 12px; margin-left: 6px; }

.benchFile {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 10px 12px;
  background: #12121a;
  font-size: 12px;
  line-height: 1.6;
  margin-bottom: 10px;
  white-space: pre-wrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.benchFile.clean { color: #6e6e7a; }

.benchFeed { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; }
.benchRow {
  display: flex;
  gap: 8px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  align-items: flex-start;
}
.benchRow:last-child { border-bottom: 0; }
.benchRow.only { background: rgba(46,120,255,0.09); }
.benchNum { color: #5e5e6a; min-width: 18px; }
.benchBody { flex: 1; min-width: 0; }
.benchChan {
  background: none; border: 0; padding: 0;
  color: var(--accent); font: inherit; font-size: 12px; font-weight: 600;
  text-align: left; cursor: pointer;
}
.benchTitle { color: var(--dim); margin-top: 2px; }
.benchWhy { color: #4ade80; font-size: 11px; margin-top: 2px; }

/* The mood choices. */
.moodRow {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  background: none;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 11px 13px;
  margin-bottom: 8px;
  font: inherit;
  color: var(--fg);
}
.moodRow .em { font-size: 19px; line-height: 1; }
.moodRow b { font-size: 14px; font-weight: 600; display: block; }
.moodRow small { color: var(--dim); font-size: 12px; }
.moodRow.on { border-color: var(--accent); background: rgba(46,120,255,0.10); }
.moodRow.on b { color: var(--accent); }

/* The tap target over the video.
   Invisible and drawn over nothing. It exists because the video is a frame
   from YouTube, which the app cannot reach into, so a tap on it went to
   YouTube's own controls and never to us. */
.tapLayer {
  position: absolute;
  inset: 0;
  z-index: 5;
  background: transparent;
  -webkit-tap-highlight-color: transparent;
}

/* A brief mark so it is obvious the tap registered, since the picture itself
   may be on a television in another room. */
.tapMark {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 66px;
  height: 66px;
  margin: -33px 0 0 -33px;
  border-radius: 50%;
  background: rgba(8,8,12,0.66);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  color: #fff;
  animation: tapPop 700ms ease-out forwards;
  pointer-events: none;
}
.tapMark[hidden] { display: none; }
@keyframes tapPop {
  0% { opacity: 0; transform: scale(0.7); }
  18% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.1); }
}

/* Lining the phone's sound up with a television. */
.syncBar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 10px;
}
.syncBar button {
  background: none;
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 999px;
  padding: 8px 14px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
}
.syncBar button:active { border-color: var(--accent); color: var(--accent); }
.syncBar span {
  flex: 1;
  text-align: center;
  font-size: 13px;
  color: var(--dim);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.rVol button {
  flex: 1;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 14px;
  padding: 17px 8px;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
}
.rVol button:active { border-color: var(--accent); color: var(--accent); }
.rVol button.on { border-color: var(--accent); color: var(--accent); }

/* The volume slider. One control, dragged rather than tapped, because the
   television has no volume of its own to step through. This sets the level
   directly, which is the only thing that actually changes what comes out. */
.volSlide {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 6px 0 8px;
}
.volSlide button {
  flex: 0 0 auto;
  background: none;
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 999px;
  width: 44px;
  height: 44px;
  font-size: 18px;
  line-height: 1;
  padding: 0;
}
.volSlide button.muted { border-color: var(--accent); color: var(--accent); }
.volSlide span {
  flex: 0 0 auto;
  min-width: 34px;
  text-align: right;
  font-size: 13px;
  color: var(--dim);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.volRange {
  flex: 1;
  min-width: 0;
  height: 34px;
  -webkit-appearance: none;
  appearance: none;
  background: none;
}
.volRange::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: #2c2c38;
}
.volRange::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: #2c2c38;
}
/* A thumb big enough to find without looking. */
.volRange::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 26px;
  height: 26px;
  margin-top: -10px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid #0b0b0d;
}
.volRange::-moz-range-thumb {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid #0b0b0d;
}

/* The small print under the prices. No price is ever shown struck through. */
.priceDisclose { margin-top: 8px; font-size: 12px; }

/* The tags under the video: which stream it came from, that it passed the
   quality check, and how old it is. They sit above the title on the phone and
   under the card on the TV screen. */
.vidTags { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.castTags { margin: 10px 0 0; }
.vidTags .tag { font-size: 11px; padding: 4px 10px; }
.tag.stream { color: var(--accent); border-color: var(--accent); }
.tag.stream.growing { color: var(--growing); border-color: var(--growing); }
.tag.stream.custom { color: var(--customize); border-color: var(--customize); }
.tag.stream.mood { color: #f59e0b; border-color: #f59e0b; }
.tag.stream.steer { color: #f97316; border-color: #f97316; }
.tag.stream.podcast { color: #14b8a6; border-color: #14b8a6; }
.tag.stream.live { color: #ef4444; border-color: #ef4444; }
.tag.stream.news { color: #facc15; border-color: #facc15; }
.tag.stream.sports { color: #fb923c; border-color: #fb923c; }
.tag.stream.gameplay { color: #a78bfa; border-color: #a78bfa; }
.tag.stream.supplements { color: #4ade80; border-color: #4ade80; }
/* Select all and Clear all, in every stream's picker. */
.pickActs { display: flex; gap: 8px; margin: 8px 0 6px; flex-wrap: wrap; }
.pickAct { background: none; border: 1px solid var(--line); border-radius: 999px; color: var(--fg); font: inherit; font-size: 13px; padding: 5px 12px; }
.pickAct:disabled { opacity: .4; }
/* The Sports picker's tabs: for looking through the sports, not choices. */
.sportTabs { display: flex; gap: 4px; flex-wrap: wrap; border-bottom: 1px solid var(--line); margin: 10px 0 8px; }
.sportTab { background: none; border: 0; border-bottom: 2px solid transparent; color: var(--dim); font: inherit; font-size: 14px;
  padding: 8px 10px; margin-bottom: -1px; display: inline-flex; align-items: center; gap: 6px; }
.sportTab.on { color: var(--fg); border-bottom-color: var(--accent); }
.sportTabCount { background: var(--accent); color: #fff; border-radius: 999px; font-size: 11px; padding: 1px 6px; }
.sportsPlaying b { color: var(--fg); }
.sportHead { margin: 14px 0 2px; color: var(--dim); font-size: 13px; }
.sportHead b { color: var(--fg); font-size: 15px; }
#sportsFind { margin-top: 8px; }
/* Every state shown. It was a box 220px tall that scrolled inside the sheet,
   with nothing to say so, and read as a list that stopped at Louisiana. */
.statePick { max-height: none; overflow: visible; }
.tag.stream.featured { animation: tagFlash 1.4s ease-in-out infinite; }
@keyframes tagFlash {
  0%, 100% { background: transparent; }
  50% { background: color-mix(in srgb, var(--accent) 35%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .tag.stream.featured { animation: none; } }
/* Auto in the bar, where Next is in Manual. Watching one in full it reads
   Next, still marked Auto. */
#strip .btn.autoBar em { font-variant-numeric: tabular-nums; }

/* Monthly or annual, on one sliding switch. */
.billing { margin-top: 8px; text-align: center; }
.billToggle { position: relative; display: grid; grid-template-columns: 1fr 1fr; background: #222229;
  border-radius: 999px; padding: 4px; max-width: 320px; margin: 0 auto; }
.billKnob { position: absolute; top: 4px; bottom: 4px; left: 4px; width: calc(50% - 4px); border-radius: 999px;
  background: var(--accent); transition: transform 0.2s ease; }
.billing.annual .billKnob { transform: translateX(100%); }
.billOpt { position: relative; z-index: 1; border: 0; background: transparent; color: var(--dim); font-weight: 600;
  padding: 9px 6px; border-radius: 999px; font-size: 14px; }
.billOpt.on { color: #fff; }
.billSave { display: inline-block; font-size: 10px; font-weight: 700; margin-left: 3px; padding: 1px 6px;
  border-radius: 999px; background: #15803d; color: #fff; vertical-align: 1px; }
.billPrice { margin-top: 14px; }
.billAmt { font-size: 34px; font-weight: 800; font-variant-numeric: tabular-nums; }
.billPer { font-size: 15px; color: var(--dim); }
.billing .billSub { margin-top: 2px; }
.billGo { margin-top: 12px; }
@media (prefers-reduced-motion: reduce) { .billKnob { transition: none; } }

/* The member's Custom Streams. */
.customRow { margin-top: 6px; }
.customActs { display: flex; gap: 14px; margin: 2px 0 4px 34px; }
.customActs .linkBtn { margin: 0; }
.linkBtn.danger { color: #ff6b60; }
#customNew { margin-top: 8px; }

/* The chat in the Custom Stream. */
.chatBox { margin-top: 10px; }
.chatLog { max-height: 42vh; min-height: 140px; overflow-y: auto; display: flex; flex-direction: column; gap: 8px;
  padding: 10px; background: #15151a; border: 1px solid var(--line); border-radius: 12px; }
.chatMsg { max-width: 85%; padding: 8px 11px; border-radius: 14px; font-size: 14px; line-height: 1.4; white-space: pre-wrap; word-wrap: break-word; }
.chatMsg.bot { align-self: flex-start; background: #24242c; border-bottom-left-radius: 4px; }
.chatMsg.me { align-self: flex-end; background: var(--customize); color: #fff; border-bottom-right-radius: 4px; }
.chatMsg.typing { color: var(--dim); font-style: italic; }
.chatRow { display: flex; gap: 8px; margin-top: 8px; align-items: flex-end; }
.chatInput { flex: 1; margin: 0; resize: none; min-height: 40px; max-height: 120px; font: inherit; }
.chatSend { flex: 0 0 auto; border: 0; border-radius: 10px; padding: 0 16px; height: 40px; font-weight: 700;
  background: var(--customize); color: #fff; }
.chatSend:disabled { opacity: .5; }

/* The Member page. */
.memberDetails { margin-top: 6px; font-size: 13px; line-height: 1.55; }
.memberDetails b { font-weight: 600; }
.memberEarnings { font-size: 26px; font-weight: 700; margin-top: 4px; font-variant-numeric: tabular-nums; }
.memberShare .inp { margin-top: 8px; }
#strip .btn.autoBar.held span,
#strip .btn.autoBar.held em { color: var(--text, #f2f2f5); }
.playHead { margin-top: 4px; }
.tag.quality { color: #3ecf8e; border-color: #1f6b4a; }
.tag.age { color: var(--dim); }

/* Where the account stands, and the two things that can be done about it.
   The words are a statement; the buttons are the controls. It used to be one
   button that looked like a label, which meant the only route to subscribing
   was a line of text nobody knew to press. */
.planRow {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}
.trialLine {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  /* A statement, not a control. No pointer, no press. */
  cursor: default;
}
.trialLine.last { color: #f5b44a; }
/* A subscriber is not being counted down at, so it is not the blue that means
   "act on this". Quieter: who they are, rather than what to do. */
.trialLine.subscriber { color: var(--dim, #9a9aa2); }

.planBtn {
  flex: 0 0 auto;
  border: 0;
  border-radius: 999px;
  padding: 7px 15px;
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}
/* Green for the one that starts money, yellow for the one that stops it.
   They are opposite actions and should never be mistaken for each other at a
   glance. A deeper green than Growing Fast's, which already means something
   else, and dark enough for the white words to read. */
.planBtn.sub { background: #15803d; }
.planBtn.sub:active { background: #116a32; }
.planBtn.account { background: #f5b44a; color: #2a2000; }
.planBtn.account:active { background: #dc9f35; }

/* Two colours, two sources. Blue is the Quality stream: the Next button and
   the Quality stream label under the video. Green is Growing Fast: the scroll,
   its heading and the Growing Fast label. */
#strip .btn.nextQuality { gap: 3px; }
#strip .btn.nextQuality span,
#strip .btn.nextQuality em { color: var(--accent); }
#strip .btn.nextQuality em { font-weight: 700; }
#strip .btn.nextQuality small {
  color: var(--accent);
  font-size: 9px;
  font-weight: 600;
  white-space: nowrap;
  line-height: 1;
}
.reel { border-top-color: rgba(52, 199, 89, 0.5); border-bottom-color: rgba(52, 199, 89, 0.5); }

/* The playback bar. Rewind, pause, forward and stop, above the big buttons,
   quieter than them because they are used less than Next. */
#playbar {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 8px;
}
.pb {
  background: #22222a;
  border: 1px solid var(--line);
  border-radius: 14px;
  color: var(--fg);
  padding: 14px 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  font: inherit;
  min-width: 0;
}
.pb span { font-size: 20px; line-height: 1; }
.pb em { font-style: normal; font-size: 10px; color: var(--dim); white-space: nowrap; }
.pb:active { background: var(--accent); border-color: var(--accent); }
.pb.on span, .pb.on em { color: var(--accent); }

/* On the phone the video is YouTube's own player, so a tap belongs to it and
   brings up its controls. The invisible layer that used to swallow every tap
   is only over the card that stands in for the video while a television is
   playing. */
body:not(.casting) .tapLayer { display: none; }

/* Test mode, and the Getting Hot flash over the scroll. */
.testBanner {
  background: #6b4b00;
  color: #ffe9b0;
  font-size: 13px;
  font-weight: 600;
  padding: 8px 14px;
  text-align: center;
}
@keyframes hotFlash {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0.25; }
}

/* The upright Shorts player. One video a screen, snapped, the way a phone
   feed behaves, over the top of everything else. */
.shortsView {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: #000;
}
.shortsView[hidden] { display: none !important; }
.shortsTrack {
  height: 100%;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.shortsTrack::-webkit-scrollbar { display: none; }
.shortSlide {
  height: 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
}
/* Upright, nine by sixteen, as tall as the screen allows. */
.shortBox {
  position: relative;
  width: min(100vw, calc((100vh - var(--safe, 0px)) * 9 / 16));
  aspect-ratio: 9 / 16;
  background: #0b0b0d;
  overflow: hidden;
}
/* The picture and the player sit on top of each other, not one after the
   other. Stacked the other way the player was pushed below the picture and
   out of sight, which looked like a still image that would not play. */
.shortBox img, .shortBox iframe, .shortBox > div {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  object-fit: cover;
}
.shortBox iframe, .shortBox > div { z-index: 2; }
.shortBox img { z-index: 1; }
.shortWords {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 16px 16px calc(18px + var(--safe, 0px));
  background: linear-gradient(to top, rgba(0,0,0,0.85), rgba(0,0,0,0));
  color: #fff;
  pointer-events: none;
}
.shortWords b { display: block; font-size: 15px; font-weight: 700; line-height: 1.3; }
.shortWords small { color: #cfcfd6; font-size: 13px; }
.shortsClose {
  position: absolute;
  top: calc(10px + env(safe-area-inset-top, 0px));
  right: 12px;
  z-index: 3;
  width: 44px; height: 44px;
  border-radius: 999px;
  border: 0;
  background: var(--fidfad);
  color: #fff;
  font-size: 19px;
  font-weight: 700;
  line-height: 1;
}
.shortsClose:active { background: #e03a86; }
/* Where the count used to be. "3 of 2760" was a fact about the pool rather
   than anything a person watching wanted, so the page says what it is. */
.shortsCount {
  position: absolute;
  top: calc(20px + env(safe-area-inset-top, 0px));
  left: 16px;
  z-index: 3;
  color: var(--fidfad);
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.1;
  /* Stops short of the close button, which sits in the opposite corner. At
     this size the words are wide enough to run under it on a narrow phone,
     and a title half hidden behind a cross is worse than a smaller title. */
  max-width: calc(100% - 78px);
}
.shortsHint {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(72px + var(--safe, 0px));
  text-align: center;
  color: #cfcfd6;
  font-size: 13px;
  z-index: 3;
  transition: opacity 400ms ease;
}
.shortsHint.gone { opacity: 0; }

/* Offered only when the phone refused to start the video with its sound on. */
.shortsSound {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(110px + var(--safe, 0px));
  z-index: 4;
  background: rgba(0,0,0,0.65);
  border: 1px solid rgba(255,255,255,0.35);
  color: #fff;
  border-radius: 999px;
  padding: 10px 18px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
}

/* Which of the two Shorts lists is playing. */
.shortsPools {
  position: absolute;
  top: calc(52px + env(safe-area-inset-top, 0px));
  left: 12px;
  z-index: 4;
  display: flex;
  gap: 8px;
}
.poolChip {
  background: rgba(0,0,0,0.55);
  border: 1px solid rgba(255,255,255,0.3);
  color: #fff;
  border-radius: 999px;
  padding: 7px 14px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
}
.poolChip.on { background: var(--accent); border-color: var(--accent); }

/* Four in the shaping row now, so the words are given a little less room and
   the pills stay on one line on a narrow phone. */
.shapeb em { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 400px) {
  #shapeBar { gap: 4px; padding: 6px 6px; }
  .shapeb { padding: 7px 2px; font-size: 11px; gap: 4px; }
}

/* One pool, so the name sits quietly at the top instead of two chips. */

/* The pairing steps in the TV sheet. Numbered because they are done in order,
   on two devices, and losing your place means starting again on the TV. */
.steps { margin: 6px 0 12px; padding-left: 22px; color: var(--dim); font-size: 13px; line-height: 1.55; }
.steps li { margin: 4px 0; }
.steps b { color: var(--fg); }

/* Said when the television did not answer. Not an error colour: it is an
   ordinary thing that happens when a TV is off, and the app carried on. */
.tvTrouble { border-left: 2px solid var(--line); padding-left: 10px; margin-bottom: 10px; }

/* ---------- the Custom menu's choice rows ---------- */
/*
   One of several, with a mark showing which. These look deliberately unlike
   the two buttons above them: those do something to the channel playing and
   are done with, these set what the stream is and stay set. A row that only
   ever gets tapped once should not look the same as a state you are living
   in.
*/
.pickRow {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  width: 100%;
  margin-top: 8px;
  padding: 12px;
  background: #0f0f13;
  border: 1px solid var(--line);
  border-radius: 11px;
  color: var(--fg);
  font: inherit;
  text-align: left;
}
.pickRow.on { border-color: var(--accent); background: #12182a; }
.pickRow b { display: block; font-size: 14px; font-weight: 600; }
.pickRow small { display: block; margin-top: 3px; font-size: 12px; color: var(--dim); }

/* The mark. A ring that fills when the choice is the one in force. */
.pickDot {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  margin-top: 2px;
  border-radius: 50%;
  border: 2px solid #4a4a58;
  position: relative;
}
.pickRow.on .pickDot { border-color: var(--accent); }
.pickRow.on .pickDot::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--accent);
}

/* Listed so the shape of the menu is final, and plainly not ready. */
.pickRow.soon { opacity: 0.55; }
.pickRow.soon .pickDot { border-style: dashed; }
.soonTag {
  margin-left: 7px;
  font-style: normal;
  font-size: 11px;
  font-weight: 600;
  color: var(--dim);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 1px 7px;
}

/* The mood list and the mix, revealed under Set Mood. Indented so it reads as
   belonging to that choice rather than as three more choices. */
.moodPicker {
  margin: 8px 0 2px 28px;
  padding-left: 11px;
  border-left: 2px solid var(--line);
}
.moodPick { display: flex; flex-wrap: wrap; gap: 6px; }
.moodChip {
  background: #16161c;
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 999px;
  padding: 6px 12px;
  font: inherit;
  font-size: 13px;
}
.moodChip.on { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }

.mixRow { display: flex; align-items: center; gap: 9px; margin-top: 12px; }
.mixRow small { flex: 0 0 auto; font-size: 11px; color: var(--dim); max-width: 78px; }
.mixSlider { flex: 1 1 auto; min-width: 0; accent-color: var(--accent); }
.mixNote { margin-top: 6px; }

/* A channel found by name. A row you press, so it is built like the other
   pressable rows rather than like a label with a picture beside it. */
.findRow {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin-top: 8px;
  padding: 8px 10px;
  background: #0f0f13;
  border: 1px solid var(--line);
  border-radius: 11px;
  color: var(--fg);
  font: inherit;
  text-align: left;
}
.findRow:active { border-color: var(--accent); }
.findRow b { display: block; font-size: 14px; font-weight: 600; }
.findRow small { display: block; margin-top: 2px; font-size: 12px; color: var(--dim); }
.findPic {
  flex: 0 0 auto;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: #1f1f26;
  object-fit: cover;
}

/* The Customize menu's stream settings: the Quality Stream's window rows,
   each a choice with its own number beside it, and the Custom Stream's list
   of channels, each tapped to take off. */
.streamPanel { margin: 4px 0 10px 30px; display: grid; gap: 8px; }
.winRow { display: flex; gap: 10px; align-items: center; }
.pickRow.small { flex: 1 1 auto; padding-block: 8px; }
.winSel { width: auto; min-width: 72px; margin: 0; }
.winSel.myChannelSelect { width: 100%; margin: 6px 0 8px; }
#myChannelDelete { margin-top: 0; }
@media (max-width: 420px) { .streamPanel { margin-left: 8px; } }

/* The Live Stream's two switches. Slid left is off, right is on. */
.liveSwitch { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%;
  margin-top: 8px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 12px;
  background: transparent; color: inherit; text-align: left; font: inherit; }
.liveSwitchWords { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.liveSwitchWords small { color: var(--dim); font-size: 12px; }
.liveSwitchTrack { position: relative; flex: 0 0 auto; width: 46px; height: 28px; border-radius: 999px;
  background: #3a3a44; transition: background 0.2s ease; }
.liveSwitchKnob { position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%;
  background: #fff; transition: transform 0.2s ease; }
.liveSwitch.on .liveSwitchTrack { background: var(--accent); }
.liveSwitch.on .liveSwitchKnob { transform: translateX(18px); }
@media (prefers-reduced-motion: reduce) { .liveSwitchTrack, .liveSwitchKnob { transition: none; } }

/* A stream in Customize: its name opens and folds its settings, the switch
   beside it turns it on and off. */
.streamRow { display: flex; align-items: center; gap: 10px; border-bottom: 1px solid var(--line); }
.streamName { flex: 1 1 auto; min-width: 0; display: grid; grid-template-columns: 1fr auto; column-gap: 8px;
  text-align: left; background: none; border: 0; color: var(--fg); font: inherit; font-size: 16px; padding: 14px 2px; }
.streamName b { grid-column: 1; }
.streamName small { grid-column: 1; color: var(--dim); font-size: 12px; margin-top: 2px; }
.streamChev { grid-column: 2; grid-row: 1 / span 2; align-self: center; color: var(--dim); font-size: 14px; }
.streamRow.on .streamName b { color: var(--accent); }
.streamSwitch { width: auto; margin: 0; padding: 6px 2px; border: 0; }
.collapseBtn { display: block; margin: 12px auto 4px; background: none; border: 1px solid var(--line); border-radius: 999px;
  color: var(--dim); font: inherit; font-size: 13px; padding: 6px 16px; }

/* The Personal Stream's channels: tap one and Delete opens under it. */
.myChannelList .myChannelRow { margin-bottom: 6px; }
.myChannelList #myChannelDelete { margin: 0 0 10px; }

/* The intro clip, over the video area (or the TV card's picture) until the
   first real video starts. */
.introClip { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 6; background: #000; }
.introClip[hidden] { display: none; }

/* A television in the Pick a TV sheet, with its Remove button beside it. */
.tvRow { display: flex; align-items: stretch; gap: 8px; }
.tvRow .pickRow { flex: 1; min-width: 0; }
.tvRemove {
  flex: none;
  margin-top: 8px;
  padding: 0 14px;
  background: none;
  border: 1px solid var(--line);
  border-radius: 11px;
  color: var(--dim);
  font: inherit;
  font-size: 13px;
}
.tvRemove:active { color: #ff6b6b; border-color: #ff6b6b; }

/* In Add a TV: YouTube's television screen tells people to open YouTube's
   app on their phone, and this tells them not to. It has to be seen before
   the code is typed, so it stands out from the ordinary notes around it. */
.tvIgnore { margin: 10px 0 12px; padding: 10px 12px; border: 1px solid var(--accent); border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 12%, transparent); font-size: 14px; line-height: 1.45; }
.tvIgnore b { display: block; margin-bottom: 2px; }

/* CC under the video: captions on or off for the phone's player. Sits at the
   right of the line the stream tags are on. */
#now { position: relative; }
.ccBtn { position: absolute; top: 0; right: 0; z-index: 2; background: transparent; color: var(--dim);
  border: 1px solid var(--line); border-radius: 6px; padding: 2px 7px; font: inherit; font-size: 11px; font-weight: 700; letter-spacing: .04em; cursor: pointer; }
.ccBtn.on { color: #fff; background: var(--accent); border-color: var(--accent); }

/* Packages on the Personal Stream: a switch each, like the streams. */
.packHead { margin-top: 14px; font-weight: 600; color: var(--fg); }
.packSwitchRow .streamName { cursor: default; }
/* Packages: alphabetical, one line each, in a list that scrolls on its own
   once there are more than fit (there will be hundreds). */
.packList { max-height: 50vh; overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  border: 1px solid var(--line); border-radius: 10px; padding: 0 10px; margin-top: 6px; }
.packList .streamRow:last-child { border-bottom: 0; }
.packName { padding: 10px 2px; }
.packName b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.packInfo { flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--line); background: none;
  color: var(--dim); font: italic 600 14px/1 Georgia, serif; padding: 0; cursor: pointer; }
.packInfoBack { position: fixed; inset: 0; z-index: 1000; background: rgba(0,0,0,.6); display: grid; place-items: center; padding: 16px; }
.packInfoCard { background: var(--panel, #141418); color: var(--fg); border: 1px solid var(--line); border-radius: 14px;
  max-width: 420px; width: 100%; padding: 18px; }
.packInfoCard b { display: block; font-size: 17px; margin-bottom: 8px; }
.packInfoCard p { margin: 0 0 14px; color: var(--dim); line-height: 1.5; }
.packInfoClose { display: block; margin-left: auto; background: none; border: 1px solid var(--line); border-radius: 999px;
  color: var(--fg); font: inherit; padding: 6px 16px; }

/* English or Español (in development, staging only). */
.langRow { display: flex; gap: 8px; margin: 4px 0 12px; }
.langBtn { flex: 1; padding: 10px; border-radius: 10px; border: 1px solid var(--line); background: #0f0f13; color: var(--fg); font: inherit; font-weight: 600; }
.langBtn.on { border-color: var(--accent); background: #12182a; color: var(--accent); }
.langAsk { position: fixed; inset: 0; z-index: 9999; background: rgba(0,0,0,.7); display: flex; align-items: center; justify-content: center; padding: 16px; }
.langAskCard { width: 100%; max-width: 360px; background: #15151a; border: 1px solid var(--line); border-radius: 14px; padding: 18px; display: grid; gap: 10px; text-align: center; }

/* The feature request box at the bottom of Customize. */
.requestBox { margin-top: 22px; padding-top: 14px; border-top: 1px solid rgba(127,127,127,0.25); }
.requestBox textarea { width: 100%; margin: 8px 0; }
