Free
0
1
Strivo
By Jonah Hale
Strivo is a bold, electric-blue health and fitness template for training studios, with a motion-blur hero, rotating program card, giant marquee, numbered services, training cycle diagram, heart rate zone calculator, reviews, FAQ tabs and services, programs, wellness plans and contact pages.
Download Codebase
Commercial License<%# letstemplates: access=premium category=health-fitness %>
<!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>Strivo | Tailwind CSS Health & Fitness Template</title>
<meta name="description" content="Strivo is a bold, electric-blue Tailwind CSS health and fitness template for training studios, with a motion-blur hero, rotating program card, giant marquee, numbered services, training cycle diagram, heart rate zone calculator, reviews, FAQ tabs and services, programs, wellness plans and contact pages.">
<meta name="keywords" content="Strivo, Tailwind CSS template, HTML website template, fitness template, training studio, HIIT, heart rate zones, personal training, wellness plans, gym landing page">
<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="Strivo | Tailwind CSS Health & Fitness Template">
<meta property="og:description" content="A bold electric-blue Tailwind CSS training template with a heart rate zone calculator, training cycle diagram and wellness plans by audience.">
<meta property="og:image" content="">
<meta property="og:image:alt" content="Strivo template preview">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="">
<meta name="twitter:title" content="Strivo | Tailwind CSS Health & Fitness Template">
<meta name="twitter:description" content="A bold electric-blue Tailwind CSS training template with a heart rate zone calculator, training cycle diagram and wellness plans by audience.">
<meta name="twitter:image" content="">
<meta name="twitter:image:alt" content="Strivo template preview">
<script src="https://cdn.tailwindcss.com/3.4.17"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;800;900&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: { volt: { DEFAULT: '#1aa3e8', deep: '#0b5fa6', pale: '#d9f0fc' }, ink: { DEFAULT: '#0b0d10', soft: '#1a1e24' }, cream: '#fbf6ef', flare: '#ff7a3d' },
fontFamily: { sans: ['Archivo', 'sans-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; } }
@keyframes marquee { to { transform: translateX(-50%); } }
html { scroll-behavior: smooth; }
[hidden] { display: none !important; }
.marquee { animation: marquee 30s linear infinite; }
.blur-photo { filter: blur(6px) saturate(1.2); transform: scale(1.08); }
.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; }
.marquee { animation: none; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}
</style>
</head>
<body class="bg-ink font-sans text-white antialiased">
<% active_page = "index" %>
<% nav = { "services" => "Services", "programs" => "Programs", "wellness-plans" => "Wellness plans" } %>
<!-- block:start navbar -->
<header class="<%= active_page == 'index' ? 'absolute inset-x-0 top-0' : 'relative bg-volt-deep' %> z-40">
<nav class="mx-auto flex max-w-7xl items-center justify-between gap-6 px-5 py-6 md:px-12 md:py-8" aria-label="Main">
<a href="index.html" class="flex items-center gap-2 text-2xl font-extrabold uppercase tracking-tight"><svg viewBox="0 0 32 20" class="h-5 w-8" aria-hidden="true"><path d="M2 6v8M6 3v14M26 3v14M30 6v8M6 10h20" fill="none" stroke="currentColor" stroke-width="3.2" stroke-linecap="square"/></svg>Strivo</a>
<ul class="hidden items-center gap-12 text-sm font-semibold uppercase tracking-wide lg:flex">
<% nav.each do |slug, label| %>
<% active = active_page == slug %>
<li><a href="<%= slug %>.html" <%= 'aria-current="page"'.html_safe if active %> class="border-b-2 pb-1 transition <%= active ? 'border-white' : 'border-transparent opacity-85 hover:border-white/60' %>"><%= label %></a></li>
<% end %>
</ul>
<div class="flex items-center gap-3">
<a href="contact.html" class="hidden border border-white px-6 py-3.5 text-sm font-semibold uppercase tracking-wide transition hover:bg-white hover:text-ink sm:inline-block">Get started</a>
<button type="button" data-menu-toggle aria-controls="mobile-menu" aria-expanded="false" class="grid h-12 w-12 place-items-center border border-white/60 lg:hidden" aria-label="Open menu"><i class="fa-solid fa-bars" aria-hidden="true"></i></button>
</div>
</nav>
<div id="mobile-menu" class="mx-5 hidden bg-white p-2 text-ink lg:hidden">
<ul class="grid">
<% { "index" => "Home" }.merge(nav).merge("contact" => "Contact").each do |slug, label| %>
<% active = active_page == slug %>
<li><a href="<%= slug %>.html" <%= 'aria-current="page"'.html_safe if active %> class="flex items-center justify-between border-b border-ink/10 px-4 py-4 text-lg font-extrabold uppercase last:border-0 <%= active ? 'bg-volt text-white' : 'hover:bg-volt-pale' %>"><%= label %><i class="fa-solid fa-arrow-right text-sm" aria-hidden="true"></i></a></li>
<% end %>
</ul>
</div>
</header>
<!-- block:end navbar -->
<% cards = [["HIIT Training", "Short, sharp intervals that build engine and grit in 30 minutes.", "1599058917212-d750089bc07e", "Woman training with battle ropes"], ["Strength Lab", "Coached lifting that grows muscle and power safely.", "1541534741688-6078c6bfb5c5", "Woman lifting a barbell in a squat rack"], ["Mobility Reset", "Joint-friendly flows that keep you moving freely.", "1599901860904-17e6ed7083a0", "Person stretching in a downward dog pose"]] %>
<!-- block:start hero -->
<section class="relative isolate overflow-hidden bg-volt">
<img src="https://images.unsplash.com/photo-1594882645126-14020914d58d?auto=format&fit=crop&w=1800&q=70" alt="" class="blur-photo absolute inset-0 -z-20 h-full w-full object-cover">
<div class="absolute inset-0 -z-10 bg-gradient-to-b from-volt/80 via-volt/40 via-55% to-ink"></div>
<div class="mx-auto max-w-7xl px-5 pb-10 pt-36 md:px-12 md:pt-44">
<h1 class="text-[3.4rem] font-extrabold uppercase leading-[.86] tracking-tight sm:text-7xl md:text-8xl lg:text-[8.5rem]" data-reveal><span class="block">Built for</span><span class="block sm:pl-[22%]">Every</span><span class="block">Stride</span></h1>
<div class="mt-8 grid gap-8 lg:-mt-24 lg:grid-cols-[1fr_minmax(0,34rem)]">
<span class="hidden lg:block"></span>
<div>
<p class="text-lg leading-relaxed md:text-2xl" data-reveal style="--reveal-delay: 80ms">Train with intent: tailored sessions, coaches who notice the details and an energy that makes every goal feel within reach.</p>
<a href="programs.html" class="mt-10 flex items-center justify-between gap-6 border border-white/40 bg-white/75 px-8 py-7 text-lg font-extrabold uppercase text-ink backdrop-blur-xl transition hover:bg-white md:ml-auto md:w-[26rem]">Find your program<i class="fa-solid fa-arrow-right" aria-hidden="true"></i></a>
</div>
</div>
<div class="mt-16 grid gap-6 md:grid-cols-2 lg:grid-cols-[1fr_1.6fr_1.1fr_1fr] lg:items-start">
<div data-reveal><p class="text-5xl font-extrabold" data-count="420">420</p><p class="mt-1 text-lg text-white/85">Body transformations</p></div>
<div class="relative min-h-[13rem] overflow-hidden bg-cream text-ink" data-hero-card data-reveal style="--reveal-delay: 80ms">
<% cards.each_with_index do |(title, text, photo, alt), index| %>
<article class="absolute inset-0 grid grid-cols-[1.1fr_1fr] transition-opacity duration-500" data-hero-slide <%= 'hidden' unless index.zero? %>>
<div class="flex flex-col p-6"><h2 class="text-2xl font-extrabold uppercase leading-none md:text-3xl"><%= title %></h2><p class="mt-auto text-sm"><%= text %></p></div>
<img src="https://images.unsplash.com/photo-<%= photo %>?auto=format&fit=crop&w=500&h=500&q=75" alt="<%= alt %>" class="h-full w-full object-cover">
</article>
<% end %>
<div class="absolute bottom-3 right-3 z-10 flex gap-1.5" role="group" aria-label="Featured programs">
<% cards.each_with_index do |(title), index| %>
<button type="button" data-hero-dot="<%= index %>" aria-pressed="<%= index.zero? %>" class="h-2 w-6 bg-ink/25 transition aria-pressed:w-10 aria-pressed:bg-ink" aria-label="Show <%= title %>"></button>
<% end %>
</div>
</div>
<div class="border-t border-white/70 pt-5" data-reveal style="--reveal-delay: 160ms"><p class="text-5xl font-extrabold"><span data-count="6000">6000</span>+</p><p class="mt-1 text-lg text-white/85">Coached sessions a year</p></div>
<p class="text-white/85 lg:pt-1" data-reveal style="--reveal-delay: 240ms">Gain muscle, sharpen power and build strength that carries into everything you do.</p>
</div>
</div>
</section>
<!-- block:end hero -->
<!-- block:start marquee -->
<section class="overflow-hidden border-y border-white/10 bg-ink py-10" aria-label="Strivo promise">
<div class="marquee flex w-max items-center gap-10 whitespace-nowrap text-6xl font-black uppercase tracking-tight md:text-8xl">
<% 2.times do |copy| %>
<% ["Train smart", "Move fast", "Lift heavy", "Recover well"].each_with_index do |word, index| %>
<span class="<%= index.odd? ? 'text-transparent [-webkit-text-stroke:2px_#1aa3e8]' : '' %>" <%= 'aria-hidden="true"'.html_safe if copy == 1 %>><%= word %></span><span class="text-volt" aria-hidden="true">✦</span>
<% end %>
<% end %>
</div>
<div class="mx-auto mt-8 flex max-w-7xl justify-end px-5 md:px-12"><a href="contact.html" class="flex items-center gap-4 bg-volt px-7 py-4 font-extrabold uppercase transition hover:bg-volt-deep">Book a free session<i class="fa-solid fa-arrow-right" aria-hidden="true"></i></a></div>
</section>
<!-- block:end marquee -->
<% services = [["Personal training", "One coach, one plan and a weekly review of every lift, run and rest day. Sessions move with your calendar and your energy.", "1517838277536-f5f99be501cd", "Hands gripping a loaded barbell"], ["HIIT & conditioning", "Thirty-minute intervals with heart rate screens on the wall, so you always know when to push and when to hold back.", "1554284126-aa88f22d8b74", "Group lifting dumbbells in a class"], ["Strength & power", "Small-group barbell work focused on technique first, then load. Perfect for first-timers and returning lifters.", "1532029837206-abbe2b7620e3", "Man pressing a barbell in a rack"], ["Mobility & recovery", "Guided mobility, breathwork and a recovery suite so the hard sessions actually pay off.", "1600881333168-2ef49b341f30", "Woman in a downward dog yoga pose"]] %>
<!-- block:start features -->
<section id="services" class="bg-cream text-ink">
<div class="mx-auto max-w-7xl px-5 py-20 md:px-12 md:py-28">
<div class="flex flex-wrap items-end justify-between gap-6">
<h2 class="max-w-2xl text-5xl font-extrabold uppercase leading-[.9] tracking-tight md:text-7xl">What we do best</h2>
<a href="services.html" class="border-b-2 border-ink pb-1 font-semibold uppercase">All services</a>
</div>
<ol class="mt-14 border-t border-ink" data-services>
<% services.each_with_index do |(title, text, photo, alt), index| %>
<li class="border-b border-ink">
<h3>
<button type="button" data-service-toggle aria-expanded="<%= index.zero? %>" aria-controls="service-<%= index %>" class="group grid w-full grid-cols-[3.5rem_1fr_auto] items-center gap-4 py-7 text-left md:grid-cols-[7rem_1fr_auto]">
<span class="text-3xl font-extrabold text-volt md:text-5xl">0<%= index + 1 %></span>
<span class="text-2xl font-extrabold uppercase md:text-5xl"><%= title %></span>
<span class="grid h-12 w-12 place-items-center border border-ink transition group-hover:bg-ink group-hover:text-white group-aria-expanded:rotate-45 group-aria-expanded:bg-volt group-aria-expanded:border-volt group-aria-expanded:text-white"><i class="fa-solid fa-plus" aria-hidden="true"></i></span>
</button>
</h3>
<div id="service-<%= index %>" class="grid gap-6 pb-8 md:grid-cols-[7rem_1fr_20rem]" <%= 'hidden' unless index.zero? %>>
<span class="hidden md:block"></span>
<p class="max-w-xl text-lg text-ink/75"><%= text %><a href="services.html" class="mt-5 block w-fit font-semibold uppercase text-volt-deep underline underline-offset-4">Learn more</a></p>
<img src="https://images.unsplash.com/photo-<%= photo %>?auto=format&fit=crop&w=640&h=420&q=75" alt="<%= alt %>" class="aspect-[3/2] w-full object-cover">
</div>
</li>
<% end %>
</ol>
</div>
</section>
<!-- block:end features -->
<% phases = [["Assess", "Weeks 1–2", "Movement screen, strength tests and a resting heart rate baseline. We find your starting line, not someone else's.", "fa-clipboard-check"], ["Build", "Weeks 3–6", "Volume climbs gradually. Technique stays sharp and every session has a clear purpose.", "fa-layer-group"], ["Peak", "Weeks 7–10", "Intensity rises, volume drops. You test new personal bests in strength and conditioning.", "fa-bolt"], ["Recover", "Weeks 11–12", "A planned deload with mobility and sleep focus, then we reassess and start the next cycle stronger.", "fa-moon"]] %>
<!-- block:start process -->
<section class="relative overflow-hidden bg-volt-deep" data-cycle>
<div class="mx-auto grid max-w-7xl items-center gap-14 px-5 py-20 md:px-12 md:py-28 lg:grid-cols-2">
<div>
<h2 class="text-5xl font-extrabold uppercase leading-[.9] tracking-tight md:text-7xl">The 12-week cycle</h2>
<p class="mt-6 max-w-md text-lg text-white/80">Every Strivo program follows the same proven rhythm. Tap a phase to see what happens inside it.</p>
<div class="mt-10 border-l-4 border-white pl-6" aria-live="polite">
<p class="text-sm font-semibold uppercase tracking-widest text-white/70" data-cycle-weeks><%= phases[0][1] %></p>
<p class="mt-2 text-4xl font-extrabold uppercase" data-cycle-title><%= phases[0][0] %></p>
<p class="mt-3 max-w-md text-white/85" data-cycle-text><%= phases[0][2] %></p>
</div>
</div>
<div class="relative mx-auto aspect-square w-full max-w-md">
<div class="absolute inset-[12%] rounded-full border-2 border-dashed border-white/40"></div>
<div class="absolute inset-[30%] grid place-items-center rounded-full bg-white text-center text-ink"><span><span class="block text-5xl font-black leading-none">12</span><span class="text-xs font-semibold uppercase tracking-widest">weeks</span></span></div>
<% positions = ["left-1/2 top-[12%]", "left-[88%] top-1/2", "left-1/2 top-[88%]", "left-[12%] top-1/2"] %>
<% phases.each_with_index do |(title, _weeks, _text, icon), index| %>
<button type="button" data-phase="<%= index %>" aria-pressed="<%= index.zero? %>" class="absolute <%= positions[index] %> flex h-24 w-24 -translate-x-1/2 -translate-y-1/2 flex-col items-center justify-center gap-1 bg-ink text-xs font-bold uppercase tracking-wide transition hover:scale-105 aria-pressed:bg-white aria-pressed:text-ink md:h-28 md:w-28"><i class="fa-solid <%= icon %> text-xl" aria-hidden="true"></i><%= title %></button>
<% end %>
</div>
</div>
<script type="application/json" data-cycle-data><%= raw phases.map { |(title, weeks, text)| { title: title, weeks: weeks, text: text } }.to_json %></script>
</section>
<!-- block:end process -->
<% age = 32 %>
<% rest = 60 %>
<% zones = [["Zone 1", "Recovery", 0.5, 0.6, "Easy walk or Mobility Reset"], ["Zone 2", "Endurance", 0.6, 0.7, "Long steady ride or easy run"], ["Zone 3", "Tempo", 0.7, 0.8, "Strength Lab circuits"], ["Zone 4", "Threshold", 0.8, 0.9, "HIIT Training intervals"], ["Zone 5", "Max effort", 0.9, 1.0, "Sprint finishers, 20 seconds max"]] %>
<% reserve = 220 - age - rest %>
<!-- block:start demo -->
<section id="zones" class="bg-ink" data-zones>
<div class="mx-auto grid max-w-7xl gap-12 px-5 py-20 md:px-12 md:py-28 lg:grid-cols-[1fr_1.3fr]">
<div>
<p class="text-sm font-semibold uppercase tracking-widest text-volt">Zone finder</p>
<h2 class="mt-4 text-5xl font-extrabold uppercase leading-[.9] tracking-tight md:text-7xl">Know your numbers</h2>
<p class="mt-6 max-w-md text-white/75">Our coaches program every session by heart rate zone. Enter two numbers to see yours.</p>
<div class="mt-10 grid gap-8">
<label class="grid gap-3"><span class="flex justify-between text-sm font-semibold uppercase tracking-wide">Age <output class="text-2xl text-volt" data-zone-age-out><%= age %></output></span><input type="range" min="18" max="75" value="<%= age %>" class="accent-[#1aa3e8]" data-zone-age></label>
<label class="grid gap-3"><span class="flex justify-between text-sm font-semibold uppercase tracking-wide">Resting heart rate <output class="text-2xl text-volt" data-zone-rest-out><%= rest %> bpm</output></span><input type="range" min="40" max="90" value="<%= rest %>" class="accent-[#1aa3e8]" data-zone-rest></label>
</div>
<p class="mt-10 border-t border-white/15 pt-6 text-white/70">Max heart rate <span class="ml-2 text-3xl font-extrabold text-white" data-zone-max><%= 220 - age %></span> bpm</p>
</div>
<div>
<ul class="grid gap-2" role="list">
<% zones.each_with_index do |(name, label, low, high), index| %>
<li>
<button type="button" data-zone="<%= index %>" aria-pressed="<%= index == 3 %>" class="group relative grid w-full grid-cols-[6rem_1fr_auto] items-center gap-4 overflow-hidden bg-ink-soft px-5 py-5 text-left transition hover:bg-white/10 aria-pressed:bg-volt">
<span class="absolute inset-y-0 left-0 bg-white/5 group-aria-pressed:bg-white/15" style="width: <%= (high * 100).round %>%"></span>
<span class="relative text-sm font-semibold uppercase tracking-wide"><%= name %></span>
<span class="relative text-xl font-extrabold uppercase"><%= label %></span>
<span class="relative text-lg font-semibold tabular-nums" data-zone-range><%= (rest + reserve * low).round %>–<%= (rest + reserve * high).round %></span>
</button>
</li>
<% end %>
</ul>
<p class="mt-6 flex items-center gap-3 border border-white/15 px-5 py-4" aria-live="polite"><i class="fa-solid fa-dumbbell text-volt" aria-hidden="true"></i><span>Try this: <strong data-zone-session><%= zones[3][4] %></strong></span></p>
</div>
</div>
<script type="application/json" data-zone-data><%= raw zones.map { |(name, label, low, high, session)| { low: low, high: high, session: session } }.to_json %></script>
</section>
<!-- block:end demo -->
<% reviews = [["I've tried every gym in town. Strivo is the first place where the plan changed when my life did.", "Nadia Brooks", "Down 11 kg in 6 months", "avatar-2"], ["The heart rate screens in HIIT are addictive. I finally understand what easy and hard really mean.", "Owen Price", "First sub-50 10K", "avatar-4"], ["Coming back after a knee injury, the coaches built my confidence before they built my squat.", "Leila Haddad", "Back to 80 kg squat", "avatar-5"], ["Twelve-week cycles keep me honest. Every deload week I'm amazed how much stronger I feel.", "Chris Moreno", "+30% on every lift", "avatar-3"]] %>
<!-- block:start reviews -->
<section class="bg-cream text-ink" data-carousel>
<div class="mx-auto max-w-7xl px-5 py-20 md:px-12 md:py-28">
<div class="flex flex-wrap items-end justify-between gap-6">
<h2 class="text-5xl font-extrabold uppercase leading-[.9] tracking-tight md:text-7xl">Member stories</h2>
<div class="flex gap-2">
<button type="button" data-prev class="grid h-14 w-14 place-items-center border border-ink transition hover:bg-ink hover:text-white" aria-label="Previous story"><i class="fa-solid fa-arrow-left" aria-hidden="true"></i></button>
<button type="button" data-next class="grid h-14 w-14 place-items-center bg-volt text-white transition hover:bg-volt-deep" aria-label="Next story"><i class="fa-solid fa-arrow-right" aria-hidden="true"></i></button>
</div>
</div>
<div class="mt-12 overflow-hidden">
<ul class="flex transition-transform duration-500 motion-reduce:transition-none" data-track>
<% reviews.each_with_index do |(quote, name, result, avatar), index| %>
<li class="w-full shrink-0 md:w-1/2 md:pr-6" aria-roledescription="slide" aria-label="<%= index + 1 %> of <%= reviews.size %>">
<figure class="flex h-full flex-col border-t-4 border-ink bg-white p-8">
<blockquote class="text-2xl font-medium leading-snug">“<%= quote %>”</blockquote>
<figcaption class="mt-auto flex items-center gap-4 pt-8"><img src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/<%= avatar %>.jpg" alt="" class="h-12 w-12 object-cover"><span><span class="block font-extrabold uppercase"><%= name %></span><span class="text-sm text-volt-deep"><%= result %></span></span></figcaption>
</figure>
</li>
<% end %>
</ul>
</div>
<div class="mt-8 flex gap-2" role="group" aria-label="Choose a story">
<% reviews.each_with_index do |_, index| %>
<button type="button" data-dot="<%= index %>" aria-pressed="<%= index.zero? %>" class="h-1.5 w-10 bg-ink/20 transition aria-pressed:bg-ink" aria-label="Story <%= index + 1 %>"></button>
<% end %>
</div>
</div>
</section>
<!-- block:end reviews -->
<% faqs = { "membership" => ["Membership", [["Can I pause my plan?", "Yes, up to six weeks a year with no fee."], ["Is there a contract?", "Monthly plans roll monthly. Annual plans save 15% and can be transferred."], ["Do you offer corporate plans?", "Yes. Teams of five or more get pooled sessions and a shared dashboard."]]], "training" => ["Training", [["I'm a complete beginner. Is that okay?", "Absolutely. Your first two weeks are an assessment phase built for exactly that."], ["How long are sessions?", "HIIT runs 30 minutes, strength and personal training 50 to 60."], ["Do I need a heart rate monitor?", "We lend chest straps for every class, or you can pair your own."]]], "recovery" => ["Recovery", [["What's in the recovery suite?", "Sauna, cold plunge, compression boots and a stretching zone."], ["Do you help with nutrition?", "Wellness plans include a monthly nutrition check-in with our dietitian."], ["Can I train with an injury?", "Often, yes. Tell us first and we'll build sessions around it with our physio."]]] } %>
<!-- block:start faq -->
<section class="bg-ink" data-faq-tabs>
<div class="mx-auto grid max-w-7xl gap-12 px-5 py-20 md:px-12 md:py-28 lg:grid-cols-[1fr_1.5fr]">
<div>
<h2 class="text-5xl font-extrabold uppercase leading-[.9] tracking-tight md:text-7xl">Questions</h2>
<div class="mt-10 flex flex-wrap gap-2 lg:flex-col lg:items-start" role="tablist" aria-label="Question topics">
<% faqs.each_with_index do |(key, (label)), index| %>
<button type="button" role="tab" id="faq-tab-<%= key %>" aria-controls="faq-<%= key %>" aria-selected="<%= index.zero? %>" tabindex="<%= index.zero? ? 0 : -1 %>" class="border border-white/30 px-5 py-3 text-sm font-semibold uppercase tracking-wide transition hover:border-white aria-selected:border-volt aria-selected:bg-volt"><%= label %></button>
<% end %>
</div>
</div>
<div>
<% faqs.each_with_index do |(key, (_label, items)), index| %>
<dl id="faq-<%= key %>" role="tabpanel" aria-labelledby="faq-tab-<%= key %>" class="border-t border-white/20" <%= 'hidden' unless index.zero? %>>
<% items.each do |(question, answer)| %>
<div class="border-b border-white/20 py-7"><dt class="text-xl font-extrabold uppercase"><%= question %></dt><dd class="mt-2 text-white/75"><%= answer %></dd></div>
<% end %>
</dl>
<% end %>
</div>
</div>
</section>
<!-- block:end faq -->
<!-- block:start footer -->
<footer class="bg-volt">
<div class="mx-auto max-w-7xl px-5 py-16 md:px-12">
<div class="grid gap-10 border-b border-white/30 pb-14 lg:grid-cols-[1.4fr_1fr]">
<p class="text-4xl font-extrabold uppercase leading-[.95] tracking-tight md:text-6xl">Your first session is on us</p>
<form class="self-end" data-newsletter novalidate>
<label for="footer-email" class="text-sm font-semibold uppercase tracking-wide">Email for a free pass</label>
<div class="mt-3 flex">
<input id="footer-email" name="email" type="email" required autocomplete="email" placeholder="you@example.com" class="min-w-0 flex-1 bg-white px-5 py-4 text-ink placeholder:text-ink/40 focus:outline-none focus:ring-2 focus:ring-ink">
<button type="submit" class="bg-ink px-6 font-extrabold uppercase transition hover:bg-ink-soft">Claim</button>
</div>
<p class="mt-3 min-h-[1.5rem] text-sm font-medium" data-form-status role="status"></p>
</form>
</div>
<div class="grid gap-10 py-12 sm:grid-cols-2 lg:grid-cols-4">
<div>
<a href="index.html" class="flex items-center gap-2 text-2xl font-extrabold uppercase"><svg viewBox="0 0 32 20" class="h-5 w-8" aria-hidden="true"><path d="M2 6v8M6 3v14M26 3v14M30 6v8M6 10h20" fill="none" stroke="currentColor" stroke-width="3.2" stroke-linecap="square"/></svg>Strivo</a>
<p class="mt-4 max-w-xs text-white/85">Modern training for people who want results without the guesswork.</p>
</div>
<% [["Train", [["Services", "services.html"], ["Programs", "programs.html"], ["Zone finder", "index.html#zones"]]], ["Join", [["Wellness plans", "wellness-plans.html"], ["Free session", "contact.html"], ["Corporate", "wellness-plans.html"]]], ["Visit", [["210 Canal Street, Manchester", nil], ["hello@strivo.fit", "mailto:hello@strivo.fit"], ["+44 161 555 0192", "tel:+441615550192"]]]].each do |(title, links)| %>
<div>
<h2 class="text-sm font-semibold uppercase tracking-widest text-white/70"><%= title %></h2>
<ul class="mt-4 grid gap-2">
<% links.each do |(label, href)| %><li><% if href %><a href="<%= href %>" class="hover:underline"><%= label %></a><% else %><%= label %><% end %></li><% end %>
</ul>
</div>
<% end %>
</div>
<p class="flex flex-wrap justify-between gap-4 border-t border-white/30 pt-6 text-sm text-white/80"><span>© 2026 Strivo Training Ltd.</span><span class="flex gap-5"><a href="contact.html" aria-label="Instagram" class="hover:text-ink"><i class="fa-brands fa-instagram" aria-hidden="true"></i></a><a href="contact.html" aria-label="TikTok" class="hover:text-ink"><i class="fa-brands fa-tiktok" aria-hidden="true"></i></a><a href="contact.html" aria-label="YouTube" class="hover:text-ink"><i class="fa-brands fa-youtube" aria-hidden="true"></i></a></span></p>
</div>
</footer>
<!-- block:end footer -->
<script>
const reducedMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
const watchMotion = !reducedMotion && !navigator.webdriver && 'IntersectionObserver' in window;
document.querySelectorAll('[data-menu-toggle]').forEach((button) => {
const menu = document.getElementById(button.getAttribute('aria-controls'));
button.addEventListener('click', () => {
const open = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!open));
menu.classList.toggle('hidden', open);
});
});
document.querySelectorAll('[data-hero-card]').forEach((root) => {
const slides = [...root.querySelectorAll('[data-hero-slide]')];
const dots = [...root.querySelectorAll('[data-hero-dot]')];
let current = 0;
const show = (index) => {
current = index;
slides.forEach((slide, i) => { slide.hidden = i !== index; });
dots.forEach((dot, i) => dot.setAttribute('aria-pressed', String(i === index)));
};
dots.forEach((dot, i) => dot.addEventListener('click', () => show(i)));
if (!reducedMotion && !navigator.webdriver) setInterval(() => { if (!root.matches(':hover')) show((current + 1) % slides.length); }, 5000);
});
document.querySelectorAll('[data-services]').forEach((root) => {
root.querySelectorAll('[data-service-toggle]').forEach((button) => button.addEventListener('click', () => {
const open = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!open));
document.getElementById(button.getAttribute('aria-controls')).hidden = open;
}));
});
document.querySelectorAll('[data-cycle]').forEach((root) => {
const data = JSON.parse(root.querySelector('[data-cycle-data]').textContent);
const buttons = [...root.querySelectorAll('[data-phase]')];
buttons.forEach((button) => button.addEventListener('click', () => {
buttons.forEach((other) => other.setAttribute('aria-pressed', String(other === button)));
const phase = data[Number(button.dataset.phase)];
root.querySelector('[data-cycle-title]').textContent = phase.title;
root.querySelector('[data-cycle-weeks]').textContent = phase.weeks;
root.querySelector('[data-cycle-text]').textContent = phase.text;
}));
});
document.querySelectorAll('[data-zones]').forEach((root) => {
const data = JSON.parse(root.querySelector('[data-zone-data]').textContent);
const age = root.querySelector('[data-zone-age]');
const rest = root.querySelector('[data-zone-rest]');
const buttons = [...root.querySelectorAll('[data-zone]')];
const update = () => {
const max = 220 - Number(age.value);
const reserve = max - Number(rest.value);
root.querySelector('[data-zone-age-out]').textContent = age.value;
root.querySelector('[data-zone-rest-out]').textContent = `${rest.value} bpm`;
root.querySelector('[data-zone-max]').textContent = max;
buttons.forEach((button, i) => { button.querySelector('[data-zone-range]').textContent = `${Math.round(Number(rest.value) + reserve * data[i].low)}–${Math.round(Number(rest.value) + reserve * data[i].high)}`; });
};
age.addEventListener('input', update);
rest.addEventListener('input', update);
buttons.forEach((button) => button.addEventListener('click', () => {
buttons.forEach((other) => other.setAttribute('aria-pressed', String(other === button)));
root.querySelector('[data-zone-session]').textContent = data[Number(button.dataset.zone)].session;
}));
});
document.querySelectorAll('[data-carousel]').forEach((root) => {
const track = root.querySelector('[data-track]');
const dots = [...root.querySelectorAll('[data-dot]')];
const count = track.children.length;
let index = 0;
const go = (next) => {
index = (next + count) % count;
track.style.transform = `translateX(-${track.children[index].offsetLeft}px)`;
dots.forEach((dot, i) => dot.setAttribute('aria-pressed', String(i === index)));
};
root.querySelector('[data-prev]').addEventListener('click', () => go(index - 1));
root.querySelector('[data-next]').addEventListener('click', () => go(index + 1));
dots.forEach((dot, i) => dot.addEventListener('click', () => go(i)));
});
document.querySelectorAll('[data-faq-tabs]').forEach((root) => {
const tabs = [...root.querySelectorAll('[role="tab"]')];
const select = (tab, focus) => {
tabs.forEach((other) => { const on = other === tab; other.setAttribute('aria-selected', String(on)); other.tabIndex = on ? 0 : -1; document.getElementById(other.getAttribute('aria-controls')).hidden = !on; });
if (focus) tab.focus();
};
tabs.forEach((tab, i) => {
tab.addEventListener('click', () => select(tab));
tab.addEventListener('keydown', (event) => {
if (event.key === 'ArrowRight' || event.key === 'ArrowDown') select(tabs[(i + 1) % tabs.length], true);
if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') select(tabs[(i - 1 + tabs.length) % tabs.length], true);
});
});
});
document.querySelectorAll('[data-newsletter]').forEach((form) => {
const status = form.querySelector('[data-form-status]');
form.addEventListener('submit', (event) => {
event.preventDefault();
const email = form.querySelector('[name="email"]');
if (!email.value.trim() || !email.checkValidity()) { status.textContent = 'Please enter a valid email address.'; email.focus(); return; }
status.textContent = 'Pass on its way. Check your inbox to book your first session.';
form.reset();
});
});
if (watchMotion) {
document.documentElement.classList.add('reveal-ready');
const observer = new IntersectionObserver((entries) => entries.forEach((entry) => {
if (entry.isIntersecting) { entry.target.classList.add('is-visible'); observer.unobserve(entry.target); }
}), { threshold: 0.15 });
document.querySelectorAll('[data-reveal]').forEach((el) => observer.observe(el));
const counter = new IntersectionObserver((entries) => entries.forEach((entry) => {
if (!entry.isIntersecting) return;
const el = entry.target; const end = Number(el.dataset.count); const start = performance.now();
const tick = (now) => { const p = Math.min((now - start) / 900, 1); el.textContent = Math.round(end * p); if (p < 1) requestAnimationFrame(tick); };
requestAnimationFrame(tick); counter.unobserve(el);
}), { threshold: 0.5 });
document.querySelectorAll('[data-count]').forEach((el) => counter.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