/* ============================================================
   SE42 · Landing — secciones (arquitectura Novu reinterpretada)
   ============================================================ */

/* ---------------- PILL (botón con texto dinámico estilo Novu) ---------------- */
function Pill({ href, label, icon, className = "", iconSize = 16, onClick }) {
  return (
    <a className={"pill " + className} href={href} onClick={onClick}>
      {icon ? <Icon name={icon} size={iconSize} /> : null}
      <span className="pill__label">
        <span className="pill__label-row">{label}</span>
        <span className="pill__label-row" aria-hidden="true">{label}</span>
      </span>
    </a>);

}

/* ---------------- NAV (píldora centrada) ---------------- */
function Nav({ t, lang, setLang, scrolled, onMenu, install }) {
  return (
    <nav className={"nav" + (scrolled ? " is-scrolled" : "")}>
      <a className="nav__logo" href="#top" aria-label="SE42"
      onClick={(e) => {e.preventDefault();window.scrollTo({ top: 0, behavior: "smooth" });}}>
        SE42
      </a>
      <div className="navpill">
        <a href="#funciones">{t.nav.feats}</a>
        <a href="#como">{t.nav.how}</a>
        <a href="#faq">{t.nav.faq}</a>
      </div>
      <div className="nav__right">
        <div className="lang" role="group" aria-label="Idioma / Language">
          <button className={lang === "es" ? "is-active" : ""} onClick={() => setLang("es")} aria-pressed={lang === "es"}>ES</button>
          <span className="sep">/</span>
          <button className={lang === "en" ? "is-active" : ""} onClick={() => setLang("en")} aria-pressed={lang === "en"}>EN</button>
        </div>
        <InstallPill t={t} install={install} label={t.nav.install} iconSize={16} />
        <button className="nav__menu" onClick={onMenu} aria-label={t.nav.menu}><Icon name="menu" size={22} /></button>
      </div>
    </nav>);

}

function MobileMenu({ t, open, onClose, lang, setLang, install }) {
  return (
    <div className={"mobile-menu" + (open ? " is-open" : "")} aria-hidden={!open}>
      <div className="mobile-menu__head">
        <span className="nav__logo" style={{ color: "var(--crudo)" }}>SE42</span>
        <button className="mobile-menu__close" onClick={onClose} aria-label={t.nav.close}><Icon name="close" size={20} /></button>
      </div>
      <nav className="mobile-menu__nav">
        <a href="#funciones" onClick={onClose}>{t.nav.feats}</a>
        <a href="#como" onClick={onClose}>{t.nav.how}</a>
        <a href="#faq" onClick={onClose}>{t.nav.faq}</a>
        <a href={install.appUrl} onClick={(e) => {onClose();install.onInstall(e);}}>{t.nav.install}</a>
      </nav>
      <div className="mobile-menu__foot">
        <div className="lang" style={{ color: "rgba(250,249,245,0.6)", borderColor: "rgba(250,249,245,0.25)" }}>
          <button className={lang === "es" ? "is-active" : ""} style={lang === "es" ? { color: "var(--crudo)" } : null} onClick={() => setLang("es")}>ES</button>
          <span className="sep">/</span>
          <button className={lang === "en" ? "is-active" : ""} style={lang === "en" ? { color: "var(--crudo)" } : null} onClick={() => setLang("en")}>EN</button>
        </div>
      </div>
    </div>);

}

