/* fx.css — visual effects for Lumen Studio EN (studio.amazstock.online), 08.10.2026.
   Ported from the UA site (deviceforge.shop, fx.css v2) and re-styled for the EN design:
   site tokens only (--paper, --ink, --accent, --brass, --line, --card, --serif, --sans).
   All classes are prefixed fx-. Only transform / opacity are animated.
   prefers-reduced-motion: everything static (plus the site's own global reduce rule).

   Sources & licences (rewritten from scratch in vanilla CSS/JS, no React/Tailwind):
   - Device scroll   — idea of "Container Scroll Animation", Aceternity UI (free component)
   - Tilt covers     — idea of "3D Card Effect", Aceternity UI (free component)
   - Ring sticker    — "Circular Text", Animata (MIT)
   - Hard-shadow CTA — uiverse.io 0xnihilism/fast-cat-82 + quiet-dog-6 (MIT)
   - Odometer        — Magic UI NumberTicker (MIT)
   - Border beam     — Magic UI BorderBeam (MIT)
   - Process beam    — Magic UI AnimatedBeam (MIT)
   - FAQ             — own code on native <details>
   - Flip words      — idea of "Flip Words", Aceternity UI (free component)
   - Sticky screen   — idea of "Sticky Scroll Reveal", Aceternity UI (free component)
   - Peel sticker    — after React Bits "StickerPeel" (MIT + Commons Clause)
   - Words on scroll — after React Bits "ScrollReveal" (MIT + Commons Clause)
   Not ported on purpose: the second (coral) marquee — rejected by the owner on the UA site.
*/

.fx-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}

/* ============ 1. DEVICE SCROLL — #work intro ============ */
.fx-ds{position:relative;overflow:clip}
.fx-ds__sticky{display:flex;flex-direction:column;justify-content:center}
.fx-ds__head{will-change:transform}
.fx-ds__stage{perspective:1000px;width:100%;display:flex;justify-content:center;padding-bottom:clamp(40px,7vh,80px)}
.fx-ds__device{position:relative;width:min(1080px,100%);aspect-ratio:16/10;border-radius:22px;padding:clamp(8px,1vw,12px);
  background:var(--ink);border:2px solid #3b352d;transform-origin:50% 0%;will-change:transform;
  box-shadow:0 9px 20px rgba(26,24,21,.22),0 37px 37px rgba(26,24,21,.18),0 84px 50px rgba(26,24,21,.1)}
