// ───────────────────────────────────────────────────────────
// Componentes compartidos — Fundación Minnesota
// ───────────────────────────────────────────────────────────
const { useState, useEffect, useRef } = React;

// ── Ala (isotipo) — PNG pre-teñido por color de marca (robusto: sin CSS mask)
function wingTone(color) {
  const c = String(color || "").toLowerCase();
  let file = "durazno", opacity = 1;
  const m = c.match(/rgba?\([^)]*?,\s*([0-9.]+)\s*\)/);
  if (m) opacity = parseFloat(m[1]);
  if (c.includes("--verde") || c.includes("93,174,158") || c.includes("93, 174, 158")) file = "verde";
  else if (c.includes("--pinar") || c.includes("47,111,98") || c.includes("47, 111, 98")) file = "pinar";
  else if (c.includes("--papel") || c.includes("251,248,244") || c.includes("251, 248, 244")) file = "papel";
  else if (c.includes("--tinta") || c.includes("28,28,28")) file = "tinta";
  else file = "durazno";
  return { file, opacity };
}

function Wing({ color = "var(--durazno)", style = {}, className = "", title }) {
  const { file, opacity } = wingTone(color);
  return (
    <span
      role={title ? "img" : "presentation"}
      aria-label={title || undefined}
      aria-hidden={title ? undefined : true}
      className={"wing " + className}
      style={{
        display: "inline-block",
        backgroundImage: `url('assets/wing-${file}.png')`,
        backgroundRepeat: "no-repeat",
        backgroundPosition: "center",
        backgroundSize: "contain",
        ...(opacity !== 1 ? { opacity } : {}),
        ...style,
      }}
    />
  );
}

// ── Registro global de elementos a revelar (scroll-based, robusto en cualquier iframe)
const RevealRegistry = (() => {
  const items = new Set();
  let raf = 0;
  function check() {
    raf = 0;
    const vh = window.innerHeight || document.documentElement.clientHeight;
    items.forEach((it) => {
      const r = it.el.getBoundingClientRect();
      if (r.top < vh * 0.92 && r.bottom > 0) {
        it.cb();
        items.delete(it);
      }
    });
  }
  function schedule() { if (!raf) raf = requestAnimationFrame(check); }
  if (typeof window !== "undefined") {
    window.addEventListener("scroll", schedule, { passive: true });
    window.addEventListener("resize", schedule, { passive: true });
    window.addEventListener("load", schedule);
    // Reintentos por si el iframe aún no tiene tamaño al montar
    [60, 200, 500, 1000, 1600].forEach((t) => setTimeout(schedule, t));
    // Reacciona a reflows tardíos (Tailwind CDN aplicando estilos,
    // fuentes o imágenes que cambian la altura del documento)
    if (window.ResizeObserver) {
      const ro = new ResizeObserver(schedule);
      const startRO = () => { if (document.body) ro.observe(document.body); };
      if (document.body) startRO();
      else window.addEventListener("DOMContentLoaded", startRO);
    }
  }
  return {
    add(el, cb) {
      const it = { el, cb };
      items.add(it);
      schedule();
      return () => items.delete(it);
    },
  };
})();

// ── Reveal on scroll: fade + movimiento, con stagger y variante opcionales
// variant: "up" (def) | "left" | "right" | "scale". x = distancia horizontal.
function Reveal({ children, as = "div", delay = 0, y = 24, x, variant = "up", className = "", style = {}, ...rest }) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduce) { setShown(true); return; }
    const remove = RevealRegistry.add(el, () => setShown(true));
    // chequeo inicial por si ya está en viewport al montar
    const r = el.getBoundingClientRect();
    const vh = window.innerHeight || document.documentElement.clientHeight || 800;
    if (r.top < vh * 0.95) setShown(true);
    // Failsafe: nunca dejar contenido oculto permanentemente
    const fail = setTimeout(() => setShown(true), 1800);
    return () => { remove(); clearTimeout(fail); };
  }, []);
  const El = as;
  const vClass = variant === "left" ? "rv-left " : variant === "right" ? "rv-right " : variant === "scale" ? "rv-scale " : "";
  const xVal = x != null ? x : (variant === "left" ? -40 : variant === "right" ? 40 : 0);
  return (
    <El
      ref={ref}
      className={"reveal " + (shown ? "reveal--in " : "") + vClass + className}
      style={{ animationDelay: `${delay}ms`, "--reveal-y": `${y}px`, "--reveal-x": `${xVal}px`, ...style }}
      {...rest}
    >
      {children}
    </El>
  );
}

