patx/afterdarklabs

fix mobile reveals indexerd

Commit ceb0356 · patx · 2026-09-03T17:48:06-04:00

Changeset
ceb0356d04aa730535252962020f4849526deef6
Parents
eff345fa2f81a17018b2de59d8624a75866f9d48

View source at this commit

Comments

No comments yet.

Log in to comment

Diff

diff --git a/docs/indexerd.html b/docs/indexerd.html
index c113031..03a7e4e 100644
--- a/docs/indexerd.html
+++ b/docs/indexerd.html
@@ -63,7 +63,13 @@
             --site-nav-height: 5.75rem;
         }
 
-        html { scroll-behavior: smooth; }
+        html {
+            max-width: 100%;
+            overflow-x: hidden;
+            overflow-x: clip;
+            overscroll-behavior-x: none;
+            scroll-behavior: smooth;
+        }
 
         @media (min-width: 1024px) {
             :root {
@@ -91,10 +97,19 @@
         }
 
         body {
+            max-width: 100%;
+            overflow-x: hidden;
+            overflow-x: clip;
+            overscroll-behavior-x: none;
             background: var(--page-bg);
             font-family: 'Ubuntu', system-ui, sans-serif;
         }
 
+        nav {
+            -webkit-backdrop-filter: none !important;
+            backdrop-filter: none !important;
+        }
+
         .heading,
         .logo-font { font-family: inherit; color: #fff; }
 
@@ -530,6 +545,7 @@
             gap: clamp(0.3rem, 0.6vw, 0.65rem);
             overflow: visible;
             padding: 0;
+            touch-action: pan-y pinch-zoom;
         }
 
         #work-scroller > article {
@@ -644,6 +660,10 @@
                 skewY(var(--card-skew, 0deg))
                 scale(var(--card-scale-x, 0.94), var(--card-scale-y, 1.04));
             transform-origin: center bottom;
+            will-change: auto;
+        }
+
+        .portfolio-scroll-ready #work-scroller > article.is-card-animating {
             will-change: opacity, filter, transform;
         }
 
@@ -667,7 +687,7 @@
             }
         }
 
-        @media (max-width: 767px) {
+        @media (hover: none), (pointer: coarse) {
             #work-scroller > article {
                 cursor: pointer;
             }
@@ -675,6 +695,15 @@
             #work-scroller > article.is-description-visible {
                 cursor: default;
             }
