From e82323f11a0efd4095d1f51a799e8d2fd99d6d45 Mon Sep 17 00:00:00 2001 From: Emi Griffith Date: Sun, 19 Jul 2026 16:37:42 -0700 Subject: [PATCH] Clarify wet bulb, add heat-stress-day share, frame total as net change (#197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Explain on the page what wet-bulb temperature measures (the evaporative-cooling ceiling on shedding heat), so the metric isn't opaque. - Report the share of heat-stress "wet-bulb" days (peak wet bulb >= 26 C) vs normal days, recent window vs the full record — mirroring the precip wet-day frequency. - Present the overall total as a direction-agnostic net change (magnitude only), not "warmer/cooler"; per-metric cards still carry direction. Bumps the score cache version. --- static/score.js | 24 +++++++++++++++++++++--- static/style.css | 6 ++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/static/score.js b/static/score.js index e1a9f5a..3b7a3a7 100644 --- a/static/score.js +++ b/static/score.js @@ -111,15 +111,16 @@ function render(data) { ${ov.score}
${esc(ov.grade)} - ${recentYrs} vs ${baseYrs} · ${s.n_recent.toLocaleString()} recent days scored + Net change · ${recentYrs} vs ${baseYrs} · ${s.n_recent.toLocaleString()} recent days scored
-

0 = no change from the long-term normal · 100 = an extreme shift. - Temperature, feels-like and humidity are weighted most.

+

A net-change total across all metrics: 0 = no change from the long-term + normal · 100 = an extreme shift. Temperature, feels-like and humidity are weighted most.

`; // ---- per-metric cards (annual) ---- const cards = METRIC_ORDER.map((k) => metricCard(annual.metrics[k])).join(""); + const wbNote = wetbulbNote(annual.metrics.wetbulb, baseYrs); // ---- by-season rows ---- const seasonRows = SEASON_ORDER.map((sk) => { @@ -138,6 +139,7 @@ function render(data) { scoreBody.innerHTML = `
${cards}
+ ${wbNote}

By season

${METRIC_ORDER.map((k) => shortLabel(k)).join(" · ")}

@@ -150,6 +152,22 @@ function render(data) { wireSummaryToggle(); } +// Explains what wet bulb is and reports the share of heat-stress ("wet-bulb") +// days vs normal days, recent vs baseline. Re-rendered on unit change. +function wetbulbNote(m, baseYrs) { + const def = `Wet bulb is how cool evaporation — like sweat — can make you in the + current air. When it climbs, sweat stops shedding heat and high temperatures turn dangerous.`; + if (!m || m.score == null || !m.freq) { + return `

${def}

`; + } + const thr = fmtTemp(m.freq.threshold_f); + const { f6, f45, d } = m.freq; + const delta = d ? ` (${d >= 0 ? "+" : ""}${d} pts)` : ""; + return `

${def} + Heat-stress days (peak wet bulb ≥ ${esc(String(thr))}): ${f6}% of recent days + vs ${f45}% across ${baseYrs}${delta} — the rest are normal.

`; +} + // One metric score card (reuses .normal-card). Null metrics show a muted reason. function metricCard(m) { if (!m) return ""; diff --git a/static/style.css b/static/style.css index 938933a..4700ffe 100644 --- a/static/style.css +++ b/static/style.css @@ -1732,6 +1732,12 @@ td.rec-date { color: var(--muted); font-size: 13px; } .score-section { margin: 20px 0; } .score-legend { font-size: 12px; color: var(--muted); margin: -6px 0 10px; } +/* Wet-bulb explainer + heat-stress-day share. */ +.score-callout { + background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; + padding: 12px 14px; margin: 14px 0 4px; font-size: 13px; line-height: 1.5; color: var(--text); +} + /* One row per season: name · overall · a chip per metric. */ .season-scores { display: grid; grid-template-columns: 64px 40px 1fr; align-items: center;