<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><!-- Google Tag Manager --><script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-M84FJCJL');</script><!-- End Google Tag Manager --><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Pie - The Quality Layer for AI-Speed Engineering</title><meta name="description" content="Pie watches every change your team pushes, tests the affected flows on your actual product, and opens PRs to fix what it finds. No scripts. No noise. Just results."><meta name="keywords" content="AI QA, automated testing, E2E testing, test automation, no-code testing, AI agents, fastest QA platform"><!-- Canonical URL --><link rel="canonical" href="https://pie.inc"><!-- Open Graph --><meta property="og:title" content="Pie - The Quality Layer for AI-Speed Engineering"><meta property="og:description" content="Pie watches every change your team pushes, tests the affected flows on your actual product, and opens PRs to fix what it finds. No scripts. No noise. Just results."><meta property="og:image" content="https://pie.inc/pie-og-image.jpg?v=2"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta property="og:image:type" content="image/jpeg"><meta property="og:url" content="https://pie.inc"><meta property="og:type" content="website"><meta property="og:site_name" content="Pie"><!-- Twitter Card --><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Pie - The Quality Layer for AI-Speed Engineering"><meta name="twitter:description" content="Pie watches every change your team pushes, tests the affected flows on your actual product, and opens PRs to fix what it finds. No scripts. No noise. Just results."><meta name="twitter:image" content="https://pie.inc/pie-og-image.jpg?v=2"><!-- Fonts --><link rel="preconnect" href="https://api.fontshare.com" crossorigin><link href="https://api.fontshare.com/v2/css?f[]=clash-display@500,600,700&f[]=satoshi@400,500,700&display=swap" rel="stylesheet"><!-- Favicon --><link rel="icon" type="image/svg+xml" href="/favicon.svg">  <script type="application/ld+json">{"@context":"https://schema.org","@type":"Organization","name":"Pie","legalName":"PieLabs, Inc.","url":"https://pie.inc","logo":"https://pie.inc/pielogo.avif","description":"The quality layer for AI-speed engineering. Pie watches every change, tests affected flows, and opens PRs to fix what it finds.","sameAs":["https://www.linkedin.com/company/pielabs-inc/"],"contactPoint":{"@type":"ContactPoint","contactType":"sales","url":"https://calendly.com/jinoo-pie/demo"}}</script> <link rel="stylesheet" href="/_astro/_slug_.CyYbK-6j.css">
<link rel="stylesheet" href="/_astro/_slug_.D1RmP-Tb.css"></head> <body class="dotted-grid noise-overlay"> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-M84FJCJL" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- ========================================
       GRADIENT BLOBS (Background)
       ======================================== --> <div class="fixed inset-0 overflow-hidden pointer-events-none z-0"> <div class="gradient-blob blob-violet absolute -top-48 left-[10%]"></div> <div class="gradient-blob blob-magenta absolute top-[30%] -right-24"></div> <div class="gradient-blob blob-orange absolute bottom-[10%] left-[20%]"></div> </div> <!-- ========================================
       NAVIGATION
       ======================================== --> <nav class="nav"> <div class="max-w-1080 mx-auto px-6 md:px-16 lg:px-6 h-full flex items-center justify-between"> <!-- Logo + Nav Links --> <div class="flex items-center gap-8"> <a href="/" class="flex items-center gap-2"> <img src="/pielogo.avif" alt="Pie" class="h-8 w-auto"> </a> <div class="hidden md:flex items-center gap-8"> <!-- Product Dropdown --> <div class="relative" id="product-dropdown"> <button class="nav-link flex items-center gap-1" id="product-trigger">
