<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { useScheduleStore } from '@/stores/schedule'
import { useRouteStore } from '@/stores/route'
import { formatTo12Hour } from '@/utils/timeFormatter'
import { analyticsService } from '@/services/analyticsService'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import LoadingBranded from '@/components/common/LoadingBranded.vue'

const route = useRoute()
const { t } = useI18n()
const scheduleStore = useScheduleStore()
const routeStore = useRouteStore()

const dropdownOpen = ref(false)
const dayFilter = ref<'all' | 'today' | 'tomorrow'>('today')

// SIB | Estado local para independizar el selector de horarios del mapa
const localSelectedRouteId = ref<string | null>(null)
const localSelectedRouteName = ref<string | null>(null)
const hasLocalSelection = computed(() => localSelectedRouteId.value !== null)

// ── Tipos de día
const DAY_TYPES: Record<string, string> = {
  'weekday':  t('schedules.types.weekday'),
  'weekend':  t('schedules.types.weekend'),
  'holiday':  t('schedules.types.holiday'),
}

// ── Calcular estado del bus según horario
function getBusStatus(timeStr: string): 'departing' | 'ontime' | 'upcoming' | 'passed' {
  if (!timeStr) return 'upcoming'
  const now = new Date()
  const [h, m] = timeStr.split(':').map(Number)
  const schedDate = new Date()
  schedDate.setHours(h || 0, m || 0, 0, 0)
  
  const diffMin = (schedDate.getTime() - now.getTime()) / 60000

  // Si el bus ya pasó (más de 2 minutos de margen de gracia)
  if (diffMin < -2) return 'passed'
  
  if (diffMin >= -2 && diffMin <= 10) return 'departing'
  if (diffMin > 10 && diffMin <= 60) return 'ontime'
  return 'upcoming'
}

// ── Calcular si el horario es "hoy" o "mañana" según tipo de día
// ── Calcular si el horario es "hoy" o "mañana" según tipo de día
function getScheduleDay(schedule: any): 'today' | 'tomorrow' | 'other' {
  const now = new Date()
  const tomorrow = new Date(now)
  tomorrow.setDate(now.getDate() + 1)

  const getDayType = (date: Date) => {
    const dow = date.getDay() // 0=Dom, 6=Sab
    return (dow === 0 || dow === 6) ? 'weekend' : 'weekday'
  }

  const todayType = getDayType(now)
  const tomorrowType = getDayType(tomorrow)

  // Comparar con el tipo del horario
  // Nota: Si el horario es 'todos', cuenta para hoy y mañana (pero priorizamos hoy si pides hoy)
  const type = (schedule.schedule_type as string) || 'todos'
  
  const isToday = type === todayType || type === 'todos'
  const isTomorrow = type === tomorrowType || type === 'todos'

  if (isToday) return 'today'
  if (isTomorrow) return 'tomorrow'
  if (type === 'holiday') return 'other'
  
  return 'other'
}

function getDayLabel(schedule: any): string {
  const type = schedule.schedule_type || 'todos'
  const now = new Date()
  const todayType = (now.getDay() === 0 || now.getDay() === 6) ? 'weekend' : 'weekday'
  
  if (type === 'todos') return t('coupons.active') // Or add "Daily" to JSON
  if (type === todayType) return t('schedules.today') || 'Hoy'
  return t('schedules.tomorrow') || 'Mañana'
}

// ── Filtrado de horarios
const filteredSchedules = computed(() => {
  const now = new Date()
  const tomorrow = new Date(now)
  tomorrow.setDate(now.getDate() + 1)
  
  const hhmmAhora = now.getHours() * 100 + now.getMinutes()

  return scheduleStore.schedules.filter(s => {
    const type = (s.schedule_type as string) || 'todos'
    const todayType = (now.getDay() === 0 || now.getDay() === 6) ? 'weekend' : 'weekday'
    const tomorrowType = (tomorrow.getDay() === 0 || tomorrow.getDay() === 6) ? 'weekend' : 'weekday'
    
    const isActuallyToday = type === todayType || type === 'todos'
    const isActuallyTomorrow = type === tomorrowType || type === 'todos'

    // Filtro Hoy: Es hoy Y no ha pasado (o es de los que dice salir en este rango)
    if (dayFilter.value === 'today') {
      const [hStr, mStr] = (s.departure_time || '00:00').split(':')
      const h = parseInt(hStr || '0')
      const m = parseInt(mStr || '0')
      const hhmmSched = h * 100 + m
      const isPassed = hhmmSched < hhmmAhora - 2 // margen de 2 min
      return isActuallyToday && !isPassed
    }

    // Filtro Mañana: Es mañana (sin importar si pasó la hora hoy)
    if (dayFilter.value === 'tomorrow') {
      return isActuallyTomorrow
    }

    // Filtro Todos: Mostrar todo
    return true
  }).sort((a, b) => (a.departure_time || '').localeCompare(b.departure_time || ''))
})

