/* global React */
// Content model — used by both design directions. Single source of truth.

const TAND = {
  name: "tand",
  subname: "Dental Wellness",
  slogan: "Amarás venir al dentista",
  guarantee: "Si no amas tu primera cita, te la regresamos.",
  phone: "442 241 0284",
  phoneHref: "tel:+524422410284",
  whatsapp: "442 241 0284",
  locations: [
    {
      id: "arcos",
      name: "Arcos",
      address: "Violetas 50, int. 5 · Jardines de Querétaro",
      hours: "L–V 9:00–19:00 · Sáb 9:00–14:00",
      lat: 20.5790,
      lng: -100.4170,
      mapLink: "https://www.google.com/maps/search/?api=1&query=Violetas+50+Jardines+de+Queretaro",
    },
    {
      id: "centro",
      name: "Centro",
      address: "Ezequiel Montes 34 · Hospital Santa Rosa de Viterbo",
      hours: "L–V 9:00–19:00 · Sáb 9:00–14:00",
      lat: 20.5897,
      lng: -100.3961,
      mapLink: "https://www.google.com/maps/search/?api=1&query=Ezequiel+Montes+34+Santa+Rosa+de+Viterbo+Queretaro",
    },
    {
      id: "juriquilla",
      name: "Juriquilla",
      address: "Próxima sede en zona norte",
      hours: "Abre en 2026",
      soon: true,
    },
  ],
  services: [
    {
      id: "bienestar",
      eyebrow: "01",
      title: "Bienestar dental",
      lede: "Prevención, limpieza y tratamientos que mantienen tu boca sana antes de que duela.",
      items: ["Limpieza profunda", "Tratamiento de caries", "Endodoncia", "Extracciones"],
      asset: "polishing",
    },
    {
      id: "ortodoncia",
      eyebrow: "02",
      title: "Ortodoncia y alineación",
      lede: "Alineadores invisibles, brackets discretos y ortopedia para cada edad y cada caso.",
      items: ["Invisalign", "Brackets estéticos", "Ortopedia maxilar", "Férulas para bruxismo"],
      asset: "aligners",
    },
    {
      id: "estetica",
      eyebrow: "03",
      title: "Estética dental",
      lede: "Diseño de sonrisa, blanqueamiento profesional y carillas hechas a la medida de tu rostro.",
      items: ["Blanqueamiento profesional", "Carillas cerámicas", "Diseño de sonrisa", "Contorneado estético"],
      asset: "veneer",
    },
    {
      id: "implantes",
      eyebrow: "04",
      title: "Prótesis e implantes",
      lede: "Recupera la pieza que perdiste con implantes, coronas y rehabilitación planeada en 3D.",
      items: ["Implantes All-on-4", "Coronas cerámicas", "Puentes fijos", "Prótesis removibles"],
      asset: "implant",
    },
  ],
  differentiators: [
    {
      icon: "garantia",
      title: "Garantía de experiencia",
      body: "Si tu primera cita no te enamora, no te cobramos. Sin formularios, sin letras chicas. Aplica desde la primera visita.",
    },
    {
      icon: "seguimiento",
      title: "Seguimiento que no se olvida de ti",
      body: "Una asistente dental real te escribe al día siguiente, te recuerda tu próxima cita y vigila cómo evoluciona tu tratamiento.",
    },
    {
      icon: "financiamiento",
      title: "Financiamiento hasta 24 MSI",
      body: "Meses sin intereses, descuento por nómina y crédito directo. Empiezas el tratamiento el mismo día que decides.",
    },
    {
      icon: "tecnologia",
      title: "Tecnología que ahorra silla",
      body: "Escáner intraoral 3D, radiografía digital de baja dosis y planeación guiada por software. Menos tiempo, más precisión.",
    },
    {
      icon: "especialistas",
      title: "Especialistas, no improvisaciones",
      body: "Cada tratamiento lo realiza el especialista del área: periodoncia, ortodoncia, implantología, estética y odontopediatría.",
    },
    {
      icon: "cuidado",
      title: "Cero juicio sobre tu historia",
      body: "Llevas años sin venir, te da pena, te dieron miedo en otro lado. Está bien. Empezamos juntos desde donde estés.",
    },
  ],
  tools: [
    {
      id: "cotizador",
      title: "Cotizador online",
      body: "Arma tu plan y conoce el precio antes de pisar la clínica.",
      cta: "Cotizar tratamiento",
    },
    {
      id: "simulador",
      title: "Simulador de sonrisa",
      body: "Sube una foto y visualiza tu resultado con IA en menos de dos minutos.",
      cta: "Probar simulador",
    },
    {
      id: "videoconsulta",
      title: "Videoconsulta gratis",
      body: "15 minutos por WhatsApp con una especialista. Sin costo, sin compromiso.",
      cta: "Empezar por WhatsApp",
    },
  ],
  testimonials: [
    {
      name: "Ana María C.",
      age: "Paciente desde 2024 · Arcos",
      quote:
        "Siempre me dio pena ir al dentista por mi historial. Desde la primera cita en tand me escucharon sin juzgar. Por fin me siento cuidada.",
      treatment: "Bienestar dental + ortodoncia",
      asset: "aligners",
    },
    {
      name: "Chava C.",
      age: "Paciente desde 2023 · Centro",
      quote:
        "Es la primera vez que un dentista me escribe al día siguiente para saber cómo me sentí. Y así fue después de cada cita. Sentí que de verdad les importaba.",
      treatment: "Implantes + corona",
      asset: "implant",
    },
    {
      name: "Mónica R.",
      age: "Paciente desde 2022 · Arcos",
      quote:
        "Soy miedosa con el dentista y aquí me tuvieron paciencia. Tanto, que estando en Canadá llamé por una molestia y me orientaron sin dudarlo.",
      treatment: "Diseño de sonrisa",
      asset: "veneer",
    },
    {
      name: "Nana A.",
      age: "Paciente desde 2025 · Arcos",
      quote:
        "Te sorprende desde que entras: el espacio, el trato, la forma en que te explican todo. Salí sin una sola duda y ya estoy recomendándolos.",
      treatment: "Carillas cerámicas",
      asset: "veneer",
    },
  ],
  googleRating: { score: "4.9", count: 412 },
  faqs: [
    {
      q: "¿Cómo funciona la garantía de experiencia?",
      a: "Si terminas tu primera cita y no la amaste, nos lo dices y te la regresamos. Sin formularios, sin letra chica. Confiamos tanto en cómo tratamos a nuestros pacientes que nos jugamos la cita.",
    },
    {
      q: "¿Aceptan seguros dentales?",
      a: "Trabajamos con las principales aseguradoras del país. Si tienes una póliza, la revisamos contigo en la primera cita. También ofrecemos financiamiento propio hasta 24 MSI sin necesidad de tarjeta.",
    },
    {
      q: "¿Puedo llevar a mis hijos?",
      a: "Sí. Tenemos odontopediatría en ambas sedes y la sala de espera está pensada para que vengan tranquilos (y sin miedo a la próxima visita).",
    },
    {
      q: "¿Cuánto dura una primera cita?",
      a: "Entre 45 y 60 minutos. Incluye diagnóstico 3D, plan de tratamiento, cotización detallada y todas tus dudas resueltas. Sin compromiso de continuar.",
    },
    {
      q: "¿Qué pasa si llevo años sin ir al dentista?",
      a: "Pasa muy seguido y no es problema. No vas a recibir un sermón. Vamos a revisar lo que hay, explicarte qué encontramos y construir contigo un plan a tu ritmo y a tu presupuesto.",
    },
  ],
  nav: [
    { label: "Servicios", href: "#servicios" },
    { label: "Por qué tand", href: "#diferenciales" },
    { label: "Herramientas", href: "#herramientas" },
    { label: "Sedes", href: "#sedes" },
    { label: "Blog", href: "#blog" },
  ],
  blog: [
    { tag: "Ortodoncia", title: "Brackets después de los 30: 7 razones para hacerlo (más allá de la estética)", read: "6 min" },
    { tag: "Estética", title: "Blanqueamiento dental en Querétaro: cuándo hacerlo y qué esperar", read: "4 min" },
    { tag: "Implantes", title: "¿Duele ponerse un implante? La verdad de principio a fin", read: "8 min" },
  ],
};

