/* ============================================================
   tug.css — T-T-Tug of War mode styles
   ============================================================ */

/* Canonical team colours — the single source of truth for blue/purple across
   the lobby, gameplay, spectator deck and results. These MUST match
   _SIDE_COLOUR in js/tug.js (left = blue, right = purple). Do NOT colour team
   UI with --accent-primary/-secondary: --accent-primary is purple, so a blue
   element styled `var(--accent-primary, #4da3ff)` renders purple (the fallback
   never applies) — that was the spectator "blue shows up purple" bug. */
:root {
  --tug-blue: #4da3ff;
  --tug-purple: #b07cf7;
  --tug-blue-tint: rgba(77, 163, 255, 0.13);
  --tug-purple-tint: rgba(176, 124, 247, 0.13);
}

/* ---- Train screen panel (minimal: create / join) ---- */
#train-input-toggle {
  margin-bottom: 0;
}

.tug-name-row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  margin-bottom: var(--space-md);
}

.tug-name-row--centered {
  flex-direction: column;
  justify-content: center;
  gap: var(--space-xs);
}

.tug-name-row--centered .tug-name-input {
  text-align: center;
}

/* Persistent Create / Join buttons at the bottom of the panel */
.tug-cta-row {
  display: flex;
  justify-content: center;
  gap: var(--space-md);
  padding-top: var(--space-md);
}

.tug-cta {
  width: 220px;
  justify-content: center;
}
/* Disabled until a display name is entered (gated in tug.js). */
.tug-cta:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}
.tug-name-hint {
  text-align: center;
  margin-top: var(--space-xs);
  color: var(--text-tertiary);
  /* Always occupy its line so toggling it never shifts the CTA buttons —
     fade in/out instead of display:none (gated in tug.js via .is-hidden). */
  min-height: 1.2em;
  transition: opacity 0.15s ease;
}
.tug-name-hint.is-hidden {
  visibility: hidden;
  opacity: 0;
}

/* Join pre-lobby overlay */
.gaps-popup-card.tug-join-card {
  max-width: 360px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
}

.tug-join-card .gaps-title {
  align-self: flex-start;
}

.tug-join-hint {
  text-align: center;
}

/* Spinner inside the Join button while the lobby loads */
.tug-join-spinner {
  width: 15px;
  height: 15px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  margin-right: 8px;
  flex-shrink: 0;
  animation: tugSpin 0.7s linear infinite;
}

@keyframes tugSpin {
  to { transform: rotate(360deg); }
}

#btn-tug-join:disabled {
  opacity: 0.75;
  cursor: progress;
}

.tug-name-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-secondary);
}

.tug-name-input {
  background: var(--bg-tertiary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-md, 10px);
  color: var(--text-primary);
  font-family: inherit;
  font-size: 0.95rem;
  padding: 8px 12px;
  width: 180px;
}

.tug-name-input:focus {
  outline: none;
  border-color: var(--accent-primary);
}

.tug-rule-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-md);
  margin-bottom: var(--space-md);
}

.tug-rule-card {
  text-align: left;
  background: var(--bg-tertiary);
  border: 2px solid var(--border-medium);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
  color: var(--text-primary);
  font-family: inherit;
}

.tug-rule-card:hover {
  border-color: var(--accent-primary-dim);
}

.tug-rule-card.selected {
  border-color: var(--accent-primary);
  background: var(--bg-secondary);
}

.tug-rule-card h3 {
  font-size: 0.95rem;
  font-weight: 700;
  margin-bottom: 4px;
  text-align: center;
}

.tug-rule-card p {
  font-size: 0.78rem;
  color: var(--text-secondary);
  line-height: 1.4;
}

.tug-option-row {
  margin-bottom: var(--space-sm);
}

/* Sub-option rows in the lobby: label centred above a full-width pair */
.tug-option-row--stacked {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  margin-bottom: var(--space-md);
}

.tug-option-row--stacked .gaps-toggle-label {
  text-align: center;
  min-width: 0;
}

.tug-option-row--stacked .gaps-toggle-btns {
  width: 100%;
}

.tug-join-input {
  background: var(--bg-tertiary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-md, 10px);
  color: var(--text-primary);
  font-family: 'JetBrains Mono', monospace;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  padding: 8px 12px;
  width: 130px;
  text-align: center;
}

.tug-join-input:focus {
  outline: none;
  border-color: var(--accent-primary);
}

.tug-join-error {
  color: var(--error);
  font-size: 0.8rem;
  margin-top: var(--space-xs);
  min-height: 1em;
}


/* ---- Gameplay top bar ---- */
.tug-topbar {
  text-align: center;
  margin-bottom: var(--space-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  padding-top: 4px;
}

.tug-input-btn {
  position: absolute;
  top: 0;
  left: 0;
}

.tug-leave-wrap {
  position: absolute;
  top: 0;
  right: 0;
}

.tug-players-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: var(--space-md);
  margin-bottom: var(--space-md);
  padding: 0 52px; /* clear the corner buttons */
}

.tug-player {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-width: 0;
}

.tug-player-name {
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
}

/* Left slot is always the blue team, right slot always the purple team. */
.tug-player--you .tug-player-name { color: var(--tug-blue); }
.tug-player--opp .tug-player-name { color: var(--tug-purple); }

.tug-player-score {
  font-family: 'JetBrains Mono', monospace;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--text-primary);
  background: var(--bg-tertiary);
  border-radius: 8px;
  padding: 2px 10px;
  min-width: 38px;
}

.tug-status-msg {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--warning, #e6b450);
  min-height: 1.2em;
  flex: 1;
  text-align: center;
}

.tug-status-msg.win  { color: var(--success); font-size: 1rem; }
.tug-status-msg.lose { color: var(--error);   font-size: 1rem; }

/* ---- The tug bar ---- */
.tug-bar-wrap {
  /* the visible track is inset by --bar-inset so it ends *behind the palm*
     of each hand; the bat travels only this inset width, so it zooms to
     exactly where the hand grabs it. Keep BAR_INSET in tug.js in sync. */
  --bar-inset: 26px;
  width: 100%;
  height: 16px;
  background: transparent;
  border-radius: 8px;
  position: relative;
  /* the bat now STANDS UP from the bar (barrel up, ~3-4 hands tall), so
     reserve the room above it instead of below. The PNG has transparent
     headroom, so we can sit a little higher and free space for the card. */
  margin-top: calc(var(--space-md) + 84px);
  margin-bottom: var(--space-md);
}
/* the actual track, inset behind the palms */
.tug-bar-wrap::before {
  content: '';
  position: absolute;
  left: var(--bar-inset);
  right: var(--bar-inset);
  top: 0;
  bottom: 0;
  background: var(--bg-tertiary);
  border-radius: inherit;
  z-index: 0;
}

/* the end-tint zones are superseded by the hands + finish glow */
.tug-zone { display: none; }

