<template>
  <div class="leaderboard light">
    <div class="header glass light">
      <div class="header-row">
        <div class="header-left">
        <button class="btn-back" @click="goHome" title="Volver al inicio">
          ← <span class="label">Inicio</span>
        </button>
        <h1><GameLogo size="medium" /> Estadísticas</h1>
        </div>
        <div class="actions">
        <button class="btn-collapse" @click="filtersCollapsed = !filtersCollapsed" :title="filtersCollapsed ? 'Mostrar filtros' : 'Ocultar filtros'">
          <span class="collapse-icon" :class="{ rotated: filtersCollapsed }">▼</span>
          <span class="collapse-text">{{ filtersCollapsed ? 'Mostrar filtros' : 'Ocultar filtros' }}</span>
        </button>
        </div>
      </div>
      <div class="header-markers filters-indicators">
        <span class="marker-chip">
          <span class="key time"></span>
          {{ periodLabel }}
          <button class="chip-x" v-if="filterState.timeMode == 'range'" @click="clearTimeFilter" title="Borrar filtro de tiempo">×</button>
        </span>
        <span class="marker-chip" v-if="filterState.rounds.length">
          <span class="key round"></span>
          Ronda: {{ filterState.rounds.join(',') }}
          <button class="chip-x" @click="filterState.rounds = []">×</button>
        </span>
        <span class="marker-chip" v-if="filterState.games.length">
          <span class="key game"></span>
          Juego: {{ filterState.games.join(',') }}
          <button class="chip-x" @click="filterState.games = []">×</button>
        </span>
        <span class="marker-chip" v-if="filterState.playerUuids.length" >
          <span class="key player"></span>
          Jugadores: {{ filterState.playerUuids.length }}
          <button class="chip-x" @click="filterState.playerUuids = []" title="Quitar selección de jugadores">×</button>
        </span>
      </div>
    </div>
  

  <div>
    
    <Transition name="filters-slide">
      <div v-if="!filtersCollapsed" class="controls glass light">
        <!-- EventFilters component with v-model -->
        <EventFilters 
          v-model="filterState"
          :raw-data="{
            players: allPlayersWithScores,
            aggregatedEvents: fullAggregatedEvents,
            activeRooms: rawActionsPayload?.activeRooms
          }"
          :compact="true"
          @filtered="onFiltered"
        />
        
        <!-- Room slice UI removida: reemplazada por rango de tiempo/activas -->
      </div>
    </Transition>
  </div>


    <EventChart 
      :event-types="ALL_CHART_TYPES"
      :event-styles="EVENT_STYLES"
      :global-event-counts="combinedGlobalCounts"
      :player-event-counts="combinedPlayerCounts"
      :selected-player-uuid="filterState.playerUuids.length ? filterState.playerUuids[0] : ''"
      :player-bar-gradient="playerBarGradient"
      view-mode="ratio"
      :loading="loading"
      :filters-collapsed="filtersCollapsed"
      :active-filters="activeFilters"
      :group-totals="{
        offers: offersTotal,
        responses: responsesTotal,
        force: forceTotal,
        shame: shameTotal,
        report: reportTotal,
        averageScore: averageScoreTotal,
        totalPlayers: totalPlayersCount
      }"
    />
    
    <AppCredits position="bottom-right" />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
import { useRouter } from 'vue-router';
import EventChart from '../components/EventChart.vue';
import EventFilters from '../components/EventFilters.vue';
import GameLogo from '../components/GameLogo.vue';
import AppCredits from '../components/AppCredits.vue';
import { useEventFilters } from '../composables/useEventFilters';


const router = useRouter();
const loading = ref(false);
const eventFilters = useEventFilters();
const filtersCollapsed = ref(false);

// Filter state using new EventFilters approach
const filterState = ref({
  timeMode: 'range' as 'active' | 'range',
  rangeFrom: '',
  rangeTo: '',
  liveEnd: true,
  rounds: [] as number[],
  games: [] as string[],
  playerUuids: [] as string[],
  rooms: [] as string[]
});

const fullAggregatedEvents = ref<Array<{ kind: string; round?: number; gameVariant?: string; roomId?: string; playerUuid?: string; timestamp?: number }>>([]);
const filteredData = ref<any>(null);