/* ---------------- HERO (centrado, sticky) ---------------- */
function Hero({ t, bg, video, install }) {
  return (
    <header className="hero" id="top">
      {video ?
      <video className="hero__bg hero__bg--video" src={video} poster={bg} autoPlay loop muted playsInline preload="auto" /> :
      <div className="hero__bg" style={{ backgroundImage: `url("${bg}")` }} />}
      <div className="hero__veil" />
      <div className="wrap">
        <p className="eyebrow hero__eyebrow">{t.hero.eyebrow}</p>
        <h1 className="display hero__title"><Headline lead={t.hero.lead} accent={t.hero.accent} /></h1>
        <p className="hero__sub">{t.hero.sub}</p>
        <div className="hero__actions">
          <InstallPill t={t} install={install} label={t.hero.cta} className="pill--lg" iconSize={18} />
        </div>
      </div>
      <a className="hero__scroll" href="#bienvenida" aria-label={t.hero.scroll}>
        <span>{t.hero.scroll}</span>
        <span className="hero__scrollbar" />
      </a>
    </header>);

}

/* ---------------- PHONE (frame con pantalla activa) ---------------- */
function Phone({ screens, active, inline }) {
  const isVid = (src) => /\.mp4($|\?)/i.test(src);
  return (
    <div className={"phone" + (inline ? " phone--inline" : "")}>
      <div className="phone__island" />
      <div className="phone__screen">
        {inline ?
        isVid(screens[active]) ?
        <video src={screens[active]} autoPlay loop muted playsInline preload="metadata" /> :
        <img src={screens[active]} alt="" /> :

        screens.map((src, i) =>
        isVid(src) ?
        <video key={i} src={src} className={i === active ? "is-active" : ""} autoPlay loop muted playsInline preload={i === active ? "auto" : "metadata"} /> :
        <img key={i} src={src} alt="" className={i === active ? "is-active" : ""} loading={i === 0 ? "eager" : "lazy"} />
        )
        }
      </div>
    </div>);

}

/* ---------------- WELCOME (carta del Residential Manager) ---------------- */
function Welcome({ t, photo, firma }) {
  const w = t.welcome;
  const firmaRef = useRef(null);
  const photoRef = useRef(null);
  /* parallax sutil de la foto al hacer scroll */
  useEffect(() => {
    const img = photoRef.current;
    if (!img) return;
    const fig = img.parentElement;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    img.style.willChange = "transform";
    img.style.transform = "scale(1.12)";
    let ticking = false;
    const update = () => {
      ticking = false;
      const r = fig.getBoundingClientRect();
      const vh = window.innerHeight;
      if (r.bottom < -200 || r.top > vh + 200) return;
      const prog = (vh / 2 - (r.top + r.height / 2)) / vh; // ~ -0.7..0.7
      const shift = Math.max(-1, Math.min(1, prog)) * (r.height * 0.08);
      img.style.transform = `translate3d(0, ${shift.toFixed(1)}px, 0) scale(1.12)`;
    };
    const onScroll = () => {if (!ticking) {ticking = true;requestAnimationFrame(update);}};
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    update();
    return () => {window.removeEventListener("scroll", onScroll);window.removeEventListener("resize", onScroll);};
  }, []);
  useEffect(() => {
    const path = firmaRef.current;
    if (!path) return;
    const len = path.getTotalLength ? path.getTotalLength() : 1400;
    path.style.strokeDasharray = len;
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduce || !path.animate || !("IntersectionObserver" in window)) {path.style.strokeDashoffset = 0;return;}
    path.style.strokeDashoffset = len;
    let done = false;
    const draw = () => {
      if (done) return;done = true;
      const a = path.animate(
        [{ strokeDashoffset: len }, { strokeDashoffset: 0 }],
        { duration: 2400, easing: "cubic-bezier(.65,0,.35,1)", fill: "forwards" }
      );
      a.onfinish = () => {path.style.strokeDashoffset = 0;};
    };
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {if (e.isIntersecting) {draw();io.disconnect();}});
    }, { threshold: 0.4 });
    io.observe(path.closest("svg") || path);
    const fb = setTimeout(() => {if (!done) {done = true;path.style.strokeDashoffset = 0;}io.disconnect();}, 6000);
    return () => {io.disconnect();clearTimeout(fb);};
  }, []);
  return (
    <section className="section welcome" id="bienvenida">
      <div className="wrap welcome__grid">
        <figure className="welcome__photo reveal">
          <img src={photo} alt={w.photoAlt} loading="lazy" ref={photoRef} />
        </figure>
        <div className="welcome__body reveal">
          <p className="eyebrow">{w.eyebrow}</p>
          <h2 className="welcome__title"><Headline lead={w.lead} accent={w.accent} /></h2>
          <div className="welcome__text">
            {w.body.map((p, i) => <p key={i}>{p}</p>)}
          </div>
          <div className="welcome__sign">
            <div className="welcome__firma" aria-hidden="true">
              <svg className="welcome__firma-svg" viewBox="0 0 560 240" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path ref={firmaRef} d="M72 158 C18 70 135 24 252 54 C342 78 322 176 235 168 C252 118 264 92 272 165 C280 120 292 94 300 165 C308 120 320 92 328 165 C336 120 348 92 356 165 C364 120 376 94 384 164 C392 120 404 92 412 160 C432 118 456 66 480 58 C522 42 548 72 536 122 M46 200 C172 252 412 248 552 150" stroke="currentColor" strokeWidth="6" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </div>
            <span className="welcome__name">{w.name}</span>
            <span className="welcome__role">{w.role}</span>
            <div className="welcome__contact">
              <a href="tel:+34624743497"><Icon name="phone" size={16} />+34 624 74 34 97</a>
              <a href="mailto:hernan@messerbranding.com"><Icon name="mail" size={16} />hernan@messerbranding.com</a>
            </div>
          </div>
        </div>
      </div>
    </section>);

}

