@nok-integration/storefront-react 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -6743,31 +6743,31 @@ function ProductView({
6743
6743
  }
6744
6744
  return unavailable;
6745
6745
  }
6746
- const showcase = "_showcase_1osag_7";
6747
- const panel = "_panel_1osag_19";
6748
- const image$1 = "_image_1osag_28";
6749
- const heroImageBox = "_heroImageBox_1osag_48";
6750
- const hero = "_hero_1osag_48";
6751
- const heroContent = "_heroContent_1osag_53";
6752
- const heroText = "_heroText_1osag_64";
6753
- const logo = "_logo_1osag_72";
6754
- const heroTitle = "_heroTitle_1osag_76";
6755
- const heroSub = "_heroSub_1osag_84";
6756
- const swipe = "_swipe_1osag_91";
6757
- const swipeLabel = "_swipeLabel_1osag_100";
6758
- const chevron = "_chevron_1osag_106";
6759
- const overlay$1 = "_overlay_1osag_118";
6760
- const copy = "_copy_1osag_130";
6761
- const title$2 = "_title_1osag_135";
6762
- const subtitle = "_subtitle_1osag_142";
6763
- const cta = "_cta_1osag_148";
6764
- const mosaicPanel = "_mosaicPanel_1osag_167";
6765
- const mosaic = "_mosaic_1osag_167";
6766
- const mRow = "_mRow_1osag_181";
6767
- const mBetween = "_mBetween_1osag_186";
6768
- const mCol = "_mCol_1osag_189";
6769
- const tile = "_tile_1osag_194";
6770
- const solid = "_solid_1osag_200";
6746
+ const showcase = "_showcase_16alm_30";
6747
+ const panel = "_panel_16alm_49";
6748
+ const image$1 = "_image_16alm_59";
6749
+ const heroImageBox = "_heroImageBox_16alm_79";
6750
+ const hero = "_hero_16alm_79";
6751
+ const heroContent = "_heroContent_16alm_84";
6752
+ const heroText = "_heroText_16alm_95";
6753
+ const logo = "_logo_16alm_103";
6754
+ const heroTitle = "_heroTitle_16alm_107";
6755
+ const heroSub = "_heroSub_16alm_115";
6756
+ const swipe = "_swipe_16alm_122";
6757
+ const swipeLabel = "_swipeLabel_16alm_131";
6758
+ const chevron = "_chevron_16alm_137";
6759
+ const overlay$1 = "_overlay_16alm_149";
6760
+ const copy = "_copy_16alm_161";
6761
+ const title$2 = "_title_16alm_166";
6762
+ const subtitle = "_subtitle_16alm_173";
6763
+ const cta = "_cta_16alm_179";
6764
+ const mosaicPanel = "_mosaicPanel_16alm_198";
6765
+ const mosaic = "_mosaic_16alm_198";
6766
+ const mRow = "_mRow_16alm_212";
6767
+ const mBetween = "_mBetween_16alm_217";
6768
+ const mCol = "_mCol_16alm_220";
6769
+ const tile = "_tile_16alm_225";
6770
+ const solid = "_solid_16alm_231";
6771
6771
  const styles$6 = {
6772
6772
  showcase,
6773
6773
  panel,
@@ -6917,53 +6917,83 @@ function MosaicPanel() {
6917
6917
  ] })
6918
6918
  ] }) });
6919
6919
  }
