/* ===========================================================================
   /watch/<Name> WHEN THERE IS NO MATCH ON.

   The companion to player-channel.css, which dresses a live match. This file
   dresses the rest of the evening -- connecting, in matchmaking, paired, on air
   without a ranked game, and dark -- drawn by
   public/resources/js/player-channel/scenes.js.

   WHY THESE SCREENS GET THIS MUCH CSS. A channel link handed out in a Kick chat
   is, for most of the people who click it, the first 33Pool screen they ever
   see, and most of the time it is one of these. They are the shop window.

   DELIBERATELY DARK, AND NOT THEMED. Like the match layout above it, this is a
   broadcast surface: it is read on a television across a room and it sits around
   video. A light variant would have to fight the feed it frames, so the page
   stays on one palette in both themes -- the same decision player-channel.css
   already made for the stage.

   THE PALETTE IS THE APP'S. #2eff73 is the green on the app's own searching
   screen, and these scenes are its echo: a player watching their phone and a
   viewer watching this page are waiting for the same match.
   ========================================================================= */

.pc-scene {
  --pc-green: #2eff73;
  --pc-green-soft: rgba(46, 255, 115, 0.16);
  --pc-line: rgba(255, 255, 255, 0.1);

  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;

  /* Tall enough to hold the frame the video will occupy, so the page does not
     lurch when a match starts and the stage replaces it. */
  min-height: clamp(420px, 52vw, 640px);
  padding: clamp(24px, 4vw, 48px) clamp(16px, 3vw, 40px);

  border: 1px solid var(--pc-line);
  border-radius: 22px;
  background:
    radial-gradient(120% 90% at 50% -10%, rgba(18, 46, 34, 0.9), transparent 60%),
    linear-gradient(170deg, #0a1018 0%, #070a10 55%, #05070b 100%);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45);
  color: #f2f6f4;
  text-align: center;
}

.pc-scene-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 880px;
  margin: 0 auto;
}

/* --------------------------------------------------------------------------
   The felt

   Decoration only, and the whole reason an empty state stopped reading as
   empty: a lit table in a dark room, with the brand green as the lamp.
   -------------------------------------------------------------------------- */

.pc-scene-felt {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.pc-scene-felt-glow {
  position: absolute;
  left: 50%;
  top: -28%;
  width: min(760px, 120%);
  aspect-ratio: 1;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(46, 255, 115, 0.16) 0%,
    rgba(46, 255, 115, 0.05) 42%,
    transparent 70%
  );
  animation: pc-breathe 9s ease-in-out infinite;
}

/* A table's chalk grid, faded out before it can compete with the copy. */
.pc-scene-felt-grid {
  position: absolute;
  inset: 0;
  opacity: 0.5;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 54px 54px;
  mask-image: radial-gradient(120% 80% at 50% 30%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(120% 80% at 50% 30%, #000 20%, transparent 78%);
}

@keyframes pc-breathe {
  0%,
  100% {
    opacity: 0.85;
    transform: translateX(-50%) scale(1);
  }
  50% {
    opacity: 1;
    transform: translateX(-50%) scale(1.06);
  }
}

/* --------------------------------------------------------------------------
   Whose channel this is

   The same strip, in the same place, in every scene -- so a state change reads
   as this page changing its mind rather than as a different page.
   -------------------------------------------------------------------------- */

.pc-ident {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  text-align: left;
  margin-bottom: clamp(18px, 3vw, 30px);
}

.pc-ident-mono {
  flex: none;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 18px;
  font-size: 26px;
  font-weight: 900;
  color: #04150a;
  background: linear-gradient(145deg, #2eff73, #12b855);
  box-shadow: 0 10px 28px rgba(46, 255, 115, 0.28);
}

.pc-ident-name {
  margin: 0;
  font-size: clamp(24px, 3.4vw, 36px);
  font-weight: 900;
  letter-spacing: -0.5px;
  line-height: 1.1;
}

.pc-ident-badges {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

/* The head count sets its own margins for the match panel, where it sits alone
   on a line. In the strip the flex gap does that job. */
.pc-ident-badges .pc-site-viewers {
  margin: 0;
}

.pc-ident-handle {
  display: inline-block;
  margin-top: 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: rgba(255, 255, 255, 0.55);
  text-decoration: none;
}

.pc-ident-handle:hover {
  color: var(--pc-green);
}

/* --------------------------------------------------------------------------
   Stat tiles
   -------------------------------------------------------------------------- */

.pc-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: 10px;
  margin: clamp(20px, 3vw, 30px) auto 0;
  max-width: 720px;
}

.pc-tile {
  padding: 14px 10px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.05);
}

.pc-tile-value {
  display: block;
  font-size: clamp(18px, 2.2vw, 24px);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  color: #ffffff;
}

.pc-tile-label {
  display: block;
  margin-top: 5px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.pc-scene-note {
  margin: clamp(18px, 2.6vw, 26px) auto 0;
  max-width: 560px;
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.58);
}

/* --------------------------------------------------------------------------
   IN MATCHMAKING

   The one state somebody will sit and watch, so it is the one that moves.
   -------------------------------------------------------------------------- */

.pc-search-kicker {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 clamp(10px, 2vw, 18px);
  padding: 7px 16px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--pc-green);
  background: var(--pc-green-soft);
  border: 1px solid rgba(46, 255, 115, 0.35);
}

.pc-search-kicker-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--pc-green);
  animation: pc-blip 1.4s ease-in-out infinite;
}

