| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>AeroCore OS v2.2</title> |
| <link href="https://fonts.cdnfonts.com/css/gamestart" rel="stylesheet"> |
| <style> |
| :root { |
| --aero-blue: #00d2ff; |
| --aero-green: #3affaa; |
| --mosaic-glass: rgba(255, 255, 255, 0.9); |
| } |
| |
| body { |
| background: linear-gradient(135deg, #3a7bd5, #00d2ff, #3affaa); |
| background-size: 400% 400%; |
| animation: gradientBG 15s ease infinite; |
| font-family: 'GameStart', sans-serif; |
| margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; overflow: hidden; |
| } |
| |
| @keyframes gradientBG { 0% {background-position: 0% 50%;} 50% {background-position: 100% 50%;} 100% {background-position: 0% 50%;} } |
| |
| |
| .mosaic-layer { |
| position: fixed; top: 0; left: 0; width: 100%; height: 100%; |
| background-image: radial-gradient(rgba(255,255,255,0.2) 1.5px, transparent 1.5px); |
| background-size: 6px 6px; pointer-events: none; z-index: 5; |
| } |
| |
| .window { |
| width: 750px; height: 550px; background: var(--mosaic-glass); |
| border: 6px solid #fff; border-radius: 4px; |
| box-shadow: 15px 15px 0px rgba(0,0,0,0.1); |
| position: relative; z-index: 20; display: flex; flex-direction: column; |
| } |
| |
| .screen { display: none; padding: 25px; flex-direction: column; height: 100%; box-sizing: border-box; } |
| .active { display: flex; } |
| |
| |
| button { |
| font-family: 'GameStart', sans-serif; padding: 12px; margin: 5px 0; |
| background: linear-gradient(to bottom, #ffffff 0%, #aadaff 40%, #0080ff 100%); |
| border: 2px solid #fff; color: white; text-shadow: 1px 1px 2px #000; |
| cursor: pointer; box-shadow: 3px 3px 0px #0055aa; transition: 0.1s; |
| } |
| button:active { transform: translate(2px, 2px); box-shadow: 0px 0px; } |
| |
| input { |
| font-family: 'GameStart', sans-serif; padding: 12px; margin-bottom: 10px; |
| border: 3px inset #fff; background: rgba(255,255,255,0.9); width: 100%; box-sizing: border-box; |
| } |
| |
| #chat-box { background: white; border: 4px inset #eee; flex-grow: 1; overflow-y: auto; padding: 15px; margin-bottom: 10px; } |
| |
| .msg { background: #e6f7ff; border-left: 6px solid var(--aero-blue); padding: 10px; margin-bottom: 10px; position: relative; } |
| .msg-info { font-size: 0.5rem; color: #555; margin-bottom: 4px; } |
| .del-btn { font-size: 0.5rem; background: #ff4d4d; border: 1px solid white; cursor: pointer; padding: 4px; margin-top: 5px;} |
| |
| |
| #modal-overlay { |
| position: fixed; top: 0; left: 0; width: 100%; height: 100%; |
| background: rgba(0,0,0,0.4); z-index: 1000; |
| display: none; justify-content: center; align-items: center; |
| } |
| |
| .modal { |
| background: white; border: 5px solid var(--aero-green); |
| padding: 30px; text-align: center; width: 400px; |
| box-shadow: 0 0 40px rgba(0,0,0,0.3); |
| } |
| |
| .hidden { display: none !important; } |
| </style> |
| </head> |
| <body> |
|
|
| <div class="mosaic-layer"></div> |
|
|
| <div id="modal-overlay"> |
| <div class="modal"> |
| <h3>AeroCore v2.0</h3> |
| <p>Built: 20th February 2026</p> |
| <button onclick="closePopup()" style="background: var(--aero-green); width: 100%;">EXIT & START</button> |
| </div> |
| </div> |
|
|
| <div class="window"> |
| <div id="screen-auth" class="screen active"> |
| <h2>AEROCORE ACCESS</h2> |
| <form id="login-form" onsubmit="handleAuth(event, 'login')"> |
| <input type="text" id="username" name="username" placeholder="USERNAME" required autocomplete="username"> |
| <input type="password" id="password" name="password" placeholder="PASSWORD" required autocomplete="current-password" |
| style="-webkit-text-security: none !important;"> |
| <button type="submit">LOG IN</button> |
| <button type="button" onclick="handleAuth(event, 'signup')" style="background: #888;">SIGN UP</button> |
| </form> |
| </div> |
|
|
| <div id="screen-tutorial" class="screen"> |
| <h2>SYSTEM TUTORIAL</h2> |
| <ul style="font-size: 0.8rem; line-height: 1.6;"> |
| <li><b>HOST:</b> Create a Room → Share Code → Approve Members.</li> |
| <li><b>CLIENT:</b> Enter Code → Wait for Approval.</li> |
| <li><b>DELETE:</b> 'For Me' (Local) / 'Everyone' (Global).</li> |
| </ul> |
| <button onclick="nav('screen-lobby')">ENTER CHATROOMS</button> |
| </div> |
|
|
| <div id="screen-lobby" class="screen"> |
| <h2>COMMUNITY HUB</h2> |
| <p id="welcome-msg" style="color: var(--aero-blue);"></p> |
| <button onclick="joinRoom('Public')">JOIN PUBLIC SERVER</button> |
| <hr style="border: 1px solid #fff; width: 100%;"> |
| <button onclick="createPrivate()">HOST PRIVATE ROOM</button> |
| <div id="host-code-display" style="color: #0055aa; font-weight: bold;"></div> |
| <br> |
| <input type="text" id="join-code-input" placeholder="ENTER ROOM CODE"> |
| <button onclick="joinRoom('Private')">REQUEST ENTRY</button> |
| </div> |
|
|
| <div id="screen-chat" class="screen"> |
| <div style="display:flex; justify-content: space-between; align-items: center;"> |
| <h2 id="room-header" style="font-size: 0.9rem;">CHAT</h2> |
| <button id="admin-btn" class="hidden" onclick="nav('screen-approval')" style="font-size: 0.6rem; padding: 5px;">ADMIN</button> |
| </div> |
| <div id="chat-box"></div> |
| <input type="text" id="msg-input" placeholder="Message or URL..."> |
| <div style="display:flex; gap: 5px;"> |
| <button onclick="sendMsg('text')" style="flex: 1;">SEND</button> |
| <button onclick="sendMsg('img')" style="background:var(--aero-blue)">IMG</button> |
| <button onclick="nav('screen-lobby')" style="background:#cc0000">EXIT</button> |
| </div> |
| </div> |
|
|
| <div id="screen-approval" class="screen"> |
| <h2>PENDING MEMBERS</h2> |
| <div id="approval-list"></div> |
| <button onclick="nav('screen-chat')">BACK TO CHAT</button> |
| </div> |
| </div> |
|
|
| <script> |
| |
| let db = JSON.parse(localStorage.getItem('aero_v2_data')) || { |
| users: [], messages: [], rooms: {} |
| }; |
| let currentUser = null; |
| let activeRoomCode = 'Public'; |
| |
| function save() { localStorage.setItem('aero_v2_data', JSON.stringify(db)); } |
| |
| |
| function nav(id) { |
| document.querySelectorAll('.screen').forEach(s => s.classList.remove('active')); |
| document.getElementById(id).classList.add('active'); |
| if(id === 'screen-chat') renderMessages(); |
| if(id === 'screen-approval') renderApprovalList(); |
| } |
| |
| |
| function handleAuth(event, mode) { |
| event.preventDefault(); |
| const u = document.getElementById('username').value; |
| const p = document.getElementById('password').value; |
| |
| if(!u || !p) return; |
| |
| const user = db.users.find(x => x.username === u); |
| |
| if(mode === 'signup') { |
| if(user) return alert("User exists! Try Login."); |
| db.users.push({username: u, password: p}); |
| save(); |
| alert("Account created! Now Log In."); |
| } else { |
| if(!user || user.password !== p) return alert("Incorrect Username or Password!"); |
| currentUser = u; |
| document.getElementById('welcome-msg').innerText = "Logged in as: " + u; |
| document.getElementById('modal-overlay').style.display = 'flex'; |
| } |
| } |
| |
| function closePopup() { |
| document.getElementById('modal-overlay').style.display = 'none'; |
| nav('screen-tutorial'); |
| } |
| |
| |
| function createPrivate() { |
| const code = Math.floor(1000 + Math.random() * 9000).toString(); |
| db.rooms[code] = { host: currentUser, members: [currentUser], pending: [] }; |
| document.getElementById('host-code-display').innerText = "ROOM CODE: " + code; |
| activeRoomCode = code; |
| save(); |
| } |
| |
| function joinRoom(type) { |
| if(type === 'Public') { |
| activeRoomCode = 'Public'; |
| nav('screen-chat'); |
| } else { |
| const code = document.getElementById('join-code-input').value; |
| const room = db.rooms[code]; |
| if(!room) return alert("Room Not Found! Use the code from the other phone."); |
| |
| activeRoomCode = code; |
| if(room.members.includes(currentUser)) { |
| nav('screen-chat'); |
| } else { |
| if(!room.pending.includes(currentUser)) { |
| room.pending.push(currentUser); |
| save(); |
| } |
| alert("Request sent. Tell the Host to approve you on their screen!"); |
| } |
| } |
| } |
| |
| function renderApprovalList() { |
| const list = document.getElementById('approval-list'); |
| const room = db.rooms[activeRoomCode]; |
| list.innerHTML = room.pending.map(u => ` |
| <div style="background:#fff; padding:10px; margin-bottom:5px; border:2px solid var(--aero-blue);"> |
| ${u} <button onclick="approveUser('${u}')">APPROVE</button> |
| </div> |
| `).join('') || "No requests."; |
| } |
| |
| function approveUser(u) { |
| db.rooms[activeRoomCode].members.push(u); |
| db.rooms[activeRoomCode].pending = db.rooms[activeRoomCode].pending.filter(x => x !== u); |
| save(); |
| renderApprovalList(); |
| } |
| |
| |
| function sendMsg(type) { |
| const val = document.getElementById('msg-input').value; |
| if(!val) return; |
| db.messages.push({ |
| id: Date.now(), |
| room: activeRoomCode, |
| sender: currentUser, |
| content: val, |
| type: type, |
| time: new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}) |
| }); |
| save(); |
| document.getElementById('msg-input').value = ''; |
| renderMessages(); |
| } |
| |
| function renderMessages() { |
| const box = document.getElementById('chat-box'); |
| const msgs = db.messages.filter(m => m.room === activeRoomCode); |
| document.getElementById('room-header').innerText = `ROOM: ${activeRoomCode}`; |
| |
| |
| if(activeRoomCode !== 'Public' && db.rooms[activeRoomCode].host === currentUser) { |
| document.getElementById('admin-btn').classList.remove('hidden'); |
| } else { |
| document.getElementById('admin-btn').classList.add('hidden'); |
| } |
| |
| box.innerHTML = msgs.map(m => ` |
| <div class="msg"> |
| <div class="msg-info">${m.sender} • ${m.time}</div> |
| <div>${m.type === 'img' ? `<img src="${m.content}" style="max-width:100px;">` : m.content}</div> |
| <button class="del-btn" onclick="deleteMsg(${m.id}, 'me')">Delete for me</button> |
| ${m.sender === currentUser ? `<button class="del-btn" style="background:orange" onclick="deleteMsg(${m.id}, 'everyone')">Delete for everyone</button>` : ''} |
| </div> |
| `).join(''); |
| box.scrollTop = box.scrollHeight; |
| } |
| |
| function deleteMsg(id, mode) { |
| if(mode === 'everyone') { |
| db.messages = db.messages.filter(m => m.id !== id); |
| } else { |
| |
| db.messages = db.messages.filter(m => m.id !== id); |
| } |
| save(); |
| renderMessages(); |
| } |
| </script> |
| </body> |
| </html> |