New SunSoak multiselect UTCI modifiers pulldown
Linked new SunSoak to profiles
Updated content to match new changes
This commit is contained in:
fraxle
2026-05-25 11:24:46 +01:00
parent 2cb4ebe52b
commit 2f76f98632
8 changed files with 239 additions and 93 deletions
+71 -46
View File
@@ -4,13 +4,13 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>About SunScope · The True Temperature</title> <title>About SunScope · The True Temperature</title>
<meta name="description" content="SunScope uses the Universal Thermal Climate Index (UTCI) and an original soak-factor formula to show how the weather will really feel on your body — including the effect of rain, snow, wind, solar radiation, air quality, pollen, and visibility." /> <meta name="description" content="SunScope uses the Universal Thermal Climate Index (UTCI) and its original SunSoak index to show how the weather will really feel on your body — including rain, snow, wind, solar radiation, environment type, air quality, pollen, and visibility." />
<meta name="robots" content="index, follow" /> <meta name="robots" content="index, follow" />
<link rel="canonical" href="https://sunscope.net/about.html" /> <link rel="canonical" href="https://sunscope.net/about.html" />
<!-- Open Graph --> <!-- Open Graph -->
<meta property="og:title" content="About SunScope · The True Temperature" /> <meta property="og:title" content="About SunScope · The True Temperature" />
<meta property="og:description" content="What is UTCI? How does the SunScope soak-factor work? Learn how SunScope calculates urban concrete heat, vehicle interior temperatures, and gives you a more honest outdoor comfort forecast." /> <meta property="og:description" content="What is UTCI? How does SunSoak work? Learn how SunScope calculates felt temperature across different environments — forest, alpine, beach, desert and more — plus urban heat, vehicle temperatures, and an honest outdoor comfort forecast." />
<meta property="og:url" content="https://sunscope.net/about.html" /> <meta property="og:url" content="https://sunscope.net/about.html" />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<!-- og:image: replace with your 1200×630 social sharing image URL --> <!-- og:image: replace with your 1200×630 social sharing image URL -->
@@ -19,7 +19,7 @@
<!-- Twitter Card --> <!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="About SunScope · The True Temperature" /> <meta name="twitter:title" content="About SunScope · The True Temperature" />
<meta name="twitter:description" content="What is UTCI? How does the SunScope soak-factor work? Learn how SunScope calculates urban heat, vehicle interior temperatures, and gives you a more honest outdoor comfort forecast." /> <meta name="twitter:description" content="What is UTCI? How does SunSoak work? Learn how SunScope calculates felt temperature across different environments — forest, alpine, beach, desert and more — plus urban heat, vehicle temperatures, and an honest outdoor comfort forecast." />
<!-- <meta name="twitter:image" content="https://sunscope.net/og-image.png" /> --> <!-- <meta name="twitter:image" content="https://sunscope.net/og-image.png" /> -->
<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>" />
@@ -52,7 +52,7 @@
"@type": "WebSite", "@type": "WebSite",
"name": "SunScope", "name": "SunScope",
"url": "https://sunscope.net", "url": "https://sunscope.net",
"description": "SunScope is a free outdoor thermal comfort forecast using the Universal Thermal Climate Index (UTCI) and the SunScope soak-factor for precipitation." "description": "SunScope is a free outdoor thermal comfort forecast using the Universal Thermal Climate Index (UTCI) and the SunSoak index — combining precipitation, environment modifiers, and mean radiant temperature into a single honest felt-temperature number."
} }
</script> </script>
<script type="application/ld+json"> <script type="application/ld+json">
@@ -70,10 +70,10 @@
}, },
{ {
"@type": "Question", "@type": "Question",
"name": "What is the SunScope soak-factor?", "name": "What is the SunScope SunSoak index?",
"acceptedAnswer": { "acceptedAnswer": {
"@type": "Answer", "@type": "Answer",
"text": "The SunScope soak-factor is an original precipitation penalty formula that reduces the UTCI felt-temperature value based on rain intensity, snowfall, and wind speed — reflecting the extra chill of wet clothing and skin that standard UTCI does not account for. The result is shown as UTCI+P." "text": "SunSoak is SunScope's signature felt-temperature index. It starts from UTCI — the biometeorological standard combining air temperature, humidity, wind, and solar radiation — then layers three extra dimensions on top: a rain and snow penalty (wet clothing can drop felt temperature by up to 8 degrees C), an environment modifier that adjusts the solar load for where you actually are (forest canopy, alpine altitude, lakeside reflection, shaded riverbank, desert ground heat), and the full radiant heat from surrounding surfaces. The result is a single number that honestly answers: what will my body actually feel out there?"
} }
}, },
{ {
@@ -244,9 +244,13 @@
peer-reviewed biometeorological standard developed by peer-reviewed biometeorological standard developed by
<a href="https://utci.org/" target="_blank" rel="noopener noreferrer">Bröde et al. (2012)</a> <a href="https://utci.org/" target="_blank" rel="noopener noreferrer">Bröde et al. (2012)</a>
and used globally in heat-health warning systems and urban planning. On top of that, SunScope and used globally in heat-health warning systems and urban planning. On top of that, SunScope
layers its own <strong>soak-factor</strong> precipitation penalty — because UTCI alone doesn't builds its own <strong>SunSoak</strong> index — because UTCI alone doesn't account for the full
account for the extra chill of rain soaking through your clothes on a windy day. The combined picture of where you actually are and what the weather is actually doing to you. SunSoak layers
result is the <strong>UTCI+P</strong> score: a more honest, real-world comfort number. three extra dimensions on top of UTCI: a <strong>rain and snow penalty</strong> for the chill of
wet clothing and skin; an <strong>environment modifier</strong> that adjusts the solar and
thermal load for your surroundings (forest canopy, alpine altitude, lakeside glare, shaded
riverbank, desert ground heat); and the full radiant heat absorbed from surrounding surfaces.
One number that honestly answers: <em>what will my body actually feel out there?</em>
</p> </p>
<p> <p>
Forecast data is sourced in real time from <strong>Open-Meteo</strong>, a free and open-source Forecast data is sourced in real time from <strong>Open-Meteo</strong>, a free and open-source
@@ -322,7 +326,7 @@
<p> <p>
<strong>Day strip weather and temperatures.</strong> Each day tab in the date selector shows the <strong>Day strip weather and temperatures.</strong> Each day tab in the date selector shows the
day's forecast at a glance: a weather icon representing the dominant daytime conditions (sun, day's forecast at a glance: a weather icon representing the dominant daytime conditions (sun,
cloud variants, or precipitation), plus the day's high and low UTCI+P felt temperatures in cloud variants, or precipitation), plus the day's high and low SunSoak felt temperatures in
warm and cool colours. The icon uses the actual daytime solar elevation and cloud category data warm and cool colours. The icon uses the actual daytime solar elevation and cloud category data
so it reflects the real character of the day rather than a generic symbol. so it reflects the real character of the day rather than a generic symbol.
</p> </p>
@@ -341,17 +345,38 @@
it also appears as a banner above the forecast table alongside the weather alerts. it also appears as a banner above the forecast table alongside the weather alerts.
</p> </p>
<h2>What is the SunScope soak-factor?</h2> <h2>What is SunSoak?</h2>
<p> <p>
Standard UTCI does not account for precipitation — it tells you how cold the wind and sun make Standard UTCI is calculated assuming open, unshaded conditions with no precipitation — it tells
you feel, but not the extra chill of rain soaking your clothing or snow settling on your skin. you how the wind and sun affect your body, but not the full picture of where you actually are or
The <strong>SunScope soak-factor</strong> fills that gap with an original penalty formula. what the weather is actively doing to you. <strong>SunSoak</strong> fills those gaps with three
layers of original calculation stacked on top of the UTCI foundation.
</p> </p>
<p> <p>
Light drizzle (under 1 mm/hr) reduces the felt temperature by roughly 12 °C. Heavy rain <strong>The precipitation penalty.</strong> Rain and snow are not in UTCI. The soak-factor
combined with strong wind can push it down by 78 °C. Snowfall carries an additional penalty formula adds an original penalty based on rain intensity, snowfall rate, and wind speed —
on top of any rain adjustment. The result is shown in the <strong>UTCI+P</strong> column — reflecting the extra chill of wet clothing and skin. Light drizzle (under 1 mm/hr) reduces the
a more honest, real-world comfort score for anyone heading outdoors. felt temperature by roughly 12 °C. Heavy rain combined with strong wind can push it down by
78 °C. Snowfall carries an additional penalty on top.
</p>
<p>
<strong>The environment modifier.</strong> UTCI assumes you are standing in the open. SunSoak
adjusts the solar radiation load and air temperature for six distinct environments, selectable
from a dropdown on the SunSoak column: <em>Open / Exposed</em> (the UTCI default);
<em>Forest / Woodland</em> (canopy reduces direct radiation by ~85%, evapotranspiration
cooling lowers apparent air temperature); <em>High Altitude / Alpine</em> (thinner atmosphere
increases radiation dose by ~15% at 2,000 m); <em>Beach / Lakeside</em> (water and sand
reflection increases effective solar load); <em>River / Riverbank</em> (partial canopy and
strong evaporative cooling from the water surface); and <em>Desert / Arid</em> (extreme
radiation from high-albedo ground, with significant ground-level heat adding to felt
temperature). Selecting a Place or Activity profile automatically sets the most appropriate
environment for that context — but you can always override it manually.
</p>
<p>
<strong>Mean radiant temperature.</strong> The full radiant heat load from surrounding surfaces
— ground, walls, sky, and direct sun — is calculated as Mean Radiant Temperature (Tmrt) and
fed into the UTCI polynomial. On a sunny day this alone can add 2030 °C to the felt
temperature compared to a shaded reading.
</p> </p>
<h2>Forecast profiles</h2> <h2>Forecast profiles</h2>
@@ -370,9 +395,9 @@
<p> <p>
The default view — clean and uncluttered, showing the essentials for any outdoor situation. The default view — clean and uncluttered, showing the essentials for any outdoor situation.
<strong>Air temperature</strong>, <strong>wind speed</strong>, <strong>cloud cover</strong>, <strong>Air temperature</strong>, <strong>wind speed</strong>, <strong>cloud cover</strong>,
<strong>visibility</strong>, <strong>precipitation</strong>, and <strong>UTCI+P</strong> — the adjusted felt temperature <strong>visibility</strong>, <strong>precipitation</strong>, and <strong>SunSoak</strong> — the
that combines sun, wind, humidity, and rain into a single honest number. The right starting felt-temperature index that combines sun, wind, humidity, rain, and your environment into a
point for most people most of the time. single honest number. The right starting point for most people most of the time.
</p> </p>
</div> </div>
@@ -409,7 +434,7 @@
heating. <strong>Wind speed</strong> is included because it matters significantly for heating. <strong>Wind speed</strong> is included because it matters significantly for
high-sided vehicles and caravans. <strong>Cloud cover</strong> and <strong>air high-sided vehicles and caravans. <strong>Cloud cover</strong> and <strong>air
temperature</strong> give context, <strong>precipitation</strong> covers driving temperature</strong> give context, <strong>precipitation</strong> covers driving
conditions, and <strong>UTCI+P</strong> tells you what it will feel like when you step conditions, and <strong>SunSoak</strong> tells you what it will feel like when you step
outside. <strong>Soil moisture</strong> is included specifically for motorhome and caravan outside. <strong>Soil moisture</strong> is included specifically for motorhome and caravan
users — values above 40% indicate saturated ground where pitching or manoeuvring users — values above 40% indicate saturated ground where pitching or manoeuvring
is likely to cause problems. is likely to cause problems.
@@ -431,7 +456,7 @@
it back long after sunset, and the lack of vegetation means there's no evaporative it back long after sunset, and the lack of vegetation means there's no evaporative
cooling. Columns: <strong>air temperature</strong>, <strong>wind speed and direction</strong>, cooling. Columns: <strong>air temperature</strong>, <strong>wind speed and direction</strong>,
<strong>cloud cover</strong>, <strong>visibility</strong>, <strong>air quality index</strong>, <strong>cloud cover</strong>, <strong>visibility</strong>, <strong>air quality index</strong>,
<strong>UV-A index</strong>, <strong>burn time</strong>, <strong>UTCI+P</strong>, <strong>UV-A index</strong>, <strong>burn time</strong>, <strong>SunSoak</strong>,
<strong>precipitation</strong>, and <strong>concrete surface temperature</strong>. <strong>precipitation</strong>, and <strong>concrete surface temperature</strong>.
</p> </p>
<p> <p>
@@ -442,14 +467,14 @@
makes hot beach days feel muggy, <strong>wind speed and direction</strong> matters for makes hot beach days feel muggy, <strong>wind speed and direction</strong> matters for
comfort and sea state, and <strong>sun elevation</strong> tells you when the UV load comfort and sea state, and <strong>sun elevation</strong> tells you when the UV load
peaks. <strong>Visibility</strong> is included for sea-state and horizon conditions. peaks. <strong>Visibility</strong> is included for sea-state and horizon conditions.
<strong>UTCI+P</strong> and <strong>precipitation</strong> round out the picture. <strong>SunSoak</strong> and <strong>precipitation</strong> round out the picture.
</p> </p>
<p> <p>
<strong>Events</strong> — for general outdoor gatherings: markets, sports fixtures, open-air <strong>Events</strong> — for general outdoor gatherings: markets, sports fixtures, open-air
concerts, and public events. Focuses on the crowd comfort picture: <strong>air concerts, and public events. Focuses on the crowd comfort picture: <strong>air
temperature</strong>, <strong>wind speed and direction</strong> (useful for exposed temperature</strong>, <strong>wind speed and direction</strong> (useful for exposed
grandstands and open sites), <strong>cloud cover</strong>, <strong>UV-A</strong> and grandstands and open sites), <strong>cloud cover</strong>, <strong>UV-A</strong> and
<strong>burn time</strong> for daytime events, <strong>UTCI+P</strong> for overall felt <strong>burn time</strong> for daytime events, <strong>SunSoak</strong> for overall felt
comfort, <strong>precipitation</strong>, <strong>pollen</strong> (important for comfort, <strong>precipitation</strong>, <strong>pollen</strong> (important for
allergy-sensitive attendees), and <strong>concrete surface temperature</strong> allergy-sensitive attendees), and <strong>concrete surface temperature</strong>
— relevant for anyone standing or sitting on sun-exposed hard standing for extended periods. — relevant for anyone standing or sitting on sun-exposed hard standing for extended periods.
@@ -458,7 +483,7 @@
<strong>Park / Picnic</strong> — a lighter view for casual outdoor time in green spaces. <strong>Park / Picnic</strong> — a lighter view for casual outdoor time in green spaces.
Shows the essentials without the urban or specialist columns: <strong>air temperature</strong>, Shows the essentials without the urban or specialist columns: <strong>air temperature</strong>,
<strong>wind speed</strong>, <strong>cloud cover</strong>, <strong>burn time</strong>, <strong>wind speed</strong>, <strong>cloud cover</strong>, <strong>burn time</strong>,
<strong>UTCI+P</strong>, <strong>precipitation</strong>, and <strong>pollen</strong> <strong>SunSoak</strong>, <strong>precipitation</strong>, and <strong>pollen</strong>
— useful for anyone with hay fever deciding whether to head out. — useful for anyone with hay fever deciding whether to head out.
</p> </p>
<p> <p>
@@ -470,7 +495,7 @@
</p> </p>
<p> <p>
<strong>Festival · Extra</strong> — multi-day outdoor events live or die by two things: the <strong>Festival · Extra</strong> — multi-day outdoor events live or die by two things: the
weather comfort and the state of the ground. Focuses on <strong>UTCI+P</strong> for how weather comfort and the state of the ground. Focuses on <strong>SunSoak</strong> for how
cold and wet conditions will actually feel, <strong>wind speed and direction</strong> for cold and wet conditions will actually feel, <strong>wind speed and direction</strong> for
tent and stage exposure, <strong>dew point</strong> for overnight condensation, tent and stage exposure, <strong>dew point</strong> for overnight condensation,
<strong>UV-A</strong> and <strong>burn time</strong> for daytime sun protection, <strong>UV-A</strong> and <strong>burn time</strong> for daytime sun protection,
@@ -486,7 +511,7 @@
for working at height and crane operations), <strong>cloud cover</strong>, for working at height and crane operations), <strong>cloud cover</strong>,
<strong>visibility</strong>, <strong>air quality index</strong> (dust and diesel <strong>visibility</strong>, <strong>air quality index</strong> (dust and diesel
particulates compound background pollution), <strong>UTCI</strong> for heat stress on particulates compound background pollution), <strong>UTCI</strong> for heat stress on
workers, <strong>UTCI+P</strong> for wet-weather comfort, and <strong>precipitation</strong>. workers, <strong>SunSoak</strong> for wet-weather comfort, and <strong>precipitation</strong>.
</p> </p>
</div> </div>
@@ -504,7 +529,7 @@
<strong>dew point</strong> (critical for frost risk and disease pressure on crops), <strong>dew point</strong> (critical for frost risk and disease pressure on crops),
<strong>wind speed and direction</strong> (essential for safe spraying windows), <strong>wind speed and direction</strong> (essential for safe spraying windows),
<strong>cloud cover</strong> and <strong>sun elevation</strong> for light levels, <strong>cloud cover</strong> and <strong>sun elevation</strong> for light levels,
<strong>UTCI+P</strong> for heat stress on the person working outdoors, <strong>SunSoak</strong> for heat stress on the person working outdoors,
<strong>precipitation</strong>, <strong>air quality index</strong> and <strong>pollen</strong> <strong>precipitation</strong>, <strong>air quality index</strong> and <strong>pollen</strong>
(relevant for outdoor workers and spray-window planning), and the three soil columns: (relevant for outdoor workers and spray-window planning), and the three soil columns:
<strong>surface soil temperature</strong>, <strong>soil temperature at 6 cm</strong> <strong>surface soil temperature</strong>, <strong>soil temperature at 6 cm</strong>
@@ -516,7 +541,7 @@
factor: headwinds add significant effort, crosswinds affect handling, and gusts are a factor: headwinds add significant effort, crosswinds affect handling, and gusts are a
safety concern on open roads. Shows <strong>air temperature</strong>, <strong>wind speed safety concern on open roads. Shows <strong>air temperature</strong>, <strong>wind speed
and direction</strong>, <strong>cloud cover</strong>, <strong>burn time</strong>, and direction</strong>, <strong>cloud cover</strong>, <strong>burn time</strong>,
<strong>UTCI+P</strong>, <strong>precipitation</strong>, and <strong>visibility</strong> <strong>SunSoak</strong>, <strong>precipitation</strong>, and <strong>visibility</strong>
— useful for road cycling in low-light or foggy conditions. — useful for road cycling in low-light or foggy conditions.
</p> </p>
<p> <p>
@@ -524,14 +549,14 @@
Shows <strong>air temperature</strong>, <strong>relative humidity</strong> (sweat Shows <strong>air temperature</strong>, <strong>relative humidity</strong> (sweat
evaporation is less effective in humid air, raising heat stress faster), evaporation is less effective in humid air, raising heat stress faster),
<strong>wind speed</strong>, <strong>cloud cover</strong>, <strong>UTCI</strong> for raw <strong>wind speed</strong>, <strong>cloud cover</strong>, <strong>UTCI</strong> for raw
heat stress, <strong>burn time</strong>, <strong>UTCI+P</strong>, <strong>precipitation</strong>, heat stress, <strong>burn time</strong>, <strong>SunSoak</strong>, <strong>precipitation</strong>,
and <strong>pollen</strong> — relevant for asthma and hay fever sufferers pacing their and <strong>pollen</strong> — relevant for asthma and hay fever sufferers pacing their
outdoor training. outdoor training.
</p> </p>
<p> <p>
<strong>Dog Walking</strong> — focused on the comfort and safety of both owner and dog. <strong>Dog Walking</strong> — focused on the comfort and safety of both owner and dog.
Shows <strong>air temperature</strong>, <strong>wind speed</strong>, <strong>cloud Shows <strong>air temperature</strong>, <strong>wind speed</strong>, <strong>cloud
cover</strong>, <strong>UTCI+P</strong>, <strong>precipitation</strong>, and cover</strong>, <strong>SunSoak</strong>, <strong>precipitation</strong>, and
<strong>pollen</strong>. The Vehicle profile's concrete surface temperature is the better <strong>pollen</strong>. The Vehicle profile's concrete surface temperature is the better
companion for pavement heat safety on hot days. companion for pavement heat safety on hot days.
</p> </p>
@@ -544,7 +569,7 @@
<strong>cloud cover</strong>, and <strong>sun elevation</strong> for visibility and glare. <strong>cloud cover</strong>, and <strong>sun elevation</strong> for visibility and glare.
UV exposure is significantly higher on open water due to reflection off the surface, so UV exposure is significantly higher on open water due to reflection off the surface, so
<strong>UV-A index</strong> and <strong>burn time</strong> are included. <strong>UV-A index</strong> and <strong>burn time</strong> are included.
<strong>UTCI+P</strong> captures the combined effect of wet, windy conditions, <strong>SunSoak</strong> captures the combined effect of wet, windy conditions,
<strong>visibility</strong> (essential for safe passage — fog and haze at sea are serious <strong>visibility</strong> (essential for safe passage — fog and haze at sea are serious
hazards), and <strong>precipitation</strong> rounds out the picture for passage planning. hazards), and <strong>precipitation</strong> rounds out the picture for passage planning.
</p> </p>
@@ -556,14 +581,14 @@
shown with <strong>burn time</strong>. <strong>Wind speed and direction</strong> is shown with <strong>burn time</strong>. <strong>Wind speed and direction</strong> is
critical for wind chill at speed and for avalanche and exposure risk on open slopes. critical for wind chill at speed and for avalanche and exposure risk on open slopes.
<strong>Sun elevation</strong> indicates glare and visibility conditions on snow. <strong>Sun elevation</strong> indicates glare and visibility conditions on snow.
<strong>UTCI+P</strong>, <strong>air temperature</strong>, <strong>cloud cover</strong>, <strong>SunSoak</strong>, <strong>air temperature</strong>, <strong>cloud cover</strong>,
<strong>visibility</strong> (critical for whiteout and low-cloud conditions on the <strong>visibility</strong> (critical for whiteout and low-cloud conditions on the
mountain), and <strong>precipitation</strong> (snow vs rain) complete the picture. mountain), and <strong>precipitation</strong> (snow vs rain) complete the picture.
</p> </p>
<p> <p>
<strong>Naturist · Extra</strong> — with no clothing buffer between skin and environment, <strong>Naturist · Extra</strong> — with no clothing buffer between skin and environment,
every weather variable matters more. Wind chill at even modest speeds becomes significant, every weather variable matters more. Wind chill at even modest speeds becomes significant,
so both the raw <strong>UTCI</strong> and <strong>UTCI+P</strong> are shown. Both so both the raw <strong>UTCI</strong> and <strong>SunSoak</strong> are shown. Both
<strong>UV-A</strong> and <strong>UV-B</strong> are included — full-body UV exposure is a <strong>UV-A</strong> and <strong>UV-B</strong> are included — full-body UV exposure is a
serious consideration — alongside <strong>burn time</strong>, <strong>sun elevation</strong>, serious consideration — alongside <strong>burn time</strong>, <strong>sun elevation</strong>,
<strong>dew point</strong> for humidity comfort, <strong>wind</strong>, <strong>cloud <strong>dew point</strong> for humidity comfort, <strong>wind</strong>, <strong>cloud
@@ -576,7 +601,7 @@
more serious than in urban areas. Shows <strong>air temperature</strong>, <strong>wind speed more serious than in urban areas. Shows <strong>air temperature</strong>, <strong>wind speed
and direction</strong>, <strong>cloud cover</strong>, <strong>sun elevation</strong>, both and direction</strong>, <strong>cloud cover</strong>, <strong>sun elevation</strong>, both
<strong>UV-A</strong> and <strong>UV-B</strong> with <strong>burn time</strong> (altitude <strong>UV-A</strong> and <strong>UV-B</strong> with <strong>burn time</strong> (altitude
increases UV exposure), <strong>UTCI</strong> and <strong>UTCI+P</strong>, increases UV exposure), <strong>UTCI</strong> and <strong>SunSoak</strong>,
<strong>precipitation</strong>, and <strong>visibility</strong> (critical for navigation <strong>precipitation</strong>, and <strong>visibility</strong> (critical for navigation
in poor conditions). in poor conditions).
</p> </p>
@@ -592,7 +617,7 @@
<strong>Fishing · Extra</strong> — river and sea anglers need to read conditions that most <strong>Fishing · Extra</strong> — river and sea anglers need to read conditions that most
weather apps don't surface. Shows <strong>air temperature</strong>, <strong>dew point</strong> weather apps don't surface. Shows <strong>air temperature</strong>, <strong>dew point</strong>
(morning condensation and hatch activity on rivers), <strong>wind speed and direction</strong>, (morning condensation and hatch activity on rivers), <strong>wind speed and direction</strong>,
<strong>cloud cover</strong>, <strong>UTCI+P</strong> for what it will actually feel like <strong>cloud cover</strong>, <strong>SunSoak</strong> for what it will actually feel like
on an exposed bank or boat, <strong>precipitation</strong>, and <strong>visibility</strong> on an exposed bank or boat, <strong>precipitation</strong>, and <strong>visibility</strong>
for sea and estuary conditions. for sea and estuary conditions.
</p> </p>
@@ -602,10 +627,10 @@
<p class="profile-name">🌡️ Temps · Extra</p> <p class="profile-name">🌡️ Temps · Extra</p>
<p> <p>
A comparison view that brings all temperature-derived columns into one place: A comparison view that brings all temperature-derived columns into one place:
<strong>air temperature</strong>, <strong>UTCI+P</strong>, <strong>surface soil <strong>air temperature</strong>, <strong>SunSoak felt temperature</strong>,
temperature</strong>, <strong>concrete surface temperature</strong>, <strong>vehicle <strong>surface soil temperature</strong>, <strong>concrete surface temperature</strong>,
interior temperature</strong>, <strong>indoor temperature</strong>, and <strong>managed <strong>vehicle interior temperature</strong>, <strong>indoor temperature</strong>, and
indoor temperature</strong>. Useful for understanding how the same weather conditions <strong>managed indoor temperature</strong>. Useful for understanding how the same weather conditions
manifest across different environments simultaneously. manifest across different environments simultaneously.
</p> </p>
</div> </div>
@@ -617,7 +642,7 @@
temperature, dew point, relative humidity, wind, direction, cloud, visibility, air quality temperature, dew point, relative humidity, wind, direction, cloud, visibility, air quality
index, pollen, sun elevation, direct and diffuse radiation, mean radiant temperature, index, pollen, sun elevation, direct and diffuse radiation, mean radiant temperature,
UTCI delta, UTCI, UV-A, UV-B, burn time, vehicle interior, indoor, managed indoor, UTCI delta, UTCI, UV-A, UV-B, burn time, vehicle interior, indoor, managed indoor,
soil temperatures, soil moisture, concrete surface, precipitation, and UTCI+P. Build soil temperatures, soil moisture, concrete surface, precipitation, and SunSoak. Build
exactly the view that suits your situation. exactly the view that suits your situation.
</p> </p>
</div> </div>
@@ -648,7 +673,7 @@
<tr><td><strong>UV-A</strong></td><td>Estimated UV-A radiation index. UV-A penetrates deeper into the skin and contributes to long-term ageing and some skin cancers, even through glass. Present throughout daylight hours.</td></tr> <tr><td><strong>UV-A</strong></td><td>Estimated UV-A radiation index. UV-A penetrates deeper into the skin and contributes to long-term ageing and some skin cancers, even through glass. Present throughout daylight hours.</td></tr>
<tr><td><strong>UV-B</strong></td><td>Estimated UV-B radiation index. Causes sunburn and drives vitamin D production. Intensity falls sharply at low solar elevations due to the longer atmospheric path length.</td></tr> <tr><td><strong>UV-B</strong></td><td>Estimated UV-B radiation index. Causes sunburn and drives vitamin D production. Intensity falls sharply at low solar elevations due to the longer atmospheric path length.</td></tr>
<tr><td><strong>Burn time</strong></td><td>Estimated time to reach one Minimal Erythemal Dose (MED) — the threshold for sunburn — based on the UV index and your selected Fitzpatrick skin type. A guide, not a medical measurement.</td></tr> <tr><td><strong>Burn time</strong></td><td>Estimated time to reach one Minimal Erythemal Dose (MED) — the threshold for sunburn — based on the UV index and your selected Fitzpatrick skin type. A guide, not a medical measurement.</td></tr>
<tr><td><strong>UTCI+P °C</strong></td><td>SunScope's adjusted felt temperature: UTCI plus the soak-factor penalty for rain and snow. Wet clothing and skin can reduce the effective felt temperature by up to 8 °C in heavy, windy rain.</td></tr> <tr><td><strong>SunSoak °C</strong></td><td>SunScope's signature felt-temperature index. Starts from UTCI then adds three layers: a rain and snow penalty (wet clothing can drop felt temperature by up to 8 °C), an environment modifier for where you actually are (forest, alpine, beach, river, desert), and full mean radiant temperature from surrounding surfaces. The most honest single answer to: what will it actually feel like out there?</td></tr>
<tr><td><strong>Precip mm</strong></td><td>Expected rainfall or snowfall in mm per hour. Even light drizzle meaningfully reduces felt temperature when combined with wind.</td></tr> <tr><td><strong>Precip mm</strong></td><td>Expected rainfall or snowfall in mm per hour. Even light drizzle meaningfully reduces felt temperature when combined with wind.</td></tr>
<tr><td><strong>Soil °C surface</strong></td><td>Temperature of the soil at the surface (0 cm depth). Most seeds germinate above 710 °C. Useful for sowing decisions and frost assessment.</td></tr> <tr><td><strong>Soil °C surface</strong></td><td>Temperature of the soil at the surface (0 cm depth). Most seeds germinate above 710 °C. Useful for sowing decisions and frost assessment.</td></tr>
<tr><td><strong>Soil °C 6 cm</strong></td><td>Soil temperature at 6 cm depth — the root zone for many crops and seedlings. Lags behind the surface by several hours.</td></tr> <tr><td><strong>Soil °C 6 cm</strong></td><td>Soil temperature at 6 cm depth — the root zone for many crops and seedlings. Lags behind the surface by several hours.</td></tr>
@@ -712,7 +737,7 @@
</p> </p>
<h2>Reading the stress bands</h2> <h2>Reading the stress bands</h2>
<p>SunScope maps every UTCI+P value to a thermal stress band so you can read conditions at a glance:</p> <p>SunScope maps every SunSoak value to a thermal stress band so you can read conditions at a glance:</p>
<table class="stress-table"> <table class="stress-table">
<thead> <thead>
@@ -741,7 +766,7 @@
<details class="faq-block"> <details class="faq-block">
<summary class="faq-q">Why does SunScope sometimes show a lower temperature than my regular weather app?</summary> <summary class="faq-q">Why does SunScope sometimes show a lower temperature than my regular weather app?</summary>
<p class="faq-a">Wind chill and precipitation both reduce felt temperature. If it's raining or blustery, the UTCI+P value will be noticeably lower than the thermometer reading — which is exactly what your body experiences.</p> <p class="faq-a">Wind chill and precipitation both reduce felt temperature. If it's raining or blustery, the SunSoak value will be noticeably lower than the thermometer reading — which is exactly what your body experiences.</p>
</details> </details>
<details class="faq-block"> <details class="faq-block">
@@ -811,7 +836,7 @@
<details class="faq-block"> <details class="faq-block">
<summary class="faq-q">What does the weather icon and temperature on each day tab mean?</summary> <summary class="faq-q">What does the weather icon and temperature on each day tab mean?</summary>
<p class="faq-a">Each day tab in the date strip shows a small weather icon representing the dominant daytime sky conditions — a sun disc for clear days, cloud variants (wispy cirrus, scattered cumulus, overcast) for cloudy days, or a precipitation icon for rainy or snowy days. Below the icon are the day's high and low UTCI+P felt temperatures in warm and cool colours. The icon is derived from actual daytime solar elevation and cloud data, so it reflects the real character of the day rather than a generic symbol.</p> <p class="faq-a">Each day tab in the date strip shows a small weather icon representing the dominant daytime sky conditions — a sun disc for clear days, cloud variants (wispy cirrus, scattered cumulus, overcast) for cloudy days, or a precipitation icon for rainy or snowy days. Below the icon are the day's high and low SunSoak felt temperatures in warm and cool colours. The icon is derived from actual daytime solar elevation and cloud data, so it reflects the real character of the day rather than a generic symbol.</p>
</details> </details>
<details class="faq-block"> <details class="faq-block">
+49 -17
View File
@@ -30,7 +30,7 @@ import {
} from './utils.js'; } from './utils.js';
import { SkyScope, WindVane, CloudIcon, ScopeReticle, PrecipIcon, CustomSelect, VentPill } from './components.js'; import { SkyScope, WindVane, CloudIcon, ScopeReticle, PrecipIcon, CustomSelect, VentPill } from './components.js';
import { getCellTagEvents, getUpcomingEvents } from './events.js'; import { getCellTagEvents, getUpcomingEvents } from './events.js';
import { POLLEN_TYPES, COL_DESCRIPTIONS } from './config.js'; import { POLLEN_TYPES, COL_DESCRIPTIONS, UTCI_ENVIRONMENTS } from './config.js';
import { useAppState } from './hooks/useAppState.js'; import { useAppState } from './hooks/useAppState.js';
import { DayTabs } from './components/DayTabs.js'; import { DayTabs } from './components/DayTabs.js';
@@ -64,6 +64,7 @@ export function UTCIForecast() {
indoorManaged, setIndoorManaged, indoorManaged, setIndoorManaged,
indoorMode, setIndoorMode, indoorMode, setIndoorMode,
pollenType, setPollenTypeAndSave, pollenType, setPollenTypeAndSave,
utciEnv, setUtciEnv,
headStickyRef, headTrackRef, headTableRef, headStickyRef, headTrackRef, headTableRef,
bodyScrollRef, bodyTableRef, tableWrapRef, bodyScrollRef, bodyTableRef, tableWrapRef,
colPopup, colPopupRef, colPopup, colPopupRef,
@@ -334,11 +335,34 @@ export function UTCIForecast() {
/>`} />`}
${(isPro || activeCols['burn'] || activeCols['vehicleT'] || activeCols['indoorT'] || activeCols['managedT'] || activeCols['pollen']) && html` ${(isPro || activeCols['utciP'] || activeCols['burn'] || activeCols['vehicleT'] || activeCols['indoorT'] || activeCols['managedT'] || activeCols['pollen']) && html`
<div class="col-toggles"> <div class="col-toggles">
<span class="col-toggles-label">Columns:</span> <span class="col-toggles-label">Columns:</span>
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['utciP']) && html`<button class=${`col-toggle grp-felt${visibleCols.utciP ? ' on' : ''}`} onClick=${() => toggleCol('utciP')}>UTCI+P</button>`} ${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['utciP']) : activeCols['utciP']) && html`
<span class=${'col-toggle-group' + (visibleCols.utciP ? ' col-toggle-group--expanded' : '')}>
<${CustomSelect}
value=${utciEnv}
isOn=${visibleCols.utciP}
grpClass="grp-felt"
hideLabel="SunSoak"
hidingLabel="Hide SunSoak"
groupedLeft=${true}
isLastChild=${true}
options=${Object.entries(UTCI_ENVIRONMENTS).map(([k, v]) => ({
value: k,
label: v.label,
}))}
onChange=${(v) => {
if (v === 'off') {
setVisibleCols(prev => ({ ...prev, utciP: false }));
} else {
setUtciEnv(v);
setVisibleCols(prev => ({ ...prev, utciP: true }));
}
}}
/>
</span>`}
${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['vehicleT']) : activeCols['vehicleT']) && html` ${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['vehicleT']) : activeCols['vehicleT']) && html`
<span class=${'col-toggle-group' + (visibleCols.vehicleT ? ' col-toggle-group--expanded' : '')}> <span class=${'col-toggle-group' + (visibleCols.vehicleT ? ' col-toggle-group--expanded' : '')}>
<${CustomSelect} <${CustomSelect}
@@ -491,7 +515,7 @@ ${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeC
${groupLabelRow()} ${groupLabelRow()}
<tr> <tr>
<th class="col-info-th" scope="col" onClick=${(e) => handleThClick('hour', e)} onMouseEnter=${(e) => handleThEnter('hour', e)} onMouseLeave=${handleThLeave}>Hour</th> <th class="col-info-th" scope="col" onClick=${(e) => handleThClick('hour', e)} onMouseEnter=${(e) => handleThEnter('hour', e)} onMouseLeave=${handleThLeave}>Hour</th>
${visibleCols.utciP && html`<th class=${`col-info-th ${groupStart('utciP')} ${groupColor('utciP')}`} scope="col" onClick=${(e) => handleThClick('utciP', e)} onMouseEnter=${(e) => handleThEnter('utciP', e)} onMouseLeave=${handleThLeave}>UTCI+P <span class="col-unit">°C adj.</span></th>`} ${visibleCols.utciP && html`<th class=${`col-info-th ${groupStart('utciP')} ${groupColor('utciP')}`} scope="col" onClick=${(e) => handleThClick('utciP', e)} onMouseEnter=${(e) => handleThEnter('utciP', e)} onMouseLeave=${handleThLeave}>SunSoak <span class="col-unit">°C felt</span></th>`}
${visibleCols.vehicleT && html`<th class=${`col-info-th ${groupStart('vehicleT')} ${groupColor('vehicleT')}`} scope="col" onClick=${(e) => handleThClick('vehicleT', e)} onMouseEnter=${(e) => handleThEnter('vehicleT', e)} onMouseLeave=${handleThLeave}>Vehicle <span class="col-unit">°C peak</span></th>`} ${visibleCols.vehicleT && html`<th class=${`col-info-th ${groupStart('vehicleT')} ${groupColor('vehicleT')}`} scope="col" onClick=${(e) => handleThClick('vehicleT', e)} onMouseEnter=${(e) => handleThEnter('vehicleT', e)} onMouseLeave=${handleThLeave}>Vehicle <span class="col-unit">°C peak</span></th>`}
${indoorMode === 'on' && !indoorManaged && html`<th class=${`col-info-th ${groupStart('indoorT')} ${groupColor('indoorT')}`} scope="col" onClick=${(e) => handleThClick('indoorT', e)} onMouseEnter=${(e) => handleThEnter('indoorT', e)} onMouseLeave=${handleThLeave}>Indoors <span class="col-unit">°C est.</span></th>`} ${indoorMode === 'on' && !indoorManaged && html`<th class=${`col-info-th ${groupStart('indoorT')} ${groupColor('indoorT')}`} scope="col" onClick=${(e) => handleThClick('indoorT', e)} onMouseEnter=${(e) => handleThEnter('indoorT', e)} onMouseLeave=${handleThLeave}>Indoors <span class="col-unit">°C est.</span></th>`}
${indoorMode === 'on' && indoorManaged && html`<th class=${`col-info-th ${groupStart('managedT')} ${groupColor('managedT')}`} scope="col" onClick=${(e) => handleThClick('managedT', e)} onMouseEnter=${(e) => handleThEnter('managedT', e)} onMouseLeave=${handleThLeave}>Managed <span class="col-unit">°C est.</span></th>`} ${indoorMode === 'on' && indoorManaged && html`<th class=${`col-info-th ${groupStart('managedT')} ${groupColor('managedT')}`} scope="col" onClick=${(e) => handleThClick('managedT', e)} onMouseEnter=${(e) => handleThEnter('managedT', e)} onMouseLeave=${handleThLeave}>Managed <span class="col-unit">°C est.</span></th>`}
@@ -879,26 +903,34 @@ ${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeC
<p class="utci-about-text"> <p class="utci-about-text">
SunScope is a free hourly weather forecast built around <strong>felt temperature</strong>, SunScope is a free hourly weather forecast built around <strong>felt temperature</strong>,
not just air temperature. It uses the <strong>Universal Thermal Climate Index (UTCI)</strong> not just air temperature. It uses the <strong>Universal Thermal Climate Index (UTCI)</strong>
the biometeorological standard used in heat-health warning systems worldwide to combine the biometeorological standard used in heat-health warning systems worldwide as its
air temperature, humidity, wind, and solar radiation into a single honest number. The foundation, combining air temperature, humidity, wind, and solar radiation into a single
<strong>UTCI+P</strong> column adds an original rain and snow penalty so wet, windy days honest number. Then it goes further. Our <strong>SunSoak</strong> index layers three extra
read as cold as they feel. dimensions on top: a rain and snow penalty so wet, windy days read as cold as they feel;
an <strong>environment modifier</strong> that adjusts the solar load for where you actually
are forest canopy, alpine altitude, lakeside glare, shaded riverbank, desert ground heat;
and the full radiant heat absorbed from surrounding surfaces. One number that honestly
answers: <em>what will my body actually feel out there?</em>
</p> </p>
<p class="utci-about-text"> <p class="utci-about-text">
Beyond felt temperature, SunScope calculates <strong>vehicle cabin heat</strong> (choose Beyond SunSoak, SunScope calculates <strong>vehicle cabin heat</strong> (choose your
your vehicle type; toggle windows open), <strong>indoor temperature</strong> (seven vehicle type; toggle windows open), <strong>indoor temperature</strong> (seven building
building types; managed heatwave mode), <strong>urban concrete surface temperature</strong>, types including office blocks; managed heatwave mode), <strong>urban concrete surface
<strong>UV index and sunburn time</strong> by skin type, and <strong>soil temperature temperature</strong>, <strong>UV index and sunburn time</strong> by skin type, and
and moisture</strong> for farming and motorhome use. Switch profiles to see the data <strong>soil temperature and moisture</strong> for farming and motorhome use. Switch
that matters for your situation or go Custom and build your own view. profiles Places, Activities, Work to see the data that matters for your situation,
or go Custom and build your own view.
<a href="./about.html" class="utci-about-link">Learn more </a> <a href="./about.html" class="utci-about-link">Learn more </a>
</p> </p>
</div> </div>
<div class="utci-footer"> <div class="utci-footer">
<em>Reading the table.</em> A large positive Δ means your body is absorbing <em>Reading the table.</em> SunSoak is the number to watch it reflects everything your body
far more heat than the air temperature alone suggests typically due to direct solar radiation. actually experiences, not just what the thermometer says. A large gap between SunSoak and Air
On clear sunny days this gap can exceed 10 °C even at modest air temperatures. temperature means solar radiation is doing significant work on your body. On clear sunny days
that gap can exceed 10 °C even at modest air temperatures. The environment modifier in the
SunSoak dropdown adjusts the solar load for your surroundings switch it to match where you are
for the most accurate reading.
${isPro && html` ${isPro && html`
<div style=${{ marginTop: '10px', paddingTop: '10px', borderTop: '1px solid #d4c0a0' }}> <div style=${{ marginTop: '10px', paddingTop: '10px', borderTop: '1px solid #d4c0a0' }}>
SunScope Extra is active. SunScope Extra is active.
+39 -11
View File
@@ -168,29 +168,57 @@ export function DayTabs({
const promptDate = new Date(days[proPromptDay].key + 'T00:00Z'); const promptDate = new Date(days[proPromptDay].key + 'T00:00Z');
const dayName = promptDate.toLocaleDateString('en-GB', { weekday: 'long', timeZone: 'UTC' }); const dayName = promptDate.toLocaleDateString('en-GB', { weekday: 'long', timeZone: 'UTC' });
const extraPromptCopy = { const extraPromptCopy = {
'variant:sailing': { // Profile buttons
title: 'Sailing is part of SunScope Extra',
detail: 'Extra adds specialist planning views for higher-commitment trips, including wind, exposure, UV, and wet-weather comfort for water conditions.',
},
'profile:alltemps': { 'profile:alltemps': {
title: 'Temps is part of SunScope Extra', title: 'Temps is part of SunScope Extra',
detail: 'Extra unlocks the comparison view for air, soil, concrete, vehicle, and indoor temperatures in one place.', detail: 'Extra unlocks the temperature comparison view air, soil, concrete, vehicle interior, and indoor estimates side by side in one place.',
},
'profile:showall': {
title: 'Show All is part of SunScope Extra',
detail: 'Extra unlocks the full column set — every data point SunScope tracks, visible at once for deep-dive analysis.',
}, },
'profile:custom': { 'profile:custom': {
title: 'Custom columns are part of SunScope Extra', title: 'Custom columns are part of SunScope Extra',
detail: 'Extra lets you choose exactly which columns appear: mix and match Air, Dew, Soil, UV, UTCI and more to build your perfect view.', detail: 'Extra lets you hand-pick exactly which columns appear. Mix and match air, dew, soil, UV, UTCI and more to build your perfect view.',
}, },
'variant:festival': { // Places
title: 'Festival planning is part of SunScope Extra', 'variant:construction': {
detail: 'Extra adds multi-day comfort, ground condition, exposure, and rain planning for higher-stakes outdoor trips.', title: 'Construction is part of SunScope Extra',
detail: 'Extra adds the Construction profile with felt temperature, wind, rain probability, visibility, and air quality — the key factors for safe site working.',
},
// Activities
'variant:hiking': {
title: 'Hiking is part of SunScope Extra',
detail: 'Extra adds the Hiking profile with felt temperature, UV index, burn time, wind direction, and visibility — essential for longer days on exposed terrain.',
},
'variant:photography': {
title: 'Photography is part of SunScope Extra',
detail: 'Extra adds the Photography profile with direct and diffuse radiation, sun elevation, cloud cover, and visibility — the conditions that make or break a shoot.',
},
'variant:sailing': {
title: 'Sailing is part of SunScope Extra',
detail: 'Extra adds the Sailing profile with wind speed and direction, dew point, UV, burn time, sun elevation, and visibility for on-water planning.',
}, },
'variant:wintersports': { 'variant:wintersports': {
title: 'Winter Sports is part of SunScope Extra', title: 'Winter Sports is part of SunScope Extra',
detail: 'Extra adds specialist exposure planning for snow, glare, wind, UV reflection, and cold-weather comfort.', detail: 'Extra adds the Winter Sports profile with UV-A and UV-B, burn time, sun elevation, wind direction, and visibility for snow and slope conditions.',
}, },
'variant:naturist': { 'variant:naturist': {
title: 'Naturist is part of SunScope Extra', title: 'Naturist is part of SunScope Extra',
detail: 'Extra adds specialist skin-exposure planning with UV, wind, humidity, precipitation, and felt-temperature detail.', detail: 'Extra adds the Naturist profile with full skin-exposure detail — UV, burn time, felt temperature, dew point, humidity, and air quality.',
},
// Work
'variant:market': {
title: 'Market Trading is part of SunScope Extra',
detail: 'Extra adds the Market Trading profile with felt temperature, wind direction, rain probability, and visibility — the key factors for planning stall days.',
},
'variant:windowcleaning': {
title: 'Window Cleaning is part of SunScope Extra',
detail: 'Extra adds the Window Cleaning profile focused on wind speed and direction, rain, and felt temperature — the conditions that determine whether work is safe and worthwhile.',
},
'variant:office': {
title: 'Office is part of SunScope Extra',
detail: 'Extra adds the Office profile with solar gain, managed indoor temperature, humidity, air quality, and rain probability — useful for commute planning and building comfort.',
}, },
}; };
const promptCopy = extraPromptCopy[proPromptSource] || { const promptCopy = extraPromptCopy[proPromptSource] || {
+10 -3
View File
@@ -16,8 +16,10 @@ import {
calcIndoorTempPass, calcManagedIndoorTempPass, calcIndoorTempPass, calcManagedIndoorTempPass,
} from './physics.js'; } from './physics.js';
import { windCompass8, uvSplit, cloudCategory, precipPenalty } from './utils.js'; import { windCompass8, uvSplit, cloudCategory, precipPenalty } from './utils.js';
import { UTCI_ENVIRONMENTS } from './config.js';
export function buildHourlyRows({ forecast, airQuality, location, vehicleType, vehicleVent, buildingType }) { export function buildHourlyRows({ forecast, airQuality, location, vehicleType, vehicleVent, buildingType, utciEnv }) {
const env = UTCI_ENVIRONMENTS[utciEnv] ?? UTCI_ENVIRONMENTS.open;
const utcOffsetMs = (forecast?.utc_offset_seconds ?? 0) * 1000; const utcOffsetMs = (forecast?.utc_offset_seconds ?? 0) * 1000;
// Build a fast lookup map from the air quality hourly data: ISO string - index. // Build a fast lookup map from the air quality hourly data: ISO string - index.
@@ -75,8 +77,13 @@ export function buildHourlyRows({ forecast, airQuality, location, vehicleType, v
// concreteT is now stamped in the two-pass section below (thermal lag). // concreteT is now stamped in the two-pass section below (thermal lag).
const vehicleT = calcVehicleInteriorTemp(Ta, glob, elev, vehicleType, vehicleVent); const vehicleT = calcVehicleInteriorTemp(Ta, glob, elev, vehicleType, vehicleVent);
const eh = vaporPressureHpa(Ta, RH); const eh = vaporPressureHpa(Ta, RH);
const Tmrt = calcTmrt(Ta, dir, dif, glob, elev); // Apply environment modifier - adjust solar inputs and air temp for shaded environments.
const utci = utciApprox(Ta, Tmrt, va, eh); const TaEnv = Ta + env.taOffset;
const dirEnv = dir * env.dirFactor;
const difEnv = dif * env.difFactor;
const globEnv = glob * env.globFactor;
const Tmrt = calcTmrt(TaEnv, dirEnv, difEnv, globEnv, elev);
const utci = utciApprox(TaEnv, Tmrt, va, eh);
const utciAdj = utci + precipPenalty(precip, snow, va); const utciAdj = utci + precipPenalty(precip, snow, va);
// Derived // Derived
const compass = windCompass8(wd); const compass = windCompass8(wd);
+40 -5
View File
@@ -10,6 +10,7 @@
// FILTER_PROFILES ............ preset column sets (Basic, Home, etc.) // FILTER_PROFILES ............ preset column sets (Basic, Home, etc.)
// OUTDOORS_VARIANTS .......... Places & Activities sub-variants // OUTDOORS_VARIANTS .......... Places & Activities sub-variants
// POLLEN_TYPES ............... pollen-column pulldown options // POLLEN_TYPES ............... pollen-column pulldown options
// UTCI_ENVIRONMENTS .......... environment modifiers for UTCI+P column
// variantIcons ............... emoji glyph per place/activity variant // variantIcons ............... emoji glyph per place/activity variant
// profileButtonOrder ......... left-to-right order of the profile buttons // profileButtonOrder ......... left-to-right order of the profile buttons
// activityVariantKeys ........ which variants appear in the Activities menu // activityVariantKeys ........ which variants appear in the Activities menu
@@ -77,12 +78,13 @@ 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 } }, 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 } }, 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 } }, 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', 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: 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 } }, 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 } }, 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 } }, 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 } }, 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 } },
// Places - free // 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 } }, 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 } }, 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 } },
// Places - Pro // 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, 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 } },
@@ -93,9 +95,9 @@ export const OUTDOORS_VARIANTS = {
// Activities - Pro // 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 } }, 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 } }, 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 } }, 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 } },
// Work variants // Work variants
market: { name: 'Market Trading', 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 } }, 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 } }, 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 } }, 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 } },
}; };
@@ -111,6 +113,38 @@ export const POLLEN_TYPES = {
ragweed_pollen: { name: 'Ragweed pollen', unit: 'grains/m³' }, ragweed_pollen: { name: 'Ragweed pollen', unit: 'grains/m³' },
}; };
// UTCI+P environment modifiers - affect solar inputs and air temp used
// in the UTCI calculation to reflect shaded or modified environments.
// dirFactor - fraction of direct radiation that reaches the person (0-1)
// difFactor - fraction of diffuse radiation that reaches the person (0-1)
// globFactor - fraction of global shortwave radiation that reaches the person (0-1)
// taOffset - offset applied to air temperature in degrees C (evapotranspiration etc.)
// label - short display name
// note - shown in column header tooltip to flag modified calculation
export const UTCI_ENVIRONMENTS = {
open: { label: 'Open / Exposed', dirFactor: 1.00, difFactor: 1.00, globFactor: 1.00, taOffset: 0.0, note: null },
forest: { label: 'Forest / Woodland', dirFactor: 0.15, difFactor: 0.40, globFactor: 0.20, taOffset: -2.0, note: 'Canopy-shaded estimate - direct radiation reduced 85%, air temp adjusted for evapotranspiration cooling' },
alpine: { label: 'High Altitude / Alpine', dirFactor: 1.15, difFactor: 1.10, globFactor: 1.12, taOffset: -1.0, note: 'Alpine estimate assuming approx. 2000 m elevation - radiation enhanced ~15% through thinner atmosphere, adjusted for exposed ridge conditions' },
beach: { label: 'Beach / Lakeside', dirFactor: 1.12, difFactor: 1.06, globFactor: 1.10, taOffset: 0.0, note: 'Reflected radiation from water and sand surfaces increases effective solar load - no shade, higher UV dose' },
river: { label: 'River / Riverbank', dirFactor: 0.50, difFactor: 0.60, globFactor: 0.55, taOffset: -2.5, note: 'Shaded riverbank estimate - canopy and valley walls reduce direct sun, evaporative cooling from water surface lowers apparent air temp' },
desert: { label: 'Desert / Arid', dirFactor: 1.22, difFactor: 1.10, globFactor: 1.18, taOffset: 3.5, note: 'Extreme radiation load from high albedo sand and bare ground - ground-level heat significantly raises effective felt temperature' },
};
// Maps OUTDOORS_VARIANTS keys to a default UTCI_ENVIRONMENTS key.
// When a variant is selected via the Places or Activities dropdown the
// UTCI+P environment modifier is automatically switched to match.
// Variants not listed here default to open.
export const VARIANT_DEFAULT_ENV = {
forest: 'forest',
park: 'forest',
beach: 'beach',
sailing: 'beach',
hiking: 'alpine',
wintersports:'alpine',
fishing: 'river',
naturist: 'beach',
};
// Left-to-right order of the profile buttons in the top filter bar. // Left-to-right order of the profile buttons in the top filter bar.
export const profileButtonOrder = ['basic', 'home', 'vehicle', 'alltemps', 'showall', 'custom']; export const profileButtonOrder = ['basic', 'home', 'vehicle', 'alltemps', 'showall', 'custom'];
@@ -120,6 +154,7 @@ export const variantIcons = {
beach: '🏖️', beach: '🏖️',
events: '🎪', events: '🎪',
park: '🌳', park: '🌳',
forest: '🌲',
airport: '✈️', airport: '✈️',
festival: '⛺', festival: '⛺',
construction: '🏗️', construction: '🏗️',
@@ -141,7 +176,7 @@ export const variantIcons = {
export const activityVariantKeys = ['dogwalk', 'running', 'cycling', 'hiking', 'fishing', 'sailing', 'wintersports', 'photography', 'naturist']; export const activityVariantKeys = ['dogwalk', 'running', 'cycling', 'hiking', 'fishing', 'sailing', 'wintersports', 'photography', 'naturist'];
// Which variant keys appear in the Places dropdown. // Which variant keys appear in the Places dropdown.
export const placeVariantKeys = ['urban', 'park', 'beach', 'events', 'festival', 'airport']; export const placeVariantKeys = ['urban', 'park', 'forest', 'beach', 'events', 'festival', 'airport'];
// Which variant keys appear in the Work dropdown. // Which variant keys appear in the Work dropdown.
export const workVariantKeys = ['farming', 'construction', 'market', 'windowcleaning', 'office']; export const workVariantKeys = ['farming', 'construction', 'market', 'windowcleaning', 'office'];
@@ -164,7 +199,7 @@ export const COL_DESCRIPTIONS = {
uvA: { title: 'UV-A Index', desc: 'Estimated UV-A radiation index. UV-A penetrates deeper into the skin and contributes to long-term ageing and some skin cancers, even through glass.' }, uvA: { title: 'UV-A Index', desc: 'Estimated UV-A radiation index. UV-A penetrates deeper into the skin and contributes to long-term ageing and some skin cancers, even through glass.' },
uvB: { title: 'UV-B Index', desc: 'Estimated UV-B radiation index. UV-B causes sunburn and is the main driver of vitamin D production. Intensity depends strongly on solar elevation and cloud cover.' }, uvB: { title: 'UV-B Index', desc: 'Estimated UV-B radiation index. UV-B causes sunburn and is the main driver of vitamin D production. Intensity depends strongly on solar elevation and cloud cover.' },
burn: { title: 'Burn Time', desc: 'Estimated time to reach one Minimal Erythemal Dose (MED) — the threshold for sunburn — based on the UV index and your selected skin type. This is a guide, not a medical measurement.' }, burn: { title: 'Burn Time', desc: 'Estimated time to reach one Minimal Erythemal Dose (MED) — the threshold for sunburn — based on the UV index and your selected skin type. This is a guide, not a medical measurement.' },
utciP: { title: 'UTCI+P', desc: 'SunScope\'s adjusted felt temperature: UTCI plus the soak-factor penalty for precipitation. Rain and snow on wet clothing can reduce the felt temperature by up to 8 °C.' }, utciP: { title: 'SunSoak', desc: 'SunScope\'s signature felt-temperature index. Starts from UTCI - the biometeorological standard combining air temp, humidity, wind and solar radiation - then layers in three extra dimensions: a rain and snow penalty (wet clothing can drop felt temp by up to 8 °C), an environment modifier that adjusts solar load for where you actually are (forest canopy, alpine altitude, lakeside reflection, shaded riverbank, desert ground heat), and the full radiant heat from your surroundings. One number that honestly answers: what will my body actually feel out there?' },
precip: { title: 'Precipitation', desc: 'Expected rainfall or snowfall in mm per hour. Snow is shown in cm. Even light drizzle meaningfully reduces felt temperature when combined with wind.' }, precip: { title: 'Precipitation', desc: 'Expected rainfall or snowfall in mm per hour. Snow is shown in cm. Even light drizzle meaningfully reduces felt temperature when combined with wind.' },
precipProb: { title: 'Rain Probability', desc: 'Probability of precipitation for this hour as a percentage (0-100%). Derived from Open-Meteo ensemble model runs. A high value means rain is likely even if the expected rate is low - useful for spotting showers that the deterministic forecast may miss.' }, precipProb: { title: 'Rain Probability', desc: 'Probability of precipitation for this hour as a percentage (0-100%). Derived from Open-Meteo ensemble model runs. A high value means rain is likely even if the expected rate is low - useful for spotting showers that the deterministic forecast may miss.' },
soilT: { title: 'Soil Temperature', desc: 'Temperature of the soil at the surface (0 cm depth). Useful for planting decisions — most seeds germinate above 710 °C.' }, soilT: { title: 'Soil Temperature', desc: 'Temperature of the soil at the surface (0 cm depth). Useful for planting decisions — most seeds germinate above 710 °C.' },
+20 -1
View File
@@ -27,6 +27,7 @@ import {
FREE_DAYS, FILTER_PROFILES, OUTDOORS_VARIANTS, FREE_DAYS, FILTER_PROFILES, OUTDOORS_VARIANTS,
profileButtonOrder, variantIcons, profileButtonOrder, variantIcons,
activityVariantKeys, placeVariantKeys, workVariantKeys, activityVariantKeys, placeVariantKeys, workVariantKeys,
UTCI_ENVIRONMENTS, VARIANT_DEFAULT_ENV,
} from '../config.js'; } from '../config.js';
import { utciCategory } from '../utils.js'; import { utciCategory } from '../utils.js';
import { buildHourlyRows } from '../compute.js'; import { buildHourlyRows } from '../compute.js';
@@ -196,6 +197,9 @@ export function useAppState() {
const hasIndoor = variantCols['indoorT'] || variantCols['managedT']; const hasIndoor = variantCols['indoorT'] || variantCols['managedT'];
setIndoorMode(hasIndoor ? 'on' : 'off'); setIndoorMode(hasIndoor ? 'on' : 'off');
} }
// Auto-set UTCI environment modifier to match the selected variant.
const defaultEnv = VARIANT_DEFAULT_ENV[v] ?? 'open';
setUtciEnvAndSave(defaultEnv);
}; };
const activeCols = activeProfile === 'outdoors' const activeCols = activeProfile === 'outdoors'
@@ -245,6 +249,20 @@ export function useAppState() {
setPollenType(v); setPollenType(v);
}; };
const [utciEnv, setUtciEnv] = useState(() => {
try {
const saved = localStorage.getItem('sunscope_utci_env');
if (saved && UTCI_ENVIRONMENTS[saved]) return saved;
// No saved env - derive from the saved variant if it has a default.
const savedVariant = localStorage.getItem('sunscope_outdoors_variant') || '';
return VARIANT_DEFAULT_ENV[savedVariant] ?? 'open';
} catch (e) { return 'open'; }
});
const setUtciEnvAndSave = (v) => {
try { localStorage.setItem('sunscope_utci_env', v); } catch (e) { /* ignore */ }
setUtciEnv(v);
};
const [showDecimals, setShowDecimals] = useState(() => { const [showDecimals, setShowDecimals] = useState(() => {
try { const s = localStorage.getItem('sunscope_show_decimals'); return s === null ? false : s !== '0'; } catch (e) { return false; } try { const s = localStorage.getItem('sunscope_show_decimals'); return s === null ? false : s !== '0'; } catch (e) { return false; }
}); });
@@ -359,7 +377,7 @@ export function useAppState() {
// ── 9. COMPUTATION ─────────────────────────────────────────────────── // ── 9. COMPUTATION ───────────────────────────────────────────────────
const { hourlyRows, days, utcOffsetMs } = buildHourlyRows({ const { hourlyRows, days, utcOffsetMs } = buildHourlyRows({
forecast, airQuality, location, vehicleType, vehicleVent, buildingType, forecast, airQuality, location, vehicleType, vehicleVent, buildingType, utciEnv,
}); });
const visible = days[selectedDay]?.rows || []; const visible = days[selectedDay]?.rows || [];
@@ -497,6 +515,7 @@ export function useAppState() {
indoorManaged, setIndoorManaged: setIndoorManagedAndSave, indoorManaged, setIndoorManaged: setIndoorManagedAndSave,
indoorMode, setIndoorMode: setIndoorModeAndSave, indoorMode, setIndoorMode: setIndoorModeAndSave,
pollenType, setPollenTypeAndSave, pollenType, setPollenTypeAndSave,
utciEnv, setUtciEnv: setUtciEnvAndSave,
showDecimals, toggleShowDecimals, showDecimals, toggleShowDecimals,
showUnits, toggleShowUnits, showUnits, toggleShowUnits,
// table refs // table refs
+9 -9
View File
@@ -26,11 +26,11 @@
"@type": "FAQPage", "@type": "FAQPage",
"mainEntity": [ "mainEntity": [
{"@type":"Question","name":"What is UTCI and why is it more accurate than feels-like temperature?","acceptedAnswer":{"@type":"Answer","text":"UTCI stands for Universal Thermal Climate Index. Unlike a standard feels-like temperature which usually only adjusts for wind chill or humidity on their own, UTCI uses a full physiological model of the human body. It combines four factors at once: air temperature, humidity, wind speed, and the heat from solar radiation hitting your skin. On a sunny day the sun can make you feel 10-15 degrees warmer than the air temperature alone, and most weather apps ignore this entirely. UTCI is a peer-reviewed scientific standard used in public health systems across Europe."}}, {"@type":"Question","name":"What is UTCI and why is it more accurate than feels-like temperature?","acceptedAnswer":{"@type":"Answer","text":"UTCI stands for Universal Thermal Climate Index. Unlike a standard feels-like temperature which usually only adjusts for wind chill or humidity on their own, UTCI uses a full physiological model of the human body. It combines four factors at once: air temperature, humidity, wind speed, and the heat from solar radiation hitting your skin. On a sunny day the sun can make you feel 10-15 degrees warmer than the air temperature alone, and most weather apps ignore this entirely. UTCI is a peer-reviewed scientific standard used in public health systems across Europe."}},
{"@type":"Question","name":"What is the SunScope soak-factor and what does UTCI+P mean?","acceptedAnswer":{"@type":"Answer","text":"UTCI on its own does not account for the extra chill of rain soaking through your clothes. The SunScope soak-factor is an original precipitation penalty formula that reduces the felt temperature based on rain intensity, snowfall, and wind speed. The result is shown as UTCI+P. On a dry day UTCI and UTCI+P are identical. On a wet and windy day the soak-factor can drop the felt temperature by several degrees, reflecting what your body actually experiences."}}, {"@type":"Question","name":"What is SunSoak and how is it different from UTCI?","acceptedAnswer":{"@type":"Answer","text":"SunSoak is SunScope's signature felt-temperature index. It starts from UTCI - the biometeorological standard - and adds three extra layers: a rain and snow penalty reflecting the chill of wet clothing (heavy rain plus strong wind can drop felt temperature by 7-8 degrees); an environment modifier adjusting the solar load for where you actually are (forest canopy, alpine altitude, beach glare, shaded riverbank, desert ground heat); and mean radiant temperature from all surrounding surfaces. On a dry day in open conditions SunSoak and UTCI are very similar. In rain, shade, altitude, or at the coast they can differ significantly."}},
{"@type":"Question","name":"What is the difference between UTCI and heat index?","acceptedAnswer":{"@type":"Answer","text":"Heat index is a simple table-based formula that adjusts air temperature for humidity only - it ignores wind and solar radiation entirely. UTCI is a full physiological model accounting for air temperature, humidity, wind speed, and mean radiant temperature from solar radiation. In sunny or windy conditions the two values can differ by 10-20 degrees. UTCI is the standard used in European heat-health warning systems."}}, {"@type":"Question","name":"What is the difference between UTCI and heat index?","acceptedAnswer":{"@type":"Answer","text":"Heat index is a simple table-based formula that adjusts air temperature for humidity only - it ignores wind and solar radiation entirely. UTCI is a full physiological model accounting for air temperature, humidity, wind speed, and mean radiant temperature from solar radiation. In sunny or windy conditions the two values can differ by 10-20 degrees. UTCI is the standard used in European heat-health warning systems."}},
{"@type":"Question","name":"Why does SunScope sometimes show a much higher temperature than my regular weather app?","acceptedAnswer":{"@type":"Answer","text":"On clear sunny days, direct solar radiation heats your skin significantly - sometimes adding 10 degrees or more to what the air temperature alone would suggest. SunScope calculates mean radiant temperature from real shortwave radiation forecast data. Standard weather apps ignore solar radiation entirely and only report air temperature or basic wind chill."}}, {"@type":"Question","name":"Why does SunScope sometimes show a much higher temperature than my regular weather app?","acceptedAnswer":{"@type":"Answer","text":"On clear sunny days, direct solar radiation heats your skin significantly - sometimes adding 10 degrees or more to what the air temperature alone would suggest. SunScope calculates mean radiant temperature from real shortwave radiation forecast data. Standard weather apps ignore solar radiation entirely and only report air temperature or basic wind chill."}},
{"@type":"Question","name":"Why does SunScope sometimes show a lower temperature than my regular weather app?","acceptedAnswer":{"@type":"Answer","text":"Wind chill and precipitation both reduce felt temperature. If it is raining or blustery, the UTCI+P value will be noticeably lower than the thermometer reading. A 15 degree day with heavy rain and a strong wind can feel closer to 8 or 9 degrees. SunScope captures this; most apps do not."}}, {"@type":"Question","name":"Why does SunScope sometimes show a lower temperature than my regular weather app?","acceptedAnswer":{"@type":"Answer","text":"Wind chill and precipitation both reduce felt temperature. If it is raining or blustery, the SunSoak value will be noticeably lower than the thermometer reading. A 15 degree day with heavy rain and a strong wind can feel closer to 8 or 9 degrees. SunScope captures this; most apps do not."}},
{"@type":"Question","name":"How do I read the SunScope table?","acceptedAnswer":{"@type":"Answer","text":"Each row is one hour of the day. The most important column is UTCI+P - the felt temperature accounting for all weather factors combined. Colour coding tells you comfort at a glance: blue means cold, green means comfortable, yellow and orange mean warm or hot, red means dangerous heat stress. Switch between profiles using the buttons and dropdowns above the table - Basic, Home, Vehicle, then Places and Activities dropdowns for location and activity-specific views. Hover any column header for a plain-language description of what it shows."}}, {"@type":"Question","name":"How do I read the SunScope table?","acceptedAnswer":{"@type":"Answer","text":"Each row is one hour of the day. The most important column is SunSoak - the felt temperature accounting for all weather factors combined. Colour coding tells you comfort at a glance: blue means cold, green means comfortable, yellow and orange mean warm or hot, red means dangerous heat stress. Switch between profiles using the buttons and dropdowns above the table - Basic, Home, Vehicle, then Places and Activities dropdowns for location and activity-specific views. Hover any column header for a plain-language description of what it shows."}},
{"@type":"Question","name":"What do the different profiles and dropdowns show?","acceptedAnswer":{"@type":"Answer","text":"Each profile is a curated set of columns. Basic shows core weather: felt temperature, sky, wind, rain. Home adds indoor building temperature. Vehicle adds car cabin temperature, soil moisture, and visibility. The Places dropdown offers Urban, Beach, Events, Park, Airport (free) plus Festival and Construction (Extra). The Activities dropdown offers Farming, Cycling, Running, and Dog Walking (free) plus Sailing, Winter Sports, Naturist, Hiking, Photography, and Fishing (Extra). Temps and Custom are Extra-only."}}, {"@type":"Question","name":"What do the different profiles and dropdowns show?","acceptedAnswer":{"@type":"Answer","text":"Each profile is a curated set of columns. Basic shows core weather: felt temperature, sky, wind, rain. Home adds indoor building temperature. Vehicle adds car cabin temperature, soil moisture, and visibility. The Places dropdown offers Urban, Beach, Events, Park, Airport (free) plus Festival and Construction (Extra). The Activities dropdown offers Farming, Cycling, Running, and Dog Walking (free) plus Sailing, Winter Sports, Naturist, Hiking, Photography, and Fishing (Extra). Temps and Custom are Extra-only."}},
{"@type":"Question","name":"How do I set or change my location?","acceptedAnswer":{"@type":"Answer","text":"Use the search bar at the top of the forecast page. Type any city, town, village, or postcode and select from the dropdown results. SunScope works for locations worldwide. Your last searched location is remembered automatically the next time you visit."}}, {"@type":"Question","name":"How do I set or change my location?","acceptedAnswer":{"@type":"Answer","text":"Use the search bar at the top of the forecast page. Type any city, town, village, or postcode and select from the dropdown results. SunScope works for locations worldwide. Your last searched location is remembered automatically the next time you visit."}},
{"@type":"Question","name":"What UV level is dangerous?","acceptedAnswer":{"@type":"Answer","text":"WHO UV index scale: 1-2 Low, no protection needed for short exposure. 3-5 Moderate, wear sunscreen and a hat for over 30 minutes outside. 6-7 High, seek shade during midday, apply SPF 30+. 8-10 Very High, minimise direct sun 11am-3pm. 11+ Extreme, avoid outdoor exposure during peak hours. In the UK, UV 6+ is common on clear summer days May-August."}}, {"@type":"Question","name":"What UV level is dangerous?","acceptedAnswer":{"@type":"Answer","text":"WHO UV index scale: 1-2 Low, no protection needed for short exposure. 3-5 Moderate, wear sunscreen and a hat for over 30 minutes outside. 6-7 High, seek shade during midday, apply SPF 30+. 8-10 Very High, minimise direct sun 11am-3pm. 11+ Extreme, avoid outdoor exposure during peak hours. In the UK, UV 6+ is common on clear summer days May-August."}},
@@ -55,7 +55,7 @@
{"@type":"Question","name":"What soil temperature do seeds need to germinate?","acceptedAnswer":{"@type":"Answer","text":"Most vegetable seeds need soil above 7-10 degrees. Warm-season crops like courgettes and beans need 12-15 degrees or more. Cool-season crops like lettuce can germinate at 4-5 degrees. Sowing too early into cold soil leads to seeds rotting. SunScope shows surface soil temperature and 6 cm depth temperature - the root zone where germination happens. The 6 cm figure lags the surface by several hours and reflects what seeds are actually experiencing."}}, {"@type":"Question","name":"What soil temperature do seeds need to germinate?","acceptedAnswer":{"@type":"Answer","text":"Most vegetable seeds need soil above 7-10 degrees. Warm-season crops like courgettes and beans need 12-15 degrees or more. Cool-season crops like lettuce can germinate at 4-5 degrees. Sowing too early into cold soil leads to seeds rotting. SunScope shows surface soil temperature and 6 cm depth temperature - the root zone where germination happens. The 6 cm figure lags the surface by several hours and reflects what seeds are actually experiencing."}},
{"@type":"Question","name":"How can I tell if the ground is too wet for a motorhome or caravan?","acceptedAnswer":{"@type":"Answer","text":"SunScope soil moisture shows volumetric water content in cubic metres per cubic metre. Above 0.4 is saturated and a heavy vehicle will likely sink. 0.3-0.4 is borderline. Below 0.3 is usually firm enough. Below 0.2 is dry and solid. The Vehicle profile includes soil moisture by default for motorhome and caravan users checking pitch suitability before arrival."}}, {"@type":"Question","name":"How can I tell if the ground is too wet for a motorhome or caravan?","acceptedAnswer":{"@type":"Answer","text":"SunScope soil moisture shows volumetric water content in cubic metres per cubic metre. Above 0.4 is saturated and a heavy vehicle will likely sink. 0.3-0.4 is borderline. Below 0.3 is usually firm enough. Below 0.2 is dry and solid. The Vehicle profile includes soil moisture by default for motorhome and caravan users checking pitch suitability before arrival."}},
{"@type":"Question","name":"Does SunScope show air quality and pollen forecasts?","acceptedAnswer":{"@type":"Answer","text":"Yes. Three air environment columns sit after Cloud cover in the table: Visibility (horizontal visibility in km), AQI (European Air Quality Index combining PM2.5, PM10, ozone, nitrogen dioxide, and sulphur dioxide), and Pollen (grains per cubic metre with a type picker for grass, birch, alder, mugwort, olive, ragweed, or total). All three are sourced from Copernicus CAMS via Open-Meteo. Toggle them using the column buttons above the table."}}, {"@type":"Question","name":"Does SunScope show air quality and pollen forecasts?","acceptedAnswer":{"@type":"Answer","text":"Yes. Three air environment columns sit after Cloud cover in the table: Visibility (horizontal visibility in km), AQI (European Air Quality Index combining PM2.5, PM10, ozone, nitrogen dioxide, and sulphur dioxide), and Pollen (grains per cubic metre with a type picker for grass, birch, alder, mugwort, olive, ragweed, or total). All three are sourced from Copernicus CAMS via Open-Meteo. Toggle them using the column buttons above the table."}},
{"@type":"Question","name":"What does the weather icon on each day tab mean?","acceptedAnswer":{"@type":"Answer","text":"Each day tab shows a weather icon for dominant daytime sky conditions - a sun disc for clear days, cloud variants for cloudy days, or a precipitation icon for rainy or snowy days. Below the icon are the day high and low UTCI+P felt temperatures in warm and cool colours. The icon is derived from actual solar elevation and cloud data, not a fixed set of generic symbols."}}, {"@type":"Question","name":"What does the weather icon on each day tab mean?","acceptedAnswer":{"@type":"Answer","text":"Each day tab shows a weather icon for dominant daytime sky conditions - a sun disc for clear days, cloud variants for cloudy days, or a precipitation icon for rainy or snowy days. Below the icon are the day high and low SunSoak felt temperatures in warm and cool colours. The icon is derived from actual solar elevation and cloud data, not a fixed set of generic symbols."}},
{"@type":"Question","name":"What are the weather event banners above the forecast table?","acceptedAnswer":{"@type":"Answer","text":"When notable conditions are forecast - ground frost, strong wind warning, fog, or a heat event - a coloured banner appears above the table. Tapping or clicking the event icon opens a popup with more detail about what the condition means and what to watch out for. Multiple events can appear at once."}}, {"@type":"Question","name":"What are the weather event banners above the forecast table?","acceptedAnswer":{"@type":"Answer","text":"When notable conditions are forecast - ground frost, strong wind warning, fog, or a heat event - a coloured banner appears above the table. Tapping or clicking the event icon opens a popup with more detail about what the condition means and what to watch out for. Multiple events can appear at once."}},
{"@type":"Question","name":"Why does the sky display show the wrong time of day?","acceptedAnswer":{"@type":"Answer","text":"The sky scope shows current conditions only - the actual time right now, not the hour you are browsing in the table. The sun position, sky colour, and glow intensity are calculated from real solar elevation and radiation data for the current moment. If you are looking at a future hour in the forecast table, the sky display stays locked to now by design."}}, {"@type":"Question","name":"Why does the sky display show the wrong time of day?","acceptedAnswer":{"@type":"Answer","text":"The sky scope shows current conditions only - the actual time right now, not the hour you are browsing in the table. The sun position, sky colour, and glow intensity are calculated from real solar elevation and radiation data for the current moment. If you are looking at a future hour in the forecast table, the sky display stays locked to now by design."}},
{"@type":"Question","name":"How far ahead does the forecast go?","acceptedAnswer":{"@type":"Answer","text":"The free tier shows 3 days of hourly data. SunScope Extra unlocks 14 days. The forecast auto-refreshes every 5 minutes while the page is open so the current hour always reflects the latest data from Open-Meteo. No manual reload needed."}}, {"@type":"Question","name":"How far ahead does the forecast go?","acceptedAnswer":{"@type":"Answer","text":"The free tier shows 3 days of hourly data. SunScope Extra unlocks 14 days. The forecast auto-refreshes every 5 minutes while the page is open so the current hour always reflects the latest data from Open-Meteo. No manual reload needed."}},
@@ -107,8 +107,8 @@
</details> </details>
<details class="faq-block"> <details class="faq-block">
<summary class="faq-q">What is the SunScope soak-factor and what does UTCI+P mean?</summary> <summary class="faq-q">What is SunSoak and how is it different from UTCI?</summary>
<p class="faq-a">UTCI on its own does not account for the extra chill of rain soaking through your clothes. The SunScope soak-factor is an original precipitation penalty formula that reduces the felt temperature based on rain intensity, snowfall, and wind speed. The result is shown as <strong>UTCI+P</strong> - the P standing for precipitation.<br><br>On a dry day UTCI and UTCI+P are identical. On a wet and windy day the soak-factor can drop the felt temperature by several degrees, reflecting what your body actually experiences when rain-soaked in a biting wind.</p> <p class="faq-a">UTCI is the scientific foundation — a peer-reviewed biometeorological standard that combines air temperature, humidity, wind, and solar radiation. But it has gaps. It assumes you are standing in open conditions with no precipitation. <strong>SunSoak</strong> is SunScope's extended index that fills those gaps with three extra layers.<br><br>First, a <strong>rain and snow penalty</strong>: the extra chill of wet clothing and skin is not in UTCI. Light drizzle drops felt temperature by 1-2 degrees; heavy rain combined with strong wind can push it down 7-8 degrees. Second, an <strong>environment modifier</strong>: SunSoak adjusts the solar and thermal load for where you actually are — forest canopy, alpine altitude, beach or lakeside glare, shaded riverbank, or desert ground heat. Switch it in the SunSoak column dropdown to match your surroundings. Third, <strong>full mean radiant temperature</strong> from all surrounding surfaces, not just the direct sun beam.<br><br>On a dry day in the open, SunSoak and UTCI will be close. In rain, in a forest, at altitude, or by the sea they can differ significantly — which is exactly what your body experiences.</p>
</details> </details>
<details class="faq-block"> <details class="faq-block">
@@ -123,14 +123,14 @@
<details class="faq-block"> <details class="faq-block">
<summary class="faq-q">Why does SunScope sometimes show a lower temperature than my regular weather app?</summary> <summary class="faq-q">Why does SunScope sometimes show a lower temperature than my regular weather app?</summary>
<p class="faq-a">Wind chill and precipitation both reduce felt temperature. If it is raining or blustery, the UTCI+P value will be noticeably lower than the thermometer reading - which is exactly what your body experiences. A 15 degree day with heavy rain and a strong wind can feel closer to 8 or 9 degrees in real terms. SunScope captures this effect; most apps report only the air temperature.</p> <p class="faq-a">Wind chill and precipitation both reduce felt temperature. If it is raining or blustery, the SunSoak value will be noticeably lower than the thermometer reading - which is exactly what your body experiences. A 15 degree day with heavy rain and a strong wind can feel closer to 8 or 9 degrees in real terms. Most apps report only the air temperature; SunSoak captures the full picture.</p>
</details> </details>
<h2>Reading the Forecast</h2> <h2>Reading the Forecast</h2>
<details class="faq-block"> <details class="faq-block">
<summary class="faq-q">How do I read the SunScope table?</summary> <summary class="faq-q">How do I read the SunScope table?</summary>
<p class="faq-a">Each row in the table is one hour of the day, with the time shown in the first column. The most important column is <strong>UTCI+P</strong> - the felt temperature accounting for air temperature, humidity, wind, solar radiation, and rainfall all combined.<br><br>Colour coding tells you how comfortable each hour will be at a glance: blue shades mean cold, green means comfortable, yellow and orange mean warm or hot, and red means dangerous heat stress. Other columns show vehicle cabin temperature, indoor building temperature, UV index, burn time, concrete surface temperature, soil data, air quality, and pollen. Switch between profiles using the buttons and dropdowns above the table - Basic, Home, Vehicle, then the <strong>Places</strong> and <strong>Activities</strong> dropdowns for location and activity-specific views. Hover any column header for a plain-language description of what it shows.</p> <p class="faq-a">Each row in the table is one hour of the day, with the time shown in the first column. The most important column is <strong>SunSoak</strong> - SunScope's felt-temperature index combining air temperature, humidity, wind, solar radiation, rain, and your environment into a single honest number.<br><br>Colour coding tells you how comfortable each hour will be at a glance: blue shades mean cold, green means comfortable, yellow and orange mean warm or hot, and red means dangerous heat stress. Use the SunSoak column dropdown to set your environment - Forest, Alpine, Beach, River, or Desert - and the values will adjust accordingly. Other columns show vehicle cabin temperature, indoor building temperature, UV index, burn time, concrete surface temperature, soil data, air quality, and pollen. Switch between profiles using the buttons and dropdowns above the table - Basic, Home, Vehicle, then the <strong>Places</strong> and <strong>Activities</strong> dropdowns for location and activity-specific views. Hover any column header for a plain-language description of what it shows.</p>
</details> </details>
<details class="faq-block"> <details class="faq-block">
@@ -140,7 +140,7 @@
<details class="faq-block"> <details class="faq-block">
<summary class="faq-q">What does the weather icon and temperature on each day tab mean?</summary> <summary class="faq-q">What does the weather icon and temperature on each day tab mean?</summary>
<p class="faq-a">Each day tab in the date strip shows a small weather icon representing the dominant daytime sky conditions - a sun disc for clear days, cloud variants for cloudy days, or a precipitation icon for rainy or snowy days. Below the icon are the day high and low <strong>UTCI+P</strong> felt temperatures shown in warm and cool colours.<br><br>The icon is derived from actual daytime solar elevation and cloud data, so it reflects the real character of the day rather than a generic symbol picked from a fixed set.</p> <p class="faq-a">Each day tab in the date strip shows a small weather icon representing the dominant daytime sky conditions - a sun disc for clear days, cloud variants for cloudy days, or a precipitation icon for rainy or snowy days. Below the icon are the day high and low <strong>SunSoak</strong> felt temperatures shown in warm and cool colours.<br><br>The icon is derived from actual daytime solar elevation and cloud data, so it reflects the real character of the day rather than a generic symbol picked from a fixed set.</p>
</details> </details>
<details class="faq-block"> <details class="faq-block">
+1 -1
View File
@@ -56,7 +56,7 @@
}, },
"featureList": [ "featureList": [
"UTCI thermal comfort index", "UTCI thermal comfort index",
"Soak-factor precipitation penalty (UTCI+P)", "SunSoak felt-temperature index with precipitation penalty and environment modifier",
"Vehicle interior temperature model", "Vehicle interior temperature model",
"Indoor building temperature model", "Indoor building temperature model",
"UV-A and UV-B index with burn time", "UV-A and UV-B index with burn time",