.tug-center-line {
  position: absolute;
  left: 50%;
  top: -4px;
  bottom: -4px;
  width: 2px;
  transform: translateX(-50%);
  background: var(--border-medium);
  border-radius: 1px;
}

.tug-bat-indicator {
  position: absolute;
  left: 50%;
  /* stand upright ON the bar: the bar sits centred in the handle (knob
     dips below the bar) so it feeds straight into the hands. The PNG is
     vertically centred with transparent padding, so the box dips well
     below to seat the handle on the bar line. */
  bottom: -66px;
  transform: translate(-50%, 0);
  pointer-events: none;
  /* Above the end-hands (z-index 5) so the sliding bat passes IN FRONT of
     the palms-out open hands. Once grabbed, the sliding bat is hidden and
     the in-fist bat (.tug-eh-bat, z-index -1) sits BEHIND the closed fist. */
  z-index: 6;
  line-height: 0;
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.5));
}
.tug-bat-indicator img { display: block; height: 220px; width: auto; }

/* Tug gameplay only: trim the question card (padding + font sizes) so it
   fits the shorter question area between the bar and the keypad without
   clipping. The bar/bat eat vertical room up top, so the card must be
   more compact here than in the solo modes. */
#screen-gameplay.tug-active .question-display {
  padding-top: var(--space-md);
  padding-bottom: var(--space-md);
  gap: var(--space-xs);
}
#screen-gameplay.tug-active .q-operand,
#screen-gameplay.tug-active .q-answer-preview {
  font-size: clamp(1.4rem, 5vw, 2.1rem);
}
#screen-gameplay.tug-active .q-operator {
  font-size: clamp(1.05rem, 3.6vw, 1.5rem);
}
#screen-gameplay.tug-active .q-equals {
  font-size: clamp(1.2rem, 4.4vw, 1.8rem);
}

/* A faint team-colour wash across the whole gameplay background, weighted
   toward the player's side (blue defends the left, purple the right) — an
   always-present, ambient reminder of their team. Kept low-alpha so the
   keypad/question stay legible; pointer-events:none so it never blocks input. */
#screen-gameplay.tug-side-blue::after,
#screen-gameplay.tug-side-purple::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
#screen-gameplay.tug-side-blue::after {
  background: radial-gradient(135% 125% at 0% 45%, rgba(77, 163, 255, 0.26), rgba(77, 163, 255, 0.1) 45%, transparent 80%);
}
#screen-gameplay.tug-side-purple::after {
  background: radial-gradient(135% 125% at 100% 45%, rgba(176, 124, 247, 0.26), rgba(176, 124, 247, 0.1) 45%, transparent 80%);
}

/* ============================================================
   Finish-line glow + persistent end-hands.
   The hands sit permanently at each end and pulse a "magnetic" wash
   inward on every correct answer from that team. The glow's inner edge
   is the win line: its width is set every frame and grows inward as
   sudden death closes (replacing the old wall + line markers).
   ============================================================ */
.tug-glow {
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.6;
  border-radius: 8px;
}
/* Solid, uniform glow across the whole encroaching section (hand → marker),
   then a soft feather over the last 22px that spills just past the marker.
   The marker itself is the only hard edge. Keep the 22px in sync with
   GLOW_TAIL in _renderFinish (tug.js). */
.tug-glow--left  { left: var(--bar-inset, 0);  background: linear-gradient(90deg, var(--team), var(--team) calc(100% - 22px), transparent); }
.tug-glow--right { right: var(--bar-inset, 0); background: linear-gradient(90deg, transparent, var(--team) 22px, var(--team)); }
.tug-glow.pulse { animation: tugGlowPulse 0.5s ease-out; }
@keyframes tugGlowPulse {
  0%   { filter: brightness(2.1); }
  100% { filter: brightness(1); }
}

/* Bright finish-line marker at the win line (inner edge of the glow). Its
   position is set every frame; it slides inward as sudden death closes and
   pulses while closing, so the shrinking arena is obvious. */
.tug-winline {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 3px;
  z-index: 2;
  transform: translateX(-50%);
  pointer-events: none;
  border-radius: 2px;
  background: var(--team);
  box-shadow: 0 0 6px var(--team), 0 0 13px var(--team), 0 0 20px var(--team);
}
.tug-winline--right { transform: translateX(50%); }
.tug-winline.closing { animation: tugWinlinePulse 0.8s ease-in-out infinite; }
@keyframes tugWinlinePulse {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.8); }
}

.tug-endhand {
  --hand: 56px;            /* ~3x the bar height (visible hand, allowing for PNG padding) */
  position: absolute;
  bottom: -20px;           /* centre the hand on the bar line */
  width: var(--hand);
  height: var(--hand);
  z-index: 5;
  pointer-events: none;
  isolation: isolate;
  filter: drop-shadow(0 0 6px var(--team));
}
/* transform-origin sits at the grip so the bat pivots where it's held.
   --spin sets the wind-up direction so each side mirrors the other:
   blue (left) winds up clockwise, purple (right) anti-clockwise — both
   sweep the bat over the top and slam down onto the centre. */
.tug-endhand--left  { left: -10px;  transform-origin: 60% 52%; --spin: 1; }
.tug-endhand--right { right: -10px; transform-origin: 40% 52%; --spin: -1; }
.tug-endhand.pulse { animation: tugHandPulse 0.45s ease-out; }
@keyframes tugHandPulse {
  0%   { filter: drop-shadow(0 0 16px var(--team)) brightness(1.3); }
  100% { filter: drop-shadow(0 0 6px var(--team)) brightness(1); }
}

.tug-vhand { position: absolute; inset: 0; isolation: isolate; transition: opacity 0.16s ease; }
.tug-vhand img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* the bat the hand grips: same PNG as the indicator, seated in the grip
   (behind the fist) with the barrel sticking up above the small hand */
.tug-eh-bat {
  position: absolute;
  bottom: -14px;
  opacity: 0;
  z-index: -1;
  pointer-events: none;
}
/* seat the bat in the grip (offset toward the fingers, per side) */
.tug-endhand--left  .tug-eh-bat { left: 60%; }
.tug-endhand--right .tug-eh-bat { left: 40%; }
.tug-eh-bat img { display: block; height: 220px; width: auto; transform: translateX(-50%); }
/* zero-size marker at the barrel tip (img is translateX(-50%), so left:0 is the
   bat centreline; top ≈ the PNG's transparent headroom). Read live each frame
   so the charge glow can follow the bat tip through the swing. */
