/* ==========================================================================
   RDC Internet y TV — Design tokens & custom styles
   ========================================================================== */

/* ---------- Accesibilidad: texto solo para lectores de pantalla ---------- */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Skip link: primer tab de la página, salta al contenido ---------- */
.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 100;
  transform: translateY(-160%);
  background: var(--navy-900);
  color: #fff;
  font: 600 0.875rem/1 Inter, sans-serif;
  padding: 12px 18px;
  border-radius: 9999px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  box-shadow: 0 12px 30px -10px rgba(3, 14, 40, 0.6);
  transition: transform 200ms var(--ease-out);
}
.skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid var(--sky-300);
  outline-offset: 3px;
}

:root {
  /* Paleta real de marca (auto ploteado y publicidad en vía pública) */
  --ink: #051826;
  --navy-950: #051826;
  --navy-900: #0C3656;   /* azul oscuro de marca */
  --navy-800: #214865;
  --navy-700: #41627B;
  --brand-600: #3777A5;
  --brand-500: #4A9FDC;  /* azul principal de marca */
  --brand-400: #6AB0E2;
  --sky-300: #71B4E3;
  --sky-200: #96C7EA;
  --mist-100: #E2E4E5;   /* gris claro principal de marca */
  --paper: #F4F6F7;
  --accent: #CE4700;     /* naranja de marca (uso puntual, CTAs) — texto blanco 4.6:1 AA */
  --accent-dark: #A83A00; /* solo para degradés/tipografía sobre blanco, no para hover */
  --accent-hover: #DE5310; /* hover: se ilumina, no se oscurece — naranja comercial */
  --line: rgba(255, 255, 255, 0.08);

  /* Familia "azul eléctrico": vive SOLO en el hero (ver DESIGN.md → Regla del
     Hero Brillante). El resto del sitio es navy. */
  --electric-deep: #0A3FAC;
  --electric: #0E63D9;
  --electric-bright: #1D86EE;
  --electric-sky: #35A1F5;

  /* Curvas de easing (más marcadas que las nativas de CSS) */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
}

html {
  -webkit-text-size-adjust: 100%;
}
/* Scroll suave solo si el usuario no pidió reducir movimiento */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

html, body {
  overflow-x: hidden;
  max-width: 100%;
}

/* El header es fixed (~110–120px con su margen). Sin esto, los saltos de ancla
   ("Internet", "Cobertura"…) dejan el título de la sección tapado por el nav. */
:target,
main > section[id],
#contenido {
  scroll-margin-top: 7.5rem;
}

body {
  background: var(--navy-950);
  color: var(--mist-100);
  caret-color: var(--sky-300);
}

::selection {
  background: var(--sky-300);
  color: var(--navy-950);
}

/* ---------- Foco visible: un solo anillo de marca para todo control ----------
   El outline sigue el border-radius propio de cada elemento; aparece al
   instante (sin transición) como corresponde a un indicador de foco. */
:focus-visible {
  outline: 2px solid var(--sky-300);
  outline-offset: 3px;
}
/* El input de búsqueda muestra foco también al hacer clic, no solo por teclado */
#channel-search:focus {
  outline: 2px solid var(--sky-300);
  outline-offset: 2px;
  border-color: rgba(113, 180, 227, 0.6);
}
/* Placeholder con contraste AA sobre el input (bg-white/5 sobre navy) */
#channel-search::placeholder { color: rgba(226, 228, 229, 0.72); opacity: 1; }

/* ---------- Barra de scroll temática (en vez de la gris del navegador) ---------- */
@supports (scrollbar-color: auto) {
  html {
    scrollbar-width: thin;
    scrollbar-color: rgba(113, 180, 227, 0.35) rgba(255, 255, 255, 0.04);
  }
}
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.03); }
::-webkit-scrollbar-thumb {
  background: rgba(113, 180, 227, 0.32);
  border-radius: 9999px;
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: rgba(113, 180, 227, 0.5); background-clip: content-box; }

img, svg {
  max-width: 100%;
  height: auto;
}

