+{/snippet}
diff --git a/src/routes/weather/compare/[location]/+page.svelte b/src/routes/weather/compare/[location]/+page.svelte
index 8e09e2e..c328477 100644
--- a/src/routes/weather/compare/[location]/+page.svelte
+++ b/src/routes/weather/compare/[location]/+page.svelte
@@ -28,6 +28,7 @@
fetchModelComparison
} from '$lib/services/weather';
+ import { useHeroActions } from '../../hero.svelte';
import { findModel, hourly, modelGroups } from '../../options';
import { defaultParameters } from '../../options';
import ModelPictogramTimeline from './ModelPictogramTimeline.svelte';
@@ -52,6 +53,8 @@
let { data }: { data: PageData } = $props();
+ useHeroActions(heroActions);
+
// the URL is the source of truth: location comes from the load function,
// which is also correct on hydrated prerendered pages. The persisted store
// only mirrors it so the header and bare /weather/* redirects follow along.
@@ -280,28 +283,8 @@
});
-
-
-
- {#if location.admin1}{location.admin1},
- {/if}{location.country ?? ''}·Seasonal outlook
-
-
-
-
+
+{#snippet heroActions()}
{#if result}
{/if}
-
+{/snippet}
diff --git a/src/routes/weather/week/[location]/+page.svelte b/src/routes/weather/week/[location]/+page.svelte
index f3324d5..e616a66 100644
--- a/src/routes/weather/week/[location]/+page.svelte
+++ b/src/routes/weather/week/[location]/+page.svelte
@@ -23,6 +23,7 @@
humanizeWeatherError
} from '$lib/services/weather';
+ import { useHeroActions } from '../../hero.svelte';
import { defaultParameters } from '../../options';
import { computeDayNightWeatherCodes } from '../../utils/weather-codes';
import DailyStripSticky from './DailyStripSticky.svelte';
@@ -37,6 +38,8 @@
let { data }: { data: PageData } = $props();
+ useHeroActions(heroActions);
+
let params = $state({
models: ['best_match'],
...defaultParameters
@@ -56,6 +59,14 @@
// arrives (no layout shift)
let enabledChartCount = $derived($storedChartLayout.filter((p) => p.variables.length > 0).length);
+ // Height the hourly table will occupy once it renders, so its placeholder
+ // reserves exactly that and nothing below it jumps. The table is a header row
+ // plus one row per enabled variable, so the count drives the estimate.
+ const TABLE_HEADER_PX = 96;
+ const TABLE_ROW_PX = 57;
+ let enabledTableRows = $derived(Object.values($storedVariablePrefs.table).filter(Boolean).length);
+ let tableSkeletonHeight = $derived(TABLE_HEADER_PX + enabledTableRows * TABLE_ROW_PX);
+
// Request only the hourly variables the table rows and meteograms actually
// show, so unused variables are never fetched. weather_code is always
// included: the day cards / strip derive their day- and night-period icons
@@ -200,45 +211,24 @@
+
+{#snippet heroActions()}
+
+ {
+ params.models = [model];
+ storedModel.set(model);
+ // a new model may not support the extended / past range
+ forecastDays = 7;
+ pastDays = 0;
+ }}
+ />
+
- {
- params.models = [model];
- storedModel.set(model);
- // a new model may not support the extended / past range
- forecastDays = 7;
- pastDays = 0;
- }}
- />
-
-
-
(variableSidebarOpen = false)} />
{#if loadError}
@@ -314,19 +304,20 @@
the strip's sentinel view-timeline so the sticky strip (a sibling of
the sentinel) can scrub its collapse from it. -->