.tug-eh-tip { position: absolute; left: 0; top: 18%; width: 0; height: 0; }
.tug-vhand .tint {
  position: absolute; inset: 0;
  background: var(--team);
  mix-blend-mode: multiply;
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}
/* open hand during play; fist (+ bat) on grab */
.tug-endhand .tug-vhand--out  { opacity: 1; }
.tug-endhand .tug-vhand--grip { opacity: 0; }
.tug-endhand.grab .tug-vhand--out  { opacity: 0; }
.tug-endhand.grab .tug-vhand--grip { opacity: 1; }
.tug-endhand.grab .tug-eh-bat { opacity: 1; }

/* victory swing: CHARGE (anti-clockwise spin-up while drifting up to the
   midline) → STRAIN (pause + vibrate, muscles loading) → super-fast SLAM
   straight down. --slam-x is the sweep to centre (set per side in JS). */
.tug-endhand.slam {
  animation: tugSlam 1.05s linear forwards;
}
@keyframes tugSlam {
  /* charge: spin up (direction per side via --spin), rise and drift to midline.
     Peak rise kept modest (-32px) so the tall bat doesn't clip the top edge. */
  0%   { transform: translate(0, 0) rotate(0deg); animation-timing-function: cubic-bezier(0.15, 0.6, 0.3, 1); }
  44%  { transform: translate(var(--slam-x, 0px), -28px) rotate(calc(var(--spin, -1) * 360deg)); animation-timing-function: linear; }
  /* strain: vibrate around the wound-up pose */
  50%  { transform: translate(calc(var(--slam-x, 0px) - 3px), -30px) rotate(calc(var(--spin, -1) * 364deg)); }
  56%  { transform: translate(calc(var(--slam-x, 0px) + 3px), -26px) rotate(calc(var(--spin, -1) * 356deg)); }
  62%  { transform: translate(calc(var(--slam-x, 0px) - 3px), -30px) rotate(calc(var(--spin, -1) * 364deg)); }
  68%  { transform: translate(calc(var(--slam-x, 0px) + 3px), -26px) rotate(calc(var(--spin, -1) * 356deg)); }
  74%  { transform: translate(calc(var(--slam-x, 0px) - 2px), -29px) rotate(calc(var(--spin, -1) * 362deg)); }
  80%  { transform: translate(var(--slam-x, 0px), -28px) rotate(calc(var(--spin, -1) * 360deg)); }
  /* hold, then SUPER-FAST slam straight down onto the centre */
  90%  { transform: translate(var(--slam-x, 0px), -28px) rotate(calc(var(--spin, -1) * 360deg)); animation-timing-function: cubic-bezier(0.9, 0, 1, 1); }
  100% { transform: translate(var(--slam-x, 0px), 10px) rotate(calc(var(--spin, -1) * 470deg)); }
}

/* impact shockwave ring (spawned at the centre on slam) */
.tug-shockwave {
  position: absolute;
  top: 50%;
  width: 12px; height: 12px;
  border-radius: 50%;
  border: 3px solid var(--team);
  transform: translate(-50%, -50%) scale(0);
  opacity: 0;
  z-index: 6;
  pointer-events: none;
}
.tug-shockwave.go { animation: tugShock 0.6s ease-out forwards; }
@keyframes tugShock {
  0%   { transform: translate(-50%, -50%) scale(0);  opacity: 0.9; }
  100% { transform: translate(-50%, -50%) scale(18); opacity: 0; }
}

/* screen-shake on impact */
@keyframes tugShake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(3px); }
  30%, 50%, 70% { transform: translateX(-7px); }
  40%, 60% { transform: translateX(7px); }
}
.tug-shake { animation: tugShake 0.5s ease; }

/* Blur used to cover the gameplay→results swap at the moment of the slam.
   The fireworks canvas lives on <body>, so it is NOT blurred. */
#screen-gameplay.tug-blur,
#screen-results.tug-blur {
  filter: blur(16px);
  transition: filter 0.24s ease;
}

/* End-of-round glow (both win and loss). A bright wash that brightens outward
   from the bat tip during the charge, PULSES during the strain/hang, then a
   very bright flash bursts from the point of contact at the slam. Body-level
   and `screen`-blended so it brightens the scene; pointer-events:none. */
.tug-charge-glow {
  position: fixed;
  width: 60vmax;
  height: 60vmax;
  border-radius: 50%;
  pointer-events: none;
  z-index: 200;
  opacity: 0;
  mix-blend-mode: screen;
  background: radial-gradient(circle,
    rgba(255, 255, 255, 0.95) 0%,
    rgba(255, 255, 255, 0.4) 26%,
    transparent 62%);
  transform: translate(-50%, -50%) scale(0.15);
  animation: tugChargeGlow 1050ms ease-in forwards;
}
/* Tint the charge glow to the winning team's colour. screen-blend brightens
   the scene toward the hue, so the core is a bright TINT of the team colour
   (not near-white) — otherwise the white core washes the colour out. */
.tug-charge-glow--blue {
  background: radial-gradient(circle,
    rgba(130, 200, 255, 0.95) 0%,
    rgba(40, 140, 255, 0.72) 38%,
    transparent 66%);
}
.tug-charge-glow--purple {
  background: radial-gradient(circle,
    rgba(190, 140, 255, 0.95) 0%,
    rgba(150, 80, 245, 0.72) 38%,
    transparent 66%);
}
@keyframes tugChargeGlow {
  /* charge: grow + brighten as the bat winds up */
  0%   { opacity: 0;    transform: translate(-50%, -50%) scale(0.15); }
  44%  { opacity: 0.55; transform: translate(-50%, -50%) scale(0.70); }
  /* strain: pulse in time with the bat shaking in the air */
  54%  { opacity: 0.85; transform: translate(-50%, -50%) scale(0.84); }
  62%  { opacity: 0.48; transform: translate(-50%, -50%) scale(0.72); }
  70%  { opacity: 0.88; transform: translate(-50%, -50%) scale(0.86); }
  80%  { opacity: 0.55; transform: translate(-50%, -50%) scale(0.78); }
  /* hold bright into the downswing */
  100% { opacity: 0.8;  transform: translate(-50%, -50%) scale(0.92); }
}
/* reduced motion: steady brighten, no pulsing */
.tug-charge-glow.reduce { animation: tugChargeGlowCalm 900ms ease-out forwards; }
@keyframes tugChargeGlowCalm {
  0%   { opacity: 0;   transform: translate(-50%, -50%) scale(0.2); }
  100% { opacity: 0.5; transform: translate(-50%, -50%) scale(0.9); }
}

.tug-slam-flash {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9998; /* below the fireworks canvas (9999) so bursts read over it */
  opacity: 0;
  background: radial-gradient(circle at var(--fx, 50%) var(--fy, 50%),
    rgba(255, 255, 255, 0.98) 0%,
    rgba(255, 255, 255, 0.6) 26%,
    transparent 62%);
  animation: tugSlamFlash 430ms ease-out forwards;
}
@keyframes tugSlamFlash {
  0%   { opacity: 0; }
  9%   { opacity: 1; }
  100% { opacity: 0; }
}
/* reduced motion: gentler flash */
.tug-slam-flash.reduce { animation: tugSlamFlashCalm 430ms ease-out forwards; }
@keyframes tugSlamFlashCalm {
  0%   { opacity: 0; }
  12%  { opacity: 0.55; }
  100% { opacity: 0; }
}