/* ---------- Fluid headline sizing (looks sharp from 320px to 4K) ---------- */
.h-hero {
  /* Titular en 3 renglones deliberados (los <br> del markup): frases cortas,
     ninguna palabra suelta, y a tamaño grande ocupa el hero con autoridad.
     text-wrap:balance queda por si algún renglón llegara a envolver en un
     ancho intermedio. */
  font-size: clamp(1.85rem, 3vw + 0.9rem, 3.4rem);
  line-height: 1.1;
  letter-spacing: -0.012em;
  text-wrap: balance;
}
.h-section {
  font-size: clamp(1.6rem, 2.6vw + 1rem, 2.25rem);
  line-height: 1.15;
  text-wrap: balance;
}

/* ---------- Scrollable tab row on small screens ---------- */
.tab-scroll {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  padding-bottom: 2px;
  /* En mobile el row sangra a los bordes con -mx-6/px-6. Sin este inset, el
     scroll-snap alinea "Todos" con el borde del viewport y lo deja más pegado
     que el resto de la página (que respira los 1.5rem de .max-w-6xl px-6). */
  scroll-padding-inline: 1.5rem;
}
.tab-scroll::-webkit-scrollbar { display: none; }
.tab-scroll > * { scroll-snap-align: start; }

@media (min-width: 640px) {
  /* A partir de sm el row ya no sangra (sm:mx-0 sm:px-0): sin inset. */
  .tab-scroll { scroll-padding-inline: 0; }
}

@media (min-width: 768px) {
  .tab-scroll {
    flex-wrap: wrap;
    overflow-x: visible;
  }
}

/* Barra de herramientas de la grilla (categorías + buscador). En fila, el
   buscador se alinea con la PRIMERA fila de chips: si las categorías envuelven
   a dos líneas, no queda flotando en el hueco de la segunda. */
@media (min-width: 640px) {
  .channel-toolbar { align-items: flex-start; }
  .channel-toolbar > .tab-scroll { flex: 1; padding-top: 1px; }
}

/* ---------- Minimum comfortable touch targets on touch devices ---------- */
@media (pointer: coarse) {
  a.rounded-full, button.rounded-full, .category-tab {
    min-height: 44px;
  }
  .cov-card { min-height: 76px; }
}

/* ==========================================================================
   HERO — azul eléctrico y dinámico (dirección tomada de la publicidad).
   El resto del sitio sigue siendo el "cielo nocturno" navy; el hero es el
   momento luminoso y de energía, y se funde de nuevo al navy en su borde.
   ========================================================================== */
#hero {
  isolation: isolate;
  /* Relleno base detrás de .hero-bg — token "azul eléctrico" de DESIGN.md */
  background: var(--electric);
  color: #fff;
}

/* Fondo: degradado azul con foco de luz arriba-derecha (como la foto) */
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(115% 90% at 86% 0%, rgba(120, 214, 255, 0.7) 0%, rgba(120, 214, 255, 0) 50%),
    radial-gradient(95% 95% at 0% 112%, rgba(6, 28, 96, 0.62) 0%, rgba(6, 28, 96, 0) 55%),
    linear-gradient(138deg, var(--electric-deep) 0%, var(--electric) 42%, var(--electric-bright) 72%, var(--electric-sky) 100%);
}

/* Partículas (canvas): flujo tenue, se desvanece hacia abajo */
.hero-net {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0.4;
  -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 94%);
  mask-image: linear-gradient(to bottom, #000 55%, transparent 94%);
}
.hero-net canvas { display: block; width: 100%; height: 100%; }

/* ---------- Hero: columna de texto + panel de oferta ----------
   Desde lg, dos columnas: el mensaje a la izquierda y el panel Internet + TV
   (lo que vendemos + el gancho comercial + el CTA) a la derecha. Debajo de lg
   se apilan, con el panel debajo del texto. */
.hero-grid { display: grid; gap: 2.5rem; }
@media (min-width: 1024px) {
  .hero-grid {
    grid-template-columns: minmax(0, 1fr) 19rem;
    gap: 2.75rem;
    align-items: center;
  }
}
@media (min-width: 1280px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr) 21rem; gap: 3.5rem; }
}