.fx-ds__base{position:absolute;left:-6%;right:-6%;top:100%;height:14px;margin-top:3px;border-radius:2px 2px 16px 16px;
  background:linear-gradient(#4a443b,var(--ink));box-shadow:0 18px 30px -14px rgba(26,24,21,.5)}
.fx-ds__base::before{content:"";position:absolute;left:50%;top:0;width:16%;height:5px;margin-left:-8%;border-radius:0 0 8px 8px;background:#0e0d0b}
.fx-ds__screen{position:relative;height:100%;border-radius:12px;overflow:hidden;background:var(--paper2)}
.fx-ds__site{will-change:transform}
.fx-ds__site img{width:100%;height:auto;display:block;max-width:none}
.fx-ds__camera{position:absolute;z-index:2;top:clamp(2px,.4vw,4px);left:50%;width:5px;height:5px;margin-left:-2.5px;border-radius:50%;background:#000;opacity:.7}
/* JS on + motion allowed: the section gets scroll room, the device sticks */
.fx-on .fx-ds{height:280vh}
.fx-on .fx-ds__sticky{position:sticky;top:0;height:100vh;height:100svh;padding:84px 0 24px}
.fx-on .fx-ds__head .shead{padding:0 0 2vh}
.fx-on .fx-ds__head>p{margin:0 0 3vh!important}
.fx-on .fx-ds__stage{padding-bottom:0}
.fx-on .fx-ds__device{width:min(1080px,100%,calc((100vh - 330px)*1.6));transform:rotateX(20deg) scale(1.05)}
@media (max-width:768px){
  .fx-ds__device{aspect-ratio:9/17;width:min(320px,100%);border-radius:36px;padding:8px;margin-bottom:10px}
  .fx-ds__screen{border-radius:29px}
  .fx-ds__base{display:none}
  .fx-ds__camera{top:6px;width:54px;height:15px;margin-left:-27px;border-radius:99px;opacity:1}
  .fx-on .fx-ds{height:260vh}
  .fx-on .fx-ds__sticky{padding:70px 0 18px}
  .fx-on .fx-ds__head .shead{padding:0 0 1.4vh}
  .fx-on .fx-ds__head>p{margin:0 0 2vh!important;font-size:.95rem}
  .fx-on .fx-ds__device{width:min(320px,100%,calc((100svh - 330px)*9/17))}
}
@media (prefers-reduced-motion:reduce){ .fx-ds__device{transform:none!important} }

/* ============ 2. RING STICKER — hero ============ */
header#top{overflow-x:clip}
.fx-ring{position:absolute;z-index:2;right:clamp(28px,8vw,140px);top:clamp(150px,34vh,330px);width:clamp(104px,9.5vw,142px);aspect-ratio:1;
  border-radius:50%;background:var(--accent);color:var(--paper);display:grid;place-items:center;pointer-events:auto;
  box-shadow:0 18px 40px -18px rgba(168,61,31,.6)}
.fx-ring__c{font-family:var(--serif);font-style:italic;font-size:clamp(1.8rem,2.6vw,2.6rem);line-height:1;letter-spacing:-.02em}
.fx-ring__svg{position:absolute;inset:-22%;width:144%;height:144%;pointer-events:none;overflow:visible;
  animation:fx-ring-spin 20s linear infinite;will-change:transform}
.fx-ring__svg text{font-family:var(--sans);font-size:11.5px;font-weight:500;letter-spacing:.06em;fill:var(--ink);text-transform:uppercase}
.fx-ring.is-paused .fx-ring__svg{animation-play-state:paused}
@keyframes fx-ring-spin{to{transform:rotate(360deg)}}
@media (max-width:820px){
  .fx-ring{width:74px;right:calc(4vw + 14px);top:calc(16vh - 40px)}
  .fx-ring__c{font-size:1.45rem}
  .fx-ring__svg text{font-size:13px}
}
@media (prefers-reduced-motion:reduce){ .fx-ring__svg{animation:none} }

/* ============ 3. CTA WITH A HARD SHADOW — contact form button ============
   No markup change: ::before = shadow, ::after = face. The button moves with the
   `translate` property, so it never fights the site's magnetic `transform`. */
.btn.fx-cta{--fx-off:5px;isolation:isolate;border-color:transparent;color:var(--paper);
  transition:color .2s,translate .22s cubic-bezier(.3,1.7,.55,1);-webkit-tap-highlight-color:transparent}
.btn.fx-cta,.btn.fx-cta:hover{background:transparent;border-color:transparent}
.btn.fx-cta::before,.btn.fx-cta::after{content:"";position:absolute;inset:-1px;border-radius:inherit;pointer-events:none}
.btn.fx-cta::before{z-index:-2;background:var(--ink);transform:translate(var(--fx-off),var(--fx-off));transition:transform .22s cubic-bezier(.3,1.7,.55,1),background-color .2s}
.btn.fx-cta::after{z-index:-1;background:var(--accent);border:2px solid var(--ink);transition:background-color .2s}
.btn.fx-cta:hover::after{background:var(--ink)}
.btn.fx-cta:hover::before{background:var(--accent)}
@media (hover:hover){
  .btn.fx-cta:hover{translate:-3px -3px}
  .btn.fx-cta:hover::before{transform:translate(calc(var(--fx-off) + 3px),calc(var(--fx-off) + 3px))}
}
.btn.fx-cta:active{translate:4px 4px;transition-duration:.06s}
.btn.fx-cta:active::before{transform:translate(calc(var(--fx-off) - 4px),calc(var(--fx-off) - 4px));transition-duration:.06s}
.btn.fx-cta:focus-visible{outline:2px solid var(--accent);outline-offset:8px}
@media (prefers-reduced-motion:reduce){ .btn.fx-cta,.btn.fx-cta::before{transition:none} }

/* ============ 4a. ODOMETER — case numbers, $39 ============ */
.fx-odo{display:inline-flex;align-items:flex-end;line-height:1;vertical-align:var(--fx-odo-va,-.06em)}
.fx-odo__d{display:inline-flex;justify-content:center;height:1em;overflow:hidden;position:relative}
.fx-odo__col{display:flex;flex-direction:column;flex:none;transform:translateY(0);
  transition:transform var(--fx-odo-dur,1.6s) cubic-bezier(.15,.85,.25,1) var(--fx-odo-delay,0s)}
.fx-odo__col span{height:1em;line-height:1em;display:block;text-align:center}
.fx-odo__s{display:inline-block;white-space:pre;height:1em;line-height:1em}
.case .no .fx-odo{--fx-odo-va:0}
@media (prefers-reduced-motion:reduce){ .fx-odo__col{transition:none} }

/* ============ 4b. BORDER BEAM — hero "instant" form ============
   A square conic layer rotates under the pill (transform: rotate); the pill fill sits on top
   with a --fx-bw inset, so only the "comet" running along the edge is visible. */
.instant.fx-beam{--fx-bw:2px;position:relative;isolation:isolate;overflow:hidden;border:0;padding:8.5px 8.5px 8.5px 21.5px}
.instant.fx-beam::before{content:"";position:absolute;left:50%;top:50%;width:150%;aspect-ratio:1;translate:-50% -50%;z-index:-2;pointer-events:none;
  background:conic-gradient(from 0deg,var(--line) 0 62%,var(--brass) 82%,var(--accent) 95%,var(--line) 100%);
  animation:fx-beam-rot 6s linear infinite}
.instant.fx-beam::after{content:"";position:absolute;inset:var(--fx-bw);z-index:-1;border-radius:inherit;background:var(--card);pointer-events:none}
.instant.fx-beam.is-paused::before{animation-play-state:paused}
@keyframes fx-beam-rot{to{transform:rotate(1turn)}}
@media(max-width:560px){ .instant.fx-beam{padding:13.5px} }
@media (prefers-reduced-motion:reduce){ .instant.fx-beam::before{animation:none;transform:rotate(200deg)} }

/* ============ 5. PROCESS BEAM — #process steps ============ */
.fx-steps{position:relative;padding-left:58px}
.fx-steps .pstep{position:relative}
.fx-steps__rail{position:absolute;left:17px;width:2px;top:0;height:0;background:var(--line);pointer-events:none}
.fx-steps__rail i{position:absolute;inset:0;background:var(--accent);transform-origin:top;transform:scaleY(0)}
.fx-step__dot{position:absolute;left:-52px;top:0;width:24px;height:24px;border-radius:50%;border:2px solid var(--ink);background:var(--paper);z-index:1;
  transition:transform .45s cubic-bezier(.3,1.6,.5,1)}
.fx-step__dot::after{content:"";position:absolute;inset:3px;border-radius:50%;background:var(--accent);transform:scale(0);transition:transform .35s cubic-bezier(.3,1.6,.5,1)}
.fx-steps .pstep.is-on .fx-step__dot{transform:scale(1.15)}
.fx-steps .pstep.is-on .fx-step__dot::after{transform:none}
.fx-steps .pstep .pn{position:relative;display:inline-block;z-index:0}
.fx-steps .pstep .pn::before{content:"";position:absolute;left:-5px;right:-7px;bottom:.18em;height:.42em;z-index:-1;background:rgba(201,168,106,.45);
  transform:scaleX(0);transform-origin:left;transition:transform .6s cubic-bezier(.2,.7,.1,1)}
.fx-steps .pstep.is-on .pn::before{transform:none}
@media (max-width:860px){ .fx-steps{padding-left:44px} .fx-step__dot{left:-44px;width:22px;height:22px} .fx-steps__rail{left:10px} }
@media (prefers-reduced-motion:reduce){ .fx-step__dot,.fx-step__dot::after,.fx-steps .pstep .pn::before{transition:none} }

/* ============ 6. TILT COVERS — #work case frames (mouse only) ============
   Tilt uses the independent `rotate` property, the site's magnetic effect keeps `transform`. */
.case .frame.fx-tilt{will-change:rotate}
.case .frame.fx-tilt.is-hot{box-shadow:0 40px 60px -34px rgba(26,24,21,.45)}

/* ============ 7. FAQ ON NATIVE <details> — #faq ============ */
.fx-faqs details.fx-faq{border-bottom:1px solid var(--line)}
.fx-faqs summary.cap-row{list-style:none;cursor:pointer;border-bottom:0;grid-template-columns:60px 1fr auto;-webkit-tap-highlight-color:transparent}
.fx-faqs summary.cap-row::-webkit-details-marker{display:none}
.fx-faqs summary.cap-row:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.fx-faq__i{position:relative;width:38px;height:38px;border-radius:50%;border:1px solid currentColor;flex:none;
  transition:transform .45s cubic-bezier(.3,1.5,.5,1),background-color .3s,border-color .3s}
.fx-faq__i::before,.fx-faq__i::after{content:"";position:absolute;left:50%;top:50%;width:14px;height:1.5px;margin:-.75px 0 0 -7px;background:currentColor;transition:background-color .3s}
.fx-faq__i::after{transform:rotate(90deg)}
details.fx-faq[open] .fx-faq__i{transform:rotate(135deg);background:var(--accent);border-color:var(--accent);color:var(--paper)}
.fx-faq__a{padding:0 4px 30px 88px;max-width:calc(62ch + 88px);color:var(--ink2);font-size:1.02rem}
details.fx-faq[open] .fx-faq__a{animation:fx-faq-in .5s cubic-bezier(.2,.8,.2,1) both}
@keyframes fx-faq-in{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
@supports (interpolate-size:allow-keywords){
  .fx-faqs details.fx-faq{interpolate-size:allow-keywords}
  .fx-faqs details.fx-faq::details-content{height:0;overflow:clip;transition:height .45s cubic-bezier(.2,.8,.2,1),content-visibility .45s allow-discrete}
  .fx-faqs details.fx-faq[open]::details-content{height:auto}
}
@media(max-width:700px){
  .fx-faqs summary.cap-row{grid-template-columns:44px 1fr auto;gap:14px}
  .fx-faq__i{width:32px;height:32px}
  .fx-faq__a{padding:0 4px 24px 62px;font-size:.98rem}
}
@media (prefers-reduced-motion:reduce){
  .fx-faqs details.fx-faq *,.fx-faqs details.fx-faq::details-content{transition:none!important;animation:none!important}
}

/* ============ 8. FLIP WORDS — "Made for …" above the case list ============ */
.fx-fliprow{display:flex;align-items:baseline;flex-wrap:wrap;gap:6px 18px;margin:clamp(20px,4vh,48px) 0 clamp(20px,4vh,40px);
  font-family:var(--serif);font-size:clamp(1.7rem,3.6vw,3rem);line-height:1.1;letter-spacing:-.02em}
.fx-flip{display:inline-grid;font-style:italic;color:var(--accent);white-space:nowrap}
.fx-flip__word{grid-area:1/1;white-space:nowrap;display:flex;overflow:hidden;padding:.06em .04em .1em 0}
.fx-flip__ch{display:inline-block;white-space:pre;transform:translateY(110%);opacity:0;
  transition:transform .55s cubic-bezier(.2,.9,.25,1),opacity .3s linear;transition-delay:calc(var(--i) * 26ms)}
.fx-flip__word.is-in .fx-flip__ch{transform:none;opacity:1}
.fx-flip__word.is-out .fx-flip__ch{transform:translateY(-110%);opacity:0;transition-duration:.38s,.25s;transition-timing-function:cubic-bezier(.6,0,.8,.3),linear}
@media (prefers-reduced-motion:reduce){ .fx-flip__ch{transition:none} }

/* ============ 9. STICKY PHONE — #inside (desktop ≥1001px, only when fx.js enabled it) ============ */
.fx-ss__pin{display:none}
.fx-ss__after{margin-top:min(4vw,52px)}
@media (min-width:1001px){ .fx-ss--on+.fx-ss__after{margin-top:12vh} }
@media (min-width:1001px){
  .fx-ss--on{display:grid;grid-template-columns:minmax(0,1fr) clamp(250px,21vw,300px);gap:clamp(40px,7vw,120px);align-items:start;margin-top:4vh}
  .fx-ss--on .fx-ss__rows{display:block;margin-top:0}
  .fx-ss--on .fx-ss__row{min-height:62vh;display:flex;flex-direction:column;justify-content:center;border-top:1px solid var(--line);padding:6vh 0}
  .fx-ss--on .fx-ss__row:first-child{border-top:0}
  .fx-ss--on .fx-ss__row .fimg{display:none}          /* the phone shows the screens */
  .fx-ss--on .fx-ss__row h3{font-size:clamp(2.2rem,4vw,3.6rem);margin:0 0 14px}
  .fx-ss--on .fx-ss__row p{font-size:1.1rem;color:var(--ink2)}
  .fx-ss--on .fx-ss__row>*{opacity:.24;transition:opacity .5s ease}
  .fx-ss--on .fx-ss__row.is-active>*{opacity:1}
  .fx-ss--on .fx-ss__pin{display:block;position:sticky;top:calc(50vh - min(600px,74vh) / 2);height:min(600px,74vh);margin:6vh 0 4vh}
  .fx-ss__phone{position:relative;height:100%;aspect-ratio:9/19;margin-inline:auto;border-radius:42px;background:var(--ink);padding:10px;
    box-shadow:12px 12px 0 var(--brass),0 30px 60px -24px rgba(26,24,21,.5);transform:rotate(-3deg)}
  .fx-ss__screen{position:relative;height:100%;border-radius:33px;overflow:hidden;background:var(--paper2)}
  .fx-ss__layer{position:absolute;inset:0;width:100%;height:100%;max-width:none;object-fit:cover;object-position:50% 0;opacity:0;transform:translateY(22px) scale(.97);
    transition:opacity .5s ease,transform .6s cubic-bezier(.2,.8,.2,1)}
  .fx-ss__layer.is-active{opacity:1;transform:none}
  .fx-ss__notch{position:absolute;left:50%;top:19px;width:72px;height:19px;margin-left:-36px;border-radius:99px;background:var(--ink);z-index:2}
}
@media (prefers-reduced-motion:reduce){ .fx-ss__layer,.fx-ss--on .fx-ss__row>*{transition:none} }

/* ============ 11. PEEL STICKER — #price ============
   "Slap" in when it scrolls into view; peel = the corner flap (scale from the corner);
   drag = the `translate`/`rotate` properties (rest tilt and site magnetism live in `transform`). */
.fx-peelwrap{position:relative;height:0;z-index:3}
.fx-sticker{position:absolute;right:clamp(0px,6vw,110px);top:clamp(10px,4vh,50px);display:inline-block;padding:14px 22px 15px;border-radius:12px;
  background:var(--brass);color:var(--ink);font-family:var(--serif);font-style:italic;font-size:clamp(1.1rem,1.6vw,1.45rem);line-height:1;white-space:nowrap;
  transform:rotate(7deg);box-shadow:0 14px 30px -14px rgba(26,24,21,.55);user-select:none;-webkit-user-select:none;touch-action:pan-y}
.fx-on .fx-sticker:not(.is-in){opacity:0}
.fx-sticker.is-in{animation:fx-slap .7s cubic-bezier(.2,.9,.3,1.25) backwards}
@keyframes fx-slap{0%{scale:1.9;rotate:-22deg;opacity:0}55%{opacity:1}70%{scale:.93;rotate:2deg}100%{scale:1;rotate:0deg;opacity:1}}
.fx-peel{position:absolute;right:0;bottom:0;width:22px;height:22px;pointer-events:none;border-radius:0 0 12px 0;
  background:linear-gradient(135deg,#fbf6ee 0%,#e6dccb 48%,var(--paper) 50%);
  box-shadow:-2px -2px 5px rgba(26,24,21,.2);transform:scale(0);transform-origin:100% 100%;transition:transform .45s cubic-bezier(.3,1.5,.5,1)}
.fx-sticker.fx-peel-on{cursor:grab}
@media (hover:hover) and (pointer:fine){
  .fx-sticker.fx-peel-on:hover .fx-peel{transform:scale(1)}
  .fx-sticker.fx-peel-on.is-drag{cursor:grabbing}
  .fx-sticker.fx-peel-on.is-drag .fx-peel{transform:scale(1.35)}
}
@media (max-width:700px){ .fx-sticker{right:0;top:-7vh;padding:10px 15px 11px;font-size:1rem} }
@media (prefers-reduced-motion:reduce){ .fx-sticker.is-in{animation:none} .fx-peel{transition:none} }

/* ============ 12. WORDS ON SCROLL + MARKER — #studio statement ============ */
.fx-w{display:inline-block}
.fx-mw{position:relative;z-index:0}
.fx-mk{position:absolute;left:-.08em;right:-.08em;top:.5em;bottom:.02em;z-index:-1;background:rgba(201,168,106,.42);border-radius:.08em;
  transform:scaleX(0);transform-origin:0 50%;pointer-events:none}
.fx-mwj .fx-mk{right:-.32em}   /* the marker also covers the space to the next word */
@media (prefers-reduced-motion:reduce){ .fx-w{opacity:1!important} .fx-mk{transform:none!important} }