/* Radial reveal: the results screen irises open from the slam point
   (--reveal-x/y are set per win in JS) as the fireworks burst from there. */
#screen-results.tug-reveal {
  animation: tugReveal 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) forwards;
}
@keyframes tugReveal {
  0% {
    clip-path: circle(0% at var(--reveal-x, 50%) var(--reveal-y, 50%));
    filter: blur(10px);
  }
  100% {
    clip-path: circle(160% at var(--reveal-x, 50%) var(--reveal-y, 50%));
    filter: blur(0);
  }
}

/* Defeated player's slam impact: an electric, strobing jolt — a full-screen
   flash, shock rings, and red lightning forking from the slam point. */
.tug-crash-flash {
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  background: radial-gradient(circle at center, rgba(255, 80, 80, 0.42), rgba(0, 0, 0, 0.6));
  animation: tugCrashFlash 0.5s steps(1, end) forwards;
}
/* strobe: a couple of hard electric flickers, then fade */
@keyframes tugCrashFlash {
  0%   { opacity: 0.95; }
  12%  { opacity: 0.25; }
  20%  { opacity: 0.9; }
  32%  { opacity: 0.2; }
  45%  { opacity: 0.55; }
  100% { opacity: 0; }
}
.tug-crash-ring {
  position: fixed;
  width: 24px; height: 24px;
  margin: -12px 0 0 -12px;
  border-radius: 50%;
  border: 4px solid rgba(255, 90, 90, 0.85);
  box-shadow: 0 0 18px rgba(255, 60, 60, 0.7);
  transform: scale(0);
  opacity: 0;
  z-index: 9999;
  pointer-events: none;
}
.tug-crash-ring.go { animation: tugCrashRing 0.7s ease-out forwards; }
@keyframes tugCrashRing {
  0%   { transform: scale(0);  opacity: 0.95; }
  100% { transform: scale(26); opacity: 0; }
}
/* white-hot inner core ring: faster, brighter, thinner */
.tug-crash-ring--core {
  border-color: rgba(255, 235, 235, 0.95);
  border-width: 3px;
  box-shadow: 0 0 16px rgba(255, 120, 120, 0.9), 0 0 30px rgba(255, 40, 40, 0.6);
}
.tug-crash-ring--core.go { animation: tugCrashRingCore 0.5s ease-out forwards; }
@keyframes tugCrashRingCore {
  0%   { transform: scale(0);  opacity: 1; }
  100% { transform: scale(16); opacity: 0; }
}

/* red lightning bolts forking from the slam point */
.tug-crash-bolts {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  overflow: visible;
}
.tug-bolt {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  animation: tugBolt 0.42s steps(1, end) forwards;
}
.tug-bolt-glow {
  stroke: rgba(255, 40, 40, 0.85);
  stroke-width: 7;
  filter: drop-shadow(0 0 8px rgba(255, 30, 30, 0.95)) drop-shadow(0 0 16px rgba(255, 0, 0, 0.7));
}
.tug-bolt-core {
  stroke: #ffe6e6;
  stroke-width: 2.4;
  filter: drop-shadow(0 0 4px rgba(255, 120, 120, 0.95));
}
/* flicker on/off like an electric arc, then snap out */
@keyframes tugBolt {
  0%   { opacity: 0; }
  6%   { opacity: 1; }
  16%  { opacity: 0.15; }
  26%  { opacity: 1; }
  40%  { opacity: 0.4; }
  52%  { opacity: 0.9; }
  100% { opacity: 0; }
}

/* big VICTORY / DEFEAT banner */
.tug-victory-banner {
  position: fixed;
  inset: 0;
  z-index: 240;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.tug-victory-banner-text {
  font-family: 'JetBrains Mono', monospace;
  font-weight: 900;
  font-size: clamp(2.5rem, 12vw, 7rem);
  letter-spacing: 0.05em;
  animation: tugBannerPop 0.5s cubic-bezier(0.2, 1.5, 0.4, 1) both;
}
.tug-victory-banner.win  .tug-victory-banner-text { color: var(--success); text-shadow: 0 0 30px var(--success); }
.tug-victory-banner.lose .tug-victory-banner-text { color: var(--error);   text-shadow: 0 0 30px var(--error); }
.tug-victory-banner.fade { opacity: 0; transition: opacity 0.4s ease; }
@keyframes tugBannerPop {
  0%   { transform: scale(0.4); opacity: 0; }
  100% { transform: scale(1);   opacity: 1; }
}

/* Reduced motion: keep the slam (it's a core moment) but drop the shake. */
@media (prefers-reduced-motion: reduce) {
  .tug-shake { animation: none; }
  .tug-victory-banner-text { animation: none; }
  .tug-crash-ring { animation: none; }
  .tug-bolt { animation: none; opacity: 0; }
  #screen-results.tug-reveal { animation: none; }
}

/* ---- Lobby ---- */
/* As wide as the train screen's content area (.screen-inner: 720px).
   Doubled selector to out-rank .gaps-popup-card's 440px max-width.
   Bottom padding moves to the sticky action footer. */
.gaps-popup-card.tug-lobby-card {
  max-width: 720px;
  width: min(720px, calc(100vw - 2 * var(--space-md)));
  max-height: 90svh;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-bottom: 0;
  /* NB: deliberately NOT using the standard `scrollbar-width` /
     `scrollbar-color` here. In current Chromium/Edge, setting
     `scrollbar-width` switches to the standard scrollbar and makes the
     browser ignore every ::-webkit-scrollbar rule below — which left
     the default arrow buttons poking into the rounded corners. Sticking
     to the ::-webkit-scrollbar pseudo-elements lets us hide those
     buttons and inset the thumb. */
}

.gaps-popup-card.tug-lobby-card::-webkit-scrollbar {
  width: 10px;
}

/* Hide the up/down arrow buttons (Windows draws them at the very ends,
   outside the track, so they poke into the rounded corners). */
.gaps-popup-card.tug-lobby-card::-webkit-scrollbar-button {
  display: none;
  height: 0;
  width: 0;
}

.gaps-popup-card.tug-lobby-card::-webkit-scrollbar-track {
  background: transparent;
  /* hold the thumb away from the top/bottom rounded corners */
  margin: var(--radius-xl) 0;
}

.gaps-popup-card.tug-lobby-card::-webkit-scrollbar-thumb {
  background: var(--border-medium);
  border-radius: 999px;
  /* transparent border insets the pill so it floats off the edge */
  border: 2px solid transparent;
  background-clip: padding-box;
}

@media (hover: hover) {
  .gaps-popup-card.tug-lobby-card::-webkit-scrollbar-thumb:hover {
    background: var(--text-tertiary);
    background-clip: padding-box;
  }
}

/* Smart-rules children share one line: Target left, Direction right */
#tug-smart-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-md);
}

