<!DOCTYPE html><!--  Last Published: Tue Aug 12 2025 15:37:39 GMT+0000 (Coordinated Universal Time)  -->
<html data-wf-page="6706b215cbf25cb04500fe9a" data-wf-site="64cda65753e0c5bc9d9a6566">
<head>
  <meta charset="utf-8">
  <title>Not Found</title>
  <meta content="Not Found" property="og:title">
  <meta content="Not Found" property="twitter:title">
  <meta content="width=device-width, initial-scale=1" name="viewport">
  <link href="css/normalize.css" rel="stylesheet" type="text/css">
  <link href="css/webflow.css" rel="stylesheet" type="text/css">
  <link href="css/my-five-star-site-c8404f.webflow.css" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com" rel="preconnect">
  <link href="https://fonts.gstatic.com" rel="preconnect" crossorigin="anonymous">
  <script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js" type="text/javascript"></script>
  <script type="text/javascript">WebFont.load({  google: {    families: ["Roboto Mono:300,700"]  }});</script>
  <script type="text/javascript">!function(o,c){var n=c.documentElement,t=" w-mod-";n.className+=t+"js",("ontouchstart"in o||o.DocumentTouch&&c instanceof DocumentTouch)&&(n.className+=t+"touch")}(window,document);</script>
  <link href="images/favicon.png" rel="shortcut icon" type="image/x-icon">
  <link href="images/webclip.png" rel="apple-touch-icon">
  <script async="" src="https://www.googletagmanager.com/gtag/js?id=G-JYYRBD77KL"></script>
  <script type="text/javascript">window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('set', 'developer_id.dZGVlNj', true);gtag('config', 'G-JYYRBD77KL');</script>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
html {
  	width:100vw;
    overflow-x:hidden;
  }
  label {
  	font-weight: normal;
  }
  @media screen and (max-width: 769px) {
     .nav-menu .small-link-text {
	 	text-decoration: none!important;
    }
  }
  @media screen and (max-width: 992px) {
     .nav-menu .small-link-text {
	 	color: var(--base-overlap-screen)!important;
    }
  }
  .w-input, .w-select {
    color: var(--base-overlap-screen);
    background-color: var(--base-green-3);
    border: none;
    height: auto;
    margin-bottom: 0;
    font-size: 1.2vw;
    line-height: 1.6;
  }
  @media screen and (min-width: 1280px) {
    .w-input, .w-select {
      font-size: 1vw;
    }
  }
  @media screen and (max-width: 991px) {
    .w-input, .w-select {
      font-size: 15px;
    }
  }
  .w-input, 
  .w-select,
  .w-button {
    padding: 1vw;
  }
  @media screen and (max-width: 991px) {
  	.w-input,
    .w-select,
  	.w-button {
      padding: 16px 24px;
  	}
  }
  .media-controls-container,
  video::-webkit-media-controls {
    display: none !important;
  }
.word {
    white-space: nowrap;
    overflow: clip;
  	display: inline-block;
  }
  .letter {
    display: inline-block;
    -webkit-transform: translateY(100%);
    -moz-transform: translateY(100%);
    -ms-transform: translateY(100%);
    -o-transform: translateY(100%);
    transform: translateY(100%);
  }
  .letter.has-transitioned {
    -webkit-animation: text_fade_in .25s ease-in;
    -moz-animation: text_fade_in .25s ease-in;
    -o-animation: text_fade_in .25s ease-in;
    animation: text_fade_in .25s ease-in;
    -webkit-transform: translateY(0%);
    -moz-transform: translateY(0%);
    -ms-transform: translateY(0%);
    -o-transform: translateY(0%);
    transform: translateY(0%);
  }
  .letter.transitioning-out {
    -webkit-animation: text_fade_out .25s ease-in;
    -moz-animation: text_fade_out .25s ease-in;
    -o-animation: text_fade_out .25s ease-in;
    animation: text_fade_out .25s ease-in;
    -webkit-transform: translateY(-100%);
    -moz-transform: translateY(-100%);
    -ms-transform: translateY(-100%);
    -o-transform: translateY(-100%);
    transform: translateY(-100%);
  }
  .link .letter {
  	text-decoration: underline;
  }
  @media screen and (max-width: 991px) {
    .large-case-centered-title .letter.fast-fade {
      transform: none!important;
      transition: none!important;
    }
  }
  @keyframes text_fade_in {
    0% {
      -webkit-transform: translateY(100%);
      -moz-transform: translateY(100%);
      -o-transform: translateY(100%);
      transform: translateY(100%);
    }
    100% {
      -webkit-transform: translateY(0%);
      -moz-transform: translateY(0%);
      -o-transform: translateY(0%);
      transform: translateY(0%);
    }
  }
   @keyframes text_fade_out {
      0% {
        transform: translateY(0%);
      }
      100% {
        transform: translateY(-100%);
      }
    }
    /* New class for slower animation */
    .letter.slow-fade.has-transitioned {
      animation: text_fade_in_slow .6s ease-in;
    }
    @keyframes text_fade_in_slow {
      0% {
        transform: translateY(100%);
      }
      100% {
        transform: translateY(0%);
      }
    }
  .footer-pills .case-pill {
  	background: rgba(254, 251, 249, 0.05);
    color:var(--base-overlap-screen);
  }
