/* =================================================================
   PERFORMANCE PASS (Emil, animation-performance)
   Causes found by frame probe at 1440x900 (before): hero load 23fps,
   expertise 18fps (53% janky frames), ring 26fps.
   ================================================================= */

/* 1. Hero: hold text hidden until fonts are in, then reveal (no font-swap reflow mid-animation) */
.pre .hero-h .w>span{transform:translateY(110%)}
.pre .kicker-row,.pre .hero-sub,.pre .hero-foot,.pre .nav>*,.pre .stage .bar{opacity:0}

/* 2. Huge blurred blobs were repainting every frame: bake them into one static gradient layer */
.blob{display:none!important}
.bg{background:radial-gradient(45% 55% at 8% 12%,rgba(223,230,255,.9),transparent 70%),radial-gradient(40% 45% at 92% 82%,rgba(255,240,184,.75),transparent 70%)}

/* 3. will-change only on what actually moves continuously */
.w>span{will-change:auto}
.res-item{will-change:auto}

/* 4. Highlight sweeps: a scaled underlay (compositor) instead of animating background-size (paint) */
.hl,.hl-g{position:relative;background:none!important;isolation:isolate}
.hl::before,.hl-g::before{content:"";position:absolute;left:0;right:0;z-index:-1;transform-origin:left center;transform:scaleX(var(--hlx,1));pointer-events:none}
.hl::before{top:56%;bottom:6%;background:var(--hl)}
.hl-g::before{top:0;bottom:0;background:var(--mint);border-radius:.08em}
.sec .hl::before,.quote .hl::before,.hl-g::before{transform:scaleX(0);transition:transform .9s cubic-bezier(.77,0,.175,1)}
.sec .hl.lit::before,.quote .hl.lit::before,.hl-g.lit::before{transform:scaleX(1)}

