/* ============================================================================
   fxcam-viewfinder.css — opt-in "broadcast viewfinder" reskin for fxcam.html.

   Loaded ONLY when the page is opened with ?viewfinder=1 (js/fxcam-viewfinder.js
   injects this <link> and adds body.fx-viewfinder). Every selector is scoped
   under body.fx-viewfinder, so this file is inert in production and touches no
   existing markup unless the mode is on.

   Concept: the fan's phone becomes a director's monitor. Corner crop marks, a
   tally light, a running timecode and a jumbotron-style lower-third reframe
   "start camera" as "go on air".

   State colours are FIXED broadcast semantics (amber = standby, red = on air)
   and never theme per game. Only brand chrome (--primary-color, logo, filter
   accents) themes, exactly like the rest of the platform. Tokens reuse
   fxcam-modern.css where present and fall back so this stands alone.
   ============================================================================ */

body.fx-viewfinder {
  --fxv-tally: #ff2d2d;   /* ON AIR — semantic, not themeable */
  --fxv-standby: #ffb020; /* STANDBY — semantic, not themeable */
  --fxv-ink: var(--fx-ink, var(--background-color, #0b0d10));
  --fxv-text: var(--fx-text, var(--primary-color, #e8eaed));
  --fxv-panel: var(--fx-panel, #15181d);
  --fxv-line: var(--fx-line, rgba(232, 234, 237, 0.14));
  --fxv-line-2: color-mix(in srgb, var(--fxv-text) 24%, transparent);
  --fxv-muted: color-mix(in srgb, var(--fxv-text) 55%, transparent);
  --fxv-brand: var(--primary-color, #e8375a);
  /* Typography follows the per-game JSON theme (--font-family /
     --secondary-font-family). Fallbacks are the local fonts.min.css family and
     system stacks only — no external fonts. Timecode/labels prefer the secondary
     face, with a system monospace fallback for tabular alignment. */
  --fxv-sans: var(--font-family, "Titillium Web", system-ui, -apple-system, sans-serif);
  --fxv-mono: var(--secondary-font-family, ui-monospace, "SF Mono", Menlo, monospace);
}

/* ---- Video as the director's monitor -------------------------------------- */
body.fx-viewfinder #videoContainer {
  border-radius: 22px;
  overflow: hidden;
  background: #05070b;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.06),
    0 20px 60px rgba(0, 0, 0, 0.5);
}

/* The app injects its own <div class="live-badge">LIVE</div>; the viewfinder
   HUD replaces it, so hide the default one in this mode only. */
body.fx-viewfinder #videoContainer .live-badge { display: none !important; }

/* ---- Crop-mark frame (injected) ------------------------------------------- */
body.fx-viewfinder .fxv-cropframe {
  position: absolute;
  inset: 16px 14px;
  pointer-events: none;
  z-index: 6;
}
body.fx-viewfinder .fxv-cropframe span {
  position: absolute;
  width: 18px;
  height: 18px;
  border: 2px solid var(--fxv-standby);
  opacity: 0.85;
  transition: border-color 0.35s ease;
}
body.fx-viewfinder .fxv-cropframe .tl { top: 0; left: 0; border-right: 0; border-bottom: 0; }
body.fx-viewfinder .fxv-cropframe .tr { top: 0; right: 0; border-left: 0; border-bottom: 0; }
body.fx-viewfinder .fxv-cropframe .bl { bottom: 0; left: 0; border-right: 0; border-top: 0; }
body.fx-viewfinder .fxv-cropframe .br { bottom: 0; right: 0; border-left: 0; border-top: 0; }
body.fx-viewfinder #videoContainer.is-live .fxv-cropframe span { border-color: var(--fxv-tally); }

/* ---- Status HUD: tally + timecode (injected) ------------------------------ */
body.fx-viewfinder .fxv-hud {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 7;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 16px 16px 0;
  pointer-events: none;
}
body.fx-viewfinder .fxv-tally {
  font-family: var(--fxv-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid rgba(255, 176, 32, 0.5);
  color: var(--fxv-standby);
  background: rgba(0, 0, 0, 0.42);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
body.fx-viewfinder .fxv-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--fxv-standby);
  animation: fxvBreathe 2.2s ease-in-out infinite;
}
body.fx-viewfinder #videoContainer.is-live .fxv-tally {
  color: #fff;
  border-color: rgba(255, 45, 45, 0.65);
  background: rgba(255, 45, 45, 0.16);
}
body.fx-viewfinder #videoContainer.is-live .fxv-dot {
  background: var(--fxv-tally);
  animation: fxvPulse 1.5s ease-out infinite;
}
body.fx-viewfinder .fxv-tc {
  font-family: var(--fxv-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  color: var(--fxv-muted);
  background: rgba(0, 0, 0, 0.42);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  padding: 5px 9px;
  border-radius: 8px;
  border: 1px solid var(--fxv-line);
}
body.fx-viewfinder #videoContainer.is-live .fxv-tc { color: var(--fxv-tally); }

/* ---- Lower-third: nickname as it hits the jumbotron (injected) ------------- */
body.fx-viewfinder .fxv-lowerthird {
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 84px; /* clears the floating shot + switch-camera buttons */
  z-index: 7;
  display: flex;
  pointer-events: none;
  transition: opacity 0.3s ease, transform 0.3s ease;
}
body.fx-viewfinder .fxv-lowerthird.is-empty { opacity: 0; transform: translateY(6px); }
body.fx-viewfinder .fxv-lt-bar {
  max-width: 82%;
  background: linear-gradient(90deg, rgba(6, 8, 12, 0.92), rgba(6, 8, 12, 0.5));
  border-left: 3px solid var(--fxv-brand);
  padding: 8px 13px;
  border-radius: 3px;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
body.fx-viewfinder .fxv-lt-name {
  font-family: var(--fxv-sans);
  font-weight: 800;
  font-size: 16px;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--fxv-text);
}
body.fx-viewfinder .fxv-lt-msg {
  font-family: var(--fxv-sans);
  color: color-mix(in srgb, var(--fxv-text) 78%, transparent);
  font-size: 13px;
  margin-top: 2px;
}
body.fx-viewfinder .fxv-lowerthird:not(.has-msg) .fxv-lt-msg { display: none; }

/* ---- Countdown reused as the broadcast "going live" beat ------------------- */
body.fx-viewfinder #countdown.countdown-overlay {
  font-family: var(--fxv-mono);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: #fff;
  background: rgba(4, 6, 10, 0.55);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

/* ---- Filter reel label + chips -------------------------------------------- */
body.fx-viewfinder .gallery-intro {
  font-family: var(--fxv-mono);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fxv-muted);
}
body.fx-viewfinder .gallery-cell {
  border-radius: 14px !important;
  border: 2px solid var(--fxv-line-2);
  background: var(--fxv-panel);
  color: var(--fxv-text);
  overflow: hidden;
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
  text-transform: uppercase;
  font-size: 1rem;
}
body.fx-viewfinder .gallery-cell.filter-on,
body.fx-viewfinder .gallery-cell.is-selected {
  border-color: var(--fxv-brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fxv-brand) 24%, transparent);
}

/* ---- Primary control: "go on air" red pill --------------------------------
   selfiecam.css sets `button { ...!important }`, so restyling #cameraBtn needs
   !important to win — scoped to viewfinder mode only. */
body.fx-viewfinder #cameraBtn.btn {
  background: var(--fxv-tally) !important;
  color: #fff !important;
  border: none !important;
  border-radius: 16px !important;
  font-weight: 800 !important;
  letter-spacing: 0.01em;
  box-shadow: 0 10px 30px -10px rgba(255, 45, 45, 0.6) !important;
}
body.fx-viewfinder #cameraBtn.btn:disabled {
  background: var(--fxv-panel) !important;
  color: var(--fxv-muted) !important;
  box-shadow: none !important;
}
/* Once broadcasting, the same button ends the broadcast — quiet, outlined. */
body.fx-viewfinder #videoContainer.is-live ~ #controls #cameraBtn.btn,
body.fx-viewfinder #controls #cameraBtn.btn.is-onair {
  background: transparent !important;
  color: var(--fxv-text) !important;
  border: 1px solid var(--fxv-line-2) !important;
  box-shadow: none !important;
}