body .transition {display: block}
.w-editor .transition {display: none;}
.no-scroll-transition {overflow: hidden; position: relative;}
</style>
</head>
<body class="_404-page">
  <div class="transition">
    <div class="transition-content"><img src="images/drive-home-logo-vertical.svg" loading="lazy" alt="" class="transition-logo"></div>
    <div data-w-id="c9a371b1-0d3e-6de0-a4d4-3e6ba6787a74" class="transition-trigger"></div>
  </div>
  <div class="flex-row-centered">
    <div class="_404-animation" data-w-id="838f88b5-fb19-aa4b-a626-5727bb8394bb" data-animation-type="lottie" data-src="documents/dh-404-animation.json" data-loop="1" data-direction="-1" data-autoplay="1" data-is-ix2-target="0" data-renderer="svg" data-default-duration="0" data-duration="2"></div>
    <h1>Page Not Found</h1>
    <p class="centered-paragraph">The page you are looking for doesn&#x27;t exist or has been moved</p>
    <div data-w-id="55f62da5-f99b-4a56-3187-f871d305efcb" class="elevated-text-container fit-content">
      <div class="background-shade base-green"></div>
      <a href="index.html" class="elevated-block flex-container-1-5vla top-layer from-light primary-cta small-cta w-inline-block">
        <h3 class="button-text page-top no-padding">Go to the homepage</h3>
      </a>
    </div>
  </div>
  <script src="https://d3e54v103j8qbb.cloudfront.net/js/jquery-3.5.1.min.dc5e7f18c8.js?site=64cda65753e0c5bc9d9a6566" type="text/javascript" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
  <script src="js/webflow.js" type="text/javascript"></script>
  <script>
//prevent page scaling when rotating device, along with meta viewport
    if (/(iPad|iPhone|iPod)/g.test(navigator.userAgent) && window.addEventListener && document.querySelector) {
        window.addEventListener('orientationchange', rotateWithNoScale, false);
    }
    function rotateWithNoScale() {
        var viewport = document.querySelector("meta[name=viewport]");
        if (viewport) {
            var content = viewport.getAttribute("content");
            viewport.setAttribute("content", content + ", maximum-scale=1.0");
            setTimeout(function () { viewport.setAttribute("content", content); }, 90);
        }
    }
</script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
  <script>
  //function to load pages
