/* GALLOS MEDIA — section components */

const gmIcons = {
  arrow: (props) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.5" {...props}>
      <path d="M5 12h14M13 6l6 6-6 6"/>
    </svg>
  ),
  arrowDown: (props) => (
    <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.5" {...props}>
      <path d="M12 5v14M6 13l6 6 6-6"/>
    </svg>
  ),
  mail: (props) => (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" {...props}>
      <rect x="2.5" y="4.5" width="19" height="15" rx="2"/>
      <path d="M3 6.5l9 6 9-6"/>
    </svg>
  ),
  phone: (props) => (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" {...props}>
      <path d="M6.5 3.5h3l1.5 4-2 1.4a12 12 0 0 0 5.1 5.1l1.4-2 4 1.5v3a2 2 0 0 1-2.2 2A16.5 16.5 0 0 1 4.5 5.7 2 2 0 0 1 6.5 3.5z"/>
    </svg>
  ),
};

/* ---------- CARRUSEL DE FRAMES (auto-deslizante) ---------- */
function ProjectCarousel({ frames, alt, interval = 3600, dots = false }) {
  const safe = frames && frames.length ? frames : [];
  const [idx, setIdx] = React.useState(0);
  // fase aleatoria para que no cambien todos a la vez
  const phase = React.useRef(Math.floor(Math.random() * 1800));

  React.useEffect(() => {
    if (safe.length <= 1) return;
    let id;
    const start = setTimeout(() => {
      id = setInterval(() => setIdx(i => (i + 1) % safe.length), interval);
    }, phase.current);
    return () => { clearTimeout(start); clearInterval(id); };
  }, [safe.length, interval]);

  if (!safe.length) return <div className="gm-carousel empty">SIN FRAMES</div>;

  return (
    <div className="gm-carousel">
      {safe.map((src, i) => (
        <img
          key={i}
          src={src}
          alt={i === 0 ? (alt || '') : ''}
          className={'gm-slide' + (i === idx ? ' on' : '')}
          loading="lazy"
          draggable="false"
        />
      ))}
      {dots && safe.length > 1 && (
        <div className="gm-dots" aria-hidden="true">
          {safe.map((_, i) => <i key={i} className={i === idx ? 'on' : ''} />)}
        </div>
      )}
    </div>
  );
}