// ── Controlador de parallax: mueve cada [data-parallax] según el scroll.
// Si data-motion="off" o prefers-reduced-motion, el CSS fuerza transform:none.
const ParallaxController = (() => {
  let raf = 0;
  function frame() {
    raf = 0;
    const vh = window.innerHeight || document.documentElement.clientHeight || 800;
    const els = document.querySelectorAll("[data-parallax]");
    els.forEach((el) => {
      const speed = parseFloat(el.getAttribute("data-speed")) || 0.06;
      const r = el.getBoundingClientRect();
      const center = r.top + r.height / 2;
      let offset = (center - vh / 2) * -speed; // hacia arriba al bajar
      offset = Math.max(-80, Math.min(80, offset)); // acotado: efecto sutil, nunca se dispara
      el.style.setProperty("--p", offset.toFixed(1) + "px");
    });
  }
  function schedule() { if (!raf) raf = requestAnimationFrame(frame); }
  if (typeof window !== "undefined") {
    window.addEventListener("scroll", schedule, { passive: true });
    window.addEventListener("resize", schedule, { passive: true });
    window.addEventListener("load", schedule);
    [100, 400, 900].forEach((t) => setTimeout(schedule, t));
  }
  return { schedule };
})();

// ── Barra de progreso de scroll (arriba de todo) ──
function ScrollProgress() {
  const ref = useRef(null);
  useEffect(() => {
    const bar = ref.current;
    if (!bar) return;
    let raf = 0;
    const update = () => {
      raf = 0;
      const doc = document.documentElement;
      const max = (doc.scrollHeight - doc.clientHeight) || 1;
      const pct = Math.min(1, Math.max(0, window.scrollY / max));
      bar.style.width = (pct * 100).toFixed(2) + "%";
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(update); };
    update();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll, { passive: true });
    return () => { window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onScroll); };
  }, []);
  return <div ref={ref} className="scroll-progress" aria-hidden="true" />;
}

// ── Eyebrow: rótulo de sección con ala diminuta
function Eyebrow({ children, color = "var(--verde)", className = "" }) {
  return (
    <div className={"flex items-center gap-2.5 " + className}>
      <Wing color={color} style={{ width: 18, height: 18 }} />
      <span
        className="eyebrow"
        style={{ color }}
      >
        {children}
      </span>
    </div>
  );
}

// ── Insignia de WhatsApp (círculo verde + auricular blanco) — alto contraste
function WABadge({ size = 22, className = "", style = {} }) {
  return (
    <svg width={size} height={size} viewBox="0 0 32 32" className={className} style={{ flexShrink: 0, ...style }} aria-hidden="true">
      <circle cx="16" cy="16" r="16" fill="#5DAE9E" />
      <path fill="#fff" d="M16 6.6c-5.2 0-9.4 4.2-9.4 9.4 0 1.65.43 3.2 1.2 4.55L6.4 25.4l5-1.31a9.36 9.36 0 0 0 4.6 1.2h.01c5.18 0 9.39-4.21 9.39-9.4 0-2.51-.98-4.87-2.75-6.64A9.32 9.32 0 0 0 16 6.6zm0 1.9a7.46 7.46 0 0 1 7.49 7.5c0 4.14-3.36 7.5-7.5 7.5h-.01a7.46 7.46 0 0 1-3.8-1.04l-.27-.16-2.83.74.76-2.76-.18-.28a7.42 7.42 0 0 1-1.14-3.96A7.5 7.5 0 0 1 16 8.5z" />
      <path fill="#fff" d="M12.85 11.6c-.18-.4-.36-.41-.53-.42l-.45-.01c-.16 0-.41.06-.63.3-.22.24-.83.81-.83 1.97 0 1.16.85 2.29.97 2.45.12.16 1.65 2.64 4.07 3.6 2.01.79 2.42.63 2.86.59.43-.04 1.4-.57 1.6-1.13.2-.55.2-1.02.14-1.12-.06-.1-.22-.16-.45-.28-.24-.12-1.4-.69-1.62-.77-.22-.08-.37-.12-.53.12-.16.24-.61.77-.74.93-.14.16-.27.18-.51.06-.24-.12-1-.37-1.91-1.18-.71-.63-1.18-1.4-1.32-1.64-.14-.24-.01-.37.11-.49.11-.11.24-.28.36-.43.12-.14.16-.24.24-.4.08-.16.04-.3-.02-.42-.06-.12-.52-1.28-.74-1.75z" />
    </svg>
  );
}

