thermograph/static/compare.html

154 lines
7.8 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Thermograph — compare comfort</title>
<meta name="description" content="Pick any point on Earth and see how its recent weather stacks up against ~45 years of local climate history — graded days, calendars, forecasts, and side-by-side comparisons." />
<meta name="theme-color" content="#f0803c" />
<!-- Link previews (Discord, Slack, iMessage…). The server fills the og:url /
og:image origins in from this request's scheme://host + base path —
crawlers need absolute URLs and don't run JS. -->
<meta property="og:type" content="website" />
<meta property="og:site_name" content="Thermograph" />
<meta property="og:title" content="Thermograph — compare comfort" />
<meta property="og:description" content="Pick any point on Earth and see how its recent weather stacks up against ~45 years of local climate history — graded days, calendars, forecasts, and side-by-side comparisons." />
<meta property="og:url" content="__ORIGIN__/compare" />
<meta property="og:image" content="__ORIGIN__/logo.png" />
<meta property="og:image:width" content="512" />
<meta property="og:image:height" content="512" />
<meta property="og:image:alt" content="Thermograph logo" />
<meta name="twitter:card" content="summary" />
<link rel="icon" href="logo.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="logo.png" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<header>
<div class="brand">
<span class="logo"></span>
<div>
<h1>Thermograph · Compare</h1>
<p class="tag">Which place best hits your comfort temperature over a date range</p>
</div>
<nav class="view-nav" aria-label="Views">
<a href="./" data-view="map">Weekly</a>
<a href="calendar" data-view="calendar">Calendar</a>
<a href="day" data-view="day">Day</a>
<a href="compare" data-view="compare" class="active">Compare</a>
</nav>
</div>
</header>
<main>
<!-- Locations to line up against each other. -->
<section class="controls">
<div class="cmp-locs">
<span class="cal-filter-label">Locations</span>
<ul id="cmp-loc-list" class="cmp-loc-list"></ul>
<div class="cmp-loc-actions">
<button type="button" id="cmp-add" class="find-btn"></button>
<button type="button" id="cmp-refresh" class="cmp-refresh-btn" hidden>Refresh comparison ↻</button>
</div>
</div>
</section>
<!-- The comfort target, what temperature to judge by, the tolerance band, and
the date range. Comfort/band/basis recompute instantly (no refetch); only
the date range or the location set trigger a data load. -->
<div id="cmp-params" class="cmp-params" hidden>
<div class="cmp-param cmp-comfort">
<div class="cmp-range-labels">
<span class="cmp-rl cmp-rl-comfort">Comfort <b id="cmp-comfort-val"></b></span>
<span class="cmp-rl cmp-rl-tol">Tolerance <b id="cmp-tol-val"></b></span>
</div>
<div class="cmp-ticks" id="cmp-ticks" aria-hidden="true">
<span class="cmp-tick tol" id="cmp-tick-tlo"></span>
<span class="cmp-tick" id="cmp-tick-lo"></span>
<span class="cmp-tick" id="cmp-tick-hi"></span>
<span class="cmp-tick tol" id="cmp-tick-thi"></span>
</div>
<div class="dual-range quad-range" id="cmp-slicer">
<div class="dual-track">
<span class="dual-fill dual-fill-tol" id="cmp-fill-tol"></span>
<span class="dual-fill" id="cmp-fill"></span>
</div>
<input id="cmp-tlo" type="range" min="30" max="100" step="1" class="thumb-tol" aria-label="Tolerance range lower bound" />
<input id="cmp-lo" type="range" min="30" max="100" step="1" aria-label="Comfort range lower bound" />
<input id="cmp-hi" type="range" min="30" max="100" step="1" aria-label="Comfort range upper bound" />
<input id="cmp-thi" type="range" min="30" max="100" step="1" class="thumb-tol" aria-label="Tolerance range upper bound" />
</div>
<span class="hint">Inner handles set your comfort range; outer handles set the tolerance range. Days in tolerance still count toward the score, scaled by how far past comfort they fall.</span>
</div>
<div class="cmp-param cmp-basis-block">
<span class="cal-filter-label">Judge each day by its</span>
<div class="metric-toggle" id="cmp-basis" role="group" aria-label="Temperature to compare">
<button type="button" data-basis="tmax" class="active">High</button>
<button type="button" data-basis="mean">Mean</button>
<button type="button" data-basis="tmin">Low</button>
<button type="button" data-basis="feels">Feels</button>
</div>
</div>
<div class="cmp-param cmp-season" id="cmp-season">
<span class="cal-filter-label">Time of year</span>
<div class="cmp-season-dd" id="cmp-season-dd"></div>
<span class="hint">Count only days in these seasons/months — re-ranks instantly.</span>
</div>
<div class="cmp-param cmp-range cal-range" id="cmp-range">
<div class="cal-range-head">
<span class="cal-filter-label">Date range</span>
<span class="hint">any span; longer loads take a moment</span>
</div>
<label>From <input id="cmp-start" type="month" /></label>
<label>To <input id="cmp-end" type="month" /></label>
<span class="hint">Editing the range arms Refresh — tap it to reload.</span>
</div>
</div>
<div id="cmp-head" class="cal-head" hidden></div>
<div class="placeholder" id="cmp-placeholder">
<p>Add two or more places to see which one best matches your comfort temperature
across a date range — the share of days that land in your comfort band, how
often it runs colder or warmer, and by how much.</p>
</div>
<!-- Baseline: every place's typical temperature on one shared axis, so their
baselines line up against each other and the shaded comfort range. -->
<section id="cmp-baseline" class="cmp-baseline" hidden></section>
<div id="cmp-results" class="cmp-results"></div>
<!-- Climate distribution, independent of the comfort filter: how each place's
days spread across a metric's Record-Low→Record-High categories, mirroring
the calendar's totals strip. Its own metric + share/count toggles. -->
<section id="cmp-dist" class="cmp-dist" hidden>
<div class="ct-head">
<div class="cmp-dist-controls">
<span class="cal-filter-label">Distribution by</span>
<div class="metric-toggle" id="cmp-dist-metric" role="group" aria-label="Distribution metric">
<button type="button" data-metric="tmax" class="active">High</button>
<button type="button" data-metric="tmin">Low</button>
<button type="button" data-metric="feels">Feels</button>
<button type="button" data-metric="humid">Humid</button>
<button type="button" data-metric="wind">Wind</button>
<button type="button" data-metric="gust">Gust</button>
<button type="button" data-metric="precip">Precip</button>
<button type="button" data-metric="dsr">Dry streak</button>
</div>
</div>
<label class="ct-count-toggle"><input type="checkbox" id="cmp-dist-count" /> Show count</label>
</div>
<div id="cmp-dist-body" class="cmp-dist-body"></div>
</section>
</main>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
2026-07-11 20:28:33 +00:00
<script type="module" src="compare.js"></script>
</body>
</html>