window.TAND = TAND;

// ————— Animation helpers —————
// Word-level blur reveal used mainly in the hero.
// Splits `text` into inline-block spans with an index CSS var so each
// word animates with a staggered delay (see .A-reveal-word in the CSS).
function A_Words(props) {
  var text = props.text;
  var start = props.start || 0;
  var em = props.em || [];
  var step = props.step;
  var base = props.base;
  var parts = String(text).split(" ").filter(Boolean);
  var children = [];
  parts.forEach(function (word, i) {
    var style = { "--i": start + i };
    if (step != null) style["--step"] = step + "ms";
    if (base != null) style["--base"] = base + "ms";
    var tag = em.indexOf(i) !== -1 ? "em" : "span";
    var wordEl = React.createElement(tag, {
      key: "w" + i,
      className: "A-reveal-word",
      style: style,
    }, word);
    children.push(wordEl);
    if (i < parts.length - 1) children.push(React.createElement(React.Fragment, { key: "s" + i }, " "));
  });
  return React.createElement(React.Fragment, null, children);
}

// Reveals `.A-reveal` elements on scroll using IntersectionObserver.
// Falls back to a scroll/resize listener that calls getBoundingClientRect,
// so preview/headless environments without working IO still reveal content.
function A_installRevealObserver() {
  if (window.__A_revealInstalled) {
    if (window.__A_revealScan) window.__A_revealScan();
    return;
  }
  window.__A_revealInstalled = true;

  var inView = function (el) {
    var r = el.getBoundingClientRect();
    var vh = window.innerHeight || document.documentElement.clientHeight;
    return r.top < vh * 0.9 && r.bottom > 0;
  };

  var scan = function () {
    var els = document.querySelectorAll(".A-reveal:not(.is-visible)");
    for (var i = 0; i < els.length; i++) {
      if (inView(els[i])) els[i].classList.add("is-visible");
    }
    return els.length;
  };
  window.__A_revealScan = scan;

  if (typeof window.IntersectionObserver === "function") {
    var obs = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("is-visible");
          obs.unobserve(entry.target);
        }
      });
    }, { threshold: 0.12, rootMargin: "0px 0px -80px 0px" });

    var observeAll = function () {
      var els = document.querySelectorAll(".A-reveal:not(.is-visible)");
      for (var i = 0; i < els.length; i++) obs.observe(els[i]);
    };
    observeAll();
    setTimeout(observeAll, 300);
    setTimeout(observeAll, 1200);
  }

  window.addEventListener("scroll", scan, { passive: true });
  window.addEventListener("resize", scan);
  scan();
  setTimeout(scan, 150);
  setTimeout(scan, 600);
}

