diff --git a/static/score.js b/static/score.js index 8ad3d3a..9f18fa8 100644 --- a/static/score.js +++ b/static/score.js @@ -6,15 +6,10 @@ import { fmtTemp, onUnitChange } from "./units.js"; import "./account.js"; // header sign-in entry + notification bell import { getJSON, TTL, prefetchViews } from "./cache.js"; import { initFindButton, setFindLabel } from "./mappicker.js"; -import { TIER_COLORS, pctOrd, fmtPrecip, fmtWind, fmtHumid, esc, placeLabel } from "./shared.js"; +import { TIER_COLORS, esc, placeLabel } from "./shared.js"; -// Display order (site convention leads with Precip), and how each metric's raw -// per-percentile value is formatted in the detail table. +// Display order (site convention leads with Precip). const METRIC_ORDER = ["precip", "tmax", "tmin", "feels", "humid", "wetbulb", "wind", "gust"]; -const FMT = { - tmax: fmtTemp, tmin: fmtTemp, feels: fmtTemp, wetbulb: fmtTemp, - humid: fmtHumid, wind: fmtWind, gust: fmtWind, precip: fmtPrecip, -}; const SEASON_NAMES = { djf: "Winter", mam: "Spring", jja: "Summer", son: "Fall" }; const SEASON_ORDER = ["djf", "mam", "jja", "son"]; @@ -210,8 +205,8 @@ function sentencesHTML(annual) { .filter((m) => m && m.score != null && m.score >= 15) .map((m) => { const mid = m.per_q && m.per_q.find((q) => q.q === 50); - const where = mid ? ` Its recent median now lands near the ${pctOrd(mid.pct)} percentile of the full record.` : ""; - return `
  • ${esc(m.label)}: ${esc(m.grade)} — about ${Math.abs(m.bias).toFixed(0)} percentile points ${esc(m.direction)}.${where}
  • `; + const where = mid ? ` At the median, recent readings sit about ${Math.abs(mid.d)} points ${mid.d >= 0 ? "higher" : "lower"} than the seasonal norm.` : ""; + return `
  • ${esc(m.label)}: ${esc(m.grade)} — about ${Math.abs(m.bias).toFixed(0)} percentile points ${esc(m.direction)} on average.${where}
  • `; }); if (!lines.length) return `

    Every metric is close to its long-term normal here — no notable recent drift.

    `; return `

    What has shifted the most:

    `; @@ -242,21 +237,20 @@ function scoreTableHTML(s) { ${head}${rows}${overallRow}`; } -// The annual per-percentile detail: for each category, the recent value and where -// it lands in the 45-year record. +// The per-percentile detail: for each band, the mean shift (in percentile points) +// averaged across the four seasons — the differentials the score is built from. function perQTableHTML(annual) { const rows = METRIC_ORDER .map((k) => annual.metrics[k]) .filter((m) => m && m.score != null && m.per_q && m.per_q.length) .map((m) => { - const fmt = FMT[m.key] || ((v) => v); const cells = m.per_q.map((q) => - `p${q.q}: ${esc(String(fmt(q.v6)))} → ${pctOrd(q.pct)} (${q.d >= 0 ? "+" : ""}${q.d})`).join(""); + `p${q.q}: ${q.d >= 0 ? "+" : ""}${q.d}`).join(""); return `${esc(m.label)}${cells}`; }).join(""); if (!rows) return ""; - return `

    Annual percentile detail

    -

    Each recent-years percentile value, and where it lands in the full record (▲/▼ = shift in percentile points).

    + return `

    Shift by percentile band

    +

    The mean shift at each percentile band, averaged across all four seasons (percentile points; ▲ higher / ▼ lower than the seasonal norm).

    ${rows}
    `; } diff --git a/static/style.css b/static/style.css index 0d77568..d4a629e 100644 --- a/static/style.css +++ b/static/style.css @@ -1737,8 +1737,11 @@ td.rec-date { color: var(--muted); font-size: 13px; } padding: 12px 14px; margin: 14px 0 4px; font-size: 13px; line-height: 1.5; color: var(--text); } -/* By-season scores: seasons as rows, one aligned column per metric. */ -.season-table th:first-child, .season-table td:first-child { text-align: left; } +/* By-season scores: seasons as rows, one uniform column per metric so every + metric lines up vertically across the seasons. Fixed layout keeps the columns + equal width; the min-width lets it scroll (not squash) on a phone. */ +.season-table { table-layout: fixed; width: 100%; min-width: 620px; max-width: 740px; } +.season-table th:first-child, .season-table td:first-child { width: 62px; text-align: left; } /* Summary reveal — pill button + caret, mirrors the season-expand pattern. */ .summary-toggle {