/* ---------------- SHOWCASE (teléfono fijo + pantallas que cambian) ---------------- */
function Showcase({ t, screens, active, registerStep, introPhone }) {
  return (
    <section className="section showcase" id="funciones">
      <div className="wrap">
        <div className="showcase__grid">
          <div className="showcase__phonecol" aria-hidden="true" style={{ gridColumn: 2, gridRow: `1 / span ${t.feats.items.length}` }}>
            <Phone screens={screens} active={active} />
          </div>
          {t.feats.items.map((f, i) =>
          <article className="showcase__step" key={i} data-step={i} ref={(el) => registerStep(i, el)}
          style={{ gridColumn: i % 2 === 0 ? 1 : 3, gridRow: i + 1 }}>
              <span className="step__index"><b>{String(i + 1).padStart(2, "0")}</b> / {String(t.feats.items.length).padStart(2, "0")} · {f.eyebrow}</span>
              <h3 className="step__title">{f.serifFirst ?
              <span><em className="accent">{f.lead}</em> {f.accent}</span> :
              <Headline lead={f.lead} accent={f.accent} />}</h3>
              <p className="step__desc">{f.desc}</p>
              <ul className="step__list">{f.list.map((li, j) => <li key={j}>{li}</li>)}</ul>
              <div className="showcase__inline"><Phone screens={screens} active={i} inline /></div>
            </article>
          )}
        </div>
      </div>
    </section>);

}