// Initialize Lenis smooth scroll. Skipped if user prefers reduced motion or
// Lenis is not loaded. Exposes `window.__A_lenis` for manual control.
function A_initLenis() {
  if (window.__A_lenisInitialized) return;
  window.__A_lenisInitialized = true;

  var reduced = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  if (reduced) return;
  if (typeof window.Lenis !== "function") return;

  var lenis = new window.Lenis({
    duration: 1.15,
    easing: function (t) { return Math.min(1, 1.001 - Math.pow(2, -10 * t)); },
    smoothWheel: true,
    smoothTouch: false,
    touchMultiplier: 1.6,
    wheelMultiplier: 1,
  });
  window.__A_lenis = lenis;

  function raf(time) {
    lenis.raf(time);
    window.requestAnimationFrame(raf);
  }
  window.requestAnimationFrame(raf);

  // Anchor links (href="#...") — let Lenis handle the scroll so it stays smooth
  document.addEventListener("click", function (e) {
    var a = e.target && e.target.closest ? e.target.closest('a[href^="#"]') : null;
    if (!a) return;
    var id = a.getAttribute("href");
    if (!id || id === "#" || id === "#whatsapp" || id === "#wa" || id === "#portal" || id === "#sim" || id === "#todas" || id === "#map") return;
    var target = document.querySelector(id);
    if (!target) return;
    e.preventDefault();
    lenis.scrollTo(target, { offset: -80, duration: 1.2 });
  });
}

window.A_Words = A_Words;
window.A_installRevealObserver = A_installRevealObserver;
window.A_initLenis = A_initLenis;