/* ---------- LIGHTBOX DESPLEGABLE ---------- */
function ProjectLightbox({ project, onClose }) {
  React.useEffect(() => {
    if (!project) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => { document.removeEventListener('keydown', onKey); document.body.style.overflow = ''; };
  }, [project]);

  if (!project) return null;
  return (
    <div className="gm-lightbox" onClick={onClose}>
      <button className="gm-lb-close" aria-label="Cerrar" onClick={onClose}>✕</button>
      <div className="gm-lb-inner" onClick={(e) => e.stopPropagation()}>
        <div className="gm-lb-media">
          <ProjectCarousel frames={project.frames} alt={project.title} interval={2600} dots />
          <div className="grain-overlay"></div>
        </div>
        <div className="gm-lb-meta">
          <span className="sec-label">{project.genre}</span>
          <h3>{project.title}</h3>
          {project.synopsis && <p className="synopsis">{project.synopsis}</p>}
          <div className="ymeta">{project.year} · {project.genre}</div>
          {project.video && (
            <div className="gm-lb-watch">
              <span className="gm-lb-prompt">¿Deseas ver el video?</span>
              <a className="gm-lb-cta" href={project.video} target="_blank" rel="noreferrer" data-interactive>
                <span>Ver video</span>
                <span className="arr" aria-hidden="true">↗</span>
              </a>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ---------- BOTÓN FLOTANTE DE WHATSAPP ---------- */
function WhatsAppFab() {
  const msg = encodeURIComponent('Hola GALLOS MEDIA, me interesa platicar sobre un proyecto.');
  return (
    <a
      className="wa-fab"
      href={`https://wa.me/526646961560?text=${msg}`}
      target="_blank"
      rel="noreferrer"
      aria-label="Escríbenos por WhatsApp"
      data-interactive
    >
      <span className="wa-pulse" aria-hidden="true"></span>
      <svg viewBox="0 0 24 24" width="30" height="30" fill="currentColor" aria-hidden="true">
        <path d="M.057 24l1.687-6.163c-1.041-1.804-1.588-3.849-1.587-5.946.003-6.556 5.338-11.891 11.893-11.891 3.181.001 6.167 1.24 8.413 3.488 2.245 2.248 3.481 5.236 3.48 8.414-.003 6.557-5.338 11.892-11.893 11.892-1.99-.001-3.951-.5-5.688-1.448l-6.305 1.654zm6.597-3.807c1.676.995 3.276 1.591 5.392 1.592 5.448 0 9.886-4.434 9.889-9.885.002-5.462-4.415-9.89-9.881-9.892-5.452 0-9.887 4.434-9.889 9.884-.001 2.225.651 3.891 1.746 5.634l-.999 3.648 3.742-.981zm11.387-5.464c-.074-.124-.272-.198-.57-.347-.297-.149-1.758-.868-2.031-.967-.272-.099-.47-.149-.669.149-.198.297-.768.967-.941 1.165-.173.198-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.5-.669-.51l-.57-.01c-.198 0-.521.074-.792.372s-1.04 1.016-1.04 2.479 1.065 2.876 1.213 3.074c.149.198 2.095 3.2 5.076 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413z"/>
      </svg>
    </a>
  );
}

/* ---------- HEADER ---------- */
function Header({ activeSection, onOpenMobile }) {
  const [scrolled, setScrolled] = React.useState(false);
  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 60);
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  const items = [
    { id: 'proyectos', label: 'PROYECTOS', href: '/proyectos' },
    { id: 'servicios', label: 'SERVICIOS', href: '/servicios' },
    { id: 'sobre-nosotros', label: 'SOBRE NOSOTROS', href: '/nosotros' },
  ];

  return (
    <header className={'header' + (scrolled ? ' scrolled' : '')}>
      <div className="header-inner">
        <a href="/inicio" className="logo-lockup" aria-label="GALLOS MEDIA — Inicio">
          <img src="assets/logo-mark-white.png" className="logo-mark" alt="" aria-hidden="true" />
          <span className="logo-word">
            <span className="lw-top">GALLOS</span>
            <span className="lw-bot">MEDIA</span>
          </span>
        </a>
        <nav className="nav">
          {items.map(it => (
            <a key={it.id} href={it.href} className={'nav-link' + (activeSection === it.id ? ' active' : '')}>
              {it.label}
            </a>
          ))}
        </nav>
        <a href="/contacto" className="cta-outline cta-stack">
          <span className="cta-lines">
            <span>Contáctanos</span>
            <span>para iniciar tu proyecto</span>
          </span>
          <span className="arr"><gmIcons.arrow /></span>
        </a>
        <button className="hamburger" aria-label="Abrir menú" onClick={onOpenMobile}>
          <span></span><span></span><span></span>
        </button>
      </div>
    </header>
  );
}

/* ---------- NAV COMPLETO REUTILIZABLE (header + menú móvil) ----------
   Se usa en todas las páginas para tener siempre el menú principal. */
function SiteNav({ active }) {
  const [mobileOpen, setMobileOpen] = React.useState(false);
  React.useEffect(() => {
    const h = document.querySelector('.hamburger');
    if (h) h.classList.toggle('open', mobileOpen);
  }, [mobileOpen]);
  return (
    <>
      <Header activeSection={active} onOpenMobile={() => setMobileOpen(o => !o)} />
      <MobileOverlay open={mobileOpen} active={active} onClose={() => setMobileOpen(false)} />
    </>
  );
}

function MobileOverlay({ open, active, onClose }) {
  React.useEffect(() => {
    if (open) document.body.style.overflow = 'hidden';
    else document.body.style.overflow = '';
    return () => { document.body.style.overflow = ''; };
  }, [open]);

  // Cierra con Escape
  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  const items = [
    { id: 'inicio', label: 'Inicio', href: '/inicio' },
    { id: 'proyectos', label: 'Proyectos', href: '/proyectos' },
    { id: 'servicios', label: 'Servicios', href: '/servicios' },
    { id: 'sobre-nosotros', label: 'Sobre Nosotros', href: '/nosotros' },
  ];
  return (
    <div className={'mobile-overlay' + (open ? ' open' : '')} aria-hidden={!open}>
      <button className="mobile-close" aria-label="Cerrar menú" onClick={onClose}>
        <span></span><span></span>
      </button>
      <nav className="mobile-nav">
        {items.map((it, i) => (
          <a
            key={it.id}
            href={it.href}
            className={'mob-link' + (active === it.id ? ' active' : '')}
            style={{ transitionDelay: `${80 + i * 55}ms` }}
            onClick={onClose}
          >
            <span className="mob-idx">{String(i + 1).padStart(2, '0')}</span>
            <span className="mob-txt">{it.label}</span>
            <span className="mob-arr" aria-hidden="true"><gmIcons.arrow /></span>
          </a>
        ))}
      </nav>
      <a className="mobile-cta" href="/contacto" onClick={onClose}>
        <span>Contáctanos para iniciar tu proyecto</span>
        <span className="arr"><gmIcons.arrow /></span>
      </a>
    </div>
  );
}

/* ---------- MOSAICO DE FONDO DEL HERO (frames que cambian como TV) ---------- */
function MosaicTile({ src }) {
  // mantiene la imagen vieja debajo y funde la nueva encima (cambio tipo "canal")
  const [stack, setStack] = React.useState([{ key: 0, src }]);
  const keyRef = React.useRef(0);
  React.useEffect(() => {
    if (!src || stack[stack.length - 1].src === src) return;
    keyRef.current += 1;
    const next = { key: keyRef.current, src };
    setStack(s => [...s, next].slice(-2));
    const t = setTimeout(() => setStack([next]), 800); // limpia la capa vieja tras el fundido
    return () => clearTimeout(t);
  }, [src]);

  return stack.map((layer, i) => (
    <img
      key={layer.key}
      src={layer.src}
      className={'mtile' + (i === stack.length - 1 ? ' top' : '')}
      alt=""
      loading="lazy"
      draggable="false"
    />
  ));
}

function HeroMosaic({ tiles = 24, swapEvery = 420 }) {
  // todos los frames de todos los proyectos, en una sola lista
  const all = React.useMemo(
    () => (window.GM_PROJECTS || []).flatMap(p => p.frames),
    []
  );

  // rejilla inicial SIN imágenes repetidas (baraja y toma las primeras `tiles`)
  const initGrid = React.useCallback(() => {
    const pool = all.slice();
    for (let i = pool.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [pool[i], pool[j]] = [pool[j], pool[i]];
    }
    return pool.slice(0, Math.min(tiles, pool.length));
  }, [all, tiles]);

  const [grid, setGrid] = React.useState(() => (all.length ? initGrid() : []));

  React.useEffect(() => {
    // necesitamos más imágenes que celdas para mantener todo distinto
    if (all.length <= tiles) return;
    const id = setInterval(() => {
      setGrid(g => {
        const used = new Set(g);
        // candidatas = imágenes que NO están ya en la rejilla (evita repetidos)
        const candidates = all.filter(s => !used.has(s));
        if (!candidates.length) return g;
        const n = g.slice();
        const i = Math.floor(Math.random() * n.length);
        n[i] = candidates[Math.floor(Math.random() * candidates.length)];
        return n; // siempre quedan 24 imágenes únicas -> nunca dos iguales, ni juntas
      });
    }, swapEvery);
    return () => clearInterval(id);
  }, [all, tiles, swapEvery]);

  if (!grid.length) return <div className="reel" aria-hidden="true"></div>;

  return (
    <div className="reel reel-mosaic" aria-hidden="true">
      {grid.map((src, i) => (
        <div className="cell" key={i}>
          <MosaicTile src={src} />
        </div>
      ))}
    </div>
  );
}

/* ---------- HERO ---------- */
function Hero() {
  return (
    <section id="inicio" className="hero" data-screen-label="01 Inicio">
      <div className="hero-bg" aria-hidden="true">
        <HeroMosaic />
        <div className="grain"></div>
      </div>

      <div className="hero-content">
        <h1 className="hero-headline">
          <span>Productora creativa</span>
          <span>impulsada por IA,</span>
          <span>piloteada por</span>
          <span className="red">humanos.</span>
        </h1>
        <p className="hero-manifesto">
          Productora de nueva generación, totalmente impulsada por inteligencia artificial y ejecutada por manos humanas. Unimos visión cinematográfica e IA para crear piezas que cuentan historias.
        </p>
      </div>

      <div className="scroll-indicator" aria-hidden="true">
        <span className="word">SCROLL</span>
        <span className="line"></span>
      </div>

      <div className="hero-bottom">
        <div className="ticker" aria-hidden="true">
          <div className="ticker-track">
            <TickerContent /><TickerContent />
          </div>
        </div>
      </div>
    </section>
  );
}

function TickerContent() {
  const items = [
    'PRODUCCIÓN CINEMATOGRÁFICA',
    'CONTENIDO VERTICAL',
    'EXPERIENCIAS INTERACTIVAS',
    'BRANDING',
    'DIRECCIÓN CREATIVA',
  ];
  return (
    <>
      {items.map((s, i) => (
        <React.Fragment key={i}>
          <span>{s}</span>
          <span className="sep">✦</span>
        </React.Fragment>
      ))}
    </>
  );
}

/* ---------- PROYECTOS ---------- */
function Proyectos() {
  const [open, setOpen] = React.useState(null);
  // Destacados desde data.jsx; se empacan por ancho (span) en filas de 12 columnas,
  // así un span-12 (p. ej. La Perrona) ocupa su propia fila y el resto se empareja.
  const featured = (window.GM_FEATURED || []);
  const spanOf = (p) => parseInt((p.span || 'span-6').replace('span-', ''), 10) || 6;
  const rows = [];
  let row = [], used = 0;
  featured.forEach((p) => {
    const w = spanOf(p);
    if (used + w > 12) { rows.push(row); row = []; used = 0; }
    row.push(p); used += w;
  });
  if (row.length) rows.push(row);

  return (
    <section id="proyectos" className="section-pad" data-screen-label="02 Proyectos">
      <div className="container">
        <div className="sec-head reveal">
          <div className="lhs">
            <h2 className="display display-lg">Nuestro<br/>trabajo.</h2>
          </div>
          <div className="rhs">
            Una muestra de proyectos donde dirección, ejecución y narrativa se encuentran. Cada pieza es desarrollada como un objeto en sí mismo, algo que aguante el paso del tiempo y conecte hoy.
          </div>
        </div>

        <div className="projects-grid">
          {rows.map((row, ri) => (
            <div className="projects-row" key={ri}>
              {row.map((p, i) => (
                <article
                  key={p.slug}
                  className={`project ${p.span || 'span-6'} ${p.vertical ? 'vertical' : ''} ${p.size || ''} reveal`}
                  style={{transitionDelay: `${i*60}ms`}}
                  onClick={() => setOpen(p)}
                >
                  <div className="thumb">
                    <div className="play-art" style={{position:'absolute', inset:0}}>
                      <ProjectCarousel frames={p.frames} alt={p.title} />
                      <div className="grain-overlay"></div>
                    </div>
                    {p.detail === 'rec' && <div className="frame-rec" aria-hidden="true"></div>}
                    {p.detail === 'tc' && <div className="frame-tc">{p.tc}</div>}
                    <div className="year">{p.year}</div>
                  </div>
                  <div className="meta">
                    <h3>{p.title}</h3>
                    <p className="synopsis">{p.synopsis}</p>
                    <div className="ymeta">{p.year} · {p.genre}</div>
                  </div>
                </article>
              ))}
            </div>
          ))}
        </div>

        <div className="section-cta reveal">
          <a href="/proyectos" className="cta-outline" style={{padding:'22px 40px'}}>
            <span>VER TRABAJO COMPLETO</span>
            <span className="arr"><gmIcons.arrow /></span>
          </a>
        </div>
      </div>

      <ProjectLightbox project={open} onClose={() => setOpen(null)} />
    </section>
  );
}

/* ---------- ENLACE DE CORREO (cross-platform) ----------
   Abre el proveedor de correo predeterminado (mailto) en cualquier sistema.
   Además copia la dirección al portapapeles como respaldo para equipos
   (p. ej. Windows) que no tengan un cliente de correo configurado. */
const GM_EMAIL = 'david@gallosmedia.com';
function MailLink() {
  const [copied, setCopied] = React.useState(false);
  const onClick = () => {
    try {
      if (navigator.clipboard) {
        navigator.clipboard.writeText(GM_EMAIL).then(() => {
          setCopied(true);
          setTimeout(() => setCopied(false), 2400);
        }).catch(() => {});
      }
    } catch (e) { /* sin portapapeles: el mailto sigue funcionando */ }
    // No prevenimos el default: el navegador abre el correo predeterminado.
  };
  return (
    <a className="contact-line" href={`mailto:${GM_EMAIL}`} onClick={onClick} data-interactive>
      <span className="cl-ico" aria-hidden="true"><gmIcons.mail /></span>
      <span className="cl-text">
        <span className="cl-label">{copied ? '✓ Correo copiado' : 'Escríbenos'}</span>
        <span className="cl-value">{GM_EMAIL}</span>
      </span>
      <span className="cl-arr arr" aria-hidden="true"><gmIcons.arrow /></span>
    </a>
  );
}

function ContactDirect({ center = false }) {
  return (
    <div className={'contact-direct reveal' + (center ? ' is-center' : '')}>
      <MailLink />
      <a className="contact-line" href="tel:+526646961560" data-interactive>
        <span className="cl-ico" aria-hidden="true"><gmIcons.phone /></span>
        <span className="cl-text">
          <span className="cl-label">Llámanos</span>
          <span className="cl-value">+52 664 696 1560</span>
        </span>
        <span className="cl-arr arr" aria-hidden="true"><gmIcons.arrow /></span>
      </a>
    </div>
  );
}

/* ---------- CONTACTO ---------- */
function Contacto() {
  return (
    <section id="contacto" className="contact section-pad has-bg-photo" data-screen-label="05 Contacto">
      <img className="contact-bg" src="assets/tienes%20un%20proyecto.jpg" alt="" aria-hidden="true" decoding="async" />
      <div className="container">
        <div className="sec-head reveal">
          <div>
            <span className="sec-label">— EMPECEMOS</span>
            <h2 style={{marginTop:24}}>¿Tienes un proyecto?</h2>
            <p className="subhead">Escríbenos. Respondemos en menos de 24 horas.</p>
          </div>
        </div>

        <ContactDirect />
      </div>
    </section>
  );
}

/* ---------- FONDO DE HUMO / VAPOR / POLVO INTERACTIVO ----------
   Bocanadas suaves (sprites pre-renderizados) que suben como vapor, se
   mueven en remolino y son revueltas por el cursor. Composición 'lighter'
   para que el humo se acumule y sea visible. Respeta prefers-reduced-motion. */
function makePuff(tint) {
  // sprite radial suave, pre-teñido (más rápido que crear gradientes por frame)
  const s = document.createElement('canvas');
  s.width = s.height = 128;
  const c = s.getContext('2d');
  const g = c.createRadialGradient(64, 64, 0, 64, 64, 64);
  g.addColorStop(0, `rgba(${tint},0.95)`);
  g.addColorStop(0.35, `rgba(${tint},0.45)`);
  g.addColorStop(1, `rgba(${tint},0)`);
  c.fillStyle = g;
  c.beginPath(); c.arc(64, 64, 64, 0, Math.PI * 2); c.fill();
  return s;
}

function DustField() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let w = 0, h = 0, dpr = 1, parts = [], raf = 0, t = 0;
    const mouse = { x: -9999, y: -9999, on: false };
    const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

    // dos texturas: humo cálido (polvo de tierra) y brasa roja (marca)
    const sprSmoke = makePuff('190,178,165');
    const sprRed = makePuff('224,46,32');

    const make = () => ({
      x: Math.random() * w,
      y: Math.random() * h,
      vx: (Math.random() - 0.5) * 0.25,
      vy: (Math.random() - 0.5) * 0.25,
      r: Math.random() * 70 + 36,           // radio de la bocanada
      a: Math.random() * 0.16 + 0.05,       // opacidad base
      red: Math.random() < 0.16,            // algunas brasas rojas
      seed: Math.random() * 1000,
    });

    const resize = () => {
      dpr = Math.min(window.devicePixelRatio || 1, 2);
      w = canvas.clientWidth; h = canvas.clientHeight;
      canvas.width = Math.max(1, w * dpr);
      canvas.height = Math.max(1, h * dpr);
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      const count = Math.min(90, Math.max(28, Math.floor(w * h * 0.00006)));
      parts = Array.from({ length: count }, make);
    };

    const draw = () => {
      t += 0.0045;
      ctx.clearRect(0, 0, w, h);
      ctx.globalCompositeOperation = 'lighter';
      for (const p of parts) {
        // flujo orgánico (remolino tipo humo)
        p.vx += Math.sin(p.y * 0.006 + t + p.seed) * 0.02;
        p.vy += Math.cos(p.x * 0.006 + t + p.seed) * 0.02;
        p.vy -= 0.006; // ligera subida (vapor)

        // interacción con el cursor: empuje + giro perpendicular
        if (mouse.on) {
          const dx = p.x - mouse.x, dy = p.y - mouse.y;
          const d2 = dx * dx + dy * dy;
          const R = 230;
          if (d2 < R * R) {
            const d = Math.sqrt(d2) || 1;
            const f = (1 - d / R) * 1.6;
            p.vx += (dx / d) * f - (dy / d) * f * 0.5;
            p.vy += (dy / d) * f + (dx / d) * f * 0.5;
          }
        }

        p.x += p.vx; p.y += p.vy;
        p.vx *= 0.93; p.vy *= 0.93;

        // reaparece por el lado opuesto
        const m = p.r;
        if (p.x < -m) p.x = w + m; else if (p.x > w + m) p.x = -m;
        if (p.y < -m) p.y = h + m; else if (p.y > h + m) p.y = -m;

        ctx.globalAlpha = p.a;
        const spr = p.red ? sprRed : sprSmoke;
        ctx.drawImage(spr, p.x - p.r, p.y - p.r, p.r * 2, p.r * 2);
      }
      ctx.globalAlpha = 1;
      ctx.globalCompositeOperation = 'source-over';
      raf = requestAnimationFrame(draw);
    };

    const onMove = (e) => {
      const r = canvas.getBoundingClientRect();
      mouse.x = e.clientX - r.left;
      mouse.y = e.clientY - r.top;
      mouse.on = e.clientY >= r.top && e.clientY <= r.bottom;
    };
    const onLeave = () => { mouse.on = false; };

    resize();
    window.addEventListener('resize', resize);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('blur', onLeave);
    if (reduce) { draw(); cancelAnimationFrame(raf); } else { draw(); }

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('resize', resize);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('blur', onLeave);
    };
  }, []);

  return <canvas ref={ref} className="dust-canvas" aria-hidden="true" />;
}

