// Shared UI primitives. Zero collisions: every styles object is namespaced.

const { useEffect, useRef, useState, useMemo, createContext, useContext } = React;

const CAL_URL = "https://cal.com/zynflow/consultation";
const TEL_URL = "tel:+14388173485";
const TEL_DISPLAY = "(438) 817-3485";
const EMAIL = "hamza@zynflow.ca";

// ---------- Language context ----------
const LangCtx = createContext({ lang: "fr", setLang: () => {}, t: window.Z_DICT.fr });

function LangProvider({ children }) {
  const [lang, setLang] = useState(() => {
    try { return localStorage.getItem("zyn-lang") || "fr"; } catch (e) { return "fr"; }
  });
  useEffect(() => {
    try { localStorage.setItem("zyn-lang", lang); } catch (e) {}
    document.documentElement.lang = lang;
  }, [lang]);
  const value = useMemo(() => ({ lang, setLang, t: window.Z_DICT[lang] }), [lang]);
  return <LangCtx.Provider value={value}>{children}</LangCtx.Provider>;
}

const useLang = () => useContext(LangCtx);

// ---------- Reveal on scroll ----------
function Reveal({ children, delay = 0, className = "", as: As = "div" }) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let done = false;
    const reveal = () => {
      if (done) return;
      done = true;
      setTimeout(() => el && el.classList.add("in"), delay);
    };

    // Safety-net fallback: if the element is already in (or near) the viewport
    // on mount, just reveal it after one frame. Covers iframe/embedded
    // contexts where IntersectionObserver may not dispatch reliably.
    const safety = requestAnimationFrame(() => {
      const rect = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      if (rect.top < vh + 200) reveal();
    });

    let io;
    if ("IntersectionObserver" in window) {
      io = new IntersectionObserver((entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            reveal();
            io.unobserve(el);
          }
        });
      }, { threshold: 0.12, rootMargin: "0px 0px -40px 0px" });
      io.observe(el);
    } else {
      reveal();
    }

    // Final belt-and-suspenders: ensure nothing stays invisible past 1.2s.
    const t = setTimeout(reveal, 1200);

    return () => {
      cancelAnimationFrame(safety);
      clearTimeout(t);
      if (io) io.disconnect();
    };
  }, [delay]);
  return <As ref={ref} className={`reveal ${className}`}>{children}</As>;
}

// ---------- Buttons ----------
function PrimaryBtn({ children, href, onClick, target, className = "", iconRight = true, ...rest }) {
  const cls = `inline-flex items-center justify-center gap-2 px-5 h-12 rounded-full bg-ink text-white text-[15px] font-medium tracking-tighter2 transition-all duration-200 hover:bg-[#1a1a1a] hover:-translate-y-0.5 active:translate-y-0 focus-ring ${className}`;
  const inner = (
    <>
      <span>{children}</span>
      {iconRight && <ArrowIcon className="w-4 h-4 transition-transform duration-200 group-hover:translate-x-0.5" />}
    </>
  );
  if (href) return <a className={`group ${cls}`} href={href} target={target} rel={target === "_blank" ? "noopener noreferrer" : undefined} onClick={onClick} {...rest}>{inner}</a>;
  return <button className={`group ${cls}`} onClick={onClick} {...rest}>{inner}</button>;
}

function GhostBtn({ children, href, onClick, target, className = "", iconRight = true, ...rest }) {
  const cls = `inline-flex items-center justify-center gap-2 px-5 h-12 rounded-full border border-line bg-white text-ink text-[15px] font-medium tracking-tighter2 transition-all duration-200 hover:border-ink/40 hover:bg-line2/40 hover:-translate-y-0.5 active:translate-y-0 focus-ring ${className}`;
  const inner = (
    <>
      <span>{children}</span>
      {iconRight && <ArrowIcon className="w-4 h-4 transition-transform duration-200 group-hover:translate-x-0.5" />}
    </>
  );
  if (href) return <a className={`group ${cls}`} href={href} target={target} rel={target === "_blank" ? "noopener noreferrer" : undefined} onClick={onClick} {...rest}>{inner}</a>;
  return <button className={`group ${cls}`} onClick={onClick} {...rest}>{inner}</button>;
}

