const { useState, useEffect, useLayoutEffect, useRef, useId } = React;

/** Scroll-triggered intro (same motion as .hero-intro-reveal); respects prefers-reduced-motion. */
function useRevealOnScroll() {
  const ref = useRef(null);
  const [revealed, setRevealed] = useState(() => {
    if (typeof window === "undefined") return false;
    return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  });
  useEffect(() => {
    if (revealed) return undefined;
    const el = ref.current;
    if (!el) return undefined;
    if (typeof IntersectionObserver === "undefined") {
      setRevealed(true);
      return undefined;
    }
    const io = new IntersectionObserver(
      entries => {
        if (entries.some(e => e.isIntersecting)) setRevealed(true);
      },
      { root: null, rootMargin: "0px 0px -10% 0px", threshold: 0.15 }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [revealed]);
  return [ref, revealed];
}

/* =========================================================
   Nav
========================================================= */
function Nav({ onCtaClick }) {
  const [open, setOpen] = useState(false);
  useEffect(() => {
    const close = () => setOpen(false);
    window.addEventListener('resize', close);
    return () => window.removeEventListener('resize', close);
  }, []);
  return (
    <div className="nav-wrap">
      <nav className="nav" aria-label="Primary">
        <a href="#top" className="nav-logo" aria-label="Omiro home">
          <img src="assets/logo-omiro.png" alt="Omiro" />
        </a>
        <div className="nav-links">
          <a href="#problem">Problem</a>
          <a href="#what-to-measure">What to Measure</a>
          <a href="#how-it-works">How It Works</a>
          <a href="#members">Early Access Members</a>
          <a href="#faq">FAQ</a>
        </div>
        <button className="nav-cta" onClick={() => { window.posthog && posthog.capture('nav_cta_clicked'); onCtaClick(); }}>Join the Waitlist</button>
        <button className="nav-hamburger" onClick={() => setOpen(o => !o)} aria-label="Menu" aria-expanded={open}>
          {open ? (
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
          ) : (
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><line x1="3" y1="7" x2="21" y2="7"/><line x1="3" y1="17" x2="21" y2="17"/></svg>
          )}
        </button>
      </nav>
      {open && (
        <div className="mobile-menu">
          <a href="#problem" onClick={() => setOpen(false)}>Problem</a>
          <a href="#what-to-measure" onClick={() => setOpen(false)}>What to Measure</a>
          <a href="#how-it-works" onClick={() => setOpen(false)}>How It Works</a>
          <a href="#members" onClick={() => setOpen(false)}>Early Access Members</a>
          <a href="#faq" onClick={() => setOpen(false)}>FAQ</a>
          <button className="nav-cta" onClick={() => { setOpen(false); window.posthog && posthog.capture('nav_cta_clicked'); onCtaClick(); }}>Join the Waitlist</button>
        </div>
      )}
    </div>
  );
}

/* =========================================================
   Hero — translation layer visual (three panels)
========================================================= */
const HERO_ANSWER_STATES = [
  {
    layout: "metric",
    chart: "line",
    badge: "Q1 compliance completion",
    metric: "94.2%",
    trend: "+6.1% vs Q4",
    bars: [0.52, 0.32, 0.72, 0.44, 0.90]
  },
  {
    layout: "metric",
    badge: "Course completions this month",
    metric: "1,847",
    trend: "+312 vs last month",
    bars: [0.28, 0.45, 0.62, 0.82, 0.96]
  },
  {
    layout: "conversational",
    question: "What are our 6-month retention rates for new hire onboarding?",
    reply: "76% of new hires from the last 6 months are still active, up 11 points from the previous cohort. Most of the lift came from adding 90-day reinforcement modules in engineering and CS."
  },
  {
    layout: "metric",
    badge: "Avg time to certification",
    metric: "12.4 days",
    trend: "-2.1 days vs Q3",
    bars: [0.9, 0.78, 0.62, 0.48, 0.32]
  }
];

function MetricLineChart({ series }) {
  const gradId = `ht-line-${useId().replace(/:/g, "")}`;
  /* Wide viewBox (~7:1) so xMidYMid meet fills the card width without non-uniform stretch. */
  const w = 280;
  const h = 40;
  const k = w / 100;
  const padX = 4 * k;
  const padY = 4;
  const plotW = w - padX * 2;
  const plotH = h - padY * 2;
  const lineStrokeW = 2.25 * k;
  const dotStrokeW = 1.55 * k;
  const dotR = 2.05 * k;
  const n = series.length;
  const step = n > 1 ? plotW / (n - 1) : 0;
  const points = series.map((v, i) => {
    const x = padX + (n > 1 ? i * step : plotW / 2);
    const y = padY + plotH - v * plotH;
    return { x, y, v };
  });
  const linePoints = points.map(p => `${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(" ");
  const areaPoints = `${padX},${padY + plotH} ${linePoints} ${padX + plotW},${padY + plotH}`;
  return (
    <div className="ht-answer-line" aria-hidden="true">
      <svg viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="xMidYMid meet">
        <defs>
          <linearGradient id={gradId} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="rgba(37,99,235,0.22)" />
            <stop offset="100%" stopColor="rgba(37,99,235,0)" />
          </linearGradient>
        </defs>
        <polygon className="ht-answer-line-fill" points={areaPoints} fill={`url(#${gradId})`} />
        <polyline
          className="ht-answer-line-stroke"
          points={linePoints}
          fill="none"
          strokeWidth={lineStrokeW}
          strokeLinecap="round"
          strokeLinejoin="round"
        />
        {points.map((p, i) => (
          <circle
            key={i}
            className="ht-answer-line-dot"
            cx={p.x}
            cy={p.y}
            r={dotR}
            strokeWidth={dotStrokeW}
          />
        ))}
      </svg>
    </div>
  );
}

function renderMetricAnswerInner(s, innerRef) {
  return (
    <div ref={innerRef} className="ht-answer-slide-inner ht-answer-slide-inner--metric">
      <div className="ht-answer-head-row">
        <span className="ht-answer-badge">{s.badge}</span>
        <button type="button" className="ht-answer-pin" aria-label="Add to dashboard" title="Add to dashboard">+</button>
      </div>
      <div className="ht-answer-value">{s.metric}</div>
      <div className="ht-answer-trend">{s.trend}</div>
      {s.chart === "line" ? (
        <MetricLineChart series={s.bars} />
      ) : (
        <div className="ht-answer-bars">
          {s.bars.map((h, j) => (
            <i key={j} style={{ height: `${h * 100}%` }} />
          ))}
        </div>
      )}
      <p className="ht-answer-foot">Source: LMS API · Updated just now</p>
    </div>
  );
}

function HeroAnswerCarousel() {
  const [displayed, setDisplayed] = useState(0);
  const [exitingIdx, setExitingIdx] = useState(null);
  const [hover, setHover] = useState(false);
  const [reduceMotion, setReduceMotion] = useState(
    () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
  );
  const [lockedHeight, setLockedHeight] = useState(null);
  const cardRef = useRef(null);
  const measureRef = useRef(null);
  const clearExitTimer = useRef(null);

  useLayoutEffect(() => {
    const measure = () => {
      const inner = measureRef.current;
      const card = cardRef.current;
      if (!inner || !card) return;
      const cs = window.getComputedStyle(card);
      const pt = parseFloat(cs.paddingTop) || 0;
      const pb = parseFloat(cs.paddingBottom) || 0;
      const ih = Math.ceil(inner.getBoundingClientRect().height);
      if (ih <= 0) return;
      setLockedHeight(ih + pt + pb);
    };
    measure();
    const id = requestAnimationFrame(measure);
    const card = cardRef.current;
    if (!card || typeof ResizeObserver === "undefined") {
      return () => cancelAnimationFrame(id);
    }
    const ro = new ResizeObserver(() => measure());
    ro.observe(card);
    return () => {
      cancelAnimationFrame(id);
      ro.disconnect();
    };
  }, []);

  useEffect(() => {
    const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
    const onChange = () => setReduceMotion(mq.matches);
    onChange();
    mq.addEventListener("change", onChange);
    return () => mq.removeEventListener("change", onChange);
  }, []);

  useEffect(() => {
    if (reduceMotion) setExitingIdx(null);
  }, [reduceMotion]);

  useEffect(() => {
    if (hover) return;
    const dur =
      HERO_ANSWER_STATES[displayed]?.layout === "conversational" ? 8000 : 3000;
    const t = window.setTimeout(() => {
      if (reduceMotion) {
        setDisplayed(d => (d + 1) % HERO_ANSWER_STATES.length);
        return;
      }
      setDisplayed(d => {
        setExitingIdx(d);
        return (d + 1) % HERO_ANSWER_STATES.length;
      });
      if (clearExitTimer.current) window.clearTimeout(clearExitTimer.current);
      clearExitTimer.current = window.setTimeout(() => {
        setExitingIdx(null);
        clearExitTimer.current = null;
      }, 620);
    }, dur);
    return () => {
      window.clearTimeout(t);
      if (clearExitTimer.current) window.clearTimeout(clearExitTimer.current);
    };
  }, [displayed, reduceMotion, hover]);

  const cardLockStyle =
    lockedHeight != null
      ? { height: lockedHeight, minHeight: lockedHeight, maxHeight: lockedHeight }
      : undefined;

  return (
    <div
      ref={cardRef}
      className="ht-answer-card ht-answer-card--carousel"
      style={cardLockStyle}
      onMouseEnter={() => {
        setHover(true);
        if (clearExitTimer.current) {
          window.clearTimeout(clearExitTimer.current);
          clearExitTimer.current = null;
        }
        setExitingIdx(null);
      }}
      onMouseLeave={() => setHover(false)}
    >
      <div className="ht-answer-measure-sizer" aria-hidden="true">
        {renderMetricAnswerInner(HERO_ANSWER_STATES[0], measureRef)}
      </div>
      <div className="ht-answer-states" aria-live={reduceMotion ? "off" : "polite"}>
        {HERO_ANSWER_STATES.map((s, i) => {
          const show = i === displayed || i === exitingIdx;
          const isExiting = !reduceMotion && exitingIdx === i;
          const isEntering = !reduceMotion && displayed === i && exitingIdx != null && exitingIdx !== i;
          const isStable = displayed === i && exitingIdx === null;
          let cls = "ht-answer-slide";
          if (!show) cls += " is-hidden";
          else if (isExiting) cls += " is-exiting";
          else if (isEntering) cls += " is-entering";
          else if (isStable) cls += " is-stable";
          return (
            <div key={i} className={cls} aria-hidden={!show}>
              {s.layout === "metric" ? (
                renderMetricAnswerInner(s, null)
              ) : (
                <div className="ht-answer-slide-inner ht-answer-slide-inner--conv">
                  <div className="ht-conv-msgs">
                    <div className="msg user ht-conv-user">
                      <div className="bubble">{s.question}</div>
                    </div>
                    <div className="msg bot ht-conv-bot">
                      <div className="avatar" aria-hidden="true">O</div>
                      <div className="bubble">{s.reply}</div>
                    </div>
                  </div>
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function HeroTranslationVisual() {
  return (
    <div className="hero-translation" aria-hidden="true">
      <p className="hero-translation-ribbon">From this. To this. In seconds.</p>
      <div className="hero-translation-panels">
        <div className="ht-panel ht-panel--lms">
          <div className="ht-panel-label">Your LMS</div>
          <div className="ht-chaos-card">
            <table className="ht-csv">
              <thead>
                <tr>
                  <th>user_id</th>
                  <th>cmpltn_dt_iso</th>
                  <th>crs_id</th>
                  <th>mgr_lvl_cd</th>
                </tr>
              </thead>
              <tbody>
                <tr><td>u_88421</td><td>2025-03-14T19:41:02Z</td><td>crs_901</td><td>04</td></tr>
                <tr><td>u_12003</td><td>2025-03-11T08:22:51Z</td><td>crs_772</td><td>02</td></tr>
                <tr><td>u_44190</td><td>2025-03-09T16:03:00Z</td><td>crs_901</td><td>04</td></tr>
              </tbody>
            </table>
            <div className="ht-chaos-report">
              <div className="ht-chaos-filters">
                <span className="ht-fake-select">Org unit ▾</span>
                <span className="ht-fake-select">Date range ▾</span>
                <span className="ht-fake-select">Course grp ▾</span>
                <span className="ht-fake-select">Mgr lvl ▾</span>
              </div>
              <div className="ht-chaos-chart">
                <i style={{ height: "38%" }} /><i style={{ height: "52%" }} /><i style={{ height: "45%" }} /><i style={{ height: "68%" }} /><i style={{ height: "55%" }} /><i style={{ height: "72%" }} /><i style={{ height: "48%" }} />
              </div>
            </div>
          </div>
        </div>

        <div className="ht-panel ht-panel--omiro">
          <div className="ht-omiro-inner">
            <div className="ht-omiro-row">
              <div className="ht-arrow ht-arrow--in" aria-hidden="true">
                <svg viewBox="0 0 44 12" fill="none">
                  <path d="M2 6h32M30 2l8 4-8 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </div>
              <div className="ht-omiro-glow">
                <img src="assets/logo-omiro.png" alt="" className="ht-omiro-logo" />
              </div>
              <p className="ht-omiro-caption">Translation layer</p>
              <div className="ht-arrow ht-arrow--out" aria-hidden="true">
                <svg viewBox="0 0 44 12" fill="none">
                  <path d="M2 6h32M30 2l8 4-8 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </div>
            </div>
          </div>
        </div>

        <div className="ht-panel ht-panel--answer">
          <div className="ht-panel-label">Your answer</div>
          <HeroAnswerCarousel />
        </div>
      </div>
    </div>
  );
}

/* =========================================================
   Inline Waitlist Form (hero)
========================================================= */
const FORMSPREE_WAITLIST_ENDPOINT = "https://formspree.io/f/xpqooqwq";

const LMS_OPTIONS = [
  "Cornerstone", "Docebo", "LearnUpon", "360Learning",
  "Sana Labs", "SAP SuccessFactors", "Workday Learning", "Other"
];

async function submitWaitlistToFormspree(email, lms, lmsOther) {
  const lmsOtherTrimmed = lms === "Other" ? (lmsOther || "").trim() : "";
  const res = await fetch(FORMSPREE_WAITLIST_ENDPOINT, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json"
    },
    body: JSON.stringify({
      email,
      _replyto: email,
      lms: lms || "",
      lms_other: lmsOtherTrimmed,
      _subject: "Omiro waitlist signup"
    })
  });
  let data = {};
  try {
    data = await res.json();
  } catch (_) {
    /* ignore */
  }
  if (!res.ok) {
    const msg =
      (typeof data.error === "string" && data.error) ||
      (Array.isArray(data.errors) && data.errors.map(e => e.message).filter(Boolean).join(" ")) ||
      `Something went wrong (${res.status}). Please try again.`;
    throw new Error(msg);
  }
}

function InlineForm({ onSubmitted }) {
  const [email, setEmail] = useState("");
  const [lms, setLms] = useState("");
  const [lmsOther, setLmsOther] = useState("");
  const [submitted, setSubmitted] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);
  const submit = async e => {
    e.preventDefault();
    if (!email.trim() || submitting) return;
    setError(null);
    setSubmitting(true);
    try {
      await submitWaitlistToFormspree(email.trim(), lms, lmsOther);
      window.posthog && posthog.identify(email.trim(), { email: email.trim(), lms: lms || null });
      window.posthog && posthog.capture('inline_form_submitted', { lms: lms || null });
      setSubmitted(true);
      onSubmitted && onSubmitted();
    } catch (err) {
      window.posthog && posthog.capture('inline_form_submission_failed', { error: err.message });
      setError(err.message || "Something went wrong. Please try again.");
    } finally {
      setSubmitting(false);
    }
  };
  if (submitted) {
    return (
      <div className="chat-demo" style={{ textAlign: "center", minHeight: 0, maxWidth: 460, padding: "28px 22px" }}>
        <div style={{ fontSize: 32, marginBottom: 8 }}>🎉</div>
        <div style={{ fontFamily: "var(--ff-head)", fontSize: 21, fontWeight: 500, color: "var(--black)", marginBottom: 6 }}>You're on the list</div>
        <div style={{ color: "var(--gray)", fontSize: 15 }}>We'll reach out when Omiro is ready.</div>
      </div>
    );
  }
  return (
    <form className="form" onSubmit={submit}>
      {error ? (
        <p className="form-error" role="alert">
          {error}
        </p>
      ) : null}
      <input
        className="input"
        type="email"
        placeholder="Enter your work email"
        value={email}
        onChange={e => setEmail(e.target.value)}
        required
      />
      <select
        className="select"
        value={lms}
        onChange={e => {
          const v = e.target.value;
          setLms(v);
          if (v !== "Other") setLmsOther("");
        }}
        aria-label="Which LMS does your org use? (optional)"
      >
        <option value="">Which LMS does your org use? (optional)</option>
        {LMS_OPTIONS.map(o => (
          <option key={o} value={o}>
            {o}
          </option>
        ))}
      </select>
      {lms === "Other" ? (
        <input
          className="input"
          type="text"
          placeholder="Which LMS? (optional)"
          value={lmsOther}
          onChange={e => setLmsOther(e.target.value)}
          autoComplete="organization"
          aria-label="Other LMS name (optional)"
        />
      ) : null}
      <button type="submit" className="btn-primary" disabled={submitting}>
        {submitting ? "Sending…" : "Join the Waitlist"}
      </button>
    </form>
  );
}

/* =========================================================
   Waitlist Modal (2-step)
========================================================= */
function WaitlistModal({ open, onClose }) {
  const [email, setEmail] = useState("");
  const [lms, setLms] = useState("");
  const [lmsOther, setLmsOther] = useState("");
  const [done, setDone] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);
  const overlayRef = useRef(null);
  const vvRaf = useRef(null);

  useEffect(() => {
    if (open) {
      setEmail("");
      setLms("");
      setLmsOther("");
      setDone(false);
      setSubmitting(false);
      setError(null);
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "";
    }
    return () => {
      document.body.style.overflow = "";
    };
  }, [open]);

  useEffect(() => {
    const onEsc = (e) => e.key === "Escape" && onClose();
    if (open) window.addEventListener("keydown", onEsc);
    return () => window.removeEventListener("keydown", onEsc);
  }, [open, onClose]);

  /* Extra bottom padding when the on-screen keyboard shrinks the visual viewport.
     Avoids translateY (negative offsetTop on iOS/WebViews can over-shift and pin the modal to the top). */
  useEffect(() => {
    if (!open) return undefined;
    const vv = window.visualViewport;
    const el = overlayRef.current;
    if (!vv || !el) return undefined;

    const applyKeyboardInset = () => {
      if (vvRaf.current != null) cancelAnimationFrame(vvRaf.current);
      vvRaf.current = requestAnimationFrame(() => {
        vvRaf.current = null;
        const layoutH = window.innerHeight;
        const top = Math.max(0, vv.offsetTop);
        const gapBelowVisual = layoutH - top - vv.height;
        const overlap = Math.max(0, Math.min(gapBelowVisual, layoutH * 0.42));
        el.style.paddingBottom = overlap > 10 ? `${Math.round(overlap)}px` : "";
      });
    };

    applyKeyboardInset();
    vv.addEventListener("resize", applyKeyboardInset);
    vv.addEventListener("scroll", applyKeyboardInset);
    const onFocusIn = ev => {
      if (
        ev.target &&
        (ev.target.tagName === "INPUT" || ev.target.tagName === "SELECT" || ev.target.tagName === "TEXTAREA")
      ) {
        window.setTimeout(applyKeyboardInset, 100);
      }
    };
    window.addEventListener("focusin", onFocusIn);
    return () => {
      if (vvRaf.current != null) cancelAnimationFrame(vvRaf.current);
      vvRaf.current = null;
      vv.removeEventListener("resize", applyKeyboardInset);
      vv.removeEventListener("scroll", applyKeyboardInset);
      window.removeEventListener("focusin", onFocusIn);
      el.style.paddingBottom = "";
    };
  }, [open]);

  if (!open) return null;

  const submit = async e => {
    e.preventDefault();
    if (!email.trim() || submitting) return;
    setError(null);
    setSubmitting(true);
    try {
      await submitWaitlistToFormspree(email.trim(), lms, lmsOther);
      window.posthog && posthog.identify(email.trim(), { email: email.trim(), lms: lms || null });
      window.posthog && posthog.capture('waitlist_submitted', { lms: lms || null });
      setDone(true);
    } catch (err) {
      window.posthog && posthog.capture('waitlist_submission_failed', { error: err.message });
      setError(err.message || "Something went wrong. Please try again.");
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div ref={overlayRef} className="modal-overlay" onClick={onClose}>
      <div className="modal-shift-wrap" onClick={e => e.stopPropagation()}>
        <div className="modal" role="dialog" aria-modal="true">
        <button className="close" onClick={onClose} aria-label="Close">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
        </button>

        {done ? (
          <div className="center">
            <div className="success-icon">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
            </div>
            <h3>You're on the list.</h3>
            <p className="sub">We'll reach out when Omiro is ready for your team.</p>
            <button className="btn-primary" onClick={onClose}>Done</button>
          </div>
        ) : (
          <>
            <h3>Get early access to Omiro.</h3>
            <p className="sub">Be first in line when we launch. We'll only use your email to let you know when Omiro is ready.</p>
            <form className="form" onSubmit={submit}>
              {error ? (
                <p className="form-error" role="alert">
                  {error}
                </p>
              ) : null}
              <input
                className="input"
                type="email"
                placeholder="Enter your work email"
                value={email}
                onChange={e => setEmail(e.target.value)}
                autoFocus
                required
              />
              <select
                className="select"
                value={lms}
                onChange={e => {
                  const v = e.target.value;
                  setLms(v);
                  if (v !== "Other") setLmsOther("");
                  if (v) window.posthog && posthog.capture('lms_selected', { lms: v });
                }}
                aria-label="Which LMS does your org use? (optional)"
              >
                <option value="">Which LMS does your org use? (optional)</option>
                {LMS_OPTIONS.map(o => (
                  <option key={o} value={o}>
                    {o}
                  </option>
                ))}
              </select>
              {lms === "Other" ? (
                <input
                  className="input"
                  type="text"
                  placeholder="Which LMS? (optional)"
                  value={lmsOther}
                  onChange={e => setLmsOther(e.target.value)}
                  autoComplete="organization"
                  aria-label="Other LMS name (optional)"
                />
              ) : null}
              <button type="submit" className="btn-primary" disabled={submitting}>
                {submitting ? "Sending…" : "Join the Waitlist"}
              </button>
            </form>
          </>
        )}
        </div>
      </div>
    </div>
  );
}

/* =========================================================
   Hero section
========================================================= */
function Hero({ onCtaClick }) {
  return (
    <header className="hero container" id="top">
      <span className="badge-pill">Coming Soon</span>
      <div className="hero-intro-reveal">
        <h1>Your LMS data,<br />finally in plain English</h1>
        <p className="sub">Omiro connects to your LMS and helps you measure what actually matters. Ask any question, get answers that go beyond activity data.</p>
        <HeroTranslationVisual />
        <div className="hero-cta-row">
          <button className="btn-primary" style={{ padding: "0 36px", width: "auto", height: "var(--h-control)", fontSize: 15 }} onClick={() => { window.posthog && posthog.capture('hero_cta_clicked'); onCtaClick(); }}>Join the Waitlist</button>
        </div>
        <div className="waitlist-proof">
          <div className="avatar-stack">
            <img src="https://framerusercontent.com/images/KD64dhKrNdxKzSajCepglBBXSM.jpg?width=128&height=128" alt="" />
            <img src="https://framerusercontent.com/images/rEmg7ZgILI8aTHSynoFCdiON3g.jpg?width=128&height=128" alt="" />
            <img src="https://framerusercontent.com/images/OJmd0F7UnO0atTkkx8R4aDYiQ.jpg?width=128&height=128" alt="" />
          </div>
          <span>Join L&D teams already on the waitlist</span>
        </div>
      </div>
    </header>
  );
}

/* =========================================================
   Problem section
========================================================= */
const PROBLEMS = [
  {
    n: "1",
    title: "Every question becomes a 4-day project",
    desc: "File ticket. Wait for export. Clean in Excel. Send Friday. Repeat.",
    icon: (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>)
  },
  {
    n: "2",
    title: "Your dashboards weren't built for the questions you actually get asked",
    desc: "40 pre-built reports in Cornerstone or Docebo, none of them quite right. So you export to CSV again.",
    icon: (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>)
  },
  {
    n: "3",
    title: "The data exists. It's just trapped.",
    desc: "Pulling it requires admin access, IT support, or a BI tool finance won't approve.",
    icon: (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>)
  }
];

function Problem() {
  const [introRef, introRevealed] = useRevealOnScroll();
  const revealTriggerRef = useRef(null);
  const [stackRevealed, setStackRevealed] = useState(() => {
    if (typeof window === "undefined") return false;
    return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  });

  useEffect(() => {
    if (stackRevealed) return undefined;
    const el = revealTriggerRef.current;
    if (!el) return undefined;
    if (typeof IntersectionObserver === "undefined") {
      setStackRevealed(true);
      return undefined;
    }
    const io = new IntersectionObserver(
      entries => {
        const hit = entries.some(e => e.isIntersecting);
        if (hit) {
          setStackRevealed(true);
        }
      },
      { root: null, rootMargin: "0px 0px -12% 0px", threshold: 0.2 }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [stackRevealed]);

  return (
    <section className="section container" id="problem">
      <div
        ref={introRef}
        className={`section-intro-reveal${introRevealed ? " is-revealed" : ""}`}
      >
        <div className="eyebrow">The Problem</div>
        <h2 className="section-title">Your LMS has the answers. Getting them out takes weeks.</h2>
        <p ref={revealTriggerRef} className="problem-sublead">
          The same loop, every week.
        </p>
      </div>
      <div className={`problem-stack${stackRevealed ? " is-revealed" : ""}`}>
        {PROBLEMS.map((p, i) => (
          <div
            className="problem-row"
            key={p.n}
            style={{ "--pr-delay": `${i * 0.28}s` }}
          >
            <div className="problem-icon">{p.icon}</div>
            <div className="problem-body">
              <div className="problem-title">{p.title}</div>
              <div className="problem-desc">{p.desc}</div>
            </div>
            <span className="problem-watermark" aria-hidden="true">{p.n}</span>
          </div>
        ))}
      </div>
    </section>
  );
}

/* =========================================================
   What to measure (between Problem and How it works)
========================================================= */
const MEASURE_COMPARE_ROWS = [
  {
    oldWay: '"Did they finish the course?"',
    withOmiro: "Who's still here 6 and 12 months after onboarding by program?"
  },
  {
    oldWay: '"What\'s our completion rate?"',
    withOmiro: "Which teams are falling behind, and on which courses?"
  },
  {
    oldWay: '"How much training did we deliver?"',
    withOmiro: "How long it takes new hires to complete required training?"
  }
];

function WhatToMeasure() {
  const [introRef, introRevealed] = useRevealOnScroll();
  const revealTriggerRef = useRef(null);
  const [gridRevealed, setGridRevealed] = useState(() => {
    if (typeof window === "undefined") return false;
    return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  });

  useEffect(() => {
    if (gridRevealed) return undefined;
    const el = revealTriggerRef.current;
    if (!el) return undefined;
    if (typeof IntersectionObserver === "undefined") {
      setGridRevealed(true);
      return undefined;
    }
    const io = new IntersectionObserver(
      entries => {
        if (entries.some(e => e.isIntersecting)) setGridRevealed(true);
      },
      { root: null, rootMargin: "0px 0px -12% 0px", threshold: 0.2 }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [gridRevealed]);

  return (
    <section className="section container" id="what-to-measure">
      <div
        ref={introRef}
        className={`section-intro-reveal${introRevealed ? " is-revealed" : ""}`}
      >
        <div className="eyebrow">What to measure</div>
        <h2 ref={revealTriggerRef} className="section-title">Stop measuring hours delivered. Start measuring what actually changes.</h2>
      </div>
      <div className={`measure-grid${gridRevealed ? " is-revealed" : ""}`}>
        {MEASURE_COMPARE_ROWS.map((row, i) => (
          <article
            key={row.oldWay}
            className="measure-card"
            style={{
              "--m-delay": `${i * 0.28}s`,
              "--m-r": `${i % 2 === 0 ? -1.1 : 0.95}deg`
            }}
          >
            <div className="measure-half measure-half--old">
              <div className="measure-kicker measure-kicker--old">Old way</div>
              <p className="measure-old-text">{row.oldWay}</p>
            </div>
            <div className="measure-half measure-half--new">
              <div className="measure-kicker measure-kicker--omiro">
                <svg
                  className="measure-check-icon"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="1.8"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  aria-hidden="true"
                >
                  <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
                  <polyline points="22 4 12 14.01 9 11.01" />
                </svg>
                <span>With Omiro</span>
              </div>
              <p className="measure-new-text">{row.withOmiro}</p>
            </div>
          </article>
        ))}
      </div>
    </section>
  );
}

/* =========================================================
   How It Works
========================================================= */
const HOW_STEPS = [
  {
    n: "1",
    title: "Connect your LMS",
    desc: "Omiro plugs into your existing LMS in minutes. No ripping and replacing anything.",
    icon: (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>)
  },
  {
    n: "2",
    title: "Just ask",
    desc: "Type any question in plain English. Compliance rates, course completions, team progress.",
    icon: (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>)
  },
  {
    n: "3",
    title: "Get your answer",
    desc: "Your data comes back instantly. Pin it to your dashboard or export to CSV.",
    icon: (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>)
  }
];

function HowItWorks() {
  const [introRef, introRevealed] = useRevealOnScroll();
  const revealTriggerRef = useRef(null);
  const [stepsRevealed, setStepsRevealed] = useState(() => {
    if (typeof window === "undefined") return false;
    return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  });

  useEffect(() => {
    if (stepsRevealed) return undefined;
    const el = revealTriggerRef.current;
    if (!el) return undefined;
    if (typeof IntersectionObserver === "undefined") {
      setStepsRevealed(true);
      return undefined;
    }
    /* `el` is the How it works subheading (<p.how-sublead>); reveal steps when this block is clearly in view. */
    const io = new IntersectionObserver(
      entries => {
        if (entries.some(e => e.isIntersecting)) {
          setStepsRevealed(true);
        }
      },
      { root: null, rootMargin: "0px 0px -18% 0px", threshold: 0.28 }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [stepsRevealed]);

  return (
    <section className="section container" id="how-it-works">
      <div
        ref={introRef}
        className={`section-intro-reveal${introRevealed ? " is-revealed" : ""}`}
      >
        <div className="eyebrow">How It Works</div>
        <h2 className="section-title">How Omiro works</h2>
        <p ref={revealTriggerRef} className="how-sublead">
          <span className="how-sublead-l1">We do the querying, cleaning, and formatting.</span>{" "}
          <span className="how-sublead-l2">You read the answer.</span>
        </p>
      </div>
      <div className={`steps-flow${stepsRevealed ? " is-revealed" : ""}`}>
        {HOW_STEPS.map((s, i) => (
          <React.Fragment key={s.n}>
            <div
              className="step-item"
              style={{
                "--hiw-delay": `${i * 0.28}s`,
                "--hiw-r": `${i % 2 === 0 ? -1.1 : 0.95}deg`
              }}
            >
              <div className="step-circle">
                <span className="step-icon">{s.icon}</span>
                <span className="step-n">{s.n}</span>
              </div>
              <div className="step-title">{s.title}</div>
              <div className="step-desc">{s.desc}</div>
            </div>
            {i < HOW_STEPS.length - 1 && (
              <div className="step-arrow" aria-hidden="true">
                <svg viewBox="0 0 40 24" fill="none"><path d="M0 12h32m0 0l-7-7m7 7l-7 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
              </div>
            )}
          </React.Fragment>
        ))}
      </div>
    </section>
  );
}

/* =========================================================
   Members / Logo bar (placeholder)
========================================================= */
function Members() {
  const [introRef, introRevealed] = useRevealOnScroll();
  const logosRevealRef = useRef(null);
  const [logosRevealed, setLogosRevealed] = useState(() => {
    if (typeof window === "undefined") return false;
    return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  });

  useEffect(() => {
    if (logosRevealed) return undefined;
    const el = logosRevealRef.current;
    if (!el) return undefined;
    if (typeof IntersectionObserver === "undefined") {
      setLogosRevealed(true);
      return undefined;
    }
    const io = new IntersectionObserver(
      entries => {
        if (entries.some(e => e.isIntersecting)) setLogosRevealed(true);
      },
      { root: null, rootMargin: "0px 0px -18% 0px", threshold: 0.28 }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [logosRevealed]);

  const logos = [
    { name: "Ria Money Transfer", src: "assets/logos/ria.png" },
    { name: "Chevron", src: "assets/chevron.svg.png" },
    { name: "Mailchimp", src: "assets/mailchimp.png" },
    { name: "athenahealth", src: "assets/logos/athena-health-logo.png" },
  ];
  return (
    <section className="members container" id="members">
      <div
        ref={introRef}
        className={`section-intro-reveal${introRevealed ? " is-revealed" : ""}`}
      >
        <div className="eyebrow">Early Access Members</div>
        <h2 className="section-title">L&D teams already on the waitlist</h2>
        <p ref={logosRevealRef} className="members-sublead">
          {"You're not the only one watching this space."}
        </p>
      </div>
      <div className={`logo-row${logosRevealed ? " is-revealed" : ""}`}>
        {logos.map((l, i) => (
          <div
            className="logo-item"
            key={l.name}
            title={l.name}
            style={{
              "--hiw-delay": `${i * 0.28}s`,
              "--hiw-r": `${i % 2 === 0 ? -1.1 : 0.95}deg`
            }}
          >
            <img src={l.src} alt={l.name} />
          </div>
        ))}
      </div>
    </section>
  );
}

/* =========================================================
   LMS logo marquee
   Own section / component. Rendered in App directly after <Hero />, before <Problem />.
========================================================= */
const LMS_MARQUEE_LOGOS = [
  { name: "Docebo", src: "assets/docebo.png" },
  { name: "Cornerstone", src: "assets/cornerstone.png" },
  { name: "360Learning", src: "assets/360learning.png" },
  { name: "Workday", src: "assets/workday.png" },
  { name: "LearnUpon", src: "assets/learnupon.png" },
];

function LmsLogoMarquee() {
  const trackLogos = [...LMS_MARQUEE_LOGOS, ...LMS_MARQUEE_LOGOS];
  return (
    <section
      className="section container"
      id="lms-marquee"
      aria-label="Learning platforms Omiro connects with"
    >
      <p className="sr-only">
        Partner platforms shown in this row: Docebo, Cornerstone, 360Learning, Workday, and LearnUpon.
      </p>
      <div className="lms-marquee-pill">
        <div className="lms-marquee-viewport">
          <div className="lms-marquee-track">
            {trackLogos.map((logo, i) => (
              <div className="lms-marquee-item" key={`${logo.name}-${i}`}>
                <img src={logo.src} alt="" width={160} height={40} loading="lazy" decoding="async" draggable={false} />
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

/* =========================================================
   FAQ (above Final CTA in App)
========================================================= */
const FAQ_ITEMS = [
  {
    q: "When will Omiro be available?",
    a: "We're working with early access partners now and rolling out access in waves through 2026. Join the waitlist and we'll reach out as soon as your spot opens up."
  },
  {
    q: "What if my LMS isn't one of the ones shown?",
    a: "Omiro is LMS-agnostic by design. If you don't see your platform in our integrations, tell us when you join the waitlist. We prioritize new integrations based on demand from early access members."
  },
  {
    q: "Do I need to replace my current LMS?",
    a: "No. Omiro works on top of your existing LMS. No migration, no re-implementation, no change to how your team uses your current tools. We just make the data in them actually usable."
  },
  {
    q: "Is my LMS data secure?",
    a: "Yes. Omiro reads from your LMS through secure API connections and doesn't store raw learner data on our servers. We take data handling seriously, especially around sensitive HR and learning data."
  },
  {
    q: "How much will Omiro cost?",
    a: "Pricing scales with company size and starts in the range of mid-market SaaS tools. Early access members get locked-in founding pricing for as long as they stay with us."
  },
  {
    q: "What does early access include?",
    a: "Early access members get hands-on time with Omiro before general availability, direct input into the roadmap, and locked-in early pricing. You'll also work directly with our team to get the integration set up for your LMS."
  },
  {
    q: "Who's behind Omiro?",
    a: "Omiro is built by a small team with backgrounds in product, learning technology, and enterprise software. We've lived the pain of trying to pull clean answers out of an LMS, which is exactly why we're building this."
  }
];

function FaqSection() {
  const [openIdx, setOpenIdx] = useState(null);
  const [introRef, introRevealed] = useRevealOnScroll();
  const faqListRevealRef = useRef(null);
  const [faqListRevealed, setFaqListRevealed] = useState(() => {
    if (typeof window === "undefined") return false;
    return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  });

  useEffect(() => {
    if (faqListRevealed) return undefined;
    const el = faqListRevealRef.current;
    if (!el) return undefined;
    if (typeof IntersectionObserver === "undefined") {
      setFaqListRevealed(true);
      return undefined;
    }
    const io = new IntersectionObserver(
      entries => {
        if (entries.some(e => e.isIntersecting)) setFaqListRevealed(true);
      },
      { root: null, rootMargin: "0px 0px -18% 0px", threshold: 0.28 }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [faqListRevealed]);

  const toggle = (i) => {
    setOpenIdx(prev => {
      const next = prev === i ? null : i;
      if (next !== null) window.posthog && posthog.capture('faq_item_expanded', { question: FAQ_ITEMS[i].q });
      return next;
    });
  };
  return (
    <section className="section container" id="faq">
      <div
        ref={introRef}
        className={`section-intro-reveal${introRevealed ? " is-revealed" : ""}`}
      >
        <div className="eyebrow">FAQ</div>
        <h2 className="section-title">Questions, answered.</h2>
        <p ref={faqListRevealRef} className="faq-sublead">
          {"Everything you'd ask before signing up."}
        </p>
      </div>
      <div className={`faq-list${faqListRevealed ? " is-revealed" : ""}`}>
        {FAQ_ITEMS.map((item, i) => {
          const isOpen = openIdx === i;
          return (
            <div
              key={i}
              className={`faq-item${isOpen ? " is-open" : ""}`}
              style={{
                "--hiw-delay": `${i * 0.28}s`,
                "--hiw-r": `${i % 2 === 0 ? -1.1 : 0.95}deg`
              }}
            >
              <button
                type="button"
                className="faq-trigger"
                id={`faq-q-${i}`}
                aria-expanded={isOpen}
                aria-controls={`faq-a-${i}`}
                onClick={() => toggle(i)}
              >
                <span className="faq-q-text">{item.q}</span>
                <span className="faq-icon" aria-hidden="true">+</span>
              </button>
              <div
                id={`faq-a-${i}`}
                className="faq-panel"
                aria-labelledby={`faq-q-${i}`}
                aria-hidden={!isOpen}
              >
                <div className="faq-panel-inner">
                  <p className="faq-answer">{item.a}</p>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </section>
  );
}

/* =========================================================
   Final CTA + mockup
========================================================= */
function FinalCTA({ onCtaClick }) {
  const [introRef, introRevealed] = useRevealOnScroll();
  return (
    <section className="final-cta container">
      <div
        ref={introRef}
        className={`section-intro-reveal${introRevealed ? " is-revealed" : ""}`}
      >
        <h2 className="section-title final-cta-title">
          <span className="final-cta-title-line">See your LMS data the way</span>
          <span className="final-cta-title-line">it was always meant to be seen</span>
        </h2>
        <p className="final-cta-sub">
          {"We'll help you measure what leadership actually cares "}
          <span className="final-cta-sub-nobr-mobile">
            <span className="final-cta-sub-join">about,</span>
            <br className="final-cta-sub-br" />
            {" "}
            <span className="final-cta-sub-tail">{"not just what's easy to pull."}</span>
          </span>
        </p>
      </div>
      <button className="btn-primary" onClick={() => { window.posthog && posthog.capture('final_cta_clicked'); onCtaClick(); }}>Join the Waitlist</button>
    </section>
  );
}


/* =========================================================
   Footer
========================================================= */
function Footer() {
  return (
    <footer className="footer">
      <div className="foot-logo">
        <img src="assets/logo-omiro.png" alt="Omiro" />
      </div>
      <div className="foot-right">
        <div className="foot-copy">© 2026 Omiro Labs. All rights reserved.</div>
        <a
          href="https://linkedin.com/company/omiro-labs"
          className="foot-linkedin"
          target="_blank"
          rel="noopener noreferrer"
          aria-label="Omiro on LinkedIn"
        >
          <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
            <path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
          </svg>
        </a>
      </div>
    </footer>
  );
}

/* =========================================================
   App shell
========================================================= */
/**
 * Vercel Web Analytics (same role as `<Analytics />` from `@vercel/analytics/react`).
 * This file is not a Next.js app, so we do not use `@vercel/analytics/next`.
 * Injects the insights script once on mount (no bundler: load package via esm.sh).
 */
function Analytics() {
  useEffect(() => {
    let cancelled = false;
    void import("https://esm.sh/@vercel/analytics@2.0.1")
      .then(mod => {
        if (cancelled || typeof mod.inject !== "function") return;
        mod.inject({ framework: "react" });
      })
      .catch(() => {});
    return () => {
      cancelled = true;
    };
  }, []);
  return null;
}

function App() {
  const [modalOpen, setModalOpen] = useState(false);
  const openModal = () => { setModalOpen(true); window.posthog && posthog.capture('waitlist_modal_opened'); };
  const closeModal = () => setModalOpen(false);
  return (
    <div className="app">
      <Analytics />
      <div className="bg-spheres" aria-hidden="true">
        <div className="sphere s1"/>
        <div className="sphere s2"/>
        <div className="sphere s3"/>
        <div className="sphere s4"/>
      </div>
      <Nav onCtaClick={openModal} />
      <Hero onCtaClick={openModal} />

      <LmsLogoMarquee />

      <Problem />
      <WhatToMeasure />
      <HowItWorks />
      <Members />

      <FaqSection />

      <FinalCTA onCtaClick={openModal} />
      <Footer />
      <WaitlistModal open={modalOpen} onClose={closeModal} />
    </div>
  );
}

Object.assign(window, { App });