// Variables for elements and transition settings
let transitionTrigger = document.querySelector(".transition-trigger");
let introDurationMS = 0;
let exitDurationMS = 1200;
let excludedClass = "no-transition";
// On Page Load
if (transitionTrigger) {
  // Temporarily add a class to disable scroll transitions on the body
  document.body.classList.add("no-scroll-transition");
  // Remove the no-scroll-transition class after the intro duration
  setTimeout(() => {
    document.body.classList.remove("no-scroll-transition");
  // Trigger the transition when the page loads if a trigger exists
   setTimeout(function() {transitionTrigger.click()}, 50); 
  }, introDurationMS);
}
// On Link Click
document.querySelectorAll("a").forEach(link => {
  link.addEventListener("click", function (e) {
    // Check if the clicked link is internal (same domain), doesn't contain a hash (#),
    // doesn't have the excluded class, and isn't set to open in a new tab
    if (this.hostname === window.location.hostname && (!document.querySelector('.home-top') || this.getAttribute("href").indexOf("#") === -1) && !this.classList.contains(excludedClass) && this.getAttribute("target") !== "_blank" && transitionTrigger) {
      // Prevent the default link behavior
      e.preventDefault();
      // Temporarily disable scroll transitions
      document.body.classList.add("no-scroll-transition");
      // Store the link's URL to redirect after the transition
      let transitionURL = this.getAttribute("href");
      // Trigger the transition
      transitionTrigger.click();
      // Redirect to the new URL after the exit transition duration
      setTimeout(() => {
        window.location = transitionURL;
      }, exitDurationMS);
    }
  });
});
// On Back Button Tap
window.onpageshow = function (event) {
  // If the page was restored from the cache (e.g., using the back button), reload the page
  if (event.persisted) {
    window.location.reload();
  }
};
// Hide Transition on Window Width Resize
setTimeout(() => {
  window.addEventListener("resize", function () {
    // After resizing the window, hide the transition element after a brief delay
    setTimeout(() => {
      let transitionElement = document.querySelector(".transition");
      if (transitionElement) {
        transitionElement.style.display = "none";
      }
    }, 50); // Delay to ensure smooth transition hide
  });
}, introDurationMS);
</script>
  <script>
  // =============================
  // 🔄 Cycle Words, Animate Text
  // =============================
  // Global variables to store timeouts, ensuring smooth transitions - ANY TIMEOUT THAT IS NOT TRACKED HERE WILL BE UNSTOPPABLE - these variables need to all be passed into the home's local function
  var initloadTimeout, fadeOutTimeout, firstFadeOutTimeout, cycleTimeout, letterTimeout, animationTimeout;
  var cyclePaused = false; // ✅ Track if cycling is paused
    var dynamicSentences = [
      "build trust with users",
      "increase customer retention",
      "simplify complex workflows",
      "drive engagement with data"
    ];
  /**
   * Function to cycle through an array of words dynamically.
   * This function animates words, ensuring they fade in and out smoothly.
   * @param {number|null} forcedIndex - If specified, starts from a given index.
   */
  function cycleWords(forcedIndex = null) {
    // Determine the current index to use, 0 if forcedIndex is null
    var currentIndex = forcedIndex !== null ? forcedIndex : 0;
    var dynamicWordElement = document.getElementById('dynamicWord');
    var wordChangeDelay = 4000; // Time between word changes
    var firstTransition = true; // Flag to handle the first transition correctly
    // Ensure the target element exists before proceeding
    if (!dynamicWordElement) {
      console.warn("⚠️ No dynamicWord element found! Check if the element exists in the DOM.");
      return;
    }
    /**
     * Inserts the new word into the target element, wrapping each letter with a span.
     */
    function applyNewWord() {
      if (cyclePaused) return; // ✅ Stop execution if paused
      dynamicWordElement.innerHTML = dynamicSentences[currentIndex].replace(/\S/g, "<span class='letter'>$&</span>");
    }
    applyNewWord(); // Initial insertion of the word
    /**
     * Handles the fade-out animation for the current word before switching.
     */
    function animateWordChange(jumpToIndex) {
      if (cyclePaused) return; // ✅ Do nothing if paused
      if (jumpToIndex === undefined) {
        currentIndex;
      } else {
        currentIndex = jumpToIndex - 1;
        if (currentIndex < 0) {
          currentIndex = 3
        }
      }
      var letters = dynamicWordElement.querySelectorAll('.letter');
      if (!firstTransition) {
        // Animate each letter fading out with staggered timing
        letters.forEach((letter, index) => {
          letterTimeout = setTimeout(() => {
            letter.classList.remove('has-transitioned')
            letter.classList.add('transitioning-out')
          }, index * 3);
        });
        fadeOutTimeout = setTimeout(changeWord, letters.length * 9);
      } 
      else {
          // On the first transition, immediately apply 'transitioning-out'
        firstFadeOutTimeout = setTimeout(() => {
          letters.forEach((letter, index) => {
            setTimeout(() => {
              letter.classList.add('transitioning-out'); 
            }, index * 3);
          });
        }, 5600);
        initloadTimeout = setTimeout(changeWord, 6000);
        firstTransition = false;
      }
    }
    /**
     * Changes the displayed word, applying a fade-in effect.
     */
    function changeWord() {
      if (cyclePaused) return;
      currentIndex = (currentIndex + 1) % dynamicSentences.length; // Cycle to the next word
      applyNewWord();
      var letters = dynamicWordElement.querySelectorAll('.letter');
      letters.forEach((letter, index) => {
        animationTimeout = setTimeout(() => {
          letter.classList.remove('transitioning-out')
          letter.classList.add('has-transitioned')
        }, index * 3);
      });
      cycleTimeout = setTimeout(animateWordChange, wordChangeDelay);
    }
    // Function to manually jump to a specific index from the progress bar
    window.jumpToSegment = function (index) {
      // Clear all active timeouts to prevent animation conflicts
      clearTimeout(initloadTimeout);
      clearTimeout(firstFadeOutTimeout);
      clearTimeout(fadeOutTimeout);
      clearTimeout(letterTimeout);
      clearTimeout(animationTimeout);
      clearTimeout(cycleTimeout);
      // Restart `cycleWords` at the given index
      animateWordChange(index)
    };
    /**
     * Pauses the cycling animation.
     */
    window.pauseCycleWords = function () {
      cyclePaused = true;
      clearTimeout(initloadTimeout);
      clearTimeout(firstFadeOutTimeout);
      clearTimeout(fadeOutTimeout);
      clearTimeout(letterTimeout);
      clearTimeout(animationTimeout);
    };
    /**
     * Resumes the cycling animation.
     */
    window.resumeCycleWords = function () {
      if (!cyclePaused) return;
      cyclePaused = false;
      clearTimeout(cycleTimeout);
      cycleTimeout = setTimeout(animateWordChange, 1000); //1000 here is an arbitrary time after hover is out of the pausing elements, not too long or to short to resume cycling
    };
    let animateTimeout = setTimeout(animateWordChange, 0);
  }
  // Start the cycling when the page loads
  window.addEventListener('load', function () {
    cycleWords();
  });
  // ✅ Event Listeners for Hover Pause (#2 and #3)
  document.querySelectorAll(".featured-case-links-container, .image-slider").forEach((element) => {
    element.addEventListener("mouseenter", () => {
      pauseCycleWords();
    });
    element.addEventListener("mouseleave", () => {
      resumeCycleWords();
    });
  });
  // =============================
  // 🔠 Break Words for Animation
  // =============================
  (function breakWords() {
    var elementsToBreak = document.querySelectorAll(".fade-text:not(#dynamicWord), .slow-fade:not(#dynamicWord), .fast-fade:not(#dynamicWord)");
    elementsToBreak.forEach((element, index) => {
      element.id = "word" + index;
      element.innerHTML = element.innerHTML.replace(/(^|<\/?[^>]+>|\s+)([^\s<]+)/g, '$1<span class="word">$2</span>');
    });
    var words = document.getElementsByClassName("word");
    for (var i = 0; i < words.length; i++) {
      var wordElement = words[i];
      wordElement.innerHTML = wordElement.textContent.replace(/\S/g, "<span class='letter'>$&</span>");
      if (wordElement.closest('.slow-fade')) {
        var letters = wordElement.querySelectorAll('.letter');
        letters.forEach((letter) => letter.classList.add('slow-fade'));
      } else if (wordElement.closest('.fast-fade')) {
        var letters = wordElement.querySelectorAll('.letter');
        letters.forEach((letter) => letter.classList.add('fast-fade'));
      }
    }
  })();
  // =============================
  // 🔄 Mutation Observer
  // =============================
  var mutatingElements = document.querySelectorAll('.fade-text');
  var disconnectedElements = new Set();
  function handleMutations(mutationsList, observer) {
    var timeIncrements = [],
        thisIncrement = 0;
    for (var mutation of mutationsList) {
      var targetStyle = window.getComputedStyle(mutation.target);
      if (mutation.type === 'attributes' && mutation.attributeName === 'style' && targetStyle.getPropertyValue("opacity") != "0") {
        var childrenLetters = mutation.target.querySelectorAll('.letter');
        var isSlowFade = mutation.target.closest('.slow-fade');
        var isFastFade = mutation.target.closest('.fast-fade');
        var staggerIncrement = isSlowFade ? 45 : isFastFade ? 3 : 15;
        childrenLetters.forEach((child, index) => {
          thisIncrement = thisIncrement + staggerIncrement;
          timeIncrements.push(thisIncrement);
          child.classList.remove('has-transitioned');
          setTimeout(() => {
            child.classList.add('has-transitioned');
          }, timeIncrements[index]);
        });
        mutatingElements.forEach((element) => {
          if (element && !disconnectedElements.has(element) && element !== mutation.target) {
            observer.observe(element, { attributes: true });
          }
        });
      }
    }
  }
  var observer = new MutationObserver(function (mutationsList) {
    handleMutations(mutationsList, observer);
  });
  mutatingElements.forEach((element) => {
    if (element && !disconnectedElements.has(element)) {
      observer.observe(element, { attributes: true });
    }
  });
</script>
  <script>
    // Function to handle video play/pause based on intersection
    function handleVideoIntersection(entries, observer) {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
            // Ensure video is muted and set to play inline
                entry.target.muted = true;
                entry.target.playsInline = true;
                //fallback
                entry.target.play().catch(error => {
                  entry.target.play();
              $('body').on('click touchstart', function () {
             	 entry.target.play();
            	});
     		 });
              entry.target.oncanplaythrough = (event) => {
                var promise = entry.target.play();
              };
            } else {
              entry.target.pause();
            }
        });
    }
    const videoObserver = new IntersectionObserver(handleVideoIntersection, {
        root: null,
        threshold: 0.5,
    });
    const videoElement = document.querySelectorAll('video');
    videoElement.forEach(function(item, i) {
      videoObserver.observe(item);
    });
</script>
  <script src="https://cdn.jsdelivr.net/gh/studio-freight/lenis@1.0.27/bundled/lenis.min.js"></script>
  <script>
  //smooth scroll
  const lenis = new Lenis();
  function raf(time) {
    lenis.raf(time)
    requestAnimationFrame(raf)
  }
  requestAnimationFrame(raf)
</script>
</body>
</html>
