// ─────────────────────────────────────────────────────────────────────────
// DentalBox Landing — primitivas (Icon, Reveal, Photo, contenido por audiencia)
// ─────────────────────────────────────────────────────────────────────────
const { useState, useEffect, useRef } = React;

function Icon({ name, size = 20, sw = 1.75, className = "", style }) {
  const pascal = name.split("-").map((s) => s[0].toUpperCase() + s.slice(1)).join("");
  const L = window.lucide || {};
  const node = (L.icons && L.icons[pascal]) || L[pascal];
  const children = Array.isArray(node) ? node.map((c, i) => React.createElement(c[0], { key: i, ...c[1] })) : null;
  return React.createElement("svg", {
    xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24",
    fill: "none", stroke: "currentColor", strokeWidth: sw, strokeLinecap: "round",
    strokeLinejoin: "round", className, style, "aria-hidden": true,
  }, children);
}

// Reveal: aparece al entrar en viewport (estado-driven, robusto en captura)
function Reveal({ children, delay = 0, y = 18, className = "", as = "div" }) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    if (!("IntersectionObserver" in window)) { setShown(true); return; }
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } });
    }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  const Comp = as;
  return (
    <Comp ref={ref} className={className}
      style={{ opacity: shown ? 1 : 0, transform: shown ? "none" : `translateY(${y}px)`,
        transition: `opacity .7s cubic-bezier(.2,.7,.3,1) ${delay}ms, transform .7s cubic-bezier(.2,.7,.3,1) ${delay}ms` }}>
      {children}
    </Comp>
  );
}

// Contador animado
function Counter({ to, suffix = "", dur = 1400 }) {
  const ref = useRef(null);
  const [val, setVal] = useState(0);
  const done = useRef(false);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !done.current) {
          done.current = true;
          const t0 = performance.now();
          const tick = (t) => { const p = Math.min(1, (t - t0) / dur); setVal(Math.round((1 - Math.pow(1 - p, 3)) * to)); if (p < 1) requestAnimationFrame(tick); };
          requestAnimationFrame(tick);
        }
      });
    }, { threshold: 0.4 });
    io.observe(el); return () => io.disconnect();
  }, [to, dur]);
  return <span ref={ref}>{val.toLocaleString("es-CL")}{suffix}</span>;
}

function Photo({ photo, alt = "", className = "", w = 900, children }) {
  const [ok, setOk] = useState(false);
  const ref = useRef(null);
  useEffect(() => { const el = ref.current; if (el && el.complete && el.naturalWidth > 0) setOk(true); }, [photo]);
  return (
    <div className={"photo-fallback relative overflow-hidden " + className}>
      <img ref={ref} src={`https://images.unsplash.com/${photo}?auto=format&fit=crop&w=${w}&q=80`} alt={alt}
        onLoad={() => setOk(true)} decoding="async"
        className="absolute inset-0 w-full h-full object-cover transition-opacity duration-700" style={{ opacity: ok ? 1 : 0 }} />
      {children}
    </div>
  );
}

function Logo({ light = false, size = 22 }) {
  return (
    <span className="inline-flex items-center gap-2 select-none">
      <span className="grid place-items-center rounded-xl" style={{ width: size * 1.7, height: size * 1.7, background: light ? "rgba(255,255,255,.14)" : "#1F4E5F" }}>
        <Icon name="hexagon" size={size} className="text-white" style={{ fill: "rgba(255,255,255,.14)" }} />
      </span>
      <span className="font-extrabold tracking-tight" style={{ fontSize: size, color: light ? "#fff" : "#1F4E5F" }}>
        Dental<span style={{ color: light ? "rgba(255,255,255,.8)" : "#15202B" }}>Box</span>
      </span>
    </span>
  );
}

function clp(n) { return "$" + n.toLocaleString("es-CL"); }

// Toggle dual de audiencia
function AudienceToggle({ value, onChange, size = "md" }) {
  const big = size === "lg";
  const opt = (k, icon, label) => {
    const active = value === k;
    return (
      <button onClick={() => onChange(k)}
        className={"relative inline-flex items-center justify-center gap-2 rounded-full font-semibold transition-all duration-300 " +
          (big ? "h-12 px-6 text-[15px]" : "h-10 px-4 text-[14px]") + " " +
          (active ? "bg-brand text-white shadow-soft" : "text-muted hover:text-ink")}>
        <Icon name={icon} size={big ? 18 : 16} /> {label}
      </button>
    );
  };
  return (
    <div className={"inline-flex items-center gap-1 rounded-full bg-white border border-line " + (big ? "p-1.5 shadow-soft" : "p-1")}>
      {opt("odontologo", "stethoscope", "Soy odontólogo")}
      {opt("clinica", "building-2", "Soy clínica")}
    </div>
  );
}

