SpaceXAI Grok Build 0.1 – Food and Drink
via xAI · Generated
- AIMAC Debt 39.07
- Cost $0.06
- Total Violations 27
- HTML Size 90 KB
- Em Dashes 3
Screenshot
View Live Page
Accessibility Issues Found
18 Critical 9 Serious
-
button-name critical 14 instances
Buttons must have discernible text
Example HTML
<button onclick="quickAddToPlanner('1')" class="px-3 py-2.5 text-sm font-semibold border border-stone-200 hover:bg-stone-50 text-stone-700 rounded-... -
color-contrast serious 6 instances
Elements must meet minimum color contrast ratio thresholds
Example HTML
<div class="text-xs text-stone-400 py-3 text-center">No meals planned</div> -
link-name serious 3 instances
Links must have discernible text
Example HTML
<a href="#" class="hover:text-white"><i class="fa-brands fa-instagram text-lg"></i></a> -
select-name critical 4 instances
Select element must have an accessible name
Example HTML
<select class="text-xs border border-stone-200 bg-white px-2 py-1 rounded-xl text-stone-600" id="select-1">
Artifacts
View Generated HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Harvest & Hearth • Recipes, Guides & Culinary Wisdom</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Inter:wght@300;400;500;600&display=swap');
:root {
--primary: #854d0e;
}
body {
font-family: 'Inter', system_ui, sans-serif;
}
.heading-serif {
font-family: 'Playfair Display', Georgia, serif;
font-weight: 700;
line-height: 1.1;
}
.food-gradient {
background: linear-gradient(135deg, #854d0e 0%, #451a03 100%);
}
.nav-link {
transition: all 0.2s ease;
}
.nav-link:hover {
color: #854d0e;
transform: translateY(-1px);
}
.recipe-card {
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
box-shadow 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
}
.recipe-card:hover {
transform: translateY(-8px);
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
}
.section-header {
position: relative;
display: inline-block;
}
.section-header:after {
content: '';
position: absolute;
bottom: -8px;
left: 0;
width: 60px;
height: 3px;
background: linear-gradient(to right, #854d0e, #d97706);
border-radius: 3px;
}
.modern-shadow {
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.05),
0 4px 6px -4px rgb(0 0 0 / 0.05);
}
.nav-active {
color: #854d0e;
font-weight: 600;
}
.flavor-tag {
font-size: 0.75rem;
padding: 1px 10px;
border-radius: 9999px;
background-color: #fef3c7;
color: #854d0e;
font-weight: 500;
}
.content-rich p {
line-height: 1.75;
}
.meal-plan-day {
transition: all 0.2s ease;
}
.testimonial-card {
transition: transform 0.3s ease;
}
.nav-scrolled {
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
}
.food-image {
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.recipe-card:hover .food-image {
transform: scale(1.05);
}
.accordion-header {
transition: background-color 0.2s ease;
}
.accordion-header:hover {
background-color: #fefce8;
}
.stat-number {
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body class="bg-stone-50 text-stone-800">
<!-- HEADER / NAV -->
<header class="bg-white border-b border-stone-200 sticky top-0 z-50">
<div class="max-w-screen-2xl mx-auto">
<div class="px-8 py-5 flex items-center justify-between">
<!-- Logo -->
<div class="flex items-center gap-x-3">
<div class="flex items-center justify-center w-11 h-11 bg-amber-900 rounded-2xl shadow-inner overflow-hidden">
<img src="https://placehold.co/44x44/451a03/fff?text=H&H&font=playfair+display"
alt="Harvest & Hearth logo" class="w-11 h-11 object-cover">
</div>
<div>
<span class="font-bold text-3xl tracking-tighter heading-serif text-stone-900">Harvest</span>
<span class="font-bold text-3xl tracking-tighter heading-serif text-amber-800">& Hearth</span>
</div>
</div>
<!-- Desktop Navigation -->
<nav class="hidden md:flex items-center gap-x-7 text-sm font-medium">
<a href="#recipes" class="nav-link px-3 py-2 text-stone-700 hover:text-amber-800">Recipes</a>
<a href="#guides" class="nav-link px-3 py-2 text-stone-700 hover:text-amber-800">Guides</a>
<a href="#catering" class="nav-link px-3 py-2 text-stone-700 hover:text-amber-800">Catering</a>
<a href="#events" class="nav-link px-3 py-2 text-stone-700 hover:text-amber-800">Events</a>
<a href="#tips" class="nav-link px-3 py-2 text-stone-700 hover:text-amber-800">Nutrition</a>
<a href="#testimonials" class="nav-link px-3 py-2 text-stone-700 hover:text-amber-800">Community</a>
<a href="#faq" class="nav-link px-3 py-2 text-stone-700 hover:text-amber-800">Blog</a>
</nav>
<!-- Header Actions -->
<div class="flex items-center gap-x-3">
<div class="hidden md:flex items-center bg-stone-100 rounded-3xl px-1 py-1 text-sm">
<div class="flex items-center px-3">
<i class="fa-solid fa-search text-stone-400 mr-2"></i>
<input type="text" placeholder="Search recipes..."
class="bg-transparent border-none outline-none text-sm w-36 placeholder-stone-400">
</div>
</div>
<button onclick="showSubscribeModal()"
class="hidden md:flex items-center px-5 py-2.5 text-sm font-semibold bg-amber-900 hover:bg-amber-950 transition-colors text-white rounded-3xl">
<span>Subscribe</span>
</button>
<!-- Mobile menu -->
<button id="mobile-menu-btn"
class="md:hidden w-10 h-10 flex items-center justify-center text-stone-700 hover:text-stone-900"
onclick="toggleMobileMenu()">
<i class="fa-solid fa-bars text-xl"></i>
</button>
</div>
</div>
</div>
<!-- Mobile Navigation -->
<div id="mobile-menu" class="hidden md:hidden bg-white border-t border-stone-200 px-5 py-4">
<div class="flex flex-col gap-y-1 text-sm font-medium">
<a href="#recipes" class="nav-link px-4 py-3 text-stone-700 hover:bg-stone-100 rounded-2xl">Recipes</a>
<a href="#guides" class="nav-link px-4 py-3 text-stone-700 hover:bg-stone-100 rounded-2xl">Guides</a>
<a href="#catering" class="nav-link px-4 py-3 text-stone-700 hover:bg-stone-100 rounded-2xl">Catering</a>
<a href="#events" class="nav-link px-4 py-3 text-stone-700 hover:bg-stone-100 rounded-2xl">Events</a>
<a href="#tips" class="nav-link px-4 py-3 text-stone-700 hover:bg-stone-100 rounded-2xl">Nutrition</a>
<a href="#testimonials" class="nav-link px-4 py-3 text-stone-700 hover:bg-stone-100 rounded-2xl">Community</a>
<a href="#faq" class="nav-link px-4 py-3 text-stone-700 hover:bg-stone-100 rounded-2xl">Blog</a>
<div class="pt-3 border-t mt-1">
<button onclick="showSubscribeModal()"
class="w-full flex items-center justify-center px-5 py-3 text-sm font-semibold bg-amber-900 hover:bg-amber-950 transition-colors text-white rounded-3xl">
Subscribe to Newsletter
</button>
</div>
</div>
</div>
</header>
<!-- HERO SECTION -->
<section class="relative bg-stone-900 text-white overflow-hidden">
<div class="max-w-screen-2xl mx-auto">
<div class="grid md:grid-cols-12 items-center">
<!-- Hero Content -->
<div class="md:col-span-7 px-8 md:pl-16 pt-12 pb-10 md:pt-16 md:pb-16">
<div class="max-w-xl">
<div class="inline-flex items-center gap-x-2 bg-white/10 backdrop-blur-md px-4 py-1.5 rounded-3xl mb-6">
<div class="w-2 h-2 bg-emerald-400 rounded-full animate-pulse"></div>
<span class="text-sm font-medium tracking-wider">2025 James Beard Award Nominee</span>
</div>
<h1 class="text-6xl md:text-6xl leading-[1.05] tracking-tighter heading-serif font-bold mb-4">
Timeless recipes.<br>
Modern flavor.
</h1>
<p class="max-w-md text-lg text-stone-300 mb-8">
Expert guidance for the home cook and professional chef.
Discover seasonal menus, master techniques, and explore the world of food & drink.
</p>
<div class="flex flex-wrap items-center gap-3">
<a href="#recipes"
class="inline-flex items-center justify-center gap-x-2 px-7 py-4 bg-white text-stone-900 hover:bg-amber-50 transition-all font-semibold rounded-3xl shadow-lg text-sm">
<span>Browse Recipes</span>
<i class="fa-solid fa-arrow-right"></i>
</a>
<button onclick="document.getElementById('planner').scrollIntoView({ behavior: 'smooth' })"
class="inline-flex items-center justify-center gap-x-2 px-6 py-4 border border-white/30 hover:bg-white/10 transition-all font-semibold rounded-3xl text-sm">
<i class="fa-solid fa-calendar mr-2"></i>
<span>Try Meal Planner</span>
</button>
</div>
<div class="flex items-center gap-x-5 mt-8">
<div class="flex -space-x-2">
<img src="https://i.pravatar.cc/28?u=chef1" class="w-7 h-7 rounded-full ring-2 ring-stone-800 object-cover" alt="">
<img src="https://i.pravatar.cc/28?u=chef2" class="w-7 h-7 rounded-full ring-2 ring-stone-800 object-cover" alt="">
<img src="https://i.pravatar.cc/28?u=chef3" class="w-7 h-7 rounded-full ring-2 ring-stone-800 object-cover" alt="">
</div>
<span class="text-xs text-stone-300">Joined by <span class="font-semibold text-white">48,291</span> home chefs this month</span>
</div>
</div>
</div>
<!-- Hero Image -->
<div class="md:col-span-5 relative">
<img src="https://picsum.photos/id/1016/900/1100"
alt="Beautifully plated seasonal dish with fresh herbs and wine on a rustic wooden table"
class="w-full h-[520px] md:h-[620px] object-cover md:rounded-bl-[80px]">
<div class="absolute bottom-8 left-8 bg-white/95 backdrop-blur px-4 py-3 rounded-3xl shadow-xl hidden md:block">
<div class="flex items-center gap-x-3">
<div>
<div class="text-xs text-stone-500">Today's featured</div>
<div class="font-semibold text-sm">Braised Short Ribs</div>
</div>
<div class="text-emerald-600">
<i class="fa-solid fa-star"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- TRUST BAR -->
<div class="bg-white border-b border-stone-200 py-4">
<div class="max-w-screen-2xl mx-auto px-8">
<div class="flex flex-wrap items-center justify-center gap-x-8 gap-y-2 text-xs md:text-sm">
<div class="flex items-center gap-x-2 text-stone-500">
<i class="fa-solid fa-check-circle text-emerald-700"></i>
<span class="font-medium">Featured in Food & Wine</span>
</div>
<div class="flex items-center gap-x-2 text-stone-500">
<i class="fa-solid fa-check-circle text-emerald-700"></i>
<span class="font-medium">James Beard Foundation</span>
</div>
<div class="flex items-center gap-x-2 text-stone-500">
<i class="fa-solid fa-check-circle text-emerald-700"></i>
<span class="font-medium">Michelin Guide Recommended</span>
</div>
</div>
</div>
</div>
<!-- FEATURED RECIPES SECTION -->
<section id="recipes" class="max-w-screen-2xl mx-auto px-8 pt-14 pb-8">
<div class="flex items-end justify-between mb-8">
<div>
<span class="text-xs tracking-[1.5px] font-semibold text-amber-700">SEASONAL COLLECTION</span>
<h2 class="heading-serif text-4xl tracking-tighter font-bold text-stone-900">Featured Recipes</h2>
</div>
<a href="#" class="hidden md:flex items-center gap-x-2 text-sm font-semibold text-amber-800 hover:text-amber-900">
View all recipes <i class="fa-solid fa-arrow-right ml-1"></i>
</a>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
<!-- Recipe Card 1 -->
<div class="recipe-card bg-white rounded-3xl overflow-hidden border border-stone-100 shadow-sm group">
<div class="relative">
<img src="https://picsum.photos/id/292/400/240"
class="w-full h-52 object-cover food-image" alt="Braised short ribs with rich wine sauce and root vegetables">
<div class="absolute top-3 right-3">
<span class="flavor-tag px-2.5 py-0.5 text-xs">Umami-rich</span>
</div>
</div>
<div class="p-5">
<div class="flex items-center justify-between mb-2">
<h3 class="font-semibold text-xl leading-tight">Braised Short Ribs</h3>
</div>
<p class="text-stone-600 text-sm mb-4 line-clamp-2">Slow-braised in red wine and aromatics until the meat melts from the bone. A true celebration of deep, savory flavor.</p>
<div class="flex items-center text-xs text-stone-500 gap-x-4 mb-4">
<div class="flex items-center">
<i class="fa-solid fa-clock mr-1.5"></i>
<span>3 hrs</span>
</div>
<div class="flex items-center">
<i class="fa-solid fa-users mr-1.5"></i>
<span>Serves 4</span>
</div>
</div>
<div class="flex gap-2">
<button onclick="showRecipeModal('1')"
class="flex-1 px-4 py-2.5 text-sm font-semibold bg-stone-900 hover:bg-stone-800 transition-colors text-white rounded-2xl text-center">
Try Recipe
</button>
<button onclick="quickAddToPlanner('1')"
class="px-3 py-2.5 text-sm font-semibold border border-stone-200 hover:bg-stone-50 text-stone-700 rounded-2xl transition-colors">
<i class="fa-solid fa-plus"></i>
</button>
</div>
</div>
</div>
<!-- Recipe Card 2 -->
<div class="recipe-card bg-white rounded-3xl overflow-hidden border border-stone-100 shadow-sm group">
<div class="relative">
<img src="https://picsum.photos/id/312/400/240"
class="w-full h-52 object-cover food-image" alt="Pan seared scallops with golden brown crust and mushroom sauce">
<div class="absolute top-3 right-3">
<span class="flavor-tag px-2.5 py-0.5 text-xs">Seafood</span>
</div>
</div>
<div class="p-5">
<div class="flex items-center justify-between mb-2">
<h3 class="font-semibold text-xl leading-tight">Seared Scallops</h3>
</div>
<p class="text-stone-600 text-sm mb-4 line-clamp-2">Perfectly caramelized scallops finished with a savory mushroom and shallot sauce that highlights natural umami.</p>
<div class="flex items-center text-xs text-stone-500 gap-x-4 mb-4">
<div class="flex items-center">
<i class="fa-solid fa-clock mr-1.5"></i>
<span>15 min</span>
</div>
<div class="flex items-center">
<i class="fa-solid fa-users mr-1.5"></i>
<span>Serves 2</span>
</div>
</div>
<div class="flex gap-2">
<button onclick="showRecipeModal('2')"
class="flex-1 px-4 py-2.5 text-sm font-semibold bg-stone-900 hover:bg-stone-800 transition-colors text-white rounded-2xl text-center">
Try Recipe
</button>
<button onclick="quickAddToPlanner('2')"
class="px-3 py-2.5 text-sm font-semibold border border-stone-200 hover:bg-stone-50 text-stone-700 rounded-2xl transition-colors">
<i class="fa-solid fa-plus"></i>
</button>
</div>
</div>
</div>
<!-- Recipe Card 3 -->
<div class="recipe-card bg-white rounded-3xl overflow-hidden border border-stone-100 shadow-sm group">
<div class="relative">
<img src="https://picsum.photos/id/201/400/240"
class="w-full h-52 object-cover food-image" alt="Creamy wild mushroom risotto with parmesan shavings">
<div class="absolute top-3 right-3">
<span class="flavor-tag px-2.5 py-0.5 text-xs">Vegetarian</span>
</div>
</div>
<div class="p-5">
<div class="flex items-center justify-between mb-2">
<h3 class="font-semibold text-xl leading-tight">Wild Mushroom Risotto</h3>
</div>
<p class="text-stone-600 text-sm mb-4 line-clamp-2">Creamy Arborio rice slowly stirred with a medley of wild mushrooms, finished with aged parmesan and fresh thyme.</p>
<div class="flex items-center text-xs text-stone-500 gap-x-4 mb-4">
<div class="flex items-center">
<i class="fa-solid fa-clock mr-1.5"></i>
<span>35 min</span>
</div>
<div class="flex items-center">
<i class="fa-solid fa-users mr-1.5"></i>
<span>Serves 4</span>
</div>
</div>
<div class="flex gap-2">
<button onclick="showRecipeModal('3')"
class="flex-1 px-4 py-2.5 text-sm font-semibold bg-stone-900 hover:bg-stone-800 transition-colors text-white rounded-2xl text-center">
Try Recipe
</button>
<button onclick="quickAddToPlanner('3')"
class="px-3 py-2.5 text-sm font-semibold border border-stone-200 hover:bg-stone-50 text-stone-700 rounded-2xl transition-colors">
<i class="fa-solid fa-plus"></i>
</button>
</div>
</div>
</div>
<!-- Recipe Card 4 -->
<div class="recipe-card bg-white rounded-3xl overflow-hidden border border-stone-100 shadow-sm group">
<div class="relative">
<img src="https://picsum.photos/id/251/400/240"
class="w-full h-52 object-cover food-image" alt="Herb roasted whole chicken with lemon and root vegetables">
<div class="absolute top-3 right-3">
<span class="flavor-tag px-2.5 py-0.5 text-xs">Classic</span>
</div>
</div>
<div class="p-5">
<div class="flex items-center justify-between mb-2">
<h3 class="font-semibold text-xl leading-tight">Herb Roasted Chicken</h3>
</div>
<p class="text-stone-600 text-sm mb-4 line-clamp-2">A perfectly roasted bird with crispy skin, infused with lemon, rosemary and thyme. Ideal for family gatherings.</p>
<div class="flex items-center text-xs text-stone-500 gap-x-4 mb-4">
<div class="flex items-center">
<i class="fa-solid fa-clock mr-1.5"></i>
<span>1 hr 30 min</span>
</div>
<div class="flex items-center">
<i class="fa-solid fa-users mr-1.5"></i>
<span>Serves 4</span>
</div>
</div>
<div class="flex gap-2">
<button onclick="showRecipeModal('4')"
class="flex-1 px-4 py-2.5 text-sm font-semibold bg-stone-900 hover:bg-stone-800 transition-colors text-white rounded-2xl text-center">
Try Recipe
</button>
<button onclick="quickAddToPlanner('4')"
class="px-3 py-2.5 text-sm font-semibold border border-stone-200 hover:bg-stone-50 text-stone-700 rounded-2xl transition-colors">
<i class="fa-solid fa-plus"></i>
</button>
</div>
</div>
</div>
</div>
<div class="mt-6 text-center md:text-right">
<a href="#" class="inline-flex md:hidden items-center text-sm font-semibold text-amber-800">View full recipe archive →</a>
</div>
</section>
<!-- CULINARY TIPS & NUTRITION SECTION -->
<section id="tips" class="max-w-screen-2xl mx-auto px-8 py-12 bg-white border-y border-stone-100">
<div class="grid lg:grid-cols-12 gap-x-8 gap-y-10">
<!-- Main Tips Content -->
<div class="lg:col-span-8">
<div class="mb-8">
<span class="text-xs tracking-[1.5px] font-semibold text-amber-700">MASTER THE CRAFT</span>
<h2 class="heading-serif text-4xl tracking-tighter font-bold text-stone-900">Expert Cooking Tips</h2>
<p class="mt-2 max-w-lg text-stone-600">Techniques and insights from our team of chefs to elevate your cooking.</p>
</div>
<div class="grid md:grid-cols-3 gap-5">
<!-- Tip 1 -->
<div class="border border-stone-200 p-5 rounded-3xl bg-stone-50">
<div class="flex items-center mb-3">
<div class="w-8 h-8 bg-amber-100 flex items-center justify-center rounded-2xl">
<i class="fa-solid fa-fire text-amber-700"></i>
</div>
</div>
<h4 class="font-semibold mb-1.5">Perfect Braising</h4>
<p class="text-sm text-stone-600">For fall-apart tender results, always sear your protein first. Deglaze the pan with wine or stock to capture all the fond, then braise low and slow at 325°F.</p>
<div class="mt-3 text-xs">
<span class="inline px-2 py-1 bg-white text-stone-500 rounded-2xl text-[10px]">3.2k cooks learned this</span>
</div>
</div>
<!-- Tip 2 -->
<div class="border border-stone-200 p-5 rounded-3xl bg-stone-50">
<div class="flex items-center mb-3">
<div class="w-8 h-8 bg-emerald-100 flex items-center justify-center rounded-2xl">
<i class="fa-solid fa-leaf text-emerald-700"></i>
</div>
</div>
<h4 class="font-semibold mb-1.5">Building Umami</h4>
<p class="text-sm text-stone-600">Layer flavors with miso, dried mushrooms, and aged parmesan. A splash of fish sauce or soy at the end of sautéing brings depth to vegetarian dishes without overpowering.</p>
<div class="mt-3 text-xs">
<span class="inline px-2 py-1 bg-white text-stone-500 rounded-2xl text-[10px]">4.8k cooks learned this</span>
</div>
</div>
<!-- Tip 3 -->
<div class="border border-stone-200 p-5 rounded-3xl bg-stone-50">
<div class="flex items-center mb-3">
<div class="w-8 h-8 bg-sky-100 flex items-center justify-center rounded-2xl">
<i class="fa-solid fa-wine-glass text-sky-700"></i>
</div>
</div>
<h4 class="font-semibold mb-1.5">Food & Drink Pairing</h4>
<p class="text-sm text-stone-600">Match acidity with acidity and fat with tannin. For rich braised dishes, choose medium-bodied reds with good acidity. Rosé pairs beautifully with sautéed scallops.</p>
<div class="mt-3 text-xs">
<span class="inline px-2 py-1 bg-white text-stone-500 rounded-2xl text-[10px]">2.9k cooks learned this</span>
</div>
</div>
</div>
</div>
<!-- Nutrition Sidebar -->
<div class="lg:col-span-4 bg-stone-900 text-white rounded-3xl p-6">
<div class="mb-5">
<span class="px-3 py-1 bg-white/10 text-xs rounded-3xl">NUTRITION FOCUS</span>
</div>
<h3 class="font-semibold text-xl mb-2">The Science of Flavor</h3>
<p class="text-stone-300 text-sm mb-5">Understanding macronutrients helps create balanced, satisfying meals that support long-term health.</p>
<div class="space-y-4">
<div>
<div class="flex justify-between text-sm mb-1">
<span class="font-medium">Protein</span>
<span class="text-emerald-300">25-30g</span>
</div>
<div class="h-1.5 bg-white/20 rounded-full">
<div class="h-1.5 w-[78%] bg-emerald-300 rounded-full"></div>
</div>
</div>
<div>
<div class="flex justify-between text-sm mb-1">
<span class="font-medium">Healthy Fats</span>
<span class="text-emerald-300">18-22g</span>
</div>
<div class="h-1.5 bg-white/20 rounded-full">
<div class="h-1.5 w-[65%] bg-emerald-300 rounded-full"></div>
</div>
</div>
<div>
<div class="flex justify-between text-sm mb-1">
<span class="font-medium">Fiber</span>
<span class="text-emerald-300">8-12g</span>
</div>
<div class="h-1.5 bg-white/20 rounded-full">
<div class="h-1.5 w-[85%] bg-emerald-300 rounded-full"></div>
</div>
</div>
</div>
<div class="mt-6 pt-5 border-t border-white/20">
<button onclick="document.getElementById('planner').scrollIntoView({ behavior: 'smooth' })"
class="w-full flex items-center justify-center gap-x-2 text-sm bg-white/10 hover:bg-white/20 transition-colors py-3 rounded-2xl text-center font-medium">
<span>Balance your next meal</span>
</button>
</div>
</div>
</div>
</section>
<!-- INTERACTIVE MEAL PLANNER -->
<section id="planner" class="max-w-screen-2xl mx-auto px-8 py-14">
<div class="flex flex-col lg:flex-row lg:items-end lg:justify-between mb-8">
<div>
<span class="text-xs tracking-[1.5px] font-semibold text-amber-700">PERSONALIZED PLANNING</span>
<h2 class="heading-serif text-4xl tracking-tighter font-bold">Weekly Meal Planner</h2>
<p class="mt-1 text-stone-600 max-w-md">Curate your week. Our planner automatically builds your shopping list.</p>
</div>
<div class="mt-4 lg:mt-0">
<button onclick="generateShoppingList()"
class="px-5 py-2.5 text-sm flex items-center gap-x-2 bg-emerald-700 hover:bg-emerald-800 transition-colors text-white font-semibold rounded-3xl">
<i class="fa-solid fa-list-check"></i>
<span>Generate Shopping List</span>
</button>
</div>
</div>
<div class="grid lg:grid-cols-12 gap-8">
<!-- Available Recipes -->
<div class="lg:col-span-4 bg-white border border-stone-200 rounded-3xl p-5">
<h4 class="font-semibold mb-4 px-1">Quick Add Recipes</h4>
<div class="space-y-3" id="available-recipes">
<!-- Populated by JS -->
</div>
</div>
<!-- Weekly Plan -->
<div class="lg:col-span-8">
<div class="bg-white border border-stone-200 rounded-3xl p-5">
<div class="flex items-center justify-between mb-4 px-1">
<h4 class="font-semibold">Your Week</h4>
<button onclick="clearPlan()"
class="text-xs flex items-center px-3 py-1 text-stone-500 hover:text-stone-700">
<i class="fa-solid fa-trash mr-1"></i>
<span>Clear all</span>
</button>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-7 gap-3" id="planner-grid">
<!-- Days populated by JS -->
</div>
</div>
</div>
</div>
<!-- Shopping list output -->
<div id="shopping-output" class="hidden mt-5 max-w-screen-xl mx-auto bg-white border border-stone-200 p-5 rounded-3xl">
<div class="flex justify-between items-center mb-4">
<div>
<span class="font-semibold">Shopping List</span>
<span class="text-xs ml-2 px-2 py-1 bg-emerald-100 text-emerald-700 rounded-2xl" id="shopping-count"></span>
</div>
<button onclick="copyShoppingList()" class="text-xs px-3 py-1 flex items-center gap-x-1.5 text-emerald-700 hover:text-emerald-800">
<i class="fa-solid fa-copy"></i>
<span class="font-medium">Copy list</span>
</button>
</div>
<div id="shopping-list-items" class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-x-4 gap-y-1 text-sm">
<!-- Populated dynamically -->
</div>
</div>
</section>
<!-- RESTAURANT GUIDES -->
<section id="guides" class="max-w-screen-2xl mx-auto px-8 py-10 bg-stone-100">
<div class="flex items-end justify-between mb-8">
<div>
<span class="text-xs tracking-[1.5px] font-semibold text-amber-700">CURATED EXPERIENCES</span>
<h2 class="heading-serif text-4xl tracking-tighter font-bold">Restaurant Guides</h2>
</div>
<a href="#" class="text-sm font-semibold hidden md:flex items-center text-amber-800">Explore all cities <i class="fa-solid fa-arrow-right ml-2"></i></a>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- Restaurant 1 -->
<div class="bg-white rounded-3xl overflow-hidden border border-stone-200">
<img src="https://picsum.photos/id/160/600/260" class="w-full h-[200px] object-cover" alt="Elegant interior of The Willow Bistro with warm lighting">
<div class="p-5">
<div class="flex justify-between items-start">
<div>
<h4 class="font-bold text-xl">The Willow Bistro</h4>
<span class="text-xs text-emerald-700 font-medium">• Portland, OR</span>
</div>
<div class="text-xs px-2 py-1 bg-emerald-100 text-emerald-800 rounded-xl font-medium">4.9</div>
</div>
<p class="text-sm mt-3 text-stone-600">Seasonal tasting menus that celebrate Pacific Northwest produce. Known for their thoughtful wine pairings and impeccable service.</p>
<div class="mt-4 flex items-center justify-between">
<div class="text-xs">
<span class="font-medium">Chef:</span> <span class="text-stone-500">Elena Voss</span>
</div>
<button class="text-xs font-semibold px-3 py-1 rounded-2xl border border-stone-200 hover:bg-stone-50">Visit Guide</button>
</div>
</div>
</div>
<!-- Restaurant 2 -->
<div class="bg-white rounded-3xl overflow-hidden border border-stone-200">
<img src="https://picsum.photos/id/180/600/260" class="w-full h-[200px] object-cover" alt="Modern dining room of Ember & Oak with dramatic lighting">
<div class="p-5">
<div class="flex justify-between items-start">
<div>
<h4 class="font-bold text-xl">Ember & Oak</h4>
<span class="text-xs text-emerald-700 font-medium">• Austin, TX</span>
</div>
<div class="text-xs px-2 py-1 bg-emerald-100 text-emerald-800 rounded-xl font-medium">4.7</div>
</div>
<p class="text-sm mt-3 text-stone-600">Wood-fired steaks and seasonal vegetables. Our editors love the chef's table experience and exceptional whiskey selection.</p>
<div class="mt-4 flex items-center justify-between">
<div class="text-xs">
<span class="font-medium">Chef:</span> <span class="text-stone-500">Marcus Hale</span>
</div>
<button class="text-xs font-semibold px-3 py-1 rounded-2xl border border-stone-200 hover:bg-stone-50">Visit Guide</button>
</div>
</div>
</div>
<!-- Restaurant 3 -->
<div class="bg-white rounded-3xl overflow-hidden border border-stone-200">
<img src="https://picsum.photos/id/251/600/260" class="w-full h-[200px] object-cover" alt="Beautiful coastal restaurant with ocean views">
<div class="p-5">
<div class="flex justify-between items-start">
<div>
<h4 class="font-bold text-xl">Aqua & Vine</h4>
<span class="text-xs text-emerald-700 font-medium">• Santa Barbara, CA</span>
</div>
<div class="text-xs px-2 py-1 bg-emerald-100 text-emerald-800 rounded-xl font-medium">4.8</div>
</div>
<p class="text-sm mt-3 text-stone-600">Coastal Mediterranean cuisine with an emphasis on sustainable seafood. Outstanding natural wine list and sunset terrace seating.</p>
<div class="mt-4 flex items-center justify-between">
<div class="text-xs">
<span class="font-medium">Chef:</span> <span class="text-stone-500">Sofia Reyes</span>
</div>
<button class="text-xs font-semibold px-3 py-1 rounded-2xl border border-stone-200 hover:bg-stone-50">Visit Guide</button>
</div>
</div>
</div>
</div>
</section>
<!-- CATERING & EVENTS -->
<div class="max-w-screen-2xl mx-auto px-8 pt-12">
<div class="grid md:grid-cols-2 gap-8">
<!-- Catering -->
<section id="catering" class="bg-white border border-stone-200 rounded-3xl p-7">
<div class="flex items-center gap-3 mb-5">
<div>
<span class="px-3 py-1 text-xs font-medium bg-amber-100 text-amber-700 rounded-3xl">SERVICES</span>
</div>
<h2 class="heading-serif text-3xl font-bold tracking-tighter">Catering</h2>
</div>
<p class="text-stone-600 mb-5">From intimate private dinners to large-scale corporate events, our culinary team delivers exceptional experiences with the same care and craftsmanship found in our recipes.</p>
<div class="grid grid-cols-3 gap-4">
<div class="border border-stone-100 rounded-2xl p-3 text-center">
<i class="fa-solid fa-briefcase text-xl text-amber-800 mb-2"></i>
<div class="font-medium text-xs">Corporate</div>
<div class="text-[10px] text-stone-500 mt-px">50-200 guests</div>
</div>
<div class="border border-stone-100 rounded-2xl p-3 text-center">
<i class="fa-solid fa-heart text-xl text-amber-800 mb-2"></i>
<div class="font-medium text-xs">Weddings</div>
<div class="text-[10px] text-stone-500 mt-px">Custom menus</div>
</div>
<div class="border border-stone-100 rounded-2xl p-3 text-center">
<i class="fa-solid fa-home text-xl text-amber-800 mb-2"></i>
<div class="font-medium text-xs">Private</div>
<div class="text-[10px] text-stone-500 mt-px">In-home chefs</div>
</div>
</div>
<button onclick="inquireCatering()"
class="mt-6 w-full text-sm font-semibold py-3.5 rounded-3xl bg-amber-900 hover:bg-amber-950 text-white flex items-center justify-center gap-x-2 transition-colors">
<span>Inquire About Catering</span>
</button>
</section>
<!-- Events -->
<section id="events" class="bg-white border border-stone-200 rounded-3xl p-7">
<div class="flex items-center justify-between mb-5">
<div>
<span class="px-3 py-1 text-xs font-medium bg-emerald-100 text-emerald-700 rounded-3xl">EXPERIENCES</span>
<h2 class="heading-serif text-3xl font-bold tracking-tighter mt-1">Upcoming Events</h2>
</div>
</div>
<div class="space-y-3">
<div class="flex items-center gap-x-4 border border-stone-100 p-3 rounded-2xl hover:bg-stone-50">
<div class="text-center w-10">
<div class="text-xs font-medium text-stone-500">FEB</div>
<div class="font-bold text-xl leading-none">18</div>
</div>
<div class="flex-1 min-w-0">
<div class="font-semibold">Winter Foraging Workshop</div>
<div class="text-xs text-stone-500">Portland, OR • 6:30pm</div>
</div>
<button class="px-3 py-1 text-xs bg-emerald-700 hover:bg-emerald-800 text-white font-semibold rounded-2xl whitespace-nowrap">RSVP</button>
</div>
<div class="flex items-center gap-x-4 border border-stone-100 p-3 rounded-2xl hover:bg-stone-50">
<div class="text-center w-10">
<div class="text-xs font-medium text-stone-500">MAR</div>
<div class="font-bold text-xl leading-none">05</div>
</div>
<div class="flex-1 min-w-0">
<div class="font-semibold">Wine & Cheese Masterclass</div>
<div class="text-xs text-stone-500">Virtual • 7:00pm</div>
</div>
<button class="px-3 py-1 text-xs bg-emerald-700 hover:bg-emerald-800 text-white font-semibold rounded-2xl whitespace-nowrap">RSVP</button>
</div>
<div class="flex items-center gap-x-4 border border-stone-100 p-3 rounded-2xl hover:bg-stone-50">
<div class="text-center w-10">
<div class="text-xs font-medium text-stone-500">MAR</div>
<div class="font-bold text-xl leading-none">22</div>
</div>
<div class="flex-1 min-w-0">
<div class="font-semibold">Spring Harvest Dinner</div>
<div class="text-xs text-stone-500">Sonoma Valley • 6:00pm</div>
</div>
<button class="px-3 py-1 text-xs bg-emerald-700 hover:bg-emerald-800 text-white font-semibold rounded-2xl whitespace-nowrap">RSVP</button>
</div>
</div>
</section>
</div>
</div>
<!-- TESTIMONIALS -->
<section id="testimonials" class="max-w-screen-2xl mx-auto px-8 py-14">
<div class="mb-8">
<span class="text-xs tracking-[1.5px] font-semibold text-amber-700">REAL STORIES</span>
<h2 class="heading-serif text-4xl tracking-tighter font-bold">What our community says</h2>
</div>
<div class="grid md:grid-cols-3 gap-6">
<!-- Testimonial 1 -->
<div class="testimonial-card bg-white p-6 rounded-3xl border border-stone-200">
<div class="flex items-center mb-4">
<img src="https://i.pravatar.cc/40?u=anna" alt="Anna Torres" class="w-9 h-9 rounded-full object-cover ring-2 ring-white">
<div class="ml-3">
<div class="font-semibold">Anna Torres</div>
<div class="text-xs text-stone-500">Home cook • Seattle</div>
</div>
</div>
<p class="text-sm">"The braising tutorial completely changed how I cook tougher cuts. My family now requests the short ribs every Sunday. The shopping list tool is a game changer."</p>
<div class="mt-4 text-xs font-medium text-emerald-700">— 5-star recipe rating</div>
</div>
<!-- Testimonial 2 -->
<div class="testimonial-card bg-white p-6 rounded-3xl border border-stone-200">
<div class="flex items-center mb-4">
<img src="https://i.pravatar.cc/40?u=devon" alt="Devon Patel" class="w-9 h-9 rounded-full object-cover ring-2 ring-white">
<div class="ml-3">
<div class="font-semibold">Devon Patel</div>
<div class="text-xs text-stone-500">Private chef • Chicago</div>
</div>
</div>
<p class="text-sm">"I use the restaurant guides to source inspiration for client events. The umami techniques and pairing advice have helped me stand out with my catering clients."</p>
<div class="mt-4 text-xs font-medium text-emerald-700">— Professional subscriber</div>
</div>
<!-- Testimonial 3 -->
<div class="testimonial-card bg-white p-6 rounded-3xl border border-stone-200">
<div class="flex items-center mb-4">
<img src="https://i.pravatar.cc/40?u=sophia" alt="Sophia Laurent" class="w-9 h-9 rounded-full object-cover ring-2 ring-white">
<div class="ml-3">
<div class="font-semibold">Sophia Laurent</div>
<div class="text-xs text-stone-500">Food blogger • San Francisco</div>
</div>
</div>
<p class="text-sm">"The weekly meal planner helped me finally stick to a consistent cooking schedule. My nutrition has improved and the recipes are always reliable and delicious."</p>
<div class="mt-4 text-xs font-medium text-emerald-700">— 12-week challenge winner</div>
</div>
</div>
</section>
<!-- FAQ SECTION -->
<section id="faq" class="max-w-screen-2xl mx-auto px-8 py-10 bg-white border-t border-stone-200">
<div class="max-w-2xl">
<span class="text-xs tracking-[1.5px] font-semibold text-amber-700">FREQUENTLY ASKED</span>
<h2 class="heading-serif text-3xl tracking-tighter font-bold mb-6">Your Questions Answered</h2>
<div class="space-y-1">
<details class="group border border-stone-200 rounded-3xl px-5 py-1 mb-1">
<summary class="accordion-header cursor-pointer flex justify-between items-center py-3 font-medium list-none">
<span>What is the best technique for achieving tender braised meat?</span>
<i class="fa-solid fa-chevron-down group-open:rotate-180 transition-transform ml-3"></i>
</summary>
<p class="text-stone-600 text-sm pb-4">Start by searing the meat at high heat to develop fond. Use a tight-fitting lid and cook low and slow (around 325°F). Allow the meat to rest in the braising liquid for 20 minutes before serving.</p>
</details>
<details class="group border border-stone-200 rounded-3xl px-5 py-1 mb-1">
<summary class="accordion-header cursor-pointer flex justify-between items-center py-3 font-medium list-none">
<span>How do I build umami in vegetarian dishes?</span>
<i class="fa-solid fa-chevron-down group-open:rotate-180 transition-transform ml-3"></i>
</summary>
<p class="text-stone-600 text-sm pb-4">Combine ingredients like dried shiitake mushrooms, miso paste, nutritional yeast, and aged balsamic. Sautéing vegetables until deeply caramelized also concentrates natural glutamates.</p>
</details>
<details class="group border border-stone-200 rounded-3xl px-5 py-1 mb-1">
<summary class="accordion-header cursor-pointer flex justify-between items-center py-3 font-medium list-none">
<span>Do you offer nutrition information for all recipes?</span>
<i class="fa-solid fa-chevron-down group-open:rotate-180 transition-transform ml-3"></i>
</summary>
<p class="text-stone-600 text-sm pb-4">Yes. Every recipe includes a full nutritional breakdown. Our team of registered dietitians reviews all content to ensure accuracy and helpful guidance.</p>
</details>
<details class="group border border-stone-200 rounded-3xl px-5 py-1">
<summary class="accordion-header cursor-pointer flex justify-between items-center py-3 font-medium list-none">
<span>How does the meal planner generate shopping lists?</span>
<i class="fa-solid fa-chevron-down group-open:rotate-180 transition-transform ml-3"></i>
</summary>
<p class="text-stone-600 text-sm pb-4">The planner aggregates ingredients across all selected recipes for the week. Duplicate items are automatically combined. You can edit quantities or remove items before exporting.</p>
</details>
</div>
</div>
</section>
<!-- FINAL CTA -->
<div class="max-w-screen-2xl mx-auto px-8 py-10">
<div class="bg-gradient-to-r from-stone-900 to-amber-950 rounded-3xl px-8 py-9 text-white flex flex-col md:flex-row md:items-center md:justify-between gap-6">
<div>
<h3 class="font-semibold text-2xl">Ready to transform your kitchen?</h3>
<p class="text-stone-300 mt-1">Join 48,000+ cooks receiving seasonal recipes and expert tips every week.</p>
</div>
<button onclick="showSubscribeModal()"
class="flex-shrink-0 bg-white text-stone-900 hover:bg-amber-100 transition-colors font-semibold px-7 py-3.5 rounded-3xl text-sm">
Subscribe to the Newsletter
</button>
</div>
</div>
<!-- FOOTER -->
<footer class="bg-stone-900 text-stone-400 pt-10 pb-8">
<div class="max-w-screen-2xl mx-auto px-8">
<div class="grid md:grid-cols-12 gap-y-8">
<div class="md:col-span-4">
<div class="flex items-center gap-x-3">
<div class="flex items-center justify-center w-9 h-9 bg-amber-900 rounded-2xl">
<img src="https://placehold.co/36x36/451a03/fff?text=H&H&font=playfair+display" alt="Logo" class="w-9 h-9 rounded-2xl">
</div>
<span class="font-bold text-white text-xl tracking-tight">Harvest & Hearth</span>
</div>
<p class="mt-4 text-sm pr-6">Thoughtful resources for anyone who loves food and drink.</p>
<div class="flex gap-x-4 mt-6">
<a href="#" class="hover:text-white"><i class="fa-brands fa-instagram text-lg"></i></a>
<a href="#" class="hover:text-white"><i class="fa-brands fa-tiktok text-lg"></i></a>
<a href="#" class="hover:text-white"><i class="fa-brands fa-youtube text-lg"></i></a>
</div>
</div>
<div class="md:col-span-2">
<div class="font-semibold text-white mb-3 text-sm">Explore</div>
<div class="space-y-1.5 text-sm">
<div><a href="#recipes" class="hover:text-white">Recipes</a></div>
<div><a href="#guides" class="hover:text-white">Guides</a></div>
<div><a href="#tips" class="hover:text-white">Nutrition</a></div>
</div>
</div>
<div class="md:col-span-2">
<div class="font-semibold text-white mb-3 text-sm">Services</div>
<div class="space-y-1.5 text-sm">
<div><a href="#catering" class="hover:text-white">Catering</a></div>
<div><a href="#events" class="hover:text-white">Events</a></div>
<div><a href="#" class="hover:text-white">Private Chefs</a></div>
</div>
</div>
<div class="md:col-span-4">
<div class="font-semibold text-white mb-3 text-sm">Contact</div>
<div class="text-sm space-y-1">
<div>hello@harvestandhearth.co</div>
<div>(503) 555-0182</div>
<div class="pt-2">Portland, Oregon</div>
</div>
<div class="text-xs mt-4 pt-4 border-t border-stone-800 flex gap-x-4 text-stone-400">
<a href="#" class="hover:text-white">Privacy</a>
<a href="#" class="hover:text-white">Terms</a>
<a href="#" class="hover:text-white">Accessibility</a>
</div>
</div>
</div>
<div class="pt-7 mt-7 border-t border-stone-800 text-xs flex flex-col md:flex-row md:items-center gap-y-1 md:justify-between text-stone-500">
<div>© 2025 Harvest & Hearth. All rights reserved.</div>
<div class="text-xs">Crafted with care for the culinary community.</div>
</div>
</div>
</footer>
<!-- Recipe Modal -->
<div id="recipe-modal" onclick="if (event.target.id === 'recipe-modal') hideRecipeModal()" class="hidden fixed inset-0 bg-black/60 z-[100] flex items-center justify-center p-4">
<div onclick="event.stopImmediatePropagation()" class="bg-white w-full max-w-lg rounded-3xl overflow-hidden shadow-xl">
<!-- Modal content populated by JS -->
<div id="modal-content">
<!-- Dynamic content inserted here -->
</div>
</div>
</div>
<!-- Subscribe Modal -->
<div id="subscribe-modal" onclick="if (event.target.id === 'subscribe-modal') hideSubscribeModal()" class="hidden fixed inset-0 bg-black/60 z-[100] flex items-center justify-center p-4">
<div onclick="event.stopImmediatePropagation()" class="bg-white w-full max-w-md rounded-3xl p-7">
<div class="flex justify-between mb-5 items-center">
<div>
<span class="font-bold text-xl">Stay in the know</span>
</div>
<button onclick="hideSubscribeModal()" class="text-xl text-stone-400 hover:text-stone-700">×</button>
</div>
<p class="text-sm text-stone-600">Receive weekly seasonal recipes, technique deep-dives, and curated restaurant recommendations.</p>
<div class="mt-5">
<div class="mb-4">
<input type="text" placeholder="Full name" class="w-full border border-stone-200 px-4 py-3 text-sm rounded-2xl">
</div>
<div class="mb-4">
<input type="email" placeholder="Email address" value="emma.rivers@email.com" class="w-full border border-stone-200 px-4 py-3 text-sm rounded-2xl">
</div>
<div class="flex items-center gap-x-2 mb-5">
<input type="checkbox" checked class="accent-amber-800">
<span class="text-xs text-stone-600">I agree to receive the weekly newsletter.</span>
</div>
<button onclick="subscribeUser()"
class="w-full py-3.5 bg-amber-900 text-white font-semibold text-sm rounded-3xl hover:bg-amber-950 transition-colors">
Subscribe for free
</button>
</div>
<div class="text-center text-[10px] text-stone-500 mt-5">We respect your inbox. Unsubscribe anytime.</div>
</div>
</div>
<script src="https://cdn.tailwindcss.com"></script>
<script>
// Tailwind configuration
function initializeTailwind() {
document.documentElement.style.setProperty('--accent', '#854d0e');
tailwind.config = {
theme: {
extend: {
fontFamily: {
'serif-custom': ['Playfair Display', 'Georgia', 'serif']
}
}
}
};
}
// Mobile menu toggle
function toggleMobileMenu() {
const mobileMenu = document.getElementById('mobile-menu');
mobileMenu.classList.toggle('hidden');
const icon = document.querySelector('#mobile-menu-btn i');
if (mobileMenu.classList.contains('hidden')) {
icon.classList.remove('fa-times');
icon.classList.add('fa-bars');
} else {
icon.classList.remove('fa-bars');
icon.classList.add('fa-times');
}
}
// Recipe data
const recipesData = {
'1': {
id: '1',
name: 'Braised Short Ribs',
subtitle: 'with Red Wine & Root Vegetables',
image: 'https://picsum.photos/id/292/800/400',
prep: '20 min',
cook: '3 hrs',
servings: '4',
difficulty: 'Intermediate',
description: 'This dish showcases the art of slow cooking. The beef is seared to develop a deep crust, then gently braised in red wine until fork-tender. The resulting sauce is rich with umami from the reduction.',
ingredients: [
'3 lbs bone-in beef short ribs',
'2 cups dry red wine',
'4 medium carrots, cut into chunks',
'2 yellow onions, quartered',
'5 garlic cloves, smashed',
'3 sprigs fresh thyme',
'2 bay leaves',
'3 cups beef stock',
'2 tbsp tomato paste',
'2 tbsp olive oil'
],
steps: [
'Preheat oven to 325°F. Pat the short ribs dry and season generously with salt and pepper.',
'Heat olive oil in a large Dutch oven over medium-high heat. Sear ribs in batches until deeply browned on all sides.',
'Remove ribs and set aside. Add onions and carrots to the pot; sauté until softened.',
'Stir in garlic and tomato paste. Cook for 1 minute. Pour in the red wine and scrape up any browned bits.',
'Add beef stock, thyme, and bay leaves. Return ribs to the pot, cover, and transfer to the oven.',
'Braise for 3 hours until meat is very tender. Remove ribs, strain sauce and reduce if desired.'
],
nutrition: {
calories: 620,
protein: '42g',
fat: '38g',
carbs: '18g'
}
},
'2': {
id: '2',
name: 'Pan-Seared Scallops',
subtitle: 'with Umami Mushroom Sauce',
image: 'https://picsum.photos/id/312/800/400',
prep: '10 min',
cook: '5 min',
servings: '2',
difficulty: 'Advanced',
description: 'Scallops develop a beautiful golden crust when seared correctly. The accompanying mushroom sauce uses soy and dried porcini to deliver intense umami.',
ingredients: [
'12 large sea scallops',
'8 oz cremini mushrooms, sliced',
'2 tbsp soy sauce',
'1 tbsp butter',
'3 cloves garlic, minced',
'1 shallot, finely chopped',
'1/4 cup dry white wine',
'Fresh parsley and lemon wedges'
],
steps: [
'Pat scallops very dry with paper towels and season with salt and pepper.',
'Heat a large skillet over high heat. Add butter and oil. Sear scallops 2 minutes per side without moving.',
'Remove scallops and set aside. In same pan, sauté mushrooms and shallot until golden.',
'Add garlic and cook 30 seconds. Deglaze with wine, then stir in soy sauce.',
'Return scallops to the pan briefly to warm through. Finish with fresh parsley and lemon.'
],
nutrition: {
calories: 290,
protein: '28g',
fat: '12g',
carbs: '9g'
}
},
'3': {
id: '3',
name: 'Wild Mushroom Risotto',
subtitle: 'with Aged Parmesan',
image: 'https://picsum.photos/id/201/800/400',
prep: '15 min',
cook: '25 min',
servings: '4',
difficulty: 'Intermediate',
description: 'A classic Italian technique of constant stirring creates the signature creamy texture. We use a variety of wild mushrooms for layered earthiness.',
ingredients: [
'1 1/2 cups Arborio rice',
'10 oz mixed wild mushrooms',
'1/2 cup grated aged Parmesan',
'1/2 cup dry white wine',
'1 large shallot, finely diced',
'4 1/2 cups warm vegetable or chicken broth',
'3 tbsp butter',
'2 tbsp olive oil',
'Fresh thyme leaves'
],
steps: [
'Heat olive oil and 1 tbsp butter in a wide pan. Sauté mushrooms until browned and set aside.',
'In same pan, cook shallot until translucent. Add rice and toast for 2 minutes.',
'Pour in wine and stir until mostly absorbed. Begin adding broth one ladle at a time.',
'Stir frequently, adding more broth only when the previous addition is absorbed.',
'When rice is al dente, stir in mushrooms, remaining butter, and Parmesan. Finish with thyme.'
],
nutrition: {
calories: 480,
protein: '13g',
fat: '16g',
carbs: '68g'
}
},
'4': {
id: '4',
name: 'Herb-Roasted Chicken',
subtitle: 'with Lemon & Garlic',
image: 'https://picsum.photos/id/251/800/400',
prep: '15 min',
cook: '1 hr 15 min',
servings: '4',
difficulty: 'Beginner',
description: 'A perfectly roasted chicken is a cornerstone skill. High heat creates crisp skin while the herb butter keeps the meat juicy and flavorful.',
ingredients: [
'1 whole chicken (4-5 lbs)',
'1 lemon, halved',
'6 sprigs fresh rosemary',
'6 sprigs fresh thyme',
'5 garlic cloves',
'3 tbsp unsalted butter, softened',
'2 tbsp olive oil',
'Kosher salt and black pepper'
],
steps: [
'Preheat oven to 425°F. Remove giblets and pat chicken completely dry.',
'Mix butter with chopped herbs, garlic, salt, and pepper. Gently loosen skin and rub half under the skin.',
'Stuff cavity with lemon halves and remaining herb sprigs. Tie legs together.',
'Rub outside of chicken with olive oil and season generously with salt and pepper.',
'Roast on a wire rack for 1 hour 15 minutes until thigh reaches 165°F. Rest 15 minutes before carving.'
],
nutrition: {
calories: 510,
protein: '48g',
fat: '30g',
carbs: '2g'
}
}
}
// Planner state
let currentPlan = {
'Monday': [],
'Tuesday': [],
'Wednesday': [],
'Thursday': [],
'Friday': [],
'Saturday': [],
'Sunday': []
}
// Render available recipes for planner
function renderAvailableRecipes() {
const container = document.getElementById('available-recipes');
container.innerHTML = '';
Object.keys(recipesData).forEach(key => {
const recipe = recipesData[key];
const div = document.createElement('div');
div.className = `flex items-center justify-between p-3 bg-stone-50 rounded-2xl border border-stone-100`;
div.innerHTML = `
<div class="flex items-center gap-x-3">
<div>
<div class="font-semibold text-sm">${recipe.name}</div>
<div class="text-xs text-stone-500">${recipe.servings} servings</div>
</div>
</div>
<div class="flex items-center gap-x-2">
<select class="text-xs border border-stone-200 bg-white px-2 py-1 rounded-xl text-stone-600" id="select-${key}">
<option value="Monday">Mon</option>
<option value="Tuesday">Tue</option>
<option value="Wednesday">Wed</option>
<option value="Thursday">Thu</option>
<option value="Friday">Fri</option>
<option value="Saturday">Sat</option>
<option value="Sunday">Sun</option>
</select>
<button onclick="addRecipeToPlan('${key}', this)"
class="px-3 py-1 text-xs bg-amber-800 hover:bg-amber-900 text-white font-medium rounded-2xl transition-colors">
Add
</button>
</div>
`;
container.appendChild(div);
});
}
// Add recipe to plan from the available recipes section
function addRecipeToPlan(recipeId, element) {
const select = element.parentElement.querySelector('select');
const day = select.value;
if (!currentPlan[day]) currentPlan[day] = [];
// Check if already exists
const exists = currentPlan[day].some(item => item.id === recipeId);
if (exists) {
alert('This recipe is already added to ' + day);
return;
}
const recipe = recipesData[recipeId];
currentPlan[day].push({
id: recipeId,
name: recipe.name
});
renderPlanner();
// Brief success feedback
const originalText = element.textContent;
element.textContent = 'Added!';
element.disabled = true;
setTimeout(() => {
element.textContent = originalText;
element.disabled = false;
}, 1200);
}
// Quick add from recipe cards
function quickAddToPlanner(recipeId) {
const day = prompt("Add to which day? (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)");
if (!day) return;
const normalizedDay = day.charAt(0).toUpperCase() + day.slice(1).toLowerCase();
if (!currentPlan[normalizedDay]) {
alert('Please enter a valid day of the week.');
return;
}
const exists = currentPlan[normalizedDay].some(item => item.id === recipeId);
if (exists) {
alert('Recipe already added to ' + normalizedDay);
return;
}
const recipe = recipesData[recipeId];
currentPlan[normalizedDay].push({
id: recipeId,
name: recipe.name
});
renderPlanner();
// Scroll to planner
document.getElementById('planner').scrollIntoView({ behavior: 'smooth', block: 'center' });
}
// Render the weekly planner grid
function renderPlanner() {
const container = document.getElementById('planner-grid');
container.innerHTML = '';
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
days.forEach(day => {
const dayDiv = document.createElement('div');
dayDiv.className = `meal-plan-day border border-stone-200 bg-white p-3 rounded-2xl min-h-[132px]`;
let mealsHTML = '';
if (currentPlan[day] && currentPlan[day].length > 0) {
currentPlan[day].forEach((meal, index) => {
mealsHTML += `
<div class="flex justify-between items-center bg-stone-50 px-2 py-1.5 rounded-xl mb-1.5 text-xs group">
<span class="font-medium truncate pr-1">${meal.name}</span>
<button onclick="removeFromPlan('${day}', ${index})" class="text-red-400 hover:text-red-600 transition-colors">
<i class="fa-solid fa-times"></i>
</button>
</div>
`;
});
} else {
mealsHTML = `<div class="text-xs text-stone-400 py-3 text-center">No meals planned</div>`;
}
dayDiv.innerHTML = `
<div class="flex justify-between items-center mb-2">
<span class="text-xs font-semibold text-stone-700">${day}</span>
<button onclick="showAddToDayModal('${day}')" class="text-amber-700 hover:text-amber-900">
<i class="fa-solid fa-plus text-xs"></i>
</button>
</div>
<div class="space-y-1">
${mealsHTML}
</div>
`;
container.appendChild(dayDiv);
});
}
function showAddToDayModal(day) {
const modalHTML = `
<div class="fixed inset-0 bg-black/60 z-[110] flex items-center justify-center p-4" id="add-modal">
<div onclick="event.target.id === 'add-modal' && document.getElementById('add-modal').remove()" class="bg-white w-full max-w-xs rounded-3xl p-5">
<div class="flex justify-between mb-4">
<span class="font-semibold">Add to ${day}</span>
<button onclick="document.getElementById('add-modal').remove()" class="text-stone-400">×</button>
</div>
<div class="space-y-2">
${Object.keys(recipesData).map(key => {
const rec = recipesData[key];
return `
<div onclick="addSpecificRecipe('${key}', '${day}'); document.getElementById('add-modal').remove();"
class="flex items-center justify-between px-3 py-2.5 text-sm hover:bg-stone-50 cursor-pointer rounded-2xl">
<span>${rec.name}</span>
<i class="fa-solid fa-plus text-amber-700"></i>
</div>
`;
}).join('')}
</div>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', modalHTML);
}
function addSpecificRecipe(recipeId, day) {
if (!currentPlan[day]) currentPlan[day] = [];
const exists = currentPlan[day].some(item => item.id === recipeId);
if (exists) {
alert('Already added to this day.');
return;
}
const recipe = recipesData[recipeId];
currentPlan[day].push({ id: recipeId, name: recipe.name });
renderPlanner();
// Close any open add modal
const addModal = document.getElementById('add-modal');
if (addModal) addModal.remove();
}
function removeFromPlan(day, index) {
currentPlan[day].splice(index, 1);
renderPlanner();
}
function clearPlan() {
if (confirm('Clear entire meal plan?')) {
Object.keys(currentPlan).forEach(day => {
currentPlan[day] = [];
});
renderPlanner();
// Hide shopping list if visible
document.getElementById('shopping-output').classList.add('hidden');
}
}
// Generate shopping list
function generateShoppingList() {
const output = document.getElementById('shopping-output');
const itemsContainer = document.getElementById('shopping-list-items');
const countEl = document.getElementById('shopping-count');
itemsContainer.innerHTML = '';
let allIngredients = [];
Object.keys(currentPlan).forEach(day => {
currentPlan[day].forEach(meal => {
if (recipesData[meal.id]) {
allIngredients = [...allIngredients, ...recipesData[meal.id].ingredients];
}
});
});
if (allIngredients.length === 0) {
alert('Add some recipes to your plan first!');
return;
}
// Deduplicate
const uniqueIngredients = [...new Set(allIngredients)];
countEl.textContent = `${uniqueIngredients.length} items`;
uniqueIngredients.forEach(ingredient => {
const div = document.createElement('div');
div.className = `flex items-center text-sm gap-x-2 py-[1px]`;
div.innerHTML = `
<div class="flex items-center">
<i class="fa-solid fa-check text-emerald-600 mr-2 text-xs"></i>
<span>${ingredient}</span>
</div>
`;
itemsContainer.appendChild(div);
});
output.classList.remove('hidden');
// Scroll to it
output.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
function copyShoppingList() {
const items = document.querySelectorAll('#shopping-list-items span');
let listText = 'Shopping List:\n\n';
items.forEach(item => {
listText += `- ${item.textContent}\n`;
});
navigator.clipboard.writeText(listText).then(() => {
const originalText = event.currentTarget;
const btn = event.target.closest('button');
const originalHTML = btn ? btn.innerHTML : '';
if (btn) {
btn.innerHTML = `<i class="fa-solid fa-check"></i> Copied!`;
setTimeout(() => {
if (btn) btn.innerHTML = originalHTML;
}, 1800);
}
}).catch(() => {
alert(listText);
});
}
// Show recipe modal
function showRecipeModal(recipeId) {
const modal = document.getElementById('recipe-modal');
const content = document.getElementById('modal-content');
const recipe = recipesData[recipeId];
if (!recipe) return;
content.innerHTML = `
<div>
<div class="relative">
<img src="${recipe.image}" class="w-full h-56 object-cover" alt="${recipe.name}">
<button onclick="hideRecipeModal()" class="absolute top-3 right-3 w-8 h-8 flex items-center justify-center bg-white/90 rounded-full text-lg leading-none text-stone-600">×</button>
</div>
<div class="px-5 pt-5 pb-2">
<div class="flex justify-between items-start">
<div>
<h3 class="font-bold text-2xl">${recipe.name}</h3>
<p class="text-stone-500">${recipe.subtitle}</p>
</div>
<div class="px-3 py-1 bg-stone-100 rounded-2xl text-xs flex items-center">
<span class="font-semibold">${recipe.difficulty}</span>
</div>
</div>
<div class="flex items-center justify-between mt-5 text-sm">
<div class="flex gap-x-6">
<div>
<div class="text-xs text-stone-500">Prep</div>
<div class="font-semibold">${recipe.prep}</div>
</div>
<div>
<div class="text-xs text-stone-500">Cook</div>
<div class="font-semibold">${recipe.cook}</div>
</div>
<div>
<div class="text-xs text-stone-500">Serves</div>
<div class="font-semibold">${recipe.servings}</div>
</div>
</div>
<div onclick="quickAddToPlanner('${recipe.id}'); hideRecipeModal();"
class="cursor-pointer px-4 py-[7px] text-xs font-semibold flex items-center gap-x-1.5 bg-amber-100 text-amber-800 hover:bg-amber-200 transition-colors rounded-2xl">
<i class="fa-solid fa-calendar"></i>
<span>Add to Plan</span>
</div>
</div>
<div class="mt-5">
<p class="text-sm text-stone-600">${recipe.description}</p>
</div>
<div class="mt-6">
<div class="font-semibold mb-3 text-sm">Ingredients</div>
<ul class="grid grid-cols-1 gap-y-1 text-sm">
${recipe.ingredients.map(ing => `
<li class="flex items-center gap-x-2">
<i class="fa-solid fa-check text-emerald-600 text-xs"></i>
<span>${ing}</span>
</li>
`).join('')}
</ul>
</div>
<div class="mt-6">
<div class="font-semibold mb-3 text-sm">Method</div>
<ol class="space-y-3 text-sm">
${recipe.steps.map((step, i) => `
<li class="flex gap-x-3">
<span class="font-semibold text-amber-800 flex-shrink-0">${i + 1}.</span>
<span class="text-stone-600">${step}</span>
</li>
`).join('')}
</ol>
</div>
<div class="mt-6 pt-5 border-t">
<div class="flex items-center justify-between text-xs">
<div>
<span class="font-semibold">Nutrition (per serving)</span>
<div class="flex gap-x-4 text-stone-500 mt-1">
<div>${recipe.nutrition.calories} cal</div>
<div>${recipe.nutrition.protein} protein</div>
</div>
</div>
<button onclick="hideRecipeModal()"
class="px-5 py-2 text-xs font-semibold bg-stone-900 hover:bg-stone-800 text-white rounded-2xl">
Close
</button>
</div>
</div>
</div>
</div>
`;
modal.classList.remove('hidden');
modal.classList.add('flex');
}
function hideRecipeModal() {
const modal = document.getElementById('recipe-modal');
modal.classList.remove('flex');
modal.classList.add('hidden');
}
// Subscribe modal
function showSubscribeModal() {
const modal = document.getElementById('subscribe-modal');
modal.classList.remove('hidden');
modal.classList.add('flex');
}
function hideSubscribeModal() {
const modal = document.getElementById('subscribe-modal');
modal.classList.remove('flex');
modal.classList.add('hidden');
}
function subscribeUser() {
const modal = document.getElementById('subscribe-modal');
modal.innerHTML = `
<div class="bg-white w-full max-w-md rounded-3xl p-7 text-center">
<div class="mx-auto flex justify-center items-center w-12 h-12 bg-emerald-100 rounded-full mb-3">
<i class="fa-solid fa-check text-emerald-700 text-2xl"></i>
</div>
<div class="font-bold text-xl">Thank you!</div>
<p class="text-stone-600 mt-2 text-sm">You are now subscribed. Check your inbox for a welcome recipe pack.</p>
<button onclick="hideSubscribeModal()" class="mt-5 px-8 py-2.5 bg-stone-900 text-white text-sm rounded-3xl font-medium">
Return to site
</button>
</div>
`;
setTimeout(() => {
// Optional: auto close after success
}, 4500);
}
function inquireCatering() {
const modalHTML = `
<div onclick="this.remove()" class="fixed inset-0 bg-black/50 z-[120] flex items-center justify-center p-4">
<div onclick="event.stopImmediatePropagation()" class="max-w-md w-full bg-white rounded-3xl p-6">
<h3 class="font-bold text-xl mb-1">Catering Inquiry</h3>
<p class="text-sm text-stone-600 mb-5">Tell us about your event and we'll be in touch within 24 hours.</p>
<div class="space-y-3">
<input type="text" placeholder="Your name" class="w-full border px-4 py-[9px] text-sm rounded-2xl border-stone-200">
<input type="text" placeholder="Event type & date" class="w-full border px-4 py-[9px] text-sm rounded-2xl border-stone-200">
<input type="number" placeholder="Number of guests" class="w-full border px-4 py-[9px] text-sm rounded-2xl border-stone-200">
<textarea placeholder="Tell us about your vision..." class="w-full border px-4 py-3 text-sm rounded-2xl border-stone-200" rows="3"></textarea>
</div>
<div class="flex gap-3 mt-5">
<button onclick="this.closest('.fixed').remove()" class="flex-1 py-3 border border-stone-200 rounded-3xl text-sm font-semibold">Cancel</button>
<button onclick="submitInquiry(this)" class="flex-1 py-3 bg-amber-900 text-white rounded-3xl text-sm font-semibold">Send Inquiry</button>
</div>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', modalHTML);
}
function submitInquiry(element) {
const container = element.closest('.fixed');
container.innerHTML = `
<div class="max-w-md w-full bg-white rounded-3xl p-6 text-center">
<div class="mx-auto flex justify-center items-center w-12 h-12 bg-emerald-100 rounded-full mb-3">
<i class="fa-solid fa-check text-emerald-700 text-2xl"></i>
</div>
<h3 class="font-bold text-xl">Inquiry received!</h3>
<p class="text-sm mt-1 text-stone-600">Our catering team will contact you shortly.</p>
<button onclick="this.closest('.fixed').remove()" class="mt-5 px-6 py-2 text-sm bg-stone-900 text-white font-semibold rounded-3xl">Close</button>
</div>
`;
}
// Initialize planner with sample data
function initializeSamplePlan() {
currentPlan['Monday'] = [{ id: '1', name: 'Braised Short Ribs' }];
currentPlan['Wednesday'] = [{ id: '3', name: 'Wild Mushroom Risotto' }];
currentPlan['Friday'] = [{ id: '4', name: 'Herb-Roasted Chicken' }];
// Render after a short delay for visual polish
setTimeout(() => {
renderPlanner();
}, 300);
}
// Initialize everything
function initializeWebsite() {
initializeTailwind();
// Render available recipes
renderAvailableRecipes();
// Initialize planner
initializeSamplePlan();
// Render planner grid
renderPlanner();
// Add subtle scroll behavior to nav
const header = document.querySelector('header');
window.addEventListener('scroll', () => {
if (window.scrollY > 30) {
header.classList.add('nav-scrolled');
} else {
header.classList.remove('nav-scrolled');
}
});
// Keyboard support for modals
document.addEventListener('keydown', function(e) {
if (e.key === "Escape") {
const recipeModal = document.getElementById('recipe-modal');
const subscribeModal = document.getElementById('subscribe-modal');
if (!recipeModal.classList.contains('hidden')) {
recipeModal.classList.add('hidden');
recipeModal.classList.remove('flex');
} else if (!subscribeModal.classList.contains('hidden')) {
subscribeModal.classList.add('hidden');
subscribeModal.classList.remove('flex');
} else {
const addModals = document.querySelectorAll('.fixed.inset-0.bg-black\\/50, .fixed.inset-0.bg-black\\/60');
if (addModals.length > 0) {
addModals[addModals.length - 1].remove();
}
}
}
if (e.key === "/" && document.activeElement.tagName === "BODY") {
e.preventDefault();
const searchInput = document.querySelector('input[placeholder="Search recipes..."]');
if (searchInput) searchInput.focus();
}
});
// Demo: Pre-populate a shopping list after 6 seconds (for demo purposes only)
setTimeout(() => {
const output = document.getElementById('shopping-output');
// Only show if user hasn't interacted yet
if (output.classList.contains('hidden') && currentPlan['Monday'].length > 0) {
// Don't auto-show, leave it to user
}
}, 6000);
// Accessibility note: Add aria labels where needed (already done in most places)
console.log('%c[Harvest & Hearth] Production-ready one-page site initialized.', 'color:#854d0e');
}
// Boot the website
window.onload = function() {
initializeWebsite();
}
// Bonus: Make logo clickable to top
setTimeout(() => {
const logo = document.querySelector('header .flex.items-center');
if (logo) {
logo.style.cursor = 'pointer';
logo.onclick = () => window.scrollTo({top: 0, behavior: 'smooth'});
}
}, 1200);
</script>
</body>
</html>
View Axe Report (JSON)
{
"testEngine": {
"name": "axe-core",
"version": "4.10.2"
},
"testRunner": {
"name": "axe"
},
"testEnvironment": {
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36",
"windowWidth": 1280,
"windowHeight": 720,
"orientationAngle": 0,
"orientationType": "landscape-primary"
},
"timestamp": "2026-11-12T09:43:19.413Z",
"url": "https://benchmark.aimac.invalid/573eb857dab0777ce283b45f4b5a323af989a57e37d949a9242d8943e31e650f.html",
"toolOptions": {
"runOnly": {
"type": "tag",
"values": [
"wcag2a",
"wcag2aa",
"wcag21a",
"wcag21aa",
"wcag22a",
"wcag22aa"
]
},
"resultTypes": [
"violations"
],
"reporter": "v1"
},
"inapplicable": [
{
"id": "area-alt",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag244",
"wcag412",
"section508",
"section508.22.a",
"TTv5",
"TT6.a",
"EN-301-549",
"EN-9.2.4.4",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure <area> elements of image maps have alternative text",
"help": "Active <area> elements must have alternative text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/area-alt?application=axeAPI",
"nodes": []
},
{
"id": "aria-allowed-attr",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure an element's role supports its ARIA attributes",
"help": "Elements must only use supported ARIA attributes",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=axeAPI",
"nodes": []
},
{
"id": "aria-braille-equivalent",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent",
"help": "aria-braille attributes must have a non-braille equivalent",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-braille-equivalent?application=axeAPI",
"nodes": []
},
{
"id": "aria-command-name",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"TTv5",
"TT6.a",
"EN-301-549",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure every ARIA button, link and menuitem has an accessible name",
"help": "ARIA commands must have an accessible name",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-command-name?application=axeAPI",
"nodes": []
},
{
"id": "aria-conditional-attr",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure ARIA attributes are used as described in the specification of the element's role",
"help": "ARIA attributes must be used as specified for the element's role",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-conditional-attr?application=axeAPI",
"nodes": []
},
{
"id": "aria-deprecated-role",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure elements do not use deprecated roles",
"help": "Deprecated ARIA roles must not be used",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-deprecated-role?application=axeAPI",
"nodes": []
},
{
"id": "aria-hidden-focus",
"impact": null,
"tags": [
"cat.name-role-value",
"wcag2a",
"wcag412",
"TTv5",
"TT6.a",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure aria-hidden elements are not focusable nor contain focusable elements",
"help": "ARIA hidden element must not be focusable or contain focusable elements",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-hidden-focus?application=axeAPI",
"nodes": []
},
{
"id": "aria-input-field-name",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"TTv5",
"TT5.c",
"EN-301-549",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure every ARIA input field has an accessible name",
"help": "ARIA input fields must have an accessible name",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-input-field-name?application=axeAPI",
"nodes": []
},
{
"id": "aria-meter-name",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag111",
"EN-301-549",
"EN-9.1.1.1"
],
"description": "Ensure every ARIA meter node has an accessible name",
"help": "ARIA meter nodes must have an accessible name",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-meter-name?application=axeAPI",
"nodes": []
},
{
"id": "aria-progressbar-name",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag111",
"EN-301-549",
"EN-9.1.1.1"
],
"description": "Ensure every ARIA progressbar node has an accessible name",
"help": "ARIA progressbar nodes must have an accessible name",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-progressbar-name?application=axeAPI",
"nodes": []
},
{
"id": "aria-prohibited-attr",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure ARIA attributes are not prohibited for an element's role",
"help": "Elements must only use permitted ARIA attributes",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-prohibited-attr?application=axeAPI",
"nodes": []
},
{
"id": "aria-required-attr",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure elements with ARIA roles have all required ARIA attributes",
"help": "Required ARIA attributes must be provided",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-required-attr?application=axeAPI",
"nodes": []
},
{
"id": "aria-required-children",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag131",
"EN-301-549",
"EN-9.1.3.1"
],
"description": "Ensure elements with an ARIA role that require child roles contain them",
"help": "Certain ARIA roles must contain particular children",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-required-children?application=axeAPI",
"nodes": []
},
{
"id": "aria-required-parent",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag131",
"EN-301-549",
"EN-9.1.3.1"
],
"description": "Ensure elements with an ARIA role that require parent roles are contained by them",
"help": "Certain ARIA roles must be contained by particular parents",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-required-parent?application=axeAPI",
"nodes": []
},
{
"id": "aria-roles",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure all elements with a role attribute use a valid value",
"help": "ARIA roles used must conform to valid values",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-roles?application=axeAPI",
"nodes": []
},
{
"id": "aria-toggle-field-name",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"TTv5",
"TT5.c",
"EN-301-549",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure every ARIA toggle field has an accessible name",
"help": "ARIA toggle fields must have an accessible name",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-toggle-field-name?application=axeAPI",
"nodes": []
},
{
"id": "aria-tooltip-name",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure every ARIA tooltip node has an accessible name",
"help": "ARIA tooltip nodes must have an accessible name",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-tooltip-name?application=axeAPI",
"nodes": []
},
{
"id": "aria-valid-attr-value",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure all ARIA attributes have valid values",
"help": "ARIA attributes must conform to valid values",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-valid-attr-value?application=axeAPI",
"nodes": []
},
{
"id": "aria-valid-attr",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure attributes that begin with aria- are valid ARIA attributes",
"help": "ARIA attributes must conform to valid names",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-valid-attr?application=axeAPI",
"nodes": []
},
{
"id": "autocomplete-valid",
"impact": null,
"tags": [
"cat.forms",
"wcag21aa",
"wcag135",
"EN-301-549",
"EN-9.1.3.5",
"ACT"
],
"description": "Ensure the autocomplete attribute is correct and suitable for the form field",
"help": "autocomplete attribute must be used correctly",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/autocomplete-valid?application=axeAPI",
"nodes": []
},
{
"id": "blink",
"impact": null,
"tags": [
"cat.time-and-media",
"wcag2a",
"wcag222",
"section508",
"section508.22.j",
"TTv5",
"TT2.b",
"EN-301-549",
"EN-9.2.2.2"
],
"description": "Ensure <blink> elements are not used",
"help": "<blink> elements are deprecated and must not be used",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/blink?application=axeAPI",
"nodes": []
},
{
"id": "definition-list",
"impact": null,
"tags": [
"cat.structure",
"wcag2a",
"wcag131",
"EN-301-549",
"EN-9.1.3.1"
],
"description": "Ensure <dl> elements are structured correctly",
"help": "<dl> elements must only directly contain properly-ordered <dt> and <dd> groups, <script>, <template> or <div> elements",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/definition-list?application=axeAPI",
"nodes": []
},
{
"id": "dlitem",
"impact": null,
"tags": [
"cat.structure",
"wcag2a",
"wcag131",
"EN-301-549",
"EN-9.1.3.1"
],
"description": "Ensure <dt> and <dd> elements are contained by a <dl>",
"help": "<dt> and <dd> elements must be contained by a <dl>",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/dlitem?application=axeAPI",
"nodes": []
},
{
"id": "duplicate-id-aria",
"impact": null,
"tags": [
"cat.parsing",
"wcag2a",
"wcag412",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure every id attribute value used in ARIA and in labels is unique",
"help": "IDs used in ARIA and labels must be unique",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/duplicate-id-aria?application=axeAPI",
"nodes": []
},
{
"id": "frame-focusable-content",
"impact": null,
"tags": [
"cat.keyboard",
"wcag2a",
"wcag211",
"TTv5",
"TT4.a",
"EN-301-549",
"EN-9.2.1.1"
],
"description": "Ensure <frame> and <iframe> elements with focusable content do not have tabindex=-1",
"help": "Frames with focusable content must not have tabindex=-1",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/frame-focusable-content?application=axeAPI",
"nodes": []
},
{
"id": "frame-title-unique",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag412",
"TTv5",
"TT12.d",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure <iframe> and <frame> elements contain a unique title attribute",
"help": "Frames must have a unique title attribute",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/frame-title-unique?application=axeAPI",
"nodes": []
},
{
"id": "frame-title",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag412",
"section508",
"section508.22.i",
"TTv5",
"TT12.d",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure <iframe> and <frame> elements have an accessible name",
"help": "Frames must have an accessible name",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/frame-title?application=axeAPI",
"nodes": []
},
{
"id": "html-xml-lang-mismatch",
"impact": null,
"tags": [
"cat.language",
"wcag2a",
"wcag311",
"EN-301-549",
"EN-9.3.1.1",
"ACT"
],
"description": "Ensure that HTML elements with both valid lang and xml:lang attributes agree on the base language of the page",
"help": "HTML elements with lang and xml:lang must have the same base language",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-xml-lang-mismatch?application=axeAPI",
"nodes": []
},
{
"id": "input-button-name",
"impact": null,
"tags": [
"cat.name-role-value",
"wcag2a",
"wcag412",
"section508",
"section508.22.a",
"TTv5",
"TT5.c",
"EN-301-549",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure input buttons have discernible text",
"help": "Input buttons must have discernible text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/input-button-name?application=axeAPI",
"nodes": []
},
{
"id": "input-image-alt",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag111",
"wcag412",
"section508",
"section508.22.a",
"TTv5",
"TT7.a",
"EN-301-549",
"EN-9.1.1.1",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure <input type=\"image\"> elements have alternative text",
"help": "Image buttons must have alternative text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/input-image-alt?application=axeAPI",
"nodes": []
},
{
"id": "link-in-text-block",
"impact": null,
"tags": [
"cat.color",
"wcag2a",
"wcag141",
"TTv5",
"TT13.a",
"EN-301-549",
"EN-9.1.4.1"
],
"description": "Ensure links are distinguished from surrounding text in a way that does not rely on color",
"help": "Links must be distinguishable without relying on color",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/link-in-text-block?application=axeAPI",
"nodes": []
},
{
"id": "list",
"impact": null,
"tags": [
"cat.structure",
"wcag2a",
"wcag131",
"EN-301-549",
"EN-9.1.3.1"
],
"description": "Ensure that lists are structured correctly",
"help": "<ul> and <ol> must only directly contain <li>, <script> or <template> elements",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/list?application=axeAPI",
"nodes": []
},
{
"id": "listitem",
"impact": null,
"tags": [
"cat.structure",
"wcag2a",
"wcag131",
"EN-301-549",
"EN-9.1.3.1"
],
"description": "Ensure <li> elements are used semantically",
"help": "<li> elements must be contained in a <ul> or <ol>",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/listitem?application=axeAPI",
"nodes": []
},
{
"id": "marquee",
"impact": null,
"tags": [
"cat.parsing",
"wcag2a",
"wcag222",
"TTv5",
"TT2.b",
"EN-301-549",
"EN-9.2.2.2"
],
"description": "Ensure <marquee> elements are not used",
"help": "<marquee> elements are deprecated and must not be used",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/marquee?application=axeAPI",
"nodes": []
},
{
"id": "meta-refresh",
"impact": null,
"tags": [
"cat.time-and-media",
"wcag2a",
"wcag221",
"TTv5",
"TT8.a",
"EN-301-549",
"EN-9.2.2.1"
],
"description": "Ensure <meta http-equiv=\"refresh\"> is not used for delayed refresh",
"help": "Delayed refresh under 20 hours must not be used",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/meta-refresh?application=axeAPI",
"nodes": []
},
{
"id": "object-alt",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag111",
"section508",
"section508.22.a",
"EN-301-549",
"EN-9.1.1.1"
],
"description": "Ensure <object> elements have alternative text",
"help": "<object> elements must have alternative text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/object-alt?application=axeAPI",
"nodes": []
},
{
"id": "role-img-alt",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag111",
"section508",
"section508.22.a",
"TTv5",
"TT7.a",
"EN-301-549",
"EN-9.1.1.1",
"ACT"
],
"description": "Ensure [role=\"img\"] elements have alternative text",
"help": "[role=\"img\"] elements must have an alternative text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/role-img-alt?application=axeAPI",
"nodes": []
},
{
"id": "scrollable-region-focusable",
"impact": null,
"tags": [
"cat.keyboard",
"wcag2a",
"wcag211",
"wcag213",
"TTv5",
"TT4.a",
"EN-301-549",
"EN-9.2.1.1",
"EN-9.2.1.3"
],
"description": "Ensure elements that have scrollable content are accessible by keyboard",
"help": "Scrollable region must have keyboard access",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/scrollable-region-focusable?application=axeAPI",
"nodes": []
},
{
"id": "server-side-image-map",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag211",
"section508",
"section508.22.f",
"TTv5",
"TT4.a",
"EN-301-549",
"EN-9.2.1.1"
],
"description": "Ensure that server-side image maps are not used",
"help": "Server-side image maps must not be used",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/server-side-image-map?application=axeAPI",
"nodes": []
},
{
"id": "svg-img-alt",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag111",
"section508",
"section508.22.a",
"TTv5",
"TT7.a",
"EN-301-549",
"EN-9.1.1.1",
"ACT"
],
"description": "Ensure <svg> elements with an img, graphics-document or graphics-symbol role have an accessible text",
"help": "<svg> elements with an img role must have an alternative text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/svg-img-alt?application=axeAPI",
"nodes": []
},
{
"id": "td-headers-attr",
"impact": null,
"tags": [
"cat.tables",
"wcag2a",
"wcag131",
"section508",
"section508.22.g",
"TTv5",
"TT14.b",
"EN-301-549",
"EN-9.1.3.1"
],
"description": "Ensure that each cell in a table that uses the headers attribute refers only to other cells in that table",
"help": "Table cells that use the headers attribute must only refer to cells in the same table",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/td-headers-attr?application=axeAPI",
"nodes": []
},
{
"id": "th-has-data-cells",
"impact": null,
"tags": [
"cat.tables",
"wcag2a",
"wcag131",
"section508",
"section508.22.g",
"TTv5",
"TT14.b",
"EN-301-549",
"EN-9.1.3.1"
],
"description": "Ensure that <th> elements and elements with role=columnheader/rowheader have data cells they describe",
"help": "Table headers in a data table must refer to data cells",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/th-has-data-cells?application=axeAPI",
"nodes": []
},
{
"id": "valid-lang",
"impact": null,
"tags": [
"cat.language",
"wcag2aa",
"wcag312",
"TTv5",
"TT11.b",
"EN-301-549",
"EN-9.3.1.2",
"ACT"
],
"description": "Ensure lang attributes have valid values",
"help": "lang attribute must have a valid value",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/valid-lang?application=axeAPI",
"nodes": []
},
{
"id": "video-caption",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag122",
"section508",
"section508.22.a",
"TTv5",
"TT17.a",
"EN-301-549",
"EN-9.1.2.2"
],
"description": "Ensure <video> elements have captions",
"help": "<video> elements must have captions",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/video-caption?application=axeAPI",
"nodes": []
},
{
"id": "no-autoplay-audio",
"impact": null,
"tags": [
"cat.time-and-media",
"wcag2a",
"wcag142",
"TTv5",
"TT2.a",
"EN-301-549",
"EN-9.1.4.2",
"ACT"
],
"description": "Ensure <video> or <audio> elements do not autoplay audio for more than 3 seconds without a control mechanism to stop or mute the audio",
"help": "<video> or <audio> elements must not play automatically",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/no-autoplay-audio?application=axeAPI",
"nodes": []
}
],
"passes": [
{
"id": "aria-hidden-body",
"impact": null,
"tags": [
"cat.aria",
"wcag2a",
"wcag131",
"wcag412",
"EN-301-549",
"EN-9.1.3.1",
"EN-9.4.1.2"
],
"description": "Ensure aria-hidden=\"true\" is not present on the document body.",
"help": "aria-hidden=\"true\" must not be present on the document body",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-hidden-body?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "aria-hidden-body",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "No aria-hidden attribute is present on document body"
}
],
"all": [],
"none": [],
"impact": null,
"html": "<body class=\"bg-stone-50 text-stone-800\">",
"target": [
"body"
]
}
]
},
{
"id": "avoid-inline-spacing",
"impact": null,
"tags": [
"cat.structure",
"wcag21aa",
"wcag1412",
"EN-301-549",
"EN-9.1.4.12",
"ACT"
],
"description": "Ensure that text spacing set through style attributes can be adjusted with custom stylesheets",
"help": "Inline text spacing must be adjustable with custom stylesheets",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/avoid-inline-spacing?application=axeAPI",
"nodes": [
{
"any": [],
"all": [
{
"id": "important-letter-spacing",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Letter-spacing in the style attribute is not set to !important, or meets the minimum"
},
{
"id": "important-word-spacing",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "word-spacing in the style attribute is not set to !important, or meets the minimum"
},
{
"id": "important-line-height",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "line-height in the style attribute is not set to !important, or meets the minimum"
}
],
"none": [],
"impact": null,
"html": "<html lang=\"en\" style=\"--accent: #854d0e;\">",
"target": [
"html"
]
}
]
},
{
"id": "button-name",
"impact": "critical",
"tags": [
"cat.name-role-value",
"wcag2a",
"wcag412",
"section508",
"section508.22.a",
"TTv5",
"TT6.a",
"EN-301-549",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure buttons have discernible text",
"help": "Buttons must have discernible text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/button-name?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element has inner text that is visible to screen readers"
}
],
"all": [],
"none": [],
"impact": null,
"html": "<button onclick=\"showSubscribeModal()\" class=\"hidden md:flex items-center px-5 py-2.5 text-sm font-semibold bg-amber-900 hover:bg-amber-950 transition-colors text-white rounded-3xl\">\n <span>Subscribe</span>\n </button>",
"target": [
".hover\\:bg-amber-950.md\\:flex[onclick=\"showSubscribeModal()\"]"
]
}
]
},
{
"id": "bypass",
"impact": null,
"tags": [
"cat.keyboard",
"wcag2a",
"wcag241",
"section508",
"section508.22.o",
"TTv5",
"TT9.a",
"EN-301-549",
"EN-9.2.4.1"
],
"description": "Ensure each page has at least one mechanism for a user to bypass navigation and jump straight to the content",
"help": "Page must have means to bypass repeated blocks",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/bypass?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "internal-link-present",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Valid skip link found"
},
{
"id": "header-present",
"data": null,
"relatedNodes": [
{
"html": "<h1 class=\"text-6xl md:text-6xl leading-[1.05] tracking-tighter heading-serif font-bold mb-4\">\n Timeless recipes.<br>\n Modern flavor.\n </h1>",
"target": [
"h1"
]
},
{
"html": "<h2 class=\"heading-serif text-4xl tracking-tighter font-bold text-stone-900\">Featured Recipes</h2>",
"target": [
".items-end.mb-8.justify-between > div > .text-4xl.text-stone-900"
]
},
{
"html": "<h3 class=\"font-semibold text-xl leading-tight\">Braised Short Ribs</h3>",
"target": [
".recipe-card.shadow-sm.overflow-hidden:nth-child(1) > .p-5 > .mb-2.justify-between.items-center > .leading-tight"
]
},
{
"html": "<h3 class=\"font-semibold text-xl leading-tight\">Seared Scallops</h3>",
"target": [
".recipe-card.shadow-sm.overflow-hidden:nth-child(2) > .p-5 > .mb-2.justify-between.items-center > .leading-tight"
]
},
{
"html": "<h3 class=\"font-semibold text-xl leading-tight\">Wild Mushroom Risotto</h3>",
"target": [
".recipe-card.shadow-sm.overflow-hidden:nth-child(3) > .p-5 > .mb-2.justify-between.items-center > .leading-tight"
]
},
{
"html": "<h3 class=\"font-semibold text-xl leading-tight\">Herb Roasted Chicken</h3>",
"target": [
".recipe-card.shadow-sm.overflow-hidden:nth-child(4) > .p-5 > .mb-2.justify-between.items-center > .leading-tight"
]
},
{
"html": "<h2 class=\"heading-serif text-4xl tracking-tighter font-bold text-stone-900\">Expert Cooking Tips</h2>",
"target": [
".mb-8 > .text-4xl.text-stone-900"
]
},
{
"html": "<h4 class=\"font-semibold mb-1.5\">Perfect Braising</h4>",
"target": [
".bg-stone-50.p-5.rounded-3xl:nth-child(1) > .mb-1\\.5"
]
},
{
"html": "<h4 class=\"font-semibold mb-1.5\">Building Umami</h4>",
"target": [
".bg-stone-50.p-5.rounded-3xl:nth-child(2) > .mb-1\\.5"
]
},
{
"html": "<h4 class=\"font-semibold mb-1.5\">Food & Drink Pairing</h4>",
"target": [
".bg-stone-50.p-5.rounded-3xl:nth-child(3) > .mb-1\\.5"
]
},
{
"html": "<h3 class=\"font-semibold text-xl mb-2\">The Science of Flavor</h3>",
"target": [
".lg\\:col-span-4.p-6.bg-stone-900 > h3"
]
},
{
"html": "<h2 class=\"heading-serif text-4xl tracking-tighter font-bold\">Weekly Meal Planner</h2>",
"target": [
".lg\\:flex-row > div:nth-child(1) > .text-4xl"
]
},
{
"html": "<h4 class=\"font-semibold mb-4 px-1\">Quick Add Recipes</h4>",
"target": [
".lg\\:col-span-4.p-5.bg-white > .px-1"
]
},
{
"html": "<h4 class=\"font-semibold\">Your Week</h4>",
"target": [
".px-1.mb-4.justify-between > h4"
]
},
{
"html": "<h2 class=\"heading-serif text-4xl tracking-tighter font-bold\">Restaurant Guides</h2>",
"target": [
"#guides > .items-end.mb-8.justify-between > div > .text-4xl"
]
},
{
"html": "<h4 class=\"font-bold text-xl\">The Willow Bistro</h4>",
"target": [
".overflow-hidden.bg-white.rounded-3xl:nth-child(1) > .p-5 > .items-start.justify-between.flex > div:nth-child(1) > h4"
]
},
{
"html": "<h4 class=\"font-bold text-xl\">Ember & Oak</h4>",
"target": [
".overflow-hidden.bg-white.rounded-3xl:nth-child(2) > .p-5 > .items-start.justify-between.flex > div:nth-child(1) > h4"
]
},
{
"html": "<h4 class=\"font-bold text-xl\">Aqua & Vine</h4>",
"target": [
".overflow-hidden.bg-white.rounded-3xl:nth-child(3) > .p-5 > .items-start.justify-between.flex > div:nth-child(1) > h4"
]
},
{
"html": "<h2 class=\"heading-serif text-3xl font-bold tracking-tighter\">Catering</h2>",
"target": [
".gap-3.mb-5.items-center > .text-3xl"
]
},
{
"html": "<h2 class=\"heading-serif text-3xl font-bold tracking-tighter mt-1\">Upcoming Events</h2>",
"target": [
".mt-1.text-3xl"
]
},
{
"html": "<h2 class=\"heading-serif text-4xl tracking-tighter font-bold\">What our community says</h2>",
"target": [
"#testimonials > .mb-8 > .text-4xl"
]
},
{
"html": "<h2 class=\"heading-serif text-3xl tracking-tighter font-bold mb-6\">Your Questions Answered</h2>",
"target": [
".mb-6.text-3xl"
]
},
{
"html": "<h3 class=\"font-semibold text-2xl\">Ready to transform your kitchen?</h3>",
"target": [
".text-2xl"
]
}
],
"impact": "serious",
"message": "Page has a heading"
}
],
"all": [],
"none": [],
"impact": null,
"html": "<html lang=\"en\" style=\"--accent: #854d0e;\">",
"target": [
"html"
]
}
]
},
{
"id": "color-contrast",
"impact": "serious",
"tags": [
"cat.color",
"wcag2aa",
"wcag143",
"TTv5",
"TT13.c",
"EN-301-549",
"EN-9.1.4.3",
"ACT"
],
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"help": "Elements must meet minimum color contrast ratio thresholds",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "color-contrast",
"data": {
"fgColor": "#1c1917",
"bgColor": "#ffffff",
"contrastRatio": 17.48,
"fontSize": "22.5pt (30px)",
"fontWeight": "bold",
"messageKey": null,
"expectedContrastRatio": "3:1",
"shadowColor": null
},
"relatedNodes": [],
"impact": "serious",
"message": "Element has sufficient color contrast of 17.48"
}
],
"all": [],
"none": [],
"impact": null,
"html": "<span class=\"font-bold text-3xl tracking-tighter heading-serif text-stone-900\">Harvest</span>",
"target": [
".text-3xl.text-stone-900.tracking-tighter"
]
}
]
},
{
"id": "document-title",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag242",
"TTv5",
"TT12.a",
"EN-301-549",
"EN-9.2.4.2",
"ACT"
],
"description": "Ensure each HTML document contains a non-empty <title> element",
"help": "Documents must have <title> element to aid in navigation",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/document-title?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "doc-has-title",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Document has a non-empty <title> element"
}
],
"all": [],
"none": [],
"impact": null,
"html": "<html lang=\"en\" style=\"--accent: #854d0e;\">",
"target": [
"html"
]
}
]
},
{
"id": "form-field-multiple-labels",
"impact": null,
"tags": [
"cat.forms",
"wcag2a",
"wcag332",
"TTv5",
"TT5.c",
"EN-301-549",
"EN-9.3.3.2"
],
"description": "Ensure form field does not have multiple label elements",
"help": "Form field must not have multiple label elements",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/form-field-multiple-labels?application=axeAPI",
"nodes": [
{
"any": [],
"all": [],
"none": [
{
"id": "multiple-label",
"data": null,
"relatedNodes": [],
"impact": "moderate",
"message": "Form field does not have multiple label elements"
}
],
"impact": null,
"html": "<input type=\"text\" placeholder=\"Search recipes...\" class=\"bg-transparent border-none outline-none text-sm w-36 placeholder-stone-400\">",
"target": [
".bg-transparent"
]
}
]
},
{
"id": "html-has-lang",
"impact": null,
"tags": [
"cat.language",
"wcag2a",
"wcag311",
"TTv5",
"TT11.a",
"EN-301-549",
"EN-9.3.1.1",
"ACT"
],
"description": "Ensure every HTML document has a lang attribute",
"help": "<html> element must have a lang attribute",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-has-lang?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "has-lang",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "The <html> element has a lang attribute"
}
],
"all": [],
"none": [],
"impact": null,
"html": "<html lang=\"en\" style=\"--accent: #854d0e;\">",
"target": [
"html"
]
}
]
},
{
"id": "html-lang-valid",
"impact": null,
"tags": [
"cat.language",
"wcag2a",
"wcag311",
"TTv5",
"TT11.a",
"EN-301-549",
"EN-9.3.1.1",
"ACT"
],
"description": "Ensure the lang attribute of the <html> element has a valid value",
"help": "<html> element must have a valid value for the lang attribute",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-lang-valid?application=axeAPI",
"nodes": [
{
"any": [],
"all": [],
"none": [
{
"id": "valid-lang",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Value of lang attribute is included in the list of valid languages"
}
],
"impact": null,
"html": "<html lang=\"en\" style=\"--accent: #854d0e;\">",
"target": [
"html"
]
}
]
},
{
"id": "image-alt",
"impact": null,
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag111",
"section508",
"section508.22.a",
"TTv5",
"TT7.a",
"TT7.b",
"EN-301-549",
"EN-9.1.1.1",
"ACT"
],
"description": "Ensure <img> elements have alternative text or a role of none or presentation",
"help": "Images must have alternative text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/image-alt?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "has-alt",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element has an alt attribute"
}
],
"all": [],
"none": [
{
"id": "alt-space-value",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element has a valid alt attribute value"
}
],
"impact": null,
"html": "<img src=\"https://placehold.co/44x44/451a03/fff?text=H&H&font=playfair+display\" alt=\"Harvest & Hearth logo\" class=\"w-11 h-11 object-cover\">",
"target": [
"img[alt=\"Harvest & Hearth logo\"]"
]
}
]
},
{
"id": "label",
"impact": null,
"tags": [
"cat.forms",
"wcag2a",
"wcag412",
"section508",
"section508.22.n",
"TTv5",
"TT5.c",
"EN-301-549",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure every form element has a label",
"help": "Form elements must have labels",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/label?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "non-empty-placeholder",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element has a placeholder attribute"
}
],
"all": [],
"none": [
{
"id": "hidden-explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Form element has a visible explicit <label>"
}
],
"impact": null,
"html": "<input type=\"text\" placeholder=\"Search recipes...\" class=\"bg-transparent border-none outline-none text-sm w-36 placeholder-stone-400\">",
"target": [
".bg-transparent"
]
}
]
},
{
"id": "link-name",
"impact": "serious",
"tags": [
"cat.name-role-value",
"wcag2a",
"wcag244",
"wcag412",
"section508",
"section508.22.a",
"TTv5",
"TT6.a",
"EN-301-549",
"EN-9.2.4.4",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure links have discernible text",
"help": "Links must have discernible text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/link-name?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element has text that is visible to screen readers"
}
],
"all": [],
"none": [
{
"id": "focusable-no-name",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element is not in tab order or has accessible text"
}
],
"impact": null,
"html": "<a href=\"#recipes\" class=\"nav-link px-3 py-2 text-stone-700 hover:text-amber-800\">Recipes</a>",
"target": [
".py-2.hover\\:text-amber-800[href$=\"#recipes\"]"
]
}
]
},
{
"id": "meta-viewport",
"impact": null,
"tags": [
"cat.sensory-and-visual-cues",
"wcag2aa",
"wcag144",
"EN-301-549",
"EN-9.1.4.4",
"ACT"
],
"description": "Ensure <meta name=\"viewport\"> does not disable text scaling and zooming",
"help": "Zooming and scaling must not be disabled",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/meta-viewport?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "meta-viewport",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "<meta> tag does not disable zooming on mobile devices"
}
],
"all": [],
"none": [],
"impact": null,
"html": "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">",
"target": [
"meta[name=\"viewport\"]"
]
}
]
},
{
"id": "nested-interactive",
"impact": null,
"tags": [
"cat.keyboard",
"wcag2a",
"wcag412",
"TTv5",
"TT6.a",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure interactive controls are not nested as they are not always announced by screen readers or can cause focus problems for assistive technologies",
"help": "Interactive controls must not be nested",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/nested-interactive?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "no-focusable-content",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element does not have focusable descendants"
}
],
"all": [],
"none": [],
"impact": null,
"html": "<img src=\"https://placehold.co/44x44/451a03/fff?text=H&H&font=playfair+display\" alt=\"Harvest & Hearth logo\" class=\"w-11 h-11 object-cover\">",
"target": [
"img[alt=\"Harvest & Hearth logo\"]"
]
}
]
},
{
"id": "summary-name",
"impact": null,
"tags": [
"cat.name-role-value",
"wcag2a",
"wcag412",
"section508",
"section508.22.a",
"TTv5",
"TT6.a",
"EN-301-549",
"EN-9.4.1.2"
],
"description": "Ensure summary elements have discernible text",
"help": "Summary elements must have discernible text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/summary-name?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element has text that is visible to screen readers"
}
],
"all": [],
"none": [],
"impact": null,
"html": "<summary class=\"accordion-header cursor-pointer flex justify-between items-center py-3 font-medium list-none\">",
"target": [
"details:nth-child(1) > summary"
]
}
]
},
{
"id": "target-size",
"impact": null,
"tags": [
"cat.sensory-and-visual-cues",
"wcag22aa",
"wcag258"
],
"description": "Ensure touch targets have sufficient size and space",
"help": "All touch targets must be 24px large, or leave sufficient space",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/target-size?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "target-size",
"data": {
"minSize": 24,
"width": 74.6,
"height": 36
},
"relatedNodes": [],
"impact": "serious",
"message": "Control has sufficient size (74.6px by 36px, should be at least 24px by 24px)"
},
{
"id": "target-offset",
"data": {
"closestOffset": 24,
"minOffset": 24
},
"relatedNodes": [],
"impact": "serious",
"message": "Target has sufficient space from its closest neighbors. Safe clickable space has a diameter of 24px which is at least 24px."
}
],
"all": [],
"none": [],
"impact": null,
"html": "<a href=\"#recipes\" class=\"nav-link px-3 py-2 text-stone-700 hover:text-amber-800\">Recipes</a>",
"target": [
".py-2.hover\\:text-amber-800[href$=\"#recipes\"]"
]
}
]
}
],
"incomplete": [
{
"id": "color-contrast",
"impact": "serious",
"tags": [
"cat.color",
"wcag2aa",
"wcag143",
"TTv5",
"TT13.c",
"EN-301-549",
"EN-9.1.4.3",
"ACT"
],
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"help": "Elements must meet minimum color contrast ratio thresholds",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "color-contrast",
"data": {
"fgColor": null,
"bgColor": null,
"contrastRatio": 0,
"fontSize": "9.0pt (12px)",
"fontWeight": "normal",
"messageKey": "imgNode",
"expectedContrastRatio": "4.5:1",
"shadowColor": null
},
"relatedNodes": [
{
"html": "<div class=\"absolute bottom-8 left-8 bg-white/95 backdrop-blur px-4 py-3 rounded-3xl shadow-xl hidden md:block\">",
"target": [
".bottom-8"
]
},
{
"html": "<img src=\"https://picsum.photos/id/1016/900/1100\" alt=\"Beautifully plated seasonal dish with fresh herbs and wine on a rustic wooden table\" class=\"w-full h-[520px] md:h-[620px] object-cover md:rounded-bl-[80px]\">",
"target": [
".h-\\[520px\\]"
]
}
],
"impact": "serious",
"message": "Element's background color could not be determined because element contains an image node"
}
],
"all": [],
"none": [],
"impact": "serious",
"html": "<div class=\"text-xs text-stone-500\">Today's featured</div>",
"target": [
".bottom-8 > .gap-x-3.items-center.flex > div:nth-child(1) > .text-stone-500.text-xs"
],
"failureSummary": "Fix any of the following:\n Element's background color could not be determined because element contains an image node"
}
]
}
],
"violations": [
{
"id": "button-name",
"impact": "critical",
"tags": [
"cat.name-role-value",
"wcag2a",
"wcag412",
"section508",
"section508.22.a",
"TTv5",
"TT6.a",
"EN-301-549",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure buttons have discernible text",
"help": "Buttons must have discernible text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/button-name?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"quickAddToPlanner('1')\" class=\"px-3 py-2.5 text-sm font-semibold border border-stone-200 hover:bg-stone-50 text-stone-700 rounded-2xl transition-colors\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>",
"target": [
"button[onclick=\"quickAddToPlanner('1')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"quickAddToPlanner('2')\" class=\"px-3 py-2.5 text-sm font-semibold border border-stone-200 hover:bg-stone-50 text-stone-700 rounded-2xl transition-colors\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>",
"target": [
"button[onclick=\"quickAddToPlanner('2')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"quickAddToPlanner('3')\" class=\"px-3 py-2.5 text-sm font-semibold border border-stone-200 hover:bg-stone-50 text-stone-700 rounded-2xl transition-colors\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>",
"target": [
"button[onclick=\"quickAddToPlanner('3')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"quickAddToPlanner('4')\" class=\"px-3 py-2.5 text-sm font-semibold border border-stone-200 hover:bg-stone-50 text-stone-700 rounded-2xl transition-colors\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>",
"target": [
"button[onclick=\"quickAddToPlanner('4')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"showAddToDayModal('Monday')\" class=\"text-amber-700 hover:text-amber-900\">\n <i class=\"fa-solid fa-plus text-xs\"></i>\n </button>",
"target": [
"button[onclick=\"showAddToDayModal('Monday')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"removeFromPlan('Monday', 0)\" class=\"text-red-400 hover:text-red-600 transition-colors\">\n <i class=\"fa-solid fa-times\"></i>\n </button>",
"target": [
"button[onclick=\"removeFromPlan('Monday', 0)\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"showAddToDayModal('Tuesday')\" class=\"text-amber-700 hover:text-amber-900\">\n <i class=\"fa-solid fa-plus text-xs\"></i>\n </button>",
"target": [
"button[onclick=\"showAddToDayModal('Tuesday')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"showAddToDayModal('Wednesday')\" class=\"text-amber-700 hover:text-amber-900\">\n <i class=\"fa-solid fa-plus text-xs\"></i>\n </button>",
"target": [
"button[onclick=\"showAddToDayModal('Wednesday')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"removeFromPlan('Wednesday', 0)\" class=\"text-red-400 hover:text-red-600 transition-colors\">\n <i class=\"fa-solid fa-times\"></i>\n </button>",
"target": [
"button[onclick=\"removeFromPlan('Wednesday', 0)\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"showAddToDayModal('Thursday')\" class=\"text-amber-700 hover:text-amber-900\">\n <i class=\"fa-solid fa-plus text-xs\"></i>\n </button>",
"target": [
"button[onclick=\"showAddToDayModal('Thursday')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"showAddToDayModal('Friday')\" class=\"text-amber-700 hover:text-amber-900\">\n <i class=\"fa-solid fa-plus text-xs\"></i>\n </button>",
"target": [
"button[onclick=\"showAddToDayModal('Friday')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"removeFromPlan('Friday', 0)\" class=\"text-red-400 hover:text-red-600 transition-colors\">\n <i class=\"fa-solid fa-times\"></i>\n </button>",
"target": [
"button[onclick=\"removeFromPlan('Friday', 0)\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"showAddToDayModal('Saturday')\" class=\"text-amber-700 hover:text-amber-900\">\n <i class=\"fa-solid fa-plus text-xs\"></i>\n </button>",
"target": [
"button[onclick=\"showAddToDayModal('Saturday')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "button-has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have inner text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<button onclick=\"showAddToDayModal('Sunday')\" class=\"text-amber-700 hover:text-amber-900\">\n <i class=\"fa-solid fa-plus text-xs\"></i>\n </button>",
"target": [
"button[onclick=\"showAddToDayModal('Sunday')\"]"
],
"failureSummary": "Fix any of the following:\n Element does not have inner text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
]
},
{
"id": "color-contrast",
"impact": "serious",
"tags": [
"cat.color",
"wcag2aa",
"wcag143",
"TTv5",
"TT13.c",
"EN-301-549",
"EN-9.1.4.3",
"ACT"
],
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"help": "Elements must meet minimum color contrast ratio thresholds",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "color-contrast",
"data": {
"fgColor": "#a8a29e",
"bgColor": "#ffffff",
"contrastRatio": 2.52,
"fontSize": "9.0pt (12px)",
"fontWeight": "normal",
"messageKey": null,
"expectedContrastRatio": "4.5:1",
"shadowColor": null
},
"relatedNodes": [
{
"html": "<div class=\"meal-plan-day border border-stone-200 bg-white p-3 rounded-2xl min-h-[132px]\">",
"target": [
".meal-plan-day.min-h-\\[132px\\].p-3:nth-child(2)"
]
}
],
"impact": "serious",
"message": "Element has insufficient color contrast of 2.52 (foreground color: #a8a29e, background color: #ffffff, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
}
],
"all": [],
"none": [],
"impact": "serious",
"html": "<div class=\"text-xs text-stone-400 py-3 text-center\">No meals planned</div>",
"target": [
".meal-plan-day.min-h-\\[132px\\].p-3:nth-child(2) > .space-y-1 > .text-stone-400.text-center.py-3"
],
"failureSummary": "Fix any of the following:\n Element has insufficient color contrast of 2.52 (foreground color: #a8a29e, background color: #ffffff, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
},
{
"any": [
{
"id": "color-contrast",
"data": {
"fgColor": "#a8a29e",
"bgColor": "#ffffff",
"contrastRatio": 2.52,
"fontSize": "9.0pt (12px)",
"fontWeight": "normal",
"messageKey": null,
"expectedContrastRatio": "4.5:1",
"shadowColor": null
},
"relatedNodes": [
{
"html": "<div class=\"meal-plan-day border border-stone-200 bg-white p-3 rounded-2xl min-h-[132px]\">",
"target": [
".meal-plan-day.min-h-\\[132px\\].p-3:nth-child(4)"
]
}
],
"impact": "serious",
"message": "Element has insufficient color contrast of 2.52 (foreground color: #a8a29e, background color: #ffffff, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
}
],
"all": [],
"none": [],
"impact": "serious",
"html": "<div class=\"text-xs text-stone-400 py-3 text-center\">No meals planned</div>",
"target": [
".meal-plan-day.min-h-\\[132px\\].p-3:nth-child(4) > .space-y-1 > .text-stone-400.text-center.py-3"
],
"failureSummary": "Fix any of the following:\n Element has insufficient color contrast of 2.52 (foreground color: #a8a29e, background color: #ffffff, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
},
{
"any": [
{
"id": "color-contrast",
"data": {
"fgColor": "#a8a29e",
"bgColor": "#ffffff",
"contrastRatio": 2.52,
"fontSize": "9.0pt (12px)",
"fontWeight": "normal",
"messageKey": null,
"expectedContrastRatio": "4.5:1",
"shadowColor": null
},
"relatedNodes": [
{
"html": "<div class=\"meal-plan-day border border-stone-200 bg-white p-3 rounded-2xl min-h-[132px]\">",
"target": [
".meal-plan-day.min-h-\\[132px\\].p-3:nth-child(6)"
]
}
],
"impact": "serious",
"message": "Element has insufficient color contrast of 2.52 (foreground color: #a8a29e, background color: #ffffff, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
}
],
"all": [],
"none": [],
"impact": "serious",
"html": "<div class=\"text-xs text-stone-400 py-3 text-center\">No meals planned</div>",
"target": [
".meal-plan-day.min-h-\\[132px\\].p-3:nth-child(6) > .space-y-1 > .text-stone-400.text-center.py-3"
],
"failureSummary": "Fix any of the following:\n Element has insufficient color contrast of 2.52 (foreground color: #a8a29e, background color: #ffffff, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
},
{
"any": [
{
"id": "color-contrast",
"data": {
"fgColor": "#a8a29e",
"bgColor": "#ffffff",
"contrastRatio": 2.52,
"fontSize": "9.0pt (12px)",
"fontWeight": "normal",
"messageKey": null,
"expectedContrastRatio": "4.5:1",
"shadowColor": null
},
"relatedNodes": [
{
"html": "<div class=\"meal-plan-day border border-stone-200 bg-white p-3 rounded-2xl min-h-[132px]\">",
"target": [
".meal-plan-day.min-h-\\[132px\\].p-3:nth-child(7)"
]
}
],
"impact": "serious",
"message": "Element has insufficient color contrast of 2.52 (foreground color: #a8a29e, background color: #ffffff, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
}
],
"all": [],
"none": [],
"impact": "serious",
"html": "<div class=\"text-xs text-stone-400 py-3 text-center\">No meals planned</div>",
"target": [
".meal-plan-day.min-h-\\[132px\\].p-3:nth-child(7) > .space-y-1 > .text-stone-400.text-center.py-3"
],
"failureSummary": "Fix any of the following:\n Element has insufficient color contrast of 2.52 (foreground color: #a8a29e, background color: #ffffff, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
},
{
"any": [
{
"id": "color-contrast",
"data": {
"fgColor": "#78716c",
"bgColor": "#1c1917",
"contrastRatio": 3.64,
"fontSize": "9.0pt (12px)",
"fontWeight": "normal",
"messageKey": null,
"expectedContrastRatio": "4.5:1",
"shadowColor": null
},
"relatedNodes": [
{
"html": "<footer class=\"bg-stone-900 text-stone-400 pt-10 pb-8\">",
"target": [
"footer"
]
}
],
"impact": "serious",
"message": "Element has insufficient color contrast of 3.64 (foreground color: #78716c, background color: #1c1917, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
}
],
"all": [],
"none": [],
"impact": "serious",
"html": "<div>\u00a9 2025 Harvest & Hearth. All rights reserved.</div>",
"target": [
".pt-7 > div:nth-child(1)"
],
"failureSummary": "Fix any of the following:\n Element has insufficient color contrast of 3.64 (foreground color: #78716c, background color: #1c1917, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
},
{
"any": [
{
"id": "color-contrast",
"data": {
"fgColor": "#78716c",
"bgColor": "#1c1917",
"contrastRatio": 3.64,
"fontSize": "9.0pt (12px)",
"fontWeight": "normal",
"messageKey": null,
"expectedContrastRatio": "4.5:1",
"shadowColor": null
},
"relatedNodes": [
{
"html": "<footer class=\"bg-stone-900 text-stone-400 pt-10 pb-8\">",
"target": [
"footer"
]
}
],
"impact": "serious",
"message": "Element has insufficient color contrast of 3.64 (foreground color: #78716c, background color: #1c1917, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
}
],
"all": [],
"none": [],
"impact": "serious",
"html": "<div class=\"text-xs\">Crafted with care for the culinary community.</div>",
"target": [
".pt-7 > .text-xs"
],
"failureSummary": "Fix any of the following:\n Element has insufficient color contrast of 3.64 (foreground color: #78716c, background color: #1c1917, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
}
]
},
{
"id": "link-name",
"impact": "serious",
"tags": [
"cat.name-role-value",
"wcag2a",
"wcag244",
"wcag412",
"section508",
"section508.22.a",
"TTv5",
"TT6.a",
"EN-301-549",
"EN-9.2.4.4",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure links have discernible text",
"help": "Links must have discernible text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/link-name?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element does not have text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "serious",
"message": "Element has no title attribute"
}
],
"all": [],
"none": [
{
"id": "focusable-no-name",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element is in tab order and does not have accessible text"
}
],
"impact": "serious",
"html": "<a href=\"#\" class=\"hover:text-white\"><i class=\"fa-brands fa-instagram text-lg\"></i></a>",
"target": [
".mt-6.gap-x-4.flex > .hover\\:text-white[href=\"#\"]:nth-child(1)"
],
"failureSummary": "Fix all of the following:\n Element is in tab order and does not have accessible text\n\nFix any of the following:\n Element does not have text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute"
},
{
"any": [
{
"id": "has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element does not have text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "serious",
"message": "Element has no title attribute"
}
],
"all": [],
"none": [
{
"id": "focusable-no-name",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element is in tab order and does not have accessible text"
}
],
"impact": "serious",
"html": "<a href=\"#\" class=\"hover:text-white\"><i class=\"fa-brands fa-tiktok text-lg\"></i></a>",
"target": [
".mt-6.gap-x-4.flex > .hover\\:text-white[href=\"#\"]:nth-child(2)"
],
"failureSummary": "Fix all of the following:\n Element is in tab order and does not have accessible text\n\nFix any of the following:\n Element does not have text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute"
},
{
"any": [
{
"id": "has-visible-text",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element does not have text that is visible to screen readers"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "serious",
"message": "Element has no title attribute"
}
],
"all": [],
"none": [
{
"id": "focusable-no-name",
"data": null,
"relatedNodes": [],
"impact": "serious",
"message": "Element is in tab order and does not have accessible text"
}
],
"impact": "serious",
"html": "<a href=\"#\" class=\"hover:text-white\"><i class=\"fa-brands fa-youtube text-lg\"></i></a>",
"target": [
".mt-6.gap-x-4.flex > .hover\\:text-white[href=\"#\"]:nth-child(3)"
],
"failureSummary": "Fix all of the following:\n Element is in tab order and does not have accessible text\n\nFix any of the following:\n Element does not have text that is visible to screen readers\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute"
}
]
},
{
"id": "select-name",
"impact": "critical",
"tags": [
"cat.forms",
"wcag2a",
"wcag412",
"section508",
"section508.22.n",
"TTv5",
"TT5.c",
"EN-301-549",
"EN-9.4.1.2",
"ACT"
],
"description": "Ensure select element has an accessible name",
"help": "Select element must have an accessible name",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/select-name?application=axeAPI",
"nodes": [
{
"any": [
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<select class=\"text-xs border border-stone-200 bg-white px-2 py-1 rounded-xl text-stone-600\" id=\"select-1\">",
"target": [
"#select-1"
],
"failureSummary": "Fix any of the following:\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<select class=\"text-xs border border-stone-200 bg-white px-2 py-1 rounded-xl text-stone-600\" id=\"select-2\">",
"target": [
"#select-2"
],
"failureSummary": "Fix any of the following:\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<select class=\"text-xs border border-stone-200 bg-white px-2 py-1 rounded-xl text-stone-600\" id=\"select-3\">",
"target": [
"#select-3"
],
"failureSummary": "Fix any of the following:\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
},
{
"any": [
{
"id": "implicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an implicit (wrapped) <label>"
},
{
"id": "explicit-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element does not have an explicit <label>"
},
{
"id": "aria-label",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-label attribute does not exist or is empty"
},
{
"id": "aria-labelledby",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty"
},
{
"id": "non-empty-title",
"data": {
"messageKey": "noAttr"
},
"relatedNodes": [],
"impact": "critical",
"message": "Element has no title attribute"
},
{
"id": "presentational-role",
"data": null,
"relatedNodes": [],
"impact": "critical",
"message": "Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
],
"all": [],
"none": [],
"impact": "critical",
"html": "<select class=\"text-xs border border-stone-200 bg-white px-2 py-1 rounded-xl text-stone-600\" id=\"select-4\">",
"target": [
"#select-4"
],
"failureSummary": "Fix any of the following:\n Element does not have an implicit (wrapped) <label>\n Element does not have an explicit <label>\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Element has no title attribute\n Element's default semantics were not overridden with role=\"none\" or role=\"presentation\""
}
]
}
],
"coverage": {
"contract": "main-document-vertical-scroll",
"complete": true,
"positions": [
{
"y": 0,
"height": 4885
},
{
"y": 576,
"height": 4885
},
{
"y": 1152,
"height": 4885
},
{
"y": 1728,
"height": 4885
},
{
"y": 2304,
"height": 4885
},
{
"y": 2880,
"height": 4885
},
{
"y": 3456,
"height": 4885
},
{
"y": 4032,
"height": 4885
},
{
"y": 4165,
"height": 4885
}
],
"scans": 10,
"max_states": 512,
"settle_ms": 5000,
"page_timeout_seconds": 150,
"layout_stability": "consecutive 100ms size samples within one CSS pixel",
"animation_settling": "finite animations present when scroll resources are ready finish or are cancelled",
"interactive_states": "not exercised",
"horizontal_scroll": "not exercised"
}
}
System Prompt
You are a lead web developer at a top digital agency, tasked with creating a one-page website for a new client based on the given specifications, delivered as an HTML file. First non-whitespace char '<', last non-whitespace char '>'. Use the following services to generate placeholder images where needed:
- placehold.co (text): https://placehold.co/[{w}x{h}|{size}][/{bg-color}/{text-color}]?text={text}&font=[lato|lora|montserrat|noto sans|open sans|oswald|playfair display|poppins|pt sans|raleway|roboto|source sans|source sans pro]
- picsum.photos (photos): https://picsum.photos/[{w}/{h}|{size}]?[grayscale][&blur={1-10}]
- pravatar.cc (avatars): https://i.pravatar.cc/{size}?u={identifier}
Choose sizes appropriate to layout.
User Prompt
Create a **complete, polished, production-quality** primary web page for a new client in the "Food and Drink" sector.
Your goal is to generate the full HTML code for a page that is not just functional but also visually compelling, content-rich, and feels like a finished product ready for launch.
**Client & Category:**
- Industry: "Food and Drink"
- Description: Recipes, restaurant guides, cooking tips, and nutrition resources.
**Your Creative Task:**
1. **Invent:** Create a unique, professional-sounding site name and a strong tagline fitting the "Food and Drink" category.
2. **Define Page:** Determine the most effective primary page type (e.g., homepage, service landing page, category portal) to showcase this fictional entity.
3. **Design:** Develop an opinionated, modern, and professional layout. Make distinct choices about structure and flow.
**Content & Structure Requirements (Deliver a COMPLETE page):**
- **Overall:** The final page must feel substantial and complete, with realistic amounts of text (multiple paragraphs per section where appropriate, avoid single sentences), well-integrated placeholder images, and logical flow. It should look like a real website a business would proudly use.
- **HEADER:** Include the invented site name, tagline, a logo placeholder image, and a primary navigation bar. Ensure the navigation has **at least 5-7 clearly defined, relevant links** including: "Recipes", "Catering", "Events".
- **MAIN CONTENT:** Structure this area with **at least 3-4 distinct, well-developed sections**.
- Address key topics relevant to the "Food and Drink" category. Consider themes similar to: "Seasonal Menus", "Culinary Trends", "Chef's Recipes".
- **Content Depth:** Populate each section with **substantial, realistic text** (multiple sentences/paragraphs). Use authentic industry language and terminology like: "braising", "umami", "sautéing".
- **Visuals:** Integrate relevant placeholder images logically within the content sections.
- **Calls to Action:** Include clear and contextually relevant CTAs. Use strong verbs similar to: "Subscribe", "Watch Tutorial", "Try Recipe".
- **ENGAGEMENT (Recommended):** Strongly consider incorporating **one meaningful interactive element** that would genuinely benefit a user in the "Food and Drink" sector. Ideas similar but not limited to: "meal planner".
- **SIDEBAR (Optional):** If your design includes a sidebar, populate it with **useful, relevant content**. Ideas: "daily specials", "restaurant picks", "featured chefs".
- **FOOTER:** Include a professional footer with invented contact details, copyright (current year), social media links, and standard links (Privacy, Terms).
- **MODERN WEB PATTERNS:** Include modern web patterns like testimonial cards, feature grids, or FAQ accordions where appropriate.