// Clear time filter - switch to active rooms mode
function clearTimeFilter() {
  filterState.value.timeMode = 'active';
}

// Handle filtered data from EventFilters component
function onFiltered(data: any) {
  filteredData.value = data;
  if (data) {
    // Update global counts from filtered data
    eventFilters.globalEventCounts.value = data.aggregatedCounts || {};
    // Update metrics
    additionalMetrics.value = data.metrics || {};
    // Recompute selected player metrics
    computeSelectedPlayersMetrics();
  }
}


const EVENTS = [
  'p1_propose', 'p1_no_offer',
  'p2_snatch', 'p2_accept', 'p2_force', 'p2_no_force', 'p2_reject',
  'p1_shame', 'p1_no_shame', 'p1_report', 'p1_no_report'
];

// New metric types for additional charts
const METRICS = [
  'players_seated', 'score_p1', 'score_p2', 'players_with_shame', 'players_without_shame'
];

const ALL_CHART_TYPES = [...EVENTS, ...METRICS];

// Event and metric styles matching OfferActions and OfferControls components
const EVENT_STYLES: Record<string, { icon: string; color: string; gradient: string }> = {
  // Event types
  'p1_propose': { icon: '✨', color: '#667eea', gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' },
  'p1_no_offer': { icon: '❌', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
  'p2_accept': { icon: '✓', color: '#10b981', gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)' },
  'p2_reject': { icon: '✕', color: '#f59e0b', gradient: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)' },
  'p2_snatch': { icon: '👹', color: '#ef4444', gradient: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)' },
  'p2_force': { icon: '⚡', color: '#667eea', gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' },
  'p2_no_force': { icon: '🚫', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
  'p1_shame': { icon: '😶', color: '#fbbf24', gradient: 'linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%)' },
  'p1_no_shame': { icon: '🙂', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
  'p1_report': { icon: '⚖️', color: '#8b5cf6', gradient: 'linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%)' },
  'p1_no_report': { icon: '🤝', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
  
  // Metric types
  'players_seated': { icon: '👥', color: '#06b6d4', gradient: 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)' },
  'score_p1': { icon: '🦃', color: '#16a34a', gradient: 'linear-gradient(135deg, #16a34a 0%, #15803d 100%)' },
  'score_p2': { icon: '🌽', color: '#d97706', gradient: 'linear-gradient(135deg, #d97706 0%, #b45309 100%)' },
  'players_with_shame': { icon: '😶', color: '#dc2626', gradient: 'linear-gradient(135deg, #dc2626 0%, #b91c1c 100%)' },
  'players_without_shame': { icon: '👥', color: '#06b6d4', gradient: 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)' }
};


// Additional metrics computation
const additionalMetrics = ref<Record<string, number>>({
  players_seated: 0,
  score_p1: 0,
  score_p2: 0,
  players_with_shame: 0,
  players_without_shame: 0
});

const selectedPlayerMetrics = ref<Record<string, number>>({
  players_seated: 0,
  score_p1: 0,
  score_p2: 0,
  players_with_shame: 0,
  players_without_shame: 0
});

// Store room score history from players
const allPlayersWithScores = ref<any[]>([]);

// Function to check if a score passes the current filters
function scorePassesFilters(score: any, roomId: string) {
  // Room filter (array): empty means all
  const rf = filterState.value.rooms;
  if (rf.length && !rf.includes(String(roomId))) return false;

  // Round filter (array)
  const rds = filterState.value.rounds;
  if (rds.length && !rds.includes(Number(score.round))) return false;

  // Game variant filter (array)
  const gfs = filterState.value.games;
  if (gfs.length && !gfs.includes(String(score.variant))) return false;

  return true;
}

// Function to compute additional metrics from players' score history
function computeMetricsFromScores() {
  if (!allPlayersWithScores.value.length) return;
  
  let totalP1Scores = 0;
  let totalP2Scores = 0;
  let p1Count = 0;
  let p2Count = 0;
  let playersWithShame = 0;
  let totalPlayersWithNames = 0;

  // Get score data from players with room score history
  allPlayersWithScores.value.forEach((player: any) => {
    if (player.name) {
      totalPlayersWithNames++;
      
      // Count players with shame tokens
      if (player.shameTokens && player.shameTokens > 0) {
        playersWithShame++;
      }
      
      // Extract scores from roomScoreHistory if available
      if (player.roomScoreHistory) {
        player.roomScoreHistory.forEach((roomScore: any) => {
          roomScore.scores.forEach((score: any) => {
            // Apply filters to scores
            if (!scorePassesFilters(score, roomScore.roomId)) {
              return;
            }
            
            if (score.role === 'P1') {
              totalP1Scores += score.score;
              p1Count++;
            } else if (score.role === 'P2') {
              totalP2Scores += score.score;
              p2Count++;
            }
          });
        });
      }
    }
  });

  const avgP1Score = p1Count > 0 ? totalP1Scores / p1Count : 0;
  const avgP2Score = p2Count > 0 ? totalP2Scores / p2Count : 0;
  
  additionalMetrics.value = {
    players_seated: totalPlayersWithNames,
    score_p1: Math.round(avgP1Score * 10) / 10, // Round to 1 decimal
    score_p2: Math.round(avgP2Score * 10) / 10,
    players_with_shame: playersWithShame,
    players_without_shame: totalPlayersWithNames - playersWithShame
  };
}

// Function to compute metrics for selected players (multi-select)
function computeSelectedPlayersMetrics() {
  const uuids = filterState.value.playerUuids;
  if (!uuids.length) {
    selectedPlayerMetrics.value = {
      players_seated: 0,
      score_p1: 0,
      score_p2: 0,
      players_with_shame: 0,
      players_without_shame: 0
    };
    return;
  }

  let totalP1Scores = 0;
  let totalP2Scores = 0;
  let p1Count = 0;
  let p2Count = 0;
  let playersWithShame = 0;

  uuids.forEach(uuid => {
    const playerData = allPlayersWithScores.value.find(p => p.uuid === uuid);
    if (!playerData) return;
    if (playerData.shameTokens && playerData.shameTokens > 0) playersWithShame++;
    if (playerData.roomScoreHistory) {
      playerData.roomScoreHistory.forEach((roomScore: any) => {
        roomScore.scores.forEach((score: any) => {
          if (!scorePassesFilters(score, roomScore.roomId)) return;
          if (score.role === 'P1') { totalP1Scores += score.score; p1Count++; }
          else if (score.role === 'P2') { totalP2Scores += score.score; p2Count++; }
        });
      });
    }
  });

  selectedPlayerMetrics.value = {
    players_seated: uuids.length,
    score_p1: p1Count > 0 ? Math.round((totalP1Scores / p1Count) * 10) / 10 : 0,
    score_p2: p2Count > 0 ? Math.round((totalP2Scores / p2Count) * 10) / 10 : 0,
    players_with_shame: playersWithShame,
    players_without_shame: uuids.length - playersWithShame
  };
}

// Combined counts for charts (events + metrics)
const combinedGlobalCounts = computed(() => ({
  ...eventFilters.globalEventCounts.value,
  ...additionalMetrics.value
}));

const combinedPlayerCounts = computed(() => ({
  ...playerEventCounts.value,
  ...selectedPlayerMetrics.value
}));


// Chart group totals
const offersTotal = computed(() => {
  const propose = eventFilters.globalEventCounts.value.p1_propose || 0;
  const noOffer = eventFilters.globalEventCounts.value.p1_no_offer || 0;
  return propose + noOffer;
});

const responsesTotal = computed(() => {
  const accept = eventFilters.globalEventCounts.value.p2_accept || 0;
  const reject = eventFilters.globalEventCounts.value.p2_reject || 0;
  const snatch = eventFilters.globalEventCounts.value.p2_snatch || 0;
  return accept + reject + snatch;
});

const forceTotal = computed(() => {
  const force = eventFilters.globalEventCounts.value.p2_force || 0;
  const noForce = eventFilters.globalEventCounts.value.p2_no_force || 0;
  return force + noForce;
});

const shameTotal = computed(() => {
  const shame = eventFilters.globalEventCounts.value.p1_shame || 0;
  const noShame = eventFilters.globalEventCounts.value.p1_no_shame || 0;
  return shame + noShame;
});

const reportTotal = computed(() => {
  const report = eventFilters.globalEventCounts.value.p1_report || 0;
  const noReport = eventFilters.globalEventCounts.value.p1_no_report || 0;
  return report + noReport;
});

const averageScoreTotal = computed(() => {
  if (!allPlayersWithScores.value.length) return 0;
  
  let totalScores = 0;
  let totalScoreCount = 0;

  // Sum all individual scores from all players regardless of role, applying filters
  allPlayersWithScores.value.forEach((player: any) => {
    if (player.roomScoreHistory) {
      player.roomScoreHistory.forEach((roomScore: any) => {
        roomScore.scores.forEach((score: any) => {
          // Apply filters to scores
          if (!scorePassesFilters(score, roomScore.roomId)) {
            return;
          }
          
          totalScores += score.score;
          totalScoreCount++;
        });
      });
    }
  });

  return totalScoreCount > 0 ? Math.round((totalScores / totalScoreCount) * 10) / 10 : 0;
});

const totalPlayersCount = computed(() => {
  return additionalMetrics.value.players_seated || 0;
});

// Active filters object
const activeFilters = computed(() => ({
  dataSource: filterState.value.timeMode === 'active' ? 'active-rooms' : 'aggregated',
  round: filterState.value.rounds.join(',') || 'all',
  game: filterState.value.games.join(',') || 'all',
  hasFilters: filterState.value.rounds.length > 0 || filterState.value.games.length > 0 || filterState.value.playerUuids.length > 0,
  selectedPlayer: filterState.value.playerUuids.length ? `${filterState.value.playerUuids.length} jugadores` : undefined,
  selectedRoom: filterState.value.rooms.length ? `${filterState.value.rooms.length} salas` : undefined
}));

// Watch for changes in filter state to update selected player metrics
watch(filterState, () => {
  computeSelectedPlayersMetrics();
}, { deep: true });

const availableRooms = ref<{ roomId: string; name: string; playerCount?: number }[]>([]);
const playerLoading = ref(false);
const playerEventCounts = ref<Record<string, number>>((Object.fromEntries(EVENTS.map(k => [k, 0])) as Record<string, number>));
const playersActionsByUuid = ref<Record<string, Record<string, number>>>({});




function goHome() {
  router.push('/');
}


// Dynamic per-player overlay bar gradient and label color
const playerBarGradient = computed(() => '#8b5cf6');



const apiBase = (import.meta as any).env?.VITE_API_URL || `${window.location.protocol}//${window.location.host}/api`;
const esActions = ref<EventSource|null>(null);
const rawActionsPayload = ref<any>(null);

// Indicator labels
const periodLabel = computed(() => {
  if (filterState.value.timeMode === 'active') return 'Salas activas';
  const from = (filterState.value.rangeFrom || '').replace('T', ' ');
  const to = (filterState.value.rangeTo || '').replace('T', ' ');
  return `${from} → ${to}${filterState.value.liveEnd ? ' (ahora)' : ''}`;
});




function closeStreams() {
  try { esActions.value?.close(); } catch {}
  esActions.value = null;
}

function setupStreams() {
  loading.value = true;
  closeStreams();

  // Único stream: players-actions-stream
  esActions.value = new EventSource(`${apiBase}/players-actions-stream`);
  esActions.value.onmessage = (e) => {
    try {
      const data = JSON.parse((e as MessageEvent).data || '{}');
      rawActionsPayload.value = data;

      const list = Array.isArray(data?.players) ? data.players : [];
      allPlayersWithScores.value = list;

      // Construir mapa de colores desde snapshot de salas activas (si está)
      const colorMap = new Map<string, string|undefined>();
      const activeRooms = data?.activeRooms?.rooms || [];
      activeRooms.forEach((r: any) => {
        (Array.isArray(r?.players) ? r.players : []).forEach((p: any) => {
          const uuid = String(p?.uuid || '');
          if (uuid && !colorMap.has(uuid)) colorMap.set(uuid, p?.color || undefined);
        });
      });


      // Mapear counts por jugador
      const byUuid: Record<string, Record<string, number>> = {};
      list.forEach((p: any) => {
        const uuid = String(p?.uuid || '');
        if (!uuid) return;
        const src = p?.counts || {};
        const normalized: Record<string, number> = Object.fromEntries(EVENTS.map(k => [k, 0])) as any;
        EVENTS.forEach(k => { normalized[k] = Number(src[k] || 0); });
        byUuid[uuid] = normalized;
      });
      playersActionsByUuid.value = byUuid;

      // Store aggregated events for the EventFilters component
      const aggEvents = Array.isArray(data?.aggregated?.detailedEvents) ? data.aggregated.detailedEvents : [];
      fullAggregatedEvents.value = aggEvents as any;


      // Construir listado de salas desde aggregated.rooms si está, si no derivar de eventos
      const roomsList = Array.isArray(data?.aggregated?.rooms) ? data.aggregated.rooms : null;
      if (roomsList) {
        availableRooms.value = roomsList
          .slice()
          .sort((a: any, b: any) => (a?.lastSeenIndex || 0) - (b?.lastSeenIndex || 0))
          .map((r: any) => ({
            roomId: String(r?.roomId || ''),
            name: `Sala ${String(r?.roomId || '').slice(0, 8)}`,
            playerCount: Number(r?.messageCount || 0)
          }))
          .filter((r: any) => !!r.roomId);
      } else {
        const lastSeenIndex: Record<string, number> = {};
        const ids = new Set<string>();
        aggEvents.forEach((ev: any, i: number) => {
          const rid = String(ev?.roomId || '').trim();
          if (!rid) return;
          ids.add(rid);
          lastSeenIndex[rid] = i;
        });
        availableRooms.value = Array.from(ids).map(rid => ({
          roomId: rid,
          name: `Sala ${rid.slice(0, 8)}`,
          playerCount: aggEvents.filter((e: any) => e?.roomId === rid).length,
          _lastSeen: lastSeenIndex[rid] ?? -1
        })).sort((a: any, b: any) => (a._lastSeen - b._lastSeen)).map(({ _lastSeen, ...rest }: any) => rest);
      }

      // Recalculate metrics from score history
      computeMetricsFromScores();

      // Actualizar conteos del/los jugador(es) seleccionado(s)
      updateSelectedPlayersCounts();

    } finally {
      loading.value = false;
    }
  };
  esActions.value.onerror = () => {};
}





function updateSelectedPlayersCounts() {
  playerLoading.value = true;
  const next: Record<string, number> = Object.fromEntries(EVENTS.map(k => [k, 0])) as any;
  const byUuid = playersActionsByUuid.value;
  filterState.value.playerUuids.forEach(uuid => {
    const counts = byUuid[uuid] || {};
    EVENTS.forEach(k => { next[k] = (next[k] || 0) + Number(counts[k] || 0); });
  });
  playerEventCounts.value = next as any;
  playerLoading.value = false;
}


onMounted(() => {
  setupStreams();
  // Initialize with aggregated data as default
  eventFilters.globalEventCounts.value = { ...eventFilters.globalEventCountsAggregated.value };
  
  // Initialize default time range for filter state
  const now = new Date();
  const from = new Date(now.getTime() - 60 * 60 * 1000); // 1h ago
  const pad = (n: number) => String(n).padStart(2, '0');
  const formatLocal = (dt: Date) => {
    const y = dt.getFullYear();
    const m = pad(dt.getMonth() + 1);
    const d = pad(dt.getDate());
    const hh = pad(dt.getHours());
    const mm = pad(dt.getMinutes());
    return `${y}-${m}-${d}T${hh}:${mm}`;
  };
  filterState.value.rangeFrom = formatLocal(from);
  filterState.value.rangeTo = formatLocal(now);
});

onUnmounted(() => {
  closeStreams();
});


// Removed totals table and sorting; keep actions stream for per-player counts only
// Deprecated: previously used to show a totals list; now unused
// const allPlayersActions = ref<{ uuid: string; name: string; total: number }[]>([]);



</script>

<style scoped>
/* Light theme aligned with other pages (UUID selector, lobby, game) */
.leaderboard.light { min-height: 100vh; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color:#0f172a; display:flex; flex-direction:column; }

.glass.light { background: rgba(255, 255, 255, 0.92); border: 1px solid rgba(229, 231, 235, 0.95); box-shadow: 0 18px 50px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.75); backdrop-filter: blur(18px) saturate(120%); -webkit-backdrop-filter: blur(18px) saturate(120%); border-radius: 16px; }

.header { display:flex; flex-direction: column; gap: 6px; padding: 8px 10px; margin-bottom: 10px; }
.header-row { display:flex; align-items:center; justify-content:space-between; gap: 8px; flex-wrap: nowrap; }
.header h1 { margin: 0; font-size: 18px; line-height: 1.2; flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 8px; }
.header-left { display:flex; align-items:center; gap: 10px; flex: 1 1 auto; min-width: 0; }
.btn-back { background:#667eea; color:#fff; border:none; border-radius:6px; padding:6px 10px; font-weight:600; cursor:pointer; transition: all 0.3s ease; font-size: 12px; }
.btn-back:hover { background:#5b6bda; transform: translateY(-1px); box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); }
.actions { display:flex; gap: 6px; flex-wrap: nowrap; align-items: center; justify-content: flex-end; flex: 0 0 auto; }
.actions .btn { background:#667eea; color:#fff; border:none; border-radius:6px; padding:4px 8px; font-weight:800; font-size: 11px; cursor:pointer; }
.actions .btn.toggle { background:#eef2ff; color:#3949ab; border:1px solid #c7d2fe; }
.actions .btn.toggle.active { background:#3949ab; color:#fff; border-color:#2e3f9a; }

.controls { display:grid; grid-template-columns: 1fr; gap: 10px; padding: 10px 12px; margin-bottom: 14px; }
.divider { border: 0; border-top: 1px solid rgba(203,213,225,0.6); margin: 6px 0; }
.legend { font-size: 13px; color:#334155; display:flex; align-items:center; gap:10px; }
.key { width: 12px; height: 12px; border-radius: 999px; display:inline-block; }
.key.global { background: linear-gradient(90deg, #34d399, #10b981); box-shadow: 0 0 8px rgba(16,185,129,0.35); }
.key.player { background: linear-gradient(90deg, #a78bfa, #6366f1); box-shadow: 0 0 8px rgba(99,102,241,0.35); }
.key.room { background: linear-gradient(90deg, #f59e0b, #d97706); box-shadow: 0 0 8px rgba(245,158,11,0.35); }
.key.round { background: linear-gradient(90deg, #06b6d4, #0891b2); box-shadow: 0 0 8px rgba(8,145,178,0.35); }
.key.game { background: linear-gradient(90deg, #ec4899, #8b5cf6); box-shadow: 0 0 8px rgba(236,72,153,0.35); }
.sep { opacity: 0.6; }

.player-chips, .room-chips { 
  display: flex; 
  flex-direction: column;
  gap: 12px;
}

.room-chips {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid rgba(203, 213, 225, 0.5);
}

/* Room slice controls */
.room-slice { margin-top: 10px; padding-top: 12px; border-top: 1px solid rgba(203,213,225,0.5); display: flex; flex-direction: column; gap: 10px; }
.slice-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.slice-info { display: flex; align-items: center; gap: 10px; color: #334155; font-weight: 600; }
.slice-summary { color: #475569; font-weight: 700; }

/* Dual range slider */
.dual-slider { position: relative; height: 36px; padding: 16px 8px; }
.dual-slider .track { position: absolute; left: 8px; right: 8px; top: 50%; height: 8px; transform: translateY(-50%); border-radius: 999px; background: linear-gradient(135deg, #e2e8f0 0%, #cbd5e1 100%); box-shadow: inset 0 1px 2px rgba(0,0,0,0.06); }
.dual-slider .highlight { position: absolute; top: 50%; height: 8px; transform: translateY(-50%); border-radius: 999px; background: linear-gradient(90deg, #06b6d4, #8b5cf6); box-shadow: 0 2px 8px rgba(139,92,246,0.25); }
.dual-slider .range { -webkit-appearance: none; appearance: none; position: absolute; left: 0; right: 0; top: 0; bottom: 0; background: transparent; pointer-events: none; }
.dual-slider .range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 22px; height: 22px; background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%); border: 2px solid #8b5cf6; border-radius: 50%; box-shadow: 0 4px 12px rgba(139,92,246,0.3); pointer-events: auto; cursor: pointer; }
.dual-slider .range::-moz-range-thumb { width: 22px; height: 22px; background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%); border: 2px solid #8b5cf6; border-radius: 50%; box-shadow: 0 4px 12px rgba(139,92,246,0.3); pointer-events: auto; cursor: pointer; }
.dual-slider .range::-ms-thumb { width: 22px; height: 22px; background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%); border: 2px solid #8b5cf6; border-radius: 50%; box-shadow: 0 4px 12px rgba(139,92,246,0.3); pointer-events: auto; cursor: pointer; }
.dual-slider .range.start { z-index: 2; }
.dual-slider .range.end { z-index: 3; }


@media (max-width: 640px) {
  .dual-slider { height: 32px; padding: 14px 6px; }
  .dual-slider .track, .dual-slider .highlight { height: 6px; }
  .dual-slider .range::-webkit-slider-thumb, .dual-slider .range::-moz-range-thumb { width: 18px; height: 18px; }
}

.search-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  justify-content: start;
  flex-wrap: wrap;
}

.search { 
  padding: 8px 10px; 
  border: 1px solid #cbd5e1; 
  background: #fff; 
  color: #0f172a; 
  border-radius: 10px; 
  min-width: 240px; 
  outline: none; 
  flex: 1;
  max-width: 300px;
}

.search::placeholder { 
  color: #64748b; 
}

.chips { 
  display: flex; 
  gap: 10px; 
  flex-wrap: wrap; 
  align-items: center;
}
.player-chips.compact .search { padding: 6px 8px; min-width: 180px; font-size: 12px; }
.player-chips.compact .chip { padding: 6px 10px; font-size: 12px; }
.player-chips.compact .avatar { width: 20px; height: 20px; font-size: 12px; }
.player-chips.compact .pagination.compact { padding: 3px 6px; }
.filters-indicators .chip-x { background: transparent; border: none; color: #64748b; margin-left: 6px; cursor: pointer; font-weight: 900; }
.secondary-filters { margin: 6px 0 4px; }
.chip { display:flex; align-items:center; gap:8px; background: color-mix(in srgb, var(--primary) 6%, white); border:1px solid color-mix(in srgb, var(--primary) 24%, #e5e7eb); padding:8px 12px; border-radius: 999px; color:#111827; cursor:pointer; transition: transform .18s ease, background .18s ease, box-shadow .18s ease; }
.chip:hover { transform: translateY(-1px); background: color-mix(in srgb, var(--primary) 10%, white); box-shadow: 0 6px 18px rgba(102,126,234,0.18); }
.chip.active { background: color-mix(in srgb, var(--primary) 18%, white); border-color: color-mix(in srgb, var(--primary) 45%, #c7d2fe); box-shadow: 0 6px 22px rgba(99,102,241,0.22); }
.chip.clear { background:#fff; border-style:dashed; color:#334155; }
.chip.room-chip { --primary: #f59e0b; }
.chip.room-chip .count { 
  background: color-mix(in srgb, var(--primary) 20%, white); 
  color: color-mix(in srgb, var(--primary) 80%, #111); 
  font-size: 11px; 
  font-weight: 800; 
  padding: 2px 6px; 
  border-radius: 10px; 
  margin-left: 4px; 
}
.avatar { width: 24px; height: 24px; border-radius: 50%; background: color-mix(in srgb, var(--primary) 25%, #eef2ff); display:grid; place-items:center; font-weight:900; color: color-mix(in srgb, var(--primary) 80%, #111); }



/* Pagination styles */
.pagination {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: rgba(255,255,255,0.82);
  border: 1px solid rgba(229,231,235,0.9);
  border-radius: 999px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.08), inset 0 1px 0 rgba(255,255,255,0.6);
  backdrop-filter: blur(10px) saturate(120%);
  -webkit-backdrop-filter: blur(10px) saturate(120%);
}

.pagination.compact {
  gap: 6px;
  padding: 4px 8px;
}

.pg-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid #cbd5e1;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  font-weight: 900;
  font-size: 16px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
  box-shadow: 0 4px 12px rgba(102,126,234,0.25);
}

.pg-btn.compact {
  width: 24px;
  height: 24px;
  font-size: 14px;
  font-weight: 800;
  box-shadow: 0 2px 8px rgba(102,126,234,0.2);
}

.pg-btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(102,126,234,0.35);
}

.pg-btn.compact:hover:not(:disabled) {
  box-shadow: 0 4px 12px rgba(102,126,234,0.3);
}

.pg-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: #e5e7eb;
  color: #94a3b8;
  box-shadow: none;
}

.pg-ind {
  font-weight: 600;
  color: #334155;
  font-size: 12px;
  min-width: 35px;
  text-align: center;
}

/* Compact filter indicators */
.filters-indicators { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; padding: 4px 0; margin: 6px 0 0; }
.marker-chip { display: inline-flex; align-items: center; gap: 6px; padding: 2px 4px; border-radius: 999px; border: none; background: transparent; color: #334155; font-size: 12px; font-weight: 700; }
.marker-chip.clickable { cursor: pointer; }


/* Time indicator key */
.key.time { background: linear-gradient(90deg, #f59e0b, #d97706); box-shadow: 0 0 8px rgba(245,158,11,0.35); }


/* Filters section styles */
.filters-section {
  transition: all 0.3s ease;
}

.btn-collapse { 
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 8px;
  border: none;
  border-radius: 6px;
  background: #eef2ff;
  color: #3949ab;
  border: 1px solid #c7d2fe;
  font-weight: 800;
  font-size: 11px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.btn-collapse:hover {
  background: rgba(255,255,255,0.9);
  border-color: #cbd5e1;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}

.collapse-icon { transition: transform 0.3s ease; font-size: 11px; }

.collapse-icon.rotated {
  transform: rotate(-90deg);
}

.filters-content {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Transition for filters */
.filters-slide-enter-active,
.filters-slide-leave-active {
  transition: all 0.3s ease;
  overflow: hidden;
}

.filters-slide-enter-from,
.filters-slide-leave-to {
  opacity: 0;
  max-height: 0;
  transform: translateY(-20px);
}

.filters-slide-enter-to,
.filters-slide-leave-from {
  opacity: 1;
  max-height: 200px;
  transform: translateY(0);
}

@media (max-width: 768px) {
  .header { padding: 6px 8px; margin-bottom: 8px; }
  .header h1 { font-size: 16px; }
  .btn-back { padding: 5px 8px; font-size: 11px; border-radius: 6px; }
  .actions { gap: 6px; flex-wrap: nowrap; }
  .actions .btn { padding: 4px 6px; font-size: 10px; border-radius: 5px; }
  .header-row { flex-wrap: nowrap; }

  
  .search {
    min-width: auto;
    max-width: none;
  }
  
  .pagination.compact {
    align-self: center;
  }
}

@media (max-width: 640px) {
  .header { gap: 4px; }
  .header-row { flex-wrap: nowrap; }
  .header-left { min-width: 120px; }
  .actions { justify-content: flex-start; flex-wrap: nowrap; }
  .btn-collapse .collapse-text {
    display: none;
  }
  
  .btn-collapse {
    padding: 4px 6px;
    min-width: 34px;
    justify-content: center;
    font-size: 10px;
    border-radius: 5px;
  }
}

@media (max-width: 480px) {
  .header h1 { font-size: 14px; }
  .btn-back { padding: 4px 6px; font-size: 10px; }
  .actions { gap: 4px; }
  .actions .btn { padding: 3px 5px; font-size: 9px; border-radius: 4px; }
  .btn-collapse { padding: 3px 5px; min-width: 30px; font-size: 9px; border-radius: 4px; }
  /* Ultra-compact: single-line header on very small screens */
  .header { flex-wrap: nowrap; padding: 4px 6px; }
  .header-left { flex: 0 1 auto; }
  .btn-back .label { display: none; }
  .actions .btn .label { display: none; }
  .header h1 { font-size: 13px; }
  .header h1 .emoji { display: none; }
  .player-chips {
    gap: 8px;
  }
  
  .chips {
    gap: 8px;
    justify-content: center;
  }
  
  .chip {
    padding: 6px 10px;
  }
  
  .pg-btn.compact {
    width: 20px;
    height: 20px;
    font-size: 12px;
  }
  
  .pg-ind {
    font-size: 11px;
    min-width: 30px;
  }
}

</style>
