LookAtU Phase 2: real waitlist form, privacy and terms pages, animations

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KDXAh86FTSBLqF8ohPqZ88
This commit is contained in:
Claude committed 2026-10-15 00:50:33 +00:00
1 parent 7be9a85754
commit 9bddc5722c
3 files changed
+114 -25

No files matched your search

+59 -25
View File
@@ -60,10 +60,15 @@ input[type=email]:focus-visible,.btn:focus-visible,summary:focus-visible,button:
#msg{text-align:center;margin-top:14px;min-height:1.5em} #msg{text-align:center;margin-top:14px;min-height:1.5em}
#msg.ok{color:var(--ok)} #msg.err{color:var(--danger)} #msg.ok{color:var(--ok)} #msg.err{color:var(--danger)}
.note{text-align:center;color:var(--muted);font-size:.85rem;margin-top:8px} .note{text-align:center;color:var(--muted);font-size:.85rem;margin-top:8px}
.sr{position:absolute;left:-9999px}
.trap{position:absolute;left:-9999px;height:0;overflow:hidden}
select{padding:13px 14px;border-radius:12px;border:1px solid var(--line);background:var(--bg);color:var(--text);font:inherit}
.consent{flex:1 1 100%;font-size:.9rem;color:var(--muted)}
.consent input{margin-right:8px}
.consent a{color:var(--brand)}
footer a{margin:0 8px}
footer{padding:30px 0;border-top:1px solid var(--line);color:var(--muted);font-size:.9rem;text-align:center} footer{padding:30px 0;border-top:1px solid var(--line);color:var(--muted);font-size:.9rem;text-align:center}
.reveal{opacity:0;transform:translateY(20px);transition:opacity .6s,transform .6s} @media (prefers-reduced-motion:reduce){.pin::after{animation:none}html{scroll-behavior:auto}}
.reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}.pin::after{animation:none}html{scroll-behavior:auto}}
@media (max-width:640px){.nav a.link{display:none}} @media (max-width:640px){.nav a.link{display:none}}
</style> </style>
</head> </head>
@@ -103,11 +108,11 @@ footer{padding:30px 0;border-top:1px solid var(--line);color:var(--muted);font-s
<h2>Everything a parent needs</h2> <h2>Everything a parent needs</h2>
<p class="sub">Five simple tools, in one app.</p> <p class="sub">Five simple tools, in one app.</p>
<div class="grid"> <div class="grid">
<div class="card reveal"><div class="ic">📍</div><h3>Live location</h3><p>Open the app and see where your child is right now.</p></div> <div class="card"><div class="ic">📍</div><h3>Live location</h3><p>Open the app and see where your child is right now.</p></div>
<div class="card reveal"><div class="ic">📊</div><h3>Activity monitor</h3><p>See which apps they use and for how long, every day.</p></div> <div class="card"><div class="ic">📊</div><h3>Activity monitor</h3><p>See which apps they use and for how long, every day.</p></div>
<div class="card reveal"><div class="ic">🔒</div><h3>App control</h3><p>Allow, block or limit apps. Approve new installs before they happen.</p></div> <div class="card"><div class="ic">🔒</div><h3>App control</h3><p>Allow, block or limit apps. Approve new installs before they happen.</p></div>
<div class="card reveal"><div class="ic">💬</div><h3>Calls &amp; messages</h3><p>Check call history and messages so you can spot trouble early.</p></div> <div class="card"><div class="ic">💬</div><h3>Calls &amp; messages</h3><p>Check call history and messages so you can spot trouble early.</p></div>
<div class="card reveal sos"><div class="ic">🚨</div><h3>Panic button</h3><p>One tap and you get an alert with their location, right away.</p></div> <div class="card sos"><div class="ic">🚨</div><h3>Panic button</h3><p>One tap and you get an alert with their location, right away.</p></div>
</div> </div>
</div> </div>
</section> </section>
@@ -117,9 +122,9 @@ footer{padding:30px 0;border-top:1px solid var(--line);color:var(--muted);font-s
<h2>How it works</h2> <h2>How it works</h2>
<p class="sub">Set up takes a few minutes.</p> <p class="sub">Set up takes a few minutes.</p>
<div class="grid steps"> <div class="grid steps">
<div class="card reveal"><h3>Install on both phones</h3><p>You get the parent app. Your child gets the child app.</p></div> <div class="card"><h3>Install on both phones</h3><p>You get the parent app. Your child gets the child app.</p></div>
<div class="card reveal"><h3>Link them together</h3><p>Scan a code on your child's phone to connect the two.</p></div> <div class="card"><h3>Link them together</h3><p>Scan a code on your child's phone to connect the two.</p></div>
<div class="card reveal"><h3>Choose your rules</h3><p>Pick which apps are allowed and what you want to see.</p></div> <div class="card"><h3>Choose your rules</h3><p>Pick which apps are allowed and what you want to see.</p></div>
</div> </div>
</div> </div>
</section> </section>
@@ -154,36 +159,65 @@ footer{padding:30px 0;border-top:1px solid var(--line);color:var(--muted);font-s
<h2>Join the waitlist</h2> <h2>Join the waitlist</h2>
<p class="sub">Be the first to know when LookAtU opens.</p> <p class="sub">Be the first to know when LookAtU opens.</p>
<form id="waitlist" novalidate> <form id="waitlist" novalidate>
<label for="email" style="position:absolute;left:-9999px">Email address</label> <label for="email" class="sr">Email address</label>
<input id="email" name="email" type="email" placeholder="you@example.com" autocomplete="email" required> <input id="email" name="email" type="email" placeholder="you@example.com" autocomplete="email" required>
<button class="btn" type="submit">Notify me</button> <label for="phone" class="sr">Your child's phone</label>
<select id="phone" name="phone">
<option value="Android">Android phone</option>
<option value="iPhone">iPhone</option>
<option value="Both">Both</option>
</select>
<div class="trap" aria-hidden="true"><label for="website">Leave this empty</label><input id="website" name="website" type="text" tabindex="-1" autocomplete="off"></div>
<label class="consent" for="agree"><input id="agree" name="agree" type="checkbox"> I agree to the <a href="privacy/">Privacy Policy</a> and want emails about LookAtU.</label>
<button class="btn" id="send" type="submit">Notify me</button>
</form> </form>
<div id="msg" role="status" aria-live="polite"></div> <div id="msg" role="status" aria-live="polite"></div>
<p class="note">Demo form: emails are not saved yet. Saving comes in Phase 2.</p> <p class="note" id="note">We only use your email to tell you when LookAtU opens. No spam.</p>
</div> </div>
</section> </section>
</main> </main>
<footer><div class="wrap">© <span id="yr">2026</span> LookAtU. Early preview.</div></footer> <footer><div class="wrap">© <span id="yr">2026</span> LookAtU. Early preview. <a href="privacy/">Privacy</a> <a href="terms/">Terms</a></div></footer>
<script> <script>
// PASTE YOUR FORM URL BETWEEN THE QUOTES (example: https://formspree.io/f/abcdwxyz). While empty, the form runs in demo mode.
var FORM_ENDPOINT = '';
(function(){ (function(){
var form=document.getElementById('waitlist'),email=document.getElementById('email'),msg=document.getElementById('msg'); var form=document.getElementById('waitlist'),email=document.getElementById('email'),msg=document.getElementById('msg'),
btn=document.getElementById('send'),note=document.getElementById('note');
document.getElementById('yr').textContent=new Date().getFullYear(); document.getElementById('yr').textContent=new Date().getFullYear();
if(!FORM_ENDPOINT){note.textContent='Demo mode: emails are not saved yet.';}
function say(cls,t){msg.className=cls;msg.textContent=t;}
form.addEventListener('submit',function(e){ form.addEventListener('submit',function(e){
e.preventDefault(); e.preventDefault();
var v=email.value.trim(); var v=email.value.trim();
if(!/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(v)){ if(!/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(v)){say('err','Please enter a real email address, like you@example.com.');email.focus();return;}
msg.className='err';msg.textContent='Please enter a real email address, like you@example.com.';email.focus();return; if(!document.getElementById('agree').checked){say('err','Please tick the box to agree to the Privacy Policy.');return;}
} if(document.getElementById('website').value){say('ok','Thank you! You are on the list.');return;}
msg.className='ok';msg.textContent='Thank you! You are on the list (demo).';form.reset(); if(!FORM_ENDPOINT){say('ok','Thank you! You are on the list (demo, not saved).');form.reset();return;}
btn.disabled=true;say('','Sending...');
fetch(FORM_ENDPOINT,{method:'POST',headers:{'Content-Type':'application/json','Accept':'application/json'},
body:JSON.stringify({email:v,phone:document.getElementById('phone').value})})
.then(function(r){if(!r.ok)throw new Error('bad status');say('ok','Thank you! You are on the list.');form.reset();})
.catch(function(){say('err','Something went wrong. Please check your internet and try again.');})
.then(function(){btn.disabled=false;});
}); });
var els=document.querySelectorAll('.reveal');
if('IntersectionObserver' in window){
var io=new IntersectionObserver(function(es){es.forEach(function(x){if(x.isIntersecting){x.target.classList.add('in');io.unobserve(x.target)}})},{threshold:.15});
els.forEach(function(el){io.observe(el)});
}else{els.forEach(function(el){el.classList.add('in')})}
})(); })();
</script> </script>
<script type="module">
// Framer Motion ("motion") adds the animations. If it fails to load, the page still shows everything.
try{
var m=await import('https://cdn.jsdelivr.net/npm/motion@11.11.13/+esm');
if(!matchMedia('(prefers-reduced-motion: reduce)').matches){
m.animate('.hero h1,.hero p,.hero .cta',{opacity:[0,1],y:[24,0]},{duration:.7,delay:m.stagger(.12)});
m.animate('.phone',{opacity:[0,1],y:[40,0]},{duration:.8,delay:.4});
document.querySelectorAll('.card').forEach(function(c){
m.inView(c,function(){m.animate(c,{opacity:[0,1],y:[24,0]},{duration:.5});});
c.addEventListener('mouseenter',function(){m.animate(c,{y:-4},{duration:.2});});
c.addEventListener('mouseleave',function(){m.animate(c,{y:0},{duration:.2});});
});
}
}catch(e){}
</script>
</body> </body>
</html> </html>
+26
View File
@@ -0,0 +1,26 @@
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>Privacy Policy – LookAtU</title>
<style>
body{margin:0;background:#0b1220;color:#eaf0ff;font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;line-height:1.7}
main{max-width:720px;margin:0 auto;padding:40px 20px}
a{color:#4f8cff}h1{margin-top:0}h2{margin-top:32px}
.draft{background:#16213a;border:1px solid #ff4d5e;border-radius:12px;padding:14px 18px;color:#a3b1d1}
</style></head><body><main>
<p><a href="../">&larr; Back to LookAtU</a></p>
<h1>Privacy Policy</h1>
<p class="draft"><strong>Draft.</strong> This page is a plain-language starting point. A lawyer must review it before LookAtU launches, because rules for children's data differ by country.</p>
<h2>What we collect today</h2>
<p>This website collects only the email address and phone type (Android, iPhone or both) that you type into the waitlist form.</p>
<h2>Why we collect it</h2>
<p>We use it only to tell you when LookAtU opens. We do not sell it. We do not use it for anything else.</p>
<h2>Who sees it</h2>
<p>The LookAtU team, and the service that stores the waitlist for us.</p>
<h2>Your choices</h2>
<p>You can ask us to delete your email at any time. Every email we send will have a way to unsubscribe.</p>
<h2>The LookAtU app (coming later)</h2>
<p>The app will handle location, activity and messages of children. Before launch we will publish full details here: what is collected, how it is protected, how long it is kept, and how a parent can delete it. The child will always be able to see that the app is installed.</p>
<h2>Contact</h2>
<p>Contact email: <em>to be added before launch</em>.</p>
</main></body></html>
+29
View File
@@ -0,0 +1,29 @@
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>Terms of Use – LookAtU</title>
<style>
body{margin:0;background:#0b1220;color:#eaf0ff;font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;line-height:1.7}
main{max-width:720px;margin:0 auto;padding:40px 20px}
a{color:#4f8cff}h1{margin-top:0}h2{margin-top:32px}
.draft{background:#16213a;border:1px solid #ff4d5e;border-radius:12px;padding:14px 18px;color:#a3b1d1}
</style></head><body><main>
<p><a href="../">&larr; Back to LookAtU</a></p>
<h1>Terms of Use</h1>
<p class="draft"><strong>Draft.</strong> This page is a plain-language starting point. A lawyer must review it before LookAtU launches, because rules for children's data differ by country.</p>
<h2>This is an early preview</h2>
<p>This website is a preview of a product that is not released yet. Nothing here is an offer to sell.</p>
<h2>Waitlist</h2>
<p>Joining the waitlist is free and does not oblige you to buy anything. You can leave at any time.</p>
<h2>Using LookAtU responsibly (when it launches)</h2>
<ul>
<li>LookAtU is for parents and legal guardians of their own children.</li>
<li>It must not be used to watch another adult or someone else's child.</li>
<li>The child must be able to see that the app is installed.</li>
<li>Parents are responsible for following the laws in their country.</li>
</ul>
<h2>Emergencies</h2>
<p>The panic button helps a child alert a parent. It does not replace the police or emergency services. In an emergency, call your local emergency number.</p>
<h2>Contact</h2>
<p>Contact email: <em>to be added before launch</em>.</p>
</main></body></html>