Product
<svg class="w-4 h-4 transition-transform duration-200" id="product-chevron" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path> </svg> </button> <div class="absolute top-full left-0 mt-2 w-48 py-2 bg-canvas-elevated border border-canvas-subtle rounded-xl shadow-xl opacity-0 invisible transition-all duration-200 transform -translate-y-2" id="product-menu"> <a href="/product/pie-qa/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Pie QA</a> <a href="/product/overview/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Product Overview</a> <a href="/product/how-it-works/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">How Pie Works</a> <a href="/product/autonomous-discovery/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Autonomous Discovery</a> <a href="/product/self-healing-tests/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Self-Healing Tests</a> <a href="/product/integrations/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Integrations</a> <a href="/product/custom-tests/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Custom Tests</a> <a href="/product/security/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Security</a> </div> </div> <a href="https://docs.pie.inc/" target="_blank" class="nav-link">Docs</a> <!-- Resources Dropdown --> <div class="relative" id="resources-dropdown"> <button class="nav-link flex items-center gap-1" id="resources-trigger">
Resources
<svg class="w-4 h-4 transition-transform duration-200" id="resources-chevron" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path> </svg> </button> <div class="absolute top-full left-0 mt-2 w-48 py-2 bg-canvas-elevated border border-canvas-subtle rounded-xl shadow-xl opacity-0 invisible transition-all duration-200 transform -translate-y-2" id="resources-menu"> <a href="/blog/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Blog</a> <a href="/customers/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Case Studies</a> <a href="/resources/whitepapers/" class="block px-4 py-2 font-body text-sm text-text-secondary hover:text-text-primary hover:bg-canvas-subtle transition-colors">Whitepapers</a> </div> </div> </div> </div> <!-- Desktop CTA --> <div class="hidden md:flex items-center gap-4"> <a href="https://app.pie.inc/" target="_blank" class="nav-link">Login</a> <a href="https://app.pie.inc/start" target="_blank" class="nav-cta">Get Started</a> </div> <!-- Mobile Menu Button --> <button id="mobile-menu-btn" class="md:hidden flex items-center justify-center w-10 h-10 rounded-lg hover:bg-canvas-elevated transition-colors" aria-label="Toggle menu"> <svg class="w-6 h-6 text-text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path id="menu-icon" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path> </svg> </button> </div> <!-- Mobile Menu --> <div id="mobile-menu" class="hidden md:hidden absolute top-full left-0 right-0 bg-canvas-base/95 backdrop-blur-lg border-b border-canvas-subtle"> <div class="max-w-1080 mx-auto px-6 md:px-16 lg:px-6 py-6 flex flex-col gap-4"> <!-- Mobile Product Section --> <div class="py-2"> <span class="nav-link font-semibold">Product</span> <div class="pl-4 mt-2 flex flex-col gap-2"> <a href="/product/pie-qa/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Pie QA</a> <a href="/product/overview/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Product Overview</a> <a href="/product/how-it-works/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">How Pie Works</a> <a href="/product/autonomous-discovery/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Autonomous Discovery</a> <a href="/product/self-healing-tests/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Self-Healing Tests</a> <a href="/product/integrations/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Integrations</a> <a href="/product/custom-tests/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Custom Tests</a> <a href="/product/security/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Security</a> </div> </div> <a href="https://docs.pie.inc/" target="_blank" class="nav-link py-2">Docs</a> <!-- Mobile Resources Section --> <div class="py-2"> <span class="nav-link font-semibold">Resources</span> <div class="pl-4 mt-2 flex flex-col gap-2"> <a href="/blog/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Blog</a> <a href="/customers/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Case Studies</a> <a href="/resources/whitepapers/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors py-1">Whitepapers</a> </div> </div> <a href="https://app.pie.inc/" target="_blank" class="nav-link py-2">Login</a> <a href="https://app.pie.inc/start" target="_blank" class="nav-cta text-center mt-2">Get Started</a> </div> </div> </nav> <!-- Page Content -->   <div class="landing-home"> <section class="relative min-h-[90vh] flex items-center overflow-hidden"> <!-- Subtle grid background --> <div class="lh-grid-bg absolute inset-0 -z-10"></div> <div class="w-full max-w-1080 mx-auto px-6 md:px-16 lg:px-6 pt-32 pb-16 md:pt-40 md:pb-20 relative z-10"> <!-- Text block — centered --> <div class="max-w-4xl mx-auto text-center"> <!-- Eyebrow --> <div class="hero-badge mb-6 flex justify-center"> <span class="font-mono text-xs font-bold text-accent-violet uppercase tracking-[0.1em]">Tests What Code Review Can't</span> </div> <!-- Headline --> <div class="hero-headline"> <h1 class="font-display font-bold text-5xl md:text-7xl xl:text-hero text-text-primary leading-[1.05] tracking-tight">
What if you never shipped <span class="text-gradient inline-block pb-1 pr-1">a bug again?</span> </h1> </div> <!-- Subheadline --> <div class="hero-subline mt-6 max-w-[640px] mx-auto"> <p class="font-body text-lg md:text-body-lg text-text-secondary leading-[1.7]">
Pie connects to your repo, tests every commit like a real user,<br>and opens PRs to fix what breaks. No scripts. No noise. Just results.
</p> </div> <!-- CTA --> <div class="hero-ctas mt-8"> <div class="flex flex-col items-center gap-4"> <a href="https://app.pie.inc/start" target="_blank" class="btn-primary justify-center"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-[18px] h-[18px]"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
Try Pie on my repo <span class="arrow-wrapper"><span class="arrow"></span></span> </a> <p class="font-body text-sm text-text-muted">
Connect your repo and staging URL. Your first scan is free.
</p> </div> </div> </div> <!-- Triptych — full-width below text --> <div class="lh-hero-triptych mt-14"> <!-- Panel 1: Pie reads your PR --> <div class="lh-hero-triptych-panel lh-hero-triptych-side lh-hero-triptych-left"> <div class="lh-hero-triptych-panel-header"> <span class="lh-hero-triptych-step">STEP 1</span> <div class="lh-hero-triptych-title-row"> <span class="lh-hero-triptych-title">Pie reads your PR</span> <span class="lh-hero-triptych-status" id="p1-status">analyzing...</span> </div> </div> <div class="lh-hero-triptych-panel-content"> <!-- Code diff mockup --> <div class="lh-hero-triptych-diff" id="p1-diff"> <div class="lh-hero-triptych-scan" id="p1-scan"></div> <!-- Static fallback (no-JS): shows final critical section --> <div class="lh-hero-triptych-diff-line lh-hero-triptych-diff-added"><span class="lh-hero-triptych-ln">42</span><span>+   const disc = <span class="lh-hero-triptych-highlight">applyPromo</span>(cart);</span></div> <div class="lh-hero-triptych-diff-line lh-hero-triptych-diff-added"><span class="lh-hero-triptych-ln">43</span><span>+   cart.total = cart.total - disc;</span></div> <div class="lh-hero-triptych-diff-filename">// checkout.service.ts</div> </div> <!-- Inline annotation --> <div class="lh-hero-triptych-annotation" id="p1-annotation"> <svg class="lh-hero-triptych-annotation-icon" viewBox="0 0 16 16" fill="none"><path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 10.5a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5zM8.75 8a.75.75 0 0 1-1.5 0V4.5a.75.75 0 0 1 1.5 0V8z" fill="#8B5CF6"></path></svg> <span>No cap on discount — total can go negative</span> </div> </div> <!-- Panel footer (flow connector) --> <div class="lh-hero-triptych-footer"> <span class="lh-hero-triptych-footer-dot"></span> <span class="lh-hero-triptych-footer-text">Opening browser →</span> </div> </div> <!-- Panel 2: Pie opens a real browser (THE MONEY SHOT) --> <div class="lh-hero-triptych-panel lh-hero-triptych-center lh-hero-dimmed"> <div class="lh-hero-triptych-panel-header"> <span class="lh-hero-triptych-step">STEP 2</span> <span class="lh-hero-triptych-title">Pie opens a real browser and tests your checkout</span> </div> <div class="lh-hero-triptych-panel-content"> <!-- Browser window mockup --> <div class="lh-hero-triptych-browser"> <!-- Browser chrome --> <div class="lh-hero-triptych-browser-chrome"> <div class="lh-hero-triptych-browser-dots"> <span style="background:#ef4444"></span> <span style="background:#eab308"></span> <span style="background:#22c55e"></span> </div> <div class="lh-hero-triptych-browser-url"> <svg class="lh-hero-triptych-lock-icon" viewBox="0 0 16 16" fill="none"><rect x="3" y="7" width="10" height="7" rx="1.5" stroke="currentColor" stroke-width="1.2"></rect><path d="M5 7V5a3 3 0 0 1 6 0v2" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"></path></svg> <span>staging.acme.com/checkout</span> </div> </div> <!-- Browser content — Lottie of Pie navigating the checkout page --> <div class="lh-hero-triptych-browser-body" id="p2-browser-body"> <canvas id="p2-lottie" class="lh-hero-triptych-browser-video" role="img" aria-label="Pie navigating a product page and detecting a broken proceed-to-cart button"></canvas> </div> </div> </div> <!-- Panel footer --> <div class="lh-hero-triptych-footer" id="p2-footer"> <span class="lh-hero-triptych-footer-dot"></span> <span class="lh-hero-triptych-footer-text">Fix generated → opening PR</span> </div> </div> <!-- Panel 3: Pie opens a fix PR --> <div class="lh-hero-triptych-panel lh-hero-triptych-side lh-hero-triptych-right"> <div class="lh-hero-triptych-panel-header"> <span class="lh-hero-triptych-step">STEP 3</span> <span class="lh-hero-triptych-title">Pie opens a fix PR</span> </div> <div class="lh-hero-triptych-panel-content"> <div class="lh-hero-triptych-pr-feed" id="p3-feed"> <!-- Older PRs (visible from start, scroll up when new PR arrives) --> <div class="lh-hero-triptych-pr lh-hero-triptych-pr-old"> <div class="lh-hero-triptych-pr-author"> <div class="lh-hero-triptych-pr-avatar"><svg viewBox="0 0 20 20" fill="none"><path d="M10 0C10.9147 0 11.7336.4047 12.292 1.043C12.5903 1.361 12.9455 1.622 13.3633 1.8C13.7976 1.984 14.2506 2.057 14.6924 2.036C15.5571 1.989 16.4238 2.281 17.0713 2.929C17.7177 3.575 18.0092 4.44 17.9531 5.285C17.9229 6.208 18.2865 7.088 18.9561 7.697C19.5967 8.271 20 9.088 20 10C20 10.912 19.5964 11.728 18.9609 12.286C18.2789 12.907 17.9109 13.796 17.9561 14.707C18.0098 15.559 17.7182 16.425 17.0713 17.071C16.4237 17.719 15.5571 18.011 14.71 17.953C14.2463 17.946 13.7949 18.019 13.3623 18.202C12.9468 18.379 12.5925 18.638 12.3066 18.951C11.7336 19.595 10.915 20 10 20C9.084 20 8.2644 19.594 7.706 18.954C7.405 18.638 7.0521 18.378 6.6377 18.202C6.2067 18.019 5.757 17.947 5.3184 17.966C4.4458 18.011 3.5781 17.72 2.9297 17.071C2.2808 16.423 1.9879 15.554 2.0469 14.705C2.0839 13.793 1.7199 12.911 1.0479 12.302C.4062 11.735 0 10.916 0 10C0 9.084.4059 8.264 1.0459 7.706C1.7122 7.084 2.0727 6.212 2.0342 5.316C1.9879 4.446 2.2798 3.578 2.9287 2.929C3.5773 2.28 4.4456 1.988 5.294 2.047C5.7521 2.056 6.2038 1.984 6.6367 1.8C7.0533 1.623 7.4072 1.362 7.6934 1.048C8.2644.405 9.0843 0 10 0Z" fill="#6B21A8"></path><path d="M9.83 5.017C10.517 5.017 11.145 5.182 11.711 5.514C12.285 5.837 12.734 6.287 13.057 6.86C13.38 7.426 13.541 8.058 13.541 8.753C13.541 9.446 13.39 10.081 13.085 10.654C12.789 11.219 12.375 11.665 11.844 11.989C11.32 12.314 10.733 12.477 10.088 12.477C9.568 12.477 9.081 12.368 8.63 12.151C8.3 11.993 8.006 11.788 7.749 11.538V14.635C7.749 14.865 7.677 15.066 7.524 15.219C7.371 15.372 7.171 15.443 6.94 15.443C6.716 15.443 6.52 15.37 6.361 15.222C6.204 15.066 6.133 14.865 6.133 14.635V8.753C6.133 8.058 6.294 7.426 6.617 6.859C6.948 6.286 7.392 5.838 7.948 5.515C8.514 5.182 9.143 5.017 9.83 5.017Z" fill="#EC4899"></path><path d="M10.23 4.617C10.917 4.617 11.545 4.782 12.111 5.114C12.685 5.437 13.134 5.887 13.457 6.46C13.78 7.026 13.941 7.658 13.941 8.353C13.941 9.046 13.79 9.681 13.485 10.254C13.189 10.819 12.775 11.265 12.244 11.589C11.72 11.914 11.133 12.077 10.488 12.077C9.968 12.077 9.481 11.968 9.03 11.751C8.7 11.593 8.406 11.388 8.149 11.138V14.235C8.149 14.465 8.077 14.666 7.924 14.819C7.771 14.972 7.571 15.043 7.34 15.043C7.116 15.043 6.92 14.97 6.761 14.822C6.604 14.666 6.533 14.465 6.533 14.235V8.353C6.533 7.658 6.694 7.026 7.017 6.459C7.348 5.886 7.792 5.438 8.348 5.115C8.914 4.782 9.543 4.617 10.23 4.617Z" fill="white"></path></svg></div> <span class="lh-hero-triptych-pr-name">pie</span> <span class="lh-hero-triptych-pr-bot-badge">bot</span> </div> <div class="lh-hero-triptych-pr-title">fix: handle null shipping address in order flow</div> <div class="lh-hero-triptych-pr-badges"> <span class="lh-hero-triptych-pr-badge lh-hero-triptych-pr-badge-merged">Merged</span> </div> </div> <div class="lh-hero-triptych-pr lh-hero-triptych-pr-old"> <div class="lh-hero-triptych-pr-author"> <div class="lh-hero-triptych-pr-avatar"><svg viewBox="0 0 20 20" fill="none"><path d="M10 0C10.9147 0 11.7336.4047 12.292 1.043C12.5903 1.361 12.9455 1.622 13.3633 1.8C13.7976 1.984 14.2506 2.057 14.6924 2.036C15.5571 1.989 16.4238 2.281 17.0713 2.929C17.7177 3.575 18.0092 4.44 17.9531 5.285C17.9229 6.208 18.2865 7.088 18.9561 7.697C19.5967 8.271 20 9.088 20 10C20 10.912 19.5964 11.728 18.9609 12.286C18.2789 12.907 17.9109 13.796 17.9561 14.707C18.0098 15.559 17.7182 16.425 17.0713 17.071C16.4237 17.719 15.5571 18.011 14.71 17.953C14.2463 17.946 13.7949 18.019 13.3623 18.202C12.9468 18.379 12.5925 18.638 12.3066 18.951C11.7336 19.595 10.915 20 10 20C9.084 20 8.2644 19.594 7.706 18.954C7.405 18.638 7.0521 18.378 6.6377 18.202C6.2067 18.019 5.757 17.947 5.3184 17.966C4.4458 18.011 3.5781 17.72 2.9297 17.071C2.2808 16.423 1.9879 15.554 2.0469 14.705C2.0839 13.793 1.7199 12.911 1.0479 12.302C.4062 11.735 0 10.916 0 10C0 9.084.4059 8.264 1.0459 7.706C1.7122 7.084 2.0727 6.212 2.0342 5.316C1.9879 4.446 2.2798 3.578 2.9287 2.929C3.5773 2.28 4.4456 1.988 5.294 2.047C5.7521 2.056 6.2038 1.984 6.6367 1.8C7.0533 1.623 7.4072 1.362 7.6934 1.048C8.2644.405 9.0843 0 10 0Z" fill="#6B21A8"></path><path d="M9.83 5.017C10.517 5.017 11.145 5.182 11.711 5.514C12.285 5.837 12.734 6.287 13.057 6.86C13.38 7.426 13.541 8.058 13.541 8.753C13.541 9.446 13.39 10.081 13.085 10.654C12.789 11.219 12.375 11.665 11.844 11.989C11.32 12.314 10.733 12.477 10.088 12.477C9.568 12.477 9.081 12.368 8.63 12.151C8.3 11.993 8.006 11.788 7.749 11.538V14.635C7.749 14.865 7.677 15.066 7.524 15.219C7.371 15.372 7.171 15.443 6.94 15.443C6.716 15.443 6.52 15.37 6.361 15.222C6.204 15.066 6.133 14.865 6.133 14.635V8.753C6.133 8.058 6.294 7.426 6.617 6.859C6.948 6.286 7.392 5.838 7.948 5.515C8.514 5.182 9.143 5.017 9.83 5.017Z" fill="#EC4899"></path><path d="M10.23 4.617C10.917 4.617 11.545 4.782 12.111 5.114C12.685 5.437 13.134 5.887 13.457 6.46C13.78 7.026 13.941 7.658 13.941 8.353C13.941 9.046 13.79 9.681 13.485 10.254C13.189 10.819 12.775 11.265 12.244 11.589C11.72 11.914 11.133 12.077 10.488 12.077C9.968 12.077 9.481 11.968 9.03 11.751C8.7 11.593 8.406 11.388 8.149 11.138V14.235C8.149 14.465 8.077 14.666 7.924 14.819C7.771 14.972 7.571 15.043 7.34 15.043C7.116 15.043 6.92 14.97 6.761 14.822C6.604 14.666 6.533 14.465 6.533 14.235V8.353C6.533 7.658 6.694 7.026 7.017 6.459C7.348 5.886 7.792 5.438 8.348 5.115C8.914 4.782 9.543 4.617 10.23 4.617Z" fill="white"></path></svg></div> <span class="lh-hero-triptych-pr-name">pie</span> <span class="lh-hero-triptych-pr-bot-badge">bot</span> </div> <div class="lh-hero-triptych-pr-title">fix: prevent duplicate charge on retry</div> <div class="lh-hero-triptych-pr-badges"> <span class="lh-hero-triptych-pr-badge lh-hero-triptych-pr-badge-merged">Merged</span> </div> </div> <div class="lh-hero-triptych-pr lh-hero-triptych-pr-old"> <div class="lh-hero-triptych-pr-author"> <div class="lh-hero-triptych-pr-avatar"><svg viewBox="0 0 20 20" fill="none"><path d="M10 0C10.9147 0 11.7336.4047 12.292 1.043C12.5903 1.361 12.9455 1.622 13.3633 1.8C13.7976 1.984 14.2506 2.057 14.6924 2.036C15.5571 1.989 16.4238 2.281 17.0713 2.929C17.7177 3.575 18.0092 4.44 17.9531 5.285C17.9229 6.208 18.2865 7.088 18.9561 7.697C19.5967 8.271 20 9.088 20 10C20 10.912 19.5964 11.728 18.9609 12.286C18.2789 12.907 17.9109 13.796 17.9561 14.707C18.0098 15.559 17.7182 16.425 17.0713 17.071C16.4237 17.719 15.5571 18.011 14.71 17.953C14.2463 17.946 13.7949 18.019 13.3623 18.202C12.9468 18.379 12.5925 18.638 12.3066 18.951C11.7336 19.595 10.915 20 10 20C9.084 20 8.2644 19.594 7.706 18.954C7.405 18.638 7.0521 18.378 6.6377 18.202C6.2067 18.019 5.757 17.947 5.3184 17.966C4.4458 18.011 3.5781 17.72 2.9297 17.071C2.2808 16.423 1.9879 15.554 2.0469 14.705C2.0839 13.793 1.7199 12.911 1.0479 12.302C.4062 11.735 0 10.916 0 10C0 9.084.4059 8.264 1.0459 7.706C1.7122 7.084 2.0727 6.212 2.0342 5.316C1.9879 4.446 2.2798 3.578 2.9287 2.929C3.5773 2.28 4.4456 1.988 5.294 2.047C5.7521 2.056 6.2038 1.984 6.6367 1.8C7.0533 1.623 7.4072 1.362 7.6934 1.048C8.2644.405 9.0843 0 10 0Z" fill="#6B21A8"></path><path d="M9.83 5.017C10.517 5.017 11.145 5.182 11.711 5.514C12.285 5.837 12.734 6.287 13.057 6.86C13.38 7.426 13.541 8.058 13.541 8.753C13.541 9.446 13.39 10.081 13.085 10.654C12.789 11.219 12.375 11.665 11.844 11.989C11.32 12.314 10.733 12.477 10.088 12.477C9.568 12.477 9.081 12.368 8.63 12.151C8.3 11.993 8.006 11.788 7.749 11.538V14.635C7.749 14.865 7.677 15.066 7.524 15.219C7.371 15.372 7.171 15.443 6.94 15.443C6.716 15.443 6.52 15.37 6.361 15.222C6.204 15.066 6.133 14.865 6.133 14.635V8.753C6.133 8.058 6.294 7.426 6.617 6.859C6.948 6.286 7.392 5.838 7.948 5.515C8.514 5.182 9.143 5.017 9.83 5.017Z" fill="#EC4899"></path><path d="M10.23 4.617C10.917 4.617 11.545 4.782 12.111 5.114C12.685 5.437 13.134 5.887 13.457 6.46C13.78 7.026 13.941 7.658 13.941 8.353C13.941 9.046 13.79 9.681 13.485 10.254C13.189 10.819 12.775 11.265 12.244 11.589C11.72 11.914 11.133 12.077 10.488 12.077C9.968 12.077 9.481 11.968 9.03 11.751C8.7 11.593 8.406 11.388 8.149 11.138V14.235C8.149 14.465 8.077 14.666 7.924 14.819C7.771 14.972 7.571 15.043 7.34 15.043C7.116 15.043 6.92 14.97 6.761 14.822C6.604 14.666 6.533 14.465 6.533 14.235V8.353C6.533 7.658 6.694 7.026 7.017 6.459C7.348 5.886 7.792 5.438 8.348 5.115C8.914 4.782 9.543 4.617 10.23 4.617Z" fill="white"></path></svg></div> <span class="lh-hero-triptych-pr-name">pie</span> <span class="lh-hero-triptych-pr-bot-badge">bot</span> </div> <div class="lh-hero-triptych-pr-title">fix: tax calculation returns NaN for empty cart</div> <div class="lh-hero-triptych-pr-badges"> <span class="lh-hero-triptych-pr-badge lh-hero-triptych-pr-badge-merged">Merged</span> </div> </div> <!-- Divider --> <div class="lh-hero-triptych-pr-divider" id="p3-divider"></div> <!-- Current PR (animated in) --> <div class="lh-hero-triptych-pr" id="p3-current-pr"> <div class="lh-hero-triptych-pr-author" id="p3-author"> <div class="lh-hero-triptych-pr-avatar"><svg viewBox="0 0 20 20" fill="none"><path d="M10 0C10.9147 0 11.7336.4047 12.292 1.043C12.5903 1.361 12.9455 1.622 13.3633 1.8C13.7976 1.984 14.2506 2.057 14.6924 2.036C15.5571 1.989 16.4238 2.281 17.0713 2.929C17.7177 3.575 18.0092 4.44 17.9531 5.285C17.9229 6.208 18.2865 7.088 18.9561 7.697C19.5967 8.271 20 9.088 20 10C20 10.912 19.5964 11.728 18.9609 12.286C18.2789 12.907 17.9109 13.796 17.9561 14.707C18.0098 15.559 17.7182 16.425 17.0713 17.071C16.4237 17.719 15.5571 18.011 14.71 17.953C14.2463 17.946 13.7949 18.019 13.3623 18.202C12.9468 18.379 12.5925 18.638 12.3066 18.951C11.7336 19.595 10.915 20 10 20C9.084 20 8.2644 19.594 7.706 18.954C7.405 18.638 7.0521 18.378 6.6377 18.202C6.2067 18.019 5.757 17.947 5.3184 17.966C4.4458 18.011 3.5781 17.72 2.9297 17.071C2.2808 16.423 1.9879 15.554 2.0469 14.705C2.0839 13.793 1.7199 12.911 1.0479 12.302C.4062 11.735 0 10.916 0 10C0 9.084.4059 8.264 1.0459 7.706C1.7122 7.084 2.0727 6.212 2.0342 5.316C1.9879 4.446 2.2798 3.578 2.9287 2.929C3.5773 2.28 4.4456 1.988 5.294 2.047C5.7521 2.056 6.2038 1.984 6.6367 1.8C7.0533 1.623 7.4072 1.362 7.6934 1.048C8.2644.405 9.0843 0 10 0Z" fill="#6B21A8"></path><path d="M9.83 5.017C10.517 5.017 11.145 5.182 11.711 5.514C12.285 5.837 12.734 6.287 13.057 6.86C13.38 7.426 13.541 8.058 13.541 8.753C13.541 9.446 13.39 10.081 13.085 10.654C12.789 11.219 12.375 11.665 11.844 11.989C11.32 12.314 10.733 12.477 10.088 12.477C9.568 12.477 9.081 12.368 8.63 12.151C8.3 11.993 8.006 11.788 7.749 11.538V14.635C7.749 14.865 7.677 15.066 7.524 15.219C7.371 15.372 7.171 15.443 6.94 15.443C6.716 15.443 6.52 15.37 6.361 15.222C6.204 15.066 6.133 14.865 6.133 14.635V8.753C6.133 8.058 6.294 7.426 6.617 6.859C6.948 6.286 7.392 5.838 7.948 5.515C8.514 5.182 9.143 5.017 9.83 5.017Z" fill="#EC4899"></path><path d="M10.23 4.617C10.917 4.617 11.545 4.782 12.111 5.114C12.685 5.437 13.134 5.887 13.457 6.46C13.78 7.026 13.941 7.658 13.941 8.353C13.941 9.046 13.79 9.681 13.485 10.254C13.189 10.819 12.775 11.265 12.244 11.589C11.72 11.914 11.133 12.077 10.488 12.077C9.968 12.077 9.481 11.968 9.03 11.751C8.7 11.593 8.406 11.388 8.149 11.138V14.235C8.149 14.465 8.077 14.666 7.924 14.819C7.771 14.972 7.571 15.043 7.34 15.043C7.116 15.043 6.92 14.97 6.761 14.822C6.604 14.666 6.533 14.465 6.533 14.235V8.353C6.533 7.658 6.694 7.026 7.017 6.459C7.348 5.886 7.792 5.438 8.348 5.115C8.914 4.782 9.543 4.617 10.23 4.617Z" fill="white"></path></svg></div> <span class="lh-hero-triptych-pr-name">pie</span> <span class="lh-hero-triptych-pr-bot-badge">bot</span> </div> <div class="lh-hero-triptych-pr-title" id="p3-title">fix: cap promo discount at cart total</div> <div class="lh-hero-triptych-pr-section" id="p3-root-section"> <span class="lh-hero-triptych-pr-label">Root cause</span> <p class="lh-hero-triptych-pr-text"><code class="lh-hero-triptych-inline-code">applyPromo()</code> on line 42 returns raw discount value without floor check.</p> </div> <div class="lh-hero-triptych-pr-section" id="p3-fix-section"> <span class="lh-hero-triptych-pr-label">Fix applied</span> <code class="lh-hero-triptych-pr-fix-code">cart.total = Math.max(0, cart.total - discount);</code> </div> <div class="lh-hero-triptych-pr-badges" id="p3-badges"> <span class="lh-hero-triptych-pr-badge lh-hero-triptych-pr-badge-green"> <svg viewBox="0 0 16 16" fill="none"><path d="M3.5 8.5L6.5 11.5L12.5 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
CI passing
</span> <span class="lh-hero-triptych-pr-badge lh-hero-triptych-pr-badge-blue"> <svg viewBox="0 0 16 16" fill="none"><path d="M3.5 8.5L6.5 11.5L12.5 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
Ready to merge
</span> </div> </div> </div> </div> <div class="lh-hero-triptych-footer" id="p3-footer"> <span class="lh-hero-triptych-footer-dot"></span> <span class="lh-hero-triptych-footer-text">Fix merged · <strong class="lh-hero-triptych-footer-bold">bug shipped zero customers</strong></span> </div> </div> </div> </div> </section> <script>
(function() {
  var diff = document.getElementById('p1-diff');
  if (!diff) return;
  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;

  // ======== Gather all elements once ========
  var panel = diff.closest('.lh-hero-triptych-left');
  var annotation = document.getElementById('p1-annotation');
  var p1Footer = panel.querySelector('.lh-hero-triptych-footer');
  var footerDot = p1Footer ? p1Footer.querySelector('.lh-hero-triptych-footer-dot') : null;
  var footerText = p1Footer ? p1Footer.querySelector('.lh-hero-triptych-footer-text') : null;
  var scan = document.getElementById('p1-scan');
  var status = document.getElementById('p1-status');

  // Panel 2 is now a looping <video> element — no JS animation.
  var p3Feed = document.getElementById('p3-feed');
  var p3Author = document.getElementById('p3-author');
  var p3Title = document.getElementById('p3-title');
  var p3RootSection = document.getElementById('p3-root-section');
  var p3FixSection = document.getElementById('p3-fix-section');
  var p3RootLabel = p3RootSection ? p3RootSection.querySelector('.lh-hero-triptych-pr-label') : null;
  var p3RootText = p3RootSection ? p3RootSection.querySelector('.lh-hero-triptych-pr-text') : null;
  var p3FixLabel = p3FixSection ? p3FixSection.querySelector('.lh-hero-triptych-pr-label') : null;
  var p3FixCode = p3FixSection ? p3FixSection.querySelector('.lh-hero-triptych-pr-fix-code') : null;
  var p3BadgesWrap = document.getElementById('p3-badges');
  var p3Badges = p3BadgesWrap ? p3BadgesWrap.querySelectorAll('.lh-hero-triptych-pr-badge') : [];
  var p3Divider = document.getElementById('p3-divider');
  var p3CurrentPr = document.getElementById('p3-current-pr');
  var p3Footer = document.getElementById('p3-footer');
  var p3FooterDot = p3Footer ? p3Footer.querySelector('.lh-hero-triptych-footer-dot') : null;
  var p3FooterText = p3Footer ? p3Footer.querySelector('.lh-hero-triptych-footer-text') : null;

  if (!p3Feed) return;

  // ======== Shared helpers ========
  function hideEl(el) {
    if (!el) return;
    el.style.opacity = '0';
    el.style.transform = 'translateY(4px)';
    el.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
  }
  function showEl(el) {
    if (!el) return;
    el.style.opacity = '1';
    el.style.transform = 'translateY(0)';
  }
  // ======== Line data (Panel 1) ========
  var L = [
    [1,'n',"import express from 'express';"],
    [2,'n',"import Stripe from 'stripe';"],
    [3,'n',"import { Logger } from './logger';"],
    [4,'n',"import { CartRepo } from './cart.repo';"],
    [5,'n',"import { validateCart } from './validate';"],
    [6,'a',"+ import { applyPromo } from './promo';"],
    [7,'b',''],
    [8,'n','interface CartItem {'],
    [9,'n','  productId: string;'],
    [10,'n','  name: string;'],
    [11,'n','  price: number;'],
    [12,'n','  qty: number;'],
    [13,'n','}'],
    [14,'b',''],
    [15,'n','interface Cart {'],
    [16,'n','  id: string;'],
    [17,'n','  user: string;'],
    [18,'n','  items: CartItem[];'],
    [19,'n','  total: number;'],
    [20,'n','  promoCode?: string;'],
    [21,'n','}'],
    [22,'b',''],
    [23,'n','export class CheckoutService {'],
    [24,'n','  private stripe: Stripe;'],
    [25,'n','  private repo: CartRepo;'],
    [26,'n','  private logger: Logger;'],
    [27,'b',''],
    [28,'n','  constructor(stripe: Stripe, repo: CartRepo) {'],
    [29,'n','    this.stripe = stripe;'],
    [30,'n','    this.repo = repo;'],
    [31,'n','    this.logger = new Logger("checkout");'],
    [32,'n','  }'],
    [33,'b',''],
    [34,'n','  private calcTotal(items: CartItem[]) {'],
    [35,'n','    return items.reduce((sum, i) =>'],
    [36,'n','      sum + i.price * i.qty, 0'],
    [37,'n','    );'],
    [38,'n','  }'],
    [39,'b',''],
    [40,'n','  async checkout(cart: Cart) {'],
    [41,'n','    await validateCart(cart);'],
    [42,'a','+ \u00a0\u00a0const disc = applyPromo(cart);','applyPromo'],
    [43,'a','+ \u00a0\u00a0cart.total = cart.total - disc;'],
    [44,'n','    const charge = await this.stripe.charge(cart.total);'],
    [45,'n','    this.logger.info("charged", { amount: cart.total });'],
    [46,'n','    await this.notify(cart.user, charge);'],
    [47,'n','    return this.process(cart);'],
    [48,'n','  }'],
    [49,'b',''],
    [50,'n','  private async notify(userId: string, charge: any) {'],
    [51,'n','    await this.repo.markPaid(userId);'],
    [52,'n','    this.logger.info("notify", { userId });'],
    [53,'n','  }'],
    [54,'b',''],
    [55,'n','  private async process(cart: Cart) {'],
    [56,'n','    const receipt = await this.repo.save(cart);'],
    [57,'n','    return { status: "ok", receipt };'],
    [58,'n','  }'],
    [59,'b',''],
    [60,'n','  async refund(chargeId: string) {'],
    [61,'n','    const charge = await this.stripe.refund(chargeId);'],
    [62,'n','    this.logger.info("refund", { chargeId });'],
    [63,'n','    return charge;'],
    [64,'n','  }'],
    [65,'b',''],
    [66,'n','  async getHistory(userId: string) {'],
    [67,'n','    return this.repo.findByUser(userId);'],
    [68,'n','  }'],
    [69,'b',''],
    [70,'n','  async applyCredit(userId: string, amt: number) {'],
    [71,'n','    const bal = await this.repo.getBalance(userId);'],
    [72,'n','    await this.repo.setBalance(userId, bal + amt);'],
    [73,'n','    this.logger.info("credit", { userId, amt });'],
    [74,'n','  }'],
    [75,'b',''],
    [76,'n','  private validatePromo(code: string) {'],
    [77,'n','    return this.repo.findPromo(code);'],
    [78,'n','  }'],
    [79,'b',''],
    [80,'n','  async updateShipping(cartId: string, addr: any) {'],
    [81,'n','    const cart = await this.repo.findCart(cartId);'],
    [82,'n','    cart.shipping = addr;'],
    [83,'n','    await this.repo.save(cart);'],
    [84,'n','  }'],
    [85,'b',''],
    [86,'n','  async estimateTax(cart: Cart) {'],
    [87,'n','    const rate = await this.repo.getTaxRate(cart);'],
    [88,'n','    return cart.total * rate;'],
    [89,'n','  }'],
    [90,'b',''],
    [91,'n','  async cancelOrder(orderId: string) {'],
    [92,'n','    const order = await this.repo.findOrder(orderId);'],
    [93,'n','    if (order.status !== "pending") throw new Error();'],
    [94,'n','    await this.refund(order.chargeId);'],
    [95,'n','    order.status = "cancelled";'],
    [96,'n','    await this.repo.save(order);'],
    [97,'n','  }'],
    [98,'b',''],
    [99,'n','  async generateInvoice(orderId: string) {'],
    [100,'n','    const order = await this.repo.findOrder(orderId);'],
    [101,'n','    return this.repo.createInvoice(order);'],
    [102,'n','  }'],
    [103,'n','}']
  ];

  function makeLine(data) {
    var num = data[0], type = data[1], code = data[2], hl = data[3];
    var el = document.createElement('div');
    el.className = 'lh-hero-triptych-diff-line';
    if (type === 'a') el.className += ' lh-hero-triptych-diff-added';
    if (num === 42 || num === 43) el.setAttribute('data-critical', '');
    var ln = document.createElement('span');
    ln.className = 'lh-hero-triptych-ln';
    ln.textContent = num;
    el.appendChild(ln);
    if (type === 'b') {
      var sp = document.createElement('span');
      sp.className = 'lh-hero-triptych-code-default';
      sp.innerHTML = '\u00a0';
      el.appendChild(sp);
    } else if (hl) {
      var span = document.createElement('span');
      var parts = code.split('applyPromo');
      span.innerHTML = escHtml(parts[0]) +
        '<span class="lh-hero-triptych-highlight lh-hero-triptych-highlight-pending">' +
        'applyPromo</span>' + escHtml(parts[1]);
      el.appendChild(span);
    } else {
      var codeSpan = document.createElement('span');
      codeSpan.className = type === 'n' ? 'lh-hero-triptych-code-default' : '';
      codeSpan.textContent = code;
      el.appendChild(codeSpan);
    }
    el.style.opacity = '0';
    el.style.transform = 'translateX(-4px)';
    return el;
  }

  function escHtml(s) {
    return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  }

  function revealLine(el) {
    el.style.transition = 'opacity 0.15s ease, transform 0.15s ease';
    el.style.opacity = '1';
    el.style.transform = 'translateX(0)';
  }

  // ======== Timer management ========
  var timers = [];
  var intervals = [];
  function sT(fn, delay) { timers.push(setTimeout(fn, delay)); }
  function sI(fn, delay) { var id = setInterval(fn, delay); intervals.push(id); return id; }
  function clearAllTimers() {
    for (var t = 0; t < timers.length; t++) clearTimeout(timers[t]);
    for (var v = 0; v < intervals.length; v++) clearInterval(intervals[v]);
    timers = [];
    intervals = [];
  }

  // ======== Reset all panels to initial state ========
  function resetAll() {
    clearAllTimers();

    // Panel 1: clear diff lines, reset scan, hide annotation/footer/status
    diff.innerHTML = '';
    diff.appendChild(scan);
    diff.scrollTop = 0;
    diff.classList.remove('lh-hero-triptych-diff-alert');
    diff.style.scrollBehavior = '';
    scan.style.opacity = '0';
    scan.style.height = '2px';
    scan.style.boxShadow = '0 0 8px rgba(139,92,246,0.4)';
    scan.style.top = '0px';
    if (annotation) {
      annotation.classList.add('lh-hero-triptych-anim-hidden-y');
      annotation.classList.remove('lh-hero-triptych-anim-visible-y');
    }
    if (footerDot) {
      footerDot.classList.add('lh-hero-triptych-footer-dot-anim');
      footerDot.classList.remove('lh-hero-triptych-anim-visible');
    }
    if (footerText) {
      footerText.classList.add('lh-hero-triptych-anim-hidden-y');
      footerText.classList.remove('lh-hero-triptych-anim-visible-y');
    }
    if (status) {
      status.textContent = 'analyzing...';
      status.classList.remove('lh-hero-triptych-status-alert');
    }

    // Panel 2: stop and reset Lottie, snap back to dimmed
    var lottie = window.__pieLottie;
    if (lottie) { lottie.stop(); }
    var p2Panel = document.querySelector('.lh-hero-triptych-center');
    if (p2Panel) { p2Panel.style.animation = 'none'; p2Panel.style.opacity = '0.5'; p2Panel.style.transform = 'translateY(0)'; p2Panel.classList.remove('lh-hero-active'); p2Panel.classList.add('lh-hero-dimmed'); }

    // Panel 3: snap to dimmed, reset feed, hide current PR, reset footer
    var p3Panel = document.querySelector('.lh-hero-triptych-right');
    if (p3Panel) { p3Panel.style.animation = 'none'; p3Panel.style.opacity = '0.5'; p3Panel.style.transform = 'translateY(0)'; }
    if (p3CurrentPr) p3CurrentPr.style.display = 'none';
    if (p3Divider) p3Divider.style.display = 'none';
    p3Feed.scrollTop = 0;
    p3Feed.style.scrollBehavior = '';
    if (p3FooterDot) { p3FooterDot.classList.add('lh-hero-triptych-footer-dot-anim'); p3FooterDot.classList.remove('lh-hero-triptych-anim-visible'); }
    if (p3FooterText) { p3FooterText.classList.add('lh-hero-triptych-anim-hidden-y'); p3FooterText.classList.remove('lh-hero-triptych-anim-visible-y'); }
    // Hide current PR badges immediately
    for (var b = 0; b < p3Badges.length; b++) {
      p3Badges[b].classList.add('lh-hero-triptych-badge-pop');
      p3Badges[b].classList.remove('lh-hero-triptych-anim-visible');
    }
  }

  // ======== Main animation function ========
  function runAnimation() {
    resetAll();

    var i;
    var panelDelay = 1000;
    var phase1Speed = 40;
    var phase3Speed0 = 30;
    var phase3Min = 15;
    var freezeDuration = 1300;

    // --- Panel 1: Code scroll ---
    var allEls = [];
    for (i = 0; i < L.length; i++) allEls.push(makeLine(L[i]));

    var time = panelDelay;
    for (i = 0; i < L.length; i++) {
      var lineNum = L[i][0];
      if (lineNum < 42) {
        scheduleReveal(allEls[i], time, lineNum);
        time += phase1Speed;
      } else if (lineNum === 42) {
        time += 150;
        scheduleReveal(allEls[i], time, lineNum);
        time += 300;
      } else if (lineNum === 43) {
        scheduleReveal(allEls[i], time, lineNum);
        time += freezeDuration;
      } else {
        var progress = (lineNum - 44) / (103 - 44);
        var speed = phase3Speed0 - (phase3Speed0 - phase3Min) * progress;
        scheduleReveal(allEls[i], time, lineNum);
        time += speed;
      }
    }
    var scrollEnd = time;

    function scheduleReveal(lineEl, t, num) {
      sT(function() {
        diff.appendChild(lineEl);
        lineEl.offsetHeight;
        revealLine(lineEl);
        diff.scrollTop = diff.scrollHeight;
        if (status && !status.classList.contains('lh-hero-triptych-status-alert')) {
          status.textContent = num + '/103';
        }
      }, t);
    }

    // Scan line
    sT(function() { scan.style.opacity = '0.35'; }, panelDelay + 8 * phase1Speed);
    var scanIntId = sI(function() {
      scan.style.top = (diff.scrollTop + diff.clientHeight - 4) + 'px';
    }, 30);

    // Critical detection
    var critTime = panelDelay + 41 * phase1Speed + 150;
    sT(function() {
      scan.style.opacity = '0.7'; scan.style.height = '3px';
      scan.style.boxShadow = '0 0 14px rgba(139,92,246,0.6)';
      var crits = diff.querySelectorAll('[data-critical]');
      for (var c = 0; c < crits.length; c++) crits[c].classList.add('lh-hero-triptych-diff-line-focus');
    }, critTime);

    var freezeStart = critTime + 350;
    sT(function() {
      var crits = diff.querySelectorAll('[data-critical]');
      if (crits.length > 0) {
        var targetScroll = crits[0].offsetTop - (diff.clientHeight / 2) + crits[0].offsetHeight;
        diff.style.scrollBehavior = 'smooth';
        diff.scrollTop = Math.max(0, targetScroll);
        sT(function() { diff.style.scrollBehavior = ''; }, 400);
      }
    }, freezeStart + 100);
    sT(function() { diff.classList.add('lh-hero-triptych-diff-alert'); }, freezeStart + 400);
    sT(function() {
      var hl = diff.querySelector('.lh-hero-triptych-highlight');
      if (hl) hl.classList.remove('lh-hero-triptych-highlight-pending');
    }, freezeStart + 500);
    sT(function() {
      if (status) { status.textContent = '\u26A0 issue on ln 42'; status.classList.add('lh-hero-triptych-status-alert'); }
    }, freezeStart + 600);
    sT(function() { diff.classList.remove('lh-hero-triptych-diff-alert'); }, freezeStart + 1200);
    sT(function() {
      scan.style.opacity = '0.3'; scan.style.height = '2px';
      scan.style.boxShadow = '0 0 8px rgba(139,92,246,0.3)';
    }, freezeStart + freezeDuration);
    sT(function() { scan.style.opacity = '0'; clearInterval(scanIntId); }, scrollEnd + 100);

    // Post-scroll
    var afterScroll = scrollEnd + 200;
    sT(function() {
      if (annotation) { annotation.classList.remove('lh-hero-triptych-anim-hidden-y'); annotation.classList.add('lh-hero-triptych-anim-visible-y'); }
    }, afterScroll);
    var footerStart = afterScroll + 400;
    sT(function() { if (footerDot) footerDot.classList.add('lh-hero-triptych-anim-visible'); }, footerStart);
    sT(function() {
      if (footerText) { footerText.classList.remove('lh-hero-triptych-anim-hidden-y'); footerText.classList.add('lh-hero-triptych-anim-visible-y'); }
    }, footerStart + 100);

    // --- Panel 2: Lottie — triggered after Panel 1 finishes ---
    var panel1End = footerStart + 600;
    sT(function() {
      startPanel2();
    }, panel1End);
  }

  // ======== Panel 2 → Panel 3 bridge ========
  function startPanel2() {
    var p2Panel = document.querySelector('.lh-hero-triptych-center');
    if (p2Panel) { p2Panel.style.animation = 'none'; p2Panel.style.transition = 'opacity 0.4s ease'; p2Panel.style.opacity = '1'; p2Panel.classList.remove('lh-hero-dimmed'); p2Panel.classList.add('lh-hero-active'); }
    var lottie = window.__pieLottie;
    if (lottie) {
      // Stop and reset to frame 0, then play once
      lottie.stop();
      lottie.play();
      // Listen for completion — DotLottie fires 'complete' at end of non-looping play
      lottie.addEventListener('complete', onPanel2Done, { once: true });
    } else {
      // Lottie not loaded yet — fall back to timed delay
      sT(onPanel2Done, 4000);
    }
  }

  function onPanel2Done() {
    runPanel3();
  }

  // ======== Panel 3: Fix PR ========
  function runPanel3() {
    var p3Panel = document.querySelector('.lh-hero-triptych-right');
    if (p3Panel) { p3Panel.style.transition = 'opacity 0.4s ease'; p3Panel.style.opacity = '1'; }
    var t = 0;
    sT(function() {
      if (p3Divider) p3Divider.style.display = '';
      if (p3CurrentPr) {
        p3CurrentPr.style.display = '';
        hideEl(p3Author); hideEl(p3Title);
        if (p3Title) p3Title.style.transform = 'translateX(-4px)';
        hideEl(p3RootLabel); hideEl(p3RootText);
        hideEl(p3FixLabel); hideEl(p3FixCode);
        for (var b = 0; b < p3Badges.length; b++) p3Badges[b].classList.add('lh-hero-triptych-badge-pop');
      }
      p3Feed.style.scrollBehavior = 'smooth';
      p3Feed.scrollTop = p3Feed.scrollHeight;
    }, t);
    sT(function() { showEl(p3Author); }, t + 300);
    sT(function() { if (p3Title) { p3Title.style.opacity = '1'; p3Title.style.transform = 'translateX(0)'; } }, t + 800);
    sT(function() { showEl(p3RootLabel); }, t + 1200);
    sT(function() { showEl(p3RootText); }, t + 1350);
    sT(function() { showEl(p3FixLabel); }, t + 1800);
    sT(function() { showEl(p3FixCode); p3Feed.scrollTop = p3Feed.scrollHeight; }, t + 1950);
    sT(function() { if (p3Badges[0]) p3Badges[0].classList.add('lh-hero-triptych-anim-visible'); p3Feed.scrollTop = p3Feed.scrollHeight; }, t + 2400);
    sT(function() { if (p3Badges[1]) p3Badges[1].classList.add('lh-hero-triptych-anim-visible'); }, t + 2550);
    sT(function() { if (p3FooterDot) p3FooterDot.classList.add('lh-hero-triptych-anim-visible'); }, t + 2900);
    sT(function() {
      if (p3FooterText) { p3FooterText.classList.remove('lh-hero-triptych-anim-hidden-y'); p3FooterText.classList.add('lh-hero-triptych-anim-visible-y'); }
    }, t + 3000);

    // --- Loop: wait 5s after Panel 3 finishes, then replay all ---
    sT(function() { runAnimation(); }, t + 3200 + 5000);
  }

  // ======== First run ========
  // Clear static fallback
  diff.innerHTML = '';
  diff.appendChild(scan);
  runAnimation();
})();
</script> <script type="module">
  // Panel 2 — Lottie init via @lottiefiles/dotlottie-web (CDN-loaded ESM).
  // Pinned to major version 0 to avoid a future v1 breaking production.
  // Uses a <canvas> target because the DotLottie core API requires a canvas.
  // Exposed on window.__pieLottie so the main animation script can control playback.
  import { DotLottie } from 'https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web@0/+esm';

  const canvas = document.getElementById('p2-lottie');
  if (canvas) {
    window.__pieLottie = new DotLottie({
      canvas,
      src: '/lottie/pie-panel2-checkout.json',
      loop: false,
      autoplay: false,
    });
  }
