- Compare: move the "Judge each day by its" basis toggle out of the filter sheet into the inline comfort card above the results (a scoring control, like the comfort slider). Handler is id-based, so no JS change for the move. - Metric selector is duplicated, not relocated: revert the sheetOnly relocation in filtersheet.js; keep the inline selector visible on all viewports and add a synced copy inside each page's filter sheet (mobile-only via CSS). The sheet copy clones the inline buttons; a single setter (setDistMetric / setColorMetric) drives the shared state and reflects the active metric on both, so picking any of the 8 metrics in either selector syncs the other and re-renders. Applies to compare's "Distribution by" and calendar's "Color the calendar by". Frontend-only; no backend or payload change.
164 lines
8.6 KiB
HTML
164 lines
8.6 KiB
HTML
<!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. -->
|
|
<!-- Comfort/tolerance target — the primary knob, kept inline above the results
|
|
(never inside the mobile filter sheet). Recomputes the ranking instantly. -->
|
|
<div id="cmp-comfort" class="cmp-comfort-wrap" hidden>
|
|
<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>
|
|
<!-- Which temperature to judge each day by — a scoring control, so it sits with
|
|
the comfort slider above the results, not in the filter sheet. -->
|
|
<div class="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>
|
|
|
|
<div id="cmp-params" class="cmp-params" hidden>
|
|
<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 Load — tap it to reload.</span>
|
|
<button type="button" id="cmp-refresh-sheet" class="cmp-refresh-btn" hidden>Load / Refresh ↻</button>
|
|
</div>
|
|
|
|
<!-- A synced copy of the "Distribution by" selector (below), for the phone
|
|
sheet; buttons are cloned from the inline one in JS. Hidden on desktop. -->
|
|
<div class="cmp-param cmp-dist-metric-block">
|
|
<span class="cal-filter-label">Distribution by</span>
|
|
<div class="metric-toggle" id="cmp-dist-metric-sheet" role="group" aria-label="Distribution metric (in filters)"></div>
|
|
</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>
|
|
<script type="module" src="compare.js"></script>
|
|
</body>
|
|
</html>
|