/* Deck bajo el titular: "Conexión estable, siempre." — la promesa que más
   importa en la zona (el internet inestable es el dolor local). Blanco al 92%:
   se lee como una voz de apoyo (más suave que el h1 800, sin ser un segundo
   color) y mantiene contraste AA sobre todo el degradé del hero, incluso en el
   tamaño mínimo del clamp en mobile — lo que el azul Señal no garantizaba. */
.hero-deck {
  margin-top: 1.15rem;
  font-family: Inter, sans-serif;
  font-weight: 600;
  font-size: clamp(1.1rem, 0.7vw + 0.95rem, 1.4rem);
  line-height: 1.3;
  color: rgba(255, 255, 255, 0.92);
  animation: hero-in 850ms var(--ease-out) 240ms backwards;
}

/* CTA de conversión en el flujo de lectura del hero: "Quiero contratar" abre
   WhatsApp. Es el primario del hero; el "Conocé más" del panel (que scrollea a
   los planes) queda como acción de apoyo dentro del panel discreto. */
.hero-actions {
  animation: hero-in 800ms var(--ease-out) 520ms backwards;
}

/* Línea de confianza bajo el subtítulo: el diferencial local, sin caja. */
.hero-trust {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font: 500 0.9375rem/1.4 Inter, sans-serif;
  color: rgba(255, 255, 255, 0.82);
  animation: hero-in 800ms var(--ease-out) 420ms backwards;
}
.hero-trust svg {
  width: 16px;
  height: 16px;
  flex: none;
  color: var(--sky-200);
}

/* Panel de oferta del hero: vidrio azul, deliberadamente discreto — el titular
   es el que manda. Fondo casi sólido (para que el texto interno mantenga
   contraste AA sin backdrop-blur sobre el canvas animado), pero borde y sombra
   apenas presentes para que el panel se apoye en la escena, no compita con el
   H1. Entra como una sola unidad; sus hijos no llevan animación aparte. */
.hero-panel {
  background: linear-gradient(180deg, rgba(13, 60, 134, 0.88), rgba(8, 40, 100, 0.9));
  border: 1px solid rgba(255, 255, 255, 0.13);
  border-radius: 1rem;
  padding: 1.6rem;
  box-shadow:
    0 1px 2px rgba(3, 16, 54, 0.3),
    0 14px 34px -18px rgba(3, 16, 54, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.14);
  animation: hero-in 750ms var(--ease-out) 480ms backwards;
  margin-top: 2.5rem;
  max-width: 27rem;
}
@media (min-width: 1024px) {
  .hero-panel { margin-top: 0; max-width: none; }
}
.hero-panel-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1.15rem;
  font: 700 0.78rem/1.3 Inter, sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.94);
}
.hero-panel-eyebrow::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: var(--sky-300);
  box-shadow: 0 0 5px 0 rgba(150, 199, 234, 0.4);
  flex: none;
}
.hero-panel-stats {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding-bottom: 1.25rem;
  margin-bottom: 1.25rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.16);
}
.hero-panel-num {
  font-family: Manrope, sans-serif;
  font-weight: 800;
  font-size: 1.5rem;
  line-height: 1;
  color: #fff;
}
/* El contador anima hasta 50 / 164 arrancando en un número del mismo largo
   (initCountUp), así el renglón "Hasta ___ Mb" no se relayoutea frame a frame.
   tabular-nums evita además el salto de ancho entre dígitos. */
.hero-panel-num .count-up { font-variant-numeric: tabular-nums; }
.hero-panel-cap {
  margin-top: 0.3rem;
  font: 500 0.8125rem/1.35 Inter, sans-serif;
  color: rgba(255, 255, 255, 0.78);
}
.hero-panel .hero-offer { margin-bottom: 1.35rem; }
.hero-panel .hero-cta { width: 100%; }
@media (prefers-reduced-motion: reduce) {
  .hero-deck,
  .hero-trust,
  .hero-actions,
  .hero-panel { animation: none; }
}