// ── Seleccionar ruta
function pickRoute(id: string, name: string) {
  dropdownOpen.value = false
  analyticsService.logEvent({
    event_name: 'schedule_viewed',
    entity_type: 'route',
    entity_id: id,
    entity_name: name,
    properties: { route_id: id }
  })
  
  // SIB | Solo actualizamos estado local (Independiente del mapa)
  localSelectedRouteId.value = id
  localSelectedRouteName.value = name
  scheduleStore.loadRouteSchedules(id)
}

// goToMap removed per request


// ── Cierre del dropdown al hacer clic fuera
function handleOutsideClick(e: MouseEvent) {
  const target = e.target as HTMLElement
  if (!target.closest('.route-selector')) dropdownOpen.value = false
}

async function fetchData(isBackground = false) {
  await routeStore.loadRoutes(undefined, false, isBackground)
  if (localSelectedRouteId.value) {
    await scheduleStore.loadRouteSchedules(localSelectedRouteId.value, isBackground)
  }
}

function handleRefocus() {
  fetchData(true)
}

onMounted(async () => {
  analyticsService.logEvent({ event_name: 'screen_view', screen_name: 'Schedules' })
  window.addEventListener('app-refocus', handleRefocus)
  
  await routeStore.loadRoutes()
  document.addEventListener('click', handleOutsideClick)

  const queryRouteId = route.query.routeId as string
  if (queryRouteId) {
    const found = routeStore.allRoutes.find(r => r.id === queryRouteId)
    if (found) pickRoute(found.id, found.name)
  } else if (routeStore.selectedRouteId) {
    // SIB | Inicializamos con la ruta del mapa, pero a partir de aquí son independientes
    const mapRoute = routeStore.allRoutes.find(r => r.id === routeStore.selectedRouteId)
    if (mapRoute) {
       localSelectedRouteId.value = mapRoute.id
       localSelectedRouteName.value = mapRoute.name
       scheduleStore.loadRouteSchedules(mapRoute.id)
    }
  }
})

const stopWatch = watch(
  () => route.query.routeId,
  (newId) => {
    if (newId) {
      const found = routeStore.allRoutes.find(r => r.id === newId as string)
      if (found) pickRoute(found.id, found.name)
    }
  }
)

onUnmounted(() => {
  stopWatch()
  document.removeEventListener('click', handleOutsideClick)
  window.removeEventListener('app-refocus', handleRefocus)
})
</script>

