SUNScope
| handleThClick('hour', e)} onMouseEnter=${(e) => handleThEnter('hour', e)} onMouseLeave=${handleThLeave}>Hour | ${visibleCols.air && html`handleThClick('air', e)} onMouseEnter=${(e) => handleThEnter('air', e)} onMouseLeave=${handleThLeave}>Air °C | `} ${visibleCols.rh && html`handleThClick('rh', e)} onMouseEnter=${(e) => handleThEnter('rh', e)} onMouseLeave=${handleThLeave}>RH % | `} ${visibleCols.dew && html`handleThClick('dew', e)} onMouseEnter=${(e) => handleThEnter('dew', e)} onMouseLeave=${handleThLeave}>Dew °C | `} ${visibleCols.soilT && html`handleThClick('soilT', e)} onMouseEnter=${(e) => handleThEnter('soilT', e)} onMouseLeave=${handleThLeave}>Soil °C surface | `} ${visibleCols.soilT6 && html`handleThClick('soilT6', e)} onMouseEnter=${(e) => handleThEnter('soilT6', e)} onMouseLeave=${handleThLeave}>Soil 6cm °C root | `} ${visibleCols.soilM && html`handleThClick('soilM', e)} onMouseEnter=${(e) => handleThEnter('soilM', e)} onMouseLeave=${handleThLeave}>Soil moist m³/m³ | `} ${visibleCols.concreteT && html`handleThClick('concreteT', e)} onMouseEnter=${(e) => handleThEnter('concreteT', e)} onMouseLeave=${handleThLeave}>Concrete °C surface | `} ${visibleCols.wind && html`handleThClick('wind', e)} onMouseEnter=${(e) => handleThEnter('wind', e)} onMouseLeave=${handleThLeave}>Wind m/s (gust) | `} ${visibleCols.dir && html`handleThClick('dir', e)} onMouseEnter=${(e) => handleThEnter('dir', e)} onMouseLeave=${handleThLeave}>Dir - | `} ${visibleCols.cloud && html`handleThClick('cloud', e)} onMouseEnter=${(e) => handleThEnter('cloud', e)} onMouseLeave=${handleThLeave}>Cloud % | `} ${visibleCols.vis && html`handleThClick('vis', e)} onMouseEnter=${(e) => handleThEnter('vis', e)} onMouseLeave=${handleThLeave}>Visibility km | `} ${visibleCols.aqi && html`handleThClick('aqi', e)} onMouseEnter=${(e) => handleThEnter('aqi', e)} onMouseLeave=${handleThLeave}>AQI EU idx | `} ${visibleCols.pollen && html`handleThClick('pollen', e)} onMouseEnter=${(e) => handleThEnter('pollen', e)} onMouseLeave=${handleThLeave}>${pollenType === 'all_pollen' ? 'Pollen' : POLLEN_TYPES[pollenType]?.name.replace(' pollen','') ?? 'Pollen'} grains/m³ | `} ${visibleCols.sun && html`handleThClick('sun', e)} onMouseEnter=${(e) => handleThEnter('sun', e)} onMouseLeave=${handleThLeave}>Sun elev° | `} ${visibleCols.direct && html`handleThClick('direct', e)} onMouseEnter=${(e) => handleThEnter('direct', e)} onMouseLeave=${handleThLeave}>Direct W/m² | `} ${visibleCols.diffuse && html`handleThClick('diffuse', e)} onMouseEnter=${(e) => handleThEnter('diffuse', e)} onMouseLeave=${handleThLeave}>Diffuse W/m² | `} ${visibleCols.tmrt && html`handleThClick('tmrt', e)} onMouseEnter=${(e) => handleThEnter('tmrt', e)} onMouseLeave=${handleThLeave}>Tmrt °C | `} ${visibleCols.delta && html`handleThClick('delta', e)} onMouseEnter=${(e) => handleThEnter('delta', e)} onMouseLeave=${handleThLeave}>Δ UTCI−Air | `} ${visibleCols.utci && html`handleThClick('utci', e)} onMouseEnter=${(e) => handleThEnter('utci', e)} onMouseLeave=${handleThLeave}>UTCI °C felt | `} ${visibleCols.uvA && html`handleThClick('uvA', e)} onMouseEnter=${(e) => handleThEnter('uvA', e)} onMouseLeave=${handleThLeave}>UV-A est. idx | `} ${visibleCols.uvB && html`handleThClick('uvB', e)} onMouseEnter=${(e) => handleThEnter('uvB', e)} onMouseLeave=${handleThLeave}>UV-B est. idx | `} ${visibleCols.burn && html`handleThClick('burn', e)} onMouseEnter=${(e) => handleThEnter('burn', e)} onMouseLeave=${handleThLeave}>Burn to MED | `} ${visibleCols.vehicleT && html`handleThClick('vehicleT', e)} onMouseEnter=${(e) => handleThEnter('vehicleT', e)} onMouseLeave=${handleThLeave}>Vehicle °C peak | `} ${indoorMode === 'on' && !indoorManaged && html`handleThClick('indoorT', e)} onMouseEnter=${(e) => handleThEnter('indoorT', e)} onMouseLeave=${handleThLeave}>Indoors °C est. | `} ${indoorMode === 'on' && indoorManaged && html`handleThClick('managedT', e)} onMouseEnter=${(e) => handleThEnter('managedT', e)} onMouseLeave=${handleThLeave}>Managed °C est. | `} ${visibleCols.precip && html`handleThClick('precip', e)} onMouseEnter=${(e) => handleThEnter('precip', e)} onMouseLeave=${handleThLeave}>Pcpt mm/h | `} ${visibleCols.utciP && html`handleThClick('utciP', e)} onMouseEnter=${(e) => handleThEnter('utciP', e)} onMouseLeave=${handleThLeave}>UTCI+P °C adj. | `}
|---|
| <${SkyScope} elev=${r.elev} dt=${r.dt} glob=${r.glob} size=${30} /> ${localHHMM} ${(() => { const rowEvents = getCellTagEvents(selectedDayEvents, r); return rowEvents.map((ev, idx) => html` handleEventTagClick(rowEvents, idx, e)} onMouseEnter=${(e) => handleEventTagEnter(rowEvents, idx, e)} onMouseLeave=${handleEventTagLeave} role="button" tabIndex="0" aria-label=${ev.title} >${ev.emoji} `); })()} | ${visibleCols.air && html`${r.Ta.toFixed(1)} | `} ${visibleCols.rh && html`${Math.round(r.RH)} | `} ${visibleCols.dew && html`${r.dew != null ? r.dew.toFixed(1) : '—'} | `} ${visibleCols.soilT && html`${r.soilT0 != null ? r.soilT0.toFixed(1) : '—'} | `} ${visibleCols.soilT6 && html`${r.soilT6 != null ? r.soilT6.toFixed(1) : '—'} | `} ${visibleCols.soilM && html`${r.soilM != null ? r.soilM.toFixed(3) : '—'} | `} ${visibleCols.concreteT && html`40 ? '#c0392b' : r.concreteT != null && r.concreteT > 30 ? '#e67e22' : '#7f8c8d', fontWeight: 'bold', background: tempBg(r.concreteT) }}> ${r.concreteT != null ? r.concreteT.toFixed(1) : '—'} | `} ${visibleCols.wind && html`${r.va.toFixed(1)}${r.gust != null && r.gust > r.va + 0.5 ? html`(${r.gust.toFixed(1)})` : ''} | `} ${visibleCols.dir && html`<${WindVane} bearing=${r.wd} size=${28} /> ${r.compass.label} | `} ${visibleCols.cloud && html`<${CloudIcon} category=${r.cloudCat} elev=${r.elev} dt=${r.dt} size=${28} /> ${Math.round(r.cc)} | `} ${visibleCols.vis && (() => { const v = r.visKm; const bg = v == null ? 'transparent' : v < 1 ? 'rgba(180,80,80,0.18)' : v < 4 ? 'rgba(210,140,50,0.15)' : v < 10 ? 'rgba(200,190,80,0.12)' : 'transparent'; const color = v != null && v < 4 ? '#8a3a1a' : '#4a3218'; return html`${v != null ? (v < 10 ? v.toFixed(1) : Math.round(v)) : '—'} | `; })()} ${visibleCols.aqi && (() => { const v = r.aqi; const bg = v == null ? 'transparent' : v < 20 ? 'rgba(80,180,100,0.15)' : v < 40 ? 'rgba(140,200,100,0.13)' : v < 60 ? 'rgba(220,200,60,0.15)' : v < 80 ? 'rgba(220,130,50,0.18)' : v < 100 ? 'rgba(200,70,50,0.18)' : 'rgba(160,30,100,0.20)'; const color = v != null && v >= 60 ? '#7a2010' : v != null && v >= 40 ? '#7a4a10' : '#2a4a20'; const label = v == null ? '—' : v < 20 ? `${v} Good` : v < 40 ? `${v} Fair` : v < 60 ? `${v} Mod` : v < 80 ? `${v} Poor` : v < 100 ? `${v} V.Poor` : `${v} Hazard`; return html`= 60 ? 600 : 400 }}>${label} | `; })()} ${visibleCols.pollen && (() => { const pollenMap = { all_pollen: [r.grassPollen, r.birchPollen, r.alderPollen, r.mugwortPollen, r.olivePollen, r.ragweedPollen].reduce((s, x) => x != null ? s + x : s, null), grass_pollen: r.grassPollen, birch_pollen: r.birchPollen, alder_pollen: r.alderPollen, mugwort_pollen: r.mugwortPollen, olive_pollen: r.olivePollen, ragweed_pollen: r.ragweedPollen, }; const v = pollenMap[pollenType] ?? null; const bg = v == null ? 'transparent' : v < 10 ? 'transparent' : v < 50 ? 'rgba(180,200,80,0.13)' : v < 200 ? 'rgba(210,150,50,0.16)' : 'rgba(200,70,50,0.18)'; const color = v != null && v >= 200 ? '#8a2010' : v != null && v >= 50 ? '#7a4a10' : '#4a3218'; const label = v == null ? '—' : v < 10 ? `${Math.round(v)} Low` : v < 50 ? `${Math.round(v)} Mod` : v < 200 ? `${Math.round(v)} High` : `${Math.round(v)} V.High`; return html`= 50 ? 600 : 400 }}>${label} | `; })()} ${visibleCols.sun && html`0 ? r.elev : null, 0, 70, '225,160,45') }}>${r.elev > 0 ? r.elev.toFixed(1) : '—'} | `} ${visibleCols.direct && html`${Math.round(r.dir)} | `} ${visibleCols.diffuse && html`${Math.round(r.dif)} | `} ${visibleCols.tmrt && html`${r.Tmrt.toFixed(1)} | `} ${visibleCols.delta && html`3 ? '#c8601a' : delta < -3 ? '#3f73c4' : '#4a3218', fontWeight: 600, background: deltaBg(delta), }}> ${delta > 0 ? '+' : ''}${delta.toFixed(1)} | `} ${visibleCols.utci && html`${r.utci.toFixed(1)}° | `} ${visibleCols.uvA && html`0 ? '#c8922a' : '#4a3218', background: scaleBg(r.uvA, 0, 8, '220,155,40') }}> ${r.uvA > 0 ? r.uvA.toFixed(1) : '—'} | `} ${visibleCols.uvB && html`0 ? '#c44a3a' : '#4a3218', background: scaleBg(r.uvB, 0, 1.2, '210,70,50') }}> ${r.uvB > 0 ? r.uvB.toFixed(2) : '—'} | `} ${visibleCols.burn && html`0 ? (burnMins < 30 ? '#c44a3a' : '#c8601a') : '#4a3218', background: burnBg(burnMins, r.uv) }}> ${burnLabel(burnMins)} | `} ${visibleCols.vehicleT && html`45 ? '#c0392b' : r.vehicleT != null && r.vehicleT > 35 ? '#e67e22' : '#7f8c8d', fontWeight: 'bold', background: tempBgStrong(r.vehicleT) }}> ${r.vehicleT != null ? r.vehicleT.toFixed(1) : '—'} | `} ${indoorMode === 'on' && !indoorManaged && html`32 ? '#c0392b' : r.indoorT != null && r.indoorT > 26 ? '#e67e22' : '#4a7a4a', fontWeight: 'bold', background: tempBgStrong(r.indoorT) }}> ${r.indoorT != null ? r.indoorT.toFixed(1) : '—'} | `} ${indoorMode === 'on' && indoorManaged && html`32 ? '#c0392b' : r.managedT != null && r.managedT > 26 ? '#e67e22' : '#4a7a4a', fontWeight: 'bold', background: tempBgStrong(r.managedT) }}> ${r.managedT != null ? r.managedT.toFixed(1) : '—'} | `} ${visibleCols.precip && html`0 ? scaleBg(r.snow, 0, 4, '90,140,210') : scaleBg(r.precip, 0, 8, '70,145,200') }}> <${PrecipIcon} precip=${r.precip} snow=${r.snow} size=${28} /> 0 ? '#2a5fa8' : r.precip > 0 ? '#2a6a90' : '#7a5c30' }}> ${r.snow > 0 ? r.snow.toFixed(1) + 'cm' : r.precip > 0 ? r.precip.toFixed(1) : '—'} | `} ${visibleCols.utciP && html`${r.utciAdj.toFixed(1)}° | `}
${COL_DESCRIPTIONS[colPopup.key].desc}
${ev.message}
What is SunScope?
SunScope is a free hourly weather forecast built around felt temperature, not just air temperature. It uses the Universal Thermal Climate Index (UTCI) — the biometeorological standard used in heat-health warning systems worldwide — to combine air temperature, humidity, wind, and solar radiation into a single honest number. The UTCI+P column adds an original rain and snow penalty so wet, windy days read as cold as they feel.
Beyond felt temperature, SunScope calculates vehicle cabin heat (choose your vehicle type; toggle windows open), indoor temperature (seven building types; managed heatwave mode), urban concrete surface temperature, UV index and sunburn time by skin type, and soil temperature and moisture for farming and motorhome use. Switch profiles to see the data that matters for your situation — or go Custom and build your own view. Learn more →