Coach — Landing Yoga
A calm yet energetic yoga coach landing page built on the coach dark palette with softened sage and lavender accents. Features a breathing hero orb, a filterable class-type grid (Vinyasa, Yin, Power, Prenatal, Meditation), a weekly schedule with live spots-left indicators, mindfulness pillars, a testimonial, and a join form with instant toast feedback. Fully responsive, keyboard accessible, and animated with soft micro-interactions.
MCP
Code
:root {
--bg: #0f1115;
--surface: #171a21;
--surface-2: #1f232c;
--lime: #c2f542;
--lime-d: #a3d62f;
--orange: #ff6b35;
--ink: #f2f4f0;
--muted: #9aa0a6;
--line: rgba(255, 255, 255, 0.10);
--line-2: rgba(255, 255, 255, 0.18);
--white: #fff;
/* calmer yoga accents layered over the coach palette */
--sage: #a9d6b8;
--sage-d: #7fbf95;
--lav: #c3b8f5;
--lav-d: #9d8fe6;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 20px;
--shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: "Inter", system-ui, sans-serif;
background:
radial-gradient(900px 600px at 85% -5%, rgba(163, 214, 149, 0.10), transparent 60%),
radial-gradient(700px 500px at 5% 10%, rgba(195, 184, 245, 0.10), transparent 55%),
var(--bg);
color: var(--ink);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a { color: inherit; text-decoration: none; }
:focus-visible {
outline: 2px solid var(--sage);
outline-offset: 3px;
border-radius: 4px;
}
/* ---------- buttons ---------- */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 12px 22px;
border-radius: 999px;
border: 1px solid transparent;
font-weight: 700;
font-size: 0.95rem;
cursor: pointer;
transition: transform 0.15s ease, box-shadow 0.2s ease, background 0.2s ease, border-color 0.2s ease;
font-family: inherit;
}
.btn:active { transform: translateY(1px) scale(0.99); }
.btn-primary {
background: var(--sage);
color: #10231a;
box-shadow: 0 0 0 rgba(169, 214, 184, 0);
}
.btn-primary:hover {
background: var(--sage-d);
box-shadow: 0 10px 30px rgba(169, 214, 184, 0.28), 0 0 22px rgba(169, 214, 184, 0.30);
transform: translateY(-1px);
}
.btn-ghost {
background: transparent;
border-color: var(--line-2);
color: var(--ink);
}
.btn-ghost:hover { border-color: var(--sage); color: var(--sage); }
.btn-sm { padding: 8px 16px; font-size: 0.85rem; }
.btn-block { width: 100%; }
/* ---------- nav ---------- */
.nav {
position: sticky;
top: 0;
z-index: 20;
display: flex;
align-items: center;
gap: 20px;
padding: 16px clamp(18px, 5vw, 56px);
background: rgba(15, 17, 21, 0.72);
backdrop-filter: blur(14px);
border-bottom: 1px solid var(--line);
}
.brand {
display: inline-flex;
align-items: center;
gap: 10px;
font-weight: 800;
font-size: 1.15rem;
letter-spacing: 0.02em;
}
.brand-thin { color: var(--sage); font-weight: 600; }
.brand-mark {
width: 22px; height: 22px;
border-radius: 50%;
background: conic-gradient(from 120deg, var(--sage), var(--lav), var(--sage));
box-shadow: 0 0 16px rgba(169, 214, 184, 0.5);
}
.nav-links {
display: flex;
gap: 26px;
margin-left: auto;
font-size: 0.92rem;
color: var(--muted);
font-weight: 500;
}
.nav-links a { transition: color 0.15s ease; }
.nav-links a:hover { color: var(--ink); }
.nav-cta { padding: 9px 18px; }
/* ---------- hero ---------- */
.hero {
display: grid;
grid-template-columns: 1.1fr 0.9fr;
gap: 40px;
align-items: center;
padding: clamp(48px, 8vw, 96px) clamp(18px, 5vw, 56px);
max-width: 1180px;
margin: 0 auto;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 9px;
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.14em;
font-weight: 700;
color: var(--sage);
padding: 7px 14px;
border: 1px solid var(--line);
border-radius: 999px;
background: var(--surface);
}
.eyebrow .dot {
width: 8px; height: 8px; border-radius: 50%;
background: var(--sage);
box-shadow: 0 0 10px var(--sage);
animation: pulse 2.4s infinite ease-in-out;
}
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
.hero-title {
font-size: clamp(2.6rem, 6.5vw, 4.4rem);
line-height: 1.02;
margin: 22px 0 18px;
font-weight: 800;
letter-spacing: -0.02em;
text-transform: uppercase;
}
.hero-title em {
font-family: "Fraunces", serif;
font-style: italic;
font-weight: 500;
text-transform: none;
letter-spacing: -0.01em;
color: var(--lav);
}
.hero-sub {
color: var(--muted);
font-size: 1.08rem;
max-width: 44ch;
margin: 0 0 28px;
}
.hero-cta { display: flex; gap: 14px; flex-wrap: wrap; }
.hero-stats {
list-style: none;
display: flex;
gap: 30px;
padding: 0;
margin: 36px 0 0;
flex-wrap: wrap;
}
.hero-stats li {
display: flex;
flex-direction: column;
font-size: 0.82rem;
color: var(--muted);
}
.hero-stats strong {
font-size: 1.5rem;
color: var(--ink);
font-weight: 800;
}
.hero-visual { position: relative; min-height: 360px; }
.orb {
position: absolute;
inset: 0;
margin: auto;
width: 300px; height: 300px;
border-radius: 50%;
background:
radial-gradient(circle at 35% 30%, rgba(195, 184, 245, 0.9), transparent 60%),
radial-gradient(circle at 70% 70%, rgba(169, 214, 184, 0.9), transparent 60%),
var(--surface-2);
filter: blur(2px);
box-shadow: 0 0 80px rgba(169, 214, 184, 0.25), inset 0 0 60px rgba(0,0,0,0.4);
animation: breathe 6s ease-in-out infinite;
}
@keyframes breathe {
0%, 100% { transform: scale(0.94); opacity: 0.85; }
50% { transform: scale(1.06); opacity: 1; }
}
.hero-card {
position: absolute;
bottom: 14px;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
gap: 3px;
background: rgba(23, 26, 33, 0.82);
backdrop-filter: blur(8px);
border: 1px solid var(--line-2);
border-radius: var(--r-md);
padding: 14px 18px;
box-shadow: var(--shadow);
min-width: 240px;
}
.hero-card-tag {
font-size: 0.68rem;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--sage);
font-weight: 700;
}
.hero-card strong { font-size: 1.05rem; }
.hero-card-meta { font-size: 0.82rem; color: var(--muted); }
/* ---------- sections ---------- */
.section {
max-width: 1180px;
margin: 0 auto;
padding: clamp(40px, 6vw, 72px) clamp(18px, 5vw, 56px);
}
.section-head {
display: flex;
justify-content: space-between;
align-items: flex-end;
gap: 20px;
flex-wrap: wrap;
margin-bottom: 34px;
}
.kicker {
font-size: 0.76rem;
text-transform: uppercase;
letter-spacing: 0.16em;
font-weight: 700;
color: var(--lav);
}
.section-title {
font-size: clamp(1.7rem, 4vw, 2.5rem);
margin: 8px 0 0;
font-weight: 800;
text-transform: uppercase;
letter-spacing: -0.01em;
}
.section-note { color: var(--muted); font-size: 0.92rem; margin: 0; max-width: 32ch; }
/* ---------- filters ---------- */
.filters { display: flex; gap: 10px; flex-wrap: wrap; }
.chip {
padding: 9px 18px;
border-radius: 999px;
border: 1px solid var(--line-2);
background: var(--surface);
color: var(--muted);
font-weight: 600;
font-size: 0.86rem;
cursor: pointer;
font-family: inherit;
transition: all 0.18s ease;
}
.chip:hover { color: var(--ink); border-color: var(--sage); }
.chip.is-active {
background: var(--sage);
color: #10231a;
border-color: var(--sage);
}
/* ---------- class grid ---------- */
.class-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 20px;
}
.class-card {
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
overflow: hidden;
transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
.class-card:hover {
transform: translateY(-4px);
border-color: var(--line-2);
box-shadow: var(--shadow);
}
.class-card.is-hidden { display: none; }
.thumb {
position: relative;
height: 140px;
display: flex;
align-items: flex-start;
justify-content: flex-end;
padding: 12px;
}
.thumb-1 { background: linear-gradient(135deg, #2c3a45, #a9d6b8); }
.thumb-2 { background: linear-gradient(135deg, #3a2c45, #ff6b35); }
.thumb-3 { background: linear-gradient(135deg, #2c3145, #c3b8f5); }
.thumb-4 { background: linear-gradient(135deg, #45383a, #a9d6b8); }
.thumb-5 { background: linear-gradient(135deg, #263845, #9d8fe6); }
.thumb-6 { background: linear-gradient(135deg, #2c4540, #7fbf95); }
.badge {
font-size: 0.7rem;
font-weight: 700;
padding: 5px 11px;
border-radius: 999px;
background: rgba(15, 17, 21, 0.72);
backdrop-filter: blur(4px);
border: 1px solid var(--line-2);
}
.badge-low { color: var(--sage); }
.badge-mid { color: var(--lav); }
.badge-high { color: var(--orange); }
.class-body { padding: 16px 18px 20px; }
.class-body h3 { margin: 0 0 6px; font-size: 1.15rem; font-weight: 700; }
.class-body p { margin: 0 0 12px; color: var(--muted); font-size: 0.9rem; }
.class-meta {
display: flex;
gap: 7px;
font-size: 0.82rem;
color: var(--muted);
font-weight: 500;
}
/* ---------- schedule ---------- */
.schedule { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 12px; }
.sch-row {
display: grid;
grid-template-columns: 110px 1fr auto auto;
gap: 18px;
align-items: center;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-md);
padding: 16px 20px;
transition: border-color 0.2s ease, background 0.2s ease;
}
.sch-row:hover { border-color: var(--line-2); }
.sch-row.is-full { opacity: 0.6; }
.sch-day { display: flex; flex-direction: column; }
.sch-day strong { font-size: 1rem; text-transform: uppercase; letter-spacing: 0.04em; }
.sch-day span { font-size: 0.82rem; color: var(--muted); }
.sch-class { display: flex; flex-direction: column; }
.sch-class strong { font-size: 1.02rem; }
.sch-class span { font-size: 0.82rem; color: var(--muted); }
.sch-spots {
font-size: 0.8rem;
font-weight: 700;
color: var(--sage);
white-space: nowrap;
}
.sch-spots.is-low { color: var(--orange); }
.sch-spots.is-full { color: var(--muted); }
/* ---------- pillars ---------- */
.pillars {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
gap: 20px;
margin-bottom: 40px;
}
.pillar {
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 26px 24px;
transition: transform 0.2s ease, border-color 0.2s ease;
}
.pillar:hover { transform: translateY(-3px); border-color: var(--line-2); }
.pillar-ico {
display: inline-flex;
align-items: center;
justify-content: center;
width: 48px; height: 48px;
border-radius: 14px;
background: var(--surface-2);
border: 1px solid var(--line);
font-size: 1.4rem;
color: var(--lav);
margin-bottom: 14px;
}
.pillar h3 { margin: 0 0 8px; font-size: 1.2rem; }
.pillar p { margin: 0; color: var(--muted); font-size: 0.92rem; }
.quote {
margin: 0;
background: linear-gradient(135deg, var(--surface-2), var(--surface));
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 34px 36px;
}
.quote blockquote {
margin: 0 0 16px;
font-family: "Fraunces", serif;
font-size: clamp(1.3rem, 3vw, 1.7rem);
font-weight: 500;
line-height: 1.35;
}
.quote figcaption {
display: flex;
align-items: center;
gap: 12px;
font-size: 0.9rem;
color: var(--muted);
font-weight: 500;
}
.q-avatar {
display: inline-flex;
align-items: center;
justify-content: center;
width: 38px; height: 38px;
border-radius: 50%;
background: var(--lav);
color: #1a1533;
font-weight: 800;
font-size: 0.82rem;
}
/* ---------- join ---------- */
.join-inner {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
align-items: center;
background:
radial-gradient(500px 300px at 90% 0%, rgba(195, 184, 245, 0.14), transparent 60%),
var(--surface);
border: 1px solid var(--line-2);
border-radius: var(--r-lg);
padding: clamp(28px, 5vw, 48px);
}
.join-copy p { color: var(--muted); }
.join-perks {
list-style: none;
padding: 0;
margin: 20px 0 0;
display: flex;
flex-direction: column;
gap: 10px;
}
.join-perks li {
position: relative;
padding-left: 26px;
font-size: 0.92rem;
}
.join-perks li::before {
content: "✓";
position: absolute;
left: 0;
color: var(--sage);
font-weight: 800;
}
.join-form { display: flex; flex-direction: column; gap: 8px; }
.join-form label {
font-size: 0.82rem;
font-weight: 600;
color: var(--muted);
margin-top: 8px;
}
.join-form input,
.join-form select {
padding: 13px 16px;
border-radius: var(--r-sm);
border: 1px solid var(--line-2);
background: var(--bg);
color: var(--ink);
font-family: inherit;
font-size: 0.95rem;
transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.join-form input:focus,
.join-form select:focus {
outline: none;
border-color: var(--sage);
box-shadow: 0 0 0 3px rgba(169, 214, 184, 0.22);
}
.join-form input.is-error { border-color: var(--orange); }
.join-form .btn { margin-top: 14px; }
.form-fine { font-size: 0.76rem; color: var(--muted); text-align: center; margin: 10px 0 0; }
/* ---------- footer ---------- */
.footer {
max-width: 1180px;
margin: 0 auto;
padding: 30px clamp(18px, 5vw, 56px) 48px;
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
border-top: 1px solid var(--line);
color: var(--muted);
font-size: 0.86rem;
flex-wrap: wrap;
}
.footer-links { display: flex; gap: 20px; }
.footer-links a:hover { color: var(--ink); }
/* ---------- toast ---------- */
.toast {
position: fixed;
left: 50%;
bottom: 28px;
transform: translate(-50%, 24px);
background: var(--surface-2);
border: 1px solid var(--sage);
color: var(--ink);
padding: 13px 22px;
border-radius: 999px;
font-size: 0.9rem;
font-weight: 600;
box-shadow: var(--shadow);
opacity: 0;
pointer-events: none;
transition: opacity 0.25s ease, transform 0.25s ease;
z-index: 60;
}
.toast.is-show { opacity: 1; transform: translate(-50%, 0); }
/* ---------- reveal ---------- */
[data-reveal] {
opacity: 0;
transform: translateY(18px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
[data-reveal].is-in { opacity: 1; transform: none; }
/* ---------- responsive ---------- */
@media (max-width: 820px) {
.hero { grid-template-columns: 1fr; }
.hero-visual { min-height: 300px; order: -1; }
.join-inner { grid-template-columns: 1fr; }
.nav-links { display: none; }
}
@media (max-width: 520px) {
.nav { gap: 12px; }
.nav-cta { margin-left: auto; }
.hero-stats { gap: 20px; }
.section-head { flex-direction: column; align-items: flex-start; }
.sch-row {
grid-template-columns: 1fr auto;
grid-template-areas:
"day spots"
"class class"
"book book";
gap: 10px 12px;
}
.sch-day { grid-area: day; flex-direction: row; align-items: baseline; gap: 8px; }
.sch-spots { grid-area: spots; justify-self: end; }
.sch-class { grid-area: class; }
.sch-book { grid-area: book; width: 100%; }
.orb { width: 220px; height: 220px; }
.footer { flex-direction: column; align-items: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
.orb, .eyebrow .dot { animation: none; }
[data-reveal] { transition: none; opacity: 1; transform: none; }
html { scroll-behavior: auto; }
}(function () {
"use strict";
/* ---------- toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("is-show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("is-show");
}, 2600);
}
/* ---------- class filters ---------- */
var chips = Array.prototype.slice.call(document.querySelectorAll(".chip"));
var cards = Array.prototype.slice.call(document.querySelectorAll(".class-card"));
chips.forEach(function (chip) {
chip.addEventListener("click", function () {
var filter = chip.getAttribute("data-filter");
chips.forEach(function (c) {
var active = c === chip;
c.classList.toggle("is-active", active);
c.setAttribute("aria-pressed", active ? "true" : "false");
});
var shown = 0;
cards.forEach(function (card) {
var cats = (card.getAttribute("data-cat") || "").split(/\s+/);
var match = filter === "all" || cats.indexOf(filter) !== -1;
card.classList.toggle("is-hidden", !match);
if (match) shown++;
});
if (filter !== "all") {
toast(shown + " " + (shown === 1 ? "class" : "classes") + " in this style");
}
});
});
/* ---------- schedule reservations ---------- */
var rows = Array.prototype.slice.call(document.querySelectorAll(".sch-row"));
rows.forEach(function (row) {
var spotsEl = row.querySelector(".sch-spots");
var btn = row.querySelector(".sch-book");
var classEl = row.querySelector(".sch-class strong");
function paint() {
var n = parseInt(spotsEl.getAttribute("data-spots"), 10);
spotsEl.classList.toggle("is-low", n > 0 && n <= 2);
spotsEl.classList.toggle("is-full", n <= 0);
if (n <= 0) {
spotsEl.textContent = "Class full";
row.classList.add("is-full");
btn.textContent = "Waitlist";
} else {
spotsEl.textContent = n + (n === 1 ? " spot left" : " spots left");
}
}
paint();
btn.addEventListener("click", function () {
var n = parseInt(spotsEl.getAttribute("data-spots"), 10);
var name = classEl ? classEl.textContent : "class";
if (n <= 0) {
toast("Added to the waitlist for " + name);
return;
}
n -= 1;
spotsEl.setAttribute("data-spots", String(n));
paint();
btn.textContent = "Reserved ✓";
setTimeout(function () {
if (parseInt(spotsEl.getAttribute("data-spots"), 10) > 0) {
btn.textContent = "Reserve";
}
}, 1600);
toast("Spot reserved for " + name);
});
});
/* ---------- join form ---------- */
var form = document.getElementById("joinForm");
if (form) {
var emailInput = document.getElementById("email");
form.addEventListener("submit", function (e) {
e.preventDefault();
var val = (emailInput.value || "").trim();
var ok = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val);
if (!ok) {
emailInput.classList.add("is-error");
emailInput.focus();
toast("Please enter a valid email");
return;
}
emailInput.classList.remove("is-error");
var goal = document.getElementById("goal");
var label = goal.options[goal.selectedIndex].text;
form.reset();
toast("Welcome to SoraFlow — pass sent for " + label.toLowerCase());
});
emailInput.addEventListener("input", function () {
emailInput.classList.remove("is-error");
});
}
/* ---------- scroll reveal ---------- */
var reveals = Array.prototype.slice.call(document.querySelectorAll("[data-reveal]"));
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.classList.add("is-in");
io.unobserve(entry.target);
}
});
},
{ threshold: 0.12 }
);
reveals.forEach(function (el) { io.observe(el); });
} else {
reveals.forEach(function (el) { el.classList.add("is-in"); });
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Sora Flow — Yoga Coaching</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Fraunces:opsz,[email protected],500;9..144,600&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<header class="nav" data-reveal>
<a class="brand" href="#top">
<span class="brand-mark" aria-hidden="true"></span>
Sora<span class="brand-thin">Flow</span>
</a>
<nav class="nav-links" aria-label="Primary">
<a href="#classes">Classes</a>
<a href="#schedule">Schedule</a>
<a href="#mindful">Mindfulness</a>
<a href="#join">Join</a>
</nav>
<a class="btn btn-ghost nav-cta" href="#join">Book a class</a>
</header>
<main id="top">
<!-- HERO -->
<section class="hero" data-reveal>
<div class="hero-copy">
<span class="eyebrow"><span class="dot" aria-hidden="true"></span> Breathe · Move · Rest</span>
<h1 class="hero-title">Find your<br /><em>calm</em> in motion</h1>
<p class="hero-sub">
Small-group yoga and breathwork with Maya Okafor. Build strength and
stillness in equal measure — no experience required, just a mat and
an open mind.
</p>
<div class="hero-cta">
<a href="#join" class="btn btn-primary">Start your practice</a>
<a href="#classes" class="btn btn-ghost">Explore classes</a>
</div>
<ul class="hero-stats" aria-label="Studio highlights">
<li><strong>12+</strong> class styles</li>
<li><strong>3.4k</strong> students guided</li>
<li><strong>4.9<span aria-hidden="true">★</span></strong> avg rating</li>
</ul>
</div>
<div class="hero-visual" aria-hidden="true">
<div class="orb"></div>
<div class="hero-card">
<span class="hero-card-tag">Next live class</span>
<strong>Morning Vinyasa</strong>
<span class="hero-card-meta">Tomorrow · 7:00 AM · 4 spots left</span>
</div>
</div>
</section>
<!-- CLASSES -->
<section id="classes" class="section" data-reveal>
<div class="section-head">
<div>
<span class="kicker">Class styles</span>
<h2 class="section-title">Choose your flow</h2>
</div>
<div class="filters" role="group" aria-label="Filter classes by style">
<button class="chip is-active" data-filter="all" aria-pressed="true">All</button>
<button class="chip" data-filter="active" aria-pressed="false">Active</button>
<button class="chip" data-filter="restore" aria-pressed="false">Restorative</button>
<button class="chip" data-filter="breath" aria-pressed="false">Breath</button>
</div>
</div>
<div class="class-grid" id="classGrid">
<article class="class-card" data-cat="active">
<div class="thumb thumb-1"><span class="badge badge-mid">Intensity 3/5</span></div>
<div class="class-body">
<h3>Vinyasa Flow</h3>
<p>Breath-linked sequences that build heat, balance and grace.</p>
<div class="class-meta"><span>60 min</span><span>·</span><span>All levels</span></div>
</div>
</article>
<article class="class-card" data-cat="active">
<div class="thumb thumb-2"><span class="badge badge-high">Intensity 4/5</span></div>
<div class="class-body">
<h3>Power Yoga</h3>
<p>Strength-driven, athletic flow to fire up your whole body.</p>
<div class="class-meta"><span>50 min</span><span>·</span><span>Intermediate</span></div>
</div>
</article>
<article class="class-card" data-cat="restore">
<div class="thumb thumb-3"><span class="badge badge-low">Intensity 1/5</span></div>
<div class="class-body">
<h3>Yin & Restore</h3>
<p>Long, gentle holds that release deep connective tissue.</p>
<div class="class-meta"><span>75 min</span><span>·</span><span>All levels</span></div>
</div>
</article>
<article class="class-card" data-cat="restore">
<div class="thumb thumb-4"><span class="badge badge-low">Intensity 2/5</span></div>
<div class="class-body">
<h3>Prenatal Calm</h3>
<p>Safe, supportive movement for every trimester of pregnancy.</p>
<div class="class-meta"><span>45 min</span><span>·</span><span>Prenatal</span></div>
</div>
</article>
<article class="class-card" data-cat="breath">
<div class="thumb thumb-5"><span class="badge badge-low">Intensity 1/5</span></div>
<div class="class-body">
<h3>Breath & Meditate</h3>
<p>Pranayama and guided stillness to settle a busy mind.</p>
<div class="class-meta"><span>30 min</span><span>·</span><span>All levels</span></div>
</div>
</article>
<article class="class-card" data-cat="active breath">
<div class="thumb thumb-6"><span class="badge badge-mid">Intensity 3/5</span></div>
<div class="class-body">
<h3>Flow & Breathwork</h3>
<p>A dynamic flow bookended by rhythmic breathing rounds.</p>
<div class="class-meta"><span>55 min</span><span>·</span><span>All levels</span></div>
</div>
</article>
</div>
</section>
<!-- SCHEDULE -->
<section id="schedule" class="section" data-reveal>
<div class="section-head">
<div>
<span class="kicker">This week</span>
<h2 class="section-title">Weekly schedule</h2>
</div>
<p class="section-note">Live spots update as classes fill. Reserve early.</p>
</div>
<ul class="schedule" id="schedule">
<li class="sch-row">
<span class="sch-day"><strong>Mon</strong><span>7:00 AM</span></span>
<span class="sch-class"><strong>Morning Vinyasa</strong><span>60 min · Studio A</span></span>
<span class="sch-spots" data-spots="4">4 spots left</span>
<button class="btn btn-primary btn-sm sch-book">Reserve</button>
</li>
<li class="sch-row">
<span class="sch-day"><strong>Tue</strong><span>6:30 PM</span></span>
<span class="sch-class"><strong>Yin & Restore</strong><span>75 min · Studio B</span></span>
<span class="sch-spots" data-spots="8">8 spots left</span>
<button class="btn btn-primary btn-sm sch-book">Reserve</button>
</li>
<li class="sch-row">
<span class="sch-day"><strong>Wed</strong><span>12:00 PM</span></span>
<span class="sch-class"><strong>Breath & Meditate</strong><span>30 min · Garden</span></span>
<span class="sch-spots" data-spots="2">2 spots left</span>
<button class="btn btn-primary btn-sm sch-book">Reserve</button>
</li>
<li class="sch-row">
<span class="sch-day"><strong>Thu</strong><span>7:15 PM</span></span>
<span class="sch-class"><strong>Power Yoga</strong><span>50 min · Studio A</span></span>
<span class="sch-spots" data-spots="1">1 spot left</span>
<button class="btn btn-primary btn-sm sch-book">Reserve</button>
</li>
<li class="sch-row">
<span class="sch-day"><strong>Sat</strong><span>9:00 AM</span></span>
<span class="sch-class"><strong>Prenatal Calm</strong><span>45 min · Studio B</span></span>
<span class="sch-spots" data-spots="6">6 spots left</span>
<button class="btn btn-primary btn-sm sch-book">Reserve</button>
</li>
</ul>
</section>
<!-- MINDFULNESS -->
<section id="mindful" class="section" data-reveal>
<div class="section-head">
<div>
<span class="kicker">The approach</span>
<h2 class="section-title">More than a workout</h2>
</div>
</div>
<div class="pillars">
<article class="pillar">
<span class="pillar-ico" aria-hidden="true">〰</span>
<h3>Breath first</h3>
<p>Every session begins by syncing movement to breath, calming the nervous system before we flow.</p>
</article>
<article class="pillar">
<span class="pillar-ico" aria-hidden="true">◇</span>
<h3>Aligned strength</h3>
<p>Precise cueing keeps joints safe while you build sustainable, functional strength.</p>
</article>
<article class="pillar">
<span class="pillar-ico" aria-hidden="true">☾</span>
<h3>Intentional rest</h3>
<p>We honour stillness — closing each class with restorative poses and a guided savasana.</p>
</article>
</div>
<figure class="quote">
<blockquote>
"Maya's classes gave me back my breath. I arrive tense and leave lighter every single time."
</blockquote>
<figcaption><span class="q-avatar" aria-hidden="true">DL</span> Dana Liu · student for 2 years</figcaption>
</figure>
</section>
<!-- JOIN -->
<section id="join" class="section join" data-reveal>
<div class="join-inner">
<div class="join-copy">
<span class="kicker">Join the studio</span>
<h2 class="section-title">Your first class is on us</h2>
<p>Drop your email to claim a free intro session and a 7-day pass. No pressure, no auto-billing.</p>
<ul class="join-perks">
<li>Unlimited class trial for a week</li>
<li>Personal level assessment</li>
<li>Access to the on-demand library</li>
</ul>
</div>
<form class="join-form" id="joinForm" novalidate>
<label for="email">Email address</label>
<input id="email" name="email" type="email" placeholder="[email protected]" autocomplete="email" required />
<label for="goal">What are you here for?</label>
<select id="goal" name="goal">
<option value="flex">Flexibility & mobility</option>
<option value="strength">Strength & tone</option>
<option value="stress">Stress relief</option>
<option value="prenatal">Prenatal support</option>
</select>
<button type="submit" class="btn btn-primary btn-block">Claim free pass</button>
<p class="form-fine">We reply within a day. Unsubscribe anytime.</p>
</form>
</div>
</section>
</main>
<footer class="footer">
<span>© 2026 SoraFlow Studio</span>
<span class="footer-links">
<a href="#classes">Classes</a>
<a href="#schedule">Schedule</a>
<a href="#join">Join</a>
</span>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>A yoga-focused variant of the coach landing template that trades the electric-lime intensity for calmer sage and lavender accents while keeping the energetic dark surfaces. The hero pairs a bold uppercase headline with a slowly breathing gradient orb and a pair of CTAs, setting a grounded, mindful tone above the fold.
Below the hero, a filterable grid of class cards lets visitors toggle between styles like Vinyasa Flow, Yin, Power and Prenatal, each with intensity badges and duration metadata. A weekly schedule renders real-feeling sessions with live spots-left counters that decrement when you reserve a slot, and a mindfulness section explains the breath, alignment and rest pillars.
Interactions are all vanilla JS: category filter chips reflow the class grid, schedule rows reserve seats and surface a toast, the join form validates the email and confirms with an accessible toast, and a scroll reveal fades sections in. Focus states are visible throughout and the layout collapses cleanly to a single column below 520px.