function AccentBtn({ children, href, onClick, target, className = "", ...rest }) {
  const cls = `inline-flex items-center justify-center gap-2 px-5 h-12 rounded-full bg-accent text-white text-[15px] font-medium tracking-tighter2 transition-all duration-200 hover:bg-accent-dark hover:-translate-y-0.5 active:translate-y-0 focus-ring ${className}`;
  const inner = (
    <>
      <span>{children}</span>
      <ArrowIcon className="w-4 h-4 transition-transform duration-200 group-hover:translate-x-0.5" />
    </>
  );
  if (href) return <a className={`group ${cls}`} href={href} target={target} rel={target === "_blank" ? "noopener noreferrer" : undefined} onClick={onClick} {...rest}>{inner}</a>;
  return <button className={`group ${cls}`} onClick={onClick} {...rest}>{inner}</button>;
}

// ---------- Icons (custom, simple) ----------
function ArrowIcon({ className = "w-4 h-4" }) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
      <path d="M5 12h14" /><path d="M13 6l6 6-6 6" />
    </svg>
  );
}
function PhoneIcon({ className = "w-5 h-5" }) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
      <path d="M22 16.92V20a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6A19.79 19.79 0 0 1 2.12 4.18 2 2 0 0 1 4.11 2h3.09a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92Z" />
    </svg>
  );
}
function MailIcon({ className = "w-5 h-5" }) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
      <rect x="3" y="5" width="18" height="14" rx="2" /><path d="M3 7l9 7 9-7" />
    </svg>
  );
}
function CalIcon({ className = "w-5 h-5" }) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
      <rect x="3" y="4" width="18" height="17" rx="2.5" /><path d="M3 10h18M8 2v4M16 2v4" />
    </svg>
  );
}
function CheckIcon({ className = "w-4 h-4" }) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
      <path d="M5 13l4 4L19 7" />
    </svg>
  );
}
function MenuIcon({ className = "w-5 h-5" }) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" className={className} aria-hidden="true">
      <path d="M4 7h16M4 12h16M4 17h16" />
    </svg>
  );
}
function CloseIcon({ className = "w-5 h-5" }) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" className={className} aria-hidden="true">
      <path d="M6 6l12 12M18 6L6 18" />
    </svg>
  );
}

// Niche icons (custom, simple geometry — avoid emojis / over-detailed SVGs)
function HouseIcon({ className }) { return (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
    <path d="M3 11l9-7 9 7" /><path d="M5 9.5V20h14V9.5" /><path d="M10 20v-5h4v5" />
  </svg>
); }
function PercentIcon({ className }) { return (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
    <circle cx="7.5" cy="7.5" r="2.5" /><circle cx="16.5" cy="16.5" r="2.5" /><path d="M5 19L19 5" />
  </svg>
); }
function ToothIcon({ className }) { return (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
    <path d="M7 4c-2 0-3 1.5-3 3.5C4 11 6 13 6.5 16c.4 2.4.7 4 2 4 1.2 0 1.5-1.5 2-3.5.3-1.2.7-1.7 1.5-1.7s1.2.5 1.5 1.7c.5 2 .8 3.5 2 3.5 1.3 0 1.6-1.6 2-4 .5-3 2.5-5 2.5-8.5 0-2-1-3.5-3-3.5-1.7 0-2.5 1-5 1S8.7 4 7 4Z" />
  </svg>
); }
function ScalesIcon({ className }) { return (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
    <path d="M12 4v16" /><path d="M5 20h14" /><path d="M5 8h14" /><path d="M5 8l-3 6a4 4 0 0 0 6 0L5 8Z" /><path d="M19 8l-3 6a4 4 0 0 0 6 0L19 8Z" />
  </svg>
); }

// ---------- Logo (wordmark) ----------
function Logo({ className = "", mono = false }) {
  const fg = mono ? "#FAFAFA" : "#0A0A0A";
  const ac = "#2E75B6";
  return (
    <a
      href="#/"
      className={`inline-flex items-baseline ${className}`}
      aria-label="Zynflow — accueil"
      style={{
        fontFamily: "'Inter', ui-sans-serif, system-ui, sans-serif",
        fontWeight: 700,
        fontSize: "22px",
        letterSpacing: "-0.025em",
        lineHeight: 1,
        color: fg
      }}
    >
      <span>Zynflow</span>
      <span
        aria-hidden="true"
        style={{
          display: "inline-block",
          width: "6px",
          height: "6px",
          borderRadius: "999px",
          background: ac,
          marginLeft: "3px",
          transform: "translateY(-1px)"
        }}
      />
    </a>
  );
}