+
+            .portfolio-scroll-ready #work-scroller > article {
+                filter: none;
+            }
+
+            #work-scroller > article > .portfolio-details {
+                -webkit-backdrop-filter: none;
+                backdrop-filter: none;
+            }
         }
 
         @media (prefers-reduced-motion: reduce) {
@@ -1175,8 +1204,12 @@
             if (!cards.length) return;
 
             const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
-            const mobileLayout = window.matchMedia('(max-width: 767px)');
+            const touchDisclosure = window.matchMedia('(hover: none), (pointer: coarse)');
             let cardTops = [];
+            let cardStates = cards.map(() => -1);
+            let layoutWidth = 0;
+            let layoutHeight = 0;
+            let lastScrollY = -1;
             let updateFrame = 0;
             let resizeFrame = 0;
 
@@ -1227,14 +1260,28 @@
 
             function updateCards() {
                 updateFrame = 0;
-                if (reduceMotion.matches) return;
+                if (reduceMotion.matches) {
+                    cards.forEach(card => card.classList.remove('is-card-animating'));
+                    return;
+                }
 
-                const viewportHeight = window.visualViewport?.height || window.innerHeight;
+                const scrollY = Math.max(0, window.scrollY);
+                const viewportHeight = layoutHeight || document.documentElement.clientHeight || window.innerHeight;
+                if (scrollY === lastScrollY) return;
+
+                lastScrollY = scrollY;
                 const revealDistance = Math.max(240, viewportHeight * 0.58);
-                const travelX = Math.min(72, window.innerWidth * 0.06);
+                const travelX = Math.min(72, document.documentElement.clientWidth * 0.06);
 
                 cards.forEach((card, index) => {
-                    const progress = clamp((window.scrollY + viewportHeight * 0.94 - cardTops[index]) / revealDistance);
+                    const progress = clamp((scrollY + viewportHeight * 0.94 - cardTops[index]) / revealDistance);
+                    const state = progress <= 0 ? 0 : progress >= 1 ? 1 : 2;
+                    if (cardStates[index] !== state) {
+                        card.classList.toggle('is-card-animating', state === 2);
+                    }
+                    if (state !== 2 && cardStates[index] === state) return;
+
+                    cardStates[index] = state;
                     const eased = 1 - Math.pow(1 - progress, 3);
                     const remaining = 1 - eased;
                     const direction = index % 2 === 0 ? -1 : 1;
@@ -1261,7 +1308,20 @@
 
             function measureCards() {
                 resizeFrame = 0;
+                const nextLayoutWidth = document.documentElement.clientWidth;
+                const nextLayoutHeight = document.documentElement.clientHeight || window.innerHeight;
+                const widthChanged = Math.abs(nextLayoutWidth - layoutWidth) >= 2;
+                const desktopHeightChanged = !touchDisclosure.matches && Math.abs(nextLayoutHeight - layoutHeight) >= 2;
+                if (layoutWidth && !widthChanged && !desktopHeightChanged) {
+                    scheduleCardUpdate();
+                    return;
+                }
+
+                layoutWidth = nextLayoutWidth;
+                layoutHeight = nextLayoutHeight;
                 cardTops = cards.map(getDocumentTop);
+                cardStates = cards.map(() => -1);
+                lastScrollY = -1;
                 fitDescriptions();
                 updateCards();
             }
@@ -1274,6 +1334,11 @@
                 if (!resizeFrame) resizeFrame = window.requestAnimationFrame(measureCards);
             }
 
+            function scheduleCardRemeasure() {
+                layoutWidth = 0;
+                scheduleCardMeasure();
+            }
+
             function closeDescriptions(exceptCard = null) {
                 cards.forEach(card => {
                     if (card !== exceptCard) card.classList.remove('is-description-visible');
@@ -1282,7 +1347,7 @@
 
             cards.forEach(card => {
                 card.addEventListener('click', event => {
-                    if (!mobileLayout.matches || event.target.closest('.portfolio-live-link')) return;
+                    if (!touchDisclosure.matches || event.target.closest('.portfolio-live-link')) return;
 
                     closeDescriptions(card);
                     card.classList.add('is-description-visible');
@@ -1290,21 +1355,21 @@
             });
 
             document.addEventListener('pointerdown', event => {
-                if (!mobileLayout.matches || event.target.closest('#work-scroller > article')) return;
+                if (!touchDisclosure.matches || event.target.closest('#work-scroller > article')) return;
                 closeDescriptions();
                 const activeCard = document.activeElement?.closest?.('#work-scroller > article');
                 if (activeCard) document.activeElement.blur();
             }, { passive: true });
 
-            mobileLayout.addEventListener('change', () => closeDescriptions());
+            touchDisclosure.addEventListener('change', () => closeDescriptions());
 
             section.classList.add('portfolio-scroll-ready');
             window.addEventListener('scroll', scheduleCardUpdate, { passive: true });
             window.addEventListener('resize', scheduleCardMeasure);
             window.visualViewport?.addEventListener('resize', scheduleCardMeasure);
-            window.addEventListener('pageshow', scheduleCardMeasure);
-            reduceMotion.addEventListener('change', scheduleCardMeasure);
-            document.fonts?.ready.then(scheduleCardMeasure);
+            window.addEventListener('pageshow', scheduleCardRemeasure);
+            reduceMotion.addEventListener('change', scheduleCardRemeasure);
+            document.fonts?.ready.then(scheduleCardRemeasure);
             measureCards();
         })();