/* ========== La Chismosa components v2 ========== */

/* ---------- i18n (ES / EN) ---------- */
const LANG_KEY = "lachismosa-lang";
function getLang() {
  try { return localStorage.getItem(LANG_KEY) === "en" ? "en" : "es"; }
  catch (e) { return "es"; }
}
function setLang(l) {
  try { localStorage.setItem(LANG_KEY, l); } catch (e) {}
  document.documentElement.lang = l;
  window.dispatchEvent(new Event("langchange"));
}
// Devuelve la cadena según el idioma actual. Uso: t("Hola", "Hello")
function t(es, en) { return getLang() === "en" ? en : es; }
// Hook: suscribe el componente a cambios de idioma para que se vuelva a renderizar.
function useLang() {
  const [lang, setL] = React.useState(getLang());
  React.useEffect(() => {
    const h = () => setL(getLang());
    window.addEventListener("langchange", h);
    document.documentElement.lang = getLang();
    return () => window.removeEventListener("langchange", h);
  }, []);
  return lang;
}

/* ---------- Flecha noreste ↗ (reutilizable) ---------- */
function ArrowNE({ size = 18 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 18 18" fill="none"
         style={{ display: "inline-block", flexShrink: 0, verticalAlign: "middle" }}
         aria-hidden="true">
      <path d="M4 14L14 4M14 4H6M14 4V12"
            stroke="currentColor" strokeWidth="1.5"
            strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

/* ---------- Custom Cursor — trazo crayón en página ---------- */
/* ---------- Custom Cursor — punto + anillo elegante ---------- */
function Cursor() {
  const ringRef = React.useRef(null);
  const dotRef  = React.useRef(null);

  React.useEffect(() => {
    if (!window.matchMedia || !window.matchMedia("(pointer: fine)").matches) return;
    const ring = ringRef.current, dot = dotRef.current;
    const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    const ease = reduced ? 1 : 0.18;
    const targets = "a, button, input, textarea, [data-cursor], .connect-badge, .lbw-col, .holding-card, .press-card, .ws-card, .carousel-card, .office-item";

    let mx = -100, my = -100, rx = -100, ry = -100, raf, shown = false;
    document.documentElement.classList.add("ec-active");

    const onMove = (e) => {
      mx = e.clientX; my = e.clientY;
      if (!shown) { shown = true; ring.style.opacity = "1"; dot.style.opacity = "1"; }
      dot.style.transform = `translate3d(${mx}px,${my}px,0) translate(-50%,-50%)`;
    };
    const onLeave = () => { shown = false; ring.style.opacity = "0"; dot.style.opacity = "0"; };
    const onOver = (e) => {
      if (e.target.closest && e.target.closest(targets)) ring.classList.add("ec-hover");
    };
    const onOut = (e) => {
      if (e.target.closest && e.target.closest(targets) &&
          !(e.relatedTarget && e.relatedTarget.closest && e.relatedTarget.closest(targets)))
        ring.classList.remove("ec-hover");
    };
    // ¿el fondo bajo el cursor es oscuro/similar al cursor? → cambiar de color
    const bgIsDark = (x, y) => {
      const stack = document.elementsFromPoint(x, y);
      let node = stack.find(el => !el.closest(".ec-ring, .ec-dot, .nav, .connect-badge"));
      while (node && node !== document.body && node !== document.documentElement) {
        const ds = node.dataset && node.dataset.navbg;
        if (ds) return ds === "dark";
        const m = getComputedStyle(node).backgroundColor.match(/rgba?\(([^)]+)\)/);
        if (m) {
          const p = m[1].split(",").map(parseFloat);
          const a = p[3] === undefined ? 1 : p[3];
          if (a >= 0.3) return (0.299 * p[0] + 0.587 * p[1] + 0.114 * p[2]) / 255 < 0.5;
        }
        node = node.parentElement;
      }
      return false;
    };

    let tick = 0;
    const loop = () => {
      rx += (mx - rx) * ease; ry += (my - ry) * ease;
      ring.style.transform = `translate3d(${rx}px,${ry}px,0) translate(-50%,-50%)`;
      if (shown && (tick++ % 6) === 0) {
        document.documentElement.classList.toggle("ec-on-dark", bgIsDark(mx, my));
      }
      raf = requestAnimationFrame(loop);
    };
    loop();
    window.addEventListener("mousemove", onMove, { passive: true });
    window.addEventListener("mouseleave", onLeave);
    document.addEventListener("mouseover", onOver);
    document.addEventListener("mouseout", onOut);
    return () => {
      cancelAnimationFrame(raf);
      document.documentElement.classList.remove("ec-active");
      document.documentElement.classList.remove("ec-on-dark");
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseleave", onLeave);
      document.removeEventListener("mouseover", onOver);
      document.removeEventListener("mouseout", onOut);
    };
  }, []);

  return (
    <>
      <div ref={ringRef} className="ec-ring" />
      <div ref={dotRef}  className="ec-dot" />
    </>
  );
}


/* ---------- Navigation ---------- */
function Nav({ active }) {
  const lang = useLang();
  const [scrolled, setScrolled] = React.useState(false);
  const [invert, setInvert] = React.useState(false);
  const ref = React.useRef(null);

  React.useEffect(() => {
    const decide = () => {
      setScrolled(window.scrollY > 40);
      const nav = ref.current;
      if (!nav) return;
      // ¿Qué hay detrás de la barra? Decidimos texto claro u oscuro según el fondo.
      const els = document.elementsFromPoint(Math.round(window.innerWidth / 2), nav.offsetHeight + 4);
      const target = els.find(el => !el.closest(".nav, .ec-ring, .ec-dot, .connect-badge"));
      let light = false, node = target;
      while (node && node !== document.body && node !== document.documentElement) {
        const ds = node.dataset && node.dataset.navbg;
        if (ds) { light = ds === "light"; break; }
        const m = getComputedStyle(node).backgroundColor.match(/rgba?\(([^)]+)\)/);
        if (m) {
          const p = m[1].split(",").map(parseFloat);
          const a = p[3] === undefined ? 1 : p[3];
          if (a >= 0.3) { light = (0.299 * p[0] + 0.587 * p[1] + 0.114 * p[2]) / 255 > 0.6; break; }
        }
        node = node.parentElement;
      }
      setInvert(light);
    };
    window.addEventListener("scroll", decide, { passive: true });
    window.addEventListener("resize", decide);
    decide();
    return () => {
      window.removeEventListener("scroll", decide);
      window.removeEventListener("resize", decide);
    };
  }, []);

  const links = [
    { id: "home",      label: t("HOME", "HOME"),          href: "La Chismosa.html" },
    { id: "nosotros",  label: t("NOSOTROS", "ABOUT"),     href: "nosotros.html" },
    { id: "servicios", label: t("SERVICIOS", "SERVICES"), href: "servicios.html" },
    { id: "archivo",   label: t("ARCHIVO", "ARCHIVE"),    href: "archivo.html" },
    { id: "contacto",  label: t("CONTACTO", "CONTACT"),   href: "contacto.html" },
  ];

  return (
    <header ref={ref} className={`nav ${scrolled ? "scrolled" : ""}${invert ? " nav-invert" : ""}`}>
      <a className="nav-brand" href="La Chismosa.html">
        <img src="assets/logo-blanco.svg" alt="laChismosa" className="nav-brand-logo" />
      </a>
      <div className="nav-center">
        <nav>
          <ul className="nav-links">
            {links.map((l, i) => (
              <li key={i}>
                <a href={l.href} className={active === l.id ? "active" : ""}>
                  <span>{l.label}</span>
                  <span>{l.label}</span>
                </a>
              </li>
            ))}
          </ul>
        </nav>
        <span className="lang-toggle" role="group" aria-label="Idioma / Language">
          <button type="button" className={lang === "es" ? "on" : "off"}
                  aria-pressed={lang === "es"} onClick={() => setLang("es")}>ES</button>
          <span className="sep"> | </span>
          <button type="button" className={lang === "en" ? "on" : "off"}
                  aria-pressed={lang === "en"} onClick={() => setLang("en")}>EN</button>
        </span>
      </div>
    </header>
  );
}

