/* Shared helpers — НефтьОргХим+ site. */
const { useState, useEffect, useRef } = React;
const REDUCED = () => window.matchMedia("(prefers-reduced-motion: reduce)").matches;

function useReveal(delay = 0, y = 24) {
  const ref = useRef(null);
  const [on, setOn] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (REDUCED()) return setOn(true);
    const io = new IntersectionObserver(([e]) => setOn(e.isIntersecting), { threshold: 0.1, rootMargin: "0px 0px -60px 0px" });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return [ref, {
    opacity: on ? 1 : 0,
    transform: on ? "none" : `translateY(${y}px)`,
    filter: on ? "none" : "blur(10px)",
    transition: `opacity 900ms var(--ease-out) ${delay}ms, transform 900ms var(--ease-out) ${delay}ms, filter 900ms var(--ease-out) ${delay}ms`
  }];
}

function Reveal({ delay = 0, y, as: Tag = "div", style, children, ...rest }) {
  const [ref, rs] = useReveal(delay, y);
  return <Tag ref={ref} style={{ ...rs, ...style }} {...rest}>{children}</Tag>;
}

/** Word-by-word blur reveal for display headings. */
function RevealText({ text, delay = 0, step = 70, style, as: Tag = "span" }) {
  const [ref, rs] = useReveal(delay, 0);
  const on = rs.opacity === 1;
  return (
    <Tag ref={ref} style={{ display: "inline", ...style }}>
      {text.split(" ").map((w, i) => (
        <span key={i} style={{ display: "inline-block", whiteSpace: "pre", opacity: on ? 1 : 0, filter: on ? "none" : "blur(9px)", transform: on ? "none" : "translateY(18px)", transition: `opacity 900ms var(--ease-out) ${delay + i * step}ms, filter 900ms var(--ease-out) ${delay + i * step}ms, transform 900ms var(--ease-out) ${delay + i * step}ms` }}>{w + " "}</span>
      ))}
    </Tag>
  );
}

function useScrollY() {
  const [y, setY] = useState(0);
  useEffect(() => {
    let t = false;
    const on = () => { if (t) return; t = true; requestAnimationFrame(() => { setY(window.scrollY); t = false; }); };
    window.addEventListener("scroll", on, { passive: true });
    on();
    return () => window.removeEventListener("scroll", on);
  }, []);
  return y;
}

/** Progress 0→1 of an element travelling through the viewport (for gentle parallax). */
function useSectionProgress(ref) {
  const y = useScrollY();
  const [p, setP] = useState(0.5);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    setP(Math.max(0, Math.min(1, (window.innerHeight - r.top) / (window.innerHeight + r.height))));
  }, [y]);
  return p;
}

/** Very small pointer parallax, in px. */
function usePointer(strength = 12) {
  const [p, setP] = useState({ x: 0, y: 0 });
  useEffect(() => {
    if (REDUCED() || window.matchMedia("(pointer: coarse)").matches) return;
    const on = (e) => setP({ x: (e.clientX / window.innerWidth - 0.5) * strength, y: (e.clientY / window.innerHeight - 0.5) * strength });
    window.addEventListener("pointermove", on, { passive: true });
    return () => window.removeEventListener("pointermove", on);
  }, []);
  return p;
}

function useActiveSection(ids) {
  const [active, setActive] = useState(ids[0]);
  useEffect(() => {
    const io = new IntersectionObserver((entries) => {
      const vis = entries.filter((e) => e.isIntersecting).sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0];
      if (vis) setActive(vis.target.id);
    }, { rootMargin: "-45% 0px -45% 0px", threshold: [0.01, 0.3] });
    ids.forEach((id) => { const el = document.getElementById(id); if (el) io.observe(el); });
    return () => io.disconnect();
  }, []);
  return active;
}

function Counter({ to, suffix = "", duration = 1600 }) {
  const ref = useRef(null);
  const [v, setV] = useState(0);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(([e]) => {
      if (!e.isIntersecting) return;
      io.disconnect();
      const t0 = performance.now();
      const step = (now) => {
        const p = Math.min((now - t0) / duration, 1);
        setV(p >= 1 ? to : Math.round(to * (1 - Math.pow(1 - p, 3))));
        if (p < 1) requestAnimationFrame(step);
      };
      requestAnimationFrame(step);
    }, { threshold: 0.6 });
    io.observe(el);
    return () => io.disconnect();
  }, [to]);
  return <span ref={ref}>{v}{suffix}</span>;
}

function Section({ id, children, style, inner, ...rest }) {
  return (
    <section id={id} style={{ position: "relative", padding: "var(--section-y) 0", ...style }} {...rest}>
      <div style={{ position: "relative", maxWidth: "var(--container)", margin: "0 auto", padding: "0 var(--gutter)", ...inner }}>{children}</div>
    </section>
  );
}

const Icon = ({ name, size = 40, color = "currentColor", style }) => (
  <span aria-hidden="true" style={{ display: "inline-block", width: size, height: size, background: color, WebkitMaskImage: `url(assets/icons/${name}.svg)`, maskImage: `url(assets/icons/${name}.svg)`, WebkitMaskSize: "contain", maskSize: "contain", WebkitMaskPosition: "center", maskPosition: "center", WebkitMaskRepeat: "no-repeat", maskRepeat: "no-repeat", ...style }} />
);

/** Slow steel ticker — used once, under the hero. */
function Ticker({ items, duration = 64 }) {
  const row = items.concat(items);
  return (
    <div style={{ overflow: "hidden", maskImage: "linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent)", WebkitMaskImage: "linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent)" }}>
      <div style={{ display: "flex", gap: "var(--sp-8)", width: "max-content", animation: `tick ${duration}s linear infinite` }}>
        {row.map((t, i) => (
          <span key={i} className="ds-mono" style={{ display: "inline-flex", alignItems: "center", gap: "var(--sp-8)", fontSize: 11, letterSpacing: "0.14em", color: "var(--steel-600)", textTransform: "uppercase", whiteSpace: "nowrap" }}>
            {t}<span style={{ width: 4, height: 4, background: "var(--steel-700)", transform: "rotate(45deg)" }} />
          </span>
        ))}
      </div>
    </div>
  );
}

Object.assign(window, { useReveal, Reveal, RevealText, useScrollY, useSectionProgress, usePointer, useActiveSection, Counter, Section, Icon, Ticker });