<template>
  <div class="sch-page">

    <!-- ── HEADER ── -->
    <header class="sch-header">
      <h1 class="sch-title">{{ t('schedules.title') }}</h1>
      <p class="sch-subtitle" v-if="!hasLocalSelection">
        {{ t('schedules.selectRoute') }}
      </p>
    </header>

    <!-- ── SELECTOR DE RUTA ── -->
    <div class="selector-wrap">
      <div class="route-selector" :class="{ 'route-selector--open': dropdownOpen }">

        <!-- Botón disparador -->
        <button
          class="selector-trigger"
          :class="{ 'selector-trigger--active': hasLocalSelection }"
          @click.stop="dropdownOpen = !dropdownOpen"
          :disabled="routeStore.isLoadingRoutes"
        >
          <div class="trigger-left">
            <div class="trigger-icon">
              <span class="material-icons">directions_bus</span>
            </div>
            <span class="trigger-text" :class="{ 'trigger-text--selected': hasLocalSelection }">
              {{ routeStore.isLoadingRoutes ? t('schedules.loadingRoutes') : (localSelectedRouteName || t('schedules.placeholder')) }}
            </span>
          </div>
          <span class="material-icons trigger-arrow" :class="{ 'trigger-arrow--up': dropdownOpen }">
            expand_more
          </span>
        </button>

        <!-- Lista desplegable -->
        <Transition name="dropdown">
          <div v-if="dropdownOpen" class="dropdown-list">
            <div
              v-if="routeStore.isLoadingRoutes"
              class="dropdown-loading"
            >
              <div class="spinner-sm"></div>
              <span>{{ t('schedules.loadingRoutes') }}</span>
            </div>
            <template v-else>
              <button
                v-for="r in routeStore.allRoutes"
                :key="r.id"
                class="dropdown-item"
                :class="{ 'dropdown-item--active': r.id === localSelectedRouteId }"
                @click.stop="pickRoute(r.id, r.name)"
              >
                <span class="material-icons dropdown-item-icon">directions_bus</span>
                <span class="dropdown-item-name">{{ r.name }}</span>
                <span v-if="r.id === localSelectedRouteId" class="material-icons dropdown-item-check">check</span>
              </button>
              <div v-if="routeStore.allRoutes.length === 0" class="dropdown-empty">
                {{ t('schedules.noRoutesAvailable') }}
              </div>
            </template>
          </div>
        </Transition>
      </div>
    </div>

    <!-- ── ESTADO VACÍO — sin ruta seleccionada ── -->
    <div v-if="!hasLocalSelection" class="empty-state">
      <div class="empty-illustration">
        <svg width="80" height="80" viewBox="0 0 80 80" fill="none">
          <circle cx="40" cy="38" r="24" stroke="var(--active-color)" stroke-width="3.5" stroke-linecap="round" stroke-dasharray="6 4"/>
          <line x1="40" y1="26" x2="40" y2="50" stroke="var(--active-color)" stroke-width="3.5" stroke-linecap="round"/>
          <line x1="28" y1="38" x2="52" y2="38" stroke="var(--active-color)" stroke-width="3.5" stroke-linecap="round"/>
          <line x1="33" y1="62" x2="47" y2="62" stroke="var(--active-color)" stroke-width="3" stroke-linecap="round"/>
          <line x1="40" y1="56" x2="40" y2="62" stroke="var(--active-color)" stroke-width="3" stroke-linecap="round"/>
        </svg>
      </div>
      <h2 class="empty-title">{{ t('schedules.schedules') }}</h2>
      <p class="empty-sub">{{ t('schedules.placeholder') }}</p>
    </div>

    <!-- ── CONTENIDO con ruta seleccionada ── -->
    <template v-else>

      <!-- Badge EN VIVO -->
      <div class="live-badge-wrap">
        <div class="live-badge">
          <span class="live-dot"></span>
          <span>{{ t('schedules.upcoming') }}</span>
        </div>
      </div>

      <!-- Chips de filtro día -->
      <div class="day-chips">
        <button class="day-chip" :class="{ 'day-chip--active': dayFilter === 'today' }" @click="dayFilter = 'today'">{{ t('schedules.today') || 'Hoy' }}</button>
        <button class="day-chip" :class="{ 'day-chip--active': dayFilter === 'tomorrow' }" @click="dayFilter = 'tomorrow'">{{ t('schedules.tomorrow') || 'Mañana' }}</button>
        <button class="day-chip" :class="{ 'day-chip--active': dayFilter === 'all' }" @click="dayFilter = 'all'">{{ t('common.all') || 'Todos' }}</button>
      </div>

      <!-- Loading -->
      <div v-if="scheduleStore.isLoading" class="state-center">
        <LoadingBranded :message="t('schedules.loading') || 'Cargando horarios...'" icon="schedule" />
      </div>

      <!-- Sin resultados en el filtro -->
      <div v-else-if="filteredSchedules.length === 0" class="empty-state empty-state--sm">
        <span class="material-icons empty-cat-icon">schedule</span>
        <p class="empty-sub">{{ t('schedules.noSchedules') }}</p>
        <button class="chip-link" @click="dayFilter = 'all'">{{ t('schedules.viewAll') || 'Ver todos los horarios' }}</button>
      </div>

      <!-- Lista de horarios -->
      <div v-else class="schedules-list">
        <div
          v-for="(schedule, i) in filteredSchedules"
          :key="schedule.id"
          class="schedule-card"
          :class="dayFilter === 'today' ? `schedule-card--${getBusStatus(schedule.departure_time)}` : 'schedule-card--upcoming'"
        >
          <!-- Borde izquierdo decorativo -->
          <div class="card-accent"></div>

          <!-- Hora -->
          <div class="card-time">
            <span class="time-big">{{ formatTo12Hour(schedule.departure_time).split(' ')[0] }}</span>
            <span class="time-ampm">{{ formatTo12Hour(schedule.departure_time).split(' ')[1] }}</span>
          </div>

          <!-- Info -->
          <div class="card-info">
            <div class="card-top-row">
              <span class="day-tag" :class="dayFilter === 'today' ? `day-tag--${getScheduleDay(schedule)}` : 'day-tag--tomorrow'">
                {{ dayFilter === 'tomorrow' ? t('schedules.tomorrow') : (dayFilter === 'all' ? getDayLabel(schedule) : getDayLabel(schedule)) }}
              </span>
              <span v-if="i === 0 && getBusStatus(schedule.departure_time) === 'departing'" class="departing-pulse">{{ t('schedules.departing') || 'SALIENDO' }}</span>
            </div>
            <p class="route-name">{{ localSelectedRouteName }}</p>
            <p class="card-detail">
              <span class="material-icons card-detail-icon">schedule</span>
              {{ DAY_TYPES[schedule.schedule_type] || schedule.schedule_type }}
            </p>
          </div>

          <!-- Badge estado -->
          <div class="status-badge" :class="dayFilter === 'today' ? `status-badge--${getBusStatus(schedule.departure_time)}` : 'status-badge--upcoming'">
            <span class="material-icons status-icon">
              {{ (dayFilter === 'today' && getBusStatus(schedule.departure_time) === 'departing') ? 'directions_run' :
                 (dayFilter === 'today' && getBusStatus(schedule.departure_time) === 'ontime') ? 'check_circle' : 
                 (dayFilter === 'today' && getBusStatus(schedule.departure_time) === 'passed') ? 'history' : 'access_time' }}
            </span>
          </div>
        </div>
      </div>

    </template>
  </div>
