mirror of Walter-Sparrow / lunar-tear
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 200 lines 5.4 kB view raw
1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<meta charset="utf-8"> 5<meta name="viewport" content="width=device-width, initial-scale=1"> 6<title>Lunar Tear – Login</title> 7<style> 8 * { margin: 0; padding: 0; box-sizing: border-box; } 9 body { 10 font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; 11 background: #0a0a0a; 12 color: #e0e0e0; 13 min-height: 100vh; 14 min-height: 100dvh; 15 display: flex; 16 align-items: center; 17 justify-content: center; 18 } 19 .card { 20 background: #161616; 21 border: 1px solid #2a2a2a; 22 border-radius: 8px; 23 padding: 40px 32px 32px; 24 width: 100%; 25 max-width: 360px; 26 } 27 h1 { 28 text-align: center; 29 font-size: 28px; 30 font-weight: 300; 31 letter-spacing: 6px; 32 text-transform: uppercase; 33 color: #c8c8c8; 34 margin-bottom: 8px; 35 } 36 .subtitle { 37 text-align: center; 38 font-size: 11px; 39 letter-spacing: 3px; 40 text-transform: uppercase; 41 color: #555; 42 margin-bottom: 32px; 43 transition: color 0.3s; 44 } 45 .error { 46 background: #2a1515; 47 border: 1px solid #5a2020; 48 color: #e08080; 49 border-radius: 4px; 50 padding: 10px 14px; 51 font-size: 13px; 52 margin-bottom: 20px; 53 } 54 label { 55 display: block; 56 font-size: 11px; 57 letter-spacing: 1px; 58 text-transform: uppercase; 59 color: #888; 60 margin-bottom: 6px; 61 } 62 input[type="text"], 63 input[type="password"] { 64 width: 100%; 65 padding: 10px 12px; 66 background: #0e0e0e; 67 border: 1px solid #333; 68 border-radius: 4px; 69 color: #e0e0e0; 70 font-size: 15px; 71 margin-bottom: 18px; 72 outline: none; 73 transition: border-color 0.2s; 74 } 75 input:focus { border-color: #666; } 76 .buttons { 77 display: flex; 78 gap: 10px; 79 margin-top: 8px; 80 } 81 button { 82 flex: 1; 83 padding: 11px 0; 84 border: 1px solid #333; 85 border-radius: 4px; 86 font-size: 13px; 87 letter-spacing: 1px; 88 cursor: pointer; 89 transition: background 0.2s, border-color 0.2s, opacity 0.3s; 90 } 91 .btn-login { 92 background: #e0e0e0; 93 color: #111; 94 border-color: #e0e0e0; 95 } 96 .btn-login:hover { background: #fff; border-color: #fff; } 97 .btn-register { 98 background: transparent; 99 color: #aaa; 100 } 101 .btn-register:hover { border-color: #666; color: #e0e0e0; } 102 .hidden { display: none; } 103 @media (max-height: 480px) { 104 body { align-items: stretch; padding: 0; } 105 .card { 106 max-width: none; border-radius: 0; border: none; 107 min-height: 100vh; min-height: 100dvh; 108 padding: 20px 24px; 109 display: flex; flex-direction: column; justify-content: center; 110 } 111 h1 { font-size: 22px; margin-bottom: 4px; } 112 .subtitle { margin-bottom: 16px; } 113 input[type="text"], 114 input[type="password"] { padding: 8px 10px; margin-bottom: 12px; } 115 .buttons { margin-top: 4px; } 116 button { padding: 9px 0; } 117 } 118</style> 119</head> 120<body> 121<form class="card" method="POST"> 122 <h1>Lunar Tear</h1> 123 <div class="subtitle" id="subtitle">Authentication</div> 124 125 {{if .Error}} 126 <div class="error">{{.Error}}</div> 127 {{end}} 128 129 <input type="hidden" name="redirect_uri" value="{{.RedirectURI}}"> 130 <input type="hidden" name="state" value="{{.State}}"> 131 <input type="hidden" name="scope" value="{{.Scope}}"> 132 133 <label for="username">Username</label> 134 <input type="text" id="username" name="username" value="{{.Username}}" autocomplete="username" autofocus required> 135 136 <label for="password">Password</label> 137 <input type="password" id="password" name="password" autocomplete="current-password" required> 138 139 <div class="buttons"> 140 <button type="submit" name="action" value="login" class="btn-login hidden" id="btn-login">Login</button> 141 <button type="submit" name="action" value="register" class="btn-register hidden" id="btn-register">Create Account</button> 142 </div> 143</form> 144<script> 145(function() { 146 var input = document.getElementById('username'); 147 var btnLogin = document.getElementById('btn-login'); 148 var btnRegister = document.getElementById('btn-register'); 149 var subtitle = document.getElementById('subtitle'); 150 var timer = null; 151 var lastChecked = ''; 152 153 function check() { 154 var name = input.value.trim(); 155 if (name === '') { 156 btnLogin.classList.add('hidden'); 157 btnRegister.classList.add('hidden'); 158 subtitle.textContent = 'Authentication'; 159 lastChecked = ''; 160 return; 161 } 162 if (name === lastChecked) return; 163 lastChecked = name; 164 165 fetch('/check-username?username=' + encodeURIComponent(name)) 166 .then(function(r) { return r.json(); }) 167 .then(function(data) { 168 if (input.value.trim() !== name) return; 169 if (data.exists) { 170 btnLogin.classList.remove('hidden'); 171 btnRegister.classList.add('hidden'); 172 subtitle.textContent = 'Welcome back'; 173 } else { 174 btnLogin.classList.add('hidden'); 175 btnRegister.classList.remove('hidden'); 176 subtitle.textContent = 'Create your account'; 177 } 178 }) 179 .catch(function() { 180 btnLogin.classList.remove('hidden'); 181 btnRegister.classList.remove('hidden'); 182 subtitle.textContent = 'Authentication'; 183 }); 184 } 185 186 input.addEventListener('input', function() { 187 clearTimeout(timer); 188 timer = setTimeout(check, 300); 189 }); 190 191 input.addEventListener('blur', function() { 192 clearTimeout(timer); 193 check(); 194 }); 195 196 if (input.value.trim() !== '') check(); 197})(); 198</script> 199</body> 200</html>