/* Capas decorativas con leve parallax al cursor (lo mueve initHeroCursorParallax) */
.hero-mesh {
  position: absolute;
  inset: -8%;
  z-index: 2;
  pointer-events: none;
  /* will-change lo pone/saca initHeroCursorParallax solo mientras el loop
     de parallax está activo — no permanente sobre esta capa grande. */
}
.hero-ribbons {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Líneas de flujo: se trasladan de izquierda a derecha en bucle lineal
   continuo (sin `alternate` ni vaivén). El <g> lleva la curva duplicada a
   +1200; al llegar a translateX(-1200) la segunda copia queda exactamente
   donde estaba la primera, así que el salto de reinicio no se ve.
   Opacidad muy baja: el movimiento se percibe pero no compite con el texto. */
.flow {
  stroke-linecap: round;
  will-change: transform;
  animation: flow-x linear infinite;
}
@keyframes flow-x {
  from { transform: translateX(0); }
  to   { transform: translateX(-1200px); }
}
.flow-deep { stroke: rgba(150, 205, 240, 0.05); stroke-width: 32; animation-duration: 20s; }
.flow-1    { stroke: rgba(206, 236, 255, 0.11); stroke-width: 1.6; animation-duration: 15s; }
.flow-warm { stroke: rgba(224, 118, 66, 0.07);  stroke-width: 1.4; animation-duration: 17s; }
.flow-2    { stroke: rgba(255, 255, 255, 0.07);  stroke-width: 1.3; animation-duration: 19s; }

.hero-glow {
  position: absolute;
  border-radius: 9999px;
  filter: blur(60px);
  will-change: transform;
}
.hero-glow-1 {
  width: 34rem; height: 34rem;
  top: -13rem; right: -9rem;
  background: radial-gradient(circle, rgba(158, 227, 255, 0.55) 0%, transparent 70%);
  animation: hero-glow-a 20s ease-in-out infinite;
}
.hero-glow-2 {
  width: 27rem; height: 27rem;
  bottom: -12rem; left: -7rem;
  background: radial-gradient(circle, rgba(206, 71, 0, 0.16) 0%, transparent 72%);
  animation: hero-glow-b 26s ease-in-out infinite;
}
@keyframes hero-glow-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(-46px, 40px) scale(1.12); }
}
@keyframes hero-glow-b {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(34px, -30px) scale(1.14); }
}

/* Borde inferior: funde el azul del hero con el navy de las secciones */
.hero-fade {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 190px;
  z-index: 3;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(12, 54, 86, 0) 0%, var(--navy-900) 94%);
}

/* Viñeta interior: enmarca el hero y le da profundidad (sombras suaves) */
#hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  box-shadow:
    inset 0 44px 72px -52px rgba(3, 16, 54, 0.42),
    inset 46px 0 96px -74px rgba(3, 16, 54, 0.34),
    inset -46px 0 96px -74px rgba(3, 16, 54, 0.34);
}

.hero-heading {
  text-shadow: 0 1px 1px rgba(4, 18, 56, 0.22), 0 3px 30px rgba(4, 18, 56, 0.38);
}
.hero-badge-dot { box-shadow: 0 0 10px 2px rgba(206, 71, 0, 0.55); }

@media (prefers-reduced-motion: reduce) {
  .hero-glow,
  .flow { animation: none; }
}

/* ---------- Hero: entrada coreografiada (una sola vez, al cargar) ----------
   Se usa `backwards` (no `both`) a propósito: al terminar la animación la
   propiedad queda libre para que :hover/:active y GSAP la controlen sin
   que el fill de la animación gane la cascada. */
@keyframes hero-in {
  from { opacity: 0; transform: translateY(22px); filter: blur(6px); }
  to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}
.hero-badge   { animation: hero-in 700ms var(--ease-out) 80ms backwards; }
.hero-heading { animation: hero-in 900ms var(--ease-out) 160ms backwards; }
.hero-sub     { animation: hero-in 800ms var(--ease-out) 320ms backwards; }

/* Oferta comercial dentro del panel: "Planes desde $18.730/mes" en UNA línea
   (etiqueta y precio con el mismo peso de lectura, el número es el que manda)
   y, debajo, el gancho de instalación como un renglón discreto — chispa Señal
   + texto, sin caja ni resaltado que pelee con la sobriedad del hero. */
