// CaseStudy.jsx — Conversion Works case study: Subscription & Purchase Growth via A/B Testing
// Faithful rebrand of the Taurist case study into the Conversion Works system.
// Features: tabbed hero metrics, scroll-spy table of contents (sticky desktop rail
// + mobile dropdown), image-slots for user-supplied imagery, mobile sticky CTA
// dropdown, and an "other case studies" carousel.

const LANDING = "/conversion";

// ---- data ---------------------------------------------------------------
const SECTIONS = [
  { id: "client",         n: "Client & Context",          num: "01" },
  { id: "challenge",      n: "Challenge & Goals",         num: "02" },
  { id: "discovery",      n: "Discovery",                 num: "03" },
  { id: "solution",       n: "Solution Overview",         num: "04" },
  { id: "implementation", n: "Implementation & Dev",      num: "05" },
  { id: "results",        n: "Results & Impact",          num: "06" },
];

const TABS = {
  "Results": [
    { v: "+113%", l: "Conversion rate (60 days)", up: true },
    { v: "+234%", l: "Add to cart", up: true },
    { v: "+198%", l: "Reached checkout", up: true },
    { v: "+226%", l: "Completed checkout", up: true },
  ],
  "First 30 days": [
    { v: "+19%", l: "Conversion rate", up: true },
    { v: "+26%", l: "Add to cart", up: true },
    { v: "+19%", l: "Reached checkout", up: true },
    { v: "+39%", l: "Completed checkout", up: true },
  ],
  "Snapshot": [
    { v: "0.48%", l: "Baseline conversion rate", up: false },
    { v: "~1.02%", l: "Conversion rate after 60 days", up: true },
    { v: "~97/mo", l: "Pumps sold at baseline", up: false },
    { v: "60 days", l: "From launch to result", up: false },
  ],
};

const SOLUTIONS = [
  {
    badge: "Solution 01",
    title: "Audit-led fixes from the CRO audit",
    body: "A 60-page CRO audit produced a prioritized backlog that drove every build decision. The highest-confidence fixes shipped first.",
    points: [
      "Image gallery strategy: video testimonials above the gallery on mobile; lifestyle, how-it-works, benefits, and science-backed frames; mobile thumbnails and a cleaner desktop gallery with zoom.",
      "Action-block clarity: rating and review count, a tighter copy hierarchy, clearer installment options, a sticky mobile CTA, and anchor links into deep sections.",
      "Education blocks below the fold: how it works, features and assembly, what's included, comparison, science-backed proof, and a benefits timeline.",
      "Assurance and support: expanded FAQ and support access, plus review filters and Q&A.",
      "Cart and checkout: a redesigned drawer, multiple upsells, free-shipping progress, payment trust, and a streamlined checkout.",
    ],
    img: "annabella-audit", src: "assets/annabella-audit.avif", ratio: "1173 / 1452", cap: "A 60-page audit of tactics we could implement to lift conversion on the site.",
  },
  {
    badge: "Solution 02",
    title: "Education-first PDP redesign",
    body: "We reorganized the product-page narrative to carry shoppers from validation to action.",
    points: [
      "New page sequence: proof → product action block → problem → solution → features → how it works → benefits → proof → comparison → FAQ → CTA.",
      "Produced new explanatory visuals to clarify the pump's unique technology and premium value.",
      "Elevated trust with quick-view reviews, badges, and FAQ placed near the CTAs.",
    ],
    img: "annabella-pdp", src: "assets/annabella-pdp.avif", ratio: "782 / 740", cap: "The education-first PDP, rebuilt around comprehension and trust.",
  },
  {
    badge: "Solution 03",
    title: "Cart drawer implementation",
    body: "A mobile-first cart drawer kept shoppers on-page and preserved purchase momentum.",
    points: [
      "An editable drawer (quantity, remove, code entry) that keeps shoppers in flow.",
      "Optimized for mobile to cut page transitions and reloads on the path to checkout.",
    ],
    img: "annabella-cart", src: "assets/annabella-cart.avif", ratio: "1173 / 1110", cap: "The new on-page cart drawer, optimized for mobile.",
  },
  {
    badge: "Solution 04",
    title: "Homepage social-proof section",
    body: "Authentic video reviews, surfaced below the fold, built credibility for first-time visitors.",
    points: [
      "Curated real customer video reviews and placed them where new visitors build trust.",
    ],
    img: "annabella-homeproof", src: "assets/annabella-homeproof.avif", ratio: "782 / 529", cap: "Homepage social proof to raise engagement and credibility.",
  },
];

