Material Design cards are a versatile and visually appealing way to present content in a structured format. They offer a clean, modern look that enhances user experience.
In this article, we will explore 10 stunning examples of Material Design cards that can inspire your next project. Each example showcases unique design elements and functionalities.
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
Subframe's drag-and-drop interface and intuitive, responsive canvas make it effortless to design pixel-perfect Material Design cards. Loved by designers and developers alike, Subframe ensures your UI is stunning and functional.
Start for free and elevate your design game 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 design game? With Subframe, you can create pixel-perfect Material Design cards and stunning UIs in minutes. Our drag-and-drop editor and beautifully crafted components make the process efficient and enjoyable.
Start for free and begin designing immediately. Experience the ease and power of Subframe today!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root { --primary: #3a6df0; --primary-light: #5884ff; --accent: #ff5722; --dark: #1e2342; --gain: #00c853; --loss: #f44336; --bg: #f9faff; --card-bg: #ffffff; --text: #1a2037; --text-secondary: #6e7794; --border: #e0e6fd; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Roboto', 'Segoe UI', sans-serif; } body { background-color: var(--bg); color: var(--text); display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 20px; } .container { max-width: 650px; width: 100%; height: 650px; display: flex; flex-direction: column; } .financial-card { background-color: var(--card-bg); border-radius: 16px; box-shadow: 0 4px 20px rgba(22, 33, 74, 0.08); padding: 24px; transition: box-shadow 0.3s ease, transform 0.3s ease; width: 100%; height: 100%; overflow: hidden; display: flex; flex-direction: column; } .financial-card:hover { box-shadow: 0 8px 30px rgba(22, 33, 74, 0.12); transform: translateY(-2px); } .card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; } .card-title { font-size: 24px; font-weight: 700; color: var(--dark); } .date-range { display: flex; align-items: center; background-color: var(--bg); padding: 8px 16px; border-radius: 12px; cursor: pointer; transition: all 0.2s ease; } .date-range:hover { background-color: var(--border); } .date-range-text { font-size: 14px; font-weight: 500; margin-right: 8px; } .card-tabs { display: flex; margin-bottom: 24px; border-bottom: 1px solid var(--border); } .tab { padding: 12px 16px; margin-right: 8px; font-size: 14px; font-weight: 500; color: var(--text-secondary); cursor: pointer; transition: all 0.2s ease; position: relative; } .tab.active { color: var(--primary); font-weight: 600; } .tab.active::after { content: ''; position: absolute; bottom: -1px; left: 0; width: 100%; height: 3px; background-color: var(--primary); border-radius: 3px 3px 0 0; } .tab:hover:not(.active) { color: var(--text); } .metrics-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-bottom: 24px; } .metric-card { background-color: var(--bg); border-radius: 12px; padding: 16px; transition: all 0.3s ease; cursor: pointer; position: relative; overflow: hidden; } .metric-card:hover { transform: translateY(-3px); box-shadow: 0 6px 12px rgba(22, 33, 74, 0.06); } .metric-card::before { content: ''; position: absolute; top: 0; left: 0; width: 4px; height: 0; background-color: var(--primary); transition: height 0.3s ease; } .metric-card:hover::before { height: 100%; } .metric-title { font-size: 14px; color: var(--text-secondary); margin-bottom: 8px; font-weight: 500; } .metric-value { font-size: 24px; font-weight: 700; color: var(--text); margin-bottom: 8px; } .metric-change { display: flex; align-items: center; font-size: 14px; font-weight: 500; } .gain { color: var(--gain); } .loss { color: var(--loss); } .chart-container { flex-grow: 1; position: relative; width: 100%; min-height: 240px; } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; } .chart-title { font-size: 18px; font-weight: 600; } .chart-legend { display: flex; gap: 16px; } .legend-item { display: flex; align-items: center; font-size: 14px; color: var(--text-secondary); } .legend-color { width: 12px; height: 12px; border-radius: 3px; margin-right: 6px; } .primary-color { background-color: var(--primary); } .accent-color { background-color: var(--accent); } .tooltip { position: absolute; background-color: var(--dark); color: white; padding: 8px 12px; border-radius: 6px; font-size: 12px; pointer-events: none; opacity: 0; transition: opacity 0.2s ease; z-index: 10; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); max-width: 180px; } canvas { width: 100%; height: 100%; } @media (max-width: 600px) { .metrics-grid { grid-template-columns: 1fr; } .card-header { flex-direction: column; align-items: flex-start; gap: 12px; } .card-tabs { overflow-x: auto; white-space: nowrap; padding-bottom: 4px; width: 100%; } } .loading-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.8); display: flex; justify-content: center; align-items: center; z-index: 100; border-radius: 16px; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; } .loader { width: 48px; height: 48px; border: 4px solid var(--primary-light); border-bottom-color: var(--primary); border-radius: 50%; animation: rotation 1s linear infinite; } @keyframes rotation { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } </style> </head> <body> <div class="container"> <div class="financial-card"> <div class="loading-overlay" id="loadingOverlay"> <div class="loader"></div> </div> <div class="card-header"> <div class="card-title">Market Performance</div> <div class="date-range" id="dateRange"> <span class="date-range-text">Last 30 days</span> <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"> <polyline points="6 9 12 15 18 9"></polyline> </svg> </div> </div> <div class="card-tabs"> <div class="tab active" data-tab="overview">Overview</div> <div class="tab" data-tab="technicals">Technicals</div> <div class="tab" data-tab="fundamentals">Fundamentals</div> <div class="tab" data-tab="news">News</div> </div> <div class="metrics-grid"> <div class="metric-card" id="priceCard"> <div class="metric-title">Current Price</div> <div class="metric-value">$187.42</div> <div class="metric-change gain"> <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"> <polyline points="18 15 12 9 6 15"></polyline> </svg> <span>+2.8% ($5.12)</span> </div> </div> <div class="metric-card" id="volumeCard"> <div class="metric-title">Trading Volume</div> <div class="metric-value">4.3M</div> <div class="metric-change loss"> <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"> <polyline points="6 9 12 15 18 9"></polyline> </svg> <span>-12.5% (620K)</span> </div> </div> <div class="metric-card" id="peCard"> <div class="metric-title">P/E Ratio</div> <div class="metric-value">24.8</div> <div class="metric-change gain"> <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"> <polyline points="18 15 12 9 6 15"></polyline> </svg> <span>+4.2% (1.0)</span> </div> </div> <div class="metric-card" id="marketCapCard"> <div class="metric-title">Market Cap</div> <div class="metric-value">$2.94T</div> <div class="metric-change gain"> <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"> <polyline points="18 15 12 9 6 15"></polyline> </svg> <span>+3.1% ($89B)</span> </div> </div> </div> <div class="chart-container"> <div class="chart-header"> <div class="chart-title">Price History</div> <div class="chart-legend"> <div class="legend-item"> <div class="legend-color primary-color"></div> <span>Share Price</span> </div> <div class="legend-item"> <div class="legend-color accent-color"></div> <span>S&P 500</span> </div> </div> </div> <canvas id="priceChart"></canvas> <div class="tooltip" id="chartTooltip"></div> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> document.addEventListener('DOMContentLoaded', function() { // Show loading const loadingOverlay = document.getElementById('loadingOverlay'); loadingOverlay.style.opacity = '1'; loadingOverlay.style.pointerEvents = 'auto'; setTimeout(() => { // Tabs functionality const tabs = document.querySelectorAll('.tab'); tabs.forEach(tab => { tab.addEventListener('click', () => { // Show loading while switching tabs loadingOverlay.style.opacity = '1'; loadingOverlay.style.pointerEvents = 'auto'; // Remove active class from all tabs tabs.forEach(t => t.classList.remove('active')); // Add active class to clicked tab tab.classList.add('active'); // Simulate loading data for the tab setTimeout(() => { loadingOverlay.style.opacity = '0'; loadingOverlay.style.pointerEvents = 'none'; }, 800); }); }); // Metric cards hover effect with enhanced data const metricCards = document.querySelectorAll('.metric-card'); const tooltip = document.getElementById('chartTooltip'); metricCards.forEach(card => { card.addEventListener('mouseenter', function() { // Add subtle pulse animation this.style.transform = 'translateY(-3px) scale(1.02)'; this.style.boxShadow = '0 8px 16px rgba(22, 33, 74, 0.1)'; }); card.addEventListener('mouseleave', function() { this.style.transform = ''; this.style.boxShadow = ''; }); card.addEventListener('click', function() { // Get card ID to determine which data to highlight const cardId = this.id; // Show loading overlay loadingOverlay.style.opacity = '1'; loadingOverlay.style.pointerEvents = 'auto'; // Simulate data update setTimeout(() => { // Update chart based on selected metric updateChartForMetric(cardId); loadingOverlay.style.opacity = '0'; loadingOverlay.style.pointerEvents = 'none'; }, 800); }); }); // Date range selector const dateRange = document.getElementById('dateRange'); const dateRangeOptions = ['Last 7 days', 'Last 30 days', 'Last 90 days', 'YTD', '1 Year']; let currentDateRangeIndex = 1; // Start with 30 days selected dateRange.addEventListener('click', function() { // Cycle through date range options currentDateRangeIndex = (currentDateRangeIndex + 1) % dateRangeOptions.length; const dateRangeText = dateRange.querySelector('.date-range-text'); dateRangeText.textContent = dateRangeOptions[currentDateRangeIndex]; // Show loading overlay loadingOverlay.style.opacity = '1'; loadingOverlay.style.pointerEvents = 'auto'; // Update chart based on new date range setTimeout(() => { updateChartDateRange(dateRangeOptions[currentDateRangeIndex]); loadingOverlay.style.opacity = '0'; loadingOverlay.style.pointerEvents = 'none'; }, 800); }); // Chart initialization const ctx = document.getElementById('priceChart').getContext('2d'); // Generate realistic stock data const generateStockData = (baseValue, volatility, trend, days) => { let price = baseValue; const data = []; for (let i = 0; i < days; i++) { // Add random movement with trend const change = (Math.random() - 0.5) * volatility + trend; price = Math.max(price + change, 0); data.push(price); } return data; }; // Generate dates for last 30 days const generateDates = (days) => { const dates = []; const today = new Date(); for (let i = days - 1; i >= 0; i--) { const date = new Date(); date.setDate(today.getDate() - i); dates.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })); } return dates; }; const days = 30; const labels = generateDates(days); const stockPriceData = generateStockData(180, 5, 0.3, days); const marketIndexData = generateStockData(450, 4, 0.2, days); // Normalize market index data to be comparable on the same scale const normalizedMarketData = marketIndexData.map(value => value / 4); let chart = new Chart(ctx, { type: 'line', data: { labels: labels, datasets: [{ label: 'Share Price', data: stockPriceData, borderColor: '#3a6df0', backgroundColor: 'rgba(58, 109, 240, 0.1)', borderWidth: 2, pointRadius: 0, pointHoverRadius: 6, pointHoverBackgroundColor: '#3a6df0', pointHoverBorderColor: '#ffffff', pointHoverBorderWidth: 2, tension: 0.4, fill: true }, { label: 'S&P 500', data: normalizedMarketData, borderColor: '#ff5722', borderWidth: 2, pointRadius: 0, pointHoverRadius: 6, pointHoverBackgroundColor: '#ff5722', pointHoverBorderColor: '#ffffff', pointHoverBorderWidth: 2, borderDash: [5, 5], tension: 0.4, fill: false }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { tooltip: { enabled: false, external: function(context) { const tooltipEl = document.getElementById('chartTooltip'); // Hide if no tooltip if (context.tooltip.opacity === 0) { tooltipEl.style.opacity = 0; return; } // Set Text const dataIndex = context.tooltip.dataPoints[0].dataIndex; const date = labels[dataIndex]; const price = stockPriceData[dataIndex].toFixed(2); const marketPrice = (normalizedMarketData[dataIndex] * 4).toFixed(2); tooltipEl.innerHTML = ` <div style="font-weight:600">${date}</div> <div style="color:#3a6df0;margin-top:4px">Price: $${price}</div> <div style="color:#ff5722;margin-top:2px">S&P 500: $${marketPrice}</div> `; // Position tooltip const position = context.chart.canvas.getBoundingClientRect(); tooltipEl.style.opacity = 1; tooltipEl.style.left = position.left + context.tooltip.caretX + 'px'; tooltipEl.style.top = position.top + context.tooltip.caretY + 'px'; tooltipEl.style.transform = 'translate(-50%, -110%)'; } }, legend: { display: false } }, scales: { x: { grid: { display: false, drawBorder: false }, ticks: { font: { size: 11 }, color: '#6e7794', maxRotation: 0, callback: function(val, index) { // Show fewer labels on x-axis return index % 5 === 0 ? this.getLabelForValue(val) : ''; } } }, y: { grid: { color: 'rgba(224, 230, 253, 0.6)', drawBorder: false }, ticks: { font: { size: 11 }, color: '#6e7794', callback: function(val) { return '$' + val.toFixed(0); } } } }, interaction: { mode: 'index', intersect: false }, hover: { mode: 'index', intersect: false } } }); // Add interactivity to chart const chartCanvas = document.getElementById('priceChart'); chartCanvas.addEventListener('mousemove', function(e) { const tooltip = document.getElementById('chartTooltip'); tooltip.style.opacity = '1'; }); chartCanvas.addEventListener('mouseleave', function() { const tooltip = document.getElementById('chartTooltip'); tooltip.style.opacity = '0'; }); function updateChartForMetric(metricId) { let newData = []; let newColor = '#3a6df0'; let newLabel = 'Share Price'; switch(metricId) { case 'volumeCard': newData = generateStockData(4, 0.5, -0.02, days); newColor = '#673ab7'; newLabel = 'Volume (M)'; break; case 'peCard': newData = generateStockData(24, 1, 0.1, days); newColor = '#00796b'; newLabel = 'P/E Ratio'; break; case 'marketCapCard': newData = generateStockData(2900, 40, 3, days); newColor = '#ff9800'; newLabel = 'Market Cap ($B)'; break; default: // priceCard or any other newData = stockPriceData; break; } chart.data.datasets[0].data = newData; chart.data.datasets[0].label = newLabel; chart.data.datasets[0].borderColor = newColor; chart.data.datasets[0].backgroundColor = `${newColor}20`; chart.data.datasets[0].pointHoverBackgroundColor = newColor; chart.update(); } function updateChartDateRange(range) { let days; let trend; switch(range) { case 'Last 7 days': days = 7; trend = 0.5; break; case 'Last 90 days': days = 90; trend = 0.15; break; case 'YTD': days = 150; trend = 0.1; break; case '1 Year': days = 365; trend = 0.05; break; default: // Last 30 days days = 30; trend = 0.3; break; } const labels = generateDates(days); const stockPriceData = generateStockData(180, 5, trend, days); const marketIndexData = generateStockData(450, 4, trend * 0.8, days); const normalizedMarketData = marketIndexData.map(value => value / 4); chart.data.labels = labels; chart.data.datasets[0].data = stockPriceData; chart.data.datasets[1].data = normalizedMarketData; // Adjust x-axis tick display based on date range if (days > 60) { chart.options.scales.x.ticks.callback = function(val, index) { return index % 15 === 0 ? this.getLabelForValue(val) : ''; }; } else if (days > 30) { chart.options.scales.x.ticks.callback = function(val, index) { return index % 10 === 0 ? this.getLabelForValue(val) : ''; }; } else { chart.options.scales.x.ticks.callback = function(val, index) { return index % 5 === 0 ? this.getLabelForValue(val) : ''; }; } chart.update(); } // Hide loading overlay when initial chart is ready loadingOverlay.style.opacity = '0'; loadingOverlay.style.pointerEvents = 'none'; }, 1000); // Initial load delay for demonstration }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Travel Booking Card</title> <style> :root { --primary: #ff7e5f; --primary-dark: #ff6347; --secondary: #feb47b; --text-dark: #2c3e50; --text-light: #ecf0f1; --background: #ffffff; --card-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); --hover-shadow: 0 15px 30px rgba(0, 0, 0, 0.15); --radius: 16px; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', sans-serif; } body { background-color: #f8f9fa; display: flex; justify-content: center; align-items: center; min-height: 700px; padding: 20px; perspective: 1000px; } .container { width: 100%; max-width: 650px; height: auto; max-height: 660px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--secondary) #f1f1f1; } .container::-webkit-scrollbar { width: 6px; } .container::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; } .container::-webkit-scrollbar-thumb { background: var(--secondary); border-radius: 10px; } .travel-card { background: var(--background); border-radius: var(--radius); box-shadow: var(--card-shadow); overflow: hidden; transition: transform 0.5s ease, box-shadow 0.3s ease; transform-style: preserve-3d; margin-bottom: 20px; position: relative; } .travel-card:hover { box-shadow: var(--hover-shadow); transform: translateY(-5px) rotateX(2deg) rotateY(2deg); } .destination-image { position: relative; height: 240px; overflow: hidden; } .destination-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.7s ease; } .travel-card:hover .destination-image img { transform: scale(1.05); } .location-marker { position: absolute; top: 20px; left: 20px; background: rgba(255, 255, 255, 0.9); color: var(--primary); padding: 8px 16px; border-radius: 50px; font-weight: 600; font-size: 14px; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); display: flex; align-items: center; gap: 8px; opacity: 0; transform: translateY(10px); transition: opacity 0.3s ease, transform 0.3s ease; } .travel-card:hover .location-marker { opacity: 1; transform: translateY(0); } .travel-info { padding: 25px; } .travel-title { font-size: 24px; font-weight: 700; color: var(--text-dark); margin-bottom: 10px; position: relative; display: inline-block; } .travel-title::after { content: ''; position: absolute; bottom: -5px; left: 0; width: 0; height: 3px; background: linear-gradient(90deg, var(--primary), var(--secondary)); transition: width 0.3s ease; border-radius: 10px; } .travel-card:hover .travel-title::after { width: 100%; } .travel-description { color: #6c757d; line-height: 1.6; margin-bottom: 20px; } .travel-meta { display: flex; justify-content: space-between; margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid rgba(0, 0, 0, 0.1); } .meta-item { display: flex; flex-direction: column; align-items: center; } .meta-label { font-size: 12px; color: #6c757d; margin-bottom: 5px; } .meta-value { font-size: 16px; font-weight: 600; color: var(--text-dark); } .price-section { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .price { font-size: 28px; font-weight: 700; color: var(--primary); } .price-note { font-size: 12px; color: #6c757d; } .action-buttons { display: flex; gap: 15px; } .btn { padding: 12px 25px; border-radius: 50px; font-weight: 600; font-size: 16px; cursor: pointer; transition: all 0.3s ease; border: none; outline: none; position: relative; overflow: hidden; } .btn-primary { background: linear-gradient(135deg, var(--primary), var(--secondary)); color: white; flex: 2; } .btn-primary::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.1)); transition: left 0.6s ease; } .btn-primary:hover::before { left: 100%; } .btn-secondary { background: transparent; color: var(--primary); border: 2px solid var(--primary); flex: 1; } .btn-secondary:hover { background: rgba(255, 126, 95, 0.1); } .save-button { position: absolute; top: 20px; right: 20px; width: 45px; height: 45px; border-radius: 50%; background: rgba(255, 255, 255, 0.9); display: flex; justify-content: center; align-items: center; cursor: pointer; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; z-index: 10; } .save-button:hover { transform: scale(1.1); } .save-button svg { width: 22px; height: 22px; fill: none; stroke: var(--primary); stroke-width: 2; transition: all 0.3s ease; } .save-button.active svg { fill: var(--primary); } .rating { display: flex; align-items: center; margin-top: 10px; } .stars { display: flex; margin-right: 10px; } .star { color: #ffc107; font-size: 18px; } .reviews { font-size: 14px; color: #6c757d; } .hidden-features { height: 0; overflow: hidden; transition: height 0.5s ease; } .travel-card.expanded .hidden-features { height: auto; margin-top: 15px; } .features-list { list-style: none; padding: 0; margin-bottom: 20px; } .features-list li { margin-bottom: 10px; display: flex; align-items: center; color: #6c757d; } .features-list li svg { margin-right: 10px; min-width: 20px; } .toggle-details { text-align: center; color: var(--primary); font-weight: 600; cursor: pointer; position: relative; padding: 5px 0; } .toggle-details::after { content: ''; position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); width: 50px; height: 2px; background: linear-gradient(90deg, transparent, var(--primary), transparent); transition: width 0.3s ease; } .toggle-details:hover::after { width: 80px; } /* Animation for new cards */ @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .travel-card { animation: fadeInUp 0.6s ease forwards; } /* Pulse animation for the booking button */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .pulse { animation: pulse 1.5s infinite; } /* Responsive design */ @media (max-width: 550px) { .travel-meta { flex-wrap: wrap; gap: 15px; } .action-buttons { flex-direction: column; } .btn { width: 100%; } .travel-title { font-size: 20px; } .destination-image { height: 180px; } } /* Special touch - shape decor */ .shape-decor { position: absolute; opacity: 0.1; pointer-events: none; z-index: -1; } .shape-1 { top: 10%; left: 5%; width: 100px; height: 100px; border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%; background: var(--primary); animation: float 8s ease-in-out infinite; } .shape-2 { bottom: 10%; right: 5%; width: 150px; height: 150px; border-radius: 38% 62% 63% 37% / 41% 44% 56% 59%; background: var(--secondary); animation: float 10s ease-in-out infinite reverse; } @keyframes float { 0% { transform: translate(0, 0) rotate(0deg); } 50% { transform: translate(10px, 10px) rotate(5deg); } 100% { transform: translate(0, 0) rotate(0deg); } } </style> </head> <body> <div class="shape-decor shape-1"></div> <div class="shape-decor shape-2"></div> <div class="container"> <div class="travel-card" id="card1"> <div class="destination-image"> <img src="https://images.unsplash.com/photo-1510414842594-a61c69b5ae57?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80" alt="Santorini, Greece"> <div class="location-marker"> <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="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path> <circle cx="12" cy="10" r="3"></circle> </svg> Santorini, Greece </div> <div class="save-button" id="save1"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path> </svg> </div> </div> <div class="travel-info"> <h2 class="travel-title">Aegean Paradise Escape</h2> <div class="rating"> <div class="stars"> <span class="star">★</span> <span class="star">★</span> <span class="star">★</span> <span class="star">★</span> <span class="star">★</span> </div> <span class="reviews">4.9 (382 reviews)</span> </div> <p class="travel-description">Experience the dazzling white-washed villages perched on cliffs overlooking the azure Aegean Sea. This 5-day adventure offers spectacular sunsets, authentic cuisine, and hidden beaches.</p> <div class="travel-meta"> <div class="meta-item"> <span class="meta-label">Duration</span> <span class="meta-value">5 Days</span> </div> <div class="meta-item"> <span class="meta-label">Group Size</span> <span class="meta-value">Up to 12</span> </div> <div class="meta-item"> <span class="meta-label">Best Season</span> <span class="meta-value">May-Oct</span> </div> </div> <div class="hidden-features"> <ul class="features-list"> <li> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> Sunset sailing around the caldera </li> <li> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> Wine tasting at local vineyards </li> <li> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> Luxury cliffside accommodations </li> </ul> </div> <div class="price-section"> <div> <div class="price">$1,289</div> <div class="price-note">per person / includes taxes & fees</div> </div> <div class="toggle-details">View Details</div> </div> <div class="action-buttons"> <button class="btn btn-primary pulse">Book This Trip</button> <button class="btn btn-secondary">Save for Later</button> </div> </div> </div> <div class="travel-card" id="card2"> <div class="destination-image"> <img src="https://images.unsplash.com/photo-1512453979798-5ea266f8880c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80" alt="Tokyo, Japan"> <div class="location-marker"> <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="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path> <circle cx="12" cy="10" r="3"></circle> </svg> Tokyo, Japan </div> <div class="save-button" id="save2"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path> </svg> </div> </div> <div class="travel-info"> <h2 class="travel-title">Tokyo Tech & Tradition</h2> <div class="rating"> <div class="stars"> <span class="star">★</span> <span class="star">★</span> <span class="star">★</span> <span class="star">★</span> <span class="star">★</span> </div> <span class="reviews">4.8 (294 reviews)</span> </div> <p class="travel-description">Discover the perfect balance of ultra-modern technology and ancient traditions in Tokyo. From neon-lit Shinjuku to serene temple gardens and world-class sushi experiences.</p> <div class="travel-meta"> <div class="meta-item"> <span class="meta-label">Duration</span> <span class="meta-value">7 Days</span> </div> <div class="meta-item"> <span class="meta-label">Group Size</span> <span class="meta-value">Up to 8</span> </div> <div class="meta-item"> <span class="meta-label">Best Season</span> <span class="meta-value">Apr-May</span> </div> </div> <div class="hidden-features"> <ul class="features-list"> <li> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> Private tea ceremony experience </li> <li> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> Tsukiji fish market tour with chef </li> <li> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> Shibuya Crossing & Harajuku exploration </li> </ul> </div> <div class="price-section"> <div> <div class="price">$2,149</div> <div class="price-note">per person / includes taxes & fees</div> </div> <div class="toggle-details">View Details</div> </div> <div class="action-buttons"> <button class="btn btn-primary">Book This Trip</button> <button class="btn btn-secondary">Save for Later</button> </div> </div> </div> </div> <script> // Toggle save button state document.querySelectorAll('.save-button').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); this.classList.toggle('active'); // Add tactile feedback this.style.transform = 'scale(0.9)'; setTimeout(() => { this.style.transform = 'scale(1.1)'; setTimeout(() => { this.style.transform = ''; }, 100); }, 100); }); }); // Toggle card expansion document.querySelectorAll('.toggle-details').forEach(toggle => { toggle.addEventListener('click', function() { const card = this.closest('.travel-card'); card.classList.toggle('expanded'); if (card.classList.contains('expanded')) { this.textContent = 'Hide Details'; } else { this.textContent = 'View Details'; } // Scroll to the card if it's expanded if (card.classList.contains('expanded')) { const cardTop = card.getBoundingClientRect().top; const containerTop = document.querySelector('.container').getBoundingClientRect().top; const scrollOffset = cardTop - containerTop; document.querySelector('.container').scrollBy({ top: scrollOffset, behavior: 'smooth' }); } }); }); // Add tactile feedback to buttons document.querySelectorAll('.btn').forEach(btn => { btn.addEventListener('mousedown', function() { this.style.transform = 'scale(0.98)'; }); btn.addEventListener('mouseup', function() { this.style.transform = ''; }); btn.addEventListener('mouseleave', function() { this.style.transform = ''; }); }); // Staggered animation on load document.addEventListener('DOMContentLoaded', function() { const cards = document.querySelectorAll('.travel-card'); cards.forEach((card, index) => { card.style.opacity = '0'; card.style.transform = 'translateY(20px)'; setTimeout(() => { card.style.transition = 'opacity 0.6s ease, transform 0.6s ease'; card.style.opacity = '1'; card.style.transform = 'translateY(0)'; }, index * 200); }); }); // Add hover effect to destination images document.querySelectorAll('.destination-image').forEach(img => { img.addEventListener('mousemove', function(e) { const { left, top, width, height } = this.getBoundingClientRect(); const x = (e.clientX - left) / width; const y = (e.clientY - top) / height; // Subtle parallax effect const image = this.querySelector('img'); const moveX = (x - 0.5) * 10; const moveY = (y - 0.5) * 10; image.style.transform = `scale(1.05) translate(${moveX}px, ${moveY}px)`; }); img.addEventListener('mouseleave', function() { const image = this.querySelector('img'); image.style.transform = ''; setTimeout(() => { image.style.transition = 'transform 0.7s ease'; }, 100); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Course Content Card</title> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); :root { --primary-color: #6C63FF; --accent-color: #FF6B6B; --secondary-accent: #4ECDC4; --text-color: #333; --light-gray: #f8f9fa; --medium-gray: #e9ecef; --dark-gray: #6c757d; --white: #ffffff; --shadow: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', sans-serif; } body { background-color: #f5f5f7; color: var(--text-color); display: flex; justify-content: center; align-items: center; min-height: 700px; padding: 20px; perspective: 1000px; } .container { width: 100%; max-width: 650px; margin: 0 auto; overflow: hidden; } .course-card { background: var(--white); border-radius: 16px; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.05), 0 6px 6px rgba(0, 0, 0, 0.03), 0 16px 24px rgba(0, 0, 0, 0.03); overflow: hidden; transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); position: relative; transform-style: preserve-3d; } .course-card:hover { transform: translateY(-8px) rotateX(2deg); box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1), 0 10px 10px rgba(0, 0, 0, 0.04); } .course-header { padding: 24px 30px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--medium-gray); position: relative; overflow: hidden; } .course-header::after { content: ''; position: absolute; height: 3px; background: linear-gradient(90deg, var(--primary-color), var(--accent-color), var(--secondary-accent)); bottom: 0; left: 0; width: 100%; transform: translateX(-100%); transition: transform 0.4s ease-out; } .course-card:hover .course-header::after { transform: translateX(0); } .course-title { font-weight: 600; font-size: 1.4rem; color: var(--text-color); margin-bottom: 4px; } .course-category { font-size: 0.9rem; color: var(--dark-gray); display: flex; align-items: center; gap: 8px; } .category-tag { background: var(--light-gray); padding: 4px 12px; border-radius: 100px; font-size: 0.75rem; font-weight: 500; color: var(--primary-color); display: inline-block; transition: all 0.2s ease; } .category-tag:hover { background: var(--primary-color); color: white; transform: scale(1.05); } .course-price { font-weight: 700; color: var(--primary-color); font-size: 1.25rem; display: flex; align-items: center; padding: 5px 12px; background: rgba(108, 99, 255, 0.08); border-radius: 8px; } .course-content { padding: 25px 30px; } .course-stats { display: flex; margin-bottom: 20px; gap: 15px; } .stat-item { display: flex; flex-direction: column; padding: 8px 15px; background: var(--light-gray); border-radius: 8px; flex: 1; transition: all 0.3s ease; cursor: pointer; } .stat-item:hover { background: var(--medium-gray); transform: translateY(-3px); } .stat-value { font-weight: 600; font-size: 1.1rem; margin-bottom: 4px; color: var(--text-color); } .stat-label { font-size: 0.8rem; color: var(--dark-gray); } .course-description { margin-bottom: 25px; line-height: 1.6; color: var(--text-color); font-size: 0.95rem; } .instructor { display: flex; align-items: center; margin-bottom: 25px; padding: 15px; background: var(--light-gray); border-radius: 12px; transition: all 0.3s ease; cursor: pointer; position: relative; overflow: hidden; } .instructor:hover { transform: translateX(5px); background: #f0f1f7; } .instructor::before { content: ''; position: absolute; left: 0; top: 0; height: 100%; width: 4px; background: var(--primary-color); transform: scaleY(0); transition: transform 0.3s ease; transform-origin: bottom; } .instructor:hover::before { transform: scaleY(1); } .instructor-avatar { width: 55px; height: 55px; border-radius: 50%; margin-right: 15px; object-fit: cover; border: 2px solid white; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .instructor-info h3 { font-weight: 600; font-size: 1rem; margin-bottom: 4px; } .instructor-info p { font-size: 0.85rem; color: var(--dark-gray); } .rating { display: flex; align-items: center; gap: 3px; margin-top: 5px; } .star { color: #ffc107; font-size: 0.85rem; } .rating-count { font-size: 0.75rem; color: var(--dark-gray); margin-left: 5px; } .course-actions { display: flex; gap: 12px; } .action-btn { padding: 12px 20px; border-radius: 8px; font-weight: 600; font-size: 0.95rem; border: none; cursor: pointer; transition: all 0.3s ease; position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; gap: 8px; flex: 1; } .primary-btn { background: var(--primary-color); color: white; } .primary-btn:hover { background: #5951e5; transform: translateY(-3px); box-shadow: 0 6px 15px rgba(108, 99, 255, 0.25); } .secondary-btn { background: transparent; color: var(--primary-color); border: 2px solid var(--primary-color); } .secondary-btn:hover { background: rgba(108, 99, 255, 0.08); transform: translateY(-3px); } .btn-ripple { position: absolute; background: rgba(255, 255, 255, 0.3); border-radius: 50%; transform: scale(0); animation: ripple 0.6s linear; pointer-events: none; } @keyframes ripple { to { transform: scale(2.5); opacity: 0; } } .progress-bar { height: 6px; background: var(--medium-gray); border-radius: 100px; margin-bottom: 25px; overflow: hidden; } .progress { height: 100%; width: 68%; background: linear-gradient(90deg, var(--primary-color), var(--secondary-accent)); border-radius: 100px; position: relative; transform-origin: left; animation: loadProgress 1.5s ease-out forwards; } @keyframes loadProgress { from { transform: scaleX(0); } to { transform: scaleX(1); } } .tab-container { display: flex; margin-bottom: 20px; border-bottom: 1px solid var(--medium-gray); } .tab { padding: 12px 18px; font-weight: 500; font-size: 0.9rem; color: var(--dark-gray); cursor: pointer; position: relative; transition: all 0.3s ease; } .tab.active { color: var(--primary-color); font-weight: 600; } .tab.active::after { content: ''; position: absolute; bottom: -1px; left: 0; width: 100%; height: 3px; background: var(--primary-color); border-radius: 3px 3px 0 0; } .tab:not(.active):hover { color: var(--text-color); background: var(--light-gray); } .content-loader { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.9); display: flex; justify-content: center; align-items: center; z-index: 10; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; } .loader { width: 40px; height: 40px; border: 3px solid var(--light-gray); border-top-color: var(--primary-color); border-radius: 50%; animation: spin 1s linear infinite; } .loading .content-loader { opacity: 1; pointer-events: all; } @keyframes spin { to { transform: rotate(360deg); } } @media (max-width: 600px) { .course-header { flex-direction: column; align-items: flex-start; gap: 15px; } .course-title { font-size: 1.2rem; } .course-price { align-self: flex-start; } .course-stats { flex-wrap: wrap; } .stat-item { min-width: 45%; } .action-btn { padding: 10px 16px; font-size: 0.9rem; } .instructor { padding: 12px; } .instructor-avatar { width: 45px; height: 45px; } } </style> </head> <body> <div class="container"> <div class="course-card"> <div class="content-loader"> <div class="loader"></div> </div> <div class="course-header"> <div> <h1 class="course-title">Advanced UI/UX Design Systems</h1> <div class="course-category"> <span class="category-tag">Design</span> <span class="category-tag">Product</span> </div> </div> <div class="course-price">$89.99</div> </div> <div class="course-content"> <div class="tab-container"> <div class="tab active" data-tab="overview">Overview</div> <div class="tab" data-tab="curriculum">Curriculum</div> <div class="tab" data-tab="reviews">Reviews</div> </div> <div class="course-stats"> <div class="stat-item"> <span class="stat-value">24</span> <span class="stat-label">Lessons</span> </div> <div class="stat-item"> <span class="stat-value">16</span> <span class="stat-label">Hours</span> </div> <div class="stat-item"> <span class="stat-value">All</span> <span class="stat-label">Levels</span> </div> </div> <div class="course-description"> Learn to create scalable design systems that power modern digital products. This course covers component libraries, accessibility standards, and design tokens with practical examples from leading tech companies. </div> <div class="progress-bar"> <div class="progress"></div> </div> <div class="instructor"> <img src="https://randomuser.me/api/portraits/women/44.jpg" alt="Sarah Johnson" class="instructor-avatar"> <div class="instructor-info"> <h3>Sarah Johnson</h3> <p>Senior Product Designer, formerly at Airbnb</p> <div class="rating"> <span class="star">★</span> <span class="star">★</span> <span class="star">★</span> <span class="star">★</span> <span class="star">★</span> <span class="rating-count">(352 reviews)</span> </div> </div> </div> <div class="course-actions"> <button class="action-btn primary-btn"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8 5.14V19.14L19 12.14L8 5.14Z" fill="white"/> </svg> Continue Learning </button> <button class="action-btn secondary-btn"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M19 9H15V3H9V9H5L12 16L19 9ZM5 18V20H19V18H5Z" fill="#6C63FF"/> </svg> Save </button> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Ripple effect for buttons const buttons = document.querySelectorAll('.action-btn'); buttons.forEach(button => { button.addEventListener('click', function(e) { const x = e.clientX - e.target.getBoundingClientRect().left; const y = e.clientY - e.target.getBoundingClientRect().top; const ripple = document.createElement('span'); ripple.classList.add('btn-ripple'); ripple.style.left = `${x}px`; ripple.style.top = `${y}px`; this.appendChild(ripple); setTimeout(() => { ripple.remove(); }, 600); }); }); // Tab switching const tabs = document.querySelectorAll('.tab'); tabs.forEach(tab => { tab.addEventListener('click', function() { // Show loading state document.querySelector('.course-card').classList.add('loading'); // Remove active class from all tabs tabs.forEach(t => t.classList.remove('active')); // Add active class to clicked tab this.classList.add('active'); // Simulate content loading setTimeout(() => { document.querySelector('.course-card').classList.remove('loading'); }, 600); }); }); // Simulate initial loading document.querySelector('.course-card').classList.add('loading'); setTimeout(() => { document.querySelector('.course-card').classList.remove('loading'); }, 800); // Smooth hover effects for instructor const instructor = document.querySelector('.instructor'); instructor.addEventListener('mouseenter', function() { this.style.transition = 'all 0.3s ease'; }); // Interactive progress bar on hover const progressBar = document.querySelector('.progress-bar'); progressBar.addEventListener('mouseenter', function() { const progress = document.querySelector('.progress'); progress.style.transition = 'width 0.4s ease-in-out'; const originalWidth = progress.style.width; // Show full progress on hover progress.style.width = '100%'; progressBar.addEventListener('mouseleave', function onLeave() { progress.style.width = '68%'; progressBar.removeEventListener('mouseleave', onLeave); }); }); // Animate category tags const categoryTags = document.querySelectorAll('.category-tag'); categoryTags.forEach(tag => { tag.addEventListener('click', function() { this.style.transition = 'all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)'; this.style.transform = 'scale(1.1)'; setTimeout(() => { this.style.transform = 'scale(1)'; }, 300); }); }); // Card tilting effect on mouse move const card = document.querySelector('.course-card'); card.addEventListener('mousemove', function(e) { const x = e.clientX - this.getBoundingClientRect().left; const y = e.clientY - this.getBoundingClientRect().top; const centerX = this.getBoundingClientRect().width / 2; const centerY = this.getBoundingClientRect().height / 2; const rotateX = (y - centerY) / 30; const rotateY = (centerX - x) / 30; this.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`; }); card.addEventListener('mouseleave', function() { this.style.transition = 'transform 0.5s ease'; this.style.transform = 'perspective(1000px) rotateX(0) rotateY(0)'; }); // Prevent default form submission behavior const form = document.querySelector('form'); if (form) { form.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>Social Pulse Aggregator</title> <style> :root { --primary: #6C5CE7; --secondary: #00CEC9; --tertiary: #FD79A8; --light: #F8F9FA; --dark: #2D3436; --gradient: linear-gradient(135deg, var(--primary), var(--secondary)); --shadow: 0 10px 30px rgba(108, 92, 231, 0.15); --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', system-ui, -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: #f5f7fa; color: var(--dark); display: flex; justify-content: center; align-items: center; min-height: 700px; padding: 20px; overflow-x: hidden; } .container { width: 100%; max-width: 700px; min-height: 600px; display: flex; flex-direction: column; gap: 20px; padding: 5px; position: relative; } .header { display: flex; align-items: center; justify-content: space-between; padding: 15px 20px; background: var(--light); border-radius: var(--radius); box-shadow: var(--shadow); position: relative; overflow: hidden; z-index: 2; } .header::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 4px; background: var(--gradient); } .header h1 { font-size: 1.5rem; font-weight: 700; color: var(--primary); margin: 0; } .header .tabs { display: flex; gap: 15px; } .tab { background: transparent; border: none; padding: 8px 12px; font-size: 0.9rem; font-weight: 600; color: var(--dark); opacity: 0.7; cursor: pointer; transition: var(--transition); border-radius: 20px; position: relative; } .tab:hover { opacity: 1; } .tab.active { opacity: 1; color: var(--primary); } .tab.active::after { content: ''; position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); width: 5px; height: 5px; background: var(--primary); border-radius: 50%; } .search-bar { display: flex; align-items: center; padding: 12px 16px; background: var(--light); border-radius: var(--radius); box-shadow: var(--shadow); margin-bottom: 10px; } .search-bar input { flex: 1; border: none; outline: none; background: transparent; font-size: 0.95rem; padding: 8px 0; color: var(--dark); transition: var(--transition); } .search-bar input::placeholder { color: rgba(45, 52, 54, 0.5); } .search-bar .search-icon { display: flex; align-items: center; justify-content: center; margin-right: 10px; color: var(--primary); } .cards-container { display: grid; grid-template-columns: 1fr; gap: 20px; overflow-y: auto; max-height: 450px; padding: 10px 5px; scroll-behavior: smooth; } .cards-container::-webkit-scrollbar { width: 6px; background: transparent; } .cards-container::-webkit-scrollbar-thumb { background: rgba(108, 92, 231, 0.2); border-radius: 3px; } .social-card { background: var(--light); border-radius: var(--radius); box-shadow: var(--shadow); padding: 20px; position: relative; overflow: hidden; transform-origin: center; transition: var(--transition); cursor: pointer; } .social-card:hover { transform: translateY(-5px); box-shadow: 0 15px 35px rgba(108, 92, 231, 0.2); } .social-card::before { content: ''; position: absolute; top: 0; left: 0; width: 4px; height: 100%; background: var(--primary); opacity: 0.8; } .social-card.twitter::before { background: #1DA1F2; } .social-card.instagram::before { background: linear-gradient(45deg, #FFDC80, #F56040, #833AB4); } .social-card.linkedin::before { background: #0077B5; } .social-card.facebook::before { background: #4267B2; } .card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 15px; } .platform-info { display: flex; align-items: center; gap: 10px; } .platform-icon { width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-size: 12px; } .twitter .platform-icon { background: #1DA1F2; } .instagram .platform-icon { background: linear-gradient(45deg, #FFDC80, #F56040, #833AB4); } .linkedin .platform-icon { background: #0077B5; } .facebook .platform-icon { background: #4267B2; } .platform-name { font-weight: 600; font-size: 0.9rem; } .timestamp { font-size: 0.8rem; color: rgba(45, 52, 54, 0.6); } .user-info { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; } .avatar { width: 42px; height: 42px; border-radius: 50%; background-size: cover; background-position: center; border: 2px solid #fff; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .user-details { display: flex; flex-direction: column; } .user-name { font-weight: 600; font-size: 0.95rem; } .user-handle { font-size: 0.8rem; color: rgba(45, 52, 54, 0.6); } .content { font-size: 0.95rem; line-height: 1.5; margin-bottom: 15px; } .media { width: 100%; border-radius: 8px; overflow: hidden; margin-bottom: 15px; position: relative; } .media img, .media video { width: 100%; height: auto; object-fit: cover; transition: var(--transition); } .media:hover img, .media:hover video { transform: scale(1.02); } .actions { display: flex; align-items: center; justify-content: space-between; border-top: 1px solid rgba(0, 0, 0, 0.05); padding-top: 12px; } .action-btn { display: flex; align-items: center; gap: 5px; background: transparent; border: none; font-size: 0.85rem; color: rgba(45, 52, 54, 0.7); padding: 6px 8px; border-radius: 4px; cursor: pointer; transition: var(--transition); } .action-btn:hover { background: rgba(108, 92, 231, 0.1); color: var(--primary); } .twitter .action-btn:hover { color: #1DA1F2; background: rgba(29, 161, 242, 0.1); } .instagram .action-btn:hover { color: #E1306C; background: rgba(225, 48, 108, 0.1); } .linkedin .action-btn:hover { color: #0077B5; background: rgba(0, 119, 181, 0.1); } .facebook .action-btn:hover { color: #4267B2; background: rgba(66, 103, 178, 0.1); } .action-btn i { font-size: 1rem; } .notification-badge { position: absolute; top: 15px; right: 15px; width: 12px; height: 12px; background: var(--tertiary); border-radius: 50%; border: 2px solid white; animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(253, 121, 168, 0.7); } 70% { transform: scale(1.1); box-shadow: 0 0 0 5px rgba(253, 121, 168, 0); } 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(253, 121, 168, 0); } } .empty-state { display: none; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 40px 20px; border-radius: var(--radius); background: var(--light); box-shadow: var(--shadow); gap: 20px; } .empty-state-icon { font-size: 3rem; color: rgba(108, 92, 231, 0.3); } .empty-state h3 { font-size: 1.2rem; color: var(--dark); margin-bottom: 10px; } .empty-state p { font-size: 0.9rem; color: rgba(45, 52, 54, 0.6); max-width: 300px; } .refresh-btn { display: flex; align-items: center; justify-content: center; gap: 8px; background: var(--gradient); color: white; border: none; border-radius: 20px; padding: 10px 20px; font-weight: 600; cursor: pointer; transition: var(--transition); box-shadow: 0 4px 12px rgba(108, 92, 231, 0.3); margin-top: 10px; } .refresh-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(108, 92, 231, 0.4); } .pulse-animation { animation: pulse-anim 1.5s infinite; } @keyframes pulse-anim { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .fade-in { animation: fadeIn 0.5s ease forwards; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .loading-indicator { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: none; flex-direction: column; align-items: center; gap: 15px; } .spinner { width: 40px; height: 40px; border: 3px solid rgba(108, 92, 231, 0.2); border-radius: 50%; border-top-color: var(--primary); animation: spin 1s ease-in-out infinite; } @keyframes spin { to { transform: rotate(360deg); } } .loading-text { font-size: 0.9rem; font-weight: 500; color: var(--primary); } .filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; } .filter-pill { background: white; border: 1px solid rgba(108, 92, 231, 0.2); border-radius: 20px; padding: 6px 12px; font-size: 0.8rem; color: var(--dark); cursor: pointer; transition: var(--transition); } .filter-pill:hover { background: rgba(108, 92, 231, 0.05); } .filter-pill.active { background: var(--primary); color: white; border-color: var(--primary); } .floating-action { position: fixed; bottom: 20px; right: 20px; width: 50px; height: 50px; background: var(--gradient); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; box-shadow: 0 4px 15px rgba(108, 92, 231, 0.4); cursor: pointer; transition: var(--transition); z-index: 10; } .floating-action:hover { transform: translateY(-3px) rotate(90deg); box-shadow: 0 6px 20px rgba(108, 92, 231, 0.5); } .new-content-indicator { position: absolute; top: 75px; left: 50%; transform: translateX(-50%); background: var(--tertiary); color: white; padding: 8px 15px; border-radius: 20px; font-size: 0.85rem; font-weight: 600; box-shadow: 0 4px 12px rgba(253, 121, 168, 0.3); display: none; z-index: 5; cursor: pointer; opacity: 0; transition: var(--transition); } .new-content-indicator.show { display: flex; align-items: center; gap: 8px; animation: slideDown 0.3s forwards, fadeOut 0.3s 3s forwards; } @keyframes slideDown { from { transform: translate(-50%, -20px); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @media (max-width: 600px) { .header { flex-direction: column; gap: 10px; align-items: flex-start; } .header .tabs { width: 100%; overflow-x: auto; padding-bottom: 5px; } .tab { white-space: nowrap; } .social-card { padding: 15px; } .actions { flex-wrap: wrap; gap: 5px; } .action-btn { padding: 5px; font-size: 0.8rem; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>Social Pulse</h1> <div class="tabs"> <button class="tab active" data-tab="all">All Updates</button> <button class="tab" data-tab="mentions">Mentions</button> <button class="tab" data-tab="trending">Trending</button> </div> </div> <div class="search-bar"> <div class="search-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="11" cy="11" r="8"></circle> <line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </div> <input type="text" placeholder="Search across your social feeds..."> </div> <div class="filters"> <button class="filter-pill active" data-filter="all">All Platforms</button> <button class="filter-pill" data-filter="twitter">Twitter</button> <button class="filter-pill" data-filter="instagram">Instagram</button> <button class="filter-pill" data-filter="linkedin">LinkedIn</button> <button class="filter-pill" data-filter="facebook">Facebook</button> </div> <div class="cards-container"> <!-- Twitter Card --> <div class="social-card twitter fade-in" data-platform="twitter"> <div class="notification-badge"></div> <div class="card-header"> <div class="platform-info"> <div class="platform-icon"> <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <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> </div> <span class="platform-name">Twitter</span> </div> <span class="timestamp">10 min ago</span> </div> <div class="user-info"> <div class="avatar" style="background-image: url('https://randomuser.me/api/portraits/women/44.jpg')"></div> <div class="user-details"> <span class="user-name">Sarah Johnson</span> <span class="user-handle">@sarahjdesign</span> </div> </div> <div class="content"> Our new responsive component library just launched! This toolkit has been a labor of love - featuring accessibly designed UI elements that adapt flawlessly across devices. #WebDesign #FrontEnd </div> <div class="media"> <img src="https://images.unsplash.com/photo-1558655146-d09347e92766?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" alt="UI Design Component Library"> </div> <div class="actions"> <button class="action-btn"> <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="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>247</span> </button> <button class="action-btn"> <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="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> </svg> <span>42</span> </button> <button class="action-btn"> <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="M17 2l4 4-4 4"></path> <path d="M3 11v-1a4 4 0 0 1 4-4h14"></path> <path d="M7 22l-4-4 4-4"></path> <path d="M21 13v1a4 4 0 0 1-4 4H3"></path> </svg> <span>89</span> </button> <button class="action-btn"> <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="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"></path> <polyline points="16 6 12 2 8 6"></polyline> <line x1="12" y1="2" x2="12" y2="15"></line> </svg> <span>Share</span> </button> </div> </div> <!-- Instagram Card --> <div class="social-card instagram fade-in" data-platform="instagram"> <div class="card-header"> <div class="platform-info"> <div class="platform-icon"> <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect> <path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path> <line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line> </svg> </div> <span class="platform-name">Instagram</span> </div> <span class="timestamp">2 hours ago</span> </div> <div class="user-info"> <div class="avatar" style="background-image: url('https://randomuser.me/api/portraits/men/32.jpg')"></div> <div class="user-details"> <span class="user-name">Alex Rivera</span> <span class="user-handle">@urban.explorer</span> </div> </div> <div class="content"> City lights at dusk never get old. Found this perfect spot while wandering through downtown. The way the neon reflects off the rain-slicked streets creates a cyberpunk vibe I couldn't resist capturing. </div> <div class="media"> <img src="https://images.unsplash.com/photo-1573108037329-51c155c4aef2?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" alt="City lights at night"> </div> <div class="actions"> <button class="action-btn"> <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="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,248</span> </button> <button class="action-btn"> <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="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> </svg> <span>97</span> </button> <button class="action-btn"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="22 12 16 12 14 15 10 15 8 12 2 12"></polyline> <path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"></path> </svg> <span>Save</span> </button> <button class="action-btn"> <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="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"></path> <polyline points="16 6 12 2 8 6"></polyline> <line x1="12" y1="2" x2="12" y2="15"></line> </svg> <span>Share</span> </button> </div> </div> <!-- LinkedIn Card --> <div class="social-card linkedin fade-in" data-platform="linkedin"> <div class="card-header"> <div class="platform-info"> <div class="platform-icon"> <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <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> </div> <span class="platform-name">LinkedIn</span> </div> <span class="timestamp">Yesterday</span> </div> <div class="user-info"> <div class="avatar" style="background-image: url('https://randomuser.me/api/portraits/women/68.jpg')"></div> <div class="user-details"> <span class="user-name">Mira Patel</span> <span class="user-handle">Product Manager at TechInnovate</span> </div> </div> <div class="content"> Excited to announce that our team has successfully launched our new AI-powered analytics dashboard after six months of development. The feedback from our beta testers has been overwhelmingly positive. Looking forward to seeing how it transforms data workflows for our enterprise clients! </div> <div class="media"> <img src="https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" alt="Analytics Dashboard"> </div> <div class="actions"> <button class="action-btn"> <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="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"></path> </svg> <span>423</span> </button> <button class="action-btn"> <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="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> </svg> <span>68</span> </button> <button class="action-btn"> <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="M17 2l4 4-4 4"></path> <path d="M3 11v-1a4 4 0 0 1 4-4h14"></path> <path d="M7 22l-4-4 4-4"></path> <path d="M21 13v1a4 4 0 0 1-4 4H3"></path> </svg> <span>127</span> </button> <button class="action-btn"> <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="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"></path> <polyline points="16 6 12 2 8 6"></polyline> <line x1="12" y1="2" x2="12" y2="15"></line> </svg> <span>Share</span> </button> </div> </div> <!-- Facebook Card --> <div class="social-card facebook fade-in" data-platform="facebook"> <div class="card-header"> <div class="platform-info"> <div class="platform-icon"> <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path> </svg> </div> <span class="platform-name">Facebook</span> </div> <span class="timestamp">3 days ago</span> </div> <div class="user-info"> <div class="avatar" style="background-image: url('https://randomuser.me/api/portraits/men/75.jpg')"></div> <div class="user-details"> <span class="user-name">David Wilson</span> <span class="user-handle">Culinary Arts Instructor</span> </div> </div> <div class="content"> Tonight's cooking workshop was a huge success! We explored regional Italian pasta techniques, and everyone created their own handmade pappardelle from scratch. Nothing beats the satisfaction of turning simple flour and eggs into something so delicious. Thanks to everyone who participated! </div> <div class="media"> <img src="https://images.unsplash.com/photo-1556761223-4c4282c73f77?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" alt="Handmade Pasta Workshop"> </div> <div class="actions"> <button class="action-btn"> <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="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"></path> </svg> <span>316</span> </button> <button class="action-btn"> <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="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> </svg> <span>42</span> </button> <button class="action-btn"> <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="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"></path> <polyline points="16 6 12 2 8 6"></polyline> <line x1="12" y1="2" x2="12" y2="15"></line> </svg> <span>Share</span> </button> </div> </div> </div> <div class="loading-indicator"> <div class="spinner"></div> <span class="loading-text">Fetching
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Premium Headphones Product Card</title> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background-color: #f7f7f7; padding: 20px; } .container { width: 100%; max-width: 700px; display: flex; flex-wrap: wrap; justify-content: center; gap: 20px; } .product-card { position: relative; width: 320px; border-radius: 16px; overflow: hidden; background-color: white; box-shadow: 0 1px 3px rgba(0,0,0,0.12); transition: transform 0.3s ease, box-shadow 0.3s ease; cursor: pointer; } .product-card:hover { transform: translateY(-8px); box-shadow: 0 10px 25px rgba(0,0,0,0.08); } .image-container { position: relative; height: 220px; overflow: hidden; background-color: #f5f5f5; } .product-image { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s cubic-bezier(0.165, 0.84, 0.44, 1); } .product-card:hover .product-image { transform: scale(1.05); } .color-options { position: absolute; bottom: 10px; right: 10px; display: flex; gap: 5px; } .color-option { width: 18px; height: 18px; border-radius: 50%; border: 2px solid white; cursor: pointer; transition: transform 0.2s ease; } .color-option:hover { transform: scale(1.2); } .color-option.active { transform: scale(1.2); box-shadow: 0 0 0 2px white, 0 0 0 3px #aaa; } .badge { position: absolute; top: 12px; left: 12px; background-color: #6200ea; color: white; font-size: 0.7rem; font-weight: 600; padding: 4px 10px; border-radius: 4px; letter-spacing: 0.5px; text-transform: uppercase; opacity: 0; transform: translateY(-10px); transition: opacity 0.3s ease, transform 0.3s ease; } .product-card:hover .badge { opacity: 1; transform: translateY(0); } .content { padding: 16px; } .product-tag { font-size: 0.7rem; font-weight: 600; color: #6200ea; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; } .product-name { font-size: 1.15rem; font-weight: 600; color: #212121; margin-bottom: 8px; transition: color 0.2s ease; } .product-card:hover .product-name { color: #6200ea; } .product-description { font-size: 0.85rem; color: #616161; line-height: 1.5; margin-bottom: 16px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .product-price { display: flex; align-items: center; margin-bottom: 16px; } .current-price { font-size: 1.35rem; font-weight: 700; color: #212121; } .original-price { font-size: 0.9rem; color: #9e9e9e; text-decoration: line-through; margin-left: 8px; } .discount { font-size: 0.7rem; font-weight: 600; color: #388e3c; background-color: #e8f5e9; padding: 3px 6px; border-radius: 4px; margin-left: 8px; } .action-bar { display: flex; justify-content: space-between; align-items: center; } .rating { display: flex; align-items: center; font-size: 0.8rem; font-weight: 500; color: #616161; } .rating-stars { position: relative; display: inline-block; font-size: 0; margin-right: 4px; } .stars-fill { position: absolute; top: 0; left: 0; color: #ffc107; overflow: hidden; white-space: nowrap; } .stars-empty { color: #e0e0e0; } .action-buttons { display: flex; gap: 10px; } .action-btn { width: 36px; height: 36px; border-radius: 50%; background-color: #f5f5f5; border: none; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: background-color 0.2s ease, transform 0.2s ease; position: relative; overflow: hidden; } .action-btn:hover { background-color: #e0e0e0; transform: scale(1.05); } .action-btn:active { transform: scale(0.95); } .action-btn i { color: #616161; font-size: 1.1rem; transition: color 0.2s ease; } .action-btn.favorite i { color: #F44336; opacity: 0; position: absolute; } .action-btn.favorite i.outline { opacity: 1; } .action-btn.favorite.active i.fill { opacity: 1; } .action-btn.favorite.active i.outline { opacity: 0; } .add-to-cart { background-color: #6200ea; color: white; font-size: 0.85rem; font-weight: 600; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; transition: background-color 0.2s ease, transform 0.2s ease; display: flex; align-items: center; gap: 8px; } .add-to-cart i { font-size: 1rem; } .add-to-cart:hover { background-color: #5000d6; } .add-to-cart:active { transform: scale(0.98); } /* Add this for the cart animation */ .cart-indicator { position: fixed; width: 12px; height: 12px; background-color: #6200ea; border-radius: 50%; z-index: 100; pointer-events: none; opacity: 0; } @media (max-width: 700px) { .container { padding: 10px; } .product-card { width: 100%; } } </style> <!-- Material Icons --> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> </head> <body> <div class="container"> <div class="product-card"> <div class="image-container"> <img src="https://images.unsplash.com/photo-1578319439584-104c94d37305?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="SoundPulse Pro X500 Wireless Headphones" class="product-image"> <div class="badge">Best Seller</div> <div class="color-options"> <div class="color-option active" style="background-color: #212121;" data-color="black"></div> <div class="color-option" style="background-color: #f5f5f5;" data-color="white"></div> <div class="color-option" style="background-color: #1976d2;" data-color="blue"></div> </div> </div> <div class="content"> <div class="product-tag">Premium Audio</div> <h3 class="product-name">SoundPulse Pro X500</h3> <p class="product-description">Active noise cancellation with adaptive sound and 40hr battery life. Industry-leading 50mm dynamic drivers for unparalleled audio clarity.</p> <div class="product-price"> <span class="current-price">$249.99</span> <span class="original-price">$329.99</span> <span class="discount">24% off</span> </div> <div class="action-bar"> <div class="rating"> <div class="rating-stars"> <div class="stars-empty">★★★★★</div> <div class="stars-fill" style="width: 94%;">★★★★★</div> </div> <span>4.7 (349)</span> </div> <div class="action-buttons"> <button class="action-btn favorite"> <i class="material-icons outline">favorite_border</i> <i class="material-icons fill">favorite</i> </button> <button class="add-to-cart"> <i class="material-icons">shopping_cart</i> Add to Cart </button> </div> </div> </div> </div> <div class="product-card"> <div class="image-container"> <img src="https://images.unsplash.com/photo-1600086827875-a63b01f1335c?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="SoundPulse Air Buds" class="product-image"> <div class="badge">New Release</div> <div class="color-options"> <div class="color-option active" style="background-color: #f5f5f5;" data-color="white"></div> <div class="color-option" style="background-color: #212121;" data-color="black"></div> <div class="color-option" style="background-color: #7b1fa2;" data-color="purple"></div> </div> </div> <div class="content"> <div class="product-tag">Wireless Audio</div> <h3 class="product-name">SoundPulse Air Buds</h3> <p class="product-description">True wireless earbuds with spatial audio and automatic device switching. Custom-designed acoustic architecture for immersive sound.</p> <div class="product-price"> <span class="current-price">$129.99</span> <span class="original-price">$159.99</span> <span class="discount">19% off</span> </div> <div class="action-bar"> <div class="rating"> <div class="rating-stars"> <div class="stars-empty">★★★★★</div> <div class="stars-fill" style="width: 90%;">★★★★★</div> </div> <span>4.5 (217)</span> </div> <div class="action-buttons"> <button class="action-btn favorite"> <i class="material-icons outline">favorite_border</i> <i class="material-icons fill">favorite</i> </button> <button class="add-to-cart"> <i class="material-icons">shopping_cart</i> Add to Cart </button> </div> </div> </div> </div> </div> <div class="cart-indicator"></div> <script> // Color option switcher document.querySelectorAll('.color-option').forEach(option => { option.addEventListener('click', function() { // Get all color options in same product card const card = this.closest('.product-card'); const options = card.querySelectorAll('.color-option'); // Remove active class from all options options.forEach(opt => opt.classList.remove('active')); // Add active class to clicked option this.classList.add('active'); // Change product image based on color (in real implementation) // For this demo, we'll just show which color was selected const colorName = this.getAttribute('data-color'); console.log(`Selected color: ${colorName}`); }); }); // Favorite button toggle document.querySelectorAll('.action-btn.favorite').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); this.classList.toggle('active'); // Add heart animation if(this.classList.contains('active')) { const heart = document.createElement('div'); heart.style.position = 'absolute'; heart.style.top = '50%'; heart.style.left = '50%'; heart.style.transform = 'translate(-50%, -50%)'; heart.style.color = '#F44336'; heart.style.fontSize = '24px'; heart.style.pointerEvents = 'none'; heart.innerHTML = '❤'; heart.style.opacity = '0'; heart.style.transition = 'all 0.5s ease'; this.appendChild(heart); setTimeout(() => { heart.style.opacity = '1'; heart.style.transform = 'translate(-50%, -150%) scale(1.5)'; }, 10); setTimeout(() => { heart.style.opacity = '0'; }, 500); setTimeout(() => { heart.remove(); }, 1000); } }); }); // Add to cart animation document.querySelectorAll('.add-to-cart').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); // Create cart indicator const indicator = document.querySelector('.cart-indicator'); // Get button position const buttonRect = this.getBoundingClientRect(); const buttonX = buttonRect.left + buttonRect.width / 2; const buttonY = buttonRect.top + buttonRect.height / 2; // Set indicator position indicator.style.left = `${buttonX}px`; indicator.style.top = `${buttonY}px`; indicator.style.opacity = '1'; indicator.style.transform = 'scale(1)'; // Animate to top right (where cart would be) setTimeout(() => { indicator.style.transition = 'all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1)'; indicator.style.left = `${window.innerWidth - 20}px`; indicator.style.top = `20px`; indicator.style.transform = 'scale(0)'; }, 10); // Reset after animation setTimeout(() => { indicator.style.transition = 'none'; indicator.style.opacity = '0'; }, 700); // Add ripple effect to the button const ripple = document.createElement('span'); ripple.className = 'ripple'; ripple.style.position = 'absolute'; ripple.style.top = `${e.offsetY}px`; ripple.style.left = `${e.offsetX}px`; ripple.style.background = 'rgba(255, 255, 255, 0.3)'; ripple.style.borderRadius = '50%'; ripple.style.transform = 'translate(-50%, -50%) scale(0)'; ripple.style.width = `${Math.max(buttonRect.width, buttonRect.height) * 2}px`; ripple.style.height = `${Math.max(buttonRect.width, buttonRect.height) * 2}px`; ripple.style.pointerEvents = 'none'; ripple.style.transition = 'transform 0.6s, opacity 0.6s'; this.appendChild(ripple); setTimeout(() => { ripple.style.transform = 'translate(-50%, -50%) scale(1)'; ripple.style.opacity = '0'; }, 10); setTimeout(() => { ripple.remove(); }, 600); // Show feedback that item was added const originalText = this.innerHTML; this.innerHTML = '<i class="material-icons">check</i>Added'; this.style.backgroundColor = '#388e3c'; setTimeout(() => { this.innerHTML = originalText; this.style.backgroundColor = ''; }, 1500); }); }); // Product card click (in real implementation would go to product page) document.querySelectorAll('.product-card').forEach(card => { card.addEventListener('click', function() { console.log('Navigating to product details page'); // In a real implementation: window.location.href = '/product/details/123'; }); }); </script> </body> </html>
<html> <head> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } :root { --bg-color: #121212; --text-color: #f0f0f0; --accent-color: #ff3e55; --secondary-accent: #4a6bff; --card-bg: #1d1d1d; --card-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); --transition-time: 0.2s; } body { background-color: var(--bg-color); color: var(--text-color); display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 20px; overflow-x: hidden; } .container { width: 100%; max-width: 650px; height: auto; max-height: 680px; overflow-y: auto; overflow-x: hidden; padding: 20px 0; scrollbar-width: thin; } .container::-webkit-scrollbar { width: 4px; } .container::-webkit-scrollbar-track { background: #0a0a0a; } .container::-webkit-scrollbar-thumb { background: #444; border-radius: 10px; } .news-header { margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center; padding: 0 15px; } .news-logo { font-size: 24px; font-weight: 700; letter-spacing: -0.5px; } .news-logo span { color: var(--accent-color); } .date-badge { background-color: #333; padding: 6px 12px; font-size: 12px; border-radius: 20px; font-weight: 500; letter-spacing: 0.5px; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2); } .news-card { background-color: var(--card-bg); border-radius: 12px; margin-bottom: 20px; overflow: hidden; box-shadow: var(--card-shadow); transform: translateY(0); transition: transform var(--transition-time) ease, box-shadow var(--transition-time) ease; position: relative; will-change: transform; } .news-card.featured { border-left: 3px solid var(--accent-color); } .news-card.breaking { border-left: 3px solid var(--secondary-accent); } .news-card:hover { transform: translateY(-5px); box-shadow: 0 14px 28px rgba(0, 0, 0, 0.4); cursor: pointer; } .news-card:active { transform: translateY(0); transition: transform 0.1s ease; } .card-img-container { height: 200px; overflow: hidden; position: relative; } .card-img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.8s ease; filter: grayscale(0.4); } .news-card:hover .card-img { transform: scale(1.05); filter: grayscale(0); } .category-badge { position: absolute; top: 15px; left: 15px; padding: 6px 12px; border-radius: 5px; font-size: 11px; text-transform: uppercase; font-weight: 600; letter-spacing: 0.8px; z-index: 2; } .featured .category-badge { background-color: var(--accent-color); } .breaking .category-badge { background-color: var(--secondary-accent); } .time-badge { position: absolute; top: 15px; right: 15px; background-color: rgba(0, 0, 0, 0.7); padding: 4px 8px; border-radius: 4px; font-size: 11px; } .card-content { padding: 20px; } .card-title { font-size: 20px; font-weight: 700; margin-bottom: 12px; line-height: 1.3; letter-spacing: -0.3px; position: relative; display: inline; background-image: linear-gradient(transparent 70%, rgba(255, 62, 85, 0.2) 0); background-size: 0 100%; background-repeat: no-repeat; transition: background-size 0.4s ease; } .news-card:hover .card-title { background-size: 100% 100%; } .breaking .card-title { background-image: linear-gradient(transparent 70%, rgba(74, 107, 255, 0.2) 0); } .card-excerpt { font-size: 14px; line-height: 1.5; color: #bebebe; margin-bottom: 15px; } .card-footer { display: flex; justify-content: space-between; align-items: center; border-top: 1px solid #333; padding-top: 15px; font-size: 12px; } .author { display: flex; align-items: center; } .author-img { width: 24px; height: 24px; border-radius: 50%; margin-right: 8px; object-fit: cover; } .read-more { color: var(--text-color); display: flex; align-items: center; opacity: 0.7; transition: opacity var(--transition-time) ease; } .read-more:hover { opacity: 1; } .read-more svg { margin-left: 6px; transition: transform var(--transition-time) ease; } .news-card:hover .read-more svg { transform: translateX(4px); } .loading-dots { display: flex; justify-content: center; align-items: center; margin: 30px 0; } .dot { width: 8px; height: 8px; margin: 0 3px; border-radius: 50%; background-color: #555; animation: pulse 1.5s infinite ease-in-out; } .dot:nth-child(2) { animation-delay: 0.2s; } .dot:nth-child(3) { animation-delay: 0.4s; } @keyframes pulse { 0%, 100% { transform: scale(0.8); opacity: 0.5; } 50% { transform: scale(1.2); opacity: 1; } } .ripple { position: absolute; background: rgba(255, 255, 255, 0.15); border-radius: 50%; transform: scale(0); pointer-events: none; animation: ripple-animation 0.6s linear; } @keyframes ripple-animation { to { transform: scale(4); opacity: 0; } } @media (max-width: 600px) { .card-img-container { height: 160px; } .card-title { font-size: 18px; } .card-excerpt { font-size: 13px; } .card-content { padding: 15px; } } </style> </head> <body> <div class="container"> <div class="news-header"> <div class="news-logo">MONO<span>PULSE</span></div> <div class="date-badge">JUNE 14, 2024</div> </div> <div class="news-card featured" data-id="1"> <div class="card-img-container"> <div class="category-badge">Featured</div> <div class="time-badge">4 hours ago</div> <img class="card-img" src="https://images.unsplash.com/photo-1648737966769-98fa89ae8d7a?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80" alt="Climate Summit"> </div> <div class="card-content"> <h2 class="card-title">Global Climate Summit Reaches Landmark Agreement to Reduce Emissions by 2030</h2> <p class="card-excerpt">After intense negotiations, world leaders announced a historic climate pact that introduces binding targets for major industrial nations and creates a $100 billion fund for developing countries.</p> <div class="card-footer"> <div class="author"> <img class="author-img" src="https://images.unsplash.com/photo-1527980965255-d3b416303d12?ixlib=rb-4.0.3&auto=format&fit=crop&w=100&q=80" alt="Author"> <span>Emma Richards</span> </div> <div class="read-more"> Read Article <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> </div> </div> </div> <div class="news-card breaking" data-id="2"> <div class="card-img-container"> <div class="category-badge">Breaking</div> <div class="time-badge">1 hour ago</div> <img class="card-img" src="https://images.unsplash.com/photo-1607799279861-4dd421887fb3?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80" alt="Tech Innovation"> </div> <div class="card-content"> <h2 class="card-title">Quantum Computing Breakthrough Could Transform Medical Research</h2> <p class="card-excerpt">Scientists have achieved a quantum processing milestone that allows for complex molecular simulations, potentially accelerating drug discovery and treatment development for previously incurable diseases.</p> <div class="card-footer"> <div class="author"> <img class="author-img" src="https://images.unsplash.com/photo-1599566150163-29194dcaad36?ixlib=rb-4.0.3&auto=format&fit=crop&w=100&q=80" alt="Author"> <span>David Chen</span> </div> <div class="read-more"> Read Article <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> </div> </div> </div> <div class="news-card" data-id="3"> <div class="card-img-container"> <div class="category-badge" style="background-color: #444;">Economy</div> <div class="time-badge">Yesterday</div> <img class="card-img" src="https://images.unsplash.com/photo-1611974789855-9c2a0a7236a3?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80" alt="Financial Markets"> </div> <div class="card-content"> <h2 class="card-title">Central Banks Announce Coordinated Policy Shift to Combat Inflation</h2> <p class="card-excerpt">In an unprecedented move, major global central banks have synchronized their monetary strategies to address persistent inflation pressures without triggering a recession.</p> <div class="card-footer"> <div class="author"> <img class="author-img" src="https://images.unsplash.com/photo-1580489944761-15a19d654956?ixlib=rb-4.0.3&auto=format&fit=crop&w=100&q=80" alt="Author"> <span>Julia Mendez</span> </div> <div class="read-more"> Read Article <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> </div> </div> </div> <div class="loading-dots"> <div class="dot"></div> <div class="dot"></div> <div class="dot"></div> </div> </div> <script> document.addEventListener('DOMContentLoaded', () => { // Create ripple effect on card click const cards = document.querySelectorAll('.news-card'); cards.forEach(card => { card.addEventListener('click', function(e) { // Create ripple element const ripple = document.createElement('span'); ripple.classList.add('ripple'); // Set ripple position based on click coordinates const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; ripple.style.left = `${x}px`; ripple.style.top = `${y}px`; // Add ripple to card this.appendChild(ripple); // Remove ripple after animation completes setTimeout(() => { ripple.remove(); }, 600); // Show "article view" effect (in this case, just highlight) this.style.boxShadow = '0 0 0 2px var(--accent-color), var(--card-shadow)'; setTimeout(() => { this.style.boxShadow = ''; }, 300); }); }); // Intersection Observer for animation when cards come into view const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; } }); }, { threshold: 0.1 }); // Set initial state and observe cards cards.forEach((card, index) => { card.style.opacity = '0'; card.style.transform = 'translateY(20px)'; card.style.transition = `opacity 0.5s ease ${index * 0.1}s, transform 0.5s ease ${index * 0.1}s, box-shadow var(--transition-time) ease, transform var(--transition-time) ease`; observer.observe(card); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Fitness Tracker Dashboard</title> <style> * { 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: 700px; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); overflow: hidden; } .dashboard { width: 650px; max-width: 100%; background: #fff; border-radius: 20px; box-shadow: 0 15px 35px rgba(50, 50, 93, 0.1), 0 5px 15px rgba(0, 0, 0, 0.07); overflow: hidden; position: relative; transition: all 0.3s ease; } .dashboard:hover { transform: translateY(-5px); box-shadow: 0 20px 40px rgba(50, 50, 93, 0.15), 0 10px 20px rgba(0, 0, 0, 0.1); } .header { background: linear-gradient(90deg, #FF416C 0%, #FF4B2B 100%); padding: 25px 30px; color: white; position: relative; overflow: hidden; } .header h1 { font-size: 1.8rem; font-weight: 700; margin-bottom: 5px; position: relative; z-index: 2; } .header p { opacity: 0.9; font-size: 0.95rem; margin-bottom: 15px; position: relative; z-index: 2; } .header::before { content: ''; position: absolute; top: -50%; right: -50%; width: 200px; height: 200px; background: rgba(255, 255, 255, 0.1); border-radius: 50%; z-index: 1; animation: pulse 15s infinite; } .header::after { content: ''; position: absolute; bottom: -30%; left: 10%; width: 150px; height: 150px; background: rgba(255, 255, 255, 0.1); border-radius: 50%; z-index: 1; animation: pulse 10s infinite 2s; } .date-selector { display: flex; justify-content: space-between; align-items: center; position: relative; z-index: 2; } .date-selector p { margin: 0; font-weight: 600; font-size: 1.1rem; } .date-nav { display: flex; gap: 15px; } .date-nav button { background: rgba(255, 255, 255, 0.2); border: none; width: 32px; height: 32px; border-radius: 50%; color: white; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; } .date-nav button:hover { background: rgba(255, 255, 255, 0.3); transform: scale(1.05); } .stats-container { padding: 25px 30px; display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 20px; } .stat-card { padding: 20px; border-radius: 15px; position: relative; overflow: hidden; transition: all 0.3s ease; background: #f8f9fa; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); cursor: pointer; } .stat-card:hover { transform: translateY(-5px); box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1); } .stat-card.steps { background: linear-gradient(135deg, #43cea2 0%, #185a9d 100%); color: white; } .stat-card.calories { background: linear-gradient(135deg, #ff9966 0%, #ff5e62 100%); color: white; } .stat-card.active { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; } .stat-card h2 { font-size: 0.9rem; font-weight: 600; margin-bottom: 15px; display: flex; align-items: center; } .stat-card h2 i { margin-right: 8px; font-size: 1.1rem; } .stat-value { font-size: 2rem; font-weight: 700; margin-bottom: 5px; position: relative; } .progress-container { height: 8px; background: rgba(255, 255, 255, 0.3); border-radius: 4px; margin: 10px 0; overflow: hidden; } .progress-bar { height: 100%; border-radius: 4px; background: white; width: 0; transition: width 1.5s cubic-bezier(0.65, 0, 0.35, 1); } .stat-target { font-size: 0.8rem; opacity: 0.9; } .activity-chart { padding: 0 30px 25px; } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .chart-header h2 { font-size: 1.1rem; color: #333; } .chart-filters { display: flex; gap: 10px; } .chart-filter { padding: 6px 12px; background: #f1f3f5; border: none; border-radius: 20px; font-size: 0.85rem; color: #495057; cursor: pointer; transition: all 0.2s ease; } .chart-filter.active { background: #FF416C; color: white; } .chart-filter:hover:not(.active) { background: #e9ecef; } .chart-container { height: 180px; position: relative; } .chart-bar { position: absolute; bottom: 0; width: 10px; background: #FF416C; border-radius: 5px 5px 0 0; transition: height 1s cubic-bezier(0.34, 1.56, 0.64, 1); cursor: pointer; } .chart-bar::before { content: attr(data-value); position: absolute; top: -25px; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.75rem; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; } .chart-bar:hover::before { opacity: 1; } .chart-bar.highlight { background: #43cea2; } .day-labels { display: flex; justify-content: space-between; margin-top: 10px; } .day-label { font-size: 0.8rem; color: #6c757d; text-align: center; width: 14.28%; } @keyframes pulse { 0% { transform: scale(1); opacity: 0.6; } 50% { transform: scale(1.1); opacity: 0.4; } 100% { transform: scale(1); opacity: 0.6; } } .badge { position: absolute; top: 15px; right: 15px; background: rgba(255, 255, 255, 0.25); color: white; padding: 3px 8px; border-radius: 12px; font-size: 0.7rem; display: flex; align-items: center; gap: 4px; } .badge.positive { background: rgba(80, 220, 100, 0.3); } .badge.negative { background: rgba(255, 100, 100, 0.3); } .stat-pattern { position: absolute; right: -30px; bottom: -30px; width: 100px; height: 100px; background-image: radial-gradient(circle, rgba(255, 255, 255, 0.15) 2px, transparent 2px); background-size: 15px 15px; z-index: 0; opacity: 0.5; } .pulse-animation { animation: pulse 2s infinite; } @media (max-width: 700px) { .dashboard { width: 95%; margin: 0 10px; } .stats-container { grid-template-columns: 1fr; padding: 20px; gap: 15px; } .header { padding: 20px; } .activity-chart { padding: 0 20px 20px; } .stat-card h2 { font-size: 0.85rem; } .stat-value { font-size: 1.7rem; } } </style> </head> <body> <div class="dashboard"> <div class="header"> <h1>Fitness Snapshot</h1> <p>Keep the momentum going, you're doing great!</p> <div class="date-selector"> <p id="current-date">Today, May 10</p> <div class="date-nav"> <button id="prev-day">←</button> <button id="next-day">→</button> </div> </div> </div> <div class="stats-container"> <div class="stat-card steps"> <h2><i>👣</i> Steps</h2> <div class="stat-value" id="steps-value">0</div> <div class="progress-container"> <div class="progress-bar" id="steps-progress"></div> </div> <div class="stat-target">Goal: 10,000 steps</div> <div class="badge positive"><i>↑</i> 12% from avg</div> <div class="stat-pattern"></div> </div> <div class="stat-card calories"> <h2><i>🔥</i> Calories</h2> <div class="stat-value" id="calories-value">0</div> <div class="progress-container"> <div class="progress-bar" id="calories-progress"></div> </div> <div class="stat-target">Goal: 2,500 cal</div> <div class="badge negative"><i>↓</i> 5% from avg</div> <div class="stat-pattern"></div> </div> <div class="stat-card active"> <h2><i>⏱️</i> Active Minutes</h2> <div class="stat-value" id="active-value">0</div> <div class="progress-container"> <div class="progress-bar" id="active-progress"></div> </div> <div class="stat-target">Goal: 60 min</div> <div class="badge positive"><i>↑</i> 8% from avg</div> <div class="stat-pattern"></div> </div> </div> <div class="activity-chart"> <div class="chart-header"> <h2>Weekly Activity</h2> <div class="chart-filters"> <button class="chart-filter active" data-metric="steps">Steps</button> <button class="chart-filter" data-metric="calories">Calories</button> <button class="chart-filter" data-metric="active">Active</button> </div> </div> <div class="chart-container" id="chart-container"> <!-- Chart bars will be generated by JS --> </div> <div class="day-labels" id="day-labels"> <!-- Day labels will be generated by JS --> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initial data const today = new Date(); let currentDate = today; updateDateDisplay(); // Sample data for the dashboard const userData = { steps: 8743, caloriesBurned: 1975, activeMinutes: 52, weeklyData: { steps: [6543, 8912, 7432, 9120, 10245, 7652, 8743], calories: [1620, 2100, 1860, 2250, 2400, 1930, 1975], active: [45, 53, 48, 62, 70, 50, 52] } }; // Goals const goals = { steps: 10000, calories: 2500, active: 60 }; // Initialize charts and stats animateStats(); renderChart('steps'); // Date navigation document.getElementById('prev-day').addEventListener('click', function() { currentDate.setDate(currentDate.getDate() - 1); updateDateDisplay(); animateStats(0.7); // Simulate different data for different days }); document.getElementById('next-day').addEventListener('click', function() { // Don't allow navigating to future dates if (currentDate < today) { currentDate.setDate(currentDate.getDate() + 1); updateDateDisplay(); animateStats(1.3); // Simulate different data for different days } }); // Chart filter buttons document.querySelectorAll('.chart-filter').forEach(button => { button.addEventListener('click', function() { document.querySelectorAll('.chart-filter').forEach(btn => btn.classList.remove('active')); this.classList.add('active'); renderChart(this.dataset.metric); }); }); // Function to update the date display function updateDateDisplay() { const options = { weekday: 'long', month: 'short', day: 'numeric' }; let dateStr = currentDate.toLocaleDateString('en-US', options); if (currentDate.toDateString() === today.toDateString()) { dateStr = 'Today, ' + dateStr.split(', ')[1]; } else if (new Date(today - 86400000).toDateString() === currentDate.toDateString()) { dateStr = 'Yesterday, ' + dateStr.split(', ')[1]; } document.getElementById('current-date').textContent = dateStr; } // Function to animate stats function animateStats(multiplier = 1) { animateStat('steps', Math.round(userData.steps * multiplier), goals.steps); animateStat('calories', Math.round(userData.caloriesBurned * multiplier), goals.calories); animateStat('active', Math.round(userData.activeMinutes * multiplier), goals.active); } // Function to animate a single stat function animateStat(id, value, goal) { const progressBar = document.getElementById(`${id}-progress`); const valueElement = document.getElementById(`${id}-value`); // Reset for animation valueElement.textContent = '0'; progressBar.style.width = '0%'; // Animate number const duration = 1500; const frameDuration = 1000 / 60; const totalFrames = Math.round(duration / frameDuration); let frame = 0; const counter = setInterval(() => { frame++; const progress = Math.min(frame / totalFrames, 1); const currentValue = Math.floor(value * progress); const progressPercentage = Math.min((value / goal) * 100, 100); valueElement.textContent = currentValue.toLocaleString(); if (frame === totalFrames) { clearInterval(counter); // Add end animation valueElement.classList.add('pulse-animation'); setTimeout(() => { valueElement.classList.remove('pulse-animation'); }, 1000); } }, frameDuration); // Animate progress bar separately (with a slight delay for effect) setTimeout(() => { const progressPercentage = Math.min((value / goal) * 100, 100); progressBar.style.width = `${progressPercentage}%`; }, 300); } // Function to render weekly chart function renderChart(metric) { const chartContainer = document.getElementById('chart-container'); const dayLabelsContainer = document.getElementById('day-labels'); chartContainer.innerHTML = ''; dayLabelsContainer.innerHTML = ''; const data = userData.weeklyData[metric]; const maxValue = Math.max(...data) * 1.1; // 10% headroom const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; data.forEach((value, index) => { // Create chart bar const bar = document.createElement('div'); bar.className = 'chart-bar'; if (index === data.length - 1) bar.classList.add('highlight'); bar.style.left = `${index * (100 / 7) + 5}%`; bar.style.height = '0'; bar.dataset.value = value; chartContainer.appendChild(bar); // Add day label const dayLabel = document.createElement('div'); dayLabel.className = 'day-label'; dayLabel.textContent = days[index]; dayLabelsContainer.appendChild(dayLabel); // Animate bars after a small delay setTimeout(() => { bar.style.height = `${(value / maxValue) * 100}%`; }, 100 + index * 100); }); } // Add hover effect for stat cards document.querySelectorAll('.stat-card').forEach(card => { card.addEventListener('mouseover', function() { this.style.transform = 'translateY(-8px) scale(1.02)'; }); card.addEventListener('mouseout', function() { this.style.transform = ''; }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Weather Forecast Card</title> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } :root { --primary: #3B82F6; --primary-light: #93C5FD; --secondary: #64748B; --light: #F1F5F9; --dark: #1E293B; --success: #10B981; --warning: #F59E0B; --danger: #EF4444; --card-radius: 16px; --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } body { font-family: 'Inter', sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; background-color: #E0F2FE; color: var(--dark); padding: 20px; } .weather-card { width: 100%; max-width: 600px; background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(10px); border-radius: var(--card-radius); overflow: hidden; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); transition: var(--transition); position: relative; z-index: 1; } .weather-card:hover { transform: translateY(-5px); box-shadow: 0 15px 35px rgba(0, 0, 0, 0.15); } .card-header { padding: 24px; position: relative; overflow: hidden; color: white; background: linear-gradient(135deg, var(--primary), var(--primary-light)); border-radius: var(--card-radius) var(--card-radius) 0 0; } .card-header::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path fill="%23FFFFFF" fill-opacity="0.1" d="M0 0 L50 0 L50 50 L0 50 Z" /><path fill="%23FFFFFF" fill-opacity="0.1" d="M50 50 L100 50 L100 100 L50 100 Z" /></svg>'); opacity: 0.3; z-index: -1; } .location { display: flex; align-items: center; margin-bottom: 16px; } .location-icon { margin-right: 8px; opacity: 0.9; } .location-text { font-size: 1.25rem; font-weight: 600; } .date-time { font-size: 0.875rem; opacity: 0.9; margin-bottom: 24px; } .current-weather { display: flex; align-items: center; justify-content: space-between; } .temperature { font-size: 3.5rem; font-weight: 700; display: flex; align-items: flex-start; } .degree { font-size: 1.5rem; margin-top: 8px; } .weather-icon { font-size: 4rem; margin-right: 8px; filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.4)); } .weather-info { text-align: right; } .weather-description { font-size: 1.25rem; font-weight: 500; margin-bottom: 4px; } .feels-like { font-size: 0.875rem; opacity: 0.9; } .weather-details { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 24px; } .weather-detail { background: rgba(255, 255, 255, 0.2); border-radius: 12px; padding: 12px; display: flex; flex-direction: column; align-items: center; transition: var(--transition); } .weather-detail:hover { background: rgba(255, 255, 255, 0.3); transform: translateY(-2px); } .detail-icon { margin-bottom: 8px; opacity: 0.9; } .detail-value { font-weight: 600; font-size: 1rem; } .detail-label { font-size: 0.75rem; opacity: 0.9; } .card-content { padding: 24px; } .section-title { display: flex; align-items: center; margin-bottom: 16px; } .section-title h3 { font-size: 1.125rem; font-weight: 600; margin-right: 8px; } .toggle-btn { background: none; border: none; color: var(--primary); cursor: pointer; display: flex; align-items: center; font-size: 0.875rem; font-weight: 500; margin-left: auto; transition: var(--transition); } .toggle-btn:hover { color: var(--primary-light); } .toggle-icon { margin-left: 4px; transition: var(--transition); } .toggle-icon.active { transform: rotate(180deg); } .hourly-forecast { overflow-x: auto; scrollbar-width: thin; scrollbar-color: var(--primary-light) var(--light); padding-bottom: 8px; max-height: 0; transition: max-height 0.5s ease-in-out; } .hourly-forecast.expanded { max-height: 400px; } .hourly-forecast::-webkit-scrollbar { height: 6px; } .hourly-forecast::-webkit-scrollbar-track { background: var(--light); border-radius: 3px; } .hourly-forecast::-webkit-scrollbar-thumb { background-color: var(--primary-light); border-radius: 3px; } .hourly-items { display: flex; gap: 16px; padding: 8px 0; } .hourly-item { min-width: 80px; background: var(--light); border-radius: 12px; padding: 12px; display: flex; flex-direction: column; align-items: center; transition: var(--transition); position: relative; overflow: hidden; } .hourly-item::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 3px; background: var(--primary); transform: scaleX(0); transform-origin: left; transition: var(--transition); } .hourly-item:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); transform: translateY(-2px); } .hourly-item:hover::after { transform: scaleX(1); } .hourly-time { font-weight: 500; margin-bottom: 8px; font-size: 0.875rem; } .hourly-icon { font-size: 2rem; margin-bottom: 8px; color: var(--primary); } .hourly-temp { font-weight: 600; font-size: 1.125rem; } .precipitation { font-size: 0.75rem; color: var(--primary); margin-top: 4px; display: flex; align-items: center; } .precipitation-icon { margin-right: 2px; font-size: 0.875rem; } .daily-forecast { margin-top: 24px; max-height: 0; overflow: hidden; transition: max-height 0.5s ease-in-out; } .daily-forecast.expanded { max-height: 400px; } .daily-items { display: grid; gap: 8px; } .daily-item { display: grid; grid-template-columns: 0.8fr 0.5fr 1.2fr 0.5fr; align-items: center; padding: 12px; background: var(--light); border-radius: 12px; transition: var(--transition); } .daily-item:hover { background: #E0F2FE; transform: translateX(5px); } .daily-day { font-weight: 500; } .daily-icon { color: var(--primary); font-size: 1.5rem; justify-self: center; } .daily-temp-range { display: flex; align-items: center; } .temp-bar { flex-grow: 1; height: 4px; background: #D1D5DB; margin: 0 8px; border-radius: 2px; position: relative; } .temp-fill { position: absolute; top: 0; left: 20%; height: 100%; width: 60%; background: linear-gradient(to right, var(--primary-light), var(--primary)); border-radius: 2px; } .daily-max { font-weight: 600; } .daily-min { color: var(--secondary); } .daily-precip { color: var(--primary); display: flex; align-items: center; justify-self: flex-end; } .switch-container { display: flex; align-items: center; justify-content: flex-end; margin-top: 24px; } .switch-label { margin-right: 8px; font-size: 0.875rem; color: var(--secondary); } .switch { position: relative; display: inline-block; width: 50px; height: 24px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: var(--light); transition: var(--transition); border-radius: 34px; } .slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: var(--transition); border-radius: 50%; } input:checked + .slider { background-color: var(--primary); } input:checked + .slider:before { transform: translateX(26px); } .refresh-btn { position: absolute; top: 20px; right: 20px; background: rgba(255, 255, 255, 0.3); border: none; width: 36px; height: 36px; border-radius: 50%; color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: var(--transition); z-index: 2; } .refresh-btn:hover { background: rgba(255, 255, 255, 0.5); transform: rotate(30deg); } .refresh-icon { font-size: 1.25rem; } .loading-indicator { display: inline-block; width: 18px; height: 18px; border: 2px solid rgba(255, 255, 255, 0.3); border-radius: 50%; border-top-color: white; animation: spin 1s infinite linear; display: none; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .weather-animation { position: absolute; top: 0; right: 0; width: 150px; height: 150px; z-index: -1; opacity: 0.7; } .sun { position: absolute; top: 25px; right: 25px; width: 60px; height: 60px; background: #FFD700; border-radius: 50%; box-shadow: 0 0 40px #FFD700; animation: pulse 3s infinite alternate; } .cloud { position: absolute; background: white; border-radius: 50px; } .cloud-1 { top: 50px; right: 30px; width: 60px; height: 20px; animation: float 8s infinite alternate; } .cloud-2 { top: 60px; right: 50px; width: 50px; height: 18px; animation: float 7s 1s infinite alternate; } .rain { position: absolute; width: 3px; background: rgba(255, 255, 255, 0.6); border-radius: 2px; } .drop-1 { height: 15px; top: 75px; right: 40px; animation: rain 1.5s infinite linear; } .drop-2 { height: 12px; top: 75px; right: 60px; animation: rain 1.7s 0.2s infinite linear; } .drop-3 { height: 10px; top: 75px; right: 80px; animation: rain 1.3s 0.5s infinite linear; } @keyframes pulse { 0% { transform: scale(1); opacity: 0.8; } 100% { transform: scale(1.1); opacity: 1; } } @keyframes float { 0% { transform: translateX(0); } 100% { transform: translateX(-20px); } } @keyframes rain { 0% { transform: translateY(0); opacity: 1; } 100% { transform: translateY(40px); opacity: 0; } } .update-bar { position: absolute; bottom: 0; left: 0; height: 3px; background: var(--primary); width: 0%; transition: width 0.3s linear; } /* Responsive styles */ @media (max-width: 600px) { .weather-card { max-width: 100%; } .weather-details { grid-template-columns: repeat(3, 1fr); gap: 4px; } .daily-item { grid-template-columns: 0.7fr 0.5fr 1fr 0.5fr; font-size: 0.875rem; } .temperature { font-size: 3rem; } .weather-icon { font-size: 3.5rem; } .card-header, .card-content { padding: 16px; } .hourly-items { padding: 4px 0; } .hourly-item { min-width: 70px; padding: 8px; } } @media (max-width: 400px) { .daily-item { grid-template-columns: 0.8fr 0.4fr 1fr; } .daily-precip { display: none; } .weather-detail { padding: 8px; } .detail-value { font-size: 0.875rem; } .detail-label { font-size: 0.7rem; } } </style> </head> <body> <div class="weather-card"> <div class="card-header"> <button class="refresh-btn" id="refreshBtn"> <div class="loading-indicator" id="loadingIndicator"></div> <span class="refresh-icon" id="refreshIcon">↻</span> </button> <div class="location"> <span class="location-icon">📍</span> <span class="location-text">San Francisco, CA</span> </div> <div class="date-time">Tuesday, May 14 • Updated 5 minutes ago</div> <div class="current-weather"> <div class="temperature">64<span class="degree">°F</span></div> <div class="weather-info"> <div class="weather-icon">⛅</div> <div class="weather-description">Partly Cloudy</div> <div class="feels-like">Feels like 61°F</div> </div> </div> <div class="weather-details"> <div class="weather-detail"> <span class="detail-icon">💨</span> <span class="detail-value">12 mph</span> <span class="detail-label">Wind</span> </div> <div class="weather-detail"> <span class="detail-icon">💧</span> <span class="detail-value">76%</span> <span class="detail-label">Humidity</span> </div> <div class="weather-detail"> <span class="detail-icon">🌅</span> <span class="detail-value">6:02 AM</span> <span class="detail-label">Sunrise</span> </div> </div> <div class="weather-animation"> <div class="sun"></div> <div class="cloud cloud-1"></div> <div class="cloud cloud-2"></div> <div class="rain drop-1"></div> <div class="rain drop-2"></div> <div class="rain drop-3"></div> </div> </div> <div class="card-content"> <div class="section-title"> <h3>Hourly Forecast</h3> <button class="toggle-btn" id="toggleHourly"> <span>View hourly</span> <span class="toggle-icon" id="hourlyIcon">▼</span> </button> </div> <div class="hourly-forecast" id="hourlyForecast"> <div class="hourly-items"> <div class="hourly-item"> <div class="hourly-time">Now</div> <div class="hourly-icon">⛅</div> <div class="hourly-temp">64°</div> <div class="precipitation"><span class="precipitation-icon">💧</span> 0%</div> </div> <div class="hourly-item"> <div class="hourly-time">11 AM</div> <div class="hourly-icon">☀️</div> <div class="hourly-temp">67°</div> <div class="precipitation"><span class="precipitation-icon">💧</span> 0%</div> </div> <div class="hourly-item"> <div class="hourly-time">12 PM</div> <div class="hourly-icon">☀️</div> <div class="hourly-temp">69°</div> <div class="precipitation"><span class="precipitation-icon">💧</span> 0%</div> </div> <div class="hourly-item"> <div class="hourly-time">1 PM</div> <div class="hourly-icon">🌤️</div> <div class="hourly-temp">70°</div> <div class="precipitation"><span class="precipitation-icon">💧</span> 0%</div> </div> <div class="hourly-item"> <div class="hourly-time">2 PM</div> <div class="hourly-icon">⛅</div> <div class="hourly-temp">70°</div> <div class="precipitation"><span class="precipitation-icon">💧</span> 5%</div> </div> <div class="hourly-item"> <div class="hourly-time">3 PM</div> <div class="hourly-icon">⛅</div> <div class="hourly-temp">69°</div> <div class="precipitation"><span class="precipitation-icon">💧</span> 10%</div> </div> <div class="hourly-item"> <div class="hourly-time">4 PM</div> <div class="hourly-icon">🌥️</div> <div class="hourly-temp">68°</div> <div class="precipitation"><span class="precipitation-icon">💧</span> 15%</div> </div> <div class="hourly-item"> <div class="hourly-time">5 PM</div> <div class="hourly-icon">🌥️</div> <div class="hourly-temp">67°</div> <div class="precipitation"><span class="precipitation-icon">💧</span> 20%</div> </div> </div> </div> <div class="section-title" style="margin-top: 24px;"> <h3>5-Day Forecast</h3> <button class="toggle-btn" id="toggleDaily"> <span>View forecast</span> <span class="toggle-icon" id="dailyIcon">▼</span> </button> </div> <div class="daily-forecast" id="dailyForecast"> <div class="daily-items"> <div class="daily-item"> <div class="daily-day">Today</div> <div class="daily-icon">⛅</div> <div class="daily-temp-range"> <span class="daily-min">58°</span> <div class="temp-bar"> <div class="temp-fill"></div> </div> <span class="daily-max">71°</span> </div> <div class="daily-precip"><span class="precipitation-icon">💧</span> 15%</div> </div> <div class="daily-item"> <div class="daily-day">Wed</div> <div class="daily-icon">🌤️</div> <div class="daily-temp-range"> <span class="daily-min">57°</span> <div class="temp-bar"> <div class="temp-fill"></div> </div> <span class="daily-max">72°</span> </div> <div class="daily-precip"><span class="precipitation-icon">💧</span> 10%</div> </div> <div class="daily-item"> <div class="daily-day">Thu</div> <div class="daily-icon">🌦️</div> <div class="daily-temp-range"> <span class="daily-min">59°</span> <div class="temp-bar"> <div class="temp-fill"></div> </div> <span class="daily-max">68°</span> </div> <div class="daily-precip"><span class="precipitation-icon">💧</span> 30%</div> </div> <div class="daily-item"> <div class="daily-day">Fri</div> <div class="daily-icon">🌧️</div> <div class="daily-temp-range"> <span class="daily-min">55°</span> <div class="temp-bar"> <div class="temp-fill"></div> </div> <span class="daily-max">63°</span> </div> <div class="daily-precip"><span class="precipitation-icon">💧</span> 70%</div> </div> <div class="daily-item"> <div class="daily-day">Sat</div> <div class="daily-icon">⛅</div> <div class="daily-temp-range"> <span class="daily-min">56°</span> <div class="temp-bar"> <div class="temp-fill"></div> </div> <span class="daily-max">66°</span> </div> <div class="daily-precip"><span class="precipitation-icon">💧</span> 25%</div> </div> </div> </div> <div class="switch-container"> <span class="switch-label">Show temperature in °C</span> <label class="switch"> <input type="checkbox" id="tempUnitToggle"> <span class="slider"></span> </label> </div> </div> <div class="update-bar" id="updateBar"></div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Toggle hourly forecast const toggleHourlyBtn = document.getElementById('toggleHourly'); const hourlyForecast = document.getElementById('hourlyForecast'); const hourlyIcon = document.getElementById('hourlyIcon'); toggleHourlyBtn.addEventListener('click', function() { hourlyForecast.classList.toggle('expanded'); hourlyIcon.classList.toggle('active'); if (hourlyForecast.classList.contains('expanded')) { toggleHourlyBtn.querySelector('span:first-child').textContent = 'Hide hourly'; } else { toggleHourlyBtn.querySelector('span:first-child').textContent = 'View hourly'; } }); // Toggle daily forecast const toggleDailyBtn = document.getElementById('toggleDaily'); const dailyForecast = document.getElementById('dailyForecast'); const dailyIcon = document.getElementById('dailyIcon'); toggleDailyBtn.addEventListener('click', function() { dailyForecast.classList.toggle('expanded'); dailyIcon.classList.toggle('active'); if (dailyForecast.classList.contains('expanded')) { toggleDailyBtn.querySelector('span:first-child').textContent = 'Hide forecast'; } else { toggleDailyBtn.querySelector('span:first-child').textContent = 'View forecast'; } }); // Temperature unit toggle const tempUnitToggle = document.getElementById('tempUnitToggle'); const temperatures = document.querySelectorAll('.temperature, .hourly-temp, .daily-min, .daily-max, .feels-like'); tempUnitToggle.addEventListener('change', function() { temperatures.forEach(temp => { const text = temp.textContent; const value = parseInt(text); if (!isNaN(value)) { if (tempUnitToggle.checked) { // Convert F to C const celsius = Math.round((value - 32) * 5 / 9); temp.textContent = text.replace(value + '°', celsius + '°'); if (temp.classList.contains('temperature')) { temp.innerHTML = celsius + '<span class="degree">°C</span>'; } else if (temp.classList.contains('feels-like')) { temp.textContent = 'Feels like ' + celsius + '°C'; } } else { // Convert C to F const fahrenheit = Math.round(value * 9 / 5 + 32); temp.textContent = text.replace(value + '°', fahrenheit + '°'); if (temp.classList.contains('temperature')) { temp.innerHTML = fahrenheit + '<span class="degree">°F</span>'; } else if (temp.classList.contains('feels-like')) { temp.textContent = 'Feels like ' + fahrenheit + '°F'; } } } }); }); // Refresh button const refreshBtn = document.getElementById('refreshBtn'); const loadingIndicator = document.getElementById('loadingIndicator'); const refreshIcon = document.getElementById('refreshIcon'); const updateBar = document.getElementById('updateBar'); refreshBtn.addEventListener('click', function() { loadingIndicator.style.display = 'inline-block'; refreshIcon.style.display = 'none'; // Simulate loading updateBar.style.width = '0%'; let progress = 0; const interval = setInterval(() => { progress += 1; updateBar.style.width = progress + '%'; if (progress >= 100) { clearInterval(interval); loadingIndicator.style.display = 'none'; refreshIcon.style.display = 'inline-block'; // Update the "updated" time document.querySelector('.date-time').textContent = 'Tuesday, May 14 • Updated just now'; // Provide some visual feedback document.querySelector('.card-header').style.animation = 'none'; setTimeout(() => { document.querySelector('.card-header').style.animation = 'pulse 0.3s'; }, 10); } }, 30); }); // Make hourly items interactive const hourlyItems = document.querySelectorAll('.hourly-item'); hourlyItems.forEach(item => { item.addEventListener('click', function() { hourlyItems.forEach(i => i.style.transform = 'none'); this.style.transform = 'scale(1.05)'; // Show a tooltip or something const time = this.querySelector('.hourly-time').textContent; const temp = this.querySelector('.hourly-temp').textContent; const icon = this.querySelector('.hourly-icon').textContent; // You can implement a tooltip here if needed console.log(`${time}: ${temp} ${icon}`); }); }); // Make daily items interactive too const dailyItems = document.querySelectorAll('.daily-item'); dailyItems.forEach(item => { item.addEventListener('click', function() { // Reset all items dailyItems.forEach(i => i.style.background = var(--light)); // Highlight this item this.style.background = '#E0F2FE'; // Update hourly forecast based on selected day (simulated) const day = this.querySelector('.daily-day').textContent; console.log(`Selected forecast for: ${day}`); }); }); // Weather animation toggle based on weather condition const weatherIcon = document.querySelector('.weather-icon'); const sunElement = document.querySelector('.sun'); const cloudElements = document.querySelectorAll('.cloud'); const rainElements = document.querySelectorAll('.rain'); function updateWeatherAnimation(weather) { // Reset all sunElement.style.display = 'none'; cloudElements.forEach(c => c.style.display = 'none'); rainElements.forEach(r => r.style.display = 'none'); // Show appropriate elements switch(weather) { case 'sunny': sunElement.style.display = 'block'; break; case 'cloudy': cloudElements.forEach(c => c.style.display = 'block'); break; case 'partly-cloudy': sunElement.style.display = 'block'; cloudElements.forEach(c => c.style.display = 'block'); break; case 'rainy': cloudElements.forEach(c => c.style.display = 'block'); rainElements.forEach(r => r.style.display = 'block'); break; } } // Initialize with partly cloudy updateWeatherAnimation('partly-cloudy'); // Auto update the bar every 5 minutes setInterval(() => { updateBar.style.width = '100%'; setTimeout(() => { updateBar.style.width = '0%'; }, 1000); }, 300000); // 5 minutes }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Downtown Beats - Community Events</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background: #f8f8f8; display: flex; align-items: center; justify-content: center; min-height: 700px; overflow-x: hidden; padding: 20px; } .app-container { width: 100%; max-width: 700px; height: 660px; background: #fff; border-radius: 20px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); overflow: hidden; position: relative; } .header { padding: 24px 28px; display: flex; align-items: center; justify-content: space-between; background: linear-gradient(135deg, #6b53ff 0%, #8a6eff 100%); color: white; position: relative; z-index: 2; } .header h1 { font-size: 1.6rem; font-weight: 700; letter-spacing: -0.5px; } .date-filter { display: flex; gap: 12px; overflow-x: auto; scrollbar-width: none; padding: 16px 24px; background: #f9f8ff; border-bottom: 1px solid rgba(0, 0, 0, 0.05); } .date-filter::-webkit-scrollbar { display: none; } .date-btn { border: none; background: white; padding: 12px 18px; border-radius: 14px; font-size: 14px; font-weight: 600; color: #6b53ff; box-shadow: 0 2px 8px rgba(107, 83, 255, 0.1); white-space: nowrap; transition: all 0.3s ease; cursor: pointer; } .date-btn:hover, .date-btn.active { background: #6b53ff; color: white; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(107, 83, 255, 0.2); } .date-btn.active { position: relative; overflow: hidden; } .date-btn.active::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 4px; background: #fff; animation: pulse 2s infinite; } .events-container { padding: 16px 24px; height: calc(100% - 186px); overflow-y: auto; scrollbar-width: thin; scrollbar-color: #6b53ff transparent; } .events-container::-webkit-scrollbar { width: 6px; } .events-container::-webkit-scrollbar-thumb { background-color: #6b53ff; border-radius: 10px; } .event-card { margin-bottom: 20px; padding: 20px; background: white; border-radius: 16px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05); transition: all 0.3s ease; position: relative; overflow: hidden; border: 1px solid #f0f0f0; } .event-card:hover { transform: translateY(-4px); box-shadow: 0 8px 25px rgba(107, 83, 255, 0.12); border-color: #e2ddff; } .event-category { position: absolute; top: 20px; right: 20px; padding: 6px 12px; border-radius: 30px; font-size: 12px; font-weight: 600; color: white; text-transform: uppercase; letter-spacing: 0.5px; } .category-music { background: linear-gradient(45deg, #ff4e50, #f9d423); } .category-art { background: linear-gradient(45deg, #56ab2f, #a8e063); } .category-food { background: linear-gradient(45deg, #ff8008, #ffc837); } .category-tech { background: linear-gradient(45deg, #396afc, #2948ff); } .event-date { font-size: 14px; color: #6b53ff; font-weight: 600; margin-bottom: 10px; display: flex; align-items: center; gap: 6px; } .event-date svg { width: 14px; height: 14px; fill: #6b53ff; } .event-title { font-size: 18px; font-weight: 700; margin-bottom: 8px; color: #222; line-height: 1.3; } .event-location { font-size: 14px; color: #666; display: flex; align-items: center; margin-bottom: 16px; gap: 6px; } .event-location svg { width: 14px; height: 14px; fill: #666; } .event-description { font-size: 14px; color: #555; line-height: 1.5; margin-bottom: 20px; } .event-actions { display: flex; gap: 10px; } .reg-btn { padding: 12px 24px; background: #6b53ff; color: white; border: none; border-radius: 12px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; flex: 1; font-size: 14px; position: relative; overflow: hidden; } .reg-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: 0.5s; } .reg-btn:hover::before { left: 100%; } .reg-btn:hover { background: #5944d7; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(107, 83, 255, 0.3); } .fav-btn { width: 46px; height: 46px; border-radius: 12px; border: 1px solid #e0e0e0; background: white; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s ease; } .fav-btn svg { width: 20px; height: 20px; fill: none; stroke: #666; stroke-width: 2; transition: all 0.3s ease; } .fav-btn:hover { border-color: #ff6b6b; background: #fff2f2; } .fav-btn:hover svg, .fav-btn.active svg { stroke: #ff6b6b; fill: #ff6b6b; } .fav-btn.active { border-color: #ff6b6b; background: #fff2f2; } .city-pattern { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICA8cGF0aCBkPSJNMCAwSDIwVjIwSDBWMFoiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wNSkiLz4KICAgIDxwYXRoIGQ9Ik00MCAwSDYwVjIwSDQwVjBaIiBmaWxsPSJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDUpIi8+CiAgICA8cGF0aCBkPSJNODAgMEgxMDBWMjBIODBWMFoiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wNSkiLz4KICAgIDxwYXRoIGQ9Ik0yMCAyMEg0MFY0MEgyMFYyMFoiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wNSkiLz4KICAgIDxwYXRoIGQ9Ik02MCAyMEg4MFY0MEg2MFYyMFoiIGZpbGw9InJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wNSkiLz4KICAgIDxwYXRoIGQ9Ik0wIDQwSDIwVjYwSDBWNDBaIiBmaWxsPSJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDUpIi8+CiAgICA8cGF0aCBkPSJNNDAgNDBINjBWNjBINDBWNDBaIiBmaWxsPSJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDUpIi8+CiAgICA8cGF0aCBkPSJNODAgNDBIMTAwVjYwSDgwVjQwWiIgZmlsbD0icmdiYSgyNTUsIDI1NSwgMjU1LCAwLjA1KSIvPgogICAgPHBhdGggZD0iTTIwIDYwSDQwVjgwSDIwVjYwWiIgZmlsbD0icmdiYSgyNTUsIDI1NSwgMjU1LCAwLjA1KSIvPgogICAgPHBhdGggZD0iTTYwIDYwSDgwVjgwSDYwVjYwWiIgZmlsbD0icmdiYSgyNTUsIDI1NSwgMjU1LCAwLjA1KSIvPgogICAgPHBhdGggZD0iTTAgODBIMjBWMTAwSDBWODBaIiBmaWxsPSJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDUpIi8+CiAgICA8cGF0aCBkPSJNNDAgODBINjBWMTAwSDQwVjgwWiIgZmlsbD0icmdiYSgyNTUsIDI1NSwgMjU1LCAwLjA1KSIvPgogICAgPHBhdGggZD0iTTgwIDgwSDEwMFYxMDBIODBWODBaIiBmaWxsPSJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDUpIi8+Cjwvc3ZnPg=='); opacity: 0.5; z-index: 1; } .empty-state { display: none; height: 100%; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 0 40px; } .empty-state svg { width: 120px; height: 120px; margin-bottom: 24px; opacity: 0.7; } .empty-state h3 { font-size: 1.4rem; color: #333; margin-bottom: 12px; } .empty-state p { color: #666; margin-bottom: 24px; line-height: 1.6; } .toast { position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%) translateY(100px); background: #333; color: white; padding: 14px 24px; border-radius: 30px; font-size: 14px; font-weight: 600; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15); z-index: 1000; opacity: 0; transition: all 0.3s ease; } .toast.show { transform: translateX(-50%) translateY(0); opacity: 1; } @keyframes pulse { 0% { opacity: 0.6; } 50% { opacity: 1; } 100% { opacity: 0.6; } } /* Animation for card appearance */ @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .event-card { animation: fadeIn 0.5s ease forwards; } .event-card:nth-child(1) { animation-delay: 0.1s; } .event-card:nth-child(2) { animation-delay: 0.2s; } .event-card:nth-child(3) { animation-delay: 0.3s; } .event-card:nth-child(4) { animation-delay: 0.4s; } /* Badge for trending events */ .trending-badge { position: absolute; top: 0; left: 24px; background: #ff6b6b; color: white; font-size: 12px; font-weight: 700; padding: 6px 12px; border-radius: 0 0 10px 10px; letter-spacing: 0.5px; box-shadow: 0 4px 10px rgba(255, 107, 107, 0.3); z-index: 2; } .trending-badge::before { content: ''; display: inline-block; width: 8px; height: 8px; background: white; border-radius: 50%; margin-right: 6px; animation: blink 1.5s infinite; } @keyframes blink { 0% { opacity: 0.4; } 50% { opacity: 1; } 100% { opacity: 0.4; } } /* Notification count indicator */ .notification-badge { position: relative; cursor: pointer; } .notification-badge svg { width: 24px; height: 24px; fill: white; } .notification-badge .count { position: absolute; top: -6px; right: -6px; background: #ff6b6b; color: white; font-size: 10px; font-weight: 700; width: 18px; height: 18px; border-radius: 50%; display: flex; align-items: center; justify-content: center; border: 2px solid #6b53ff; } /* Responsive adjustments */ @media (max-width: 480px) { .app-container { border-radius: 0; height: 100vh; max-height: 700px; } .header { padding: 20px; } .date-filter { padding: 12px 16px; } .date-btn { padding: 10px 16px; font-size: 13px; } .events-container { padding: 12px 16px; } .event-card { padding: 16px; } .event-title { font-size: 16px; } .reg-btn { padding: 10px 20px; font-size: 13px; } } /* Ticket animation */ .ticket-anim { position: absolute; left: -30px; top: -20px; width: 40px; height: 40px; transform: scale(0); opacity: 0; z-index: 10; } .ticket-anim svg { width: 100%; height: 100%; fill: #6b53ff; } @keyframes ticketFly { 0% { transform: scale(0) rotate(0deg); opacity: 0; } 10% { transform: scale(1) rotate(0deg); opacity: 1; } 60% { transform: scale(1.2) translateY(-60px) translateX(40px) rotate(20deg); opacity: 1; } 100% { transform: scale(0.5) translateY(-100px) translateX(100px) rotate(45deg); opacity: 0; } } </style> </head> <body> <div class="app-container"> <div class="header"> <h1>Downtown Beats</h1> <div class="notification-badge"> <svg viewBox="0 0 24 24"> <path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z"></path> </svg> <span class="count">3</span> </div> <div class="city-pattern"></div> </div> <div class="date-filter"> <button class="date-btn active">Today</button> <button class="date-btn">Tomorrow</button> <button class="date-btn">This Weekend</button> <button class="date-btn">Next Week</button> <button class="date-btn">This Month</button> </div> <div class="events-container"> <div class="event-card"> <div class="trending-badge">Trending</div> <div class="event-category category-music">Music</div> <div class="event-date"> <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> Today, 8:00 PM - 11:30 PM </div> <h3 class="event-title">Underground Jazz Collective: The Blue Note Sessions</h3> <div class="event-location"> <svg viewBox="0 0 24 24"> <path d="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z"></path> </svg> Velvet Lounge, 123 Harmony Street </div> <p class="event-description">Join the city's finest jazz musicians for an intimate evening of improvisational brilliance. Limited seating available.</p> <div class="event-actions"> <button class="reg-btn">Register Now • $25</button> <button class="fav-btn"> <svg viewBox="0 0 24 24"> <path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"></path> </svg> </button> </div> <div class="ticket-anim"> <svg viewBox="0 0 24 24"> <path d="M22,10V6C22,4.89 21.1,4 20,4H4C2.9,4 2,4.89 2,6V10C3.11,10 4,10.9 4,12C4,13.1 3.11,14 2,14V18C2,19.1 2.9,20 4,20H20C21.1,20 22,19.1 22,18V14C20.9,14 20,13.1 20,12C20,10.9 20.9,10 22,10M13,17.5H11V15.5H13V17.5M13,13H11V7H13V13Z"></path> </svg> </div> </div> <div class="event-card"> <div class="event-category category-food">Food</div> <div class="event-date"> <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> Tomorrow, 6:00 PM - 9:00 PM </div> <h3 class="event-title">Urban Feast: Street Food Festival</h3> <div class="event-location"> <svg viewBox="0 0 24 24"> <path d="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z"></path> </svg> Riverside Plaza, 450 River Walk </div> <p class="event-description">Experience 30+ local food vendors offering global cuisine. Live cooking demos and craft beer sampling included.</p> <div class="event-actions"> <button class="reg-btn">Register Now • $15</button> <button class="fav-btn"> <svg viewBox="0 0 24 24"> <path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"></path> </svg> </button> </div> <div class="ticket-anim"> <svg viewBox="0 0 24 24"> <path d="M22,10V6C22,4.89 21.1,4 20,4H4C2.9,4 2,4.89 2,6V10C3.11,10 4,10.9 4,12C4,13.1 3.11,14 2,14V18C2,19.1 2.9,20 4,20H20C21.1,20 22,19.1 22,18V14C20.9,14 20,13.1 20,12C20,10.9 20.9,10 22,10M13,17.5H11V15.5H13V17.5M13,13H11V7H13V13Z"></path> </svg> </div> </div> <div class="event-card"> <div class="event-category category-tech">Tech</div> <div class="event-date"> <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> Saturday, 10:00 AM - 4:00 PM </div> <h3 class="event-title">Hackers & Makers: Urban Innovation Summit</h3> <div class="event-location"> <svg viewBox="0 0 24 24"> <path d="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z"></path> </svg> The Innovation Hub, 78 Circuit Avenue </div> <p class="event-description">A hands-on tech showcase featuring workshops on AI, blockchain, and urban tech solutions. Bring your laptop!</p> <div class="event-actions"> <button class="reg-btn">Register Now • Free</button> <button class="fav-btn"> <svg viewBox="0 0 24 24"> <path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"></path> </svg> </button> </div> <div class="ticket-anim"> <svg viewBox="0 0 24 24"> <path d="M22,10V6C22,4.89 21.1,4 20,4H4C2.9,4 2,4.89 2,6V10C3.11,10 4,10.9 4,12C4,13.1 3.11,14 2,14V18C2,19.1 2.9,20 4,20H20C21.1,20 22,19.1 22,18V14C20.9,14 20,13.1 20,12C20,10.9 20.9,10 22,10M13,17.5H11V15.5H13V17.5M13,13H11V7H13V13Z"></path> </svg> </div> </div> <div class="event-card"> <div class="event-category category-art">Art</div> <div class="event-date"> <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> Sunday, 12:00 PM - 7:00 PM </div> <h3 class="event-title">Urban Canvas: Street Art Festival & Workshop</h3> <div class="event-location"> <svg viewBox="0 0 24 24"> <path d="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z"></path> </svg> Graffiti Alley, 221 Expression Street </div> <p class="event-description">Watch renowned street artists transform blank walls into masterpieces. Participate in spray painting workshops and mural tours.</p> <div class="event-actions"> <button class="reg-btn">Register Now • $10</button> <button class="fav-btn"> <svg viewBox="0 0 24 24"> <path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"></path> </svg> </button> </div> <div class="ticket-anim"> <svg viewBox="0 0 24 24"> <path d="M22,10V6C22,4.89 21.1,4 20,4H4C2.9,4 2,4.89 2,6V10C3.11,10 4,10.9 4,12C4,13.1 3.11,14 2,14V18C2,19.1 2.9,20 4,20H20C21.1,20 22,19.1 22,18V14C20.9,14 20,13.1 20,12C20,10.9 20.9,10 22,10M13,17.5H11V15.5H13V17.5M13,13H11V7H13V13Z"></path> </svg> </div> </div> </div> <div class="empty-state"> <svg viewBox="0 0 24 24"> <path d="M19,19H5V8H19M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M16.5,18H15V9.5H16.5M11.5,18H10V9.5H11.5M14,16H12.5V14.5H14M14,13H12.5V11.5H14M9,11.5H7.5V10H9M9,14.5H7.5V13H9M9,16H7.5V15.5H9" fill="#6b53ff"/> </svg> <h3>No events found</h3> <p>There are no events scheduled for this date. Try selecting another day or check back later.</p> <button class="reg-btn">Browse All Events</button> </div> </div> <div class="toast">Registration successful! Check your email for details.</div> <script> document.addEventListener('DOMContentLoaded', function() { // Date filter buttons const dateButtons = document.querySelectorAll('.date-btn'); const eventsContainer = document.querySelector('.events-container'); const emptyState = document.querySelector('.empty-state'); dateButtons.forEach(button => { button.addEventListener('click', function() { // Remove active class from all buttons dateButtons.forEach(btn => btn.classList.remove('active')); // Add active class to clicked button this.classList.add('active'); // Simulate loading different events if (this.textContent === 'This Month' || this.textContent === 'Next Week') { eventsContainer.style.display = 'none'; emptyState.style.display = 'flex'; } else { eventsContainer.style.display = 'block'; emptyState.style.display = 'none'; // Reapply animation to cards const cards = document.querySelectorAll('.event-card'); cards.forEach((card, index) => { card.style.animation = 'none'; card.offsetHeight; // Trigger reflow card.style.animation = `fadeIn 0.5s ease forwards ${index * 0.1}s`; }); } }); }); // Favorite buttons const favButtons = document.querySelectorAll('.fav-btn'); favButtons.forEach(button => { button.addEventListener('click', function() { this.classList.toggle('active'); if (this.classList.contains('active')) { showToast('Added to favorites!'); }
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Creative Agency Portfolio</title> <style> @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Space Grotesk', sans-serif; } :root { --primary-color: #101010; --secondary-color: #f5f5f5; --accent-color: #ff3e55; --hover-color: rgba(255, 62, 85, 0.05); --card-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); --card-hover-shadow: 0 16px 32px rgba(0, 0, 0, 0.18); --transition-speed: 0.25s; } body { background-color: var(--secondary-color); color: var(--primary-color); width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; overflow-x: hidden; padding: 1rem; } .portfolio-container { width: 100%; max-width: 700px; height: 700px; display: flex; flex-direction: column; position: relative; overflow: hidden; } .portfolio-header { padding: 1.5rem; z-index: 10; } .portfolio-header h1 { font-size: 2rem; font-weight: 700; margin-bottom: 0.5rem; letter-spacing: -0.02em; } .portfolio-header p { font-size: 1rem; opacity: 0.8; max-width: 70%; } .projects-grid { display: grid; grid-template-columns: repeat(2, 1fr); grid-gap: 1.5rem; padding: 0 1.5rem 1.5rem; overflow-y: auto; height: 100%; scrollbar-width: none; -ms-overflow-style: none; } .projects-grid::-webkit-scrollbar { display: none; } .project-card { position: relative; background-color: white; border-radius: 8px; overflow: hidden; cursor: pointer; box-shadow: var(--card-shadow); transform: translateY(0); transition: transform var(--transition-speed) ease, box-shadow var(--transition-speed) ease, opacity 0.3s ease; height: 280px; opacity: 0; animation: fadeIn 0.5s forwards; animation-delay: calc(var(--order) * 0.1s); } @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .project-card:hover { transform: translateY(-8px); box-shadow: var(--card-hover-shadow); } .project-card:active { transform: translateY(-4px); transition: transform 0.1s ease; } .project-image { height: 65%; width: 100%; overflow: hidden; position: relative; } .project-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s ease; } .project-card:hover .project-image img { transform: scale(1.05); } .project-tag { position: absolute; top: 12px; left: 12px; background-color: var(--accent-color); color: white; font-size: 0.7rem; font-weight: 500; padding: 0.25rem 0.5rem; border-radius: 4px; text-transform: uppercase; letter-spacing: 0.03em; } .project-content { padding: 1rem; height: 35%; display: flex; flex-direction: column; justify-content: space-between; } .project-title { font-size: 1rem; font-weight: 600; margin-bottom: 0.25rem; line-height: 1.2; color: var(--primary-color); } .project-description { font-size: 0.8rem; color: rgba(0, 0, 0, 0.7); line-height: 1.4; } .project-meta { display: flex; justify-content: space-between; align-items: center; margin-top: 0.5rem; font-size: 0.7rem; color: rgba(0, 0, 0, 0.5); } .view-more { color: var(--accent-color); font-weight: 500; display: flex; align-items: center; gap: 4px; transition: gap 0.3s ease; } .project-card:hover .view-more { gap: 8px; } .filter-buttons { display: flex; gap: 0.5rem; margin-bottom: 1.25rem; overflow-x: auto; padding-bottom: 0.5rem; scrollbar-width: none; -ms-overflow-style: none; } .filter-buttons::-webkit-scrollbar { display: none; } .filter-btn { background: none; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 20px; padding: 0.3rem 0.8rem; font-size: 0.75rem; cursor: pointer; white-space: nowrap; transition: all 0.2s ease; } .filter-btn.active { background-color: var(--primary-color); color: white; border-color: var(--primary-color); } .filter-btn:hover:not(.active) { background-color: var(--hover-color); } .expanded-view { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: white; z-index: 20; display: flex; flex-direction: column; transform: translateY(100%); transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1); padding: 1.5rem; overflow-y: auto; } .expanded-view.active { transform: translateY(0); } .expanded-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; } .close-btn { background: none; border: none; cursor: pointer; font-size: 1.5rem; color: var(--primary-color); width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: background-color 0.2s ease; } .close-btn:hover { background-color: rgba(0, 0, 0, 0.05); } .expanded-image { width: 100%; height: 260px; overflow: hidden; border-radius: 8px; margin-bottom: 1.5rem; } .expanded-image img { width: 100%; height: 100%; object-fit: cover; } .expanded-content h2 { font-size: 1.5rem; margin-bottom: 0.5rem; } .expanded-tag { display: inline-block; background-color: var(--accent-color); color: white; font-size: 0.7rem; padding: 0.25rem 0.5rem; border-radius: 4px; margin-bottom: 1rem; text-transform: uppercase; } .expanded-description { line-height: 1.6; margin-bottom: 1.5rem; } .stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1.5rem; } .stat-item { background-color: rgba(0, 0, 0, 0.03); padding: 1rem; border-radius: 8px; text-align: center; } .stat-value { font-size: 1.5rem; font-weight: 600; display: block; margin-bottom: 0.25rem; } .stat-label { font-size: 0.7rem; color: rgba(0, 0, 0, 0.6); } @media (max-width: 600px) { .projects-grid { grid-template-columns: 1fr; } .portfolio-header h1 { font-size: 1.75rem; } .portfolio-header p { max-width: 100%; } .project-card { height: 250px; } .stats-grid { grid-template-columns: 1fr 1fr; } } /* Custom loading animation */ .loading-circle { position: absolute; width: 40px; height: 40px; top: 50%; left: 50%; margin-top: -20px; margin-left: -20px; border: 3px solid rgba(0, 0, 0, 0.1); border-top-color: var(--accent-color); border-radius: 50%; animation: spin 0.8s linear infinite; opacity: 0; transition: opacity 0.2s; } @keyframes spin { to { transform: rotate(360deg); } } .loading .loading-circle { opacity: 1; } .loading .projects-grid { opacity: 0.5; } /* Cursor effect */ .custom-cursor { position: fixed; width: 20px; height: 20px; border-radius: 50%; background-color: var(--accent-color); transform: translate(-50%, -50%) scale(0); pointer-events: none; z-index: 9999; opacity: 0.5; transition: transform 0.1s ease; mix-blend-mode: difference; } </style> </head> <body> <div class="custom-cursor"></div> <div class="portfolio-container"> <div class="portfolio-header"> <h1>Our Selected Work</h1> <p>Expertly crafted digital experiences that drive engagement and deliver results.</p> <div class="filter-buttons"> <button class="filter-btn active" data-filter="all">All</button> <button class="filter-btn" data-filter="branding">Branding</button> <button class="filter-btn" data-filter="web">Web Design</button> <button class="filter-btn" data-filter="app">App Development</button> <button class="filter-btn" data-filter="motion">Motion</button> </div> </div> <div class="projects-grid"> <div class="project-card" data-category="branding" style="--order: 1"> <div class="project-image"> <img src="https://images.unsplash.com/photo-1620288627223-53302f4e8c74?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="Nomad Coffee Brand Identity"> <div class="project-tag">Branding</div> </div> <div class="project-content"> <div> <h3 class="project-title">Nomad Coffee Brand Identity</h3> <p class="project-description">Artisanal identity system for a boutique roaster focused on ethical sourcing.</p> </div> <div class="project-meta"> <span>2023</span> <span class="view-more">View project <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></span> </div> </div> </div> <div class="project-card" data-category="web" style="--order: 2"> <div class="project-image"> <img src="https://images.unsplash.com/photo-1541462608143-67571c6738dd?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="Meridian Architecture Portfolio"> <div class="project-tag">Web Design</div> </div> <div class="project-content"> <div> <h3 class="project-title">Meridian Architecture Portfolio</h3> <p class="project-description">Minimalist platform showcasing award-winning architectural projects with immersive navigation.</p> </div> <div class="project-meta"> <span>2023</span> <span class="view-more">View project <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></span> </div> </div> </div> <div class="project-card" data-category="app" style="--order: 3"> <div class="project-image"> <img src="https://images.unsplash.com/photo-1605236453806-6ff36851218e?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="Pulse Health Monitoring App"> <div class="project-tag">App Development</div> </div> <div class="project-content"> <div> <h3 class="project-title">Pulse Health Monitoring App</h3> <p class="project-description">Intuitive health tracking platform with personalized analytics and seamless device integration.</p> </div> <div class="project-meta"> <span>2022</span> <span class="view-more">View project <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></span> </div> </div> </div> <div class="project-card" data-category="motion" style="--order: 4"> <div class="project-image"> <img src="https://images.unsplash.com/photo-1574375927938-d5a98e8ffe85?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="Nebula Music Visualizer"> <div class="project-tag">Motion</div> </div> <div class="project-content"> <div> <h3 class="project-title">Nebula Music Visualizer</h3> <p class="project-description">Dynamic audio-reactive animation system for a leading electronic music label's livestreams.</p> </div> <div class="project-meta"> <span>2023</span> <span class="view-more">View project <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></span> </div> </div> </div> <div class="project-card" data-category="web" style="--order: 5"> <div class="project-image"> <img src="https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="Horizon Financial Dashboard"> <div class="project-tag">Web Design</div> </div> <div class="project-content"> <div> <h3 class="project-title">Horizon Financial Dashboard</h3> <p class="project-description">Data-driven interface redesign with intuitive visualization tools for wealth management.</p> </div> <div class="project-meta"> <span>2022</span> <span class="view-more">View project <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></span> </div> </div> </div> <div class="project-card" data-category="branding" style="--order: 6"> <div class="project-image"> <img src="https://images.unsplash.com/photo-1542744173-8e7e53415bb0?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="Vertex Ventures Rebrand"> <div class="project-tag">Branding</div> </div> <div class="project-content"> <div> <h3 class="project-title">Vertex Ventures Rebrand</h3> <p class="project-description">Strategic rebranding for a tech-focused venture capital firm with global portfolio.</p> </div> <div class="project-meta"> <span>2022</span> <span class="view-more">View project <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></span> </div> </div> </div> </div> <div class="loading-circle"></div> <div class="expanded-view"> <div class="expanded-header"> <div class="expanded-tag">Branding</div> <button class="close-btn">×</button> </div> <div class="expanded-image"> <img src="https://images.unsplash.com/photo-1620288627223-53302f4e8c74?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="Expanded Project Image"> </div> <div class="expanded-content"> <h2>Nomad Coffee Brand Identity</h2> <p class="expanded-description"> We created a comprehensive identity system for Nomad Coffee, an artisanal roaster focused on ethical bean sourcing and unique flavor profiles. The branding needed to convey quality craftsmanship while remaining approachable and distinct in a competitive market. </p> <div class="stats-grid"> <div class="stat-item"> <span class="stat-value">85%</span> <span class="stat-label">Brand Recognition</span> </div> <div class="stat-item"> <span class="stat-value">42%</span> <span class="stat-label">Sales Increase</span> </div> <div class="stat-item"> <span class="stat-value">4</span> <span class="stat-label">Design Awards</span> </div> </div> <p class="expanded-description"> Our solution embraces tactile textures and earthy tones that reflect the origins of their beans. We developed a modular system that adapts across packaging, digital touchpoints, and retail environments while maintaining a cohesive narrative. </p> </div> </div> </div> <script> // Filter functionality const filterButtons = document.querySelectorAll('.filter-btn'); const projectCards = document.querySelectorAll('.project-card'); const portfolioContainer = document.querySelector('.portfolio-container'); const loadingCircle = document.querySelector('.loading-circle'); const expandedView = document.querySelector('.expanded-view'); const closeBtn = document.querySelector('.close-btn'); const customCursor = document.querySelector('.custom-cursor'); // Custom cursor effect document.addEventListener('mousemove', (e) => { window.requestAnimationFrame(() => { customCursor.style.left = `${e.clientX}px`; customCursor.style.top = `${e.clientY}px`; }); }); document.addEventListener('mouseenter', () => { customCursor.style.transform = 'translate(-50%, -50%) scale(1)'; }); document.addEventListener('mouseleave', () => { customCursor.style.transform = 'translate(-50%, -50%) scale(0)'; }); document.addEventListener('mousedown', () => { customCursor.style.transform = 'translate(-50%, -50%) scale(1.5)'; }); document.addEventListener('mouseup', () => { customCursor.style.transform = 'translate(-50%, -50%) scale(1)'; }); // Filter projects filterButtons.forEach(button => { button.addEventListener('click', () => { // Show loading state portfolioContainer.classList.add('loading'); // Remove active class from all buttons filterButtons.forEach(btn => btn.classList.remove('active')); // Add active class to clicked button button.classList.add('active'); const filter = button.getAttribute('data-filter'); // Simulate loading delay setTimeout(() => { projectCards.forEach(card => { const category = card.getAttribute('data-category'); // Reset animation delays for proper re-animation card.style.animationDelay = '0s'; card.style.opacity = '0'; if (filter === 'all' || category === filter) { setTimeout(() => { card.style.display = 'block'; card.style.opacity = '1'; }, 50); } else { card.style.display = 'none'; } }); // Remove loading state portfolioContainer.classList.remove('loading'); }, 400); }); }); // Project card click to show expanded view projectCards.forEach(card => { card.addEventListener('click', () => { // Get project details const projectImage = card.querySelector('.project-image img').src; const projectTitle = card.querySelector('.project-title').textContent; const projectCategory = card.querySelector('.project-tag').textContent; // Update expanded view content expandedView.querySelector('.expanded-image img').src = projectImage; expandedView.querySelector('h2').textContent = projectTitle; expandedView.querySelector('.expanded-tag').textContent = projectCategory; // Show expanded view expandedView.classList.add('active'); }); }); // Close expanded view closeBtn.addEventListener('click', () => { expandedView.classList.remove('active'); }); // Add hover effect to project cards projectCards.forEach(card => { card.addEventListener('mouseenter', () => { // Scale down other cards slightly projectCards.forEach(otherCard => { if (otherCard !== card) { otherCard.style.transform = 'scale(0.98)'; otherCard.style.opacity = '0.7'; } }); }); card.addEventListener('mouseleave', () => { // Reset all cards projectCards.forEach(otherCard => { otherCard.style.transform = ''; otherCard.style.opacity = ''; }); }); }); </script> </body> </html>