Recipe cards are a timeless way to share and preserve culinary creations. Whether you're a professional chef or a home cook, having a well-designed recipe card can make all the difference.
In this article, we'll explore ten inspiring recipe card examples that combine functionality with aesthetic appeal. Get ready to elevate your kitchen game with these creative designs.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Designers and developers, elevate your recipe card designs with Subframe's drag-and-drop interface. Its intuitive, responsive canvas ensures pixel-perfect UI every time.
Loved by creatives, Subframe makes stunning designs effortless. Start for free and transform your projects today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Ready to elevate your UI designs? With Subframe, you can create pixel-perfect recipe cards and more in minutes. Its drag-and-drop interface ensures efficiency and stunning results.
Start creating immediately and see the difference. Start for free today!
<html> <head> <style> @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;500;700&family=Playfair+Display:wght@700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Montserrat', sans-serif; background-color: #f9f9f9; color: #333; display: flex; justify-content: center; align-items: center; min-height: 700px; padding: 20px; } .recipe-card-container { width: 100%; max-width: 650px; position: relative; perspective: 1000px; } .recipe-card { background-color: white; border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); overflow: hidden; transform-style: preserve-3d; transition: transform 0.6s cubic-bezier(0.23, 1, 0.32, 1); width: 100%; } .recipe-card:hover { transform: translateY(-5px); } .recipe-header { position: relative; height: 300px; overflow: hidden; } .recipe-image { width: 100%; height: 100%; object-fit: cover; transform: scale(1); transition: transform 0.8s ease; filter: brightness(0.95); } .recipe-card:hover .recipe-image { transform: scale(1.05); filter: brightness(1); } .recipe-meta { position: absolute; bottom: 0; width: 100%; display: flex; justify-content: space-between; align-items: center; padding: 15px 20px; background: linear-gradient(to top, rgba(0,0,0,0.8), transparent); color: white; } .recipe-title { font-family: 'Playfair Display', serif; font-size: 24px; margin: 0; text-shadow: 0 1px 3px rgba(0,0,0,0.3); } .recipe-time { font-size: 14px; display: flex; align-items: center; background: rgba(255,255,255,0.15); padding: 5px 12px; border-radius: 20px; backdrop-filter: blur(5px); } .time-icon { margin-right: 5px; width: 16px; height: 16px; } .recipe-content { padding: 25px; } .recipe-tabs { display: flex; border-bottom: 1px solid #eee; margin-bottom: 20px; } .tab { padding: 10px 20px; font-weight: 500; color: #999; cursor: pointer; position: relative; transition: all 0.3s; } .tab.active { color: #ff6b6b; } .tab.active::after { content: ''; position: absolute; bottom: -1px; left: 0; width: 100%; height: 2px; background-color: #ff6b6b; } .tab-content { display: none; } .tab-content.active { display: block; animation: fadeIn 0.5s; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .section-title { font-size: 18px; font-weight: 700; margin-bottom: 15px; color: #444; } .ingredients-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 20px; } .ingredient { display: flex; align-items: center; transition: all 0.3s; padding: 8px 12px; border-radius: 6px; border-left: 3px solid transparent; } .ingredient:hover { background-color: #f8f7ff; border-left: 3px solid #6c5ce7; transform: translateX(5px); } .ingredient-highlight { position: absolute; background-color: white; border-radius: 8px; box-shadow: 0 5px 20px rgba(0,0,0,0.15); padding: 15px; max-width: 200px; z-index: 10; opacity: 0; transform: translateY(10px); pointer-events: none; transition: all 0.3s; } .ingredient-highlight.active { opacity: 1; transform: translateY(0); } .highlight-title { font-weight: 700; font-size: 14px; margin-bottom: 5px; color: #555; } .highlight-desc { font-size: 12px; line-height: 1.4; color: #666; } .step { margin-bottom: 20px; counter-increment: step-counter; position: relative; padding-left: 45px; } .step::before { content: counter(step-counter); position: absolute; left: 0; top: 0; width: 30px; height: 30px; background-color: #ff6b6b; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 14px; } .step-content { line-height: 1.6; color: #555; } .cooking-tip { margin-top: 12px; padding: 12px; background-color: #fff8e8; border-left: 3px solid #ffcc5c; border-radius: 4px; font-size: 14px; color: #6b5900; transform: translateY(20px); opacity: 0; transition: all 0.3s; } .step:hover .cooking-tip { opacity: 1; transform: translateY(0); } .recipe-footer { display: flex; justify-content: space-between; align-items: center; padding: 15px 25px; background-color: #f5f5f5; border-top: 1px solid #eee; } .nutrition { display: flex; gap: 15px; } .nutrition-item { text-align: center; } .nutrition-value { font-weight: 700; color: #6c5ce7; font-size: 16px; } .nutrition-label { font-size: 12px; color: #777; text-transform: uppercase; } .bookmark-btn { background-color: white; border: none; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 3px 10px rgba(0,0,0,0.1); transition: all 0.3s; } .bookmark-btn:hover { transform: scale(1.1); box-shadow: 0 5px 15px rgba(0,0,0,0.15); } .bookmark-icon { width: 18px; height: 18px; fill: none; stroke: #777; stroke-width: 2; transition: all 0.3s; } .bookmark-btn.active .bookmark-icon { fill: #ff6b6b; stroke: #ff6b6b; } @media (max-width: 600px) { .recipe-title { font-size: 20px; } .recipe-header { height: 220px; } .ingredients-list { grid-template-columns: 1fr; } .recipe-tabs { overflow-x: auto; white-space: nowrap; padding-bottom: 5px; } .tab { padding: 10px 15px; font-size: 14px; } .recipe-meta { flex-direction: column; align-items: flex-start; gap: 10px; } .recipe-time { align-self: flex-end; } } </style> </head> <body> <div class="recipe-card-container"> <div class="recipe-card"> <div class="recipe-header"> <img src="https://images.unsplash.com/photo-1551248429-40975aa4de74" alt="Herb-Crusted Salmon with Citrus Salsa" class="recipe-image"> <div class="recipe-meta"> <h1 class="recipe-title">Herb-Crusted Salmon with Citrus Salsa</h1> <div class="recipe-time"> <svg class="time-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2"/> <path d="M12 7V12L15 15" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> </svg> 25 min </div> </div> </div> <div class="recipe-content"> <div class="recipe-tabs"> <div class="tab active" data-tab="ingredients">Ingredients</div> <div class="tab" data-tab="instructions">Instructions</div> <div class="tab" data-tab="notes">Chef's Notes</div> </div> <div id="ingredients-content" class="tab-content active"> <h3 class="section-title">What You'll Need</h3> <div class="ingredients-list"> <div class="ingredient" data-ingredient="salmon"> <span>4 salmon fillets (6oz each)</span> </div> <div class="ingredient" data-ingredient="herbs"> <span>2 tbsp fresh herbs, chopped</span> </div> <div class="ingredient" data-ingredient="breadcrumbs"> <span>½ cup panko breadcrumbs</span> </div> <div class="ingredient" data-ingredient="dijon"> <span>1 tbsp Dijon mustard</span> </div> <div class="ingredient" data-ingredient="orange"> <span>1 orange, segmented</span> </div> <div class="ingredient" data-ingredient="grapefruit"> <span>½ grapefruit, segmented</span> </div> <div class="ingredient" data-ingredient="avocado"> <span>1 ripe avocado, diced</span> </div> <div class="ingredient" data-ingredient="jalapeño"> <span>1 jalapeño, minced</span> </div> </div> <div id="ingredient-highlight" class="ingredient-highlight"> <h4 class="highlight-title">Salmon</h4> <p class="highlight-desc">Wild-caught Pacific salmon has a rich, buttery flavor and contains more omega-3 fatty acids than farm-raised.</p> </div> </div> <div id="instructions-content" class="tab-content"> <h3 class="section-title">Steps to Follow</h3> <div class="steps"> <div class="step"> <p class="step-content">Preheat oven to 425°F (220°C). Mix breadcrumbs with chopped herbs, 1 tbsp olive oil, salt, and pepper.</p> <div class="cooking-tip">For extra flavor, try mixing thyme, dill, and parsley for your herb blend.</div> </div> <div class="step"> <p class="step-content">Pat salmon fillets dry with paper towels. Brush the tops with Dijon mustard and press the herb mixture onto each fillet.</p> <div class="cooking-tip">Make sure to press firmly so the crust adheres well during cooking.</div> </div> <div class="step"> <p class="step-content">Place salmon on a lined baking sheet, herb-side up. Bake for 12-15 minutes until the crust is golden and salmon flakes easily.</p> <div class="cooking-tip">For perfect doneness, salmon should reach an internal temperature of 145°F (63°C).</div> </div> <div class="step"> <p class="step-content">While salmon bakes, combine citrus segments, diced avocado, minced jalapeño, 2 tbsp olive oil, lime juice, and salt to make the salsa.</p> <div class="cooking-tip">Make the salsa just before serving to keep the avocado fresh and bright.</div> </div> <div class="step"> <p class="step-content">Serve each salmon fillet with a generous spoonful of citrus salsa and a lime wedge.</p> <div class="cooking-tip">A sprinkle of flaky sea salt on the finished dish makes all the flavors pop!</div> </div> </div> </div> <div id="notes-content" class="tab-content"> <h3 class="section-title">Chef's Insights</h3> <p style="line-height: 1.6; margin-bottom: 15px;">This herb-crusted salmon is my go-to for entertaining because it's both impressive and surprisingly simple. The contrast between the crisp herb crust and tender salmon creates a textural masterpiece.</p> <p style="line-height: 1.6; margin-bottom: 15px;">The citrus salsa brings brightness that cuts through the richness of the salmon. For a dinner party, you can prepare the herb crust and salsa components ahead of time, then simply assemble and bake when guests arrive.</p> <p style="line-height: 1.6;">Wine pairing suggestion: A crisp Sauvignon Blanc or unoaked Chardonnay complements this dish beautifully, highlighting the herbs and citrus notes.</p> </div> </div> <div class="recipe-footer"> <div class="nutrition"> <div class="nutrition-item"> <div class="nutrition-value">320</div> <div class="nutrition-label">Calories</div> </div> <div class="nutrition-item"> <div class="nutrition-value">28g</div> <div class="nutrition-label">Protein</div> </div> <div class="nutrition-item"> <div class="nutrition-value">18g</div> <div class="nutrition-label">Fat</div> </div> <div class="nutrition-item"> <div class="nutrition-value">8g</div> <div class="nutrition-label">Carbs</div> </div> </div> <button class="bookmark-btn"> <svg class="bookmark-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path> </svg> </button> </div> </div> </div> <script> // Tab switching functionality const tabs = document.querySelectorAll('.tab'); const tabContents = document.querySelectorAll('.tab-content'); tabs.forEach(tab => { tab.addEventListener('click', () => { const tabId = tab.getAttribute('data-tab'); // Remove active class from all tabs and contents tabs.forEach(t => t.classList.remove('active')); tabContents.forEach(c => c.classList.remove('active')); // Add active class to current tab and content tab.classList.add('active'); document.getElementById(`${tabId}-content`).classList.add('active'); }); }); // Ingredient highlighting functionality const ingredients = document.querySelectorAll('.ingredient'); const highlightBox = document.getElementById('ingredient-highlight'); const ingredientInfo = { 'salmon': { title: 'Salmon', desc: 'Wild-caught Pacific salmon has a rich, buttery flavor and contains more omega-3 fatty acids than farm-raised.' }, 'herbs': { title: 'Fresh Herbs', desc: 'A mix of dill, parsley, and thyme creates a fragrant crust that infuses the salmon with aromatics as it bakes.' }, 'breadcrumbs': { title: 'Panko Breadcrumbs', desc: 'Japanese-style panko creates a lighter, crispier texture than traditional breadcrumbs for the perfect crust.' }, 'dijon': { title: 'Dijon Mustard', desc: 'Acts as the "glue" for the herb crust while adding tangy depth that complements the rich salmon.' }, 'orange': { title: 'Orange', desc: 'Adds sweet citrus notes to the salsa that balance the richness of both the salmon and avocado.' }, 'grapefruit': { title: 'Grapefruit', desc: 'Provides bitter-sweet complexity and beautiful pink color contrast in the fresh salsa.' }, 'avocado': { title: 'Avocado', desc: 'Creates creamy texture in the salsa that contrasts with the crisp herb crust of the salmon.' }, 'jalapeño': { title: 'Jalapeño', desc: 'Adds gentle heat that enhances the flavor of the citrus without overwhelming the delicate salmon.' } }; ingredients.forEach(ingredient => { ingredient.addEventListener('mouseenter', (e) => { const ingredientType = ingredient.getAttribute('data-ingredient'); const info = ingredientInfo[ingredientType]; highlightBox.querySelector('.highlight-title').textContent = info.title; highlightBox.querySelector('.highlight-desc').textContent = info.desc; // Position the highlight box near the ingredient const rect = ingredient.getBoundingClientRect(); const containerRect = document.querySelector('.recipe-card-container').getBoundingClientRect(); const leftPosition = rect.left - containerRect.left; let topPosition = rect.top - containerRect.top; // Adjust if would display off-bottom if (topPosition + 100 > containerRect.height) { topPosition = topPosition - 80; } highlightBox.style.left = `${leftPosition + rect.width + 20}px`; highlightBox.style.top = `${topPosition}px`; highlightBox.classList.add('active'); }); ingredient.addEventListener('mouseleave', () => { highlightBox.classList.remove('active'); }); }); // Bookmark functionality const bookmarkBtn = document.querySelector('.bookmark-btn'); bookmarkBtn.addEventListener('click', () => { bookmarkBtn.classList.toggle('active'); // Add a subtle animation bookmarkBtn.animate([ { transform: 'scale(0.8)' }, { transform: 'scale(1.2)' }, { transform: 'scale(1)' } ], { duration: 300, easing: 'ease-out' }); }); // Recipe card hover effect const recipeCard = document.querySelector('.recipe-card'); recipeCard.addEventListener('mousemove', (e) => { const rect = recipeCard.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const centerX = rect.width / 2; const centerY = rect.height / 2; const rotateY = (x - centerX) / 50; const rotateX = (centerY - y) / 50; recipeCard.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateY(-5px)`; }); recipeCard.addEventListener('mouseleave', () => { recipeCard.style.transform = ''; }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root { --primary-color: #8B4513; --secondary-color: #D2B48C; --accent-color: #A0522D; --text-color: #3A2A1D; --light-text: #6F4E37; --card-bg: #F5F2EA; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Georgia', serif; background-color: #EADFC4; background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDQwIDQwIj48ZyBmaWxsPSIjZDJiNDhjIiBmaWxsLW9wYWNpdHk9IjAuMiI+PHBhdGggZD0iTTAgMGg0MHY0MEgwVjB6TTIwIDIwaDIwdjIwSDIwVjIweiIvPjwvZz48L3N2Zz4='); color: var(--text-color); display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 20px; overflow-x: hidden; } .container { max-width: 650px; width: 100%; height: 640px; overflow-y: auto; padding: 10px; position: relative; } .header { text-align: center; margin-bottom: 25px; position: relative; } .header h1 { font-family: 'Brush Script MT', cursive; color: var(--primary-color); font-size: 2.2rem; position: relative; display: inline-block; margin-bottom: 5px; } .header h1::after { content: ''; position: absolute; bottom: -5px; left: 10%; width: 80%; height: 3px; background-color: var(--accent-color); border-radius: 2px; } .header p { font-style: italic; color: var(--light-text); font-size: 0.95rem; margin-top: 12px; } .recipe-cards-container { display: grid; grid-template-columns: 1fr; gap: 40px; } .recipe-card { position: relative; height: 480px; perspective: 2500px; border-radius: 10px; box-shadow: 0 15px 25px rgba(0, 0, 0, 0.1); } .card-inner { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform 0.8s cubic-bezier(0.75, 0, 0.25, 1); } .card-front, .card-back { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; border-radius: 10px; padding: 25px; display: flex; flex-direction: column; } .card-front { background-color: var(--card-bg); background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIgdmlld0JveD0iMCAwIDYwIDYwIj48ZyBmaWxsPSIjOEI0NTEzIiBmaWxsLW9wYWNpdHk9IjAuMDUiPjxwYXRoIGQ9Ik0zNiAzMGE2IDYgMCAxIDAgMC0xMiA2IDYgMCAwIDAgMCAxMnptMCAwYTYgNiAwIDEgMCAwLTEyIDYgNiAwIDAgMCAwIDEyem0xMiAxMmE2IDYgMCAxIDAgMC0xMiA2IDYgMCAwIDAgMCAxMnptLTI0IDBhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6bTAgMTJhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6bTI0IDBhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6TTEyIDMwYTYgNiAwIDEgMCAwLTEyIDYgNiAwIDAgMCAwIDEyem0wIDBhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6bTAgMTJhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6bTI0LTI0YTYgNiAwIDEgMCAwLTEyIDYgNiAwIDAgMCAwIDEyeiIvPjwvZz48L3N2Zz4='); border: 1px solid rgba(139, 69, 19, 0.2); } .card-back { background-color: var(--card-bg); background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIgdmlld0JveD0iMCAwIDYwIDYwIj48ZyBmaWxsPSIjOEI0NTEzIiBmaWxsLW9wYWNpdHk9IjAuMDUiPjxwYXRoIGQ9Ik0zNiAzMGE2IDYgMCAxIDAgMC0xMiA2IDYgMCAwIDAgMCAxMnptMCAwYTYgNiAwIDEgMCAwLTEyIDYgNiAwIDAgMCAwIDEyem0xMiAxMmE2IDYgMCAxIDAgMC0xMiA2IDYgMCAwIDAgMCAxMnptLTI0IDBhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6bTAgMTJhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6bTI0IDBhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6TTEyIDMwYTYgNiAwIDEgMCAwLTEyIDYgNiAwIDAgMCAwIDEyem0wIDBhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6bTAgMTJhNiA2IDAgMSAwIDAtMTIgNiA2IDAgMCAwIDAgMTJ6bTI0LTI0YTYgNiAwIDEgMCAwLTEyIDYgNiAwIDAgMCAwIDEyeiIvPjwvZz48L3N2Zz4='); transform: rotateY(180deg); border: 1px solid rgba(139, 69, 19, 0.2); overflow-y: auto; } .recipe-title { font-family: 'Brush Script MT', cursive; color: var(--primary-color); font-size: 1.8rem; margin-bottom: 5px; text-align: center; position: relative; } .recipe-title::after { content: ''; position: absolute; bottom: -5px; left: 25%; width: 50%; height: 2px; background-color: var(--accent-color); opacity: 0.6; } .card-image { width: 85%; height: 180px; margin: 15px auto; object-fit: cover; border-radius: 8px; border: 3px solid white; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08); transform: rotate(-2deg); transition: transform 0.3s ease; } .card-image:hover { transform: rotate(0deg) scale(1.02); } .recipe-info { display: flex; justify-content: space-between; margin: 10px 0; font-size: 0.9rem; color: var(--light-text); font-style: italic; border-top: 1px dashed rgba(139, 69, 19, 0.3); border-bottom: 1px dashed rgba(139, 69, 19, 0.3); padding: 8px 0; } .ingredients { margin-top: 15px; } .ingredients h3, .instructions h3 { font-family: 'Brush Script MT', cursive; color: var(--primary-color); font-size: 1.3rem; margin-bottom: 10px; display: flex; align-items: center; } .ingredients h3 svg, .instructions h3 svg { margin-right: 8px; width: 24px; height: 24px; } .ingredients ul { list-style-type: none; padding-left: 10px; } .ingredients li { padding: 5px 0; font-size: 0.95rem; position: relative; padding-left: 22px; line-height: 1.4; } .ingredients li::before { content: "✦"; position: absolute; left: 0; color: var(--accent-color); } .flip-btn { align-self: center; margin-top: auto; padding: 8px 20px; background-color: var(--accent-color); color: white; border: none; border-radius: 20px; cursor: pointer; font-family: 'Georgia', serif; box-shadow: 0 3px 5px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; position: relative; overflow: hidden; } .flip-btn::after { content: ''; position: absolute; width: 100%; height: 100%; top: 0; left: -100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: 0.3s; } .flip-btn:hover { transform: translateY(-3px); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.15); } .flip-btn:hover::after { left: 100%; } .instructions { margin-top: 15px; } .step { margin-bottom: 15px; position: relative; padding-left: 40px; } .step-number { position: absolute; left: 0; top: 0; width: 30px; height: 30px; background-color: var(--secondary-color); color: var(--primary-color); border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: bold; font-family: 'Brush Script MT', cursive; font-size: 18px; } .step-text { font-size: 0.95rem; line-height: 1.5; } .card-footer { margin-top: 15px; text-align: center; font-style: italic; font-size: 0.85rem; color: var(--light-text); } .card-tag { display: inline-block; background-color: rgba(210, 180, 140, 0.3); padding: 3px 8px; border-radius: 12px; margin: 5px 3px; font-size: 0.85rem; color: var(--primary-color); border: 1px dashed rgba(139, 69, 19, 0.2); } .notes { margin-top: 15px; padding: 10px; background-color: rgba(255, 244, 224, 0.7); border-radius: 8px; border-left: 3px solid var(--secondary-color); font-style: italic; font-size: 0.9rem; } .notes h4 { color: var(--primary-color); margin-bottom: 5px; font-family: 'Brush Script MT', cursive; font-size: 1.1rem; } .corner-fold { position: absolute; top: 0; right: 0; width: 50px; height: 50px; background: linear-gradient(135deg, transparent 50%, #E6D7B8 50%); border-radius: 0 0 0 10px; } .flipped .card-inner { transform: rotateY(180deg); } @media (max-width: 650px) { .container { padding: 5px; height: 600px; } .recipe-card { height: 520px; } .card-front, .card-back { padding: 15px; } .recipe-title { font-size: 1.5rem; } .card-image { height: 150px; } } @media (max-width: 450px) { .header h1 { font-size: 1.8rem; } .recipe-title { font-size: 1.3rem; } .ingredients li, .step-text { font-size: 0.9rem; } } .pencil-decoration { position: absolute; width: 80px; height: 6px; background-color: var(--secondary-color); border-radius: 3px; top: 70px; right: 50px; transform: rotate(30deg); box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .pencil-decoration::before { content: ''; position: absolute; right: -8px; top: -2px; width: 10px; height: 10px; background-color: var(--primary-color); border-radius: 2px; } .pencil-decoration::after { content: ''; position: absolute; left: -5px; top: 0; width: 6px; height: 6px; background-color: #FFB6C1; border-radius: 50%; } /* Custom scrollbar */ .card-back::-webkit-scrollbar { width: 6px; } .card-back::-webkit-scrollbar-track { background: rgba(210, 180, 140, 0.1); } .card-back::-webkit-scrollbar-thumb { background-color: var(--secondary-color); border-radius: 3px; } .stamped { position: absolute; right: 20px; top: 40px; transform: rotate(15deg); opacity: 0.8; color: var(--accent-color); border: 2px dashed var(--accent-color); padding: 5px 10px; border-radius: 5px; font-family: 'Courier New', monospace; font-weight: bold; font-size: 0.8rem; } </style> </head> <body> <div class="container"> <div class="header"> <h1>Grandma's Recipe Box</h1> <p>Treasured recipes from our family kitchen to yours</p> <div class="pencil-decoration"></div> </div> <div class="recipe-cards-container"> <div class="recipe-card"> <div class="card-inner"> <div class="card-front"> <div class="corner-fold"></div> <h2 class="recipe-title">Apple & Cinnamon Pie</h2> <img src="https://images.unsplash.com/photo-1568571780765-9276ac8b75a7?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" alt="Apple Cinnamon Pie" class="card-image"> <div class="stamped">FAMILY FAVORITE</div> <div class="recipe-info"> <span>⏰ Prep: 30 mins</span> <span>🔥 Cook: 45 mins</span> <span>🍽️ Serves: 8</span> </div> <div class="ingredients"> <h3> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2"></path> <path d="M7 2v20"></path> <path d="M21 15V2"></path> <path d="M18 15a3 3 0 1 0 0 6 3 3 0 0 0 0-6z"></path> </svg> Ingredients </h3> <ul> <li>6-7 tart apples (Granny Smith), peeled and sliced</li> <li>¾ cup granulated sugar</li> <li>2 tablespoons all-purpose flour</li> <li>1 teaspoon ground cinnamon</li> <li>¼ teaspoon freshly grated nutmeg</li> <li>2 tablespoons butter, cut into small pieces</li> <li>Homemade pie crust for top and bottom</li> <li>1 egg beaten with 1 tablespoon water</li> </ul> </div> <button class="flip-btn">See Full Recipe</button> </div> <div class="card-back"> <h2 class="recipe-title">Apple & Cinnamon Pie</h2> <div class="instructions"> <h3> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path> </svg> Instructions </h3> <div class="step"> <div class="step-number">1</div> <div class="step-text">Preheat your oven to 425°F (220°C). Place a baking sheet on the lower rack to catch any drips.</div> </div> <div class="step"> <div class="step-number">2</div> <div class="step-text">Roll out half the pastry and line a 9-inch pie plate. Trim the edges leaving a ½-inch overhang.</div> </div> <div class="step"> <div class="step-number">3</div> <div class="step-text">In a large bowl, mix sliced apples, sugar, flour, cinnamon, and nutmeg until apples are evenly coated.</div> </div> <div class="step"> <div class="step-number">4</div> <div class="step-text">Pour the apple mixture into the pie crust and dot with butter pieces.</div> </div> <div class="step"> <div class="step-number">5</div> <div class="step-text">Roll out the remaining pastry and cover the pie. Trim, seal, and flute the edges. Cut several slits in the top crust for steam to escape.</div> </div> <div class="step"> <div class="step-number">6</div> <div class="step-text">Brush the top with egg wash for a golden finish.</div> </div> <div class="step"> <div class="step-number">7</div> <div class="step-text">Bake for 45 minutes, or until crust is golden and filling is bubbly. Cover edges with foil if browning too quickly.</div> </div> </div> <div class="notes"> <h4>Grandma's Notes</h4> <p>Add a pinch of salt to the apples to enhance sweetness. For extra crunch, sprinkle the top with turbinado sugar before baking. Serve warm with a scoop of vanilla ice cream!</p> </div> <div class="card-footer"> <div class="card-tag">#Dessert</div> <div class="card-tag">#Autumn</div> <div class="card-tag">#FamilyRecipe</div> </div> <button class="flip-btn">Back to Recipe</button> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const recipeCards = document.querySelectorAll('.recipe-card'); const flipButtons = document.querySelectorAll('.flip-btn'); flipButtons.forEach(button => { button.addEventListener('click', function() { const card = this.closest('.recipe-card'); card.classList.toggle('flipped'); // Add a subtle bounce animation when flipping card.animate([ { transform: 'scale(1)' }, { transform: 'scale(1.02)' }, { transform: 'scale(1)' } ], { duration: 500, easing: 'ease-out' }); }); }); // Add interactive hover sound effect for buttons flipButtons.forEach(button => { button.addEventListener('mouseenter', function() { this.style.transform = 'translateY(-3px)'; this.style.boxShadow = '0 5px 10px rgba(0, 0, 0, 0.15)'; }); button.addEventListener('mouseleave', function() { this.style.transform = ''; this.style.boxShadow = ''; }); }); // Prevent card flipping when scrolling inside card-back const cardBackElements = document.querySelectorAll('.card-back'); cardBackElements.forEach(cardBack => { cardBack.addEventListener('wheel', function(e) { e.stopPropagation(); }); }); // Add a slight tilt effect to the recipe card on mouse move recipeCards.forEach(card => { card.addEventListener('mousemove', function(e) { const cardRect = card.getBoundingClientRect(); const cardCenterX = cardRect.left + cardRect.width / 2; const cardCenterY = cardRect.top + cardRect.height / 2; const mouseX = e.clientX - cardCenterX; const mouseY = e.clientY - cardCenterY; // Calculate tilt angle (limited to small amount) const tiltX = (mouseY / cardRect.height) * 5; const tiltY = -(mouseX / cardRect.width) * 5; // Only apply tilt if card is not flipped if (!card.classList.contains('flipped')) { card.querySelector('.card-inner').style.transform = `rotateX(${tiltX}deg) rotateY(${tiltY}deg)`; } }); card.addEventListener('mouseleave', function() { // Reset transform if not flipped if (!card.classList.contains('flipped')) { card.querySelector('.card-inner').style.transform = ''; } else { card.querySelector('.card-inner').style.transform = 'rotateY(180deg)'; } }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Global Flavors Recipe Card</title> <style> :root { --primary-color: #ff7e5f; --secondary-color: #feb47b; --text-color: #333; --light-color: #fff; --dark-color: #222; --accent-color-1: #60d394; --accent-color-2: #d4a5a5; --accent-color-3: #9d8189; --accent-color-4: #5c80bc; --transition: all 0.3s ease; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f5f5f5; display: flex; justify-content: center; align-items: center; height: 100vh; overflow: hidden; padding: 15px; } .container { max-width: 650px; width: 100%; height: 650px; background: var(--light-color); border-radius: 16px; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); overflow: hidden; position: relative; transition: var(--transition); } .recipe-card { display: flex; flex-direction: column; height: 100%; overflow: hidden; } .header { padding: 20px; background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); color: var(--light-color); position: relative; overflow: hidden; transition: var(--transition); } .cuisine-tag { position: absolute; top: 0; right: 0; background: rgba(0, 0, 0, 0.2); padding: 5px 15px; border-bottom-left-radius: 8px; font-size: 0.8rem; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; } .pattern { position: absolute; width: 100%; height: 100%; top: 0; left: 0; opacity: 0.2; background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.4'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); transition: opacity 0.5s ease; } .header:hover .pattern { opacity: 0.3; animation: patternShift 10s linear infinite; } @keyframes patternShift { from { background-position: 0 0; } to { background-position: 100px 100px; } } .title-area { position: relative; z-index: 1; } h1 { font-size: 2rem; margin-bottom: 5px; font-weight: 700; } .subtitle { font-size: 1rem; opacity: 0.9; margin-bottom: 15px; } .stats { display: flex; gap: 15px; margin-top: 10px; } .stat { display: flex; align-items: center; font-size: 0.85rem; } .stat svg { width: 18px; height: 18px; margin-right: 5px; fill: var(--light-color); } .content { flex: 1; padding: 20px; overflow-y: auto; position: relative; display: flex; flex-direction: column; } .tabs { display: flex; margin-bottom: 20px; border-bottom: 2px solid #eee; position: sticky; top: 0; background: white; z-index: 10; } .tab { padding: 10px 20px; cursor: pointer; font-weight: 600; color: var(--text-color); opacity: 0.6; transition: var(--transition); position: relative; } .tab:hover { opacity: 0.8; } .tab.active { opacity: 1; color: var(--primary-color); } .tab.active::after { content: ''; position: absolute; bottom: -2px; left: 0; width: 100%; height: 2px; background-color: var(--primary-color); } .tab-content { display: none; flex: 1; } .tab-content.active { display: block; animation: fadeIn 0.5s ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .ingredients { margin-bottom: 20px; } .ingredient-list { list-style-type: none; } .ingredient-item { padding: 10px 5px; border-bottom: 1px dashed #eee; display: flex; align-items: center; position: relative; cursor: pointer; } .ingredient-item::before { content: '•'; margin-right: 8px; color: var(--primary-color); font-size: 1.2rem; } .ingredient-item .info-icon { margin-left: auto; width: 18px; height: 18px; background-color: var(--accent-color-1); border-radius: 50%; display: flex; justify-content: center; align-items: center; color: white; font-size: 12px; cursor: pointer; transition: var(--transition); } .ingredient-item .info-icon:hover { transform: scale(1.1); } .substitutions { background-color: #f8f9fa; border-radius: 8px; padding: 15px; margin-top: 10px; font-size: 0.9rem; display: none; animation: slideDown 0.3s ease; } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } .substitutions.active { display: block; } .substitute { display: flex; align-items: center; margin-bottom: 5px; } .substitute:last-child { margin-bottom: 0; } .substitute::before { content: '→'; margin-right: 8px; color: var(--accent-color-1); } .steps { counter-reset: step-counter; } .step { margin-bottom: 20px; position: relative; padding-left: 40px; } .step::before { counter-increment: step-counter; content: counter(step-counter); position: absolute; left: 0; top: 0; width: 30px; height: 30px; background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); color: white; border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: bold; } .cuisine-switcher { position: absolute; bottom: 20px; right: 20px; z-index: 20; } .switch-btn { background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); color: white; border: none; padding: 10px 15px; border-radius: 30px; cursor: pointer; font-weight: 600; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); display: flex; align-items: center; gap: 5px; transition: var(--transition); } .switch-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2); } .switch-btn svg { width: 16px; height: 16px; fill: white; } /* Theme styles for different cuisines */ .container.thai { --primary-color: #ff6b6b; --secondary-color: #f9c80e; } .container.mexican { --primary-color: #4ecdc4; --secondary-color: #ff9f1c; } .container.italian { --primary-color: #43aa8b; --secondary-color: #f94144; } .container.indian { --primary-color: #f9844a; --secondary-color: #a0c4ff; } .container.japanese { --primary-color: #5e60ce; --secondary-color: #ff9e00; } /* Interactive elements */ .recipe-image { width: 100%; height: 150px; background-size: cover; background-position: center; border-radius: 8px; margin-bottom: 20px; position: relative; overflow: hidden; transition: var(--transition); } .recipe-image:hover { transform: scale(1.02); } .recipe-image::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.4)); } .recipe-image .caption { position: absolute; bottom: 10px; left: 10px; color: white; font-size: 0.8rem; z-index: 1; } .cultural-note { background-color: #f8f9fa; border-left: 4px solid var(--primary-color); padding: 10px 15px; margin: 20px 0; font-size: 0.9rem; line-height: 1.5; border-radius: 0 8px 8px 0; } /* Responsive adjustments */ @media (max-width: 600px) { .container { height: 600px; } h1 { font-size: 1.5rem; } .stats { flex-wrap: wrap; } .tab { padding: 10px; font-size: 0.9rem; } .step { padding-left: 35px; } .step::before { width: 25px; height: 25px; font-size: 0.8rem; } } /* Scrollbar styling */ .content::-webkit-scrollbar { width: 6px; } .content::-webkit-scrollbar-track { background: #f5f5f5; } .content::-webkit-scrollbar-thumb { background-color: #ddd; border-radius: 10px; } .content::-webkit-scrollbar-thumb:hover { background-color: #ccc; } /* Loading animation */ .loading { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.9); display: flex; justify-content: center; align-items: center; z-index: 100; transition: opacity 0.5s ease; } .spinner { width: 40px; height: 40px; border: 4px solid rgba(255, 126, 95, 0.2); border-left-color: var(--primary-color); border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .hide { opacity: 0; pointer-events: none; } </style> </head> <body> <div class="container thai" id="recipe-container"> <div class="loading" id="loading"> <div class="spinner"></div> </div> <div class="recipe-card"> <div class="header"> <div class="pattern"></div> <div class="cuisine-tag" id="cuisine-tag">Thai</div> <div class="title-area"> <h1 id="recipe-title">Thai Green Curry with Vegetables</h1> <div class="subtitle" id="recipe-subtitle">A fragrant, spicy Thai curry with coconut milk and fresh vegetables</div> <div class="stats"> <div class="stat"> <svg viewBox="0 0 24 24"> <path d="M12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22C6.47,22 2,17.5 2,12A10,10 0 0,1 12,2M12.5,7V12.25L17,14.92L16.25,16.15L11,13V7H12.5Z"></path> </svg> <span id="prep-time">Prep: 15 mins</span> </div> <div class="stat"> <svg viewBox="0 0 24 24"> <path d="M12,3C10.89,3 10,3.89 10,5H14C14,3.89 13.11,3 12,3M3,14A1,1 0 0,1 2,13A1,1 0 0,1 3,12H4.58C5.04,10.37 6.38,9.04 8.01,8.57L7.13,7.68C6.74,7.29 6.74,6.65 7.13,6.26C7.5,5.87 8.15,5.87 8.54,6.26L10.25,8H13.75L15.46,6.26C15.85,5.87 16.5,5.87 16.89,6.26C17.28,6.65 17.28,7.29 16.89,7.68L16,8.57C17.63,9.04 18.96,10.37 19.42,12H21C21.55,12 22,12.45 22,13C22,13.55 21.55,14 21,14H19.41C18.96,15.64 17.62,16.97 16,17.42V18A1,1 0 0,1 15,19H14C14,19.55 13.55,20 13,20H11C10.45,20 10,19.55 10,19H9A1,1 0 0,1 8,18V17.41C6.39,16.96 5.04,15.63 4.59,14H3M12,8C9.79,8 8,9.79 8,12C8,14.21 9.79,16 12,16C14.21,16 16,14.21 16,12C16,9.79 14.21,8 12,8Z"></path> </svg> <span id="cook-time">Cook: 25 mins</span> </div> <div class="stat"> <svg viewBox="0 0 24 24"> <path d="M12,6C13.11,6 14,5.1 14,4C14,3.62 13.9,3.27 13.71,2.97L12,0L10.29,2.97C10.1,3.27 10,3.62 10,4A2,2 0 0,0 12,6M16.6,16L15.53,14.92L14.45,16C13.15,17.29 10.87,17.3 9.56,16L8.5,14.92L7.4,16C6.75,16.65 5.88,17 4.96,17C4.23,17 3.56,16.77 3,16.39V21A1,1 0 0,0 4,22H20A1,1 0 0,0 21,21V16.39C20.44,16.77 19.77,17 19.04,17C18.12,17 17.25,16.65 16.6,16M18,9H13V7H11V9H6A3,3 0 0,0 3,12V13.54C3,14.62 3.88,15.5 4.96,15.5C5.5,15.5 6,15.3 6.34,14.93L8.5,12.8L10.61,14.93C11.35,15.67 12.64,15.67 13.38,14.93L15.5,12.8L17.65,14.93C18,15.3 18.5,15.5 19.03,15.5C20.12,15.5 21,14.62 21,13.54V12A3,3 0 0,0 18,9Z"></path> </svg> <span id="servings">Serves: 4</span> </div> <div class="stat"> <svg viewBox="0 0 24 24"> <path d="M17.66 11.2C17.43 10.9 17.15 10.64 16.89 10.38C16.22 9.78 15.46 9.35 14.82 8.72C13.33 7.26 13 4.85 13.95 3C13 3.23 12.17 3.75 11.46 4.32C8.87 6.4 7.85 10.07 9.07 13.22C9.11 13.32 9.15 13.42 9.15 13.55C9.15 13.77 9 13.97 8.8 14.05C8.57 14.15 8.33 14.09 8.14 13.93C8.08 13.88 8.04 13.83 8 13.76C6.87 12.33 6.69 10.28 7.45 8.64C5.78 10 4.87 12.3 5 14.47C5.06 14.97 5.12 15.47 5.29 15.97C5.43 16.57 5.7 17.17 6 17.7C7.08 19.43 8.95 20.67 10.96 20.92C13.1 21.19 15.39 20.8 17.03 19.32C18.86 17.66 19.5 15 18.56 12.72L18.43 12.46C18.22 12 17.66 11.2 17.66 11.2M14.5 17.5C14.22 17.74 13.76 18 13.4 18.1C12.28 18.5 11.16 17.94 10.5 17.28C11.69 17 12.4 16.12 12.61 15.23C12.78 14.43 12.46 13.77 12.33 13C12.21 12.26 12.23 11.63 12.5 10.94C12.69 11.32 12.89 11.7 13.13 12C13.9 13 15.11 13.44 15.37 14.8C15.41 14.94 15.43 15.08 15.43 15.23C15.46 16.05 15.1 16.95 14.5 17.5H14.5Z"></path> </svg> <span id="heat-level">Medium Spicy</span> </div> </div> </div> </div> <div class="content"> <div class="tabs"> <div class="tab active" data-tab="ingredients">Ingredients</div> <div class="tab" data-tab="steps">Steps</div> <div class="tab" data-tab="notes">Cultural Notes</div> </div> <div class="tab-content active" id="ingredients"> <div class="recipe-image" id="recipe-image" style="background-image: url('https://images.unsplash.com/photo-1455619452474-d2be8b1e70cd?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=80')"> <div class="caption">Traditional Thai Green Curry</div> </div> <div class="ingredients"> <ul class="ingredient-list" id="ingredient-list"> <li class="ingredient-item"> 2 tbsp green curry paste <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">Red curry paste for a spicier flavor</div> <div class="substitute">Yellow curry paste for a milder taste</div> </div> </li> <li class="ingredient-item"> 400ml coconut milk <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">Light coconut milk for a lower-fat option</div> <div class="substitute">Coconut cream + water for a richer curry</div> </div> </li> <li class="ingredient-item"> 200g firm tofu, cubed <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">Chicken breast (300g) for non-vegetarians</div> <div class="substitute">Tempeh for a different texture</div> </div> </li> <li class="ingredient-item"> 1 red bell pepper, sliced <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">Any color bell pepper works well</div> <div class="substitute">Add Thai chili for extra heat</div> </div> </li> <li class="ingredient-item"> 1 small eggplant, cubed <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">Thai eggplant for authenticity</div> <div class="substitute">Zucchini if eggplant is unavailable</div> </div> </li> <li class="ingredient-item"> 100g snow peas <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">Green beans cut into 2-inch pieces</div> <div class="substitute">Sugar snap peas work well too</div> </div> </li> <li class="ingredient-item"> 2 kaffir lime leaves <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">1 tsp lime zest + bay leaf</div> <div class="substitute">Freeze-dried lime leaves if fresh unavailable</div> </div> </li> <li class="ingredient-item"> 1 tbsp fish sauce <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">Soy sauce + pinch of salt for vegetarians</div> <div class="substitute">Vegan fish sauce alternatives available</div> </div> </li> <li class="ingredient-item"> 1 tbsp palm sugar <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">Brown sugar works as a substitute</div> <div class="substitute">Maple syrup for a different sweetness</div> </div> </li> <li class="ingredient-item"> Fresh Thai basil leaves <div class="info-icon">i</div> <div class="substitutions"> <div class="substitute">Regular basil if Thai basil unavailable</div> <div class="substitute">Mint leaves for a different twist</div> </div> </li> </ul> </div> </div> <div class="tab-content" id="steps"> <div class="steps"> <div class="step">In a large wok or pan, heat 1 tablespoon of vegetable oil over medium heat. Add the green curry paste and cook for 1-2 minutes until fragrant, stirring constantly to prevent burning.</div> <div class="step">Pour in half the coconut milk and bring to a gentle simmer, stirring to combine with the curry paste. Cook for 2-3 minutes until the oil begins to separate from the coconut milk.</div> <div class="step">Add the tofu cubes and cook for 2 minutes, gently stirring to coat with the curry sauce.</div> <div class="step">Add the eggplant and cook for 5 minutes until it begins to soften.</div> <div class="step">Pour in the remaining coconut milk, fish sauce, palm sugar, and kaffir lime leaves. Bring to a simmer and cook for 5 minutes.</div> <div class="step">Add the bell pepper and snow peas. Cook for another 3-4 minutes until the vegetables are tender but still crisp.</div> <div class="step">Taste and adjust seasonings as needed. Remove from heat and stir in fresh Thai basil leaves.</div> <div class="step">Serve hot with jasmine rice and garnish with additional Thai basil and thinly sliced red chili if desired.</div> </div> </div> <div class="tab-content" id="notes"> <div class="cultural-note"> <strong>Thai Green Curry (แกงเขียวหวาน - Kaeng Khiao Wan)</strong> literally translates to "sweet green curry" despite its spicy flavor. The "sweet" refers to the shade of green rather than the taste. </div> <div class="cultural-note"> In Thailand, curry is typically eaten with rice as part of a larger meal with multiple dishes, not as a standalone dish like in Western countries. </div> <div class="cultural-note"> The balance of flavors is crucial in Thai cuisine, with this dish exemplifying the harmony between spicy (curry paste), sweet (palm sugar), salty (fish sauce), and aromatic (kaffir lime, basil) elements. </div> <div class="cultural-note"> Traditional Thai cooking doesn't use measuring cups or spoons—it's all about tasting and adjusting as you go, following the Thai philosophy of cooking with "heart and soul" (ใส่ใจ - sai jai). </div> </div> </div> </div> <div class="cuisine-switcher"> <button class="switch-btn" id="switch-cuisine"> <svg viewBox="0 0 24 24"> <path d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z" /> <path d="M12,20V22A10,10 0 0,0 22,12H20A8,8 0 0,1 12,20Z" /> <path d="M19.95,11A8,8 0 0,0 12,3.05V7.09C14.84,7.57 17.1,9 19,11H19.95Z" /> </svg> Change Cuisine </button> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Cuisine data with different recipes const cuisines = [ { name: 'Thai', title: 'Thai Green Curry with Vegetables', subtitle: 'A fragrant, spicy Thai curry with coconut milk and fresh vegetables', prepTime: 'Prep: 15 mins', cookTime: 'Cook: 25 mins', servings: 'Serves: 4', heatLevel: 'Medium Spicy', image: 'https://images.unsplash.com/photo-1455619452474-d2be8b1e70cd?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=80', imageCaption: 'Traditional Thai Green Curry', ingredients: [ { name: '2 tbsp green curry paste', substitutes: [ 'Red curry paste for a spicier flavor', 'Yellow curry paste for a milder taste' ] }, { name: '400ml coconut milk', substitutes: [ 'Light coconut milk for a lower-fat option', 'Coconut cream + water for a richer curry' ] }, { name: '200g firm tofu, cubed', substitutes: [ 'Chicken breast (300g) for non-vegetarians', 'Tempeh for a different texture' ] }, { name: '1 red bell pepper, sliced', substitutes: [ 'Any color bell pepper works well', 'Add Thai chili for extra heat' ] }, { name: '1 small eggplant, cubed', substitutes: [ 'Thai eggplant for authenticity', 'Zucchini if eggplant is unavailable' ] }, { name: '100g snow peas', substitutes: [ 'Green beans cut into 2-inch pieces', 'Sugar snap peas work well too' ] }, { name: '2 kaffir lime leaves', substitutes: [ '1 tsp lime zest + bay leaf', 'Freeze-dried lime leaves if fresh unavailable' ] }, { name: '1 tbsp fish sauce', substitutes: [ 'Soy sauce + pinch of salt for vegetarians', 'Vegan fish sauce alternatives available' ] }, { name: '1 tbsp palm sugar', substitutes: [ 'Brown sugar works as a substitute', 'Maple syrup for a different sweetness' ] }, { name: 'Fresh Thai basil leaves', substitutes: [ 'Regular basil if Thai basil unavailable', 'Mint leaves for a different twist' ] } ], steps: [ 'In a large wok or pan, heat 1 tablespoon of vegetable oil over medium heat. Add the green curry paste and cook for 1-2 minutes until fragrant, stirring constantly to prevent burning.', 'Pour in half the coconut milk and bring to a gentle simmer, stirring to combine with the curry paste. Cook for 2-3 minutes until the oil begins to separate from the coconut milk.', 'Add the tofu cubes and cook for 2 minutes, gently stirring to coat with the curry sauce.', 'Add the eggplant and cook for 5 minutes until it begins to soften.', 'Pour in the remaining coconut milk, fish sauce, palm sugar, and kaffir lime leaves. Bring to a simmer and cook for 5 minutes.', 'Add the bell pepper and snow peas. Cook for another 3-4 minutes until the vegetables are tender but still crisp.', 'Taste and adjust seasonings as needed. Remove from heat and stir in fresh Thai basil leaves.', 'Serve hot with jasmine rice and garnish with additional Thai basil and thinly sliced red chili if desired.' ], culturalNotes: [ '<strong>Thai Green Curry (แกงเขียวหวาน - Kaeng Khiao Wan)</strong> literally translates to "sweet green curry" despite its spicy flavor. The "sweet" refers to the shade of green rather than the taste.', 'In Thailand, curry is typically eaten with rice as part of a larger meal with multiple dishes, not as a standalone dish like in Western countries.', 'The balance of flavors is crucial in Thai cuisine, with this dish exemplifying the harmony between spicy (curry paste), sweet (palm sugar), salty (fish sauce), and aromatic (kaffir lime, basil) elements.', 'Traditional Thai cooking doesn\'t use measuring cups or spoons—it\'s all about tasting and adjusting as you go, following the Thai philosophy of cooking with "heart and soul" (ใส่ใจ - sai jai).' ] }, { name: 'Mexican', title: 'Authentic Chicken Mole Poblano', subtitle: 'A rich, complex sauce with chocolate and chilies served over tender chicken', prepTime: 'Prep: 30 mins', cookTime: 'Cook: 1 hr 45 mins', servings: 'Serves: 6', heatLevel: 'Medium Spicy', image: 'https://images.unsplash.com/photo-1562059390-a761a084768e?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=80', imageCaption: 'Traditional Mole Poblano', ingredients: [ { name: '4 dried ancho chilies, seeded', substitutes: [ 'Guajillo chilies for less heat', 'Mulato chilies for a sweeter flavor' ] }, { name: '2 dried chipotle chilies', substitutes: [ 'Morita chilies for a smokier taste', '1 tbsp chipotle in adobo sauce' ] }, { name: '1/4 cup sesame seeds', substitutes: [ 'Pumpkin seeds (pepitas) for a nuttier flavor', 'Sunflower seeds work in a pinch' ] }, { name: '1/4 cup raisins', substitutes: [ 'Dried cranberries for a tart twist', 'Dried apricots, finely chopped' ] }, { name: '2 corn tortillas, torn into pieces', substitutes: [ '2 slices of stale bread', '2 tbsp corn masa flour' ] }, { name: '2 oz dark chocolate (70% cocoa)', substitutes:
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root { --spring-primary: #e4f1d5; --spring-secondary: #b5e8a1; --spring-accent: #f9c5d1; --summer-primary: #f8e9a1; --summer-secondary: #f76b1c; --summer-accent: #32b4c2; --fall-primary: #f3a683; --fall-secondary: #a8712c; --fall-accent: #903839; --winter-primary: #c8d6e5; --winter-secondary: #227093; --winter-accent: #70367c; --season-primary: var(--spring-primary); --season-secondary: var(--spring-secondary); --season-accent: var(--spring-accent); --season-text: #333; --card-radius: 16px; --shadow: 0 10px 30px rgba(0,0,0,0.1); --transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background-color: #f8f9fa; padding: 15px; overflow-x: hidden; } .container { width: 100%; max-width: 650px; height: 670px; position: relative; overflow: hidden; border-radius: var(--card-radius); box-shadow: var(--shadow); background-color: white; transition: var(--transition); } .season-selector { position: absolute; top: 20px; right: 20px; z-index: 100; display: flex; gap: 8px; background-color: rgba(255, 255, 255, 0.9); padding: 8px; border-radius: 30px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } .season-btn { width: 40px; height: 40px; border-radius: 50%; border: none; cursor: pointer; background-size: cover; background-position: center; opacity: 0.7; transition: var(--transition); position: relative; } .season-btn.active { opacity: 1; transform: scale(1.15); box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); } .season-btn:hover { opacity: 1; transform: scale(1.1); } .season-btn[data-season="spring"] { background-image: url('https://images.unsplash.com/photo-1490750967868-88aa4486c946?ixlib=rb-4.0.3&auto=format&fit=crop&w=100&q=80'); } .season-btn[data-season="summer"] { background-image: url('https://images.unsplash.com/photo-1535498730771-e735b998cd64?ixlib=rb-4.0.3&auto=format&fit=crop&w=100&q=80'); } .season-btn[data-season="fall"] { background-image: url('https://images.unsplash.com/photo-1507371341124-8c2f22d4fd2b?ixlib=rb-4.0.3&auto=format&fit=crop&w=100&q=80'); } .season-btn[data-season="winter"] { background-image: url('https://images.unsplash.com/photo-1544847558-3ccacb31ee7f?ixlib=rb-4.0.3&auto=format&fit=crop&w=100&q=80'); } .recipe-card { position: relative; height: 100%; overflow: hidden; display: flex; flex-direction: column; } .card-header { height: 280px; background-size: cover; background-position: center; position: relative; overflow: hidden; } .card-header::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(0deg, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0) 60%); } .season-badge { position: absolute; top: 20px; left: 20px; background-color: rgba(255, 255, 255, 0.9); padding: 5px 12px; border-radius: 20px; font-weight: 600; font-size: 14px; color: var(--season-secondary); box-shadow: 0 2px 5px rgba(0,0,0,0.1); text-transform: capitalize; } .recipe-title { position: absolute; bottom: 20px; left: 20px; right: 20px; color: white; font-size: 28px; font-weight: 700; text-shadow: 0 2px 4px rgba(0,0,0,0.3); } .card-body { flex: 1; padding: 25px; background-color: white; color: var(--season-text); overflow-y: auto; position: relative; } .recipe-details { display: flex; justify-content: space-between; margin-bottom: 20px; font-size: 15px; color: #666; } .detail-item { display: flex; align-items: center; gap: 5px; } .detail-item svg { width: 18px; height: 18px; fill: var(--season-secondary); } .ingredients-title, .instructions-title, .tips-title { font-size: 18px; font-weight: 600; margin-bottom: 10px; color: var(--season-secondary); display: flex; align-items: center; gap: 8px; } .ingredients-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-bottom: 20px; } .ingredient-item { display: flex; align-items: center; gap: 8px; font-size: 15px; padding: 8px 0; border-bottom: 1px dashed #eee; } .ingredient-swap { margin-left: auto; background-color: var(--season-accent); color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px; cursor: pointer; transition: all 0.2s; display: flex; align-items: center; gap: 3px; } .ingredient-swap:hover { transform: translateY(-2px); box-shadow: 0 3px 6px rgba(0,0,0,0.1); } .instructions-list { margin-bottom: 20px; } .instruction-step { margin-bottom: 12px; position: relative; padding-left: 30px; font-size: 15px; line-height: 1.5; } .instruction-step:before { content: attr(data-step); position: absolute; left: 0; top: 0; width: 22px; height: 22px; background-color: var(--season-secondary); color: white; border-radius: 50%; display: flex; justify-content: center; align-items: center; font-size: 12px; font-weight: 600; } .seasonal-tips { background-color: var(--season-primary); padding: 15px; border-radius: 10px; margin-top: 10px; } .tips-list { font-size: 14px; line-height: 1.5; } .tip-item { margin-bottom: 8px; position: relative; padding-left: 20px; } .tip-item:before { content: "✓"; position: absolute; left: 0; top: 0; color: var(--season-secondary); font-weight: bold; } .swap-modal { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(0.8); opacity: 0; pointer-events: none; background-color: white; border-radius: 12px; padding: 20px; width: 80%; max-width: 320px; box-shadow: 0 15px 30px rgba(0,0,0,0.2); z-index: 1000; transition: all 0.3s; } .swap-modal.active { opacity: 1; pointer-events: all; transform: translate(-50%, -50%) scale(1); } .swap-title { font-size: 18px; font-weight: 600; margin-bottom: 15px; color: var(--season-secondary); } .swap-options { display: flex; flex-direction: column; gap: 10px; margin-bottom: 15px; } .swap-option { display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 8px; background-color: #f5f5f5; cursor: pointer; transition: all 0.2s; } .swap-option:hover { background-color: var(--season-primary); } .swap-option img { width: 35px; height: 35px; object-fit: cover; border-radius: 5px; } .swap-option-info { flex: 1; } .swap-option-name { font-weight: 600; font-size: 15px; } .swap-option-season { font-size: 12px; color: #666; } .swap-close { margin-top: 10px; padding: 8px 15px; background-color: var(--season-secondary); color: white; border: none; border-radius: 5px; cursor: pointer; transition: all 0.2s; width: 100%; } .swap-close:hover { background-color: var(--season-accent); } .overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); opacity: 0; pointer-events: none; transition: opacity 0.3s; z-index: 900; } .overlay.active { opacity: 1; pointer-events: all; } @media (max-width: 600px) { .card-header { height: 200px; } .recipe-title { font-size: 22px; } .ingredients-list { grid-template-columns: 1fr; } .ingredients-title, .instructions-title, .tips-title { font-size: 16px; } .ingredient-item, .instruction-step, .tip-item { font-size: 14px; } .season-selector { top: 10px; right: 10px; } .season-btn { width: 35px; height: 35px; } } .season-transition { animation: fadeIn 0.6s ease-in-out; } @keyframes fadeIn { 0% { opacity: 0; transform: translateY(10px); } 100% { opacity: 1; transform: translateY(0); } } /* Customized Scrollbar */ .card-body::-webkit-scrollbar { width: 6px; } .card-body::-webkit-scrollbar-track { background: #f1f1f1; } .card-body::-webkit-scrollbar-thumb { background-color: var(--season-secondary); border-radius: 20px; } </style> </head> <body> <div class="container"> <div class="season-selector"> <button class="season-btn active" data-season="spring" title="Spring"></button> <button class="season-btn" data-season="summer" title="Summer"></button> <button class="season-btn" data-season="fall" title="Fall"></button> <button class="season-btn" data-season="winter" title="Winter"></button> </div> <div class="recipe-card"> <div class="card-header"> <div class="season-badge">Spring</div> <h1 class="recipe-title">Spring Pea & Asparagus Risotto</h1> </div> <div class="card-body"> <div class="recipe-details"> <div class="detail-item"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4M12,6A6,6 0 0,0 6,12A6,6 0 0,0 12,18A6,6 0 0,0 18,12A6,6 0 0,0 12,6M12,8A4,4 0 0,1 16,12A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8"></path></svg> 35 mins </div> <div class="detail-item"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,3C6.5,3 2,6.58 2,11C2,15.42 6.5,19 12,19C14.24,19 16.27,18.22 17.85,16.95C17.97,17.11 18.11,17.26 18.25,17.4C17.95,18.08 17.27,18.54 16.5,18.54C16.39,18.54 16.28,18.53 16.17,18.5C15.45,18.31 14.7,18.76 14.5,19.47C14.3,20.17 14.76,20.93 15.47,21.13C15.74,21.21 16.02,21.25 16.5,21.25C18.88,21.25 21,19.38 21,17C21,16.2 20.76,15.45 20.31,14.83C21.38,13.74 22,12.45 22,11C22,6.58 17.5,3 12,3M12,17C7.58,17 4,14.31 4,11C4,7.69 7.58,5 12,5C16.42,5 20,7.69 20,11C20,14.31 16.42,17 12,17Z"></path></svg> 4 servings </div> <div class="detail-item"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3,3H21V5H3V3M3,7H21V9H3V7M3,11H21V13H3V11M3,15H21V17H3V15M3,19H21V21H3V19Z"></path></svg> Medium </div> </div> <h2 class="ingredients-title"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M4.5 10.5C5.88 10.5 7 9.38 7 8C7 6.62 5.88 5.5 4.5 5.5C3.12 5.5 2 6.62 2 8C2 9.38 3.12 10.5 4.5 10.5ZM19.44 14.5C19.79 13.69 19.79 12.8 19.44 12L21.16 10.69C21.44 10.47 21.51 10.09 21.33 9.79C20.7 8.69 19.64 7.9 18.35 7.55C18 7.45 17.65 7.62 17.5 7.97L16.69 9.94C15.97 9.69 15.19 9.69 14.47 9.94L13.66 7.97C13.51 7.62 13.16 7.45 12.81 7.55C11.53 7.9 10.47 8.69 9.84 9.79C9.67 10.09 9.73 10.47 10.01 10.69L11.73 12C11.38 12.8 11.38 13.69 11.73 14.5L10.01 15.81C9.73 16.03 9.67 16.41 9.84 16.71C10.47 17.81 11.53 18.6 12.81 18.95C13.16 19.05 13.51 18.88 13.66 18.53L14.47 16.56C15.19 16.81 15.97 16.81 16.69 16.56L17.5 18.53C17.65 18.88 18 19.05 18.35 18.95C19.64 18.6 20.7 17.81 21.33 16.71C21.51 16.41 21.44 16.03 21.16 15.81L19.44 14.5ZM15.58 14.38C14.99 14.38 14.5 13.89 14.5 13.29C14.5 12.7 14.99 12.21 15.58 12.21C16.17 12.21 16.66 12.7 16.66 13.29C16.66 13.89 16.17 14.38 15.58 14.38ZM4.5 21.5C5.88 21.5 7 20.38 7 19C7 17.62 5.88 16.5 4.5 16.5C3.12 16.5 2 17.62 2 19C2 20.38 3.12 21.5 4.5 21.5Z" fill="currentColor"/> </svg> Ingredients </h2> <div class="ingredients-list"> <div class="ingredient-item"> 1½ cups Arborio rice </div> <div class="ingredient-item"> 5 cups vegetable broth </div> <div class="ingredient-item"> 1 bunch fresh asparagus <span class="ingredient-swap" data-ingredient="asparagus">Swap</span> </div> <div class="ingredient-item"> 1 cup fresh peas <span class="ingredient-swap" data-ingredient="peas">Swap</span> </div> <div class="ingredient-item"> 1 small leek, sliced </div> <div class="ingredient-item"> 3 cloves garlic, minced </div> <div class="ingredient-item"> ½ cup dry white wine </div> <div class="ingredient-item"> 2 tbsp mint leaves <span class="ingredient-swap" data-ingredient="mint">Swap</span> </div> <div class="ingredient-item"> ⅓ cup grated Parmesan </div> <div class="ingredient-item"> 2 tbsp olive oil </div> </div> <h2 class="instructions-title"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2ZM18 20H6V4H13V9H18V20ZM10 19L11.88 17.12L10.47 15.71L13.29 12.88L14.7 14.29L11.88 17.12L13.76 19H10Z" fill="currentColor"/> </svg> Instructions </h2> <div class="instructions-list"> <div class="instruction-step" data-step="1"> Trim asparagus and cut into 1-inch pieces. Bring a pot of water to boil, blanch asparagus for 2 minutes, then immediately transfer to ice water. </div> <div class="instruction-step" data-step="2"> In a large saucepan, heat olive oil over medium heat. Add sliced leeks and cook until softened, about 3 minutes. </div> <div class="instruction-step" data-step="3"> Add garlic and cook for 30 seconds until fragrant. Add rice and stir to coat with oil, toasting for about 2 minutes. </div> <div class="instruction-step" data-step="4"> Pour in white wine and stir until absorbed. Begin adding warm broth, one ladle at a time, stirring frequently and adding more broth once absorbed. </div> <div class="instruction-step" data-step="5"> After about 15 minutes, add blanched asparagus and fresh peas. Continue adding broth and stirring until rice is creamy and just tender, about 5-7 more minutes. </div> <div class="instruction-step" data-step="6"> Remove from heat, stir in Parmesan cheese, chopped mint, and season with salt and pepper. Cover and let rest for 2 minutes before serving. </div> </div> <h2 class="tips-title"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM12 20C7.58 20 4 16.42 4 12C4 7.58 7.58 4 12 4C16.42 4 20 7.58 20 12C20 16.42 16.42 20 12 20ZM11 16H13V18H11V16ZM12.61 6.04C10.55 5.74 8.73 7.01 8.18 8.83C8 9.41 8.44 10 9.05 10H9.25C9.66 10 9.99 9.71 10.13 9.33C10.45 8.44 11.4 7.83 12.43 8.05C13.38 8.25 14.08 9.23 14 10.2C13.9 11.5 12.38 11.98 11.55 13.03C11.18 13.48 11 14.08 11 14.7V15H13V14.7C13 14.15 13.38 13.56 13.93 13.13C14.73 12.5 15.6 11.64 15.86 10.5C16.27 8.56 14.89 6.54 12.61 6.04Z" fill="currentColor"/> </svg> Spring Seasonal Tips </h2> <div class="seasonal-tips"> <div class="tips-list"> <div class="tip-item"> For the freshest spring peas, look for firm, bright green pods that are plump but not bulging. </div> <div class="tip-item"> Young spring asparagus will have tightly closed tips and a smooth, firm texture. </div> <div class="tip-item"> Add tender young pea shoots as a garnish for an extra burst of spring flavor and visual appeal. </div> <div class="tip-item"> This dish pairs beautifully with a crisp Sauvignon Blanc which complements the fresh spring vegetables. </div> </div> </div> </div> </div> </div> <div class="overlay"></div> <div class="swap-modal"> <h3 class="swap-title">Seasonal Ingredient Swaps</h3> <div class="swap-options"> <!-- Will be populated by JavaScript --> </div> <button class="swap-close">Close</button> </div> <script> document.addEventListener('DOMContentLoaded', () => { // Season data const seasonData = { spring: { title: "Spring Pea & Asparagus Risotto", image: "https://images.unsplash.com/photo-1557413878-cb3cc8295b14?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", tips: [ "For the freshest spring peas, look for firm, bright green pods that are plump but not bulging.", "Young spring asparagus will have tightly closed tips and a smooth, firm texture.", "Add tender young pea shoots as a garnish for an extra burst of spring flavor and visual appeal.", "This dish pairs beautifully with a crisp Sauvignon Blanc which complements the fresh spring vegetables." ] }, summer: { title: "Summer Tomato & Corn Risotto", image: "https://images.unsplash.com/photo-1606790309755-48130583a36c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", tips: [ "Use vine-ripened heirloom tomatoes for the most intense summer flavor.", "Fresh corn is sweetest when in season - cut it directly off the cob for best results.", "A splash of lemon juice brightens the risotto and balances the sweetness of summer corn.", "Garnish with torn basil leaves just before serving to preserve their aromatic qualities." ] }, fall: { title: "Fall Butternut Squash & Sage Risotto", image: "https://images.unsplash.com/photo-1517686748843-bb360cfc62b3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", tips: [ "Look for butternut squash with a matte, beige exterior - shiny skin indicates it was harvested too early.", "Roasting the squash before adding to the risotto develops a deeper caramelized flavor.", "Frying sage leaves in butter creates a crispy garnish and infuses the butter with flavor.", "A pinch of nutmeg complements the earthiness of the squash and highlights fall spice notes." ] }, winter: { title: "Winter Mushroom & Kale Risotto", image: "https://images.unsplash.com/photo-1547592180-aded18671dd4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80", tips: [ "Use a variety of winter mushrooms like shiitake, oyster, and cremini for complex flavor.", "Massaging kale with olive oil before adding it to the risotto helps tenderize it.", "Rehydrated dried porcini mushrooms and their soaking liquid add incredible depth to the broth.", "Finish with a drizzle of truffle oil for an elegant touch perfect for winter entertaining." ] } }; // Ingredient swap options const ingredientSwaps = { asparagus: [ { name: "Asparagus", season: "Spring", image: "https://images.unsplash.com/photo-1633683694295-89f1a3bbdcdb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" }, { name: "Zucchini", season: "Summer", image: "https://images.unsplash.com/photo-1583687355032-89b902b7335f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" }, { name: "Brussels Sprouts", season: "Fall", image: "https://images.unsplash.com/photo-1624295412439-7bb2a5a4f9c1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" }, { name: "Broccoli", season: "Winter", image: "https://images.unsplash.com/photo-1459411621453-7b03977f4bfc?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" } ], peas: [ { name: "Fresh Peas", season: "Spring", image: "https://images.unsplash.com/photo-1587735243615-c03f25aaff15?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" }, { name: "Sweet Corn", season: "Summer", image: "https://images.unsplash.com/photo-1551754655-cd27e38d2076?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" }, { name: "Butternut Squash", season: "Fall", image: "https://images.unsplash.com/photo-1570586437263-ab629fccc818?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" }, { name: "Wild Mushrooms", season: "Winter", image: "https://images.unsplash.com/photo-1504674900247-0877df9cc836?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" } ], mint: [ { name: "Mint", season: "Spring", image: "https://images.unsplash.com/photo-1600326145554-f85c91b1a917?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" }, { name: "Basil", season: "Summer", image: "https://images.unsplash.com/photo-1600717535275-0b5d77b683d7?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" }, { name: "Sage", season: "Fall", image: "https://images.unsplash.com/photo-1603129624917-87ecab9fa56e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" }, { name: "Thyme", season: "Winter", image: "https://images.unsplash.com/photo-1581003794073-6b4a91e01830?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" } ] }; // DOM elements const seasonBtns = document.querySelectorAll('.season-btn'); const seasonBadge = document.querySelector('.season-badge'); const recipeTitle = document.querySelector('.recipe-title'); const cardHeader = document.querySelector('.card-header'); const seasonalTips = document.querySelector('.tips-list'); const swapButtons = document.querySelectorAll('.ingredient-swap'); const swapModal = document.querySelector('.swap-modal'); const swapOptions = document.querySelector('.swap-options'); const swapClose = document.querySelector('.swap-close'); const overlay = document.querySelector('.overlay'); // Set the current season's theme function setSeasonTheme(season) { document.documentElement.style.setProperty('--season-primary', `var(--${season}-primary)`); document.documentElement.style.setProperty('--season-secondary', `var(--${season}-secondary)`); document.documentElement.style.setProperty('--season-accent', `var(--${season}-accent)`); // Update active button seasonBtns.forEach(btn => { btn.classList.remove('active');
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>QuickBite Recipe Card</title> <style> :root { --primary: #ff6b6b; --secondary: #4ecdc4; --dark: #292f36; --light: #f7fff7; --accent: #ffd166; --timer-bg: rgba(247, 255, 247, 0.9); --shadow: 0 4px 6px rgba(0, 0, 0, 0.1); --card-radius: 16px; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f5f5f5; color: var(--dark); display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 20px; } .recipe-card { background-color: white; width: 100%; max-width: 650px; height: 650px; border-radius: var(--card-radius); box-shadow: var(--shadow); overflow: hidden; position: relative; display: flex; flex-direction: column; } .recipe-header { background: linear-gradient(to right, var(--primary), var(--secondary)); padding: 24px; color: white; position: relative; overflow: hidden; } .recipe-header h1 { font-size: 28px; margin-bottom: 8px; font-weight: 700; position: relative; z-index: 2; } .recipe-meta { display: flex; gap: 20px; font-size: 14px; position: relative; z-index: 2; } .meta-item { display: flex; align-items: center; gap: 6px; } .meta-item svg { width: 18px; height: 18px; } .pattern { position: absolute; top: 0; right: 0; width: 200px; height: 100%; background: repeating-linear-gradient( 45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1) 10px, transparent 10px, transparent 20px ); z-index: 1; } .recipe-content { padding: 24px; flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 20px; } .ingredients-section { background-color: #f9f9f9; padding: 16px; border-radius: 12px; border-left: 4px solid var(--accent); } .ingredients-section h2 { font-size: 18px; margin-bottom: 12px; color: var(--dark); display: flex; align-items: center; gap: 8px; } .ingredients-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 16px; } .ingredient-item { font-size: 15px; display: flex; align-items: center; gap: 8px; } .steps-section h2 { font-size: 18px; margin-bottom: 16px; color: var(--dark); display: flex; align-items: center; gap: 8px; } .steps-list { display: flex; flex-direction: column; gap: 16px; } .step { position: relative; padding-left: 50px; padding-bottom: 16px; border-left: 2px solid #e0e0e0; margin-left: 10px; } .step:last-child { border-left: 2px solid transparent; } .step-number { position: absolute; left: -12px; top: -5px; width: 24px; height: 24px; background-color: var(--primary); color: white; border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: 600; font-size: 14px; } .step-content { font-size: 16px; line-height: 1.5; } .step.active .step-number { background-color: var(--secondary); transform: scale(1.2); transition: transform 0.3s ease; } .step.completed .step-number { background-color: #6fd08c; } .step.completed .step-content { color: #767676; } .step.completed::before { content: "✓"; position: absolute; left: -12px; top: -5px; width: 24px; height: 24px; background-color: #6fd08c; color: white; border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: 600; font-size: 14px; } .timer-container { position: fixed; bottom: 20px; right: 20px; background: var(--timer-bg); padding: 16px; border-radius: 12px; box-shadow: var(--shadow); display: none; z-index: 100; backdrop-filter: blur(5px); max-width: 200px; } .timer-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .timer-title { font-weight: 600; font-size: 16px; } .close-timer { background: none; border: none; color: var(--dark); cursor: pointer; font-size: 18px; } .timer-display { font-size: 28px; text-align: center; font-weight: 700; color: var(--primary); margin: 10px 0; } .timer-controls { display: flex; gap: 8px; } .timer-btn { background-color: var(--secondary); border: none; color: white; padding: 8px 12px; border-radius: 6px; cursor: pointer; flex: 1; font-weight: 600; transition: background-color 0.3s ease; } .timer-btn:hover { background-color: var(--primary); } .timer-btn.pause { background-color: var(--accent); } .timer-btn.reset { background-color: var(--dark); } .progress-bar { width: 100%; height: 6px; background-color: #e0e0e0; border-radius: 3px; margin-top: 16px; overflow: hidden; } .progress { height: 100%; background-color: var(--secondary); width: 0%; transition: width 0.3s ease; } .timer-link { color: var(--secondary); text-decoration: underline; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; font-weight: 600; } .timer-link:hover { color: var(--primary); } .serving-control { display: flex; align-items: center; gap: 12px; margin-top: -10px; margin-bottom: 10px; } .serving-btn { width: 30px; height: 30px; border-radius: 50%; border: 2px solid var(--secondary); background-color: white; color: var(--secondary); font-weight: bold; cursor: pointer; display: flex; justify-content: center; align-items: center; transition: all 0.2s ease; } .serving-btn:hover { background-color: var(--secondary); color: white; } .serving-count { font-weight: 600; font-size: 16px; } .quantity { transition: all 0.3s ease; } @media (max-width: 600px) { .recipe-header h1 { font-size: 24px; } .ingredients-list { grid-template-columns: 1fr; } .recipe-content { padding: 16px; } } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .pulse { animation: pulse 1s infinite; } /* Custom scrollbar */ .recipe-content::-webkit-scrollbar { width: 6px; } .recipe-content::-webkit-scrollbar-track { background: #f1f1f1; } .recipe-content::-webkit-scrollbar-thumb { background-color: var(--secondary); border-radius: 20px; } </style> </head> <body> <div class="recipe-card"> <div class="recipe-header"> <h1>Spicy Garlic Shrimp Pasta</h1> <div class="recipe-meta"> <div class="meta-item"> <svg viewBox="0 0 24 24" fill="white"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-.01-14c-.55 0-1 .45-1 1v5c0 .28.11.53.29.71l3.01 3.01c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13 11.6V7c0-.55-.45-1-1.01-1z"/> </svg> <span>Ready in 15 min</span> </div> <div class="meta-item"> <svg viewBox="0 0 24 24" fill="white"> <path d="M16 6v6c0 1.1.9 2 2 2h1v7c0 .55.45 1 1 1s1-.45 1-1V3.13c0-.65-.61-1.13-1.24-.98C17.6 2.68 16 4.51 16 6zm-5 3H9V3c0-.55-.45-1-1-1s-1 .45-1 1v6H5V3c0-.55-.45-1-1-1s-1 .45-1 1v6c0 2.21 1.79 4 4 4v8c0 .55.45 1 1 1s1-.45 1-1v-8c2.21 0 4-1.79 4-4V3c0-.55-.45-1-1-1s-1 .45-1 1v6z"/> </svg> <span>Medium Heat</span> </div> </div> <div class="pattern"></div> </div> <div class="recipe-content"> <div class="serving-control"> <button class="serving-btn" id="decrease-serving">-</button> <div class="serving-count"><span id="serving-number">2</span> servings</div> <button class="serving-btn" id="increase-serving">+</button> </div> <div class="ingredients-section"> <h2> <svg width="18" height="18" viewBox="0 0 24 24" fill="var(--dark)"> <path d="M4 9h16v2H4V9zm0 4h10v2H4v-2z"/> <path d="M17 5a2 2 0 0 1 2 2h-5a2 2 0 0 1 2-2h1zm0-2h-1a4 4 0 0 0-4 4h9a4 4 0 0 0-4-4zm-7 14v-1h10v1c0 2-1.22 3-3 3h-4c-1.78 0-3-1-3-3z"/> </svg> Ingredients </h2> <div class="ingredients-list"> <div class="ingredient-item"> <span class="quantity" data-base="8">8</span> oz linguine pasta </div> <div class="ingredient-item"> <span class="quantity" data-base="12">12</span> large shrimp, peeled </div> <div class="ingredient-item"> <span class="quantity" data-base="3">3</span> cloves garlic, minced </div> <div class="ingredient-item"> <span class="quantity" data-base="2">2</span> tbsp olive oil </div> <div class="ingredient-item"> <span class="quantity" data-base="1">1</span> tsp red pepper flakes </div> <div class="ingredient-item"> <span class="quantity" data-base="0.25">1/4</span> cup white wine </div> <div class="ingredient-item"> <span class="quantity" data-base="1">1</span> tbsp butter </div> <div class="ingredient-item"> <span class="quantity" data-base="2">2</span> tbsp fresh parsley </div> </div> </div> <div class="steps-section"> <h2> <svg width="18" height="18" viewBox="0 0 24 24" fill="var(--dark)"> <path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z"/> <path d="M9 13h6v2H9zm0 3h6v2H9zm0-6h4v2H9z"/> </svg> Steps to Follow </h2> <div class="steps-list"> <div class="step" data-step="1"> <div class="step-number">1</div> <div class="step-content"> Bring a large pot of salted water to boil. Cook pasta according to package directions. <span class="timer-link" data-minutes="8" data-seconds="0"> <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-.01-14c-.55 0-1 .45-1 1v5c0 .28.11.53.29.71l3.01 3.01c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13 11.6V7c0-.55-.45-1-1.01-1z"/> </svg> Start 8m timer </span> </div> </div> <div class="step" data-step="2"> <div class="step-number">2</div> <div class="step-content"> While pasta cooks, heat olive oil in a large skillet over medium-high heat. Add minced garlic and red pepper flakes, cook for 30 seconds until fragrant. </div> </div> <div class="step" data-step="3"> <div class="step-number">3</div> <div class="step-content"> Add shrimp to skillet, cook for 2 minutes on each side until pink and opaque. <span class="timer-link" data-minutes="2" data-seconds="0"> <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-.01-14c-.55 0-1 .45-1 1v5c0 .28.11.53.29.71l3.01 3.01c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13 11.6V7c0-.55-.45-1-1.01-1z"/> </svg> Start 2m timer </span> </div> </div> <div class="step" data-step="4"> <div class="step-number">4</div> <div class="step-content"> Pour in white wine, let it reduce by half (about 1 minute). Add butter and stir until melted. </div> </div> <div class="step" data-step="5"> <div class="step-number">5</div> <div class="step-content"> Drain pasta and add it directly to the skillet. Toss to coat everything evenly. Sprinkle with fresh parsley and serve immediately. </div> </div> </div> </div> </div> </div> <div class="timer-container" id="timer-container"> <div class="timer-header"> <div class="timer-title">Timer</div> <button class="close-timer" id="close-timer">×</button> </div> <div class="timer-display" id="timer-display">00:00</div> <div class="timer-controls"> <button class="timer-btn start" id="start-timer">Start</button> <button class="timer-btn reset" id="reset-timer">Reset</button> </div> <div class="progress-bar"> <div class="progress" id="timer-progress"></div> </div> </div> <script> // Timer functionality let timerInterval; let totalSeconds = 0; let originalSeconds = 0; let isTimerRunning = false; const timerDisplay = document.getElementById('timer-display'); const timerContainer = document.getElementById('timer-container'); const startTimerBtn = document.getElementById('start-timer'); const resetTimerBtn = document.getElementById('reset-timer'); const closeTimerBtn = document.getElementById('close-timer'); const timerProgress = document.getElementById('timer-progress'); // Servings functionality const decreaseBtn = document.getElementById('decrease-serving'); const increaseBtn = document.getElementById('increase-serving'); const servingNumber = document.getElementById('serving-number'); const quantities = document.querySelectorAll('.quantity'); // Steps tracking const steps = document.querySelectorAll('.step'); let currentStep = 1; // Timer links const timerLinks = document.querySelectorAll('.timer-link'); // Format time for display function formatTime(seconds) { const mins = Math.floor(seconds / 60); const secs = seconds % 60; return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; } // Start or pause the timer function toggleTimer() { if (isTimerRunning) { clearInterval(timerInterval); startTimerBtn.textContent = 'Resume'; startTimerBtn.classList.add('pause'); } else { timerInterval = setInterval(updateTimer, 1000); startTimerBtn.textContent = 'Pause'; startTimerBtn.classList.remove('pause'); } isTimerRunning = !isTimerRunning; } // Update timer every second function updateTimer() { if (totalSeconds > 0) { totalSeconds--; const progressPercentage = ((originalSeconds - totalSeconds) / originalSeconds) * 100; timerProgress.style.width = `${progressPercentage}%`; timerDisplay.textContent = formatTime(totalSeconds); } else { clearInterval(timerInterval); isTimerRunning = false; startTimerBtn.textContent = 'Start'; startTimerBtn.classList.remove('pause'); timerProgress.style.width = '100%'; timerDisplay.classList.add('pulse'); // Complete the current step automatically if (currentStep <= steps.length) { steps[currentStep-1].classList.add('completed'); if (currentStep < steps.length) { currentStep++; setTimeout(() => { steps[currentStep-1].classList.add('active'); steps[currentStep-1].scrollIntoView({ behavior: 'smooth', block: 'center' }); }, 500); } } setTimeout(() => { timerDisplay.classList.remove('pulse'); }, 3000); } } // Reset timer function resetTimer() { clearInterval(timerInterval); isTimerRunning = false; totalSeconds = originalSeconds; timerDisplay.textContent = formatTime(totalSeconds); startTimerBtn.textContent = 'Start'; startTimerBtn.classList.remove('pause'); timerProgress.style.width = '0%'; } // Set up a new timer function setTimer(minutes, seconds) { totalSeconds = (minutes * 60) + seconds; originalSeconds = totalSeconds; timerDisplay.textContent = formatTime(totalSeconds); timerContainer.style.display = 'block'; timerProgress.style.width = '0%'; // If timer is already running, stop it if (isTimerRunning) { clearInterval(timerInterval); isTimerRunning = false; } startTimerBtn.textContent = 'Start'; startTimerBtn.classList.remove('pause'); } // Update ingredient quantities function updateQuantities(servings) { quantities.forEach(quantity => { const baseAmount = parseFloat(quantity.getAttribute('data-base')); const newAmount = (baseAmount * servings / 2); // Format the display for fractions if (newAmount === 0.25) quantity.textContent = "1/4"; else if (newAmount === 0.5) quantity.textContent = "1/2"; else if (newAmount === 0.75) quantity.textContent = "3/4"; else if (newAmount === 1.5) quantity.textContent = "1 1/2"; else if (newAmount === 1.25) quantity.textContent = "1 1/4"; else if (newAmount === 1.75) quantity.textContent = "1 3/4"; else quantity.textContent = newAmount; }); } // Initialize active step steps[0].classList.add('active'); // Timer button event listeners startTimerBtn.addEventListener('click', toggleTimer); resetTimerBtn.addEventListener('click', resetTimer); closeTimerBtn.addEventListener('click', () => { timerContainer.style.display = 'none'; if (isTimerRunning) { clearInterval(timerInterval); isTimerRunning = false; } }); // Timer links event listeners timerLinks.forEach(link => { link.addEventListener('click', (e) => { const minutes = parseInt(link.getAttribute('data-minutes')) || 0; const seconds = parseInt(link.getAttribute('data-seconds')) || 0; setTimer(minutes, seconds); // Get step number from parent and set as current const stepElement = link.closest('.step'); if (stepElement) { const stepNum = parseInt(stepElement.getAttribute('data-step')); // Reset styles steps.forEach(step => step.classList.remove('active')); // Set new active step stepElement.classList.add('active'); currentStep = stepNum; } }); }); // Serving buttons event listeners decreaseBtn.addEventListener('click', () => { let servings = parseInt(servingNumber.textContent); if (servings > 1) { servings--; servingNumber.textContent = servings; updateQuantities(servings); } }); increaseBtn.addEventListener('click', () => { let servings = parseInt(servingNumber.textContent); if (servings < 8) { servings++; servingNumber.textContent = servings; updateQuantities(servings); } }); // Click on steps to mark as complete steps.forEach(step => { step.addEventListener('click', () => { const stepNum = parseInt(step.getAttribute('data-step')); // If clicking on current step, mark as complete and move to next if (stepNum === currentStep) { step.classList.add('completed'); if (currentStep < steps.length) { currentStep++; setTimeout(() => { steps[currentStep-1].classList.add('active'); }, 300); } } // If clicking on a previous step, toggle completion else if (stepNum < currentStep) { if (step.classList.contains('completed')) { step.classList.remove('completed'); } else { step.classList.add('completed'); } } // If clicking on a future step, make it active else if (stepNum > currentStep) { steps.forEach(s => s.classList.remove('active')); step.classList.add('active'); currentStep = stepNum; } }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Interactive Recipe Card</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', sans-serif; } body { background-color: #f9f4f0; display: flex; justify-content: center; align-items: center; min-height: 100vh; perspective: 1200px; overflow: hidden; } .container { width: 100%; max-width: 700px; height: 700px; padding: 20px; display: flex; justify-content: center; align-items: center; position: relative; } .recipe-card { width: 90%; height: 90%; position: relative; transform-style: preserve-3d; transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .flip-button { position: absolute; bottom: 15px; right: 15px; z-index: 10; background: #ff6b6b; color: white; border: none; border-radius: 50%; width: 50px; height: 50px; font-size: 20px; cursor: pointer; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; display: flex; justify-content: center; align-items: center; } .flip-button:hover { transform: scale(1.1); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); } .recipe-front, .recipe-back { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; border-radius: 20px; overflow: hidden; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); background: white; display: flex; flex-direction: column; } .recipe-back { transform: rotateY(180deg); } .recipe-header { padding: 20px; background: linear-gradient(135deg, #ff6b6b 0%, #ffa3a3 100%); color: white; display: flex; justify-content: space-between; align-items: center; flex-shrink: 0; } .recipe-title { font-size: 1.8rem; font-weight: 700; margin-bottom: 5px; } .recipe-subtitle { font-size: 1rem; opacity: 0.9; } .recipe-info { display: flex; gap: 15px; padding: 10px 20px; background: rgba(255, 255, 255, 0.15); margin-top: 5px; border-radius: 0 0 20px 20px; } .info-item { display: flex; flex-direction: column; align-items: center; font-size: 0.8rem; } .info-value { font-weight: 700; font-size: 1rem; } .recipe-image { width: 100%; height: 200px; object-fit: cover; border-bottom: 3px solid #ff6b6b; } .recipe-content { padding: 20px; flex: 1; overflow-y: auto; scrollbar-width: thin; position: relative; } .recipe-content::-webkit-scrollbar { width: 5px; } .recipe-content::-webkit-scrollbar-thumb { background-color: #ff6b6b; border-radius: 10px; } .section-title { font-size: 1.3rem; color: #ff6b6b; margin-bottom: 15px; display: flex; align-items: center; position: relative; } .section-title::after { content: ''; flex: 1; height: 2px; background: linear-gradient(90deg, #ff6b6b 0%, transparent 100%); margin-left: 10px; } .ingredients-list { list-style-type: none; margin-bottom: 20px; } .ingredient-item { display: flex; align-items: center; padding: 8px 0; border-bottom: 1px dashed #eee; transition: transform 0.3s ease, background-color 0.3s ease; } .ingredient-item:hover { transform: translateX(5px); color: #ff6b6b; } .ingredient-checkbox { margin-right: 10px; appearance: none; width: 18px; height: 18px; border: 2px solid #ddd; border-radius: 4px; cursor: pointer; position: relative; transition: all 0.2s ease; } .ingredient-checkbox:checked { background-color: #ff6b6b; border-color: #ff6b6b; } .ingredient-checkbox:checked::after { content: '✓'; position: absolute; color: white; font-size: 12px; top: 50%; left: 50%; transform: translate(-50%, -50%); } .ingredient-checkbox:checked + .ingredient-text { text-decoration: line-through; color: #aaa; } .step-list { counter-reset: step-counter; } .step-item { position: relative; padding: 15px 0 15px 40px; margin-bottom: 15px; border-bottom: 1px solid #eee; transition: transform 0.3s ease; } .step-item:hover { transform: translateY(-3px); } .step-item::before { counter-increment: step-counter; content: counter(step-counter); position: absolute; left: 0; top: 15px; width: 30px; height: 30px; background: #ff6b6b; color: white; border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: bold; } .timer-button { background: #f5f5f5; border: none; border-radius: 15px; padding: 3px 8px; font-size: 0.8rem; color: #555; cursor: pointer; margin-left: 5px; transition: all 0.3s ease; display: inline-flex; align-items: center; } .timer-button:hover { background: #ff6b6b; color: white; } .timer-button i { margin-right: 3px; } .recipe-tips { margin-top: 20px; padding: 15px; background: #fff9f9; border-left: 3px solid #ff6b6b; border-radius: 5px; } .tips-title { font-weight: 600; color: #ff6b6b; margin-bottom: 5px; } .flipped { transform: rotateY(180deg); } .timer-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 1000; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; } .timer-modal.active { opacity: 1; pointer-events: all; } .timer-content { background: white; padding: 20px; border-radius: 15px; width: 80%; max-width: 300px; text-align: center; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2); transform: scale(0.8); transition: transform 0.3s ease; } .timer-modal.active .timer-content { transform: scale(1); } .timer-display { font-size: 2.5rem; font-weight: bold; margin: 15px 0; color: #ff6b6b; } .timer-controls { display: flex; justify-content: center; gap: 10px; margin-top: 20px; } .timer-btn { padding: 8px 15px; border: none; border-radius: 20px; cursor: pointer; font-weight: 600; transition: all 0.3s ease; } .start-btn { background: #ff6b6b; color: white; } .start-btn:hover { background: #ff5252; } .cancel-btn { background: #f0f0f0; color: #555; } .cancel-btn:hover { background: #e0e0e0; } .nutrition-chart { display: flex; justify-content: space-between; margin-top: 20px; padding: 10px; background: #f9f9f9; border-radius: 10px; } .nutrition-item { display: flex; flex-direction: column; align-items: center; width: 23%; } .nutrient-circle { width: 60px; height: 60px; border-radius: 50%; background: conic-gradient(#ff6b6b var(--percent), #eee var(--percent)); display: flex; justify-content: center; align-items: center; position: relative; margin-bottom: 5px; } .nutrient-circle::before { content: ""; position: absolute; width: 50px; height: 50px; border-radius: 50%; background: white; } .nutrient-value { position: relative; font-weight: bold; font-size: 0.9rem; color: #ff6b6b; } .nutrient-label { font-size: 0.8rem; color: #666; text-align: center; } @media (max-width: 520px) { .recipe-card { width: 100%; height: 95%; } .recipe-title { font-size: 1.5rem; } .recipe-info { flex-wrap: wrap; } .nutrition-chart { flex-wrap: wrap; } .nutrition-item { width: 48%; margin-bottom: 10px; } } /* Animation for ingredients */ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .ingredients-list .ingredient-item { opacity: 0; animation: fadeIn 0.3s ease forwards; } .ingredients-list .ingredient-item:nth-child(1) { animation-delay: 0.1s; } .ingredients-list .ingredient-item:nth-child(2) { animation-delay: 0.2s; } .ingredients-list .ingredient-item:nth-child(3) { animation-delay: 0.3s; } .ingredients-list .ingredient-item:nth-child(4) { animation-delay: 0.4s; } .ingredients-list .ingredient-item:nth-child(5) { animation-delay: 0.5s; } .ingredients-list .ingredient-item:nth-child(6) { animation-delay: 0.6s; } .ingredients-list .ingredient-item:nth-child(7) { animation-delay: 0.7s; } /* Recipe tag styles */ .recipe-tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 15px 0; } .recipe-tag { background: #ffebeb; color: #ff6b6b; padding: 4px 10px; border-radius: 20px; font-size: 0.8rem; font-weight: 500; transition: all 0.3s ease; } .recipe-tag:hover { background: #ff6b6b; color: white; transform: scale(1.05); } /* Progress tracker */ .progress-tracker { position: absolute; top: 20px; right: 20px; width: 40px; height: 40px; border-radius: 50%; background: #f0f0f0; display: flex; justify-content: center; align-items: center; font-size: 0.8rem; font-weight: bold; color: #ff6b6b; z-index: 5; box-shadow: 0 2px 5px rgba(0,0,0,0.1); cursor: pointer; transition: all 0.3s ease; } .progress-tracker:hover { transform: scale(1.1); } .progress-tracker svg { width: 100%; height: 100%; position: absolute; top: 0; left: 0; transform: rotate(-90deg); } .progress-tracker circle { fill: none; stroke-width: 5; stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: var(--progress, 100); transition: stroke-dashoffset 0.5s ease; } </style> </head> <body> <div class="container"> <div class="recipe-card"> <!-- Front side: Ingredients --> <div class="recipe-front"> <img src="https://images.unsplash.com/photo-1560717845-968823efbee1?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="Lemon Herb Salmon" class="recipe-image"> <div class="recipe-header"> <div> <h1 class="recipe-title">Lemon Herb Salmon</h1> <p class="recipe-subtitle">A Mediterranean-inspired delight</p> </div> <div class="recipe-info"> <div class="info-item"> <span class="info-value">25</span> <span>mins</span> </div> <div class="info-item"> <span class="info-value">4</span> <span>servings</span> </div> <div class="info-item"> <span class="info-value">425</span> <span>calories</span> </div> </div> </div> <div class="recipe-content"> <div class="recipe-tags"> <span class="recipe-tag">Mediterranean</span> <span class="recipe-tag">High-Protein</span> <span class="recipe-tag">Gluten-Free</span> <span class="recipe-tag">Pescatarian</span> </div> <h2 class="section-title">Ingredients</h2> <ul class="ingredients-list"> <li class="ingredient-item"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">4 salmon fillets (6 oz each), skin-on</span> </li> <li class="ingredient-item"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">3 tbsp extra virgin olive oil</span> </li> <li class="ingredient-item"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">2 lemons (1 zested & juiced, 1 sliced)</span> </li> <li class="ingredient-item"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">4 cloves garlic, minced</span> </li> <li class="ingredient-item"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">2 tbsp fresh dill, chopped</span> </li> <li class="ingredient-item"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">2 tbsp fresh parsley, chopped</span> </li> <li class="ingredient-item"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">1 tsp dried oregano</span> </li> <li class="ingredient-item"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">Salt and black pepper to taste</span> </li> <li class="ingredient-item"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">¼ tsp red pepper flakes (optional)</span> </li> </ul> <div class="nutrition-chart"> <div class="nutrition-item"> <div class="nutrient-circle" style="--percent: 75%"> <span class="nutrient-value">25g</span> </div> <span class="nutrient-label">Protein</span> </div> <div class="nutrition-item"> <div class="nutrient-circle" style="--percent: 30%"> <span class="nutrient-value">12g</span> </div> <span class="nutrient-label">Carbs</span> </div> <div class="nutrition-item"> <div class="nutrient-circle" style="--percent: 55%"> <span class="nutrient-value">19g</span> </div> <span class="nutrient-label">Fats</span> </div> <div class="nutrition-item"> <div class="nutrient-circle" style="--percent: 15%"> <span class="nutrient-value">2g</span> </div> <span class="nutrient-label">Fiber</span> </div> </div> </div> <button class="flip-button"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8 5L5 8L8 11" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M5 8H14C17.314 8 20 10.686 20 14C20 17.314 17.314 20 14 20H4" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> </div> <!-- Back side: Instructions --> <div class="recipe-back"> <div class="recipe-header"> <div> <h1 class="recipe-title">Cooking Instructions</h1> <p class="recipe-subtitle">Step-by-step guide to perfection</p> </div> </div> <div class="progress-tracker"> <svg viewBox="0 0 36 36"> <circle cx="18" cy="18" r="16" stroke="#eee" /> <circle cx="18" cy="18" r="16" stroke="#ff6b6b" style="--progress: 100" id="progress-circle" /> </svg> <span id="progress-text">0%</span> </div> <div class="recipe-content"> <h2 class="section-title">Preparation</h2> <ol class="step-list"> <li class="step-item"> Pat the salmon fillets dry with paper towels and season both sides with salt and pepper. </li> <li class="step-item"> In a bowl, mix olive oil, lemon zest, lemon juice, minced garlic, dill, parsley, oregano, and red pepper flakes. </li> <li class="step-item"> Place the salmon fillets skin-side down on a parchment-lined baking sheet. </li> </ol> <h2 class="section-title">Cooking Method</h2> <ol class="step-list" start="4"> <li class="step-item"> Preheat your oven to 375°F (190°C). <button class="timer-button" data-time="0"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 7V12L15 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> Preheat</button> </li> <li class="step-item"> Spread the herb mixture evenly over the top of each salmon fillet, making sure they're well coated. </li> <li class="step-item"> Arrange lemon slices around and slightly under the edges of the fillets. </li> <li class="step-item"> Bake in the preheated oven for 12-15 minutes until the salmon is opaque and flakes easily with a fork. <button class="timer-button" data-time="15"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 7V12L15 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> 15:00</button> </li> <li class="step-item"> For a crispy top, broil on high for the final 2 minutes of cooking (optional). <button class="timer-button" data-time="2"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 7V12L15 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> 2:00</button> </li> </ol> <h2 class="section-title">Serving Suggestions</h2> <ol class="step-list" start="9"> <li class="step-item"> Let the salmon rest for 2-3 minutes before serving. </li> <li class="step-item"> Garnish with additional fresh herbs and a squeeze of lemon juice. </li> <li class="step-item"> Serve with a side of steamed asparagus and lemon herb quinoa for a complete meal. </li> </ol> <div class="recipe-tips"> <h3 class="tips-title">Chef's Tips</h3> <p>For the juiciest salmon, avoid overcooking. The fish should be slightly translucent in the center when you remove it from the oven as it will continue cooking from residual heat.</p> <p>Wild-caught salmon typically has better flavor but requires less cooking time than farm-raised.</p> </div> </div> <button class="flip-button"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M16 5L19 8L16 11" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M19 8H10C6.686 8 4 10.686 4 14C4 17.314 6.686 20 10 20H20" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> </div> </div> </div> <!-- Timer Modal --> <div class="timer-modal" id="timerModal"> <div class="timer-content"> <h2>Cooking Timer</h2> <div class="timer-display" id="timerDisplay">00:00</div> <div class="timer-controls"> <button class="timer-btn start-btn" id="startTimer">Start</button> <button class="timer-btn cancel-btn" id="cancelTimer">Cancel</button> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Flip card functionality const card = document.querySelector('.recipe-card'); const flipButtons = document.querySelectorAll('.flip-button'); flipButtons.forEach(button => { button.addEventListener('click', function() { card.classList.toggle('flipped'); }); }); // Timer functionality const timerButtons = document.querySelectorAll('.timer-button'); const timerModal = document.getElementById('timerModal'); const timerDisplay = document.getElementById('timerDisplay'); const startTimerBtn = document.getElementById('startTimer'); const cancelTimerBtn = document.getElementById('cancelTimer'); let timerInterval; let timerSeconds = 0; let isTimerRunning = false; timerButtons.forEach(button => { button.addEventListener('click', function() { const minutes = parseInt(this.dataset.time); timerSeconds = minutes * 60; updateTimerDisplay(); timerModal.classList.add('active'); }); }); cancelTimerBtn.addEventListener('click', function() { clearInterval(timerInterval); isTimerRunning = false; startTimerBtn.textContent = 'Start'; timerModal.classList.remove('active'); }); startTimerBtn.addEventListener('click', function() { if (isTimerRunning) { clearInterval(timerInterval); isTimerRunning = false; startTimerBtn.textContent = 'Resume'; } else { startTimer(); isTimerRunning = true; startTimerBtn.textContent = 'Pause'; } }); function startTimer() { timerInterval = setInterval(function() { if (timerSeconds > 0) { timerSeconds--; updateTimerDisplay(); } else { clearInterval(timerInterval); isTimerRunning = false; startTimerBtn.textContent = 'Start'; alert("Time's up!"); } }, 1000); } function updateTimerDisplay() { const minutes = Math.floor(timerSeconds / 60); const seconds = timerSeconds % 60; timerDisplay.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; } // Progress tracking const checkboxes = document.querySelectorAll('.ingredient-checkbox'); const stepItems = document.querySelectorAll('.step-item'); const progressCircle = document.getElementById('progress-circle'); const progressText = document.getElementById('progress-text'); const totalItems = checkboxes.length + stepItems.length; let completedItems = 0; function updateProgress() { completedItems = Array.from(checkboxes).filter(checkbox => checkbox.checked).length; const progress = Math.round((completedItems / totalItems) * 100); progressCircle.style.strokeDashoffset = 100 - progress; progressText.textContent = `${progress}%`; } checkboxes.forEach(checkbox => { checkbox.addEventListener('change', updateProgress); }); // Add ingredient hover animations const ingredientItems = document.querySelectorAll('.ingredient-item'); ingredientItems.forEach(item => { item.addEventListener('mouseenter', function() { this.style.transform = 'translateX(5px)'; }); item.addEventListener('mouseleave', function() { this.style.transform = 'translateX(0)'; }); }); // Add step hover animations stepItems.forEach(item => { item.addEventListener('mouseenter', function() { this.style.transform = 'translateY(-3px)'; }); item.addEventListener('mouseleave', function() { this.style.transform = 'translateY(0)'; }); }); // Initialize progress updateProgress(); // Prevent actual form submission document.addEventListener('submit', function(e) { e.preventDefault(); return false; }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Blogger's Favorite Recipe Card</title> <style> @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Poppins:wght@300;400;500;600&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } :root { --primary: #ff6b6b; --secondary: #f9d5bb; --accent: #67b26f; --text: #2d3436; --light: #f8f9fa; --shadow: rgba(0, 0, 0, 0.1); } body { font-family: 'Poppins', sans-serif; background-color: #f5f5f5; color: var(--text); display: flex; justify-content: center; align-items: center; min-height: 700px; overflow-x: hidden; padding: 20px; } .recipe-container { width: 100%; max-width: 650px; height: auto; max-height: 680px; overflow-y: auto; background: white; border-radius: 16px; box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1); position: relative; transition: transform 0.3s ease; scroll-behavior: smooth; } .recipe-container::-webkit-scrollbar { width: 6px; } .recipe-container::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; } .recipe-container::-webkit-scrollbar-thumb { background: var(--secondary); border-radius: 10px; } .recipe-header { position: relative; height: 280px; overflow: hidden; border-radius: 16px 16px 0 0; } .recipe-image { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; } .recipe-container:hover .recipe-image { transform: scale(1.05); } .recipe-overlay { position: absolute; bottom: 0; left: 0; right: 0; padding: 25px; background: linear-gradient(to top, rgba(0,0,0,0.8), transparent); color: white; } .recipe-title { font-family: 'Playfair Display', serif; font-size: 2.2rem; font-weight: 700; margin-bottom: 10px; text-shadow: 1px 1px 3px rgba(0,0,0,0.3); } .recipe-meta { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .recipe-author { display: flex; align-items: center; } .author-avatar { width: 35px; height: 35px; border-radius: 50%; margin-right: 10px; border: 2px solid white; } .author-name { font-size: 0.85rem; font-weight: 500; } .recipe-stats { display: flex; gap: 15px; } .stat { display: flex; align-items: center; font-size: 0.8rem; } .stat i { margin-right: 5px; font-size: 1rem; } .recipe-actions { position: absolute; top: 20px; right: 20px; display: flex; gap: 15px; } .action-btn { width: 40px; height: 40px; border-radius: 50%; background: white; display: flex; justify-content: center; align-items: center; cursor: pointer; box-shadow: 0 3px 6px rgba(0,0,0,0.1); transition: all 0.3s ease; } .action-btn:hover { transform: translateY(-3px); box-shadow: 0 5px 10px rgba(0,0,0,0.2); } .action-btn.saved { background: var(--accent); color: white; } .action-btn i { font-size: 1.2rem; color: var(--primary); } .action-btn.saved i { color: white; } .recipe-content { padding: 30px; } .recipe-tabs { display: flex; border-bottom: 1px solid #eee; margin-bottom: 25px; } .tab { padding: 10px 20px; font-weight: 500; cursor: pointer; position: relative; color: #999; transition: color 0.3s ease; } .tab.active { color: var(--primary); } .tab:after { content: ''; position: absolute; bottom: -1px; left: 0; width: 100%; height: 3px; background: var(--primary); transform: scaleX(0); transition: transform 0.3s ease; } .tab.active:after { transform: scaleX(1); } .tab-content { display: none; } .tab-content.active { display: block; animation: fadeIn 0.5s ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .ingredients-list { list-style: none; } .ingredient-item { padding: 10px 0; display: flex; align-items: center; border-bottom: 1px dashed #eee; } .ingredient-checkbox { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; border: 2px solid var(--secondary); border-radius: 5px; margin-right: 15px; position: relative; cursor: pointer; transition: all 0.2s ease; } .ingredient-checkbox:checked { background-color: var(--accent); border-color: var(--accent); } .ingredient-checkbox:checked:after { content: '✓'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-size: 12px; } .ingredient-checkbox:checked + .ingredient-text { text-decoration: line-through; color: #aaa; } .instructions-list { counter-reset: step-counter; list-style: none; } .instruction-item { position: relative; padding: 15px 0 15px 40px; border-bottom: 1px dashed #eee; } .instruction-item:before { content: counter(step-counter); counter-increment: step-counter; position: absolute; left: 0; top: 15px; width: 28px; height: 28px; background: var(--secondary); color: var(--text); border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: 600; font-size: 0.9rem; } .notes-content { background: #fffde7; padding: 20px; border-radius: 8px; font-style: italic; position: relative; } .notes-content:before { content: '"'; font-size: 60px; color: rgba(0,0,0,0.1); position: absolute; top: -10px; left: 10px; font-family: Georgia, serif; } .comment-section { margin-top: 30px; } .comment-form { display: flex; margin-bottom: 20px; } .comment-input { flex: 1; padding: 12px 15px; border: 1px solid #eee; border-radius: 30px; outline: none; transition: border 0.3s ease; font-family: 'Poppins', sans-serif; } .comment-input:focus { border-color: var(--primary); } .send-btn { background: var(--primary); color: white; border: none; width: 45px; height: 45px; border-radius: 50%; margin-left: 10px; cursor: pointer; transition: all 0.3s ease; display: flex; justify-content: center; align-items: center; } .send-btn:hover { background: #ff4757; transform: scale(1.05); } .comment-list { max-height: 200px; overflow-y: auto; } .comment { padding: 12px 15px; background: #f9f9f9; border-radius: 10px; margin-bottom: 10px; } .comment-author { font-weight: 600; font-size: 0.9rem; margin-bottom: 5px; display: flex; align-items: center; } .comment-author img { width: 25px; height: 25px; border-radius: 50%; margin-right: 8px; } .comment-time { font-size: 0.7rem; color: #999; margin-left: 10px; } .comment-text { font-size: 0.85rem; line-height: 1.5; } .tag { display: inline-block; padding: 5px 12px; background: var(--secondary); color: var(--text); border-radius: 30px; font-size: 0.75rem; margin-right: 8px; margin-bottom: 8px; transition: all 0.3s ease; } .tag:hover { background: var(--primary); color: white; transform: translateY(-2px); } .pulse-effect { animation: pulse 1.5s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } .hover-scale { transition: transform 0.3s ease; } .hover-scale:hover { transform: scale(1.03); } @media (max-width: 600px) { .recipe-title { font-size: 1.8rem; } .recipe-content { padding: 20px; } .tab { padding: 10px 15px; font-size: 0.9rem; } .recipe-header { height: 220px; } } /* SVG */ .feather { width: 20px; height: 20px; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; fill: none; } </style> </head> <body> <div class="recipe-container"> <div class="recipe-header"> <img src="https://images.unsplash.com/photo-1565958011703-44f9829ba187?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80" alt="Maple Bourbon Glazed Brussels Sprouts" class="recipe-image"> <div class="recipe-overlay"> <h1 class="recipe-title">Maple Bourbon Glazed Brussels Sprouts</h1> <div class="recipe-meta"> <div class="recipe-author"> <img src="https://i.pravatar.cc/150?img=32" alt="Olivia Green" class="author-avatar"> <span class="author-name">Olivia Green</span> </div> <div class="recipe-stats"> <div class="stat"> <svg class="feather" viewBox="0 0 24 24"> <circle cx="12" cy="12" r="10"></circle> <polyline points="12 6 12 12 16 14"></polyline> </svg> <span>30 min</span> </div> <div class="stat"> <svg class="feather" viewBox="0 0 24 24"> <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path> </svg> <span>1.2k</span> </div> </div> </div> </div> <div class="recipe-actions"> <div class="action-btn bookmark-btn"> <svg class="feather" viewBox="0 0 24 24"> <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path> </svg> </div> <div class="action-btn share-btn"> <svg class="feather" viewBox="0 0 24 24"> <circle cx="18" cy="5" r="3"></circle> <circle cx="6" cy="12" r="3"></circle> <circle cx="18" cy="19" r="3"></circle> <line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line> <line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line> </svg> </div> </div> </div> <div class="recipe-content"> <div class="recipe-tabs"> <div class="tab active" data-tab="ingredients">Ingredients</div> <div class="tab" data-tab="instructions">Instructions</div> <div class="tab" data-tab="notes">Chef's Notes</div> <div class="tab" data-tab="comments">Comments</div> </div> <div class="tab-content active" id="ingredients"> <ul class="ingredients-list"> <li class="ingredient-item hover-scale"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">1 lb Brussels sprouts, trimmed and halved</span> </li> <li class="ingredient-item hover-scale"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">2 tbsp olive oil</span> </li> <li class="ingredient-item hover-scale"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">3 tbsp maple syrup (pure, not pancake syrup)</span> </li> <li class="ingredient-item hover-scale"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">2 tbsp bourbon whiskey</span> </li> <li class="ingredient-item hover-scale"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">2 cloves garlic, minced</span> </li> <li class="ingredient-item hover-scale"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">2 tbsp apple cider vinegar</span> </li> <li class="ingredient-item hover-scale"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">1/4 tsp red pepper flakes (optional)</span> </li> <li class="ingredient-item hover-scale"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">Salt and freshly ground black pepper, to taste</span> </li> <li class="ingredient-item hover-scale"> <input type="checkbox" class="ingredient-checkbox"> <span class="ingredient-text">1/4 cup chopped toasted pecans for garnish</span> </li> </ul> <div style="margin-top: 20px"> <span class="tag">Fall Recipe</span> <span class="tag">Vegetarian</span> <span class="tag">Side Dish</span> <span class="tag">Thanksgiving</span> </div> </div> <div class="tab-content" id="instructions"> <ol class="instructions-list"> <li class="instruction-item"> Preheat your oven to 425°F (220°C). Line a baking sheet with parchment paper. </li> <li class="instruction-item"> In a large bowl, toss Brussels sprouts with olive oil, salt, and pepper. Spread them in a single layer on the prepared baking sheet, cut side down. </li> <li class="instruction-item"> Roast in the preheated oven for 20-25 minutes until the sprouts are crispy on the outside and tender on the inside, stirring halfway through. </li> <li class="instruction-item"> While the sprouts are roasting, prepare the glaze. In a small saucepan over medium heat, combine maple syrup, bourbon, garlic, and red pepper flakes (if using). Bring to a simmer and cook for about 3-4 minutes until slightly reduced. </li> <li class="instruction-item"> Remove from heat and stir in the apple cider vinegar. </li> <li class="instruction-item"> When the Brussels sprouts are done roasting, transfer them to a large bowl. Pour the maple bourbon glaze over them and toss to coat evenly. </li> <li class="instruction-item"> Sprinkle with toasted pecans, adjust seasoning if needed, and serve immediately. </li> </ol> </div> <div class="tab-content" id="notes"> <div class="notes-content"> <p>This recipe completely transformed how I feel about Brussels sprouts! The key is getting them really crispy in the oven before adding the glaze. If you're not a bourbon fan, you can substitute with apple juice, but you'll miss that wonderful depth of flavor.</p> <p style="margin-top: 15px">For an extra kick, try adding a tablespoon of whole grain mustard to the glaze. And if you want to make this ahead for a dinner party, roast the sprouts and prepare the glaze separately, then combine and reheat just before serving.</p> <p style="margin-top: 15px">Trust me, even Brussels sprout skeptics will be converted!</p> </div> </div> <div class="tab-content" id="comments"> <div class="comment-section"> <div class="comment-form"> <input type="text" class="comment-input" placeholder="Add a comment..."> <button class="send-btn"> <svg class="feather" viewBox="0 0 24 24"> <line x1="22" y1="2" x2="11" y2="13"></line> <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon> </svg> </button> </div> <div class="comment-list"> <div class="comment hover-scale"> <div class="comment-author"> <img src="https://i.pravatar.cc/150?img=44" alt="User"> <span>Maya Johnson</span> <span class="comment-time">2 days ago</span> </div> <div class="comment-text"> Made these for Thanksgiving and they were a hit! Even my father-in-law who hates vegetables asked for seconds. </div> </div> <div class="comment hover-scale"> <div class="comment-author"> <img src="https://i.pravatar.cc/150?img=68" alt="User"> <span>Jack Wilson</span> <span class="comment-time">5 days ago</span> </div> <div class="comment-text"> I subbed maple syrup with honey because that's what I had on hand. Still delicious! The bourbon adds such a nice flavor. </div> </div> <div class="comment hover-scale"> <div class="comment-author"> <img src="https://i.pravatar.cc/150?img=47" alt="User"> <span>Priya Patel</span> <span class="comment-time">1 week ago</span> </div> <div class="comment-text"> Perfect recipe! I added a tablespoon of Dijon mustard to the glaze as suggested in the notes and it was incredible. Will definitely make again. </div> </div> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Tab switching const tabs = document.querySelectorAll('.tab'); const tabContents = document.querySelectorAll('.tab-content'); tabs.forEach(tab => { tab.addEventListener('click', function() { const tabId = this.getAttribute('data-tab'); // Remove active class from all tabs tabs.forEach(t => t.classList.remove('active')); // Add active class to clicked tab this.classList.add('active'); // Hide all tab contents tabContents.forEach(content => content.classList.remove('active')); // Show the selected tab content document.getElementById(tabId).classList.add('active'); }); }); // Bookmark functionality const bookmarkBtn = document.querySelector('.bookmark-btn'); bookmarkBtn.addEventListener('click', function() { this.classList.toggle('saved'); if (this.classList.contains('saved')) { this.innerHTML = ` <svg class="feather" viewBox="0 0 24 24"> <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" fill="currentColor"></path> </svg> `; // Add pulse effect when saved this.classList.add('pulse-effect'); // Remove pulse effect after animation completes setTimeout(() => { this.classList.remove('pulse-effect'); }, 1500); } else { this.innerHTML = ` <svg class="feather" viewBox="0 0 24 24"> <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path> </svg> `; } }); // Share button functionality const shareBtn = document.querySelector('.share-btn'); shareBtn.addEventListener('click', function() { // Create a temporary popup with share options const sharePopup = document.createElement('div'); sharePopup.style.position = 'absolute'; sharePopup.style.top = '80px'; sharePopup.style.right = '20px'; sharePopup.style.background = 'white'; sharePopup.style.padding = '15px'; sharePopup.style.borderRadius = '8px'; sharePopup.style.boxShadow = '0 5px 15px rgba(0,0,0,0.1)'; sharePopup.style.zIndex = '100'; sharePopup.style.width = '180px'; sharePopup.innerHTML = ` <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px; cursor: pointer"> <svg width="20" height="20" viewBox="0 0 24 24" fill="#3b5998"> <path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path> </svg> <span>Facebook</span> </div> <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px; cursor: pointer"> <svg width="20" height="20" viewBox="0 0 24 24" fill="#1DA1F2"> <path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path> </svg> <span>Twitter</span> </div> <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px; cursor: pointer"> <svg width="20" height="20" viewBox="0 0 24 24" fill="#0077B5"> <path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path> <rect x="2" y="9" width="4" height="12"></rect> <circle cx="4" cy="4" r="2"></circle> </svg> <span>LinkedIn</span> </div> <div style="display: flex; align-items: center; gap: 10px; cursor: pointer"> <svg width="20" height="20" viewBox="0 0 24 24" fill="#3b5998"> <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect> <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path> </svg> <span>Copy Link</span> </div> `; document.querySelector('.recipe-header').appendChild(sharePopup); // Close share popup when clicking elsewhere document.addEventListener('click', function closePopup(e) { if (!sharePopup.contains(e.target) && e.target !== shareBtn) { sharePopup.remove(); document.removeEventListener('click', closePopup); } }); }); // Comment functionality const commentForm = document.querySelector('.comment-form'); const commentInput = document.querySelector('.comment-input'); const commentList = document.querySelector('.comment-list'); commentForm.addEventListener('submit', function(e) { e.preventDefault(); }); document.querySelector('.send-btn').addEventListener('click', function() { if (commentInput.value.trim() !== '') { addComment(commentInput.value); commentInput.value = ''; } }); commentInput.addEventListener('keypress', function(e) { if (e.key === 'Enter' && commentInput.value.trim() !== '') { addComment(commentInput.value); commentInput.value = ''; } }); function addComment(text) { const newComment = document.createElement('div'); newComment.className = 'comment hover-scale'; // Get random avatar from pravatar const randomNum = Math.floor(Math.random() * 70); newComment.innerHTML = ` <div class="comment-author"> <img src="https://i.pravatar.cc/150?img=${randomNum}" alt="User"> <span>You</span> <span class="comment-time">Just now</span> </div> <div class="comment-text"> ${text} </div> `; // Add with animation newComment.style.opacity = '0'; newComment.style.transform = 'translateY(10px)'; commentList.prepend(newComment); // Trigger animation setTimeout(() => { newComment.style.transition = 'all 0.3s ease'; newComment.style.opacity = '1'; newComment.style.transform = 'translateY(0)'; }, 10); } }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Smart Kitchen Recipe Card</title> <style> :root { --primary: #4F7942; --secondary: #F68E5F; --accent: #FFD166; --light: #F8F9FA; --dark: #343a40; --shadow: 0 4px 6px rgba(0, 0, 0, 0.1); --radius: 12px; --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f7f9fc; color: var(--dark); display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 20px; overflow-x: hidden; } .recipe-card { background: white; width: 100%; max-width: 680px; height: 680px; border-radius: var(--radius); box-shadow: var(--shadow); display: flex; flex-direction: column; overflow: hidden; position: relative; transition: var(--transition); } .recipe-header { padding: 20px; background: linear-gradient(45deg, var(--primary), #2D6A4F); color: white; display: flex; justify-content: space-between; align-items: center; } .recipe-title h1 { font-size: 1.6rem; margin-bottom: 5px; } .recipe-title p { font-size: 0.9rem; opacity: 0.9; } .voice-command { display: flex; align-items: center; background: rgba(255, 255, 255, 0.2); padding: 8px 12px; border-radius: 30px; cursor: pointer; transition: var(--transition); } .voice-command:hover { background: rgba(255, 255, 255, 0.3); transform: translateY(-2px); } .voice-command svg { margin-right: 8px; } .recipe-content { display: flex; height: calc(100% - 90px); overflow: hidden; } .recipe-sidebar { width: 180px; background: #f1f3f5; padding: 20px; overflow-y: auto; border-right: 1px solid #e9ecef; } .ingredients-title { font-size: 1rem; font-weight: 600; margin-bottom: 15px; display: flex; align-items: center; } .ingredients-title svg { margin-right: 8px; } .ingredient-item { display: flex; align-items: center; margin-bottom: 15px; padding: 8px; border-radius: 8px; cursor: pointer; transition: var(--transition); } .ingredient-item:hover { background: white; box-shadow: 0 2px 5px rgba(0,0,0,0.05); } .ingredient-icon { width: 28px; height: 28px; border-radius: 50%; background: var(--secondary); display: flex; align-items: center; justify-content: center; margin-right: 10px; color: white; } .ingredient-details { font-size: 0.85rem; } .ingredient-amount { font-weight: 600; margin-top: 3px; color: var(--primary); font-size: 0.8rem; } .recipe-steps { flex: 1; padding: 20px; overflow-y: auto; } .steps-title { font-size: 1rem; font-weight: 600; margin-bottom: 20px; display: flex; align-items: center; } .steps-title svg { margin-right: 8px; } .step-item { margin-bottom: 20px; position: relative; padding: 15px; border-radius: var(--radius); background: white; box-shadow: 0 2px 8px rgba(0,0,0,0.05); transition: var(--transition); border-left: 3px solid var(--primary); } .step-item:hover { box-shadow: 0 5px 15px rgba(0,0,0,0.1); transform: translateY(-2px); } .step-number { position: absolute; top: -10px; left: -10px; width: 25px; height: 25px; background: var(--primary); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.75rem; font-weight: bold; } .step-content { margin-bottom: 10px; } .step-tooltip { background: var(--light); padding: 8px 12px; border-radius: 8px; font-size: 0.8rem; color: var(--dark); opacity: 0.9; display: flex; align-items: center; margin-top: 10px; } .step-tooltip svg { margin-right: 8px; min-width: 14px; color: var(--secondary); } .voice-tip { display: inline-flex; align-items: center; background: rgba(79, 121, 66, 0.1); padding: 5px 8px; border-radius: 4px; font-size: 0.75rem; margin-top: 8px; color: var(--primary); cursor: pointer; transition: var(--transition); } .voice-tip:hover { background: rgba(79, 121, 66, 0.2); } .voice-tip svg { margin-right: 4px; min-width: 12px; } .modal { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); display: flex; align-items: center; justify-content: center; opacity: 0; visibility: hidden; transition: var(--transition); z-index: 100; } .modal.active { opacity: 1; visibility: visible; } .modal-content { background: white; width: 90%; max-width: 400px; border-radius: var(--radius); padding: 25px; transform: translateY(20px); transition: transform 0.3s ease; } .modal.active .modal-content { transform: translateY(0); } .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #e9ecef; } .modal-title { font-size: 1.2rem; font-weight: 600; color: var(--dark); } .close-modal { background: none; border: none; font-size: 1.5rem; cursor: pointer; color: var(--dark); transition: var(--transition); } .close-modal:hover { color: var(--secondary); } .modal-body { margin-bottom: 20px; } .modal-body p { margin-bottom: 10px; line-height: 1.5; } .nutrient-info { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 15px; } .nutrient-item { flex: 1; min-width: calc(50% - 10px); background: #f8f9fa; padding: 10px; border-radius: 8px; text-align: center; } .nutrient-value { font-size: 1.1rem; font-weight: 600; color: var(--primary); } .nutrient-label { font-size: 0.75rem; color: var(--dark); opacity: 0.8; } .timer-control { display: flex; align-items: center; gap: 15px; margin-top: 10px; } .timer-display { font-size: 1.2rem; font-weight: 600; color: var(--primary); background: #f1f3f5; padding: 8px 15px; border-radius: 8px; min-width: 80px; text-align: center; } .timer-btn { background: var(--primary); color: white; border: none; border-radius: 8px; padding: 8px 15px; cursor: pointer; transition: var(--transition); display: flex; align-items: center; justify-content: center; } .timer-btn:hover { background: #3D5C33; } .timer-btn svg { margin-right: 5px; } .voice-feedback { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); background: rgba(52, 58, 64, 0.9); color: white; padding: 10px 20px; border-radius: 30px; font-size: 0.9rem; opacity: 0; transition: opacity 0.3s ease; } .voice-feedback.active { opacity: 1; animation: fadeInOut 3s forwards; } @keyframes fadeInOut { 0% { opacity: 0; } 20% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; } } .pulse { animation: pulse 1.5s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @media (max-width: 700px) { .recipe-content { flex-direction: column; height: calc(100% - 90px); } .recipe-sidebar { width: 100%; height: 120px; overflow-x: auto; overflow-y: hidden; display: flex; flex-direction: row; border-right: none; border-bottom: 1px solid #e9ecef; padding: 10px; } .ingredients-list { display: flex; flex-direction: row; } .ingredients-title { display: none; } .ingredient-item { min-width: 120px; margin-right: 10px; } .recipe-steps { height: calc(100% - 120px); } } </style> </head> <body> <div class="recipe-card"> <div class="recipe-header"> <div class="recipe-title"> <h1>Garlic Butter Shrimp Pasta</h1> <p>Ready in 20 minutes • 4 servings</p> </div> <div class="voice-command" id="activate-voice"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path> <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path> <line x1="12" y1="19" x2="12" y2="23"></line> <line x1="8" y1="23" x2="16" y2="23"></line> </svg> Voice Commands </div> </div> <div class="recipe-content"> <div class="recipe-sidebar"> <div class="ingredients-title"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="8" y1="6" x2="21" y2="6"></line> <line x1="8" y1="12" x2="21" y2="12"></line> <line x1="8" y1="18" x2="21" y2="18"></line> <line x1="3" y1="6" x2="3.01" y2="6"></line> <line x1="3" y1="12" x2="3.01" y2="12"></line> <line x1="3" y1="18" x2="3.01" y2="18"></line> </svg> Ingredients </div> <div class="ingredients-list"> <div class="ingredient-item" data-ingredient="shrimp"> <div class="ingredient-icon">🦐</div> <div class="ingredient-details"> <div>Shrimp</div> <div class="ingredient-amount">1 lb</div> </div> </div> <div class="ingredient-item" data-ingredient="pasta"> <div class="ingredient-icon">🍝</div> <div class="ingredient-details"> <div>Linguine</div> <div class="ingredient-amount">8 oz</div> </div> </div> <div class="ingredient-item" data-ingredient="butter"> <div class="ingredient-icon">🧈</div> <div class="ingredient-details"> <div>Butter</div> <div class="ingredient-amount">4 tbsp</div> </div> </div> <div class="ingredient-item" data-ingredient="garlic"> <div class="ingredient-icon">🧄</div> <div class="ingredient-details"> <div>Garlic</div> <div class="ingredient-amount">4 cloves</div> </div> </div> <div class="ingredient-item" data-ingredient="lemon"> <div class="ingredient-icon">🍋</div> <div class="ingredient-details"> <div>Lemon</div> <div class="ingredient-amount">1 whole</div> </div> </div> <div class="ingredient-item" data-ingredient="parsley"> <div class="ingredient-icon">🌿</div> <div class="ingredient-details"> <div>Parsley</div> <div class="ingredient-amount">¼ cup</div> </div> </div> </div> </div> <div class="recipe-steps"> <div class="steps-title"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="8" y1="19" x2="8" y2="21"></line> <line x1="8" y1="13" x2="8" y2="15"></line> <line x1="16" y1="19" x2="16" y2="21"></line> <line x1="16" y1="13" x2="16" y2="15"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="12" y1="15" x2="12" y2="17"></line> <path d="M20 16.58A5 5 0 0 0 18 7h-1.26A8 8 0 1 0 4 15.25"></path> </svg> Preparation Steps </div> <div class="step-item"> <div class="step-number">1</div> <div class="step-content"> Bring a large pot of salted water to a boil. Cook linguine according to package instructions until al dente. </div> <div class="step-tooltip"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="16" x2="12" y2="12"></line> <line x1="12" y1="8" x2="12.01" y2="8"></line> </svg> Reserve ½ cup of pasta water before draining. </div> <div class="voice-tip" data-tip="pasta-cooking"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path> <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path> <line x1="12" y1="19" x2="12" y2="23"></line> <line x1="8" y1="23" x2="16" y2="23"></line> </svg> Voice tip: "Set pasta timer" </div> </div> <div class="step-item"> <div class="step-number">2</div> <div class="step-content"> While pasta is cooking, peel and devein shrimp. Pat dry with paper towels and season with salt and pepper. </div> <div class="step-tooltip"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="16" x2="12" y2="12"></line> <line x1="12" y1="8" x2="12.01" y2="8"></line> </svg> Make sure shrimp are completely dry to ensure proper browning. </div> <div class="voice-tip" data-tip="shrimp-prep"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path> <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path> <line x1="12" y1="19" x2="12" y2="23"></line> <line x1="8" y1="23" x2="16" y2="23"></line> </svg> Voice tip: "Show me how to devein shrimp" </div> </div> <div class="step-item"> <div class="step-number">3</div> <div class="step-content"> In a large skillet, melt 2 tablespoons of butter over medium-high heat. Add shrimp and cook until opaque and slightly golden, about 1-2 minutes per side. </div> <div class="step-tooltip"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="16" x2="12" y2="12"></line> <line x1="12" y1="8" x2="12.01" y2="8"></line> </svg> Don't overcrowd the pan - cook in batches if needed. </div> <div class="voice-tip" data-tip="shrimp-cooking"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path> <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path> <line x1="12" y1="19" x2="12" y2="23"></line> <line x1="8" y1="23" x2="16" y2="23"></line> </svg> Voice tip: "Set timer for shrimp" </div> </div> <div class="step-item"> <div class="step-number">4</div> <div class="step-content"> Remove shrimp to a plate. In the same skillet, add remaining butter and minced garlic. Cook until fragrant, about 30 seconds. </div> <div class="step-tooltip"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="16" x2="12" y2="12"></line> <line x1="12" y1="8" x2="12.01" y2="8"></line> </svg> Be careful not to burn the garlic - it should turn golden, not brown. </div> <div class="voice-tip" data-tip="garlic-cooking"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path> <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path> <line x1="12" y1="19" x2="12" y2="23"></line> <line x1="8" y1="23" x2="16" y2="23"></line> </svg> Voice tip: "When is garlic done?" </div> </div> <div class="step-item"> <div class="step-number">5</div> <div class="step-content"> Add lemon juice, zest, and 1/4 cup of reserved pasta water. Return shrimp to the skillet, add drained pasta, and toss to combine. </div> <div class="step-tooltip"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="16" x2="12" y2="12"></line> <line x1="12" y1="8" x2="12.01" y2="8"></line> </svg> Add more pasta water if sauce is too thick. </div> <div class="voice-tip" data-tip="sauce-consistency"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path> <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path> <line x1="12" y1="19" x2="12" y2="23"></line> <line x1="8" y1="23" x2="16" y2="23"></line> </svg> Voice tip: "Right pasta sauce consistency" </div> </div> <div class="step-item"> <div class="step-number">6</div> <div class="step-content"> Garnish with chopped parsley, red pepper flakes (optional), and serve immediately with extra lemon wedges. </div> <div class="step-tooltip"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="16" x2="12" y2="12"></line> <line x1="12" y1="8" x2="12.01" y2="8"></line> </svg> Drizzle with olive oil for extra richness if desired. </div> <div class="voice-tip" data-tip="plating"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path> <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path> <line x1="12" y1="19" x2="12" y2="23"></line> <line x1="8" y1="23" x2="16" y2="23"></line> </svg> Voice tip: "Show me plating ideas" </div> </div> </div> </div> <div class="voice-feedback" id="voice-feedback"> Listening... </div> <!-- Ingredient Modals --> <div class="modal" id="ingredient-modal"> <div class="modal-content"> <div class="modal-header"> <div class="modal-title" id="ingredient-title">Ingredient Details</div> <button class="close-modal">×</button> </div> <div class="modal-body" id="ingredient-details"> <!-- Content will be dynamically inserted --> </div> </div> </div> <!-- Timer Modal --> <div class="modal" id="timer-modal"> <div class="modal-content"> <div class="modal-header"> <div class="modal-title">Kitchen Timer</div> <button class="close-modal">×</button> </div> <div class="modal-body"> <p>Set a timer for your cooking step:</p> <div class="timer-control"> <div class="timer-display" id="timer-display">00:00</div> <button class="timer-btn" id="timer-start"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polygon points="5 3 19 12 5 21 5 3"></polygon> </svg> Start </button> <button class="timer-btn" id="timer-reset"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M3 2v6h6"></path> <path d="M21 12A9 9 0 0 0 6 5.3L3 8"></path> <path d="M21 22v-6h-6"></path> <path d="M3 12a9 9 0 0 0 15 6.7l3-2.7"></path> </svg> Reset </button> </div> </div> </div> </div> <!-- Voice Tips Modal --> <div class="modal" id="voice-tip-modal"> <div class="modal-content"> <div class="modal-header"> <div class="modal-title" id="tip-title">Voice Tip</div> <button class="close-modal">×</button> </div> <div class="modal-body" id="tip-content"> <!-- Content will be dynamically inserted --> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Ingredient details modal const ingredientModal = document.getElementById('ingredient-modal'); const ingredientTitle = document.getElementById('ingredient-title'); const ingredientDetails = document.getElementById('ingredient-details'); const ingredientItems = document.querySelectorAll('.ingredient-item'); // Timer modal and functionality const timerModal = document.getElementById('timer-modal'); const timerDisplay = document.getElementById('timer-display'); const timerStartBtn = document.getElementById('timer-start'); const timerResetBtn = document.getElementById('timer-reset'); // Voice tip modal const voiceTipModal = document.getElementById('voice-tip-modal'); const tipTitle = document.getElementById('tip-title'); const tipContent = document.getElementById('tip-content'); const voiceTips = document.querySelectorAll('.voice-tip'); // Voice feedback element const voiceFeedback = document.getElementById('voice-feedback'); const activateVoice = document.getElementById('activate-voice'); // Close buttons for all modals const closeButtons = document.querySelectorAll('.close-modal'); // Ingredient data const ingredientData = { 'shrimp': { name: 'Shrimp', amount: '1 pound (450g)', details: 'Look for medium to large shrimp (16-20 count). Fresh is best, but frozen and thawed works well too.', tips: 'Pat dry thoroughly before cooking to get a nice sear. Avoid overcooking as they become rubbery.', nutrients: [ { label: 'Protein', value: '24g' }, { label: 'Fat', value: '1.7g' }, { label: 'Carbs', value: '0g' }, { label: 'Calories', value: '120' } ] }, 'pasta': { name: 'Linguine Pasta', amount: '8 ounces (225g)', details: 'Linguine is ideal for this dish, but fettuccine or spaghetti can be substituted.', tips: 'Cook until al dente - firm to the bite. Reserve some pasta water to help bind the sauce.', nutrients: [ { label: 'Protein', value: '7g' }, { label: 'Fat', value: '1g' }, { label: 'Carbs', value: '43g' }, { label: 'Calories', value: '210' } ] }, 'butter': { name: 'Unsalted Butter', amount: '4 tablespoons (56g)', details: 'Use unsalted butter to control the sodium content. High-quality butter makes a difference in flavor.', tips: 'For a nuttier flavor, let the butter brown slightly before adding garlic.', nutrients: [ { label: 'Protein', value: '0g' }, { label: 'Fat', value: '11g' }, { label: 'Carbs', value: '0g' }, { label: 'Calories', value: '100' } ] }, 'garlic': { name: 'Fresh Garlic', amount: '4 cloves (12g)', details: 'Fresh garlic provides the best flavor. Mince finely for even distribution in the sauce.', tips: 'Let minced garlic rest for 10 minutes before cooking to enhance its health benefits.', nutrients: [ { label: 'Protein', value: '0.6g' }, { label: 'Fat', value: '0g' }, { label: 'Carbs', value: '3g' }, { label: 'Calories', value: '15' } ] }, 'lemon': { name: 'Fresh Lemon', amount: '1 whole lemon', details: 'You\'ll need both the juice (about 2-3 tbsp) and the zest (about 1 tsp) from one medium lemon.', tips: 'Zest before juicing. Roll the lemon on the counter with firm pressure before cutting to extract more juice.', nutrients: [ { label: 'Vitamin C', value: '53mg' }, { label: 'Potassium', value: '116mg' }, { label: 'Carbs', value: '5g' }, { label: 'Calories', value: '20' } ] }, 'parsley': { name: 'Fresh Parsley
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Family Recipe Card</title> <style> @import url('https://fonts.googleapis.com/css2?family=Caveat:wght@400;700&family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Roboto:wght@300;400&display=swap'); :root { --primary-color: #f7e9d7; --secondary-color: #f3d2c1; --accent-color: #8bd3dd; --text-color: #3d3d3d; --highlight-color: #e98a15; --white: #ffffff; --shadow: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Roboto', sans-serif; background-color: #f8f5f2; background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='%23e5d6ca' fill-opacity='0.2' fill-rule='evenodd'/%3E%3C/svg%3E"); color: var(--text-color); display: flex; justify-content: center; align-items: center; min-height: 700px; overflow: hidden; position: relative; } .container { width: 100%; max-width: 700px; height: 700px; padding: 20px; position: relative; overflow: hidden; display: flex; flex-direction: column; justify-content: center; align-items: center; } .scrapbook { width: 100%; max-width: 650px; height: 650px; background-color: var(--primary-color); border-radius: 15px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); padding: 25px; position: relative; overflow: hidden; transform-style: preserve-3d; transform: perspective(1000px); transition: transform 0.5s ease; } .recipe-cards { width: 100%; height: 100%; position: relative; perspective: 1000px; } .recipe-card { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; transform-style: preserve-3d; transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275); padding: 20px; display: flex; flex-direction: column; justify-content: flex-start; align-items: center; background-color: var(--white); border-radius: 10px; box-shadow: 0 5px 15px var(--shadow); opacity: 0; pointer-events: none; } .recipe-card.active { opacity: 1; transform: rotateY(0deg); pointer-events: all; z-index: 10; } .recipe-card.prev { transform: rotateY(-180deg); opacity: 0; } .recipe-card.next { transform: rotateY(180deg); opacity: 0; } .recipe-header { width: 100%; margin-bottom: 20px; text-align: center; position: relative; } .recipe-title { font-family: 'Playfair Display', serif; font-size: 2.2rem; color: var(--highlight-color); margin-bottom: 5px; text-decoration: underline; text-decoration-style: wavy; text-decoration-color: var(--accent-color); letter-spacing: 1px; } .recipe-subtitle { font-family: 'Caveat', cursive; font-size: 1.2rem; color: var(--text-color); font-weight: normal; margin-bottom: 10px; } .polaroid { background: var(--white); padding: 15px 15px 40px 15px; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); transform: rotate(-3deg); margin: 15px auto; position: relative; transition: transform 0.3s ease; max-width: 80%; cursor: pointer; } .polaroid:hover { transform: rotate(0deg) scale(1.03); box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15); } .polaroid::after { content: ""; position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%); width: 80%; height: 2px; background-color: var(--accent-color); } .photo { width: 100%; height: 180px; object-fit: cover; border-radius: 3px; } .photo-caption { font-family: 'Caveat', cursive; text-align: center; margin-top: 10px; font-size: 1.1rem; color: var(--text-color); } .recipe-content { display: flex; width: 100%; margin-top: 15px; } .ingredients { flex: 1; padding: 10px; background-color: var(--secondary-color); border-radius: 8px; margin-right: 10px; position: relative; overflow: hidden; } .ingredients::before { content: ""; position: absolute; top: 0; right: 0; width: 30px; height: 30px; background-color: var(--primary-color); border-bottom-left-radius: 30px; z-index: 1; } .instructions { flex: 1.5; padding: 10px; background-color: var(--primary-color); border-radius: 8px; position: relative; } .content-title { font-family: 'Playfair Display', serif; font-size: 1.2rem; margin-bottom: 10px; text-align: center; color: var(--highlight-color); } ul, ol { padding-left: 20px; margin-bottom: 10px; } ul li, ol li { margin-bottom: 5px; font-size: 0.9rem; line-height: 1.4; } .memory-bubble { position: absolute; right: -20px; bottom: 20px; width: 120px; height: 120px; background-color: var(--accent-color); border-radius: 50%; display: flex; justify-content: center; align-items: center; transform: rotate(12deg); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); opacity: 0; transition: all 0.5s ease; cursor: pointer; overflow: hidden; } .memory-bubble.show { opacity: 1; right: 20px; transform: rotate(5deg); } .memory-content { font-family: 'Caveat', cursive; font-size: 0.9rem; color: var(--text-color); text-align: center; padding: 10px; transition: transform 0.3s ease; } .memory-bubble:hover .memory-content { transform: scale(1.1); } .story-layer { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.95); display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 30px; opacity: 0; pointer-events: none; transition: opacity 0.5s ease; z-index: 20; } .story-layer.active { opacity: 1; pointer-events: all; } .story-content { max-width: 80%; background-color: var(--white); padding: 30px; border-radius: 10px; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1); position: relative; transform: scale(0.9); transition: transform 0.5s ease; } .story-layer.active .story-content { transform: scale(1); } .story-title { font-family: 'Playfair Display', serif; font-size: 1.8rem; color: var(--highlight-color); margin-bottom: 15px; text-align: center; } .story-text { font-family: 'Roboto', sans-serif; font-size: 1rem; line-height: 1.6; margin-bottom: 20px; } .close-story { position: absolute; top: 15px; right: 15px; width: 30px; height: 30px; background: var(--accent-color); border-radius: 50%; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: background-color 0.3s ease, transform 0.3s ease; } .close-story:hover { background-color: var(--highlight-color); transform: rotate(90deg); } .close-story::before, .close-story::after { content: ""; position: absolute; width: 15px; height: 2px; background-color: var(--white); } .close-story::before { transform: rotate(45deg); } .close-story::after { transform: rotate(-45deg); } .navigation { position: absolute; bottom: 20px; display: flex; justify-content: space-between; width: 80%; z-index: 15; } .nav-btn { background-color: var(--accent-color); color: var(--white); border: none; width: 50px; height: 50px; border-radius: 50%; cursor: pointer; display: flex; justify-content: center; align-items: center; font-size: 1.5rem; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); transition: transform 0.3s ease, background-color 0.3s ease; } .nav-btn:hover { transform: scale(1.1); background-color: var(--highlight-color); } .nav-btn:disabled { background-color: #ccc; cursor: not-allowed; transform: scale(1); } .nav-dots { display: flex; justify-content: center; align-items: center; } .dot { width: 12px; height: 12px; border-radius: 50%; background-color: var(--secondary-color); margin: 0 5px; cursor: pointer; transition: transform 0.3s ease, background-color 0.3s ease; } .dot.active { background-color: var(--highlight-color); transform: scale(1.2); } .dot:hover { transform: scale(1.2); } .hand-drawn { position: absolute; font-family: 'Caveat', cursive; color: var(--highlight-color); transform: rotate(-5deg); z-index: 5; } .doodle { position: absolute; opacity: 0.7; z-index: 2; } .doodle-1 { top: 10px; right: 20px; width: 60px; height: 50px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' width='100' height='100' fill='none' stroke='%23e98a15' stroke-width='2'%3E%3Cpath d='M20,50 Q35,20 50,50 Q65,80 80,50' stroke-linecap='round'/%3E%3Cpath d='M30,60 Q50,40 70,60' stroke-linecap='round'/%3E%3C/svg%3E"); background-size: contain; background-repeat: no-repeat; } .doodle-2 { bottom: 30px; left: 20px; width: 40px; height: 40px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' width='100' height='100' fill='none' stroke='%238bd3dd' stroke-width='2'%3E%3Cpath d='M30,30 L70,70 M30,70 L70,30' stroke-linecap='round'/%3E%3Ccircle cx='50' cy='50' r='30' stroke-dasharray='5,5'/%3E%3C/svg%3E"); background-size: contain; background-repeat: no-repeat; } .tape { position: absolute; background-color: rgba(255, 255, 255, 0.6); transform: rotate(var(--rotation, 0deg)); box-shadow: 0 1px 5px rgba(0, 0, 0, 0.05); z-index: 3; } .tape-1 { top: 5px; left: 40%; width: 80px; height: 25px; --rotation: -5deg; } .tape-2 { right: 40px; bottom: 50px; width: 60px; height: 20px; --rotation: 10deg; } .washi-tape { position: absolute; height: 15px; background: linear-gradient(to right, var(--accent-color) 30%, var(--highlight-color) 30%, var(--highlight-color) 70%, var(--accent-color) 70%); opacity: 0.8; transform: rotate(var(--rotation, 0deg)); z-index: 2; } .washi-1 { top: 20px; left: 10px; width: 100px; --rotation: -10deg; } .washi-2 { bottom: 40px; right: 10px; width: 120px; --rotation: 5deg; } @media (max-width: 600px) { .scrapbook { padding: 15px; } .recipe-card { padding: 15px; } .recipe-title { font-size: 1.8rem; } .recipe-content { flex-direction: column; } .ingredients { margin-right: 0; margin-bottom: 10px; } .polaroid { padding: 10px 10px 30px 10px; max-width: 90%; } .photo { height: 150px; } .memory-bubble { width: 100px; height: 100px; right: 10px; bottom: 10px; } .memory-bubble.show { right: 10px; } .story-content { max-width: 95%; padding: 20px; } .story-title { font-size: 1.5rem; } .navigation { width: 90%; } } /* Animation classes */ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes recipeFloat { 0%, 100% { transform: translateY(0) rotate(var(--rotation, 0deg)); } 50% { transform: translateY(-10px) rotate(var(--rotation, 0deg)); } } .fade-in { animation: fadeIn 0.5s ease forwards; } .float { animation: recipeFloat 5s ease-in-out infinite; } .scratch { position: relative; } .scratch::before { content: ""; position: absolute; width: 100%; height: 3px; background-color: var(--accent-color); bottom: -2px; left: 0; transform: scaleX(0); transform-origin: left; transition: transform 0.3s ease; } .recipe-card:hover .scratch::before { transform: scaleX(1); } /* Paper texture */ .paper-texture { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100' height='100' filter='url(%23noise)' opacity='0.05'/%3E%3C/svg%3E"); opacity: 0.3; pointer-events: none; z-index: 1; } </style> </head> <body> <div class="container"> <div class="scrapbook"> <div class="washi-tape washi-1"></div> <div class="washi-tape washi-2"></div> <div class="tape tape-1"></div> <div class="tape tape-2"></div> <div class="doodle doodle-1"></div> <div class="doodle doodle-2"></div> <div class="recipe-cards"> <!-- Recipe Card 1: Grandma's Apple Pie --> <div class="recipe-card active"> <div class="paper-texture"></div> <div class="recipe-header"> <h1 class="recipe-title">Grandma's Apple Pie</h1> <h2 class="recipe-subtitle">A treasured recipe passed down four generations</h2> </div> <div class="polaroid"> <img src="https://images.unsplash.com/photo-1621743478914-cc8a86d7e7b5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" alt="Homemade Apple Pie" class="photo"> <p class="photo-caption">Thanksgiving 1988, Grandma's kitchen</p> </div> <div class="recipe-content"> <div class="ingredients"> <h3 class="content-title">Ingredients</h3> <ul> <li class="scratch">2 cups flour, sifted</li> <li>1 tsp salt</li> <li>⅔ cup shortening</li> <li>5-6 tbsp cold water</li> <li>8 cups thinly sliced apples</li> <li>¾ cup sugar</li> <li>2 tbsp cinnamon</li> <li>2 tbsp butter</li> </ul> </div> <div class="instructions"> <h3 class="content-title">Instructions</h3> <ol> <li>Mix flour and salt, cut in shortening until pieces are pea-sized</li> <li>Sprinkle with water, toss with fork until moist</li> <li>Form into ball, divide in half, roll out on floured surface</li> <li>Line 9" pie plate with bottom crust</li> <li>Mix apples, sugar, cinnamon; pour into crust</li> <li>Dot with butter, cover with top crust, seal edges</li> <li>Cut slits in top, bake at 425°F for 40-45 minutes</li> </ol> </div> </div> <div class="memory-bubble"> <div class="memory-content">Click for Grandma's secret!</div> </div> <div class="story-layer"> <div class="story-content"> <div class="close-story"></div> <h3 class="story-title">The Secret to Grandma's Perfect Crust</h3> <p class="story-text">Every Sunday after church, Grandma Rose would make her famous apple pie. She'd always say "the secret's in the crust!" What she didn't tell everyone was that she'd replace 2 tablespoons of the water with apple cider vinegar. She claimed it made the crust flakier without any vinegar taste.</p> <p class="story-text">During the Great Depression, she won a county fair baking contest with this pie, which helped the family through hard times when they sold slices at local markets. To this day, no Thanksgiving is complete without recreating her recipe exactly as written in her flowery handwriting in the family cookbook.</p> </div> </div> </div> <!-- Recipe Card 2: Uncle Tony's Spaghetti Sauce --> <div class="recipe-card next"> <div class="paper-texture"></div> <div class="recipe-header"> <h1 class="recipe-title">Uncle Tony's Sunday Sauce</h1> <h2 class="recipe-subtitle">The all-day Italian gravy that brings the family together</h2> </div> <div class="polaroid"> <img src="https://images.unsplash.com/photo-1627042633145-b780d842ba25?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" alt="Italian Tomato Sauce" class="photo"> <p class="photo-caption">Uncle Tony stirring the pot, summer 1975</p> </div> <div class="recipe-content"> <div class="ingredients"> <h3 class="content-title">Ingredients</h3> <ul> <li>¼ cup olive oil</li> <li>1 lb Italian sausage</li> <li>1 lb meatballs (homemade)</li> <li>1 large onion, diced</li> <li>6 cloves garlic, minced</li> <li>2 cans San Marzano tomatoes</li> <li>1 small can tomato paste</li> <li>2 bay leaves</li> <li>Basil, parsley, salt, pepper</li> </ul> </div> <div class="instructions"> <h3 class="content-title">Instructions</h3> <ol> <li>Brown sausage and meatballs in olive oil, remove</li> <li>Sauté onions until translucent, add garlic</li> <li>Add tomatoes, paste, and herbs</li> <li>Return meat to pot, bring to simmer</li> <li>Reduce heat to lowest setting</li> <li>Simmer for at least 4 hours, stirring occasionally</li> <li>Remove bay leaves before serving</li> <li>Serve over pasta with grated pecorino</li> </ol> </div> </div> <div class="memory-bubble"> <div class="memory-content">Uncle Tony's ritual</div> </div> <div class="story-layer"> <div class="story-content"> <div class="close-story"></div> <h3 class="story-title">The Sunday Ritual</h3> <p class="story-text">Every Sunday at exactly 7am, Uncle Tony would start his sauce. He'd sing old Neapolitan songs while cooking, claiming the sauce could hear him and would taste better for it. No one was allowed to lift the lid except him—he'd say "you let the spirit out!" if anyone tried.</p> <p class="story-text">He brought this recipe from Naples in 1946, and although he became a successful accountant, his true passion was cooking this sauce. The whole neighborhood knew it was Sunday when that aroma filled the air. He always saved the end pieces of bread to "fare la scarpetta" (sop up the sauce) which he considered the highest compliment to the cook.</p> </div> </div> </div> <!-- Recipe Card 3: Mom's Chocolate Chip Cookies --> <div class="recipe-card next"> <div class="paper-texture"></div> <div class="recipe-header"> <h1 class="recipe-title">Mom's After-School Cookies</h1> <h2 class="recipe-subtitle">The chocolate chip cookies that healed all bad days</h2> </div> <div class="polaroid"> <img src="https://images.unsplash.com/photo-1499636136210-6f4ee915583e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" alt="Chocolate Chip Cookies" class="photo"> <p class="photo-caption">First day of school tradition, 1992</p> </div> <div class="recipe-content"> <div class="ingredients"> <h3 class="content-title">Ingredients</h3> <ul> <li>1 cup butter, softened</li> <li>1 cup white sugar</li> <li>1 cup packed brown sugar</li> <li>2 eggs</li> <li>2 tsp vanilla extract</li> <li>3 cups all-purpose flour</li> <li>1 tsp baking soda</li> <li>2 tsp hot water</li> <li>½ tsp salt</li> <li>2 cups chocolate chips</li> <li>1 cup chopped walnuts</li> </ul> </div> <div class="instructions"> <h3 class="content-title">Instructions</h3> <ol> <li>Preheat oven to 350°F (175°C)</li> <li>Cream butter and sugars until smooth</li> <li>Beat in eggs one at a time, then vanilla</li> <li>Dissolve baking soda in hot water, add to batter</li> <li>Add salt, flour, chocolate chips, and nuts</li> <li>Drop by large spoonfuls onto ungreased pans</li> <li>Bake for 10 minutes or until edges are golden</li> </ol> </div> </div> <div class="memory-bubble"> <div class="memory-content">Mom's special touch</div> </div> <div class="story-layer"> <div class="story-content"> <div class="close-story"></div> <h3 class="story-title">The Kitchen Timer Tradition</h3> <p class="story-text">Mom would always time these cookies to come out of the oven exactly 10 minutes before we got home from school. She had this uncanny ability to know when someone had a bad day—those days there would be extra cookies waiting.</p> <p class="story-text">She'd use the old red kitchen timer that made a loud 'ding!' When I was 12 and broke my arm at soccer practice, she brought still-warm cookies to the hospital. She claimed the secret was to always refrigerate the dough for at least 4 hours before baking, and to add the chocolate chips last so they wouldn't melt into the dough during mixing.</p> </div> </div> </div> </div> <div class="navigation"> <button class="nav-btn prev-btn" disabled>←</button> <div class="nav-dots"> <div class="dot active" data-index="0"></div> <div class="dot" data-index="1"></div> <div class="dot" data-index="2"></div> </div> <button class="nav-btn next-btn">→</button> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const recipeCards = document.querySelectorAll('.recipe-card'); const prevBtn = document.querySelector('.prev-btn'); const nextBtn = document.querySelector('.next-btn'); const dots = document.querySelectorAll('.dot'); const memoryBubbles = document.querySelectorAll('.memory-bubble'); const storyLayers = document.querySelectorAll('.story-layer'); const closeStoryBtns = document.querySelectorAll('.close-story'); let currentIndex = 0; const totalCards = recipeCards.length; // Initialize the first recipe card and memory bubble setTimeout(() => { memoryBubbles[0].classList.add('show'); }, 1500); // Update recipe cards based on current index function updateCards() { // Update recipe cards recipeCards.forEach((card, index) => { card.classList.remove('active', 'prev', 'next'); if (index === currentIndex) { card.classList.add('active'); } else if (index < currentIndex) { card.classList.add('prev'); } else { card.classList.add('next'); } }); // Update dots dots.forEach((dot, index) => { dot.classList.toggle('active', index === currentIndex); }); // Update buttons prevBtn.disabled = currentIndex === 0; nextBtn.disabled = currentIndex === totalCards - 1; // Show memory bubble for current card with delay memoryBubbles.forEach((bubble, index) => { bubble.classList.remove('show'); if (index === currentIndex) { setTimeout(() => { bubble.classList.add('show'); }, 1000); } }); } // Navigation event listeners prevBtn.addEventListener('click', () => { if (currentIndex > 0) { currentIndex--; updateCards(); } }); nextBtn.addEventListener('click', () => { if (currentIndex < totalCards - 1) { currentIndex++; updateCards(); } }); // Dot navigation dots.forEach((dot, index) => { dot.addEventListener('click', () => { currentIndex = index; updateCards(); }); }); // Memory bubble click to show story memoryBubbles.forEach((bubble, index) => { bubble.addEventListener('click', () => { storyLayers[index].classList.add('active'); }); }); // Close story button closeStoryBtns.forEach((btn, index) => { btn.addEventListener('click', () => { storyLayers[index].classList.remove('active'); }); }); // Click outside story to close storyLayers.forEach(layer => { layer.addEventListener('click', (e) => { if (e.target === layer) { layer.
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vegan Recipe Card</title> <style> :root { --primary-color: #5d9c59; --secondary-color: #a7d7c5; --accent-color: #f7e1d7; --text-color: #2c3e50; --rating-color: #f39c12; --background-color: #f8f9fa; --card-shadow: 0 8px 30px rgba(0, 0, 0, 0.1); --border-radius: 16px; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: var(--background-color); color: var(--text-color); display: flex; justify-content: center; align-items: center; min-height: 700px; padding: 15px; overflow-x: hidden; } .recipe-card { background-color: white; width: 100%; max-width: 650px; border-radius: var(--border-radius); overflow: hidden; box-shadow: var(--card-shadow); position: relative; transition: transform 0.3s ease, box-shadow 0.3s ease; } .recipe-card:hover { transform: translateY(-5px); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); } .eco-badge { position: absolute; right: 20px; top: 20px; background-color: rgba(93, 156, 89, 0.85); color: white; padding: 8px 15px; border-radius: 30px; font-weight: 600; font-size: 0.75rem; display: flex; align-items: center; gap: 5px; z-index: 2; backdrop-filter: blur(4px); box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } .eco-badge svg { width: 16px; height: 16px; } .card-image { width: 100%; height: 200px; position: relative; overflow: hidden; } .card-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.7s ease; } .recipe-card:hover .card-image img { transform: scale(1.05); } .image-overlay { position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent); height: 50%; display: flex; flex-direction: column; justify-content: flex-end; padding: 20px; color: white; } .prep-time { display: flex; align-items: center; gap: 5px; font-size: 0.85rem; margin-bottom: 5px; } .card-content { padding: 25px; } .card-title { font-size: 1.7rem; margin-bottom: 10px; color: var(--primary-color); font-weight: 700; } .card-description { font-size: 0.95rem; line-height: 1.6; margin-bottom: 20px; color: #555; } .ingredients-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .ingredients-title { font-size: 1.1rem; font-weight: 600; display: flex; align-items: center; gap: 8px; } .ingredients-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-bottom: 25px; } .ingredient-item { display: flex; align-items: center; gap: 8px; font-size: 0.9rem; line-height: 1.4; position: relative; padding-left: 24px; } .ingredient-item:before { content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; background-color: var(--secondary-color); border-radius: 50%; opacity: 0.5; transition: all 0.2s ease; } .ingredient-item:hover:before { opacity: 1; transform: translateY(-50%) scale(1.2); } .ingredient-tooltip { position: absolute; bottom: 100%; left: 0; background-color: var(--primary-color); color: white; padding: 5px 10px; border-radius: 5px; font-size: 0.75rem; opacity: 0; visibility: hidden; transition: all 0.3s ease; z-index: 10; white-space: nowrap; pointer-events: none; } .ingredient-tooltip:after { content: ""; position: absolute; top: 100%; left: 10px; border-width: 5px; border-style: solid; border-color: var(--primary-color) transparent transparent transparent; } .ingredient-item:hover .ingredient-tooltip { opacity: 1; visibility: visible; transform: translateY(-5px); } .origin-link { color: var(--primary-color); text-decoration: none; font-weight: 500; display: inline-flex; align-items: center; gap: 5px; font-size: 0.85rem; transition: all 0.2s ease; border-bottom: 1px dashed var(--secondary-color); padding-bottom: 2px; } .origin-link:hover { color: #4a7a47; } .rating-section { display: flex; justify-content: space-between; align-items: center; margin-top: 25px; padding-top: 20px; border-top: 1px solid #eee; } .rating-stars { display: flex; gap: 5px; } .rating-star { cursor: pointer; color: #ddd; font-size: 1.4rem; transition: transform 0.2s ease, color 0.2s ease; } .rating-star:hover { transform: scale(1.2); } .rating-star.active { color: var(--rating-color); } .comment-section { margin-top: 20px; } .comment-input { display: flex; margin-bottom: 15px; } .comment-input input { flex-grow: 1; padding: 12px 15px; border: 1px solid #ddd; border-radius: 30px; outline: none; transition: all 0.2s ease; } .comment-input input:focus { border-color: var(--primary-color); box-shadow: 0 0 0 2px rgba(93, 156, 89, 0.2); } .submit-comment { background-color: var(--primary-color); color: white; border: none; border-radius: 30px; padding: 0 20px; margin-left: 10px; cursor: pointer; transition: all 0.2s ease; font-weight: 600; } .submit-comment:hover { background-color: #4a7a47; transform: translateY(-2px); } .comments-list { max-height: 150px; overflow-y: auto; padding-right: 10px; } .comment-item { background-color: #f9f9f9; padding: 12px 15px; border-radius: 10px; margin-bottom: 10px; font-size: 0.9rem; position: relative; border-left: 3px solid var(--secondary-color); } .comment-user { font-weight: 600; color: var(--primary-color); margin-bottom: 5px; display: flex; justify-content: space-between; } .comment-text { line-height: 1.4; } .comment-date { font-size: 0.75rem; color: #999; } .progress-bar { height: 5px; width: 100%; background-color: #eee; border-radius: 3px; overflow: hidden; margin-top: 10px; } .progress { height: 100%; background-color: var(--secondary-color); width: 0; transition: width 0.5s ease; } .nutritional-info { display: flex; gap: 15px; margin-top: 20px; overflow-x: auto; padding-bottom: 5px; } .nutrition-item { background-color: var(--accent-color); padding: 10px 15px; border-radius: 12px; display: flex; flex-direction: column; align-items: center; min-width: 70px; transition: transform 0.2s ease; } .nutrition-item:hover { transform: translateY(-3px); } .nutrition-value { font-weight: 700; font-size: 1.1rem; color: var(--primary-color); } .nutrition-label { font-size: 0.75rem; color: #666; } .loading-spinner { display: inline-block; width: 20px; height: 20px; border: 2px solid rgba(255,255,255,0.3); border-radius: 50%; border-top-color: white; animation: spin 0.8s linear infinite; margin-right: 5px; display: none; } @keyframes spin { to { transform: rotate(360deg); } } .leaf-animation { position: absolute; width: 20px; height: 20px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%235d9c59'%3E%3Cpath d='M17.5 4.5c0 3-2.5 5.5-5.5 5.5-3.2 0-5.4-2.8-5.5-5.4-.1 2.1.7 4.8 2.7 6.2-1 .8-1.7 2-1.7 3.3 0 2.3 1.9 4.1 4.2 4.1 1.2 0 2.4-.4 3.3-1.2-.4 1.8-1.6 3.4-3.3 4-.3.1-.5.4-.5.7 0 .5.4.8.8.8 3.5-.8 6.1-4 6.1-7.7 0-1.8-.6-3.5-1.6-4.9.3-.5.7-1.1.9-1.7.3-.8.5-1.7.5-2.6 0-.5-.3-1-.8-1-.2 0-.4.1-.6.2z'/%3E%3C/svg%3E"); pointer-events: none; opacity: 0; } @media (max-width: 500px) { .ingredients-list { grid-template-columns: 1fr; } .card-title { font-size: 1.4rem; } .rating-section { flex-direction: column; align-items: flex-start; gap: 15px; } .nutritional-info { gap: 10px; } .nutrition-item { min-width: 60px; padding: 8px 10px; } } /* Custom Scrollbar */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; } ::-webkit-scrollbar-thumb { background: var(--secondary-color); border-radius: 10px; } ::-webkit-scrollbar-thumb:hover { background: var(--primary-color); } </style> </head> <body> <div class="recipe-card"> <div class="eco-badge"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/> </svg> Eco-friendly </div> <div class="card-image"> <img src="https://images.unsplash.com/photo-1512621776951-a57141f2eefd?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80" alt="Rainbow Buddha Bowl"> <div class="image-overlay"> <div class="prep-time"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71V3.5z"/> <path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm7-8A7 7 0 1 1 1 8a7 7 0 0 1 14 0z"/> </svg> Prep Time: 20 mins | Cook Time: 15 mins </div> </div> </div> <div class="card-content"> <h2 class="card-title">Rainbow Buddha Bowl</h2> <p class="card-description">A nutritionally balanced plant-based bowl that's as beautiful to look at as it is delicious to eat. This colorful dish brings together raw and roasted seasonal vegetables, protein-rich quinoa, and a creamy tahini dressing for a perfect harmony of flavors and textures.</p> <div class="ingredients-header"> <h3 class="ingredients-title"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16"> <path d="M14.5 3a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h13zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z"/> <path d="M7 5.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm-1.496-.854a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 1 1 .708-.708l.146.147 1.146-1.147a.5.5 0 0 1 .708 0zM7 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm-1.496-.854a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 0 1 .708-.708l.146.147 1.146-1.147a.5.5 0 0 1 .708 0z"/> </svg> Ingredients </h3> <a href="#" class="origin-link" id="origins-toggle"> View origins <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M8 1a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L7.5 13.293V1.5A.5.5 0 0 1 8 1z"/> </svg> </a> </div> <div class="ingredients-list"> <div class="ingredient-item" data-origin="Peruvian Andes"> <span>1 cup quinoa, rinsed</span> <div class="ingredient-tooltip">Origin: Peruvian Andes</div> </div> <div class="ingredient-item" data-origin="California, USA"> <span>1 large avocado, sliced</span> <div class="ingredient-tooltip">Origin: California, USA</div> </div> <div class="ingredient-item" data-origin="Mexico"> <span>1 cup black beans, cooked</span> <div class="ingredient-tooltip">Origin: Mexico</div> </div> <div class="ingredient-item" data-origin="Local Farm"> <span>2 cups kale, chopped</span> <div class="ingredient-tooltip">Origin: Local Farm</div> </div> <div class="ingredient-item" data-origin="Local Farm"> <span>1 sweet potato, roasted</span> <div class="ingredient-tooltip">Origin: Local Farm</div> </div> <div class="ingredient-item" data-origin="Mediterranean"> <span>2 tbsp tahini</span> <div class="ingredient-tooltip">Origin: Mediterranean</div> </div> <div class="ingredient-item" data-origin="Sicily, Italy"> <span>1 lemon, juiced</span> <div class="ingredient-tooltip">Origin: Sicily, Italy</div> </div> <div class="ingredient-item" data-origin="Local Farm"> <span>1/4 cup pumpkin seeds</span> <div class="ingredient-tooltip">Origin: Local Farm</div> </div> </div> <div class="nutritional-info"> <div class="nutrition-item"> <span class="nutrition-value">485</span> <span class="nutrition-label">Calories</span> </div> <div class="nutrition-item"> <span class="nutrition-value">18g</span> <span class="nutrition-label">Protein</span> </div> <div class="nutrition-item"> <span class="nutrition-value">22g</span> <span class="nutrition-label">Fats</span> </div> <div class="nutrition-item"> <span class="nutrition-value">58g</span> <span class="nutrition-label">Carbs</span> </div> <div class="nutrition-item"> <span class="nutrition-value">13g</span> <span class="nutrition-label">Fiber</span> </div> </div> <div class="rating-section"> <div class="rating-stars" id="rating-stars"> <span class="rating-star" data-rating="1">★</span> <span class="rating-star" data-rating="2">★</span> <span class="rating-star" data-rating="3">★</span> <span class="rating-star" data-rating="4">★</span> <span class="rating-star" data-rating="5">★</span> </div> <div class="rating-count">4.7 (142 ratings)</div> </div> <div class="comment-section"> <div class="comment-input"> <input type="text" placeholder="Share your experience with this recipe..." id="comment-input"> <button class="submit-comment" id="submit-comment"> <div class="loading-spinner" id="comment-spinner"></div> Post </button> </div> <div class="progress-bar"> <div class="progress" id="comment-progress"></div> </div> <div class="comments-list" id="comments-list"> <div class="comment-item"> <div class="comment-user"> <span>Elena G.</span> <span class="comment-date">2 days ago</span> </div> <div class="comment-text">This bowl is stunning! I added some cumin to the sweet potatoes while roasting and it was divine. The tahini dressing is the perfect complement!</div> </div> <div class="comment-item"> <div class="comment-user"> <span>Marcus T.</span> <span class="comment-date">1 week ago</span> </div> <div class="comment-text">Made this for my non-vegan family and they loved it! The contrast between warm and cold ingredients makes it special.</div> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Rating functionality const stars = document.querySelectorAll('.rating-star'); stars.forEach(star => { star.addEventListener('click', function() { const rating = this.getAttribute('data-rating'); // Reset all stars stars.forEach(s => s.classList.remove('active')); // Activate stars up to selected rating for (let i = 0; i < rating; i++) { stars[i].classList.add('active'); } // Create leaf animation for (let i = 0; i < 5; i++) { createLeafAnimation(); } }); star.addEventListener('mouseover', function() { const rating = this.getAttribute('data-rating'); // Preview rating for (let i = 0; i < 5; i++) { if (i < rating) { stars[i].style.color = 'var(--rating-color)'; } else { stars[i].style.color = '#ddd'; } } }); star.addEventListener('mouseout', function() { // Reset to actual rating stars.forEach(s => { if (s.classList.contains('active')) { s.style.color = 'var(--rating-color)'; } else { s.style.color = '#ddd'; } }); }); }); // Comment submission const commentInput = document.getElementById('comment-input'); const submitButton = document.getElementById('submit-comment'); const commentsList = document.getElementById('comments-list'); const spinner = document.getElementById('comment-spinner'); const progressBar = document.getElementById('comment-progress'); submitButton.addEventListener('click', function() { const commentText = commentInput.value.trim(); if (commentText) { // Show spinner and progress spinner.style.display = 'inline-block'; // Simulate progress let progress = 0; const interval = setInterval(() => { progress += 5; progressBar.style.width = progress + '%'; if (progress >= 100) { clearInterval(interval); spinner.style.display = 'none'; progressBar.style.width = '0'; // Add new comment const today = new Date(); const comment = document.createElement('div'); comment.className = 'comment-item'; comment.innerHTML = ` <div class="comment-user"> <span>You</span> <span class="comment-date">Just now</span> </div> <div class="comment-text">${commentText}</div> `; // Add with animation comment.style.opacity = '0'; comment.style.transform = 'translateY(10px)'; commentsList.prepend(comment); setTimeout(() => { comment.style.transition = 'all 0.3s ease'; comment.style.opacity = '1'; comment.style.transform = 'translateY(0)'; }, 50); // Clear input commentInput.value = ''; } }, 50); } }); // Enter key in comment input commentInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { submitButton.click(); } }); // Ingredient origin tooltips const ingredients = document.querySelectorAll('.ingredient-item'); ingredients.forEach(ingredient => { ingredient.addEventListener('mouseenter', function() { const tooltip = this.querySelector('.ingredient-tooltip'); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; }); ingredient.addEventListener('mouseleave', function() { const tooltip = this.querySelector('.ingredient-tooltip'); tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); }); // Leaf animation function createLeafAnimation() { const leaf = document.createElement('div'); leaf.className = 'leaf-animation'; const card = document.querySelector('.recipe-card'); card.appendChild(leaf); // Random position const startX = Math.random() * card.offsetWidth; const startY = card.offsetHeight - 50; leaf.style.left = startX + 'px'; leaf.style.top = startY + 'px'; leaf.style.opacity = '0.8'; // Random rotation const rotation = Math.random() * 360; leaf.style.transform = `rotate(${rotation}deg)`; // Animation setTimeout(() => { leaf.style.transition = 'all 3s ease-out'; leaf.style.top = startY - Math.random() * 200 - 100 + 'px'; leaf.style.left = startX + (Math.random() * 100 - 50) + 'px'; leaf.style.opacity = '0'; leaf.style.transform = `rotate(${rotation + 360}deg)`; setTimeout(() => { leaf.remove(); }, 3000); }, 10); } // Origins toggle const originsToggle = document.getElementById('origins-toggle'); let originsVisible = false; originsToggle.addEventListener('click', function(e) { e.preventDefault(); originsVisible = !originsVisible; if (originsVisible) { ingredients.forEach(ingredient => { const origin = ingredient.getAttribute('data-origin'); const tooltip = ingredient.querySelector('.ingredient-tooltip'); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; }); this.innerHTML = `Hide origins <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M8 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L7.5 2.707V14.5a.5.5 0 0 0 .5.5z"/> </svg>`; } else { ingredients.forEach(ingredient => { const tooltip = ingredient.querySelector('.ingredient-tooltip'); tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); this.innerHTML = `View origins <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M8 1a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L7.5 13.293V1.5A.5.5 0 0 1 8 1z"/> </svg>`; } }); }); </script> </body> </html>