/* ---------------- HOW (scroll horizontal anclado) ---------------- */
function HowCards({ t, media }) {
  const wrapRef = useRef(null);
  const trackRef = useRef(null);
  const stickyRef = useRef(null);
  const idxRef = useRef(0);
  const nudge = (dir) => {
    const track = trackRef.current,sticky = stickyRef.current;if (!track || !sticky) return;
    const cards = track.querySelectorAll(".hcard");if (!cards.length) return;
    const railScrolls = sticky.scrollWidth - sticky.clientWidth > 5;
    if (railScrolls) {
      idxRef.current = Math.max(0, Math.min(cards.length - 1, idxRef.current + dir));
      const padL = parseFloat(getComputedStyle(track).paddingLeft) || 0;
      sticky.scrollTo({ left: Math.max(0, cards[idxRef.current].offsetLeft - padL), behavior: "smooth" });
    } else {
      const step = cards.length > 1 ? cards[1].offsetLeft - cards[0].offsetLeft : 320;
      window.scrollBy({ top: dir * step, behavior: "smooth" });
    }
  };
  useEffect(() => {
    const wrap = wrapRef.current,track = trackRef.current;
    if (!wrap || !track) return;
    let maxX = 0,ticking = false;
    const isDesktop = () => window.matchMedia("(min-width: 820px)").matches;
    const apply = () => {
      ticking = false;
      if (!isDesktop() || maxX <= 0) {track.style.transform = "";return;}
      const top = wrap.getBoundingClientRect().top + window.scrollY;
      const p = Math.min(Math.max(window.scrollY - top, 0), maxX);
      track.style.transform = `translate3d(${-p}px,0,0)`;
    };
    const layout = () => {
      if (!isDesktop()) {wrap.style.height = "";track.style.transform = "";maxX = 0;return;}
      const cards = track.querySelectorAll(".hcard");
      // travel extra de un paso para que la última tarjeta acabe donde
      // ahora queda la penúltima (no pegada al borde derecho)
      let extra = 0;
      if (cards.length >= 2) extra = cards[cards.length - 1].offsetLeft - cards[cards.length - 2].offsetLeft - 90;
      maxX = Math.max(0, track.scrollWidth - window.innerWidth + 48 + extra);
      wrap.style.height = window.innerHeight + maxX + "px";
      apply();
    };
    const onScroll = () => {if (!ticking) {ticking = true;requestAnimationFrame(apply);}};
    layout();
    const t2 = setTimeout(layout, 500);
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", layout);
    return () => {window.removeEventListener("scroll", onScroll);window.removeEventListener("resize", layout);clearTimeout(t2);};
  }, [t]);

  return (
    <section className="section section--tint how" id="como">
      <div className="wrap">
        <div className="how-head reveal">
          <div className="how-head__lead">
            <p className="eyebrow sec-head__eyebrow">{t.how.eyebrow}</p>
            <h2 className="sec-head__title"><Headline lead={t.how.lead} accent={t.how.accent} /></h2>
          </div>
          <p className="how-head__sub">{t.how.sub}</p>
        </div>
      </div>
      <div className="hscroll" ref={wrapRef}>
        <div className="hscroll__sticky" ref={stickyRef}>
          <div className="hscroll__track" ref={trackRef} role="list">
            {t.how.cards.map((c, i) => {
              const m = media[i];
              return (
                <div className="hcard" role="listitem" key={i}>
                  <div className="hcard__bg" aria-hidden="true">
                    {m && m.type === "video" ?
                    <video src={m.src} autoPlay loop muted playsInline preload="metadata" /> :
                    m ? <img src={m.src} alt="" loading="lazy" /> : null}
                  </div>
                  <div className="hcard__scrim" aria-hidden="true" />
                  <div className="hcard__text">
                    <span className="hcard__n">{c.n}</span>
                    <h3 className="hcard__title"><Headline lead={c.lead} accent={c.accent} /></h3>
                    <p className="hcard__body">{c.body}</p>
                  </div>
                </div>);

            })}
          </div>
        </div>
        <div className="how-nav" aria-hidden="false">
          <button className="how-arrow" onClick={() => nudge(-1)} aria-label="Anterior"><Icon name="arrow" size={20} style={{ transform: "rotate(180deg)" }} /></button>
          <button className="how-arrow" onClick={() => nudge(1)} aria-label="Siguiente"><Icon name="arrow" size={20} /></button>
        </div>
      </div>
    </section>);

}
function Band({ t, bg }) {
  const bgRef = useRef(null);
  const secRef = useRef(null);
  useEffect(() => {
    const el = bgRef.current,sec = secRef.current;
    if (!el || !sec) return;
    el.style.backgroundImage = `url("${bg}")`;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    let ticking = false;
    const metaItems = Array.from(sec.querySelectorAll(".band__meta-item"));
    const update = () => {
      ticking = false;
      const r = sec.getBoundingClientRect();
      const vh = window.innerHeight;
      if (r.bottom < -200 || r.top > vh + 200) return;
      const prog = (vh / 2 - (r.top + r.height / 2)) / vh; // ~ -0.7..0.7
      const shift = Math.max(-1, Math.min(1, prog * 1.8)) * (r.height * 0.12);
      el.style.transform = `translate3d(0, ${shift.toFixed(1)}px, 0)`;
      // revelado en orden, gobernado por el scroll: primero el resto del
      // bloque, luego cada item con icono uno tras otro
      const p = (vh * 0.9 - r.top) / (vh * 0.6);
      const thresholds = [0.34, 0.56, 0.78];
      metaItems.forEach((it, i) => {it.classList.toggle("is-shown", p >= thresholds[i]);});
    };
    const onScroll = () => {if (!ticking) {ticking = true;requestAnimationFrame(update);}};
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    update();

    // dibujar los iconos del bocadillo al entrar en vista
    const paths = sec.querySelectorAll(".band__meta svg path");
    paths.forEach((p) => {try {const L = p.getTotalLength();p.style.strokeDasharray = L;p.style.strokeDashoffset = L;} catch (e) {}});
    let drawn = false;
    const drawIcons = () => {
      if (drawn) return;drawn = true;
      paths.forEach((p, i) => {
        let L;try {L = p.getTotalLength();} catch (e) {return;}
        const a = p.animate([{ strokeDashoffset: L }, { strokeDashoffset: 0 }],
        { duration: 650, delay: 120 + i * 60, easing: "cubic-bezier(.65,0,.35,1)", fill: "forwards" });
        a.onfinish = () => {p.style.strokeDashoffset = 0;};
      });
    };
    const io2 = new IntersectionObserver((es) => es.forEach((e) => {if (e.isIntersecting) {drawIcons();sec.classList.add("band--in");io2.disconnect();}}), { threshold: 0.5 });
    io2.observe(sec);
    const fb2 = setTimeout(() => {if (!drawn) {drawn = true;paths.forEach((p) => {p.style.strokeDashoffset = 0;});}sec.classList.add("band--in");io2.disconnect();}, 6000);

    return () => {window.removeEventListener("scroll", onScroll);window.removeEventListener("resize", onScroll);io2.disconnect();clearTimeout(fb2);};
  }, [bg]);
  return (
    <section className="section section--dark band" ref={secRef} id="tu-residencia">
      <div className="band__bg" aria-hidden="true" ref={bgRef} />
      <div className="band__veil" aria-hidden="true" />
      <div className="wrap">
        <p className="eyebrow reveal" style={{ marginBottom: 24 }}>{t.band.eyebrow}</p>
        <h2 className="band__title reveal"><Headline lead={t.band.lead} accent={t.band.accent} /></h2>
        <p className="band__sub reveal">{t.band.sub}</p>
        <div className="band__meta reveal">
          {t.band.meta.map((m, i) => <span className="band__meta-item" style={{ "--i": i }} key={i}><Icon name={META_ICON[m] || "shield"} size={16} />{m}</span>)}
        </div>
      </div>
    </section>);

}

