{"version":3,"file":"SectionAppear.6M5-Yerr.mjs","names":["useRef","useRef","__esmMin","init_npm_react_18_3_1","init_ssg_sandbox_shims","window","c","init_jsx_runtime","ce","de","animate","init_framer_motion_DhsWWWsN","clamp","a","b","v","withScrollStack","ref","vp","section","raf","visible","apply","cards","n","rect","vh","total","p","isMobile","slot","s","localP","DWELL","k","frac","adv","UNCOVER","blurI","EXIT","PEEK","card","i","bel","el","y","scale","blur","depth","MAX_DEPTH","SCALE_STEP","MAX_BLUR","blurEl","on","schedule","io","entries","snapT","doSnap","tot","best","bestP","ps","targetTop","targetScrollY","onScrollSnap","Component","props","init_ScrollStackOverride","withAppear","done","run","t","init_SectionAppear"],"sources":["https:/framerusercontent.com/modules/7AgdL8mG7NzftzUT2vuk/h5abSVKAn5A4VR3E3PoN/ScrollStackOverride.js","https:/framerusercontent.com/modules/ePTw7eMIb0Hlwo9CzNQE/EKJ7MQysELelATIMUF05/SectionAppear.js"],"sourcesContent":["import{jsx as _jsx}from\"react/jsx-runtime\";import{useEffect,useRef}from\"react\";function clamp(v,a,b){return Math.max(a,Math.min(b,v));}// Scroll-glued card cascade (mimics the reference video, flipped to move UP).\n// Front card centered; the rest peek out below it, slightly scaled down (that\n// scaled, receding stack is the \"3D depth\"). The front card slides up-and-out;\n// the NEXT card HOLDS in place until the front one has fully uncovered it, then\n// it gets dragged up into the front. Flat cards, no rotation, no fade; every\n// card eventually leaves (the section empties before the next section).\nconst PEEK=6// % of card height between stacked cards (peek out the bottom)\n;const SCALE_STEP=.05// each card further back is this much smaller\n;const MAX_DEPTH=6;const MAX_BLUR=3// px — slight blur on stacked (not-yet-uncovered) cards\n;const EXIT=145// % of card height a leaving card travels up\n;const UNCOVER=.65// fraction of the front card's exit before the next is dragged up\n;// (by here the front card has slid completely off the next one)\nconst DWELL=.5// MOBILE only: fraction of each card's scroll slot it holds fully\n;// displayed at the front before it starts flipping to the next\nexport function withScrollStack(Component){return props=>{const ref=useRef(null);useEffect(()=>{const vp=ref.current;if(!vp)return;vp.style.position=\"sticky\";vp.style.top=\"0px\";const section=vp.closest('[data-framer-name=\"Portfolio Stack\"]')||vp.parentElement;let raf=0;let visible=false;const apply=()=>{raf=0;const cards=vp.querySelectorAll('[data-framer-name=\"StackCard\"]');const n=cards.length;if(n===0)return;// progress while the viewport is pinned, so the cascade (incl. the\n// last card settling to center) plays before the section releases.\nconst rect=section.getBoundingClientRect();const vh=window.innerHeight||800;const total=rect.height-vh;const p=total>0?clamp(-rect.top/total,0,1):0;// MOBILE: kill the (expensive) blur filters and add a \"dwell\" so each\n// card holds fully-displayed at the front before the next one flips.\nconst isMobile=(typeof window!==\"undefined\"?window.innerWidth:1e3)<=809;let a// \"active\" pointer, 0..n\n;if(isMobile){// each card gets a slot; the first DWELL of it holds the card at\n// the front, the rest flips it to the next\nconst slot=p*n;const s=Math.min(Math.floor(slot),n-1);const localP=slot-s;a=localP<DWELL?s:s+(localP-DWELL)/(1-DWELL);}else{a=p*n;}const k=Math.floor(a)// index of the card currently exiting from the front\n;const frac=a-k// 0..1 through that card's exit\n;// the stack behind holds, then advances one slot once the front\n// card has fully uncovered the next one\nconst adv=frac<UNCOVER?0:(frac-UNCOVER)/(1-UNCOVER);// card nearest center carries the progressive blur\nconst yFront=frac*EXIT;const yNext=(1-adv)*PEEK;let blurI=yFront<=yNext?k:k+1;if(blurI>=n)blurI=n-1;cards.forEach((card,i)=>{const c=card;if(card.dataset.ssInit!==\"1\"){card.style.position=\"absolute\";card.style.top=\"0\";card.style.left=\"0\";card.style.width=\"100%\";card.style.height=\"100%\";card.style.zIndex=String(n-i);card.style.transformOrigin=\"center center\";card.style.transition=\"none\";card.style.opacity=\"1\";card.style.filter=\"none\";let bel=card.querySelector('[data-framer-name=\"ProgressiveBlur\"]');if(!bel){for(const el of Array.from(card.querySelectorAll(\"*\"))){if(getComputedStyle(el).backdropFilter!==\"none\"){bel=el;break;}}}c._ssBlur=bel;c._ssBlurOn=null;card.dataset.ssInit=\"1\";}let y;let scale;let blur=0// covered (stacked) cards are slightly blurry; clears\n;// to 0 as a card advances to the (uncovered) front\nif(i===n-1&&a>=n-1){// last card: once fully uncovered it STAYS centered (no\n// cascade-exit); it just scrolls up with the section as the\n// next section arrives\ny=0;scale=1;}else if(i<k){// already gone (further up)\ny=-(a-i)*EXIT;scale=1;}else if(i===k){// current front card: sliding straight up and out\ny=-frac*EXIT;scale=1;}else{// behind the front: holds at its slot, then the whole stack\n// advances one slot (each card's depth drops by `adv`)\nconst depth=i-k-adv;y=depth*PEEK;scale=1-clamp(depth,0,MAX_DEPTH)*SCALE_STEP;// full slight blur while stacked (depth>=1), fading to 0 as the\n// card is uncovered and advances to the front (depth -> 0).\n// Disabled on mobile — filter blur is too heavy there.\nblur=isMobile?0:clamp(depth,0,1)*MAX_BLUR;}card.style.transform=`translate3d(0, ${y}%, 0) scale(${scale})`;card.style.filter=blur>.05?`blur(${blur}px)`:\"none\";const blurEl=c._ssBlur;if(blurEl){// progressive (backdrop-filter) blur is the biggest mobile\n// perf cost — keep it off entirely on mobile\nconst on=!isMobile&&i===blurI;if(c._ssBlurOn!==on){blurEl.style.display=on?\"\":\"none\";c._ssBlurOn=on;}}});};const schedule=()=>{if(!visible||raf)return;raf=requestAnimationFrame(apply);};const io=new IntersectionObserver(entries=>{visible=entries[0].isIntersecting;if(visible)schedule();},{rootMargin:\"200px 0px 200px 0px\"});io.observe(section);window.addEventListener(\"scroll\",schedule,{passive:true});window.addEventListener(\"resize\",schedule);// MOBILE: snap to the nearest card's resting spot when scrolling stops\nlet snapT;const doSnap=()=>{const mob=(typeof window!==\"undefined\"?window.innerWidth:1e3)<=809;if(!mob)return;const cards=vp.querySelectorAll('[data-framer-name=\"StackCard\"]');const n=cards.length;if(!n)return;const rect=section.getBoundingClientRect();const vh=window.innerHeight||800;const tot=rect.height-vh;if(tot<=0)return;const p=clamp(-rect.top/tot,0,1);// each card rests around the centre of its dwell\nlet best=0;let bestP=DWELL/2/n;for(let s=0;s<n;s++){const ps=(s+DWELL/2)/n;if(Math.abs(ps-p)<Math.abs(bestP-p)){best=s;bestP=ps;}}// let the user scroll OUT of the section in either direction\nif(best===n-1&&p>bestP)return;if(best===0&&p<bestP)return;const targetTop=-bestP*tot;const targetScrollY=window.scrollY+rect.top-targetTop;if(Math.abs(targetScrollY-window.scrollY)<2)return;window.scrollTo({top:targetScrollY,behavior:\"smooth\"});};const onScrollSnap=()=>{if(snapT)clearTimeout(snapT);snapT=setTimeout(doSnap,140);};window.addEventListener(\"scroll\",onScrollSnap,{passive:true});apply();return()=>{io.disconnect();window.removeEventListener(\"scroll\",schedule);window.removeEventListener(\"resize\",schedule);window.removeEventListener(\"scroll\",onScrollSnap);if(snapT)clearTimeout(snapT);if(raf)cancelAnimationFrame(raf);};},[]);return /*#__PURE__*/_jsx(Component,{ref:ref,...props});};}\nexport const __FramerMetadata__ = {\"exports\":{\"withScrollStack\":{\"type\":\"reactHoc\",\"name\":\"withScrollStack\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./ScrollStackOverride.map","import{jsx as _jsx}from\"react/jsx-runtime\";import{useEffect,useRef}from\"react\";import{animate}from\"framer-motion\";// Entrance for the portfolio-stack cards: rise up from below + dissolve in +\n// un-blur, with a slight delay. Fires once, when the cards first come into view.\n// Animates the component's own element (no wrapper — wrapping broke the layout),\n// and drops the filter when done so it can't interfere with the progressive blur.\nexport function withAppear(Component){return props=>{const ref=useRef(null);useEffect(()=>{const el=ref.current;if(!el)return;// mobile: drop the blur (filter animation is heavy) — dissolve + rise only\nconst isMobile=(typeof window!==\"undefined\"?window.innerWidth:1e3)<=809;// start hidden (below, blurred, transparent)\nel.style.opacity=\"0\";if(!isMobile)el.style.filter=\"blur(16px)\";el.style.transform=\"translateY(70px)\";el.style.willChange=\"opacity, transform\";let done=false;const run=()=>{if(done)return;done=true;const target=isMobile?{opacity:[0,1],y:[70,0]}:{opacity:[0,1],y:[70,0],filter:[\"blur(16px)\",\"blur(0px)\"]};animate(el,target,{duration:isMobile?.8:1,delay:.35,ease:[.16,1,.3,1]}).then(()=>{if(!isMobile)el.style.filter=\"none\";el.style.willChange=\"auto\";});};let io=null;if(typeof IntersectionObserver!==\"undefined\"){io=new IntersectionObserver(entries=>{if(entries.some(e=>e.isIntersecting)){io&&io.disconnect();run();}},{threshold:.25});io.observe(el);}else{run();}// safety: never stay hidden forever if the observer never fires\nconst t=setTimeout(run,5e3);return()=>{io&&io.disconnect();clearTimeout(t);};},[]);return /*#__PURE__*/_jsx(Component,{ref:ref,...props});};}\nexport const __FramerMetadata__ = {\"exports\":{\"withAppear\":{\"type\":\"reactHoc\",\"name\":\"withAppear\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./SectionAppear.map"],"mappings":"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"}