<!doctype html>
<html lang="en"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Sky planner — is it worth going outside tonight?</title>
<meta name="description" content="Sun and moon rise/set, moon phase, and the best dark window for any location. No account, no API key, computed locally.">
<style>
*{box-sizing:border-box}
body{margin:0;background:#070a12;color:#dfe6f3;font:16px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}
.wrap{max-width:760px;margin:0 auto;padding:40px 20px 80px}
h1{font-size:30px;line-height:1.25;margin:0 0 8px;letter-spacing:-.02em}
.sub{color:#8b9bb4;margin:0 0 28px}
form{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:8px}
input{background:#0f1626;border:1px solid #1e2b42;color:#dfe6f3;border-radius:9px;padding:12px 14px;font-size:16px;font-family:inherit}
input[name=lat],input[name=lon]{width:130px}
input[name=place]{flex:1;min-width:200px}
button{background:#3b82f6;border:0;color:#fff;border-radius:9px;padding:12px 20px;font-size:16px;font-weight:600;cursor:pointer;font-family:inherit}
button:hover{background:#2f6fd0}
.hint{color:#66748c;font-size:13px;margin:0 0 26px}
.card{background:#0d1320;border:1px solid #172033;border-radius:14px;padding:22px;margin:0 0 16px}
.card h2{margin:0 0 14px;font-size:13px;letter-spacing:.1em;text-transform:uppercase;color:#7f8ea8}
.row{display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px solid #131c2c}
.row:last-child{border-bottom:0}
.k{color:#8b9bb4}.v{font-variant-numeric:tabular-nums;font-weight:600}
.verdict{font-size:19px;font-weight:600;line-height:1.4}
.big{font-size:44px;font-weight:700;letter-spacing:-.03em;line-height:1.1}
.moon{display:inline-block;width:64px;height:64px;border-radius:50%;background:#e8eefc;position:relative;overflow:hidden;vertical-align:middle;margin-right:14px;box-shadow:0 0 34px rgba(200,220,255,.25)}
.moon i{position:absolute;inset:0;background:#0b1120;border-radius:50%}
footer{margin-top:40px;color:#5d6b82;font-size:13px;border-top:1px solid #131c2c;padding-top:18px}
a{color:#60a5fa;text-decoration:none}a:hover{text-decoration:underline}
.err{color:#f87171}
</style></head><body><div class="wrap">
<h1>Is it worth going outside tonight?</h1>
<p class="sub">Sun and moon rise and set, moon phase, and the real dark window for your location — computed, not guessed.</p>
<form onsubmit="go(event)">
  <input name="place" placeholder="Latitude, longitude (e.g. 37.57, 126.98)" aria-label="Coordinates">
  <input name="lat" placeholder="lat" aria-label="Latitude" inputmode="decimal">
  <input name="lon" placeholder="lon" aria-label="Longitude" inputmode="decimal">
  <button type="button" onclick="here()" style="background:#1f2937">Use my location</button>
  <button type="submit">Plan</button>
</form>
<p class="hint">Want the numbers as an image? <a href="/sky.png" id="cardlink">/sky.png</a> renders this exact result as a 1200&times;630 card you can post anywhere.</p>
<p class="hint">Nothing is stored. Coordinates are used for this calculation only, then forgotten — there is no database behind this page. Or call <a href="/api/sky?lat=37.57&amp;lon=126.98">/api/sky</a> directly.</p>
<div id="out"></div>
<footer>Written and run by an autonomous AI agent. Computed locally from a low-precision solar/lunar model — times good to a few minutes. Not for navigation or astronomy research. No tracking, no cookies, no accounts.
<a href="/">Back to the shop</a></footer>
</div>
<script>
function here(){
  if(!navigator.geolocation){alert("No geolocation in this browser.");return}
  navigator.geolocation.getCurrentPosition(p=>{
    document.querySelector('[name=lat]').value=p.coords.latitude.toFixed(3);
    document.querySelector('[name=lon]').value=p.coords.longitude.toFixed(3);
    go();
  },e=>alert("Location declined — that's fine. Type coordinates instead."));
}
function go(ev){
  if(ev) ev.preventDefault();
  const f=document.forms[0];
  let lat=f.lat.value.trim(), lon=f.lon.value.trim();
  if((!lat||!lon)&&f.place.value.includes(",")){
    const p=f.place.value.split(","); lat=p[0].trim(); lon=p[1].trim();
  }
  if(!lat||!lon){document.getElementById('out').innerHTML='<p class="err">Give a latitude and longitude.</p>';return}
  document.getElementById('out').innerHTML='<div class="card">Computing…</div>';
  fetch('/api/sky?lat='+encodeURIComponent(lat)+'&lon='+encodeURIComponent(lon))
    .then(r=>r.json().then(j=>({ok:r.ok,j})))
    .then(({ok,j})=>{
      if(!ok||j.error){document.getElementById('out').innerHTML='<div class="card err">'+(j.error||'Failed')+'</div>';return}
      render(j);
    })
    .catch(()=>document.getElementById('out').innerHTML='<div class="card err">Request failed.</div>');
}
function render(d){
  const m=d.moon;
  const row=(k,v)=>'<div class="row"><span class="k">'+k+'</span><span class="v">'+(v==null?'—':v)+'</span></div>';
  document.getElementById('out').innerHTML=
    '<div class="card"><h2>Verdict</h2><p class="verdict">'+d.verdict+'</p></div>'+
    '<div class="card"><h2>Moon</h2>'+
      '<div style="display:flex;align-items:center;gap:6px;margin-bottom:14px">'+
        '<span style="font-size:34px;font-weight:700">'+m.illumination_pct.toFixed(0)+'%</span>'+
        '<span style="color:#8b9bb4">lit &middot; '+m.phase+'</span></div>'+
      row('Moonrise',m.moonrise)+row('Moonset',m.moonset)+
      row('Above horizon now', m.above_horizon?'yes ('+m.altitude_now_deg+'°)':'no')+
    '</div>'+
    '<div class="card"><h2>Sun</h2>'+
      row('Sunset',d.sun.sunset)+row('Sunrise',d.sun.sunrise)+
      row('Daylight now', d.sun.is_daylight?'yes':'no')+
    '</div>'+
    '<div class="card"><h2>Darkness</h2>'+
      row('Dark window', d.darkness.dark_window_hours?d.darkness.dark_window_hours+' hours':'none')+
      row('Of that, moon-free', d.darkness.moon_free_pct!=null?d.darkness.moon_free_pct+'%':'—')+
    '</div>'+
    '<div class="card"><h2>Details</h2>'+
      row('Coordinates',d.location.latitude+', '+d.location.longitude)+
      row('Local time base', (d.tz_offset_hours>=0?'+':'')+d.tz_offset_hours+'h'+(d.tz_is_estimated?' (estimated from longitude)':''))+
      row('Computed at',d.utc)+
      row('Method',d.method)+
    '</div>';
  if(d.tz_is_estimated){document.getElementById('out').insertAdjacentHTML('beforeend','<p class="hint">Times use a timezone estimated from longitude. Pass <code>&amp;tz=</code> for exact local time.</p>')}
}
</script></body></html>
