/* fx.css — візуальні ефекти Lumen Studio UA (deviceforge.shop), 08.10.2026.
   Усі класи з префіксом fx-. Анімуються лише transform / opacity.
   prefers-reduced-motion: усе статично (плюс загальне правило сайту *{animation:none;transition:none}).

   Джерела й ліцензії (переписано з нуля на ванільний CSS/JS, без React/Tailwind):
   - Device scroll  — ідея «Container Scroll Animation», Aceternity UI (free component), ui.aceternity.com
   - Tilt covers    — ідея «3D Card Effect», Aceternity UI (free component), ui.aceternity.com
   - Ring sticker   — «Circular Text», Animata (MIT), github.com/codse/animata
   - CTA-кнопки     — uiverse.io 0xnihilism/fast-cat-82 + quiet-dog-6 (MIT)
   - Odometer       — Magic UI NumberTicker (MIT), magicui.design
   - Border beam    — Magic UI BorderBeam (MIT), magicui.design
   - Process beam   — Magic UI AnimatedBeam (MIT), magicui.design
   - FAQ            — власний код на нативних <details> (без запозичень)
   v2 (08.10.2026):
   - Flip words     — ідея «Flip Words», Aceternity UI (free component), ui.aceternity.com/components/flip-words
   - Sticky screen  — ідея «Sticky Scroll Reveal», Aceternity UI (free component), ui.aceternity.com
   - Дві стрічки    — за мотивами React Bits «ScrollVelocity» (MIT + Commons Clause), reactbits.dev
   - Наклейка       — за мотивами React Bits «StickerPeel» (MIT + Commons Clause), reactbits.dev
   - Слова по скролу — за мотивами React Bits «ScrollReveal» (MIT + Commons Clause), reactbits.dev
   React Bits: MIT з Commons Clause — використання в проєктах дозволено, продаж самих компонентів — ні.
*/

