This commit is contained in:
IndyDevDan 2025-06-06 12:00:20 -05:00
parent c99af0e299
commit 4be8fcb158
16 changed files with 13476 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,854 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Organic Nature Search Hub</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Georgia', serif;
background: linear-gradient(135deg, #f5f5dc 0%, #e8e3d3 100%);
color: #2d3a24;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
position: relative;
overflow-x: hidden;
}
/* Animated background vines */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
url("data:image/svg+xml,%3Csvg width='100' height='100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10,50 Q30,20 50,50 T90,50' stroke='%23a8b89c' stroke-width='0.5' fill='none' opacity='0.3'/%3E%3C/svg%3E");
background-size: 200px 200px;
animation: floatVines 30s ease-in-out infinite;
pointer-events: none;
opacity: 0.3;
}
@keyframes floatVines {
0%, 100% { transform: translateX(0) translateY(0); }
50% { transform: translateX(-20px) translateY(-10px); }
}
main {
width: 100%;
max-width: 800px;
position: relative;
z-index: 1;
}
h1 {
text-align: center;
color: #4a5c3a;
margin-bottom: 40px;
font-size: 2.5em;
font-weight: 300;
position: relative;
}
h1::after {
content: '🌿';
position: absolute;
right: -40px;
top: 50%;
transform: translateY(-50%) rotate(-20deg);
font-size: 0.6em;
animation: sway 4s ease-in-out infinite;
}
@keyframes sway {
0%, 100% { transform: translateY(-50%) rotate(-20deg); }
50% { transform: translateY(-50%) rotate(20deg); }
}
.hybrid-component {
background: rgba(255, 255, 255, 0.9);
border-radius: 30px;
padding: 40px;
box-shadow:
0 10px 40px rgba(74, 92, 58, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.9);
position: relative;
overflow: visible;
}
/* Decorative leaf corners */
.hybrid-component::before,
.hybrid-component::after {
content: '🍃';
position: absolute;
font-size: 2em;
opacity: 0.3;
animation: leafFloat 6s ease-in-out infinite;
}
.hybrid-component::before {
top: -10px;
left: -10px;
transform: rotate(-45deg);
}
.hybrid-component::after {
bottom: -10px;
right: -10px;
transform: rotate(135deg);
animation-delay: 3s;
}
@keyframes leafFloat {
0%, 100% { transform: translateY(0) rotate(inherit); }
50% { transform: translateY(-5px) rotate(calc(inherit + 10deg)); }
}
/* Search Container */
.search-container {
position: relative;
margin-bottom: 30px;
}
.search-wrapper {
position: relative;
background: linear-gradient(135deg, #f0f4e8 0%, #e8eede 100%);
border-radius: 25px;
border: 2px solid #c5d4b5;
overflow: hidden;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.search-wrapper:focus-within {
transform: scale(1.02);
box-shadow: 0 8px 30px rgba(139, 168, 112, 0.2);
border-color: #8ba870;
}
.search-input {
width: 100%;
padding: 20px 60px 20px 25px;
font-size: 18px;
font-family: inherit;
border: none;
background: transparent;
color: #2d3a24;
outline: none;
}
.search-input::placeholder {
color: #7a8b6a;
transition: opacity 0.3s;
}
.search-input:focus::placeholder {
opacity: 0.5;
}
.search-icon {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
width: 24px;
height: 24px;
cursor: pointer;
transition: transform 0.3s ease-out;
}
.search-icon:hover {
transform: translateY(-50%) scale(1.1);
}
.search-icon svg {
width: 100%;
height: 100%;
stroke: #7a8b6a;
stroke-width: 2;
fill: none;
transition: stroke 0.3s;
}
.search-wrapper:focus-within .search-icon svg {
stroke: #4a5c3a;
}
/* Growing vine animation on search */
.search-vine {
position: absolute;
bottom: -2px;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #8ba870 0%, #a4b896 50%, #8ba870 100%);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.search-wrapper:focus-within .search-vine {
transform: scaleX(1);
}
/* Autocomplete Dropdown */
.autocomplete {
position: absolute;
top: 100%;
left: 0;
right: 0;
margin-top: 10px;
background: rgba(255, 255, 255, 0.98);
border-radius: 20px;
box-shadow: 0 10px 40px rgba(74, 92, 58, 0.15);
overflow: hidden;
opacity: 0;
transform: translateY(-10px) scale(0.95);
pointer-events: none;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 10;
}
.autocomplete.active {
opacity: 1;
transform: translateY(0) scale(1);
pointer-events: all;
}
.autocomplete-item {
padding: 15px 25px;
cursor: pointer;
display: flex;
align-items: center;
gap: 15px;
position: relative;
overflow: hidden;
transition: all 0.3s ease-out;
}
.autocomplete-item::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 4px;
background: #8ba870;
transform: scaleY(0);
transition: transform 0.3s ease-out;
}
.autocomplete-item:hover {
background: #f0f4e8;
padding-left: 35px;
}
.autocomplete-item:hover::before {
transform: scaleY(1);
}
.autocomplete-icon {
font-size: 1.2em;
opacity: 0;
transform: scale(0) rotate(-180deg);
transition: all 0.3s ease-out;
}
.autocomplete-item:hover .autocomplete-icon {
opacity: 1;
transform: scale(1) rotate(0);
}
/* Recent Items (Seed Pods) */
.recent-items {
margin-bottom: 30px;
}
.recent-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 15px;
color: #4a5c3a;
}
.recent-header h3 {
font-size: 1.1em;
font-weight: 400;
}
.seed-pods {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.seed-pod {
background: linear-gradient(135deg, #e8d5b7 0%, #d4c4a0 100%);
border: 1px solid #c9b897;
border-radius: 20px;
padding: 8px 16px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease-out;
position: relative;
overflow: hidden;
}
.seed-pod::before {
content: '🌰';
position: absolute;
left: -20px;
top: 50%;
transform: translateY(-50%);
opacity: 0;
transition: all 0.3s ease-out;
}
.seed-pod:hover {
transform: translateY(-2px) scale(1.05);
box-shadow: 0 4px 15px rgba(180, 160, 120, 0.3);
padding-left: 30px;
background: linear-gradient(135deg, #f0e2c4 0%, #dcc8a5 100%);
}
.seed-pod:hover::before {
left: 8px;
opacity: 1;
}
/* Filters (Unfolding Leaves) */
.filters {
margin-bottom: 30px;
}
.filters-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15px;
}
.filters-header h3 {
color: #4a5c3a;
font-size: 1.1em;
font-weight: 400;
}
.filter-toggle {
background: none;
border: none;
cursor: pointer;
font-size: 1.2em;
transition: transform 0.3s ease-out;
}
.filter-toggle.active {
transform: rotate(180deg);
}
.filter-leaves {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 12px;
max-height: 0;
overflow: hidden;
opacity: 0;
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.filter-leaves.open {
max-height: 200px;
opacity: 1;
margin-top: 15px;
}
.filter-leaf {
background: linear-gradient(135deg, #d4e4c5 0%, #c5d4b5 100%);
border: 1px solid #b5c4a5;
border-radius: 15px 5px 15px 5px;
padding: 10px 15px;
cursor: pointer;
transition: all 0.3s ease-out;
position: relative;
overflow: hidden;
}
.filter-leaf::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, #a4b896 0%, #8ba870 100%);
opacity: 0;
transition: opacity 0.3s ease-out;
}
.filter-leaf.active::before {
opacity: 1;
}
.filter-leaf span {
position: relative;
z-index: 1;
display: flex;
align-items: center;
gap: 8px;
color: #4a5c3a;
font-size: 14px;
transition: color 0.3s;
}
.filter-leaf.active span {
color: white;
}
.filter-leaf:hover {
transform: scale(1.05) rotate(-2deg);
box-shadow: 0 4px 15px rgba(139, 168, 112, 0.2);
}
/* Results Preview */
.results-preview {
opacity: 0;
transform: translateY(20px);
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.results-preview.active {
opacity: 1;
transform: translateY(0);
}
.results-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid #e5e5e5;
}
.results-header h3 {
color: #4a5c3a;
font-size: 1.1em;
font-weight: 400;
}
.results-count {
color: #7a8b6a;
font-size: 14px;
}
.result-item {
background: linear-gradient(135deg, #fafaf5 0%, #f5f5f0 100%);
border: 1px solid #e5e5e5;
border-radius: 15px;
padding: 20px;
margin-bottom: 15px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: all 0.3s ease-out;
}
.result-item::before {
content: '';
position: absolute;
left: -100%;
top: 0;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent 0%, rgba(139, 168, 112, 0.1) 50%, transparent 100%);
transition: left 0.5s ease-out;
}
.result-item:hover::before {
left: 100%;
}
.result-item:hover {
transform: translateX(5px);
box-shadow: 0 4px 20px rgba(139, 168, 112, 0.1);
border-color: #c5d4b5;
}
.result-title {
font-size: 16px;
font-weight: 600;
color: #2d3a24;
margin-bottom: 8px;
}
.result-description {
font-size: 14px;
color: #7a8b6a;
line-height: 1.5;
}
.result-meta {
display: flex;
gap: 15px;
margin-top: 10px;
font-size: 12px;
color: #a0a0a0;
}
/* Loading animation */
.loading-roots {
display: none;
justify-content: center;
align-items: center;
height: 100px;
gap: 10px;
}
.loading-roots.active {
display: flex;
}
.root {
width: 4px;
height: 40px;
background: linear-gradient(to bottom, #8ba870, #4a5c3a);
border-radius: 2px;
animation: growRoot 1.2s ease-in-out infinite;
}
.root:nth-child(2) { animation-delay: 0.1s; }
.root:nth-child(3) { animation-delay: 0.2s; }
.root:nth-child(4) { animation-delay: 0.3s; }
.root:nth-child(5) { animation-delay: 0.4s; }
@keyframes growRoot {
0%, 100% {
transform: scaleY(0.4);
opacity: 0.5;
}
50% {
transform: scaleY(1);
opacity: 1;
}
}
/* Breathing idle animation */
.breathing {
animation: breathe 4s ease-in-out infinite;
}
@keyframes breathe {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.02); }
}
</style>
</head>
<body>
<main>
<h1>Search Hub - Organic Nature Theme</h1>
<div class="hybrid-component breathing">
<!-- Search Bar with Growing Vine -->
<div class="search-container">
<div class="search-wrapper">
<input
type="text"
class="search-input"
placeholder="Plant your search seeds..."
id="searchInput"
>
<div class="search-icon" id="searchIcon">
<svg viewBox="0 0 24 24">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
</div>
<div class="search-vine"></div>
</div>
<!-- Autocomplete Dropdown (Blooming Flowers) -->
<div class="autocomplete" id="autocomplete">
<div class="autocomplete-item">
<span class="autocomplete-icon">🌸</span>
<span>Organic vegetables delivery</span>
</div>
<div class="autocomplete-item">
<span class="autocomplete-icon">🌺</span>
<span>Organic farming techniques</span>
</div>
<div class="autocomplete-item">
<span class="autocomplete-icon">🌼</span>
<span>Organic garden design ideas</span>
</div>
<div class="autocomplete-item">
<span class="autocomplete-icon">🌻</span>
<span>Organic skincare products</span>
</div>
</div>
</div>
<!-- Recent Items (Seed Pods) -->
<div class="recent-items">
<div class="recent-header">
<span>🌱</span>
<h3>Recently Planted</h3>
</div>
<div class="seed-pods">
<div class="seed-pod">Garden tools</div>
<div class="seed-pod">Composting guide</div>
<div class="seed-pod">Native plants</div>
<div class="seed-pod">Herb garden</div>
<div class="seed-pod">Soil health</div>
</div>
</div>
<!-- Filters (Unfolding Leaves) -->
<div class="filters">
<div class="filters-header">
<h3>🍀 Filter by Category</h3>
<button class="filter-toggle" id="filterToggle">🍃</button>
</div>
<div class="filter-leaves" id="filterLeaves">
<div class="filter-leaf" data-filter="plants">
<span>🌿 Plants</span>
</div>
<div class="filter-leaf" data-filter="tools">
<span>🛠️ Tools</span>
</div>
<div class="filter-leaf" data-filter="guides">
<span>📖 Guides</span>
</div>
<div class="filter-leaf" data-filter="seeds">
<span>🌰 Seeds</span>
</div>
<div class="filter-leaf" data-filter="organic">
<span>🌾 Organic</span>
</div>
<div class="filter-leaf" data-filter="indoor">
<span>🪴 Indoor</span>
</div>
</div>
</div>
<!-- Loading Animation -->
<div class="loading-roots" id="loadingRoots">
<div class="root"></div>
<div class="root"></div>
<div class="root"></div>
<div class="root"></div>
<div class="root"></div>
</div>
<!-- Results Preview (Natural Growth) -->
<div class="results-preview" id="resultsPreview">
<div class="results-header">
<h3>🌳 Growing Results</h3>
<span class="results-count">5 branches found</span>
</div>
<div class="result-item">
<div class="result-title">Organic Vegetable Garden Starter Kit</div>
<div class="result-description">
Everything you need to start your own organic vegetable garden, including heirloom seeds,
natural fertilizers, and comprehensive growing guides.
</div>
<div class="result-meta">
<span>🌟 4.8 rating</span>
<span>💚 Eco-friendly</span>
<span>📦 Ships in 2 days</span>
</div>
</div>
<div class="result-item">
<div class="result-title">Complete Guide to Companion Planting</div>
<div class="result-description">
Learn which plants grow better together and create a thriving ecosystem in your garden
using natural symbiotic relationships.
</div>
<div class="result-meta">
<span>📚 Digital guide</span>
<span>🌱 Beginner friendly</span>
<span>⏱️ 45 min read</span>
</div>
</div>
<div class="result-item">
<div class="result-title">Handcrafted Cedar Raised Garden Beds</div>
<div class="result-description">
Beautiful, sustainably sourced cedar garden beds that naturally resist pests and weather
while providing the perfect growing environment.
</div>
<div class="result-meta">
<span>🪵 Sustainable wood</span>
<span>🔨 Easy assembly</span>
<span>🎯 Custom sizes</span>
</div>
</div>
</div>
</div>
</main>
<script>
// Nature-inspired search hub functionality
const searchInput = document.getElementById('searchInput');
const autocomplete = document.getElementById('autocomplete');
const filterToggle = document.getElementById('filterToggle');
const filterLeaves = document.getElementById('filterLeaves');
const resultsPreview = document.getElementById('resultsPreview');
const loadingRoots = document.getElementById('loadingRoots');
const seedPods = document.querySelectorAll('.seed-pod');
const filterItems = document.querySelectorAll('.filter-leaf');
let searchTimeout;
let activeFilters = new Set();
// Search input handling with vine growth
searchInput.addEventListener('input', (e) => {
const value = e.target.value;
clearTimeout(searchTimeout);
if (value.length > 0) {
// Show autocomplete with blooming animation
autocomplete.classList.add('active');
// Simulate search delay with root growth
searchTimeout = setTimeout(() => {
showSearchResults();
}, 800);
} else {
autocomplete.classList.remove('active');
resultsPreview.classList.remove('active');
}
});
// Click outside to close autocomplete
document.addEventListener('click', (e) => {
if (!e.target.closest('.search-container')) {
autocomplete.classList.remove('active');
}
});
// Autocomplete item selection
document.querySelectorAll('.autocomplete-item').forEach(item => {
item.addEventListener('click', () => {
const text = item.querySelector('span:last-child').textContent;
searchInput.value = text;
autocomplete.classList.remove('active');
showSearchResults();
// Add to recent items
addToRecentItems(text);
});
});
// Filter toggle animation
filterToggle.addEventListener('click', () => {
filterToggle.classList.toggle('active');
filterLeaves.classList.toggle('open');
});
// Filter leaf selection
filterItems.forEach(leaf => {
leaf.addEventListener('click', () => {
leaf.classList.toggle('active');
const filter = leaf.dataset.filter;
if (activeFilters.has(filter)) {
activeFilters.delete(filter);
} else {
activeFilters.add(filter);
}
// Trigger filtered search if there's a search term
if (searchInput.value) {
showSearchResults();
}
});
});
// Seed pod (recent item) clicks
seedPods.forEach(pod => {
pod.addEventListener('click', () => {
searchInput.value = pod.textContent;
showSearchResults();
});
});
// Show search results with growth animation
function showSearchResults() {
// Show loading roots
resultsPreview.classList.remove('active');
loadingRoots.classList.add('active');
// Simulate loading time
setTimeout(() => {
loadingRoots.classList.remove('active');
resultsPreview.classList.add('active');
// Update results count based on filters
const count = 5 - activeFilters.size;
document.querySelector('.results-count').textContent =
`${count} branch${count !== 1 ? 'es' : ''} found`;
}, 1200);
}
// Add to recent items
function addToRecentItems(text) {
const seedPodsContainer = document.querySelector('.seed-pods');
const existingPods = Array.from(seedPods);
// Check if already exists
const exists = existingPods.some(pod => pod.textContent === text);
if (!exists) {
// Create new seed pod
const newPod = document.createElement('div');
newPod.className = 'seed-pod';
newPod.textContent = text.substring(0, 20) + (text.length > 20 ? '...' : '');
// Add click handler
newPod.addEventListener('click', () => {
searchInput.value = text;
showSearchResults();
});
// Add with growth animation
newPod.style.transform = 'scale(0)';
seedPodsContainer.insertBefore(newPod, seedPodsContainer.firstChild);
// Animate growth
setTimeout(() => {
newPod.style.transform = 'scale(1)';
newPod.style.transition = 'transform 0.3s ease-out';
}, 10);
// Remove oldest if too many
if (seedPodsContainer.children.length > 8) {
const oldest = seedPodsContainer.lastChild;
oldest.style.transform = 'scale(0)';
setTimeout(() => oldest.remove(), 300);
}
}
}
// Result item hover sound effect (optional - using CSS only for now)
document.querySelectorAll('.result-item').forEach(item => {
item.addEventListener('mouseenter', () => {
// Could add subtle nature sound here
item.style.transform = 'translateX(5px)';
});
});
// Initial breathing animation
const component = document.querySelector('.hybrid-component');
setInterval(() => {
component.classList.add('breathing');
}, 100);
</script>
</body>
</html>

View File

@ -0,0 +1,829 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Architectural Brutalism Dashboard Widget</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Helvetica Neue', Arial, sans-serif;
background: #1a1a1a;
color: #e0e0e0;
line-height: 1.6;
padding: 40px;
min-height: 100vh;
overflow-x: hidden;
}
main {
max-width: 1400px;
margin: 0 auto;
}
h1 {
font-size: 3em;
font-weight: 900;
letter-spacing: -0.02em;
color: #fff;
margin-bottom: 40px;
text-transform: uppercase;
text-shadow: 4px 4px 0 #000;
}
/* Brutalist Dashboard Container */
.hybrid-component {
background: #2a2a2a;
padding: 0;
border: 8px solid #333;
box-shadow:
0 10px 0 #1a1a1a,
0 20px 0 #0a0a0a,
0 20px 40px rgba(0,0,0,0.8);
position: relative;
}
/* Control Panel Header */
.control-panel {
background: linear-gradient(to bottom, #404040, #303030);
padding: 20px 30px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 4px solid #1a1a1a;
position: relative;
}
.control-panel::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 8px;
background: repeating-linear-gradient(
90deg,
#ff6b6b 0,
#ff6b6b 20px,
#ffcc00 20px,
#ffcc00 40px
);
}
/* Industrial Switches (Filters) */
.filter-bank {
display: flex;
gap: 20px;
align-items: center;
}
.industrial-switch {
position: relative;
width: 80px;
height: 40px;
background: #1a1a1a;
border: 3px solid #333;
cursor: pointer;
overflow: hidden;
transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.industrial-switch:hover {
transform: translateY(-2px);
box-shadow: 0 4px 0 #000;
}
.switch-label {
position: absolute;
top: -25px;
left: 50%;
transform: translateX(-50%);
font-size: 11px;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 700;
color: #999;
}
.switch-handle {
position: absolute;
left: 3px;
top: 3px;
width: 34px;
height: 28px;
background: linear-gradient(to bottom, #666, #444);
border: 2px solid #222;
transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.industrial-switch.active .switch-handle {
left: 39px;
background: linear-gradient(to bottom, #ff6b6b, #e55a5a);
box-shadow: 0 0 10px #ff6b6b;
}
/* Control Buttons */
.control-buttons {
display: flex;
gap: 15px;
}
.brutalist-button {
background: #333;
border: 3px solid #444;
color: #fff;
padding: 10px 20px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
cursor: pointer;
position: relative;
transition: all 0.2s;
font-size: 12px;
}
.brutalist-button:hover {
transform: translate(-2px, -2px);
box-shadow: 2px 2px 0 #ff6b6b;
}
.brutalist-button:active {
transform: translate(0, 0);
box-shadow: none;
}
.brutalist-button.refresh {
background: #444;
border-color: #555;
}
.brutalist-button.export {
background: #3a3a3a;
border-color: #4a4a4a;
}
.brutalist-button.settings {
background: #383838;
border-color: #484848;
padding: 10px 15px;
}
/* Main Dashboard Content */
.dashboard-content {
display: grid;
grid-template-columns: 1fr 300px;
min-height: 500px;
}
/* Chart Area - Concrete Blocks */
.chart-container {
background: #1a1a1a;
padding: 40px;
position: relative;
overflow: hidden;
}
.concrete-chart {
height: 400px;
display: flex;
align-items: flex-end;
justify-content: space-around;
gap: 20px;
position: relative;
}
.chart-block {
flex: 1;
background: linear-gradient(to bottom, #4a4a4a, #3a3a3a);
position: relative;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border: 4px solid #2a2a2a;
box-shadow:
inset 0 -4px 0 #1a1a1a,
0 4px 0 #0a0a0a;
}
.chart-block:hover {
transform: translateY(-10px);
box-shadow:
inset 0 -4px 0 #1a1a1a,
0 14px 0 #0a0a0a,
0 14px 20px rgba(0,0,0,0.5);
}
.chart-block::before {
content: attr(data-value);
position: absolute;
top: -30px;
left: 50%;
transform: translateX(-50%);
font-weight: 900;
font-size: 18px;
color: #ff6b6b;
text-shadow: 2px 2px 0 #000;
}
.chart-block::after {
content: attr(data-label);
position: absolute;
bottom: -30px;
left: 50%;
transform: translateX(-50%);
font-weight: 700;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 1px;
color: #666;
}
/* Grid Overlay */
.grid-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
background-image:
repeating-linear-gradient(0deg, transparent, transparent 39px, #2a2a2a 39px, #2a2a2a 40px),
repeating-linear-gradient(90deg, transparent, transparent 19.5%, #2a2a2a 19.5%, #2a2a2a 20%);
opacity: 0.3;
}
/* Side Panel - Settings & Alerts */
.side-panel {
background: #262626;
border-left: 4px solid #1a1a1a;
display: flex;
flex-direction: column;
}
/* Settings Panel */
.settings-panel {
padding: 30px 20px;
border-bottom: 4px solid #1a1a1a;
}
.panel-title {
font-weight: 900;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 2px;
margin-bottom: 20px;
color: #999;
}
.control-group {
margin-bottom: 20px;
}
.control-label {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 1px;
color: #666;
margin-bottom: 8px;
display: block;
}
.brutalist-slider {
width: 100%;
height: 8px;
background: #1a1a1a;
outline: none;
-webkit-appearance: none;
cursor: pointer;
position: relative;
}
.brutalist-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 20px;
height: 20px;
background: linear-gradient(to bottom, #666, #444);
border: 3px solid #222;
cursor: pointer;
}
.brutalist-slider::-moz-range-thumb {
width: 20px;
height: 20px;
background: linear-gradient(to bottom, #666, #444);
border: 3px solid #222;
cursor: pointer;
}
.brutalist-select {
width: 100%;
padding: 8px 12px;
background: #1a1a1a;
border: 3px solid #333;
color: #999;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
cursor: pointer;
font-size: 11px;
}
/* Alert System */
.alert-panel {
flex: 1;
padding: 30px 20px;
display: flex;
flex-direction: column;
}
.alert-lights {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
margin-top: 20px;
}
.alert-indicator {
aspect-ratio: 1;
background: #1a1a1a;
border: 4px solid #2a2a2a;
position: relative;
cursor: pointer;
transition: all 0.3s;
}
.alert-indicator::before {
content: attr(data-alert);
position: absolute;
bottom: -20px;
left: 50%;
transform: translateX(-50%);
font-size: 9px;
text-transform: uppercase;
letter-spacing: 1px;
color: #555;
white-space: nowrap;
}
.alert-indicator.active {
animation: alertPulse 1s infinite;
background: #ff6b6b;
border-color: #ff4444;
box-shadow:
0 0 20px #ff6b6b,
inset 0 0 20px rgba(255,255,255,0.3);
}
.alert-indicator.warning {
background: #ffcc00;
border-color: #ffaa00;
box-shadow:
0 0 20px #ffcc00,
inset 0 0 20px rgba(255,255,255,0.3);
}
@keyframes alertPulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.8; transform: scale(0.95); }
}
/* Export Blueprint Overlay */
.blueprint-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.95);
display: none;
z-index: 1000;
padding: 40px;
overflow: auto;
}
.blueprint-overlay.active {
display: block;
}
.blueprint-content {
max-width: 1200px;
margin: 0 auto;
background: #001a33;
border: 4px solid #003366;
padding: 40px;
position: relative;
}
.blueprint-grid {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
repeating-linear-gradient(0deg, transparent, transparent 19px, #003366 19px, #003366 20px),
repeating-linear-gradient(90deg, transparent, transparent 19px, #003366 19px, #003366 20px);
opacity: 0.2;
pointer-events: none;
}
.blueprint-title {
font-size: 24px;
font-weight: 900;
text-transform: uppercase;
letter-spacing: 3px;
color: #66ccff;
margin-bottom: 30px;
text-shadow: 2px 2px 0 #003366;
}
.blueprint-data {
font-family: 'Courier New', monospace;
color: #66ccff;
line-height: 1.8;
position: relative;
z-index: 1;
}
.blueprint-close {
position: absolute;
top: 20px;
right: 20px;
width: 40px;
height: 40px;
background: #003366;
border: 3px solid #66ccff;
color: #66ccff;
font-size: 24px;
font-weight: 900;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
}
.blueprint-close:hover {
background: #66ccff;
color: #001a33;
transform: rotate(90deg);
}
/* Rotating Refresh Animation */
@keyframes concreteRotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.brutalist-button.refresh.rotating {
animation: concreteRotate 2s cubic-bezier(0.25, 0.46, 0.45, 0.94) infinite;
}
/* Responsive Design */
@media (max-width: 1024px) {
.dashboard-content {
grid-template-columns: 1fr;
}
.side-panel {
border-left: none;
border-top: 4px solid #1a1a1a;
display: grid;
grid-template-columns: 1fr 1fr;
}
.settings-panel {
border-right: 4px solid #1a1a1a;
border-bottom: none;
}
}
@media (max-width: 768px) {
body {
padding: 20px;
}
h1 {
font-size: 2em;
}
.control-panel {
flex-direction: column;
gap: 20px;
align-items: stretch;
}
.filter-bank {
justify-content: space-around;
}
.control-buttons {
justify-content: space-around;
}
.chart-container {
padding: 20px;
}
.concrete-chart {
height: 300px;
}
}
</style>
</head>
<body>
<main>
<h1>Dashboard Widget - Architectural Brutalism Theme</h1>
<div class="hybrid-component">
<!-- Control Panel with Filters and Actions -->
<div class="control-panel">
<div class="filter-bank">
<div class="industrial-switch" data-filter="revenue">
<span class="switch-label">Revenue</span>
<div class="switch-handle"></div>
</div>
<div class="industrial-switch" data-filter="users">
<span class="switch-label">Users</span>
<div class="switch-handle"></div>
</div>
<div class="industrial-switch" data-filter="traffic">
<span class="switch-label">Traffic</span>
<div class="switch-handle"></div>
</div>
<div class="industrial-switch" data-filter="sales">
<span class="switch-label">Sales</span>
<div class="switch-handle"></div>
</div>
</div>
<div class="control-buttons">
<button class="brutalist-button refresh">↻ Refresh</button>
<button class="brutalist-button export">⬇ Export</button>
<button class="brutalist-button settings"></button>
</div>
</div>
<!-- Main Dashboard Content -->
<div class="dashboard-content">
<!-- Chart Container with Concrete Blocks -->
<div class="chart-container">
<div class="concrete-chart" id="chart">
<div class="chart-block" data-value="87%" data-label="Jan" style="height: 87%"></div>
<div class="chart-block" data-value="92%" data-label="Feb" style="height: 92%"></div>
<div class="chart-block" data-value="76%" data-label="Mar" style="height: 76%"></div>
<div class="chart-block" data-value="84%" data-label="Apr" style="height: 84%"></div>
<div class="chart-block" data-value="95%" data-label="May" style="height: 95%"></div>
<div class="chart-block" data-value="79%" data-label="Jun" style="height: 79%"></div>
</div>
<div class="grid-overlay"></div>
</div>
<!-- Side Panel with Settings and Alerts -->
<div class="side-panel">
<!-- Settings Panel -->
<div class="settings-panel">
<h3 class="panel-title">Control Infrastructure</h3>
<div class="control-group">
<label class="control-label">Update Frequency</label>
<input type="range" class="brutalist-slider" min="1" max="60" value="30">
</div>
<div class="control-group">
<label class="control-label">Data Granularity</label>
<select class="brutalist-select">
<option>Hourly</option>
<option>Daily</option>
<option selected>Monthly</option>
<option>Yearly</option>
</select>
</div>
<div class="control-group">
<label class="control-label">Alert Threshold</label>
<input type="range" class="brutalist-slider" min="0" max="100" value="75">
</div>
</div>
<!-- Alert Panel -->
<div class="alert-panel">
<h3 class="panel-title">Warning System</h3>
<div class="alert-lights">
<div class="alert-indicator" data-alert="CPU Load"></div>
<div class="alert-indicator active" data-alert="Memory"></div>
<div class="alert-indicator" data-alert="Network"></div>
<div class="alert-indicator warning" data-alert="Storage"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Blueprint Export Overlay -->
<div class="blueprint-overlay" id="blueprintOverlay">
<div class="blueprint-content">
<div class="blueprint-grid"></div>
<button class="blueprint-close" onclick="closeBlueprint()">×</button>
<h2 class="blueprint-title">System Architecture Blueprint</h2>
<pre class="blueprint-data" id="blueprintData"></pre>
</div>
</div>
</main>
<script>
// Industrial Switch Functionality
const switches = document.querySelectorAll('.industrial-switch');
const chartBlocks = document.querySelectorAll('.chart-block');
switches.forEach(switchEl => {
switchEl.addEventListener('click', function() {
this.classList.toggle('active');
updateChartData();
});
});
// Chart Block Interactions
chartBlocks.forEach(block => {
block.addEventListener('click', function() {
// Animate block
this.style.transition = 'all 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55)';
this.style.transform = 'translateY(-20px) scale(1.05)';
setTimeout(() => {
this.style.transform = 'translateY(0) scale(1)';
}, 600);
// Flash value
const value = this.getAttribute('data-value');
this.setAttribute('data-value', '▓▓▓');
setTimeout(() => {
this.setAttribute('data-value', value);
}, 300);
});
});
// Refresh Functionality
const refreshBtn = document.querySelector('.brutalist-button.refresh');
refreshBtn.addEventListener('click', function() {
this.classList.add('rotating');
// Simulate data refresh
setTimeout(() => {
updateChartData();
this.classList.remove('rotating');
// Flash all blocks
chartBlocks.forEach((block, index) => {
setTimeout(() => {
const newHeight = Math.floor(Math.random() * 30) + 70;
block.style.height = newHeight + '%';
block.setAttribute('data-value', newHeight + '%');
}, index * 100);
});
}, 2000);
});
// Export Blueprint Functionality
const exportBtn = document.querySelector('.brutalist-button.export');
exportBtn.addEventListener('click', function() {
generateBlueprint();
document.getElementById('blueprintOverlay').classList.add('active');
});
function generateBlueprint() {
const activeFilters = Array.from(switches)
.filter(s => s.classList.contains('active'))
.map(s => s.getAttribute('data-filter'));
const chartData = Array.from(chartBlocks).map(block => ({
label: block.getAttribute('data-label'),
value: block.getAttribute('data-value')
}));
const blueprint = `DASHBOARD CONFIGURATION BLUEPRINT
===============================================
Generated: ${new Date().toISOString()}
Version: 1.0.0
ACTIVE FILTERS:
${activeFilters.length ? activeFilters.map(f => ` - ${f.toUpperCase()}`).join('\n') : ' - NONE'}
CHART DATA STRUCTURE:
${chartData.map(d => ` ${d.label}: ${d.value}`).join('\n')}
SYSTEM ALERTS:
- CPU Load: NORMAL
- Memory: CRITICAL
- Network: NORMAL
- Storage: WARNING
SETTINGS:
- Update Frequency: 30s
- Data Granularity: MONTHLY
- Alert Threshold: 75%
BUILD INSTRUCTIONS:
1. Initialize concrete block rendering engine
2. Configure industrial switch matrix
3. Establish alert monitoring pipeline
4. Activate data refresh mechanism
5. Enable blueprint export system
END BLUEPRINT
===============================================`;
document.getElementById('blueprintData').textContent = blueprint;
}
function closeBlueprint() {
document.getElementById('blueprintOverlay').classList.remove('active');
}
// Settings Panel Interactions
const sliders = document.querySelectorAll('.brutalist-slider');
sliders.forEach(slider => {
slider.addEventListener('input', function() {
// Visual feedback
const percent = (this.value - this.min) / (this.max - this.min);
this.style.background = `linear-gradient(to right, #ff6b6b 0%, #ff6b6b ${percent * 100}%, #1a1a1a ${percent * 100}%, #1a1a1a 100%)`;
});
});
// Alert System
const alertIndicators = document.querySelectorAll('.alert-indicator');
// Simulate random alerts
setInterval(() => {
const randomAlert = alertIndicators[Math.floor(Math.random() * alertIndicators.length)];
const alertType = Math.random() > 0.5 ? 'active' : 'warning';
// Clear other alerts occasionally
if (Math.random() > 0.7) {
alertIndicators.forEach(alert => {
alert.classList.remove('active', 'warning');
});
}
// Set new alert
randomAlert.classList.add(alertType);
}, 5000);
// Update chart based on active filters
function updateChartData() {
const activeFilters = Array.from(switches)
.filter(s => s.classList.contains('active'))
.map(s => s.getAttribute('data-filter'));
// Simulate different data based on filters
chartBlocks.forEach((block, index) => {
let baseValue = parseInt(block.style.height);
activeFilters.forEach(filter => {
switch(filter) {
case 'revenue':
baseValue += Math.random() * 10 - 5;
break;
case 'users':
baseValue += Math.random() * 15 - 7.5;
break;
case 'traffic':
baseValue += Math.random() * 20 - 10;
break;
case 'sales':
baseValue += Math.random() * 12 - 6;
break;
}
});
baseValue = Math.max(20, Math.min(100, baseValue));
block.style.height = Math.floor(baseValue) + '%';
block.setAttribute('data-value', Math.floor(baseValue) + '%');
});
}
// Keyboard shortcuts
document.addEventListener('keydown', (e) => {
if (e.key === 'r' && (e.metaKey || e.ctrlKey)) {
e.preventDefault();
refreshBtn.click();
} else if (e.key === 'e' && (e.metaKey || e.ctrlKey)) {
e.preventDefault();
exportBtn.click();
} else if (e.key === 'Escape') {
closeBlueprint();
}
});
// Initialize sliders with gradient
sliders.forEach(slider => {
slider.dispatchEvent(new Event('input'));
});
</script>
</body>
</html>

View File

@ -0,0 +1,855 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ocean Depths Advanced Search - Themed Hybrid UI #11</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(180deg, #001f3f 0%, #003366 20%, #004080 50%, #000033 100%);
min-height: 100vh;
color: #e0f7fa;
overflow-x: hidden;
position: relative;
}
/* Animated bubbles background */
.bubble {
position: absolute;
background: radial-gradient(circle, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0.1) 100%);
border-radius: 50%;
opacity: 0.6;
animation: rise 10s infinite linear;
}
@keyframes rise {
from {
transform: translateY(100vh) translateX(0) scale(1);
}
to {
transform: translateY(-100px) translateX(100px) scale(0.5);
}
}
/* Water ripple effect */
.water-ripple {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(transparent 30%, rgba(0,100,200,0.1) 50%, transparent 70%);
animation: ripple 8s ease-in-out infinite;
pointer-events: none;
}
@keyframes ripple {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(20px); }
}
/* Main container */
.ocean-depths-container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
position: relative;
z-index: 10;
}
/* Title with bioluminescence */
.title {
text-align: center;
font-size: 3em;
margin-bottom: 40px;
text-shadow: 0 0 20px #00ffff, 0 0 40px #00ffff;
animation: glow 3s ease-in-out infinite alternate;
}
@keyframes glow {
from { text-shadow: 0 0 20px #00ffff, 0 0 40px #00ffff; }
to { text-shadow: 0 0 30px #00ffff, 0 0 50px #00ffff, 0 0 70px #00ffff; }
}
/* Periscope Search Bar */
.periscope-search {
position: relative;
width: 100%;
max-width: 600px;
margin: 0 auto 40px;
}
.periscope-lens {
position: absolute;
left: -60px;
top: 50%;
transform: translateY(-50%);
width: 50px;
height: 50px;
background: radial-gradient(circle, #1a5490 0%, #0d47a1 50%, #001f3f 100%);
border-radius: 50%;
border: 3px solid #00acc1;
box-shadow: 0 0 20px rgba(0,172,193,0.5);
}
.search-input {
width: 100%;
padding: 20px 60px 20px 20px;
font-size: 1.2em;
background: rgba(0,50,100,0.8);
border: 2px solid #00acc1;
border-radius: 50px;
color: #e0f7fa;
box-shadow: inset 0 2px 10px rgba(0,0,0,0.5), 0 0 20px rgba(0,172,193,0.3);
transition: all 0.3s ease;
}
.search-input:focus {
outline: none;
box-shadow: inset 0 2px 10px rgba(0,0,0,0.5), 0 0 30px rgba(0,255,255,0.5);
}
.search-button {
position: absolute;
right: 5px;
top: 50%;
transform: translateY(-50%);
padding: 15px 25px;
background: linear-gradient(135deg, #00acc1 0%, #0277bd 100%);
border: none;
border-radius: 50px;
color: white;
cursor: pointer;
font-size: 1.1em;
transition: all 0.3s ease;
}
.search-button:hover {
background: linear-gradient(135deg, #00bcd4 0%, #0288d1 100%);
box-shadow: 0 0 20px rgba(0,188,212,0.5);
}
/* Control Panel with Valves */
.control-panel {
display: flex;
gap: 20px;
margin-bottom: 40px;
flex-wrap: wrap;
justify-content: center;
}
/* Filter Valves */
.filter-valve {
position: relative;
width: 120px;
height: 120px;
}
.valve-wheel {
width: 100%;
height: 100%;
background: radial-gradient(circle, #1565c0 0%, #0d47a1 50%, #001f3f 100%);
border-radius: 50%;
border: 4px solid #00acc1;
position: relative;
cursor: pointer;
transition: transform 0.3s ease;
box-shadow: 0 5px 20px rgba(0,0,0,0.5);
}
.valve-wheel::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80%;
height: 4px;
background: #00acc1;
box-shadow: 0 0 10px rgba(0,172,193,0.5);
}
.valve-wheel::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(90deg);
width: 80%;
height: 4px;
background: #00acc1;
box-shadow: 0 0 10px rgba(0,172,193,0.5);
}
.valve-wheel.active {
transform: rotate(45deg);
border-color: #00ffff;
box-shadow: 0 5px 30px rgba(0,255,255,0.5);
}
.valve-label {
text-align: center;
margin-top: 10px;
font-size: 0.9em;
color: #b3e5fc;
}
/* Sonar Controls (Advanced Operators) */
.sonar-controls {
background: rgba(0,50,100,0.6);
border: 2px solid #00acc1;
border-radius: 20px;
padding: 20px;
margin-bottom: 40px;
backdrop-filter: blur(10px);
}
.sonar-title {
text-align: center;
margin-bottom: 20px;
font-size: 1.3em;
color: #00ffff;
text-shadow: 0 0 10px rgba(0,255,255,0.5);
}
.operator-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
justify-content: center;
}
.operator-btn {
padding: 10px 20px;
background: linear-gradient(135deg, #004080 0%, #002050 100%);
border: 1px solid #00acc1;
border-radius: 25px;
color: #b3e5fc;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.operator-btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 0;
height: 0;
border-radius: 50%;
background: rgba(0,255,255,0.3);
transition: width 0.3s, height 0.3s;
}
.operator-btn:hover::before {
width: 100%;
height: 100%;
}
.operator-btn:hover {
border-color: #00ffff;
color: #ffffff;
box-shadow: 0 0 15px rgba(0,255,255,0.5);
}
/* Autocomplete Bubbles */
.autocomplete-bubbles {
position: absolute;
top: 100%;
left: 0;
right: 0;
margin-top: 10px;
display: none;
}
.autocomplete-bubbles.active {
display: block;
}
.bubble-suggestion {
background: rgba(0,100,200,0.8);
border: 1px solid #00acc1;
border-radius: 30px;
padding: 10px 20px;
margin-bottom: 10px;
cursor: pointer;
transition: all 0.3s ease;
animation: bubbleIn 0.5s ease;
}
@keyframes bubbleIn {
from {
opacity: 0;
transform: translateY(20px) scale(0.8);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.bubble-suggestion:hover {
background: rgba(0,150,255,0.9);
transform: translateX(10px);
box-shadow: 0 0 20px rgba(0,255,255,0.3);
}
/* Ship's Log (History) */
.ships-log {
background: rgba(0,50,100,0.6);
border: 2px solid #00acc1;
border-radius: 20px;
padding: 20px;
margin-bottom: 40px;
backdrop-filter: blur(10px);
}
.log-title {
font-size: 1.5em;
margin-bottom: 20px;
color: #00ffff;
text-shadow: 0 0 10px rgba(0,255,255,0.5);
}
.log-entry {
background: rgba(0,30,60,0.5);
border-left: 3px solid #00acc1;
padding: 10px 15px;
margin-bottom: 10px;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.log-entry:hover {
background: rgba(0,50,100,0.7);
border-left-color: #00ffff;
transform: translateX(5px);
}
.log-timestamp {
font-size: 0.8em;
color: #80deea;
}
/* Treasure Chest (Saved Searches) */
.treasure-chest {
position: fixed;
bottom: 20px;
right: 20px;
width: 80px;
height: 60px;
cursor: pointer;
z-index: 100;
}
.chest-body {
position: absolute;
bottom: 0;
width: 100%;
height: 40px;
background: linear-gradient(135deg, #8b6914 0%, #cdaa3d 50%, #8b6914 100%);
border-radius: 5px;
box-shadow: 0 5px 20px rgba(0,0,0,0.5);
}
.chest-lid {
position: absolute;
bottom: 35px;
width: 100%;
height: 25px;
background: linear-gradient(135deg, #cdaa3d 0%, #eedc82 50%, #cdaa3d 100%);
border-radius: 5px 5px 0 0;
transform-origin: bottom;
transition: transform 0.3s ease;
}
.treasure-chest:hover .chest-lid {
transform: rotateX(-45deg);
}
.saved-searches {
position: fixed;
bottom: 100px;
right: 20px;
background: rgba(0,50,100,0.9);
border: 2px solid #cdaa3d;
border-radius: 10px;
padding: 20px;
display: none;
max-width: 300px;
backdrop-filter: blur(10px);
}
.saved-searches.open {
display: block;
animation: treasureOpen 0.5s ease;
}
@keyframes treasureOpen {
from {
opacity: 0;
transform: scale(0.8) translateY(20px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
/* Fish School Results */
.results-ocean {
min-height: 400px;
position: relative;
background: rgba(0,30,60,0.3);
border-radius: 20px;
padding: 20px;
overflow: hidden;
}
.fish-result {
background: linear-gradient(135deg, #004080 0%, #0066cc 100%);
border: 1px solid #00acc1;
border-radius: 50px 20px 20px 50px;
padding: 20px;
margin-bottom: 20px;
position: relative;
transition: all 0.3s ease;
animation: swim 20s ease-in-out infinite;
}
@keyframes swim {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(10px) rotate(1deg); }
50% { transform: translateX(-10px) rotate(-1deg); }
75% { transform: translateX(5px) rotate(0.5deg); }
}
.fish-result::before {
content: '>';
position: absolute;
right: -15px;
top: 50%;
transform: translateY(-50%);
font-size: 2em;
color: #004080;
}
.fish-result:hover {
background: linear-gradient(135deg, #0066cc 0%, #0099ff 100%);
transform: translateX(20px);
box-shadow: 0 0 30px rgba(0,153,255,0.3);
}
.result-title {
font-size: 1.2em;
margin-bottom: 10px;
color: #00ffff;
}
.result-description {
color: #b3e5fc;
line-height: 1.6;
}
/* Pressure Gauge */
.pressure-gauge {
position: fixed;
top: 20px;
right: 20px;
width: 100px;
height: 100px;
background: radial-gradient(circle, #001f3f 0%, #000033 100%);
border-radius: 50%;
border: 3px solid #00acc1;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 20px rgba(0,172,193,0.5);
}
.gauge-needle {
position: absolute;
width: 3px;
height: 40px;
background: #ff0000;
bottom: 50%;
left: 50%;
transform-origin: bottom;
transform: translateX(-50%) rotate(0deg);
transition: transform 0.5s ease;
box-shadow: 0 0 10px rgba(255,0,0,0.5);
}
.gauge-center {
width: 20px;
height: 20px;
background: #00acc1;
border-radius: 50%;
position: relative;
z-index: 10;
}
/* Responsive */
@media (max-width: 768px) {
.title {
font-size: 2em;
}
.control-panel {
gap: 10px;
}
.filter-valve {
width: 80px;
height: 80px;
}
.periscope-lens {
display: none;
}
.search-input {
padding: 15px 50px 15px 15px;
}
}
</style>
</head>
<body>
<div class="water-ripple"></div>
<!-- Animated bubbles -->
<div id="bubbleContainer"></div>
<div class="ocean-depths-container">
<h1 class="title">Ocean Depths Search</h1>
<!-- Periscope Search Bar -->
<div class="periscope-search">
<div class="periscope-lens"></div>
<input type="text" class="search-input" id="searchInput" placeholder="Explore the depths...">
<button class="search-button" onclick="performSearch()">Dive</button>
<!-- Autocomplete Bubbles -->
<div class="autocomplete-bubbles" id="autocompleteBubbles"></div>
</div>
<!-- Control Panel with Filter Valves -->
<div class="control-panel">
<div class="filter-valve">
<div class="valve-wheel" onclick="toggleFilter(this, 'recent')" data-filter="recent"></div>
<div class="valve-label">Recent</div>
</div>
<div class="filter-valve">
<div class="valve-wheel" onclick="toggleFilter(this, 'deep')" data-filter="deep"></div>
<div class="valve-label">Deep Search</div>
</div>
<div class="filter-valve">
<div class="valve-wheel" onclick="toggleFilter(this, 'images')" data-filter="images"></div>
<div class="valve-label">Images</div>
</div>
<div class="filter-valve">
<div class="valve-wheel" onclick="toggleFilter(this, 'videos')" data-filter="videos"></div>
<div class="valve-label">Videos</div>
</div>
<div class="filter-valve">
<div class="valve-wheel" onclick="toggleFilter(this, 'archived')" data-filter="archived"></div>
<div class="valve-label">Archived</div>
</div>
</div>
<!-- Sonar Controls (Advanced Operators) -->
<div class="sonar-controls">
<div class="sonar-title">Sonar Operations</div>
<div class="operator-buttons">
<button class="operator-btn" onclick="addOperator('AND')">AND</button>
<button class="operator-btn" onclick="addOperator('OR')">OR</button>
<button class="operator-btn" onclick="addOperator('NOT')">NOT</button>
<button class="operator-btn" onclick="addOperator('*')">Wildcard</button>
<button class="operator-btn" onclick="addOperator('\"\"')">Exact</button>
<button class="operator-btn" onclick="addOperator('~')">Fuzzy</button>
<button class="operator-btn" onclick="addOperator('^')">Boost</button>
<button class="operator-btn" onclick="addOperator('[]')">Range</button>
</div>
</div>
<!-- Ship's Log (History) -->
<div class="ships-log">
<div class="log-title">Ship's Log</div>
<div id="searchHistory"></div>
</div>
<!-- Results Ocean -->
<div class="results-ocean" id="resultsOcean">
<div class="fish-result">
<div class="result-title">Deep Sea Discovery</div>
<div class="result-description">Begin your exploration of the ocean depths...</div>
</div>
</div>
</div>
<!-- Treasure Chest (Saved Searches) -->
<div class="treasure-chest" onclick="toggleSavedSearches()">
<div class="chest-lid"></div>
<div class="chest-body"></div>
</div>
<div class="saved-searches" id="savedSearches">
<h3 style="color: #cdaa3d; margin-bottom: 15px;">Treasured Searches</h3>
<div id="savedSearchesList"></div>
<button class="operator-btn" style="margin-top: 10px;" onclick="saveCurrentSearch()">Save Current</button>
</div>
<!-- Pressure Gauge -->
<div class="pressure-gauge">
<div class="gauge-needle" id="pressureNeedle"></div>
<div class="gauge-center"></div>
</div>
<script>
// Initialize bubbles
function createBubbles() {
const container = document.getElementById('bubbleContainer');
for (let i = 0; i < 20; i++) {
const bubble = document.createElement('div');
bubble.className = 'bubble';
bubble.style.width = Math.random() * 40 + 10 + 'px';
bubble.style.height = bubble.style.width;
bubble.style.left = Math.random() * 100 + '%';
bubble.style.animationDelay = Math.random() * 10 + 's';
bubble.style.animationDuration = Math.random() * 10 + 10 + 's';
container.appendChild(bubble);
}
}
// Active filters
let activeFilters = new Set();
// Search history
let searchHistory = [];
// Saved searches
let savedSearches = JSON.parse(localStorage.getItem('oceanSearches') || '[]');
// Toggle filter
function toggleFilter(element, filter) {
element.classList.toggle('active');
if (activeFilters.has(filter)) {
activeFilters.delete(filter);
} else {
activeFilters.add(filter);
}
updatePressure();
}
// Add operator to search
function addOperator(operator) {
const input = document.getElementById('searchInput');
if (operator === '\"\"') {
const start = input.selectionStart;
const end = input.selectionEnd;
const text = input.value;
input.value = text.substring(0, start) + '\"' + text.substring(start, end) + '\"' + text.substring(end);
input.focus();
input.setSelectionRange(end + 2, end + 2);
} else if (operator === '[]') {
input.value += ' [TO ]';
input.focus();
input.setSelectionRange(input.value.length - 4, input.value.length - 4);
} else {
input.value += ' ' + operator + ' ';
input.focus();
}
}
// Autocomplete functionality
const searchInput = document.getElementById('searchInput');
const autocompleteBubbles = document.getElementById('autocompleteBubbles');
const suggestions = [
'coral reefs ecosystem',
'deep sea creatures',
'ocean currents patterns',
'marine biodiversity',
'underwater volcanoes',
'bioluminescent organisms',
'ocean floor mapping',
'submarine canyons',
'hydrothermal vents',
'abyssal plains'
];
searchInput.addEventListener('input', function() {
const value = this.value.toLowerCase();
if (value.length > 2) {
const matches = suggestions.filter(s => s.toLowerCase().includes(value));
showAutocomplete(matches);
} else {
hideAutocomplete();
}
});
function showAutocomplete(matches) {
autocompleteBubbles.innerHTML = '';
if (matches.length > 0) {
autocompleteBubbles.classList.add('active');
matches.slice(0, 5).forEach((match, index) => {
const bubble = document.createElement('div');
bubble.className = 'bubble-suggestion';
bubble.textContent = match;
bubble.style.animationDelay = index * 0.1 + 's';
bubble.onclick = () => {
searchInput.value = match;
hideAutocomplete();
};
autocompleteBubbles.appendChild(bubble);
});
}
}
function hideAutocomplete() {
autocompleteBubbles.classList.remove('active');
}
// Perform search
function performSearch() {
const query = searchInput.value;
if (query.trim()) {
// Add to history
addToHistory(query);
// Generate results
generateResults(query);
// Update pressure
updatePressure();
// Hide autocomplete
hideAutocomplete();
}
}
// Add to history
function addToHistory(query) {
const timestamp = new Date().toLocaleTimeString();
searchHistory.unshift({ query, timestamp });
if (searchHistory.length > 10) searchHistory.pop();
updateHistoryDisplay();
}
// Update history display
function updateHistoryDisplay() {
const historyContainer = document.getElementById('searchHistory');
historyContainer.innerHTML = '';
searchHistory.forEach(entry => {
const logEntry = document.createElement('div');
logEntry.className = 'log-entry';
logEntry.innerHTML = `
<div>${entry.query}</div>
<div class="log-timestamp">${entry.timestamp}</div>
`;
logEntry.onclick = () => {
searchInput.value = entry.query;
performSearch();
};
historyContainer.appendChild(logEntry);
});
}
// Generate results
function generateResults(query) {
const resultsOcean = document.getElementById('resultsOcean');
resultsOcean.innerHTML = '';
const sampleResults = [
{ title: 'Deep Ocean Mysteries', description: 'Exploring the unknown depths where light cannot reach...' },
{ title: 'Bioluminescent Wonders', description: 'Creatures that create their own light in the darkness...' },
{ title: 'Underwater Canyons', description: 'Massive geological formations carved by ancient currents...' },
{ title: 'Marine Life Adaptations', description: 'How organisms survive extreme pressure and darkness...' },
{ title: 'Ocean Current Patterns', description: 'The invisible rivers that flow through our seas...' }
];
sampleResults.forEach((result, index) => {
const fishResult = document.createElement('div');
fishResult.className = 'fish-result';
fishResult.style.animationDelay = index * 2 + 's';
fishResult.innerHTML = `
<div class="result-title">${result.title}</div>
<div class="result-description">${result.description}</div>
`;
resultsOcean.appendChild(fishResult);
});
}
// Toggle saved searches
function toggleSavedSearches() {
const savedSearchesPanel = document.getElementById('savedSearches');
savedSearchesPanel.classList.toggle('open');
if (savedSearchesPanel.classList.contains('open')) {
updateSavedSearchesList();
}
}
// Save current search
function saveCurrentSearch() {
const query = searchInput.value;
if (query.trim() && !savedSearches.includes(query)) {
savedSearches.push(query);
localStorage.setItem('oceanSearches', JSON.stringify(savedSearches));
updateSavedSearchesList();
}
}
// Update saved searches list
function updateSavedSearchesList() {
const list = document.getElementById('savedSearchesList');
list.innerHTML = '';
savedSearches.forEach(search => {
const item = document.createElement('div');
item.className = 'log-entry';
item.textContent = search;
item.onclick = () => {
searchInput.value = search;
performSearch();
toggleSavedSearches();
};
list.appendChild(item);
});
}
// Update pressure gauge
function updatePressure() {
const needle = document.getElementById('pressureNeedle');
const pressure = (activeFilters.size * 15) + (searchHistory.length * 5);
needle.style.transform = `translateX(-50%) rotate(${Math.min(pressure, 180)}deg)`;
}
// Keyboard shortcuts
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
performSearch();
}
});
// Initialize
createBubbles();
updateSavedSearchesList();
// Click outside to close autocomplete
document.addEventListener('click', function(e) {
if (!searchInput.contains(e.target) && !autocompleteBubbles.contains(e.target)) {
hideAutocomplete();
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,810 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Art Deco Profile Dashboard - Iteration 12</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Bebas+Neue&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Playfair Display', serif;
background: #0a0a0a;
color: #f4e7d1;
min-height: 100vh;
overflow-x: hidden;
}
/* Art Deco Background Pattern */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(212, 175, 55, 0.03) 10px,
rgba(212, 175, 55, 0.03) 20px
),
repeating-linear-gradient(
-45deg,
transparent,
transparent 10px,
rgba(212, 175, 55, 0.03) 10px,
rgba(212, 175, 55, 0.03) 20px
);
pointer-events: none;
z-index: 1;
}
.dashboard {
position: relative;
z-index: 2;
max-width: 1400px;
margin: 0 auto;
padding: 40px 20px;
}
/* Header with Art Deco Frame */
.header {
text-align: center;
margin-bottom: 50px;
position: relative;
}
.header h1 {
font-family: 'Bebas Neue', cursive;
font-size: 4rem;
letter-spacing: 0.2em;
color: #d4af37;
text-shadow:
0 0 20px rgba(212, 175, 55, 0.5),
2px 2px 4px rgba(0, 0, 0, 0.8);
margin-bottom: 10px;
}
.header-ornament {
width: 300px;
height: 40px;
margin: 0 auto;
background: linear-gradient(90deg,
transparent 0%,
#d4af37 20%,
#d4af37 80%,
transparent 100%
);
position: relative;
clip-path: polygon(
0 50%, 10% 0, 90% 0, 100% 50%,
90% 100%, 10% 100%
);
}
/* Main Grid Layout */
.main-grid {
display: grid;
grid-template-columns: 350px 1fr;
gap: 30px;
margin-bottom: 40px;
}
/* Profile Section */
.profile-section {
background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%);
border: 2px solid #d4af37;
border-radius: 0;
padding: 30px;
position: relative;
overflow: hidden;
}
.profile-section::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: repeating-conic-gradient(
from 0deg at 50% 50%,
transparent 0deg,
rgba(212, 175, 55, 0.1) 10deg,
transparent 20deg
);
animation: rotate 60s linear infinite;
}
@keyframes rotate {
to { transform: rotate(360deg); }
}
/* Avatar Container */
.avatar-container {
position: relative;
width: 200px;
height: 200px;
margin: 0 auto 30px;
z-index: 2;
}
.avatar-frame {
position: absolute;
inset: -20px;
background: conic-gradient(
from 45deg,
#d4af37 0deg,
#f4e7d1 45deg,
#d4af37 90deg,
#8b6914 135deg,
#d4af37 180deg,
#f4e7d1 225deg,
#d4af37 270deg,
#8b6914 315deg,
#d4af37 360deg
);
clip-path: polygon(
50% 0%, 100% 25%, 100% 75%, 50% 100%,
0% 75%, 0% 25%
);
animation: shimmer 4s ease-in-out infinite;
}
@keyframes shimmer {
0%, 100% { opacity: 1; }
50% { opacity: 0.7; }
}
.avatar {
position: absolute;
inset: 0;
background: linear-gradient(135deg, #2a2a2a, #1a1a1a);
clip-path: polygon(
50% 0%, 100% 25%, 100% 75%, 50% 100%,
0% 75%, 0% 25%
);
display: flex;
align-items: center;
justify-content: center;
font-family: 'Bebas Neue', cursive;
font-size: 4rem;
color: #d4af37;
}
.profile-name {
font-size: 1.8rem;
text-align: center;
margin-bottom: 10px;
color: #f4e7d1;
position: relative;
z-index: 2;
}
.profile-title {
font-size: 1rem;
text-align: center;
color: #d4af37;
letter-spacing: 0.2em;
text-transform: uppercase;
position: relative;
z-index: 2;
}
/* Stats as Golden Ratio Meters */
.stats-container {
margin-top: 40px;
position: relative;
z-index: 2;
}
.stat-meter {
margin-bottom: 25px;
}
.stat-label {
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 0.1em;
margin-bottom: 8px;
color: #d4af37;
}
.meter-track {
height: 20px;
background: #1a1a1a;
border: 1px solid #d4af37;
position: relative;
overflow: hidden;
}
.meter-fill {
height: 100%;
background: linear-gradient(90deg,
#8b6914 0%,
#d4af37 50%,
#f4e7d1 100%
);
transition: width 1s ease-out;
position: relative;
}
.meter-fill::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
90deg,
transparent 0%,
rgba(255, 255, 255, 0.3) 50%,
transparent 100%
);
animation: slide 2s infinite;
}
@keyframes slide {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.meter-value {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
font-family: 'Bebas Neue', cursive;
color: #0a0a0a;
font-weight: bold;
z-index: 2;
}
/* Main Content Area */
.main-content {
display: flex;
flex-direction: column;
gap: 30px;
}
/* Activity Feed as Newspaper */
.activity-feed {
background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%);
border: 2px solid #d4af37;
padding: 30px;
position: relative;
}
.feed-header {
border-bottom: 3px double #d4af37;
padding-bottom: 20px;
margin-bottom: 30px;
text-align: center;
}
.feed-title {
font-family: 'Bebas Neue', cursive;
font-size: 2.5rem;
letter-spacing: 0.3em;
color: #d4af37;
}
.feed-date {
font-size: 0.9rem;
color: #8b6914;
margin-top: 5px;
}
.feed-columns {
column-count: 2;
column-gap: 30px;
column-rule: 1px solid #d4af37;
}
.feed-item {
break-inside: avoid;
margin-bottom: 20px;
padding: 15px;
background: rgba(212, 175, 55, 0.05);
border-left: 3px solid #d4af37;
}
.feed-item-time {
font-size: 0.8rem;
color: #8b6914;
text-transform: uppercase;
letter-spacing: 0.1em;
}
.feed-item-text {
margin-top: 5px;
line-height: 1.6;
}
/* Settings Panel */
.settings-panel {
background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%);
border: 2px solid #d4af37;
padding: 30px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}
.control-group {
padding: 20px;
background: rgba(212, 175, 55, 0.05);
border: 1px solid #d4af37;
position: relative;
}
.control-label {
font-family: 'Bebas Neue', cursive;
font-size: 1.2rem;
letter-spacing: 0.1em;
color: #d4af37;
margin-bottom: 15px;
}
.luxury-switch {
position: relative;
width: 60px;
height: 30px;
background: #1a1a1a;
border: 2px solid #d4af37;
cursor: pointer;
transition: all 0.3s;
}
.luxury-switch::before {
content: '';
position: absolute;
width: 22px;
height: 22px;
top: 2px;
left: 2px;
background: #d4af37;
transition: transform 0.3s;
}
.luxury-switch.active::before {
transform: translateX(30px);
}
.luxury-slider {
width: 100%;
height: 30px;
background: #1a1a1a;
border: 2px solid #d4af37;
position: relative;
cursor: pointer;
margin-top: 10px;
}
.slider-fill {
height: 100%;
background: linear-gradient(90deg, #8b6914, #d4af37);
width: 50%;
transition: width 0.3s;
}
/* Achievements as Medallions */
.achievements-section {
background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%);
border: 2px solid #d4af37;
padding: 30px;
margin-top: 30px;
}
.achievements-header {
text-align: center;
margin-bottom: 30px;
}
.achievements-title {
font-family: 'Bebas Neue', cursive;
font-size: 2rem;
letter-spacing: 0.2em;
color: #d4af37;
}
.medallions-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 20px;
}
.medallion {
width: 100px;
height: 100px;
margin: 0 auto;
position: relative;
cursor: pointer;
transition: transform 0.3s;
}
.medallion:hover {
transform: scale(1.1) rotate(5deg);
}
.medallion-outer {
position: absolute;
inset: 0;
background: conic-gradient(
from 0deg,
#d4af37 0deg,
#f4e7d1 60deg,
#d4af37 120deg,
#8b6914 180deg,
#d4af37 240deg,
#f4e7d1 300deg,
#d4af37 360deg
);
border-radius: 50%;
animation: rotate 20s linear infinite;
}
.medallion-inner {
position: absolute;
inset: 10px;
background: #1a1a1a;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-family: 'Bebas Neue', cursive;
font-size: 2rem;
color: #d4af37;
}
.medallion-name {
text-align: center;
margin-top: 10px;
font-size: 0.8rem;
color: #d4af37;
}
/* Connections Constellation */
.connections-section {
background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%);
border: 2px solid #d4af37;
padding: 30px;
margin-top: 30px;
position: relative;
overflow: hidden;
}
.constellation-canvas {
width: 100%;
height: 300px;
position: relative;
}
.connection-node {
position: absolute;
width: 60px;
height: 60px;
background: #1a1a1a;
border: 2px solid #d4af37;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-family: 'Bebas Neue', cursive;
color: #d4af37;
cursor: pointer;
transition: all 0.3s;
z-index: 2;
}
.connection-node:hover {
transform: scale(1.2);
background: #d4af37;
color: #0a0a0a;
box-shadow: 0 0 30px rgba(212, 175, 55, 0.8);
}
.connection-line {
position: absolute;
height: 1px;
background: linear-gradient(90deg,
transparent 0%,
#d4af37 50%,
transparent 100%
);
transform-origin: left center;
z-index: 1;
opacity: 0.5;
}
/* Responsive Design */
@media (max-width: 768px) {
.main-grid {
grid-template-columns: 1fr;
}
.feed-columns {
column-count: 1;
}
.header h1 {
font-size: 3rem;
}
}
</style>
</head>
<body>
<div class="dashboard">
<!-- Header -->
<header class="header">
<h1>PROFILE LUXE</h1>
<div class="header-ornament"></div>
</header>
<!-- Main Grid -->
<div class="main-grid">
<!-- Profile Section -->
<aside class="profile-section">
<!-- Avatar -->
<div class="avatar-container">
<div class="avatar-frame"></div>
<div class="avatar">VL</div>
</div>
<h2 class="profile-name">Victoria Luxmore</h2>
<p class="profile-title">Elite Member Since 1925</p>
<!-- Stats Meters -->
<div class="stats-container">
<div class="stat-meter">
<div class="stat-label">Prestige Level</div>
<div class="meter-track">
<div class="meter-fill" style="width: 85%">
<span class="meter-value">85</span>
</div>
</div>
</div>
<div class="stat-meter">
<div class="stat-label">Social Influence</div>
<div class="meter-track">
<div class="meter-fill" style="width: 72%">
<span class="meter-value">72</span>
</div>
</div>
</div>
<div class="stat-meter">
<div class="stat-label">Activity Score</div>
<div class="meter-track">
<div class="meter-fill" style="width: 90%">
<span class="meter-value">90</span>
</div>
</div>
</div>
<div class="stat-meter">
<div class="stat-label">Elite Status</div>
<div class="meter-track">
<div class="meter-fill" style="width: 95%">
<span class="meter-value">95</span>
</div>
</div>
</div>
</div>
</aside>
<!-- Main Content -->
<main class="main-content">
<!-- Activity Feed -->
<section class="activity-feed">
<div class="feed-header">
<h2 class="feed-title">SOCIETY CHRONICLE</h2>
<p class="feed-date">December 6, 1925</p>
</div>
<div class="feed-columns">
<article class="feed-item">
<time class="feed-item-time">10:45 PM</time>
<p class="feed-item-text">Attended the exclusive Gatsby soirée at the Plaza. Spectacular evening of jazz and champagne.</p>
</article>
<article class="feed-item">
<time class="feed-item-time">8:30 PM</time>
<p class="feed-item-text">Achieved Diamond Elite status. Privileges now include access to the Penthouse Lounge.</p>
</article>
<article class="feed-item">
<time class="feed-item-time">6:15 PM</time>
<p class="feed-item-text">New connection established with Charleston M. Distinguished member of the Arts Society.</p>
</article>
<article class="feed-item">
<time class="feed-item-time">4:00 PM</time>
<p class="feed-item-text">Portfolio update: Art collection valued at new heights. Monet acquisition confirmed.</p>
</article>
<article class="feed-item">
<time class="feed-item-time">2:30 PM</time>
<p class="feed-item-text">Received invitation to the Annual Metropolis Gala. Black tie mandatory.</p>
</article>
<article class="feed-item">
<time class="feed-item-time">12:00 PM</time>
<p class="feed-item-text">Luncheon at the Ritz with fellow Elite members. Discussed upcoming charity auction.</p>
</article>
</div>
</section>
<!-- Settings Panel -->
<section class="settings-panel">
<div class="control-group">
<h3 class="control-label">PRIVACY MODE</h3>
<div class="luxury-switch" onclick="toggleSwitch(this)"></div>
</div>
<div class="control-group">
<h3 class="control-label">NOTIFICATIONS</h3>
<div class="luxury-switch active" onclick="toggleSwitch(this)"></div>
</div>
<div class="control-group">
<h3 class="control-label">VISIBILITY</h3>
<div class="luxury-slider" onclick="adjustSlider(event, this)">
<div class="slider-fill"></div>
</div>
</div>
<div class="control-group">
<h3 class="control-label">EXCLUSIVITY</h3>
<div class="luxury-slider" onclick="adjustSlider(event, this)">
<div class="slider-fill" style="width: 80%"></div>
</div>
</div>
</section>
</main>
</div>
<!-- Achievements Section -->
<section class="achievements-section">
<div class="achievements-header">
<h2 class="achievements-title">MEDALLIONS OF DISTINCTION</h2>
</div>
<div class="medallions-grid">
<div class="medallion">
<div class="medallion-outer"></div>
<div class="medallion-inner"></div>
<p class="medallion-name">ELITE STATUS</p>
</div>
<div class="medallion">
<div class="medallion-outer"></div>
<div class="medallion-inner"></div>
<p class="medallion-name">DIAMOND TIER</p>
</div>
<div class="medallion">
<div class="medallion-outer"></div>
<div class="medallion-inner"></div>
<p class="medallion-name">HIGH SOCIETY</p>
</div>
<div class="medallion">
<div class="medallion-outer"></div>
<div class="medallion-inner"></div>
<p class="medallion-name">CLUB MEMBER</p>
</div>
<div class="medallion">
<div class="medallion-outer"></div>
<div class="medallion-inner"></div>
<p class="medallion-name">PHILANTHROPIST</p>
</div>
<div class="medallion">
<div class="medallion-outer"></div>
<div class="medallion-inner"></div>
<p class="medallion-name">ARISTOCRAT</p>
</div>
</div>
</section>
<!-- Connections Constellation -->
<section class="connections-section">
<h2 class="achievements-title" style="text-align: center; margin-bottom: 30px;">SOCIAL CONSTELLATION</h2>
<div class="constellation-canvas" id="constellation">
<!-- Connection nodes will be dynamically positioned -->
</div>
</section>
</div>
<script>
// Toggle luxury switches
function toggleSwitch(element) {
element.classList.toggle('active');
}
// Adjust luxury sliders
function adjustSlider(event, slider) {
const rect = slider.getBoundingClientRect();
const percentage = ((event.clientX - rect.left) / rect.width) * 100;
const fill = slider.querySelector('.slider-fill');
fill.style.width = Math.max(0, Math.min(100, percentage)) + '%';
}
// Animate stat meters on load
window.addEventListener('load', () => {
const meters = document.querySelectorAll('.meter-fill');
meters.forEach((meter, index) => {
const targetWidth = meter.style.width;
meter.style.width = '0%';
setTimeout(() => {
meter.style.width = targetWidth;
}, 100 + index * 200);
});
});
// Create connections constellation
function createConstellation() {
const canvas = document.getElementById('constellation');
const connections = [
{ id: 'CM', x: 20, y: 30 },
{ id: 'JG', x: 80, y: 20 },
{ id: 'DF', x: 50, y: 50 },
{ id: 'NK', x: 30, y: 70 },
{ id: 'TW', x: 70, y: 80 },
{ id: 'ES', x: 90, y: 60 },
{ id: 'RL', x: 10, y: 50 }
];
// Create nodes
connections.forEach(conn => {
const node = document.createElement('div');
node.className = 'connection-node';
node.textContent = conn.id;
node.style.left = conn.x + '%';
node.style.top = conn.y + '%';
node.style.transform = 'translate(-50%, -50%)';
canvas.appendChild(node);
});
// Create connection lines
for (let i = 0; i < connections.length; i++) {
for (let j = i + 1; j < connections.length; j++) {
if (Math.random() > 0.5) { // Random connections
const line = document.createElement('div');
line.className = 'connection-line';
const x1 = connections[i].x;
const y1 = connections[i].y;
const x2 = connections[j].x;
const y2 = connections[j].y;
const distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
const angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
line.style.width = distance + '%';
line.style.left = x1 + '%';
line.style.top = y1 + '%';
line.style.transform = `rotate(${angle}deg)`;
canvas.appendChild(line);
}
}
}
}
createConstellation();
// Add hover effects to medallions
document.querySelectorAll('.medallion').forEach(medallion => {
medallion.addEventListener('click', function() {
this.style.animation = 'none';
setTimeout(() => {
this.style.animation = '';
}, 10);
});
});
// Parallax effect for background pattern
document.addEventListener('mousemove', (e) => {
const x = e.clientX / window.innerWidth;
const y = e.clientY / window.innerHeight;
document.body.style.backgroundPosition = `${x * 20}px ${y * 20}px`;
});
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,969 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Steampunk Machinery Communication Hub</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;600&family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Libre Baskerville', serif;
background: #1a1511;
color: #d4af37;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
background-image:
radial-gradient(circle at 20% 50%, rgba(212, 175, 55, 0.1) 0%, transparent 50%),
radial-gradient(circle at 80% 50%, rgba(184, 134, 11, 0.1) 0%, transparent 50%),
radial-gradient(circle at 50% 20%, rgba(218, 165, 32, 0.05) 0%, transparent 50%);
}
h1 {
font-family: 'Cinzel', serif;
font-size: 2.5rem;
text-align: center;
margin-bottom: 2rem;
color: #daa520;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8),
0 0 20px rgba(212, 175, 55, 0.3);
letter-spacing: 2px;
}
.communication-hub {
width: 100%;
max-width: 1400px;
background: linear-gradient(145deg, #2a2217, #1f1813);
border: 3px solid #8b6914;
border-radius: 15px;
padding: 30px;
box-shadow:
inset 0 0 50px rgba(212, 175, 55, 0.1),
0 0 30px rgba(212, 175, 55, 0.2),
0 10px 20px rgba(0, 0, 0, 0.5);
position: relative;
overflow: hidden;
}
/* Decorative gears */
.gear {
position: absolute;
opacity: 0.1;
animation: rotate 20s linear infinite;
}
.gear-1 {
top: -50px;
right: -50px;
width: 150px;
height: 150px;
animation-duration: 30s;
}
.gear-2 {
bottom: -30px;
left: -30px;
width: 100px;
height: 100px;
animation-direction: reverse;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Main layout grid */
.hub-grid {
display: grid;
grid-template-columns: 300px 1fr 250px;
gap: 20px;
position: relative;
z-index: 1;
}
/* Participant Manifest (Left Panel) */
.passenger-manifest {
background: #1f1611;
border: 2px solid #8b6914;
border-radius: 10px;
padding: 15px;
box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.5);
}
.manifest-header {
font-family: 'Cinzel', serif;
font-size: 1.2rem;
text-align: center;
margin-bottom: 15px;
color: #daa520;
text-transform: uppercase;
letter-spacing: 1px;
}
.participant {
background: linear-gradient(145deg, #2a2217, #1f1813);
border: 1px solid #8b6914;
border-radius: 8px;
padding: 10px;
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 10px;
position: relative;
overflow: hidden;
transition: all 0.3s ease;
}
.participant:hover {
transform: translateX(5px);
box-shadow: 0 0 15px rgba(212, 175, 55, 0.3);
}
.participant-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
border: 2px solid #8b6914;
background: #2a2217;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: #daa520;
}
.participant-info {
flex: 1;
}
.participant-name {
font-weight: 600;
color: #daa520;
font-size: 0.9rem;
}
.participant-status {
font-size: 0.8rem;
color: #b8860b;
font-style: italic;
}
.steam-indicator {
position: absolute;
right: 10px;
width: 8px;
height: 8px;
border-radius: 50%;
background: #4ade80;
box-shadow: 0 0 10px #4ade80;
animation: steam-pulse 2s ease-in-out infinite;
}
@keyframes steam-pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(1.2); }
}
/* Center Panel */
.center-panel {
display: flex;
flex-direction: column;
gap: 20px;
}
/* Projection Apparatus (Screen Share) */
.projection-apparatus {
background: #0a0908;
border: 3px solid #8b6914;
border-radius: 10px;
height: 400px;
position: relative;
overflow: hidden;
box-shadow:
inset 0 0 50px rgba(0, 0, 0, 0.8),
0 0 20px rgba(212, 175, 55, 0.2);
}
.projection-screen {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: radial-gradient(ellipse at center, #1a1511 0%, #0a0908 100%);
position: relative;
}
.projection-content {
text-align: center;
padding: 20px;
}
.projection-icon {
font-size: 4rem;
margin-bottom: 20px;
animation: projection-flicker 3s ease-in-out infinite;
}
@keyframes projection-flicker {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.8; }
}
.projection-controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 15px;
}
/* Brass Valves (Video Controls) */
.brass-valves {
background: linear-gradient(145deg, #2a2217, #1f1813);
border: 2px solid #8b6914;
border-radius: 10px;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
gap: 30px;
}
.valve-control {
position: relative;
width: 80px;
height: 80px;
cursor: pointer;
transition: transform 0.3s ease;
}
.valve-control:hover {
transform: scale(1.1);
}
.valve-wheel {
width: 100%;
height: 100%;
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, #daa520 0%, #8b6914 50%, #654321 100%);
border: 3px solid #654321;
position: relative;
box-shadow:
inset 0 0 20px rgba(0, 0, 0, 0.5),
0 5px 10px rgba(0, 0, 0, 0.5);
transition: transform 0.5s ease;
}
.valve-control.active .valve-wheel {
transform: rotate(180deg);
box-shadow:
inset 0 0 20px rgba(212, 175, 55, 0.5),
0 5px 10px rgba(0, 0, 0, 0.5),
0 0 20px rgba(212, 175, 55, 0.5);
}
.valve-spokes {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60%;
height: 60%;
}
.valve-spoke {
position: absolute;
width: 2px;
height: 50%;
background: #654321;
left: 50%;
transform-origin: bottom;
}
.valve-spoke:nth-child(1) { transform: translateX(-50%) rotate(0deg); }
.valve-spoke:nth-child(2) { transform: translateX(-50%) rotate(45deg); }
.valve-spoke:nth-child(3) { transform: translateX(-50%) rotate(90deg); }
.valve-spoke:nth-child(4) { transform: translateX(-50%) rotate(135deg); }
.valve-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, #daa520 0%, #8b6914 100%);
border: 2px solid #654321;
}
.valve-label {
position: absolute;
bottom: -25px;
left: 50%;
transform: translateX(-50%);
font-size: 0.8rem;
color: #b8860b;
text-transform: uppercase;
letter-spacing: 1px;
white-space: nowrap;
}
/* Right Panel */
.right-panel {
display: flex;
flex-direction: column;
gap: 20px;
}
/* Phonograph Cylinder (Recording) */
.phonograph-cylinder {
background: linear-gradient(145deg, #2a2217, #1f1813);
border: 2px solid #8b6914;
border-radius: 10px;
padding: 20px;
text-align: center;
}
.cylinder-mechanism {
width: 120px;
height: 40px;
background: linear-gradient(90deg, #8b6914 0%, #daa520 25%, #8b6914 50%, #daa520 75%, #8b6914 100%);
border-radius: 20px;
margin: 0 auto 15px;
position: relative;
box-shadow:
inset 0 0 10px rgba(0, 0, 0, 0.5),
0 5px 10px rgba(0, 0, 0, 0.3);
}
.cylinder-mechanism.recording {
animation: cylinder-spin 2s linear infinite;
}
@keyframes cylinder-spin {
from { background-position: 0 0; }
to { background-position: 100px 0; }
}
.record-button {
background: radial-gradient(circle at 30% 30%, #dc2626 0%, #991b1b 100%);
border: 3px solid #7f1d1d;
border-radius: 50%;
width: 60px;
height: 60px;
margin: 0 auto;
cursor: pointer;
position: relative;
transition: all 0.3s ease;
box-shadow:
inset 0 0 20px rgba(0, 0, 0, 0.5),
0 5px 10px rgba(0, 0, 0, 0.5);
}
.record-button:hover {
transform: scale(1.1);
box-shadow:
inset 0 0 20px rgba(220, 38, 38, 0.5),
0 5px 10px rgba(0, 0, 0, 0.5),
0 0 20px rgba(220, 38, 38, 0.5);
}
.record-button.recording {
animation: record-pulse 1s ease-in-out infinite;
}
@keyframes record-pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
/* Steam Puffs (Reactions) */
.steam-reactions {
background: linear-gradient(145deg, #2a2217, #1f1813);
border: 2px solid #8b6914;
border-radius: 10px;
padding: 15px;
}
.reactions-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.steam-button {
background: radial-gradient(circle at 30% 30%, #654321 0%, #3e2723 100%);
border: 2px solid #8b6914;
border-radius: 8px;
padding: 15px;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
font-size: 1.5rem;
position: relative;
overflow: hidden;
}
.steam-button:hover {
transform: scale(1.05);
box-shadow: 0 0 15px rgba(212, 175, 55, 0.5);
}
.steam-puff {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
width: 30px;
height: 30px;
background: radial-gradient(circle, rgba(255, 255, 255, 0.8) 0%, transparent 70%);
border-radius: 50%;
opacity: 0;
pointer-events: none;
}
.steam-button:active .steam-puff {
animation: steam-rise 1s ease-out;
}
@keyframes steam-rise {
0% {
opacity: 0;
transform: translateX(-50%) translateY(0) scale(0.5);
}
50% {
opacity: 1;
}
100% {
opacity: 0;
transform: translateX(-50%) translateY(-50px) scale(1.5);
}
}
/* Pneumatic Tube Messages (Chat) */
.pneumatic-chat {
grid-column: 1 / -1;
background: linear-gradient(145deg, #1f1611, #141210);
border: 2px solid #8b6914;
border-radius: 10px;
padding: 20px;
height: 300px;
display: flex;
flex-direction: column;
}
.tube-messages {
flex: 1;
overflow-y: auto;
margin-bottom: 15px;
padding-right: 10px;
}
.tube-messages::-webkit-scrollbar {
width: 10px;
}
.tube-messages::-webkit-scrollbar-track {
background: #1f1611;
border-radius: 5px;
}
.tube-messages::-webkit-scrollbar-thumb {
background: #8b6914;
border-radius: 5px;
}
.message-capsule {
background: linear-gradient(145deg, #2a2217, #1f1813);
border: 1px solid #8b6914;
border-radius: 20px;
padding: 12px 20px;
margin-bottom: 10px;
position: relative;
animation: tube-arrive 0.5s ease-out;
}
@keyframes tube-arrive {
from {
opacity: 0;
transform: translateY(-20px) scale(0.8);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.message-sender {
font-weight: 600;
color: #daa520;
margin-bottom: 5px;
font-size: 0.9rem;
}
.message-text {
color: #d4af37;
font-size: 0.95rem;
line-height: 1.4;
}
.message-time {
position: absolute;
top: 5px;
right: 15px;
font-size: 0.7rem;
color: #8b6914;
font-style: italic;
}
.tube-input-container {
display: flex;
gap: 10px;
}
.tube-input {
flex: 1;
background: #1f1611;
border: 2px solid #8b6914;
border-radius: 20px;
padding: 10px 20px;
color: #d4af37;
font-family: 'Libre Baskerville', serif;
font-size: 0.95rem;
outline: none;
transition: all 0.3s ease;
}
.tube-input:focus {
box-shadow: 0 0 15px rgba(212, 175, 55, 0.3);
border-color: #daa520;
}
.tube-send {
background: radial-gradient(circle at 30% 30%, #8b6914 0%, #654321 100%);
border: 2px solid #654321;
border-radius: 50%;
width: 40px;
height: 40px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: #daa520;
font-size: 1.2rem;
transition: all 0.3s ease;
}
.tube-send:hover {
transform: scale(1.1);
box-shadow: 0 0 15px rgba(212, 175, 55, 0.5);
}
/* Decorative elements */
.brass-plate {
position: absolute;
background: linear-gradient(145deg, #daa520 0%, #8b6914 100%);
border: 1px solid #654321;
border-radius: 5px;
padding: 5px 10px;
font-size: 0.7rem;
color: #1f1611;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
}
.hub-label {
top: 10px;
right: 20px;
}
/* Gauge decorations */
.pressure-gauge {
position: absolute;
top: 20px;
left: 20px;
width: 60px;
height: 60px;
background: radial-gradient(circle at 30% 30%, #2a2217 0%, #1f1813 100%);
border: 3px solid #8b6914;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.5);
}
.gauge-needle {
position: absolute;
width: 2px;
height: 20px;
background: #dc2626;
transform-origin: bottom;
animation: gauge-wobble 3s ease-in-out infinite;
}
@keyframes gauge-wobble {
0%, 100% { transform: rotate(-30deg); }
50% { transform: rotate(30deg); }
}
/* Responsive adjustments */
@media (max-width: 1200px) {
.hub-grid {
grid-template-columns: 1fr;
}
.passenger-manifest,
.right-panel {
display: none;
}
}
</style>
</head>
<body>
<main>
<h1>Communication Hub - Steampunk Machinery Theme</h1>
<div class="communication-hub">
<!-- Decorative gears -->
<svg class="gear gear-1" viewBox="0 0 100 100">
<path d="M50 15 L55 5 L45 5 Z M50 85 L55 95 L45 95 Z M85 50 L95 55 L95 45 Z M15 50 L5 55 L5 45 Z" fill="#8b6914"/>
<circle cx="50" cy="50" r="35" fill="none" stroke="#8b6914" stroke-width="3"/>
<circle cx="50" cy="50" r="20" fill="none" stroke="#8b6914" stroke-width="2"/>
</svg>
<svg class="gear gear-2" viewBox="0 0 100 100">
<path d="M50 15 L55 5 L45 5 Z M50 85 L55 95 L45 95 Z M85 50 L95 55 L95 45 Z M15 50 L5 55 L5 45 Z" fill="#8b6914"/>
<circle cx="50" cy="50" r="35" fill="none" stroke="#8b6914" stroke-width="3"/>
</svg>
<!-- Brass plate label -->
<div class="brass-plate hub-label">Victorian Comm Station</div>
<!-- Pressure gauge decoration -->
<div class="pressure-gauge">
<div class="gauge-needle"></div>
</div>
<div class="hub-grid">
<!-- Passenger Manifest (Participant List) -->
<div class="passenger-manifest">
<h2 class="manifest-header">Passenger Manifest</h2>
<div class="participant">
<div class="participant-avatar">VW</div>
<div class="participant-info">
<div class="participant-name">Victoria Whitmore</div>
<div class="participant-status">Chief Engineer</div>
</div>
<div class="steam-indicator"></div>
</div>
<div class="participant">
<div class="participant-avatar">AT</div>
<div class="participant-info">
<div class="participant-name">Augustus Thornbury</div>
<div class="participant-status">Navigator</div>
</div>
<div class="steam-indicator"></div>
</div>
<div class="participant">
<div class="participant-avatar">ES</div>
<div class="participant-info">
<div class="participant-name">Eleanor Sterling</div>
<div class="participant-status">Communications</div>
</div>
<div class="steam-indicator"></div>
</div>
<div class="participant">
<div class="participant-avatar">RB</div>
<div class="participant-info">
<div class="participant-name">Reginald Blackwood</div>
<div class="participant-status">Guest Observer</div>
</div>
<div class="steam-indicator" style="background: #fbbf24;"></div>
</div>
</div>
<!-- Center Panel -->
<div class="center-panel">
<!-- Projection Apparatus (Screen Share) -->
<div class="projection-apparatus">
<div class="projection-screen">
<div class="projection-content">
<div class="projection-icon">🎭</div>
<h3 style="color: #daa520; margin-bottom: 10px;">Projection Chamber Active</h3>
<p style="color: #b8860b; font-style: italic;">Awaiting visual transmission...</p>
</div>
<div class="projection-controls">
<button class="tube-send" style="width: 50px; height: 50px;">
<span>📽️</span>
</button>
<button class="tube-send" style="width: 50px; height: 50px;">
<span>🔍</span>
</button>
</div>
</div>
</div>
<!-- Brass Valves (Video Controls) -->
<div class="brass-valves">
<div class="valve-control" id="camera-valve">
<div class="valve-wheel">
<div class="valve-spokes">
<div class="valve-spoke"></div>
<div class="valve-spoke"></div>
<div class="valve-spoke"></div>
<div class="valve-spoke"></div>
</div>
<div class="valve-center"></div>
</div>
<div class="valve-label">Camera</div>
</div>
<div class="valve-control active" id="audio-valve">
<div class="valve-wheel">
<div class="valve-spokes">
<div class="valve-spoke"></div>
<div class="valve-spoke"></div>
<div class="valve-spoke"></div>
<div class="valve-spoke"></div>
</div>
<div class="valve-center"></div>
</div>
<div class="valve-label">Audio</div>
</div>
<div class="valve-control" id="screen-valve">
<div class="valve-wheel">
<div class="valve-spokes">
<div class="valve-spoke"></div>
<div class="valve-spoke"></div>
<div class="valve-spoke"></div>
<div class="valve-spoke"></div>
</div>
<div class="valve-center"></div>
</div>
<div class="valve-label">Screen</div>
</div>
</div>
</div>
<!-- Right Panel -->
<div class="right-panel">
<!-- Phonograph Cylinder (Recording) -->
<div class="phonograph-cylinder">
<h3 style="color: #daa520; margin-bottom: 15px; font-size: 1rem;">Recording Chamber</h3>
<div class="cylinder-mechanism"></div>
<button class="record-button" id="record-btn"></button>
<p style="color: #b8860b; margin-top: 10px; font-size: 0.8rem;">00:00:00</p>
</div>
<!-- Steam Puffs (Reactions) -->
<div class="steam-reactions">
<h3 style="color: #daa520; margin-bottom: 15px; font-size: 1rem; text-align: center;">Steam Signals</h3>
<div class="reactions-grid">
<button class="steam-button">
👍
<div class="steam-puff"></div>
</button>
<button class="steam-button">
❤️
<div class="steam-puff"></div>
</button>
<button class="steam-button">
😂
<div class="steam-puff"></div>
</button>
<button class="steam-button">
👏
<div class="steam-puff"></div>
</button>
<button class="steam-button">
🎩
<div class="steam-puff"></div>
</button>
<button class="steam-button">
⚙️
<div class="steam-puff"></div>
</button>
</div>
</div>
</div>
<!-- Pneumatic Tube Messages (Chat) -->
<div class="pneumatic-chat">
<div class="tube-messages" id="chat-messages">
<div class="message-capsule">
<div class="message-time">14:32</div>
<div class="message-sender">Victoria Whitmore</div>
<div class="message-text">Greetings, fellow inventors! The atmospheric pressure readings are optimal for today's demonstration.</div>
</div>
<div class="message-capsule">
<div class="message-time">14:33</div>
<div class="message-sender">Augustus Thornbury</div>
<div class="message-text">Splendid! I've calibrated the projection apparatus to maximum clarity. The aetheric interference should be minimal.</div>
</div>
<div class="message-capsule">
<div class="message-time">14:35</div>
<div class="message-sender">Eleanor Sterling</div>
<div class="message-text">All pneumatic tubes are functioning at peak efficiency. Message velocity has increased by 23% since last fortnight.</div>
</div>
</div>
<div class="tube-input-container">
<input type="text" class="tube-input" id="chat-input" placeholder="Compose your pneumatic message...">
<button class="tube-send" id="send-btn"></button>
</div>
</div>
</div>
</div>
</main>
<script>
// Valve controls
const valves = document.querySelectorAll('.valve-control');
valves.forEach(valve => {
valve.addEventListener('click', function() {
this.classList.toggle('active');
// Add steam effect
const steamEffect = document.createElement('div');
steamEffect.style.cssText = `
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100px;
height: 100px;
background: radial-gradient(circle, rgba(255,255,255,0.3) 0%, transparent 70%);
border-radius: 50%;
animation: steam-expand 1s ease-out forwards;
pointer-events: none;
`;
this.appendChild(steamEffect);
setTimeout(() => steamEffect.remove(), 1000);
});
});
// Add CSS for steam expansion
const style = document.createElement('style');
style.textContent = `
@keyframes steam-expand {
from {
opacity: 1;
transform: translate(-50%, -50%) scale(0);
}
to {
opacity: 0;
transform: translate(-50%, -50%) scale(2);
}
}
`;
document.head.appendChild(style);
// Recording functionality
const recordBtn = document.getElementById('record-btn');
const cylinderMech = document.querySelector('.cylinder-mechanism');
let isRecording = false;
let recordingTime = 0;
let recordingInterval;
recordBtn.addEventListener('click', function() {
isRecording = !isRecording;
this.classList.toggle('recording');
cylinderMech.classList.toggle('recording');
if (isRecording) {
recordingInterval = setInterval(() => {
recordingTime++;
const hours = Math.floor(recordingTime / 3600).toString().padStart(2, '0');
const minutes = Math.floor((recordingTime % 3600) / 60).toString().padStart(2, '0');
const seconds = (recordingTime % 60).toString().padStart(2, '0');
this.nextElementSibling.textContent = `${hours}:${minutes}:${seconds}`;
}, 1000);
} else {
clearInterval(recordingInterval);
}
});
// Chat functionality
const chatInput = document.getElementById('chat-input');
const sendBtn = document.getElementById('send-btn');
const chatMessages = document.getElementById('chat-messages');
function sendMessage() {
const text = chatInput.value.trim();
if (text) {
const time = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false });
const messageHtml = `
<div class="message-capsule">
<div class="message-time">${time}</div>
<div class="message-sender">You</div>
<div class="message-text">${text}</div>
</div>
`;
chatMessages.insertAdjacentHTML('beforeend', messageHtml);
chatInput.value = '';
chatMessages.scrollTop = chatMessages.scrollHeight;
// Add pneumatic tube sound effect simulation
sendBtn.style.transform = 'scale(0.9)';
setTimeout(() => sendBtn.style.transform = 'scale(1)', 200);
}
}
sendBtn.addEventListener('click', sendMessage);
chatInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendMessage();
});
// Steam reactions
const steamButtons = document.querySelectorAll('.steam-button');
steamButtons.forEach(button => {
button.addEventListener('click', function() {
// Create multiple steam puffs
for (let i = 0; i < 3; i++) {
setTimeout(() => {
const puff = document.createElement('div');
puff.className = 'steam-puff';
puff.style.left = `${40 + (Math.random() * 20)}%`;
puff.style.animation = 'steam-rise 1s ease-out forwards';
this.appendChild(puff);
setTimeout(() => puff.remove(), 1000);
}, i * 100);
}
});
});
// Participant status updates
setInterval(() => {
const indicators = document.querySelectorAll('.steam-indicator');
indicators.forEach(indicator => {
if (Math.random() > 0.7) {
indicator.style.animationDuration = Math.random() * 2 + 1 + 's';
}
});
}, 5000);
// Add some ambient gauge movements
const gaugeNeedle = document.querySelector('.gauge-needle');
setInterval(() => {
const rotation = -30 + Math.random() * 60;
gaugeNeedle.style.transform = `rotate(${rotation}deg)`;
}, 2000);
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,805 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Glass Morphism Input Intelligence</title>
<style>
:root {
--glass-bg: rgba(255, 255, 255, 0.1);
--glass-border: rgba(255, 255, 255, 0.2);
--glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
--glass-blur: blur(10px);
--text-primary: #1a1a1a;
--text-secondary: #666;
--accent-valid: #22c55e;
--accent-invalid: #ef4444;
--accent-info: #3b82f6;
--gradient-edge: linear-gradient(135deg,
rgba(255, 255, 255, 0.3) 0%,
rgba(255, 255, 255, 0.1) 100%);
}
@media (prefers-color-scheme: dark) {
:root {
--glass-bg: rgba(255, 255, 255, 0.05);
--glass-border: rgba(255, 255, 255, 0.1);
--glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
--text-primary: #f5f5f5;
--text-secondary: #a8a8a8;
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
color: var(--text-primary);
}
main {
width: 100%;
max-width: 600px;
}
h1 {
text-align: center;
margin-bottom: 40px;
color: white;
font-weight: 300;
font-size: 2.5em;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.input-intelligence {
position: relative;
margin-bottom: 40px;
}
.glass-container {
background: var(--glass-bg);
backdrop-filter: var(--glass-blur);
-webkit-backdrop-filter: var(--glass-blur);
border-radius: 16px;
border: 1px solid var(--glass-border);
box-shadow: var(--glass-shadow);
padding: 24px;
position: relative;
overflow: hidden;
}
.glass-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: var(--gradient-edge);
}
.input-wrapper {
position: relative;
margin-bottom: 16px;
}
.glass-input {
width: 100%;
padding: 16px 48px 16px 16px;
font-size: 16px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid var(--glass-border);
border-radius: 12px;
color: var(--text-primary);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
transition: all 0.3s ease;
outline: none;
}
.glass-input:focus {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
.input-status {
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
width: 24px;
height: 24px;
opacity: 0;
transition: opacity 0.3s ease;
}
.input-status.show {
opacity: 1;
}
.status-icon {
width: 100%;
height: 100%;
stroke-width: 2;
}
.status-icon.valid {
stroke: var(--accent-valid);
}
.status-icon.invalid {
stroke: var(--accent-invalid);
}
.status-icon.loading {
stroke: var(--accent-info);
animation: rotate 1s linear infinite;
}
@keyframes rotate {
to { transform: rotate(360deg); }
}
.help-tooltip {
position: absolute;
top: calc(100% + 8px);
left: 0;
right: 0;
background: var(--glass-bg);
backdrop-filter: var(--glass-blur);
-webkit-backdrop-filter: var(--glass-blur);
border: 1px solid var(--glass-border);
border-radius: 12px;
padding: 12px 16px;
box-shadow: var(--glass-shadow);
opacity: 0;
transform: translateY(-10px);
transition: all 0.3s ease;
pointer-events: none;
z-index: 10;
}
.help-tooltip.show {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
.help-tooltip::before {
content: '';
position: absolute;
top: -6px;
left: 24px;
width: 12px;
height: 12px;
background: var(--glass-bg);
border: 1px solid var(--glass-border);
border-right: none;
border-bottom: none;
transform: rotate(45deg);
}
.help-text {
font-size: 14px;
color: var(--text-secondary);
line-height: 1.4;
}
.autocomplete-dropdown {
position: absolute;
top: calc(100% + 8px);
left: 0;
right: 0;
background: var(--glass-bg);
backdrop-filter: var(--glass-blur);
-webkit-backdrop-filter: var(--glass-blur);
border: 1px solid var(--glass-border);
border-radius: 12px;
box-shadow: var(--glass-shadow);
opacity: 0;
transform: translateY(-10px) scale(0.98);
transition: all 0.3s ease;
pointer-events: none;
z-index: 20;
max-height: 240px;
overflow-y: auto;
}
.autocomplete-dropdown.show {
opacity: 1;
transform: translateY(0) scale(1);
pointer-events: auto;
}
.autocomplete-item {
padding: 12px 16px;
cursor: pointer;
transition: all 0.2s ease;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
position: relative;
overflow: hidden;
}
.autocomplete-item:last-child {
border-bottom: none;
}
.autocomplete-item::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.1);
transition: left 0.3s ease;
}
.autocomplete-item:hover::before,
.autocomplete-item.selected::before {
left: 0;
}
.autocomplete-item.selected {
background: rgba(255, 255, 255, 0.05);
}
.autocomplete-primary {
color: var(--text-primary);
font-weight: 500;
margin-bottom: 4px;
}
.autocomplete-secondary {
color: var(--text-secondary);
font-size: 12px;
}
.format-hint {
position: absolute;
top: 50%;
right: 48px;
transform: translateY(-50%);
font-size: 12px;
color: var(--text-secondary);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.format-hint.show {
opacity: 0.7;
}
.demo-section {
margin-bottom: 32px;
}
.demo-title {
color: white;
font-size: 1.2em;
margin-bottom: 16px;
font-weight: 300;
}
.feature-list {
background: var(--glass-bg);
backdrop-filter: var(--glass-blur);
-webkit-backdrop-filter: var(--glass-blur);
border: 1px solid var(--glass-border);
border-radius: 12px;
padding: 16px;
font-size: 14px;
color: var(--text-secondary);
line-height: 1.6;
}
.feature-list li {
margin-left: 20px;
margin-bottom: 8px;
}
@media (max-width: 640px) {
h1 {
font-size: 2em;
}
.glass-container {
padding: 20px;
}
.glass-input {
font-size: 16px;
}
}
</style>
</head>
<body>
<main>
<h1>Input Intelligence - Glass Morphism Theme</h1>
<div class="demo-section">
<h2 class="demo-title">Email Input with Validation</h2>
<div class="input-intelligence">
<div class="glass-container">
<div class="input-wrapper">
<input
type="text"
class="glass-input"
id="emailInput"
placeholder="Enter your email address"
autocomplete="off"
>
<span class="format-hint" id="emailFormatHint"></span>
<div class="input-status" id="emailStatus">
<svg class="status-icon" viewBox="0 0 24 24" fill="none">
<!-- Dynamic SVG content inserted by JS -->
</svg>
</div>
</div>
<div class="help-tooltip" id="emailHelp">
<p class="help-text"></p>
</div>
<div class="autocomplete-dropdown" id="emailAutocomplete"></div>
</div>
</div>
</div>
<div class="demo-section">
<h2 class="demo-title">Phone Number with Smart Formatting</h2>
<div class="input-intelligence">
<div class="glass-container">
<div class="input-wrapper">
<input
type="text"
class="glass-input"
id="phoneInput"
placeholder="Enter phone number"
autocomplete="off"
>
<span class="format-hint" id="phoneFormatHint"></span>
<div class="input-status" id="phoneStatus">
<svg class="status-icon" viewBox="0 0 24 24" fill="none">
<!-- Dynamic SVG content inserted by JS -->
</svg>
</div>
</div>
<div class="help-tooltip" id="phoneHelp">
<p class="help-text"></p>
</div>
<div class="autocomplete-dropdown" id="phoneAutocomplete"></div>
</div>
</div>
</div>
<div class="demo-section">
<h2 class="demo-title">Credit Card with Security Features</h2>
<div class="input-intelligence">
<div class="glass-container">
<div class="input-wrapper">
<input
type="text"
class="glass-input"
id="cardInput"
placeholder="Enter card number"
autocomplete="off"
>
<span class="format-hint" id="cardFormatHint"></span>
<div class="input-status" id="cardStatus">
<svg class="status-icon" viewBox="0 0 24 24" fill="none">
<!-- Dynamic SVG content inserted by JS -->
</svg>
</div>
</div>
<div class="help-tooltip" id="cardHelp">
<p class="help-text"></p>
</div>
<div class="autocomplete-dropdown" id="cardAutocomplete"></div>
</div>
</div>
</div>
<div class="feature-list">
<ul>
<li>Real-time validation with visual feedback</li>
<li>Contextual help that adapts to input</li>
<li>Smart formatting as you type</li>
<li>Intelligent autocomplete suggestions</li>
<li>Glass morphism design with depth hierarchy</li>
<li>Light/dark mode adaptive styling</li>
</ul>
</div>
</main>
<script>
// SVG Icons
const icons = {
valid: '<circle cx="12" cy="12" r="10"></circle><path d="M9 12l2 2 4-4"></path>',
invalid: '<circle cx="12" cy="12" r="10"></circle><path d="M15 9l-6 6"></path><path d="M9 9l6 6"></path>',
loading: '<circle cx="12" cy="12" r="10" stroke-dasharray="50" stroke-dashoffset="10"></circle>'
};
// Input Intelligence Class
class InputIntelligence {
constructor(inputId, config) {
this.input = document.getElementById(inputId);
this.status = document.getElementById(inputId.replace('Input', 'Status'));
this.help = document.getElementById(inputId.replace('Input', 'Help'));
this.autocomplete = document.getElementById(inputId.replace('Input', 'Autocomplete'));
this.formatHint = document.getElementById(inputId.replace('Input', 'FormatHint'));
this.config = config;
this.selectedIndex = -1;
this.suggestions = [];
this.init();
}
init() {
this.input.addEventListener('input', this.handleInput.bind(this));
this.input.addEventListener('focus', this.handleFocus.bind(this));
this.input.addEventListener('blur', this.handleBlur.bind(this));
this.input.addEventListener('keydown', this.handleKeydown.bind(this));
this.autocomplete.addEventListener('click', this.handleAutocompleteClick.bind(this));
}
handleInput(e) {
const value = e.target.value;
// Clear previous timeout
clearTimeout(this.validationTimeout);
clearTimeout(this.autocompleteTimeout);
// Show loading state
this.showStatus('loading');
// Format input
if (this.config.formatter) {
const formatted = this.config.formatter(value);
if (formatted !== value) {
e.target.value = formatted;
this.showFormatHint(this.config.formatHint);
}
}
// Validate after delay
this.validationTimeout = setTimeout(() => {
this.validate(e.target.value);
}, 500);
// Show autocomplete after delay
if (value.length >= this.config.minLength) {
this.autocompleteTimeout = setTimeout(() => {
this.showAutocomplete(value);
}, 300);
} else {
this.hideAutocomplete();
}
}
handleFocus() {
if (this.input.value.length >= this.config.minLength) {
this.showAutocomplete(this.input.value);
}
this.showHelp(this.config.initialHelp);
}
handleBlur(e) {
// Delay to allow autocomplete clicks
setTimeout(() => {
if (!this.autocomplete.contains(e.relatedTarget)) {
this.hideAutocomplete();
this.hideHelp();
this.hideFormatHint();
}
}, 200);
}
handleKeydown(e) {
if (!this.autocomplete.classList.contains('show')) return;
const items = this.autocomplete.querySelectorAll('.autocomplete-item');
switch(e.key) {
case 'ArrowDown':
e.preventDefault();
this.selectedIndex = Math.min(this.selectedIndex + 1, items.length - 1);
this.updateSelection(items);
break;
case 'ArrowUp':
e.preventDefault();
this.selectedIndex = Math.max(this.selectedIndex - 1, -1);
this.updateSelection(items);
break;
case 'Enter':
if (this.selectedIndex >= 0 && this.selectedIndex < items.length) {
e.preventDefault();
this.selectSuggestion(this.suggestions[this.selectedIndex]);
}
break;
case 'Escape':
this.hideAutocomplete();
break;
}
}
handleAutocompleteClick(e) {
const item = e.target.closest('.autocomplete-item');
if (item) {
const index = Array.from(item.parentNode.children).indexOf(item);
this.selectSuggestion(this.suggestions[index]);
}
}
validate(value) {
if (!value) {
this.hideStatus();
this.showHelp(this.config.initialHelp);
return;
}
const result = this.config.validator(value);
if (result.valid) {
this.showStatus('valid');
this.showHelp(result.help || this.config.validHelp);
} else {
this.showStatus('invalid');
this.showHelp(result.help || this.config.invalidHelp);
}
}
showAutocomplete(value) {
this.suggestions = this.config.getSuggestions(value);
this.selectedIndex = -1;
if (this.suggestions.length === 0) {
this.hideAutocomplete();
return;
}
this.autocomplete.innerHTML = this.suggestions.map((suggestion, index) => `
<div class="autocomplete-item">
<div class="autocomplete-primary">${suggestion.primary}</div>
${suggestion.secondary ? `<div class="autocomplete-secondary">${suggestion.secondary}</div>` : ''}
</div>
`).join('');
this.autocomplete.classList.add('show');
}
hideAutocomplete() {
this.autocomplete.classList.remove('show');
this.selectedIndex = -1;
}
updateSelection(items) {
items.forEach((item, index) => {
item.classList.toggle('selected', index === this.selectedIndex);
});
}
selectSuggestion(suggestion) {
this.input.value = suggestion.value;
this.hideAutocomplete();
this.validate(suggestion.value);
this.input.focus();
}
showStatus(type) {
const icon = this.status.querySelector('.status-icon');
icon.innerHTML = icons[type];
icon.className = `status-icon ${type}`;
this.status.classList.add('show');
}
hideStatus() {
this.status.classList.remove('show');
}
showHelp(text) {
this.help.querySelector('.help-text').textContent = text;
this.help.classList.add('show');
}
hideHelp() {
this.help.classList.remove('show');
}
showFormatHint(text) {
this.formatHint.textContent = text;
this.formatHint.classList.add('show');
clearTimeout(this.formatHintTimeout);
this.formatHintTimeout = setTimeout(() => {
this.hideFormatHint();
}, 2000);
}
hideFormatHint() {
this.formatHint.classList.remove('show');
}
}
// Email configuration
const emailConfig = {
minLength: 3,
initialHelp: 'Enter a valid email address',
validHelp: 'Email address looks good!',
invalidHelp: 'Please enter a valid email format',
formatHint: 'Auto-formatted',
validator: (value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return {
valid: emailRegex.test(value),
help: value.includes('@') && !value.includes('.') ?
'Don\'t forget the domain extension (e.g., .com)' : null
};
},
formatter: (value) => {
return value.toLowerCase().replace(/\s/g, '');
},
getSuggestions: (value) => {
const domains = [
{ domain: 'gmail.com', provider: 'Google' },
{ domain: 'outlook.com', provider: 'Microsoft' },
{ domain: 'yahoo.com', provider: 'Yahoo' },
{ domain: 'icloud.com', provider: 'Apple' },
{ domain: 'protonmail.com', provider: 'ProtonMail' }
];
if (value.includes('@') && !value.split('@')[1]) {
const [username] = value.split('@');
return domains.map(d => ({
primary: `${username}@${d.domain}`,
secondary: `${d.provider} email`,
value: `${username}@${d.domain}`
}));
}
return [];
}
};
// Phone configuration
const phoneConfig = {
minLength: 3,
initialHelp: 'Enter a phone number',
validHelp: 'Phone number is valid',
invalidHelp: 'Please enter a valid phone number',
formatHint: 'Auto-formatted',
validator: (value) => {
const digits = value.replace(/\D/g, '');
return {
valid: digits.length >= 10 && digits.length <= 15,
help: digits.length < 10 ? 'Phone number too short' :
digits.length > 15 ? 'Phone number too long' : null
};
},
formatter: (value) => {
const digits = value.replace(/\D/g, '');
if (digits.length <= 3) return digits;
if (digits.length <= 6) return `(${digits.slice(0, 3)}) ${digits.slice(3)}`;
if (digits.length <= 10) return `(${digits.slice(0, 3)}) ${digits.slice(3, 6)}-${digits.slice(6)}`;
return `+${digits.slice(0, digits.length - 10)} (${digits.slice(-10, -7)}) ${digits.slice(-7, -4)}-${digits.slice(-4)}`;
},
getSuggestions: (value) => {
const countryCodes = [
{ code: '+1', country: 'United States / Canada' },
{ code: '+44', country: 'United Kingdom' },
{ code: '+33', country: 'France' },
{ code: '+49', country: 'Germany' },
{ code: '+81', country: 'Japan' }
];
if (value === '+' || value.startsWith('+')) {
return countryCodes
.filter(c => c.code.startsWith(value))
.map(c => ({
primary: c.code,
secondary: c.country,
value: c.code + ' '
}));
}
return [];
}
};
// Credit card configuration
const cardConfig = {
minLength: 4,
initialHelp: 'Enter your credit card number',
validHelp: 'Card number is valid',
invalidHelp: 'Please enter a valid card number',
formatHint: 'Formatting applied',
validator: (value) => {
const digits = value.replace(/\s/g, '');
// Basic Luhn algorithm check
if (digits.length < 13 || digits.length > 19) {
return { valid: false };
}
let sum = 0;
let isEven = false;
for (let i = digits.length - 1; i >= 0; i--) {
let digit = parseInt(digits[i]);
if (isEven) {
digit *= 2;
if (digit > 9) digit -= 9;
}
sum += digit;
isEven = !isEven;
}
return {
valid: sum % 10 === 0,
help: digits.length < 16 ? 'Card number incomplete' : null
};
},
formatter: (value) => {
const digits = value.replace(/\s/g, '');
const groups = [];
// Detect card type and format accordingly
if (digits.startsWith('34') || digits.startsWith('37')) {
// American Express: 4-6-5
groups.push(digits.slice(0, 4), digits.slice(4, 10), digits.slice(10, 15));
} else {
// Others: 4-4-4-4
for (let i = 0; i < digits.length; i += 4) {
groups.push(digits.slice(i, i + 4));
}
}
return groups.filter(g => g).join(' ');
},
getSuggestions: (value) => {
const cardTypes = [
{ prefix: '4', type: 'Visa', icon: '💳' },
{ prefix: '5', type: 'Mastercard', icon: '💳' },
{ prefix: '34', type: 'American Express', icon: '💳' },
{ prefix: '37', type: 'American Express', icon: '💳' },
{ prefix: '6', type: 'Discover', icon: '💳' }
];
const digits = value.replace(/\s/g, '');
if (digits.length <= 2) {
return cardTypes
.filter(c => c.prefix.startsWith(digits))
.map(c => ({
primary: `${c.icon} ${c.type}`,
secondary: `Starts with ${c.prefix}`,
value: c.prefix
}));
}
return [];
}
};
// Initialize all inputs
new InputIntelligence('emailInput', emailConfig);
new InputIntelligence('phoneInput', phoneConfig);
new InputIntelligence('cardInput', cardConfig);
</script>
</body>
</html>

View File

@ -0,0 +1,718 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Retro Computing Action Controller</title>
<style>
/* Retro Terminal Theme */
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 20px;
background: #000000;
color: #00ff00;
font-family: 'Courier New', monospace;
font-size: 14px;
line-height: 1.4;
overflow-x: hidden;
}
/* CRT Monitor Effect */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(
rgba(18, 16, 16, 0) 50%,
rgba(0, 0, 0, 0.25) 50%
);
background-size: 100% 2px;
z-index: 1;
pointer-events: none;
animation: scanlines 8s linear infinite;
}
@keyframes scanlines {
0% { background-position: 0 0; }
100% { background-position: 0 10px; }
}
main {
position: relative;
z-index: 2;
max-width: 800px;
margin: 0 auto;
}
h1 {
color: #00ff00;
text-transform: uppercase;
letter-spacing: 2px;
font-size: 1.2em;
margin-bottom: 30px;
text-shadow: 0 0 10px #00ff00;
}
/* Terminal Container */
.terminal-controller {
background: #0a0a0a;
border: 2px solid #00ff00;
border-radius: 8px;
padding: 20px;
box-shadow:
0 0 20px rgba(0, 255, 0, 0.5),
inset 0 0 20px rgba(0, 255, 0, 0.1);
position: relative;
overflow: hidden;
}
/* Terminal Header */
.terminal-header {
border-bottom: 1px solid #00ff00;
padding-bottom: 10px;
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.terminal-title {
color: #00ff00;
text-transform: uppercase;
letter-spacing: 1px;
}
.terminal-status {
display: flex;
gap: 10px;
}
.status-indicator {
width: 8px;
height: 8px;
background: #00ff00;
border-radius: 50%;
box-shadow: 0 0 5px #00ff00;
animation: blink 2s infinite;
}
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0.3; }
}
/* Command History */
.command-history {
height: 200px;
overflow-y: auto;
margin-bottom: 20px;
padding: 10px;
background: rgba(0, 0, 0, 0.5);
border: 1px solid #00ff00;
font-size: 12px;
}
.command-history::-webkit-scrollbar {
width: 8px;
}
.command-history::-webkit-scrollbar-track {
background: #0a0a0a;
}
.command-history::-webkit-scrollbar-thumb {
background: #00ff00;
border-radius: 4px;
}
.history-entry {
margin-bottom: 8px;
opacity: 0.8;
}
.history-entry.command {
color: #00ff00;
}
.history-entry.output {
color: #00cc00;
padding-left: 20px;
}
.history-entry.error {
color: #ff3333;
padding-left: 20px;
}
.history-entry.success {
color: #00ff00;
padding-left: 20px;
}
/* Command Input Area */
.command-input-area {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
background: rgba(0, 0, 0, 0.7);
border: 1px solid #00ff00;
position: relative;
}
.prompt {
color: #00ff00;
font-weight: bold;
}
.command-display {
flex: 1;
color: #00ff00;
position: relative;
}
.cursor {
display: inline-block;
width: 8px;
height: 14px;
background: #00ff00;
animation: cursor-blink 1s infinite;
vertical-align: text-bottom;
}
@keyframes cursor-blink {
0%, 49% { opacity: 1; }
50%, 100% { opacity: 0; }
}
/* Action Buttons */
.action-buttons {
display: flex;
gap: 10px;
margin-top: 20px;
}
.terminal-button {
flex: 1;
background: transparent;
border: 1px solid #00ff00;
color: #00ff00;
padding: 12px 20px;
font-family: 'Courier New', monospace;
font-size: 12px;
text-transform: uppercase;
cursor: pointer;
position: relative;
overflow: hidden;
transition: all 0.3s;
}
.terminal-button:hover {
background: rgba(0, 255, 0, 0.1);
box-shadow: 0 0 10px rgba(0, 255, 0, 0.5);
text-shadow: 0 0 5px #00ff00;
}
.terminal-button:active {
transform: scale(0.98);
}
.terminal-button.executing {
pointer-events: none;
animation: pulse 0.5s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
/* Loading Animation */
.loading-animation {
display: none;
text-align: center;
padding: 20px;
color: #00ff00;
}
.loading-animation.active {
display: block;
}
.loading-bar {
width: 100%;
height: 20px;
border: 1px solid #00ff00;
margin: 10px 0;
position: relative;
overflow: hidden;
}
.loading-progress {
height: 100%;
background: #00ff00;
width: 0%;
transition: width 0.3s;
box-shadow: 0 0 10px #00ff00;
}
.loading-text {
font-size: 12px;
margin-top: 10px;
}
/* Confirmation Dialog */
.confirmation-dialog {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #000000;
border: 2px solid #00ff00;
padding: 20px;
z-index: 10;
box-shadow: 0 0 30px rgba(0, 255, 0, 0.8);
}
.confirmation-dialog.active {
display: block;
}
.confirmation-message {
margin-bottom: 20px;
color: #00ff00;
}
.confirmation-prompt {
color: #ffff00;
margin-bottom: 10px;
}
.confirmation-options {
display: flex;
gap: 20px;
justify-content: center;
}
.confirmation-option {
color: #00ff00;
cursor: pointer;
padding: 5px 10px;
border: 1px solid transparent;
}
.confirmation-option:hover {
border-color: #00ff00;
background: rgba(0, 255, 0, 0.1);
}
/* ASCII Art Elements */
.ascii-decoration {
color: #00ff00;
opacity: 0.3;
font-size: 10px;
line-height: 1;
white-space: pre;
margin: 20px 0;
}
/* Sound indicator */
.sound-indicator {
position: fixed;
bottom: 20px;
right: 20px;
color: #00ff00;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s;
}
.sound-indicator.active {
opacity: 1;
}
/* Glitch effect for errors */
@keyframes glitch {
0%, 100% {
text-shadow:
-2px 0 #ff0000,
2px 0 #00ffff;
}
25% {
text-shadow:
2px 0 #ff0000,
-2px 0 #00ffff;
}
50% {
text-shadow:
-2px 0 #ff0000,
2px 0 #00ffff;
}
}
.glitch {
animation: glitch 0.5s infinite;
}
</style>
</head>
<body>
<main>
<h1>Action Controller - Retro Computing Theme</h1>
<div class="terminal-controller">
<div class="terminal-header">
<div class="terminal-title">SYSTEM TERMINAL v3.1</div>
<div class="terminal-status">
<div class="status-indicator"></div>
<div class="status-indicator"></div>
<div class="status-indicator"></div>
</div>
</div>
<div class="ascii-decoration">
╔═══════════════════════════════════════════════════════════════╗
║ ┌─┐┌─┐┌┬┐┬┌─┐┌┐┌ ┌─┐┌─┐┌┐┌┌┬┐┬─┐┌─┐┬ ┬ ┌─┐┬─┐ ║
║ ├─┤│ │ ││ ││││ │ │ ││││ │ ├┬┘│ ││ │ ├┤ ├┬┘ ║
║ ┴ ┴└─┘ ┴ ┴└─┘┘└┘ └─┘└─┘┘└┘ ┴ ┴└─└─┘┴─┘┴─┘└─┘┴└─ ║
╚═══════════════════════════════════════════════════════════════╝
</div>
<div class="command-history" id="commandHistory">
<div class="history-entry command">&gt; SYSTEM INITIALIZED</div>
<div class="history-entry output">Ready for commands...</div>
<div class="history-entry output">Type 'HELP' for available commands</div>
</div>
<div class="command-input-area">
<span class="prompt">&gt;</span>
<div class="command-display" id="commandDisplay">
<span id="currentCommand"></span><span class="cursor"></span>
</div>
</div>
<div class="loading-animation" id="loadingAnimation">
<div>EXECUTING COMMAND...</div>
<div class="loading-bar">
<div class="loading-progress" id="loadingProgress"></div>
</div>
<div class="loading-text" id="loadingText">Processing...</div>
</div>
<div class="action-buttons">
<button class="terminal-button" data-command="DEPLOY">
[F1] DEPLOY
</button>
<button class="terminal-button" data-command="ANALYZE">
[F2] ANALYZE
</button>
<button class="terminal-button" data-command="BACKUP">
[F3] BACKUP
</button>
<button class="terminal-button" data-command="SHUTDOWN">
[F4] SHUTDOWN
</button>
</div>
<div class="confirmation-dialog" id="confirmationDialog">
<div class="confirmation-message" id="confirmMessage"></div>
<div class="confirmation-prompt">CONFIRM ACTION? [Y/N]</div>
<div class="confirmation-options">
<span class="confirmation-option" id="confirmYes">[Y] YES</span>
<span class="confirmation-option" id="confirmNo">[N] NO</span>
</div>
</div>
</div>
<div class="sound-indicator" id="soundIndicator">♪ BEEP</div>
</main>
<script>
// Terminal State Management
const terminal = {
history: [],
currentCommand: '',
isExecuting: false,
commandQueue: []
};
// DOM Elements
const commandHistory = document.getElementById('commandHistory');
const currentCommandEl = document.getElementById('currentCommand');
const loadingAnimation = document.getElementById('loadingAnimation');
const loadingProgress = document.getElementById('loadingProgress');
const loadingText = document.getElementById('loadingText');
const confirmationDialog = document.getElementById('confirmationDialog');
const confirmMessage = document.getElementById('confirmMessage');
const soundIndicator = document.getElementById('soundIndicator');
// Command Definitions
const commands = {
DEPLOY: {
description: 'Deploy system updates',
requiresConfirmation: true,
loadingTime: 3000,
steps: [
'Initializing deployment sequence...',
'Checking system integrity...',
'Uploading files...',
'Verifying checksums...',
'Deployment complete!'
]
},
ANALYZE: {
description: 'Run system analysis',
requiresConfirmation: false,
loadingTime: 2000,
steps: [
'Starting analysis...',
'Scanning processes...',
'Checking memory usage...',
'Analysis complete!'
]
},
BACKUP: {
description: 'Create system backup',
requiresConfirmation: true,
loadingTime: 4000,
steps: [
'Preparing backup...',
'Compressing data...',
'Writing to storage...',
'Verifying backup integrity...',
'Backup successful!'
]
},
SHUTDOWN: {
description: 'Shutdown system',
requiresConfirmation: true,
loadingTime: 2000,
steps: [
'Initiating shutdown sequence...',
'Saving state...',
'Closing connections...',
'System shutdown complete.'
]
}
};
// Sound Effects (using Web Audio API)
function playBeep(frequency = 800, duration = 100) {
try {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.frequency.value = frequency;
oscillator.type = 'square';
gainNode.gain.value = 0.1;
oscillator.start();
oscillator.stop(audioContext.currentTime + duration / 1000);
// Show sound indicator
soundIndicator.classList.add('active');
setTimeout(() => soundIndicator.classList.remove('active'), 300);
} catch (e) {
console.log('Audio not supported');
}
}
// Add entry to command history
function addHistoryEntry(text, type = 'command') {
const entry = document.createElement('div');
entry.className = `history-entry ${type}`;
entry.textContent = type === 'command' ? `> ${text}` : text;
commandHistory.appendChild(entry);
commandHistory.scrollTop = commandHistory.scrollHeight;
// Add to history array
terminal.history.push({ text, type, timestamp: new Date() });
}
// Show loading animation
async function showLoading(command) {
loadingAnimation.classList.add('active');
const steps = commands[command].steps;
const stepDuration = commands[command].loadingTime / steps.length;
for (let i = 0; i < steps.length; i++) {
loadingText.textContent = steps[i];
loadingProgress.style.width = `${((i + 1) / steps.length) * 100}%`;
playBeep(600 + (i * 100), 50);
await new Promise(resolve => setTimeout(resolve, stepDuration));
}
loadingAnimation.classList.remove('active');
loadingProgress.style.width = '0%';
}
// Show confirmation dialog
function showConfirmation(command) {
return new Promise((resolve) => {
confirmMessage.textContent = `Execute ${command} command?`;
confirmationDialog.classList.add('active');
playBeep(1000, 100);
const handleYes = () => {
confirmationDialog.classList.remove('active');
playBeep(1200, 50);
cleanup();
resolve(true);
};
const handleNo = () => {
confirmationDialog.classList.remove('active');
playBeep(400, 100);
cleanup();
resolve(false);
};
const handleKeypress = (e) => {
if (e.key.toLowerCase() === 'y') handleYes();
if (e.key.toLowerCase() === 'n') handleNo();
};
const cleanup = () => {
document.getElementById('confirmYes').removeEventListener('click', handleYes);
document.getElementById('confirmNo').removeEventListener('click', handleNo);
document.removeEventListener('keypress', handleKeypress);
};
document.getElementById('confirmYes').addEventListener('click', handleYes);
document.getElementById('confirmNo').addEventListener('click', handleNo);
document.addEventListener('keypress', handleKeypress);
});
}
// Execute command
async function executeCommand(command) {
if (terminal.isExecuting) return;
terminal.isExecuting = true;
// Add command to history
addHistoryEntry(command, 'command');
currentCommandEl.textContent = '';
// Check if command exists
if (!commands[command]) {
addHistoryEntry(`ERROR: Unknown command '${command}'`, 'error');
document.body.classList.add('glitch');
playBeep(200, 200);
setTimeout(() => document.body.classList.remove('glitch'), 500);
terminal.isExecuting = false;
return;
}
// Show command description
addHistoryEntry(commands[command].description, 'output');
// Check for confirmation
if (commands[command].requiresConfirmation) {
const confirmed = await showConfirmation(command);
if (!confirmed) {
addHistoryEntry('Command cancelled', 'output');
terminal.isExecuting = false;
return;
}
}
// Execute with loading animation
try {
await showLoading(command);
addHistoryEntry(`${command} executed successfully`, 'success');
playBeep(1600, 100);
setTimeout(() => playBeep(1800, 100), 150);
} catch (error) {
addHistoryEntry(`ERROR: ${command} failed - ${error.message}`, 'error');
playBeep(300, 300);
}
terminal.isExecuting = false;
}
// Handle button clicks
document.querySelectorAll('.terminal-button').forEach(button => {
button.addEventListener('click', async function() {
if (terminal.isExecuting) return;
const command = this.dataset.command;
this.classList.add('executing');
await executeCommand(command);
this.classList.remove('executing');
});
});
// Keyboard shortcuts
document.addEventListener('keydown', async (e) => {
if (terminal.isExecuting) return;
// Function key shortcuts
if (e.key === 'F1') {
e.preventDefault();
await executeCommand('DEPLOY');
} else if (e.key === 'F2') {
e.preventDefault();
await executeCommand('ANALYZE');
} else if (e.key === 'F3') {
e.preventDefault();
await executeCommand('BACKUP');
} else if (e.key === 'F4') {
e.preventDefault();
await executeCommand('SHUTDOWN');
}
// Type command
if (e.key.length === 1 && !e.ctrlKey && !e.metaKey) {
terminal.currentCommand += e.key.toUpperCase();
currentCommandEl.textContent = terminal.currentCommand;
playBeep(1000, 30);
}
// Enter to execute typed command
if (e.key === 'Enter' && terminal.currentCommand) {
await executeCommand(terminal.currentCommand);
terminal.currentCommand = '';
currentCommandEl.textContent = '';
}
// Backspace
if (e.key === 'Backspace' && terminal.currentCommand) {
terminal.currentCommand = terminal.currentCommand.slice(0, -1);
currentCommandEl.textContent = terminal.currentCommand;
playBeep(800, 30);
}
});
// Initial beep on load
window.addEventListener('load', () => {
setTimeout(() => {
playBeep(800, 100);
setTimeout(() => playBeep(1000, 100), 150);
setTimeout(() => playBeep(1200, 100), 300);
}, 500);
});
// Add some random flicker effect
setInterval(() => {
if (Math.random() > 0.95) {
document.body.style.opacity = '0.95';
setTimeout(() => {
document.body.style.opacity = '1';
}, 50);
}
}, 3000);
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,854 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Zen Philosophy Navigation Center</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
/* Zen color palette - calm, muted tones */
--zen-white: #fafaf8;
--zen-sand: #e8e3da;
--zen-stone: #b8b2a6;
--zen-moss: #7a8672;
--zen-water: #6b7f8c;
--zen-shadow: #4a4a48;
--zen-ink: #2c2c2a;
/* Breathing animation timing */
--breathe-in: 3s;
--breathe-out: 4s;
--transition-flow: cubic-bezier(0.4, 0.0, 0.2, 1);
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: linear-gradient(135deg, var(--zen-white) 0%, var(--zen-sand) 100%);
color: var(--zen-ink);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
main {
width: 100%;
max-width: 1200px;
}
h1 {
text-align: center;
font-weight: 300;
font-size: 2rem;
color: var(--zen-shadow);
margin-bottom: 3rem;
letter-spacing: 0.1em;
}
/* Navigation Center Container */
.navigation-center {
background: var(--zen-white);
border-radius: 20px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.05);
padding: 2rem;
position: relative;
overflow: hidden;
}
/* Zen decoration - subtle circle pattern */
.navigation-center::before {
content: '';
position: absolute;
width: 300px;
height: 300px;
border-radius: 50%;
background: radial-gradient(circle, transparent 60%, var(--zen-sand) 100%);
top: -150px;
right: -150px;
opacity: 0.3;
animation: breathe var(--breathe-in) ease-in-out infinite alternate;
}
@keyframes breathe {
0% { transform: scale(1); opacity: 0.3; }
100% { transform: scale(1.1); opacity: 0.2; }
}
/* Top Section - Search and Actions */
.nav-top {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
align-items: center;
}
/* Search as Mindful Exploration */
.search-container {
flex: 1;
position: relative;
}
.search-input {
width: 100%;
padding: 1rem 3rem 1rem 1.5rem;
border: 2px solid transparent;
background: var(--zen-sand);
border-radius: 30px;
font-size: 1rem;
color: var(--zen-ink);
transition: all 0.4s var(--transition-flow);
}
.search-input:focus {
outline: none;
background: var(--zen-white);
border-color: var(--zen-stone);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}
.search-input::placeholder {
color: var(--zen-stone);
}
.search-icon {
position: absolute;
right: 1.5rem;
top: 50%;
transform: translateY(-50%);
color: var(--zen-stone);
pointer-events: none;
transition: color 0.4s var(--transition-flow);
}
.search-input:focus + .search-icon {
color: var(--zen-moss);
}
/* Quick Actions as Zen Shortcuts */
.quick-actions {
display: flex;
gap: 0.5rem;
}
.action-stone {
width: 48px;
height: 48px;
border-radius: 50%;
background: var(--zen-sand);
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--zen-shadow);
transition: all 0.3s var(--transition-flow);
position: relative;
overflow: hidden;
}
.action-stone:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
background: var(--zen-stone);
color: var(--zen-white);
}
.action-stone::after {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at center, var(--zen-water) 0%, transparent 70%);
opacity: 0;
transition: opacity 0.6s ease;
}
.action-stone:active::after {
opacity: 0.3;
animation: ripple 0.6s ease-out;
}
@keyframes ripple {
0% { transform: scale(0); }
100% { transform: scale(2); }
}
/* Breadcrumbs as Stepping Path */
.stepping-path {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 2rem;
padding: 1rem;
background: linear-gradient(90deg, var(--zen-sand) 0%, transparent 100%);
border-radius: 10px;
overflow-x: auto;
scrollbar-width: thin;
scrollbar-color: var(--zen-stone) transparent;
}
.path-stone {
white-space: nowrap;
color: var(--zen-shadow);
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 20px;
transition: all 0.3s var(--transition-flow);
position: relative;
}
.path-stone:hover {
background: var(--zen-white);
color: var(--zen-moss);
}
.path-divider {
color: var(--zen-stone);
font-size: 0.8rem;
}
.path-stone.current {
background: var(--zen-moss);
color: var(--zen-white);
}
/* Tabs as Meditation Stones */
.meditation-stones {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
padding: 1rem;
background: var(--zen-sand);
border-radius: 15px;
overflow-x: auto;
scrollbar-width: thin;
scrollbar-color: var(--zen-stone) transparent;
}
.stone-tab {
padding: 1rem 2rem;
border: none;
background: var(--zen-white);
border-radius: 30px;
cursor: pointer;
color: var(--zen-shadow);
font-size: 1rem;
white-space: nowrap;
transition: all 0.4s var(--transition-flow);
position: relative;
overflow: hidden;
}
.stone-tab::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, var(--zen-moss) 0%, var(--zen-water) 100%);
opacity: 0;
transition: opacity 0.4s var(--transition-flow);
}
.stone-tab:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
}
.stone-tab.active {
color: var(--zen-white);
}
.stone-tab.active::before {
opacity: 1;
}
.stone-tab span {
position: relative;
z-index: 1;
}
/* Content Area */
.content-garden {
background: var(--zen-white);
border-radius: 15px;
padding: 2rem;
min-height: 300px;
position: relative;
overflow: hidden;
}
.content-section {
display: none;
animation: fadeInUp 0.6s var(--transition-flow);
}
.content-section.active {
display: block;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* State Memory Indicator */
.consciousness-indicator {
position: absolute;
bottom: 2rem;
right: 2rem;
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
background: var(--zen-sand);
border-radius: 20px;
font-size: 0.9rem;
color: var(--zen-shadow);
opacity: 0;
transform: translateY(10px);
transition: all 0.4s var(--transition-flow);
}
.consciousness-indicator.visible {
opacity: 1;
transform: translateY(0);
}
.consciousness-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--zen-moss);
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 0.4; transform: scale(1); }
50% { opacity: 1; transform: scale(1.2); }
}
/* Search Results Dropdown */
.search-results {
position: absolute;
top: 100%;
left: 0;
right: 0;
margin-top: 0.5rem;
background: var(--zen-white);
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
max-height: 300px;
overflow-y: auto;
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: all 0.3s var(--transition-flow);
z-index: 10;
}
.search-results.visible {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.search-result {
padding: 1rem 1.5rem;
cursor: pointer;
transition: background 0.2s ease;
border-bottom: 1px solid var(--zen-sand);
}
.search-result:last-child {
border-bottom: none;
}
.search-result:hover {
background: var(--zen-sand);
}
.search-result-title {
font-weight: 500;
color: var(--zen-ink);
margin-bottom: 0.25rem;
}
.search-result-path {
font-size: 0.85rem;
color: var(--zen-stone);
}
/* Tooltip for actions */
.tooltip {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%) translateY(-5px);
background: var(--zen-ink);
color: var(--zen-white);
padding: 0.5rem 1rem;
border-radius: 8px;
font-size: 0.85rem;
white-space: nowrap;
opacity: 0;
visibility: hidden;
transition: all 0.3s var(--transition-flow);
pointer-events: none;
}
.action-stone:hover .tooltip {
opacity: 1;
visibility: visible;
transform: translateX(-50%) translateY(-10px);
}
/* Responsive adjustments */
@media (max-width: 768px) {
.nav-top {
flex-direction: column;
}
.quick-actions {
width: 100%;
justify-content: center;
}
.meditation-stones {
gap: 0.5rem;
padding: 0.75rem;
}
.stone-tab {
padding: 0.75rem 1.5rem;
font-size: 0.9rem;
}
.consciousness-indicator {
bottom: 1rem;
right: 1rem;
font-size: 0.8rem;
}
}
</style>
</head>
<body>
<main>
<h1>Navigation Center - Zen Philosophy Theme</h1>
<div class="navigation-center">
<!-- Top Section with Search and Quick Actions -->
<div class="nav-top">
<div class="search-container">
<input
type="text"
class="search-input"
placeholder="Begin your mindful exploration..."
id="searchInput"
>
<svg class="search-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
<div class="search-results" id="searchResults">
<!-- Search results will be populated here -->
</div>
</div>
<div class="quick-actions">
<button class="action-stone" data-action="home">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
<span class="tooltip">Return to beginning</span>
</button>
<button class="action-stone" data-action="bookmark">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="m19 21-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>
</svg>
<span class="tooltip">Mark this moment</span>
</button>
<button class="action-stone" data-action="settings">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="3"></circle>
<path d="M12 1v6m0 6v6m11-11h-6m-6 0H1"></path>
</svg>
<span class="tooltip">Adjust your path</span>
</button>
</div>
</div>
<!-- Breadcrumbs as Stepping Path -->
<div class="stepping-path" id="steppingPath">
<a href="#" class="path-stone" data-path="root">Garden</a>
<span class="path-divider"></span>
<a href="#" class="path-stone" data-path="meditation">Meditation</a>
<span class="path-divider"></span>
<a href="#" class="path-stone current" data-path="breathing">Breathing</a>
</div>
<!-- Tabs as Meditation Stones -->
<div class="meditation-stones" id="meditationStones">
<button class="stone-tab active" data-tab="breathing">
<span>Breathing</span>
</button>
<button class="stone-tab" data-tab="mindfulness">
<span>Mindfulness</span>
</button>
<button class="stone-tab" data-tab="movement">
<span>Movement</span>
</button>
<button class="stone-tab" data-tab="reflection">
<span>Reflection</span>
</button>
<button class="stone-tab" data-tab="wisdom">
<span>Wisdom</span>
</button>
</div>
<!-- Content Area -->
<div class="content-garden">
<div class="content-section active" data-content="breathing">
<h2>The Art of Breathing</h2>
<p>In the garden of consciousness, breath is the first step on the path to awareness. Each inhale brings new possibilities, each exhale releases what no longer serves.</p>
<br>
<p>Begin with simple observation. Notice the natural rhythm without forcing change. Like water finding its level, let your breath find its own peaceful cadence.</p>
<br>
<p>Practice the 4-7-8 technique: Inhale for 4 counts, hold for 7, exhale for 8. This ancient pattern calms the mind and prepares the spirit for deeper meditation.</p>
</div>
<div class="content-section" data-content="mindfulness">
<h2>Present Moment Awareness</h2>
<p>Mindfulness is the art of being fully present. Like a still pond reflecting the sky, the mindful mind mirrors reality without distortion.</p>
<br>
<p>Start with your senses. What do you see, hear, feel in this exact moment? Each sensation is a doorway to presence, a bridge from thinking to being.</p>
<br>
<p>When thoughts arise, observe them like clouds passing through an empty sky. No need to grasp or push away - simply witness and return to now.</p>
</div>
<div class="content-section" data-content="movement">
<h2>Meditation in Motion</h2>
<p>Movement meditation transforms everyday actions into spiritual practice. Walking, stretching, even washing dishes can become paths to enlightenment.</p>
<br>
<p>Try walking meditation: Each step deliberate, each movement conscious. Feel the earth beneath your feet, the air around your body. This is moving zen.</p>
<br>
<p>Gentle yoga or tai chi brings harmony between body and mind. Flow like water, bend like bamboo - strength through flexibility, power through peace.</p>
</div>
<div class="content-section" data-content="reflection">
<h2>The Mirror of Self</h2>
<p>Reflection deepens understanding. Like a mountain lake that reveals both surface and depths, contemplation shows us who we truly are.</p>
<br>
<p>Journal your thoughts without judgment. Let words flow like a stream, carrying insights from the depths of consciousness to the light of awareness.</p>
<br>
<p>Ask yourself: What am I grateful for today? What lessons has life offered? In quiet reflection, wisdom emerges naturally, like flowers blooming in their season.</p>
</div>
<div class="content-section" data-content="wisdom">
<h2>Ancient Teachings</h2>
<p>"The pine teaches silence, the rock teaches patience, the water teaches persistence." These natural teachers surround us, offering lessons to those who listen.</p>
<br>
<p>Zen masters remind us: "Before enlightenment, chop wood, carry water. After enlightenment, chop wood, carry water." Profound truth lives in simple actions.</p>
<br>
<p>Study the wisdom traditions not as dogma but as maps. Each tradition offers a different path up the same mountain. Find the way that resonates with your spirit.</p>
</div>
</div>
<!-- State Memory Indicator -->
<div class="consciousness-indicator" id="consciousnessIndicator">
<span class="consciousness-dot"></span>
<span>State remembered</span>
</div>
</div>
</main>
<script>
// State Management - Conscious Awareness
class NavigationState {
constructor() {
this.state = this.loadState() || {
currentTab: 'breathing',
breadcrumbs: ['root', 'meditation', 'breathing'],
searchHistory: [],
bookmarks: [],
lastVisit: Date.now()
};
this.saveStateDebounced = this.debounce(this.saveState.bind(this), 1000);
}
loadState() {
try {
const saved = localStorage.getItem('zenNavState');
return saved ? JSON.parse(saved) : null;
} catch (e) {
return null;
}
}
saveState() {
try {
localStorage.setItem('zenNavState', JSON.stringify(this.state));
this.showConsciousnessIndicator();
} catch (e) {
console.error('Could not save state:', e);
}
}
showConsciousnessIndicator() {
const indicator = document.getElementById('consciousnessIndicator');
indicator.classList.add('visible');
setTimeout(() => {
indicator.classList.remove('visible');
}, 2000);
}
updateTab(tabName) {
this.state.currentTab = tabName;
this.saveStateDebounced();
}
updateBreadcrumbs(path) {
const index = this.state.breadcrumbs.indexOf(path);
if (index > -1) {
this.state.breadcrumbs = this.state.breadcrumbs.slice(0, index + 1);
} else {
this.state.breadcrumbs.push(path);
}
this.saveStateDebounced();
}
addSearchTerm(term) {
if (!this.state.searchHistory.includes(term)) {
this.state.searchHistory.unshift(term);
this.state.searchHistory = this.state.searchHistory.slice(0, 10);
this.saveStateDebounced();
}
}
debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
}
// Initialize Navigation State
const navState = new NavigationState();
// Tab Navigation - Meditation Stones
const tabs = document.querySelectorAll('.stone-tab');
const contents = document.querySelectorAll('.content-section');
function switchTab(tabName) {
tabs.forEach(tab => {
if (tab.dataset.tab === tabName) {
tab.classList.add('active');
} else {
tab.classList.remove('active');
}
});
contents.forEach(content => {
if (content.dataset.content === tabName) {
content.classList.add('active');
} else {
content.classList.remove('active');
}
});
navState.updateTab(tabName);
updateBreadcrumbsForTab(tabName);
}
tabs.forEach(tab => {
tab.addEventListener('click', () => {
switchTab(tab.dataset.tab);
});
});
// Breadcrumb Navigation - Stepping Path
function updateBreadcrumbsForTab(tabName) {
const pathElement = document.getElementById('steppingPath');
const newPath = ['root', 'meditation', tabName];
pathElement.innerHTML = newPath.map((step, index) => {
const isLast = index === newPath.length - 1;
const stone = `<a href="#" class="path-stone ${isLast ? 'current' : ''}" data-path="${step}">${step.charAt(0).toUpperCase() + step.slice(1)}</a>`;
const divider = isLast ? '' : '<span class="path-divider"></span>';
return stone + divider;
}).join('');
// Re-attach breadcrumb listeners
attachBreadcrumbListeners();
navState.updateBreadcrumbs(tabName);
}
function attachBreadcrumbListeners() {
document.querySelectorAll('.path-stone').forEach(stone => {
stone.addEventListener('click', (e) => {
e.preventDefault();
const path = stone.dataset.path;
if (path !== 'root' && path !== 'meditation') {
switchTab(path);
}
});
});
}
// Search Functionality - Mindful Exploration
const searchInput = document.getElementById('searchInput');
const searchResults = document.getElementById('searchResults');
const searchableContent = [
{ title: 'Breathing Techniques', path: 'Meditation > Breathing', tab: 'breathing' },
{ title: '4-7-8 Breathing Method', path: 'Meditation > Breathing > Techniques', tab: 'breathing' },
{ title: 'Present Moment Practice', path: 'Meditation > Mindfulness', tab: 'mindfulness' },
{ title: 'Walking Meditation', path: 'Meditation > Movement', tab: 'movement' },
{ title: 'Tai Chi Basics', path: 'Meditation > Movement > Forms', tab: 'movement' },
{ title: 'Journaling for Insight', path: 'Meditation > Reflection', tab: 'reflection' },
{ title: 'Zen Teachings', path: 'Meditation > Wisdom', tab: 'wisdom' },
{ title: 'Natural Teachers', path: 'Meditation > Wisdom > Nature', tab: 'wisdom' }
];
searchInput.addEventListener('input', (e) => {
const query = e.target.value.toLowerCase().trim();
if (query.length > 2) {
const results = searchableContent.filter(item =>
item.title.toLowerCase().includes(query) ||
item.path.toLowerCase().includes(query)
);
if (results.length > 0) {
displaySearchResults(results);
searchResults.classList.add('visible');
} else {
searchResults.classList.remove('visible');
}
} else {
searchResults.classList.remove('visible');
}
});
searchInput.addEventListener('blur', (e) => {
setTimeout(() => {
searchResults.classList.remove('visible');
if (e.target.value.trim()) {
navState.addSearchTerm(e.target.value.trim());
}
}, 200);
});
function displaySearchResults(results) {
searchResults.innerHTML = results.map(result => `
<div class="search-result" data-tab="${result.tab}">
<div class="search-result-title">${result.title}</div>
<div class="search-result-path">${result.path}</div>
</div>
`).join('');
// Add click handlers to results
searchResults.querySelectorAll('.search-result').forEach(result => {
result.addEventListener('mousedown', (e) => {
e.preventDefault();
const tab = result.dataset.tab;
switchTab(tab);
searchInput.value = '';
searchResults.classList.remove('visible');
});
});
}
// Quick Actions - Zen Shortcuts
const actionButtons = document.querySelectorAll('.action-stone');
actionButtons.forEach(button => {
button.addEventListener('click', () => {
const action = button.dataset.action;
switch(action) {
case 'home':
switchTab('breathing');
searchInput.value = '';
break;
case 'bookmark':
const currentTab = navState.state.currentTab;
if (!navState.state.bookmarks.includes(currentTab)) {
navState.state.bookmarks.push(currentTab);
navState.saveState();
button.style.color = 'var(--zen-moss)';
}
break;
case 'settings':
// In a real app, this would open settings
alert('Settings would open here - adjust your meditation preferences');
break;
}
});
});
// Restore state on load
window.addEventListener('load', () => {
// Restore last tab
if (navState.state.currentTab) {
switchTab(navState.state.currentTab);
}
// Highlight bookmarked items
if (navState.state.bookmarks.includes(navState.state.currentTab)) {
const bookmarkButton = document.querySelector('[data-action="bookmark"]');
bookmarkButton.style.color = 'var(--zen-moss)';
}
// Initialize breadcrumb listeners
attachBreadcrumbListeners();
});
// Smooth scroll for tab container
const tabContainer = document.querySelector('.meditation-stones');
let isDown = false;
let startX;
let scrollLeft;
tabContainer.addEventListener('mousedown', (e) => {
if (e.target.classList.contains('stone-tab')) return;
isDown = true;
startX = e.pageX - tabContainer.offsetLeft;
scrollLeft = tabContainer.scrollLeft;
});
tabContainer.addEventListener('mouseleave', () => {
isDown = false;
});
tabContainer.addEventListener('mouseup', () => {
isDown = false;
});
tabContainer.addEventListener('mousemove', (e) => {
if (!isDown) return;
e.preventDefault();
const x = e.pageX - tabContainer.offsetLeft;
const walk = (x - startX) * 2;
tabContainer.scrollLeft = scrollLeft - walk;
});
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,896 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Handcrafted Paper Content Card</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Patrick+Hand&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Patrick Hand', cursive;
background: linear-gradient(135deg, #f5f1e8 0%, #fafaf0 100%);
min-height: 100vh;
padding: 2rem;
position: relative;
overflow-x: hidden;
}
/* Wood texture background */
body::before {
content: '';
position: fixed;
inset: 0;
background-image:
repeating-linear-gradient(90deg, rgba(139, 90, 43, 0.03) 0px, transparent 1px, transparent 2px, rgba(139, 90, 43, 0.03) 3px),
repeating-linear-gradient(0deg, rgba(139, 90, 43, 0.03) 0px, transparent 1px, transparent 2px, rgba(139, 90, 43, 0.03) 3px);
pointer-events: none;
}
main {
max-width: 1200px;
margin: 0 auto;
position: relative;
z-index: 1;
}
h1 {
font-family: 'Kalam', cursive;
font-size: 2.5rem;
color: #4a3f36;
text-align: center;
margin-bottom: 3rem;
text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
position: relative;
}
h1::after {
content: '';
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
width: 200px;
height: 2px;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 2"><path d="M0,1 Q25,0 50,1 T100,1" stroke="%234a3f36" fill="none" stroke-width="0.5"/></svg>');
opacity: 0.5;
}
.content-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2.5rem;
margin-top: 3rem;
}
.paper-card {
position: relative;
background: #fefef4;
padding: 1.5rem;
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.1));
transition: transform 0.3s ease, filter 0.3s ease;
cursor: pointer;
}
.paper-card::before {
content: '';
position: absolute;
inset: -2px;
background: #fefef4;
z-index: -1;
clip-path: polygon(
0% 2%, 2% 0%, 15% 1%, 30% 0%, 45% 2%, 60% 0%, 75% 1%, 90% 0%, 100% 2%,
99% 15%, 100% 30%, 98% 45%, 100% 60%, 99% 75%, 100% 90%, 98% 100%,
85% 99%, 70% 100%, 55% 98%, 40% 100%, 25% 99%, 10% 100%, 0% 98%,
1% 85%, 0% 70%, 2% 55%, 0% 40%, 1% 25%, 0% 10%
);
}
.paper-card:hover {
transform: translateY(-4px) rotate(0.5deg);
filter: drop-shadow(0 8px 16px rgba(0,0,0,0.15));
}
/* Paper texture overlay */
.paper-texture {
position: absolute;
inset: 0;
opacity: 0.3;
background-image:
repeating-linear-gradient(45deg, transparent, transparent 35px, rgba(0,0,0,.02) 35px, rgba(0,0,0,.02) 70px),
repeating-linear-gradient(-45deg, transparent, transparent 35px, rgba(0,0,0,.02) 35px, rgba(0,0,0,.02) 70px);
pointer-events: none;
}
/* Bookmark ribbon */
.bookmark-ribbon {
position: absolute;
top: -5px;
right: 20px;
width: 30px;
height: 60px;
background: #d32f2f;
clip-path: polygon(0 0, 100% 0, 100% 85%, 50% 100%, 0 85%);
transition: all 0.3s ease;
cursor: pointer;
z-index: 10;
}
.bookmark-ribbon::before {
content: '★';
position: absolute;
top: 10px;
left: 50%;
transform: translateX(-50%);
color: white;
font-size: 1.2rem;
}
.bookmark-ribbon.active {
background: #fbc02d;
transform: translateY(5px);
}
/* Content preview */
.card-preview {
margin-bottom: 1rem;
}
.card-image {
width: 100%;
height: 200px;
background: #f5f5dc;
position: relative;
overflow: hidden;
margin-bottom: 1rem;
clip-path: polygon(
0% 1%, 1% 0%, 99% 0%, 100% 1%,
100% 99%, 99% 100%, 1% 100%, 0% 99%
);
}
.card-image img {
width: 100%;
height: 100%;
object-fit: cover;
filter: sepia(0.1) contrast(0.9);
}
.sketch-overlay {
position: absolute;
inset: 0;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M10,10 Q50,5 90,10 M10,90 Q50,95 90,90 M10,10 Q5,50 10,90 M90,10 Q95,50 90,90" stroke="%23000" fill="none" stroke-width="0.2" opacity="0.3"/></svg>');
pointer-events: none;
}
.card-title {
font-family: 'Kalam', cursive;
font-size: 1.5rem;
font-weight: 700;
color: #2c3e50;
margin-bottom: 0.5rem;
position: relative;
}
.card-description {
color: #5a6c7d;
line-height: 1.6;
margin-bottom: 1rem;
}
/* Handwritten metadata */
.metadata {
display: flex;
gap: 1rem;
margin-bottom: 1rem;
font-size: 0.9rem;
color: #7a8694;
}
.metadata span {
position: relative;
padding-bottom: 2px;
}
.metadata span::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 1"><path d="M0,0.5 Q5,0 10,0.5 T20,0.5" stroke="%237a8694" fill="none" stroke-width="0.5"/></svg>');
opacity: 0.3;
}
/* Paper cutout action buttons */
.action-buttons {
display: flex;
gap: 0.5rem;
position: relative;
}
.paper-button {
padding: 0.7rem 1.2rem;
background: #fefef4;
border: none;
font-family: 'Patrick Hand', cursive;
font-size: 1rem;
color: #4a3f36;
cursor: pointer;
position: relative;
transition: all 0.3s ease;
filter: drop-shadow(2px 2px 4px rgba(0,0,0,0.1));
}
.paper-button::before {
content: '';
position: absolute;
inset: -1px;
background: inherit;
z-index: -1;
clip-path: polygon(
0% 5%, 5% 0%, 95% 0%, 100% 5%,
100% 95%, 95% 100%, 5% 100%, 0% 95%
);
}
.paper-button:hover {
transform: translateY(-2px) rotate(-1deg);
filter: drop-shadow(4px 4px 8px rgba(0,0,0,0.15));
}
.paper-button:active {
transform: translateY(0) rotate(0);
filter: drop-shadow(1px 1px 2px rgba(0,0,0,0.1));
}
.paper-button.primary {
background: #e8f5e9;
color: #2e7d32;
}
.paper-button.secondary {
background: #fff3e0;
color: #e65100;
}
/* Share paper airplane */
.share-button {
position: relative;
overflow: visible;
}
.paper-airplane {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
opacity: 0;
pointer-events: none;
}
.paper-airplane.flying {
animation: fly-away 1.5s ease-out forwards;
}
@keyframes fly-away {
0% {
opacity: 1;
transform: translate(-50%, -50%) rotate(0deg) scale(1);
}
100% {
opacity: 0;
transform: translate(200px, -200px) rotate(45deg) scale(0.5);
}
}
/* Modal as unfolding paper */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
z-index: 1000;
}
.modal-overlay.active {
opacity: 1;
pointer-events: all;
}
.paper-modal {
background: #fefef4;
max-width: 600px;
width: 90%;
max-height: 80vh;
position: relative;
filter: drop-shadow(0 10px 30px rgba(0,0,0,0.3));
transform: scale(0.7) rotateX(90deg);
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
transform-style: preserve-3d;
perspective: 1000px;
}
.modal-overlay.active .paper-modal {
transform: scale(1) rotateX(0);
}
.paper-modal::before {
content: '';
position: absolute;
inset: -3px;
background: #fefef4;
z-index: -1;
clip-path: polygon(
0% 3%, 3% 0%, 20% 2%, 40% 0%, 60% 2%, 80% 0%, 97% 3%, 100% 3%,
98% 20%, 100% 40%, 98% 60%, 100% 80%, 97% 97%, 97% 100%,
80% 98%, 60% 100%, 40% 98%, 20% 100%, 3% 97%, 0% 97%,
2% 80%, 0% 60%, 2% 40%, 0% 20%
);
}
.modal-content {
padding: 2.5rem;
overflow-y: auto;
max-height: 80vh;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: start;
margin-bottom: 1.5rem;
}
.modal-title {
font-family: 'Kalam', cursive;
font-size: 2rem;
color: #2c3e50;
}
.close-button {
background: none;
border: none;
font-size: 2rem;
color: #7a8694;
cursor: pointer;
transition: transform 0.3s ease;
font-family: 'Patrick Hand', cursive;
}
.close-button:hover {
transform: rotate(90deg);
}
.modal-body {
line-height: 1.8;
color: #4a5568;
}
.modal-body p {
margin-bottom: 1rem;
}
/* Fold lines on modal */
.fold-lines {
position: absolute;
inset: 0;
pointer-events: none;
opacity: 0.1;
background-image:
linear-gradient(90deg, #000 1px, transparent 1px),
linear-gradient(0deg, #000 1px, transparent 1px);
background-size: 200px 200px;
background-position: center;
}
/* Coffee stain decoration */
.coffee-stain {
position: absolute;
width: 80px;
height: 80px;
border-radius: 50%;
background: radial-gradient(circle, rgba(139, 90, 43, 0.1) 0%, rgba(139, 90, 43, 0.05) 50%, transparent 70%);
top: 20px;
right: 30px;
transform: rotate(45deg);
}
/* Pencil sketch decorations */
.pencil-sketch {
position: absolute;
opacity: 0.2;
pointer-events: none;
}
.sketch-1 {
bottom: 10px;
left: 10px;
width: 50px;
height: 50px;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><circle cx="25" cy="25" r="20" fill="none" stroke="%234a3f36" stroke-width="0.5" stroke-dasharray="1,2"/><path d="M15,25 Q25,15 35,25 T25,35" fill="none" stroke="%234a3f36" stroke-width="0.5"/></svg>');
}
.sketch-2 {
top: 50%;
right: -20px;
width: 40px;
height: 100px;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 100"><path d="M20,10 Q10,30 20,50 T20,90" fill="none" stroke="%234a3f36" stroke-width="0.5"/><circle cx="20" cy="30" r="5" fill="none" stroke="%234a3f36" stroke-width="0.5"/><circle cx="20" cy="70" r="5" fill="none" stroke="%234a3f36" stroke-width="0.5"/></svg>');
}
/* Loading state */
.loading-sketch {
display: inline-block;
width: 20px;
height: 20px;
margin-left: 0.5rem;
animation: sketch-draw 1.5s ease-in-out infinite;
}
@keyframes sketch-draw {
0%, 100% {
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M5,10 L10,10" stroke="%234a3f36" fill="none" stroke-width="1"/></svg>');
}
50% {
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M5,10 L15,10" stroke="%234a3f36" fill="none" stroke-width="1"/></svg>');
}
}
/* Share popup */
.share-popup {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: #fefef4;
padding: 1rem;
margin-bottom: 0.5rem;
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.1));
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
}
.share-popup.active {
opacity: 1;
pointer-events: all;
}
.share-popup::before {
content: '';
position: absolute;
inset: -1px;
background: #fefef4;
z-index: -1;
clip-path: polygon(
0% 5%, 5% 0%, 95% 0%, 100% 5%,
100% 85%, 90% 90%, 50% 100%, 10% 90%, 0% 85%
);
}
.share-options {
display: flex;
gap: 0.5rem;
}
.share-option {
padding: 0.5rem;
background: none;
border: none;
cursor: pointer;
font-size: 1.2rem;
transition: transform 0.2s ease;
}
.share-option:hover {
transform: scale(1.2) rotate(5deg);
}
</style>
</head>
<body>
<main>
<h1>Content Card - Handcrafted Paper Theme</h1>
<div class="content-grid">
<!-- Article Card -->
<div class="paper-card" data-id="1">
<div class="paper-texture"></div>
<div class="bookmark-ribbon" onclick="toggleBookmark(event, this)"></div>
<div class="coffee-stain"></div>
<div class="card-preview">
<div class="card-image">
<img src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 200'><rect fill='%23e8dcc6' width='400' height='200'/><text x='50%' y='50%' text-anchor='middle' dy='.3em' fill='%234a3f36' font-family='Patrick Hand' font-size='24'>Mountain Sketch</text><path d='M50,150 L150,50 L250,150 M200,100 L300,150' stroke='%234a3f36' fill='none' stroke-width='2'/><circle cx='320' cy='40' r='20' fill='none' stroke='%234a3f36' stroke-width='1.5'/></svg>" alt="Mountain landscape">
<div class="sketch-overlay"></div>
</div>
<h3 class="card-title">The Art of Mountain Sketching</h3>
<p class="card-description">Exploring the timeless techniques of capturing mountain landscapes with pencil and paper...</p>
</div>
<div class="metadata">
<span>📅 March 15, 2024</span>
<span>✏️ 5 min read</span>
<span>👁️ 1.2k views</span>
</div>
<div class="action-buttons">
<button class="paper-button primary" onclick="openModal(1)">
Read More
</button>
<button class="paper-button secondary share-button" onclick="toggleShare(event, this)">
Share ✈️
<svg class="paper-airplane" viewBox="0 0 20 20">
<path d="M2,2 L18,10 L2,18 L5,10 Z" fill="#e65100"/>
</svg>
<div class="share-popup">
<div class="share-options">
<button class="share-option" onclick="shareVia('twitter')">🐦</button>
<button class="share-option" onclick="shareVia('facebook')">📘</button>
<button class="share-option" onclick="shareVia('email')">📧</button>
<button class="share-option" onclick="shareVia('copy')">📋</button>
</div>
</div>
</button>
</div>
<div class="pencil-sketch sketch-1"></div>
</div>
<!-- Recipe Card -->
<div class="paper-card" data-id="2">
<div class="paper-texture"></div>
<div class="bookmark-ribbon" onclick="toggleBookmark(event, this)"></div>
<div class="card-preview">
<div class="card-image">
<img src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 200'><rect fill='%23f5e6d3' width='400' height='200'/><text x='50%' y='30%' text-anchor='middle' dy='.3em' fill='%234a3f36' font-family='Patrick Hand' font-size='24'>Grandma's Recipe</text><circle cx='200' cy='120' r='40' fill='none' stroke='%234a3f36' stroke-width='2'/><path d='M160,120 Q200,80 240,120' fill='none' stroke='%234a3f36' stroke-width='1.5'/><circle cx='180' cy='110' r='3' fill='%234a3f36'/><circle cx='220' cy='110' r='3' fill='%234a3f36'/></svg>" alt="Recipe illustration">
<div class="sketch-overlay"></div>
</div>
<h3 class="card-title">Handwritten Apple Pie Recipe</h3>
<p class="card-description">A treasured family recipe passed down through generations, written on aged paper...</p>
</div>
<div class="metadata">
<span>🥧 Dessert</span>
<span>⏱️ 2 hours</span>
<span>⭐ 4.9 rating</span>
</div>
<div class="action-buttons">
<button class="paper-button primary" onclick="openModal(2)">
View Recipe
</button>
<button class="paper-button secondary share-button" onclick="toggleShare(event, this)">
Share ✈️
<svg class="paper-airplane" viewBox="0 0 20 20">
<path d="M2,2 L18,10 L2,18 L5,10 Z" fill="#e65100"/>
</svg>
<div class="share-popup">
<div class="share-options">
<button class="share-option" onclick="shareVia('twitter')">🐦</button>
<button class="share-option" onclick="shareVia('facebook')">📘</button>
<button class="share-option" onclick="shareVia('email')">📧</button>
<button class="share-option" onclick="shareVia('copy')">📋</button>
</div>
</div>
</button>
</div>
<div class="pencil-sketch sketch-2"></div>
</div>
<!-- Journal Entry Card -->
<div class="paper-card" data-id="3">
<div class="paper-texture"></div>
<div class="bookmark-ribbon active" onclick="toggleBookmark(event, this)"></div>
<div class="card-preview">
<div class="card-image">
<img src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 200'><rect fill='%23ede4d3' width='400' height='200'/><text x='50%' y='30%' text-anchor='middle' dy='.3em' fill='%234a3f36' font-family='Patrick Hand' font-size='20'>Travel Journal</text><path d='M100,100 Q150,80 200,100 T300,100' stroke='%234a3f36' fill='none' stroke-width='1' stroke-dasharray='2,3'/><path d='M150,130 L170,110 L190,120 L210,105 L230,115 L250,100' stroke='%234a3f36' fill='none' stroke-width='1.5'/></svg>" alt="Journal sketch">
<div class="sketch-overlay"></div>
</div>
<h3 class="card-title">Adventures in Tuscany</h3>
<p class="card-description">Hand-drawn maps and stories from a summer journey through Italian countryside...</p>
</div>
<div class="metadata">
<span>📍 Travel</span>
<span>📖 8 pages</span>
<span>💭 32 comments</span>
</div>
<div class="action-buttons">
<button class="paper-button primary" onclick="openModal(3)">
Open Journal
</button>
<button class="paper-button secondary share-button" onclick="toggleShare(event, this)">
Share ✈️
<svg class="paper-airplane" viewBox="0 0 20 20">
<path d="M2,2 L18,10 L2,18 L5,10 Z" fill="#e65100"/>
</svg>
<div class="share-popup">
<div class="share-options">
<button class="share-option" onclick="shareVia('twitter')">🐦</button>
<button class="share-option" onclick="shareVia('facebook')">📘</button>
<button class="share-option" onclick="shareVia('email')">📧</button>
<button class="share-option" onclick="shareVia('copy')">📋</button>
</div>
</div>
</button>
</div>
</div>
</div>
</main>
<!-- Modal Overlay -->
<div class="modal-overlay" onclick="closeModal(event)">
<div class="paper-modal" onclick="event.stopPropagation()">
<div class="fold-lines"></div>
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title">Content Title</h2>
<button class="close-button" onclick="closeModal()">&times;</button>
</div>
<div class="modal-body">
<!-- Content will be dynamically inserted -->
</div>
</div>
</div>
</div>
<script>
// Content data
const contentData = {
1: {
title: "The Art of Mountain Sketching",
content: `
<p>There's something magical about sitting on a mountainside with nothing but a sketchbook and pencil. The rough texture of handmade paper beneath your fingers connects you to centuries of artists who've attempted to capture nature's grandeur.</p>
<p>I learned this technique from an old artist in the Alps, who showed me how to use quick, confident strokes to suggest the massive scale of mountain peaks. "Don't try to draw every rock," he said, his weathered hands moving the pencil with practiced ease. "Let the paper breathe."</p>
<p>The key is in the observation. Watch how shadows play across the ridges at different times of day. Notice how atmospheric perspective makes distant peaks appear lighter, almost ghostlike. These subtleties, captured in graphite on paper, can convey more emotion than any photograph.</p>
<p>My favorite papers for mountain sketching are those with a bit of tooth - rough enough to catch the graphite and create texture, but smooth enough for fine details. I often carry several weights, switching between them as the drawing develops.</p>
<p>Remember, the goal isn't perfection. It's about capturing a moment, a feeling, the essence of standing small before nature's monuments. Let your lines be loose, your shading suggestive. The best mountain sketches feel alive, as if the wind might blow through them at any moment.</p>
`
},
2: {
title: "Grandma's Handwritten Apple Pie Recipe",
content: `
<p><em>Found tucked between the pages of her cookbook, written in fountain pen on paper now yellowed with age...</em></p>
<p><strong>For the Crust (makes enough for top and bottom):</strong><br>
2½ cups flour<br>
1 tsp salt<br>
1 cup cold butter (Grandma's note: "must be COLD!")<br>
¼ to ½ cup ice water</p>
<p><strong>For the Filling:</strong><br>
6-8 tart apples (she preferred Granny Smith)<br>
¾ cup sugar (adjust to taste)<br>
2 tbsp flour<br>
1 tsp cinnamon<br>
¼ tsp nutmeg<br>
Pinch of salt<br>
2 tbsp butter</p>
<p><em>Her handwritten notes in the margin:</em> "The secret is in the apples - they should make you pucker just a little when raw. And always, always use real butter. None of that margarine nonsense."</p>
<p><strong>Instructions:</strong><br>
Mix flour and salt. Cut in cold butter until mixture resembles coarse crumbs. Add ice water gradually until dough comes together. Divide in half, wrap, and chill for at least an hour.</p>
<p>Peel and slice apples thin. Toss with sugar, flour, and spices. Roll out bottom crust, fill with apples, dot with butter. Cover with top crust, seal edges, cut vents.</p>
<p>Bake at 425°F for 15 minutes, then reduce to 350°F for 35-45 minutes until golden brown. <em>(Another note: "If the edges brown too quick, cover with foil")</em></p>
<p><em>At the bottom, in shaky handwriting:</em> "Made this for your grandfather every Sunday. Now it's your turn to carry on the tradition. All my love, Grandma"</p>
`
},
3: {
title: "Adventures in Tuscany - Travel Journal",
content: `
<p><strong>Day 1 - Arrival in Florence</strong><br>
<em>Sketched from the Piazzale Michelangelo at sunset</em></p>
<p>The paper of this journal already feels different here - maybe it's the Tuscan air, or maybe it's just my imagination. The city spreads below like a Renaissance painting come to life. Terra cotta roofs catch the golden hour light, and I try to capture it with quick pencil strokes.</p>
<p><strong>Day 3 - The Hills of Chianti</strong><br>
<em>Wine stains on this page are intentional... mostly</em></p>
<p>Spent the morning sketching vineyards. The way the vines create these perfect lines across the hillsides - it's like nature's own ruled paper. Met an old vintner who laughed at my attempts to draw his ancient olive trees. "You cannot draw age," he said, "you must feel it." I think I understand.</p>
<p><strong>Day 5 - Siena's Secret Gardens</strong><br>
<em>Pressed flowers between these pages</em></p>
<p>Found a hidden garden behind the cathedral. The kind of place that makes you want to fill every page with drawings. Stone benches worn smooth by centuries, fountains singing softly, cats lounging in patches of sun. My sketches can't capture the smell of jasmine or the sound of church bells, but they try.</p>
<p><strong>Day 8 - The Coast at Cinque Terre</strong><br>
<em>Salt spray has warped these pages slightly</em></p>
<p>Different paper would have been better for the coast - this handmade stock doesn't love the humidity. But there's something perfect about the way the moisture makes my ink lines bleed slightly, like the boundaries between sea and sky in the morning mist.</p>
<p><strong>Last Day - Reflections</strong><br>
This journal is fuller than just sketches and words. It holds pressed flowers, wine stains, smudges of local soil, even a few tears of joy. The paper has absorbed this journey, becoming part of the story itself. That's the magic of keeping a handwritten travel journal - it becomes an artifact of the adventure, not just a record of it.</p>
`
}
};
// Toggle bookmark
function toggleBookmark(event, element) {
event.stopPropagation();
element.classList.toggle('active');
const isActive = element.classList.contains('active');
const cardTitle = element.closest('.paper-card').querySelector('.card-title').textContent;
if (isActive) {
showNotification(`"${cardTitle}" added to bookmarks`);
} else {
showNotification(`"${cardTitle}" removed from bookmarks`);
}
}
// Open modal
function openModal(contentId) {
const modal = document.querySelector('.modal-overlay');
const modalTitle = modal.querySelector('.modal-title');
const modalBody = modal.querySelector('.modal-body');
const content = contentData[contentId];
modalTitle.textContent = content.title;
modalBody.innerHTML = content.content;
modal.classList.add('active');
document.body.style.overflow = 'hidden';
}
// Close modal
function closeModal(event) {
if (event && event.target !== event.currentTarget) return;
const modal = document.querySelector('.modal-overlay');
modal.classList.remove('active');
document.body.style.overflow = '';
}
// Toggle share popup
function toggleShare(event, button) {
event.stopPropagation();
// Close all other share popups
document.querySelectorAll('.share-popup').forEach(popup => {
if (popup !== button.querySelector('.share-popup')) {
popup.classList.remove('active');
}
});
const popup = button.querySelector('.share-popup');
popup.classList.toggle('active');
}
// Share functionality
function shareVia(platform) {
event.stopPropagation();
const card = event.target.closest('.paper-card');
const title = card.querySelector('.card-title').textContent;
const shareButton = card.querySelector('.share-button');
const airplane = shareButton.querySelector('.paper-airplane');
// Close popup
const popup = shareButton.querySelector('.share-popup');
popup.classList.remove('active');
// Animate paper airplane
airplane.classList.add('flying');
setTimeout(() => {
airplane.classList.remove('flying');
}, 1500);
// Show notification
const messages = {
twitter: `Shared "${title}" on Twitter`,
facebook: `Shared "${title}" on Facebook`,
email: `Email composed for "${title}"`,
copy: `Link copied for "${title}"`
};
showNotification(messages[platform]);
}
// Show notification
function showNotification(message) {
const notification = document.createElement('div');
notification.className = 'notification';
notification.textContent = message;
notification.style.cssText = `
position: fixed;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
background: #fefef4;
padding: 1rem 2rem;
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
z-index: 2000;
font-family: 'Patrick Hand', cursive;
color: #4a3f36;
clip-path: polygon(
0% 5%, 5% 0%, 95% 0%, 100% 5%,
100% 95%, 95% 100%, 5% 100%, 0% 95%
);
animation: slide-up 0.3s ease-out;
`;
// Add animation keyframes if not already present
if (!document.querySelector('#notification-styles')) {
const style = document.createElement('style');
style.id = 'notification-styles';
style.textContent = `
@keyframes slide-up {
from {
opacity: 0;
transform: translateX(-50%) translateY(20px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
}
`;
document.head.appendChild(style);
}
document.body.appendChild(notification);
setTimeout(() => {
notification.style.animation = 'slide-up 0.3s ease-out reverse';
setTimeout(() => notification.remove(), 300);
}, 2000);
}
// Close share popups when clicking outside
document.addEventListener('click', () => {
document.querySelectorAll('.share-popup.active').forEach(popup => {
popup.classList.remove('active');
});
});
// Add hover effect to cards for subtle animation
document.querySelectorAll('.paper-card').forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = `translateY(-4px) rotate(${Math.random() * 2 - 1}deg)`;
});
card.addEventListener('mouseleave', function() {
this.style.transform = '';
});
});
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeModal();
document.querySelectorAll('.share-popup.active').forEach(popup => {
popup.classList.remove('active');
});
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,853 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Digital Minimalism Form Wizard</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary: #000000;
--secondary: #666666;
--tertiary: #999999;
--background: #ffffff;
--surface: #fafafa;
--accent: #0066ff;
--error: #ff3333;
--success: #00cc88;
--border: #e5e5e5;
--shadow: rgba(0, 0, 0, 0.05);
--transition: 300ms cubic-bezier(0.4, 0, 0.2, 1);
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background-color: var(--background);
color: var(--primary);
line-height: 1.6;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
}
main {
width: 100%;
max-width: 800px;
}
h1 {
font-size: 1.5rem;
font-weight: 300;
margin-bottom: 3rem;
text-align: center;
letter-spacing: -0.02em;
}
.hybrid-component {
background: var(--surface);
border: 1px solid var(--border);
padding: 3rem;
position: relative;
}
/* Progress Line - Minimal */
.progress-line {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 2px;
background: var(--border);
overflow: hidden;
}
.progress-fill {
height: 100%;
background: var(--accent);
width: 0%;
transition: width var(--transition);
}
/* Step Indicators - Geometric Dots */
.step-indicators {
display: flex;
justify-content: space-between;
margin-bottom: 4rem;
position: relative;
}
.step-indicator {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
z-index: 2;
}
.step-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--background);
border: 2px solid var(--border);
transition: all var(--transition);
margin-bottom: 0.75rem;
}
.step-indicator.active .step-dot {
background: var(--accent);
border-color: var(--accent);
transform: scale(1.2);
}
.step-indicator.completed .step-dot {
background: var(--success);
border-color: var(--success);
}
.step-label {
font-size: 0.75rem;
color: var(--tertiary);
text-transform: uppercase;
letter-spacing: 0.05em;
transition: color var(--transition);
}
.step-indicator.active .step-label,
.step-indicator.completed .step-label {
color: var(--primary);
}
/* Step Connection Line */
.step-connection {
position: absolute;
top: 6px;
left: 0;
right: 0;
height: 1px;
background: var(--border);
z-index: 1;
}
/* Form Steps */
.form-steps {
min-height: 300px;
position: relative;
}
.form-step {
display: none;
animation: fadeIn var(--transition) ease-out;
}
.form-step.active {
display: block;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Form Groups */
.form-group {
margin-bottom: 2rem;
}
.form-label {
display: block;
font-size: 0.875rem;
color: var(--secondary);
margin-bottom: 0.5rem;
font-weight: 500;
}
.form-input {
width: 100%;
padding: 0.75rem 0;
font-size: 1rem;
border: none;
border-bottom: 1px solid var(--border);
background: transparent;
transition: border-color var(--transition);
font-family: inherit;
}
.form-input:focus {
outline: none;
border-color: var(--accent);
}
.form-input.error {
border-color: var(--error);
}
/* Validation Messages */
.validation-message {
font-size: 0.75rem;
margin-top: 0.25rem;
height: 1rem;
color: var(--error);
opacity: 0;
transform: translateY(-5px);
transition: all var(--transition);
}
.validation-message.show {
opacity: 1;
transform: translateY(0);
}
/* Radio Groups */
.radio-group {
display: flex;
gap: 2rem;
margin-top: 1rem;
}
.radio-option {
display: flex;
align-items: center;
cursor: pointer;
}
.radio-input {
width: 20px;
height: 20px;
border: 2px solid var(--border);
border-radius: 50%;
margin-right: 0.5rem;
position: relative;
transition: border-color var(--transition);
}
.radio-option input[type="radio"] {
display: none;
}
.radio-option input[type="radio"]:checked + .radio-input {
border-color: var(--accent);
}
.radio-option input[type="radio"]:checked + .radio-input::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--accent);
}
/* Navigation */
.form-navigation {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 3rem;
padding-top: 2rem;
border-top: 1px solid var(--border);
}
.nav-button {
background: none;
border: 1px solid var(--border);
padding: 0.75rem 2rem;
font-size: 0.875rem;
cursor: pointer;
transition: all var(--transition);
font-family: inherit;
display: flex;
align-items: center;
gap: 0.5rem;
}
.nav-button:hover {
border-color: var(--primary);
background: var(--primary);
color: var(--background);
}
.nav-button.primary {
background: var(--primary);
color: var(--background);
border-color: var(--primary);
}
.nav-button.primary:hover {
background: var(--accent);
border-color: var(--accent);
}
.nav-button:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.nav-button:disabled:hover {
background: none;
color: var(--primary);
border-color: var(--border);
}
/* Arrow Icons */
.arrow {
width: 16px;
height: 16px;
position: relative;
}
.arrow::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 8px;
height: 8px;
border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: translate(-50%, -50%) rotate(-45deg);
}
.arrow.left::before {
transform: translate(-50%, -50%) rotate(135deg);
}
/* Save State Indicator */
.save-state {
position: absolute;
top: 1rem;
right: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.75rem;
color: var(--tertiary);
opacity: 0;
transition: opacity var(--transition);
}
.save-state.show {
opacity: 1;
}
.save-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--success);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 0.3;
}
50% {
opacity: 1;
}
}
/* Summary Step */
.summary-section {
margin-bottom: 2rem;
}
.summary-label {
font-size: 0.75rem;
color: var(--tertiary);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 0.25rem;
}
.summary-value {
font-size: 1rem;
color: var(--primary);
}
/* Success State */
.success-message {
text-align: center;
padding: 3rem;
animation: fadeIn var(--transition) ease-out;
}
.success-icon {
width: 48px;
height: 48px;
margin: 0 auto 1.5rem;
position: relative;
}
.success-icon::before {
content: '';
position: absolute;
top: 50%;
left: 25%;
width: 10px;
height: 16px;
border-right: 2px solid var(--success);
border-bottom: 2px solid var(--success);
transform: translateY(-60%) rotate(45deg);
}
.success-icon::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 2px solid var(--success);
border-radius: 50%;
}
/* Responsive */
@media (max-width: 640px) {
.hybrid-component {
padding: 2rem 1.5rem;
}
.step-label {
font-size: 0.625rem;
}
.nav-button {
padding: 0.625rem 1.5rem;
font-size: 0.75rem;
}
}
</style>
</head>
<body>
<main>
<h1>Form Wizard - Digital Minimalism Theme</h1>
<div class="hybrid-component">
<!-- Progress Line -->
<div class="progress-line">
<div class="progress-fill" id="progressFill"></div>
</div>
<!-- Save State Indicator -->
<div class="save-state" id="saveState">
<div class="save-indicator"></div>
<span>Auto-saved</span>
</div>
<!-- Step Indicators -->
<div class="step-indicators">
<div class="step-connection"></div>
<div class="step-indicator active" data-step="1">
<div class="step-dot"></div>
<span class="step-label">Personal</span>
</div>
<div class="step-indicator" data-step="2">
<div class="step-dot"></div>
<span class="step-label">Account</span>
</div>
<div class="step-indicator" data-step="3">
<div class="step-dot"></div>
<span class="step-label">Preferences</span>
</div>
<div class="step-indicator" data-step="4">
<div class="step-dot"></div>
<span class="step-label">Review</span>
</div>
</div>
<!-- Form Steps -->
<div class="form-steps">
<!-- Step 1: Personal Information -->
<div class="form-step active" data-step="1">
<div class="form-group">
<label class="form-label" for="firstName">First Name</label>
<input type="text" class="form-input" id="firstName" required>
<div class="validation-message" id="firstNameError">Please enter your first name</div>
</div>
<div class="form-group">
<label class="form-label" for="lastName">Last Name</label>
<input type="text" class="form-input" id="lastName" required>
<div class="validation-message" id="lastNameError">Please enter your last name</div>
</div>
<div class="form-group">
<label class="form-label" for="email">Email Address</label>
<input type="email" class="form-input" id="email" required>
<div class="validation-message" id="emailError">Please enter a valid email address</div>
</div>
</div>
<!-- Step 2: Account Setup -->
<div class="form-step" data-step="2">
<div class="form-group">
<label class="form-label" for="username">Username</label>
<input type="text" class="form-input" id="username" required>
<div class="validation-message" id="usernameError">Username must be at least 3 characters</div>
</div>
<div class="form-group">
<label class="form-label" for="password">Password</label>
<input type="password" class="form-input" id="password" required>
<div class="validation-message" id="passwordError">Password must be at least 8 characters</div>
</div>
<div class="form-group">
<label class="form-label" for="confirmPassword">Confirm Password</label>
<input type="password" class="form-input" id="confirmPassword" required>
<div class="validation-message" id="confirmPasswordError">Passwords do not match</div>
</div>
</div>
<!-- Step 3: Preferences -->
<div class="form-step" data-step="3">
<div class="form-group">
<label class="form-label">Notification Frequency</label>
<div class="radio-group">
<label class="radio-option">
<input type="radio" name="notifications" value="daily" checked>
<div class="radio-input"></div>
<span>Daily</span>
</label>
<label class="radio-option">
<input type="radio" name="notifications" value="weekly">
<div class="radio-input"></div>
<span>Weekly</span>
</label>
<label class="radio-option">
<input type="radio" name="notifications" value="never">
<div class="radio-input"></div>
<span>Never</span>
</label>
</div>
</div>
<div class="form-group">
<label class="form-label">Theme Preference</label>
<div class="radio-group">
<label class="radio-option">
<input type="radio" name="theme" value="light" checked>
<div class="radio-input"></div>
<span>Light</span>
</label>
<label class="radio-option">
<input type="radio" name="theme" value="dark">
<div class="radio-input"></div>
<span>Dark</span>
</label>
<label class="radio-option">
<input type="radio" name="theme" value="auto">
<div class="radio-input"></div>
<span>Auto</span>
</label>
</div>
</div>
</div>
<!-- Step 4: Review -->
<div class="form-step" data-step="4">
<div class="summary-section">
<div class="summary-label">Personal Information</div>
<div class="summary-value" id="summaryName">-</div>
<div class="summary-value" id="summaryEmail">-</div>
</div>
<div class="summary-section">
<div class="summary-label">Account Details</div>
<div class="summary-value" id="summaryUsername">-</div>
</div>
<div class="summary-section">
<div class="summary-label">Preferences</div>
<div class="summary-value" id="summaryNotifications">-</div>
<div class="summary-value" id="summaryTheme">-</div>
</div>
</div>
<!-- Success State -->
<div class="form-step" data-step="success">
<div class="success-message">
<div class="success-icon"></div>
<h2 style="font-weight: 300; margin-bottom: 0.5rem;">Account Created</h2>
<p style="color: var(--secondary);">Welcome to your minimal digital experience.</p>
</div>
</div>
</div>
<!-- Navigation -->
<div class="form-navigation">
<button class="nav-button" id="prevBtn" disabled>
<span class="arrow left"></span>
Previous
</button>
<button class="nav-button primary" id="nextBtn">
Next
<span class="arrow"></span>
</button>
</div>
</div>
</main>
<script>
// Form Wizard State
const formWizard = {
currentStep: 1,
totalSteps: 4,
formData: {},
saveTimeout: null
};
// DOM Elements
const progressFill = document.getElementById('progressFill');
const saveState = document.getElementById('saveState');
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
// Initialize form data from localStorage
function initializeFormData() {
const savedData = localStorage.getItem('formWizardData');
if (savedData) {
formWizard.formData = JSON.parse(savedData);
restoreFormData();
}
}
// Save form data
function saveFormData() {
// Collect current step data
collectStepData();
// Save to localStorage
localStorage.setItem('formWizardData', JSON.stringify(formWizard.formData));
// Show save indicator
saveState.classList.add('show');
clearTimeout(formWizard.saveTimeout);
formWizard.saveTimeout = setTimeout(() => {
saveState.classList.remove('show');
}, 2000);
}
// Restore form data
function restoreFormData() {
// Restore all form fields
Object.keys(formWizard.formData).forEach(key => {
const element = document.getElementById(key);
if (element) {
if (element.type === 'radio') {
const radio = document.querySelector(`input[name="${element.name}"][value="${formWizard.formData[key]}"]`);
if (radio) radio.checked = true;
} else {
element.value = formWizard.formData[key];
}
}
});
}
// Collect data from current step
function collectStepData() {
const currentStepElement = document.querySelector(`.form-step[data-step="${formWizard.currentStep}"]`);
if (!currentStepElement) return;
// Text inputs
currentStepElement.querySelectorAll('.form-input').forEach(input => {
if (input.value) {
formWizard.formData[input.id] = input.value;
}
});
// Radio inputs
currentStepElement.querySelectorAll('input[type="radio"]:checked').forEach(radio => {
formWizard.formData[radio.name] = radio.value;
});
}
// Validate current step
function validateStep() {
const currentStepElement = document.querySelector(`.form-step[data-step="${formWizard.currentStep}"]`);
if (!currentStepElement) return true;
let isValid = true;
// Validate text inputs
currentStepElement.querySelectorAll('.form-input[required]').forEach(input => {
const errorElement = document.getElementById(input.id + 'Error');
if (!input.value.trim()) {
input.classList.add('error');
if (errorElement) errorElement.classList.add('show');
isValid = false;
} else if (input.type === 'email' && !isValidEmail(input.value)) {
input.classList.add('error');
if (errorElement) errorElement.classList.add('show');
isValid = false;
} else if (input.id === 'username' && input.value.length < 3) {
input.classList.add('error');
if (errorElement) errorElement.classList.add('show');
isValid = false;
} else if (input.id === 'password' && input.value.length < 8) {
input.classList.add('error');
if (errorElement) errorElement.classList.add('show');
isValid = false;
} else if (input.id === 'confirmPassword') {
const password = document.getElementById('password').value;
if (input.value !== password) {
input.classList.add('error');
if (errorElement) errorElement.classList.add('show');
isValid = false;
} else {
input.classList.remove('error');
if (errorElement) errorElement.classList.remove('show');
}
} else {
input.classList.remove('error');
if (errorElement) errorElement.classList.remove('show');
}
});
return isValid;
}
// Email validation
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
// Update progress
function updateProgress() {
const progress = ((formWizard.currentStep - 1) / formWizard.totalSteps) * 100;
progressFill.style.width = progress + '%';
}
// Update step indicators
function updateStepIndicators() {
document.querySelectorAll('.step-indicator').forEach((indicator, index) => {
const stepNum = index + 1;
indicator.classList.remove('active', 'completed');
if (stepNum < formWizard.currentStep) {
indicator.classList.add('completed');
} else if (stepNum === formWizard.currentStep) {
indicator.classList.add('active');
}
});
}
// Show step
function showStep(stepNumber) {
// Hide all steps
document.querySelectorAll('.form-step').forEach(step => {
step.classList.remove('active');
});
// Show current step
const currentStepElement = document.querySelector(`.form-step[data-step="${stepNumber}"]`);
if (currentStepElement) {
currentStepElement.classList.add('active');
}
// Update navigation buttons
prevBtn.disabled = stepNumber === 1;
if (stepNumber === formWizard.totalSteps) {
nextBtn.textContent = 'Submit';
nextBtn.innerHTML = 'Submit <span class="arrow"></span>';
} else {
nextBtn.textContent = 'Next';
nextBtn.innerHTML = 'Next <span class="arrow"></span>';
}
// Update progress and indicators
updateProgress();
updateStepIndicators();
// Update summary if on review step
if (stepNumber === 4) {
updateSummary();
}
}
// Update summary
function updateSummary() {
document.getElementById('summaryName').textContent =
`${formWizard.formData.firstName || ''} ${formWizard.formData.lastName || ''}`;
document.getElementById('summaryEmail').textContent =
formWizard.formData.email || '-';
document.getElementById('summaryUsername').textContent =
`Username: ${formWizard.formData.username || '-'}`;
document.getElementById('summaryNotifications').textContent =
`Notifications: ${formWizard.formData.notifications || 'daily'}`;
document.getElementById('summaryTheme').textContent =
`Theme: ${formWizard.formData.theme || 'light'}`;
}
// Next step
function nextStep() {
if (formWizard.currentStep === formWizard.totalSteps) {
// Submit form
if (validateStep()) {
collectStepData();
saveFormData();
showStep('success');
progressFill.style.width = '100%';
// Clear saved data after successful submission
localStorage.removeItem('formWizardData');
// Hide navigation
document.querySelector('.form-navigation').style.display = 'none';
}
} else {
if (validateStep()) {
collectStepData();
saveFormData();
formWizard.currentStep++;
showStep(formWizard.currentStep);
}
}
}
// Previous step
function prevStep() {
if (formWizard.currentStep > 1) {
formWizard.currentStep--;
showStep(formWizard.currentStep);
}
}
// Event Listeners
nextBtn.addEventListener('click', nextStep);
prevBtn.addEventListener('click', prevStep);
// Auto-save on input change
document.querySelectorAll('.form-input, input[type="radio"]').forEach(input => {
input.addEventListener('change', () => {
saveFormData();
});
});
// Clear validation on input
document.querySelectorAll('.form-input').forEach(input => {
input.addEventListener('input', () => {
const errorElement = document.getElementById(input.id + 'Error');
if (input.value.trim()) {
input.classList.remove('error');
if (errorElement) errorElement.classList.remove('show');
}
});
});
// Initialize
initializeFormData();
showStep(formWizard.currentStep);
</script>
</body>
</html>