// Contenido que cambia según audiencia
const AUDIENCE = {
  odontologo: {
    eyebrow: "Para profesionales",
    title: ["Atiende donde quieras,", "por jornada."],
    sub: "Reserva consultas dentales por jornada (AM o PM) en las mejores comunas de Santiago. Llega con tus pacientes; el resto ya está listo.",
    ctaMain: { label: "Explorar boxes", href: "marketplace.html?public=1", icon: "search" },
    ctaAlt: { label: "Crear cuenta gratis", href: "app.html?register=1", icon: "arrow-right" },
    pills: ["Sin contratos ni mensualidad", "Esterilización incluida", "Reserva en minutos"],
    pasos: [
      { icon: "search", t: "Busca y compara", d: "Filtra por comuna, equipamiento, precio y tipo de box. Mira fotos, reseñas y disponibilidad real." },
      { icon: "calendar-check", t: "Reserva tu jornada", d: "Elige AM, PM o día completo en el calendario y paga seguro. Recibes tu comprobante al instante." },
      { icon: "stethoscope", t: "Llega y atiende", d: "El box está limpio, esterilizado y equipado. Tú solo te preocupas de tus pacientes." },
    ],
    benefTitle: "Pensado para tu práctica",
    benefits: [
      { icon: "wallet", t: "Paga solo lo que usas", d: "Sin arriendo fijo ni gastos comunes. Una jornada o un mes completo, tú decides." },
      { icon: "map-pin", t: "Elige dónde atender", d: "Acércate a tus pacientes con boxes en Las Condes, Vitacura, Providencia, Ñuñoa y más." },
      { icon: "badge-check", t: "Espacios verificados", d: "Cada clínica pasa por verificación de identidad y equipamiento antes de publicar." },
      { icon: "sparkles", t: "Para cada especialidad", d: "Box clínico, estético o pabellón quirúrgico, según lo que necesites ese día." },
    ],
  },
  clinica: {
    eyebrow: "Para clínicas",
    title: ["Rentabiliza tus boxes", "en las horas muertas."],
    sub: "Publica tus consultas dentales y arriéndalas por jornada a profesionales verificados. Tú pones el espacio; nosotros, la demanda.",
    ctaMain: { label: "Publicar mi box", href: "app.html?role=clinica&register=1", icon: "plus-square" },
    ctaAlt: { label: "Ver cómo funciona", href: "#como-funciona", icon: "arrow-down" },
    pills: ["Publicar es gratis", "Tú defines precio y agenda", "Pagos quincenales garantizados"],
    pasos: [
      { icon: "plus-square", t: "Publica tu box", d: "Súbelo en minutos: tipo (clínico, estético o pabellón), fotos, equipamiento y precio por jornada." },
      { icon: "calendar-range", t: "Abre tu disponibilidad", d: "Define qué jornadas AM/PM quieres arrendar. Acepta o automatiza las solicitudes." },
      { icon: "banknote", t: "Recibe tus ingresos", d: "Liquidaciones quincenales directo a tu cuenta. Mira ocupación e ingresos en tu panel." },
    ],
    benefTitle: "Tu espacio, mejor aprovechado",
    benefits: [
      { icon: "trending-up", t: "Ingreso extra real", d: "Convierte jornadas vacías en ingresos. Sin costo de publicación ni permanencia." },
      { icon: "shield-check", t: "Solo profesionales verificados", d: "Trabajas con odontólogos validados por identidad y registro en la Superintendencia." },
      { icon: "sliders-horizontal", t: "Control total", d: "Tú defines precios, horarios, políticas de cancelación y quién entra a tu clínica." },
      { icon: "bar-chart-3", t: "Panel con métricas", d: "Ocupación, ingresos por tipo de box, reservas y reseñas, todo en un lugar." },
    ],
  },
};

const BOX_TIPOS_L = [
  { key: "clinico", label: "Box clínico", icon: "stethoscope", color: "brand", price: 45000,
    desc: "Diagnóstico, operatoria, endodoncia y controles. El caballo de batalla de toda consulta.",
    equip: ["Sillón dental", "RX periapical", "Autoclave", "Fotocurado"], photo: "photo-1629909613654-28e377c37b09" },
  { key: "estetico", label: "Box estético", icon: "sparkles", color: "estetico", price: 68000,
    desc: "Blanqueamiento, carillas y diseño de sonrisa en un ambiente pensado para la estética.",
    equip: ["Lámpara LED de blanqueo", "Cámara intraoral", "Sillón premium", "Iluminación de color"], photo: "photo-1609840114035-3c981b782dfe" },
  { key: "pabellon", label: "Box pabellón", icon: "activity-square", color: "pabellon", price: 95000,
    desc: "Cirugía e implantología con estándar quirúrgico, campo estéril y monitoreo.",
    equip: ["Sillón quirúrgico", "Motor de implantes", "Lámpara cialítica", "Monitor de signos"], photo: "photo-1588776813677-77aaf5595b83" },
];

const FEATURED = [
  { name: "Atelier El Golf", comuna: "Las Condes", tipo: "clinico", price: 58000, rating: 4.9, photo: "photo-1629909613654-28e377c37b09", today: true },
  { name: "Estudio de Sonrisa", comuna: "Vitacura", tipo: "estetico", price: 68000, rating: 4.9, photo: "photo-1609840114035-3c981b782dfe", today: false },
  { name: "Casa Manuel Montt", comuna: "Providencia", tipo: "clinico", price: 48000, rating: 4.7, photo: "photo-1606811841689-23dfddce3e95", today: true },
];

const COLORS = {
  brand:    { soft: "bg-brand-50 text-brand-600", solid: "text-brand-600", bar: "#256175", chip: "bg-brand-50 text-brand-700" },
  estetico: { soft: "bg-estetico-50 text-estetico", solid: "text-estetico", bar: "#C77D1A", chip: "bg-estetico-50 text-estetico" },
  pabellon: { soft: "bg-pabellon-50 text-pabellon", solid: "text-pabellon", bar: "#C0395A", chip: "bg-pabellon-50 text-pabellon" },
};

Object.assign(window, { Icon, Reveal, Counter, Photo, Logo, clp, AudienceToggle, AUDIENCE, BOX_TIPOS_L, FEATURED, COLORS });
