Every column in the forecast table explained in plain language, from Air and Shade through
- to Lightning Potential, air quality, pollen, and SunSoak.
+ to lightning warnings, air quality, pollen, and SunSoak.
diff --git a/assets/css/table.css b/assets/css/table.css
index 356002e..3198f9b 100644
--- a/assets/css/table.css
+++ b/assets/css/table.css
@@ -765,11 +765,13 @@
.active-profile-row.grp-wind { border-color: rgba(106,34,16,0.30); }
.active-profile-row.grp-ambient { border-color: rgba(60,58,53,0.30); }
.active-profile-row.grp-surface { border-color: rgba(11,62,114,0.30); }
+.active-profile-row.grp-pets { border-color: rgba(10,81,88,0.30); }
.active-profile-row.grp-felt .active-profile-row-value { color: #075c3a; }
.active-profile-row.grp-wind .active-profile-row-value { color: #6a2210; }
.active-profile-row.grp-ambient .active-profile-row-value { color: #3c3a35; }
.active-profile-row.grp-surface .active-profile-row-value { color: #0b3e72; }
+.active-profile-row.grp-pets .active-profile-row-value { color: #0a5158; }
/* Vertical rule separating general-use profiles from technical ones */
.profile-divider {
@@ -1085,6 +1087,7 @@
.col-toggle.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; border-color: rgba(7,92,58,0.35); }
.col-toggle.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; border-color: rgba(11,62,114,0.30); }
+.col-toggle.grp-pets { background: rgba(214,238,240,0.50); color: #0a5158; border-color: rgba(10,81,88,0.30); }
.col-toggle.grp-ambient { background: rgba(236,234,227,0.50); color: #3c3a35; border-color: rgba(60,58,53,0.30); }
.col-toggle.grp-precip { background: rgba(247,228,238,0.50); color: #6b1e3a; border-color: rgba(107,30,58,0.30); }
.col-toggle.grp-sky { background: rgba(234,232,252,0.50); color: #352e7a; border-color: rgba(53,46,122,0.30); }
@@ -1094,6 +1097,7 @@
.col-toggle.grp-felt:hover { background: rgba(213,233,226,0.80); color: #075c3a; border-color: rgba(7,92,58,0.55); }
.col-toggle.grp-surface:hover { background: rgba(211,224,238,0.80); color: #0b3e72; border-color: rgba(11,62,114,0.50); }
+.col-toggle.grp-pets:hover { background: rgba(204,228,230,0.80); color: #0a5158; border-color: rgba(10,81,88,0.50); }
.col-toggle.grp-ambient:hover { background: rgba(226,224,217,0.80); color: #3c3a35; border-color: rgba(60,58,53,0.50); }
.col-toggle.grp-precip:hover { background: rgba(237,218,228,0.80); color: #6b1e3a; border-color: rgba(107,30,58,0.50); }
.col-toggle.grp-sky:hover { background: rgba(224,222,242,0.80); color: #352e7a; border-color: rgba(53,46,122,0.50); }
@@ -1103,6 +1107,7 @@
.col-toggle.grp-felt.on { background: #0f9e63; border-color: #0f9e63; color: #fff; }
.col-toggle.grp-surface.on { background: #2672c8; border-color: #2672c8; color: #fff; }
+.col-toggle.grp-pets.on { background: #17868f; border-color: #17868f; color: #fff; }
.col-toggle.grp-ambient.on { background: #7a7870; border-color: #7a7870; color: #fff; }
.col-toggle.grp-precip.on { background: #b03060; border-color: #b03060; color: #fff; }
.col-toggle.grp-sky.on { background: #6058c8; border-color: #6058c8; color: #fff; }
@@ -1112,6 +1117,7 @@
.col-toggle.grp-felt.on:hover { background: #0c7d4e; border-color: #0c7d4e; color: #fff; }
.col-toggle.grp-surface.on:hover { background: #1e5aa0; border-color: #1e5aa0; color: #fff; }
+.col-toggle.grp-pets.on:hover { background: #116b73; border-color: #116b73; color: #fff; }
.col-toggle.grp-ambient.on:hover { background: #5e5c56; border-color: #5e5c56; color: #fff; }
.col-toggle.grp-precip.on:hover { background: #8c264c; border-color: #8c264c; color: #fff; }
.col-toggle.grp-sky.on:hover { background: #4c48a8; border-color: #4c48a8; color: #fff; }
@@ -1816,6 +1822,7 @@
.utci-table th.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; }
.utci-table th.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; }
+.utci-table th.grp-pets { background: rgba(214,238,240,0.50); color: #0a5158; }
.utci-table th.grp-ambient { background: rgba(236,234,227,0.50); color: #3c3a35; }
.utci-table th.grp-precip { background: rgba(247,228,238,0.50); color: #6b1e3a; }
.utci-table th.grp-sky { background: rgba(234,232,252,0.50); color: #352e7a; }
@@ -1825,6 +1832,7 @@
.utci-table th.grp-felt.col-info-th:hover { background: rgba(213,233,226,0.80); }
.utci-table th.grp-surface.col-info-th:hover { background: rgba(211,224,238,0.80); }
+.utci-table th.grp-pets.col-info-th:hover { background: rgba(204,228,230,0.80); }
.utci-table th.grp-ambient.col-info-th:hover { background: rgba(226,224,217,0.80); }
.utci-table th.grp-precip.col-info-th:hover { background: rgba(237,218,228,0.80); }
.utci-table th.grp-sky.col-info-th:hover { background: rgba(224,222,242,0.80); }
@@ -1834,6 +1842,7 @@
.utci-table th.grp-felt .col-unit { color: #0f9e63; }
.utci-table th.grp-surface .col-unit { color: #2672c8; }
+.utci-table th.grp-pets .col-unit { color: #17868f; }
.utci-table th.grp-ambient .col-unit { color: #7a7870; }
.utci-table th.grp-precip .col-unit { color: #b03060; }
.utci-table th.grp-sky .col-unit { color: #6058c8; }
@@ -1859,6 +1868,7 @@
.utci-table .grp-label-row th.grp-felt { background: rgba(223,243,236,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);}
.utci-table .grp-label-row th.grp-surface { background: rgba(221,234,248,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);}
+.utci-table .grp-label-row th.grp-pets { background: rgba(214,238,240,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);}
.utci-table .grp-label-row th.grp-ambient { background: rgba(236,234,227,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);}
.utci-table .grp-label-row th.grp-precip { background: rgba(247,228,238,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);}
.utci-table .grp-label-row th.grp-sky { background: rgba(234,232,252,0.50); border-left: 2px solid rgba(74,50,24,0.18); border-bottom: 1px solid rgba(74,50,24,0.18);}
@@ -2201,8 +2211,14 @@
.fvt-btn:first-child {
border-radius: 3px 0 0 3px;
}
-.fvt-btn:last-child {
+/* Only the outer corners are rounded; every segment after the first drops
+ its left border so neighbours share one 1.5px rule rather than stacking
+ two. Keyed off the sibling rather than :last-child so it still holds with
+ three segments (Quick / Detailed / Table). */
+.fvt-btn + .fvt-btn {
border-left: none;
+}
+.fvt-btn:last-child {
border-radius: 0 3px 3px 0;
}
.fvt-btn:hover {
@@ -2650,6 +2666,7 @@
two different backgrounds is what makes them drift apart. */
.utci-table-rotated .grp-felt { --grp-tint: rgba(223,243,236,0.50); }
.utci-table-rotated .grp-surface { --grp-tint: rgba(221,234,248,0.50); }
+.utci-table-rotated .grp-pets { --grp-tint: rgba(214,238,240,0.50); }
.utci-table-rotated .grp-ambient { --grp-tint: rgba(236,234,227,0.50); }
.utci-table-rotated .grp-precip { --grp-tint: rgba(247,228,238,0.50); }
.utci-table-rotated .grp-sky { --grp-tint: rgba(234,232,252,0.50); }
@@ -2734,11 +2751,11 @@
}
@media (max-width: 640px) {
- /* Icon-only on narrow screens โ the toolbar is already tight. */
- .table-rotate-btn {
- font-size: 0;
- gap: 0;
- padding: 6px 7px;
+ /* Tighter segments on narrow screens โ the toolbar is already tight,
+ and there are three of them now. */
+ .fvt-btn {
+ padding: 6px 6px;
+ gap: 2px;
}
}
@@ -2769,58 +2786,17 @@
}
/* โโ TOOLBAR BUTTON HEIGHTS โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- Quick/Detailed, Rotate and Edit columns sit on one row and have to
- agree on height. They didn't: the first two set line-height:1 while
- Edit columns leaves it at normal, so the same 6px padding produced a
- box ~3px taller. Pinning one line-height and one min-height across all
- three settles it regardless of font-size differences. */
+ The view segments and Edit columns sit on one row and have to agree on
+ height. They didn't: the segments set line-height:1 while Edit columns
+ leaves it at normal, so the same 6px padding produced a box ~3px
+ taller. Pinning one line-height and one min-height across both settles
+ it regardless of font-size differences. */
.fvt-btn,
-.table-rotate-btn,
.col-toggles-edit-btn {
min-height: 29px;
line-height: 1;
}
-/* โโ ROTATE BUTTON โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- Sits beside the Quick/Detailed view toggle and only while the detailed
- table is showing. Deliberately mirrors .fvt-btn โ same type, padding,
- border and states โ so it reads as part of that control group rather
- than a stray button. Standalone, so it keeps a radius on all corners
- where .fvt-btn splits its radius across the segmented pair. */
-.table-rotate-btn {
- display: inline-flex;
- align-items: center;
- gap: 4px;
- font-family: Manrope, sans-serif;
- font-size: 11px;
- font-weight: 700;
- line-height: 1;
- padding: 6px 8px;
- cursor: pointer;
- border: 1.5px solid #c9b08a;
- border-radius: 3px;
- background: #f5edd6;
- color: #6b4228;
- transition: background 0.12s, border-color 0.12s, color 0.12s;
-}
-.table-rotate-btn:hover {
- border-color: #c8922a;
- background: #fef3dc;
-}
-.table-rotate-btn.on {
- background: #c8922a;
- border-color: #c8922a;
- color: #fff;
-}
-/* The icon turns with the state it describes โ flat when hours run down
- the side, quarter-turned when they run along the top. */
-.table-rotate-btn .fvt-btn-icon {
- transition: transform 0.18s ease;
-}
-.table-rotate-btn.on .fvt-btn-icon {
- transform: rotate(90deg);
-}
-
/* โโ MOBILE โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */
@media (max-width: 640px) {
.utci-rotated-scroll {
diff --git a/assets/css/ui.css b/assets/css/ui.css
index f59124b..27ee8eb 100644
--- a/assets/css/ui.css
+++ b/assets/css/ui.css
@@ -234,6 +234,7 @@
.cs-btn.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; border-color: rgba(7,92,58,0.35); }
.cs-btn.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; border-color: rgba(11,62,114,0.30); }
+.cs-btn.grp-pets { background: rgba(214,238,240,0.50); color: #0a5158; border-color: rgba(10,81,88,0.30); }
.cs-btn.grp-ambient { background: rgba(236,234,227,0.50); color: #3c3a35; border-color: rgba(60,58,53,0.30); }
.cs-btn.grp-precip { background: rgba(247,228,238,0.50); color: #6b1e3a; border-color: rgba(107,30,58,0.30); }
.cs-btn.grp-sky { background: rgba(234,232,252,0.50); color: #352e7a; border-color: rgba(53,46,122,0.30); }
@@ -243,6 +244,7 @@
.cs-btn.grp-felt:hover { background: rgba(213,233,226,0.80); color: #075c3a; border-color: rgba(7,92,58,0.55); }
.cs-btn.grp-surface:hover { background: rgba(211,224,238,0.80); color: #0b3e72; border-color: rgba(11,62,114,0.50); }
+.cs-btn.grp-pets:hover { background: rgba(204,228,230,0.80); color: #0a5158; border-color: rgba(10,81,88,0.50); }
.cs-btn.grp-ambient:hover { background: rgba(226,224,217,0.80); color: #3c3a35; border-color: rgba(60,58,53,0.50); }
.cs-btn.grp-precip:hover { background: rgba(237,218,228,0.80); color: #6b1e3a; border-color: rgba(107,30,58,0.50); }
.cs-btn.grp-sky:hover { background: rgba(224,222,242,0.80); color: #352e7a; border-color: rgba(53,46,122,0.50); }
@@ -253,6 +255,7 @@
/* Dropdown buttons - lighter palette to match toggle pills */
.cs-btn.grp-felt.on { background: #2ab578; border-color: #2ab578; color: #fff; }
.cs-btn.grp-surface.on { background: #4088d4; border-color: #4088d4; color: #fff; }
+.cs-btn.grp-pets.on { background: #34a0a8; border-color: #34a0a8; color: #fff; }
.cs-btn.grp-ambient.on { background: #929088; border-color: #929088; color: #fff; }
.cs-btn.grp-precip.on { background: #c24e6c; border-color: #c24e6c; color: #fff; }
.cs-btn.grp-sky.on { background: #786ec8; border-color: #786ec8; color: #fff; }
@@ -262,6 +265,7 @@
.cs-btn.grp-felt.on:hover { background: #1e9e64; border-color: #1e9e64; color: #fff; }
.cs-btn.grp-surface.on:hover { background: #2e72bc; border-color: #2e72bc; color: #fff; }
+.cs-btn.grp-pets.on:hover { background: #17868f; border-color: #17868f; color: #fff; }
.cs-btn.grp-ambient.on:hover { background: #7a7870; border-color: #7a7870; color: #fff; }
.cs-btn.grp-precip.on:hover { background: #a83c5a; border-color: #a83c5a; color: #fff; }
.cs-btn.grp-sky.on:hover { background: #6258b0; border-color: #6258b0; color: #fff; }
@@ -272,6 +276,7 @@
/* Toggle pills - lighter palette */
.col-toggle.grp-felt.on { background: #2ab578; border-color: #2ab578; color: #fff; }
.col-toggle.grp-surface.on { background: #4088d4; border-color: #4088d4; color: #fff; }
+.col-toggle.grp-pets.on { background: #34a0a8; border-color: #34a0a8; color: #fff; }
.col-toggle.grp-ambient.on { background: #929088; border-color: #929088; color: #fff; }
.col-toggle.grp-precip.on { background: #c24e6c; border-color: #c24e6c; color: #fff; }
.col-toggle.grp-sky.on { background: #786ec8; border-color: #786ec8; color: #fff; }
@@ -281,6 +286,7 @@
.col-toggle.grp-felt.on:hover { background: #1e9e64; border-color: #1e9e64; color: #fff; }
.col-toggle.grp-surface.on:hover { background: #2e72bc; border-color: #2e72bc; color: #fff; }
+.col-toggle.grp-pets.on:hover { background: #17868f; border-color: #17868f; color: #fff; }
.col-toggle.grp-ambient.on:hover { background: #7a7870; border-color: #7a7870; color: #fff; }
.col-toggle.grp-precip.on:hover { background: #a83c5a; border-color: #a83c5a; color: #fff; }
.col-toggle.grp-sky.on:hover { background: #6258b0; border-color: #6258b0; color: #fff; }
diff --git a/assets/js/app.js b/assets/js/app.js
index 3511a26..1f0253b 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -233,7 +233,7 @@ export function UTCIForecast() {
indoorMode, setIndoorMode,
pollenType, setPollenTypeAndSave,
utciEnv, setUtciEnv,
- tableRotated, toggleTableRotated,
+ tableRotated, setTableRotated,
headStickyRef, headTrackRef, headTableRef,
bodyScrollRef, bodyTableRef, tableWrapRef,
colPopup, colPopupRef,
@@ -430,10 +430,11 @@ export function UTCIForecast() {
// Columns that mark the start of a logical group - used to draw a faint
// vertical border separating groups in the forecast table.
const GROUP_ORDER = {
- felt: ['utciP', 'shadeT', 'vehicleT', 'indoorT', 'managedT', 'burn', 'utci', 'delta', 'tmrt'],
- surface: ['concreteT', 'soilT', 'soilT6', 'soilM', 'furSurfaceT', 'pawT'],
- ambient: ['petShadeT', 'petHomeT', 'air', 'rh', 'dew'],
- precip: ['precip', 'precipProb', 'lightning'],
+ felt: ['utciP', 'shadeT', 'vehicleT', 'indoorT', 'managedT', 'utci', 'burn'],
+ surface: ['concreteT', 'soilT', 'soilT6', 'soilM'],
+ pets: ['furSurfaceT', 'pawT', 'petShadeT', 'petHomeT'],
+ ambient: ['air', 'rh', 'dew'],
+ precip: ['precip', 'precipProb'],
sky: ['cloud', 'vis'],
wind: ['wind', 'dir'],
airqual: ['aqi', 'pollen'],
@@ -464,7 +465,7 @@ export function UTCIForecast() {
};
// Display names for the column groups โ used for the spanning labels
// above the columns normally, and for the divider rows when rotated.
- const GROUP_LABELS = { felt: 'Felt', surface: 'Surface', ambient: 'Ambient', precip: 'Precip', sky: 'Sky', wind: 'Wind', airqual: 'Air quality', solar: 'Solar' };
+ const GROUP_LABELS = { felt: 'Felt', surface: 'Surface', pets: 'Pets', ambient: 'Ambient', precip: 'Precip', sky: 'Sky', wind: 'Wind', airqual: 'Air quality', solar: 'Solar' };
// Builds the group label row above the column headers.
// Each visible group gets one spanning cell; groups with no visible
// columns are skipped entirely. Hour always gets a blank lead cell.
@@ -1168,30 +1169,32 @@ export function UTCIForecast() {
The angle of the sun above the horizon in degrees. Below 0ยฐ the sun has set. The higher the elevation, the more intense the radiation reaching the ground.
Direct W/mยฒ
Shortwave solar radiation arriving as a direct beam from the sun. The primary driver of skin heating on sunny days.
Diffuse W/mยฒ
Solar radiation scattered from all directions across the sky. Present even under cloud cover; contributes to the overall solar heat load.
-
Tmrt ยฐC
Mean Radiant Temperature โ the combined heat from direct sun, scattered sky light, and ground reflection expressed as a temperature. Can exceed air temperature by 20โ30 ยฐC on a sunny day; this is why shade feels so much cooler, and it is one of the inputs to UTCI.
-
UTCIโAir ฮ
The gap between the UTCI felt temperature and the plain air temperature. A large positive value means solar radiation is adding significant heat stress beyond what the thermometer shows.
UTCI ยฐC
Universal Thermal Climate Index โ the peer-reviewed standard felt temperature, combining air temp, humidity, wind, and solar radiation. Always computed from the raw open-ground reading: it does not move when you change the Solar Model, and it excludes precipitation. That is deliberate โ it is the fixed benchmark to read SunSoak against, so the gap between the two shows exactly what your surroundings and the weather are adding.
UV-A
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.
UV-B
Estimated UV-B radiation index. Causes sunburn and drives vitamin D production. Intensity depends strongly on solar elevation and cloud cover, falling sharply at low sun angles.
@@ -104,8 +102,7 @@
SunSoak ยฐC
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), a Solar Model for where you actually are (forest, alpine, beach, river, open water, desert), and full mean radiant temperature from surrounding surfaces. The most honest single answer to: what will it actually feel like out there?
Shade ยฐC felt
SunSoak with the sun taken away โ the felt temperature standing in the typical shade of the selected Solar Model (building shadow, beach umbrella, tree canopy, boat panels, and so on). You are still outdoors, so wind, humidity and rain affect you exactly as they do in the open; only the direct beam and part of the sky are blocked. Expect several degrees below SunSoak in daytime sun, and near-identical readings after dark, when there is no sun to stand out of.
Precip mm
Expected rainfall in mm per hour; snowfall is shown in cm. Even light drizzle meaningfully reduces felt temperature when combined with wind.
-
Rain %
Probability of precipitation for this hour (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 the deterministic forecast may miss.
-
Lightning
Lightning Potential Index (LPI) from Open-Meteo in J/kg โ a convective energy index. Values above 5 suggest moderate lightning risk, above 25 suggest high risk.
+
Rain %
Probability of precipitation for this hour (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 the deterministic forecast may miss. A โก beside the percentage marks a thundery hour, driven by the Lightning Potential Index (LPI) from Open-Meteo: it appears above 5 J/kg (moderate risk) and turns bold above 25 (high risk), with the cell tinted amber either way.
Soil ยฐC surface
Temperature of the soil at the surface (0 cm depth). Most seeds germinate above 7โ10 ยฐC. Useful for sowing decisions and frost assessment.
Soil ยฐC 6 cm
Soil temperature at 6 cm depth โ the root zone for many crops and seedlings. Lags behind the surface by several hours.
Soil moisture
Water saturation of the top 1 cm of soil as a percentage. Above 40% indicates saturated ground; below 20% is dry. Useful for assessing whether ground is workable, and for motorhome or caravan pitch suitability.
Full control over which columns appear in the table, starting from a blank slate. Toggle any
combination of air temperature, Shade Air, dew point, relative humidity, wind, direction, cloud,
- visibility, air quality 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,
- soil temperatures, soil moisture, concrete surface, precipitation, rain probability, lightning
- potential, and SunSoak. Build exactly the view that suits your situation.
+ visibility, air quality index, pollen, sun elevation, direct and diffuse radiation,
+ UTCI, UV-A, UV-B, burn time, vehicle interior, indoor, managed indoor,
+ soil temperatures, soil moisture, concrete surface, precipitation, rain probability,
+ and SunSoak. Build exactly the view that suits your situation.