// ---------- Navbar ----------
function Navbar({ route, setRoute }) {
  const { t, lang, setLang } = useLang();
  const [open, setOpen] = useState(false);
  const [scrolled, setScrolled] = useState(false);

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 8);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  useEffect(() => { setOpen(false); }, [route]);

  const items = [
    { id: "home", label: t.nav.home },
    { id: "services", label: t.nav.services },
    { id: "blog", label: t.nav.blog },
    { id: "contact", label: t.nav.contact }
  ];

  return (
    <header className={`sticky top-0 z-50 transition-all duration-300 ${scrolled ? "bg-bg/85 backdrop-blur-md border-b border-line" : "bg-transparent border-b border-transparent"}`}>
      <div className="max-w-[1240px] mx-auto px-6 md:px-10 h-16 md:h-[72px] flex items-center justify-between">
        <button onClick={() => setRoute("home")} className="focus-ring rounded">
          <Logo />
        </button>

        <nav className="hidden md:flex items-center gap-1">
          {items.map((it) => (
            <button
              key={it.id}
              onClick={() => setRoute(it.id)}
              className={`px-3 h-9 rounded-full text-[14px] tracking-tighter2 transition-colors ${route === it.id ? "text-ink" : "text-ink-muted hover:text-ink"}`}
            >
              {it.label}
              {route === it.id && <span className="ml-2 inline-block w-1 h-1 rounded-full bg-accent align-middle"></span>}
            </button>
          ))}
        </nav>

        <div className="flex items-center gap-2">
          <button
            onClick={() => setLang(lang === "fr" ? "en" : "fr")}
            className="hidden sm:inline-flex items-center gap-1 h-9 px-3 rounded-full border border-line text-[12px] font-medium tracking-[0.08em] text-ink-muted hover:text-ink hover:border-ink/30 transition-colors focus-ring"
            aria-label="Toggle language"
          >
            <span className={lang === "fr" ? "text-ink" : ""}>FR</span>
            <span className="text-line">·</span>
            <span className={lang === "en" ? "text-ink" : ""}>EN</span>
          </button>
          <a
            href={CAL_URL} target="_blank" rel="noopener noreferrer"
            className="hidden md:inline-flex items-center gap-2 h-9 px-4 rounded-full bg-ink text-white text-[13px] font-medium tracking-tighter2 hover:bg-[#1a1a1a] transition-colors focus-ring"
          >
            {t.nav.cta}
            <ArrowIcon className="w-3.5 h-3.5" />
          </a>
          <button onClick={() => setOpen((o) => !o)} className="md:hidden inline-flex items-center justify-center w-10 h-10 rounded-full border border-line focus-ring" aria-label="Menu">
            {open ? <CloseIcon /> : <MenuIcon />}
          </button>
        </div>
      </div>

      {open && (
        <div className="md:hidden border-t border-line bg-bg/95 backdrop-blur-md">
          <div className="px-6 py-6 flex flex-col gap-1">
            {items.map((it) => (
              <button
                key={it.id}
                onClick={() => setRoute(it.id)}
                className={`text-left px-3 py-3 rounded-lg text-[18px] tracking-tighter2 ${route === it.id ? "text-ink bg-line2" : "text-ink-muted"}`}
              >
                {it.label}
              </button>
            ))}
            <div className="flex items-center gap-3 mt-3">
              <button
                onClick={() => setLang(lang === "fr" ? "en" : "fr")}
                className="inline-flex items-center gap-1 h-10 px-4 rounded-full border border-line text-[13px]"
              >
                <span className={lang === "fr" ? "text-ink font-medium" : "text-ink-muted"}>FR</span>
                <span className="text-line">·</span>
                <span className={lang === "en" ? "text-ink font-medium" : "text-ink-muted"}>EN</span>
              </button>
              <a href={CAL_URL} target="_blank" rel="noopener noreferrer" className="inline-flex items-center gap-2 h-10 px-4 rounded-full bg-ink text-white text-[13px]">
                {t.nav.cta} <ArrowIcon className="w-3.5 h-3.5" />
              </a>
            </div>
          </div>
        </div>
      )}
    </header>
  );
}