.hero-offer .price-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 0.5rem;
  color: #fff;
}
.hero-offer .price {
  font-family: Manrope, sans-serif;
  font-weight: 800;
  font-size: clamp(1.6rem, 1vw + 1.3rem, 1.9rem);
  line-height: 1;
}
.hero-offer .price-label { font-size: 1rem; font-weight: 500; color: rgba(255, 255, 255, 0.72); }
.hero-offer .price-per   { font-size: 1rem; font-weight: 500; color: rgba(255, 255, 255, 0.68); }
.hero-offer .promo-line {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.55rem;
  font-size: 0.875rem;
  color: rgba(255, 255, 255, 0.78);
}
.hero-offer .promo-line svg { width: 1rem; height: 1rem; flex: none; color: var(--sky-300); }
.hero-offer .promo-line strong { color: #fff; font-weight: 600; }

/* La entrada del CTA la aporta el .hero-panel que lo contiene (una sola unidad). */
/* #hero para ganarle a la utilidad transition-colors de Tailwind */
#hero .hero-cta {
  transition: transform 220ms var(--ease-out), background-color 220ms var(--ease-out), border-color 220ms var(--ease-out), box-shadow 220ms var(--ease-out);
}
#hero .hero-cta-primary {
  box-shadow:
    0 2px 6px rgba(110, 38, 0, 0.4),
    0 14px 30px -10px rgba(206, 71, 0, 0.5),
    0 26px 50px -16px rgba(90, 32, 0, 0.4);
}
@media (hover: hover) and (pointer: fine) {
  #hero .hero-cta:hover { transform: translateY(-2px); }
  #hero .hero-cta-primary:hover {
    box-shadow:
      0 2px 8px rgba(110, 38, 0, 0.45),
      0 18px 38px -10px rgba(206, 71, 0, 0.58),
      0 34px 64px -16px rgba(90, 32, 0, 0.45);
  }
}
#hero .hero-cta:active { transform: translateY(0) scale(0.975); }
.hero-cta .hero-cta-arrow {
  transition: transform 300ms var(--ease-out);
}
.hero-cta:hover .hero-cta-arrow {
  transform: translateX(3px);
}