</template>

<style scoped>
/* ═══════════════════════════════════════════
   BASE
═══════════════════════════════════════════ */
.sch-page {
  min-height: 100vh;
  background: var(--bg-primary);
  padding-bottom: 100px;
}

/* ═══════════════════════════════════════════
   HEADER
═══════════════════════════════════════════ */
.sch-header {
  padding: 1.5rem 1.25rem 1rem;
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border-color);
}

.sch-title {
  font-size: 1.75rem;
  font-weight: 900;
  color: var(--text-primary);
  margin: 0;
  letter-spacing: -0.02em;
}

.sch-subtitle {
  margin: 0.25rem 0 0;
  font-size: 0.875rem;
  color: var(--text-secondary);
  font-weight: 500;
}

/* ═══════════════════════════════════════════
   SELECTOR DE RUTA
═══════════════════════════════════════════ */
.selector-wrap {
  padding: 1rem 1.25rem;
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border-color);
  position: relative;
  z-index: 50;
}

.route-selector { position: relative; }

/* Botón trigger */
.selector-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1rem 1rem 1rem 0.875rem;
  background: var(--bg-primary);
  border: 1.5px solid var(--border-color);
  border-radius: 1rem;
  cursor: pointer;
  transition: border-color 0.2s;
  font-family: inherit;
}

.selector-trigger:hover:not(:disabled),
.route-selector--open .selector-trigger {
  border-color: var(--active-color);
}

.selector-trigger--active {
  border-color: var(--active-color);
  border-width: 2px;
}

.selector-trigger:disabled { opacity: 0.5; cursor: not-allowed; }

.trigger-left {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex: 1;
  min-width: 0;
}