// ---------- Footer ----------
function Footer({ setRoute }) {
  const { t } = useLang();

  const linkCls = "text-ink-muted hover:text-ink hover:underline underline-offset-4 transition-all duration-200 text-left";

  const goAnchor = (routeId, anchorId) => {
    const currentHash = (window.location.hash || "").replace("#/", "").replace("#", "");
    const sameRoute = currentHash === routeId || (routeId === "home" && currentHash === "");
    if (!sameRoute) setRoute(routeId);
    const scrollIt = () => {
      const el = document.getElementById(anchorId);
      if (!el) return;
      const y = el.getBoundingClientRect().top + window.pageYOffset - 24;
      window.scrollTo({ top: y, behavior: "smooth" });
    };
    setTimeout(scrollIt, sameRoute ? 0 : 220);
  };

  const resources = [
    { label: t.footer.resourcesItems[0], onClick: () => goAnchor("home", "ai-audit") },
    { label: t.footer.resourcesItems[1], onClick: () => goAnchor("home", "roi-calculator") },
    { label: t.footer.resourcesItems[2], onClick: () => goAnchor("blog", "newsletter") }
  ];
  const legal = [
    { label: t.footer.legalItems[0], onClick: () => setRoute("politique-confidentialite") },
    { label: t.footer.legalItems[1], onClick: () => setRoute("conditions") },
    { label: t.footer.legalItems[2], onClick: () => setRoute("loi-25") }
  ];

  return (
    <footer className="border-t border-line bg-white">
      <div className="max-w-[1240px] mx-auto px-6 md:px-10 py-16 md:py-20">
        <div className="grid grid-cols-1 md:grid-cols-12 gap-10">
          <div className="md:col-span-4">
            <Logo />
            <p className="mt-5 text-ink-muted text-[15px] max-w-sm leading-relaxed">{t.footer.tagline}</p>
            <div className="mt-6 inline-flex items-center gap-2 text-[12px] font-mono text-ink-faint">
              <span className="inline-block w-1.5 h-1.5 rounded-full bg-emerald-500 live-dot" />
              zynflow.ca · live demo
            </div>
          </div>

          <div className="md:col-span-2">
            <div className="text-[11px] font-mono uppercase tracking-[0.16em] text-ink-faint">{t.footer.links}</div>
            <ul className="mt-4 space-y-2.5 text-[14.5px]">
              {[["home", t.nav.home], ["services", t.nav.services], ["blog", t.nav.blog], ["contact", t.nav.contact]].map(([id, label]) => (
                <li key={id}>
                  <button onClick={() => setRoute(id)} className={linkCls}>{label}</button>
                </li>
              ))}
            </ul>
          </div>

          <div className="md:col-span-2">
            <div className="text-[11px] font-mono uppercase tracking-[0.16em] text-ink-faint">{t.footer.pricing}</div>
            <ul className="mt-4 space-y-2.5 text-[14.5px]">
              {t.footer.pricingItems.map((p, i) => (
                <li key={i}>
                  <button onClick={() => setRoute("services")} className={linkCls}>{p}</button>
                </li>
              ))}
            </ul>
          </div>

          <div className="md:col-span-2">
            <div className="text-[11px] font-mono uppercase tracking-[0.16em] text-ink-faint">{t.footer.resources}</div>
            <ul className="mt-4 space-y-2.5 text-[14.5px]">
              {resources.map((r, i) => (
                <li key={i}>
                  <button onClick={r.onClick} className={linkCls}>{r.label}</button>
                </li>
              ))}
            </ul>
          </div>

          <div className="md:col-span-2">
            <div className="text-[11px] font-mono uppercase tracking-[0.16em] text-ink-faint">{t.footer.legal}</div>
            <ul className="mt-4 space-y-2.5 text-[14.5px]">
              {legal.map((l, i) => (
                <li key={i}>
                  <button onClick={l.onClick} className={linkCls}>{l.label}</button>
                </li>
              ))}
            </ul>
          </div>
        </div>

        <div className="mt-12 pt-6 border-t border-line flex flex-col md:flex-row md:items-center md:justify-between gap-3">
          <div className="space-y-1">
            <p className="text-[12px] font-mono text-ink-faint">{t.footer.copyright}</p>
            <p className="text-[12px] font-mono text-ink-faint">{t.footer.compliance}</p>
          </div>
          <div className="flex items-center gap-4 text-[12.5px]">
            <a href={TEL_URL} className="text-ink hover:text-accent hover:underline underline-offset-4 transition-all duration-200">{TEL_DISPLAY}</a>
            <span className="text-line">·</span>
            <a href={`mailto:${EMAIL}`} className="text-ink hover:text-accent hover:underline underline-offset-4 transition-all duration-200">{EMAIL}</a>
          </div>
        </div>
      </div>
    </footer>
  );
}

