diff --git a/.eleventy.js b/.eleventy.js index 7fa4aa299d..9e61d5ff5f 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -103,6 +103,7 @@ module.exports = function(eleventyConfig) { eleventyConfig.addPassthroughCopy("src/events/hm25-invite.ics"); eleventyConfig.addPassthroughCopy("src/webinars/2025/simplifying-opc-ua/opc-ua-webinar-flows.zip"); eleventyConfig.addPassthroughCopy("src/js/ai-expert-modal.js"); + eleventyConfig.addPassthroughCopy("src/js/bending-grid.js"); // Watch content images for the image pipeline eleventyConfig.addWatchTarget("src/**/*.{svg,webp,png,jpeg,gif}"); diff --git a/src/_includes/layouts/base.njk b/src/_includes/layouts/base.njk index 2f9e34565c..b8782e66ee 100644 --- a/src/_includes/layouts/base.njk +++ b/src/_includes/layouts/base.njk @@ -546,4 +546,8 @@ eleventyComputed: }); {%- endif -%} + + + + \ No newline at end of file diff --git a/src/css/style.css b/src/css/style.css index c5cd1601bc..74aea78ee8 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -1981,36 +1981,103 @@ lite-youtube::before { } .raster-gradient-bg { - background: radial-gradient(circle 80vw at 100% 0%, theme(colors.indigo.50), transparent); position: relative; + min-height: 100vh; } -.raster-gradient-bg::before { - content: ""; +/* Grid Container - Extends beyond hero with bottom fade */ +.bending-grid-container { position: absolute; top: 0; left: 0; - right: 0; - bottom: 0; - background-image: - linear-gradient(rgba(99, 102, 241, 0.15) 1px, transparent 1px), - linear-gradient(90deg, rgba(99, 102, 241, 0.15) 1px, transparent 1px); + width: 100%; + height: 120%; /* Extends 20% beyond hero */ + pointer-events: none; + z-index: 1; + perspective: 1540px; + perspective-origin: 60% 25%; + /* Fade out at bottom - starts at 70%, transparent at 100% */ + mask-image: linear-gradient( + to bottom, + black 0%, + black 70%, + rgba(0, 0, 0, 0.8) 80%, + rgba(0, 0, 0, 0.5) 90%, + transparent 100% + ); + -webkit-mask-image: linear-gradient( + to bottom, + black 0%, + black 70%, + rgba(0, 0, 0, 0.8) 80%, + rgba(0, 0, 0, 0.5) 90%, + transparent 100% + ); +} + +/* Grid - Position adjusted for 120% container, with top fade */ +.bending-grid { + position: absolute; + width: 250%; + height: 800%; + left: -75%; + top: 25%; /* Positioned just below AI text input */ + background-image: + linear-gradient(rgba(99, 102, 241, 0.25) 1px, transparent 1px), + linear-gradient(90deg, rgba(99, 102, 241, 0.25) 1px, transparent 1px); background-size: 20px 20px; - - /* Mask using the gradient - grid fades in/out */ - mask: linear-gradient(to top, - transparent 35%, /* invisible at bottom */ - black 56%, /* fully visible starts */ - black 78%, /* fully visible ends */ - transparent 97% /* invisible at top */ + transform-origin: center top; + /* Fade out top edge of grid pattern */ + mask-image: linear-gradient( + to bottom, + transparent 0%, + rgba(0, 0, 0, 0.1) 1%, + rgba(0, 0, 0, 0.3) 2%, + rgba(0, 0, 0, 0.6) 3%, + rgba(0, 0, 0, 0.9) 4%, + black 5% ); - -webkit-mask: linear-gradient(to top, - transparent 35%, - black 56%, - black 78%, - transparent 97% + -webkit-mask-image: linear-gradient( + to bottom, + transparent 0%, + rgba(0, 0, 0, 0.1) 1%, + rgba(0, 0, 0, 0.3) 2%, + rgba(0, 0, 0, 0.6) 3%, + rgba(0, 0, 0, 0.9) 4%, + black 5% + ); +} + +/* Top fade - Absolute positioning within hero */ +.grid-fade-top { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 70%; + background: linear-gradient( + to bottom, + white 0%, + white 20%, + rgba(255, 255, 255, 0.98) 40%, + rgba(255, 255, 255, 0.92) 55%, + rgba(255, 255, 255, 0.8) 70%, + rgba(255, 255, 255, 0.5) 85%, + transparent 100% ); - pointer-events: none; - border-radius: inherit; + z-index: 2; +} + +/* Side fades - Absolute positioning within hero */ +.grid-fade-sides { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: + linear-gradient(to right, white 0%, transparent 20%, transparent 80%, white 100%); + pointer-events: none; + z-index: 2; } \ No newline at end of file diff --git a/src/index.njk b/src/index.njk index 325a110777..e4e674464b 100644 --- a/src/index.njk +++ b/src/index.njk @@ -54,6 +54,12 @@ hubspot: ---
+ +
+
+
+
+
@@ -63,7 +69,7 @@ hubspot:

{{ site.messaging.subtitle | replace("-", "‑") | safe }}

- + {% include "components/ai-chat-interface.njk" %} @@ -73,9 +79,9 @@ hubspot:
Or get a quick look at FlowFuse in 90 seconds
- diff --git a/src/js/bending-grid.js b/src/js/bending-grid.js new file mode 100644 index 0000000000..fc6d09b2cb --- /dev/null +++ b/src/js/bending-grid.js @@ -0,0 +1,35 @@ +const grid = document.getElementById('hero-grid'); +const fadeTop = document.getElementById('grid-fade-top'); + +if (grid && fadeTop) { + // Configuration - Only rotation animation + const config = { + startRotateX: 75, // More angled at start + endRotateX: 0, + scrollDistance: 30, + startFadeHeight: 42, + endFadeHeight: 8, + }; + + function lerp(start, end, progress) { + return start + (end - start) * progress; + } + + function updateGrid() { + const scrollY = window.scrollY; + const vh = window.innerHeight; + + const progress = Math.min(scrollY / (vh * (config.scrollDistance / 100)), 1); + + const rotateX = lerp(config.startRotateX, config.endRotateX, progress); + const fadeHeight = lerp(config.startFadeHeight, config.endFadeHeight, progress); + + // ONLY rotate angle - no position changes + grid.style.transform = `rotateX(${rotateX}deg)`; + + fadeTop.style.height = `${fadeHeight}%`; + } + + window.addEventListener('scroll', updateGrid, { passive: true }); + updateGrid(); +}