From 9823fd47ec651da9b2c13f97d51d17b3edc01230 Mon Sep 17 00:00:00 2001 From: Emi Griffith Date: Sun, 19 Jul 2026 17:22:38 -0700 Subject: [PATCH] Stack score-card tier labels; clarify the wet-bulb explainer (#201) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On a narrow (2-up) phone card, a long grade like 'Extreme shift — windier' crammed into the card's top-right corner and wrapped into a cluster. Restructure each card to a clean vertical stack — metric name, score, tier, detail line — so the label always has room, on mobile and desktop alike. Also reword the wet-bulb explainer to state plainly what it is (the lowest temperature evaporating sweat can cool you to). --- static/score.js | 28 +++++++++++++++------------- static/style.css | 9 +++++++++ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/static/score.js b/static/score.js index 9f18fa8..8ba4d6d 100644 --- a/static/score.js +++ b/static/score.js @@ -148,8 +148,8 @@ function render(data) { // 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.`; + const def = `Wet bulb is the lowest temperature that evaporating sweat can cool you to. + When it climbs, sweat can't shed heat fast enough and hot days turn dangerous.`; if (!m || m.score == null || !m.freq) { return `

${def}

`; } @@ -161,28 +161,30 @@ function wetbulbNote(m, baseYrs) { vs ${f45}% across ${baseYrs}${delta} — the rest are normal.

`; } -// One metric score card (reuses .normal-card). Null metrics show a muted reason. +// One metric score card. The tier and its direction stack under the score on +// their own lines (rather than crammed top-right), so a long grade like +// "Extreme shift — windier" never clusters in the corner on a narrow card. function metricCard(m) { if (!m) return ""; if (m.score == null) { - return `
-

${esc(m.label)}

+ return `
+

${esc(m.label)}

${esc(m.reason || "no data")}
`; } - return `
-

${esc(m.label)}

${esc(m.grade)}
+ return `
+

${esc(m.label)}

${m.score}
-
${scoreDirection(m)}
+
${esc(m.tier)}
+
${scoreDetail(m)}
`; } -// A short "shifted N pts warmer" line for a metric card. -function scoreDirection(m) { - if (m.score < 15) return "steady vs the long-term normal"; - const pts = Math.abs(m.bias).toFixed(0); - return `~${pts} pts ${esc(m.direction)}`; +// The muted detail line under a card's tier — the signed drift, or a steady note. +function scoreDetail(m) { + if (m.score < 15) return "close to the long-term normal"; + return `~${Math.abs(m.bias).toFixed(0)} pts ${esc(m.direction)}`; } function seasonCell(m) { diff --git a/static/style.css b/static/style.css index d4a629e..7c5f5c9 100644 --- a/static/style.css +++ b/static/style.css @@ -1731,6 +1731,15 @@ td.rec-date { color: var(--muted); font-size: 13px; } .score-section { margin: 20px 0; } +/* Score metric cards: name · score · tier · detail, each on its own line so a + long grade never crams into the corner on a narrow (2-up) phone card. */ +.score-card h3 { margin-bottom: 6px; } +.score-card .nc-tier { + font-size: 12px; font-weight: 700; margin-top: 3px; line-height: 1.25; + color: color-mix(in oklab, var(--cat, var(--muted)), var(--text) 22%); +} +.score-card .range { margin-top: 1px; } + /* Wet-bulb explainer + heat-stress-day share. */ .score-callout { background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px;