// ── Botón / CTA
function CTA({ href, children, variant = "primary", external = false, onClick, className = "", icon = "arrow" }) {
  const base =
    "cta inline-flex items-center justify-center gap-2.5 rounded-full font-cta select-none transition-all duration-300";
  const variants = {
    primary: "bg-[var(--durazno)] text-[var(--tinta)] hover:brightness-[1.04] shadow-[0_10px_30px_-12px_rgba(244,166,120,0.9)]",
    outlineLight: "border-2 border-[rgba(251,248,244,0.6)] text-[var(--papel)] hover:bg-[rgba(251,248,244,0.12)] hover:border-[var(--papel)]",
    outlineDark: "border-2 border-[var(--verde)] text-[var(--pinar)] hover:bg-[rgba(93,174,158,0.1)]",
    ghostLight: "text-[var(--papel)] hover:opacity-80",
    verde: "bg-[var(--verde)] text-white hover:brightness-[1.04] shadow-[0_10px_30px_-12px_rgba(93,174,158,0.9)]",
  };
  return (
    <a
      href={href}
      onClick={onClick}
      target={external ? "_blank" : undefined}
      rel={external ? "noopener noreferrer" : undefined}
      className={`${base} ${variants[variant]} ${className}`}
      style={{ padding: "0.95rem 1.6rem" }}
    >
      <span>{children}</span>
      {icon === "arrow" && <Icon name="arrow" size={18} />}
      {icon === "wa" && <WABadge size={22} />}
    </a>
  );
}

// ── Iconografía line-art (trazo fino, terminales redondeadas, 24×24)
const ICONS = {
  arrow: <><path d="M4 12h15" /><path d="M13 6l6 6-6 6" /></>,
  whatsapp: (
    <><path d="M5 19l1.3-3.7A7.2 7.2 0 1 1 9 18.4L5 19z" />
      <path d="M9.2 9.3c.2 1.6 1.9 3.3 3.5 3.5.5.1.9-.2 1.2-.6.2-.3.5-.4.8-.2l1.1.7c.3.2.4.6.2.9-.5.8-1.5 1.1-2.5.8-2-.6-3.7-2.3-4.3-4.3-.3-1 .1-2 .9-2.5.3-.2.7-.1.9.2l.6 1c.2.3.1.6-.1.9-.4.3-.7.7-.6 1.2" /></>
  ),
  chevronDown: <><path d="M6 9l6 6 6-6" /></>,
  menu: <><path d="M4 7h16" /><path d="M4 12h16" /><path d="M4 17h16" /></>,
  close: <><path d="M6 6l12 12" /><path d="M18 6L6 18" /></>,
  // Adicción
  primaria: <><circle cx="12" cy="12" r="8" /><circle cx="12" cy="12" r="2.6" /></>,
  progresiva: <><path d="M4 16c3 0 3-5 6-5s3 4 6 4" /><path d="M16 9h4v4" /><path d="M16 15l4-4" /></>,
  tratable: <><path d="M12 21v-7" /><path d="M12 14c0-3 2.4-5.4 6-5.5-.1 3.4-2.4 5.6-6 5.5z" /><path d="M12 16c0-2.4-1.8-4.3-5-4.4.1 2.8 2 4.5 5 4.4z" /></>,
  // Tratamientos
  casa: <><path d="M4 11l8-6 8 6" /><path d="M6 10v9h12v-9" /><path d="M10 19v-5h4v5" /></>,
  sol: <><circle cx="12" cy="12" r="4" /><path d="M12 3v2.5M12 18.5V21M3 12h2.5M18.5 12H21M5.6 5.6l1.8 1.8M16.6 16.6l1.8 1.8M18.4 5.6l-1.8 1.8M7.4 16.6l-1.8 1.8" /></>,
  camino: <><path d="M7 21c0-4 10-4 10-9s-8-3-8-7" /><circle cx="9" cy="5" r="1.4" /><circle cx="15" cy="12" r="1.4" /><circle cx="8" cy="19" r="1.4" /></>,
  consejeria: <><path d="M4 6.5A2.5 2.5 0 0 1 6.5 4h11A2.5 2.5 0 0 1 20 6.5v6A2.5 2.5 0 0 1 17.5 15H10l-4 4v-4H6.5A2.5 2.5 0 0 1 4 12.5z" /><path d="M9 9.5h6M9 12h4" /></>,
  familia: <><circle cx="8.5" cy="8" r="2.4" /><circle cx="15.5" cy="8" r="2.4" /><path d="M4.5 19c0-2.8 1.8-4.5 4-4.5s4 1.7 4 4.5" /><path d="M12.5 18.7c.2-2.4 1.9-3.9 3.9-3.9 2.2 0 3.6 1.7 3.6 4.2" /></>,
  prevencion: <><path d="M12 3l7 2.5v5c0 4.3-3 7.5-7 9-4-1.5-7-4.7-7-9v-5z" /><path d="M9 11.5l2 2 4-4" /></>,
  // Enfoque
  equipo: <><circle cx="12" cy="7" r="2.3" /><circle cx="5.5" cy="10" r="2" /><circle cx="18.5" cy="10" r="2" /><path d="M8.5 18c0-2.4 1.6-4 3.5-4s3.5 1.6 3.5 4" /><path d="M2.8 16.5c0-1.9 1.3-3.2 2.7-3.2.8 0 1.5.3 2 .9" /><path d="M21.2 16.5c0-1.9-1.3-3.2-2.7-3.2-.8 0-1.5.3-2 .9" /></>,
  integral: <><circle cx="12" cy="12" r="8.2" /><circle cx="12" cy="12" r="4.6" /><circle cx="12" cy="12" r="1.2" /></>,
  rigor: <><path d="M12 4v15" /><path d="M7 19h10" /><path d="M5 8l7-2 7 2" /><path d="M5 8l-2 4.5c1.3 1 2.7 1 4 0z" /><path d="M19 8l-2 4.5c1.3 1 2.7 1 4 0z" /></>,
  sosten: <><path d="M8 12c0-2 1.4-3.4 3.2-3.4 1.3 0 2 .7 2.8 1.9.8 1.2 1.5 1.9 2.8 1.9C18.6 12.4 20 11 20 9" transform="translate(0 1.5)" /><path d="M16 12c0-2-1.4-3.4-3.2-3.4-1.3 0-2 .7-2.8 1.9-.8 1.2-1.5 1.9-2.8 1.9C5.4 12.4 4 11 4 9" transform="translate(0 4.2)" /></>,
  // Contacto
  location: <><path d="M12 21c4-4 6-7.2 6-10a6 6 0 1 0-12 0c0 2.8 2 6 6 10z" /><circle cx="12" cy="11" r="2.3" /></>,
  instagram: <><rect x="4" y="4" width="16" height="16" rx="4.5" /><circle cx="12" cy="12" r="3.5" /><circle cx="16.8" cy="7.2" r="0.6" fill="currentColor" stroke="none" /></>,
  globe: <><circle cx="12" cy="12" r="8" /><path d="M4 12h16" /><path d="M12 4c2.4 2.2 3.6 5 3.6 8s-1.2 5.8-3.6 8c-2.4-2.2-3.6-5-3.6-8s1.2-5.8 3.6-8z" /></>,
  check: <><path d="M5 12.5l4.5 4.5L19 7" /></>,
};

