From 8588051141b4c907350ff683263da65d8873fe4d Mon Sep 17 00:00:00 2001
From: Emi Griffith
Date: Sun, 19 Jul 2026 18:48:33 -0700
Subject: [PATCH] Remove em-dashes from site copy and tighten the prose (#206)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Replace em-dashes in user-facing copy across the server-rendered pages,
static frontend views, and the strings the app injects at runtime, using
colons, commas, parentheses or full stops as the context wants. Data
placeholder glyphs (a lone "—" for a missing reading) are left alone,
since a hyphen there reads as a minus sign in temperature columns.
Also tighten the high-visibility surfaces (home hero and meta, about,
privacy, city and records ledes, glossary blurbs) toward a plainer,
more direct voice while keeping every factual claim intact.
Claude-Session: https://claude.ai/code/session_01XXxmNFy9cZ6Gh8Y9thZn62
---
static/app.js | 10 +++++-----
static/calendar.html | 10 +++++-----
static/calendar.js | 8 ++++----
static/chart.js | 10 +++++-----
static/compare.html | 10 +++++-----
static/compare.js | 4 ++--
static/day.html | 6 +++---
static/digest.js | 4 ++--
static/ios-install.js | 2 +-
static/legend.html | 14 +++++++-------
static/mappicker.js | 4 ++--
static/score.html | 6 +++---
static/score.js | 6 +++---
static/subscriptions.html | 8 ++++----
static/subscriptions.js | 12 ++++++------
15 files changed, 57 insertions(+), 57 deletions(-)
diff --git a/static/app.js b/static/app.js
index 9d28fba..b52df92 100644
--- a/static/app.js
+++ b/static/app.js
@@ -101,10 +101,10 @@ heroLocate?.addEventListener("click", () => {
// like the button did nothing.
locateMsg(
err.code === err.PERMISSION_DENIED
- ? "Location permission was declined — pick a spot on the map instead."
+ ? "Location permission was declined. Pick a spot on the map instead."
: err.code === err.TIMEOUT
? "That took too long. Try again, or pick a spot on the map."
- : "Your location isn't available right now — pick a spot on the map instead.",
+ : "Your location isn't available right now. Pick a spot on the map instead.",
);
},
{ enableHighAccuracy: false, timeout: 10000, maximumAge: 600000 },
@@ -255,7 +255,7 @@ function render(data) {
Check historical data→
-
${data.target_date} vs a typical day — tap a metric for the full breakdown
+
${data.target_date} vs a typical day. Tap a metric for the full breakdown
Search a place — or open this from a graded location on the map — to see how
+
Search a place, or open this from a graded location on the map, to see how
every day of the last two years graded against that spot's own climate history.
@@ -561,8 +561,8 @@ function renderTotals(visible) {
const total = buckets.reduce((n, b) => n + b.n, 0);
const head = wActive
- ? `${days.length.toLocaleString()} of ${visible.length.toLocaleString()} shown days match the weather filter — by ${title}:`
- : `${visible.length.toLocaleString()} days shown — by ${title}:`;
+ ? `${days.length.toLocaleString()} of ${visible.length.toLocaleString()} shown days match the weather filter, by ${title}:`
+ : `${visible.length.toLocaleString()} days shown, by ${title}:`;
// The strip prints each category's share by default, or the raw day count when the
// "Show count" checkbox (state: showCount) is ticked.
const countToggle =
@@ -583,7 +583,7 @@ function renderKey() {
const segs = steps.map(([lab, d]) =>
`
${lab}
`).join("");
- keyEl.innerHTML = `
Days since last rain — dry streak (caps at ${DRY_CAP} days)
+ keyEl.innerHTML = `
Days since last rain: dry streak (caps at ${DRY_CAP} days)
${segs}
${GUIDE_LINK}`;
return;
}
diff --git a/static/chart.js b/static/chart.js
index ace1159..d48dfae 100644
--- a/static/chart.js
+++ b/static/chart.js
@@ -196,8 +196,8 @@ export function tempChart(key, days, n, xFor, C) {
legend:
`${s.label} (dashed = median)` +
`Band shaded by grade tier` +
- `Points labeled value · percentile — grade from the band tier (scale below)`,
- subtitle: `${s.label} — recent trend vs normal`,
+ `Points labeled value · percentile; grade from the band tier (scale below)`,
+ subtitle: `${s.label}: recent trend vs normal`,
aria: `Recent ${s.label.toLowerCase()} versus the normal range.`,
});
}
@@ -220,7 +220,7 @@ export function precipChart(days, n, xFor, C) {
`Precipitation (dashed = median)` +
`Band shaded by rain-intensity tier` +
`Rain days labeled amount · percentile (rain scale below)`,
- subtitle: "Precipitation — daily totals vs normal",
+ subtitle: "Precipitation: daily totals vs normal",
aria: "Daily precipitation totals versus the normal range.",
});
}
@@ -237,9 +237,9 @@ export function dryChart(days, n, xFor, C) {
fmtLabel: (v) => `${Math.round(v)}`,
labelOn: (v) => v > 0, // label the streak length; rain days (0) just show the dot
legend:
- `Days since last rain — dry streak` +
+ `Days since last rain: dry streak` +
`Rain that day (streak = 0)`,
- subtitle: "Dry streak — days since last measurable rain",
+ subtitle: "Dry streak: days since last measurable rain",
aria: "Days since last measurable rain, as a line.",
});
}
diff --git a/static/compare.html b/static/compare.html
index 5d7eb6f..17e2e2c 100644
--- a/static/compare.html
+++ b/static/compare.html
@@ -3,7 +3,7 @@
- Thermograph — compare comfort
+ Thermograph: compare comfort
-
+
@@ -116,7 +116,7 @@
Time of year
- Count only days in these seasons/months — re-ranks instantly.
+ Count only days in these seasons/months; re-ranks instantly.
@@ -126,7 +126,7 @@
- Editing the range arms Load — tap it to reload.
+ Editing the range arms Load; tap it to reload.
@@ -142,7 +142,7 @@
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
+ 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.
`;
// Key under the bar: a color swatch + name + share for every non-empty bucket, in
// the same cold→hot order as the bar, so small spans are still clearly labeled. On
@@ -510,7 +510,7 @@ function renderResults() {
const span = `${monthLabel(range.start)} – ${monthLabel(range.end)}`;
const winName = namePrimary(win.loc.name);
const lead = scored.length > 1
- ? `${winName} is the best match for ${fmtTemp(lo)}–${fmtTemp(hi)} — score ${Math.round(win.s.score)}/100`
+ ? `${winName} is the best match for ${fmtTemp(lo)}–${fmtTemp(hi)}: score ${Math.round(win.s.score)}/100`
: `${winName}: match score ${Math.round(win.s.score)}/100 for ${fmtTemp(lo)}–${fmtTemp(hi)}`;
head.hidden = false;
head.innerHTML = `
${lead}
` +
diff --git a/static/day.html b/static/day.html
index 4f88eab..71b0c1d 100644
--- a/static/day.html
+++ b/static/day.html
@@ -3,7 +3,7 @@
- Thermograph — a single day
+ Thermograph: a single day
-
+
@@ -76,7 +76,7 @@
-
Pick a place and a day — or open this from a day on the map or calendar — to see
+
Pick a place and a day, or open this from a day on the map or calendar, to see
the value at every tier boundary for that day's typical climate.
diff --git a/static/digest.js b/static/digest.js
index c408d65..a34b060 100644
--- a/static/digest.js
+++ b/static/digest.js
@@ -48,7 +48,7 @@ for (const form of document.querySelectorAll("form[data-digest]")) {
});
const data = await res.json().catch(() => ({}));
if (status) {
- status.textContent = data.message || "Something went wrong — try again.";
+ status.textContent = data.message || "Something went wrong. Try again.";
status.hidden = false;
}
if (res.ok) {
@@ -60,7 +60,7 @@ for (const form of document.querySelectorAll("form[data-digest]")) {
}
} catch {
if (status) {
- status.textContent = "Couldn't reach the server — try again.";
+ status.textContent = "Couldn't reach the server. Try again.";
status.hidden = false;
}
} finally {
diff --git a/static/ios-install.js b/static/ios-install.js
index 9ce5f72..183fa2d 100644
--- a/static/ios-install.js
+++ b/static/ios-install.js
@@ -49,7 +49,7 @@ function build() {
'' +
'' +
'
Add Thermograph to your Home Screen' +
- 'Tap Share, then Add to Home Screen — it’s how to get weather alerts on iPhone.
' +
+ 'Tap Share, then Add to Home Screen. It’s how to get weather alerts on iPhone.
' +
'';
el.querySelector(".ios-a2hs-x").addEventListener("click", () => {
remember();
diff --git a/static/legend.html b/static/legend.html
index 5216ed4..cd33c7e 100644
--- a/static/legend.html
+++ b/static/legend.html
@@ -3,7 +3,7 @@
- Thermograph — reading the grades
+ Thermograph: reading the grades
-
+
@@ -66,17 +66,17 @@
decades of local records, then reports the percentile where the day falls in it.
So a 60° day can be “Above Normal” in one place or season and
“Below Normal” in another. That's why the categories read
- “Above/Below Normal”, “High/Low”, and “Near Record” —
+ “Above/Below Normal”, “High/Low”, and “Near Record”,
never “hot” or “cold”.
-
Grade scale — percentile of the local ±7-day history
+
Grade scale: percentile of the local ±7-day history
-
Rain intensity — percentile among rain days
+
Rain intensity: percentile among rain days
Precipitation is graded only across days that actually saw rain, so
“Heavy” means heavy for a rainy day here. Dry days are colored by
their dry streak instead (below).
@@ -87,14 +87,14 @@
The metrics
High / Low
The day's highest and lowest air temperature (°F).
-
Feels
Apparent temperature — what the air actually felt like once humidity
+
Feels
Apparent temperature: what the air actually felt like once humidity
and wind are factored in, taking whichever apparent extreme (heat-index high or
wind-chill low) sits further from a temperate baseline, graded against its own history.
Humid
Absolute humidity: grams of water vapor per cubic meter of air (g/m³).
Wind
Average sustained wind speed (mph).
Gust
Peak wind gust for the day (mph).
Precip
Total precipitation (inches), graded by intensity among rain days.
-
Dry streak
Consecutive days since the last measurable rain — the color deepens
+
Dry streak
Consecutive days since the last measurable rain; the color deepens
the longer it's been dry, and resets to blue on a rain day.
diff --git a/static/mappicker.js b/static/mappicker.js
index 10ffc4e..d1de4b1 100644
--- a/static/mappicker.js
+++ b/static/mappicker.js
@@ -121,7 +121,7 @@ function renderSug(list) {
if (!shown.length) { sugEl.hidden = true; return; }
shown.forEach((r) => {
const li = document.createElement("li");
- li.innerHTML = `${r.name} — ${[r.admin1, r.country].filter(Boolean).join(", ")}`;
+ li.innerHTML = `${r.name}, ${[r.admin1, r.country].filter(Boolean).join(", ")}`;
// A picked search result is an unambiguous choice — drop the pin, recenter,
// and select it right away (the map is there for manual/fine picks).
li.onclick = () => {
@@ -146,7 +146,7 @@ function setPin(lat, lon, zoom) {
else marker = L.marker([lat, lon], pinIcon ? { icon: pinIcon } : undefined).addTo(map);
map.setView([lat, lon], zoom || map.getZoom());
confirmBtn.disabled = false;
- hintEl.textContent = "Pin set — confirm below, or tap elsewhere to move it.";
+ hintEl.textContent = "Pin set. Confirm below, or tap elsewhere to move it.";
}
function finish(p) {
diff --git a/static/score.html b/static/score.html
index c75880d..69af6e5 100644
--- a/static/score.html
+++ b/static/score.html
@@ -3,7 +3,7 @@
- Thermograph — climate score
+ Thermograph: climate score
-
+
@@ -63,7 +63,7 @@
-
Pick a place — or open this from the map or calendar — to see how much its
+
Pick a place, or open this from the map or calendar, to see how much its
recent climate has drifted from its long-term normal, metric by metric.
${def}
Heat-stress days (peak wet bulb ≥ ${esc(String(thr))}): ${f6}% of recent days
- vs ${f45}% across ${baseYrs}${delta} — the rest are normal.
`;
+ vs ${f45}% across ${baseYrs}${delta}. The rest are normal.`;
}
// One metric score card. The tier and its direction stack under the score on
@@ -208,9 +208,9 @@ function sentencesHTML(annual) {
.map((m) => {
const mid = m.per_q && m.per_q.find((q) => q.q === 50);
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}
`;
+ 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.
`;
+ if (!lines.length) return `
Every metric is close to its long-term normal here, with no notable recent drift.
Thermograph can watch any city and tell you when its weather turns
- unusually extreme for that place — a heat spell, a cold snap, heavy rain — graded
+ unusually extreme for that place (a heat spell, a cold snap, heavy rain), graded
against ~45 years of local climate history.
-
Pick a city and the metrics to watch — high, low, feels-like, rain, wind…
+
Pick a city and the metrics to watch: high, low, feels-like, rain, wind…
Set a threshold. Alert when a day passes, say, the 97th percentile for
that location. Higher = rarer, so fewer but more significant alerts.
-
Get notified in-app (and via OS push on this device) when a recorded day — or
- the upcoming forecast — crosses your threshold. At most one notification per week per alert.
+
Get notified in-app (and via OS push on this device) when a recorded day, or
+ the upcoming forecast, crosses your threshold. At most one notification per week per alert.
For example: “Tell me when Tokyo's high passes the 97th percentile.”