/* ---------- FOOTER ---------- */
function Footer({ home = '' }) {
  // en otras páginas (catálogo) los enlaces deben volver a la home + sección
  return (
    <footer className="footer" data-screen-label="06 Footer">
      <div className="container">
        <div className="footer-grid">
          <div>
            <img src="assets/logo-mark-white.png" alt="GALLOS" className="footer-iso" />
            <p className="footer-tag">Productora creativa impulsada por IA, piloteada por humanos.</p>
          </div>
          <div className="footer-col">
            <h4>Navegación</h4>
            <ul>
              <li><a href="/inicio">Inicio</a></li>
              <li><a href="/proyectos">Proyectos</a></li>
              <li><a href="/servicios">Servicios</a></li>
              <li><a href="/nosotros">Sobre Nosotros</a></li>
              <li><a href="/contacto">Contacto</a></li>
            </ul>
          </div>
          <div className="footer-col">
            <h4>Síguenos</h4>
            <ul>
              <li><a href="https://www.instagram.com/gallos.media/" target="_blank" rel="noreferrer">Instagram <span className="arr">↗</span></a></li>
              <li><a href="https://www.tiktok.com/@gallos.media" target="_blank" rel="noreferrer">TikTok <span className="arr">↗</span></a></li>
              <li><a href="https://wa.me/526646961560" target="_blank" rel="noreferrer">WhatsApp <span className="arr">↗</span></a></li>
            </ul>
          </div>
        </div>
      </div>

      <div className="megaword" aria-hidden="true">GALLOS MEDIA</div>

      <div className="container">
        <div className="footer-bottom">
          <div>© 2026 GALLOS MEDIA — TODOS LOS DERECHOS RESERVADOS</div>
        </div>
      </div>
    </footer>
  );
}

Object.assign(window, { Header, MobileOverlay, SiteNav, Hero, Proyectos, Contacto, ContactDirect, MailLink, DustField, Footer, ProjectCarousel, ProjectLightbox, WhatsAppFab });