@keyframes pc-blip {
  0%,
  100% {
    opacity: 1;
    box-shadow: 0 0 0 0 rgba(46, 255, 115, 0.55);
  }
  50% {
    opacity: 0.5;
    box-shadow: 0 0 0 7px rgba(46, 255, 115, 0);
  }
}

/* The radar. Rings leave the ball and fade; a slow sweep turns behind them. */
.pc-radar {
  position: relative;
  width: clamp(200px, 30vw, 260px);
  height: clamp(200px, 30vw, 260px);
  margin: 0 auto;
  display: grid;
  place-items: center;
}

.pc-radar-ring {
  position: absolute;
  width: 116px;
  height: 116px;
  border-radius: 50%;
  border: 2px solid rgba(46, 255, 115, 0.5);
  opacity: 0;
  animation: pc-ping 2400ms ease-out infinite;
}

.pc-radar-ring:nth-of-type(2) {
  animation-delay: 800ms;
}

.pc-radar-ring:nth-of-type(3) {
  animation-delay: 1600ms;
}

@keyframes pc-ping {
  0% {
    opacity: 0;
    transform: scale(0.7);
  }
  12% {
    opacity: 0.55;
  }
  100% {
    opacity: 0;
    transform: scale(2.05);
  }
}

.pc-radar-sweep {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    rgba(46, 255, 115, 0.22) 0deg,
    rgba(46, 255, 115, 0) 70deg,
    rgba(46, 255, 115, 0) 360deg
  );
  mask-image: radial-gradient(circle, transparent 42%, #000 44%, #000 96%, transparent 98%);
  -webkit-mask-image: radial-gradient(circle, transparent 42%, #000 44%, #000 96%, transparent 98%);
  animation: pc-sweep 5.2s linear infinite;
}

@keyframes pc-sweep {
  to {
    transform: rotate(360deg);
  }
}

/* The ball itself is BallRail's SVG, which sizes off font-size (1.55em). */
.pc-radar-ball {
  position: relative;
  font-size: clamp(42px, 6.4vw, 62px);
  filter: drop-shadow(0 12px 26px rgba(0, 0, 0, 0.55));
}

.pc-radar-ball .ov-ball {
  display: block;
}

/* Restarted from the JS on every swap, which is what makes each number land. */
.pc-radar-ball.is-swap {
  animation: pc-ball-in 480ms cubic-bezier(0.22, 1.4, 0.4, 1) both;
}

@keyframes pc-ball-in {
  0% {
    opacity: 0;
    transform: scale(0.62) rotate(-22deg);
  }
  100% {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
}

/* The rotating line. Two lines' worth of height is reserved so that a long
   phrase typing itself out cannot push the clock below it down the page. */
.pc-search-line {
  position: relative;
  min-height: 3.2em;
  margin: clamp(14px, 2.4vw, 22px) auto 0;
  max-width: 620px;
  font-size: clamp(17px, 2.4vw, 22px);
  font-weight: 800;
  line-height: 1.5;
  letter-spacing: 0.2px;
  color: #ffffff;
  text-shadow: 0 0 16px rgba(46, 255, 115, 0.45);
  opacity: 1;
  transition: opacity 400ms ease;
}

.pc-search-line.is-out {
  opacity: 0;
}

/* The cursor belongs to the line, not to the text, so it keeps blinking while a
   finished phrase is held -- which is most of the time it is on screen. */
.pc-search-line::after {
  content: "▌";
  margin-left: 2px;
  color: var(--pc-green);
  animation: pc-caret 1s steps(1) infinite;
}

@keyframes pc-caret {
  0%,
  49% {
    opacity: 1;
  }
  50%,
  100% {
    opacity: 0;
  }
}

.pc-search-clock {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 9px;
  margin: 10px 0 0;
  font-size: clamp(22px, 3vw, 30px);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  color: var(--pc-green);
}

.pc-search-clock small {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42);
}

/* --------------------------------------------------------------------------
   PAIRED, NOT STARTED

   One side named -- this channel, already named in the URL -- and one side not.
   See scenes.js for why the other half of the board stays a question mark.
   -------------------------------------------------------------------------- */

.pc-found-kicker {
  display: inline-block;
  margin: 0 0 clamp(16px, 2.6vw, 26px);
  padding: 8px 18px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: #1a0d03;
  background: linear-gradient(90deg, #ffb066, #ef5c23);
  box-shadow: 0 10px 28px rgba(239, 92, 35, 0.32);
}

.pc-vs {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(10px, 2.4vw, 26px);
  max-width: 620px;
  margin: 0 auto;
}

.pc-vs-side {
  padding: clamp(16px, 2.4vw, 24px) 12px;
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(255, 255, 255, 0.05);
}

.pc-vs-mono {
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  margin: 0 auto 12px;
  border-radius: 50%;
  font-size: 28px;
  font-weight: 900;
  color: #04150a;
  background: linear-gradient(145deg, #2eff73, #12b855);
}

/* The opponent. Dashed and grey on purpose: it has to read as withheld rather
   than as a slot the page failed to fill. */
.pc-vs-side.is-secret {
  border-style: dashed;
  border-color: rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.03);
}

.pc-vs-side.is-secret .pc-vs-mono {
  color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.08);
  border: 1px dashed rgba(255, 255, 255, 0.3);
}

.pc-vs-name {
  display: block;
  font-size: clamp(15px, 2vw, 19px);
  font-weight: 900;
  line-height: 1.2;
  word-break: break-word;
}

.pc-vs-sub {
  display: block;
  margin-top: 6px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}

.pc-vs-bolt {
  font-size: clamp(16px, 2.4vw, 22px);
  font-weight: 900;
  letter-spacing: 1px;
  color: rgba(255, 255, 255, 0.35);
}

/* The host's one countdown ticker writes into this, as it did before. */
.pc-scene .pc-countdown {
  margin-top: clamp(18px, 2.6vw, 26px);
  font-size: clamp(30px, 5vw, 46px);
  line-height: 1.1;
}

/* --------------------------------------------------------------------------
   ON AIR, NO RANKED MATCH
   -------------------------------------------------------------------------- */

.pc-channel-stage {
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 18px 46px rgba(0, 0, 0, 0.45);
}

.pc-channel-note {
  margin: 14px auto 0;
  max-width: 620px;
  font-size: 13.5px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.6);
}

