/* Watch Party. The characters and bubbles live inside a VideoOverlayEngine host
   (overlay/video-overlay.css), which is sized to the rendered picture:
     .wp-npcs     in the 'npcs' layer     (z 30)
     .wp-bubbles  in the 'dialogue' layer (z 50)

   Motion rule, same as Mob Mode: JS places things with `transform` (per frame
   for a walking character, on change for a bubble); CSS animates the separate
   `translate`, `rotate`, `scale` and `opacity` properties, which compose with
   it. So no animation here ever fights the placement.

   Everything is inert: the crowd never takes a click, so the player's own
   controls underneath always work. */

/* ---- 👥 Watch Party button, in the action row beside Treasure Rush --------- */
/* The row (wall/wall.css .watch-actions) holds its slots for Watch Party and
   Mob Mode (watch-actions.js watchActionSlot). A slot is layout-transparent,
   so what a feature puts in it sits in the row like any other button. With six
   buttons the row wraps on a phone rather than running off the screen. */

.watch-actions { flex-wrap: wrap; }
.watch-actions__slot { display: contents; }
.watch-actions__slot[hidden] { display: none; }

.wp-bar { display: inline-flex; align-items: center; gap: 6px; }
.watch-actions .wp-btn {
  gap: 6px;
  font-weight: 800;
  color: #fff;
  background: #2563eb;               /* blue */
  border-color: transparent;
  touch-action: manipulation;
}
.watch-actions .wp-btn:hover { background: #1d4ed8; }
.watch-actions .wp-btn:focus-visible { outline: 2px solid #1e3a8a; outline-offset: 2px; }
.wp-btn__icon { font-size: 15px; line-height: 1; }
.wp-btn__state:empty { display: none; }
.wp-btn__state {
  padding: 2px 6px;
  border-radius: 999px;
  background: #fff;
  color: #1d4ed8;
  font-size: 10.5px;
  font-weight: 900;
  letter-spacing: .08em;
}
.watch-actions .wp-btn--on { background: #1e3a8a; }
.watch-actions .wp-btn--on:hover { background: #1e40af; }
.watch-actions .wp-btn--unavailable { background: #93a3b8; cursor: default; }
.wp-bar__note { font-size: 12.5px; font-weight: 600; opacity: .85; white-space: nowrap; }
.wp-bar__note:empty { display: none; }

/* ---- Characters ------------------------------------------------------------ */

.wp-npcs { position: absolute; inset: 0; pointer-events: none; }

/* Placed by JS: transform = translate3d(left of box, top of box). */
.wp-npc {
  position: absolute;
  left: 0;
  top: 0;
  will-change: transform;
  pointer-events: none;
  transition: opacity .25s ease;
}
.wp-npc__body {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  transform: scaleX(var(--wp-flip, 1));
  transform-origin: 50% 100%;
}
.wp-npc__img {
  max-width: none;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: 50% 100%;
  filter: drop-shadow(0 4px 3px rgba(0, 0, 0, .45));
  transform-origin: 50% 100%;
  user-select: none;
  -webkit-user-drag: none;
  animation: wp-bob 3s ease-in-out infinite;
}
.wp-npc__initials {
  display: none;
  align-self: center;
  width: 70%;
  aspect-ratio: 1;
  max-width: 64px;
  border-radius: 50%;
  background: #312e81;
  color: #fff;
  font: 900 clamp(11px, 1.6vw, 18px)/1 system-ui, sans-serif;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 10px rgba(0, 0, 0, .4);
}
.wp-npc--noart .wp-npc__img { display: none; }
.wp-npc--noart .wp-npc__initials { display: flex; }

/* Poses. A character without an authored frame set shows them as motion on
   its one image; one with a set also swaps frames (watch-party-renderer.js). */
.wp-npc[data-anim="walk"] .wp-npc__img { animation: wp-waddle .42s ease-in-out infinite; }
.wp-npc[data-anim="talk"] .wp-npc__img { animation: wp-talk .5s ease-in-out infinite; }
.wp-npc[data-anim="laugh"] .wp-npc__img { animation: wp-laugh .34s ease-in-out infinite; }
.wp-npc[data-anim="confused"] .wp-npc__img { animation: wp-confused 1.3s ease-in-out infinite; }
.wp-npc[data-anim="angry"] .wp-npc__img { animation: wp-angry .16s linear infinite; filter: drop-shadow(0 4px 3px rgba(0, 0, 0, .45)) saturate(1.3) hue-rotate(-12deg); }
.wp-npc--shot[data-anim="jump"] .wp-npc__img { animation: wp-jump .6s cubic-bezier(.3, .7, .4, 1) 1, wp-talk .5s ease-in-out .6s infinite; }
.wp-npc--shot[data-anim="shocked"] .wp-npc__img { animation: wp-shocked .5s ease-out 1, wp-talk .5s ease-in-out .5s infinite; }
.wp-npc[data-anim="idle"] .wp-npc__img { animation: wp-bob 3s ease-in-out infinite; }

/* Paused video: the talk stops mid-gesture; idling carries on. */
.wp-npcs--paused .wp-npc:not([data-anim="idle"]) .wp-npc__img { animation-play-state: paused; }

/* Appearing without a walk (entrances off, or turned on while paused). */
.wp-npc--pop { animation: wp-pop .32s ease-out; }
.wp-npc--leaving { opacity: 0; }
/* Leaving the stage when the party is switched off or the video ends. */
.wp-npc--exit-left .wp-npc__body { animation: wp-exit-left .6s ease-in forwards; }
.wp-npc--exit-right .wp-npc__body { animation: wp-exit-right .6s ease-in forwards; }

/* The native controls are up: the crowd steps back so the scrubber reads. */
.wp-npcs--controls .wp-npc { opacity: .42; }

.wp-npc__emote {
  position: absolute;
  left: 50%;
  bottom: 100%;
  translate: -50% 0;
  font-size: clamp(14px, 2.2vw, 24px);
  line-height: 1;
  opacity: 0;
  filter: drop-shadow(0 2px 2px rgba(0, 0, 0, .5));
}
.wp-npc__emote.is-on { animation: wp-emote 1.8s ease-out forwards; }

@keyframes wp-bob { 50% { translate: 0 -2.5%; } }
@keyframes wp-talk { 0%, 100% { translate: 0 0; scale: 1 1; } 50% { translate: 0 -4%; scale: 1.02 .98; } }
@keyframes wp-laugh { 0%, 100% { rotate: -3deg; translate: 0 0; } 50% { rotate: 3deg; translate: 0 -5%; } }
@keyframes wp-confused { 0%, 100% { rotate: 0deg; } 30% { rotate: -7deg; } 70% { rotate: 5deg; } }
@keyframes wp-angry { 0%, 100% { translate: -1.5% 0; } 50% { translate: 1.5% 0; } }
@keyframes wp-jump { 0% { translate: 0 0; scale: 1.06 .92; } 45% { translate: 0 -28%; scale: .96 1.05; } 80% { translate: 0 0; scale: 1.05 .94; } 100% { translate: 0 0; scale: 1 1; } }
@keyframes wp-shocked { 0% { scale: 1 1; } 20% { scale: .9 1.14; translate: 0 -8%; } 60% { scale: 1.04 .97; translate: 0 0; } 100% { scale: 1 1; } }
@keyframes wp-waddle { 0%, 100% { rotate: -4deg; translate: 0 0; } 50% { rotate: 4deg; translate: 0 -5%; } }
@keyframes wp-pop { from { opacity: 0; scale: .7; } to { opacity: 1; scale: 1; } }
@keyframes wp-exit-left { to { translate: -140% 0; opacity: 0; } }
@keyframes wp-exit-right { to { translate: 140% 0; opacity: 0; } }
@keyframes wp-emote {
  0% { opacity: 0; translate: -50% 20%; scale: .5; }
  15% { opacity: 1; translate: -50% -25%; scale: 1.15; }
  30% { scale: 1; }
  80% { opacity: 1; translate: -50% -35%; }
  100% { opacity: 0; translate: -50% -55%; }
}

/* ---- Bubbles --------------------------------------------------------------- */
/* The MMO's bubble (game.css .monster-bubble / .player-bubble): white, heavy
   type, a tail at the speaker. Font size and width follow the picture's width
   (set by the renderer), so a phone and a monitor both get a readable bubble
   that never takes over the frame. */

.wp-bubbles {
  position: absolute;
  inset: 0;
  pointer-events: none;
  --wp-font: 15px;
  --wp-maxw: 260px;
}
.wp-bubble {
  position: absolute;
  left: 0;
  top: 0;
  width: max-content;
  min-width: 64px;
  max-width: var(--wp-maxw);
  padding: .45em .8em .5em;
  border-radius: 14px;
  background: rgba(255, 255, 255, .97);
  color: #14181d;
  font: 800 var(--wp-font)/1.28 system-ui, -apple-system, "Segoe UI", sans-serif;
  text-align: center;
  white-space: normal;
  overflow-wrap: anywhere;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .35);
  transform-origin: 50% 100%;
  animation: wp-bubble-in .18s ease-out;
  will-change: transform;
}
.wp-bubble[hidden] { display: none; }
.wp-bubble.is-leaving { opacity: 0; scale: .92; transition: opacity .14s ease, scale .14s ease; }
.wp-bubble__name {
  margin: 0 0 .1em;
  font-size: .68em;
  font-weight: 900;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--wp-name, #6d28d9);
}
.wp-bubble__name:empty { display: none; }
.wp-bubble__text { margin: 0; }

/* The tail: a downward triangle whose x the renderer sets, so it still points
   at the speaker when the bubble is pushed in from the edge of the picture. */
.wp-bubble__tail {
  position: absolute;
  top: 100%;
  left: 50%;
  width: 0;
  height: 0;
  translate: -50% 0;
  border: 7px solid transparent;
  border-top-color: rgba(255, 255, 255, .97);
}

/* Thought: a rounder cloud, and the tail is two little puffs. */
.wp-bubble--thought { border-radius: 26px; font-style: italic; font-weight: 700; }
.wp-bubble--thought .wp-bubble__tail {
  border: 0;
  width: 10px;
  height: 10px;
  margin-top: 3px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .97);
  box-shadow: 0 3px 8px rgba(0, 0, 0, .25);
}
.wp-bubble--thought .wp-bubble__tail::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 12px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .97);
}

/* A name colour per character, by cast order, so a viewer learns who is who. */
.wp-bubble[data-hue="0"] { --wp-name: #7c3aed; }
.wp-bubble[data-hue="1"] { --wp-name: #0e7490; }
.wp-bubble[data-hue="2"] { --wp-name: #c2410c; }
.wp-bubble[data-hue="3"] { --wp-name: #15803d; }
.wp-bubble[data-hue="4"] { --wp-name: #be185d; }
.wp-bubble[data-hue="5"] { --wp-name: #1d4ed8; }

.wp-bubbles--compact .wp-bubble { border-radius: 11px; padding: .38em .62em .42em; }
.wp-bubbles--compact .wp-bubble__tail { border-width: 6px; }

@keyframes wp-bubble-in {
  from { opacity: 0; scale: .8; }
  to { opacity: 1; scale: 1; }
}

/* ---- Admin preview badge (hud layer) ---------------------------------------- */

.wp-badge {
  position: absolute;
  right: 10px;
  top: 10px;
  padding: 4px 8px;
  border: 2px solid #a78bfa;
  border-radius: 6px;
  color: #ddd6fe;
  background: rgba(10, 12, 20, .6);
  font: 900 11px/1 system-ui, sans-serif;
  letter-spacing: .08em;
}

@media (prefers-reduced-motion: reduce) {
  .wp-npc__img, .wp-npc[data-anim] .wp-npc__img { animation: none !important; }
  .wp-bubble { animation: none; }
  .wp-npc__emote.is-on { animation: none; opacity: 1; }
}