/* Indicador de scroll al pie del hero: solo una flechita que rebota apenas. */
.hero-scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 18px;
  /* Por encima del degradado de salida (.hero-fade, z-3) y de la viñeta
     (#hero::after, z-4); si no, el fade lo tapaba por completo. */
  z-index: 6;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.68);
  animation: hero-in 700ms var(--ease-out) 950ms backwards;
}
.hero-scroll-cue:hover { color: #fff; }
.hero-scroll-cue svg {
  display: block;
  animation: cue-bounce 1.9s var(--ease-in-out) infinite;
}
@keyframes cue-bounce {
  0%, 100% { transform: translateY(0); opacity: .6; }
  50%      { transform: translateY(5px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-badge, .hero-heading, .hero-sub, .hero-scroll-cue {
    animation: none;
  }
  .hero-scroll-cue svg { animation: none; }
  .wa-float { animation: none; }
}

/* ---------- Nav: panel de cristal ----------
   Arriba de todo: cristal translúcido y liviano — el hero (color y movimiento)
   se ve difuminado detrás, con un filo de luz superior y una sombra sutil.
   Al scrollear: el mismo cristal se tiñe de navy, se vuelve más opaco y gana
   peso (sombra + blur), para separarse del contenido. */
.nav-shell {
  background: linear-gradient(180deg, rgba(11, 32, 66, 0.34) 0%, rgba(6, 20, 46, 0.44) 100%);
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow:
    0 10px 30px -14px rgba(3, 14, 40, 0.42),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
  -webkit-backdrop-filter: blur(14px) saturate(135%);
  backdrop-filter: blur(14px) saturate(135%);
  transition:
    background 340ms var(--ease-out),
    box-shadow 340ms var(--ease-out),
    border-color 340ms var(--ease-out),
    -webkit-backdrop-filter 340ms var(--ease-out),
    backdrop-filter 340ms var(--ease-out);
}
header.is-scrolled .nav-shell {
  background: linear-gradient(180deg, rgba(7, 24, 52, 0.82) 0%, rgba(4, 16, 40, 0.86) 100%);
  border-color: rgba(255, 255, 255, 0.14);
  box-shadow:
    0 16px 38px -14px rgba(0, 0, 0, 0.55),
    inset 0 1px 0 rgba(255, 255, 255, 0.13);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  backdrop-filter: blur(18px) saturate(150%);
}

/* Sin soporte de backdrop-filter: fondo un poco más sólido para no perder legibilidad */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .nav-shell { background: linear-gradient(180deg, rgba(11, 32, 66, 0.6), rgba(6, 20, 46, 0.7)); }
  header.is-scrolled .nav-shell { background: linear-gradient(180deg, rgba(7, 24, 52, 0.94), rgba(4, 16, 40, 0.96)); }
}

/* ---------- Reveal on scroll ---------- */
/* --reveal-delay lo fija initReveal() en main.js: escalona hermanos
   dentro de un mismo contenedor (grillas de planes, tarjetas, etc.) */
.reveal {
  --reveal-delay: 0ms;
  opacity: 0;
  transform: translateY(18px);
  filter: blur(6px);
  transition: opacity .6s var(--ease-out), transform .6s var(--ease-out), filter .6s var(--ease-out);
  transition-delay: var(--reveal-delay);
}
.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}

/* Grilla de canales: misma entrada fade-up que .reveal, pero suelta la
   transición al terminar (.reveal-done) para que fadeSwap maneje los cambios
   de nivel/categoría sin arrastre. */
.reveal-grid {
  opacity: 0;
  transform: translateY(18px);
  filter: blur(6px);
  transition: opacity .6s var(--ease-out), transform .6s var(--ease-out), filter .6s var(--ease-out);
}
.reveal-grid.is-visible {
  opacity: 1;
  transform: none;
  filter: none;
}
.reveal-grid.reveal-done {
  transition: none;
}
@media (prefers-reduced-motion: reduce) {
  .reveal-grid { transition: none; opacity: 1; transform: none; filter: none; }
}

/* ---------- Speed bars ---------- */
/* transform en vez de width: animar una propiedad de layout causa thrash;
   scaleX() con transform-origin:left produce el mismo efecto visual sobre
   una capa compuesta. */
.speed-fill {
  width: 100%;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 1.1s var(--ease-out);
}

/* ---------- Glass card (dark surfaces: hero, mesh, footer, CTA final) ---------- */
.glass {
  background: linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.02));
  border: 1px solid var(--line);
  backdrop-filter: blur(6px);
}

/* ---------- Feedback táctil en botones (Emil Kowalski: los botones
   deben sentirse presionados) ---------- */
.btn-press {
  transition: transform 160ms var(--ease-out);
}
.btn-press:active {
  transform: scale(0.97);
}

/* ---------- CTAs naranjas: al pasar el cursor se iluminan (color + glow cálido),
   nunca se oscurecen ---------- */
.btn-accent {
  transition: background-color .2s ease, box-shadow .25s var(--ease-out), transform 160ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .btn-accent:hover {
    box-shadow: 0 12px 28px -10px rgba(222, 83, 16, 0.55), 0 0 0 1px rgba(255, 200, 160, 0.22) inset;
  }
}

/* ---------- Carteles de localidades: ahora enlaces a WhatsApp con la
   consulta de esa localidad. Mismo lenguaje de hover que el resto. ---------- */
.cov-card { display: block; }
.cov-arrow {
  display: inline-block;
  margin-left: 0.15rem;
  color: var(--sky-300);
  opacity: 0;
  transform: translateX(-3px);
  transition: opacity .2s var(--ease-out), transform .2s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .cov-card {
    transition: transform .22s var(--ease-out), border-color .22s var(--ease-out),
                background-color .22s var(--ease-out), box-shadow .22s var(--ease-out);
  }
  .cov-card:hover {
    transform: translateY(-3px);
    border-color: rgba(113, 180, 227, 0.45);
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0.03));
    box-shadow: 0 16px 32px -18px rgba(3, 14, 40, 0.55);
  }
  .cov-card:hover .cov-arrow,
  .cov-card:focus-visible .cov-arrow { opacity: 1; transform: translateX(0); }
}
/* En touch (sin hover) la flecha se muestra fija: la tarjeta ES un enlace */
@media (hover: none) {
  .cov-arrow { opacity: 0.9; transform: none; }
}