/* ---- Share-to-screen actions ---------------------------------------------- */
body.fx-viewfinder #screenshotBtn.btn, body.fx-viewfinder #recordingBtn.btn {
  background: transparent !important;
  color: var(--fxv-text) !important;
  border: 1px solid var(--fxv-line-2) !important;
  border-radius: 14px !important;
  font-weight: 600 !important;
  font-size: 1rem !important;
  line-height: 1;
}
body.fx-viewfinder #floatingShotBtn {
  border-color: #fff !important;
  background: rgba(0, 0, 0, 0.5) !important;
}

/* ---- Green room (seat/queue lobby) ---------------------------------------- */
body.fx-viewfinder #seatLobby {
  background:
    radial-gradient(110% 60% at 50% 0%, color-mix(in srgb, var(--fxv-standby) 10%, transparent), transparent 60%),
    var(--fxv-ink);
}
body.fx-viewfinder .seat-lobby-card h2 {
  font-family: var(--fxv-mono);
  font-size: 12px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--fxv-standby);
  font-weight: 600;
}
body.fx-viewfinder .seat-lobby-pos {
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--fxv-standby);
}
body.fx-viewfinder .seat-lobby-spinner {
  border-color: rgba(255, 176, 32, 0.25);
  border-top-color: var(--fxv-standby);
}
body.fx-viewfinder .seat-lobby-card.next-up {
  box-shadow: 0 0 0 3px var(--fxv-standby), 0 0 28px rgba(255, 176, 32, 0.35);
}
body.fx-viewfinder #seatGoLiveBtn.btn {
  background: var(--fxv-tally) !important;
  color: #fff !important;
  border: none !important;
  border-radius: 14px !important;
  font-weight: 800 !important;
}

