2.2.5
Fix UI issues
This commit is contained in:
@@ -395,8 +395,14 @@
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Mobile header layout ────────────────────────────────────────────── */
|
/* ── Stacked header layout (mobile + tablet) ─────────────────────────────
|
||||||
@media (max-width: 640px) {
|
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 {
|
.utci-header {
|
||||||
grid-template-columns: 1fr; /* single column — stack title, dial, search */
|
grid-template-columns: 1fr; /* single column — stack title, dial, search */
|
||||||
grid-template-areas: none; /* flow in DOM order: left, dial, selector, why */
|
grid-template-areas: none; /* flow in DOM order: left, dial, selector, why */
|
||||||
@@ -414,7 +420,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.header-right {
|
.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 {
|
.utci-title {
|
||||||
|
|||||||
@@ -210,9 +210,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.profile-btn {
|
.profile-btn {
|
||||||
width: 80px;
|
width: 100px;
|
||||||
height: 80px;
|
height: 100px;
|
||||||
flex: none; /* never shrink below 80px — the row scrolls instead */
|
flex: none; /* never shrink below 100px — the row scrolls instead */
|
||||||
padding: 0;
|
padding: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -958,8 +958,8 @@
|
|||||||
|
|
||||||
/* Slightly smaller cards on mobile */
|
/* Slightly smaller cards on mobile */
|
||||||
.profile-btn {
|
.profile-btn {
|
||||||
width: 68px;
|
width: 80px;
|
||||||
height: 68px;
|
height: 80px;
|
||||||
flex: none;
|
flex: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-10
@@ -447,12 +447,12 @@
|
|||||||
Used for the Places / Activities / Work triggers in the profile bar. */
|
Used for the Places / Activities / Work triggers in the profile bar. */
|
||||||
|
|
||||||
.profile-scroll .cs-wrap {
|
.profile-scroll .cs-wrap {
|
||||||
height: 80px;
|
height: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cs-btn.profile-card {
|
.cs-btn.profile-card {
|
||||||
width: 80px;
|
width: 100px;
|
||||||
height: 80px;
|
height: 100px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -490,21 +490,32 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
display: flex;
|
/* Block (not flex) so text-overflow:ellipsis cuts cleanly on the trailing
|
||||||
align-items: center;
|
edge — e.g. "Forest / Wo…" — instead of a flex item clipping both sides.
|
||||||
justify-content: center;
|
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-size: 10px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
background: rgba(30,18,8,0.52);
|
background: rgba(30,18,8,0.52);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 0 14px 0 4px;
|
padding: 0 17px 0 6px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
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 {
|
.cs-btn.profile-card .cs-arrow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 6px;
|
right: 6px;
|
||||||
@@ -540,11 +551,11 @@
|
|||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.profile-scroll .cs-wrap {
|
.profile-scroll .cs-wrap {
|
||||||
height: 68px;
|
height: 80px;
|
||||||
}
|
}
|
||||||
.cs-btn.profile-card {
|
.cs-btn.profile-card {
|
||||||
width: 68px;
|
width: 80px;
|
||||||
height: 68px;
|
height: 80px;
|
||||||
}
|
}
|
||||||
.cs-btn.profile-card .cs-arrow {
|
.cs-btn.profile-card .cs-arrow {
|
||||||
bottom: 7px;
|
bottom: 7px;
|
||||||
@@ -555,6 +566,7 @@
|
|||||||
}
|
}
|
||||||
.cs-btn.profile-card .cs-btn-label {
|
.cs-btn.profile-card .cs-btn-label {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,19 @@ function weatherGradient(r, g, b) {
|
|||||||
return `linear-gradient(135deg, ${light} 0%, ${mid} 60%, ${dark} 100%)`;
|
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({
|
export function DayTabs({
|
||||||
days,
|
days,
|
||||||
selectedDay, setSelectedDay,
|
selectedDay, setSelectedDay,
|
||||||
@@ -328,6 +341,7 @@ export function DayTabs({
|
|||||||
: modalCloudCat === 'wispy' ? [200, 180, 130]
|
: modalCloudCat === 'wispy' ? [200, 180, 130]
|
||||||
: [220, 190, 50];
|
: [220, 190, 50];
|
||||||
const wBg = weatherGradient(wR, wG, wB);
|
const wBg = weatherGradient(wR, wG, wB);
|
||||||
|
const wBgActive = weatherGradientActive(wR, wG, wB);
|
||||||
const wText = '#2a1d10';
|
const wText = '#2a1d10';
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
@@ -347,7 +361,7 @@ export function DayTabs({
|
|||||||
? `${band.label} · SunScope Extra unlocks day ${i + 1}`
|
? `${band.label} · SunScope Extra unlocks day ${i + 1}`
|
||||||
: `${band.label} · day ${i + 1} of 14`}
|
: `${band.label} · day ${i + 1} of 14`}
|
||||||
style=${{
|
style=${{
|
||||||
background: wBg,
|
background: isActive ? wBgActive : wBg,
|
||||||
color: wText,
|
color: wText,
|
||||||
border: '1px solid #c9b08a',
|
border: '1px solid #c9b08a',
|
||||||
opacity: locked ? 0.5 : 1,
|
opacity: locked ? 0.5 : 1,
|
||||||
@@ -361,7 +375,7 @@ export function DayTabs({
|
|||||||
bottom: 0,
|
bottom: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
height: isActive ? '5px' : '4px',
|
height: isActive ? '8px' : '7px',
|
||||||
background: band.bg,
|
background: band.bg,
|
||||||
borderTop: '1px solid #c9b08a',
|
borderTop: '1px solid #c9b08a',
|
||||||
borderRadius: '0 0 2px 2px',
|
borderRadius: '0 0 2px 2px',
|
||||||
@@ -387,6 +401,7 @@ export function DayTabs({
|
|||||||
marginTop: '2px',
|
marginTop: '2px',
|
||||||
letterSpacing: 0,
|
letterSpacing: 0,
|
||||||
textTransform: 'none',
|
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)',
|
||||||
}}>
|
}}>
|
||||||
<span style=${{ color: '#c0622a', fontWeight: 600 }}>${dayHi}°</span>
|
<span style=${{ color: '#c0622a', fontWeight: 600 }}>${dayHi}°</span>
|
||||||
<span style=${{ opacity: 0.5 }}> / </span>
|
<span style=${{ opacity: 0.5 }}> / </span>
|
||||||
|
|||||||
@@ -339,17 +339,17 @@ export function useAppState() {
|
|||||||
const activityValue = activeProfile === 'outdoors' && activityVariantKeys.includes(outdoorsVariant)
|
const activityValue = activeProfile === 'outdoors' && activityVariantKeys.includes(outdoorsVariant)
|
||||||
? outdoorsVariant
|
? outdoorsVariant
|
||||||
: 'off';
|
: '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)
|
const placeValue = activeProfile === 'outdoors' && placeVariantKeys.includes(outdoorsVariant)
|
||||||
? outdoorsVariant
|
? outdoorsVariant
|
||||||
: 'off';
|
: 'off';
|
||||||
const placeLabel = placeOptions.find((o) => o.value === placeValue)?.label;
|
const placeLabel = placeOptions.find((o) => o.value === placeValue)?.name;
|
||||||
const workValue = activeProfile === 'farming'
|
const workValue = activeProfile === 'farming'
|
||||||
? 'farming'
|
? 'farming'
|
||||||
: activeProfile === 'outdoors' && workVariantKeys.includes(outdoorsVariant)
|
: activeProfile === 'outdoors' && workVariantKeys.includes(outdoorsVariant)
|
||||||
? outdoorsVariant
|
? outdoorsVariant
|
||||||
: 'off';
|
: 'off';
|
||||||
const workLabel = workOptions.find((o) => o.value === workValue)?.label;
|
const workLabel = workOptions.find((o) => o.value === workValue)?.name;
|
||||||
|
|
||||||
// ── 6. TABLE REFS ────────────────────────────────────────────────────
|
// ── 6. TABLE REFS ────────────────────────────────────────────────────
|
||||||
const headStickyRef = useRef(null);
|
const headStickyRef = useRef(null);
|
||||||
|
|||||||
+4
-4
@@ -27,7 +27,7 @@
|
|||||||
css/ui.css Status banners, legend, about, footer, responsive
|
css/ui.css Status banners, legend, about, footer, responsive
|
||||||
════════════════════════════════════════════════════════════════════════ */
|
════════════════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
@import "./css/base.css";
|
@import "./css/base.css?v=15g";
|
||||||
@import "./css/header.css";
|
@import "./css/header.css?v=15g";
|
||||||
@import "./css/table.css";
|
@import "./css/table.css?v=15g";
|
||||||
@import "./css/ui.css";
|
@import "./css/ui.css?v=15g";
|
||||||
|
|||||||
+1
-1
@@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
<link rel="preconnect" href="https://api.open-meteo.com" crossorigin />
|
<link rel="preconnect" href="https://api.open-meteo.com" crossorigin />
|
||||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>☀️</text></svg>" />
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>☀️</text></svg>" />
|
||||||
<link rel="stylesheet" href="./assets/sunscope.css?v=15b">
|
<link rel="stylesheet" href="./assets/sunscope.css?v=15g">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user