.tug-lobby-subtitle {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-tertiary);
  text-align: center;
  margin: var(--space-md) 0 var(--space-sm);
}

.tug-lobby-settings {
  border-top: 1px solid var(--border-medium);
  margin-top: var(--space-sm);
}

/* The reparented Operations/Direction/Ranges tile loses its card chrome
   inside the modal so it reads as part of the lobby */
#tug-rules-slot .settings-tile,
#tug-rules-slot #rules-tile {
  background: transparent;
  border: none;
  box-shadow: none;
  padding: 0;
  margin: 0;
}

#tug-rules-slot .settings-tile-section {
  padding: var(--space-md) 0 0;
}

/* No divider lines between the reparented sections inside the lobby */
#tug-rules-slot .settings-tile-section + .settings-tile-section {
  border-top: none;
}

/* Action buttons stay pinned to the bottom of the modal while the
   settings above them scroll (opaque background masks what passes
   underneath — no shadow, it showed even when nothing scrolls) */
.tug-lobby-actions {
  display: flex;
  gap: var(--space-sm);
  position: sticky;
  bottom: 0;
  z-index: 5;
  background: var(--bg-secondary);
  padding: var(--space-md) 0 var(--space-xl);
}

.tug-lobby-actions .btn {
  flex: 1;
  justify-content: center;
}

/* Guest preview: label/value rows in two columns */
#tug-lobby-settings-guest {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: var(--space-xl);
  align-content: start;
  padding-top: var(--space-xs);
}

.tug-preview-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  padding: 6px 2px;
  border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.06));
  min-width: 0;
}

.tug-preview-row:nth-last-child(-n+2) {
  border-bottom: none;
}

.tug-preview-label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-tertiary);
  white-space: nowrap;
}

.tug-preview-value {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-primary);
  text-align: right;
}

.tug-lobby-status {
  font-size: 0.88rem;
  color: var(--text-secondary);
  margin: var(--space-sm) 0 var(--space-md);
  min-height: 1.2em;
}

.tug-lobby-status.error {
  color: var(--error);
  background: var(--error-dim);
  border: 1px solid var(--error);
  border-radius: var(--radius-md, 8px);
  padding: 10px 14px;
  font-size: 0.9rem;
  line-height: 1.5;
}

/* Ready AND Start grey out properly while their conditions aren't met */
.tug-lobby-actions .btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none;
}

.tug-code-section {
  text-align: center;
  background: var(--bg-tertiary);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
  margin-bottom: var(--space-md);
}

.tug-code-label {
  display: block;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
  color: var(--text-tertiary);
  margin-bottom: var(--space-xs);
}

.tug-code-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
}

.tug-room-code {
  font-family: 'JetBrains Mono', monospace;
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  background: var(--accent-gradient);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* Pulse placeholder shown while the room code is being created */
.tug-code-loading {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  vertical-align: middle;
}

.tug-code-dot {
  width: 0.5em;
  height: 0.85em;
  border-radius: 5px;
  background: var(--border-medium);
  animation: tugCodePulse 1.1s ease-in-out infinite;
}

.tug-code-dot:nth-child(2) { animation-delay: 0.12s; }
.tug-code-dot:nth-child(3) { animation-delay: 0.24s; }
.tug-code-dot:nth-child(4) { animation-delay: 0.36s; }
.tug-code-dot:nth-child(5) { animation-delay: 0.48s; }

@keyframes tugCodePulse {
  0%, 100% { opacity: 0.3; }
  50%      { opacity: 1; }
}

.tug-lobby-players {
  margin-bottom: var(--space-md);
}

/* Blue team — spectators — purple team */
.tug-team-cols {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--space-sm);
}

.tug-team-col {
  background: var(--bg-tertiary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-lg);
  padding: var(--space-sm);
  min-height: 96px;
}

.tug-team-col--blue   { border-top: 3px solid var(--tug-blue); }
.tug-team-col--spec   { border-top: 3px solid var(--border-medium); }
.tug-team-col--purple { border-top: 3px solid var(--tug-purple); }

.tug-team-col-title {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  text-align: center;
  color: var(--text-tertiary);
  margin-bottom: var(--space-sm);
}

.tug-team-col--blue   .tug-team-col-title { color: var(--tug-blue); }
.tug-team-col--purple .tug-team-col-title { color: var(--tug-purple); }

/* Spotlight the local player's current column so their team reads instantly.
   Colour the whole border to match the accent top bar (so they merge into one
   clean outline) + a soft outer glow — no hard box-shadow ring, which would
   double up against the 3px coloured border-top. */
.tug-team-col--mine { position: relative; }
.tug-team-col--blue.tug-team-col--mine {
  background: var(--tug-blue-tint);
  border-color: var(--tug-blue);
  box-shadow: 0 0 10px -1px var(--tug-blue), 0 0 26px 0 var(--tug-blue);
}
.tug-team-col--purple.tug-team-col--mine {
  background: var(--tug-purple-tint);
  border-color: var(--tug-purple);
  box-shadow: 0 0 10px -1px var(--tug-purple), 0 0 26px 0 var(--tug-purple);
}
.tug-team-col--spec.tug-team-col--mine {
  background: var(--bg-secondary);
  border-color: var(--border-medium);
  box-shadow: 0 0 10px -1px var(--border-medium), 0 0 22px 0 var(--border-medium);
}

/* Guest cue shown when the host has locked teams. */
.tug-lock-note {
  text-align: center;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: var(--space-sm);
}

.tug-team-col-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  /* Big lobbies: each column scrolls instead of stretching the modal */
  max-height: 264px;
  overflow-y: auto;
}

.tug-team-empty {
  text-align: center;
  color: var(--text-tertiary);
  font-size: 0.85rem;
  padding: var(--space-xs) 0;
}

.tug-player-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-md);
  padding: 6px 8px;
  min-width: 0;
}

.tug-player-chip.is-ready {
  border-color: var(--success);
}

.tug-chip-name {
  font-weight: 600;
  font-size: 0.85rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.tug-chip-status {
  display: inline-flex;
  align-items: center;
  color: var(--text-tertiary);
  font-size: 0.75rem;
  flex-shrink: 0;
}

.tug-player-chip.is-ready .tug-chip-status {
  color: var(--success);
}

/* Person icon = you, house icon = host */
.tug-chip-icon {
  display: inline-flex;
  align-items: center;
  color: var(--text-tertiary);
  flex-shrink: 0;
}

.tug-chip-icon--you {
  color: var(--accent-secondary);
}

.tug-move-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-tertiary);
  border: 1px solid var(--border-medium);
  border-radius: 6px;
  color: var(--text-secondary);
  cursor: pointer;
  padding: 3px;
  flex-shrink: 0;
  transition: all var(--transition-fast);
}

