/* Shared broadcast base: gfx canvas/pattern/fx, keying, connection dot. */
/* ════════════════════════════════════════════════════════════
   BROADCAST GRAPHICS  (graphics.html)
   Standalone, URL-param-driven full-screen graphics for the
   stream: countdown, starting-soon / break card, player intro.
   All sit on a fixed 1920×1080 canvas so OBS Browser Source
   coordinates are reliable. Add ?bg=transparent to key over a
   clean program feed.
   ════════════════════════════════════════════════════════════ */

.gfx-page {
  position: relative;
  width: 1920px;
  height: 1080px;
  overflow: hidden;
  background: var(--black);
}
/* Brand court-grid wash + soft red vignette on the solid background */
/* Brand pattern background layer. Static = the framed 16:9 crop. When animated
   (?fx=rotate|zoom|flow) it becomes an oversized centred square so it can rotate
   or scale without ever exposing the page corners. */
.gfx-bg {
  position: absolute;
  inset: 0;
  background: #000 url('../img/pattern.png') center / cover no-repeat;
  z-index: 0;
  pointer-events: none;
}
.gfx-bg.fx-rotate, .gfx-bg.fx-zoom, .gfx-bg.fx-flow {
  inset: auto;
  top: 50%; left: 50%;
  width: 2400px; height: 2400px;
  transform: translate(-50%, -50%);
  background-image: url('../img/pattern-sq.png');
}
html.gfx-transparent .gfx-bg { display: none; }

@keyframes gfxbg-rotate {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to   { transform: translate(-50%, -50%) rotate(360deg); }
}
@keyframes gfxbg-zoom {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.16); }
}
@keyframes gfxbg-flow {
  0%   { transform: translate(-50%, -50%) rotate(0deg)   scale(1.04); }
  50%  { transform: translate(-50%, -50%) rotate(180deg) scale(1.14); }
  100% { transform: translate(-50%, -50%) rotate(360deg) scale(1.04); }
}
.gfx-bg.fx-rotate { animation: gfxbg-rotate var(--fx-speed, 90s) linear infinite; }
.gfx-bg.fx-zoom   { animation: gfxbg-zoom   var(--fx-speed, 16s) ease-in-out infinite; }
.gfx-bg.fx-flow   { animation: gfxbg-flow   var(--fx-speed, 70s) linear infinite; }

/* Transparent / keyable mode — drop the background so OBS can
   composite the graphic over the live court feed. */
html.gfx-transparent,
html.gfx-transparent body { background: transparent !important; }
html.gfx-transparent body::before { display: none; }
html.gfx-transparent .gfx-page { background: transparent; }
html.gfx-transparent .gfx-page::before { display: none; }

/* Every graphic is hidden until graphics.js activates the right one */
.gfx { display: none; position: absolute; inset: 0; z-index: 1; }
.gfx.active { display: flex; }

/* ── Connection state (kit/live.js stamps html[data-conn]) ──────────────────
 * A quiet amber dot on the venue boards while realtime is down and the
 * heartbeat poll is carrying updates. Never rendered on keyed graphics —
 * only surfaces that place a .conn-dot element opt in. */
.conn-dot {
  position: fixed;
  right: 18px;
  bottom: 18px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #c9962e;
  opacity: 0;
  transition: opacity 0.6s ease;
  pointer-events: none;
  z-index: 40;
}
html[data-conn="degraded"] .conn-dot { opacity: 0.85; }

