Wayloom UI Template - Let's templates
Wayloom preview 1
Free
0 2

Wayloom

By Jonah Hale

Wayloom is a calm, editorial startup template for travel-tech and marketplace platforms, with an expanding image hero, impact stats, a four-step model and a team page.

Live Demo
wayloom-tailwind.html
<%# letstemplates: access=free category=startup %>
<!DOCTYPE html>
<html lang="en">
<head>
  <script>
    window.FontAwesomeConfig = { autoReplaceSvg: 'nest' };
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Wayloom | Tailwind CSS Startup Template</title>
  <meta name="description" content="Wayloom is a calm, editorial Tailwind CSS startup template for travel-tech and marketplace platforms, with an expanding image hero, impact stats, a four-step model and a team page.">
  <meta name="keywords" content="Wayloom, Tailwind CSS template, HTML website template, startup template, travel tech, experience marketplace, B2B platform, multi-page startup website">
  <meta name="author" content="Let's templates">
  <link rel="canonical" href="">

  <meta property="og:type" content="product">
  <meta property="og:site_name" content="Let's templates">
  <meta property="og:locale" content="en_US">
  <meta property="og:url" content="">
  <meta property="og:title" content="Wayloom | Tailwind CSS Startup Template">
  <meta property="og:description" content="A calm, editorial Tailwind CSS startup template for travel-tech and marketplace platforms, with an expanding image hero, impact stats, a four-step model and a team page.">
  <meta property="og:image" content="">
  <meta property="og:image:alt" content="Wayloom template preview">

  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:url" content="">
  <meta name="twitter:title" content="Wayloom | Tailwind CSS Startup Template">
  <meta name="twitter:description" content="A calm, editorial Tailwind CSS startup template for travel-tech and marketplace platforms, with an expanding image hero, impact stats, a four-step model and a team page.">
  <meta name="twitter:image" content="">
  <meta name="twitter:image:alt" content="Wayloom template preview">
  <script src="https://cdn.tailwindcss.com/3.4.17"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=Cormorant+Garamond:wght@500&display=swap" rel="stylesheet">
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            cream: '#f5f0e3',
            sand: '#e8e4d4',
            pine: '#1f5552',
            'pine-dark': '#163f3d'
          },
          fontFamily: {
            display: ['"Schibsted Grotesk"', 'ui-sans-serif', 'system-ui', 'sans-serif'],
            sans: ['Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'],
            serif: ['"Cormorant Garamond"', 'Georgia', 'serif']
          }
        }
      }
    };
  </script>
  <style>
    @view-transition { navigation: auto; }
    ::view-transition-old(root) { animation: 180ms ease-out both page-fade-out; }
    ::view-transition-new(root) { animation: 220ms ease-in both page-fade-in; }
    @keyframes page-fade-out { to { opacity: 0; } }
    @keyframes page-fade-in { from { opacity: 0; } }
    html { scroll-behavior: smooth; scroll-padding-top: 6rem; }
    [hidden] { display: none !important; }
    [data-panel] { flex: 1 1 0%; min-width: 0; }
    [data-panel][aria-expanded="true"] { flex: 5 1 0%; }
    [data-panel] [data-panel-body] { opacity: 0; transition: opacity .4s ease .1s; }
    [data-panel][aria-expanded="true"] [data-panel-body] { opacity: 1; }
    [data-panel][aria-expanded="true"] [data-panel-tall] { display: none; }
    [data-panel][aria-expanded="false"] [data-panel-body] { display: none; }
    .reveal-ready [data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity .6s ease, transform .6s ease; transition-delay: var(--reveal-delay, 0ms); }
    .reveal-ready [data-reveal].is-visible { opacity: 1; transform: none; }
    @media (prefers-reduced-motion: reduce) {
      html { scroll-behavior: auto; }
      [data-panel] [data-panel-body] { transition: none; }
      ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
    }
  </style>