/* ---------- Intro / persiana ---------- */
function Intro({ onDone }) {
  const N = 10;
  const ref = React.useRef(null);

  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const strips = el.querySelectorAll(".intro-strip");
    const half = N / 2;
    strips.forEach((s, i) => {
      const dist = Math.abs(i - (half - 0.5));
      s.style.setProperty("--d", `${(dist / half) * 0.3}s`);
      s.style.transformOrigin = i < half ? "top center" : "bottom center";
    });
    const t1 = setTimeout(() => el.classList.add("opening"), 900);
    const t2 = setTimeout(() => onDone?.(), 900 + 680 + 300 + 120);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, []);

  return (
    <div ref={ref} className="intro">
      {Array.from({ length: N }).map((_, i) => (
        <div key={i} className="intro-strip" />
      ))}
      <div className="intro-mark">
        <div className="intro-mark-text">
          La <em>Chismosa</em>
        </div>
      </div>
    </div>
  );
}

/* ---------- Invisible ink ---------- */
function InkText({ children }) {
  const ref    = React.useRef(null);
  const heat   = React.useRef(0);
  const rafRef = React.useRef(null);

  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      const dist = Math.hypot(e.clientX - (r.left + r.width / 2), e.clientY - (r.top + r.height / 2));
      const radius = Math.max(r.width * 0.5, 80) + 170;
      const target = Math.max(0, 1 - dist / radius);
      cancelAnimationFrame(rafRef.current);
      const tick = () => {
        heat.current += (target - heat.current) * 0.08;
        el.style.setProperty("--heat", heat.current.toFixed(3));
        if (Math.abs(heat.current - target) > 0.002)
          rafRef.current = requestAnimationFrame(tick);
      };
      tick();
    };
    window.addEventListener("mousemove", onMove, { passive: true });
    return () => { window.removeEventListener("mousemove", onMove); cancelAnimationFrame(rafRef.current); };
  }, []);

  return <span ref={ref} className="ink">{children}</span>;
}

