ironchronicle / login.html
hts-ai's picture
🐳 15/02 - 00:56 - fini la simulation en passe en reel en pro
743b870 verified
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IronChronicle | Secure Login</title>
<link rel="icon" type="image/x-icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🛡️</text></svg>">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
military: {
500: '#22c55e',
600: '#16a34a',
800: '#14532d',
900: '#052e16',
950: '#020617',
}
},
fontFamily: {
mono: ['"Courier Prime"', 'Courier', 'monospace'],
sans: ['"Inter"', 'sans-serif'],
}
}
}
}
</script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Courier+Prime:wght@400;700&display=swap');
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #020617 0%, #0f172a 50%, #020617 100%);
}
.login-container {
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(20px);
border: 1px solid rgba(34, 197, 94, 0.2);
}
.input-field {
background: rgba(0, 0, 0, 0.4);
border: 1px solid rgba(71, 85, 105, 0.6);
transition: all 0.3s ease;
}
.input-field:focus {
border-color: #22c55e;
box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.1);
outline: none;
}
.login-btn {
background: linear-gradient(135deg, #22c55e, #16a34a);
transition: all 0.3s ease;
}
.login-btn:hover {
background: linear-gradient(135deg, #16a34a, #15803d);
box-shadow: 0 4px 20px rgba(34, 197, 94, 0.4);
transform: translateY(-2px);
}
.login-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
}
.shield-icon {
filter: drop-shadow(0 0 20px rgba(34, 197, 94, 0.5));
}
.scan-line {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #22c55e, transparent);
animation: scan 3s linear infinite;
}
@keyframes scan {
0% { transform: translateY(0); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(400px); opacity: 0; }
}
.error-shake {
animation: shake 0.5s ease-in-out;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-10px); }
40%, 80% { transform: translateX(10px); }
}
.loading-spinner {
border: 2px solid rgba(255, 255, 255, 0.2);
border-top: 2px solid #22c55e;
border-radius: 50%;
width: 20px;
height: 20px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.footer-text {
font-family: 'Courier Prime', monospace;
font-size: 0.7rem;
color: rgba(100, 116, 139, 0.6);
}
</style>
</head>
<body class="min-h-screen flex items-center justify-center p-4">
<div class="w-full max-w-md">
<!-- Logo Header -->
<div class="text-center mb-8">
<div class="inline-flex items-center justify-center w-20 h-20 rounded-full bg-slate-900 border border-military-500/30 shield-icon mb-4">
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
</svg>
</div>
<h1 class="text-3xl font-bold text-white tracking-wider">IRON<span class="text-military-500">CHRONICLE</span></h1>
<p class="text-slate-500 text-sm mt-2 font-mono">MILITARY NARRATIVE SYSTEM v4.2.0</p>
</div>
<!-- Login Container -->
<div class="login-container rounded-2xl p-8 relative overflow-hidden">
<div class="scan-line"></div>
<h2 class="text-xl font-semibold text-white text-center mb-6">SECURE ACCESS</h2>
<form id="login-form" class="space-y-5">
<!-- Username Field -->
<div>
<label for="username" class="block text-sm font-medium text-slate-400 mb-2">Username</label>
<div class="relative">
<i data-feather="user" class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-500"></i>
<input
type="text"
id="username"
name="username"
class="input-field w-full pl-10 pr-4 py-3 rounded-lg text-white placeholder-slate-500"
placeholder="Enter username"
autocomplete="username"
>
</div>
</div>
<!-- Password Field -->
<div>
<label for="password" class="block text-sm font-medium text-slate-400 mb-2">Password</label>
<div class="relative">
<i data-feather="lock" class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-500"></i>
<input
type="password"
id="password"
name="password"
class="input-field w-full pl-10 pr-4 py-3 rounded-lg text-white placeholder-slate-500"
placeholder="Enter password"
autocomplete="current-password"
>
</div>
</div>
<!-- Error Message -->
<div id="error-message" class="hidden bg-red-900/30 border border-red-500/50 rounded-lg p-3 text-red-400 text-sm text-center"></div>
<!-- Submit Button -->
<button
type="submit"
id="login-btn"
class="login-btn w-full py-3 rounded-lg text-white font-semibold flex items-center justify-center gap-2"
>
<i data-feather="shield" class="w-5 h-5"></i>
<span>SECURE LOGIN</span>
</button>
</form>
<!-- System Info -->
<div class="mt-6 pt-6 border-t border-slate-700">
<div class="grid grid-cols-2 gap-4 text-center">
<div class="footer-text">
<div class="text-slate-500">ENCRYPTION</div>
<div class="text-military-500">AES-256-GCM</div>
</div>
<div class="footer-text">
<div class="text-slate-500">NODE</div>
<div class="text-military-500">EU-WEST-4</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<div class="text-center mt-6">
<p class="footer-text">
RESTRICTED ACCESS AUTHORIZED PERSONNEL ONLY<br>
© 2024 IRONCHRONICLE SYSTEM
</p>
</div>
</div>
<script>
// Initialize Feather Icons
document.addEventListener('DOMContentLoaded', () => {
feather.replace();
// Credentials (in production, use proper backend authentication)
const API_BASE_URL = window.location.hostname === 'localhost'
? 'http://localhost:3000/api'
: 'https://api.ironchronicle.secure/api';
const loginForm = document.getElementById('login-form');
const errorMessage = document.getElementById('error-message');
const loginBtn = document.getElementById('login-btn');
loginForm.addEventListener('submit', async (e) => {
e.preventDefault();
const username = document.getElementById('username').value.trim();
const password = document.getElementById('password').value;
// Reset error
errorMessage.classList.add('hidden');
// Show loading state
loginBtn.disabled = true;
loginBtn.innerHTML = '<div class="loading-spinner"></div><span>AUTHENTICATING...</span>';
feather.replace();
try {
// Production API call
const response = await fetch(`${API_BASE_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Request-ID': crypto.randomUUID()
},
body: JSON.stringify({ username, password })
});
const data = await response.json();
if (response.ok && data.token) {
// Store secure session
sessionStorage.setItem('ironchronicle_token', data.token);
sessionStorage.setItem('ironchronicle_user', data.user.username);
sessionStorage.setItem('ironchronicle_clearance', data.user.clearance);
sessionStorage.setItem('ironchronicle_session_id', data.sessionId);
showToast('Authentication successful. Establishing secure connection...', 'success');
// Redirect with token
setTimeout(() => {
window.location.href = `index.html?sid=${data.sessionId}`;
}, 800);
} else {
throw new Error(data.message || 'Authentication failed');
}
} catch (error) {
errorMessage.textContent = error.message || 'System unavailable. Contact administrator.';
errorMessage.classList.remove('hidden');
// Security shake effect
const container = document.querySelector('.login-container');
container.classList.add('error-shake');
setTimeout(() => container.classList.remove('error-shake'), 500);
// Log failed attempt (in production, send to SIEM)
console.warn(`Failed login attempt: ${username} at ${new Date().toISOString()}`);
} finally {
loginBtn.disabled = false;
loginBtn.innerHTML = '<i data-feather="shield" class="w-5 h-5"></i><span>SECURE LOGIN</span>';
feather.replace();
}
});
// Check for existing valid session
const existingToken = sessionStorage.getItem('ironchronicle_token');
if (existingToken) {
// Validate token silently
fetch(`${API_BASE_URL}/auth/verify`, {
headers: { 'Authorization': `Bearer ${existingToken}` }
}).then(r => {
if (r.ok) window.location.href = 'index.html';
}).catch(() => {
sessionStorage.clear(); // Clear invalid session
});
}
// Toast notification function
window.showToast = function(message, type = 'info') {
const toast = document.createElement('div');
const bgColor = type === 'success' ? 'bg-military-600' : type === 'error' ? 'bg-red-600' : 'bg-slate-700';
toast.className = `fixed bottom-4 left-1/2 transform -translate-x-1/2 ${bgColor} text-white px-6 py-3 rounded-lg shadow-lg flex items-center gap-2 text-sm font-medium animate-fade-in`;
toast.innerHTML = `<i data-feather="${type === 'success' ? 'check-circle' : 'alert-circle'}" class="w-4 h-4"></i><span>${message}</span>`;
document.body.appendChild(toast);
feather.replace();
setTimeout(() => {
toast.style.opacity = '0';
toast.style.transform = 'translateX(-50%) translateY(20px)';
toast.style.transition = 'all 0.3s ease';
setTimeout(() => toast.remove(), 300);
}, 3000);
};
});
</script>
</body>
</html>