/* ---- Immersive fullscreen (only while the camera is live) -----------------
   The default fxcam video is a boxed 90vw × 50vh letterbox. In viewfinder mode,
   once streaming starts the camera fills the screen (clamped to the phone-frame
   width on desktop) and the controls float as a bottom dock over it. Scoped to
   .fxv-streaming so the form stage is untouched. */
body.fx-viewfinder.fxv-streaming #videoContainer {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 430px; /* matches mobile-frame; full width on a real phone */
  height: 100%;
  margin: 0;
  border-radius: 0;
  background: #05070b !important; /* beat selfiecam's inline orange */
  box-shadow: none;
  z-index: 30;
}
body.fx-viewfinder.fxv-streaming #videoContainer .fxv-cropframe { inset: 20px 16px; }

body.fx-viewfinder.fxv-streaming #localVideo,
body.fx-viewfinder.fxv-streaming #deepar-container,
body.fx-viewfinder.fxv-streaming #deepar-container canvas {
  width: 100%;
  height: 100%;
  max-width: none;
  aspect-ratio: auto;
  border: none;
  border-radius: 0;
  object-fit: cover;
  box-shadow: none;
}

/* #localVideo (raw camera) and #deepar-container (filtered canvas) are both
   height:100% block boxes, so in normal flow the raw feed fills the screen and
   the filtered canvas is pushed below the fold (clipped by #videoContainer's
   overflow:hidden) — the fan never sees the filter live. Stack them instead:
   the DeepAR canvas is the visible layer, the raw video stays behind it purely
   as DeepAR's input source. */
body.fx-viewfinder.fxv-streaming #localVideo,
body.fx-viewfinder.fxv-streaming #deepar-container {
  position: absolute;
  inset: 0;
}
body.fx-viewfinder.fxv-streaming #localVideo { z-index: 1; }
body.fx-viewfinder.fxv-streaming #deepar-container { z-index: 2; }

/* Show the WHOLE camera frame, not a zoomed-in crop. Filling the screen meant
   object-fit:cover on the video and, worse, DeepAR sizing its canvas to the
   ~9:19.5 screen and cropping the camera to fill it — the fan saw a narrow
   slice of what the jumbotron gets. Instead both layers take the camera's own
   aspect ratio (--fxv-cam-ar, set from videoWidth/videoHeight in fxcam.html),
   as large as fits, centred on the black ground. DeepAR re-reads the container's
   computed size every frame, so its canvas follows (camera flip, rotation). */
body.fx-viewfinder.fxv-streaming #localVideo,
body.fx-viewfinder.fxv-streaming #deepar-container {
  inset: auto;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(100%, calc(100vh * var(--fxv-cam-ar, 0.5625)));
  width: min(100%, calc(100dvh * var(--fxv-cam-ar, 0.5625)));
  height: auto;
  aspect-ratio: var(--fxv-cam-ar, 0.5625);
}

/* Controls become a translucent bottom dock over the video. */
body.fx-viewfinder.fxv-streaming #controls {
  position: fixed;
  left: 50%;
  bottom: 0;
  margin-bottom: 50px;
  width: 100%;
  max-width: 430px;
  z-index: 40;
  margin: 0;
  padding: 18px 16px calc(18px + env(safe-area-inset-bottom, 0px));
  padding-bottom: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: linear-gradient(180deg, transparent, rgba(4, 6, 10, 0.82) 32%, rgba(4, 6, 10, 0.92));
}
/* The floating round shutter (bottom:16px, inline !important — can't be moved)
   would collide with the dock, so hide it and use the labelled share button. */
body.fx-viewfinder.fxv-streaming #floatingShotBtn.is-visible { display: none !important; }

/* The ext-slider promo strip is position:fixed bottom:0 at z-index:10000, so it
   paints straight over this dock (z-index:40) and swallows the filter carousel and
   the stop/share buttons. Raising the dock isn't the answer: while the fan is on the
   jumbotron the dock IS the UI, and a promo strip over the live feed is noise — so
   drop the strip for the duration of the stream (same call lumen-tilt makes once a
   fan joins). It comes back at bottom:0 as soon as streaming ends.
   !important + this sheet's load order are both required: mobile-frame.css sets
   `.ext-slider{display:block!important}` and is linked before this file. */
body.fx-viewfinder.fxv-streaming .ext-slider { display: none !important; }
/* Raise the lower-third clear of the dock. */
body.fx-viewfinder.fxv-streaming .fxv-lowerthird { bottom: 188px; }
/* Move the flip-camera control up to the top-right, clear of the dock (its
   bottom/right come from inline styles, so !important is needed to win). */
body.fx-viewfinder.fxv-streaming #switchCameraBtn {
  top: 60px !important;
  bottom: auto !important;
  right: 16px !important;
}

/* ---- Motion ---------------------------------------------------------------- */
@keyframes fxvBreathe { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
@keyframes fxvPulse {
  0% { box-shadow: 0 0 0 0 rgba(255, 45, 45, 0.6); }
  100% { box-shadow: 0 0 0 9px rgba(255, 45, 45, 0); }
}
@media (prefers-reduced-motion: reduce) {
  body.fx-viewfinder .fxv-dot,
  body.fx-viewfinder #videoContainer.is-live .fxv-dot { animation: none; }
}