/* A scene wrapped around a 16:9 feed has no use for a tall minimum, and the
   880px column the text scenes read best at is a small television. The feed
   gets the room a match feed gets. */
.pc-scene--channel {
  min-height: 0;
}

.pc-scene--channel .pc-scene-inner {
  max-width: 1120px;
}

/* --------------------------------------------------------------------------
   DARK
   -------------------------------------------------------------------------- */

.pc-offline-head {
  margin: 0;
  font-size: clamp(20px, 2.8vw, 27px);
  font-weight: 900;
  letter-spacing: -0.2px;
}

.pc-offline-sub {
  margin: 12px auto 0;
  max-width: 540px;
  font-size: 14.5px;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.6);
}

/* --------------------------------------------------------------------------
   Where else to go
   -------------------------------------------------------------------------- */

.pc-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: clamp(20px, 3vw, 28px) 0 0;
}

.pc-action {
  display: inline-flex;
  align-items: center;
  padding: 11px 20px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: 0.2px;
  text-decoration: none;
  color: #ffffff;
  background: rgba(255, 255, 255, 0.07);
  transition:
    transform 160ms ease,
    background 160ms ease,
    border-color 160ms ease;
}

.pc-action:hover {
  transform: translateY(-1px);
  background: rgba(255, 255, 255, 0.13);
  border-color: rgba(255, 255, 255, 0.3);
  color: #ffffff;
}