// ---------- Loi 25 banner ----------
function Loi25Banner() {
  const { t } = useLang();
  const [hidden, setHidden] = useState(() => {
    try { return localStorage.getItem("zyn-loi25") === "ok"; } catch (e) { return false; }
  });
  if (hidden) return null;
  const dismiss = () => {
    setHidden(true);
    try { localStorage.setItem("zyn-loi25", "ok"); } catch (e) {}
  };
  return (
    <div className="fixed bottom-4 inset-x-4 md:inset-x-auto md:right-6 md:bottom-6 z-40 max-w-md">
      <div className="bg-white border border-line rounded-2xl shadow-[0_10px_40px_-12px_rgba(0,0,0,0.18)] p-4 flex items-start gap-3">
        <div className="mt-0.5 shrink-0 w-8 h-8 rounded-full bg-accent-tint text-accent grid place-items-center">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className="w-4 h-4"><path d="M12 2l8 4v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6l8-4Z" /><path d="M9 12l2 2 4-4" /></svg>
        </div>
        <p className="text-[13.5px] text-ink-muted leading-relaxed flex-1">{t.loi25.text}</p>
        <div className="shrink-0 flex items-center gap-1.5">
          <button onClick={dismiss} className="text-[12.5px] font-medium px-3 h-9 rounded-full text-ink-muted hover:text-ink hover:bg-line2 transition-colors">{t.loi25.more}</button>
          <button onClick={dismiss} className="text-[13px] font-medium px-3 h-9 rounded-full bg-ink text-white hover:bg-[#1a1a1a] transition-colors">{t.loi25.ok}</button>
        </div>
      </div>
    </div>
  );
}

// ---------- Eyebrow / Section heading ----------
function Eyebrow({ children, className = "" }) {
  return <div className={`text-[11px] font-mono uppercase tracking-[0.18em] text-ink-faint ${className}`}>{children}</div>;
}

function SectionHeader({ kicker, title, sub, align = "left", className = "" }) {
  return (
    <div className={`${align === "center" ? "text-center mx-auto max-w-3xl" : ""} ${className}`}>
      {kicker && <Eyebrow>{kicker}</Eyebrow>}
      <h2 className="mt-5 text-4xl md:text-[56px] leading-[1.02] tracking-tightest font-semibold text-ink text-balance">{title}</h2>
      {sub && <p className="mt-5 text-[17px] md:text-[19px] text-ink-muted leading-relaxed max-w-2xl text-balance">{sub}</p>}
    </div>
  );
}

// ---------- Inputs ----------
function TextInput({ label, hint, ...rest }) {
  return (
    <label className="block">
      {label && <span className="block text-[12px] font-medium text-ink-muted mb-2">{label}</span>}
      <input
        {...rest}
        className="w-full h-12 px-4 rounded-xl border border-line bg-white text-ink placeholder:text-ink-faint text-[15px] focus:border-accent focus:outline-none focus:ring-4 focus:ring-accent/15 transition-shadow"
      />
      {hint && <span className="block text-[12px] text-ink-faint mt-2">{hint}</span>}
    </label>
  );
}

function Textarea({ label, ...rest }) {
  return (
    <label className="block">
      {label && <span className="block text-[12px] font-medium text-ink-muted mb-2">{label}</span>}
      <textarea
        rows="5"
        {...rest}
        className="w-full px-4 py-3 rounded-xl border border-line bg-white text-ink placeholder:text-ink-faint text-[15px] focus:border-accent focus:outline-none focus:ring-4 focus:ring-accent/15 transition-shadow resize-none"
      />
    </label>
  );
}

// Striped placeholder for portrait/imagery slots
function Placeholder({ ratio = "1/1", label, className = "" }) {
  const styleStripe = {
    backgroundImage: "repeating-linear-gradient(45deg, rgba(10,10,10,0.045) 0 2px, transparent 2px 14px)"
  };
  return (
    <div className={`relative w-full overflow-hidden rounded-2xl border border-line bg-line2/40 ${className}`} style={{ aspectRatio: ratio }}>
      <div className="absolute inset-0" style={styleStripe} />
      <div className="absolute inset-0 grid place-items-center">
        <span className="font-mono text-[11px] uppercase tracking-[0.18em] text-ink-faint bg-bg/80 px-2.5 py-1 rounded">{label}</span>
      </div>
    </div>
  );
}

// ---------- Exports ----------
Object.assign(window, {
  LangProvider, LangCtx, useLang, Reveal,
  PrimaryBtn, GhostBtn, AccentBtn,
  ArrowIcon, PhoneIcon, MailIcon, CalIcon, CheckIcon, MenuIcon, CloseIcon,
  HouseIcon, PercentIcon, ToothIcon, ScalesIcon,
  Logo, Navbar, Footer, Loi25Banner,
  Eyebrow, SectionHeader, TextInput, Textarea, Placeholder,
  CAL_URL, TEL_URL, TEL_DISPLAY, EMAIL
});