const OTHER = [
  { id: "other-hfb", name: "Her Fantasy Box", img: "assets/cases/herfantasybox.avif", href: "/conversion/case-study/subscription-purchase-growth", desc: "A 2-year experimentation program — 63 tests, 42 winners, and subscription growth across PDP, cart, and collections.", m: [["+26.41% mobile conversion lift", true], ["+27.56% subscription lift", true]] },
  { id: "other-omnilux", name: "Omnilux", img: "assets/cases/omnilux.avif", desc: "High-ticket DTC proof moved closer to the buying decision across nav, PDP, and homepage.", m: [["+58% CVR lift — reviews in nav", true], ["+35% CVR lift — PDP testimonial video", true]] },
  { id: "other-juvenon", name: "Juvenon", img: "assets/cases/juvenon.avif", desc: "PDP purchase options made easier to act on, with a featured win measured to confidence.", m: [["+35.24% CVR lift — featured PDP win", true], ["99.18% statistical confidence", false]] },
  { id: "other-wigdealer", name: "WigDealer", img: "assets/cases/wigdealer.avif", desc: "Cart, collection, and PDP friction reduced across the funnel for compounding gains.", m: [["+10.74% RPV lift — cart simplification", true], ["+7.77% CVR lift — collection top-fold", true]] },
];