/* ============ 1. DEVICE SCROLL (Aceternity idea) ============ */
.fx-ds{position:relative;overflow:clip;padding:0 0 clamp(80px,11vw,150px)}
.fx-ds__sticky{display:flex;flex-direction:column;align-items:center;justify-content:center}
.fx-ds__head{text-align:center;max-width:900px;margin:0 auto clamp(18px,3.2vh,40px);will-change:transform}
.fx-ds__head .h2{font-size:clamp(26px,4.6vw,66px);margin:0}
.fx-ds__head .h2 .bl{color:var(--blue)}
.fx-ds__head .sub{margin:14px auto 0;max-width:660px}
.fx-ds__stage{perspective:1000px;width:100%;display:flex;justify-content:center}
.fx-ds__device{position:relative;width:min(1080px,100%,calc((100vh - 330px)*1.6));aspect-ratio:16/10;
  border-radius:26px;padding:clamp(8px,1.2vw,14px);background:#1b1b20;border:3px solid #3a3a42;
  transform-origin:50% 0%;will-change:transform;
  box-shadow:0 9px 20px #0000004a,0 37px 37px #00000042,0 84px 50px #00000026,0 149px 60px #0000000a}
.fx-ds__base{position:absolute;left:-6%;right:-6%;top:100%;height:16px;margin-top:3px;border-radius:2px 2px 18px 18px;
  background:linear-gradient(#3a3a42,#1b1b20);box-shadow:0 18px 30px -14px #0000007a}
.fx-ds__base::before{content:"";position:absolute;left:50%;top:0;width:16%;height:6px;margin-left:-8%;border-radius:0 0 8px 8px;background:#0e0e12}
.fx-ds__screen{position:relative;height:100%;border-radius:14px;overflow:hidden;background:#0d0b09}
.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(1px,.45vw,4px);left:50%;width:6px;height:6px;margin-left:-3px;border-radius:50%;background:#000;opacity:.7}
/* JS увімкнено + рух дозволено: секція дає «запас прокрутки», екран липне */
.fx-on .fx-ds{height:280vh;padding:0}
.fx-on .fx-ds__sticky{position:sticky;top:0;height:100vh;height:100svh;padding:72px 0 30px}
.fx-on .fx-ds__device{transform:rotateX(20deg) scale(1.05)}
@media (max-width:768px){
  .fx-ds__device{aspect-ratio:9/17;width:min(330px,100%,calc((100vh - 290px)*9/17));border-radius:38px;padding:9px}
  .fx-ds__screen{border-radius:30px}
  .fx-ds__base{display:none}
  .fx-ds__camera{top:7px;width:58px;height:16px;margin-left:-29px;border-radius:99px;opacity:1}
  .fx-on .fx-ds{height:260vh}
  .fx-on .fx-ds__sticky{padding:66px 0 22px}
}
@media (prefers-reduced-motion:reduce){ .fx-ds__device{transform:none!important} }

/* ============ 2. RING STICKER (Animata Circular Text, MIT) ============ */
.fx-ring__svg{position:absolute;inset:-18%;width:136%;height:136%;pointer-events:none;overflow:visible;
  animation:fx-ring-spin 18s linear infinite;will-change:transform}
.fx-ring__svg text{font-family:var(--disp);font-size:12.5px;letter-spacing:.04em;fill:#fff;text-transform:uppercase}
@keyframes fx-ring-spin{to{transform:rotate(360deg)}}
@media (max-width:860px){ .fx-ring__svg{inset:-12%;width:124%;height:124%} .fx-ring__svg text{font-size:14px} }
@media (prefers-reduced-motion:reduce){ .fx-ring__svg{animation:none} }

/* ============ 3. CTA — жорстка тінь (uiverse, MIT) ============
   Без зміни розмітки: ::before = тінь, ::after = лаймове «обличчя» з чорнильною рамкою.
   Кнопка рухається властивістю translate (не конфліктує з магнітним transform сайту),
   тінь компенсує зсув і стоїть на місці. */
.btn.lime{--fx-off:5px;position:relative;isolation:isolate;transition:transform .2s,color .2s,translate .22s cubic-bezier(.3,1.7,.55,1);-webkit-tap-highlight-color:transparent}
.btn.lime,.btn.lime:hover{background:transparent}
.btn.lime::before,.btn.lime::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none}
.btn.lime::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)}
.btn.lime::after{z-index:-1;background:var(--lime);border:2.5px solid var(--ink);transition:background-color .2s}
.btn.lime:hover::after{background:#fff}
@media (hover:hover){
  .btn.lime:hover{translate:-3px -3px}
  .btn.lime:hover::before{transform:translate(calc(var(--fx-off) + 3px),calc(var(--fx-off) + 3px))}
}
.btn.lime:active{translate:4px 4px;transition-duration:.06s}
.btn.lime:active::before{transform:translate(calc(var(--fx-off) - 4px),calc(var(--fx-off) - 4px));transition-duration:.06s}
.btn.lime:focus-visible{outline:3px solid var(--ink);outline-offset:6px}
nav .btn.lime{--fx-off:4px}

/* ============ 4a. ODOMETER (Magic UI NumberTicker, MIT) ============ */
.fx-odo{display:inline-flex;align-items:flex-end;line-height:1;vertical-align:var(--fx-odo-va,-.02em)}
.fx-odo__d{display:inline-flex;justify-content:center;height:.92em;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:.92em;line-height:.92em;display:block;text-align:center}
.fx-odo__s{display:inline-block;white-space:pre;height:.92em;line-height:.92em}
.fx-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
@media (prefers-reduced-motion:reduce){ .fx-odo__col{transition:none} }

/* ============ 4b. BORDER BEAM (Magic UI BorderBeam, MIT) ============
   Шар з conic-gradient крутиться під карткою (transform: rotate), зверху — заливка
   картки з відступом --fx-bw. Видно лише «комету», що біжить кромкою. */
.pc.fx-beam{--fx-bw:3px;--fx-r:30px;border:0;background:var(--ink);isolation:isolate;
  padding:calc(clamp(28px,3.4vw,50px) + var(--fx-bw))}
.pc.fx-beam::before{content:"";position:absolute;inset:-60%;z-index:-2;pointer-events:none;
  background:conic-gradient(from 0deg,transparent 0 66%,var(--lime) 84%,var(--coral) 96%,transparent 100%);
  animation:fx-beam-rot 6s linear infinite}
.pc.fx-beam::after{content:"";position:absolute;inset:var(--fx-bw);z-index:-1;border-radius:calc(var(--fx-r) - var(--fx-bw));background:var(--card);pointer-events:none}
.pc.fx-beam.is-paused::before{animation-play-state:paused}
@keyframes fx-beam-rot{to{transform:rotate(1turn)}}
@media (prefers-reduced-motion:reduce){ .pc.fx-beam::before{animation:none;transform:rotate(200deg)} }

/* ============ 5. PROCESS BEAM (Magic UI AnimatedBeam, MIT) ============ */
.steps.fx-steps{position:relative}
.fx-steps__svg{position:absolute;left:0;top:0;width:100%;height:100%;overflow:visible;pointer-events:none;z-index:0}
.fx-steps__svg path{fill:none;stroke-linecap:round}
.fx-steps__ghost{stroke:rgba(14,14,18,.22);stroke-width:2;stroke-dasharray:2 8}
.fx-steps__live{stroke:var(--ink);stroke-width:3}
.fx-step__dot{position:absolute;left:24px;top:-42px;width:24px;height:24px;border-radius:50%;border:2.5px 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(--lime);transform:scale(0);transition:transform .35s cubic-bezier(.3,1.6,.5,1)}
.fx-steps .step.is-on .fx-step__dot{transform:scale(1.25)}
.fx-steps .step.is-on .fx-step__dot::after{transform:none}
.fx-steps .step:last-child .fx-step__dot::after{background:var(--coral)}
/* номер кроку «підсвічується» маркером */
.fx-steps .step .n{position:relative;display:inline-block;z-index:0}
.fx-steps .step .n::before{content:"";position:absolute;left:-6px;right:-8px;bottom:6px;height:.36em;z-index:-1;background:var(--lime);
  transform:scaleX(0);transform-origin:left;transition:transform .6s cubic-bezier(.2,.7,.1,1)}
.fx-steps .step:last-child .n::before{display:none}
.fx-steps .step.is-on .n::before{transform:none}
.fx-steps__rail{display:none}
@media (max-width:1000px){
  .steps.fx-steps{grid-template-columns:1fr;padding-left:42px;gap:22px}
  .fx-steps__svg{display:none}
  .fx-step__dot{left:-42px;top:34px}
  .fx-steps__rail{display:block;position:absolute;left:11px;top:46px;bottom:60px;width:2px;background:rgba(14,14,18,.18)}
  .fx-steps__rail i{position:absolute;inset:0;background:var(--ink);transform-origin:top;transform:scaleY(0)}
}
@media (prefers-reduced-motion:reduce){ .fx-step__dot,.fx-step__dot::after,.fx-steps .step .n::before{transition:none} }

/* ============ 6. TILT COVERS (Aceternity 3D Card idea) ============ */
.fx-tilt .im{will-change:transform}
.fx-tilt.is-hot .im{transition:none}
.fx-tilt .im img{transition:transform .6s cubic-bezier(.2,.8,.2,1)}
.fx-tilt.is-hot .im img{transform:scale(1.05)}

/* ============ 7. FAQ (нативні details) ============ */
.faq details.fx-faq summary{-webkit-tap-highlight-color:transparent}
.faq details.fx-faq summary:focus-visible{outline:2.5px solid var(--ink);outline-offset:4px}
.fx-faq__q{transition:transform .35s cubic-bezier(.3,1.4,.5,1)}
@media (hover:hover){ .faq details.fx-faq summary:hover .fx-faq__q{transform:translateX(8px)} }
.faq details.fx-faq summary i{position:relative;font-size:0;color:transparent;border:2.5px solid var(--ink);
  transition:transform .45s cubic-bezier(.3,1.5,.5,1),background-color .3s}
.faq details.fx-faq summary i::before,.faq details.fx-faq summary i::after{content:"";position:absolute;left:50%;top:50%;width:16px;height:2.5px;margin:-1.25px 0 0 -8px;border-radius:2px;background:var(--ink);transition:background-color .3s}
.faq details.fx-faq summary i::after{transform:rotate(90deg)}
.faq details.fx-faq[open] summary i{transform:rotate(135deg);background:var(--coral);color:transparent}
.faq details.fx-faq[open] summary i::before,.faq details.fx-faq[open] summary i::after{background:#fff}
.faq details.fx-faq[open] .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){
  .faq details.fx-faq{interpolate-size:allow-keywords}
  .faq details.fx-faq::details-content{height:0;overflow:clip;transition:height .45s cubic-bezier(.2,.8,.2,1),content-visibility .45s allow-discrete}
  .faq details.fx-faq[open]::details-content{height:auto}
}
@media (prefers-reduced-motion:reduce){
  .faq details.fx-faq *,.faq details.fx-faq::details-content{transition:none!important;animation:none!important}
}


/* ======================= v2 ======================= */

/* ============ 8. FLIP WORDS (Aceternity idea) — #roboty ============
   Усі слова в одній клітинці grid → ширина плашки = найдовше слово, рядок не стрибає. */
.fx-fliprow{font-size:clamp(20px,3.1vw,44px);line-height:1.15;margin-top:clamp(18px,2.2vw,30px);color:#fff}
.fx-flip{display:inline-grid;vertical-align:bottom;color:var(--ink);background:var(--lime);
  padding:.06em .2em .02em;border-radius:.12em;transform:rotate(-1.5deg);white-space:nowrap}
.fx-flip__word{grid-area:1/1;white-space:nowrap;display:flex;overflow:hidden;padding:.04em 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 (max-width:560px){ .fx-fliprow{font-size:clamp(17px,5.4vw,24px)} }
@media (prefers-reduced-motion:reduce){ .fx-flip__ch{transition:none} }

/* ============ 9. STICKY SCREEN (Aceternity Sticky Scroll Reveal idea) ============
   Лише десктоп ≥1001px і лише коли fx.js увімкнув (.fx-ss--on). Інакше — як було. */
.fx-ss__pin{display:none}
@media (min-width:1001px){
  .fx-ss--on{margin-bottom:-160px;display:grid;grid-template-columns:minmax(0,1fr) clamp(240px,22vw,300px);gap:clamp(40px,5vw,90px);align-items:start}
  .fx-ss--on .fx-ss__pin{display:block;position:sticky;top:calc(50vh - min(600px,76vh) / 2);height:min(600px,76vh)}
  .fx-ss--on .fx-ss__rows{padding-bottom:160px}   /* запас для sticky (телефон вищий за останній рядок), компенсовано margin-bottom */
  .fx-ss--on .obj{grid-template-columns:1fr 1fr;opacity:.28;transition:opacity .5s ease}
  .fx-ss--on .obj.is-active{opacity:1}
  .fx-ss--on .obj .shot{display:none}          /* скріни показує телефон */
  .fx-ss__phone{position:relative;height:100%;aspect-ratio:9/19;margin-inline:auto;border-radius:44px;background:var(--ink);padding:11px;
    box-shadow:10px 10px 0 var(--blue),0 30px 60px -24px rgba(14,14,18,.5)}   /* 08.10: рівно — нахил робив кадри кривими */
  .fx-ss__screen{position:relative;height:100%;border-radius:34px;overflow:hidden;background:#141210}
  .fx-ss__layer{position:absolute;inset:0;width:100%;height:100%;max-width:none;object-fit:cover;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:20px;width:76px;height:20px;margin-left:-38px;border-radius:99px;background:var(--ink);z-index:2}
}
@media (prefers-reduced-motion:reduce){ .fx-ss__layer,.fx-ss--on .obj{transition:none} }

/* ============ 10. ДВІ СТРІЧКИ ХРЕСТ-НАВХРЕСТ (React Bits ScrollVelocity, MIT + Commons Clause) ============
   Лаймова — сайтова .marq.tilt (не змінена), коралова — її копія з fx.js, одразу під нею (не перекриваються, 08.10). */
.fx-mx{position:relative;z-index:4;overflow-x:clip}
.fx-mx .marq.tilt{z-index:2}
.marq.fx-mq2{position:relative;z-index:1;width:108vw;margin:14px 0 0 -4vw;background:var(--coral);color:#fff;
  transform:rotate(-.9deg)}
.marq.fx-mq2 span::after{color:var(--lime)}
.marq.fx-mq2 .tr{animation-direction:reverse;animation-duration:30s}

/* ============ 11. НАКЛЕЙКА «З АДМІНКОЮ!» (React Bits StickerPeel, MIT + Commons Clause) ============
   «Шльоп» замість pop (той самий delay, fill backwards → після нього hover-scale сайту працює).
   Відгин кутика = трикутник-«виворіт» (scale від кута). Перетягування — властивість translate
   (сайт рухає наклейку через transform, pop — через scale/rotate: ніхто нікому не заважає). */
.st2[data-fx-peel]{animation:fx-slap .7s cubic-bezier(.2,.9,.3,1.25) 1.75s 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}}
.st2 .fx-peel{position:absolute;right:0;bottom:0;width:24px;height:24px;pointer-events:none;border-radius:0 0 14px 0;
  background:linear-gradient(135deg,#fff6ef 0%,#e9d9cc 48%,var(--blue) 50%);
  box-shadow:-2px -2px 5px rgba(14,14,18,.22);transform:scale(0);transform-origin:100% 100%;
  transition:transform .45s cubic-bezier(.3,1.5,.5,1)}
.st2.fx-peel-on{cursor:grab}
@media (hover:hover) and (pointer:fine){
  .st2.fx-peel-on:hover .fx-peel{transform:scale(1)}
  .st2.fx-peel-on.is-drag{cursor:grabbing}
  .st2.fx-peel-on.is-drag .fx-peel{transform:scale(1.35)}
}
@media (prefers-reduced-motion:reduce){ .st2[data-fx-peel]{animation:none} .st2 .fx-peel{transition:none} }

/* ============ 12. СЛОВА ПО СКРОЛУ (React Bits ScrollReveal, MIT + Commons Clause) — #ne-demo ============ */
.fx-w{display:inline-block}
.fx-mw{position:relative;z-index:0}
.fx-mk{position:absolute;left:-.1em;right:-.1em;top:.12em;bottom:.04em;z-index:-1;background:var(--lime);border-radius:.1em;
  transform:scaleX(0);transform-origin:0 50%;pointer-events:none}
.h2 .fx-mk{top:.02em;bottom:-.02em;left:-.06em;right:-.06em}
.fx-mwj .fx-mk{right:-.34em}   /* маркер перекриває пробіл до наступного слова */
.h2 .fx-mwj .fx-mk{right:-.3em}
.sub .fx-mark{color:var(--ink)}
@media (prefers-reduced-motion:reduce){ .fx-w{opacity:1!important} .fx-mk{transform:none!important} }
