-
Comfort & tolerance
+
+ Comfort
+ Tolerance
+
+
+
+
+
+
+
diff --git a/static/compare.js b/static/compare.js
index 01de8ec..967f70b 100644
--- a/static/compare.js
+++ b/static/compare.js
@@ -151,7 +151,12 @@ const loInput = document.getElementById("cmp-lo");
const hiInput = document.getElementById("cmp-hi");
const tloInput = document.getElementById("cmp-tlo");
const thiInput = document.getElementById("cmp-thi");
-const rangeVal = document.getElementById("cmp-range-val");
+const comfortValEl = document.getElementById("cmp-comfort-val");
+const tolValEl = document.getElementById("cmp-tol-val");
+const tickEls = {
+ tlo: document.getElementById("cmp-tick-tlo"), lo: document.getElementById("cmp-tick-lo"),
+ hi: document.getElementById("cmp-tick-hi"), thi: document.getElementById("cmp-tick-thi"),
+};
const fillEl = document.getElementById("cmp-fill");
const fillTolEl = document.getElementById("cmp-fill-tol");
const basisToggle = document.getElementById("cmp-basis");
@@ -369,9 +374,17 @@ function rankCard(loc, s, rank) {
parts.map((p) => ` `).join("") +
`
`;
// 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.
+ // the same cold→hot order as the bar, so small spans are still clearly labeled. On
+ // desktop each label is positioned at its segment's midpoint (the ends anchored to
+ // the bar edges); on mobile it falls back to a plain wrapping row.
+ let acc = 0;
const key = `
` +
- parts.map((p) => ` ${p.label} ${pct(p.w)} `).join("") +
+ parts.map((p, i) => {
+ const mid = acc + p.w / 2; acc += p.w;
+ const pos = i === 0 ? "left:0" : i === parts.length - 1 ? "right:0" : `left:${mid}%`;
+ const edge = i === 0 ? " cmp-key-first" : i === parts.length - 1 ? " cmp-key-last" : "";
+ return ` ${p.label} ${pct(p.w)} `;
+ }).join("") +
`
`;
const bands = `
${pct(s.tolPct)} within tolerance · typically ${deg(s.mad)} off comfort
`;
const sub = win ? `
★ Best match · ${s.n} days` : `${s.n} days`;
@@ -508,11 +521,17 @@ locList.addEventListener("click", (e) => {
const pctPos = (v) => (v - R_MIN) / (R_MAX - R_MIN) * 100;
function syncSlicer() {
tloInput.value = tlo; loInput.value = lo; hiInput.value = hi; thiInput.value = thi;
- rangeVal.textContent = `${fmtTemp(lo)}–${fmtTemp(hi)} · tolerance ${fmtTemp(tlo)}–${fmtTemp(thi)}`;
+ comfortValEl.textContent = `${fmtTemp(lo)}–${fmtTemp(hi)}`;
+ tolValEl.textContent = `${fmtTemp(tlo)}–${fmtTemp(thi)}`;
fillEl.style.left = `${pctPos(lo)}%`;
fillEl.style.right = `${100 - pctPos(hi)}%`;
fillTolEl.style.left = `${pctPos(tlo)}%`;
fillTolEl.style.right = `${100 - pctPos(thi)}%`;
+ // A temperature marker above each handle (the four band borders).
+ for (const [k, v] of [["tlo", tlo], ["lo", lo], ["hi", hi], ["thi", thi]]) {
+ tickEls[k].style.left = `${pctPos(v)}%`;
+ tickEls[k].textContent = fmtTemp(v);
+ }
}
function slicerChanged() {
lsSet(CMP.lo, String(lo)); lsSet(CMP.hi, String(hi));
diff --git a/static/style.css b/static/style.css
index cf04eb2..34373cb 100644
--- a/static/style.css
+++ b/static/style.css
@@ -864,6 +864,14 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 24px 60px; }
.cmp-key-item { display: inline-flex; align-items: center; gap: 6px; }
.cmp-key-item b { color: var(--text); font-weight: 700; }
.cmp-sw { width: 12px; height: 12px; border-radius: 3px; flex: 0 0 auto; }
+/* Desktop: spread the labels across the bar's width, each centred under its own
+ segment (first/last pinned to the ends so they never spill past the edge). */
+@media (min-width: 641px) {
+ .cmp-key { position: relative; display: block; height: 18px; }
+ .cmp-key-item { position: absolute; transform: translateX(-50%); white-space: nowrap; }
+ .cmp-key-first { transform: none; }
+ .cmp-key-last { transform: none; }
+}
.cmp-bands { margin: 8px 0 0; font-size: 12.5px; color: var(--muted); }
.cmp-bands b { color: var(--text); }
@@ -922,6 +930,15 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 24px 60px; }
.cmp-skel-badge, .cmp-skel-name, .cmp-skel-big, .cmp-skel-bar { animation: none; }
}
+/* Comfort vs tolerance shown as two separate labels, and a temperature marker above
+ each of the four handles (the band borders). */
+.cmp-range-labels { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 0 0 6px; font-size: 13px; color: var(--muted); }
+.cmp-rl b { color: var(--text); font-size: 15px; margin-left: 2px; }
+.cmp-rl-comfort b { color: var(--accent); }
+.cmp-ticks { position: relative; height: 17px; }
+.cmp-tick { position: absolute; transform: translateX(-50%); font-size: 11px; font-weight: 700; color: var(--text); white-space: nowrap; }
+.cmp-tick.tol { color: var(--muted); font-weight: 600; }
+
/* Dual-handle comfort slicer: two range inputs overlaid on a shared track, with a
fill marking the selected span. Only the thumbs take pointer events, so both
handles stay grabbable even where the inputs overlap. */