-
Notifications
You must be signed in to change notification settings - Fork 0
Archive old prototypes and implement Neobrutalist Valentine Protocol #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| <title>ISSUE NO. 001: THE VALENTINE PROTOCOL</title> | ||
|
|
||
| <!-- Tailwind CSS --> | ||
| <script src="https://cdn.tailwindcss.com"></script> | ||
|
|
||
| <!-- Google Fonts --> | ||
| <link rel="preconnect" href="https://fonts.googleapis.com"> | ||
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | ||
| <link href="https://fonts.googleapis.com/css2?family=Anton&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet"> | ||
|
|
||
| <!-- GSAP --> | ||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script> | ||
|
|
||
| <!-- Canvas Confetti --> | ||
| <script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.6.0/dist/confetti.browser.min.js"></script> | ||
|
|
||
| <!-- Custom Styles Link --> | ||
| <link rel="stylesheet" href="style.css"> | ||
|
|
||
| <script> | ||
| tailwind.config = { | ||
| theme: { | ||
| extend: { | ||
| colors: { | ||
| 'obsidian': '#000000', | ||
| 'stark-white': '#FFFFFF', | ||
| 'electric-pink': '#FF0055', | ||
| }, | ||
| fontFamily: { | ||
| 'header': ['Anton', 'sans-serif'], | ||
| 'mono': ['JetBrains Mono', 'monospace'], | ||
| } | ||
| } | ||
| } | ||
| } | ||
| </script> | ||
| </head> | ||
| <body class="bg-electric-pink min-h-screen overflow-hidden flex items-center justify-center cursor-crosshair"> | ||
|
|
||
| <!-- Background Grid --> | ||
| <div class="fixed inset-0 grid-background pointer-events-none z-0"></div> | ||
|
|
||
| <!-- Floating 3D Elements Container --> | ||
| <div id="floating-elements" class="fixed inset-0 pointer-events-none z-10 overflow-hidden"> | ||
| <!-- Elements will be added here via JS or simple CSS elements --> | ||
| <div class="floating-icon absolute top-10 left-10 text-4xl opacity-50">❤️</div> | ||
| <div class="floating-icon absolute bottom-20 right-20 text-4xl opacity-50">⚡</div> | ||
| <div class="floating-icon absolute top-1/2 left-10 text-4xl opacity-50">💾</div> | ||
| <div class="floating-icon absolute top-20 right-1/4 text-4xl opacity-50">🔒</div> | ||
| </div> | ||
|
|
||
| <!-- Main Container --> | ||
| <main class="relative z-20 w-full max-w-4xl p-4"> | ||
|
|
||
| <!-- Product Box --> | ||
| <div id="product-box" class="bg-stark-white border-4 border-obsidian shadow-[8px_8px_0px_#000] p-6 md:p-12 relative transform transition-transform duration-300"> | ||
|
|
||
| <!-- Technical Specs Header --> | ||
| <div class="flex justify-between items-start mb-8 font-mono text-sm md:text-base border-b-2 border-obsidian pb-4"> | ||
| <div class="flex flex-col"> | ||
| <span class="font-bold">ISSUE NO. 001</span> | ||
| <span>THE VALENTINE PROTOCOL</span> | ||
| </div> | ||
| <div class="text-right flex flex-col items-end"> | ||
| <div id="countdown" class="font-bold text-electric-pink">00:00:00</div> | ||
| <span class="text-xs">TIME REMAINING TO ACCEPT</span> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Main Content --> | ||
| <div class="text-center space-y-8"> | ||
| <h2 class="font-header text-2xl md:text-3xl tracking-wide text-obsidian/80"> | ||
| BRIAN x [HER NAME] // OFFICIAL COLLABORATION | ||
| </h2> | ||
|
|
||
| <h1 class="font-header text-6xl md:text-8xl leading-none text-obsidian transform hover:scale-105 transition-transform duration-300"> | ||
| WILL YOU BE<br>MY VALENTINE? | ||
| </h1> | ||
|
|
||
| <!-- Interaction Area --> | ||
| <div class="flex flex-col md:flex-row items-center justify-center gap-8 mt-12 relative h-32 md:h-40"> | ||
|
|
||
| <!-- YES Button --> | ||
| <button id="yes-btn" class="w-full md:w-3/5 bg-[#00FF00] hover:bg-[#00DD00] text-obsidian font-header text-4xl py-4 border-4 border-obsidian shadow-[4px_4px_0px_#000] active:translate-y-1 active:shadow-none transition-all duration-100 uppercase tracking-wider relative overflow-hidden group"> | ||
| <span class="relative z-10">YES [ACCEPT]</span> | ||
| <div class="absolute inset-0 bg-white/20 translate-y-full group-hover:translate-y-0 transition-transform duration-300"></div> | ||
| </button> | ||
|
|
||
| <!-- NO Button (The Unclickable) --> | ||
| <button id="no-btn" class="bg-stark-white text-obsidian font-mono font-bold text-xl py-4 px-8 border-4 border-obsidian shadow-[4px_4px_0px_#000] uppercase tracking-wider absolute md:static"> | ||
| NO | ||
| </button> | ||
|
|
||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Footer / Terminal --> | ||
| <div class="mt-12 border-t-2 border-obsidian pt-4"> | ||
| <div class="bg-obsidian text-[#00FF00] font-mono text-xs p-4 h-32 overflow-y-auto shadow-inner" id="terminal"> | ||
| <div>> Initializing Valentine Protocol v1.0...</div> | ||
| <div>> Target acquired: [HER NAME]</div> | ||
| <div>> Analysis: 100% Compatible</div> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Absolute decorative corner markers --> | ||
| <div class="absolute top-0 left-0 w-4 h-4 border-t-4 border-l-4 border-obsidian -mt-1 -ml-1"></div> | ||
| <div class="absolute top-0 right-0 w-4 h-4 border-t-4 border-r-4 border-obsidian -mt-1 -mr-1"></div> | ||
| <div class="absolute bottom-0 left-0 w-4 h-4 border-b-4 border-l-4 border-obsidian -mb-1 -ml-1"></div> | ||
| <div class="absolute bottom-0 right-0 w-4 h-4 border-b-4 border-r-4 border-obsidian -mb-1 -mr-1"></div> | ||
|
|
||
| </div> | ||
|
|
||
| <!-- Voucher Overlay (Hidden by default) --> | ||
| <div id="voucher-overlay" class="fixed inset-0 z-50 flex items-center justify-center bg-obsidian/90 hidden opacity-0 transition-opacity duration-500"> | ||
| <div class="bg-stark-white border-4 border-electric-pink p-8 max-w-2xl w-full mx-4 shadow-[16px_16px_0px_#FF0055] transform rotate-1 relative"> | ||
|
|
||
| <!-- StockX Style Tag --> | ||
| <div class="absolute -right-4 -top-4 bg-[#00FF00] text-obsidian font-bold font-mono text-xs px-2 py-1 border-2 border-obsidian shadow-[2px_2px_0px_#000] rotate-12"> | ||
| VERIFIED AUTHENTIC | ||
| </div> | ||
|
|
||
| <div class="border-b-4 border-dashed border-obsidian pb-6 mb-6 text-center"> | ||
| <h2 class="font-header text-6xl text-obsidian mb-2">CONFIRMED</h2> | ||
| <p class="font-mono text-sm text-gray-600">TRANSACTION ID: #L0V3-2024-FOREVER</p> | ||
| </div> | ||
|
|
||
| <div class="space-y-4 font-mono"> | ||
| <div class="flex justify-between border-b border-gray-300 pb-2"> | ||
| <span class="font-bold">ITEM:</span> | ||
| <span>VALENTINE'S DINNER DATE</span> | ||
| </div> | ||
| <div class="flex justify-between border-b border-gray-300 pb-2"> | ||
| <span class="font-bold">LOCATION:</span> | ||
| <span>THAT TEMPE RESTAURANT</span> | ||
| </div> | ||
| <div class="flex justify-between border-b border-gray-300 pb-2"> | ||
| <span class="font-bold">DATE:</span> | ||
| <span>FEB 14, 2024</span> | ||
| </div> | ||
| <div class="flex justify-between border-b border-gray-300 pb-2"> | ||
| <span class="font-bold">PRICE:</span> | ||
| <span>$0.00 (MY TREAT)</span> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div class="mt-8 text-center"> | ||
| <p class="font-header text-2xl text-electric-pink">SEE YOU THERE</p> | ||
| </div> | ||
|
|
||
| <!-- Barcode --> | ||
| <div class="mt-6 h-12 bg-obsidian w-full relative overflow-hidden"> | ||
| <div class="absolute inset-0 flex justify-between items-center px-2 text-white font-mono text-xs tracking-[0.5em]"> | ||
| ||| || ||| | |||| ||| | || || | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| </main> | ||
|
|
||
| <script src="script.js"></script> | ||
| </body> | ||
| </html> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,209 @@ | ||
| document.addEventListener('DOMContentLoaded', () => { | ||
| // --- Elements --- | ||
| const noBtn = document.getElementById('no-btn'); | ||
| const yesBtn = document.getElementById('yes-btn'); | ||
| const productBox = document.getElementById('product-box'); | ||
| const terminal = document.getElementById('terminal'); | ||
| const countdownEl = document.getElementById('countdown'); | ||
| const floatingElements = document.querySelectorAll('.floating-icon'); | ||
| const voucherOverlay = document.getElementById('voucher-overlay'); | ||
|
|
||
| // --- GSAP Entrance --- | ||
| gsap.from(productBox, { | ||
| duration: 1.5, | ||
| y: 100, | ||
| opacity: 0, | ||
| ease: "power4.out", | ||
| delay: 0.5 | ||
| }); | ||
|
|
||
| gsap.from("#product-box > *", { | ||
| duration: 1, | ||
| y: 20, | ||
| opacity: 0, | ||
| stagger: 0.1, | ||
| ease: "power2.out", | ||
| delay: 1 | ||
| }); | ||
|
|
||
| // --- Countdown Timer --- | ||
| // Set a random time between 2 to 5 hours from now | ||
| let remainingTime = (Math.floor(Math.random() * 3) + 2) * 60 * 60; | ||
|
|
||
| function updateCountdown() { | ||
| if (remainingTime <= 0) { | ||
| remainingTime = (Math.floor(Math.random() * 3) + 2) * 60 * 60; // Reset | ||
| } | ||
| remainingTime--; | ||
|
|
||
| const h = Math.floor(remainingTime / 3600); | ||
| const m = Math.floor((remainingTime % 3600) / 60); | ||
| const s = remainingTime % 60; | ||
|
|
||
| countdownEl.innerText = `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`; | ||
| } | ||
|
|
||
| setInterval(updateCountdown, 1000); | ||
| updateCountdown(); | ||
|
|
||
| // --- Terminal Logic --- | ||
| const logMessages = [ | ||
| "Analyzing relationship compatibility... 100%", | ||
| "Stress testing 'Yes' response... SUCCESS.", | ||
| "Error: 'No' option corrupted by Love.exe.", | ||
| "Optimizing romance algorithms...", | ||
| "Checking shipping availability... IMMEDIATE.", | ||
| "Heartbeat detected: ELEVATED.", | ||
| "Synchronizing emotional state...", | ||
| ]; | ||
|
|
||
| let logIndex = 0; | ||
|
|
||
| function addLog(message) { | ||
| const div = document.createElement('div'); | ||
| div.innerText = `> ${message}`; | ||
| terminal.appendChild(div); | ||
| terminal.scrollTop = terminal.scrollHeight; | ||
| } | ||
|
|
||
| function runTerminal() { | ||
| if (logIndex < logMessages.length) { | ||
| addLog(logMessages[logIndex]); | ||
| logIndex++; | ||
| setTimeout(runTerminal, Math.random() * 2000 + 1000); | ||
| } | ||
| } | ||
|
|
||
| setTimeout(runTerminal, 2000); | ||
|
|
||
| // --- Evasive 'No' Button Logic --- | ||
| let noBtnScale = 1; | ||
| const noBtnTexts = ["NO", "ARE YOU SURE?", "REALLY?", "ERROR 404", "TRY AGAIN", "NOPE", "TOO SLOW"]; | ||
| let textIndex = 0; | ||
|
|
||
| document.addEventListener('mousemove', (e) => { | ||
| const rect = noBtn.getBoundingClientRect(); | ||
| const btnX = rect.left + rect.width / 2; | ||
| const btnY = rect.top + rect.height / 2; | ||
|
|
||
| const dist = Math.hypot(e.clientX - btnX, e.clientY - btnY); | ||
|
|
||
| // If mouse is within 100px (as per prompt "The Logic" 50px vs "Solid Prompt" 100px, taking 100px for better effect) | ||
| if (dist < 100) { | ||
| teleportButton(); | ||
| } | ||
| }); | ||
|
|
||
| function teleportButton() { | ||
| // Teleport | ||
| const maxX = window.innerWidth - noBtn.offsetWidth - 50; | ||
| const maxY = window.innerHeight - noBtn.offsetHeight - 50; | ||
|
|
||
| const newX = Math.random() * maxX; | ||
| const newY = Math.random() * maxY; | ||
|
|
||
| noBtn.style.position = 'fixed'; | ||
| noBtn.style.left = `${newX}px`; | ||
| noBtn.style.top = `${newY}px`; | ||
| noBtn.style.zIndex = '50'; // Ensure it's above other things but below overlay | ||
|
|
||
| // Shrink | ||
| noBtnScale *= 0.9; | ||
| noBtn.style.transform = `scale(${noBtnScale})`; | ||
|
|
||
| // Change Text | ||
| textIndex = (textIndex + 1) % noBtnTexts.length; | ||
| noBtn.innerText = noBtnTexts[textIndex]; | ||
|
|
||
| // Add log | ||
| addLog(`Warning: 'No' evasion triggered. Integrity: ${Math.floor(noBtnScale * 100)}%`); | ||
| } | ||
|
|
||
| // Just in case they tab to it or touch screen | ||
| noBtn.addEventListener('mouseover', teleportButton); | ||
| noBtn.addEventListener('click', (e) => { | ||
| e.preventDefault(); | ||
| teleportButton(); | ||
| }); | ||
|
|
||
| // --- 'Yes' Button Logic --- | ||
| yesBtn.addEventListener('click', () => { | ||
| // 1. Confetti | ||
| const duration = 3000; | ||
| const end = Date.now() + duration; | ||
|
|
||
| (function frame() { | ||
| confetti({ | ||
| particleCount: 5, | ||
| angle: 60, | ||
| spread: 55, | ||
| origin: { x: 0 }, | ||
| colors: ['#FF0055', '#FFFFFF', '#000000'] | ||
| }); | ||
| confetti({ | ||
| particleCount: 5, | ||
| angle: 120, | ||
| spread: 55, | ||
| origin: { x: 1 }, | ||
| colors: ['#FF0055', '#FFFFFF', '#000000'] | ||
| }); | ||
|
|
||
| if (Date.now() < end) { | ||
| requestAnimationFrame(frame); | ||
| } | ||
| }()); | ||
|
|
||
| // 2. Visual Feedback | ||
| addLog("RESPONSE CONFIRMED: YES."); | ||
| addLog("Initiating celebratory sequence..."); | ||
|
|
||
| // 3. Transition | ||
| gsap.to(productBox, { | ||
| duration: 0.5, | ||
| scale: 0.9, | ||
| opacity: 0, | ||
| ease: "power2.in", | ||
| onComplete: () => { | ||
| productBox.style.display = 'none'; | ||
| voucherOverlay.classList.remove('hidden'); | ||
| // Trigger reflow to enable transition | ||
| void voucherOverlay.offsetWidth; | ||
| voucherOverlay.classList.remove('opacity-0'); | ||
|
|
||
| // Animate voucher in | ||
| gsap.from("#voucher-overlay > div", { | ||
| duration: 1, | ||
| y: 50, | ||
| rotation: -5, | ||
| opacity: 0, | ||
| ease: "elastic.out(1, 0.5)" | ||
| }); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| // --- Interactive Parallax for Floating Elements --- | ||
| document.addEventListener('mousemove', (e) => { | ||
| const mouseX = e.clientX / window.innerWidth; | ||
| const mouseY = e.clientY / window.innerHeight; | ||
|
|
||
| floatingElements.forEach((el, index) => { | ||
| const speed = (index + 1) * 10; | ||
| const x = (window.innerWidth / 2 - e.clientX) / speed; | ||
| const y = (window.innerHeight / 2 - e.clientY) / speed; | ||
|
|
||
| // Apply parallax effect to the product box instead of floating elements | ||
| // to avoid conflict with CSS keyframe animations. | ||
| const depth = 20; | ||
| const moveX = (e.clientX - window.innerWidth / 2) / window.innerWidth * depth; | ||
| const moveY = (e.clientY - window.innerHeight / 2) / window.innerHeight * depth; | ||
|
|
||
| gsap.to(productBox, { | ||
| duration: 1, | ||
| x: moveX, | ||
| y: moveY, | ||
| ease: "power1.out" | ||
| }); | ||
| }); | ||
| }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Parallax loop redundantly animates same element multiple timesMedium Severity The parallax mousemove handler iterates over |
||
| }); | ||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Voucher displays hardcoded date from 2 years ago
Low Severity
The voucher confirmation screen displays a hardcoded date of "FEB 14, 2024" which is 2 years in the past. Unlike the obvious
[HER NAME]placeholders, this date appears legitimate but is incorrect for the intended use as a Valentine's Day dinner invitation. The recipient would see a past date, making the invitation confusing or appearing like an old/expired voucher.