.trigger-icon {
  width: 40px;
  height: 40px;
  border-radius: 0.625rem;
  background: var(--active-color);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.trigger-icon .material-icons { font-size: 1.25rem; color: #101820; }

.trigger-text {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.trigger-text--selected {
  color: var(--text-primary);
  font-weight: 800;
}

.trigger-arrow {
  color: var(--text-secondary);
  transition: transform 0.25s;
  flex-shrink: 0;
}

.trigger-arrow--up { transform: rotate(180deg); }

/* Dropdown */
.dropdown-list {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0;
  right: 0;
  background: var(--bg-secondary);
  border: 1.5px solid var(--border-color);
  border-radius: 1rem;
  overflow: hidden;
  box-shadow: 0 12px 40px rgba(0,0,0,0.25);
  z-index: 100;
}

.dropdown-loading {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1.25rem;
  color: var(--text-secondary);
  font-size: 0.875rem;
}

.dropdown-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1rem;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border-color);
  color: var(--text-primary);
  font-size: 0.9375rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  text-align: left;
  transition: background 0.15s;
}

.dropdown-item:last-child { border-bottom: none; }

.dropdown-item:hover { background: var(--bg-primary); }

.dropdown-item--active {
  color: var(--active-color);
  background: rgba(254, 231, 21, 0.06);
}

.dropdown-item-icon {
  font-size: 1.125rem;
  color: var(--text-secondary);
  flex-shrink: 0;
}

.dropdown-item--active .dropdown-item-icon { color: var(--active-color); }

.dropdown-item-name { flex: 1; }

.dropdown-item-check {
  font-size: 1.125rem;
  color: var(--active-color);
  flex-shrink: 0;
}

.dropdown-empty {
  padding: 1.25rem;
  text-align: center;
  color: var(--text-secondary);
  font-size: 0.875rem;
}

/* Animación dropdown */
.dropdown-enter-active,
.dropdown-leave-active {
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.dropdown-enter-from,
.dropdown-leave-to {
  opacity: 0;
  transform: translateY(-8px);
}

/* ═══════════════════════════════════════════
   BADGE EN VIVO + BOTÓN MAPA
═══════════════════════════════════════════ */
.live-badge-wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.875rem 1.25rem 0;
}

.live-badge {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--text-secondary);
}

.live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #22c55e;
  animation: pulse-green 1.5s ease-in-out infinite;
  flex-shrink: 0;
}

@keyframes pulse-green {
  0%, 100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.5); }
  50% { box-shadow: 0 0 0 6px rgba(34, 197, 94, 0); }
}

.map-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.5rem 0.875rem;
  background: var(--bg-secondary);
  border: 1.5px solid var(--border-color);
  border-radius: 99px;
  color: var(--text-primary);
  font-size: 0.8125rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.2s;
}

.map-btn:hover { border-color: var(--active-color); }
.map-btn .material-icons { font-size: 1rem; }

/* ═══════════════════════════════════════════
   CHIPS DÍA
═══════════════════════════════════════════ */
.day-chips {
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem 1.25rem;
}

.day-chip {
  padding: 0.4rem 0.875rem;
  border-radius: 99px;
  border: 1.5px solid var(--border-color);
  background: var(--bg-primary);
  color: var(--text-secondary);
  font-size: 0.8125rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: all 0.18s;
}

.day-chip:hover { border-color: var(--active-color); color: var(--text-primary); }

.day-chip--active {
  background: var(--active-color);
  border-color: var(--active-color);
  color: #101820;
}

/* ═══════════════════════════════════════════
   LISTA DE HORARIOS
═══════════════════════════════════════════ */
.schedules-list {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  padding: 0 1.25rem;
  max-width: 640px;
  margin: 0 auto;
}

.schedule-card {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  background: var(--bg-secondary);
  border: 1.5px solid var(--border-color);
  border-radius: 1rem;
  padding: 1rem;
  position: relative;
  overflow: hidden;
  transition: transform 0.15s;
}

.schedule-card:hover { transform: translateX(4px); }

/* Variantes de estado */
.schedule-card--departing {
  border-color: var(--active-color);
  box-shadow: 0 0 16px rgba(254, 231, 21, 0.12);
}