/* ---------- Plan cards ---------- */
.plan-card {
  transition: border-color .3s var(--ease-out), transform .3s var(--ease-out), box-shadow .3s var(--ease-out), background-color .3s var(--ease-out);
}
.plan-card.is-featured {
  /* Arranca un paso más oscuro que brand-600 para que el texto claro
     de la tarjeta destacada llegue a contraste AA sobre el degradé. */
  background: linear-gradient(160deg, #2d6389, var(--navy-800) 70%);
  color: #fff;
}

/* ---------- Chips ---------- */
.chip {
  transition: transform .2s var(--ease-out), background-color .2s ease, border-color .2s ease;
}

/* ---------- Channel grid ---------- */
.channel-tile {
  padding: 10px 12px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.025);
  transition: transform .18s var(--ease-out), border-color .18s ease, background-color .18s ease;
}

/* Chip del logo: cuadrado redondeado con fondo adaptado al logo */
.channel-logo {
  position: relative;
  width: 48px;
  height: 48px;
  border-radius: 11px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.09);
  background: linear-gradient(145deg, #1c3b56, #0a2135);
  transition: background .2s ease, border-color .2s ease;
}
.channel-logo[data-tone="light"] {
  background: linear-gradient(160deg, #ffffff, #e9edf1);
  border-color: rgba(5, 24, 38, 0.12);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
.channel-logo-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 5px;
}
.channel-fallback {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--sky-200, #96C7EA);
}

/* Hover con elevación: solo en dispositivos con mouse real, para que
   el hover no quede "pegado" al tocar en celulares/tablets */
@media (hover: hover) and (pointer: fine) {
  .plan-card:hover {
    transform: translateY(-5px);
    border-color: rgba(74, 159, 220, 0.45);
    box-shadow: 0 24px 50px -25px rgba(0, 0, 0, 0.55);
  }
  .chip:hover {
    transform: translateY(-2px);
  }
  .channel-tile:hover {
    transform: translateY(-2px);
    border-color: rgba(74, 159, 220, 0.5);
    background-color: rgba(74, 159, 220, 0.07);
  }
}

.category-tab {
  transition: color .2s ease, background-color .2s ease, border-color .2s ease;
}
.category-tab[data-active="true"] {
  background: var(--brand-500);
  color: #fff;
  border-color: transparent;
}

/* ---------- Tier tabs (TV Básico / Plus / Full) ---------- */
.tier-tab {
  transition: color .2s ease, background-color .2s ease, border-color .2s ease;
}
.tier-tab:not([data-active="true"]):hover {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.25);
}

.channel-section {
  display: none;
}
.channel-section[data-visible="true"] {
  display: block;
  /* Cada categoría es un bloque grande e independiente: el navegador se
     ahorra el layout/paint de las que están fuera de pantalla (importa con
     la grilla acumulativa de Full ~164 tiles). */
  content-visibility: auto;
  contain-intrinsic-size: auto 480px;
}
/* Separación entre categorías cuando se ven varias a la vez ("Todos"): aire
   generoso arriba de cada grupo nuevo, no cuando queda una sola categoría. */
.channel-section[data-visible="true"] + .channel-section[data-visible="true"] {
  margin-top: 2.5rem;
}

/* Encabezado de categoría + badge "Nuevo en Plus/Full" para los grupos
   premium que se suman en cada nivel. */
.channel-cat-heading { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.55rem; }
.channel-cat-new {
  font: 600 0.72rem/1 Inter, sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--navy-950);
  background: linear-gradient(180deg, var(--sky-200), var(--sky-300));
  border-radius: 9999px;
  padding: 0.2rem 0.55rem;
}
.channel-section[data-added] .channel-tile {
  border-color: rgba(150, 199, 234, 0.28);
}