function Icon({ name, size = 24, stroke = 1.6, className = "", style = {} }) {
  return (
    <svg
      width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round"
      className={className} style={style} aria-hidden="true"
    >
      {ICONS[name] || null}
    </svg>
  );
}

// ── Formas orgánicas decorativas (círculo, anillo) — siempre al fondo
function Blob({ color, size = 320, top, left, right, bottom, opacity = 1, ring = false, className = "", blur = 0, parallax = true, speed }) {
  const s = typeof size === "number" ? `${size}px` : size;
  // Las formas más grandes se mueven más lento (sensación de profundidad).
  const numericSize = typeof size === "number" ? size : 320;
  const spd = speed != null ? speed : Math.max(0.03, Math.min(0.12, 90 / numericSize));
  const pAttrs = parallax ? { "data-parallax": "", "data-speed": spd } : {};
  return (
    <span
      aria-hidden="true"
      className={"organic " + className}
      {...pAttrs}
      style={{
        position: "absolute", top, left, right, bottom, width: s, height: s,
        borderRadius: "50%", opacity, pointerEvents: "none", filter: blur ? `blur(${blur}px)` : undefined,
        ...(ring
          ? { border: `2px solid ${color}`, background: "transparent" }
          : { background: color }),
      }}
    />
  );
}

// ── Onda divisoria entre secciones (curva, nunca ángulo)
function Wave({ color = "var(--papel)", flip = false, height = 90, className = "" }) {
  return (
    <div className={"wave-wrap " + className} style={{ lineHeight: 0, transform: flip ? "scaleY(-1)" : "none" }} aria-hidden="true">
      <svg viewBox="0 0 1440 120" preserveAspectRatio="none" style={{ display: "block", width: "100%", height }}>
        <path fill={color} d="M0,64 C220,120 420,8 720,40 C1010,72 1230,120 1440,56 L1440,120 L0,120 Z" />
      </svg>
    </div>
  );
}

// ── Slot de imagen (placeholder con proporción correcta; el usuario puede soltar su foto)
function Slot({ id, ratio = "16 / 9", shape = "rounded", radius = 20, label, className = "", style = {}, circle = false }) {
  return (
    <div className={"slot-frame " + className} style={{ aspectRatio: ratio, ...style }}>
      <image-slot
        id={id}
        shape={circle ? "circle" : shape}
        radius={radius}
        placeholder={label}
        style={{ width: "100%", height: "100%", display: "block" }}
      ></image-slot>
    </div>
  );
}

Object.assign(window, { Wing, Reveal, Eyebrow, CTA, Icon, WABadge, Blob, Wave, Slot, ScrollProgress });
