From 4f6716283b7b9f2ff61af37c75f35f848d334b44 Mon Sep 17 00:00:00 2001 From: Emi Griffith Date: Wed, 15 Jul 2026 22:42:59 -0700 Subject: [PATCH] Mobile hamburger nav; crisp SVG logo; month travel-note callout (#117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Collapse the view navigation into a hamburger menu on phones. The nav is wrapped in a
(pure CSS, no JS — so it works on the crawlable SEO pages too): transparent (display:contents) on desktop so the tabs render inline, a dropdown behind a hamburger under 640px. The °F/°C toggle, bell and account stay in the header bar; units.js/account.js now anchor their injected controls on the wrapper. - Replace the header logo: the ▚ glyph was a rotated Unicode char that fonts rendered inconsistently (warped). Use a crisp inline SVG of the two accent squares (currentColor) across all headers. - Month pages: turn the plain "Visiting in ?" line into a bordered callout with a CTA button, matching the city page's travel box. Verified in Firefox and Chromium at desktop and 390px, light and dark: desktop nav inline, mobile hamburger opens the dropdown, logo crisp, travel note styled. --- static/account.js | 4 +-- static/calendar.html | 7 +++-- static/compare.html | 7 +++-- static/day.html | 7 +++-- static/index.html | 7 +++-- static/legend.html | 7 +++-- static/style.css | 58 +++++++++++++++++++++++++++++++-------- static/subscriptions.html | 7 +++-- static/units.js | 4 +-- 9 files changed, 81 insertions(+), 27 deletions(-) diff --git a/static/account.js b/static/account.js index fadc900..23fd273 100644 --- a/static/account.js +++ b/static/account.js @@ -259,8 +259,8 @@ function ensureAcctEl() { if (!acctEl) { acctEl = document.createElement("div"); acctEl.className = "acct"; - const nav = brand.querySelector(".view-nav"); - brand.insertBefore(acctEl, nav); // top-right, just left of the view tabs + const anchor = brand.querySelector(".nav-menu") || brand.querySelector(".view-nav"); + brand.insertBefore(acctEl, anchor); // top-right, just left of the nav menu } return acctEl; } diff --git a/static/calendar.html b/static/calendar.html index 6678ea6..8b20f87 100644 --- a/static/calendar.html +++ b/static/calendar.html @@ -29,16 +29,19 @@
- +

Thermograph · Calendar

-
diff --git a/static/compare.html b/static/compare.html index f5322b8..a5ed789 100644 --- a/static/compare.html +++ b/static/compare.html @@ -29,17 +29,20 @@
- +

Thermograph · Compare

Which place best hits your comfort temperature over a date range

-
diff --git a/static/day.html b/static/day.html index 680aef4..ae8a0e5 100644 --- a/static/day.html +++ b/static/day.html @@ -29,17 +29,20 @@
- +

Thermograph · Day

Every percentile boundary for one day vs its typical climate

-
diff --git a/static/index.html b/static/index.html index 9d5c767..128a008 100644 --- a/static/index.html +++ b/static/index.html @@ -32,17 +32,20 @@
- +

Thermograph

Grading today's weather against ~45 years of local climate history

-
diff --git a/static/legend.html b/static/legend.html index 756621b..f67db2b 100644 --- a/static/legend.html +++ b/static/legend.html @@ -28,17 +28,20 @@
- +

Thermograph · Guide

What the metrics and percentile grades mean

-
diff --git a/static/style.css b/static/style.css index e1cc59b..7782d5c 100644 --- a/static/style.css +++ b/static/style.css @@ -67,17 +67,18 @@ header { instead of bumping the toggle onto its own line. */ .brand > div:not(.unit-toggle):not(.acct) { flex: 1 1 0; min-width: 0; } .logo { - font-size: 30px; color: var(--accent); - transform: rotate(90deg); - display: inline-block; + display: inline-flex; + align-items: center; + flex-shrink: 0; } +.logo svg { width: 28px; height: 28px; display: block; } h1 { margin: 0; font-size: 22px; letter-spacing: -0.02em; } .tag { margin: 2px 0 0; color: var(--muted); font-size: 13px; } /* Compact header (e.g. Calendar): no tagline, roughly half the height. Only the vertical padding is trimmed so the responsive side padding stands. */ header.compact { padding-top: 9px; padding-bottom: 9px; } -header.compact .logo { font-size: 22px; } +header.compact .logo svg { width: 22px; height: 22px; } header.compact h1 { font-size: 18px; } main { max-width: 1200px; margin: 0 auto; padding: 20px 24px 60px; } @@ -490,6 +491,19 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 24px 60px; } .view-nav a:hover { color: var(--text); } .view-nav a.active { background: var(--accent); color: #fff; } +/* Hamburger wrapper. On desktop it's transparent (display:contents) so the nav + renders inline as pills and the hamburger summary is hidden; on phones (the + 640px block) it becomes a dropdown while the F/C toggle, bell and account stay + in the header bar. */ +.nav-menu { display: contents; } +/* A closed
hides its non-summary content; force the nav visible on + desktop (the 640px block re-hides it behind the hamburger on phones). */ +.nav-menu > .view-nav { display: inline-flex; } +.nav-menu::details-content { display: contents; } +.nav-toggle { display: none; list-style: none; cursor: pointer; } +.nav-toggle::-webkit-details-marker { display: none; } +.nav-toggle svg { display: block; } + /* --- calendar subpage --- */ .metric-toggle { display: flex; flex-wrap: wrap; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; @@ -1296,14 +1310,27 @@ main { max-width: 1200px; margin: 0 auto; padding: 20px 24px 60px; } h1 { font-size: 19px; } .tag { font-size: 12px; } - /* Let the header wrap so the view switcher drops to its own full-width row - (and stays a comfortable touch target) instead of crowding the title. */ + /* Let the header wrap if the control cluster runs out of room. */ .brand { flex-wrap: wrap; } - /* Full-width bar; each tab is an equal, fully-tappable third. The unit toggle - stays on the title row (pushed to the top-right); the tabs wrap below it. */ - .view-nav { margin-left: 0; width: 100%; } - .unit-toggle + .view-nav { margin-left: 0; } - .view-nav a { min-height: 44px; padding: 8px 12px; } + /* The view navigation collapses into a hamburger dropdown; the F/C toggle, bell + and account stay in the header bar beside it. */ + /* A real box again (not display:contents) so it's the positioning context for + the absolute dropdown and holds the hamburger. */ + .nav-menu { display: inline-flex; position: relative; align-self: center; } + .nav-toggle { + display: inline-flex; align-items: center; justify-content: center; + width: 44px; height: 40px; border: 1px solid var(--border); border-radius: 10px; + background: var(--surface-2); color: var(--text); + } + .nav-menu[open] .nav-toggle { border-color: var(--accent); color: var(--accent); } + .view-nav { + position: absolute; right: 0; top: calc(100% + 8px); z-index: 60; margin: 0; + flex-direction: column; align-items: stretch; width: max-content; min-width: 176px; + box-shadow: 0 12px 30px rgba(0, 0, 0, .35); + } + .nav-menu:not([open]) .view-nav { display: none; } + .view-nav a { min-height: 44px; padding: 10px 14px; justify-content: flex-start; } + .view-nav a + a::before { display: none; } /* Collapse the account entry to an icon-only button so it doesn't crush the title/tagline on narrow screens (it still opens the modal / menu). */ .acct-btn span { display: none; } @@ -1572,6 +1599,15 @@ td.rec-date { color: var(--muted); font-size: 13px; } .city-event p { margin: 0; } .city-travel { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 14px 18px; margin: 28px 0; } .city-travel h2 { margin-top: 4px; } +/* Month page: the "visiting in ?" prompt as a compact callout — text on + the left, a CTA button on the right (stacks on narrow screens). */ +.travel-note { + display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; + background: var(--surface); border: 1px solid var(--border); border-radius: 12px; + padding: 14px 18px; margin: 22px 0; +} +.travel-note p { margin: 0; flex: 1 1 240px; } +.travel-note .cta { flex-shrink: 0; margin-top: 0; } .travel-note { font-size: 15px; } /* Hub / directory of cities */ diff --git a/static/subscriptions.html b/static/subscriptions.html index 815e6df..81cec3a 100644 --- a/static/subscriptions.html +++ b/static/subscriptions.html @@ -26,17 +26,20 @@
- +

Thermograph · Alerts

Get notified when a city's weather passes the percentile you set

-
diff --git a/static/units.js b/static/units.js index 7e5980d..3dd3518 100644 --- a/static/units.js +++ b/static/units.js @@ -63,7 +63,7 @@ function syncUnitToggle(wrap) { const b = e.target.closest("button[data-unit]"); if (b) setUnit(b.dataset.unit); }); - const nav = brand.querySelector(".view-nav"); - brand.insertBefore(wrap, nav); // sits just left of the view tabs (top-right) + const anchor = brand.querySelector(".nav-menu") || brand.querySelector(".view-nav"); + brand.insertBefore(wrap, anchor); // sits just left of the nav (top-right) syncUnitToggle(wrap); })();