{"version":3,"file":"StackFade.inHDzOfx.mjs","names":["useRef","useState"],"sources":["https:/framerusercontent.com/modules/VDENeIGRDe393vheHp7X/jhbIKQRsBQOnxDtFXktE/StackFade.js"],"sourcesContent":["import{jsx as _jsx}from\"react/jsx-runtime\";import{forwardRef,useEffect,useRef,useState}from\"react\";/**\n * Sticky stacking-card effect (solid white \"behind\" state — no transparency).\n *\n * Each card is `position: sticky`. As the NEXT sticky card scrolls up to cover\n * the current one, the current card:\n *   - stays fully OPAQUE (never see-through) on a solid white base,\n *   - scales down slightly and lifts (so it reads as sitting \"behind\"),\n *   - fades its own CONTENTS away, revealing the solid white card beneath —\n *     so the scrolled-past card becomes a clean white card in the back while\n *     the front card stays fully readable.\n *\n * Self-tuning: it finds the next sticky sibling and reads that card's own `top`\n * from the DOM, so the same override works on any sticky stack. A card with no\n * following sticky sibling (the last/front card) is left fully intact.\n *\n *   coverRatio = the recede animation plays out over (coverRatio * next card's\n *   own rendered height) px of scroll. This makes the transition distance scale\n *   with however tall cards actually render at the current breakpoint/viewport,\n *   instead of a fixed pixel value — so Desktop, Tablet, and Phone all get a\n *   transition that takes a consistent amount of reading time, since a bigger\n *   rendered card takes more scroll to fully cover, and a small one takes less.\n *\n *   minCover/maxCover clamp the computed distance so it can't collapse to ~0 on\n *   very short cards or stretch absurdly long on very tall ones.\n */function recede(Component,coverRatio=.6,minCover=160,maxCover=600){return /*#__PURE__*/forwardRef((props,ref)=>{const elRef=useRef(null);const raf=useRef(0);const[s,setS]=useState(1);const[ty,setTy]=useState(0);useEffect(()=>{// Fade the card's direct children (image, text, background art) to\n// reveal the solid white card root underneath.\nconst setContents=v=>{const el=elRef.current;if(!el)return;const kids=el.children;for(let i=0;i<kids.length;i++){kids[i].style.opacity=String(v);}};const reset=()=>{setS(1);setTy(0);setContents(1);};const update=()=>{const el=elRef.current;if(!el)return;// Find the next sticky sibling — the card that covers this one.\nlet next=el.nextElementSibling;while(next&&getComputedStyle(next).position!==\"sticky\"){next=next.nextElementSibling;}if(!next){reset()// last/front card — stays fully intact\n;return;}let nextPinTop=parseFloat(getComputedStyle(next).top);if(!isFinite(nextPinTop))nextPinTop=0;const nextRect=next.getBoundingClientRect();const nextTop=nextRect.top;// Scale the transition distance to how tall the next card\n// actually renders at this viewport/breakpoint, instead of a\n// fixed px value — so timing stays consistent across Desktop,\n// Tablet, and Phone regardless of how content wraps.\nconst cover=Math.max(minCover,Math.min(maxCover,nextRect.height*coverRatio));// p = 0 when the next card is `cover` px below its pin line,\n// p = 1 when the next card reaches its pin (fully covering this card).\nconst p=Math.max(0,Math.min(1,(nextPinTop+cover-nextTop)/cover));// easeInOut cubic for a soft transition\nconst e=p<.5?4*p*p*p:1-Math.pow(-2*p+2,3)/2;setS(1-e*.08)// shrink up to 8% (sits \"behind\")\n;setTy(-e*28)// lift up to 28px\n;setContents(1-e)// contents fade -> reveals solid white card\n;};const onScroll=()=>{cancelAnimationFrame(raf.current);raf.current=requestAnimationFrame(update);};window.addEventListener(\"scroll\",onScroll,{passive:true});window.addEventListener(\"resize\",onScroll);update();return()=>{window.removeEventListener(\"scroll\",onScroll);window.removeEventListener(\"resize\",onScroll);cancelAnimationFrame(raf.current);};},[]);return /*#__PURE__*/_jsx(Component,{...props,ref:n=>{elRef.current=n;if(typeof ref===\"function\")ref(n);else if(ref)ref.current=n;},style:{...props.style||{},opacity:1,backgroundColor:\"#ffffff\",transform:`translateY(${ty}px) scale(${s})`,transformOrigin:\"center top\",willChange:\"transform\"}});});}// withStackFade1–3 are identical, self-tuning recede overrides for any non-last\n// card in a sticky stack.\nexport function withStackFade1(Component){return recede(Component);}export function withStackFade2(Component){return recede(Component);}export function withStackFade3(Component){return recede(Component);}// Last/front card in a stack — no animation, but it gets the SAME solid white,\n// fully-opaque base as the others so it can never look transparent.\nexport function withStackFade4(Component){return /*#__PURE__*/forwardRef((props,ref)=>{return /*#__PURE__*/_jsx(Component,{...props,ref:ref,style:{...props.style||{},opacity:1,backgroundColor:\"#ffffff\"}});});}\nexport const __FramerMetadata__ = {\"exports\":{\"withStackFade2\":{\"type\":\"reactHoc\",\"name\":\"withStackFade2\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withStackFade1\":{\"type\":\"reactHoc\",\"name\":\"withStackFade1\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withStackFade4\":{\"type\":\"reactHoc\",\"name\":\"withStackFade4\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withStackFade3\":{\"type\":\"reactHoc\",\"name\":\"withStackFade3\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./StackFade.map"],"mappings":"qJAwBG,SAAS,EAAO,EAAU,EAAW,GAAG,EAAS,IAAI,EAAS,IAAI,CAAC,OAAoB,GAAY,EAAM,IAAM,CAAC,IAAM,EAAMA,EAAO,IAAI,EAAQ,EAAIA,EAAO,CAAC,EAAO,CAAC,EAAE,GAAMC,EAAS,CAAC,EAAO,CAAC,EAAG,GAAOA,EAAS,CAAC,EAcgJ,OAd9I,MAAc,CAEpO,IAAM,EAAY,GAAG,CAAC,IAAM,EAAG,EAAM,QAAQ,GAAG,CAAC,EAAG,OAAO,IAAM,EAAK,EAAG,SAAS,IAAI,IAAI,EAAE,EAAE,EAAE,EAAK,OAAO,IAAK,EAAK,EAAE,CAAC,MAAM,QAAQ,OAAO,CAAC,CAAG,EAAQ,MAAU,CAAC,EAAK,CAAC,EAAE,EAAM,CAAC,EAAE,EAAY,CAAC,CAAE,EAAQ,MAAW,CAAC,IAAM,EAAG,EAAM,QAAQ,GAAG,CAAC,EAAG,OACvP,IAAI,EAAK,EAAG,mBAAmB,KAAM,GAAM,iBAAiB,CAAI,CAAC,CAAC,WAAW,UAAU,EAAK,EAAK,mBAAoB,GAAG,CAAC,EAAK,CAAC,EAAM,EACpI,MAAO,CAAC,IAAI,EAAW,WAAW,iBAAiB,CAAI,CAAC,CAAC,GAAG,EAAM,SAAS,CAAU,IAAE,EAAW,GAAE,IAAM,EAAS,EAAK,sBAAsB,EAAQ,EAAQ,EAAS,IAIlK,EAAM,KAAK,IAAI,EAAS,KAAK,IAAI,EAAS,EAAS,OAAO,CAAU,CAAC,EAErE,EAAE,KAAK,IAAI,EAAE,KAAK,IAAI,GAAG,EAAW,EAAM,GAAS,CAAK,CAAC,EACzD,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,GAAW,GAAG,EAAE,IAAE,EAAG,EAAE,EAAK,EAAE,EAAE,GAAG,EACvD,EAAM,CAAC,EAAE,EAAE,EACX,EAAY,EAAE,CAAC,CACf,EAAQ,MAAa,CAAC,qBAAqB,EAAI,OAAO,EAAE,EAAI,QAAQ,sBAAsB,CAAM,CAAE,EAAgH,OAA9G,EAAO,iBAAiB,SAAS,EAAS,CAAC,QAAQ,EAAI,CAAC,EAAE,EAAO,iBAAiB,SAAS,CAAQ,EAAE,EAAO,MAAY,CAAC,EAAO,oBAAoB,SAAS,CAAQ,EAAE,EAAO,oBAAoB,SAAS,CAAQ,EAAE,qBAAqB,EAAI,OAAO,CAAE,CAAE,EAAE,CAAC,CAAC,EAAsB,EAAK,EAAU,CAAC,GAAG,EAAM,IAAI,GAAG,CAAC,EAAM,QAAQ,EAAK,OAAO,GAAM,WAAW,EAAI,CAAC,EAAU,IAAI,EAAI,QAAQ,EAAE,EAAE,MAAM,CAAC,GAAG,EAAM,OAAO,CAAC,EAAE,QAAQ,EAAE,gBAAgB,UAAU,UAAU,cAAc,EAAG,YAAY,EAAE,GAAG,gBAAgB,aAAa,WAAW,WAAW,CAAC,CAAC,CAAE,CAAC,CAAE,CAE3oB,SAAgB,EAAe,EAAU,CAAC,OAAO,EAAO,CAAS,CAAE,CAAC,SAAgB,EAAe,EAAU,CAAC,OAAO,EAAO,CAAS,CAAE,CAAC,SAAgB,EAAe,EAAU,CAAC,OAAO,EAAO,CAAS,CAAE,qBAxCjK,IAAwD"}