</head>
<body class="bg-cream font-sans text-pine antialiased">
  <% active_page = "index" %>

  <!-- block:start navbar -->
  <header class="sticky top-0 z-40 bg-cream/95 backdrop-blur">
    <nav class="mx-auto flex max-w-[90rem] items-stretch justify-between border-b border-pine/15 px-6 lg:px-20">
      <a href="index.html" class="flex items-center gap-2 py-6 pr-10 font-display text-3xl font-bold tracking-tight text-pine lg:border-r lg:border-pine/15">
        <i class="fa-solid fa-cube text-2xl" aria-hidden="true"></i>
        Wayloom
      </a>
      <div class="hidden flex-1 items-center justify-center gap-2 xl:flex">
        <% { "index" => "Home", "problem" => "Problem", "solution" => "Solution", "model" => "Model", "platform" => "Platform", "about" => "About", "team" => "Team" }.each do |slug, label| %>
          <% active = active_page == slug %>
          <a href="<%= slug == "index" ? "index.html" : "#{slug}.html" %>" <%= 'aria-current="page"'.html_safe if active %> class="px-6 py-3 text-lg transition <%= active ? "bg-sand text-pine" : "text-pine-dark/80 hover:text-pine" %>"><%= label %></a>
        <% end %>
      </div>
      <div class="flex items-center gap-4 py-5 lg:border-l lg:border-pine/15 lg:pl-10">
        <a href="contact.html" class="hidden bg-pine px-8 py-4 font-display text-lg font-semibold text-cream transition hover:bg-pine-dark sm:inline-flex">Partner with us</a>
        <button type="button" id="menu-toggle" aria-expanded="false" aria-controls="mobile-menu" class="inline-flex h-12 w-12 items-center justify-center border border-pine/20 xl:hidden">
          <i class="fa-solid fa-bars" aria-hidden="true"></i>
          <span class="sr-only">Toggle menu</span>
        </button>
      </div>
    </nav>
    <div id="mobile-menu" hidden class="border-b border-pine/15 bg-cream px-6 pb-6 xl:hidden">
      <% { "index" => "Home", "problem" => "Problem", "solution" => "Solution", "model" => "Model", "platform" => "Platform", "about" => "About", "team" => "Team" }.each do |slug, label| %>
        <a href="<%= slug == "index" ? "index.html" : "#{slug}.html" %>" class="block border-b border-pine/10 py-3 text-lg <%= "font-semibold" if active_page == slug %>"><%= label %></a>
      <% end %>
      <a href="contact.html" class="mt-4 block bg-pine px-6 py-4 text-center font-display font-semibold text-cream">Partner with us</a>
    </div>
  </header>
  <!-- block:end navbar -->

  <!-- block:start hero -->
  <section id="hero" class="px-6 pb-16 pt-14 lg:px-20 lg:pt-24">
    <div class="mx-auto grid max-w-[90rem] items-start gap-12 lg:grid-cols-[1fr_1.05fr]">
      <div data-reveal>
        <span class="inline-flex rounded-full bg-sand px-6 py-2.5 text-lg">Gather. Shape. Share. Earn.</span>
        <h1 class="mt-8 font-display text-5xl font-semibold leading-[1.02] tracking-tight md:text-6xl xl:text-7xl">The worldwide supply layer for real local experiences</h1>
        <p class="mt-8 max-w-2xl text-xl leading-relaxed text-pine/90">Wayloom is the <strong class="font-semibold">connective tissue</strong> of the experience economy, linking local hosts and operators to global booking platforms, brands and travelers.</p>
        <div class="mt-10 flex flex-wrap gap-4">
          <a href="contact.html" class="bg-pine px-9 py-5 font-display text-lg font-semibold text-cream transition hover:bg-pine-dark">Partner with us</a>
          <a href="platform.html" class="border-2 border-pine px-9 py-[1.125rem] font-display text-lg font-semibold transition hover:bg-pine hover:text-cream">Browse supply integrations</a>
        </div>
      </div>
      <div data-reveal style="--reveal-delay:120ms" class="flex h-[30rem] gap-3 sm:h-[36rem] sm:gap-5" role="tablist" aria-label="Featured experiences">
        <% [
          { image: "1775644672234-cfaadb6919a3", alt: "Two travelers reading a map beside an old stone archway", copy: "Hosts in <strong class=\"font-semibold\">140 cities</strong> list once on Wayloom and reach every major booking channel the same week." },
          { image: "1741272689174-f7f03b09a0ab", alt: "Dancer in traditional costume performing with musicians", copy: "Cultural performances, workshops and festivals get rich storytelling pages that <strong class=\"font-semibold\">convert lookers into guests</strong>." },
          { image: "1768154626896-44290a532fc7", alt: "Heritage palace reflected in a long courtyard pool", copy: "Heritage sites and guided tours sync live availability, so <strong class=\"font-semibold\">no slot is ever double-booked</strong>." }
        ].each_with_index do |panel, index| %>
          <div data-panel aria-expanded="<%= index.zero? %>" class="relative flex flex-col border-x border-pine/60 <%= "px-0" %>">
            <button type="button" role="tab" aria-selected="<%= index.zero? %>" aria-controls="panel-<%= index %>" data-panel-trigger class="absolute inset-0 z-10 <%= "pointer-events-none" if index.zero? %>">
              <span class="sr-only">Show experience <%= index + 1 %></span>
            </button>
            <div data-panel-tall class="h-full overflow-hidden">
              <img src="https://images.unsplash.com/photo-<%= panel[:image] %>?auto=format&fit=crop&w=400&h=1000&q=80" alt="<%= panel[:alt] %>" class="h-full w-full object-cover grayscale">
            </div>
            <div id="panel-<%= index %>" data-panel-body role="tabpanel" class="flex h-full flex-col px-3 sm:px-5">
              <div class="aspect-[3/2] overflow-hidden">
                <img src="https://images.unsplash.com/photo-<%= panel[:image] %>?auto=format&fit=crop&w=900&h=600&q=80" alt="<%= panel[:alt] %>" class="h-full w-full object-cover grayscale">
              </div>
              <p class="mt-8 text-lg leading-relaxed sm:text-xl"><%= panel[:copy].html_safe %></p>
            </div>
            <span class="absolute bottom-6 left-1/2 -translate-x-1/2 font-serif text-2xl <%= index.zero? ? "text-pine" : "text-white" %>" data-panel-number>0<%= index + 1 %></span>
          </div>
        <% end %>
      </div>
    </div>
  </section>
  <!-- block:end hero -->

  <!-- block:start stats -->
  <section id="impact" class="relative overflow-hidden px-6 pb-24 lg:px-20">
    <div class="pointer-events-none absolute left-20 top-36 hidden text-pine/40 lg:block" aria-hidden="true">
      <i class="fa-solid fa-leaf absolute left-10 top-10 -rotate-45 text-7xl"></i>
      <i class="fa-solid fa-leaf absolute left-28 top-0 rotate-12 text-6xl text-pine/30"></i>
      <i class="fa-solid fa-seedling absolute left-0 top-32 text-8xl"></i>
      <i class="fa-solid fa-leaf absolute left-40 top-28 rotate-[70deg] text-7xl text-pine/25"></i>
      <span class="block h-64 w-72"></span>
    </div>
    <dl class="relative mx-auto grid max-w-[90rem] gap-10 border-b border-pine/15 pb-20 sm:grid-cols-2 lg:grid-cols-4 lg:gap-0">
      <% [["25000", "+", "Experiences gathered"], ["500", "K+", "Bookings unlocked"], ["30", "+", "Enterprise partners"], ["200", "+", "Live API connections"]].each_with_index do |(value, suffix, label), index| %>
        <div data-reveal style="--reveal-delay:<%= index * 80 %>ms" class="flex flex-col lg:px-12 <%= "lg:border-l lg:border-pine/15" unless index.zero? %> <%= "lg:pl-0" if index.zero? %>">
          <dt class="order-2 mt-3 text-xl text-pine/80"><%= label %></dt>
          <dd class="font-display text-6xl font-semibold tracking-tight"><span data-count-to="<%= value %>"><%= value.to_i.to_s.reverse.scan(/\d{1,3}/).join(",").reverse %></span><%= suffix %></dd>
        </div>
      <% end %>
    </dl>
  </section>
  <!-- block:end stats -->

  <!-- block:start about -->
  <section id="problem" class="px-6 py-24 lg:px-20">
    <div class="mx-auto grid max-w-[90rem] items-center gap-14 lg:grid-cols-2">
      <div data-reveal class="grid grid-cols-2 gap-5">
        <div class="aspect-[3/4] overflow-hidden"><img src="https://images.unsplash.com/photo-1787676259212-7e39dae5dd14?auto=format&fit=crop&w=700&q=80" alt="Travelers walking down a narrow historic alley" class="h-full w-full object-cover grayscale"></div>
        <div class="mt-16 aspect-[3/4] overflow-hidden"><img src="https://images.unsplash.com/photo-1595351298020-038700609878?auto=format&fit=crop&w=700&q=80" alt="Potter shaping clay on a spinning wheel" class="h-full w-full object-cover grayscale"></div>
      </div>
      <div data-reveal style="--reveal-delay:100ms">
        <span class="inline-flex rounded-full bg-sand px-5 py-2">The problem</span>
        <h2 class="mt-6 font-display text-4xl font-semibold leading-tight tracking-tight md:text-5xl">The best local experiences are the hardest ones to book</h2>
        <p class="mt-6 text-lg leading-relaxed text-pine/80">Most hosts run on phone calls, spreadsheets and goodwill. Global platforms can't plug into them, so travelers end up with the same handful of generic tours.</p>
        <ul class="mt-8 space-y-4 text-lg">
          <% ["Fragmented inventory across thousands of tiny operators", "No shared format for stories, photos or availability", "Payouts that take weeks and eat into thin margins"].each do |item| %>
            <li class="flex gap-4"><i class="fa-solid fa-minus mt-2 text-sm" aria-hidden="true"></i><%= item %></li>
          <% end %>
        </ul>
        <a href="problem.html" class="mt-10 inline-flex items-center gap-3 font-display text-lg font-semibold underline decoration-2 underline-offset-8">Read the full picture <i class="fa-solid fa-arrow-right text-sm" aria-hidden="true"></i></a>
      </div>
    </div>
  </section>
  <!-- block:end about -->

  <!-- block:start features -->
  <section id="solution" class="bg-pine px-6 py-24 text-cream lg:px-20">
    <div class="mx-auto max-w-[90rem]">
      <div data-reveal class="flex flex-wrap items-end justify-between gap-8">
        <div class="max-w-3xl">
          <span class="inline-flex rounded-full bg-cream/10 px-5 py-2">The solution</span>
          <h2 class="mt-6 font-display text-4xl font-semibold leading-tight tracking-tight md:text-5xl">One clean pipe from local host to global demand</h2>
        </div>
        <a href="solution.html" class="border-2 border-cream px-8 py-4 font-display font-semibold transition hover:bg-cream hover:text-pine">How it works</a>
      </div>
      <div class="mt-16 grid gap-px bg-cream/15 sm:grid-cols-2 lg:grid-cols-4">
        <% [
          ["fa-layer-group", "Unified catalog", "Every experience normalized into one schema, with photos, policies and pricing."],
          ["fa-feather", "Story studio", "Editors help hosts turn a two-line listing into a page people want to read."],
          ["fa-share-nodes", "Smart distribution", "Push inventory to booking sites, airlines and hotel apps from one dashboard."],
          ["fa-wallet", "Fast payouts", "Hosts get paid within days, in local currency, with transparent fees."]
        ].each_with_index do |(icon, title, copy), index| %>
          <div data-reveal style="--reveal-delay:<%= index * 80 %>ms" class="bg-pine p-8">
            <i class="fa-solid <%= icon %> text-3xl text-sand" aria-hidden="true"></i>
            <h3 class="mt-8 font-display text-2xl font-semibold"><%= title %></h3>
            <p class="mt-3 text-cream/70"><%= copy %></p>
          </div>
        <% end %>
      </div>
    </div>
  </section>
  <!-- block:end features -->

  <!-- block:start process -->
  <section id="model" class="px-6 py-24 lg:px-20">
    <div class="mx-auto max-w-[90rem]">
      <div data-reveal class="max-w-3xl">
        <span class="inline-flex rounded-full bg-sand px-5 py-2">The model</span>
        <h2 class="mt-6 font-display text-4xl font-semibold leading-tight tracking-tight md:text-5xl">Four moves that turn a local gem into global revenue</h2>
      </div>
      <ol class="mt-16 grid gap-10 md:grid-cols-2 lg:grid-cols-4">
        <% [
          ["Gather", "We onboard hosts and import their offers, schedules and photos in a single session."],
          ["Shape", "Our editors write the story, translate it and tag it for the channels that fit."],
          ["Share", "Listings go live across partner platforms with synced, real-time availability."],
          ["Earn", "Bookings settle automatically and hosts see every payout in one ledger."]
        ].each_with_index do |(title, copy), index| %>
          <li data-reveal style="--reveal-delay:<%= index * 80 %>ms" class="border-t-2 border-pine pt-6">
            <span class="font-serif text-3xl">0<%= index + 1 %></span>
            <h3 class="mt-4 font-display text-3xl font-semibold"><%= title %></h3>
            <p class="mt-3 text-lg text-pine/80"><%= copy %></p>
          </li>
        <% end %>
      </ol>
    </div>
  </section>
  <!-- block:end process -->

  <!-- block:start integrations -->
  <section id="platform" class="bg-sand/60 px-6 py-24 lg:px-20">
    <div class="mx-auto grid max-w-[90rem] items-center gap-14 lg:grid-cols-[1fr_1.1fr]">
      <div data-reveal>
        <span class="inline-flex rounded-full bg-cream px-5 py-2">The platform</span>
        <h2 class="mt-6 font-display text-4xl font-semibold leading-tight tracking-tight md:text-5xl">Plugs into the channels your guests already use</h2>
        <p class="mt-6 text-lg leading-relaxed text-pine/80">A single API and a set of ready-made connectors mean partners go live in days, not quarters.</p>
        <a href="platform.html" class="mt-10 inline-flex bg-pine px-8 py-4 font-display font-semibold text-cream">Explore the platform</a>
      </div>
      <ul data-reveal style="--reveal-delay:100ms" class="grid grid-cols-2 gap-4 sm:grid-cols-3">
        <% [["fa-plane-departure", "Airlines"], ["fa-hotel", "Hotel apps"], ["fa-globe", "Online agencies"], ["fa-mobile-screen", "Super apps"], ["fa-credit-card", "Card perks"], ["fa-code", "Open API"]].each do |icon, label| %>
          <li class="flex flex-col items-start gap-6 bg-cream p-6">
            <i class="fa-solid <%= icon %> text-2xl" aria-hidden="true"></i>
            <span class="font-display text-lg font-semibold"><%= label %></span>
          </li>
        <% end %>
      </ul>
    </div>
  </section>
  <!-- block:end integrations -->

  <!-- block:start team -->
  <section id="team" class="px-6 py-24 lg:px-20">
    <div class="mx-auto max-w-[90rem]">
      <div data-reveal class="flex flex-wrap items-end justify-between gap-6">
        <div>
          <span class="inline-flex rounded-full bg-sand px-5 py-2">The team</span>
          <h2 class="mt-6 font-display text-4xl font-semibold tracking-tight md:text-5xl">Operators, editors and engineers</h2>
        </div>
        <a href="team.html" class="inline-flex items-center gap-3 font-display text-lg font-semibold underline decoration-2 underline-offset-8">Meet everyone <i class="fa-solid fa-arrow-right text-sm" aria-hidden="true"></i></a>
      </div>
      <div class="mt-14 grid gap-8 sm:grid-cols-2 lg:grid-cols-4">
        <% [["Anika Rao", "Co-founder, CEO", 5], ["Mateo Silva", "Co-founder, CTO", 2], ["Lena Hartmann", "Head of Supply", 6], ["Kofi Mensah", "Head of Partnerships", 3]].each_with_index do |(name, role, avatar), index| %>
          <figure data-reveal style="--reveal-delay:<%= index * 80 %>ms">
            <div class="aspect-[4/5] overflow-hidden bg-sand"><img src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-<%= avatar %>.jpg" alt="Portrait of <%= name %>" class="h-full w-full object-cover grayscale"></div>
            <figcaption class="mt-4"><span class="block font-display text-xl font-semibold"><%= name %></span><span class="text-pine/70"><%= role %></span></figcaption>
          </figure>
        <% end %>
      </div>
    </div>
  </section>
  <!-- block:end team -->

  <!-- block:start cta -->
  <section class="px-6 pb-24 lg:px-20">
    <div data-reveal class="relative mx-auto max-w-[90rem] overflow-hidden bg-pine-dark">
      <img src="https://images.unsplash.com/photo-1743485754079-d7fde0e9283f?auto=format&fit=crop&w=1600&q=70" alt="Lantern-lit night market with food stalls" class="absolute inset-0 h-full w-full object-cover opacity-30 grayscale">
      <div class="relative px-8 py-20 text-center text-cream md:px-16">
        <h2 class="mx-auto max-w-3xl font-display text-4xl font-semibold leading-tight tracking-tight md:text-5xl">Bring the world's most memorable experiences to your guests</h2>
        <div class="mt-10 flex flex-wrap justify-center gap-4">
          <a href="contact.html" class="bg-cream px-9 py-5 font-display text-lg font-semibold text-pine">Partner with us</a>
          <a href="model.html" class="border-2 border-cream px-9 py-[1.125rem] font-display text-lg font-semibold">See the model</a>
        </div>
      </div>
    </div>
  </section>
  <!-- block:end cta -->

  <!-- block:start footer -->
  <footer class="border-t border-pine/15 px-6 py-16 lg:px-20">
    <div class="mx-auto grid max-w-[90rem] gap-12 md:grid-cols-[1.5fr_1fr_1fr_1fr]">
      <div>
        <a href="index.html" class="flex items-center gap-2 font-display text-3xl font-bold"><i class="fa-solid fa-cube text-2xl" aria-hidden="true"></i>Wayloom</a>
        <p class="mt-4 max-w-sm text-pine/80">The supply layer that takes local experiences worldwide.</p>
      </div>
      <div>
        <p class="font-display font-semibold">Company</p>
        <ul class="mt-4 space-y-2 text-pine/80">
          <li><a href="about.html" class="hover:text-pine">About</a></li>
          <li><a href="team.html" class="hover:text-pine">Team</a></li>
          <li><a href="contact.html" class="hover:text-pine">Contact</a></li>
        </ul>
      </div>
      <div>
        <p class="font-display font-semibold">Product</p>
        <ul class="mt-4 space-y-2 text-pine/80">
          <li><a href="solution.html" class="hover:text-pine">Solution</a></li>
          <li><a href="model.html" class="hover:text-pine">Model</a></li>
          <li><a href="platform.html" class="hover:text-pine">Platform</a></li>
        </ul>
      </div>
      <div>
        <p class="font-display font-semibold">Follow</p>
        <div class="mt-4 flex gap-3">
          <% [["fa-linkedin-in", "https://linkedin.com", "LinkedIn"], ["fa-x-twitter", "https://x.com", "X"], ["fa-instagram", "https://instagram.com", "Instagram"]].each do |icon, href, label| %>
            <a href="<%= href %>" class="inline-flex h-11 w-11 items-center justify-center border border-pine/30 hover:bg-pine hover:text-cream" aria-label="<%= label %>"><i class="fa-brands <%= icon %>" aria-hidden="true"></i></a>
          <% end %>
        </div>
      </div>
    </div>
    <p class="mx-auto mt-14 max-w-[90rem] border-t border-pine/15 pt-6 text-sm text-pine/60">&copy; <span data-current-year>2026</span> Wayloom. All rights reserved.</p>
  </footer>
  <!-- block:end footer -->

  <script>
    const menuToggle = document.getElementById('menu-toggle');
    const mobileMenu = document.getElementById('mobile-menu');
    if (menuToggle && mobileMenu) {
      menuToggle.addEventListener('click', () => {
        const expanded = menuToggle.getAttribute('aria-expanded') === 'true';
        menuToggle.setAttribute('aria-expanded', String(!expanded));
        mobileMenu.hidden = expanded;
      });
    }

    const panels = document.querySelectorAll('[data-panel]');
    panels.forEach((panel) => {
      panel.querySelector('[data-panel-trigger]').addEventListener('click', () => {
        panels.forEach((other) => {
          const active = other === panel;
          other.setAttribute('aria-expanded', String(active));
          const trigger = other.querySelector('[data-panel-trigger]');
          trigger.setAttribute('aria-selected', String(active));
          trigger.classList.toggle('pointer-events-none', active);
          const number = other.querySelector('[data-panel-number]');
          number.classList.toggle('text-pine', active);
          number.classList.toggle('text-white', !active);
        });
      });
    });

    document.querySelectorAll('[data-current-year]').forEach((el) => { el.textContent = new Date().getFullYear(); });

    const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (!reduceMotion && !navigator.webdriver && 'IntersectionObserver' in window) {
      document.body.classList.add('reveal-ready');
      const revealObserver = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          if (!entry.isIntersecting) return;
          entry.target.classList.add('is-visible');
          revealObserver.unobserve(entry.target);
        });
      }, { threshold: 0.15 });
      document.querySelectorAll('[data-reveal]').forEach((el) => revealObserver.observe(el));

      const countObserver = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          if (!entry.isIntersecting) return;
          const el = entry.target;
          const target = parseInt(el.dataset.countTo, 10);
          const start = performance.now();
          const step = (now) => {
            const progress = Math.min((now - start) / 700, 1);
            el.textContent = Math.round(progress * target).toLocaleString('en-US');
            if (progress < 1) requestAnimationFrame(step);
          };
          requestAnimationFrame(step);
          countObserver.unobserve(el);
        });
      }, { threshold: 0.4 });
      document.querySelectorAll('[data-count-to]').forEach((el) => countObserver.observe(el));
    }
  </script>
</body>
</html>

Unlimited access to all templates

Unlock our entire library of premium UI kits, dashboards, and landing pages. Renews automatically, cancel anytime.

$20 / 3 months or $60 / year
Get Unlimited Access

More Startup Templates