@media (hover: hover) {
  .tug-move-btn:hover {
    color: var(--text-primary);
    border-color: var(--accent-primary);
    background: var(--bg-elevated);
  }
}


/* ---- Countdown overlay ---- */
.tug-countdown-overlay {
  position: fixed;
  inset: 0;
  z-index: 250;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* Team labels flank the countdown number (blue left, purple right). A
   1fr/auto/1fr grid keeps the number perfectly centred regardless of the side
   widths. The player's side lights up with a silhouette behind its name; the
   other dims. Spectators see only the number (.is-spec hides the labels). */
.tug-countdown-sides {
  width: min(600px, 92vw);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-md);
}
.tug-cd-side {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-size: 2.1rem;
  font-weight: 700;
  opacity: 0.35;
  transition: opacity 0.2s ease;
}
.tug-cd-side--blue   { justify-self: start; }
.tug-cd-side--purple { justify-self: end; }
.tug-cd-side--blue   .tug-cd-side-name,
.tug-cd-side--blue   .tug-cd-arrow { color: var(--tug-blue); }
.tug-cd-side--purple .tug-cd-side-name,
.tug-cd-side--purple .tug-cd-arrow { color: var(--tug-purple); }
.tug-cd-arrow { font-size: 2rem; line-height: 1; }
.tug-countdown-sides.is-spec .tug-cd-side { visibility: hidden; }

/* Silhouette behind the player's own team name. */
.tug-cd-name-wrap { position: relative; display: inline-flex; align-items: center; }
.tug-cd-side-name { position: relative; z-index: 1; white-space: nowrap; }
.tug-cd-figure {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -52%);
  height: 2.6em;
  width: auto;
  opacity: 0;
  z-index: 0;
}
.tug-cd-side--blue   .tug-cd-figure { color: var(--tug-blue); }
.tug-cd-side--purple .tug-cd-figure { color: var(--tug-purple); }

/* The active side: full opacity, a soft team glow on the name, and its
   silhouette revealed. */
.tug-countdown-sides.is-blue   .tug-cd-side--blue,
.tug-countdown-sides.is-purple .tug-cd-side--purple { opacity: 1; }
.tug-countdown-sides.is-blue   .tug-cd-side--blue   .tug-cd-side-name { text-shadow: 0 0 14px var(--tug-blue); }
.tug-countdown-sides.is-purple .tug-cd-side--purple .tug-cd-side-name { text-shadow: 0 0 14px var(--tug-purple); }
.tug-countdown-sides.is-blue   .tug-cd-side--blue   .tug-cd-figure,
.tug-countdown-sides.is-purple .tug-cd-side--purple .tug-cd-figure { opacity: 0.28; }

.tug-countdown-num {
  font-family: 'JetBrains Mono', monospace;
  font-size: 7rem;
  font-weight: 800;
  background: var(--accent-gradient);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  line-height: 1;
}

.tug-countdown-num.tick {
  animation: tugCountTick 0.5s ease;
}

@keyframes tugCountTick {
  0%   { transform: scale(1.4); opacity: 0.4; }
  100% { transform: scale(1);   opacity: 1; }
}

/* ---- Inline correct-answer flash (replaces BTC's pausing reveal) ---- */
.q-answer-preview.tug-answer-flash {
  color: var(--success);
  animation: tugAnswerFlash 0.4s ease;
}

@keyframes tugAnswerFlash {
  0%   { transform: scale(0.7); opacity: 0; }
  100% { transform: scale(1);   opacity: 1; }
}

/* ---- Results ---- */
/* When the lobby is gone, Rematch / View Lobby grey out so it's clear
   that leaving is the only option left */
#btn-tug-rematch:disabled,
#btn-tug-view-lobby:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none;
}

.tug-results-notice {
  text-align: center;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--warning, #e6b450);
  margin: var(--space-sm) 0;
  min-height: 1.2em;
}

.tug-exit-lobby-btn {
  color: var(--error);
  border-color: var(--error-dim);
}

@media (hover: hover) {
  .tug-exit-lobby-btn:hover {
    color: var(--error);
    background: var(--error-dim);
    border-color: var(--error);
  }
}

.results-header.tug-result-header {
  display: block !important;
  text-align: center;
  margin-bottom: var(--space-md);
}

#results-title.tug-victory {
  background: linear-gradient(135deg, hsl(175, 72%, 46%), hsl(145, 70%, 50%), hsl(55, 88%, 52%));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  font-size: 2rem;
}

#results-title.tug-defeat {
  color: var(--error);
  font-size: 2rem;
}

/* ---- Host: spectator-data visibility toggle ---- */
/* Compact icon toggles, centred above the columns (= above the spectators
   column). Details show via the [data-tooltip] hover bubble. */
.tug-host-toggles {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
}

.tug-spec-data-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-pill, 999px);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}

/* Icon-only variant: square pill, no label. */
.tug-icon-toggle {
  justify-content: center;
  gap: 0;
  width: 38px;
  height: 38px;
  padding: 0;
}

.tug-spec-data-toggle.is-on {
  color: var(--accent-primary, #4da3ff);
  border-color: var(--accent-primary, #4da3ff);
}

.tug-spec-data-eye { display: inline-flex; line-height: 0; }
.tug-spec-data-toggle .eye-off { display: none; }
.tug-spec-data-toggle:not(.is-on) .eye-open { display: none; }
.tug-spec-data-toggle:not(.is-on) .eye-off { display: inline; }

@media (hover: hover) {
  .tug-spec-data-toggle:hover { border-color: var(--accent-primary, #4da3ff); }
}

/* ---- Host team tools (shuffle / auto-balance) ---- */
.tug-host-tools {
  display: flex;
  justify-content: center;
  gap: var(--space-sm);
  margin: calc(-1 * var(--space-xs)) 0 var(--space-md);
}

.tug-host-tool-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  padding: 6px 14px;
}

/* ============================================================
   Spectator broadcast deck
   ============================================================ */
.tug-spec {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-lg) var(--space-md) var(--space-md);
  width: 100%;
  max-width: 860px;
  margin: 0 auto;
}

/* While spectating, the deck needs more width than the playing column allows
   and may run taller than the viewport — give it room and let it scroll. */
#screen-gameplay.tug-spectating .gameplay-inner {
  max-width: 920px;
  padding-left: var(--space-md);
  padding-right: var(--space-md);
  overflow-y: auto;
}

.tug-spec-leave-btn {
  position: absolute;
  top: var(--space-sm);
  right: var(--space-sm);
  z-index: 3;
}

/* Three balanced columns — Blue (left), LIVE (centre), Purple (right). The
   equal 1fr side columns keep LIVE centred and give each team room; names
   ellipsis and scores reserve digit space, so growing counters never overlap. */
.tug-spec-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-lg);
  /* clear the absolutely-positioned leave button on the right; pad the left
     to match so the LIVE badge stays centred */
  padding: var(--space-xs) 56px 0;
}

