Mobile fixes
This commit is contained in:
fraxle
2026-06-02 19:36:54 +01:00
parent 51e5381de6
commit bf4c1a0136
4 changed files with 258 additions and 68 deletions
+103 -42
View File
@@ -21,6 +21,7 @@
// ════════════════════════════════════════════════════════════════════════
import { h, render, Fragment } from '../vendor/preact.js';
import { useState, useRef, useEffect } from '../vendor/preact-hooks.js';
import htm from '../vendor/htm.js';
import {
utciCategory, UTCI_BANDS, bandGradient,
@@ -45,7 +46,7 @@ export function UTCIForecast() {
const {
location, setLocationAndSave,
forecast, airQuality, loading, error, now, fetchedAt,
searchQuery, setSearchQuery, searchResults, searching,
searchQuery, setSearchQuery, searchResults, setSearchResults, searching,
selectedDay, setSelectedDay,
proPromptDay, setProPromptDay,
proPromptSource, setProPromptSource,
@@ -84,7 +85,38 @@ export function UTCIForecast() {
bannerVisible, bannerStageRef,
bannerSlideTo, dismissBanner,
} = useAppState();
// Search is hidden by default and revealed via the magnifier next to the
// location. The input then overlays the location line to save space.
const [searchOpen, setSearchOpen] = useState(false);
const searchWrapRef = useRef(null);
const searchInputRef = useRef(null);
// Focus the input the moment the search opens.
useEffect(() => {
if (searchOpen) searchInputRef.current?.focus();
}, [searchOpen]);
// Close the search on outside-click or Escape, clearing any stray query.
useEffect(() => {
if (!searchOpen) return;
const onDown = (e) => {
if (searchWrapRef.current && !searchWrapRef.current.contains(e.target)) {
setSearchOpen(false);
setSearchQuery('');
}
};
const onKey = (e) => {
if (e.key === 'Escape') { setSearchOpen(false); setSearchQuery(''); }
};
document.addEventListener('mousedown', onDown);
document.addEventListener('keydown', onKey);
return () => {
document.removeEventListener('mousedown', onDown);
document.removeEventListener('keydown', onKey);
};
}, [searchOpen, setSearchQuery]);
// Columns that mark the start of a logical group - used to draw a faint
// vertical border separating groups in the forecast table.
const GROUP_ORDER = {
@@ -317,48 +349,77 @@ export function UTCIForecast() {
<span class="title-sun">SUN</span><span class="title-scope">Scope</span>
</h1>
<div class="utci-tagline">See the sun the way your skin does.</div>
<div class="utci-search-wrap">
<input
class="utci-search"
type="text"
placeholder="Search any town or city…"
value=${searchQuery}
onInput=${(e) => setSearchQuery(e.currentTarget.value)}
/>
${searchResults.length > 0 && html`
<div class="utci-results">
${searchResults.map((r) => html`
<div
key=${`${r.id}-${r.latitude}`}
class="utci-result"
onClick=${() => {
setLocationAndSave({
name: `${r.name}${r.admin1 ? ', ' + r.admin1 : ''}`,
lat: r.latitude,
lon: r.longitude,
country: r.country_code,
});
setSearchQuery('');
setSearchResults([]);
setSelectedDay(0);
}}
>
<div>${r.name}${r.admin1 ? `, ${r.admin1}` : ''}</div>
<div class="utci-result-meta">
${r.country} · ${r.latitude.toFixed(2)}°, ${r.longitude.toFixed(2)}°
</div>
</div>`)}
<div class="utci-loc-search" ref=${searchWrapRef}>
<div class="utci-current-loc">
<button
type="button"
class="utci-loc-name"
aria-label="Search for a town or city"
aria-expanded=${searchOpen}
onClick=${() => setSearchOpen((v) => !v)}
>
<svg class="utci-loc-pin" viewBox="0 0 24 24" width="15" height="15" aria-hidden="true">
<path fill="currentColor" d="M12 2c-3.87 0-7 3.13-7 7 0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7z" />
<circle cx="12" cy="9" r="2.5" fill="#fffcf2" />
</svg>
${location.name}
</button>
<button
type="button"
class="utci-search-toggle"
aria-label="Search for a town or city"
aria-expanded=${searchOpen}
onClick=${() => setSearchOpen((v) => !v)}
>
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true">
<circle cx="10.5" cy="10.5" r="6.5" fill="none" stroke="currentColor" stroke-width="2" />
<line x1="15.5" y1="15.5" x2="21" y2="21" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
</svg>
</button>
<span class="utci-loc-coords">
${location.lat.toFixed(3)}°, ${location.lon.toFixed(3)}°
</span>
</div>
${fetchedAt && !loading && html`
<div class="utci-fetch-time">Last update: ${fetchedAt.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</div>`}
${searchOpen && html`
<div class="utci-search-wrap utci-search-overlay">
<input
ref=${searchInputRef}
class="utci-search"
type="text"
placeholder="Search any town or city…"
value=${searchQuery}
onInput=${(e) => setSearchQuery(e.currentTarget.value)}
/>
${searchResults.length > 0 && html`
<div class="utci-results">
${searchResults.map((r) => html`
<div
key=${`${r.id}-${r.latitude}`}
class="utci-result"
onClick=${() => {
setLocationAndSave({
name: `${r.name}${r.admin1 ? ', ' + r.admin1 : ''}`,
lat: r.latitude,
lon: r.longitude,
country: r.country_code,
});
setSearchQuery('');
setSearchResults([]);
setSelectedDay(0);
setSearchOpen(false);
}}
>
<div>${r.name}${r.admin1 ? `, ${r.admin1}` : ''}</div>
<div class="utci-result-meta">
${r.country} · ${r.latitude.toFixed(2)}°, ${r.longitude.toFixed(2)}°
</div>
</div>`)}
</div>`}
${searching && html`<div class="utci-searching">Searching…</div>`}
</div>`}
${searching && html`<div class="utci-searching">Searching…</div>`}
</div>
<div class="utci-current-loc">
${location.name}
<span class="utci-loc-coords">
${location.lat.toFixed(3)}°, ${location.lon.toFixed(3)}°
</span>
</div>
${fetchedAt && !loading && html`
<div class="utci-fetch-time">Last update: ${fetchedAt.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</div>`}
</div>
<div class="scope-col">
+20 -20
View File
@@ -83,31 +83,31 @@ export const FILTER_PROFILES = {
// Places sub-variants - each has its own column set.
// Selecting a variant applies its cols to visibleCols.
export const OUTDOORS_VARIANTS = {
urban: { name: 'Urban', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: true, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: true, pollen: false } },
beach: { name: 'Beach', cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
events: { name: 'Events', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: true, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: false, pollen: true } },
festival: { name: 'Festival', cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: true, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: true, pollen: true } },
wintersports: { name: 'Winter Sports', proOnly: true, cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
naturist: { name: 'Naturist', proOnly: true, cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: false, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: true, pollen: true } },
sailing: { name: 'Sailing', proOnly: true, cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
urban: { name: 'Urban', scene: "url('assets/images/profiles/urban.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: true, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: true, pollen: false } },
beach: { name: 'Beach', scene: "url('assets/images/profiles/beach.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
events: { name: 'Events', scene: "url('assets/images/profiles/events.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: true, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: false, pollen: true } },
festival: { name: 'Festival', scene: "url('assets/images/profiles/festival.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: true, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: true, pollen: true } },
wintersports: { name: 'Winter Sports', proOnly: true, scene: "url('assets/images/profiles/winter.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
naturist: { name: 'Naturist', proOnly: true, scene: "url('assets/images/profiles/naturist.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: false, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: true, pollen: true } },
sailing: { name: 'Sailing', proOnly: true, scene: "url('assets/images/profiles/sailing.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
// Places - free
park: { name: 'Park / Picnic', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: false, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: false, pollen: true } },
forest: { name: 'Forest / Woodland', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: false, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: true, pollen: true } },
airport: { name: 'Airport / Travel', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: false, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
park: { name: 'Park / Picnic', scene: "url('assets/images/profiles/park.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: false, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: false, pollen: true } },
forest: { name: 'Forest / Woodland', scene: "url('assets/images/profiles/forest.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: false, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: true, pollen: true } },
airport: { name: 'Airport / Travel', scene: "url('assets/images/profiles/airport.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: false, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
// Places - Pro
construction: { name: 'Construction', proOnly: true, cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: true, pollen: false } },
construction: { name: 'Construction', proOnly: true, scene: "url('assets/images/profiles/construction.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: true, pollen: false } },
// Activities - free
cycling: { name: 'Cycling', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
running: { name: 'Running', cols: { hour: true, air: true, rh: true, dew: false, wind: true, dir: false, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: false, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: false, pollen: true } },
dogwalk: { name: 'Dog Walking', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: false, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: false, pollen: true } },
cycling: { name: 'Cycling', scene: "url('assets/images/profiles/cycling.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
running: { name: 'Running', scene: "url('assets/images/profiles/running.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: true, dew: false, wind: true, dir: false, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: false, uvB: false, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: false, pollen: true } },
dogwalk: { name: 'Dog Walking', scene: "url('assets/images/profiles/walking.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: false, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: false, pollen: true } },
// Activities - Pro
hiking: { name: 'Hiking', proOnly: true, cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
photography: { name: 'Photography', proOnly: true, cols: { hour: true, air: true, rh: false, dew: false, wind: false, dir: false, cloud: true, sun: true, direct: true, diffuse: true, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: false, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
fishing: { name: 'Fishing', proOnly: true, cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
hiking: { name: 'Hiking', proOnly: true, scene: "url('assets/images/profiles/hiking.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
photography: { name: 'Photography', proOnly: true, scene: "url('assets/images/profiles/photography.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: false, dir: false, cloud: true, sun: true, direct: true, diffuse: true, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: false, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
fishing: { name: 'Fishing', proOnly: true, scene: "url('assets/images/profiles/fishing.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
// Work variants
market: { name: 'Market Trading', proOnly: true, cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
windowcleaning: { name: 'Window Cleaning', proOnly: true, cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
office: { name: 'Office', proOnly: true, cols: { hour: true, air: true, rh: true, dew: false, wind: false, dir: false, cloud: true, sun: true, direct: true, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: true, vis: false, aqi: true, pollen: false } },
market: { name: 'Market Trading', proOnly: true, scene: "url('assets/images/profiles/market.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
windowcleaning: { name: 'Window Cleaning', proOnly: true, scene: "url('assets/images/profiles/window.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: true, aqi: false, pollen: false } },
office: { name: 'Office', proOnly: true, scene: "url('assets/images/profiles/office.png') center / cover no-repeat, linear-gradient(160deg,#c2d4cc,#e2ece6)", cols: { hour: true, air: true, rh: true, dew: false, wind: false, dir: false, cloud: true, sun: true, direct: true, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: true, precipProb: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: true, vis: false, aqi: true, pollen: false } },
};
// Pollen type options shown in the pulldown selector.