/* 5. Expertise cards: no transition-delay chains, no gradient bars repainting, cheaper shadows */
.card{box-shadow:0 1px 2px rgba(17,17,16,.05),0 8px 20px -12px rgba(17,17,16,.18)}
.viz-bars i{background:#6b74ff;transition:transform .7s cubic-bezier(.23,1,.32,1)}
.viz-bars i:last-of-type{background:var(--green)}
.viz-bars i:nth-child(n){transition-delay:0s}
.card.in .viz-bars i:nth-child(2){transition-delay:.04s}.card.in .viz-bars i:nth-child(3){transition-delay:.08s}
.card.in .viz-bars i:nth-child(4){transition-delay:.12s}.card.in .viz-bars i:nth-child(5){transition-delay:.16s}.card.in .viz-bars i:nth-child(6){transition-delay:.2s}
.gauge .g{transition:stroke-dashoffset 1s cubic-bezier(.23,1,.32,1)}
.ph .cta{animation:none}
.card.in .ph .cta{animation:nudge 2.4s 1s infinite}
@media (hover:hover) and (pointer:fine){ .card:hover{box-shadow:0 1px 2px rgba(17,17,16,.05),0 18px 34px -16px rgba(17,17,16,.26)} }

/* 6. Ring section: the full-viewport mix-blend grain and 120vmax waves were the heavy paint */
.ring::before{mix-blend-mode:normal;opacity:.06}
.stage-end::after{mix-blend-mode:normal;opacity:.06}
.waves i{width:80vmax;height:80vmax;left:-40vmax;top:-40vmax;will-change:transform,opacity}
.waves i:nth-child(n+4){display:none}
.ring::after{-webkit-mask:none;mask:none;opacity:.6}
.caller-av i{will-change:transform,opacity}

/* 7. Pause decorative loops when their section is off-screen (JS toggles .off) */
.off .waves i,.off .caller-av i,.off .accept,.off .mq-track,.off .ph .cta{animation-play-state:paused!important}

/* 8. Fix: experience heading sized to its column (id rule was overriding) */
@media (min-width:1000px){
  #experience .xp-head .sec-h{font-size:clamp(46px,4.8vw,92px)!important}
}

html{scroll-behavior:auto}
@media (prefers-reduced-motion:no-preference){ html:focus-within{scroll-behavior:smooth} }

/* story asleep (off-screen): skip paint + compositing of its giant layers */
.stage-in.asleep{visibility:hidden}
.stage-in.asleep *{animation-play-state:paused!important}
.stage-in.asleep .zoom,.stage-in.asleep .stage-end{display:none}
.zoom{will-change:transform}

/* reveal: compositor-only, driven by one IntersectionObserver */
.rv{opacity:0;transform:translate3d(0,22px,0);transition:opacity .6s cubic-bezier(.23,1,.32,1),transform .6s cubic-bezier(.23,1,.32,1)}
.rv.rv-in{opacity:1;transform:none}
.card.rv:hover{transition-delay:0s!important}

/* expertise: one move per card, visuals start after the card lands, no long transition chains */
.card.rv{transition:opacity .45s cubic-bezier(.23,1,.32,1),transform .45s cubic-bezier(.23,1,.32,1)}
.card .viz *{transition:none!important}
.card.viz-go .viz-bars i{transition:transform .6s cubic-bezier(.23,1,.32,1)!important}
.card.viz-go .gauge .g{transition:stroke-dashoffset .8s cubic-bezier(.23,1,.32,1)!important}
.card.in:not(.viz-go) .viz-bars i{--bv:0}
.card.in:not(.viz-go) .gauge{--gv:0}
.card.viz-go .viz-bars i{--bv:1}
.card.viz-go .gauge{--gv:.98}
.viz-bars i{transition-delay:0s!important}
/* hover lift only for real pointers, transform only */
@media (hover:hover) and (pointer:fine){ .card{transition:transform .35s cubic-bezier(.23,1,.32,1),opacity .45s cubic-bezier(.23,1,.32,1)} .card:hover{box-shadow:inherit} }
/* skeleton shimmer + scroll cue: only run while the hero/story is on screen */
.stage-in.asleep .skel i,.stage-in.asleep .scroll-cue i::after{animation:none}

/* ring: the big ripple circles become one tiny scaled ring (no huge border repaint) */
.waves{left:28%;top:46%}
.waves i{width:240px!important;height:240px!important;left:-120px!important;top:-120px!important;border:1.5px solid rgba(127,240,180,.22);
  animation:wave2 6s cubic-bezier(.23,1,.32,1) infinite}
.waves i:nth-child(2){animation-delay:2s}.waves i:nth-child(3){animation-delay:4s}
@keyframes wave2{0%{transform:scale(.3);opacity:0}15%{opacity:1}100%{transform:scale(4.2);opacity:0}}
@media (max-width:899px){ .waves{left:50%;top:22%} }
/* call log: slide the list, no per-row layout */
.call-log{contain:layout paint}
.call-log li{will-change:auto}
.log{contain:paint}
.phone-frame{contain:layout paint}

/* below-the-fold sections: skip layout + paint until they are near the viewport */
.ring,.marquee,#about,#expertise,#experience,#work,.nums-sec,.contact{content-visibility:auto;contain-intrinsic-size:auto 1000px}

/* highlight v2: background on the inline box itself (wraps correctly across lines);
   one-time sweep via background-size transition, then static */
.hl,.hl-g{position:static;isolation:auto}
.hl::before,.hl-g::before{content:none!important;display:none!important}
.hl{background:linear-gradient(transparent 58%,var(--hl) 58%,var(--hl) 94%,transparent 94%) 0 0/100% 100% no-repeat!important;-webkit-box-decoration-break:clone;box-decoration-break:clone}
.hl-g{background:linear-gradient(var(--mint),var(--mint)) 0 0/100% 100% no-repeat!important;-webkit-box-decoration-break:clone;box-decoration-break:clone}
.sec .hl,.quote .hl,.hl-g{background-size:0% 100%!important;transition:background-size .9s cubic-bezier(.77,0,.175,1)}
.sec .hl.lit,.quote .hl.lit,.hl-g.lit{background-size:100% 100%!important}
/* race: the lead number leads, position is secondary context */
.lane-n b{color:var(--mint)}
.lane-n span{font-size:13px}
