Files
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

181 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Waggle · Sign in</title>
<script>document.documentElement.classList.add('js');</script>
<link rel="stylesheet" href="../styles/waggle.css">
<style>
body { height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
.controls { flex: none; display: flex; align-items: center; gap: 14px; padding: 11px 20px; border-bottom: 1px solid var(--line-soft); background: color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter: blur(10px); z-index: 30; }
.controls .lab { font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim); }
.seg { display: inline-flex; padding: 3px; gap: 3px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--line-soft); }
.seg button { font-family: var(--sans); font-size: 12px; font-weight: 600; cursor: pointer; border: 0; background: transparent; color: var(--text-muted); padding: 6px 11px; border-radius: 7px; transition: .14s; white-space:nowrap; }
.seg button.on { background: var(--honey); color: #1a1407; }
.controls .right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.tbtn { width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--line); background: var(--surface); color: var(--text-2); cursor: pointer; }
.tbtn:hover { border-color: var(--honey-line); color: var(--honey); }
.split { flex:1; min-height:0; display:grid; grid-template-columns: 1.05fr 1fr; }
/* brand panel */
.brandside { position:relative; overflow:hidden; padding: 56px; display:flex; flex-direction:column; justify-content:space-between; background: linear-gradient(160deg, var(--bg-2), var(--bg)); border-right:1px solid var(--line-soft); }
.brandside .comb { position:absolute; inset:0; opacity:.6; pointer-events:none; mask-image: radial-gradient(90% 80% at 30% 30%, black, transparent 75%); }
.brandside .bk { position:relative; display:flex; align-items:center; gap:12px; }
.brandside .bk .mk { width:34px; height:38px; display:grid; place-items:center; font-weight:800; font-size:16px; color:#1a1407; background:linear-gradient(150deg,var(--honey-bright),var(--honey-deep)); box-shadow:var(--honey-glow); }
.brandside .bk b { font-size:19px; font-weight:700; letter-spacing:-0.01em; }
.brandside .pitch { position:relative; }
.brandside .pitch h2 { font-size: clamp(26px,3vw,38px); font-weight:600; letter-spacing:-0.025em; line-height:1.08; margin:0 0 16px; max-width:16ch; }
.brandside .pitch h2 em { font-style:normal; color:var(--honey); }
.brandside .pitch p { font-size:15px; color:var(--text-2); line-height:1.55; max-width:42ch; margin:0; }
.brandside .trust { position:relative; display:flex; flex-direction:column; gap:11px; }
.brandside .trust .t { display:flex; align-items:center; gap:11px; font-size:13.5px; color:var(--text-2); }
.brandside .trust .t svg { width:17px; height:17px; stroke:var(--honey); fill:none; stroke-width:1.8; flex:none; }
/* form panel */
.formside { display:flex; align-items:center; justify-content:center; padding: 40px 32px; overflow:auto; }
.formcard { width:100%; max-width: 380px; }
.fhead { text-align:center; margin-bottom: 26px; }
.fhead h1 { font-size: 24px; font-weight:650; letter-spacing:-0.02em; margin:0 0 6px; }
.fhead p { font-size:13.5px; color:var(--text-muted); margin:0; }
.fhead p a { color:var(--honey); text-decoration:none; font-weight:600; cursor:pointer; }
.sso { display:grid; gap:9px; margin-bottom:18px; }
.ssobtn { display:flex; align-items:center; justify-content:center; gap:10px; padding:11px; border-radius:11px; border:1px solid var(--line-strong); background:var(--surface); color:var(--text); font-family:var(--sans); font-size:14px; font-weight:600; cursor:pointer; transition:.14s; }
.ssobtn:hover { border-color:var(--honey-line); background:var(--surface-2); }
.ssobtn .g { width:18px; height:18px; border-radius:4px; display:grid; place-items:center; font-family:var(--mono); font-size:11px; font-weight:700; background:var(--surface-3); flex:none; }
.divider { display:flex; align-items:center; gap:12px; margin:18px 0; color:var(--text-dim); font-size:12px; font-family:var(--mono); }
.divider::before, .divider::after { content:''; flex:1; height:1px; background:var(--line-soft); }
.fld { margin-bottom:13px; }
.fld label { display:block; font-size:12.5px; font-weight:600; color:var(--text-2); margin-bottom:6px; }
.fld input { width:100%; padding:11px 14px; border-radius:11px; border:1px solid var(--line); background:var(--surface); color:var(--text); font-family:var(--sans); font-size:14.5px; outline:none; transition:.14s; }
.fld input:focus { border-color:var(--honey-line); box-shadow:var(--honey-glow); }
.fld .lrow { display:flex; align-items:center; justify-content:space-between; }
.fld .lrow a { font-size:11.5px; color:var(--honey); text-decoration:none; cursor:pointer; }
.submit { width:100%; padding:12px; border-radius:11px; border:0; background:var(--honey); color:#1a1407; font-family:var(--sans); font-size:15px; font-weight:650; cursor:pointer; transition:.14s; margin-top:6px; }
.submit:hover { background:var(--honey-bright); }
.fineprint { text-align:center; font-size:11.5px; color:var(--text-dim); margin-top:16px; line-height:1.5; } .fineprint a { color:var(--text-2); }
/* OTP */
.otp { display:flex; gap:10px; justify-content:center; margin:8px 0 4px; }
.otp input { width:48px; height:56px; text-align:center; font-family:var(--mono); font-size:22px; border-radius:12px; border:1px solid var(--line); background:var(--surface); color:var(--text); outline:none; }
.otp input:focus { border-color:var(--honey-line); box-shadow:var(--honey-glow); }
.otp input.filled { border-color:var(--honey-line); color:var(--honey); }
.resend { text-align:center; font-size:12.5px; color:var(--text-muted); margin-top:14px; } .resend a { color:var(--honey); cursor:pointer; }
/* local-first banner */
.localnote { display:flex; gap:10px; align-items:flex-start; padding:12px 14px; border-radius:11px; background:var(--honey-wash); border:1px solid var(--honey-line); margin-bottom:20px; }
.localnote svg { width:16px; height:16px; stroke:var(--honey); fill:none; stroke-width:1.8; flex:none; margin-top:1px; }
.localnote p { margin:0; font-size:12px; color:var(--text-2); line-height:1.5; } .localnote b { color:var(--text); }
.view { display:none; } .view.on { display:block; }
@media (max-width: 820px){ .split { grid-template-columns:1fr; } .brandside { display:none; } }
</style>
</head>
<body>
<div class="controls">
<span class="lab">Auth · Clerk · state</span>
<div class="seg" id="seg">
<button class="on" data-v="signin">Sign in</button>
<button data-v="signup">Sign up</button>
<button data-v="verify">Verify</button>
<button data-v="sso">SSO</button>
</div>
<div class="right"><button class="tbtn" id="tbtn" title="Toggle theme"></button></div>
</div>
<div class="split">
<div class="brandside">
<div class="comb"></div>
<div class="bk"><div class="mk hex">W</div><b>Waggle</b></div>
<div class="pitch">
<h2>Your work follows you, <em>everywhere.</em></h2>
<p>Sign in to sync your hive across devices, collaborate with a team, and pick up any project exactly where you left off — on any machine.</p>
</div>
<div class="trust">
<div class="t"><svg viewBox="0 0 24 24"><path d="M12 3l8 4v5c0 5-3.5 7.5-8 9-4.5-1.5-8-4-8-9V7z"/></svg>An account is optional — Waggle runs fully local without one</div>
<div class="t"><svg viewBox="0 0 24 24"><path d="M5 12h14M13 6l6 6-6 6"/></svg>Your memory stays yours; sign-in only adds sync</div>
</div>
</div>
<div class="formside">
<div class="formcard">
<!-- SIGN IN -->
<div class="view on" data-view="signin">
<div class="fhead"><h1>Welcome back</h1><p>New to Waggle? <a data-go="signup">Create an account</a></p></div>
<div class="sso">
<button class="ssobtn"><span class="g">G</span>Continue with Google</button>
<button class="ssobtn"><span class="g"></span>Continue with Apple</button>
</div>
<div class="divider">or</div>
<div class="fld"><label>Email</label><input type="email" value="mara@egzakta.com"></div>
<div class="fld"><div class="lrow"><label>Password</label><a data-go="verify">Forgot?</a></div><input type="password" value="••••••••••"></div>
<button class="submit" data-go="home">Sign in</button>
<div class="fineprint">By continuing you agree to the <a href="#">Terms</a> &amp; <a href="#">Privacy Policy</a>.</div>
</div>
<!-- SIGN UP -->
<div class="view" data-view="signup">
<div class="fhead"><h1>Create your hive</h1><p>Already have an account? <a data-go="signin">Sign in</a></p></div>
<div class="localnote"><svg viewBox="0 0 24 24"><path d="M3 11l9-8 9 8M5 10v10h14V10"/></svg><p><b>You don't need this to start.</b> Waggle works locally right away — create an account only when you want sync or a team.</p></div>
<div class="sso">
<button class="ssobtn"><span class="g">G</span>Sign up with Google</button>
</div>
<div class="divider">or</div>
<div class="fld"><label>Name</label><input value="Mara Kovač"></div>
<div class="fld"><label>Email</label><input type="email" placeholder="you@company.com"></div>
<div class="fld"><label>Password</label><input type="password" placeholder="At least 10 characters"></div>
<button class="submit" data-go="verify">Create account</button>
<div class="fineprint">We'll send a code to verify your email.</div>
</div>
<!-- VERIFY (OTP) -->
<div class="view" data-view="verify">
<div class="fhead"><h1>Check your email</h1><p>We sent a 6-digit code to <b style="color:var(--text-2)">mara@egzakta.com</b></p></div>
<div class="otp" id="otp"></div>
<button class="submit" data-go="home" style="margin-top:18px">Verify &amp; continue</button>
<div class="resend">Didn't get it? <a>Resend code</a> · <a data-go="signin">Use a different email</a></div>
</div>
<!-- SSO / ORG -->
<div class="view" data-view="sso">
<div class="fhead"><h1>Single sign-on</h1><p>Use your organization's identity provider.</p></div>
<div class="fld"><label>Work email or organization</label><input placeholder="you@company.com"></div>
<button class="submit" data-go="home">Continue with SSO</button>
<div class="divider">enterprise</div>
<div class="localnote" style="background:var(--bg-2);border-color:var(--line-soft)"><svg viewBox="0 0 24 24" style="stroke:var(--text-muted)"><path d="M9 12l2 2 4-4M12 3l8 4v5c0 5-3.5 7.5-8 9-4.5-1.5-8-4-8-9V7z"/></svg><p>SAML, SCIM provisioning, and audit logs are available on <b>Teams</b> and <b>KVARK</b>. <a style="color:var(--honey)" href="#">Talk to sales →</a></p></div>
<div class="fineprint"><a data-go="signin">← Back to sign in</a></div>
</div>
</div>
</div>
</div>
<script>
const root = document.documentElement, tbtn = document.getElementById('tbtn');
function setTheme(t){ root.setAttribute('data-theme', t); tbtn.textContent = t==='dark'?'☾':'☀'; try{localStorage.setItem('waggle-concept-theme',t);}catch(e){} }
setTheme((()=>{ try{ return localStorage.getItem('waggle-concept-theme')||'dark'; }catch(e){ return 'dark'; } })());
tbtn.onclick = () => setTheme(root.getAttribute('data-theme')==='dark'?'light':'dark');
window.addEventListener('message', e => { if(e.data && e.data.theme) setTheme(e.data.theme); });
window.addEventListener('storage', e => { if(e.key==='waggle-concept-theme' && e.newValue) setTheme(e.newValue); });
// OTP boxes
document.getElementById('otp').innerHTML = Array.from({length:6},(_, i)=>`<input maxlength="1" inputmode="numeric" data-i="${i}" value="${i<3?[2,4,9][i]:''}">`).join('');
document.querySelectorAll('#otp input').forEach((inp,i,arr)=>{
if(inp.value) inp.classList.add('filled');
inp.addEventListener('input', e=>{ inp.classList.toggle('filled', !!inp.value); if(inp.value && arr[i+1]) arr[i+1].focus(); });
inp.addEventListener('keydown', e=>{ if(e.key==='Backspace' && !inp.value && arr[i-1]) arr[i-1].focus(); });
});
function go(v){
if(v==='home'){ document.body.style.transition='opacity .25s'; document.body.style.opacity='.4'; setTimeout(()=>{ try{ location.href='../Waggle Reimagined.html#home'; }catch(e){} }, 260); return; }
document.querySelectorAll('.view').forEach(el=>el.classList.toggle('on', el.dataset.view===v));
document.querySelectorAll('#seg button').forEach(b=>b.classList.toggle('on', b.dataset.v===v));
}
document.getElementById('seg').addEventListener('click', e=>{ const b=e.target.closest('button'); if(b) go(b.dataset.v); });
document.addEventListener('click', e=>{ const a=e.target.closest('[data-go]'); if(a){ e.preventDefault(); go(a.dataset.go); } });
</script>
</body>
</html>