View File

@ -0,0 +1,691 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Playful Animation Media Player</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary-pink: #FF6B9D;
--primary-yellow: #FFC857;
--primary-blue: #4ECDC4;
--primary-purple: #A8E6CF;
--primary-orange: #FF6F61;
--bg-color: #FAF3F0;
--text-dark: #2D3436;
--white: #FFFFFF;
--shadow: rgba(0, 0, 0, 0.1);
}
@keyframes bounce {
0%, 100% { transform: translateY(0) scale(1); }
50% { transform: translateY(-10px) scale(1.05); }
}
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(-5deg); }
75% { transform: rotate(5deg); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
@keyframes dance {
0%, 100% { transform: translateX(0) rotate(0deg); }
25% { transform: translateX(-5px) rotate(-2deg); }
75% { transform: translateX(5px) rotate(2deg); }
}
@keyframes rainbow {
0% { filter: hue-rotate(0deg); }
100% { filter: hue-rotate(360deg); }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}
body {
font-family: 'Comic Sans MS', cursive, sans-serif;
background: var(--bg-color);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
overflow-x: hidden;
}
main {
width: 100%;
max-width: 800px;
}
h1 {
text-align: center;
color: var(--text-dark);
margin-bottom: 30px;
font-size: 2.5em;
animation: wiggle 2s ease-in-out infinite;
text-shadow: 3px 3px 0px var(--primary-pink);
}
.media-player {
background: var(--white);
border-radius: 30px;
box-shadow: 0 20px 40px var(--shadow);
overflow: hidden;
position: relative;
}
/* Visualizer Section */
.visualizer {
height: 200px;
background: linear-gradient(135deg, var(--primary-blue) 0%, var(--primary-purple) 100%);
position: relative;
overflow: hidden;
}
.wave {
position: absolute;
bottom: 0;
width: 100%;
height: 100%;
display: flex;
align-items: flex-end;
justify-content: space-around;
padding: 0 20px;
}
.wave-bar {
width: 6%;
background: var(--white);
border-radius: 10px 10px 0 0;
transition: height 0.2s ease;
animation: dance 1s ease-in-out infinite;
opacity: 0.8;
}
.wave-bar:nth-child(odd) {
animation-delay: 0.1s;
background: var(--primary-yellow);
}
.wave-bar:nth-child(even) {
animation-delay: 0.2s;
background: var(--primary-pink);
}
/* Current Song Display */
.current-song {
padding: 20px;
text-align: center;
background: var(--white);
position: relative;
}
.song-title {
font-size: 1.5em;
color: var(--text-dark);
margin-bottom: 5px;
animation: pulse 2s ease-in-out infinite;
}
.song-artist {
color: #7D8E95;
font-size: 1.1em;
}
/* Controls Section */
.controls {
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
background: var(--white);
}
.control-btn {
background: var(--primary-pink);
border: none;
color: var(--white);
width: 60px;
height: 60px;
border-radius: 50%;
font-size: 1.5em;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
box-shadow: 0 5px 15px rgba(255, 107, 157, 0.3);
}
.control-btn:hover {
animation: bounce 0.5s ease-in-out;
transform: scale(1.1);
box-shadow: 0 10px 25px rgba(255, 107, 157, 0.5);
}
.control-btn:active {
transform: scale(0.95);
}
.play-btn {
background: var(--primary-blue);
width: 80px;
height: 80px;
font-size: 2em;
box-shadow: 0 5px 15px rgba(78, 205, 196, 0.3);
}
.play-btn:hover {
box-shadow: 0 10px 25px rgba(78, 205, 196, 0.5);
}
/* Progress Bar */
.progress-container {
padding: 0 20px 20px;
background: var(--white);
}
.progress-bar {
width: 100%;
height: 20px;
background: #F0F0F0;
border-radius: 10px;
overflow: hidden;
position: relative;
cursor: pointer;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, var(--primary-pink) 0%, var(--primary-yellow) 50%, var(--primary-blue) 100%);
width: 35%;
border-radius: 10px;
position: relative;
transition: width 0.3s ease;
animation: rainbow 3s linear infinite;
}
.progress-handle {
position: absolute;
right: -10px;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 30px;
background: var(--white);
border: 4px solid var(--primary-pink);
border-radius: 50%;
cursor: grab;
box-shadow: 0 2px 10px var(--shadow);
animation: pulse 1s ease-in-out infinite;
}
/* Playlist Section */
.playlist-container {
max-height: 300px;
overflow-y: auto;
padding: 20px;
background: #F8F8F8;
}
.playlist-item {
background: var(--white);
padding: 15px;
margin-bottom: 10px;
border-radius: 15px;
display: flex;
align-items: center;
gap: 15px;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.playlist-item:hover {
transform: translateX(10px);
animation: dance 0.5s ease-in-out;
box-shadow: 0 5px 15px var(--shadow);
}
.playlist-item.active {
background: linear-gradient(135deg, var(--primary-pink) 0%, var(--primary-purple) 100%);
color: var(--white);
animation: dance 2s ease-in-out infinite;
}
.playlist-number {
width: 40px;
height: 40px;
background: var(--primary-yellow);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: var(--text-dark);
font-size: 1.2em;
}
.playlist-item.active .playlist-number {
background: var(--white);
animation: bounce 1s ease-in-out infinite;
}
/* Quality Selector */
.quality-selector {
padding: 20px;
background: var(--white);
display: flex;
gap: 15px;
justify-content: center;
flex-wrap: wrap;
}
.quality-bubble {
width: 60px;
height: 60px;
border-radius: 50%;
background: var(--primary-purple);
color: var(--text-dark);
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
font-size: 0.9em;
position: relative;
box-shadow: 0 5px 10px var(--shadow);
}
.quality-bubble:hover {
animation: float 1s ease-in-out;
transform: scale(1.2);
}
.quality-bubble.active {
background: var(--primary-orange);
color: var(--white);
animation: pulse 1s ease-in-out infinite;
transform: scale(1.3);
}
.quality-bubble.low { width: 50px; height: 50px; font-size: 0.8em; }
.quality-bubble.medium { width: 60px; height: 60px; }
.quality-bubble.high { width: 70px; height: 70px; font-size: 1em; }
.quality-bubble.ultra { width: 80px; height: 80px; font-size: 1.1em; }
/* Share Button */
.share-section {
padding: 20px;
background: var(--white);
text-align: center;
border-top: 2px dashed #E0E0E0;
}
.share-btn {
background: linear-gradient(135deg, var(--primary-orange) 0%, var(--primary-pink) 100%);
color: var(--white);
border: none;
padding: 15px 40px;
border-radius: 30px;
font-size: 1.2em;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
font-weight: bold;
box-shadow: 0 5px 15px rgba(255, 111, 97, 0.3);
}
.share-btn:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(255, 111, 97, 0.5);
animation: wiggle 0.5s ease-in-out;
}
/* Confetti */
.confetti {
position: fixed;
width: 10px;
height: 10px;
top: -10px;
animation: confetti-fall 3s linear forwards;
z-index: 1000;
}
@keyframes confetti-fall {
0% {
transform: translateY(0) rotate(0deg);
opacity: 1;
}
100% {
transform: translateY(100vh) rotate(720deg);
opacity: 0;
}
}
/* Responsive */
@media (max-width: 600px) {
h1 { font-size: 2em; }
.control-btn { width: 50px; height: 50px; font-size: 1.2em; }
.play-btn { width: 70px; height: 70px; font-size: 1.8em; }
.quality-bubble { width: 50px; height: 50px; font-size: 0.8em; }
.quality-bubble.low { width: 40px; height: 40px; font-size: 0.7em; }
.quality-bubble.medium { width: 50px; height: 50px; }
.quality-bubble.high { width: 60px; height: 60px; font-size: 0.9em; }
.quality-bubble.ultra { width: 70px; height: 70px; font-size: 1em; }
}
</style>
</head>
<body>
<main>
<h1>🎵 Bouncy Music Box 🎵</h1>
<div class="media-player">
<!-- Visualizer -->
<div class="visualizer">
<div class="wave" id="waveContainer">
<!-- Wave bars will be generated by JavaScript -->
</div>
</div>
<!-- Current Song Display -->
<div class="current-song">
<div class="song-title" id="songTitle">Happy Dance Time</div>
<div class="song-artist" id="songArtist">The Joyful Beats</div>
</div>
<!-- Progress Bar -->
<div class="progress-container">
<div class="progress-bar" id="progressBar">
<div class="progress-fill" id="progressFill">
<div class="progress-handle"></div>
</div>
</div>
</div>
<!-- Controls -->
<div class="controls">
<button class="control-btn" id="prevBtn">⏮️</button>
<button class="control-btn play-btn" id="playBtn">▶️</button>
<button class="control-btn" id="nextBtn">⏭️</button>
</div>
<!-- Quality Selector -->
<div class="quality-selector">
<div class="quality-bubble low" data-quality="low">128k</div>
<div class="quality-bubble medium" data-quality="medium">256k</div>
<div class="quality-bubble high active" data-quality="high">320k</div>
<div class="quality-bubble ultra" data-quality="ultra">FLAC</div>
</div>
<!-- Playlist -->
<div class="playlist-container">
<div class="playlist-item active" data-index="0">
<div class="playlist-number">1</div>
<div>
<div>Happy Dance Time</div>
<small>The Joyful Beats</small>
</div>
</div>
<div class="playlist-item" data-index="1">
<div class="playlist-number">2</div>
<div>
<div>Bouncy Castle Dreams</div>
<small>Rainbow Unicorns</small>
</div>
</div>
<div class="playlist-item" data-index="2">
<div class="playlist-number">3</div>
<div>
<div>Bubble Pop Symphony</div>
<small>Giggle Factory</small>
</div>
</div>
<div class="playlist-item" data-index="3">
<div class="playlist-number">4</div>
<div>
<div>Marshmallow Clouds</div>
<small>Sweet Melodies</small>
</div>
</div>
<div class="playlist-item" data-index="4">
<div class="playlist-number">5</div>
<div>
<div>Confetti Carnival</div>
<small>Party Pirates</small>
</div>
</div>
</div>
<!-- Share Section -->
<div class="share-section">
<button class="share-btn" id="shareBtn">🎉 Share the Joy! 🎉</button>
</div>
</div>
</main>
<script>
// Playlist data
const playlist = [
{ title: 'Happy Dance Time', artist: 'The Joyful Beats' },
{ title: 'Bouncy Castle Dreams', artist: 'Rainbow Unicorns' },
{ title: 'Bubble Pop Symphony', artist: 'Giggle Factory' },
{ title: 'Marshmallow Clouds', artist: 'Sweet Melodies' },
{ title: 'Confetti Carnival', artist: 'Party Pirates' }
];
let currentSongIndex = 0;
let isPlaying = false;
let progress = 35;
let animationFrame;
let currentQuality = 'high';
// Create wave bars
const waveContainer = document.getElementById('waveContainer');
for (let i = 0; i < 15; i++) {
const bar = document.createElement('div');
bar.className = 'wave-bar';
bar.style.height = '20%';
bar.style.animationDelay = `${i * 0.1}s`;
waveContainer.appendChild(bar);
}
// Visualizer animation
function animateVisualizer() {
const bars = document.querySelectorAll('.wave-bar');
bars.forEach((bar, index) => {
if (isPlaying) {
const height = Math.random() * 80 + 20;
bar.style.height = `${height}%`;
// More complex animations for higher quality
if (currentQuality === 'ultra') {
bar.style.transform = `scaleX(${1 + Math.random() * 0.2}) rotate(${Math.random() * 5 - 2.5}deg)`;
} else if (currentQuality === 'high') {
bar.style.transform = `scaleX(${1 + Math.random() * 0.1})`;
}
} else {
bar.style.height = '20%';
bar.style.transform = 'scaleX(1) rotate(0deg)';
}
});
animationFrame = requestAnimationFrame(animateVisualizer);
}
// Play/Pause functionality
const playBtn = document.getElementById('playBtn');
playBtn.addEventListener('click', () => {
isPlaying = !isPlaying;
playBtn.textContent = isPlaying ? '⏸️' : '▶️';
if (isPlaying) {
animateVisualizer();
simulateProgress();
// Make playlist item dance more when playing
document.querySelector('.playlist-item.active').style.animationDuration = '0.5s';
} else {
document.querySelector('.playlist-item.active').style.animationDuration = '2s';
}
});
// Progress simulation
function simulateProgress() {
if (isPlaying && progress < 100) {
progress += 0.1;
document.getElementById('progressFill').style.width = `${progress}%`;
requestAnimationFrame(simulateProgress);
}
}
// Progress bar click
document.getElementById('progressBar').addEventListener('click', (e) => {
const rect = e.currentTarget.getBoundingClientRect();
progress = ((e.clientX - rect.left) / rect.width) * 100;
document.getElementById('progressFill').style.width = `${progress}%`;
});
// Song navigation
function changeSong(index) {
// Update current song index
currentSongIndex = index;
if (currentSongIndex < 0) currentSongIndex = playlist.length - 1;
if (currentSongIndex >= playlist.length) currentSongIndex = 0;
// Update UI
document.getElementById('songTitle').textContent = playlist[currentSongIndex].title;
document.getElementById('songArtist').textContent = playlist[currentSongIndex].artist;
// Update playlist active state
document.querySelectorAll('.playlist-item').forEach((item, i) => {
item.classList.toggle('active', i === currentSongIndex);
});
// Reset progress
progress = 0;
document.getElementById('progressFill').style.width = '0%';
// Bounce effect on song change
const songDisplay = document.querySelector('.current-song');
songDisplay.style.animation = 'bounce 0.5s ease-in-out';
setTimeout(() => {
songDisplay.style.animation = '';
}, 500);
}
// Previous/Next buttons
document.getElementById('prevBtn').addEventListener('click', () => {
changeSong(currentSongIndex - 1);
});
document.getElementById('nextBtn').addEventListener('click', () => {
changeSong(currentSongIndex + 1);
});
// Playlist item clicks
document.querySelectorAll('.playlist-item').forEach((item, index) => {
item.addEventListener('click', () => {
changeSong(index);
});
});
// Quality selector
document.querySelectorAll('.quality-bubble').forEach(bubble => {
bubble.addEventListener('click', () => {
document.querySelectorAll('.quality-bubble').forEach(b => b.classList.remove('active'));
bubble.classList.add('active');
currentQuality = bubble.dataset.quality;
// Bounce all quality bubbles for fun
document.querySelectorAll('.quality-bubble').forEach(b => {
b.style.animation = 'bounce 0.5s ease-in-out';
setTimeout(() => {
b.style.animation = '';
}, 500);
});
// Update visualizer complexity based on quality
const bars = document.querySelectorAll('.wave-bar');
bars.forEach((bar, i) => {
if (currentQuality === 'ultra') {
bar.style.width = '5%';
} else if (currentQuality === 'high') {
bar.style.width = '6%';
} else if (currentQuality === 'medium') {
bar.style.width = '7%';
} else {
bar.style.width = '8%';
}
});
});
});
// Share button with confetti
document.getElementById('shareBtn').addEventListener('click', () => {
// Create confetti burst
for (let i = 0; i < 50; i++) {
const confetti = document.createElement('div');
confetti.className = 'confetti';
confetti.style.left = Math.random() * window.innerWidth + 'px';
confetti.style.backgroundColor = ['#FF6B9D', '#FFC857', '#4ECDC4', '#A8E6CF', '#FF6F61'][Math.floor(Math.random() * 5)];
confetti.style.animationDelay = Math.random() * 0.5 + 's';
confetti.style.animationDuration = (Math.random() * 2 + 2) + 's';
document.body.appendChild(confetti);
setTimeout(() => confetti.remove(), 4000);
}
// Bounce the share button
const btn = document.getElementById('shareBtn');
btn.style.animation = 'bounce 0.5s ease-in-out';
setTimeout(() => {
btn.style.animation = '';
}, 500);
// Show mock share message
const originalText = btn.textContent;
btn.textContent = '🎊 Shared! 🎊';
setTimeout(() => {
btn.textContent = originalText;
}, 2000);
});
// Start visualizer animation
animateVisualizer();
// Add some fun interactions
document.addEventListener('mousemove', (e) => {
if (isPlaying) {
const x = e.clientX / window.innerWidth;
const y = e.clientY / window.innerHeight;
// Subtle tilt effect on the player
const player = document.querySelector('.media-player');
const tiltX = (y - 0.5) * 5;
const tiltY = (x - 0.5) * -5;
player.style.transform = `perspective(1000px) rotateX(${tiltX}deg) rotateY(${tiltY}deg)`;
}
});
// Reset tilt on mouse leave
document.addEventListener('mouseleave', () => {
document.querySelector('.media-player').style.transform = '';
});
</script>
</body>
</html>