.tug-spec-team {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  min-width: 0;
}
.tug-spec-team--blue   { justify-self: start; }
.tug-spec-team--purple { justify-self: end; }

.tug-spec-team-name {
  font-weight: 700;
  font-size: 1.05rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.tug-spec-team--blue .tug-spec-team-name   { color: var(--tug-blue); }
.tug-spec-team--purple .tug-spec-team-name { color: var(--tug-purple); }

.tug-spec-score {
  font-size: 1.9rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  flex: none;
  min-width: 1.5ch;
}
.tug-spec-team--blue   .tug-spec-score { text-align: right; }
.tug-spec-team--purple .tug-spec-score { text-align: left; }

/* Narrow screens: a single row can't hold both teams + the centre badge, so
   stack — LIVE on its own top row, the two teams beneath (still left/right).
   Right padding clears the absolutely-positioned leave button. */
@media (max-width: 560px) {
  .tug-spec-header {
    /* two equal team halves filling the row, split by a fixed centre gutter so
       the scores can never meet; LIVE sits on its own row above. */
    grid-template-columns: minmax(0, 1fr) var(--space-md) minmax(0, 1fr);
    grid-template-areas:
      "live live   live"
      "blue .      purple";
    gap: var(--space-xs) 0;
    padding: var(--space-xs) 56px 0 var(--space-sm);
  }
  .tug-spec-live         { grid-area: live; justify-self: center; }
  /* fill the half-column (justify-self:stretch) so names ellipsis instead of
     overflowing; align each team's content toward its outer edge. */
  .tug-spec-team--blue   { grid-area: blue;   justify-self: stretch; }
  .tug-spec-team--purple { grid-area: purple; justify-self: stretch; justify-content: flex-end; }
  .tug-spec-score        { font-size: 1.5rem; }
  .tug-spec-team-name    { font-size: 0.95rem; }
}

.tug-spec-live {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-secondary);
  white-space: nowrap;
  flex: none;
}

.tug-spec-live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--error, #e05656);
  animation: tugCodePulse 1.4s ease-in-out infinite;
}

.tug-spec-watchers {
  font-weight: 500;
  letter-spacing: normal;
  color: var(--text-tertiary);
}

/* The deck's bar is the centrepiece — bigger than the topbar one */
.tug-spec-bar-wrap {
  height: 22px;
  border-radius: 11px;
  /* bat stands up from the bar → reserve room above, not below */
  margin-top: calc(var(--space-sm) + 120px);
  margin-bottom: var(--space-md);
}

/* ---- Momentum strip ---- */
.tug-spec-momentum {
  --pull: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  min-height: 1.6em;
}

.tug-spec-momentum-label {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text-secondary);
  min-width: 150px;
  text-align: center;
}

.tug-spec-momentum.pull-left  .tug-spec-momentum-label { color: var(--tug-blue); }
.tug-spec-momentum.pull-right .tug-spec-momentum-label { color: var(--tug-purple); }

.tug-spec-chevrons {
  display: inline-flex;
  gap: 3px;
  opacity: 0;
  transition: opacity 0.25s;
}

.tug-spec-chevrons i {
  width: 9px;
  height: 9px;
  border-top: 3px solid currentColor;
  border-left: 3px solid currentColor;
  border-radius: 1px;
}

.tug-spec-chevrons--left {
  color: var(--tug-blue);
}
.tug-spec-chevrons--left i {
  transform: rotate(-45deg);
  animation: tugChevMarchL 0.9s linear infinite;
}

.tug-spec-chevrons--right {
  color: var(--tug-purple);
}
.tug-spec-chevrons--right i {
  transform: rotate(135deg);
  animation: tugChevMarchR 0.9s linear infinite;
}

.tug-spec-chevrons--right i:nth-child(2), .tug-spec-chevrons--left i:nth-child(2) { animation-delay: 0.15s; }
.tug-spec-chevrons--right i:nth-child(3), .tug-spec-chevrons--left i:nth-child(3) { animation-delay: 0.3s; }

/* Chevron intensity follows |velocity| via --pull (set per frame) */
.tug-spec-momentum.pull-left  .tug-spec-chevrons--left,
.tug-spec-momentum.pull-right .tug-spec-chevrons--right {
  opacity: calc(0.35 + 0.65 * var(--pull));
}

@keyframes tugChevMarchL {
  0%, 100% { opacity: 0.25; }
  50%      { opacity: 1; }
}
@keyframes tugChevMarchR {
  0%, 100% { opacity: 0.25; }
  50%      { opacity: 1; }
}

/* Win banner on the deck */
.tug-spec-status {
  min-height: 1.4em;
  text-align: center;
  font-size: 1.2rem;
  font-weight: 800;
}

.tug-spec-status.win  { color: var(--tug-blue); }
.tug-spec-status.lose { color: var(--tug-purple); }

/* ---- Rosters + play-by-play ---- */
.tug-spec-panels {
  display: grid;
  grid-template-columns: 1fr 0.9fr 1fr;
  gap: var(--space-sm);
  align-items: start;
}

.tug-spec-roster,
.tug-spec-ticker-col {
  background: var(--bg-tertiary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-lg);
  padding: var(--space-sm);
}

.tug-spec-roster--blue   { border-top: 3px solid var(--tug-blue); }
.tug-spec-ticker-col     { border-top: 3px solid var(--border-medium); }
.tug-spec-roster--purple { border-top: 3px solid var(--tug-purple); }

.tug-spec-roster-title {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
  text-align: center;
  margin-bottom: var(--space-sm);
}

.tug-spec-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  max-height: 300px;
  overflow-y: auto;
}

.tug-spec-chip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  background: var(--bg-secondary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-md);
  padding: 5px 10px;
  font-size: 0.88rem;
}

.tug-spec-chip-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tug-spec-chip-count {
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
}

.tug-spec-chip.pulse {
  animation: tugChipPulse 0.6s ease-out;
}

@keyframes tugChipPulse {
  0%   { border-color: var(--success); box-shadow: 0 0 0 3px rgba(80, 200, 120, 0.25); }
  100% { border-color: var(--border-medium); box-shadow: 0 0 0 0 rgba(80, 200, 120, 0); }
}

.tug-spec-ticker {
  display: flex;
  flex-direction: column;
  gap: 5px;
  max-height: 300px;
  overflow: hidden;
}

.tug-spec-tick {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  padding: 3px 6px;
  border-radius: var(--radius-sm);
  animation: tugTickIn 0.25s ease-out;
}

@keyframes tugTickIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.tug-spec-tick-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
}