.pc-action.is-kick {
  color: #04150a;
  background: linear-gradient(135deg, #2eff73, #14c45c);
  border-color: transparent;
}

.pc-action.is-kick:hover {
  color: #04150a;
  background: linear-gradient(135deg, #58ff90, #1ad96a);
}

.pc-action.is-quiet {
  background: transparent;
  color: rgba(255, 255, 255, 0.68);
}

/* --------------------------------------------------------------------------
   What this page becomes

   For the visitor who arrived at the quiet moment. A dark page with no
   explanation is indistinguishable from a dead one.
   -------------------------------------------------------------------------- */

.pc-pitch {
  margin-top: clamp(26px, 4vw, 40px);
  padding-top: clamp(22px, 3vw, 30px);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.pc-pitch-head {
  margin: 0 0 16px;
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}

.pc-pitch-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pc-pitch-card {
  padding: 18px;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.04);
  text-align: left;
}

.pc-pitch-card strong {
  display: block;
  margin-bottom: 7px;
  font-size: 14.5px;
  font-weight: 900;
  color: var(--pc-green);
}

.pc-pitch-card span {
  display: block;
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.62);
}

/* --------------------------------------------------------------------------
   Before the socket answers
   -------------------------------------------------------------------------- */

.pc-boot {
  display: grid;
  gap: 12px;
  max-width: 460px;
  margin: 0 auto;
}

.pc-boot-bar {
  height: 14px;
  border-radius: 999px;
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.05) 0%,
    rgba(255, 255, 255, 0.13) 50%,
    rgba(255, 255, 255, 0.05) 100%
  );
  background-size: 200% 100%;
  animation: pc-shimmer 1.6s linear infinite;
}

.pc-boot-bar:nth-child(2) {
  width: 78%;
  margin: 0 auto;
}

.pc-boot-bar:nth-child(3) {
  width: 52%;
  margin: 0 auto;
}

@keyframes pc-shimmer {
  to {
    background-position: -200% 0;
  }
}

/* --------------------------------------------------------------------------
   It did not load
   -------------------------------------------------------------------------- */

/* A failure has less to say than a scene, and a half-empty 640px panel makes a
   small problem look like a broken page. */
.pc-scene--error {
  min-height: clamp(300px, 32vw, 400px);
}

.pc-error-head {
  margin: 0;
  font-size: clamp(20px, 2.8vw, 26px);
  font-weight: 900;
}

.pc-error-sub {
  margin: 12px auto 0;
  max-width: 520px;
  font-size: 14.5px;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.6);
}

/* --------------------------------------------------------------------------
   Phones
   -------------------------------------------------------------------------- */

@media (max-width: 560px) {
  .pc-ident {
    flex-direction: column;
    gap: 12px;
    text-align: center;
  }

  .pc-ident-badges {
    justify-content: center;
  }

  /* Three columns at this width gives each side about 90px, which is not enough
     for a display name. Stacked, with the "vs" between them. */
  .pc-vs {
    grid-template-columns: 1fr;
  }

  .pc-vs-bolt {
    padding: 2px 0;
  }
}

/* --------------------------------------------------------------------------
   Reduced motion

   Every scene still says everything it says, and the searching screen still
   rotates its copy and ticks its clock -- those carry the information. What
   goes is the movement: the radar, the breathing glow, the typing, the pop on
   each ball, the shimmer. scenes.js drops the typewriter itself, since a line
   appearing a character at a time is the part that is read aloud.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  /* Not frozen -- removed. A stopped radar sweep is a wedge sitting off to one
     side of the ball, which reads as a rendering fault rather than as a sweep
     that is holding still. */
  .pc-radar-sweep {
    display: none;
  }

  .pc-scene-felt-glow,
  .pc-search-kicker-dot,
  .pc-boot-bar,
  .pc-search-line::after,
  .pc-radar-ball.is-swap {
    animation: none;
  }

  .pc-radar-ring {
    /* One steady ring rather than three invisible ones: the animation is what
       was making them visible at all. */
    opacity: 0.35;
    transform: scale(1.35);
    animation: none;
  }

  .pc-radar-ring:nth-of-type(2),
  .pc-radar-ring:nth-of-type(3) {
    display: none;
  }

  .pc-search-line {
    transition: none;
  }

  .pc-action:hover {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   What else is on tonight

   The compact live board, below a dead-end scene. Its own cards and headings are
   live-matches.css's; this only places it.
   -------------------------------------------------------------------------- */

.player-channel-elsewhere {
  margin-top: clamp(20px, 3vw, 32px);
}

.player-channel-elsewhere[hidden] {
  display: none;
}