6920
+ function useShowcaseTop(ref) {
6921
+ useEffect(() => {
6922
+ const el = ref.current;
6923
+ if (!el) return;
6924
+ const measure = () => {
6925
+ const top = Math.max(0, Math.round(el.getBoundingClientRect().top + window.scrollY));
6926
+ el.style.setProperty("--showcase-top", `${top}px`);
6927
+ };
6928
+ measure();
6929
+ window.addEventListener("resize", measure);
6930
+ window.addEventListener("orientationchange", measure);
6931
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
6932
+ if (observer && el.parentElement) observer.observe(el.parentElement);
6933
+ return () => {
6934
+ window.removeEventListener("resize", measure);
6935
+ window.removeEventListener("orientationchange", measure);
6936
+ observer?.disconnect();
6937
+ };
6938
+ }, [ref]);
6939
+ }
6920
6940
  function HomeShowcase() {
6921
6941
  const assetUrl = useAssetUrl();
6922
- return /* @__PURE__ */ jsx(ShopSurface, { tone: "dark", fill: true, children: /* @__PURE__ */ jsxs("div", { className: styles$6.showcase, children: [
6923
- /* @__PURE__ */ jsxs("section", { className: `${styles$6.panel} ${styles$6.hero}`, "aria-label": "DAZN Shop", children: [
6924
- /* @__PURE__ */ jsx("div", { className: styles$6.heroImageBox, children: /* @__PURE__ */ jsx(
6925
- ShopImage,
6926
- {
6927
- src: "/figma/home/hero.jpg",
6928
- alt: "",
6929
- fill: true,
6930
- priority: true,
6931
- sizes: "(max-width: 480px) 100vw, 480px",
6932
- className: styles$6.image
6933
- }
6934
- ) }),
6935
- /* @__PURE__ */ jsxs("div", { className: styles$6.heroContent, children: [
6936
- /* @__PURE__ */ jsxs("div", { className: styles$6.heroText, children: [
6937
- /* @__PURE__ */ jsx(
6938
- "img",
6939
- {
6940
- src: assetUrl("/figma/home/dazn-logo.svg"),
6941
- alt: "DAZN",
6942
- className: styles$6.logo
6943
- }
6944
- ),
6945
- /* @__PURE__ */ jsx("h1", { className: styles$6.heroTitle, children: "DAZN SHOP" }),
6946
- /* @__PURE__ */ jsx("p", { className: styles$6.heroSub, children: "Fresh drops inspired by sport, culture, and everyday movement" })
6947
- ] }),
6948
- /* @__PURE__ */ jsxs("div", { className: styles$6.swipe, children: [
6949
- /* @__PURE__ */ jsx("p", { className: styles$6.swipeLabel, children: "Swipe down for more" }),
6950
- /* @__PURE__ */ jsx("svg", { className: styles$6.chevron, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
6951
- "path",
6952
- {
6953
- d: "M6 9l6 6 6-6",
6954
- stroke: "currentColor",
6955
- strokeWidth: "2",
6956
- strokeLinecap: "round",
6957
- strokeLinejoin: "round"
6958
- }
6959
- ) })
6942
+ const showcaseRef = useRef(null);
6943
+ useShowcaseTop(showcaseRef);
6944
+ return (
6945
+ /*
6946
+ * No `fill`. The surface used to force `min-height: 100dvh` around a scroller that was
6947
+ * a different height, so the difference showed as a dead band of bare background. The
6948
+ * showcase paints its own dark ground and now owns its own height, so there is nothing
6949
+ * for the surface to fill.
6950
+ */
6951
+ /* @__PURE__ */ jsx(ShopSurface, { tone: "dark", children: /* @__PURE__ */ jsxs("div", { className: styles$6.showcase, ref: showcaseRef, children: [
6952
+ /* @__PURE__ */ jsxs("section", { className: `${styles$6.panel} ${styles$6.hero}`, "aria-label": "DAZN Shop", children: [
6953
+ /* @__PURE__ */ jsx("div", { className: styles$6.heroImageBox, children: /* @__PURE__ */ jsx(
6954
+ ShopImage,
6955
+ {
6956
+ src: "/figma/home/hero.jpg",
6957
+ alt: "",
6958
+ fill: true,
6959
+ priority: true,
6960
+ sizes: "(max-width: 480px) 100vw, 480px",
6961
+ className: styles$6.image
6962
+ }
6963
+ ) }),
6964
+ /* @__PURE__ */ jsxs("div", { className: styles$6.heroContent, children: [
6965
+ /* @__PURE__ */ jsxs("div", { className: styles$6.heroText, children: [
6966
+ /* @__PURE__ */ jsx(
6967
+ "img",
6968
+ {
6969
+ src: assetUrl("/figma/home/dazn-logo.svg"),
6970
+ alt: "DAZN",
6971
+ className: styles$6.logo
6972
+ }
6973
+ ),
6974
+ /* @__PURE__ */ jsx("h1", { className: styles$6.heroTitle, children: "DAZN SHOP" }),
6975
+ /* @__PURE__ */ jsx("p", { className: styles$6.heroSub, children: "Fresh drops inspired by sport, culture, and everyday movement" })
6976
+ ] }),
6977
+ /* @__PURE__ */ jsxs("div", { className: styles$6.swipe, children: [
6978
+ /* @__PURE__ */ jsx("p", { className: styles$6.swipeLabel, children: "Swipe down for more" }),
6979
+ /* @__PURE__ */ jsx("svg", { className: styles$6.chevron, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
6980
+ "path",
6981
+ {
6982
+ d: "M6 9l6 6 6-6",
6983
+ stroke: "currentColor",
6984
+ strokeWidth: "2",
6985
+ strokeLinecap: "round",
6986
+ strokeLinejoin: "round"
6987
+ }
6988
+ ) })
6989
+ ] })
6960
6990
  ] })
6961
- ] })
6962
- ] }),
6963
- PANELS_TOP.map((p) => /* @__PURE__ */ jsx(CategoryPanel, { panel: p }, p.key)),
6964
- /* @__PURE__ */ jsx(MosaicPanel, {}),
6965
- PANELS_BOTTOM.map((p) => /* @__PURE__ */ jsx(CategoryPanel, { panel: p }, p.key))
6966
- ] }) });
6991
+ ] }),
6992
+ PANELS_TOP.map((p) => /* @__PURE__ */ jsx(CategoryPanel, { panel: p }, p.key)),
6993
+ /* @__PURE__ */ jsx(MosaicPanel, {}),
6994
+ PANELS_BOTTOM.map((p) => /* @__PURE__ */ jsx(CategoryPanel, { panel: p }, p.key))
6995
+ ] }) })
6996
+ );
6967
6997
  }
6968
6998
  const overlay = "_overlay_s4eai_1";
6969
6999
  const scrim = "_scrim_s4eai_10";
@@ -6743,31 +6743,31 @@ function ProductView({
6743
6743
  }
6744
6744
  return unavailable;
6745
6745
  }
6746
- const showcase = "_showcase_1osag_7";
6747
- const panel = "_panel_1osag_19";
6748
- const image$1 = "_image_1osag_28";
6749
- const heroImageBox = "_heroImageBox_1osag_48";
6750
- const hero = "_hero_1osag_48";
6751
- const heroContent = "_heroContent_1osag_53";
6752
- const heroText = "_heroText_1osag_64";
6753
- const logo = "_logo_1osag_72";
6754
- const heroTitle = "_heroTitle_1osag_76";
6755
- const heroSub = "_heroSub_1osag_84";
6756
- const swipe = "_swipe_1osag_91";
6757
- const swipeLabel = "_swipeLabel_1osag_100";
6758
- const chevron = "_chevron_1osag_106";
6759
- const overlay$1 = "_overlay_1osag_118";
6760
- const copy = "_copy_1osag_130";
6761
- const title$2 = "_title_1osag_135";
6762
- const subtitle = "_subtitle_1osag_142";
6763
- const cta = "_cta_1osag_148";
6764
- const mosaicPanel = "_mosaicPanel_1osag_167";
6765
- const mosaic = "_mosaic_1osag_167";
6766
- const mRow = "_mRow_1osag_181";
6767
- const mBetween = "_mBetween_1osag_186";
6768
- const mCol = "_mCol_1osag_189";
6769
- const tile = "_tile_1osag_194";
6770
- const solid = "_solid_1osag_200";
6746
+ const showcase = "_showcase_16alm_30";
6747
+ const panel = "_panel_16alm_49";
6748
+ const image$1 = "_image_16alm_59";
6749
+ const heroImageBox = "_heroImageBox_16alm_79";
6750
+ const hero = "_hero_16alm_79";
6751
+ const heroContent = "_heroContent_16alm_84";
6752
+ const heroText = "_heroText_16alm_95";
6753
+ const logo = "_logo_16alm_103";
6754
+ const heroTitle = "_heroTitle_16alm_107";
6755
+ const heroSub = "_heroSub_16alm_115";
6756
+ const swipe = "_swipe_16alm_122";
6757
+ const swipeLabel = "_swipeLabel_16alm_131";
6758
+ const chevron = "_chevron_16alm_137";
6759
+ const overlay$1 = "_overlay_16alm_149";
6760
+ const copy = "_copy_16alm_161";
6761
+ const title$2 = "_title_16alm_166";
6762
+ const subtitle = "_subtitle_16alm_173";
6763
+ const cta = "_cta_16alm_179";
6764
+ const mosaicPanel = "_mosaicPanel_16alm_198";
6765
+ const mosaic = "_mosaic_16alm_198";
6766
+ const mRow = "_mRow_16alm_212";
6767
+ const mBetween = "_mBetween_16alm_217";
6768
+ const mCol = "_mCol_16alm_220";
6769
+ const tile = "_tile_16alm_225";
6770
+ const solid = "_solid_16alm_231";
6771
6771
  const styles$6 = {
6772
6772
  showcase,
6773
6773
  panel,
@@ -6917,53 +6917,83 @@ function MosaicPanel() {
6917
6917
  ] })
