lemonlink/services/immich.html

441 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Immich - Login</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, sans-serif;
background: #0f172a;
min-height: 100vh;
color: #fff;
overflow-x: hidden;
}
/* Demo Banner */
.demo-banner {
background: rgba(0,0,0,0.9);
color: #fff;
text-align: center;
padding: 12px;
font-size: 13px;
position: relative;
z-index: 1000;
border-bottom: 1px solid #333;
}
.demo-banner a {
color: #60a5fa;
text-decoration: none;
}
/* Abstract Background Shapes */
.bg-shapes {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
z-index: 0;
}
.shape {
position: absolute;
border-radius: 50%;
filter: blur(60px);
opacity: 0.6;
}
.shape-1 {
width: 600px;
height: 600px;
background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
left: -200px;
top: -100px;
}
.shape-2 {
width: 500px;
height: 500px;
background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
right: -150px;
bottom: -100px;
}
.shape-3 {
width: 300px;
height: 300px;
background: #60a5fa;
left: 60%;
top: 60%;
opacity: 0.4;
}
.shape-4 {
width: 200px;
height: 200px;
background: #3b82f6;
left: 30%;
top: 20%;
opacity: 0.3;
}
/* Main Container */
.container {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 40px 20px;
}
/* Logo */
.logo {
margin-bottom: 30px;
}
.logo svg {
width: 120px;
height: 120px;
}
/* Login Card */
.login-card {
background: rgba(30, 41, 59, 0.95);
backdrop-filter: blur(20px);
border-radius: 16px;
padding: 32px;
width: 100%;
max-width: 360px;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
}
.login-title {
font-size: 20px;
font-weight: 600;
text-align: center;
margin-bottom: 24px;
color: #fff;
}
/* Input Groups with Floating Labels */
.input-group {
position: relative;
margin-bottom: 20px;
}
.input-group input {
width: 100%;
height: 52px;
padding: 16px 44px 8px 16px;
background: #0f172a;
border: 1px solid #334155;
border-radius: 8px;
font-size: 15px;
color: #fff;
transition: border-color 0.2s, box-shadow 0.2s;
}
.input-group input:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
}
.input-group label {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
font-size: 15px;
color: #94a3b8;
pointer-events: none;
transition: all 0.2s;
background: transparent;
padding: 0 4px;
}
.input-group input:focus + label,
.input-group input:not(:placeholder-shown) + label {
top: 0;
transform: translateY(-50%) scale(0.85);
color: #60a5fa;
background: #0f172a;
}
.input-group input:focus + label {
color: #60a5fa;
}
/* Icons inside inputs */
.input-icon {
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
color: #64748b;
cursor: pointer;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.input-icon:hover {
color: #94a3b8;
}
/* Remember Me */
.remember-row {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.remember-checkbox {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-size: 14px;
color: #cbd5e1;
}
.remember-checkbox input[type="checkbox"] {
width: 16px;
height: 16px;
accent-color: #3b82f6;
cursor: pointer;
}
/* Login Button */
.login-btn {
width: 100%;
height: 44px;
background: #3b82f6;
color: #fff;
border: none;
border-radius: 8px;
font-size: 15px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
transition: background 0.2s;
margin-bottom: 16px;
}
.login-btn:hover {
background: #2563eb;
}
.login-btn svg {
width: 16px;
height: 16px;
}
/* Alternative Login */
.alt-login {
text-align: center;
}
.alt-login-btn {
background: transparent;
border: none;
color: #cbd5e1;
font-size: 14px;
cursor: pointer;
padding: 8px 16px;
transition: color 0.2s;
}
.alt-login-btn:hover {
color: #fff;
text-decoration: underline;
}
/* Forgot Password */
.forgot-password {
text-align: center;
margin-top: 12px;
}
.forgot-password a {
color: #cbd5e1;
font-size: 14px;
text-decoration: none;
}
.forgot-password a:hover {
color: #fff;
text-decoration: underline;
}
/* Footer */
footer {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(30, 41, 59, 0.9);
padding: 12px 24px;
border-radius: 24px;
font-size: 13px;
color: #94a3b8;
z-index: 10;
}
footer a {
color: #fff;
text-decoration: none;
font-weight: 500;
}
/* Loading State */
.login-btn.loading {
pointer-events: none;
}
.login-btn.loading::after {
content: '';
width: 16px;
height: 16px;
border: 2px solid rgba(255,255,255,0.3);
border-top-color: #fff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* Responsive */
@media (max-width: 480px) {
.login-card {
padding: 24px;
}
.logo svg {
width: 100px;
height: 100px;
}
}
</style>
</head>
<body>
<div class="demo-banner">
🔒 This is a demo login page. The real service is private. <a href="https://lemonlink.eu">← Back to LemonLink</a>
</div>
<div class="bg-shapes">
<div class="shape shape-1"></div>
<div class="shape shape-2"></div>
<div class="shape shape-3"></div>
<div class="shape shape-4"></div>
</div>
<div class="container">
<div class="logo">
<svg viewBox="0 0 100 100" fill="none">
<circle cx="50" cy="50" r="45" fill="white"/>
<circle cx="35" cy="42" r="11" fill="#0f172a"/>
<circle cx="65" cy="42" r="11" fill="#0f172a"/>
<circle cx="50" cy="65" r="11" fill="#0f172a"/>
</svg>
</div>
<div class="login-card">
<h1 class="login-title">Log in to Nextcloud</h1>
<form onsubmit="handleLogin(event)">
<div class="input-group">
<input type="text" id="user" placeholder=" " autocomplete="off" required>
<label for="user">Account name or email</label>
</div>
<div class="input-group">
<input type="password" id="password" placeholder=" " required>
<label for="password">Password</label>
<span class="input-icon" onclick="togglePassword()" title="Show password">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
<circle cx="12" cy="12" r="3"/>
</svg>
</span>
</div>
<div class="remember-row">
<label class="remember-checkbox">
<input type="checkbox" checked>
<span>Remember me</span>
</label>
</div>
<button type="submit" class="login-btn" id="loginBtn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
Log in
</button>
</form>
<div class="alt-login">
<button class="alt-login-btn" onclick="alert('Demo page - device login not available')">
Log in with a device
</button>
</div>
<div class="forgot-password">
<a href="#" onclick="alert('Demo page - password reset not available'); return false;">
Forgot password?
</a>
</div>
</div>
</div>
<footer>
<a href="https://nextcloud.com" target="_blank">Nextcloud</a> a safe home for all your data
</footer>
<script>
function handleLogin(e) {
e.preventDefault();
const btn = document.getElementById('loginBtn');
const originalContent = btn.innerHTML;
btn.classList.add('loading');
btn.innerHTML = 'Logging in…';
setTimeout(() => {
btn.classList.remove('loading');
btn.innerHTML = originalContent;
alert('🔒 This is a demo page. The real Nextcloud is not exposed.');
}, 1000);
}
function togglePassword() {
const pw = document.getElementById('password');
pw.type = pw.type === 'password' ? 'text' : 'password';
}
// Focus username on load
document.getElementById('user').focus();
</script>
</body>
</html>