.schedule-card--ontime { border-left-color: #22c55e; border-left-width: 3px; }
.schedule-card--upcoming { border-left-color: #3b82f6; border-left-width: 3px; }

/* Acento izquierdo */
.card-accent {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  border-radius: 1rem 0 0 1rem;
}

.schedule-card--departing .card-accent { background: var(--active-color); }
.schedule-card--ontime    .card-accent { background: #22c55e; }
.schedule-card--upcoming  .card-accent { background: #3b82f6; }

/* Hora */
.card-time {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  min-width: 64px;
  padding-left: 0.25rem;
}

.time-big {
  font-size: 1.5rem;
  font-weight: 900;
  color: var(--active-color);
  letter-spacing: -0.03em;
  line-height: 1;
}

.time-ampm {
  font-size: 0.6875rem;
  font-weight: 800;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Info */
.card-info { flex: 1; min-width: 0; }

.card-top-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}

.day-tag {
  font-size: 0.6875rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.1rem 0.45rem;
  border-radius: 99px;
}

.day-tag--today   { background: rgba(34, 197, 94, 0.15); color: #22c55e; }
.day-tag--tomorrow{ background: rgba(59, 130, 246, 0.15); color: #3b82f6; }
.day-tag--other   { background: var(--bg-primary); color: var(--text-secondary); }

.departing-pulse {
  font-size: 0.6rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #101820;
  background: var(--active-color);
  padding: 0.1rem 0.5rem;
  border-radius: 99px;
  animation: blink 1.2s ease-in-out infinite;
}

@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

/* Estado Pasado (Faded) */
.schedule-card--passed {
  opacity: 0.5;
  filter: grayscale(0.8);
  border-left-color: #6b7280;
  border-left-width: 3px;
  transform: none !important; /* No hover effect for passed */
}

.schedule-card--passed .card-accent {
  background: #6b7280;
}

.schedule-card--passed .time-big {
  color: #6b7280;
}

.status-badge--passed {
  background: rgba(107, 114, 128, 0.15);
  color: #6b7280;
}

.route-name {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 800;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-detail {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin: 0.2rem 0 0;
  font-size: 0.8125rem;
  color: var(--text-secondary);
}

.card-detail-icon { font-size: 0.875rem; }

/* Badge estado (derecha) */
.status-badge {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.status-badge--departing { background: rgba(254, 231, 21, 0.15); color: var(--active-color); }
.status-badge--ontime    { background: rgba(34, 197, 94, 0.15);  color: #22c55e; }
.status-badge--upcoming  { background: rgba(59, 130, 246, 0.15); color: #3b82f6; }

.status-icon { font-size: 1.25rem; }

/* ═══════════════════════════════════════════
   ESTADO VACÍO
═══════════════════════════════════════════ */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 3.5rem 2rem;
  text-align: center;
  max-width: 360px;
  margin: 1.5rem auto 0;
}

.empty-state--sm { padding: 2rem 1.25rem; }

.empty-illustration {
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: var(--bg-secondary);
  border: 1.5px dashed var(--border-color);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.5rem;
}

.empty-title {
  font-size: 1.375rem;
  font-weight: 900;
  color: var(--text-primary);
  margin: 0 0 0.625rem;
  letter-spacing: -0.02em;
}

.empty-sub {
  font-size: 0.9375rem;
  color: var(--text-secondary);
  line-height: 1.55;
  margin: 0;
}

.empty-cat-icon {
  font-size: 3rem;
  color: var(--text-secondary);
  opacity: 0.35;
  margin-bottom: 0.75rem;
}

.chip-link {
  margin-top: 1rem;
  background: none;
  border: 1.5px solid var(--active-color);
  color: var(--active-color);
  border-radius: 99px;
  padding: 0.5rem 1.25rem;
  font-size: 0.875rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.2s, color 0.2s;
}

.chip-link:hover {
  background: var(--active-color);
  color: #101820;
}

/* ═══════════════════════════════════════════
   SPINNERS
═══════════════════════════════════════════ */
.state-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 3rem 1.25rem;
  gap: 1rem;
  color: var(--text-secondary);
  font-size: 0.9375rem;
}

.spinner, .spinner-sm {
  border: 2.5px solid var(--border-color);
  border-top-color: var(--active-color);
  border-radius: 50%;
  animation: spin 0.75s linear infinite;
}

.spinner    { width: 2rem; height: 2rem; }
.spinner-sm { width: 1rem; height: 1rem; }

@keyframes spin { to { transform: rotate(360deg); } }
</style>