/* ---------------- CAPABILITIES (marquee) ---------------- */
function Capabilities({ t }) {
  const chips = t.capabilities.chips;
  const loop = chips.concat(chips);
  return (
    <section className="section caps" id="capacidades">
      <div className="wrap">
        <div className="sec-head sec-head--center caps__head reveal">
          <p className="eyebrow sec-head__eyebrow">{t.capabilities.eyebrow}</p>
          <h2 className="sec-head__title"><Headline lead={t.capabilities.lead} accent={t.capabilities.accent} /></h2>
          <p className="sec-head__sub">{t.capabilities.sub}</p>
        </div>
      </div>
      <div className="marquee reveal" aria-label={t.capabilities.lead}>
        <div className="marquee__track">
          {loop.map((c, i) =>
          <span className="chip" key={i} aria-hidden={i >= chips.length}>
              <span className="chip__ico"><Icon name={c.i} size={18} /></span>{c.t}
            </span>
          )}
        </div>
      </div>
    </section>);

}

/* ---------------- FAQ ---------------- */
function FAQ({ t }) {
  const [open, setOpen] = useState(0);
  const refs = useRef([]);
  return (
    <section className="section" id="faq">
      <div className="wrap faq">
        <div className="sec-head reveal">
          <p className="eyebrow sec-head__eyebrow">{t.faq.eyebrow}</p>
          <h2 className="sec-head__title"><Headline lead={t.faq.lead} accent={t.faq.accent} /></h2>
        </div>
        <div className="faq__list reveal">
          {t.faq.items.map((it, i) => {
            const isOpen = open === i;
            return (
              <div className={"faq__item" + (isOpen ? " is-open" : "")} key={i} onMouseEnter={() => setOpen(i)}>
                <button className="faq__q" aria-expanded={isOpen} onClick={() => setOpen(isOpen ? -1 : i)} onFocus={() => setOpen(i)}>
                  <span>{it.q}</span><span className="faq__plus" aria-hidden="true" />
                </button>
                <div className="faq__a" style={{ maxHeight: isOpen && refs.current[i] ? refs.current[i].scrollHeight : 0 }}>
                  <div className="faq__a-inner" ref={(el) => refs.current[i] = el}>{it.a}</div>
                </div>
              </div>);

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

}

/* ---------------- CTA + FOOTER (capa oscura inferior, fija) ---------------- */
function BottomLayer({ t, logo, bg, begrand, layerRef, install }) {
  return (
    <div className="bottom-layer" ref={layerRef}>
      <div className="bottom-layer__bg" aria-hidden="true" style={{ backgroundImage: `url("${bg}")` }} />
      <div className="bottom-layer__veil" aria-hidden="true" />
      <section className="cta" id="instalar">
        <div className="wrap">
          <h2 className="cta__title">{t.cta.lead} <em className="accent">{t.cta.accent}</em> {t.cta.tail}</h2>
          <p className="cta__sub">{(Array.isArray(t.cta.sub) ? t.cta.sub : [t.cta.sub]).map((line, i) =>
            <span key={i} style={{ display: "block" }}>{line}</span>
            )}</p>
          <div className="cta__actions">
            <InstallPill t={t} install={install} label={t.cta.primary} className="pill--lg pill--invert" iconSize={18} />
          </div>

          <footer className="foot">
            <div className="foot__top">
              <nav className="foot__nav">
                {t.foot.cols[0].links.map(([label, href], j) =>
                <a href={href} key={j}>{label}</a>
                )}
              </nav>
              <div className="foot__logos">
                <a href="https://messerbranding.com" target="_blank" rel="noopener" aria-label="Messer">
                  <img className="foot__logo" src={logo} alt="Messer Living" />
                </a>
                <span className="foot__divider" aria-hidden="true" />
                <a href="https://begrand.es" target="_blank" rel="noopener" aria-label="Be Grand">
                  <img className="foot__begrand-logo" src={begrand} alt="Be Grand" />
                </a>
              </div>
            </div>
            <div className="foot__bar">
              <span>© {t.foot.copyright}</span>
              <span style={{ display: "inline-flex", gap: 18 }}>
                {t.foot.legal.map(([label, href], i) => <a href={href} key={i}>{label}</a>)}
              </span>
            </div>
          </footer>
        </div>
      </section>
    </div>);

}

Object.assign(window, { Pill, Nav, MobileMenu, Hero, Phone, Welcome, Showcase, HowCards, Band, Capabilities, FAQ, BottomLayer });