diff --git a/static/day.js b/static/day.js index 8405a9a..41f0931 100644 --- a/static/day.js +++ b/static/day.js @@ -132,6 +132,22 @@ function render(data) { ].join(""); } +// Collapse a space-separated unit shared by both bounds ("17.3 g/m³–19.9 g/m³" +// → "17.3–19.9 g/m³") so ranges fit the narrow value column on phones. Attached +// units (76°, 0.25") pass through untouched. +function fmtRange(fmt, lo, hi) { + const a = fmt(lo), b = fmt(hi); + const i = a.lastIndexOf(" "); + if (i > 0 && b.endsWith(a.slice(i))) return `${a.slice(0, i)}–${b}`; + return `${a}–${b}`; +} +// The unit-less value for the ◀ marker — the unit is already on the range beside +// it and in the card's summary, and dropping it keeps the marker on one line. +const bareVal = (fmt, v) => { + const s = fmt(v), i = s.lastIndexOf(" "); + return i > 0 ? s.slice(0, i) : s; +}; + // One metric card: an observed summary line + the tier ladder (highest tier on // top). The tier the observed value falls into is highlighted with its value. function ladderCard(title, m, fmt, kind) { @@ -153,7 +169,7 @@ function ladderCard(title, m, fmt, kind) { ? `median ${fmt(m.ladder.median)}` : `${m.ladder.rain_days.toLocaleString()} rain days · dry ${m.ladder.dry_pct}%`; const note = `${noteLeft}` + - `Historical Range ${fmt(m.ladder.min)}–${fmt(m.ladder.max)}`; + `Historical Range ${fmtRange(fmt, m.ladder.min, m.ladder.max)}`; const rows = m.ladder.tiers.map((t) => { const active = t.c === activeClass ? " active" : ""; @@ -163,9 +179,9 @@ function ladderCard(title, m, fmt, kind) { if (t.c === "dry") { val = t.range; pct = ""; } else if (t.hi == null) val = `> ${fmt(t.lo)}`; // top tier: strictly beyond p99 else if (t.lo == null) val = `< ${fmt(t.hi)}`; // bottom tier: strictly below p1 - else val = `${fmt(t.lo)}–${fmt(t.hi)}`; + else val = fmtRange(fmt, t.lo, t.hi); const marker = t.c === activeClass && obs - ? `◀ ${fmt(obs.value)}` : ""; + ? `◀ ${bareVal(fmt, obs.value)}` : ""; return `
${t.label} diff --git a/static/style.css b/static/style.css index a86365c..26a0f40 100644 --- a/static/style.css +++ b/static/style.css @@ -459,10 +459,12 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 24px 60px; } .day-step:disabled { opacity: .4; cursor: default; } /* Metric cards: one column on phones, side by side on monitors so the page - doesn't run as a single long strip of full-width ladders. */ -#day-body { display: grid; grid-template-columns: 1fr; gap: 16px; align-items: start; } -@media (min-width: 1000px) { #day-body { grid-template-columns: repeat(2, 1fr); } } -@media (min-width: 3400px) { #day-body { grid-template-columns: repeat(3, 1fr); } } + doesn't run as a single long strip of full-width ladders. minmax(0, 1fr) + (not bare 1fr, whose min is the content) so one wide ladder row can't inflate + the shared column track past the viewport and push the whole page off-center. */ +#day-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; } +@media (min-width: 1000px) { #day-body { grid-template-columns: repeat(2, minmax(0, 1fr)); } } +@media (min-width: 3400px) { #day-body { grid-template-columns: repeat(3, minmax(0, 1fr)); } } .ladder-card { background: var(--surface); border: 1px solid var(--border); @@ -502,10 +504,14 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 24px 60px; } .ladder-sw { width: 14px; height: 14px; border-radius: 4px; } .ladder-label { font-weight: 700; color: color-mix(in oklab, var(--cat, var(--text)), var(--text) 22%); } .ladder-pct { color: var(--muted); font-size: 12px; } -.ladder-val { justify-self: end; font-variant-numeric: tabular-nums; white-space: nowrap; } +/* Value ranges may wrap (long unit strings like "8.1 g/m³–12.9 g/m³" on narrow + phones) — nowrap here would widen the row past the card and scroll the page. */ +.ladder-val { justify-self: end; text-align: right; font-variant-numeric: tabular-nums; } /* Observed marker: stays in the rightmost column but reads from its left edge, so the arrow sits right beside the value range it points at. */ .ladder-mk { justify-self: start; min-width: 0; } +/* Markers are unit-less ("◀ 11.5") so nowrap can't push them past the card — + the widest (precip, ◀ 0.25") bleeds a few px into the row padding at most. */ .ladder-mark { color: var(--accent); font-weight: 800; white-space: nowrap; font-size: 12.5px; } @@ -857,10 +863,13 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 24px 60px; } #cal-tip .tt-type { font-size: 13.5px; margin: 1px 0 5px; padding-bottom: 5px; } #cal-tip .tt-grid { column-gap: 8px; row-gap: 2px; } /* Day ladder on mobile: tighten the fixed tracks but keep every column (including - the percentile range) so the ranges still line up down the ladder. */ + the percentile range) so the ranges still line up down the ladder. Slack moved + from the pct/marker tracks to the value column keeps the longest range + ("17.3–19.9 g/m³", ~88px) on one line down to ~375px screens; narrower than + that it wraps at the unit. The label track can't give ("Above Normal" ≈ 89px). */ .day-nav { width: 100%; } .day-date { flex: 1; } - .ladder-row { grid-template-columns: 13px 90px 54px 1fr 48px; column-gap: 8px; font-size: 12.5px; } + .ladder-row { grid-template-columns: 13px 90px 46px 1fr 42px; column-gap: 8px; font-size: 12.5px; } header { padding: 14px 16px; } h1 { font-size: 19px; }