From e00d38cbfbbd1a39fe916d63154905a2a15f7ad9 Mon Sep 17 00:00:00 2001 From: fraxle Date: Tue, 2 Jun 2026 22:40:15 +0100 Subject: [PATCH] 2.2.5 Fix UI issues --- assets/css/header.css | 12 +++++++++--- assets/css/table.css | 10 +++++----- assets/css/ui.css | 32 ++++++++++++++++++++++---------- assets/js/components/DayTabs.js | 19 +++++++++++++++++-- assets/js/hooks/useAppState.js | 6 +++--- assets/sunscope.css | 8 ++++---- index.html | 2 +- 7 files changed, 61 insertions(+), 28 deletions(-) diff --git a/assets/css/header.css b/assets/css/header.css index f98fa90..253e032 100644 --- a/assets/css/header.css +++ b/assets/css/header.css @@ -395,8 +395,14 @@ text-transform: uppercase; } -/* ── Mobile header layout ────────────────────────────────────────────── */ -@media (max-width: 640px) { +/* ── Stacked header layout (mobile + tablet) ───────────────────────────── + The desktop 3-column grid (left | dial | why-panel) needs ~960px of + viewport to fit: the location/search box is 300px, the "Why it feels like" + panel ~300px, plus the 220px dial and gaps. Below that the rigid columns + can't shrink and the why-panel overflows off the right edge, so we stack + everything into one centred column — matching where the glance rail also + drops below the table. */ +@media (max-width: 960px) { .utci-header { grid-template-columns: 1fr; /* single column — stack title, dial, search */ grid-template-areas: none; /* flow in DOM order: left, dial, selector, why */ @@ -414,7 +420,7 @@ } .header-right { - align-items: flex-start; /* left-align location on mobile */ + align-items: center; /* centre the "Why it feels like" panel under the dial */ } .utci-title { diff --git a/assets/css/table.css b/assets/css/table.css index 7e9c6f1..9447554 100644 --- a/assets/css/table.css +++ b/assets/css/table.css @@ -210,9 +210,9 @@ } .profile-btn { - width: 80px; - height: 80px; - flex: none; /* never shrink below 80px — the row scrolls instead */ + width: 100px; + height: 100px; + flex: none; /* never shrink below 100px — the row scrolls instead */ padding: 0; position: relative; display: inline-flex; @@ -958,8 +958,8 @@ /* Slightly smaller cards on mobile */ .profile-btn { - width: 68px; - height: 68px; + width: 80px; + height: 80px; flex: none; } diff --git a/assets/css/ui.css b/assets/css/ui.css index bdbf8b9..6d032b9 100644 --- a/assets/css/ui.css +++ b/assets/css/ui.css @@ -447,12 +447,12 @@ Used for the Places / Activities / Work triggers in the profile bar. */ .profile-scroll .cs-wrap { - height: 80px; + height: 100px; } .cs-btn.profile-card { - width: 80px; - height: 80px; + width: 100px; + height: 100px; padding: 0; position: relative; flex-direction: column; @@ -490,21 +490,32 @@ left: 0; right: 0; height: 24px; - display: flex; - align-items: center; - justify-content: center; + /* Block (not flex) so text-overflow:ellipsis cuts cleanly on the trailing + edge — e.g. "Forest / Wo…" — instead of a flex item clipping both sides. + line-height vertically centres the single line; text-align centres short + labels while long ones ellipsise against the right pad that clears the + arrow. */ + display: block; + line-height: 24px; + text-align: center; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; background: rgba(30,18,8,0.52); color: #fff; - padding: 0 14px 0 4px; + padding: 0 17px 0 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +/* When the label overflows it must read left-to-right so the ellipsis lands on + the end ("Forest / Wo…"); centred overflow would clip the start too. */ +.cs-btn.profile-card.on .cs-btn-label { + text-align: left; +} + .cs-btn.profile-card .cs-arrow { position: absolute; right: 6px; @@ -540,11 +551,11 @@ @media (max-width: 640px) { .profile-scroll .cs-wrap { - height: 68px; + height: 80px; } .cs-btn.profile-card { - width: 68px; - height: 68px; + width: 80px; + height: 80px; } .cs-btn.profile-card .cs-arrow { bottom: 7px; @@ -555,6 +566,7 @@ } .cs-btn.profile-card .cs-btn-label { height: 20px; + line-height: 20px; font-size: 9px; } } diff --git a/assets/js/components/DayTabs.js b/assets/js/components/DayTabs.js index ad74102..1e6491d 100644 --- a/assets/js/components/DayTabs.js +++ b/assets/js/components/DayTabs.js @@ -63,6 +63,19 @@ function weatherGradient(r, g, b) { return `linear-gradient(135deg, ${light} 0%, ${mid} 60%, ${dark} 100%)`; } +// Active-tab variant: a more solid (less pastelised) version of the weather +// colour, drawn as a radial gradient whose strong colour sits at the outer +// edge and softens toward a lighter centre — so the hue reads as radiating +// inward from the outside of the tab. +function weatherGradientActive(r, g, b) { + const blend = (c) => Math.round(c + (255 - c) * 0.42); + const [mr, mg, mb] = [blend(r), blend(g), blend(b)]; + const lighten = (c) => Math.min(255, Math.round(c + (255 - c) * 0.38)); + const center = `rgb(${lighten(mr)},${lighten(mg)},${lighten(mb)})`; + const edge = `rgb(${mr},${mg},${mb})`; + return `radial-gradient(circle at 50% 50%, ${center} 0%, ${center} 28%, ${edge} 100%)`; +} + export function DayTabs({ days, selectedDay, setSelectedDay, @@ -328,6 +341,7 @@ export function DayTabs({ : modalCloudCat === 'wispy' ? [200, 180, 130] : [220, 190, 50]; const wBg = weatherGradient(wR, wG, wB); + const wBgActive = weatherGradientActive(wR, wG, wB); const wText = '#2a1d10'; return html` @@ -347,7 +361,7 @@ export function DayTabs({ ? `${band.label} · SunScope Extra unlocks day ${i + 1}` : `${band.label} · day ${i + 1} of 14`} style=${{ - background: wBg, + background: isActive ? wBgActive : wBg, color: wText, border: '1px solid #c9b08a', opacity: locked ? 0.5 : 1, @@ -361,7 +375,7 @@ export function DayTabs({ bottom: 0, left: 0, right: 0, - height: isActive ? '5px' : '4px', + height: isActive ? '8px' : '7px', background: band.bg, borderTop: '1px solid #c9b08a', borderRadius: '0 0 2px 2px', @@ -387,6 +401,7 @@ export function DayTabs({ marginTop: '2px', letterSpacing: 0, textTransform: 'none', + textShadow: '0 0 14px rgba(255,255,255,0.85), 0 0 11px rgba(255,255,255,0.7), 0 0 8px rgba(255,255,255,0.6), 0 0 5px rgba(255,255,255,0.5)', }}> ${dayHi}° / diff --git a/assets/js/hooks/useAppState.js b/assets/js/hooks/useAppState.js index 6eafb37..4443215 100644 --- a/assets/js/hooks/useAppState.js +++ b/assets/js/hooks/useAppState.js @@ -339,17 +339,17 @@ export function useAppState() { const activityValue = activeProfile === 'outdoors' && activityVariantKeys.includes(outdoorsVariant) ? outdoorsVariant : 'off'; - const activityLabel = activityOptions.find((o) => o.value === activityValue)?.label; + const activityLabel = activityOptions.find((o) => o.value === activityValue)?.name; const placeValue = activeProfile === 'outdoors' && placeVariantKeys.includes(outdoorsVariant) ? outdoorsVariant : 'off'; - const placeLabel = placeOptions.find((o) => o.value === placeValue)?.label; + const placeLabel = placeOptions.find((o) => o.value === placeValue)?.name; const workValue = activeProfile === 'farming' ? 'farming' : activeProfile === 'outdoors' && workVariantKeys.includes(outdoorsVariant) ? outdoorsVariant : 'off'; - const workLabel = workOptions.find((o) => o.value === workValue)?.label; + const workLabel = workOptions.find((o) => o.value === workValue)?.name; // ── 6. TABLE REFS ──────────────────────────────────────────────────── const headStickyRef = useRef(null); diff --git a/assets/sunscope.css b/assets/sunscope.css index 1532dec..4a7e7e9 100644 --- a/assets/sunscope.css +++ b/assets/sunscope.css @@ -27,7 +27,7 @@ css/ui.css Status banners, legend, about, footer, responsive ════════════════════════════════════════════════════════════════════════ */ -@import "./css/base.css"; -@import "./css/header.css"; -@import "./css/table.css"; -@import "./css/ui.css"; +@import "./css/base.css?v=15g"; +@import "./css/header.css?v=15g"; +@import "./css/table.css?v=15g"; +@import "./css/ui.css?v=15g"; diff --git a/index.html b/index.html index 4ed78cf..d6b2498 100644 --- a/index.html +++ b/index.html @@ -70,7 +70,7 @@ - +