9.5 KB 296 lines
Raw Download
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>NEON | Local Search Engine</title> <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;700&display=swap" rel="stylesheet"> <style> :root { --bg: #000000; --text: #ffffff; --accent: #ffffff; --faded: rgba(255, 255, 255, 0.1); --neon-blue: #4dabff; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Space Grotesk', sans-serif; } body { background-color: var(--bg); min-height: 100vh; color: var(--text); display: flex; flex-direction: column; overflow-x: hidden; line-height: 1.5; } body::before { content: ""; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: url('https://grainy-gradients.vercel.app/noise.svg'); opacity: 0.05; pointer-events: none; z-index: 99; } #container { flex-grow: 1; display: flex; flex-direction: column; justify-content: center; align-items: center; transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1); padding: 20px; } .logo-container { margin-bottom: 50px; text-align: left; } .logo-line { font-size: 16px; font-weight: 700; letter-spacing: 0.5rem; text-transform: uppercase; line-height: 1.4; display: flex; align-items: baseline; } .logo-line span { font-weight: 300; letter-spacing: 0.2rem; opacity: 0.4; margin-left: 15px; font-size: 13px; } .search-wrapper { width: 100%; max-width: 550px; position: relative; z-index: 10; margin-bottom: 20px; } input { width: 100%; background: transparent; border: none; border-left: 1px solid var(--faded); padding: 15px 60px 15px 25px; color: white; font-size: 20px; font-weight: 300; outline: none; transition: 0.4s; } input:focus { border-left: 1px solid var(--accent); } .search-trigger { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); background: transparent; border: none; color: white; cursor: pointer; padding: 12px; opacity: 0.2; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; border-radius: 50%; } input:not(:placeholder-shown) ~ .search-trigger, .search-trigger:hover { opacity: 1; background: rgba(255,255,255,0.05); filter: drop-shadow(0 0 12px white); } #results-view { display: none; width: 100%; max-width: 800px; margin: 0 auto; padding: 0 20px 120px 20px; } /* --- HAMBURGER MENU --- */ #menu-toggle { position: fixed; top: 30px; right: 30px; z-index: 1000; background: transparent; border: none; cursor: pointer; display: flex; flex-direction: column; gap: 6px; padding: 10px; } .bar { width: 22px; height: 1px; background-color: white; transition: 0.3s; } .active-toggle .bar:nth-child(1) { transform: translateY(7px) rotate(45deg); } .active-toggle .bar:nth-child(2) { opacity: 0; } .active-toggle .bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); } #sidebar { position: fixed; top: 0; right: -320px; width: 320px; height: 100%; background: rgba(0, 0, 0, 0.98); backdrop-filter: blur(20px); border-left: 1px solid var(--faded); z-index: 999; transition: 0.5s cubic-bezier(0.16, 1, 0.3, 1); padding: 100px 50px; } #sidebar.active { right: 0; } .nav-header { font-size: 10px; letter-spacing: 5px; color: var(--faded); margin-bottom: 50px; text-transform: uppercase; } .nav-links { display: flex; flex-direction: column; gap: 30px; } .nav-links a { color: white; text-decoration: none; font-size: 18px; font-weight: 300; letter-spacing: 2px; transition: 0.3s; } .nav-links a:hover { color: var(--neon-blue); padding-left: 10px; } /* --- LOCAL RESULT STYLES --- */ .result-item { margin-bottom: 35px; opacity: 0; transform: translateY(15px); animation: slideUp 0.6s ease forwards; } .result-title { color: var(--neon-blue); text-decoration: none; font-size: 20px; display: block; margin-bottom: 6px; font-weight: 400; } .result-title:hover { text-decoration: underline; } .result-link { color: #666; font-size: 11px; margin-top: 5px; word-break: break-all; text-transform: uppercase; letter-spacing: 1px; } .no-results { color: #444; font-size: 14px; letter-spacing: 1px; text-align: center; margin-top: 40px; } body.searching #container { justify-content: flex-start; padding-top: 40px; min-height: auto; flex-grow: 0; } body.searching .logo-container { margin-bottom: 30px; transform: scale(0.8); } body.searching #results-view { display: block; } @keyframes slideUp { from { opacity: 0; transform: translateY(15px); } to { opacity: 1; transform: translateY(0); } } .footer { position: fixed; bottom: 30px; width: 100%; text-align: center; font-size: 10px; letter-spacing: 5px; color: var(--faded); pointer-events: none; } </style> </head> <body> <button id="menu-toggle" onclick="toggleMenu()"> <div class="bar"></div> <div class="bar"></div> <div class="bar"></div> </button> <nav id="sidebar"> <div class="nav-header">Local Engine</div> <div class="nav-links"> <a href="#" onclick="toggleMenu()">Search Home</a> </div> </nav> <div id="container"> <div class="logo-container"> <div class="logo-line">N<span>ext</span></div> <div class="logo-line">E<span>volution</span></div> <div class="logo-line">O<span>f</span></div> <div class="logo-line">N<span>avigation</span></div> </div> <div class="search-wrapper"> <input type="text" id="queryInput" placeholder="explore" autocomplete="off" spellcheck="false" autofocus> <button class="search-trigger" id="searchBtn"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> <circle cx="11" cy="11" r="8"></circle> <line x1="21" x2="16.65" y1="21" y2="16.65"></line> </svg> </button> </div> </div> <div id="results-view"> <div id="main-web-results"></div> </div> <div class="footer">SIMPLE. FAST. YOURS.</div> <script src="sites.js"></script> <script> const input = document.getElementById('queryInput'); const searchBtn = document.getElementById('searchBtn'); const body = document.body; const webDiv = document.getElementById('main-web-results'); // Parse data from sites.js file const sites = rawSitesData.split('\n') .map(line => line.trim()) .filter(line => line.length > 0); // Sidebar View Toggle Function function toggleMenu() { document.getElementById('sidebar').classList.toggle('active'); document.getElementById('menu-toggle').classList.toggle('active-toggle'); } // High-performance clean search functionality function performSearch() { const rawQuery = input.value.toLowerCase().trim(); if (!rawQuery) { body.classList.remove('searching'); webDiv.innerHTML = ''; return; } body.classList.add('searching'); webDiv.innerHTML = ""; const queryTerms = rawQuery.split(/\s+/); const cleanQuery = rawQuery.replace(/[^a-z0-9]/g, ''); let htmlOutput = ''; let matchCount = 0; for (let i = 0; i < sites.length; i++) { const site = sites[i]; const lowerSite = site.toLowerCase(); const cleanSite = lowerSite.replace(/[^a-z0-9]/g, ''); let isMatch = false; if (lowerSite.includes(rawQuery)) { isMatch = true; } else if (cleanSite.includes(cleanQuery)) { isMatch = true; } else { let matchAllTerms = true; for (let j = 0; j < queryTerms.length; j++) { if (!lowerSite.includes(queryTerms[j])) { matchAllTerms = false; break; } } if (matchAllTerms) { isMatch = true; } } if (isMatch) { let displayHost = site; try { displayHost = new URL(`https://${site}`).hostname; } catch(e){} htmlOutput += ` <div class="result-item" style="animation-delay: ${matchCount * 0.04}s"> <a href="https://${site}" target="_blank" rel="noopener noreferrer" class="result-title">${site}</a> <div class="result-link">${displayHost}</div> </div> `; matchCount++; } } webDiv.innerHTML = htmlOutput || '<div class="no-results">ZERO NODES FOUND.</div>'; } searchBtn.addEventListener('click', performSearch); input.addEventListener('keydown', (e) => { if (e.key === 'Enter') performSearch(); }); </script> </body> </html>