/* ---------- Hero canvas ---------- */
#hero-canvas {
  width: 100%;
  height: 100%;
  display: block;
}

/* ---------- Floating WhatsApp button ---------- */
.wa-float {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  width: 60px;
  height: 60px;
  border-radius: 9999px;
  background: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 30px -8px rgba(206, 71, 0, 0.55), 0 2px 8px rgba(5, 24, 38, 0.35);
  transition: transform .2s var(--ease-out), box-shadow .2s ease, background-color .2s ease;
  animation: wa-float-in 500ms var(--ease-out) 1.3s backwards;
}
.wa-float:active {
  transform: scale(0.94);
}
@media (hover: hover) and (pointer: fine) {
  .wa-float:hover {
    transform: translateY(-3px) scale(1.05);
    background: var(--accent-hover);
    box-shadow: 0 16px 34px -8px rgba(222, 83, 16, 0.65), 0 2px 8px rgba(5, 24, 38, 0.4);
  }
}
@keyframes wa-float-in {
  from { opacity: 0; transform: scale(0.75) translateY(16px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
.wa-float::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 9999px;
  background: var(--accent);
  animation: wa-pulse 2.6s cubic-bezier(.4,0,.6,1) infinite;
  z-index: -1;
}
@media (max-width: 640px) {
  .wa-float { right: 14px; bottom: 14px; width: 54px; height: 54px; }
}
@keyframes wa-pulse {
  0% { transform: scale(1); opacity: .55; }
  70% { transform: scale(1.7); opacity: 0; }
  100% { transform: scale(1.7); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .wa-float::before { animation: none; }
}

/* Ampliación de WiFi: entre md y lg, la columna fija de 440px deja muy poco
   aire para el texto. Achicamos imagen y gap en esa franja; desde lg vuelve
   al layout de dos columnas amplio. */
@media (min-width: 768px) and (max-width: 1023.98px) {
  .wifi-amp-grid {
    grid-template-columns: minmax(0, 320px) 1fr;
    gap: 2rem;
  }
}

/* ---------- Router illustration glow ---------- */
.equip-glow {
  filter: drop-shadow(0 20px 45px rgba(74, 159, 220, 0.4));
}

/* ---------- Router: anillos de señal WiFi emitiéndose ----------
   Mismo lenguaje que el pulso del flotante de WhatsApp: anillos detrás
   del elemento (z-index negativo), teñidos con el azul de "Señal" de
   marca, nunca naranja (el naranja queda reservado para la acción). */
.wifi-emit {
  position: relative;
  isolation: isolate;
}
.wifi-emit .wifi-ring {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 58%;
  aspect-ratio: 1;
  border-radius: 9999px;
  border: 1.5px solid rgba(113, 180, 227, 0.55);
  opacity: 0;
  z-index: -1;
  animation: wifi-ring-emit 3.6s var(--ease-in-out) infinite;
}
.wifi-emit .wifi-ring:nth-child(2) { animation-delay: 1.15s; }
.wifi-emit .wifi-ring:nth-child(3) { animation-delay: 2.3s; }
.wifi-emit .wifi-ground {
  position: absolute;
  left: 50%;
  bottom: 3%;
  width: 68%;
  height: 16%;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(5, 24, 38, 0.5), transparent 75%);
  z-index: -2;
}
@keyframes wifi-ring-emit {
  0%   { transform: scale(0.6); opacity: 0; }
  14%  { opacity: 0.7; }
  100% { transform: scale(1.9); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .wifi-emit .wifi-ring { animation: none; opacity: 0; }
}

/* ---------- Marquee (town strip) ---------- */
@keyframes marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
.marquee-track {
  animation: marquee 32s linear infinite;
}
.marquee-wrap:hover .marquee-track {
  animation-play-state: paused;
}
/* Difumina los extremos para que el texto no corte de forma abrupta */
.marquee-wrap {
  mask-image: linear-gradient(90deg, transparent, black 10%, black 90%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, black 10%, black 90%, transparent);
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .reveal { transition: none; opacity: 1; transform: none; filter: none; }
  .speed-fill { transition: none; }
  .marquee-track { animation: none; }
}
