/* atoms.jsx — shared primitives */
const { useState, useEffect, useRef, useCallback, useMemo } = React;

/* Photo block.
   - If you pass a `src` (e.g. src="assets/mi-foto.jpg") it shows the real photo.
   - If you DON'T pass a src, it shows the warm gradient placeholder with a label.
   To add a real photo: drop the image file in the /assets folder, then add
   src="assets/your-file.jpg" to the matching <Photo .../> tag. */
function Photo({ tone = "default", label = "photo", src = "", alt = "", className = "", style = {}, children }) {
  const cls = `ph ph-${tone} ${className}`.trim();
  return (
    <div className={cls} style={style}>
      {src
        ? <img src={src} alt={alt || label} loading="lazy"
               style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", zIndex: 1 }} />
        : <span className="ph-label">{label}</span>}
      {children}
    </div>
  );
}

/* Eyebrow with dot */
function Eyebrow({ children, className = "" }) {
  return (
    <div className={`eyebrow ${className}`.trim()}>
      <span className="dot"></span>{children}
    </div>
  );
}

/* Reveal-on-scroll wrapper */
function Reveal({ as: As = "div", delay = 0, children, className = "", ...rest }) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;

    // Fallback 1: if element is already in viewport on mount, reveal immediately.
    const r = el.getBoundingClientRect();
    if (r.top < window.innerHeight && r.bottom > 0) {
      el.classList.add("is-in");
      return;
    }

    let io;
    if (typeof IntersectionObserver !== "undefined") {
      io = new IntersectionObserver((entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            el.classList.add("is-in");
            io.unobserve(el);
          }
        });
      }, { threshold: 0.08, rootMargin: "0px 0px -8% 0px" });
      io.observe(el);
    }

    // Fallback 2: hard timeout — never leave content invisible.
    const t = setTimeout(() => {
      el.classList.add("is-in");
      io && io.disconnect();
    }, 1200);

    return () => {
      clearTimeout(t);
      io && io.disconnect();
    };
  }, []);
  const delayCls = delay ? ` delay-${delay}` : "";
  const merged = `reveal${delayCls} ${className}`.trim();
  return <As ref={ref} className={merged} {...rest}>{children}</As>;
}

/* Arrow icon */
function Arr({ size = 14 }) {
  return (
    <svg className="arrow" width={size} height={size} viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round">
      <path d="M2 7h10" />
      <path d="M8 3l4 4-4 4" />
    </svg>
  );
}

/* Plus icon (for FAQ) */
function Plus({ size = 18 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 18 18" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round">
      <path d="M9 3v12M3 9h12" />
    </svg>
  );
}

/* Section heading row */
function SectionHead({ eyebrow, title, sub, align = "left" }) {
  return (
    <div className="services-head" style={{ marginBottom: 56 }}>
      <div>
        {eyebrow && <Eyebrow>{eyebrow}</Eyebrow>}
        <h2 className="section-title" style={{ marginTop: eyebrow ? 18 : 0 }} dangerouslySetInnerHTML={{ __html: title }} />
      </div>
      {sub && <p className="lead" style={{ maxWidth: "38ch" }}>{sub}</p>}
    </div>
  );
}

Object.assign(window, { Photo, Eyebrow, Reveal, Arr, Plus, SectionHead });