/* ---------- Redacted text ---------- */
function Redacted({ children, delay = 0 }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    el.style.setProperty("--rd", `${delay}s`);
    const io = new IntersectionObserver(([entry]) => {
      if (!entry.isIntersecting) return;
      io.disconnect();
      el.classList.add("revealed");
    }, { threshold: 0.9, rootMargin: "0px 0px -120px 0px" });
    io.observe(el);
    return () => io.disconnect();
  }, [delay]);
  return (
    <span ref={ref} className="redacted">
      {children}
      <span className="redacted-bar" aria-hidden="true" />
    </span>
  );
}

/* ---------- HERO V2 — Bloque 1 ---------- */
// Posición y radio del sello dentro del frame del vídeo, normalizados (0–1 sobre el ancho).
// Como el vídeo se recorta con object-fit:cover, calculamos dónde cae el sello en cada
// viewport (escritorio, tablet, móvil) en lugar de fijar porcentajes por media query.
const HERO_SEAL = { x: 0.486, y: 0.579, r: 0.019 };

function Hero() {
  const lang = useLang();
  const heroRef = React.useRef(null);
  const videoRef = React.useRef(null);
  const openRef = React.useRef(null);
  const [opened, setOpened] = React.useState(false);

  // Sitúa el botón sobre el sello calculando el recorte cover del vídeo en este viewport.
  React.useEffect(() => {
    const place = () => {
      const sec = heroRef.current, btn = openRef.current, v = videoRef.current;
      if (!sec || !btn || !v) return;
      const vr = v.getBoundingClientRect();            // área real del elemento vídeo
      const sr = sec.getBoundingClientRect();          // para coords relativas a la sección
      const W = vr.width, H = vr.height;
      const vw = v.videoWidth  || 3840;
      const vh = v.videoHeight || 2160;
      const scale = Math.max(W / vw, H / vh);          // object-fit: cover
      const dispW = vw * scale, dispH = vh * scale;
      const offX = (W - dispW) / 2, offY = (H - dispH) / 2;
      // Horizontalmente lo dejamos centrado en pantalla (como el indicador SCROLL);
      // el área es grande y el sello —casi centrado— queda holgadamente dentro.
      const yInVideo = offY + HERO_SEAL.y * dispH;
      btn.style.top = (vr.top - sr.top + yInVideo) + "px";
      btn.style.setProperty("--seal-r", (HERO_SEAL.r * dispW) + "px");
    };
    place();
    window.addEventListener("resize", place);
    const v = videoRef.current;
    if (v) v.addEventListener("loadedmetadata", place);
    return () => {
      window.removeEventListener("resize", place);
      if (v) v.removeEventListener("loadedmetadata", place);
    };
  }, [opened]);

  // El vídeo arranca pausado en el primer frame: no se reproduce hasta pulsar ABRIR.
  React.useEffect(() => {
    const v = videoRef.current;
    if (!v) return;
    v.muted = true;
    const hold = () => { v.pause(); v.currentTime = 0; };
    hold();
    v.addEventListener("loadeddata", hold, { once: true });
    return () => v.removeEventListener("loadeddata", hold);
  }, []);

  // Abrir el sobre: reproduce el vídeo de fondo del hero (en color y con sonido).
  const abrirSobre = () => {
    const v = videoRef.current;
    if (v) {
      v.muted = false;
      v.currentTime = 0;
      v.play().catch(() => { v.muted = true; v.play().catch(() => {}); });
    }
    setOpened(true);
  };

  // Al terminar el vídeo: se detiene, vuelve al primer frame y reaparece el botón.
  const alTerminar = () => {
    const v = videoRef.current;
    if (v) { v.pause(); v.currentTime = 0; }
    setOpened(false);
  };

  return (
    <section id="top" ref={heroRef}
             className={"hero-v2" + (opened ? " is-opened" : "")} data-navbg="dark">
      <div className="hero-v2-bg">
        <video
          ref={videoRef}
          src="assets/la-chismosa-hero.mp4"
          playsInline preload="auto"
          onEnded={alTerminar}
          style={{ width: "100%", height: "100%", objectFit: "cover" }}
        />
        <div className="hero-v2-dark" />
      </div>
      {!opened && (
        <button ref={openRef} className="hero-open" onClick={abrirSobre} aria-label={t("Abrir el sobre y reproducir el vídeo", "Open the envelope and play the video")}>
          <span className="hero-open-indicator" aria-hidden="true">
            <span className="hero-open-line"></span>
            <span className="hero-open-text">{t("Abrir", "Open")}</span>
          </span>
        </button>
      )}
      <button className="hero-scroll" aria-label={t("Desliza hacia abajo", "Scroll down")}
              onClick={() => window.scrollTo({ top: Math.round(window.innerHeight * 0.9), behavior: "smooth" })}>
        <span className="hero-scroll-text">SCROLL</span>
        <span className="hero-scroll-line" aria-hidden="true"></span>
      </button>
    </section>
  );
}