// ---- scroll-spy hook ----------------------------------------------------
function useScrollSpy(ids, offset = 130) {
  const [active, setActive] = useState(null);
  useEffect(() => {
    const onScroll = () => {
      let cur = null;
      for (const id of ids) {
        const el = document.getElementById(id);
        if (el && el.getBoundingClientRect().top <= offset) cur = id;
      }
      setActive(cur);
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return active;
}

// ---- shared atoms -------------------------------------------------------
function Slot({ id, placeholder, radius = 12, style, src }) {
  return React.createElement("image-slot", { id, placeholder, radius: String(radius), style, src: src ? assetUrl(src) : undefined });
}
function Stars({ n = 5, size = 13 }) {
  return <span className="csx-quote-stars" style={{ fontSize: size }}>{Array.from({ length: n }).map((_, i) => <i key={i} className="ri-star-fill" />)}</span>;
}

// ---- nav ----------------------------------------------------------------
function CaseNav() {
  const [scrolled, setScrolled] = useState(false);
  const [openIdx, setOpenIdx] = useState(-1);
  const [menuOpen, setMenuOpen] = useState(false);
  const [mCasesOpen, setMCasesOpen] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 24);
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  useEffect(() => {
    document.body.style.overflow = menuOpen ? "hidden" : "";
    document.body.classList.toggle("nav-menu-open", menuOpen);
    return () => { document.body.style.overflow = ""; document.body.classList.remove("nav-menu-open"); };
  }, [menuOpen]);
  const links = [
    { label: "The Audit", href: LANDING + "#convert" },
    { label: "Case Studies", href: LANDING + "#showcase", dropdown: [
      { label: "Her Fantasy Box", href: "/conversion/case-study/subscription-purchase-growth", sub: "Subscription & purchase growth" },
      { label: "Annabella", href: "#top", sub: "Audit-led Shopify rebuild" },
    ] },
    { label: "How it works", href: LANDING + "#how" },
    { label: "FAQs", href: LANDING + "#faq" },
  ];
  const lstyle = { fontFamily: "var(--font-ui)", fontSize: 14, fontWeight: 500, color: "var(--fg2)", textDecoration: "none", transition: "color .15s" };
  return (
    <React.Fragment>
    <nav style={{
      position: "fixed", top: 0, left: 0, right: 0, zIndex: 50,
      transition: "background .3s, border-color .3s, backdrop-filter .3s",
      background: scrolled ? "rgba(2,3,13,0.74)" : "rgba(2,3,13,0.4)",
      backdropFilter: "blur(16px)", WebkitBackdropFilter: "blur(16px)",
      borderBottom: `1px solid ${scrolled ? "var(--border-subtle)" : "transparent"}`,
    }}>
      <div className="wrap" style={{ display: "flex", alignItems: "center", justifyContent: "space-between", height: 74 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <a href={LANDING} aria-label="Conversion Works home" style={{ display: "inline-flex", alignItems: "center", textDecoration: "none" }}>
            <Logo height={42} />
          </a>
          <a href="https://www.taurist.com/" className="nav-byline" style={{ fontFamily: "var(--font-ui)", fontSize: 11, fontWeight: 600, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--fg3)", paddingLeft: 12, borderLeft: "1px solid var(--border-default)", textDecoration: "none" }}>by Taurist</a>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 34 }} className="nav-links">
          {links.map((l, i) => {
            if (!l.dropdown) {
              return (
                <a key={l.label} href={l.href} style={lstyle}
                  onMouseEnter={(e) => (e.currentTarget.style.color = "var(--fg1)")}
                  onMouseLeave={(e) => (e.currentTarget.style.color = "var(--fg2)")}
                >{l.label}</a>
              );
            }
            const open = openIdx === i;
            return (
              <div key={l.label} style={{ position: "relative" }}
                onMouseEnter={() => setOpenIdx(i)} onMouseLeave={() => setOpenIdx(-1)}>
                <a href={l.href} style={{ ...lstyle, display: "inline-flex", alignItems: "center", gap: 5, color: open ? "var(--fg1)" : "var(--fg2)" }}>
                  {l.label}
                  <i className="ri-arrow-down-s-line" style={{ fontSize: 16, transition: "transform .2s", transform: open ? "rotate(180deg)" : "none" }} />
                </a>
                <div style={{ position: "absolute", top: "100%", left: -8, paddingTop: 14, opacity: open ? 1 : 0, transform: open ? "translateY(0)" : "translateY(-6px)", pointerEvents: open ? "auto" : "none", transition: "opacity .18s, transform .18s" }}>
                  <div style={{ minWidth: 248, padding: 7, borderRadius: 14, background: "rgba(11,16,32,0.96)", border: "1px solid var(--border-default)", backdropFilter: "blur(16px)", WebkitBackdropFilter: "blur(16px)", boxShadow: "0 18px 44px rgba(0,0,0,0.5)" }}>
                    {l.dropdown.map((d) => (
                      <a key={d.label} href={d.href} style={{ display: "block", padding: "10px 13px", borderRadius: 9, textDecoration: "none", transition: "background .15s" }}
                        onMouseEnter={(e) => (e.currentTarget.style.background = "rgba(255,255,255,0.05)")}
                        onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")}>
                        <span style={{ display: "block", fontFamily: "var(--font-ui)", fontSize: 14, fontWeight: 600, color: "var(--fg1)" }}>{d.label}</span>
                        <span style={{ display: "block", fontFamily: "var(--font-body)", fontWeight: 300, fontSize: 12.5, color: "var(--fg3)", marginTop: 2 }}>{d.sub}</span>
                      </a>
                    ))}
                  </div>
                </div>
              </div>
            );
          })}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 12 }} className="nav-cta-group">
          <a href={LANDING + "#cta"} className="btn btn-primary btn-sm nav-primary-cta">Get 5 free fixes</a>
          <button type="button" className="nav-burger" aria-label="Open menu" onClick={() => setMenuOpen(true)}><i className="ri-menu-line" /></button>
        </div>
      </div>
    </nav>
    {menuOpen && (
      <div className="nav-mobile-menu">
        <div className="nmm-head">
          <div className="nmm-id">
            <a href={LANDING} aria-label="Conversion Works home" style={{ display: "inline-flex" }}>
              <Logo height={42} />
            </a>
            <a href="https://www.taurist.com/" className="nmm-byline" onClick={() => setMenuOpen(false)}>by Taurist</a>
          </div>
          <button type="button" className="nmm-close" aria-label="Close menu" onClick={() => setMenuOpen(false)}><i className="ri-close-line" /></button>
        </div>
        <nav className="nmm-links">
          {links.map((l) => l.dropdown ? (
            <div key={l.label} className="nmm-group">
              <button type="button" className="nmm-link nmm-link--btn" aria-expanded={mCasesOpen} onClick={() => setMCasesOpen((o) => !o)}>
                {l.label}
                <i className="ri-arrow-down-s-line" style={{ transition: "transform .2s", transform: mCasesOpen ? "rotate(180deg)" : "none" }} />
              </button>
              <div className={"nmm-cases-sub" + (mCasesOpen ? " open" : "")}>
                {l.dropdown.map((d) => (
                  <a key={d.label} href={d.href} className="nmm-sublink" onClick={() => setMenuOpen(false)}>
                    <b>{d.label}</b>{d.sub}
                  </a>
                ))}
              </div>
            </div>
          ) : (
            <a key={l.label} href={l.href} className="nmm-link" onClick={() => setMenuOpen(false)}>{l.label}</a>
          ))}
          <a href={LANDING + "#cta"} className="btn btn-primary nmm-cta" onClick={() => setMenuOpen(false)}>Get 5 free fixes</a>
        </nav>
        <div className="nmm-foot">
          <a href="https://www.taurist.com/" target="_blank" rel="noopener noreferrer">taurist</a>
          <span>|</span>
          <a href="https://www.taurist.com/siteworks" target="_blank" rel="noopener noreferrer">siteworks</a>
          <span>|</span>
          <a href="https://www.taurist.com/workers" target="_blank" rel="noopener noreferrer">workers</a>
        </div>
      </div>
    )}
    </React.Fragment>
  );
}

// ---- hero ---------------------------------------------------------------
function Hero() {
  const [tab, setTab] = useState("Results");
  return (
    <header className="csx-hero">
      <div className="haze-bloom" aria-hidden="true" />
      <div className="csx-wrap">
        <div className="csx-crumb">
          <a href={LANDING + "#showcase"}>Case Studies</a>
          <i className="ri-arrow-right-s-line" />
          <span className="csx-crumb-cur">Doubling DTC sales in 60 days</span>
        </div>
        <div className="csx-hero-grid">
          <div className="csx-hero-text" style={{ position: "relative" }}>
            <span className="csx-hero-ghost" aria-hidden="true">Annabella</span>
            <div className="eyebrow csx-hero-eyebrow"><span className="dot" />CRO Audit · High-Converting Design · DTC Baby Care</div>
            <h1 className="csx-hero-title">How a DTC baby-care brand <span className="gradient-text" style={{ background: "var(--grad-halo)", WebkitBackgroundClip: "text", backgroundClip: "text", WebkitTextFillColor: "transparent" }}>doubled sales in 60 days</span></h1>
          </div>
          <div className="csx-hero-media">
            <Slot id="annabella-cover" radius={20} src="assets/annabella-cover.avif" placeholder="Drop the Annabella hero image" />
          </div>
          <div className="csx-hero-metrics">
            <div className="csx-tabs" role="tablist">
              {Object.keys(TABS).map((k) => (
                <button key={k} role="tab" aria-selected={tab === k} className={"csx-tab" + (tab === k ? " is-active" : "")} onClick={() => setTab(k)}>{k}</button>
              ))}
            </div>
            <div className="csx-stats">
              {TABS[tab].map((s, i) => (
                <div className="csx-stat" key={tab + i}>
                  <div className="csx-stat-num">{s.v}{s.up && <i className="ri-arrow-up-line csx-up" />}</div>
                  <div className="csx-stat-label">{s.l}</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </header>
  );
}

// ---- meta band ----------------------------------------------------------
function MetaBand() {
  const services = [
    { i: "ri-focus-3-line", t: "CRO Audit" },
    { i: "ri-pen-nib-line", t: "High-Converting Design" },
    { i: "ri-code-s-slash-line", t: "Full Implementation & Dev" },
  ];
  const facts = [
    { i: "ri-store-2-line", t: "Industry", v: "DTC · Baby care · Fem-tech" },
    { i: "ri-calendar-2-line", t: "Timeline", v: "~3 months, contract to launch" },
    { i: "ri-stack-line", t: "Stack", v: "Figma, Shopify, GA4, Hotjar" },
  ];
  return (
    <section className="csx-meta">
      <div className="csx-wrap">
        <div className="glass csx-meta-card">
          <div className="csx-meta-grid">
            <div>
              <div className="csx-label">Summary</div>
              <p className="csx-summary-text">Annabella entered the US with a patented breast pump but a 0.48% conversion rate. We rebuilt navigation, information architecture, and an education-first PDP — plus a mobile cart drawer and homepage social proof — to streamline the journey and double conversion in 60 days.</p>
              <div className="csx-label">Services</div>
              <div className="csx-chips">
                {services.map((s) => <span className="csx-chip" key={s.t}><i className={s.i} />{s.t}</span>)}
              </div>
            </div>
            <div className="csx-meta-sub">
              <div className="csx-facts">
                {facts.map((f) => (
                  <div className="csx-fact" key={f.t}>
                    <span className="csx-fact-ic"><i className={f.i} /></span>
                    <div>
                      <p className="csx-fact-t">{f.t}</p>
                      <p className="csx-fact-v">{f.v}</p>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ---- desktop sticky rail ------------------------------------------------
function Rail({ active }) {
  return (
    <aside className="csx-rail">
      <div>
        <div className="csx-toc-title"><i className="ri-list-unordered" />Table of Contents</div>
        <nav className="csx-toc">
          {SECTIONS.map((s) => (
            <a key={s.id} href={"#" + s.id} className={"csx-toc-link" + (active === s.id ? " is-active" : "")}>{s.n}</a>
          ))}
        </nav>
      </div>
      <div className="glass glass--featured csx-wins">
        <div className="csx-wins-h">Want to know what we would fix first?</div>
        <p className="csx-wins-p">Run a quick PDP scan for 5 visible fixes. If you like the fixes, connect with our founder and we will map a deeper CRO audit based on your data.</p>
        <a href={LANDING + "#cta"} className="btn btn-primary btn-sm">Get my 5 free PDP fixes <i className="ri-arrow-right-line" /></a>
        <div className="csx-wins-proof">
          <div className="csx-wins-badge">
            <span className="csx-wins-stars csx-wins-stars--tp"><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /></span>
            <img src={assetUrl("assets/trustpilot-wordmark.png")} alt="Trustpilot" />
          </div>
          <div className="csx-wins-badge">
            <span className="csx-wins-stars"><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /></span>
            <img src={assetUrl("assets/clutch-wordmark.png")} alt="Clutch" />
          </div>
        </div>
      </div>
    </aside>
  );
}

// ---- mobile TOC dropdown ------------------------------------------------
function MobileTOC({ active }) {
  const [open, setOpen] = useState(false);
  const cur = SECTIONS.find((s) => s.id === active);
  const label = cur ? cur.n : "Table of Contents";
  return (
    <div className={"csx-toc-mob" + (open ? " is-open" : "")}>
      <button className="csx-toc-mob-btn" onClick={() => setOpen(!open)} aria-expanded={open}>
        <span className="csx-toc-mob-cur"><i className="ri-list-unordered" />{label}</span>
        <i className="ri-arrow-down-s-line csx-toc-mob-chev" />
      </button>
      <div className="csx-toc-mob-panel">
        <div className="csx-toc-mob-list">
          <div className="csx-toc-mob-list-inner">
            {SECTIONS.map((s) => (
              <a key={s.id} href={"#" + s.id} className={active === s.id ? "is-active" : ""} onClick={() => setOpen(false)}>{s.n}</a>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// ---- mobile sticky CTA dropdown -----------------------------------------
function MobileCTA() {
  const [open, setOpen] = useState(false);
  const [show, setShow] = useState(false);
  useEffect(() => {
    const onScroll = () => {
      const a = document.getElementById("client");
      const past = a ? a.getBoundingClientRect().top < window.innerHeight * 0.85 : false;
      setShow(past);
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  useEffect(() => {
    document.body.classList.toggle("csx-cta-on", show);
    return () => document.body.classList.remove("csx-cta-on");
  }, [show]);
  return (
    <div className={"csx-mobcta" + (open ? " is-open" : "") + (show ? " is-visible" : "")}>
      <button className="csx-mobcta-bar" onClick={() => setOpen(!open)} aria-expanded={open}>
        <span className="csx-mobcta-lead"><span className="csx-mobcta-dot" />Build visitor loyalty</span>
        <i className="ri-arrow-up-s-line csx-mobcta-chev" />
      </button>
      <div className="csx-mobcta-panel">
        <div className="csx-mobcta-inner">
          <div className="csx-mobcta-content">
            <div className="csx-mobcta-h">Turn browsers into repeat visitors.</div>
            <p className="csx-mobcta-p">Discover ways to guide visitors from first click to long-term engagement — starting with 5 free fixes for your store.</p>
            <a href={LANDING + "#cta"} className="btn btn-primary">Claim your free audit <i className="ri-arrow-right-line" /></a>
            <div className="csx-wins-proof csx-mobcta-proof">
              <div className="csx-wins-badge">
                <span className="csx-wins-stars csx-wins-stars--tp"><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /></span>
                <img src={assetUrl("assets/trustpilot-wordmark.png")} alt="Trustpilot" />
              </div>
              <div className="csx-wins-badge">
                <span className="csx-wins-stars"><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /><i className="ri-star-fill" /></span>
                <img src={assetUrl("assets/clutch-wordmark.png")} alt="Clutch" />
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ---- solution block -----------------------------------------------------
function SolutionBlock({ s }) {
  return (
    <div className="csx-test">
      <div className="csx-test-head">
        <span className="csx-test-badge">{s.badge}</span>
        <h3 className="csx-test-title">{s.title}</h3>
      </div>
      <p className="csx-p" style={{ marginTop: 0 }}>{s.body}</p>
      <ul className="csx-list">
        {s.points.map((p, i) => <li key={i}>{p}</li>)}
      </ul>
      <div className="csx-figure" style={{ marginTop: 22 }}>
        <Slot id={s.img} src={s.src} radius={14} style={s.ratio ? { aspectRatio: s.ratio } : undefined} placeholder={"Drop the " + s.title.toLowerCase() + " visual"} />
        <p className="csx-figcap">{s.cap}</p>
      </div>
    </div>
  );
}

// ---- article ------------------------------------------------------------
function H2({ id, num, children }) {
  return (
    <h2 className="csx-h2" id={id}>
      {num && <span className="csx-h2-num">{num}</span>}{children}
    </h2>
  );
}

function Article() {
  return (
    <article className="csx-article">
      {/* 01 — Client & Context */}
      <section className="csx-sec" id="client" data-screen-label="Client & Context" style={{ scrollMarginTop: 110 }}>
        <H2 num="01">Client &amp; Context</H2>
        <p className="csx-p">Annabella is a 7-figure fem-tech brand and breast-pump manufacturer with a patented pump that simulates a baby's tongue. After succeeding internationally, the brand entered the US through its DTC site, Amazon, and social — into stiff competition and low brand awareness.</p>
        <p className="csx-p">At kickoff, the US store converted at just <strong>0.48%</strong> sitewide — roughly <strong>97 pumps a month</strong>. US shoppers needed clearer education to understand Annabella's unique technology and premium positioning.</p>
      </section>

      {/* 02 — Challenge & Goals */}
      <section className="csx-sec" id="challenge" data-screen-label="Challenge & Goals">
        <H2 num="02">Challenge &amp; Goals</H2>
        <div className="csx-cols2">
          <div className="csx-subcard csx-subcard--neg">
            <p className="csx-subcard-h"><i className="ri-error-warning-line" />Challenges</p>
            <ul className="csx-list">
              <li><strong>Category competition and price anchoring</strong> — US buyers compare against lower-priced pumps, so the education burden is high.</li>
              <li><strong>Education gaps on PDP</strong> — basic images didn't explain the technology or value; the gallery was highly engaged but under-utilized.</li>
              <li><strong>Trust and proof gaps</strong> — sparse US reviews, minimal social proof on home and PDP, and warranty/financing cues that weren't prominent.</li>
              <li><strong>Friction in the purchase flow</strong> — no cart drawer, multiple mobile page loads, unclear sizing, and weak support links.</li>
            </ul>
          </div>
          <div className="csx-subcard csx-subcard--pos">
            <p className="csx-subcard-h"><i className="ri-focus-3-line" />Goals</p>
            <ul className="csx-list">
              <li>Increase conversion by improving <strong>comprehension on PDP</strong> with an education-first structure and clearer action-block hierarchy.</li>
              <li>Reduce friction from <strong>PDP → cart → checkout</strong> with a mobile-first cart drawer and cleaner checkout cues.</li>
              <li>Raise <strong>trust and intent</strong> with authentic social proof, clearer review signals, and service assurances.</li>
              <li>Strengthen ops with reusable <strong>templates, components, and a practical GA4 event schema</strong>.</li>
            </ul>
          </div>
        </div>
      </section>

      {/* 03 — Discovery */}
      <section className="csx-sec" id="discovery" data-screen-label="Discovery">
        <H2 num="03">Discovery</H2>
        <p className="csx-p" style={{ marginTop: 0 }}>Analytics stack: GA4, Shopify Analytics, and Hotjar, plus a competitive scan. The evidence pointed in one direction.</p>
        <ul className="csx-list">
          <li><strong>Heatmaps</strong> — heavy interaction with the gallery, signalling a chance to make the media educational.</li>
          <li><strong>Support and chat logs</strong> — repeated educational questions that called for in-flow education.</li>
          <li><strong>Funnel data</strong> — materially higher conversion for users entering via PDP than via the homepage.</li>
        </ul>
        <div className="csx-figure">
          <Slot id="annabella-discovery" radius={14} src="assets/annabella-discovery.avif" style={{ aspectRatio: "782 / 386" }} placeholder="Drop the discovery / analytics visual" />
          <p className="csx-figcap">Heatmaps, session review, and funnel analysis pointed to education-first PDPs.</p>
        </div>
      </section>

      {/* 04 — Solutions */}
      <section className="csx-sec" id="solution" data-screen-label="Solution Overview">
        <H2 num="04">Solution Overview <span style={{ color: "var(--fg3)", fontWeight: 400, fontSize: 20 }}>(design &amp; build)</span></H2>
        <p className="csx-p">We prioritized the highest-impact work from the audit and shipped it straight to production — no split testing in this phase.</p>
        {SOLUTIONS.map((s) => <SolutionBlock key={s.badge} s={s} />)}
      </section>

      {/* 05 — Implementation */}
      <section className="csx-sec" id="implementation" data-screen-label="Implementation & Development">
        <H2 num="05">Implementation &amp; Development</H2>
        <div className="csx-spec" style={{ marginTop: 18 }}>
          <div className="csx-spec-k">Design</div>
          <div className="csx-spec-v">Figma</div>
          <div className="csx-spec-k">Build</div>
          <div className="csx-spec-v">Shopify, built directly (no split testing this phase)</div>
          <div className="csx-spec-k">Tracking</div>
          <div className="csx-spec-v">GA4 event schema — variant_select, add_to_cart, cart_drawer_open, drawer_checkout, faq_toggle, and form_start / submit.</div>
          <div className="csx-spec-k">Accessibility &amp; performance</div>
          <div className="csx-spec-v">Alt text, focus states, image sizing, and lazy-loading.</div>
        </div>
      </section>

      {/* 06 — Results & Impact */}
      <section className="csx-sec" id="results" data-screen-label="Results & Impact">
        <H2 num="06">Results &amp; Impact</H2>
        <p className="csx-p" style={{ marginTop: 0 }}>Baseline: <strong>0.48%</strong> conversion rate, roughly 97 pumps a month. No A/B tests this phase — lifts reflect the rollout of the education-first PDP, cart drawer, and homepage social proof.</p>
        <div className="csx-ba" style={{ marginTop: 22 }}>
          <div className="csx-ba-col csx-ba-col--before">
            <span className="csx-ba-tag">Before</span>
            <Slot id="annabella-res-before" src="assets/annabella-results-before.avif" style={{ aspectRatio: "2448 / 3168" }} placeholder="Before metrics" />
          </div>
          <div className="csx-ba-col csx-ba-col--after">
            <span className="csx-ba-tag">After</span>
            <Slot id="annabella-res-after" src="assets/annabella-results-after.avif" style={{ aspectRatio: "2448 / 3168" }} placeholder="After metrics" />
          </div>
        </div>
        <p className="csx-figcap">Shopify funnel breakdown — before engagement vs. after 60 days.</p>
        <div className="csx-cols2">
          <div className="csx-subcard">
            <p className="csx-subcard-h" style={{ color: "var(--magenta-300)" }}><i className="ri-rocket-2-line" />First 30 days post-launch</p>
            <ul className="csx-list">
              <li>Add to cart <strong>+26%</strong>.</li>
              <li>Reached checkout <strong>+19%</strong>.</li>
              <li>Completed checkout <strong>+39%</strong>.</li>
              <li>Conversion rate <strong>+19%</strong>.</li>
            </ul>
          </div>
          <div className="csx-subcard">
            <p className="csx-subcard-h" style={{ color: "var(--violet-400)" }}><i className="ri-line-chart-line" />Days 31–60</p>
            <ul className="csx-list">
              <li>Add to cart <strong>+234%</strong>.</li>
              <li>Reached checkout <strong>+198%</strong>.</li>
              <li>Completed checkout <strong>+226%</strong>.</li>
              <li>Conversion rate <strong>+113%</strong> (0.48% → ~1.02%).</li>
            </ul>
          </div>
        </div>
        <div className="glass csx-winbox">
          <p className="csx-winbox-h">60-day headline — education-first PDP, cart drawer, homepage proof</p>
          <div className="csx-winrow">
            <span className="csx-winrow-l">Conversion rate</span>
            <span className="csx-winrow-v">+113%</span>
          </div>
          <div className="csx-winrow">
            <span className="csx-winrow-l">Add to cart</span>
            <span className="csx-winrow-v">+234%</span>
          </div>
          <div className="csx-winrow">
            <span className="csx-winrow-l">Completed checkout</span>
            <span className="csx-winrow-v">+226%</span>
          </div>
        </div>
        <div className="csx-subcard" style={{ marginTop: 18 }}>
          <p className="csx-subcard-h" style={{ color: "var(--violet-400)" }}><i className="ri-lightbulb-flash-line" />Why it worked — key learnings</p>
          <ul className="csx-list">
            <li>For high-consideration products, <strong>education inside the PDP</strong> is the highest-leverage move.</li>
            <li><strong>Cart drawers</strong> reduce friction, boost perceived speed, and set up later AOV lifts.</li>
            <li>Authentic, human <strong>video social proof</strong> builds trust more than logos alone.</li>
          </ul>
        </div>
      </section>

      {/* Final CTA */}
      <section className="csx-sec" data-screen-label="Get started">
        <div className="glass glass--featured csx-cta">
          <div className="haze-bloom" aria-hidden="true" />
          <div className="csx-cta-inner">
            <h3 className="csx-cta-h">Double your conversions like Annabella.</h3>
            <div className="csx-cta-checks">
              <div className="csx-cta-check"><i className="ri-check-line" />Turn education-first PDPs into measurable revenue growth.</div>
              <div className="csx-cta-check"><i className="ri-check-line" />Reduce checkout friction with a cart drawer and mobile-first optimizations.</div>
              <div className="csx-cta-check"><i className="ri-check-line" />Build trust with authentic social proof and data-backed design.</div>
            </div>
            <div className="csx-cta-actions">
              <a href={LANDING + "#cta"} className="btn btn-primary">Book a call with our founder <i className="ri-arrow-right-line" /></a>
              <a href={LANDING + "#cta"} className="btn btn-secondary">Get my 5 free PDP fixes</a>
            </div>
          </div>
        </div>
      </section>
    </article>
  );
}

// ---- other case studies -------------------------------------------------
function OtherCases() {
  const trackRef = useRef(null);
  const [idx, setIdx] = useState(0);
  const scrollTo = (i) => {
    const track = trackRef.current; if (!track) return;
    const card = track.children[i];
    if (card) track.scrollTo({ left: card.offsetLeft - track.offsetLeft, behavior: "smooth" });
  };
  const onScroll = () => {
    const track = trackRef.current; if (!track) return;
    let nearest = 0, best = Infinity;
    [...track.children].forEach((c, i) => {
      const d = Math.abs(c.offsetLeft - track.offsetLeft - track.scrollLeft);
      if (d < best) { best = d; nearest = i; }
    });
    setIdx(nearest);
  };
  const step = (dir) => scrollTo(Math.max(0, Math.min(OTHER.length - 1, idx + dir)));
  return (
    <section className="csx-other">
      <div className="csx-wrap">
        <div className="csx-other-head">
          <h2 className="csx-other-title">Other case studies</h2>
          <div className="csx-other-nav">
            <button className="csx-arrow" onClick={() => step(-1)} aria-label="Previous"><i className="ri-arrow-left-line" /></button>
            <button className="csx-arrow" onClick={() => step(1)} aria-label="Next"><i className="ri-arrow-right-line" /></button>
          </div>
        </div>
        <div className="csx-other-track" ref={trackRef} onScroll={onScroll}>
          {OTHER.map((c) => (
            <article className="csx-other-card" key={c.id}>
              <div className="csx-other-media"><img src={assetUrl(c.img)} alt={c.name} loading="lazy" /></div>
              <div className="csx-other-body">
                <p className="csx-other-desc">{c.desc}</p>
                <div className="csx-other-metrics">
                  {c.m.map(([txt, up], i) => (
                    <div className="csx-other-metric" key={i}>
                      <i className={up ? "ri-arrow-up-line" : "ri-timer-flash-line"} style={{ color: up ? "var(--success)" : "var(--violet-400)" }} />
                      <span>{txt}</span>
                    </div>
                  ))}
                </div>
                {c.href && <a href={c.href} className="csx-other-link">View case study <i className="ri-arrow-right-line" /></a>}
              </div>
            </article>
          ))}
        </div>
        <div className="csx-dots">
          {OTHER.map((c, i) => <button key={i} className={"csx-dot" + (idx === i ? " is-active" : "")} onClick={() => scrollTo(i)} aria-label={"Go to " + c.name} />)}
        </div>
      </div>
    </section>
  );
}

// ---- footer -------------------------------------------------------------
function CaseFooter() {
  const cols = [
    { head: "Conversion Works", links: [["The problem", LANDING + "#work"], ["What we build", LANDING + "#workers"], ["Process", LANDING + "#how"], ["Case studies", LANDING + "#showcase"], ["Pricing", LANDING + "#pricing"]] },
    { head: "Taurist", links: [["Taurist Technologies", "https://www.taurist.com/"], ["Siteworks", "https://www.taurist.com/siteworks"], ["Workers", "https://www.taurist.com/workers"], ["About", "https://www.taurist.com/about"], ["Notes", "https://www.taurist.com/notes"], ["Email Us", "mailto:hello@taurist.com"]] },
  ];
  const link = { fontFamily: "var(--font-body)", fontWeight: 300, fontSize: 14, color: "var(--fg3)", textDecoration: "none", transition: "color .15s", width: "fit-content" };
  const colHead = { fontFamily: "var(--font-ui)", fontSize: 12, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--fg2)", marginBottom: 16 };
  return (
    <footer style={{ borderTop: "1px solid var(--border-subtle)", background: "var(--neutral-900)", paddingTop: 64, position: "relative" }}>
      <div className="streak" style={{ position: "absolute", top: 0, left: 0, right: 0, opacity: 0.4 }} />
      <div className="wrap">
        <div style={{ display: "grid", gap: 40, paddingBottom: 52, gridTemplateColumns: "1.6fr 1fr 1fr" }} className="footer-grid">
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 14, flexWrap: "wrap", rowGap: 8 }}>
              <Logo height={40} />
              <span style={{ width: 1, height: 20, background: "var(--border-default)" }} />
              <span style={{ fontFamily: "var(--font-ui)", fontSize: 12, fontWeight: 600, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--fg3)" }}>by Taurist Technologies Inc</span>
            </div>
            <p style={{ fontFamily: "var(--font-body)", fontWeight: 300, fontSize: 14, lineHeight: 1.6, color: "var(--fg2)", margin: "20px 0 0", maxWidth: 360 }}>
              Founder-led Shopify CRO. We find the friction, fix the flow, and measure what moved.
            </p>
            <a href={LANDING + "#cta"} className="btn btn-primary btn-sm" style={{ marginTop: 24 }}>Get my 5 free fixes <i className="ri-arrow-right-line" /></a>
          </div>
          {cols.map((c) => (
            <div key={c.head}>
              <div style={colHead}>{c.head}</div>
              <div style={{ display: "flex", flexDirection: "column", gap: 11 }}>
                {c.links.map(([t, h]) => (
                  <a key={t} href={h} style={link} {...(h.startsWith("http") ? { target: "_blank", rel: "noopener noreferrer" } : {})}
                    onMouseEnter={(e) => (e.currentTarget.style.color = "var(--magenta-300)")}
                    onMouseLeave={(e) => (e.currentTarget.style.color = "var(--fg3)")}>{t}</a>
                ))}
              </div>
            </div>
          ))}
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "22px 0", borderTop: "1px solid var(--border-subtle)", flexWrap: "wrap", gap: 16 }}>
          <span style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "var(--fg3)" }}>© 2026 Taurist Technologies Inc. All rights reserved.</span>
          <a href="https://www.taurist.com/siteworks" target="_blank" rel="noopener noreferrer" style={{ display: "inline-flex", alignItems: "center", gap: 9, fontFamily: "var(--font-body)", fontSize: 13, color: "var(--fg3)", textDecoration: "none", transition: "color .15s" }}
            onMouseEnter={(e) => (e.currentTarget.style.color = "var(--fg1)")}
            onMouseLeave={(e) => (e.currentTarget.style.color = "var(--fg3)")}>
            Like this site? Built by
            <img src={assetUrl("assets/siteworks-mark.avif")} alt="" width="20" height="20" style={{ display: "block" }} />
            <span style={{ fontWeight: 600, color: "var(--fg1)" }}>Siteworks.</span>
          </a>
          <div style={{ display: "flex", alignItems: "center", gap: 22 }}>
            <a href="https://www.taurist.com/privacy-policy" style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "var(--fg3)", textDecoration: "none" }}>Privacy Policy</a>
            <a href="https://www.taurist.com/terms-conditions" style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "var(--fg3)", textDecoration: "none" }}>Terms of Service</a>
          </div>
        </div>
      </div>
    </footer>
  );
}

// ---- page ---------------------------------------------------------------
function CaseStudyPage() {
  const ids = SECTIONS.map((s) => s.id);
  const active = useScrollSpy(ids);
  const lens = useLensChat();
  // Any CTA on the page opens the Lens chat instead of navigating away.
  useEffect(() => {
    const onClick = (e) => {
      const a = e.target.closest('a[href$="#cta"]');
      if (a && lens && lens.openFullscreen) { e.preventDefault(); lens.openFullscreen(); }
    };
    document.addEventListener("click", onClick);
    return () => document.removeEventListener("click", onClick);
  }, [lens]);
  // cursor-following light on primary/secondary buttons (matches the rest of the site)
  useEffect(() => {
    const onMove = (e) => {
      const btn = e.target.closest(".btn-primary, .btn-secondary");
      if (btn) {
        const r = btn.getBoundingClientRect();
        btn.style.setProperty("--mx", `${((e.clientX - r.left) / r.width) * 100}%`);
        btn.style.setProperty("--my", `${((e.clientY - r.top) / r.height) * 100}%`);
      }
    };
    document.addEventListener("pointermove", onMove);
    return () => document.removeEventListener("pointermove", onMove);
  }, []);
  return (
    <div className="csx-page">
      <CaseNav />
      <Hero />
      <MetaBand />
      <div className="csx-wrap">
        <MobileTOC active={active} />
        <div className="csx-layout">
          <Rail active={active} />
          <Article />
        </div>
      </div>
      <OtherCases />
      <CaseFooter />
      <MobileCTA />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(
  <LensChatProvider>
    <CaseStudyPage />
    <LensLauncher />
    <LensFullscreen />
  </LensChatProvider>
);
