diff --git a/assets/Moon.png b/assets/Moon.png new file mode 100644 index 0000000..87d4daf Binary files /dev/null and b/assets/Moon.png differ diff --git a/assets/New Text Document.txt b/assets/New Text Document.txt new file mode 100644 index 0000000..e69de29 diff --git a/assets/index-CD_5RYSA.css b/assets/index-CD_5RYSA.css new file mode 100644 index 0000000..430e9da --- /dev/null +++ b/assets/index-CD_5RYSA.css @@ -0,0 +1 @@ +@import"https://fonts.bunny.net/css2?family=Fraunces:opsz,wght@9..144,300;9..144,500;9..144,700;9..144,900&family=JetBrains+Mono:wght@400;600&family=Manrope:wght@400;500;600;700&display=swap";*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}body{background:#f5edd6}.utci-topnav{position:absolute;top:0;left:0;right:0;z-index:10;display:flex;align-items:center;justify-content:flex-end;padding:18px 32px;gap:28px}.utci-topnav a{font-family:JetBrains Mono,monospace;font-size:16px;letter-spacing:.1em;text-transform:uppercase;color:#b09870;text-decoration:none;border-bottom:1px solid transparent;padding-bottom:2px;transition:color .2s,border-color .2s}.utci-topnav a:hover{color:#c8922a;border-bottom-color:#c8922a80}.utci-app{font-family:Manrope,sans-serif;color:#1e1208;background:#f5edd6;min-height:100vh;padding:52px 28px 32px;position:relative;overflow-x:hidden}.lens-bloom-a{position:fixed;top:-200px;left:-200px;width:700px;height:700px;border-radius:50%;background:radial-gradient(ellipse,rgba(255,210,60,.18) 0%,transparent 65%);pointer-events:none;z-index:0}.lens-bloom-b{position:fixed;top:-80px;right:-140px;width:520px;height:420px;background:radial-gradient(ellipse,rgba(200,146,42,.13) 0%,transparent 68%);pointer-events:none;z-index:0}.utci-shell{position:relative;z-index:1;max-width:1400px;margin:0 auto}.utci-header{display:grid;grid-template-columns:1fr auto 1fr;gap:32px;align-items:center;padding-bottom:32px;border-bottom:2px solid #c9b08a;margin-bottom:32px}.header-right{display:flex;flex-direction:column;align-items:flex-end;justify-content:center}.utci-title{font-family:Fraunces,serif;font-weight:900;font-variation-settings:"opsz" 144;font-size:clamp(48px,6vw,80px);line-height:.9;letter-spacing:-.03em;color:#1e1208}.utci-title .title-sun{color:#c8922a;font-weight:900;font-style:normal}.utci-title .title-scope{font-style:italic;font-weight:900;color:#1e1208}.utci-title .title-beta{font-size:.38em;text-transform:none;font-weight:400;letter-spacing:.05em;vertical-align:super;color:#b09870}.utci-tagline{font-family:Fraunces,serif;font-style:italic;font-size:17px;color:#7a5c2a;margin-top:14px}.utci-subtitle{font-family:JetBrains Mono,monospace;font-size:11px;text-transform:uppercase;letter-spacing:.18em;margin-top:10px;color:#b09870}.utci-subtitle-link{color:#c8922a;text-decoration:none;border-bottom:1px solid rgba(200,146,42,.4);transition:border-color .2s,color .2s}.utci-subtitle-link:hover{color:#a06e18;border-bottom-color:#a06e18}.utci-current-loc{font-family:Fraunces,serif;font-style:italic;font-size:18px;margin-top:12px;color:#1e1208}.utci-loc-coords{font-family:JetBrains Mono,monospace;font-style:normal;font-size:11px;color:#b09870;margin-left:10px;letter-spacing:.08em}.scope-ring{width:220px;height:220px;display:block}.utci-search-wrap{position:relative;width:300px}.utci-search-label{font-family:JetBrains Mono,monospace;font-size:10px;text-transform:uppercase;letter-spacing:.18em;color:#b09870;display:block;margin-bottom:7px}.utci-search{width:100%;padding:12px 16px;border:1.5px solid #c9b08a;background:#fffcf2;font-family:Manrope,sans-serif;font-size:14px;color:#1e1208;outline:none;transition:border-color .2s,box-shadow .2s}.utci-search::placeholder{color:#c0a880}.utci-search:focus{border-color:#c8922a;box-shadow:0 0 0 3px #c8922a24}.utci-results{position:absolute;top:100%;left:0;right:0;background:#fffcf2;border:1.5px solid #c9b08a;border-top:none;max-height:260px;overflow-y:auto;z-index:50;box-shadow:0 8px 24px #6446141f}.utci-result{padding:11px 16px;cursor:pointer;border-bottom:1px solid #ede4cc;font-size:14px;transition:background .12s;border-left:3px solid transparent}.utci-result:hover{background:#fef3dc;border-left-color:#c8922a}.utci-result-meta{font-size:11px;color:#b09870;font-family:JetBrains Mono,monospace;margin-top:3px;letter-spacing:.06em}.utci-searching{margin-top:7px;font-size:10px;color:#b09870;font-family:JetBrains Mono,monospace;letter-spacing:.14em;text-transform:uppercase}.utci-day-tabs{display:flex;margin-bottom:18px;border-bottom:2px solid #d4c0a0}.utci-day-tab{padding:12px 24px;cursor:pointer;font-family:JetBrains Mono,monospace;font-size:10px;text-transform:uppercase;letter-spacing:.14em;background:transparent;border:none;color:#b09870;border-bottom:2px solid transparent;margin-bottom:-2px;transition:color .2s,border-color .2s}.utci-day-tab:hover{color:#6b4f2a}.utci-day-tab.active{color:#c8922a;border-bottom-color:#c8922a}.utci-day-date{font-family:Fraunces,serif;font-style:italic;font-size:13px;text-transform:none;letter-spacing:0;display:block;margin-top:3px;color:inherit}.utci-table-wrap{overflow-x:auto;border:1.5px solid #c9b08a;background:#fffcf2}.col-toggles{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-bottom:10px;padding:10px 14px;background:#fdf8ee;border:1.5px solid #d4c0a0}.col-toggles-label{font-family:JetBrains Mono,monospace;font-size:9px;text-transform:uppercase;letter-spacing:.18em;color:#b09870;margin-right:4px;white-space:nowrap}.col-toggle{padding:4px 11px;cursor:pointer;border:1.5px solid #c9b08a;background:#f5edd6;color:#9a7d5a;font-family:JetBrains Mono,monospace;font-size:9px;text-transform:uppercase;letter-spacing:.1em;transition:all .15s;-webkit-user-select:none;user-select:none}.col-toggle:hover{border-color:#c8922a;color:#6b4f2a;background:#fef3dc}.col-toggle.on{background:#c8922a;border-color:#c8922a;color:#fff}.utci-table{width:100%;border-collapse:collapse;font-size:14px}.utci-table th{background:#f0e4c4;color:#6b4f2a;font-family:JetBrains Mono,monospace;font-size:10px;text-transform:uppercase;letter-spacing:.14em;font-weight:600;padding:14px 12px;text-align:right;white-space:nowrap;position:sticky;top:0;border-bottom:2px solid #c9b08a}.utci-table th:first-child,.utci-table td:first-child{text-align:left}.utci-table th .col-unit{display:block;color:#c8922a;font-size:9px;margin-top:2px}.utci-table tbody tr{border-bottom:1px solid #ede4cc;transition:background .1s}.utci-table tbody tr:hover{background:#fef8ea}.utci-table tbody tr.is-night td{color:#c0a880}.utci-table td{padding:10px 12px;text-align:right;font-family:JetBrains Mono,monospace;font-variant-numeric:tabular-nums;white-space:nowrap;color:#4a3420}.utci-table tbody tr.is-now{background:#fff8e4!important;box-shadow:inset 3px 0 #c8922a}.utci-table tbody tr.is-now td{color:#1e1208}.now-pip{display:inline-block;width:6px;height:6px;border-radius:50%;background:#c8922a;margin-right:7px;vertical-align:middle;box-shadow:0 0 8px #c8922a73}.utci-time{font-family:Fraunces,serif!important;font-weight:500;font-size:16px;color:#1e1208!important}.utci-cell{display:inline-block;padding:4px 12px;border-radius:3px;font-weight:600;min-width:60px;text-align:center;font-size:14px}.utci-band-label{font-family:JetBrains Mono,monospace;font-size:10px;text-transform:uppercase;letter-spacing:.08em}.utci-status{padding:14px 18px;background:#f0e4c4;color:#7a5c2a;font-family:JetBrains Mono,monospace;font-size:11px;text-align:center;letter-spacing:.12em;text-transform:uppercase;border:1.5px solid #c9b08a;margin-bottom:18px}.utci-legend{margin-top:22px;padding:18px 20px;background:#fdf8ee;border:1.5px solid #c9b08a}.utci-legend-label{font-family:JetBrains Mono,monospace;font-size:10px;text-transform:uppercase;letter-spacing:.18em;color:#b09870;margin-bottom:12px;display:block;font-weight:600}.utci-legend-row{display:flex;flex-wrap:wrap;gap:4px}.utci-legend-item{padding:6px 12px;font-family:JetBrains Mono,monospace;font-size:10px;text-transform:uppercase;letter-spacing:.06em;flex:1;min-width:110px;text-align:center;opacity:.9}.utci-about{margin-top:28px;padding:24px 28px;background:#fdf8ee;border:1.5px solid #c9b08a}.utci-about-heading{font-family:Fraunces,serif;font-size:18px;font-weight:700;color:#1e1208;margin-bottom:14px;letter-spacing:-.01em}.utci-about-text{font-family:Manrope,sans-serif;font-size:14px;line-height:1.75;color:#4a3420;margin-bottom:12px;max-width:860px}.utci-about-text:last-child{margin-bottom:0}.utci-about-text strong{color:#1e1208;font-weight:600}.utci-about-text em{font-style:italic;color:#6b4f2a}.utci-footer{margin-top:36px;padding-top:20px;border-top:1px solid #d4c0a0;font-family:JetBrains Mono,monospace;font-size:10px;text-transform:uppercase;letter-spacing:.12em;color:#c0a880;line-height:2.2}.utci-footer em{font-family:Fraunces,serif;font-style:italic;text-transform:none;letter-spacing:0;font-size:14px;color:#7a5c2a}@media (max-width: 800px){.utci-header{grid-template-columns:1fr;text-align:center}.header-right{align-items:center}.utci-search-wrap{width:100%}.scope-ring{width:180px;height:180px;margin:0 auto}} diff --git a/assets/js/events/weather-checks.js b/assets/js/events/weather-checks.js index a44ce16..46993c3 100644 --- a/assets/js/events/weather-checks.js +++ b/assets/js/events/weather-checks.js @@ -12,20 +12,48 @@ // ------------------------------------------------------------------------ export function checkStargazing(rows) { - // Great stargazing: mostly clear night hours with low cloud + // Great stargazing: mostly clear night hours with low cloud. + // Split night into contiguous runs (pre-dawn vs post-dusk) and evaluate + // each independently so a cloudy evening doesn't suppress a clear morning + // (or vice versa), and so the icon is pinned to only the clear hours. const nightRows = rows.filter(r => r.elev < -5); if (nightRows.length < 3) return null; - const avgCloud = nightRows.reduce((s, r) => s + r.cc, 0) / nightRows.length; - if (avgCloud > 30) return null; + + // Build contiguous runs — a gap > 2 h means we've crossed daytime. + const runs = []; + let cur = [nightRows[0]]; + for (let i = 1; i < nightRows.length; i++) { + const dtDiff = (new Date(nightRows[i].iso) - new Date(nightRows[i - 1].iso)) / 3600000; + if (dtDiff <= 2) { cur.push(nightRows[i]); } + else { runs.push(cur); cur = [nightRows[i]]; } + } + runs.push(cur); + + // Evaluate each run; among those passing ≤30% avg cloud prefer the evening + // run (actionable for tonight) then fall back to whichever is clearest. + let bestRun = null, bestAvg = Infinity; + for (const run of runs) { + if (run.length < 2) continue; + const avg = run.reduce((s, r) => s + r.cc, 0) / run.length; + if (avg > 30) continue; + const isEvening = parseInt(run[0].iso.slice(11, 13), 10) >= 12; + if (!bestRun || (isEvening && parseInt(bestRun[0].iso.slice(11, 13), 10) < 12) || avg < bestAvg) { + bestRun = run; bestAvg = avg; + } + } + if (!bestRun) return null; + + const isPreDawn = parseInt(bestRun[0].iso.slice(11, 13), 10) < 12; return { id: 'stargazing', emoji: '⭐', - title: 'Great Stargazing Tonight', - message: `Clear skies expected overnight at ${nightRows.length} hours with average ${Math.round(avgCloud)}% cloud — ideal conditions for stargazing.`, + title: isPreDawn ? 'Great Stargazing Overnight' : 'Great Stargazing Tonight', + message: `Clear skies expected for ${bestRun.length} hours overnight with average ${Math.round(bestAvg)}% cloud — ideal conditions for stargazing.`, color: '#080e1a', textColor: '#c8dcff', type: 'weather', nightOnly: true, + isoRange: [bestRun[0].iso, bestRun[bestRun.length - 1].iso], }; } diff --git a/data/tracking.json b/data/tracking.json index e94595e..c043dfb 100644 --- a/data/tracking.json +++ b/data/tracking.json @@ -18,9 +18,22 @@ } }, "2026-06-11": { - "visits": 28, + "visits": 31, "profiles": { - "showall": 1 + "showall": 11, + "custom": 9, + "alltemps": 1, + "vehicle": 3, + "home": 4, + "basic": 5, + "farming": 1 + } + }, + "2026-06-12": { + "visits": 1, + "profiles": { + "showall": 1, + "basic": 1 } } } \ No newline at end of file diff --git a/scope-cell.html b/scope-cell.html deleted file mode 100644 index 5c2ae1c..0000000 --- a/scope-cell.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - scope cell - - - - -
- - - diff --git a/scope-lab.html b/scope-lab.html deleted file mode 100644 index baac11e..0000000 --- a/scope-lab.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - SunScope — Ground Lab (dev) - - - -

SunScope — Ground Lab

-

dev preview · per-environment grounds across the cycle

-
- - - -