biggfitt / index.html
biggdadda's picture
Add 1 files
b657284 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SmartFit: AI Workout Generator</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.pulse-animation {
animation: pulse 2s infinite;
}
.exercise-card {
transition: all 0.3s ease;
}
.exercise-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(79, 70, 229, 0.15);
}
.fade-in {
animation: fadeIn 0.5s ease-in forwards;
opacity: 0;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.progress-ring__circle {
transition: stroke-dashoffset 0.75s ease-in-out;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
.input-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background: #4f46e5;
cursor: pointer;
}
.input-slider::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
background: #4f46e5;
cursor: pointer;
}
</style>
</head>
<body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<header class="text-center mb-12">
<h1 class="text-4xl md:text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-indigo-600 to-purple-600 mb-2">SmartFit</h1>
<p class="text-lg text-gray-600 max-w-2xl mx-auto">Generate personalized workouts tailored to your fitness goals and body metrics</p>
</header>
<div class="max-w-5xl mx-auto bg-white rounded-2xl shadow-xl overflow-hidden">
<div class="md:flex">
<!-- Input Section -->
<div class="md:w-2/5 p-8 bg-gradient-to-br from-indigo-600 to-purple-600 text-white">
<h2 class="text-2xl font-bold mb-6 flex items-center">
<i class="fas fa-cog mr-2"></i> Workout Settings
</h2>
<div class="space-y-6">
<div>
<label class="block text-sm font-medium mb-2">Calories to Burn</label>
<div class="relative">
<input type="number" id="calories" min="100" max="1500" step="50" value="400"
class="w-full px-4 py-3 rounded-xl bg-indigo-500/50 border border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-300 focus:border-transparent">
<span class="absolute right-4 top-3.5 text-indigo-200">kcal</span>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-2">Duration (minutes)</label>
<input type="range" id="duration" min="10" max="90" value="30" step="5"
class="w-full h-2 bg-indigo-500/50 rounded-lg appearance-none cursor-pointer input-slider">
<div class="flex justify-between text-xs text-indigo-200 mt-1">
<span>10 min</span>
<span id="duration-value">30 min</span>
<span>90 min</span>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium mb-2">Age</label>
<div class="relative">
<input type="number" id="age" min="16" max="80" value="30"
class="w-full px-4 py-3 rounded-xl bg-indigo-500/50 border border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-300 focus:border-transparent">
<span class="absolute right-4 top-3.5 text-indigo-200">yrs</span>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-2">Weight</label>
<div class="relative">
<input type="number" id="weight" min="40" max="150" value="70"
class="w-full px-4 py-3 rounded-xl bg-indigo-500/50 border border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-300 focus:border-transparent">
<span class="absolute right-4 top-3.5 text-indigo-200">kg</span>
</div>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-2">Workout Type</label>
<div class="grid grid-cols-3 gap-2">
<button class="type-btn active px-3 py-2 rounded-xl bg-indigo-800 text-white text-sm flex items-center justify-center" data-type="fullbody">
<i class="fas fa-running mr-1"></i> Full Body
</button>
<button class="type-btn px-3 py-2 rounded-xl bg-indigo-500 hover:bg-indigo-700 text-white text-sm flex items-center justify-center" data-type="strength">
<i class="fas fa-dumbbell mr-1"></i> Strength
</button>
<button class="type-btn px-3 py-2 rounded-xl bg-indigo-500 hover:bg-indigo-700 text-white text-sm flex items-center justify-center" data-type="cardio">
<i class="fas fa-heartbeat mr-1"></i> Cardio
</button>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-2">Intensity Level</label>
<div class="flex justify-between">
<span class="text-xs text-indigo-200">Light</span>
<span class="text-xs text-indigo-200">Moderate</span>
<span class="text-xs text-indigo-200">Intense</span>
</div>
<input type="range" id="intensity" min="1" max="3" value="2" step="1"
class="w-full h-2 bg-indigo-500/50 rounded-lg appearance-none cursor-pointer input-slider mt-1">
</div>
<button id="generate-btn" class="w-full py-3 px-4 bg-white text-indigo-700 font-bold rounded-xl hover:bg-indigo-100 transition duration-300 flex items-center justify-center pulse-animation">
<i class="fas fa-bolt mr-2"></i> Generate Workout
</button>
</div>
</div>
<!-- Results Section -->
<div class="md:w-3/5 p-8 bg-white">
<div id="results-placeholder" class="h-full flex flex-col items-center justify-center py-12 text-center">
<div class="w-32 h-32 bg-indigo-100 rounded-full flex items-center justify-center mb-6">
<img src="https://cdn-icons-png.flaticon.com/512/3128/3128857.png" alt="Workout" class="w-20 h-20">
</div>
<h3 class="text-xl font-semibold text-gray-700 mb-2">Your Custom Workout Awaits</h3>
<p class="text-gray-500 max-w-md">Set your fitness parameters and click the generate button to create your personalized workout plan.</p>
</div>
<div id="results-container" class="hidden h-full">
<div class="flex justify-between items-center mb-6">
<div>
<h2 class="text-2xl font-bold text-gray-800">Your Workout Plan</h2>
<div class="flex items-center mt-1">
<span id="workout-type" class="px-2 py-1 rounded-full bg-indigo-100 text-indigo-800 text-xs font-medium mr-2">Full Body</span>
<span id="workout-intensity" class="px-2 py-1 rounded-full bg-purple-100 text-purple-800 text-xs font-medium">Moderate</span>
</div>
</div>
<div class="flex space-x-2">
<button id="save-btn" class="px-4 py-1 bg-indigo-100 text-indigo-700 rounded-lg text-sm hover:bg-indigo-200 transition flex items-center">
<i class="fas fa-bookmark mr-1"></i> Save
</button>
<button id="print-btn" class="px-4 py-1 bg-gray-100 text-gray-700 rounded-lg text-sm hover:bg-gray-200 transition flex items-center">
<i class="fas fa-print mr-1"></i> Print
</button>
</div>
</div>
<div class="flex items-center justify-between mb-6 p-5 bg-gradient-to-r from-indigo-50 to-purple-50 rounded-xl border border-indigo-100">
<div>
<h3 class="font-medium text-gray-700 flex items-center">
<i class="fas fa-chart-line text-indigo-500 mr-2"></i> Workout Summary
</h3>
<p class="text-sm text-gray-500" id="workout-summary"></p>
</div>
<div class="relative w-20 h-20">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path class="text-gray-200" d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831" fill="none" stroke-width="3" stroke="currentColor"/>
<path class="progress-ring__circle text-indigo-600" stroke-dasharray="100, 100" d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831" fill="none" stroke-width="3" stroke="currentColor"/>
<text x="18" y="22.5" class="text-sm font-bold fill-indigo-700" text-anchor="middle" id="calories-progress">0%</text>
</svg>
</div>
</div>
<div id="exercises-container" class="space-y-4 max-h-[400px] overflow-y-auto pr-2">
<!-- Exercises will be inserted here -->
</div>
</div>
</div>
</div>
</div>
<div class="mt-12 text-center text-gray-500 text-sm">
<p>Calorie calculations are estimates and may vary based on individual metabolism and intensity.</p>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const caloriesInput = document.getElementById('calories');
const durationInput = document.getElementById('duration');
const durationValue = document.getElementById('duration-value');
const ageInput = document.getElementById('age');
const weightInput = document.getElementById('weight');
const typeBtns = document.querySelectorAll('.type-btn');
const intensityInput = document.getElementById('intensity');
const generateBtn = document.getElementById('generate-btn');
const resultsPlaceholder = document.getElementById('results-placeholder');
const resultsContainer = document.getElementById('results-container');
const exercisesContainer = document.getElementById('exercises-container');
const workoutSummary = document.getElementById('workout-summary');
const workoutType = document.getElementById('workout-type');
const workoutIntensity = document.getElementById('workout-intensity');
const caloriesProgress = document.getElementById('calories-progress');
const saveBtn = document.getElementById('save-btn');
const printBtn = document.getElementById('print-btn');
let currentType = 'fullbody';
let currentIntensity = 2;
const intensityNames = ['Light', 'Moderate', 'Intense'];
// Update duration value display
durationInput.addEventListener('input', function() {
durationValue.textContent = `${this.value} min`;
});
// Update intensity display
intensityInput.addEventListener('input', function() {
currentIntensity = parseInt(this.value);
});
// Type button selection
typeBtns.forEach(btn => {
btn.addEventListener('click', function() {
typeBtns.forEach(b => b.classList.remove('active', 'bg-indigo-800'));
typeBtns.forEach(b => b.classList.add('bg-indigo-500', 'hover:bg-indigo-700'));
this.classList.add('active', 'bg-indigo-800');
this.classList.remove('bg-indigo-500', 'hover:bg-indigo-700');
currentType = this.dataset.type;
});
});
// Generate workout
generateBtn.addEventListener('click', generateWorkout);
// Save workout
saveBtn.addEventListener('click', function() {
const toast = document.createElement('div');
toast.className = 'fixed bottom-4 right-4 px-4 py-2 bg-green-500 text-white rounded-lg shadow-lg flex items-center';
toast.innerHTML = '<i class="fas fa-check-circle mr-2"></i> Workout saved to your profile!';
document.body.appendChild(toast);
setTimeout(() => {
toast.classList.add('opacity-0', 'transition-opacity', 'duration-300');
setTimeout(() => toast.remove(), 300);
}, 2000);
});
// Print workout
printBtn.addEventListener('click', function() {
window.print();
});
function generateWorkout() {
const calories = parseInt(caloriesInput.value);
const duration = parseInt(durationInput.value);
const age = parseInt(ageInput.value);
const weight = parseInt(weightInput.value);
// Validate inputs
if (isNaN(calories) || isNaN(duration) || isNaN(age) || isNaN(weight)) {
showError('Please fill in all fields with valid numbers');
return;
}
if (age < 16 || age > 80) {
showError('Please enter an age between 16 and 80');
return;
}
if (weight < 40 || weight > 150) {
showError('Please enter a weight between 40kg and 150kg');
return;
}
// Generate exercises
const exercises = generateExercises(calories, duration, weight, age);
// Display results
displayWorkout(exercises, calories, duration);
}
function showError(message) {
const errorEl = document.createElement('div');
errorEl.className = 'fixed top-4 right-4 px-4 py-2 bg-red-500 text-white rounded-lg shadow-lg flex items-center';
errorEl.innerHTML = `<i class="fas fa-exclamation-circle mr-2"></i> ${message}`;
document.body.appendChild(errorEl);
setTimeout(() => {
errorEl.classList.add('opacity-0', 'transition-opacity', 'duration-300');
setTimeout(() => errorEl.remove(), 300);
}, 3000);
}
function generateExercises(targetCalories, duration, weight, age) {
// Exercise database with MET values
const exerciseDB = {
fullbody: [
{ name: "Burpees", met: 8.0, sets: 3, reps: 15, rest: 30, desc: "Full-body explosive exercise", video: "https://www.youtube.com/embed/auBLPXO8Fww" },
{ name: "Jump Squats", met: 8.0, sets: 3, reps: 12, rest: 45, desc: "Plyometric squat variation", video: "https://www.youtube.com/embed/2R73dAs7QZk" },
{ name: "Mountain Climbers", met: 8.0, sets: 3, duration: "30 sec", rest: 30, desc: "Cardio and core exercise", video: "https://www.youtube.com/embed/cnyTQDSE884" },
{ name: "Kettlebell Swings", met: 8.0, sets: 3, reps: 20, rest: 45, desc: "Hip-hinging power movement", video: "https://www.youtube.com/embed/mKDIuUbH94Q" },
{ name: "Box Jumps", met: 7.5, sets: 3, reps: 10, rest: 60, desc: "Plyometric leg exercise", video: "https://www.youtube.com/embed/5yL9pERqeCE" },
],
strength: [
{ name: "Push-ups", met: 3.8, sets: 4, reps: 12, rest: 60, desc: "Classic chest exercise", video: "https://www.youtube.com/embed/IODxDxX7oi4" },
{ name: "Pull-ups", met: 4.0, sets: 3, reps: 8, rest: 90, desc: "Upper back development", video: "https://www.youtube.com/embed/eGo4IYlbE5g" },
{ name: "Dumbbell Squats", met: 5.0, sets: 4, reps: 12, rest: 60, desc: "Leg strengthening", video: "https://www.youtube.com/embed/ECxYgeX5o0s" },
{ name: "Shoulder Press", met: 4.5, sets: 3, reps: 10, rest: 75, desc: "Shoulder development", video: "https://www.youtube.com/embed/qEwKCR5JCog" },
{ name: "Deadlifts", met: 6.0, sets: 4, reps: 8, rest: 120, desc: "Posterior chain strength", video: "https://www.youtube.com/embed/VL5Ab0T07e4" },
],
cardio: [
{ name: "Running (6 mph)", met: 9.8, duration: "5 min", desc: "Moderate pace running", video: "https://www.youtube.com/embed/5hcm1boZE7Q" },
{ name: "Jump Rope", met: 10.0, duration: "3 min", desc: "High intensity skipping", video: "https://www.youtube.com/embed/1BZM2Vre5oc" },
{ name: "Rowing Machine", met: 7.0, duration: "10 min", desc: "Full-body cardio", video: "https://www.youtube.com/embed/GXi7x5qOavU" },
{ name: "Cycling (moderate)", met: 7.0, duration: "10 min", desc: "Steady state cycling", video: "https://www.youtube.com/embed/9Y_1K6NqMCQ" },
{ name: "Stair Climbing", met: 8.0, duration: "5 min", desc: "Lower body endurance", video: "https://www.youtube.com/embed/N4Bx7k8iiF0" },
]
};
// Adjust MET based on intensity (1-3 scale)
const intensityFactor = [0.8, 1.0, 1.2][currentIntensity - 1];
// Adjust for age (MET decreases slightly with age)
const ageFactor = 1 - ((age - 30) * 0.0025);
let availableExercises = [...exerciseDB[currentType]];
// Distribute exercises based on duration
const numExercises = Math.min(Math.max(
Math.floor(duration / (currentType === 'cardio' ? 5 : 7)),
3),
6
);
const exercises = [];
let remainingDuration = duration * 60; // Convert to seconds
let remainingCalories = targetCalories;
// If cardio, we'll do rounds of different cardio exercises
if (currentType === 'cardio') {
const rounds = Math.max(1, Math.min(3, Math.floor(duration / 15)));
const perRoundDuration = Math.floor(duration * 60 / rounds);
const perRoundCalories = Math.floor(targetCalories / rounds);
for (let round = 0; round < rounds; round++) {
// Select random cardio exercises for this round
const selected = [];
let roundDuration = 0;
let roundCalories = 0;
// Keep adding exercises until we reach about 80% of round duration
while (roundDuration < perRoundDuration * 0.8 && availableExercises.length > 0) {
const randomIndex = Math.floor(Math.random() * availableExercises.length);
const exercise = availableExercises[randomIndex];
const exDuration = parseInt(exercise.duration) * 60;
// Calculate calories for this exercise
const exCalories = Math.round(
(exercise.met * intensityFactor * ageFactor * weight * (parseInt(exercise.duration) / 60) * 3.5) / 200
);
selected.push({
...exercise,
duration: exercise.duration,
calories: exCalories,
isCardio: true
});
roundDuration += exDuration;
roundCalories += exCalories;
availableExercises.splice(randomIndex, 1);
}
// Add rest periods (20% of round time)
if (selected.length > 0) {
const restDuration = Math.floor(perRoundDuration * 0.2 / selected.length);
for (let i = 0; i < selected.length; i++) {
selected[i].rest = restDuration + " sec";
}
exercises.push({
name: `Cardio Round ${round + 1}`,
exercises: [...selected],
duration: roundDuration + (restDuration * selected.length),
calories: roundCalories,
isRound: true
});
}
}
}
else { // Strength or full body
for (let i = 0; i < numExercises; i++) {
// For the last exercise, use all remaining time
const isLast = i === numExercises - 1;
const targetExDuration = isLast ?
remainingDuration :
Math.max(
90,
Math.min(
600,
Math.floor(remainingDuration / (numExercises - i))
)
);
// Select random exercise
const randomIndex = Math.floor(Math.random() * availableExercises.length);
let exercise = availableExercises[randomIndex];
// Calculate total time for this exercise (sets * (rep time + rest))
// Assuming 4 seconds per rep and given rest time
const repTime = 4;
const totalExTime = exercise.sets * (
(exercise.reps ? (exercise.reps * repTime) : parseInt(exercise.duration)) +
(exercise.rest || 0)
);
// Scale sets if needed to fit target duration
let exDuration = totalExTime;
let scaledSets = exercise.sets;
if (exDuration > targetExDuration && exercise.sets > 1) {
scaledSets = Math.max(1, Math.floor(targetExDuration / (
(exercise.reps ? (exercise.reps * repTime) : parseInt(exercise.duration)) +
(exercise.rest || 0)
)));
exDuration = scaledSets * (
(exercise.reps ? (exercise.reps * repTime) : parseInt(exercise.duration)) +
(exercise.rest || 0)
);
}
// Calculate calories for this exercise
const activeTime = scaledSets * (exercise.reps ? (exercise.reps * repTime) : parseInt(exercise.duration));
const exCalories = Math.round(
(exercise.met * intensityFactor * ageFactor * weight * (activeTime / 3600) * 3.5) / 200
);
exercises.push({
...exercise,
sets: scaledSets,
duration: exDuration,
calories: exCalories
});
remainingDuration -= exDuration;
remainingCalories -= exCalories;
availableExercises.splice(randomIndex, 1);
if (availableExercises.length === 0) {
availableExercises = [...exerciseDB[currentType]]; // Reset if we run out
}
}
// Adjust last exercise to account for any remaining calories
if (exercises.length > 0 && remainingCalories > 0) {
const lastEx = exercises[exercises.length - 1];
const additionalSets = Math.min(
2,
Math.ceil(remainingCalories / (lastEx.calories / lastEx.sets))
);
if (additionalSets > 0) {
lastEx.sets += additionalSets;
const activeTime = additionalSets * (lastEx.reps ? (lastEx.reps * 4) : parseInt(lastEx.duration));
const additionalCalories = Math.round(
(lastEx.met * intensityFactor * ageFactor * weight * (activeTime / 3600) * 3.5) / 200
);
lastEx.calories += additionalCalories;
lastEx.duration += additionalSets * (
(lastEx.reps ? (lastEx.reps * 4) : parseInt(lastEx.duration)) +
(lastEx.rest || 0)
);
}
}
}
return exercises;
}
function displayWorkout(exercises, targetCalories, duration) {
// Hide placeholder, show results
resultsPlaceholder.classList.add('hidden');
resultsContainer.classList.remove('hidden');
// Update workout type and intensity display
workoutType.textContent = currentType === 'fullbody' ? 'Full Body' :
currentType === 'strength' ? 'Strength' : 'Cardio';
workoutIntensity.textContent = intensityNames[currentIntensity - 1];
// Calculate total calories and time from exercises
let totalCalories = exercises.reduce((sum, ex) => sum + (ex.calories || 0), 0);
const progressPercent = Math.min(100, Math.round((totalCalories / targetCalories) * 100));
// Update summary
workoutSummary.textContent = `${exercises.length} ${currentType === 'cardio' ? 'rounds' : 'exercises'}${duration} minutes • ~${totalCalories} calories`;
// Update progress circle
const circle = document.querySelector('.progress-ring__circle');
const radius = 16;
const circumference = radius * 2 * Math.PI;
const offset = circumference - (progressPercent / 100) * circumference;
circle.style.strokeDasharray = `${circumference} ${circumference}`;
circle.style.strokeDashoffset = offset;
caloriesProgress.textContent = `${progressPercent}%`;
// Clear previous exercises
exercisesContainer.innerHTML = '';
// Add exercises to DOM
exercises.forEach((exercise, index) => {
if (exercise.isRound) {
// This is a cardio round containing multiple exercises
const roundElement = document.createElement('div');
roundElement.className = 'exercise-card bg-white p-5 rounded-xl border-2 border-indigo-100 fade-in mb-4';
roundElement.style.animationDelay = `${index * 0.1}s`;
roundElement.innerHTML = `
<div class="flex justify-between items-center mb-3">
<h3 class="font-bold text-indigo-700 text-lg">${exercise.name}</h3>
<span class="px-2 py-1 rounded-full bg-indigo-100 text-indigo-800 text-xs font-medium">
Total: ${Math.floor(exercise.duration / 60)} min
</span>
</div>
<div class="bg-indigo-50 p-3 rounded-lg mb-3">
<div class="flex justify-between text-sm mb-2">
<span><i class="fas fa-fire text-indigo-500 mr-1"></i> ${exercise.calories} kcal</span>
</div>
<div class="flex justify-between text-xs text-gray-500">
<span>${exercise.exercises.length} exercises</span>
<span>${Math.floor(exercise.exercises[0].rest)} sec rest between</span>
</div>
</div>
<div class="space-y-3">
${exercise.exercises.map((ex, i) => `
<div class="flex items-start bg-gray-50 p-2 rounded-lg">
<div class="mr-3 mt-1">
<div class="w-8 h-8 rounded-full bg-red-100 flex items-center justify-center">
<i class="fas fa-heartbeat text-red-500 text-sm"></i>
</div>
</div>
<div class="flex-1">
<div class="flex justify-between items-start">
<h4 class="font-medium text-gray-800 text-sm">${ex.name}</h4>
</div>
<div class="flex justify-between text-xs text-gray-500 mt-1">
<span><i class="far fa-clock mr-1"></i> ${ex.duration}</span>
<span><i class="fas fa-stopwatch mr-1"></i> Rest: ${ex.rest}</span>
</div>
</div>
</div>
`).join('')}
</div>
`;
exercisesContainer.appendChild(roundElement);
} else {
// Regular exercise
const exerciseElement = document.createElement('div');
exerciseElement.className = 'exercise-card bg-white p-5 rounded-xl border border-gray-200 hover:border-indigo-300 fade-in';
exerciseElement.style.animationDelay = `${index * 0.1}s`;
// Get icon and color based on type
let iconClass, bgColor, textColor;
if (currentType === 'cardio') {
iconClass = 'fas fa-heartbeat';
bgColor = 'red';
textColor = 'red';
} else if (currentType === 'strength') {
iconClass = 'fas fa-dumbbell';
bgColor = 'blue';
textColor = 'blue';
} else {
iconClass = 'fas fa-running';
bgColor = 'purple';
textColor = 'purple';
}
exerciseElement.innerHTML = `
<div class="flex items-start">
<div class="mr-4">
<div class="w-12 h-12 rounded-xl bg-${bgColor}-100 flex items-center justify-center">
<i class="${iconClass} text-${textColor}-500"></i>
</div>
</div>
<div class="flex-1">
<div class="flex justify-between items-start">
<h3 class="font-bold text-gray-800">${exercise.name}</h3>
<div class="flex space-x-2">
${exercise.sets ? `<span class="px-2 py-0.5 rounded-full bg-gray-100 text-gray-800 text-xs font-medium">${exercise.sets}x sets</span>` : ''}
<span class="px-2 py-0.5 rounded-full bg-${bgColor}-100 text-${textColor}-800 text-xs font-medium">
${Math.floor(exercise.duration / 60)} min
</span>
</div>
</div>
<p class="text-xs text-gray-500 mt-1">${exercise.desc}</p>
<div class="mt-3">
<div class="flex justify-between text-sm">
<span class="flex items-center"><i class="fas fa-fire text-${textColor}-500 mr-1"></i> ~${exercise.calories} kcal</span>
${exercise.reps ? `<span class="flex items-center"><i class="fas fa-redo text-${textColor}-500 mr-1"></i> ${exercise.reps} reps</span>` : ''}
${exercise.rest ? `<span class="flex items-center"><i class="fas fa-stopwatch text-${textColor}-500 mr-1"></i> ${exercise.rest} sec rest</span>` : ''}
</div>
</div>
<div class="mt-3">
<details class="text-sm">
<summary class="text-${textColor}-600 font-medium cursor-pointer">Show demonstration</summary>
<div class="mt-2 aspect-w-16 aspect-h-9">
<iframe class="w-full h-48 rounded-lg" src="${exercise.video}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
</details>
</div>
</div>
</div>
`;
exercisesContainer.appendChild(exerciseElement);
}
});
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - <a href="https://enzostvs-deepsite.hf.space?remix=biggdadda/biggfitt" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
</html>