.tug-spec-tick--blue   .tug-spec-tick-dot { background: var(--tug-blue); }
.tug-spec-tick--purple .tug-spec-tick-dot { background: var(--tug-purple); }

.tug-spec-tick-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tug-spec-tick-pts {
  font-weight: 700;
  color: var(--success);
}

/* ---- Hidden player data: collapse to the bar + a team-only feed ---- */
#tug-spectator.hide-player-data .tug-spec-roster {
  display: none;
}

#tug-spectator.hide-player-data .tug-spec-panels {
  grid-template-columns: minmax(0, 360px);
  justify-content: center;
}

/* ---- Mobile ---- */
@media (max-width: 600px) {
  .tug-rule-cards {
    grid-template-columns: 1fr;
  }

  .tug-players-row {
    padding: 0 46px;
  }

  .tug-player-name {
    max-width: 80px;
    font-size: 0.85rem;
  }

  .tug-countdown-num {
    font-size: 5rem;
  }
  .tug-cd-side { font-size: 1.4rem; }
  .tug-cd-arrow { font-size: 1.3rem; }

  .tug-bat-indicator img { height: 190px; }

  .tug-bar-wrap {
    margin-top: calc(var(--space-md) + 72px);
    margin-bottom: var(--space-md);
  }

  /* Narrow screens: smart-rules children stack again */
  #tug-smart-options {
    grid-template-columns: 1fr;
    gap: 0;
  }

  /* …and the guest rules preview goes back to one column */
  #tug-lobby-settings-guest {
    grid-template-columns: 1fr;
  }

  /* Spectator deck stacks: bar stays on top, panels go single-column */
  .tug-spec-panels {
    grid-template-columns: 1fr;
  }

  .tug-spec-score {
    font-size: 1.4rem;
  }

  .tug-spec-bar-wrap {
    margin-top: calc(var(--space-sm) + 104px);
    margin-bottom: var(--space-md);
  }
}

/* ============================================================
   Tug of War results — Personal / Match / Session tabs
   ============================================================ */
.results-tabs {
  display: flex;
  gap: var(--space-xs);
  justify-content: center;
  max-width: 360px;
  margin: 0 auto var(--space-md);
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  padding: var(--space-xs);
}

.results-tab {
  flex: 1;
  padding: var(--space-sm) var(--space-md);
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.15s ease, color 0.15s ease;
}

.results-tab.active {
  background: var(--accent-primary);
  color: #fff;
}

@media (hover: hover) {
  .results-tab:hover:not(.active) { color: var(--text-primary); }
}

.results-empty {
  text-align: center;
  color: var(--text-secondary);
  padding: var(--space-lg) var(--space-md);
}

/* ---- Match graph (vertical, time-down) ---- */
.results-match { --c-blue: var(--tug-blue); --c-purple: var(--tug-purple); }

.tug-match-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: 520px;
  margin: 0 auto var(--space-sm);
  font-size: 0.85rem;
  font-weight: 700;
}
.tug-match-team.blue   { color: var(--c-blue); }
.tug-match-team.purple { color: var(--c-purple); }
.tug-match-axis-label {
  color: var(--text-secondary);
  font-weight: 600;
  font-size: 0.75rem;
}

.tug-match-svg {
  display: block;
  margin: 0 auto;
  height: min(58vh, 500px);
  width: auto;
  max-width: 100%;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
}

.tug-match-win.win-blue   { fill: var(--c-blue);   opacity: 0.07; }
.tug-match-win.win-purple { fill: var(--c-purple); opacity: 0.07; }

.tug-match-grid {
  stroke: var(--border-medium);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  opacity: 0.4;
}
.tug-match-time {
  fill: var(--text-secondary);
  font-size: 3px;
  font-family: inherit;
}
.tug-match-center {
  stroke: var(--text-secondary);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 2 2;
  opacity: 0.5;
}
/* Progress trail, drawn as per-segment polylines whose stroke colour + glow
   opacity are set inline (tied to how near the bat is to the win line). */
.tug-match-seg {
  fill: none;
  stroke-width: 1.8;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.tug-match-seg--glow { stroke-width: 4; }
.tug-mk { stroke: rgba(0, 0, 0, 0.25); stroke-width: 0.3; }
.tug-mk.mk-correct { fill: var(--success); }
.tug-mk.mk-wrong   { fill: var(--error); }

/* Finish-line markers at ±1 on the graph, team-coloured to match the
   live bar (blue left, purple right). */
.tug-match-winline {
  stroke-width: 1.4;
  vector-effect: non-scaling-stroke;
  opacity: 0.85;
}
.tug-match-winline--left  { stroke: var(--tug-blue); }
.tug-match-winline--right { stroke: var(--tug-purple); }

/* Sudden-death walls closing in over time; the bright edge is the win
   line sweeping inward (team-coloured to match the live marker). */
.tug-match-wall { opacity: 0.12; }
.tug-match-wall--left  { fill: var(--tug-blue); }
.tug-match-wall--right { fill: var(--tug-purple); }
.tug-match-wall-edge {
  fill: none;
  stroke-width: 1.4;
  vector-effect: non-scaling-stroke;
  opacity: 0.8;
}
.tug-match-wall-edge--left  { stroke: var(--tug-blue); }
.tug-match-wall-edge--right { stroke: var(--tug-purple); }

.tug-match-legend {
  display: flex;
  gap: var(--space-md);
  justify-content: center;
  margin-top: var(--space-sm);
  font-size: 0.8rem;
  color: var(--text-secondary);
}
.tug-match-legend .lg { display: inline-flex; align-items: center; gap: 6px; }
.tug-match-legend .dot {
  width: 10px; height: 10px; border-radius: 50%; display: inline-block;
}
.tug-match-legend .dot.mk-correct { background: var(--success); }
.tug-match-legend .dot.mk-wrong   { background: var(--error); }

/* ---- Session leaderboard ---- */
.tug-leaderboard-wrap { overflow-x: auto; }

.tug-leaderboard {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.tug-leaderboard th,
.tug-leaderboard td {
  padding: var(--space-sm) var(--space-sm);
  text-align: center;
  white-space: nowrap;
}
.tug-leaderboard th {
  color: var(--text-secondary);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border-medium);
}
.tug-leaderboard td { border-bottom: 1px solid var(--border-medium); }
.tug-leaderboard .lb-rank { width: 2rem; color: var(--text-secondary); }
.tug-leaderboard .lb-name { text-align: left; font-weight: 600; }
.tug-leaderboard .lb-wins { font-weight: 700; color: var(--accent-secondary); }
.tug-leaderboard .lb-op { font-weight: 700; }
.tug-leaderboard tbody tr:first-child .lb-rank { color: var(--accent-secondary); font-weight: 700; }

.lb-team-blue   .lb-name { color: var(--tug-blue); }
.lb-team-purple .lb-name { color: var(--tug-purple); }