/* ---------- Bloque 2 — Vídeo & Quote ---------- */
function VideoQuote() {
  const lang = useLang();
  return (
    <section className="vq-section">
      <div className="vq-left">
        <div className="vq-left-bg">
          <img src="assets/tulipanes.jpg" alt="" />
          <div className="vq-left-overlay" />
        </div>
        <div className="vq-left-content">
          <h2 className="vq-heading">
            {t("Todo", "It all")}<br />{t("empieza", "begins")}<br />{t("con una conversación.", "with a conversation.")}
          </h2>
          <p className="vq-body">
            {t("Y nos encargamos de", "And we make sure")}<br />{t("que nadie la ignore", "no one ignores it")}
          </p>
          <a href="#contacto" className="vq-cta">
            <span>{t("¿HABLAMOS?", "SHALL WE TALK?")}</span>
            <ArrowNE size={20} />
          </a>
        </div>
      </div>
      <div className="vq-right">
        <img src="assets/camara-foto.jpg" alt="" className="vq-right-img" />
        <div className="vq-right-blend" />
      </div>
    </section>
  );
}

/* ---------- Bloque 3 — Nosotras ---------- */
function Manifesto() {
  const lang = useLang();
  return (
    <section id="nosotros" className="manifesto">
      <div className="manifesto-inner">
        <div className="manifesto-label-v2">| {t("NOSOTRAS", "ABOUT US")}</div>
        <div className="manifesto-body">
          <h2 className="display">
            {t("Construimos ", "We build ")}<em style={{ color: "var(--crimson)" }}>{t("narrativas", "narratives")}</em>{t(" para marcas donde el detalle no decora: ", " for brands where detail doesn't decorate: it ")}<em style={{ color: "var(--crimson)" }}>{t("define", "defines")}</em>.
          </h2>
          <div className="manifesto-body-sub">
            <p>
              {t("Somos una agencia de comunicación especializada en hospitality, gastronomía y proyectos con identidad propia. Trabajamos con hoteles, restaurantes y marcas que entienden que hoy la conversación también forma parte de la experiencia.", "We are a communications agency specialized in hospitality, gastronomy and projects with their own identity. We work with hotels, restaurants and brands that understand that today the conversation is also part of the experience.")}
            </p>
            <p>
              {t("A través de estrategia, prensa, influencia y contenido, convertimos marcas en conversaciones que dejan huella. Porque en hospitality, lo que se dice también construye deseo, posicionamiento y cultura.", "Through strategy, press, influence and content, we turn brands into conversations that leave a mark. Because in hospitality, what gets said also builds desire, positioning and culture.")}
            </p>
            <a href="nosotros.html" className="text-link-cta manifesto-cta-btn">
              {t("CONÓCENOS", "ABOUT US")} <ArrowNE />
            </a>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ---------- Bloque 4 — Servicios ---------- */
function Services() {
  const lang = useLang();
  const shiftRef = React.useRef(null);

  // Empujón sutil del scroll: la animación CSS hace el grueso del movimiento;
  // el scroll solo añade un pequeño desplazamiento extra sobre una capa aparte.
  React.useEffect(() => {
    const el = shiftRef.current;
    if (!el) return;
    const AMPLITUDE = 200; // px — empujón del scroll algo más marcado
    let raf = 0;
    const update = () => {
      raf = 0;
      const section = el.closest(".services-v2");
      if (!section) return;
      const rect = section.getBoundingClientRect();
      // progreso 0→1 mientras la sección cruza la ventana
      const raw = (window.innerHeight - rect.top) / (window.innerHeight + rect.height);
      const progress = Math.max(0, Math.min(1, raw));
      el.style.transform = `translateX(-${progress * AMPLITUDE}px)`;
    };
    const onScroll = () => { if (!raf) raf = window.requestAnimationFrame(update); };
    window.addEventListener("scroll", onScroll, { passive: true });
    update();
    return () => {
      window.removeEventListener("scroll", onScroll);
      if (raf) window.cancelAnimationFrame(raf);
    };
  }, []);

  const copy = lang === "en" ?
    "INFLUENCER MARKETING  ·  DIGITAL STRATEGY  ·  EMAIL MARKETING  ·  ONLINE REPUTATION  ·  VISUAL IDENTITY  ·  " :"INFLUENCER MARKETING  ·  ESTRATEGIA DIGITAL  ·  EMAIL MARKETING  ·  ONLINE REPUTATION  ·  IDENTIDAD VISUAL  ·  ";

  return (
    <section id="servicios" className="services-v2">
      <div className="services-v2-inner">
        <div className="services-v2-top">
          <p className="services-v2-label">| {t("SERVICIOS", "SERVICES")}</p>
          <h2 className="services-v2-headline">
            {t("No trabajamos para generar ruido.", "We don't work to make noise.")}<br />
            {t("Trabajamos para generar ", "We work to make ")}<em>{t("impacto", "impact")}</em>.
          </h2>
        </div>
        <div className="services-v2-names">
          <p className="services-v2-name">{t("PRENSA", "PRESS")}</p>
          <div className="services-v2-marquee-wrap">
            <div ref={shiftRef} className="services-v2-marquee-shift">
              <div className="services-v2-marquee-track">
                <span className="services-v2-name">{copy}</span>
                <span className="services-v2-name">{copy}</span>
                <span className="services-v2-name">{copy}</span>
              </div>
            </div>
          </div>
        </div>
        <a href="nosotros.html" className="text-link-cta text-link-cta--light">
          {t("CONÓCENOS", "ABOUT US")} <ArrowNE />
        </a>
      </div>
    </section>
  );
}

/* ---------- Bloque 5 — Imagen a sangre ---------- */
function MapaBlock({ src, height }) {
  return (
    <div className="mapa-block" style={{ height: height + "px" }}>
      <img src={src} alt="" />
    </div>
  );
}

/* ---------- WorldMap — Our Workspaces ---------- */
const OFFICES = [
  { id: "malaga",  city: "Málaga",          type: "Oficina corporativa",      addr: "Hacienda del Mar — Meliá Collection, meeting center", tz: "Europe/Madrid",       img: "assets/maps/malaga.png" },
  { id: "madrid",  city: "Madrid",           type: "Oficinas centrales",        addr: "C/ de Fernando Santos, Chamberí, 27",                tz: "Europe/Madrid",       img: "assets/maps/madrid.png" },
  { id: "cancun",  city: "Cancún",           type: "Área Técnica y Comercial", addr: "Carretera Aeropuerto-Bonfil km 11.5",                 tz: "America/Cancun",      img: "assets/maps/cancun.png" },
  { id: "cdmx",   city: "Ciudad de México", type: "Área Técnica y Comercial", addr: "Campus corporativo de Coyoacán, PB T2",               tz: "America/Mexico_City", img: "assets/maps/mexico-city.png" },
  { id: "brasil",  city: "Brasil",           type: "Área Técnica y Comercial", addr: "São Paulo",                                           tz: "America/Sao_Paulo",   img: "assets/maps/rio-de-janeiro.png" },
  { id: "middle", city: "Middle East",       type: "Coming soon",               addr: "Dubai / Riyadh",                                      tz: null,                  img: "assets/maps/riyadh.png" },
  { id: "miami",  city: "Miami",            type: "Coming soon",               addr: "Miami, FL",                                           tz: null,                  img: "assets/maps/miami.png" },
];

function getStatus(tz) {
  if (!tz) return "soon";
  try {
    const parts = new Intl.DateTimeFormat("en-US", {
      timeZone: tz, hour: "numeric", hour12: false, weekday: "short"
    }).formatToParts(new Date());
    const weekday = parts.find(p => p.type === "weekday")?.value;
    const hour    = parseInt(parts.find(p => p.type === "hour")?.value || "0");
    return (!["Sat","Sun"].includes(weekday) && hour >= 9 && hour < 18) ? "open" : "closed";
  } catch(e) { return "closed"; }
}

function StatusBadge({ status }) {
  useLang();
  if (status === "soon") return React.createElement("span", { className: "status-badge status-soon" }, t("Próximamente", "Coming soon"));
  if (status === "open") return React.createElement("span", { className: "status-badge status-open" },
    React.createElement("span", { className: "status-dot" }), t("Abierto ahora", "Open now")
  );
  return React.createElement("span", { className: "status-badge status-closed" },
    React.createElement("span", { className: "status-dot" }), t("Cerrado", "Closed")
  );
}

const OFFICE_TYPE_EN = {
  "Oficina corporativa": "Corporate office",
  "Oficinas centrales": "Headquarters",
  "Área Técnica y Comercial": "Technical & Commercial Division",
  "Coming soon": "Coming soon",
};
function officeType(type) { return t(type, OFFICE_TYPE_EN[type] || type); }

function WorldMap() {
  const lang = useLang();
  const [active, setActive] = React.useState("malaga");
  const activeIdx = OFFICES.findIndex(o => o.id === active);
  const activeOffice = OFFICES[activeIdx] || OFFICES[0];

  return (
    <section id="proyectos" className="map-section">
      <div className="map-head">
        <div>
          <p className="section-overline">| OUR WORKSPACES</p>
          <h2>{t("Distintas ciudades, una forma de entender ", "Different cities, one way of understanding ")}<em style={{ color: "var(--crimson)" }}>hospitality</em>.</h2>
        </div>
      </div>

      <div className="carousel-wrap">
        <div className="carousel-stage" style={{ height: "720px" }}>
          {OFFICES.map((o, i) => {
            const offset = i - activeIdx;
            const abs    = Math.abs(offset);
            const pos    = abs === 0 ? "center" : abs === 1 ? (offset < 0 ? "left" : "right") : "hidden";
            const status = getStatus(o.tz);
            return (
              <div key={o.id} className={`carousel-card ${pos} ${status === "soon" ? "soon" : ""}`}
                   onClick={() => setActive(o.id)}>
                <div className="carousel-thumb">
                  {o.img && <img src={o.img} alt={o.city} className="carousel-map" />}
                  <div className="carousel-cap">{o.city}</div>
                </div>
                <div className="carousel-meta">
                  <span className="carousel-city">{o.city}</span>
                  <span className="carousel-type">{officeType(o.type)}</span>
                  <span className="carousel-addr">{o.addr}</span>
                </div>
              </div>
            );
          })}
        </div>

        <div className="carousel-side">
          <div className="carousel-side-head">
            <span>{String(activeIdx + 1).padStart(2, "0")} / {String(OFFICES.length).padStart(2, "0")}</span>
            <StatusBadge status={getStatus(activeOffice.tz)} />
          </div>
          <div className="office-list">
            {OFFICES.map(o => {
              const status = getStatus(o.tz);
              return (
                <button key={o.id}
                  className={`office-item ${status === "soon" ? "soon" : ""} ${active === o.id ? "active" : ""}`}
                  onClick={() => setActive(o.id)}
                  onMouseEnter={() => setActive(o.id)}>
                  <div className="row1">
                    <span className="name">{o.city}</span>
                    <StatusBadge status={status} />
                  </div>
                  <div className="office-type">{officeType(o.type)}</div>
                  <div className="addr">{o.addr}</div>
                </button>
              );
            })}
          </div>
        </div>
      </div>
    </section>
  );
}

/* ---------- Bloque 7 — Quote "Y SÍ" ---------- */
function QuoteSection() {
  const lang = useLang();
  return (
    <section id="contacto" className="quote-section">
      <p className="qs-pre">{t("Y SÍ,", "AND YES,")}</p>
      <p className="qs-main">
        {t("Nos ", "We ")}<em>{t("encanta", "love")}</em>{t(" hablar de ti", " talking about you")}
      </p>
      <p className="qs-sub">
        {t("SABEMOS QUE ALGUNAS HISTORIAS", "WE KNOW SOME STORIES")}<br />{t("NACIERON PARA SER CONTADAS", "WERE BORN TO BE TOLD")}
      </p>
      <p className="qs-cta-text">{t("¿Estás listo para contar la tuya?", "Ready to tell yours?")}</p>
    </section>
  );
}

/* ---------- Archivo / Portfolio ---------- */
const PRESS = [
  { meta: "Hospitality · 2025", title: "Relanzamiento de marca para un resort boutique en la Costa del Sol.",       titleEn: "Brand relaunch for a boutique resort on the Costa del Sol.",      cap: "Hacienda · coastal", cls: "wide",
    img: "https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=900&q=85&fit=crop" },
  { meta: "F&B · 2025",         title: "Apertura editorial de un restaurante firma en Ciudad de México.",            titleEn: "Editorial opening of a signature restaurant in Mexico City.",     cap: "Interior · dining",  cls: "tall",
    img: "https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=900&q=85&fit=crop" },
  { meta: "Architecture · 2024",title: "Narrativa de producto para un estudio de arquitectura residencial.",         titleEn: "Product narrative for a residential architecture studio.",        cap: "Atelier · studio",   cls: "third",
    img: "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=900&q=85&fit=crop" },
  { meta: "Prensa · 2024",      title: "Campaña internacional · 28 medios internacionales de referencia.",          titleEn: "International campaign · 28 leading international media outlets.",  cap: "Press · portfolio",  cls: "third",
    img: "https://images.unsplash.com/photo-1511578314322-379afb476865?w=900&q=85&fit=crop" },
  { meta: "Interior · 2024",    title: "Guardianship de marca para una colección de mobiliario de autor.",          titleEn: "Brand guardianship for a designer furniture collection.",         cap: "FF&E · detail",      cls: "third",
    img: "https://images.unsplash.com/photo-1555041469-a586c61ea9bc?w=900&q=85&fit=crop" },
];

function Press() {
  const lang = useLang();
  return (
    <section id="prensa" className="press press--white">
      <div className="press-head">
        <div>
          <p className="section-overline">| {t("ARCHIVO", "ARCHIVE")}</p>
          <h2>{t("Un portfolio ", "An ")}<em style={{ color: "var(--crimson)" }}>{t("editado", "edited")}</em>{t(".", " portfolio.")}<br />{t("Seleccionado, nunca acumulado.", "Curated, never accumulated.")}</h2>
        </div>
        <a href="#" className="text-link-cta" style={{ alignSelf: "flex-end" }}>
          {t("Archivo completo", "Full archive")} <ArrowNE />
        </a>
      </div>
      <div className="press-grid">
        {PRESS.map((p, i) => (
          <article key={i} className={`press-card ${p.cls}`}>
            <div className="thumb">
              {p.img && <img src={p.img} alt={p.cap} loading="lazy" />}
              <div className="placeholder" />
              <div className="caption">{p.cap}</div>
            </div>
            <div className="meta">
              <span>{p.meta.replace("Prensa", t("Prensa", "Press"))}</span>
              <span>0{i + 1} / 0{PRESS.length}</span>
            </div>
            <h3 className="title">{t(p.title, p.titleEn)}</h3>
          </article>
        ))}
      </div>
    </section>
  );
}

/* ---------- HoldingBrandName ---------- */
function HoldingBrandName({ slug }) {
  const names = {
    talentchef: "TalentChef", tailors: "Tailors", guinda: "Guinda",
    alia: "ALIA", libo: "LIBO", lachismosa: "laChismosa"
  };
  if (!names[slug]) return null;
  return React.createElement("img", {
    src: "assets/logos/" + slug + ".svg",
    alt: names[slug],
    className: "brand-logo",
    loading: "lazy"
  });
}

/* ---------- Holding / Sister brands ---------- */
const HOLDING_BRANDS = [
  { cat: "FOOD & BEVERAGE",        slug: "talentchef",  img: "assets/Talent Chef.png",   tone: 1 },
  { cat: "HOTEL BRANDS",           slug: "tailors",     img: "assets/tailor.png",         tone: 2, imgPos: "center 10%" },
  { cat: "INTERIOR DESIGN & FF&E", slug: "guinda",      img: "assets/guinda.png",         tone: 3 },
  { cat: "ARCHITECTURE",           slug: "alia",        img: "assets/Alia.png",           tone: 4 },
  { cat: "ASSETS GUARDIANSHIP",    slug: "libo",        img: "assets/Libro.png",          tone: 5 },
  { cat: "COMMUNICATION",          slug: "lachismosa",  img: "assets/La chismosa.png",    tone: 6, current: true },
];

function Holding() {
  return (
    <section className="holding" aria-label="LittleBig Hospitality Group">
      <div className="holding-head">
        <img src="assets/logos/littlebig.svg" className="holding-logo" alt="LittleBig Hospitality Group" />
      </div>

      <div className="holding-grid">
        {HOLDING_BRANDS.map((b, i) => (
          <a key={i} href="#" className={`holding-card ${b.current ? "is-current" : ""}`}
             onClick={(e) => e.preventDefault()}>
            <div className="holding-cat">{b.cat}</div>
            <div className="holding-thumb">
              <div className={`holding-stripes tone-${b.tone}`} />
              <img className="holding-img" src={b.img} alt={b.slug} loading="lazy"
                   style={b.imgPos ? { objectPosition: b.imgPos } : {}}
                   onError={(e) => { e.target.style.display = "none"; }} />
              <div className="holding-overlay" />
              <div className="holding-name">
                <HoldingBrandName slug={b.slug} />
              </div>
              <div className="holding-arrow" aria-hidden="true">
                <ArrowNE size={22} />
              </div>
              {b.current && <div className="holding-current">— You are here</div>}
            </div>
          </a>
        ))}
      </div>
    </section>
  );
}

/* ---------- Footer corporativo ---------- */
function Footer() {
  const lang = useLang();
  const offices = [
    { city: "MADRID",           addr: <>C/ de Fernando Santo,<br />Chamberí, 27</> },
    { city: t("MÁLAGA", "MALAGA"), addr: <>Hacienda del Mar Melia<br />{t("Collection, meeting center", "Collection, meeting center")}</> },
    { city: t("BRASIL", "BRAZIL"), addr: t("Próximamente", "Coming soon") },
    { city: t("CANCÚN", "CANCUN"), addr: <>{t("Carretera Aeropuerto-", "Carretera Aeropuerto-")}<br />Bonfil km 11.5</> },
    { city: t("CIUDAD DE MÉXICO", "MEXICO CITY"), addr: <>{t("Campus corporativo de", "Corporate campus,")}<br />{t("Coyoacán, PB T2", "Coyoacán, GF T2")}</> },
    { city: "MIDDLE EAST",      addr: t("Próximamente", "Coming soon") },
    { city: "MIAMI",            addr: t("Próximamente", "Coming soon") },
  ];

  return (
    <footer className="site-footer">
      <div className="site-footer-inner">
        <p className="footer-ws-label">OUR WORKSPACES</p>

        <div className="footer-offices">
          <div className="footer-offices-grid">
            {offices.map(({ city, addr }) => (
              <div className="footer-office" key={city}>
                <h6 className="footer-city">{city}</h6>
                <p className="footer-addr">{addr}</p>
              </div>
            ))}
          </div>

          <div className="footer-contact-col">
            <span className="footer-lets-talk">LET'S TALK</span>
            <a href="https://www.instagram.com/lachismosacomunicacion/" target="_blank" rel="noopener noreferrer" className="footer-contact-link">Instagram</a>
            <a href="https://www.linkedin.com/company/la-chismosa-comunicaci%C3%B3n/" target="_blank" rel="noopener noreferrer" className="footer-contact-link">Linkedin</a>
            <span className="footer-contact-link">+34 900 155 155</span>
          </div>
        </div>

        <hr className="footer-rule" />

        <div className="footer-bar">
          <div className="footer-brand">
            <span style={{ fontFamily: "var(--sans)", fontSize: "14px", color: "rgba(255,255,255,.5)", marginRight: "4px" }}>©</span>
            <img src="assets/logo-blanco.svg" alt="laChismosa" className="footer-brand-logo" />
          </div>
          <nav className="footer-bar-nav">
            <a href="nosotros.html">{t("NOSOTROS", "ABOUT")}</a>
            <a href="servicios.html">{t("SERVICIOS", "SERVICES")}</a>
            <a href="archivo.html">{t("ARCHIVO", "ARCHIVE")}</a>
            <a href="contacto.html">{t("CONTACTO", "CONTACT")}</a>
          </nav>
          <div className="footer-bar-legal">
            <a href="aviso-legal.html">{t("Aviso Legal", "Legal Notice")}</a>
            <span> | </span>
            <a href="politica-privacidad.html">{t("Política de privacidad", "Privacy Policy")}</a>
            <span> | </span>
            <a href="cookies.html">Cookies</a>
          </div>
        </div>
      </div>
    </footer>
  );
}

/* ---------- Badge circular "Let's connect" — sticky compartido ---------- */
/* (sustituye al antiguo botón silencio; nombre conservado para no romper páginas) */
function SilencioSticky() {
  const [fill, setFill] = React.useState(0);
  React.useEffect(() => {
    const onScroll = () => {
      const max = document.documentElement.scrollHeight - window.innerHeight;
      setFill(max > 0 ? Math.max(0, Math.min(1, window.scrollY / max)) : 0);
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    onScroll();
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, []);
  return (
    <a href="contacto.html#contacto-form"
       className="connect-badge"
       style={{ "--fillpct": (fill * 100).toFixed(2) + "%" }}
       aria-label="Let's connect" title="Let's connect">
      <svg className="connect-badge-ring" viewBox="0 0 100 100" aria-hidden="true">
        <defs>
          <path id="connectCircle" d="M50,50 m-37,0 a37,37 0 1,1 74,0 a37,37 0 1,1 -74,0" />
        </defs>
        <text>
          <textPath href="#connectCircle" startOffset="0" textLength="232.5" lengthAdjust="spacing">
            LET'S CONNECT • LET'S CONNECT •
          </textPath>
        </text>
      </svg>
      <span className="connect-badge-icon">
        <img src="assets/favicon-blanco.svg" alt="laChismosa" />
      </span>
      <span className="connect-badge-bla" aria-hidden="true">bla bla bla bla bla bla bla bla bla bla bla bla bla</span>
    </a>
  );
}

Object.assign(window, {
  Intro, Cursor, Nav, Hero, VideoQuote, Manifesto, Services, MapaBlock, WorldMap, QuoteSection,
  Press, Holding, Footer, Redacted, InkText, HoldingBrandName, SilencioSticky
});