6918
6918
  ] }) });
6919
6919
  }
6920
+ function useShowcaseTop(ref) {
6921
+ useEffect(() => {
6922
+ const el = ref.current;
6923
+ if (!el) return;
6924
+ const measure = () => {
6925
+ const top = Math.max(0, Math.round(el.getBoundingClientRect().top + window.scrollY));
6926
+ el.style.setProperty("--showcase-top", `${top}px`);
6927
+ };
6928
+ measure();
6929
+ window.addEventListener("resize", measure);
6930
+ window.addEventListener("orientationchange", measure);
6931
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
6932
+ if (observer && el.parentElement) observer.observe(el.parentElement);
6933
+ return () => {
6934
+ window.removeEventListener("resize", measure);
6935
+ window.removeEventListener("orientationchange", measure);
6936
+ observer?.disconnect();
6937
+ };
6938
+ }, [ref]);
6939
+ }
6920
6940
  function HomeShowcase() {
6921
6941
  const assetUrl = useAssetUrl();
6922
- return /* @__PURE__ */ jsx(ShopSurface, { tone: "dark", fill: true, children: /* @__PURE__ */ jsxs("div", { className: styles$6.showcase, children: [
6923
- /* @__PURE__ */ jsxs("section", { className: `${styles$6.panel} ${styles$6.hero}`, "aria-label": "DAZN Shop", children: [
6924
- /* @__PURE__ */ jsx("div", { className: styles$6.heroImageBox, children: /* @__PURE__ */ jsx(
6925
- ShopImage,
6926
- {
6927
- src: "/figma/home/hero.jpg",
6928
- alt: "",
6929
- fill: true,
6930
- priority: true,
6931
- sizes: "(max-width: 480px) 100vw, 480px",
6932
- className: styles$6.image
6933
- }
6934
- ) }),
6935
- /* @__PURE__ */ jsxs("div", { className: styles$6.heroContent, children: [
6936
- /* @__PURE__ */ jsxs("div", { className: styles$6.heroText, children: [
6937
- /* @__PURE__ */ jsx(
6938
- "img",
6939
- {
6940
- src: assetUrl("/figma/home/dazn-logo.svg"),
6941
- alt: "DAZN",
6942
- className: styles$6.logo
6943
- }
6944
- ),
6945
- /* @__PURE__ */ jsx("h1", { className: styles$6.heroTitle, children: "DAZN SHOP" }),
6946
- /* @__PURE__ */ jsx("p", { className: styles$6.heroSub, children: "Fresh drops inspired by sport, culture, and everyday movement" })
6947
- ] }),
6948
- /* @__PURE__ */ jsxs("div", { className: styles$6.swipe, children: [
6949
- /* @__PURE__ */ jsx("p", { className: styles$6.swipeLabel, children: "Swipe down for more" }),
6950
- /* @__PURE__ */ jsx("svg", { className: styles$6.chevron, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
6951
- "path",
6952
- {
6953
- d: "M6 9l6 6 6-6",
6954
- stroke: "currentColor",
6955
- strokeWidth: "2",
6956
- strokeLinecap: "round",
6957
- strokeLinejoin: "round"
6958
- }
6959
- ) })
6942
+ const showcaseRef = useRef(null);
6943
+ useShowcaseTop(showcaseRef);
6944
+ return (
6945
+ /*
6946
+ * No `fill`. The surface used to force `min-height: 100dvh` around a scroller that was
6947
+ * a different height, so the difference showed as a dead band of bare background. The
6948
+ * showcase paints its own dark ground and now owns its own height, so there is nothing
6949
+ * for the surface to fill.
6950
+ */
6951
+ /* @__PURE__ */ jsx(ShopSurface, { tone: "dark", children: /* @__PURE__ */ jsxs("div", { className: styles$6.showcase, ref: showcaseRef, children: [
6952
+ /* @__PURE__ */ jsxs("section", { className: `${styles$6.panel} ${styles$6.hero}`, "aria-label": "DAZN Shop", children: [
6953
+ /* @__PURE__ */ jsx("div", { className: styles$6.heroImageBox, children: /* @__PURE__ */ jsx(
6954
+ ShopImage,
6955
+ {
6956
+ src: "/figma/home/hero.jpg",
6957
+ alt: "",
6958
+ fill: true,
6959
+ priority: true,
6960
+ sizes: "(max-width: 480px) 100vw, 480px",
6961
+ className: styles$6.image
6962
+ }
6963
+ ) }),
6964
+ /* @__PURE__ */ jsxs("div", { className: styles$6.heroContent, children: [
6965
+ /* @__PURE__ */ jsxs("div", { className: styles$6.heroText, children: [
6966
+ /* @__PURE__ */ jsx(
6967
+ "img",
6968
+ {
6969
+ src: assetUrl("/figma/home/dazn-logo.svg"),
6970
+ alt: "DAZN",
6971
+ className: styles$6.logo
6972
+ }
6973
+ ),
6974
+ /* @__PURE__ */ jsx("h1", { className: styles$6.heroTitle, children: "DAZN SHOP" }),
6975
+ /* @__PURE__ */ jsx("p", { className: styles$6.heroSub, children: "Fresh drops inspired by sport, culture, and everyday movement" })
6976
+ ] }),
6977
+ /* @__PURE__ */ jsxs("div", { className: styles$6.swipe, children: [
6978
+ /* @__PURE__ */ jsx("p", { className: styles$6.swipeLabel, children: "Swipe down for more" }),
6979
+ /* @__PURE__ */ jsx("svg", { className: styles$6.chevron, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
6980
+ "path",
6981
+ {
6982
+ d: "M6 9l6 6 6-6",
6983
+ stroke: "currentColor",
6984
+ strokeWidth: "2",
6985
+ strokeLinecap: "round",
6986
+ strokeLinejoin: "round"
6987
+ }
6988
+ ) })
6989
+ ] })
6960
6990
  ] })
6961
- ] })
6962
- ] }),
6963
- PANELS_TOP.map((p) => /* @__PURE__ */ jsx(CategoryPanel, { panel: p }, p.key)),
6964
- /* @__PURE__ */ jsx(MosaicPanel, {}),
6965
- PANELS_BOTTOM.map((p) => /* @__PURE__ */ jsx(CategoryPanel, { panel: p }, p.key))
6966
- ] }) });
6991
+ ] }),
6992
+ PANELS_TOP.map((p) => /* @__PURE__ */ jsx(CategoryPanel, { panel: p }, p.key)),
6993
+ /* @__PURE__ */ jsx(MosaicPanel, {}),
6994
+ PANELS_BOTTOM.map((p) => /* @__PURE__ */ jsx(CategoryPanel, { panel: p }, p.key))
6995
+ ] }) })
6996
+ );
6967
6997
  }
6968
6998
  const overlay = "_overlay_s4eai_1";
6969
6999
  const scrim = "_scrim_s4eai_10";
@@ -1729,34 +1729,65 @@
1729
1729
  * outline CTA). Always dark (#080e12), independent of theme. Measurements are taken
1730
1730
  * from Figma: overlay pad 24, gap 16, title 32, subtitle 16/1.55, button h48 radius 8.
1731
1731
  */
1732
- ._showcase_1osag_7 {
1733
- height: calc(100dvh - 56px); /* below the 56px webview header */
1732
+
1733
+ /*
1734
+ * The height of this scroller is the one measurement a mounted component cannot guess.
1735
+ *
1736
+ * It used to be `calc(100dvh - 56px)`, and both halves were wrong.
1737
+ *
1738
+ * **The 56 was a hard-coded guess at somebody else's header.** We are mounted inside a
1739
+ * host page whose chrome we do not own and cannot see. Where the host's header was not
1740
+ * 56px — DAZN's storefront runs 69 — the scroller ended up shorter than the space it was
1741
+ * given, leaving a dead band of bare surface at the bottom. Because the band sits below
1742
+ * the fold until the document itself scrolls, it appeared only after scrolling down and
1743
+ * back: exactly the report from 13 Aug 2026.
1744
+ *
1745
+ * **`dvh` is the wrong unit for a snap container.** It is the *dynamic* viewport, so it
1746
+ * grows as a mobile browser hides its URL bar and shrinks as it returns. Every panel then
1747
+ * resizes during the very scroll that snapping depends on, and the container is left
1748
+ * parked between snap points. `svh` is the stable smallest value and never changes
1749
+ * mid-scroll. The cost is a small gap when the chrome is hidden; the alternative is a
1750
+ * layout that moves under the reader's thumb.
1751
+ *
1752
+ * `--showcase-top` is measured at mount and on resize (see HomeShowcase.tsx) rather than
1753
+ * assumed: whatever the host puts above us, we take the rest.
1754
+ */
1755
+ ._showcase_16alm_30 {
1756
+ height: calc(100svh - var(--showcase-top, 0px));
1734
1757
  overflow-y: auto;
1735
1758
  scroll-snap-type: y mandatory;
1759
+ /*
1760
+ * Do not hand the scroll on to the host page when this container reaches its end.
1761
+ * Chaining is what let the outer document sit at a different offset from this one, so a
1762
+ * reader who scrolled to the bottom and back found the page in a state neither scroller
1763
+ * agreed on.
1764
+ */
1765
+ overscroll-behavior-y: contain;
1736
1766
  -webkit-overflow-scrolling: touch;
1737
1767
  background: #080e12;
1738
1768
  scrollbar-width: none;
1739
1769
  }
1740
- ._showcase_1osag_7::-webkit-scrollbar {
1770
+ ._showcase_16alm_30::-webkit-scrollbar {
1741
1771
  display: none;
1742
1772
  }
1743
1773
 
1744
- ._panel_1osag_19 {
1774
+ ._panel_16alm_49 {
1745
1775
  position: relative;
1746
- height: calc(100dvh - 56px);
1776
+ /* Matches the scroller exactly, or snapping has nothing to align to. */
1777
+ height: calc(100svh - var(--showcase-top, 0px));
1747
1778
  scroll-snap-align: start;
1748
1779
  scroll-snap-stop: always;
1749
1780
  overflow: hidden;
1750
1781
  background: #080e12;
1751
1782
  }
1752
1783
 
1753
- ._image_1osag_28 {
1784
+ ._image_16alm_59 {
1754
1785
  object-fit: cover;
1755
1786
  object-position: center;
1756
1787
  }
1757
1788
 
1758
1789
  /* Bottom scrim so overlay text stays legible over any photo. */
1759
- ._panel_1osag_19::after {
1790
+ ._panel_16alm_49::after {
1760
1791
  content: '';
1761
1792
  position: absolute;
1762
1793
  inset: 0;
@@ -1770,12 +1801,12 @@
1770
1801
  * (`edit_9 1`) is 375x674 and stops where the opaque "swipe down" bar starts. Giving it
1771
1802
  * its own box keeps the shot at its native aspect instead of cover-cropping the sides.
1772
1803
  */
1773
- ._heroImageBox_1osag_48 {
1804
+ ._heroImageBox_16alm_79 {
1774
1805
  position: absolute;
1775
1806
  inset: 0 0 82px;
1776
1807
  overflow: hidden;
1777
1808
  }
1778
- ._hero_1osag_48 ._heroContent_1osag_53 {
1809
+ ._hero_16alm_79 ._heroContent_16alm_84 {
1779
1810
  position: absolute;
1780
1811
  bottom: 15px;
1781
1812
  left: 0;
@@ -1786,7 +1817,7 @@
1786
1817
  gap: 24px;
1787
1818
  align-items: stretch;
1788
1819
  }
1789
- ._heroText_1osag_64 {
1820
+ ._heroText_16alm_95 {
1790
1821
  display: flex;
1791
1822
  flex-direction: column;
1792
1823
  gap: 8px;
@@ -1794,11 +1825,11 @@
1794
1825
  padding: 0 24px;
1795
1826
  text-align: center;
1796
1827
  }
1797
- ._logo_1osag_72 {
1828
+ ._logo_16alm_103 {
1798
1829
  width: 48px;
1799
1830
  height: 48px;
1800
1831
  }
1801
- ._heroTitle_1osag_76 {
1832
+ ._heroTitle_16alm_107 {
1802
1833
  margin: 0;
1803
1834
  font-size: 56px;
1804
1835
  line-height: 1.3;
@@ -1806,14 +1837,14 @@
1806
1837
  letter-spacing: -1.12px;
1807
1838
  color: #f9fafa;
1808
1839
  }
1809
- ._heroSub_1osag_84 {
1840
+ ._heroSub_16alm_115 {
1810
1841
  margin: 0;
1811
1842
  font-size: 16px;
1812
1843
  line-height: 1.55;
1813
1844
  color: #f9fafa;
1814
1845
  max-width: 327px;
1815
1846
  }
1816
- ._swipe_1osag_91 {
1847
+ ._swipe_16alm_122 {
1817
1848
  display: flex;
1818
1849
  flex-direction: column;
1819
1850
  align-items: center;
@@ -1822,25 +1853,25 @@
1822
1853
  justify-content: center;
1823
1854
  background: #080e12;
1824
1855
  }
1825
- ._swipeLabel_1osag_100 {
1856
+ ._swipeLabel_16alm_131 {
1826
1857
  margin: 0;
1827
1858
  font-size: 14px;
1828
1859
  line-height: 1;
1829
1860
  color: rgba(255, 255, 255, 0.54);
1830
1861
  }
1831
- ._chevron_1osag_106 {
1862
+ ._chevron_16alm_137 {
1832
1863
  width: 24px;
1833
1864
  height: 24px;
1834
1865
  color: rgba(255, 255, 255, 0.54);
1835
- animation: _bob_1osag_1 1.8s ease-in-out infinite;
1866
+ animation: _bob_16alm_1 1.8s ease-in-out infinite;
1836
1867
  }
1837
- @keyframes _bob_1osag_1 {
1868
+ @keyframes _bob_16alm_1 {
1838
1869
  0%, 100% { transform: translateY(0); }
1839
1870
  50% { transform: translateY(4px); }
1840
1871
  }
1841
1872
 
1842
1873
  /* ── Category panels ── */
1843
- ._overlay_1osag_118 {
1874
+ ._overlay_16alm_149 {
1844
1875
  position: absolute;
1845
1876
  bottom: 0;
1846
1877
  left: 0;
@@ -1852,25 +1883,25 @@
1852
1883
  align-items: flex-start;
1853
1884
  padding: 0 24px 24px;
1854
1885
  }
1855
- ._copy_1osag_130 {
1886
+ ._copy_16alm_161 {
1856
1887
  display: flex;
1857
1888
  flex-direction: column;
1858
1889
  gap: 8px;
1859
1890
  }
1860
- ._title_1osag_135 {
1891
+ ._title_16alm_166 {
1861
1892
  margin: 0;
1862
1893
  font-size: 32px;
1863
1894
  line-height: 1.2;
1864
1895
  font-weight: 700;
1865
1896
  color: #f9fafa;
1866
1897
  }
1867
- ._subtitle_1osag_142 {
1898
+ ._subtitle_16alm_173 {
1868
1899
  margin: 0;
1869
1900
  font-size: 16px;
1870
1901
  line-height: 1.55;
1871
1902
  color: #f9fafa;
1872
1903
  }
1873
- ._cta_1osag_148 {
1904
+ ._cta_16alm_179 {
1874
1905
  display: inline-flex;
1875
1906
  align-items: center;
1876
1907
  justify-content: center;
@@ -1884,45 +1915,45 @@
1884
1915
  font-weight: 700;
1885
1916
  text-decoration: none;
1886
1917
  }
1887
- ._cta_1osag_148:active {
1918
+ ._cta_16alm_179:active {
1888
1919
  background: rgba(249, 250, 250, 0.12);
1889
1920
  }
1890
1921
 
1891
1922
  /* ── Mosaic gallery panel ── */
1892
- ._mosaicPanel_1osag_167 {
1923
+ ._mosaicPanel_16alm_198 {
1893
1924
  display: flex;
1894
1925
  align-items: center;
1895
1926
  justify-content: center;
1896
1927
  }
1897
- ._mosaicPanel_1osag_167::after {
1928
+ ._mosaicPanel_16alm_198::after {
1898
1929
  display: none;
1899
1930
  }
1900
- ._mosaic_1osag_167 {
1931
+ ._mosaic_16alm_198 {
1901
1932
  display: flex;
1902
1933
  flex-direction: column;
1903
1934
  gap: 12px;
1904
1935
  width: 343px;
1905
1936
  }
1906
- ._mRow_1osag_181 {
1937
+ ._mRow_16alm_212 {
1907
1938
  display: flex;
1908
1939
  gap: 12px;
1909
1940
  align-items: center;
1910
1941
  }
1911
- ._mBetween_1osag_186 {
1942
+ ._mBetween_16alm_217 {
1912
1943
  justify-content: space-between;
1913
1944
  }
1914
- ._mCol_1osag_189 {
1945
+ ._mCol_16alm_220 {
1915
1946
  display: flex;
1916
1947
  flex-direction: column;
1917
1948
  gap: 10px;
1918
1949
  }
1919
- ._tile_1osag_194 {
1950
+ ._tile_16alm_225 {
1920
1951
  position: relative;
1921
1952
  border-radius: 6px;
1922
1953
  overflow: hidden;
1923
1954
  flex-shrink: 0;
1924
1955
  }
1925
- ._solid_1osag_200 {
1956
+ ._solid_16alm_231 {
1926
1957
  background: #171e23;
1927
1958
  }
1928
1959
  ._overlay_s4eai_1 {
package/dist/styles.css CHANGED
@@ -1729,34 +1729,65 @@
1729
1729
  * outline CTA). Always dark (#080e12), independent of theme. Measurements are taken
1730
1730
  * from Figma: overlay pad 24, gap 16, title 32, subtitle 16/1.55, button h48 radius 8.
1731
1731
  */
1732
- ._showcase_1osag_7 {
1733
- height: calc(100dvh - 56px); /* below the 56px webview header */
1732
+
1733
+ /*
1734
+ * The height of this scroller is the one measurement a mounted component cannot guess.
1735
+ *
1736
+ * It used to be `calc(100dvh - 56px)`, and both halves were wrong.
1737
+ *
1738
+ * **The 56 was a hard-coded guess at somebody else's header.** We are mounted inside a
1739
+ * host page whose chrome we do not own and cannot see. Where the host's header was not
1740
+ * 56px — DAZN's storefront runs 69 — the scroller ended up shorter than the space it was
1741
+ * given, leaving a dead band of bare surface at the bottom. Because the band sits below
1742
+ * the fold until the document itself scrolls, it appeared only after scrolling down and
1743
+ * back: exactly the report from 13 Aug 2026.
1744
+ *
1745
+ * **`dvh` is the wrong unit for a snap container.** It is the *dynamic* viewport, so it
1746
+ * grows as a mobile browser hides its URL bar and shrinks as it returns. Every panel then
1747
+ * resizes during the very scroll that snapping depends on, and the container is left
1748
+ * parked between snap points. `svh` is the stable smallest value and never changes
1749
+ * mid-scroll. The cost is a small gap when the chrome is hidden; the alternative is a
1750
+ * layout that moves under the reader's thumb.
1751
+ *
1752
+ * `--showcase-top` is measured at mount and on resize (see HomeShowcase.tsx) rather than
1753
+ * assumed: whatever the host puts above us, we take the rest.
1754
+ */
1755
+ ._showcase_16alm_30 {
1756
+ height: calc(100svh - var(--showcase-top, 0px));
1734
1757
  overflow-y: auto;
1735
1758
  scroll-snap-type: y mandatory;
1759
+ /*
1760
+ * Do not hand the scroll on to the host page when this container reaches its end.
1761
+ * Chaining is what let the outer document sit at a different offset from this one, so a
1762
+ * reader who scrolled to the bottom and back found the page in a state neither scroller
1763
+ * agreed on.
1764
+ */
1765
+ overscroll-behavior-y: contain;
1736
1766
  -webkit-overflow-scrolling: touch;
1737
1767
  background: #080e12;
1738
1768
  scrollbar-width: none;
1739
1769
  }
1740
- ._showcase_1osag_7::-webkit-scrollbar {
1770
+ ._showcase_16alm_30::-webkit-scrollbar {
1741
1771
  display: none;
1742
1772
  }
1743
1773
 
1744
- ._panel_1osag_19 {
1774
+ ._panel_16alm_49 {
1745
1775
  position: relative;
1746
- height: calc(100dvh - 56px);
1776
+ /* Matches the scroller exactly, or snapping has nothing to align to. */
1777
+ height: calc(100svh - var(--showcase-top, 0px));
1747
1778
  scroll-snap-align: start;
1748
1779
  scroll-snap-stop: always;
1749
1780
  overflow: hidden;
1750
1781
  background: #080e12;
1751
1782
  }
1752
1783
 
1753
- ._image_1osag_28 {
1784
+ ._image_16alm_59 {
1754
1785
  object-fit: cover;
1755
1786
  object-position: center;
1756
1787
  }
1757
1788
 
1758
1789
  /* Bottom scrim so overlay text stays legible over any photo. */
1759
- ._panel_1osag_19::after {
1790
+ ._panel_16alm_49::after {
1760
1791
  content: '';
1761
1792
  position: absolute;
1762
1793
  inset: 0;
@@ -1770,12 +1801,12 @@
1770
1801
  * (`edit_9 1`) is 375x674 and stops where the opaque "swipe down" bar starts. Giving it
1771
1802
  * its own box keeps the shot at its native aspect instead of cover-cropping the sides.
1772
1803
  */
1773
- ._heroImageBox_1osag_48 {
1804
+ ._heroImageBox_16alm_79 {
1774
1805
  position: absolute;
1775
1806
  inset: 0 0 82px;
1776
1807
  overflow: hidden;
1777
1808
  }
1778
- ._hero_1osag_48 ._heroContent_1osag_53 {
1809
+ ._hero_16alm_79 ._heroContent_16alm_84 {
1779
1810
  position: absolute;
1780
1811
  bottom: 15px;
1781
1812
  left: 0;
@@ -1786,7 +1817,7 @@
1786
1817
  gap: 24px;
1787
1818
  align-items: stretch;
1788
1819
  }
1789
- ._heroText_1osag_64 {
1820
+ ._heroText_16alm_95 {
1790
1821
  display: flex;
1791
1822
  flex-direction: column;
1792
1823
  gap: 8px;
@@ -1794,11 +1825,11 @@
1794
1825
  padding: 0 24px;
1795
1826
  text-align: center;
1796
1827
  }
1797
- ._logo_1osag_72 {
1828
+ ._logo_16alm_103 {
1798
1829
  width: 48px;
1799
1830
  height: 48px;
1800
1831
  }
1801
- ._heroTitle_1osag_76 {
1832
+ ._heroTitle_16alm_107 {
1802
1833
  margin: 0;
1803
1834
  font-size: 56px;
1804
1835
  line-height: 1.3;
@@ -1806,14 +1837,14 @@
1806
1837
  letter-spacing: -1.12px;
1807
1838
  color: #f9fafa;
1808
1839
  }
1809
- ._heroSub_1osag_84 {
1840
+ ._heroSub_16alm_115 {
1810
1841
  margin: 0;
1811
1842
  font-size: 16px;
1812
1843
  line-height: 1.55;
1813
1844
  color: #f9fafa;
1814
1845
  max-width: 327px;
1815
1846
  }
1816
- ._swipe_1osag_91 {
1847
+ ._swipe_16alm_122 {
1817
1848
  display: flex;
1818
1849
  flex-direction: column;
1819
1850
  align-items: center;
@@ -1822,25 +1853,25 @@
1822
1853
  justify-content: center;
1823
1854
  background: #080e12;
1824
1855
  }
1825
- ._swipeLabel_1osag_100 {
1856
+ ._swipeLabel_16alm_131 {
1826
1857
  margin: 0;
1827
1858
  font-size: 14px;
1828
1859
  line-height: 1;
1829
1860
  color: rgba(255, 255, 255, 0.54);
1830
1861
  }
1831
- ._chevron_1osag_106 {
1862
+ ._chevron_16alm_137 {
1832
1863
  width: 24px;
1833
1864
  height: 24px;
1834
1865
  color: rgba(255, 255, 255, 0.54);
1835
- animation: _bob_1osag_1 1.8s ease-in-out infinite;
1866
+ animation: _bob_16alm_1 1.8s ease-in-out infinite;
1836
1867
  }
1837
- @keyframes _bob_1osag_1 {
1868
+ @keyframes _bob_16alm_1 {
1838
1869
  0%, 100% { transform: translateY(0); }
1839
1870
  50% { transform: translateY(4px); }
1840
1871
  }
1841
1872
 
1842
1873
  /* ── Category panels ── */
1843
- ._overlay_1osag_118 {
1874
+ ._overlay_16alm_149 {
1844
1875
  position: absolute;
1845
1876
  bottom: 0;
1846
1877
  left: 0;
@@ -1852,25 +1883,25 @@
1852
1883
  align-items: flex-start;
1853
1884
  padding: 0 24px 24px;
1854
1885
  }
1855
- ._copy_1osag_130 {
1886
+ ._copy_16alm_161 {
1856
1887
  display: flex;
1857
1888
  flex-direction: column;
1858
1889
  gap: 8px;
1859
1890
  }
1860
- ._title_1osag_135 {
1891
+ ._title_16alm_166 {
1861
1892
  margin: 0;
1862
1893
  font-size: 32px;
1863
1894
  line-height: 1.2;
1864
1895
  font-weight: 700;
1865
1896
  color: #f9fafa;
1866
1897
  }
1867
- ._subtitle_1osag_142 {
1898
+ ._subtitle_16alm_173 {
1868
1899
  margin: 0;
1869
1900
  font-size: 16px;
1870
1901
  line-height: 1.55;
1871
1902
  color: #f9fafa;
1872
1903
  }
1873
- ._cta_1osag_148 {
1904
+ ._cta_16alm_179 {
1874
1905
  display: inline-flex;
1875
1906
  align-items: center;
1876
1907
  justify-content: center;
@@ -1884,45 +1915,45 @@
1884
1915
  font-weight: 700;
1885
1916
  text-decoration: none;
1886
1917
  }
1887
- ._cta_1osag_148:active {
1918
+ ._cta_16alm_179:active {
1888
1919
  background: rgba(249, 250, 250, 0.12);
1889
1920
  }
1890
1921
 
1891
1922
  /* ── Mosaic gallery panel ── */
1892
- ._mosaicPanel_1osag_167 {
1923
+ ._mosaicPanel_16alm_198 {
1893
1924
  display: flex;
1894
1925
  align-items: center;
1895
1926
  justify-content: center;
1896
1927
  }
1897
- ._mosaicPanel_1osag_167::after {
1928
+ ._mosaicPanel_16alm_198::after {
1898
1929
  display: none;
1899
1930
  }
1900
- ._mosaic_1osag_167 {
1931
+ ._mosaic_16alm_198 {
1901
1932
  display: flex;
1902
1933
  flex-direction: column;
1903
1934
  gap: 12px;
1904
1935
  width: 343px;
1905
1936
  }
1906
- ._mRow_1osag_181 {
1937
+ ._mRow_16alm_212 {
1907
1938
  display: flex;
1908
1939
  gap: 12px;
1909
1940
  align-items: center;
1910
1941
  }
1911
- ._mBetween_1osag_186 {
1942
+ ._mBetween_16alm_217 {
1912
1943
  justify-content: space-between;
1913
1944
  }
1914
- ._mCol_1osag_189 {
1945
+ ._mCol_16alm_220 {
1915
1946
  display: flex;
1916
1947
  flex-direction: column;
1917
1948
  gap: 10px;
1918
1949
  }
1919
- ._tile_1osag_194 {
1950
+ ._tile_16alm_225 {
1920
1951
  position: relative;
1921
1952
  border-radius: 6px;
1922
1953
  overflow: hidden;
1923
1954
  flex-shrink: 0;
1924
1955
  }
1925
- ._solid_1osag_200 {
1956
+ ._solid_16alm_231 {
1926
1957
  background: #171e23;
1927
1958
  }
1928
1959
  ._overlay_s4eai_1 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nok-integration/storefront-react",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Mountable React storefront components: catalogue, product detail and cart, mounted directly into a host DOM tree. No iframe.",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {