Coach — Pricing Plans
An energetic dark pricing section for a fitness coaching brand with three tiers — Self, Guided, and 1-on-1 — each showing feature checklists, a glowing most-popular badge, and electric-lime CTAs. A monthly/quarterly billing toggle animates every price and surfaces a save badge, while hover lift, keyboard focus rings, and a toast confirm plan selection for a punchy, conversion-ready layout.
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.1);
--line-2: rgba(255, 255, 255, 0.18);
--white: #fff;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 20px;
}
* {
box-sizing: border-box;
}
html {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
margin: 0;
min-height: 100vh;
background:
radial-gradient(
1100px 520px at 78% -8%,
rgba(194, 245, 66, 0.12),
transparent 60%
),
radial-gradient(
900px 480px at 12% 8%,
rgba(255, 107, 53, 0.1),
transparent 55%
),
var(--bg);
color: var(--ink);
font-family: "Inter", system-ui, sans-serif;
line-height: 1.5;
padding: clamp(20px, 5vw, 64px) 18px;
}
.wrap {
max-width: 1080px;
margin: 0 auto;
}
/* ---------- Header ---------- */
.head {
text-align: center;
margin-bottom: 40px;
}
.eyebrow {
display: inline-block;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--lime);
background: rgba(194, 245, 66, 0.08);
border: 1px solid rgba(194, 245, 66, 0.28);
padding: 6px 14px;
border-radius: 999px;
margin-bottom: 18px;
}
.head h1 {
font-size: clamp(30px, 6vw, 52px);
font-weight: 800;
letter-spacing: -0.02em;
line-height: 1.05;
text-transform: uppercase;
margin: 0 0 14px;
}
.sub {
color: var(--muted);
max-width: 460px;
margin: 0 auto 26px;
font-size: 16px;
}
/* ---------- Billing toggle ---------- */
.billing {
display: flex;
justify-content: center;
}
.toggle {
position: relative;
display: inline-flex;
padding: 5px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: 999px;
}
.toggle-btn {
position: relative;
z-index: 2;
border: 0;
background: transparent;
color: var(--muted);
font-family: inherit;
font-size: 14px;
font-weight: 700;
letter-spacing: 0.02em;
padding: 10px 22px;
border-radius: 999px;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 8px;
transition: color 0.25s ease;
}
.toggle-btn.is-active {
color: #0f1115;
}
.toggle-btn:focus-visible {
outline: 2px solid var(--lime);
outline-offset: 3px;
}
.mini-pill {
font-size: 10px;
font-weight: 800;
letter-spacing: 0.06em;
text-transform: uppercase;
padding: 3px 7px;
border-radius: 999px;
background: rgba(255, 107, 53, 0.9);
color: #fff;
}
.toggle-btn.is-active .mini-pill {
background: #0f1115;
color: var(--lime);
}
.toggle-thumb {
position: absolute;
z-index: 1;
top: 5px;
left: 5px;
height: calc(100% - 10px);
width: 50%;
border-radius: 999px;
background: var(--lime);
box-shadow: 0 0 20px rgba(194, 245, 66, 0.5);
transition: transform 0.32s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.toggle[data-period="quarterly"] .toggle-thumb {
transform: translateX(100%);
}
/* ---------- Grid ---------- */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
align-items: stretch;
}
.plan {
position: relative;
display: flex;
flex-direction: column;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 28px 24px;
transition:
transform 0.22s ease,
border-color 0.22s ease,
box-shadow 0.22s ease;
}
.plan:hover,
.plan:focus-visible {
transform: translateY(-6px);
border-color: var(--line-2);
box-shadow: 0 20px 44px rgba(0, 0, 0, 0.4);
outline: none;
}
.plan:focus-visible {
border-color: var(--lime);
box-shadow: 0 0 0 3px rgba(194, 245, 66, 0.35);
}
.plan.popular {
background: linear-gradient(180deg, #1c2029, var(--surface));
border-color: rgba(194, 245, 66, 0.5);
box-shadow:
0 0 0 1px rgba(194, 245, 66, 0.15),
0 24px 60px rgba(194, 245, 66, 0.08);
}
.plan.popular:hover,
.plan.popular:focus-visible {
box-shadow:
0 0 0 1px rgba(194, 245, 66, 0.3),
0 28px 64px rgba(194, 245, 66, 0.16);
}
.badge {
position: absolute;
top: -13px;
left: 50%;
transform: translateX(-50%);
font-size: 11px;
font-weight: 800;
letter-spacing: 0.12em;
text-transform: uppercase;
color: #0f1115;
background: var(--lime);
padding: 6px 16px;
border-radius: 999px;
box-shadow: 0 6px 20px rgba(194, 245, 66, 0.45);
white-space: nowrap;
}
.plan-top {
min-height: 78px;
}
.tier {
display: block;
font-size: 15px;
font-weight: 800;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--ink);
}
.plan.popular .tier {
color: var(--lime);
}
.tier-desc {
margin: 8px 0 0;
font-size: 13.5px;
color: var(--muted);
}
/* ---------- Price ---------- */
.price {
display: flex;
align-items: baseline;
gap: 2px;
margin: 18px 0 4px;
}
.cur {
font-size: 22px;
font-weight: 700;
color: var(--muted);
align-self: flex-start;
margin-top: 8px;
}
.amount {
font-size: 52px;
font-weight: 800;
letter-spacing: -0.03em;
line-height: 1;
font-variant-numeric: tabular-nums;
}
.per {
font-size: 15px;
font-weight: 600;
color: var(--muted);
}
.billed {
margin: 0 0 22px;
font-size: 12.5px;
color: var(--muted);
}
/* ---------- Features ---------- */
.feats {
list-style: none;
margin: 0 0 24px;
padding: 20px 0 0;
border-top: 1px solid var(--line);
display: grid;
gap: 12px;
flex: 1;
}
.feats li {
position: relative;
padding-left: 30px;
font-size: 14px;
color: var(--ink);
}
.feats li::before {
content: "";
position: absolute;
left: 0;
top: 1px;
width: 19px;
height: 19px;
border-radius: 50%;
background-repeat: no-repeat;
background-position: center;
background-size: 12px;
}
.feats li.on::before {
background-color: rgba(194, 245, 66, 0.16);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c2f542' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}
.feats li.off {
color: var(--muted);
}
.feats li.off::before {
background-color: rgba(255, 255, 255, 0.05);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa0a6' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");
}
/* ---------- CTA ---------- */
.cta {
width: 100%;
border: 0;
border-radius: var(--r-md);
padding: 15px 18px;
font-family: inherit;
font-size: 14px;
font-weight: 800;
letter-spacing: 0.06em;
text-transform: uppercase;
color: #0f1115;
background: var(--lime);
cursor: pointer;
transition:
transform 0.15s ease,
box-shadow 0.22s ease,
background 0.2s ease;
}
.cta:hover {
background: var(--lime-d);
box-shadow: 0 10px 30px rgba(194, 245, 66, 0.4);
transform: translateY(-2px);
}
.cta:active {
transform: translateY(0);
}
.cta:focus-visible {
outline: 3px solid var(--lime);
outline-offset: 3px;
}
.cta.ghost {
background: transparent;
color: var(--ink);
border: 1px solid var(--line-2);
}
.cta.ghost:hover {
background: var(--surface-2);
border-color: var(--lime);
color: var(--lime);
box-shadow: none;
}
/* ---------- Footer ---------- */
.foot {
text-align: center;
color: var(--muted);
font-size: 13.5px;
margin: 34px 0 0;
}
/* ---------- Toast ---------- */
.toast {
position: fixed;
left: 50%;
bottom: 26px;
transform: translate(-50%, 140%);
background: var(--surface-2);
color: var(--ink);
border: 1px solid var(--line-2);
border-left: 4px solid var(--lime);
padding: 13px 20px;
border-radius: var(--r-md);
font-size: 14px;
font-weight: 600;
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
opacity: 0;
transition:
transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
opacity 0.3s ease;
z-index: 50;
max-width: calc(100% - 36px);
}
.toast.show {
transform: translate(-50%, 0);
opacity: 1;
}
/* ---------- Responsive ---------- */
@media (max-width: 900px) {
.grid {
grid-template-columns: 1fr;
max-width: 460px;
margin: 0 auto;
}
.plan.popular {
order: -1;
}
}
@media (max-width: 520px) {
body {
padding: 28px 14px;
}
.head {
margin-bottom: 30px;
}
.toggle-btn {
padding: 9px 16px;
font-size: 13px;
}
.plan {
padding: 24px 20px;
}
.plan-top {
min-height: 0;
}
.amount {
font-size: 46px;
}
}(function () {
"use strict";
var toggle = document.getElementById("toggle");
var buttons = Array.prototype.slice.call(
toggle.querySelectorAll(".toggle-btn")
);
var plans = Array.prototype.slice.call(document.querySelectorAll(".plan"));
var toastEl = document.getElementById("toast");
var toastTimer;
var currentPeriod = "monthly";
/* --- Toast helper --- */
function toast(msg) {
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2600);
}
/* --- Animated count from current to target --- */
function animateAmount(el, to) {
var from = parseInt(el.textContent, 10) || 0;
if (from === to) {
el.textContent = to;
return;
}
var start = performance.now();
var dur = 380;
function frame(now) {
var p = Math.min((now - start) / dur, 1);
var eased = 1 - Math.pow(1 - p, 3);
el.textContent = Math.round(from + (to - from) * eased);
if (p < 1) requestAnimationFrame(frame);
else el.textContent = to;
}
requestAnimationFrame(frame);
}
/* --- Render all prices for a period --- */
function render(period) {
currentPeriod = period;
toggle.setAttribute("data-period", period);
buttons.forEach(function (b) {
var active = b.dataset.period === period;
b.classList.toggle("is-active", active);
b.setAttribute("aria-pressed", active ? "true" : "false");
});
plans.forEach(function (plan) {
var priceBox = plan.querySelector(".price");
var amountEl = plan.querySelector("[data-amount]");
var billedEl = plan.querySelector("[data-billed]");
var value = parseInt(priceBox.getAttribute("data-" + period), 10);
animateAmount(amountEl, value);
if (period === "quarterly") {
billedEl.textContent = "$" + value * 3 + " billed every 3 months";
} else {
billedEl.textContent = "Billed monthly";
}
});
}
buttons.forEach(function (b) {
b.addEventListener("click", function () {
if (b.dataset.period !== currentPeriod) render(b.dataset.period);
});
});
/* --- CTA selection --- */
plans.forEach(function (plan) {
var cta = plan.querySelector("[data-cta]");
var name = plan.dataset.plan;
function choose() {
plans.forEach(function (p) {
p.style.removeProperty("--picked");
});
var label =
currentPeriod === "quarterly" ? "quarterly billing" : "monthly billing";
toast("Nice — " + name + " plan selected (" + label + ").");
}
cta.addEventListener("click", function (e) {
e.stopPropagation();
choose();
});
/* Whole card is keyboard-activatable */
plan.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
choose();
}
});
});
render("monthly");
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Forge — Coaching Plans</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&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<main class="wrap">
<header class="head">
<span class="eyebrow">Forge Athletics</span>
<h1>Pick your training intensity</h1>
<p class="sub">
Coaching that scales with your goals. Cancel anytime, keep the momentum.
</p>
<div class="billing" role="group" aria-label="Billing period">
<div class="toggle" id="toggle">
<button
class="toggle-btn is-active"
data-period="monthly"
aria-pressed="true"
>
Monthly
</button>
<button
class="toggle-btn"
data-period="quarterly"
aria-pressed="false"
>
Quarterly
<span class="mini-pill">Save 20%</span>
</button>
<span class="toggle-thumb" aria-hidden="true"></span>
</div>
</div>
</header>
<section class="grid" aria-label="Coaching plans">
<!-- SELF -->
<article class="plan" tabindex="0" data-plan="Self">
<div class="plan-top">
<span class="tier">Self</span>
<p class="tier-desc">Train solo with the full app and library.</p>
</div>
<div class="price" data-monthly="29" data-quarterly="23">
<span class="cur">$</span>
<span class="amount" data-amount>29</span>
<span class="per">/mo</span>
</div>
<p class="billed" data-billed>Billed monthly</p>
<ul class="feats">
<li class="on">Full workout library (400+ sessions)</li>
<li class="on">Adaptive weekly training plan</li>
<li class="on">Progress & PR tracking</li>
<li class="on">Community leaderboard</li>
<li class="off">Form check video reviews</li>
<li class="off">1-on-1 coach calls</li>
</ul>
<button class="cta ghost" data-cta>Start Self</button>
</article>
<!-- GUIDED (popular) -->
<article class="plan popular" tabindex="0" data-plan="Guided">
<span class="badge">Most Popular</span>
<div class="plan-top">
<span class="tier">Guided</span>
<p class="tier-desc">Coach-built blocks with weekly check-ins.</p>
</div>
<div class="price" data-monthly="59" data-quarterly="47">
<span class="cur">$</span>
<span class="amount" data-amount>59</span>
<span class="per">/mo</span>
</div>
<p class="billed" data-billed>Billed monthly</p>
<ul class="feats">
<li class="on">Everything in Self</li>
<li class="on">Personalized 4-week blocks</li>
<li class="on">Form check video reviews</li>
<li class="on">Weekly async coach check-in</li>
<li class="on">Nutrition macro targets</li>
<li class="off">1-on-1 coach calls</li>
</ul>
<button class="cta" data-cta>Choose Guided</button>
</article>
<!-- 1-ON-1 -->
<article class="plan" tabindex="0" data-plan="1-on-1">
<div class="plan-top">
<span class="tier">1-on-1</span>
<p class="tier-desc">A dedicated coach in your corner, all in.</p>
</div>
<div class="price" data-monthly="129" data-quarterly="103">
<span class="cur">$</span>
<span class="amount" data-amount>129</span>
<span class="per">/mo</span>
</div>
<p class="billed" data-billed>Billed monthly</p>
<ul class="feats">
<li class="on">Everything in Guided</li>
<li class="on">Dedicated named coach</li>
<li class="on">Two 30-min calls / month</li>
<li class="on">Daily message support</li>
<li class="on">Custom meal plan</li>
<li class="on">Injury & mobility protocols</li>
</ul>
<button class="cta ghost" data-cta>Go 1-on-1</button>
</article>
</section>
<p class="foot">
Every plan starts with a 7-day free trial. No equipment lock-in, no
contracts.
</p>
</main>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>A high-energy pricing block built for a personal-training brand. Three coaching tiers — Self, Guided, and 1-on-1 — sit side by side, each with an uppercase display heading, a price that reads at a glance, a feature checklist with lime check marks, and a full-width call to action. The middle card carries a glowing “Most Popular” badge and an outer lime aura so the recommended plan pulls the eye first.
A monthly/quarterly segmented toggle sits above the grid. Flipping it re-renders every price with a quick count animation, swaps the per-period suffix, and reveals a “Save 20%” pill on the quarterly view. Prices are stored as data on each card so the script stays declarative and easy to extend with more tiers.
Every interactive element is keyboard reachable with a visible lime focus ring, cards lift and brighten on hover, and choosing a plan fires a small toast confirming the selection. The layout collapses to a single stacked column under 520px while keeping the popular card’s emphasis intact.