</script> <section class="max-w-[720px] mx-auto px-5 lg:px-8 py-[120px] border-t border-[rgba(255,255,255,0.05)]" data-reveal> <div class="text-center mb-12"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-4">Sound familiar?</div> <h2 class="font-display font-bold text-4xl md:text-5xl tracking-tight leading-[1.1] text-text-primary">
Code review approved it.<br><span class="text-gradient">The product broke anyway.</span> </h2> </div> <!-- Juxtaposition card --> <div class="lh-sf-card" id="sf-card" style="--split: 62%;"> <!-- RIGHT PANEL (production) — sits behind, full width --> <div class="lh-sf-panel lh-sf-right font-body"> <div class="lh-sf-status"> <span class="lh-sf-status-dot lh-sf-status-dot--red"></span> <span class="lh-sf-status-label lh-sf-status-label--red" id="sf-r-status">Production</span> </div> <p class="lh-sf-title lh-sf-title--red font-body" id="sf-r-title">Checkout total renders $0.00 for all orders</p> <p class="lh-sf-desc lh-sf-desc--red font-body" id="sf-r-desc">Discovered by a customer. 4 hours after deploy. CI was green.</p> <div class="lh-sf-pills lh-sf-pills--red" id="sf-r-pills"> <span class="lh-sf-pill lh-sf-pill--red font-body">847 errors in 30 min</span> <span class="lh-sf-pill lh-sf-pill--red font-body">12 customer reports</span> </div> </div> <!-- LEFT PANEL (CI/code) — sits on top with clip-path --> <div class="lh-sf-panel lh-sf-left font-body" id="sf-left"> <div class="lh-sf-status"> <span class="lh-sf-status-dot lh-sf-status-dot--green"></span> <span class="lh-sf-status-label lh-sf-status-label--green" id="sf-l-status">CI passed</span> </div> <p class="lh-sf-title lh-sf-title--green font-body" id="sf-l-title">PR #412 — Refactor payment reduce logic</p> <p class="lh-sf-desc lh-sf-desc--green font-body" id="sf-l-desc">Order total renders $0.00. Discount logic skips the merge after the reduce function changed.</p> <div class="lh-sf-pills lh-sf-pills--green" id="sf-l-pills"> <span class="lh-sf-pill lh-sf-pill--green font-body">3 approvals</span> <span class="lh-sf-pill lh-sf-pill--green font-body">all checks pass</span> <span class="lh-sf-pill lh-sf-pill--green font-body">merged to main</span> </div> </div> <!-- SVG diagonal divider --> <svg class="lh-sf-divider" viewBox="0 0 631 354" preserveAspectRatio="none"> <line id="sf-div-line" x1="391.2" y1="0" x2="296.6" y2="354" stroke="rgba(255,255,255,0.1)" stroke-width="1.5"></line> </svg> <!-- Drag handle --> <div class="lh-sf-handle" id="sf-handle"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none"> <path d="M7 9L4 12L7 15" stroke="#A1A1AA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> <path d="M17 9L20 12L17 15" stroke="#A1A1AA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> <line x1="9" y1="7" x2="9" y2="17" stroke="#3F3F46" stroke-width="1"></line> <line x1="15" y1="7" x2="15" y2="17" stroke="#3F3F46" stroke-width="1"></line> </svg> </div> </div> <!-- Dot navigation --> <div class="lh-sf-dots"> <button type="button" class="lh-sf-dot lh-sf-dot--active" data-i="0" aria-label="Show bug 1"></button> <button type="button" class="lh-sf-dot" data-i="1" aria-label="Show bug 2"></button> <button type="button" class="lh-sf-dot" data-i="2" aria-label="Show bug 3"></button> </div> <div class="text-center mt-12"> <p class="font-body text-lg text-text-secondary leading-relaxed max-w-2xl mx-auto">
These are the bugs that pass every code review tool on the market. They don't live in the diff. They live in the running product. <strong class="text-text-primary">Pie catches them because Pie actually uses your product, the same way your customers do.</strong> </p> </div> </section> <script>
(function() {
  var card = document.getElementById('sf-card');
  if (!card) return;

  var divLine = document.getElementById('sf-div-line');
  var handle = document.getElementById('sf-handle');

  var prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  var dragging = false;

  var cards = [
    {
      leftStatus: "CI passed",
      leftTitle: "PR #412 \u2014 Refactor payment reduce logic",
      leftDesc: "Order total renders $0.00. Discount logic skips the merge after the reduce function changed.",
      leftPills: ["3 approvals", "all checks pass", "merged to main"],
      rightStatus: "Production",
      rightTitle: "Checkout total renders $0.00 for all orders",
      rightDesc: "Discovered by a customer. 4 hours after deploy. CI was green.",
      rightPills: ["847 errors in 30 min", "12 customer reports"]
    },
    {
      leftStatus: "CI passed",
      leftTitle: "PR #287 \u2014 Update auth redirect flow",
      leftDesc: "Session token doesn\u2019t persist across redirects. Works on Chrome, silent failure on Safari.",
      leftPills: ["2 approvals", "CI green", "merged to main"],
      rightStatus: "Production",
      rightTitle: "Login fails on mobile Safari for 18% of users",
      rightDesc: "Two days before anyone noticed. Found via support ticket spike.",
      rightPills: ["342 failed logins", "48 support tickets"]
    },
    {
      leftStatus: "CI passed",
      leftTitle: "PR #503 \u2014 Migrate data layer to v2",
      leftDesc: "Component crashes when the API returns an empty array. No error boundary, white screen.",
      leftPills: ["4 approvals", "all checks pass", "staging OK"],
      rightStatus: "Production",
      rightTitle: "Dashboard goes blank for new accounts",
      rightDesc: "Three support tickets before engineering noticed. Shipped on a Friday.",
      rightPills: ["white screen", "3 escalations in 1 hour"]
    }
  ];

  function setSplit(pct) {
    pct = Math.max(25, Math.min(85, pct));
    card.style.setProperty('--split', pct + '%');
    var topX = (pct / 100) * 631;
    var botX = ((pct - 15) / 100) * 631;
    divLine.setAttribute('x1', topX);
    divLine.setAttribute('x2', botX);
    handle.style.left = ((pct - 7.5) / 100 * 100) + '%';
  }

  function updateFromPointer(e) {
    var rect = card.getBoundingClientRect();
    var pct = ((e.clientX - rect.left) / rect.width) * 100;
    setSplit(pct + 7.5);
  }

  function updatePills(containerId, pills, color) {
    var el = document.getElementById(containerId);
    el.innerHTML = '';
    pills.forEach(function(text) {
      var span = document.createElement('span');
      span.className = 'lh-sf-pill lh-sf-pill--' + color + ' font-body';
      span.textContent = text;
      el.appendChild(span);
    });
  }

  function setCard(i) {
    var c = cards[i];
    document.getElementById('sf-l-status').textContent = c.leftStatus;
    document.getElementById('sf-l-title').textContent = c.leftTitle;
    document.getElementById('sf-l-desc').textContent = c.leftDesc;
    updatePills('sf-l-pills', c.leftPills, 'green');
    document.getElementById('sf-r-status').textContent = c.rightStatus;
    document.getElementById('sf-r-title').textContent = c.rightTitle;
    document.getElementById('sf-r-desc').textContent = c.rightDesc;
    updatePills('sf-r-pills', c.rightPills, 'red');
    setSplit(62);
    document.querySelectorAll('.lh-sf-dot').forEach(function(d, idx) {
      d.classList.toggle('lh-sf-dot--active', idx === i);
    });
  }

  // Drag interaction
  if (!prefersReduced) {
    card.addEventListener('pointerdown', function(e) {
      dragging = true;
      card.setPointerCapture(e.pointerId);
      updateFromPointer(e);
    });
    card.addEventListener('pointermove', function(e) {
      if (!dragging) return;
      updateFromPointer(e);
    });
    card.addEventListener('pointerup', function() { dragging = false; });
    card.addEventListener('pointercancel', function() { dragging = false; });
  }

  // Dot navigation
  document.querySelectorAll('.lh-sf-dot').forEach(function(dot) {
    dot.addEventListener('click', function() {
      var i = Number(dot.getAttribute('data-i'));
      setCard(i);
    });
  });

  // Initialize
  setSplit(62);
})();
</script> <section class="max-w-[1120px] mx-auto px-5 lg:px-8 py-[120px] relative" data-reveal> <div class="text-center mb-12"> <h2 class="font-display font-bold text-4xl md:text-5xl text-text-primary mb-6 tracking-tight">
The numbers behind <span class="text-gradient">the gap</span> </h2> </div> <div class="grid md:grid-cols-3 bg-[#050506] border border-[rgba(255,255,255,0.05)] rounded-[24px] p-6 lg:p-10 shadow-[0_0_40px_rgba(0,0,0,0.5)]" data-reveal-stagger> <div class="text-center px-4 py-8 md:py-0"> <div class="font-mono text-[clamp(40px,5vw,56px)] font-bold text-white tracking-tighter mb-2">6.4x</div> <div class="font-display font-semibold text-lg text-text-primary mb-4">more code generated by AI</div> <div class="font-mono text-[11px] text-text-muted">That's 6.4 times more surface area to review, maintain, and break.</div> </div> <div class="text-center px-4 border-y md:border-y-0 md:border-x border-[rgba(255,255,255,0.05)] py-8 md:py-0"> <div class="font-mono text-[clamp(40px,5vw,56px)] font-bold text-white tracking-tighter mb-2">96%</div> <div class="font-display font-semibold text-lg text-text-primary mb-4">of devs don't trust AI code</div> <div class="font-mono text-[11px] text-text-muted">Only 48% check it before committing.</div> </div> <div class="text-center px-4 py-8 md:py-0"> <div class="font-mono text-[clamp(40px,5vw,56px)] font-bold text-white tracking-tighter mb-2">68%</div> <div class="font-display font-semibold text-lg text-text-primary mb-4">more issues per AI-authored PR</div> <div class="font-mono text-[11px] text-text-muted">CodeRabbit PR analysis, 2025</div> </div> </div> </section> <section class="lh-hpw-section border-t border-[rgba(255,255,255,0.05)]"> <div class="max-w-1080 mx-auto px-6 md:px-16 lg:px-6 py-[120px]"> <!-- Header --> <div class="text-center mb-16" data-reveal> <div class="inline-flex items-center gap-[7px] px-[14px] py-[5px] rounded-full font-mono text-[12.5px] font-bold text-accent-violet bg-[linear-gradient(135deg,rgba(139,92,246,0.1),rgba(217,70,239,0.05))] border border-[rgba(139,92,246,0.2)] tracking-[0.06em] mb-5">HOW PIE WORKS</div> <h2 class="font-display font-semibold text-[clamp(2.2rem,5vw,3.2rem)] text-text-primary tracking-[-0.04em] leading-[1.08] mb-4">
Three steps to <span class="text-gradient">zero bugs</span> </h2> <p class="font-body text-base text-text-secondary max-w-[480px] mx-auto">Connect your repo. Here's what happens when your next PR merges.</p> </div> <!-- Timeline --> <div class="lh-story"> <!-- ═══ BEAT 1: PR merges — text left, card right ═══ --> <div class="lh-beat" data-reveal> <div class="lh-beat-left"> <div class="lh-beat-title">Code merges. CI is green.</div> <div class="lh-beat-desc">All checks pass. Ships to production.</div> </div> <div class="lh-beat-node"><div class="lh-node-dot lh-node-dot--violet text-accent-violet"><svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="18" r="3"></circle><circle cx="6" cy="6" r="3"></circle><path d="M6 21V9a9 9 0 0 0 9 9"></path></svg></div></div> <div class="lh-beat-right"> <div class="lh-card lh-glow-hover bg-[#0a0a0b]"> <div class="p-[18px_20px]"> <div class="text-[14.5px] font-semibold text-text-primary mb-2">Refactor payment — migrate to PaymentIntents</div> <div class="text-[12px] mb-3.5"> <span class="text-accent-violet font-semibold">● Merged</span> </div> <div class="pt-3 border-t border-[rgba(255,255,255,0.08)] flex items-center gap-2 flex-wrap text-[11px] text-text-muted font-medium tracking-[0.02em]">
PIE SCANNING → AFFECTED FLOWS
<span class="lh-flow-tag">checkout flow</span> <span class="lh-flow-tag">refund flow</span> </div> </div> </div> </div> </div> <!-- ═══ BEAT 2: Pie finds the bug — card left, text right ═══ --> <div class="lh-beat" data-reveal> <div class="lh-beat-left lh-beat-left--visual"> <!-- Browser Mockup Card --> <div class="lh-bento-card bg-[#0a0a0b] p-0 overflow-visible relative lh-glow-hover"> <div class="absolute inset-0 rounded-[1.25rem] overflow-hidden bg-[radial-gradient(ellipse_at_center,rgba(139,92,246,0.1)_0%,transparent_70%)] pointer-events-none"></div> <div class="bg-[rgba(255,255,255,0.03)] border-b border-[rgba(255,255,255,0.05)] px-4 py-3 flex items-center gap-4 rounded-t-[1.25rem] overflow-hidden"> <div class="flex items-center gap-1.5 opacity-50"> <div class="w-3 h-3 rounded-full bg-red-400"></div> <div class="w-3 h-3 rounded-full bg-amber-400"></div> <div class="w-3 h-3 rounded-full bg-accent-success"></div> </div> <div class="bg-[rgba(255,255,255,0.05)] rounded px-3 py-1 text-[12px] font-mono text-[rgba(255,255,255,0.5)] flex-1 text-center truncate">staging.yourapp.com/checkout</div> </div> <div class="p-8 pb-12"> <div class="max-w-[280px] mx-auto bg-[#111113] border border-[rgba(255,255,255,0.05)] rounded-lg p-6 shadow-xl relative text-left"> <div class="border-b border-[rgba(255,255,255,0.05)] pb-3 mb-6 font-medium text-white flex justify-between"> <span>Checkout</span> <span class="text-[rgba(255,255,255,0.3)]">Cart</span> </div> <div class="space-y-4"> <div class="bg-[rgba(255,255,255,0.02)] border border-[rgba(255,255,255,0.05)] p-2 rounded text-[13px] text-white"><a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="17647665767f5774787a6776796e3974787a">[email&#160;protected]</a></div> <div class="bg-[rgba(255,255,255,0.02)] border border-[rgba(255,255,255,0.05)] p-2 rounded text-[13px] text-white font-mono">4242 &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; 4242</div> <div class="bg-[rgba(239,68,68,0.05)] border border-red-400 p-2 rounded text-[13px] text-red-400 font-bold font-mono shadow-[0_0_15px_rgba(239,68,68,0.2)]">$0.00</div> </div> <div class="mt-6 bg-accent-violet text-white text-center p-2 rounded text-[13px] font-bold">Complete Purchase</div> <!-- Pie cursor pointing at $0.00 field --> <div class="absolute right-[164px] bottom-[72px] lh-pie-cursor"> <!-- Cursor arrow icon --> <img src="/icons/cursor.svg" alt="" width="32" height="32" style="min-width:32px;min-height:32px;" class="drop-shadow-[0_0_8px_rgba(139,92,246,0.5)] relative z-10 -translate-x-6"> <!-- Tooltip extending below cursor --> <div class="absolute top-5 -left-1 bg-[rgba(10,10,12,0.95)] border border-[rgba(239,68,68,0.3)] shadow-[0_10px_30px_rgba(0,0,0,0.8)] rounded-lg px-3 py-2 w-[190px] text-left"> <div class="text-[11px] font-mono text-red-400 font-bold">Checkout Failure</div> </div> </div> </div> </div> </div> </div> <div class="lh-beat-node"><div class="lh-node-dot lh-node-dot--orange text-accent-orange"><svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg></div></div> <div class="lh-beat-right lh-beat-right--text"> <div class="lh-beat-title">Caught! Customers can checkout for free.</div> <div class="lh-beat-desc">Pie opened the app, ran the checkout flow, and caught the $0.00 bug. Code review missed it — the diff looked fine.</div> </div> </div> <!-- ═══ BEAT 3: Fix PR ready — text left, card right ═══ --> <div class="lh-beat" data-reveal> <div class="lh-beat-left"> <div class="lh-beat-title">Minutes later, the fix is ready.</div> <div class="lh-beat-desc">Pie traced the bug, wrote the patch, and opened a PR. Your team reviews and merges.</div> </div> <div class="lh-beat-node"><div class="lh-node-dot lh-node-dot--green text-accent-success"><svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg></div></div> <div class="lh-beat-right"> <div class="lh-card lh-glow-hover bg-[#0a0a0b]"> <div class="p-5"> <div class="flex items-center gap-1.5 text-[12.5px] font-semibold text-accent-success mb-3"> <div class="w-5 h-5 rounded-full bg-[rgba(34,197,94,0.1)] flex items-center justify-center"> <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M20 6L9 17l-5-5"></path></svg> </div>
Fix verified
</div> <div class="font-display text-[17px] font-semibold text-text-primary tracking-[-0.01em] mb-1.5">fix: checkout total shows $0.00 after discount</div> <div class="flex items-center gap-1.5 text-[11.5px] text-text-muted mb-4"> <div class="w-4 h-4 rounded-full bg-[linear-gradient(135deg,#8B5CF6,#D946EF)] flex items-center justify-center text-[8px] text-white font-bold">P</div>
pie-bot
</div> <!-- Before / After --> <div class="grid grid-cols-2 gap-2 mb-4"> <div class="lh-ba-panel lh-ba-panel--before"> <div class="lh-ba-label">Before</div> <div class="lh-ba-val">$0.00</div> </div> <div class="lh-ba-panel lh-ba-panel--after"> <div class="lh-ba-label">After</div> <div class="lh-ba-val">$49.99</div> </div> </div> <div class="flex items-center gap-3.5 pt-3 border-t border-[rgba(255,255,255,0.08)] text-[11.5px] font-medium"> <span class="flex items-center gap-1 text-accent-success"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M20 6L9 17l-5-5"></path></svg> CI passed</span> <span class="flex items-center gap-1 text-accent-success"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M20 6L9 17l-5-5"></path></svg> No conflicts</span> <span class="flex items-center gap-1 text-accent-success"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M20 6L9 17l-5-5"></path></svg> Ready to merge</span> </div> </div> </div> </div> </div> </div> </div> </section> <section class="max-w-[1120px] mx-auto px-5 lg:px-8 py-[120px] border-t border-[rgba(255,255,255,0.05)]" data-reveal> <div class="text-center mb-16"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-4">Features</div> <h2 class="font-display font-bold text-4xl md:text-5xl text-text-primary tracking-tight">
What Pie catches <span class="text-gradient">for you</span> </h2> </div> <div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6" data-reveal-stagger> <div class="lh-bento-card lh-glow-hover p-6"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-3">Autofix</div> <h3 class="font-display font-semibold text-lg text-text-primary mb-2">Get PRs, not tickets</h3> <p class="font-body text-sm text-text-secondary leading-relaxed">When Pie finds a bug, it opens a pull request with the fix. Root cause analysis included. Review, approve, ship.</p> </div><div class="lh-bento-card lh-glow-hover p-6"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-3">PR Gate</div> <h3 class="font-display font-semibold text-lg text-text-primary mb-2">One feed for every PR</h3> <p class="font-body text-sm text-text-secondary leading-relaxed">Findings, severity levels, and direct links to the code. Know what shipped and what broke before your users do.</p> </div><div class="lh-bento-card lh-glow-hover p-6"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-3">Coverage Loop</div> <h3 class="font-display font-semibold text-lg text-text-primary mb-2">See exactly what Pie tested</h3> <p class="font-body text-sm text-text-secondary leading-relaxed">Screenshots at every step. Pass/fail status for each flow. Who owns the branch, what changed, where it broke.</p> </div><div class="lh-bento-card lh-glow-hover p-6"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-3">Auto-Tracking</div> <h3 class="font-display font-semibold text-lg text-text-primary mb-2">Connect once, test every commit</h3> <p class="font-body text-sm text-text-secondary leading-relaxed">Link your GitHub repo. Pie watches for changes and identifies affected flows automatically.</p> </div><div class="lh-bento-card lh-glow-hover p-6"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-3">Vision-Based Testing</div> <h3 class="font-display font-semibold text-lg text-text-primary mb-2">AI that uses your product</h3> <p class="font-body text-sm text-text-secondary leading-relaxed">Not DOM selectors. Pie sees your app the way a real user does. Catches what scripted tests miss.</p> </div><div class="lh-bento-card lh-glow-hover p-6"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-3">Test Generation</div> <h3 class="font-display font-semibold text-lg text-text-primary mb-2">Tests that write themselves</h3> <p class="font-body text-sm text-text-secondary leading-relaxed">Pie generates test cases from the PRs it discovers. Coverage grows as your product evolves.</p> </div> </div> </section> <section class="max-w-[1120px] mx-auto px-5 lg:px-8 py-[120px] border-t border-[rgba(255,255,255,0.05)]" data-reveal> <div class="text-center mb-16"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-4">Zero friction</div> <h2 class="font-display font-bold text-4xl md:text-5xl text-text-primary tracking-tight">
Built for <span class="text-gradient">engineering teams</span> </h2> </div> <div class="grid md:grid-cols-3 gap-6 mb-16" data-reveal-stagger> <!-- Card 1: No scripts --> <div class="lh-bento-card p-6 text-center"> <div class="w-14 h-14 rounded-xl bg-accent-violet/10 border border-accent-violet/20 flex items-center justify-center mx-auto mb-5"> <svg class="w-6 h-6 text-accent-violet" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24"> <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path> </svg> </div> <h3 class="font-display font-semibold text-lg text-text-primary mb-2">No scripts to maintain</h3> <p class="font-body text-sm text-text-secondary leading-relaxed">Pie generates and adapts tests automatically. When your UI changes, your tests don't break.</p> </div> <!-- Card 2: No noise --> <div class="lh-bento-card p-6 text-center"> <div class="w-14 h-14 rounded-xl bg-accent-violet/10 border border-accent-violet/20 flex items-center justify-center mx-auto mb-5"> <svg class="w-6 h-6 text-accent-violet" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24"> <path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path> <line x1="12" y1="2" x2="12" y2="12"></line> </svg> </div> <h3 class="font-display font-semibold text-lg text-text-primary mb-2">No noise to filter</h3> <p class="font-body text-sm text-text-secondary leading-relaxed">Only real bugs. No flaky tests, no false positives. When Pie reports something, it's worth your attention.</p> </div> <!-- Card 3: No context switching --> <div class="lh-bento-card p-6 text-center"> <div class="w-14 h-14 rounded-xl bg-accent-violet/10 border border-accent-violet/20 flex items-center justify-center mx-auto mb-5"> <svg class="w-6 h-6 text-accent-violet" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> <line x1="9" y1="3" x2="9" y2="21"></line> </svg> </div> <h3 class="font-display font-semibold text-lg text-text-primary mb-2">No context switching</h3> <p class="font-body text-sm text-text-secondary leading-relaxed">Results show up as PRs in your existing workflow. Review, merge, move on. No dashboard to learn.</p> </div> </div> <!-- Quote block --> <div class="max-w-[800px] mx-auto"> <div class="lh-bento-card p-8 border-l-[3px] border-l-accent-violet relative overflow-hidden"> <div class="absolute top-0 right-0 p-6 text-accent-violet opacity-10"> <svg width="60" height="60" viewBox="0 0 24 24" fill="currentColor"><path d="M14.017 21v-7.391c0-5.704 3.731-9.57 8.983-10.609l.995 2.151c-2.432.917-3.995 3.638-3.995 5.849h4v10h-9.983zm-14.017 0v-7.391c0-5.704 3.748-9.57 9-10.609l.996 2.151c-2.433.917-3.996 3.638-3.996 5.849h3.983v10h-9.983z"></path></svg> </div> <div class="font-display font-medium text-lg text-text-primary italic leading-[1.6] mb-6 relative z-10 max-w-2xl">
"It's like having a QA team that never sleeps, never complains, and actually writes the fixes."
</div> <div class="font-mono text-xs text-text-muted">
— VP Engineering, Series B Startup
</div> </div> </div> </section> <section class="w-full bg-[rgba(255,255,255,0.01)] border-y border-[rgba(255,255,255,0.05)] py-16" data-reveal> <div class="max-w-[1120px] mx-auto px-5 lg:px-8 text-center"> <h2 class="font-display font-bold text-4xl md:text-5xl text-text-primary mb-12 tracking-tight">
Works with the tools <span class="text-gradient">your team already uses</span> </h2> <div class="flex flex-wrap items-center justify-center gap-x-14 gap-y-8"> <div class="flex items-center gap-3 text-text-muted hover:text-text-primary transition-colors font-bold text-[18px]"> <svg class="w-6 h-6" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"></path> </svg> GitHub
</div> <div class="flex items-center gap-3 text-text-muted hover:text-[#FC6D26] transition-colors font-bold text-[18px]"> <svg class="w-6 h-6" viewBox="0 0 24 24" fill="currentColor"> <path d="m23.6 9.593-.033-.086L20.3.98a.851.851 0 0 0-.336-.405.879.879 0 0 0-1.002.07.866.866 0 0 0-.286.406l-2.209 6.76H7.533L5.324 1.051a.857.857 0 0 0-.286-.408.878.878 0 0 0-1.003-.07.858.858 0 0 0-.335.406L.433 9.507l-.032.086a6.066 6.066 0 0 0 2.012 7.01l.011.008.027.02 4.987 3.734 2.468 1.867 1.503 1.136a1.012 1.012 0 0 0 1.222 0l1.503-1.136 2.468-1.867 5.014-3.754.012-.01a6.07 6.07 0 0 0 2.01-7.008z"></path> </svg> GitLab
</div> <div class="flex items-center gap-3 text-text-muted hover:text-text-primary transition-colors font-bold text-[18px]"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path> </svg> Web, iOS, Android
</div> <div class="flex items-center gap-3 text-text-muted hover:text-text-primary transition-colors font-bold text-[18px]"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path> </svg> Your CI/CD
</div> <div class="flex items-center gap-3 text-text-muted hover:text-text-primary transition-colors font-bold text-[18px] slack-logo"> <svg class="w-6 h-6" viewBox="0 0 24 24"> <path class="slack-red" fill="currentColor" d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zM6.313 15.165a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313z"></path> <path class="slack-blue" fill="currentColor" d="M8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zM8.834 6.313a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312z"></path> <path class="slack-green" fill="currentColor" d="M18.956 8.834a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zM17.688 8.834a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312z"></path> <path class="slack-yellow" fill="currentColor" d="M15.165 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zM15.165 17.688a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z"></path> </svg> Slack
</div> </div> </div> </section> <section class="max-w-[1120px] mx-auto px-5 lg:px-8 py-[120px] border-t border-[rgba(255,255,255,0.05)]" data-reveal> <div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center"> <!-- Left: headline + body --> <div> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-4">Build vs Buy</div> <h2 class="font-display font-bold text-4xl md:text-5xl text-text-primary tracking-tight mb-6">
You've probably tried building this yourself
</h2> <div class="font-body text-lg text-text-secondary leading-[1.7] space-y-5"> <p>Most teams duct-tape together Codex agents, PR bots, and overnight scripts — and it works, for a while. Pie is what that setup looks like when someone builds it as a product.</p> </div> </div> <!-- Right: quote card --> <div class="lh-bento-card p-8 border-l-[3px] border-l-accent-violet relative overflow-hidden"> <div class="absolute top-0 right-0 p-6 text-accent-violet opacity-10"> <svg width="60" height="60" viewBox="0 0 24 24" fill="currentColor"><path d="M14.017 21v-7.391c0-5.704 3.731-9.57 8.983-10.609l.995 2.151c-2.432.917-3.995 3.638-3.995 5.849h4v10h-9.983zm-14.017 0v-7.391c0-5.704 3.748-9.57 9-10.609l.996 2.151c-2.433.917-3.996 3.638-3.996 5.849h3.983v10h-9.983z"></path></svg> </div> <div class="font-display font-medium text-lg text-text-primary italic leading-[1.6] mb-6 relative z-10">
"I've basically been doing that same workflow on my own, and it would be nice to not have to develop that. That seems like something that's not a core value of our company."
</div> <div class="font-mono text-xs text-text-muted">
— VP Engineering, 1000+ person engineering org
</div> </div> </div> </section> <section class="max-w-[1120px] mx-auto px-5 lg:px-8 py-[120px] border-t border-[rgba(255,255,255,0.05)]" data-reveal> <div class="text-center mb-16"> <div class="font-mono text-xs font-bold text-accent-violet tracking-[0.1em] uppercase mb-4">What teams are saying</div> <h2 class="font-display font-bold text-4xl md:text-5xl text-text-primary tracking-tight">
Real results from <span class="text-gradient">real teams</span> </h2> </div> <div class="grid md:grid-cols-3 gap-6" data-reveal-stagger> <div class="lh-bento-card lh-glow-hover p-6 flex flex-col justify-between"> <div> <!-- Stars --> <div class="flex items-center gap-1 mb-4"> <svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg> </div> <!-- Quote --> <p class="font-body text-[15px] text-text-secondary italic leading-relaxed mb-6">An iOS-only crash that happened after three specific steps? Our QA team never would have caught that. Pie found it on the first scan.</p> </div> <!-- Attribution --> <div class="pt-4 border-t border-[rgba(255,255,255,0.06)]"> <span class="font-mono text-xs text-text-muted">— Mobile QA Lead, Consumer Tech Startup</span> </div> </div><div class="lh-bento-card lh-glow-hover p-6 flex flex-col justify-between"> <div> <!-- Stars --> <div class="flex items-center gap-1 mb-4"> <svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg> </div> <!-- Quote --> <p class="font-body text-[15px] text-text-secondary italic leading-relaxed mb-6">We used to find regressions a week after they shipped. Now we catch them before the PR even merges. It changed how we think about testing.</p> </div> <!-- Attribution --> <div class="pt-4 border-t border-[rgba(255,255,255,0.06)]"> <span class="font-mono text-xs text-text-muted">— Engineering Manager, Series A Fintech</span> </div> </div><div class="lh-bento-card lh-glow-hover p-6 flex flex-col justify-between"> <div> <!-- Stars --> <div class="flex items-center gap-1 mb-4"> <svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg><svg class="w-4 h-4 text-accent-violet" fill="currentColor" viewBox="0 0 24 24"> <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> </svg> </div> <!-- Quote --> <p class="font-body text-[15px] text-text-secondary italic leading-relaxed mb-6">The autofix feature is honestly what sold us. Finding bugs is one thing. Getting a PR with the fix already written? That&#39;s next level.</p> </div> <!-- Attribution --> <div class="pt-4 border-t border-[rgba(255,255,255,0.06)]"> <span class="font-mono text-xs text-text-muted">— Senior Engineer, E-commerce Platform</span> </div> </div> </div> </section> <section id="cta" class="text-center py-[140px] relative" data-reveal> <div class="absolute inset-0 bg-[radial-gradient(circle_at_center,rgba(139,92,246,0.04)_0%,transparent_60%)] pointer-events-none -z-10"></div> <div class="max-w-[720px] mx-auto px-5"> <h2 class="font-display font-bold text-4xl md:text-5xl lg:text-[clamp(44px,6vw,60px)] text-text-primary tracking-tighter leading-[1.05] mb-12">
Your team pushes code.<br><span class="text-gradient">Pie makes sure it actually works.</span> </h2> <a href="https://app.pie.inc/start" target="_blank" class="btn-primary inline-flex mb-6"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-[18px] h-[18px]"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
Try it for free <span class="arrow-wrapper"><span class="arrow"></span></span> </a> <p class="font-body text-sm text-text-muted leading-[1.6] max-w-md mx-auto">
Connect GitHub or GitLab and see results on your actual codebase. It's free, there's no demo to sit through, and nobody's going to call you.
</p> </div> </section> <section class="max-w-[720px] mx-auto px-5 lg:px-8 py-[120px] border-t border-[rgba(255,255,255,0.05)]" data-reveal> <div class="text-center mb-12"> <h2 class="font-display font-bold text-4xl md:text-5xl text-text-primary tracking-tight">
Frequently Asked <span class="text-gradient">Questions</span> </h2> </div> <div class="space-y-0"> <div class="faq-item"> <button class="faq-question"> <span>How is Pie different from code review tools like CodeRabbit or Greptile?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">Code review tools analyze your code. Pie tests your running product. CodeRabbit can tell you if your checkout function looks correct. Pie actually clicks &quot;Buy Now&quot; on staging and confirms the payment goes through. They read diffs. We use the app.</p> </div> </div><div class="faq-item"> <button class="faq-question"> <span>What does &quot;2-click install&quot; actually mean?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">You authorize Pie on GitHub, pick a repo, and paste your staging URL. That&#39;s it. No SDK, no test scripts, no config files. Pie figures out your user flows automatically by exploring your app.</p> </div> </div><div class="faq-item"> <button class="faq-question"> <span>How does Pie know what to test?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">Pie reads your commit diffs to understand what changed, then maps that to the user flows it discovered when it first explored your app. If your payment form changed, Pie tests checkout. If you touched the nav, it tests cross-page navigation. It&#39;s not random.</p> </div> </div><div class="faq-item"> <button class="faq-question"> <span>Does Pie work with mobile apps?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">Yes. Pie tests iOS and Android apps in simulators, not just web. Same 2-click setup. Same autofix PRs. Mobile-specific bugs like gesture failures, deep link issues, and in-app purchase flows are all covered.</p> </div> </div><div class="faq-item"> <button class="faq-question"> <span>What about false positives?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">Pie only reports bugs it can reproduce. Every finding includes a step-by-step recording of how to trigger it. If Pie reports it, it&#39;s real. No flaky tests, no &quot;works on my machine&quot; arguments.</p> </div> </div><div class="faq-item"> <button class="faq-question"> <span>How does the autofix feature work?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">When Pie finds a bug, it doesn&#39;t just log it. It traces the issue back to the source code, identifies the likely root cause, and opens a PR with a suggested fix. You review and merge, or reject if it&#39;s wrong. Most fixes merge without changes.</p> </div> </div><div class="faq-item"> <button class="faq-question"> <span>Is my code safe? Where does it go?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">Pie runs on secure, isolated infrastructure. Your code never leaves your repo, we only read the diffs. Your staging environment is accessed the same way your CI does. We&#39;re SOC 2 compliant. Reach out and we&#39;ll share the documentation.</p> </div> </div><div class="faq-item"> <button class="faq-question"> <span>What if I already have Playwright or Cypress tests?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">You can run both, or let Pie take over entirely. Pie can analyze your existing test cases and rebuild them using AI, with zero ongoing maintenance. Most teams that migrate see better coverage and stop dealing with flaky tests. We&#39;ll help with the transition.</p> </div> </div><div class="faq-item"> <button class="faq-question"> <span>What does it cost?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">Your first scan is free, no credit card required. After that, pricing scales with your usage. We offer packages for teams of all sizes. Reach out and we&#39;ll put together a quote.</p> </div> </div><div class="faq-item"> <button class="faq-question"> <span>Can I self-host Pie?</span> <svg class="faq-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path> </svg> </button> <div class="faq-answer"> <p class="font-body text-text-secondary">Not currently. Pie runs as a managed service. For teams with strict data residency requirements, reach out and we&#39;ll discuss options.</p> </div> </div> </div> </section> </div>  <!-- ========================================
       FOOTER
       ======================================== --> <footer class="relative py-16 border-t border-canvas-subtle"> <div class="max-w-1080 mx-auto px-6 md:px-16 lg:px-6"> <div class="grid md:grid-cols-5 gap-12 mb-12"> <!-- Brand --> <div class="md:col-span-1"> <a href="/" class="flex items-center gap-2 mb-4"> <img src="/pielogo.avif" alt="Pie" class="h-8 w-auto"> </a> <p class="font-body text-sm text-text-secondary mb-4">
The quality layer for AI-speed engineering.
</p> <!-- SOC 2 Badge --> <div class="inline-flex items-center gap-2 px-3 py-2 rounded-lg bg-canvas-elevated border border-canvas-subtle"> <svg class="w-4 h-4 text-accent-success" fill="currentColor" viewBox="0 0 20 20"> <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path> </svg> <span class="font-body text-xs text-text-secondary">SOC 2&reg; Certified</span> </div> </div> <!-- Product --> <div> <h4 class="font-display font-semibold text-sm text-text-primary mb-4">Product</h4> <ul class="space-y-3"> <li><a href="/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Home</a></li> <li><a href="/product/pie-qa/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Pie QA</a></li> <li><a href="/product/overview/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Product Overview</a></li> <li><a href="/product/how-it-works/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">How Pie Works</a></li> <li><a href="/product/autonomous-discovery/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Autonomous Discovery</a></li> <li><a href="/product/self-healing-tests/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Self-Healing Tests</a></li> <li><a href="/product/integrations/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Integrations</a></li> <li><a href="/product/custom-tests/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Custom Tests</a></li> <li><a href="/product/security/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Security</a></li> </ul> </div> <!-- Resources --> <div> <h4 class="font-display font-semibold text-sm text-text-primary mb-4">Resources</h4> <ul class="space-y-3"> <li><a href="https://docs.pie.inc/" target="_blank" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Docs</a></li> <li><a href="/blog/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Blog</a></li> <li><a href="/customers/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Case Studies</a></li> <li><a href="/resources/whitepapers/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Whitepapers</a></li> </ul> </div> <!-- Company --> <div> <h4 class="font-display font-semibold text-sm text-text-primary mb-4">Company</h4> <ul class="space-y-3"> <li><a href="https://www.linkedin.com/company/pielabs-inc/jobs/" target="_blank" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Work with us</a></li> <li><a href="https://www.linkedin.com/company/pielabs-inc/" target="_blank" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">LinkedIn</a></li> </ul> </div> <!-- Legal --> <div> <h4 class="font-display font-semibold text-sm text-text-primary mb-4">Legal</h4> <ul class="space-y-3"> <li><a href="/privacy-policy/" class="font-body text-sm text-text-secondary hover:text-text-primary transition-colors">Privacy Policy</a></li> </ul> </div> </div> <!-- Copyright --> <div class="pt-8 border-t border-canvas-subtle"> <p class="font-body text-sm text-text-muted text-center">
PieLabs, Inc. &copy; 2026. All rights reserved.
</p> </div> </div> </footer> <!-- ========================================
       JAVASCRIPT
       ======================================== --> <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js" defer></script><script src="/main.js"></script> </body> </html> <script type="module">const r=new IntersectionObserver(e=>{e.forEach(t=>{t.isIntersecting&&(t.target.classList.add("visible"),r.unobserve(t.target))})},{threshold:.15});document.querySelectorAll("[data-reveal], [data-reveal-stagger]").forEach(e=>{r.observe(e)});document.querySelectorAll(".lh-glow-hover").forEach(e=>{e.addEventListener("mousemove",t=>{const o=e.getBoundingClientRect(),s=t.clientX-o.left,c=t.clientY-o.top;e.style.setProperty("--mouse-x",`${s}px`),e.style.setProperty("--mouse-y",`${c}px`)})});</script>