Бесшовный переход

Видеоинструкция по подключению
Категория
Последнее обновление
2 Ноября, 2026
В подписке, Эффекты, GSAP
Скриншоты шаблона

Пошаговая инструкция с подключением кода

Общее
Подключение всех переходов выполняется одинаково. Отличаются только классы ссылок, отвечающих за переход между страницами, и сам скрипт перехода. Скрипт подключается в head или в начале страницы.

Классы на ссылки для переходов:
pt-link - Наклон по диагонали;
fs-link - Сдвиг кадра;
av-link - Дуговой переход;
sv-link - Спиральный переход;
dv-link - Тающий переход;
Наклон по диагонали (Diagonal Flow)
В начало страницы или шапку добавляем код, через блок T123
CSS / JS

<!--Бесшовный переход
https://mt-webdesign.ru/seamless-->
<style class="pt-style">
.pt-root{scrollbar-gutter:stable;scroll-behavior:auto!important}
.pt-root.pt-busy{overscroll-behavior:none}
.pt-page{position:relative}
.pt-incoming{position:fixed!important;top:0;left:0;height:100vh;overflow:clip;pointer-events:none}
.pt-veil{position:fixed;inset:0;z-index:2;background:#000;opacity:0;visibility:hidden;pointer-events:none}
</style>
<script src="https://matilda-design.ru/library/GSAP.js"></script>
<script src="https://matilda-design.ru/library/ScrollTrigger.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@barba/core@2.10.3/dist/barba.umd.js"></script>
<script class="pt-bootstrap">
(function(){
"use strict";
// Цвет подложки, видимой во время перехода.
const TRANSITION_BACKGROUND = "#000000";
// Скругление углов во время перехода, в пикселях.
const TRANSITION_RADIUS = 0;
if(window.TildaPageTransitions)return;
const api=window.TildaPageTransitions={
version:"1.5.0-lifecycle",documentToken:Date.now().toString(36)+"-"+Math.random().toString(36).slice(2),
bootCount:1,transitions:0,nativeInits:0,activeNativeListeners:0,errors:[],
lastTransition:null,ready:false
};
const state={pending:false,busy:false,oldScroll:0,oldFocus:null,lockStyles:null,epoch:0};
const pageStates=new WeakMap();
const scriptLoads=new Map();
const loadedScripts=new Set(Array.from(document.scripts,s=>s.src).filter(Boolean));
const executedScripts=new WeakSet();
let initialScope=null,initialPage=null;
function makeScope(page){return {
key:"ptRuntime"+(++nativeSerial),page,disposed:false,listeners:new Set(),timers:new Set(),intervals:new Set(),
frames:new Set(),observers:new Set(),jquery:new Set(),styles:new Set(),portals:new Set(),formKeys:[],sbsAuto:false,
readyJobs:[],loadJobs:[],replay:false,customCount:0,contexts:new Set(),webgl:new Set()
}}
function lifecycleJob(s,target,type,callback,options){
if(!s?.replay||!callback||!((target===document&&type==="DOMContentLoaded")||(target===window&&type==="load")))return false;
const name=type==="load"?"loadJobs":"readyJobs",queue=s[name];
if(s[name+"Done"]){raw.timeout(()=>{try{inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?target:callback,[new Event(type)])}catch(error){report(error)}},0);return true}
if(!queue.some(j=>j.callback===callback&&j.target===target))queue.push({target,type,callback,options});
return true;
}
function flushJobs(s,name){
const jobs=s[name].splice(0);
for(const j of jobs){if(s.disposed)break;try{
const fn=typeof j.callback==="function"?j.callback:j.callback.handleEvent;
inNative(s,fn,typeof j.callback==="function"?j.target:j.callback,[new Event(j.type)]);
}catch(error){report(error)}}
s[name+"Done"]=true;
}
let nativeOwner=null,nativeSerial=0;
const scriptOwners=new WeakMap();
const raw={
add:EventTarget.prototype.addEventListener,remove:EventTarget.prototype.removeEventListener,
timeout:window.setTimeout.bind(window),clearTimeout:window.clearTimeout.bind(window),interval:window.setInterval.bind(window),clearInterval:window.clearInterval.bind(window),
raf:window.requestAnimationFrame.bind(window),caf:window.cancelAnimationFrame.bind(window),
append:Node.prototype.appendChild,insert:Node.prototype.insertBefore,
xhrSend:window.XMLHttpRequest?.prototype.send
};
let routeHistory=null;
for(const method of ["pushState","replaceState"]){
const original=history[method].bind(history);
history[method]=function(value,title,url){
if(value?.from==="barba")routeHistory=value;
else if(api.ready||owner()){
const base=history.state?.from==="barba"?history.state:routeHistory;
if(base)value={from:base.from,index:base.index,states:base.states,...(value||{})};
}
return original(value,title,url);
};
}
const popstateDescriptor=Object.getOwnPropertyDescriptor(window,"onpopstate");
if(popstateDescriptor?.get&&popstateDescriptor?.set&&popstateDescriptor.configurable){
Object.defineProperty(window,"onpopstate",{configurable:true,enumerable:popstateDescriptor.enumerable,
get(){return popstateDescriptor.get.call(window)},
set(fn){const s=owner(),wrapped=s&&typeof fn==="function"?function(event){
if(s.disposed)return;
const value=event?.state||history.state;
if(value?.storepartuid&&!value.productData){
const active=document.querySelector(".pt-page:not(.pt-incoming)");
if(active?.getAttribute("data-barba-namespace")!==location.pathname)return;
if(value.opts&&typeof window.t_catalog_loadProducts==="function"){
value.opts.isPublishedPage=true;
return inNative(s,window.t_catalog_loadProducts,window,["",value.recid,value.opts]);
}
return;
}
return inNative(s,fn,this,[event]);
}:fn;
if(s)s.popstateHandler=wrapped;
popstateDescriptor.set.call(window,wrapped);
}
});
}
const listenerMap=new WeakMap();
function owner(){
if(nativeOwner)return nativeOwner;
const script=document.currentScript;
const known=script&&scriptOwners.get(script);if(known)return known;
if(!initialPage&&((script&&!script.src&&!script.classList.contains("pt-bootstrap")&&!script.closest("header,footer"))||(!script&&document.readyState==="interactive"))){
initialScope=initialScope||makeScope(null);if(script)scriptOwners.set(script,initialScope);return initialScope;
}
return null;
}
function scopeFor(page){const s=pageState(page);if(!s.nativeScope)s.nativeScope=makeScope(page);return s.nativeScope}
function inNative(s,fn,thisArg,args){
if(s?.disposed||s?.paused)return;
const before=nativeOwner,classes=new Set(document.body?.classList||[]);nativeOwner=s;
try{
if(s&&window.gsap?.context){
if(!s.gsapContext||s.gsapOwner!==window.gsap){s.gsapOwner=window.gsap;s.gsapContext=gsap.context(()=>{});s.contexts.add(s.gsapContext)}
let result;s.gsapContext.add(()=>{result=fn.apply(thisArg,args||[])});return result;
}
return fn.apply(thisArg,args||[]);
}finally{
if(s){s.bodyClasses=s.bodyClasses||new Set();for(const name of document.body?.classList||[])if(!classes.has(name))s.bodyClasses.add(name)}
nativeOwner=before;
}
}
function owned(s,fn){if(typeof fn!=="function")return fn;return function(...args){return inNative(s,fn,this,args)}}
function refreshNativeCounts(){
let globals=0,observers=0,timers=0;
document.querySelectorAll(".pt-page").forEach(p=>{const s=pageStates.get(p)?.nativeScope;if(s&&!s.disposed){globals+=Array.from(s.listeners).filter(r=>r.target===window||r.target===document||r.target===document.body).length;observers+=s.observers.size;timers+=s.timers.size+s.intervals.size}});
api.activeNativeListeners=globals;api.nativeObservers=observers;api.nativeTimers=timers;
}
let jqueryRegistering=false;
EventTarget.prototype.addEventListener=function(type,callback,options){
const s=owner();
if(lifecycleJob(s,this,type,callback,options))return;
if(!s||!callback||jqueryRegistering)return raw.add.call(this,type,callback,options);
const capture=typeof options==="boolean"?options:!!options?.capture;
let list=listenerMap.get(this);if(!list){list=[];listenerMap.set(this,list)}
const existing=list.find(r=>r.s===s&&r.type===type&&r.callback===callback&&r.capture===capture);
if(existing)return raw.add.call(this,type,existing.wrapped,options);
const r={s,target:this,type,callback,capture,options,wrapped:null};
r.wrapped=function(...args){if(options?.once){s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)}
return inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?this:callback,args)};
list.push(r);s.listeners.add(r);return raw.add.call(this,type,r.wrapped,options);
};
EventTarget.prototype.removeEventListener=function(type,callback,options){
const activeScope=owner();
if(activeScope?.replay)for(const name of ["readyJobs","loadJobs"])activeScope[name]=activeScope[name].filter(j=>!(j.target===this&&j.type===type&&j.callback===callback));
const list=listenerMap.get(this),capture=typeof options==="boolean"?options:!!options?.capture,s=owner();
const matches=list?.filter(r=>r.type===type&&r.callback===callback&&r.capture===capture&&(!s||r.s===s))||[];
if(!matches.length)return raw.remove.call(this,type,callback,options);
matches.forEach(r=>{raw.remove.call(this,type,r.wrapped,options);r.s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)});
};
window.setTimeout=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.timeout(fn,ms,...args);let id;id=raw.timeout(()=>{s.timers.delete(id);inNative(s,fn,window,args)},ms);s.timers.add(id);return id};
window.clearTimeout=function(id){const s=owner();s?.timers.delete(id);return raw.clearTimeout(id)};
window.setInterval=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.interval(fn,ms,...args);const id=raw.interval(owned(s,fn),ms,...args);s.intervals.add(id);return id};
window.clearInterval=function(id){const s=owner();s?.intervals.delete(id);return raw.clearInterval(id)};
window.requestAnimationFrame=function(fn){const s=owner();if(!s)return raw.raf.call(window,fn);let id;id=raw.raf.call(window,t=>{s.frames.delete(id);inNative(s,fn,window,[t])});s.frames.add(id);return id};
window.cancelAnimationFrame=function(id){owner()?.frames.delete(id);return raw.caf.call(window,id)};
for(const key of ["IntersectionObserver","ResizeObserver","MutationObserver"]){
const Original=window[key];if(!Original)continue;
window[key]=new Proxy(Original,{construct(Target,args,newTarget){const s=owner();if(s)args[0]=owned(s,args[0]);const observer=Reflect.construct(Target,args,newTarget===window[key]?Target:newTarget);if(s)s.observers.add(observer);return observer}});
}
function noteInsertion(parent,node){const s=owner();if(!s||!node)return;if(parent===document.head&&node.tagName==="STYLE")s.styles.add(node);if(parent===document.body&&node.tagName==="DIV"){node.classList.add("pt-native-portal");s.portals.add(node)}}
Node.prototype.appendChild=function(node){noteInsertion(this,node);return raw.append.call(this,node)};
Node.prototype.insertBefore=function(node,before){noteInsertion(this,node);return raw.insert.call(this,node,before)};
if(raw.xhrSend)XMLHttpRequest.prototype.send=function(...args){const s=owner();if(s)for(const name of ["onreadystatechange","onload","onerror","onloadend"]){if(typeof this[name]==="function")this[name]=owned(s,this[name])}return raw.xhrSend.apply(this,args)};
if(window.jQuery){
const $=window.jQuery,baseOn=$.fn.on,baseReady=$.fn.ready;
$.fn.ready=function(fn){const s=owner();if(!s)return baseReady.call(this,fn);
if(s.replay){lifecycleJob(s,document,"DOMContentLoaded",function(){return fn.call(document,$)});return this}
return baseReady.call(this,owned(s,fn));
};
$.fn.on=function(...args){const s=owner();if(!s)return baseOn.apply(this,args);
if(s.replay&&this.length===1&&this[0]===window&&typeof args[0]==="string"&&args[0].split(/\s+/).every(t=>t.split(".")[0]==="load")){
const callback=args.slice(1).findLast(a=>typeof a==="function");
if(callback){lifecycleJob(s,window,"load",callback);return this}
}
const ns="."+s.key;
const names=t=>t.split(/\s+/).filter(Boolean).map(t=>t+ns).join(" ");
if(typeof args[0]==="string")args[0]=names(args[0]);
else if(args[0]&&typeof args[0]==="object")args[0]=Object.fromEntries(Object.entries(args[0]).map(([k,v])=>[names(k),owned(s,v)]));
for(let i=1;i<args.length;i++)if(typeof args[i]==="function"){const original=args[i],wrapped=owned(s,original);wrapped.guid=original.guid||(original.guid=$.guid++);args[i]=wrapped}
s.jquery.add(this);const previous=jqueryRegistering;jqueryRegistering=true;try{return baseOn.apply(this,args)}finally{jqueryRegistering=previous}
};
}
function disposeNative(page){
const s=pageStates.get(page)?.nativeScope;if(!s)return;
s.disposed=true;
if(s.popstateHandler&&window.onpopstate===s.popstateHandler)window.onpopstate=null;
s.listeners.forEach(r=>{raw.remove.call(r.target,r.type,r.wrapped,r.options);const list=listenerMap.get(r.target);const i=list?.indexOf(r);if(i>=0)list.splice(i,1)});
s.timers.forEach(raw.clearTimeout);s.intervals.forEach(raw.clearInterval);s.frames.forEach(id=>raw.caf.call(window,id));
s.observers.forEach(o=>o.disconnect());s.jquery.forEach(q=>q.off("."+s.key));
s.contexts.forEach(c=>c.revert());s.webgl.forEach(gl=>gl.getExtension("WEBGL_lose_context")?.loseContext());
s.readyJobs.length=0;s.loadJobs.length=0;s.bodyClasses?.forEach(name=>document.body.classList.remove(name));
s.styles.forEach(n=>n.remove());s.portals.forEach(n=>n.remove());
if(window.initForms)s.formKeys.forEach(k=>delete window.initForms[k]);
s.listeners.clear();s.timers.clear();s.intervals.clear();s.frames.clear();s.observers.clear();s.jquery.clear();
refreshNativeCounts();
}
const rawGetContext=HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext=function(...args){const gl=rawGetContext.apply(this,args),s=owner();if(s&&gl&&/webgl/i.test(args[0]))s.webgl.add(gl);return gl};
const cssLoads=new Map();
function diagnostics(){const site=document.querySelector(".pt-site");if(!site)return;Object.assign(site.dataset,{ptDocument:api.documentToken,ptTransitions:String(api.transitions),ptNativeInits:String(api.nativeInits),ptCustomInits:String(api.customInits||0),ptVersion:api.version,ptNativeListeners:String(api.activeNativeListeners),ptErrors:String(api.errors.length),ptObservers:String(api.nativeObservers||0),ptTimers:String(api.nativeTimers||0),ptReady:String(api.ready),ptDuration:String(api.lastTransition?.duration||0)});}
function report(error){api.errors.push(String(error?.message||error));diagnostics();console.error("[Diagonal Flow]",error)}
function cubic(x1,y1,x2,y2){
const coord=(t,a,b)=>3*(1-t)*(1-t)*t*a+3*(1-t)*t*t*b+t*t*t;
return p=>{if(p<=0||p>=1)return p;let lo=0,hi=1,t=p;for(let n=0;n<22;n++){t=(lo+hi)/2;if(coord(t,x1,x2)<p)lo=t;else hi=t}return coord(t,y1,y2)};
}
const parallax=cubic(.7,.05,.13,1),contentEase=cubic(.625,.05,0,1);
const config={duration:1.2,leaveY:"-20vh",enterY:"100vh",revealAt:.33,
clipStart:"polygon(0% 100%, 100% 40%, 100% 100%, 0% 100%)",
clipMid:"polygon(0% 60%, 100% 0%, 100% 100%, 0% 100%)",
clipEnd:"polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)"};
api.config={...config,ease:[.7,.05,.13,1],contentEase:[.625,.05,0,1]};
function nativeRecord(marker){
let node=marker;
while(node&&node.parentElement){
if(Array.from(node.children).some(c=>c.tagName==="SCRIPT"&&/t396_init\s*\(/.test(c.textContent)))return node;
node=node.parentElement;
}
return null;
}
function prepare(doc,url){
const existing=doc.querySelector(".pt-page");
if(existing)return existing;
const markers=Array.from(doc.querySelectorAll(".pt-section-marker"));
const discovered=Array.from(doc.querySelectorAll("script")).filter(s=>!s.src&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(s.textContent)&&/t396_init\s*\(/.test(s.textContent)).map(s=>s.parentElement);
const records=Array.from(new Set([...markers.map(nativeRecord).filter(Boolean),...discovered])).filter(n=>!n.closest("header,footer"));
if(!records.length)return null;
records.forEach(n=>n.classList.add("pt-section"));
const site=records[0].parentElement;
site.classList.add("pt-site");site.setAttribute("data-barba","wrapper");
const page=doc.createElement("main");page.className="pt-page";
page.setAttribute("data-barba","container");
page.setAttribute("data-barba-namespace",new URL(url||location.href,location.href).pathname);
const children=Array.from(site.childNodes);
site.insertBefore(page,site.firstChild);
children.forEach(n=>{if(n.nodeType===1&&["HEADER","FOOTER"].includes(n.tagName)){n.classList.add("pt-shared");return;}if(n.nodeType===1)n.classList.add("pt-native-record");page.appendChild(n)});
page.querySelectorAll("*").forEach(n=>{if(n.hasAttribute("data-animate-sbs-event"))n.classList.add("pt-native-sbs")});
return page;
}
function pageState(page){
let s=pageStates.get(page);
if(!s){s={context:null,listeners:[],timers:[],nativeReady:false,reveals:[],cleanup:[]};pageStates.set(page,s)}
return s;
}
const frame=()=>new Promise(resolve=>requestAnimationFrame(resolve));
const bounded=(p,ms)=>Promise.race([p,new Promise((_,reject)=>setTimeout(()=>reject(Error("Page readiness timeout")),ms))]);
async function fontsReady(){if(document.fonts)await bounded(document.fonts.ready,3000).catch(()=>{})}
function loadCSS(href){
const absolute=new URL(href,location.href).href;
const present=Array.from(document.querySelectorAll('link[rel="stylesheet"]')).find(n=>n.href===absolute);
if(present?.sheet)return Promise.resolve();
if(cssLoads.has(absolute))return cssLoads.get(absolute);
const p=new Promise((resolve,reject)=>{
const link=present||document.createElement("link");
link.rel="stylesheet";link.href=absolute;
link.addEventListener("load",resolve,{once:true});link.addEventListener("error",()=>reject(Error("Stylesheet failed: "+absolute)),{once:true});
if(!present){link.classList.add("pt-loaded-style");document.head.appendChild(link)}
setTimeout(()=>{if(link.sheet)resolve();else reject(Error("Stylesheet timeout: "+absolute))},8000);
});cssLoads.set(absolute,p);return p;
}
function loadScript(src,scope){
const absolute=new URL(src,location.href).href;
if(scriptLoads.has(absolute))return scriptLoads.get(absolute);
if(loadedScripts.has(absolute))return Promise.resolve();
if(/tilda-blocks-page[^/]*\.js(?:\?|$)/.test(absolute)){
const p=fetch(absolute).then(response=>{if(!response.ok)throw Error("Page bundle failed: "+absolute);return response.text()}).then(source=>{
const names=Array.from(new Set(Array.from(source.matchAll(/\bfunction\s+([A-Za-z_$][\w$]*)\s*\(/g),m=>m[1])));
const expose=names.map(name=>'if(typeof '+name+'==="function"&&typeof window['+JSON.stringify(name)+']!=="function")window['+JSON.stringify(name)+']='+name+';').join("\n");
inNative(scope,()=>Function(source+"\n;"+expose+"\n//# sourceURL="+absolute)());
});
scriptLoads.set(absolute,p);return p;
}
const p=new Promise((resolve,reject)=>{const s=document.createElement("script");s.src=absolute;if(scope)scriptOwners.set(s,scope);s.onload=()=>{loadedScripts.add(absolute);resolve()};s.onerror=()=>reject(Error("Dependency failed: "+absolute));document.head.appendChild(s)});
scriptLoads.set(absolute,p);return p;
}
async function syncAssets(html,page){
const scope=scopeFor(page);scope.formsBefore=new Set(Object.keys(window.initForms||{}));
const doc=new DOMParser().parseFromString(html,"text/html");
const source=prepare(doc,location.href)?.parentElement;
const target=document.querySelector(".pt-site");
if(source&&target)for(const a of Array.from(source.attributes))if(a.name.startsWith("data-tilda-"))target.setAttribute(a.name,a.value);
await Promise.all(Array.from(doc.querySelectorAll('link[rel="stylesheet"]')).map(n=>loadCSS(n.href)));
// Keep libraries once; load missing Tilda dependencies, never a second GSAP/Barba/bootstrap.
for(const s of Array.from(doc.querySelectorAll("script[src]"))){
if(/tilda(?:cdn|cdn\.com)|tildacdn|tilda\.ws/.test(s.src)&&!s.src.includes("tilda-events")){
const already=loadedScripts.has(s.src)||scriptLoads.has(s.src);
if(!already&&s.src.includes("tilda-animation-sbs"))scope.sbsAuto=true;
if(!already&&s.src.includes("tilda-animation-2."))scope.basicAuto=true;
await loadScript(s.src,scope);
}
}
const selector='meta[name="description"],meta[name="robots"],link[rel="canonical"],meta[property^="og:"],meta[name^="twitter:"]';
document.head.querySelectorAll(selector).forEach(n=>n.remove());
doc.head.querySelectorAll(selector).forEach(n=>document.head.appendChild(document.importNode(n,true)));
}
async function nativeInit(page){
const s=pageState(page);if(s.nativeReady)return;
const scope=scopeFor(page);
if(typeof window.t396_init!=="function")await bounded(new Promise(resolve=>window.t_onFuncLoad("t396_init",resolve)),8000);
for(const block of page.querySelectorAll(".pt-native-record")){
if(block.querySelector(".pt-bootstrap,.pt-style"))continue;
const scripts=Array.from(block.querySelectorAll("script")).filter(n=>!n.src&&!n.type?.includes("json")&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(n.textContent));
for(const script of scripts){inNative(scope,()=>Function(script.textContent)());executedScripts.add(script);api.nativeInits++;}
}
await frame();await frame();
s.nativeReady=true;
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
scope.formKeys=Object.keys(window.initForms||{}).filter(k=>!scope.formsBefore?.has(k));
window.dispatchEvent(new Event("resize"));
await fontsReady();await frame();refreshNativeCounts();
}
function scriptEnvironment(page){
const selectAll=selector=>{
if(selector==="body")return [document.body];if(selector==="html"||selector===":root")return [document.documentElement];
return [...page.querySelectorAll(selector),...Array.from(document.querySelectorAll(".pt-shared")).flatMap(n=>[...(n.matches(selector)?[n]:[]),...n.querySelectorAll(selector)])];
};
let scriptNode=null;
const doc=new Proxy(document,{get(target,key){
if(key==="currentScript")return scriptNode;
if(key==="querySelector")return selector=>selectAll(selector)[0]||null;
if(key==="querySelectorAll")return selectAll;
if(key==="getElementById")return id=>Array.from(page.querySelectorAll("[id]")).find(n=>n.id===id)||null;
const value=Reflect.get(target,key,target);return typeof value==="function"?value.bind(target):value;
}});
const win=window;
const jq=window.jQuery&&new Proxy(window.jQuery,{apply(target,thisArg,args){
if(args[0]===doc)args[0]=document;if(args[0]===win)args[0]=window;
if(typeof args[0]==="string"&&args.length===1&&!args[0].trim().startsWith("<"))return target(selectAll(args[0]));
return Reflect.apply(target,thisArg,args);
}});
return {doc,win,jq,setScript:n=>scriptNode=n};
}
async function customInit(page){
const state=pageState(page),s=scopeFor(page);if(state.customReady)return;
state.customReady=true;s.replay=true;
const env=scriptEnvironment(page);
for(const script of Array.from(page.querySelectorAll("script"))){
if(executedScripts.has(script)||script.closest(".pt-shared")||script.classList.contains("pt-bootstrap")||script.parentElement?.querySelector(":scope > .pt-bootstrap"))continue;
const type=script.type.trim().toLowerCase();
if(type&&!/^(?:module|(?:text|application)\/(?:java|ecma)script)$/.test(type))continue;
try{
if(script.src){
await loadScript(script.src,null);executedScripts.add(script);continue;
}
if(!script.textContent.trim())continue;
env.setScript(script);scriptOwners.set(script,s);
const fn=Function("window","document","$","jQuery",(type==="module"?'"use strict";\n':"")+script.textContent);
inNative(s,fn,window,[env.win,env.doc,env.jq,env.jq]);
executedScripts.add(script);s.customCount++;api.customInits=(api.customInits||0)+1;
}catch(error){report(error)}
}
flushJobs(s,"readyJobs");
diagnostics();
}
async function customAfterEnter(page){
const s=scopeFor(page);if(!s.replay)return;
await fontsReady();await frame();
flushJobs(s,"loadJobs");flushJobs(s,"readyJobs");
refreshNativeCounts();diagnostics();
}
function nativeAfterEnter(page){
const scope=scopeFor(page);
inNative(scope,()=>{
if(typeof window.t_lazyload_update==="function")window.t_lazyload_update();
if(typeof window.t_animate__init==="function"&&!scope.basicAuto)window.t_animate__init();
if(page.querySelector(".pt-native-sbs")&&typeof window.t_animationSBS__init==="function"&&!scope.sbsAuto)window.t_animationSBS__init();
});
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
refreshNativeCounts();
}
function freezeFixed(page){
const s=pageState(page);if(s.fixedFrozen)return;
const properties=["position","top","left","right","bottom","width","height","box-sizing"];
const items=Array.from(page.querySelectorAll("*")).filter(node=>getComputedStyle(node).position==="fixed").map(node=>({
node,rect:node.getBoundingClientRect(),values:properties.map(p=>[p,node.style.getPropertyValue(p),node.style.getPropertyPriority(p)])
})).filter(item=>item.rect.width>0&&item.rect.height>0);
s.fixedFrozen=items;
for(const item of items){
const {node,rect}=item;
node.classList.add("pt-fixed-frozen");
const set=(p,v)=>node.style.setProperty(p,v,"important");
set("position","absolute");set("top","0px");set("left","0px");set("right","auto");set("bottom","auto");
const parent=node.offsetParent,box=parent?.getBoundingClientRect();
const sx=parent?.offsetWidth&&box?.width?box.width/parent.offsetWidth:1;
const sy=parent?.offsetHeight&&box?.height?box.height/parent.offsetHeight:1;
set("box-sizing","border-box");set("width",rect.width/sx+"px");set("height",rect.height/sy+"px");
const moved=node.getBoundingClientRect();
set("left",(rect.left-moved.left)/sx+"px");set("top",(rect.top-moved.top)/sy+"px");
}
}
function restoreFixed(page){
const s=pageStates.get(page);if(!s?.fixedFrozen)return;
for(const item of s.fixedFrozen){
for(const [property,value,priority] of item.values){
if(value)item.node.style.setProperty(property,value,priority);else item.node.style.removeProperty(property);
}
item.node.classList.remove("pt-fixed-frozen");
}
s.fixedFrozen=null;
}
function cleanup(page){
const s=pageStates.get(page);if(!s)return;
restoreFixed(page);
disposeNative(page);
s.context?.revert();s.cleanup.forEach(f=>f());
s.listeners.forEach(({target,type,listener,options})=>{target.removeEventListener(type,listener,options);api.activeNativeListeners--});
s.cleanup=[];s.listeners=[];s.context=null;pageStates.delete(page);
}
function lock(){
if(state.busy)return;
state.busy=true;state.oldScroll=window.scrollY;state.oldFocus=document.activeElement;
document.documentElement.classList.add("pt-busy");
}
function unlock(){state.busy=false;state.pending=false;document.documentElement.classList.remove("pt-busy")}
function focusPage(page){
const heading=page.querySelector(".pt-title h1,.pt-title h2,.pt-title h3")||page;
const prev=heading.getAttribute("tabindex");
heading.setAttribute("tabindex","-1");heading.focus({preventScroll:true});
heading.addEventListener("blur",()=>{if(prev===null)heading.removeAttribute("tabindex");else heading.setAttribute("tabindex",prev)},{once:true});
}
function blockScroll(e){if(state.busy)e.preventDefault()}
function blockKeys(e){if(state.busy&&["ArrowDown","ArrowUp","PageDown","PageUp","Home","End"," "].includes(e.key))e.preventDefault()}
function restore(page){
state.oldScroll=0;
window.scrollTo({top:0,left:0,behavior:"instant"});
gsap.set(page,{clearProps:"position,top,right,bottom,left,width,height,zIndex,transform,clipPath,webkitClipPath,willChange,visibility,borderRadius"});
page.classList.remove("pt-incoming");restoreFixed(page);page.inert=false;
gsap.set(veil,{autoAlpha:0});
}
let veil;
async function start(){
if(!window.gsap||!window.barba||!window.ScrollTrigger)throw Error("GSAP, ScrollTrigger or Barba failed to load");
gsap.registerPlugin(ScrollTrigger);
gsap.ticker.lagSmoothing(0);
const first=prepare(document,location.href);if(!first)throw Error("No native Zero Blocks found");
initialPage=first;
if(initialScope){initialScope.page=first;pageState(first).nativeScope=initialScope}
Array.from(document.scripts).forEach(s=>{if(s.src)loadedScripts.add(s.src)});
document.documentElement.classList.add("pt-root");
pageState(first).nativeReady=true;
scopeFor(first).formKeys=Object.keys(window.initForms||{});
if(window.onpopstate)inNative(scopeFor(first),()=>{window.onpopstate=window.onpopstate});
history.scrollRestoration="manual";
veil=document.createElement("div");veil.className="pt-veil";veil.style.backgroundColor=TRANSITION_BACKGROUND;veil.setAttribute("aria-hidden","true");document.querySelector(".pt-site").appendChild(veil);
const baseToDocument=barba.dom.toDocument.bind(barba.dom);
barba.dom.toDocument=function(html){const doc=baseToDocument(html);prepare(doc,location.href);return doc};
barba.dom.toElement=function(html){return barba.dom.toDocument(html).documentElement};
barba.hooks.before(data=>{
lock();freezeFixed(data.current.container);state.epoch++;data.current.container.inert=true;
scopeFor(data.current.container).paused=true;
api.lastTransition={from:data.current.url.path,to:data.next.url.path,started:performance.now(),epoch:state.epoch};
});
barba.hooks.beforeEnter(async data=>{
const next=data.next.container;
if(!api.ready)return;
next.classList.add("pt-incoming");next.inert=true;
gsap.set(next,{width:document.documentElement.clientWidth,zIndex:3,y:"100vh",visibility:"hidden"});
await syncAssets(data.next.html,next);
await nativeInit(next);
await customInit(next);
freezeFixed(next);
});
barba.hooks.afterLeave(data=>{
cleanup(data.current.container);
data.current.container.remove();
});
barba.hooks.afterEnter(async data=>{
restore(data.next.container);nativeAfterEnter(data.next.container);await customAfterEnter(data.next.container);ScrollTrigger.refresh();
});
barba.hooks.after(data=>{
unlock();data.next.container.classList.add("pt-ready");focusPage(data.next.container);
refreshNativeCounts();api.transitions++;api.lastTransition.finished=performance.now();
api.lastTransition.duration=api.lastTransition.finished-api.lastTransition.started;diagnostics();
document.dispatchEvent(new CustomEvent("pt:after",{detail:{url:location.href,count:api.transitions}}));
});
barba.init({timeout:10000,preventRunning:true,cacheIgnore:false,prefetchIgnore:false,
prevent:({el,href})=>{
if(window.innerWidth<320||!el.closest(".pt-link,.fs-link")||el.hasAttribute("download"))return true;
const u=new URL(href,location.href);
return u.origin!==location.origin||!!u.hash;
},
requestError:(_trigger,_action,url,error)=>{report(error);unlock();return true},
transitions:[{name:"diagonal-parallax",sync:true,
async once(data){await fontsReady();await frame();api.ready=true;diagnostics()},
leave(data){
const old=data.current.container;
gsap.set(old,{position:"relative",zIndex:1,borderRadius:TRANSITION_RADIUS,...(TRANSITION_RADIUS>0?{overflow:"clip"}:{})});
const tl=gsap.timeline();
tl.fromTo(veil,{autoAlpha:0},{autoAlpha:.5,duration:config.duration,ease:parallax},0);
tl.fromTo(old,{y:"0vh",force3D:false},{y:config.leaveY,duration:config.duration,ease:parallax,force3D:false},0);
return tl;
},
enter(data){
const next=data.next.container;
const tl=gsap.timeline();
tl.set(next,{visibility:"visible",borderRadius:TRANSITION_RADIUS,willChange:"clip-path",clipPath:config.clipStart,webkitClipPath:config.clipStart},0);
tl.fromTo(next,{y:config.enterY,force3D:false},{y:"0vh",duration:config.duration,ease:parallax,force3D:false},0);
tl.to(next,{clipPath:config.clipMid,webkitClipPath:config.clipMid,duration:.22,ease:parallax},0);
tl.to(next,{clipPath:config.clipEnd,webkitClipPath:config.clipEnd,duration:.76,ease:parallax},.22);
return tl;
}
}]
});
document.addEventListener("click",e=>{
const link=e.target.closest?.(".pt-link a,a.pt-link,.fs-link a,a.fs-link");if(!link||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;
if(state.busy||state.pending){e.preventDefault();e.stopImmediatePropagation();return}
if(window.innerWidth<320)return;
const href=new URL(link.href,location.href);
if(href.origin!==location.origin||href.hash||link.target==="_blank")return;
if(href.pathname===location.pathname&&href.search===location.search){e.preventDefault();e.stopImmediatePropagation();return}
state.pending=true;
},true);
window.addEventListener("scroll",()=>{if(state.busy&&window.scrollY!==state.oldScroll)window.scrollTo(0,state.oldScroll)},{passive:true});
window.addEventListener("wheel",blockScroll,{passive:false});
window.addEventListener("touchmove",blockScroll,{passive:false});
window.addEventListener("keydown",blockKeys);
api.status=()=>({ready:api.ready,busy:state.busy,pending:state.pending,transitions:api.transitions,
containers:document.querySelectorAll(".pt-page").length,sections:document.querySelectorAll(".pt-page .pt-section").length,
nativeInits:api.nativeInits,nativeListeners:api.activeNativeListeners,documentToken:api.documentToken,errors:api.errors.slice()});
}
const ready=()=>start().catch(error=>{report(error);unlock()});
if(document.readyState==="loading")raw.add.call(document,"DOMContentLoaded",ready,{once:true});else ready();
})();
</script>
Сдвиг кадра (Frame Shift)
В начало страницы или шапку добавляем код, через блок T123
CSS / JS

<!--Бесшовный переход
https://mt-webdesign.ru/seamless-->
<style class="fs-style">
.fs-root{scrollbar-gutter:stable;scroll-behavior:auto!important}
.fs-root.fs-busy{overscroll-behavior:none}
.fs-page{position:relative}
.fs-incoming{position:fixed!important;top:0;left:0;height:100vh;overflow:clip;pointer-events:none}
.fs-stage-content{position:relative;width:100%}
.fs-flow-spacer{pointer-events:none;visibility:hidden}
.fs-backdrop{position:fixed;inset:0;z-index:0;background:#000;opacity:0;visibility:hidden;pointer-events:none}
</style>
<script src="https://matilda-design.ru/library/GSAP.js"></script>
<script src="https://matilda-design.ru/library/ScrollTrigger.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@barba/core@2.10.3/dist/barba.umd.js"></script>
<script class="fs-bootstrap">
(function(){
"use strict";
// Цвет подложки, видимой во время перехода.
const TRANSITION_BACKGROUND = "#a1ff62";
// Скругление углов во время перехода.
const TRANSITION_RADIUS = 12;
if(window.TildaFrameShift)return;
const api=window.TildaFrameShift={
version:"1.1.0-lifecycle",documentToken:Date.now().toString(36)+"-"+Math.random().toString(36).slice(2),
bootCount:1,transitions:0,nativeInits:0,activeNativeListeners:0,errors:[],
lastTransition:null,ready:false
};
const state={pending:false,busy:false,oldScroll:0,oldFocus:null,lockStyles:null,epoch:0};
const pageStates=new WeakMap();
const scriptLoads=new Map();
const loadedScripts=new Set(Array.from(document.scripts,s=>s.src).filter(Boolean));
const executedScripts=new WeakSet();
let initialScope=null,initialPage=null;
function makeScope(page){return {
key:"fsRuntime"+(++nativeSerial),page,disposed:false,listeners:new Set(),timers:new Set(),intervals:new Set(),
frames:new Set(),observers:new Set(),jquery:new Set(),styles:new Set(),portals:new Set(),formKeys:[],sbsAuto:false,
readyJobs:[],loadJobs:[],replay:false,customCount:0,contexts:new Set(),webgl:new Set()
}}
function lifecycleJob(s,target,type,callback,options){
if(!s?.replay||!callback||!((target===document&&type==="DOMContentLoaded")||(target===window&&type==="load")))return false;
const name=type==="load"?"loadJobs":"readyJobs",queue=s[name];
if(s[name+"Done"]){raw.timeout(()=>{try{inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?target:callback,[new Event(type)])}catch(error){report(error)}},0);return true}
if(!queue.some(j=>j.callback===callback&&j.target===target))queue.push({target,type,callback,options});
return true;
}
function flushJobs(s,name){
const jobs=s[name].splice(0);
for(const j of jobs){if(s.disposed)break;try{
const fn=typeof j.callback==="function"?j.callback:j.callback.handleEvent;
inNative(s,fn,typeof j.callback==="function"?j.target:j.callback,[new Event(j.type)]);
}catch(error){report(error)}}
s[name+"Done"]=true;
}
let nativeOwner=null,nativeSerial=0;
const scriptOwners=new WeakMap();
const raw={
add:EventTarget.prototype.addEventListener,remove:EventTarget.prototype.removeEventListener,
timeout:window.setTimeout.bind(window),clearTimeout:window.clearTimeout.bind(window),interval:window.setInterval.bind(window),clearInterval:window.clearInterval.bind(window),
raf:window.requestAnimationFrame.bind(window),caf:window.cancelAnimationFrame.bind(window),
append:Node.prototype.appendChild,insert:Node.prototype.insertBefore,
xhrSend:window.XMLHttpRequest?.prototype.send
};
let routeHistory=null;
for(const method of ["pushState","replaceState"]){
const original=history[method].bind(history);
history[method]=function(value,title,url){
if(value?.from==="barba")routeHistory=value;
else if(api.ready||owner()){
const base=history.state?.from==="barba"?history.state:routeHistory;
if(base)value={from:base.from,index:base.index,states:base.states,...(value||{})};
}
return original(value,title,url);
};
}
const popstateDescriptor=Object.getOwnPropertyDescriptor(window,"onpopstate");
if(popstateDescriptor?.get&&popstateDescriptor?.set&&popstateDescriptor.configurable){
Object.defineProperty(window,"onpopstate",{configurable:true,enumerable:popstateDescriptor.enumerable,
get(){return popstateDescriptor.get.call(window)},
set(fn){const s=owner(),wrapped=s&&typeof fn==="function"?function(event){
if(s.disposed)return;
const value=event?.state||history.state;
if(value?.storepartuid&&!value.productData){
const active=document.querySelector(".fs-page:not(.fs-incoming)");
if(active?.getAttribute("data-barba-namespace")!==location.pathname)return;
if(value.opts&&typeof window.t_catalog_loadProducts==="function"){
value.opts.isPublishedPage=true;
return inNative(s,window.t_catalog_loadProducts,window,["",value.recid,value.opts]);
}
return;
}
return inNative(s,fn,this,[event]);
}:fn;
if(s)s.popstateHandler=wrapped;
popstateDescriptor.set.call(window,wrapped);
}
});
}
const listenerMap=new WeakMap();
function owner(){
if(nativeOwner)return nativeOwner;
const script=document.currentScript;
const known=script&&scriptOwners.get(script);if(known)return known;
if(!initialPage&&((script&&!script.src&&!script.classList.contains("fs-bootstrap")&&!script.closest("header,footer"))||(!script&&document.readyState==="interactive"))){
initialScope=initialScope||makeScope(null);if(script)scriptOwners.set(script,initialScope);return initialScope;
}
return null;
}
function scopeFor(page){const s=pageState(page);if(!s.nativeScope)s.nativeScope=makeScope(page);return s.nativeScope}
function inNative(s,fn,thisArg,args){
if(s?.disposed||s?.paused)return;
const before=nativeOwner,classes=new Set(document.body?.classList||[]);nativeOwner=s;
try{
if(s&&window.gsap?.context){
if(!s.gsapContext||s.gsapOwner!==window.gsap){s.gsapOwner=window.gsap;s.gsapContext=gsap.context(()=>{});s.contexts.add(s.gsapContext)}
let result;s.gsapContext.add(()=>{result=fn.apply(thisArg,args||[])});return result;
}
return fn.apply(thisArg,args||[]);
}finally{
if(s){s.bodyClasses=s.bodyClasses||new Set();for(const name of document.body?.classList||[])if(!classes.has(name))s.bodyClasses.add(name)}
nativeOwner=before;
}
}
function owned(s,fn){if(typeof fn!=="function")return fn;return function(...args){return inNative(s,fn,this,args)}}
function refreshNativeCounts(){
let globals=0,observers=0,timers=0;
document.querySelectorAll(".fs-page").forEach(p=>{const s=pageStates.get(p)?.nativeScope;if(s&&!s.disposed){globals+=Array.from(s.listeners).filter(r=>r.target===window||r.target===document||r.target===document.body).length;observers+=s.observers.size;timers+=s.timers.size+s.intervals.size}});
api.activeNativeListeners=globals;api.nativeObservers=observers;api.nativeTimers=timers;
}
let jqueryRegistering=false;
EventTarget.prototype.addEventListener=function(type,callback,options){
const s=owner();
if(lifecycleJob(s,this,type,callback,options))return;
if(!s||!callback||jqueryRegistering)return raw.add.call(this,type,callback,options);
const capture=typeof options==="boolean"?options:!!options?.capture;
let list=listenerMap.get(this);if(!list){list=[];listenerMap.set(this,list)}
const existing=list.find(r=>r.s===s&&r.type===type&&r.callback===callback&&r.capture===capture);
if(existing)return raw.add.call(this,type,existing.wrapped,options);
const r={s,target:this,type,callback,capture,options,wrapped:null};
r.wrapped=function(...args){if(options?.once){s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)}
return inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?this:callback,args)};
list.push(r);s.listeners.add(r);return raw.add.call(this,type,r.wrapped,options);
};
EventTarget.prototype.removeEventListener=function(type,callback,options){
const activeScope=owner();
if(activeScope?.replay)for(const name of ["readyJobs","loadJobs"])activeScope[name]=activeScope[name].filter(j=>!(j.target===this&&j.type===type&&j.callback===callback));
const list=listenerMap.get(this),capture=typeof options==="boolean"?options:!!options?.capture,s=owner();
const matches=list?.filter(r=>r.type===type&&r.callback===callback&&r.capture===capture&&(!s||r.s===s))||[];
if(!matches.length)return raw.remove.call(this,type,callback,options);
matches.forEach(r=>{raw.remove.call(this,type,r.wrapped,options);r.s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)});
};
window.setTimeout=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.timeout(fn,ms,...args);let id;id=raw.timeout(()=>{s.timers.delete(id);inNative(s,fn,window,args)},ms);s.timers.add(id);return id};
window.clearTimeout=function(id){const s=owner();s?.timers.delete(id);return raw.clearTimeout(id)};
window.setInterval=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.interval(fn,ms,...args);const id=raw.interval(owned(s,fn),ms,...args);s.intervals.add(id);return id};
window.clearInterval=function(id){const s=owner();s?.intervals.delete(id);return raw.clearInterval(id)};
window.requestAnimationFrame=function(fn){const s=owner();if(!s)return raw.raf.call(window,fn);let id;id=raw.raf.call(window,t=>{s.frames.delete(id);inNative(s,fn,window,[t])});s.frames.add(id);return id};
window.cancelAnimationFrame=function(id){owner()?.frames.delete(id);return raw.caf.call(window,id)};
for(const key of ["IntersectionObserver","ResizeObserver","MutationObserver"]){
const Original=window[key];if(!Original)continue;
window[key]=new Proxy(Original,{construct(Target,args,newTarget){const s=owner();if(s)args[0]=owned(s,args[0]);const observer=Reflect.construct(Target,args,newTarget===window[key]?Target:newTarget);if(s)s.observers.add(observer);return observer}});
}
function noteInsertion(parent,node){const s=owner();if(!s||!node)return;if(parent===document.head&&node.tagName==="STYLE")s.styles.add(node);if(parent===document.body&&node.tagName==="DIV"){node.classList.add("fs-native-portal");s.portals.add(node)}}
Node.prototype.appendChild=function(node){noteInsertion(this,node);return raw.append.call(this,node)};
Node.prototype.insertBefore=function(node,before){noteInsertion(this,node);return raw.insert.call(this,node,before)};
if(raw.xhrSend)XMLHttpRequest.prototype.send=function(...args){const s=owner();if(s)for(const name of ["onreadystatechange","onload","onerror","onloadend"]){if(typeof this[name]==="function")this[name]=owned(s,this[name])}return raw.xhrSend.apply(this,args)};
if(window.jQuery){
const $=window.jQuery,baseOn=$.fn.on,baseReady=$.fn.ready;
$.fn.ready=function(fn){const s=owner();if(!s)return baseReady.call(this,fn);
if(s.replay){lifecycleJob(s,document,"DOMContentLoaded",function(){return fn.call(document,$)});return this}
return baseReady.call(this,owned(s,fn));
};
$.fn.on=function(...args){const s=owner();if(!s)return baseOn.apply(this,args);
if(s.replay&&this.length===1&&this[0]===window&&typeof args[0]==="string"&&args[0].split(/\s+/).every(t=>t.split(".")[0]==="load")){
const callback=args.slice(1).findLast(a=>typeof a==="function");
if(callback){lifecycleJob(s,window,"load",callback);return this}
}
const ns="."+s.key;
const names=t=>t.split(/\s+/).filter(Boolean).map(t=>t+ns).join(" ");
if(typeof args[0]==="string")args[0]=names(args[0]);
else if(args[0]&&typeof args[0]==="object")args[0]=Object.fromEntries(Object.entries(args[0]).map(([k,v])=>[names(k),owned(s,v)]));
for(let i=1;i<args.length;i++)if(typeof args[i]==="function"){const original=args[i],wrapped=owned(s,original);wrapped.guid=original.guid||(original.guid=$.guid++);args[i]=wrapped}
s.jquery.add(this);const previous=jqueryRegistering;jqueryRegistering=true;try{return baseOn.apply(this,args)}finally{jqueryRegistering=previous}
};
}
function disposeNative(page){
const s=pageStates.get(page)?.nativeScope;if(!s)return;
s.disposed=true;
if(s.popstateHandler&&window.onpopstate===s.popstateHandler)window.onpopstate=null;
s.listeners.forEach(r=>{raw.remove.call(r.target,r.type,r.wrapped,r.options);const list=listenerMap.get(r.target);const i=list?.indexOf(r);if(i>=0)list.splice(i,1)});
s.timers.forEach(raw.clearTimeout);s.intervals.forEach(raw.clearInterval);s.frames.forEach(id=>raw.caf.call(window,id));
s.observers.forEach(o=>o.disconnect());s.jquery.forEach(q=>q.off("."+s.key));
s.contexts.forEach(c=>c.revert());s.webgl.forEach(gl=>gl.getExtension("WEBGL_lose_context")?.loseContext());
s.readyJobs.length=0;s.loadJobs.length=0;s.bodyClasses?.forEach(name=>document.body.classList.remove(name));
s.styles.forEach(n=>n.remove());s.portals.forEach(n=>n.remove());
if(window.initForms)s.formKeys.forEach(k=>delete window.initForms[k]);
s.listeners.clear();s.timers.clear();s.intervals.clear();s.frames.clear();s.observers.clear();s.jquery.clear();
refreshNativeCounts();
}
const rawGetContext=HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext=function(...args){const gl=rawGetContext.apply(this,args),s=owner();if(s&&gl&&/webgl/i.test(args[0]))s.webgl.add(gl);return gl};
const cssLoads=new Map();
function diagnostics(){const site=document.querySelector(".fs-site");if(!site)return;Object.assign(site.dataset,{fsDocument:api.documentToken,fsTransitions:String(api.transitions),fsNativeInits:String(api.nativeInits),fsCustomInits:String(api.customInits||0),fsVersion:api.version,fsNativeListeners:String(api.activeNativeListeners),fsErrors:String(api.errors.length),fsObservers:String(api.nativeObservers||0),fsTimers:String(api.nativeTimers||0),fsReady:String(api.ready),fsDuration:String(api.lastTransition?.duration||0)});}
function report(error){api.errors.push(String(error?.message||error));diagnostics();console.error("[Frame Shift]",error)}
const config={duration:3,phaseDuration:1,scale:.8,borderRadius:TRANSITION_RADIUS,ease:"expo.inOut"};
api.config={...config};
function nativeRecord(marker){
let node=marker;
while(node&&node.parentElement){
if(Array.from(node.children).some(c=>c.tagName==="SCRIPT"&&/t396_init\s*\(/.test(c.textContent)))return node;
node=node.parentElement;
}
return null;
}
function prepare(doc,url){
const existing=doc.querySelector(".fs-page");
if(existing)return existing;
const markers=Array.from(doc.querySelectorAll(".fs-section-marker"));
const discovered=Array.from(doc.querySelectorAll("script")).filter(s=>!s.src&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(s.textContent)&&/t396_init\s*\(/.test(s.textContent)).map(s=>s.parentElement);
const records=Array.from(new Set([...markers.map(nativeRecord).filter(Boolean),...discovered])).filter(n=>!n.closest("header,footer"));
if(!records.length)return null;
records.forEach(n=>n.classList.add("fs-section"));
const site=records[0].parentElement;
site.classList.add("fs-site");site.setAttribute("data-barba","wrapper");
const page=doc.createElement("main");page.className="fs-page";
page.setAttribute("data-barba","container");
page.setAttribute("data-barba-namespace",new URL(url||location.href,location.href).pathname);
const children=Array.from(site.childNodes);
site.insertBefore(page,site.firstChild);
children.forEach(n=>{if(n.nodeType===1&&["HEADER","FOOTER"].includes(n.tagName)){n.classList.add("fs-shared");return;}if(n.nodeType===1)n.classList.add("fs-native-record");page.appendChild(n)});
page.querySelectorAll("*").forEach(n=>{if(n.hasAttribute("data-animate-sbs-event"))n.classList.add("fs-native-sbs")});
return page;
}
function pageState(page){
let s=pageStates.get(page);
if(!s){s={context:null,listeners:[],timers:[],nativeReady:false,reveals:[],cleanup:[]};pageStates.set(page,s)}
return s;
}
const frame=()=>new Promise(resolve=>requestAnimationFrame(resolve));
const bounded=(p,ms)=>Promise.race([p,new Promise((_,reject)=>setTimeout(()=>reject(Error("Page readiness timeout")),ms))]);
async function fontsReady(){if(document.fonts)await bounded(document.fonts.ready,3000).catch(()=>{})}
function loadCSS(href){
const absolute=new URL(href,location.href).href;
const present=Array.from(document.querySelectorAll('link[rel="stylesheet"]')).find(n=>n.href===absolute);
if(present?.sheet)return Promise.resolve();
if(cssLoads.has(absolute))return cssLoads.get(absolute);
const p=new Promise((resolve,reject)=>{
const link=present||document.createElement("link");
link.rel="stylesheet";link.href=absolute;
link.addEventListener("load",resolve,{once:true});link.addEventListener("error",()=>reject(Error("Stylesheet failed: "+absolute)),{once:true});
if(!present){link.classList.add("fs-loaded-style");document.head.appendChild(link)}
setTimeout(()=>{if(link.sheet)resolve();else reject(Error("Stylesheet timeout: "+absolute))},8000);
});cssLoads.set(absolute,p);return p;
}
function loadScript(src,scope){
const absolute=new URL(src,location.href).href;
if(scriptLoads.has(absolute))return scriptLoads.get(absolute);
if(loadedScripts.has(absolute))return Promise.resolve();
if(/tilda-blocks-page[^/]*\.js(?:\?|$)/.test(absolute)){
const p=fetch(absolute).then(response=>{if(!response.ok)throw Error("Page bundle failed: "+absolute);return response.text()}).then(source=>{
const names=Array.from(new Set(Array.from(source.matchAll(/\bfunction\s+([A-Za-z_$][\w$]*)\s*\(/g),m=>m[1])));
const expose=names.map(name=>'if(typeof '+name+'==="function"&&typeof window['+JSON.stringify(name)+']!=="function")window['+JSON.stringify(name)+']='+name+';').join("\n");
inNative(scope,()=>Function(source+"\n;"+expose+"\n//# sourceURL="+absolute)());
});
scriptLoads.set(absolute,p);return p;
}
const p=new Promise((resolve,reject)=>{const s=document.createElement("script");s.src=absolute;if(scope)scriptOwners.set(s,scope);s.onload=()=>{loadedScripts.add(absolute);resolve()};s.onerror=()=>reject(Error("Dependency failed: "+absolute));document.head.appendChild(s)});
scriptLoads.set(absolute,p);return p;
}
async function syncAssets(html,page){
const scope=scopeFor(page);scope.formsBefore=new Set(Object.keys(window.initForms||{}));
const doc=new DOMParser().parseFromString(html,"text/html");
const source=prepare(doc,location.href)?.parentElement;
const target=document.querySelector(".fs-site");
if(source&&target)for(const a of Array.from(source.attributes))if(a.name.startsWith("data-tilda-"))target.setAttribute(a.name,a.value);
await Promise.all(Array.from(doc.querySelectorAll('link[rel="stylesheet"]')).map(n=>loadCSS(n.href)));
for(const s of Array.from(doc.querySelectorAll("script[src]"))){
if(/tilda(?:cdn|cdn\.com)|tildacdn|tilda\.ws/.test(s.src)&&!s.src.includes("tilda-events")){
const already=loadedScripts.has(s.src)||scriptLoads.has(s.src);
if(!already&&s.src.includes("tilda-animation-sbs"))scope.sbsAuto=true;
if(!already&&s.src.includes("tilda-animation-2."))scope.basicAuto=true;
await loadScript(s.src,scope);
}
}
const selector='meta[name="description"],meta[name="robots"],link[rel="canonical"],meta[property^="og:"],meta[name^="twitter:"]';
document.head.querySelectorAll(selector).forEach(n=>n.remove());
doc.head.querySelectorAll(selector).forEach(n=>document.head.appendChild(document.importNode(n,true)));
}
async function nativeInit(page){
const s=pageState(page);if(s.nativeReady)return;
const scope=scopeFor(page);
if(typeof window.t396_init!=="function")await bounded(new Promise(resolve=>window.t_onFuncLoad("t396_init",resolve)),8000);
for(const block of page.querySelectorAll(".fs-native-record")){
if(block.querySelector(".fs-bootstrap,.fs-style"))continue;
const scripts=Array.from(block.querySelectorAll("script")).filter(n=>!n.src&&!n.type?.includes("json")&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(n.textContent));
for(const script of scripts){inNative(scope,()=>Function(script.textContent)());executedScripts.add(script);api.nativeInits++;}
}
await frame();await frame();
s.nativeReady=true;
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
scope.formKeys=Object.keys(window.initForms||{}).filter(k=>!scope.formsBefore?.has(k));
window.dispatchEvent(new Event("resize"));
await fontsReady();await frame();refreshNativeCounts();
}
function scriptEnvironment(page){
const selectAll=selector=>{
if(selector==="body")return [document.body];if(selector==="html"||selector===":root")return [document.documentElement];
return [...page.querySelectorAll(selector),...Array.from(document.querySelectorAll(".fs-shared")).flatMap(n=>[...(n.matches(selector)?[n]:[]),...n.querySelectorAll(selector)])];
};
let scriptNode=null;
const doc=new Proxy(document,{get(target,key){
if(key==="currentScript")return scriptNode;
if(key==="querySelector")return selector=>selectAll(selector)[0]||null;
if(key==="querySelectorAll")return selectAll;
if(key==="getElementById")return id=>Array.from(page.querySelectorAll("[id]")).find(n=>n.id===id)||null;
const value=Reflect.get(target,key,target);return typeof value==="function"?value.bind(target):value;
}});
const win=window;
const jq=window.jQuery&&new Proxy(window.jQuery,{apply(target,thisArg,args){
if(args[0]===doc)args[0]=document;if(args[0]===win)args[0]=window;
if(typeof args[0]==="string"&&args.length===1&&!args[0].trim().startsWith("<"))return target(selectAll(args[0]));
return Reflect.apply(target,thisArg,args);
}});
return {doc,win,jq,setScript:n=>scriptNode=n};
}
async function customInit(page){
const state=pageState(page),s=scopeFor(page);if(state.customReady)return;
state.customReady=true;s.replay=true;
const env=scriptEnvironment(page);
for(const script of Array.from(page.querySelectorAll("script"))){
if(executedScripts.has(script)||script.closest(".fs-shared")||script.classList.contains("fs-bootstrap")||script.parentElement?.querySelector(":scope > .fs-bootstrap"))continue;
const type=script.type.trim().toLowerCase();
if(type&&!/^(?:module|(?:text|application)\/(?:java|ecma)script)$/.test(type))continue;
try{
if(script.src){
await loadScript(script.src,null);executedScripts.add(script);continue;
}
if(!script.textContent.trim())continue;
env.setScript(script);scriptOwners.set(script,s);
const fn=Function("window","document","$","jQuery",(type==="module"?'"use strict";\n':"")+script.textContent);
inNative(s,fn,window,[env.win,env.doc,env.jq,env.jq]);
executedScripts.add(script);s.customCount++;api.customInits=(api.customInits||0)+1;
}catch(error){report(error)}
}
flushJobs(s,"readyJobs");
diagnostics();
}
async function customAfterEnter(page){
const s=scopeFor(page);if(!s.replay)return;
await fontsReady();await frame();
flushJobs(s,"loadJobs");flushJobs(s,"readyJobs");
refreshNativeCounts();diagnostics();
}
function nativeAfterEnter(page){
const scope=scopeFor(page);
inNative(scope,()=>{
if(typeof window.t_lazyload_update==="function")window.t_lazyload_update();
if(typeof window.t_animate__init==="function"&&!scope.basicAuto)window.t_animate__init();
if(page.querySelector(".fs-native-sbs")&&typeof window.t_animationSBS__init==="function"&&!scope.sbsAuto)window.t_animationSBS__init();
});
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
refreshNativeCounts();
}
function freezeFixed(page){
const s=pageState(page);if(s.fixedFrozen)return;
const properties=["position","top","left","right","bottom","width","height","box-sizing"];
const items=Array.from(page.querySelectorAll("*")).filter(node=>getComputedStyle(node).position==="fixed").map(node=>({
node,rect:node.getBoundingClientRect(),values:properties.map(p=>[p,node.style.getPropertyValue(p),node.style.getPropertyPriority(p)])
})).filter(item=>item.rect.width>0&&item.rect.height>0);
s.fixedFrozen=items;
for(const item of items){
const {node,rect}=item;
node.classList.add("fs-fixed-frozen");
const set=(p,v)=>node.style.setProperty(p,v,"important");
set("position","absolute");set("top","0px");set("left","0px");set("right","auto");set("bottom","auto");
const parent=node.offsetParent,box=parent?.getBoundingClientRect();
const sx=parent?.offsetWidth&&box?.width?box.width/parent.offsetWidth:1;
const sy=parent?.offsetHeight&&box?.height?box.height/parent.offsetHeight:1;
set("box-sizing","border-box");set("width",rect.width/sx+"px");set("height",rect.height/sy+"px");
const moved=node.getBoundingClientRect();
set("left",(rect.left-moved.left)/sx+"px");set("top",(rect.top-moved.top)/sy+"px");
}
}
function restoreFixed(page){
const s=pageStates.get(page);if(!s?.fixedFrozen)return;
for(const item of s.fixedFrozen){
for(const [property,value,priority] of item.values){
if(value)item.node.style.setProperty(property,value,priority);else item.node.style.removeProperty(property);
}
item.node.classList.remove("fs-fixed-frozen");
}
s.fixedFrozen=null;
}
function stagePage(page,scroll=0){
const s=pageState(page);if(s.stage)return;
const properties=["position","top","left","right","bottom","width","height","overflow","background-color","border-radius","transform-origin","will-change","z-index","pointer-events"];
const values=properties.map(p=>[p,page.style.getPropertyValue(p),page.style.getPropertyPriority(p)]);
const rect=page.getBoundingClientRect();
let spacer=null;
if(!page.classList.contains("fs-incoming")){
spacer=document.createElement("div");spacer.className="fs-flow-spacer";
spacer.style.height=rect.height+"px";page.parentElement.insertBefore(spacer,page);
}
const content=document.createElement("div");content.className="fs-stage-content";
const nodes=Array.from(page.childNodes);nodes.forEach(node=>content.appendChild(node));page.appendChild(content);
content.style.top=-scroll+"px";
let color=getComputedStyle(page).backgroundColor;
if(color==="transparent"||color==="rgba(0, 0, 0, 0)")color=getComputedStyle(document.body).backgroundColor;
if(color==="transparent"||color==="rgba(0, 0, 0, 0)")color="#fff";
s.stage={content,spacer,values};
gsap.set(page,{position:"fixed",top:0,left:0,width:document.documentElement.clientWidth,height:window.innerHeight,overflow:"clip",backgroundColor:color,transformOrigin:"50% 50%"});
}
function restoreStage(page){
const s=pageStates.get(page);if(!s?.stage)return;
const {content,spacer,values}=s.stage;
while(content.firstChild)page.insertBefore(content.firstChild,content);
content.remove();spacer?.remove();
values.forEach(([property,value,priority])=>{if(value)page.style.setProperty(property,value,priority);else page.style.removeProperty(property)});
s.stage=null;
}
const motions=new WeakMap();
function frameShift(data){
if(motions.has(data))return motions.get(data);
const old=data.current.container,next=data.next.container;
const tl=gsap.timeline({defaults:{duration:config.phaseDuration,ease:config.ease}});
const done=new Promise(resolve=>tl.eventCallback("onComplete",resolve));
motions.set(data,done);
tl.set(backdrop,{autoAlpha:1},0);
tl.set(old,{zIndex:1,willChange:"transform,border-radius"},0);
tl.set(next,{visibility:"visible",zIndex:2,willChange:"transform,border-radius"},0);
tl.to(old,{scale:config.scale,borderRadius:config.borderRadius},0);
tl.to(old,{yPercent:-100},1);
tl.to(next,{yPercent:0},1);
tl.to(next,{scale:1,borderRadius:0},2);
return done;
}
function cleanup(page){
const s=pageStates.get(page);if(!s)return;
restoreFixed(page);
restoreStage(page);
disposeNative(page);
s.context?.revert();s.cleanup.forEach(f=>f());
s.listeners.forEach(({target,type,listener,options})=>{target.removeEventListener(type,listener,options);api.activeNativeListeners--});
s.cleanup=[];s.listeners=[];s.context=null;pageStates.delete(page);
}
function lock(){
if(state.busy)return;
state.busy=true;state.oldScroll=window.scrollY;state.oldFocus=document.activeElement;
document.documentElement.classList.add("fs-busy");
}
function unlock(){state.busy=false;state.pending=false;document.documentElement.classList.remove("fs-busy")}
function focusPage(page){
const heading=page.querySelector(".fs-title h1,.fs-title h2,.fs-title h3")||page;
const prev=heading.getAttribute("tabindex");
heading.setAttribute("tabindex","-1");heading.focus({preventScroll:true});
heading.addEventListener("blur",()=>{if(prev===null)heading.removeAttribute("tabindex");else heading.setAttribute("tabindex",prev)},{once:true});
}
function blockScroll(e){if(state.busy)e.preventDefault()}
function blockKeys(e){if(state.busy&&["ArrowDown","ArrowUp","PageDown","PageUp","Home","End"," "].includes(e.key))e.preventDefault()}
function restore(page){
state.oldScroll=0;
window.scrollTo({top:0,left:0,behavior:"instant"});
gsap.set(page,{clearProps:"position,top,right,bottom,left,width,height,zIndex,transform,clipPath,webkitClipPath,willChange,visibility,borderRadius,transformOrigin,pointerEvents"});
page.classList.remove("fs-incoming");restoreFixed(page);restoreStage(page);page.inert=false;
gsap.set(backdrop,{autoAlpha:0});
}
let backdrop;
async function start(){
if(!window.gsap||!window.barba||!window.ScrollTrigger)throw Error("GSAP, ScrollTrigger or Barba failed to load");
gsap.registerPlugin(ScrollTrigger);
gsap.ticker.lagSmoothing(0);
const first=prepare(document,location.href);if(!first)throw Error("No native Zero Blocks found");
initialPage=first;
if(initialScope){initialScope.page=first;pageState(first).nativeScope=initialScope}
Array.from(document.scripts).forEach(s=>{if(s.src)loadedScripts.add(s.src)});
document.documentElement.classList.add("fs-root");
pageState(first).nativeReady=true;
scopeFor(first).formKeys=Object.keys(window.initForms||{});
if(window.onpopstate)inNative(scopeFor(first),()=>{window.onpopstate=window.onpopstate});
history.scrollRestoration="manual";
backdrop=document.createElement("div");backdrop.className="fs-backdrop";backdrop.style.backgroundColor=TRANSITION_BACKGROUND;backdrop.setAttribute("aria-hidden","true");document.querySelector(".fs-site").appendChild(backdrop);
const baseToDocument=barba.dom.toDocument.bind(barba.dom);
barba.dom.toDocument=function(html){const doc=baseToDocument(html);prepare(doc,location.href);return doc};
barba.dom.toElement=function(html){return barba.dom.toDocument(html).documentElement};
barba.hooks.before(data=>{
lock();stagePage(data.current.container,state.oldScroll);freezeFixed(data.current.container);state.epoch++;data.current.container.inert=true;
scopeFor(data.current.container).paused=true;
api.lastTransition={from:data.current.url.path,to:data.next.url.path,started:performance.now(),epoch:state.epoch};
});
barba.hooks.beforeEnter(async data=>{
const next=data.next.container;
if(!api.ready)return;
next.classList.add("fs-incoming");next.inert=true;
stagePage(next,0);
gsap.set(next,{zIndex:2,yPercent:100,scale:config.scale,borderRadius:config.borderRadius,visibility:"hidden"});
await syncAssets(data.next.html,next);
await nativeInit(next);
await customInit(next);
freezeFixed(next);
});
barba.hooks.afterLeave(data=>{
cleanup(data.current.container);
data.current.container.remove();
});
barba.hooks.afterEnter(async data=>{
restore(data.next.container);nativeAfterEnter(data.next.container);await customAfterEnter(data.next.container);ScrollTrigger.refresh();
});
barba.hooks.after(data=>{
unlock();data.next.container.classList.add("fs-ready");focusPage(data.next.container);
refreshNativeCounts();api.transitions++;api.lastTransition.finished=performance.now();
api.lastTransition.duration=api.lastTransition.finished-api.lastTransition.started;diagnostics();
document.dispatchEvent(new CustomEvent("pt:after",{detail:{url:location.href,count:api.transitions}}));
});
barba.init({timeout:10000,preventRunning:true,cacheIgnore:false,prefetchIgnore:false,
prevent:({el,href})=>{
if(window.innerWidth<320||!el.closest(".fs-link")||el.hasAttribute("download"))return true;
const u=new URL(href,location.href);
return u.origin!==location.origin||!!u.hash;
},
requestError:(_trigger,_action,url,error)=>{report(error);unlock();return true},
transitions:[{name:"frame-shift",sync:true,
async once(data){await fontsReady();await frame();api.ready=true;diagnostics()},
leave(data){return frameShift(data)},
enter(data){return frameShift(data)}
}]
});
document.addEventListener("click",e=>{
const link=e.target.closest?.(".fs-link a,a.fs-link");if(!link||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;
if(state.busy||state.pending){e.preventDefault();e.stopImmediatePropagation();return}
if(window.innerWidth<320)return;
const href=new URL(link.href,location.href);
if(href.origin!==location.origin||href.hash||link.target==="_blank")return;
if(href.pathname===location.pathname&&href.search===location.search){e.preventDefault();e.stopImmediatePropagation();return}
state.pending=true;
},true);
window.addEventListener("scroll",()=>{if(state.busy&&window.scrollY!==state.oldScroll)window.scrollTo(0,state.oldScroll)},{passive:true});
window.addEventListener("wheel",blockScroll,{passive:false});
window.addEventListener("touchmove",blockScroll,{passive:false});
window.addEventListener("keydown",blockKeys);
api.status=()=>({ready:api.ready,busy:state.busy,pending:state.pending,transitions:api.transitions,
containers:document.querySelectorAll(".fs-page").length,sections:document.querySelectorAll(".fs-page .fs-section").length,
nativeInits:api.nativeInits,nativeListeners:api.activeNativeListeners,documentToken:api.documentToken,errors:api.errors.slice()});
}
const ready=()=>start().catch(error=>{report(error);unlock()});
if(document.readyState==="loading")raw.add.call(document,"DOMContentLoaded",ready,{once:true});else ready();
})();
</script>
Дуговой переход (Arc Veil)
В начало страницы или шапку добавляем код, через блок T123
CSS / JS

<!--Бесшовный переход
https://mt-webdesign.ru/seamless-->
<style class="av-style">
.av-root{scrollbar-gutter:stable;scroll-behavior:auto!important}
.av-root.av-busy{overscroll-behavior:none}
.av-page{position:relative}
.av-veil{position:fixed;inset:0;width:100%;height:100vh;height:100dvh;z-index:2147483000;visibility:hidden;opacity:0;pointer-events:none}
.av-veil svg{display:block;width:100%;height:100%;overflow:hidden}
</style>
<script src="https://matilda-design.ru/library/GSAP.js"></script>
<script src="https://matilda-design.ru/library/ScrollTrigger.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@barba/core@2.10.3/dist/barba.umd.js"></script>
<script class="av-bootstrap">
(function(){
"use strict";
const TRANSITION_COLOR = "#a1ff62";
const TRANSITION_PHASE_DURATION = 0.5;
if(window.TildaArcVeil)return;
const api=window.TildaArcVeil={
version:"1.0.0",documentToken:Date.now().toString(36)+"-"+Math.random().toString(36).slice(2),
bootCount:1,transitions:0,nativeInits:0,activeNativeListeners:0,errors:[],
lastTransition:null,ready:false
};
const state={pending:false,busy:false,oldScroll:0,oldFocus:null,lockStyles:null,epoch:0};
const pageStates=new WeakMap();
const scriptLoads=new Map();
const loadedScripts=new Set(Array.from(document.scripts,s=>s.src).filter(Boolean));
const executedScripts=new WeakSet();
let initialScope=null,initialPage=null;
function makeScope(page){return {
key:"avRuntime"+(++nativeSerial),page,disposed:false,listeners:new Set(),timers:new Set(),intervals:new Set(),
frames:new Set(),observers:new Set(),jquery:new Set(),styles:new Set(),portals:new Set(),formKeys:[],sbsAuto:false,
readyJobs:[],loadJobs:[],replay:false,customCount:0,contexts:new Set(),webgl:new Set()
}}
function lifecycleJob(s,target,type,callback,options){
if(!s?.replay||!callback||!((target===document&&type==="DOMContentLoaded")||(target===window&&type==="load")))return false;
const name=type==="load"?"loadJobs":"readyJobs",queue=s[name];
if(s[name+"Done"]){raw.timeout(()=>{try{inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?target:callback,[new Event(type)])}catch(error){report(error)}},0);return true}
if(!queue.some(j=>j.callback===callback&&j.target===target))queue.push({target,type,callback,options});
return true;
}
function flushJobs(s,name){
const jobs=s[name].splice(0);
for(const j of jobs){if(s.disposed)break;try{
const fn=typeof j.callback==="function"?j.callback:j.callback.handleEvent;
inNative(s,fn,typeof j.callback==="function"?j.target:j.callback,[new Event(j.type)]);
}catch(error){report(error)}}
s[name+"Done"]=true;
}
let nativeOwner=null,nativeSerial=0;
const scriptOwners=new WeakMap();
const raw={
add:EventTarget.prototype.addEventListener,remove:EventTarget.prototype.removeEventListener,
timeout:window.setTimeout.bind(window),clearTimeout:window.clearTimeout.bind(window),interval:window.setInterval.bind(window),clearInterval:window.clearInterval.bind(window),
raf:window.requestAnimationFrame.bind(window),caf:window.cancelAnimationFrame.bind(window),
append:Node.prototype.appendChild,insert:Node.prototype.insertBefore,
xhrSend:window.XMLHttpRequest?.prototype.send
};
let routeHistory=null;
for(const method of ["pushState","replaceState"]){
const original=history[method].bind(history);
history[method]=function(value,title,url){
if(value?.from==="barba")routeHistory=value;
else if(api.ready||owner()){
const base=history.state?.from==="barba"?history.state:routeHistory;
if(base)value={from:base.from,index:base.index,states:base.states,...(value||{})};
}
return original(value,title,url);
};
}
const popstateDescriptor=Object.getOwnPropertyDescriptor(window,"onpopstate");
if(popstateDescriptor?.get&&popstateDescriptor?.set&&popstateDescriptor.configurable){
Object.defineProperty(window,"onpopstate",{configurable:true,enumerable:popstateDescriptor.enumerable,
get(){return popstateDescriptor.get.call(window)},
set(fn){const s=owner(),wrapped=s&&typeof fn==="function"?function(event){
if(s.disposed)return;
const value=event?.state||history.state;
if(value?.storepartuid&&!value.productData){
const active=document.querySelector(".av-page:not(.av-incoming)");
if(active?.getAttribute("data-barba-namespace")!==location.pathname)return;
if(value.opts&&typeof window.t_catalog_loadProducts==="function"){
value.opts.isPublishedPage=true;
return inNative(s,window.t_catalog_loadProducts,window,["",value.recid,value.opts]);
}
return;
}
return inNative(s,fn,this,[event]);
}:fn;
if(s)s.popstateHandler=wrapped;
popstateDescriptor.set.call(window,wrapped);
}
});
}
const listenerMap=new WeakMap();
function owner(){
if(nativeOwner)return nativeOwner;
const script=document.currentScript;
const known=script&&scriptOwners.get(script);if(known)return known;
if(!initialPage&&((script&&!script.src&&!script.classList.contains("av-bootstrap")&&!script.closest("header,footer"))||(!script&&document.readyState==="interactive"))){
initialScope=initialScope||makeScope(null);if(script)scriptOwners.set(script,initialScope);return initialScope;
}
return null;
}
function scopeFor(page){const s=pageState(page);if(!s.nativeScope)s.nativeScope=makeScope(page);return s.nativeScope}
function inNative(s,fn,thisArg,args){
if(s?.disposed||s?.paused)return;
const before=nativeOwner,classes=new Set(document.body?.classList||[]);nativeOwner=s;
try{
if(s&&window.gsap?.context){
if(!s.gsapContext||s.gsapOwner!==window.gsap){s.gsapOwner=window.gsap;s.gsapContext=gsap.context(()=>{});s.contexts.add(s.gsapContext)}
let result;s.gsapContext.add(()=>{result=fn.apply(thisArg,args||[])});return result;
}
return fn.apply(thisArg,args||[]);
}finally{
if(s){s.bodyClasses=s.bodyClasses||new Set();for(const name of document.body?.classList||[])if(!classes.has(name))s.bodyClasses.add(name)}
nativeOwner=before;
}
}
function owned(s,fn){if(typeof fn!=="function")return fn;return function(...args){return inNative(s,fn,this,args)}}
function refreshNativeCounts(){
let globals=0,observers=0,timers=0;
document.querySelectorAll(".av-page").forEach(p=>{const s=pageStates.get(p)?.nativeScope;if(s&&!s.disposed){globals+=Array.from(s.listeners).filter(r=>r.target===window||r.target===document||r.target===document.body).length;observers+=s.observers.size;timers+=s.timers.size+s.intervals.size}});
api.activeNativeListeners=globals;api.nativeObservers=observers;api.nativeTimers=timers;
}
let jqueryRegistering=false;
EventTarget.prototype.addEventListener=function(type,callback,options){
const s=owner();
if(lifecycleJob(s,this,type,callback,options))return;
if(!s||!callback||jqueryRegistering)return raw.add.call(this,type,callback,options);
const capture=typeof options==="boolean"?options:!!options?.capture;
let list=listenerMap.get(this);if(!list){list=[];listenerMap.set(this,list)}
const existing=list.find(r=>r.s===s&&r.type===type&&r.callback===callback&&r.capture===capture);
if(existing)return raw.add.call(this,type,existing.wrapped,options);
const r={s,target:this,type,callback,capture,options,wrapped:null};
r.wrapped=function(...args){if(options?.once){s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)}
return inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?this:callback,args)};
list.push(r);s.listeners.add(r);return raw.add.call(this,type,r.wrapped,options);
};
EventTarget.prototype.removeEventListener=function(type,callback,options){
const activeScope=owner();
if(activeScope?.replay)for(const name of ["readyJobs","loadJobs"])activeScope[name]=activeScope[name].filter(j=>!(j.target===this&&j.type===type&&j.callback===callback));
const list=listenerMap.get(this),capture=typeof options==="boolean"?options:!!options?.capture,s=owner();
const matches=list?.filter(r=>r.type===type&&r.callback===callback&&r.capture===capture&&(!s||r.s===s))||[];
if(!matches.length)return raw.remove.call(this,type,callback,options);
matches.forEach(r=>{raw.remove.call(this,type,r.wrapped,options);r.s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)});
};
window.setTimeout=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.timeout(fn,ms,...args);let id;id=raw.timeout(()=>{s.timers.delete(id);inNative(s,fn,window,args)},ms);s.timers.add(id);return id};
window.clearTimeout=function(id){const s=owner();s?.timers.delete(id);return raw.clearTimeout(id)};
window.setInterval=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.interval(fn,ms,...args);const id=raw.interval(owned(s,fn),ms,...args);s.intervals.add(id);return id};
window.clearInterval=function(id){const s=owner();s?.intervals.delete(id);return raw.clearInterval(id)};
window.requestAnimationFrame=function(fn){const s=owner();if(!s)return raw.raf.call(window,fn);let id;id=raw.raf.call(window,t=>{s.frames.delete(id);inNative(s,fn,window,[t])});s.frames.add(id);return id};
window.cancelAnimationFrame=function(id){owner()?.frames.delete(id);return raw.caf.call(window,id)};
for(const key of ["IntersectionObserver","ResizeObserver","MutationObserver"]){
const Original=window[key];if(!Original)continue;
window[key]=new Proxy(Original,{construct(Target,args,newTarget){const s=owner();if(s)args[0]=owned(s,args[0]);const observer=Reflect.construct(Target,args,newTarget===window[key]?Target:newTarget);if(s)s.observers.add(observer);return observer}});
}
function noteInsertion(parent,node){const s=owner();if(!s||!node)return;if(parent===document.head&&node.tagName==="STYLE")s.styles.add(node);if(parent===document.body&&node.tagName==="DIV"){node.classList.add("av-native-portal");s.portals.add(node)}}
Node.prototype.appendChild=function(node){noteInsertion(this,node);return raw.append.call(this,node)};
Node.prototype.insertBefore=function(node,before){noteInsertion(this,node);return raw.insert.call(this,node,before)};
if(raw.xhrSend)XMLHttpRequest.prototype.send=function(...args){const s=owner();if(s)for(const name of ["onreadystatechange","onload","onerror","onloadend"]){if(typeof this[name]==="function")this[name]=owned(s,this[name])}return raw.xhrSend.apply(this,args)};
if(window.jQuery){
const $=window.jQuery,baseOn=$.fn.on,baseReady=$.fn.ready;
$.fn.ready=function(fn){const s=owner();if(!s)return baseReady.call(this,fn);
if(s.replay){lifecycleJob(s,document,"DOMContentLoaded",function(){return fn.call(document,$)});return this}
return baseReady.call(this,owned(s,fn));
};
$.fn.on=function(...args){const s=owner();if(!s)return baseOn.apply(this,args);
if(s.replay&&this.length===1&&this[0]===window&&typeof args[0]==="string"&&args[0].split(/\s+/).every(t=>t.split(".")[0]==="load")){
const callback=args.slice(1).findLast(a=>typeof a==="function");
if(callback){lifecycleJob(s,window,"load",callback);return this}
}
const ns="."+s.key;
const names=t=>t.split(/\s+/).filter(Boolean).map(t=>t+ns).join(" ");
if(typeof args[0]==="string")args[0]=names(args[0]);
else if(args[0]&&typeof args[0]==="object")args[0]=Object.fromEntries(Object.entries(args[0]).map(([k,v])=>[names(k),owned(s,v)]));
for(let i=1;i<args.length;i++)if(typeof args[i]==="function"){const original=args[i],wrapped=owned(s,original);wrapped.guid=original.guid||(original.guid=$.guid++);args[i]=wrapped}
s.jquery.add(this);const previous=jqueryRegistering;jqueryRegistering=true;try{return baseOn.apply(this,args)}finally{jqueryRegistering=previous}
};
}
function disposeNative(page){
const s=pageStates.get(page)?.nativeScope;if(!s)return;
s.disposed=true;
if(s.popstateHandler&&window.onpopstate===s.popstateHandler)window.onpopstate=null;
s.listeners.forEach(r=>{raw.remove.call(r.target,r.type,r.wrapped,r.options);const list=listenerMap.get(r.target);const i=list?.indexOf(r);if(i>=0)list.splice(i,1)});
s.timers.forEach(raw.clearTimeout);s.intervals.forEach(raw.clearInterval);s.frames.forEach(id=>raw.caf.call(window,id));
s.observers.forEach(o=>o.disconnect());s.jquery.forEach(q=>q.off("."+s.key));
s.contexts.forEach(c=>c.revert());s.webgl.forEach(gl=>gl.getExtension("WEBGL_lose_context")?.loseContext());
s.readyJobs.length=0;s.loadJobs.length=0;s.bodyClasses?.forEach(name=>document.body.classList.remove(name));
s.styles.forEach(n=>n.remove());s.portals.forEach(n=>n.remove());
if(window.initForms)s.formKeys.forEach(k=>delete window.initForms[k]);
s.listeners.clear();s.timers.clear();s.intervals.clear();s.frames.clear();s.observers.clear();s.jquery.clear();
refreshNativeCounts();
}
const rawGetContext=HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext=function(...args){const gl=rawGetContext.apply(this,args),s=owner();if(s&&gl&&/webgl/i.test(args[0]))s.webgl.add(gl);return gl};
const cssLoads=new Map();
function diagnostics(){const site=document.querySelector(".av-site");if(!site)return;Object.assign(site.dataset,{avDocument:api.documentToken,avTransitions:String(api.transitions),avNativeInits:String(api.nativeInits),avCustomInits:String(api.customInits||0),avVersion:api.version,avNativeListeners:String(api.activeNativeListeners),avErrors:String(api.errors.length),avObservers:String(api.nativeObservers||0),avTimers:String(api.nativeTimers||0),avReady:String(api.ready),avDuration:String(api.lastTransition?.duration||0)});}
function report(error){api.errors.push(String(error?.message||error));diagnostics();console.error("[Arc Veil]",error)}
const config={phaseDuration:TRANSITION_PHASE_DURATION,color:TRANSITION_COLOR,easeIn:"sine.in",easeOut:"sine.out",duration:TRANSITION_PHASE_DURATION*4};
api.config={...config};
function nativeRecord(marker){
let node=marker;
while(node&&node.parentElement){
if(Array.from(node.children).some(c=>c.tagName==="SCRIPT"&&/t396_init\s*\(/.test(c.textContent)))return node;
node=node.parentElement;
}
return null;
}
function prepare(doc,url){
const existing=doc.querySelector(".av-page");
if(existing)return existing;
const markers=Array.from(doc.querySelectorAll(".av-section-marker"));
const discovered=Array.from(doc.querySelectorAll("script")).filter(s=>!s.src&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(s.textContent)&&/t396_init\s*\(/.test(s.textContent)).map(s=>s.parentElement);
const records=Array.from(new Set([...markers.map(nativeRecord).filter(Boolean),...discovered])).filter(n=>!n.closest("header,footer"));
if(!records.length)return null;
records.forEach(n=>n.classList.add("av-section"));
const site=records[0].parentElement;
site.classList.add("av-site");site.setAttribute("data-barba","wrapper");
const page=doc.createElement("main");page.className="av-page";
page.setAttribute("data-barba","container");
page.setAttribute("data-barba-namespace",new URL(url||location.href,location.href).pathname);
const children=Array.from(site.childNodes);
site.insertBefore(page,site.firstChild);
children.forEach(n=>{if(n.nodeType===1&&["HEADER","FOOTER"].includes(n.tagName)){n.classList.add("av-shared");return;}if(n.nodeType===1)n.classList.add("av-native-record");page.appendChild(n)});
page.querySelectorAll("*").forEach(n=>{if(n.hasAttribute("data-animate-sbs-event"))n.classList.add("av-native-sbs")});
return page;
}
function pageState(page){
let s=pageStates.get(page);
if(!s){s={context:null,listeners:[],timers:[],nativeReady:false,reveals:[],cleanup:[]};pageStates.set(page,s)}
return s;
}
const frame=()=>new Promise(resolve=>requestAnimationFrame(resolve));
const bounded=(p,ms)=>Promise.race([p,new Promise((_,reject)=>setTimeout(()=>reject(Error("Page readiness timeout")),ms))]);
async function fontsReady(){if(document.fonts)await bounded(document.fonts.ready,3000).catch(()=>{})}
function loadCSS(href){
const absolute=new URL(href,location.href).href;
const present=Array.from(document.querySelectorAll('link[rel="stylesheet"]')).find(n=>n.href===absolute);
if(present?.sheet)return Promise.resolve();
if(cssLoads.has(absolute))return cssLoads.get(absolute);
const p=new Promise((resolve,reject)=>{
const link=present||document.createElement("link");
link.rel="stylesheet";link.href=absolute;
link.addEventListener("load",resolve,{once:true});link.addEventListener("error",()=>reject(Error("Stylesheet failed: "+absolute)),{once:true});
if(!present){link.classList.add("av-loaded-style");document.head.appendChild(link)}
setTimeout(()=>{if(link.sheet)resolve();else reject(Error("Stylesheet timeout: "+absolute))},8000);
});cssLoads.set(absolute,p);return p;
}
function loadScript(src,scope){
const absolute=new URL(src,location.href).href;
if(scriptLoads.has(absolute))return scriptLoads.get(absolute);
if(loadedScripts.has(absolute))return Promise.resolve();
if(/tilda-blocks-page[^/]*\.js(?:\?|$)/.test(absolute)){
const p=fetch(absolute).then(response=>{if(!response.ok)throw Error("Page bundle failed: "+absolute);return response.text()}).then(source=>{
const names=Array.from(new Set(Array.from(source.matchAll(/\bfunction\s+([A-Za-z_$][\w$]*)\s*\(/g),m=>m[1])));
const expose=names.map(name=>'if(typeof '+name+'==="function"&&typeof window['+JSON.stringify(name)+']!=="function")window['+JSON.stringify(name)+']='+name+';').join("\n");
inNative(scope,()=>Function(source+"\n;"+expose+"\n//# sourceURL="+absolute)());
});
scriptLoads.set(absolute,p);return p;
}
const p=new Promise((resolve,reject)=>{const s=document.createElement("script");s.src=absolute;if(scope)scriptOwners.set(s,scope);s.onload=()=>{loadedScripts.add(absolute);resolve()};s.onerror=()=>reject(Error("Dependency failed: "+absolute));document.head.appendChild(s)});
scriptLoads.set(absolute,p);return p;
}
async function syncAssets(html,page){
const scope=scopeFor(page);scope.formsBefore=new Set(Object.keys(window.initForms||{}));
const doc=new DOMParser().parseFromString(html,"text/html");
const source=prepare(doc,location.href)?.parentElement;
const target=document.querySelector(".av-site");
if(source&&target)for(const a of Array.from(source.attributes))if(a.name.startsWith("data-tilda-"))target.setAttribute(a.name,a.value);
await Promise.all(Array.from(doc.querySelectorAll('link[rel="stylesheet"]')).map(n=>loadCSS(n.href)));
// Keep libraries once; load missing Tilda dependencies, never a second GSAP/Barba/bootstrap.
for(const s of Array.from(doc.querySelectorAll("script[src]"))){
if(/tilda(?:cdn|cdn\.com)|tildacdn|tilda\.ws/.test(s.src)&&!s.src.includes("tilda-events")){
const already=loadedScripts.has(s.src)||scriptLoads.has(s.src);
if(!already&&s.src.includes("tilda-animation-sbs"))scope.sbsAuto=true;
if(!already&&s.src.includes("tilda-animation-2."))scope.basicAuto=true;
await loadScript(s.src,scope);
}
}
const selector='meta[name="description"],meta[name="robots"],link[rel="canonical"],meta[property^="og:"],meta[name^="twitter:"]';
document.head.querySelectorAll(selector).forEach(n=>n.remove());
doc.head.querySelectorAll(selector).forEach(n=>document.head.appendChild(document.importNode(n,true)));
}
async function nativeInit(page){
const s=pageState(page);if(s.nativeReady)return;
const scope=scopeFor(page);
if(typeof window.t396_init!=="function")await bounded(new Promise(resolve=>window.t_onFuncLoad("t396_init",resolve)),8000);
for(const block of page.querySelectorAll(".av-native-record")){
if(block.querySelector(".av-bootstrap,.av-style"))continue;
const scripts=Array.from(block.querySelectorAll("script")).filter(n=>!n.src&&!n.type?.includes("json")&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(n.textContent));
for(const script of scripts){inNative(scope,()=>Function(script.textContent)());executedScripts.add(script);api.nativeInits++;}
}
await frame();await frame();
s.nativeReady=true;
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
scope.formKeys=Object.keys(window.initForms||{}).filter(k=>!scope.formsBefore?.has(k));
window.dispatchEvent(new Event("resize"));
await fontsReady();await frame();refreshNativeCounts();
}
function scriptEnvironment(page){
const selectAll=selector=>{
if(selector==="body")return [document.body];if(selector==="html"||selector===":root")return [document.documentElement];
return [...page.querySelectorAll(selector),...Array.from(document.querySelectorAll(".av-shared")).flatMap(n=>[...(n.matches(selector)?[n]:[]),...n.querySelectorAll(selector)])];
};
let scriptNode=null;
const doc=new Proxy(document,{get(target,key){
if(key==="currentScript")return scriptNode;
if(key==="querySelector")return selector=>selectAll(selector)[0]||null;
if(key==="querySelectorAll")return selectAll;
if(key==="getElementById")return id=>Array.from(page.querySelectorAll("[id]")).find(n=>n.id===id)||null;
const value=Reflect.get(target,key,target);return typeof value==="function"?value.bind(target):value;
}});
const win=window;
const jq=window.jQuery&&new Proxy(window.jQuery,{apply(target,thisArg,args){
if(args[0]===doc)args[0]=document;if(args[0]===win)args[0]=window;
if(typeof args[0]==="string"&&args.length===1&&!args[0].trim().startsWith("<"))return target(selectAll(args[0]));
return Reflect.apply(target,thisArg,args);
}});
return {doc,win,jq,setScript:n=>scriptNode=n};
}
async function customInit(page){
const state=pageState(page),s=scopeFor(page);if(state.customReady)return;
state.customReady=true;s.replay=true;
const env=scriptEnvironment(page);
for(const script of Array.from(page.querySelectorAll("script"))){
if(executedScripts.has(script)||script.closest(".av-shared")||script.classList.contains("av-bootstrap")||script.parentElement?.querySelector(":scope > .av-bootstrap"))continue;
const type=script.type.trim().toLowerCase();
if(type&&!/^(?:module|(?:text|application)\/(?:java|ecma)script)$/.test(type))continue;
try{
if(script.src){
await loadScript(script.src,null);executedScripts.add(script);continue;
}
if(!script.textContent.trim())continue;
env.setScript(script);scriptOwners.set(script,s);
const fn=Function("window","document","$","jQuery",(type==="module"?'"use strict";\n':"")+script.textContent);
inNative(s,fn,window,[env.win,env.doc,env.jq,env.jq]);
executedScripts.add(script);s.customCount++;api.customInits=(api.customInits||0)+1;
}catch(error){report(error)}
}
flushJobs(s,"readyJobs");
diagnostics();
}
async function customAfterEnter(page){
const s=scopeFor(page);if(!s.replay)return;
await fontsReady();await frame();
flushJobs(s,"loadJobs");flushJobs(s,"readyJobs");
refreshNativeCounts();diagnostics();
}
function nativeAfterEnter(page){
const scope=scopeFor(page);
inNative(scope,()=>{
if(typeof window.t_lazyload_update==="function")window.t_lazyload_update();
if(typeof window.t_animate__init==="function"&&!scope.basicAuto)window.t_animate__init();
if(page.querySelector(".av-native-sbs")&&typeof window.t_animationSBS__init==="function"&&!scope.sbsAuto)window.t_animationSBS__init();
});
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
refreshNativeCounts();
}
const ARC_PATHS={
bottomEmpty:"M 0 100 V 100 Q 50 100 100 100 V 100 z",
bottomCurveUp:"M 0 100 V 50 Q 50 0 100 50 V 100 z",
bottomFull:"M 0 100 V 0 Q 50 0 100 0 V 100 z",
topFull:"M 0 0 V 100 Q 50 100 100 100 V 0 z",
topCurveUp:"M 0 0 V 50 Q 50 0 100 50 V 0 z",
topEmpty:"M 0 0 V 0 Q 50 0 100 0 V 0 z",
topCurveDown:"M 0 0 V 50 Q 50 100 100 50 V 0 z",
bottomCurveDown:"M 0 100 V 50 Q 50 100 100 50 V 100 z"
};
function sequenceFor(reverse){return reverse?{
cover:[ARC_PATHS.topEmpty,ARC_PATHS.topCurveDown,ARC_PATHS.topFull],
uncover:[ARC_PATHS.bottomFull,ARC_PATHS.bottomCurveDown,ARC_PATHS.bottomEmpty]
}:{
cover:[ARC_PATHS.bottomEmpty,ARC_PATHS.bottomCurveUp,ARC_PATHS.bottomFull],
uncover:[ARC_PATHS.topFull,ARC_PATHS.topCurveUp,ARC_PATHS.topEmpty]
}}
let veil,path;
function phase(data,part){
const sequence=sequenceFor(typeof data.trigger==="string")[part];
const site=document.querySelector(".av-site");if(site){site.dataset.avPhase=part;site.dataset.avDirection=typeof data.trigger==="string"?"down":"up"}
gsap.set(veil,{autoAlpha:1,pointerEvents:"auto"});
path.setAttribute("d",sequence[0]);
return new Promise(resolve=>{
const tl=gsap.timeline({onComplete:()=>{if(site)site.dataset.avPhase=part==="cover"?"covered":"revealed";resolve()}});
tl.to(path,{attr:{d:sequence[1]},duration:config.phaseDuration,ease:config.easeIn},0);
tl.to(path,{attr:{d:sequence[2]},duration:config.phaseDuration,ease:config.easeOut},config.phaseDuration);
});
}
function cleanup(page){
const s=pageStates.get(page);if(!s)return;
disposeNative(page);s.context?.revert();s.cleanup.forEach(f=>f());
s.listeners.forEach(({target,type,listener,options})=>target.removeEventListener(type,listener,options));
pageStates.delete(page);
}
function lock(){if(state.busy)return;state.busy=true;state.oldScroll=window.scrollY;state.oldFocus=document.activeElement;document.documentElement.classList.add("av-busy")}
function unlock(){state.busy=false;state.pending=false;document.documentElement.classList.remove("av-busy")}
function blockScroll(e){if(state.busy)e.preventDefault()}
function blockKeys(e){if(state.busy&&["ArrowDown","ArrowUp","PageDown","PageUp","Home","End"," "].includes(e.key))e.preventDefault()}
function focusPage(page){
const heading=page.querySelector(".av-title h1,.av-title h2,.av-title h3")||page,prev=heading.getAttribute("tabindex");
heading.setAttribute("tabindex","-1");heading.focus({preventScroll:true});
heading.addEventListener("blur",()=>{if(prev===null)heading.removeAttribute("tabindex");else heading.setAttribute("tabindex",prev)},{once:true});
}
function resetOverlay(){path.setAttribute("d",ARC_PATHS.bottomEmpty);gsap.set(veil,{autoAlpha:0,pointerEvents:"none"})}
async function start(){
if(!window.gsap||!window.barba||!window.ScrollTrigger)throw Error("GSAP, ScrollTrigger or Barba failed to load");
gsap.registerPlugin(ScrollTrigger);gsap.ticker.lagSmoothing(0);
const first=prepare(document,location.href);if(!first)throw Error("No native Zero Blocks found");
initialPage=first;if(initialScope){initialScope.page=first;pageState(first).nativeScope=initialScope}
Array.from(document.scripts).forEach(s=>{if(s.src)loadedScripts.add(s.src)});
document.documentElement.classList.add("av-root");pageState(first).nativeReady=true;
scopeFor(first).formKeys=Object.keys(window.initForms||{});
if(window.onpopstate)inNative(scopeFor(first),()=>{window.onpopstate=window.onpopstate});
history.scrollRestoration="manual";
veil=document.createElement("div");veil.className="av-veil";veil.setAttribute("aria-hidden","true");
const svg=document.createElementNS("http://www.w3.org/2000/svg","svg");
svg.setAttribute("viewBox","0 0 100 100");svg.setAttribute("preserveAspectRatio","xMidYMin slice");
path=document.createElementNS("http://www.w3.org/2000/svg","path");
path.setAttribute("d",ARC_PATHS.bottomEmpty);path.setAttribute("fill",config.color);path.setAttribute("stroke",config.color);
path.setAttribute("stroke-width","2");path.setAttribute("vector-effect","non-scaling-stroke");
svg.appendChild(path);veil.appendChild(svg);document.body.appendChild(veil);
const baseToDocument=barba.dom.toDocument.bind(barba.dom);
barba.dom.toDocument=function(html){const doc=baseToDocument(html);prepare(doc,location.href);return doc};
barba.dom.toElement=function(html){return barba.dom.toDocument(html).documentElement};
barba.hooks.before(data=>{
lock();state.epoch++;scopeFor(data.current.container).paused=true;data.current.container.inert=true;
api.lastTransition={from:data.current.url.path,to:data.next.url.path,started:performance.now(),epoch:state.epoch};
});
barba.hooks.afterLeave(data=>{cleanup(data.current.container);data.current.container.remove()});
barba.hooks.beforeEnter(async data=>{
if(!api.ready)return;
const next=data.next.container;next.inert=true;
state.oldScroll=0;window.scrollTo({top:0,left:0,behavior:"instant"});
await syncAssets(data.next.html,next);await nativeInit(next);await customInit(next);
nativeAfterEnter(next);await customAfterEnter(next);ScrollTrigger.refresh();
});
barba.hooks.afterEnter(data=>{data.next.container.inert=false;ScrollTrigger.refresh()});
barba.hooks.after(data=>{
resetOverlay();unlock();data.next.container.classList.add("av-ready");focusPage(data.next.container);
refreshNativeCounts();api.transitions++;api.lastTransition.finished=performance.now();
api.lastTransition.duration=api.lastTransition.finished-api.lastTransition.started;diagnostics();
document.dispatchEvent(new CustomEvent("av:after",{detail:{url:location.href,count:api.transitions}}));
});
barba.init({timeout:15000,preventRunning:true,cacheIgnore:false,prefetchIgnore:false,
prevent:({el,href})=>{
if(window.innerWidth<320||!el.closest(".av-link")||el.hasAttribute("download"))return true;
const u=new URL(href,location.href);return u.origin!==location.origin||!!u.hash;
},
requestError:(_trigger,_action,url,error)=>{report(error);if(veil)resetOverlay();unlock();return true},
transitions:[{name:"arc-veil",sync:false,
async once(){await fontsReady();await frame();api.ready=true;diagnostics()},
leave(data){return phase(data,"cover")},enter(data){return phase(data,"uncover")}
}]
});
document.addEventListener("click",e=>{
const link=e.target.closest?.(".av-link a,a.av-link");if(!link||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;
if(state.busy||state.pending){e.preventDefault();e.stopImmediatePropagation();return}
if(window.innerWidth<320)return;
const href=new URL(link.href,location.href);if(href.origin!==location.origin||href.hash||link.target==="_blank")return;
if(href.pathname===location.pathname&&href.search===location.search){e.preventDefault();e.stopImmediatePropagation();return}
state.pending=true;
},true);
window.addEventListener("scroll",()=>{if(state.busy&&window.scrollY!==state.oldScroll)window.scrollTo(0,state.oldScroll)},{passive:true});
window.addEventListener("wheel",blockScroll,{passive:false});window.addEventListener("touchmove",blockScroll,{passive:false});window.addEventListener("keydown",blockKeys);
api.status=()=>({ready:api.ready,busy:state.busy,pending:state.pending,transitions:api.transitions,documentToken:api.documentToken,errors:api.errors.slice()});
}
const ready=()=>start().catch(error=>{report(error);if(veil)resetOverlay();unlock()});
if(document.readyState==="loading")raw.add.call(document,"DOMContentLoaded",ready,{once:true});else ready();
})();
</script>
Спиральный переход (Spiral Veil)
В начало страницы или шапку добавляем код, через блок T123
CSS / JS

<!--Бесшовный переход
https://mt-webdesign.ru/seamless-->
<style class="sv-style">
.sv-root{scrollbar-gutter:stable;scroll-behavior:auto!important}
.sv-root.sv-busy{overscroll-behavior:none}
.sv-page{position:relative}
.sv-veil{position:fixed;inset:0;width:100%;height:100vh;height:100dvh;overflow:hidden;z-index:2147483000;visibility:hidden;opacity:0;pointer-events:none}
.sv-stroke{width:100%;height:100%;display:grid;place-items:center}
.sv-stroke svg{display:block;width:125%;height:100%;aspect-ratio:1}
</style>
<script src="https://matilda-design.ru/library/GSAP.js"></script>
<script src="https://matilda-design.ru/library/ScrollTrigger.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@barba/core@2.10.3/dist/barba.umd.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/DrawSVGPlugin.min.js"></script>
<script class="sv-bootstrap">
(function(){
"use strict";
// Цвет спирали и параметры её прорисовки.
const TRANSITION_COLOR = "#a1ff62";
const TRANSITION_SETTINGS = {
startWidth:100, coverWidth:400,
fadeDuration:0.5, drawDuration:1.4, growDelay:0.18, growDuration:1.4,
shrinkDuration:1, eraseDelay:0.45, eraseDuration:1
};
if(window.TildaSpiralVeil)return;
const api=window.TildaSpiralVeil={
version:"1.0.0",documentToken:Date.now().toString(36)+"-"+Math.random().toString(36).slice(2),
bootCount:1,transitions:0,nativeInits:0,activeNativeListeners:0,errors:[],
lastTransition:null,ready:false
};
const state={pending:false,busy:false,oldScroll:0,oldFocus:null,lockStyles:null,epoch:0};
const pageStates=new WeakMap();
const scriptLoads=new Map();
const loadedScripts=new Set(Array.from(document.scripts,s=>s.src).filter(Boolean));
const executedScripts=new WeakSet();
let initialScope=null,initialPage=null;
function makeScope(page){return {
key:"svRuntime"+(++nativeSerial),page,disposed:false,listeners:new Set(),timers:new Set(),intervals:new Set(),
frames:new Set(),observers:new Set(),jquery:new Set(),styles:new Set(),portals:new Set(),formKeys:[],sbsAuto:false,
readyJobs:[],loadJobs:[],replay:false,customCount:0,contexts:new Set(),webgl:new Set()
}}
function lifecycleJob(s,target,type,callback,options){
if(!s?.replay||!callback||!((target===document&&type==="DOMContentLoaded")||(target===window&&type==="load")))return false;
const name=type==="load"?"loadJobs":"readyJobs",queue=s[name];
if(s[name+"Done"]){raw.timeout(()=>{try{inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?target:callback,[new Event(type)])}catch(error){report(error)}},0);return true}
if(!queue.some(j=>j.callback===callback&&j.target===target))queue.push({target,type,callback,options});
return true;
}
function flushJobs(s,name){
const jobs=s[name].splice(0);
for(const j of jobs){if(s.disposed)break;try{
const fn=typeof j.callback==="function"?j.callback:j.callback.handleEvent;
inNative(s,fn,typeof j.callback==="function"?j.target:j.callback,[new Event(j.type)]);
}catch(error){report(error)}}
s[name+"Done"]=true;
}
let nativeOwner=null,nativeSerial=0;
const scriptOwners=new WeakMap();
const raw={
add:EventTarget.prototype.addEventListener,remove:EventTarget.prototype.removeEventListener,
timeout:window.setTimeout.bind(window),clearTimeout:window.clearTimeout.bind(window),interval:window.setInterval.bind(window),clearInterval:window.clearInterval.bind(window),
raf:window.requestAnimationFrame.bind(window),caf:window.cancelAnimationFrame.bind(window),
append:Node.prototype.appendChild,insert:Node.prototype.insertBefore,
xhrSend:window.XMLHttpRequest?.prototype.send
};
let routeHistory=null;
for(const method of ["pushState","replaceState"]){
const original=history[method].bind(history);
history[method]=function(value,title,url){
if(value?.from==="barba")routeHistory=value;
else if(api.ready||owner()){
const base=history.state?.from==="barba"?history.state:routeHistory;
if(base)value={from:base.from,index:base.index,states:base.states,...(value||{})};
}
return original(value,title,url);
};
}
const popstateDescriptor=Object.getOwnPropertyDescriptor(window,"onpopstate");
if(popstateDescriptor?.get&&popstateDescriptor?.set&&popstateDescriptor.configurable){
Object.defineProperty(window,"onpopstate",{configurable:true,enumerable:popstateDescriptor.enumerable,
get(){return popstateDescriptor.get.call(window)},
set(fn){const s=owner(),wrapped=s&&typeof fn==="function"?function(event){
if(s.disposed)return;
const value=event?.state||history.state;
if(value?.storepartuid&&!value.productData){
const active=document.querySelector(".sv-page:not(.sv-incoming)");
if(active?.getAttribute("data-barba-namespace")!==location.pathname)return;
if(value.opts&&typeof window.t_catalog_loadProducts==="function"){
value.opts.isPublishedPage=true;
return inNative(s,window.t_catalog_loadProducts,window,["",value.recid,value.opts]);
}
return;
}
return inNative(s,fn,this,[event]);
}:fn;
if(s)s.popstateHandler=wrapped;
popstateDescriptor.set.call(window,wrapped);
}
});
}
const listenerMap=new WeakMap();
function owner(){
if(nativeOwner)return nativeOwner;
const script=document.currentScript;
const known=script&&scriptOwners.get(script);if(known)return known;
if(!initialPage&&((script&&!script.src&&!script.classList.contains("sv-bootstrap")&&!script.closest("header,footer"))||(!script&&document.readyState==="interactive"))){
initialScope=initialScope||makeScope(null);if(script)scriptOwners.set(script,initialScope);return initialScope;
}
return null;
}
function scopeFor(page){const s=pageState(page);if(!s.nativeScope)s.nativeScope=makeScope(page);return s.nativeScope}
function inNative(s,fn,thisArg,args){
if(s?.disposed||s?.paused)return;
const before=nativeOwner,classes=new Set(document.body?.classList||[]);nativeOwner=s;
try{
if(s&&window.gsap?.context){
if(!s.gsapContext||s.gsapOwner!==window.gsap){s.gsapOwner=window.gsap;s.gsapContext=gsap.context(()=>{});s.contexts.add(s.gsapContext)}
let result;s.gsapContext.add(()=>{result=fn.apply(thisArg,args||[])});return result;
}
return fn.apply(thisArg,args||[]);
}finally{
if(s){s.bodyClasses=s.bodyClasses||new Set();for(const name of document.body?.classList||[])if(!classes.has(name))s.bodyClasses.add(name)}
nativeOwner=before;
}
}
function owned(s,fn){if(typeof fn!=="function")return fn;return function(...args){return inNative(s,fn,this,args)}}
function refreshNativeCounts(){
let globals=0,observers=0,timers=0;
document.querySelectorAll(".sv-page").forEach(p=>{const s=pageStates.get(p)?.nativeScope;if(s&&!s.disposed){globals+=Array.from(s.listeners).filter(r=>r.target===window||r.target===document||r.target===document.body).length;observers+=s.observers.size;timers+=s.timers.size+s.intervals.size}});
api.activeNativeListeners=globals;api.nativeObservers=observers;api.nativeTimers=timers;
}
let jqueryRegistering=false;
EventTarget.prototype.addEventListener=function(type,callback,options){
const s=owner();
if(lifecycleJob(s,this,type,callback,options))return;
if(!s||!callback||jqueryRegistering)return raw.add.call(this,type,callback,options);
const capture=typeof options==="boolean"?options:!!options?.capture;
let list=listenerMap.get(this);if(!list){list=[];listenerMap.set(this,list)}
const existing=list.find(r=>r.s===s&&r.type===type&&r.callback===callback&&r.capture===capture);
if(existing)return raw.add.call(this,type,existing.wrapped,options);
const r={s,target:this,type,callback,capture,options,wrapped:null};
r.wrapped=function(...args){if(options?.once){s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)}
return inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?this:callback,args)};
list.push(r);s.listeners.add(r);return raw.add.call(this,type,r.wrapped,options);
};
EventTarget.prototype.removeEventListener=function(type,callback,options){
const activeScope=owner();
if(activeScope?.replay)for(const name of ["readyJobs","loadJobs"])activeScope[name]=activeScope[name].filter(j=>!(j.target===this&&j.type===type&&j.callback===callback));
const list=listenerMap.get(this),capture=typeof options==="boolean"?options:!!options?.capture,s=owner();
const matches=list?.filter(r=>r.type===type&&r.callback===callback&&r.capture===capture&&(!s||r.s===s))||[];
if(!matches.length)return raw.remove.call(this,type,callback,options);
matches.forEach(r=>{raw.remove.call(this,type,r.wrapped,options);r.s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)});
};
window.setTimeout=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.timeout(fn,ms,...args);let id;id=raw.timeout(()=>{s.timers.delete(id);inNative(s,fn,window,args)},ms);s.timers.add(id);return id};
window.clearTimeout=function(id){const s=owner();s?.timers.delete(id);return raw.clearTimeout(id)};
window.setInterval=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.interval(fn,ms,...args);const id=raw.interval(owned(s,fn),ms,...args);s.intervals.add(id);return id};
window.clearInterval=function(id){const s=owner();s?.intervals.delete(id);return raw.clearInterval(id)};
window.requestAnimationFrame=function(fn){const s=owner();if(!s)return raw.raf.call(window,fn);let id;id=raw.raf.call(window,t=>{s.frames.delete(id);inNative(s,fn,window,[t])});s.frames.add(id);return id};
window.cancelAnimationFrame=function(id){owner()?.frames.delete(id);return raw.caf.call(window,id)};
for(const key of ["IntersectionObserver","ResizeObserver","MutationObserver"]){
const Original=window[key];if(!Original)continue;
window[key]=new Proxy(Original,{construct(Target,args,newTarget){const s=owner();if(s)args[0]=owned(s,args[0]);const observer=Reflect.construct(Target,args,newTarget===window[key]?Target:newTarget);if(s)s.observers.add(observer);return observer}});
}
function noteInsertion(parent,node){const s=owner();if(!s||!node)return;if(parent===document.head&&node.tagName==="STYLE")s.styles.add(node);if(parent===document.body&&node.tagName==="DIV"){node.classList.add("sv-native-portal");s.portals.add(node)}}
Node.prototype.appendChild=function(node){noteInsertion(this,node);return raw.append.call(this,node)};
Node.prototype.insertBefore=function(node,before){noteInsertion(this,node);return raw.insert.call(this,node,before)};
if(raw.xhrSend)XMLHttpRequest.prototype.send=function(...args){const s=owner();if(s)for(const name of ["onreadystatechange","onload","onerror","onloadend"]){if(typeof this[name]==="function")this[name]=owned(s,this[name])}return raw.xhrSend.apply(this,args)};
if(window.jQuery){
const $=window.jQuery,baseOn=$.fn.on,baseReady=$.fn.ready;
$.fn.ready=function(fn){const s=owner();if(!s)return baseReady.call(this,fn);
if(s.replay){lifecycleJob(s,document,"DOMContentLoaded",function(){return fn.call(document,$)});return this}
return baseReady.call(this,owned(s,fn));
};
$.fn.on=function(...args){const s=owner();if(!s)return baseOn.apply(this,args);
if(s.replay&&this.length===1&&this[0]===window&&typeof args[0]==="string"&&args[0].split(/\s+/).every(t=>t.split(".")[0]==="load")){
const callback=args.slice(1).findLast(a=>typeof a==="function");
if(callback){lifecycleJob(s,window,"load",callback);return this}
}
const ns="."+s.key;
const names=t=>t.split(/\s+/).filter(Boolean).map(t=>t+ns).join(" ");
if(typeof args[0]==="string")args[0]=names(args[0]);
else if(args[0]&&typeof args[0]==="object")args[0]=Object.fromEntries(Object.entries(args[0]).map(([k,v])=>[names(k),owned(s,v)]));
for(let i=1;i<args.length;i++)if(typeof args[i]==="function"){const original=args[i],wrapped=owned(s,original);wrapped.guid=original.guid||(original.guid=$.guid++);args[i]=wrapped}
s.jquery.add(this);const previous=jqueryRegistering;jqueryRegistering=true;try{return baseOn.apply(this,args)}finally{jqueryRegistering=previous}
};
}
function disposeNative(page){
const s=pageStates.get(page)?.nativeScope;if(!s)return;
s.disposed=true;
if(s.popstateHandler&&window.onpopstate===s.popstateHandler)window.onpopstate=null;
s.listeners.forEach(r=>{raw.remove.call(r.target,r.type,r.wrapped,r.options);const list=listenerMap.get(r.target);const i=list?.indexOf(r);if(i>=0)list.splice(i,1)});
s.timers.forEach(raw.clearTimeout);s.intervals.forEach(raw.clearInterval);s.frames.forEach(id=>raw.caf.call(window,id));
s.observers.forEach(o=>o.disconnect());s.jquery.forEach(q=>q.off("."+s.key));
s.contexts.forEach(c=>c.revert());s.webgl.forEach(gl=>gl.getExtension("WEBGL_lose_context")?.loseContext());
s.readyJobs.length=0;s.loadJobs.length=0;s.bodyClasses?.forEach(name=>document.body.classList.remove(name));
s.styles.forEach(n=>n.remove());s.portals.forEach(n=>n.remove());
if(window.initForms)s.formKeys.forEach(k=>delete window.initForms[k]);
s.listeners.clear();s.timers.clear();s.intervals.clear();s.frames.clear();s.observers.clear();s.jquery.clear();
refreshNativeCounts();
}
const rawGetContext=HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext=function(...args){const gl=rawGetContext.apply(this,args),s=owner();if(s&&gl&&/webgl/i.test(args[0]))s.webgl.add(gl);return gl};
const cssLoads=new Map();
function diagnostics(){const site=document.querySelector(".sv-site");if(!site)return;Object.assign(site.dataset,{svDocument:api.documentToken,svTransitions:String(api.transitions),svNativeInits:String(api.nativeInits),svCustomInits:String(api.customInits||0),svVersion:api.version,svNativeListeners:String(api.activeNativeListeners),svErrors:String(api.errors.length),svObservers:String(api.nativeObservers||0),svTimers:String(api.nativeTimers||0),svReady:String(api.ready),svDuration:String(api.lastTransition?.duration||0)});}
function report(error){api.errors.push(String(error?.message||error));diagnostics();console.error("[Spiral Veil]",error)}
const config={...TRANSITION_SETTINGS,color:TRANSITION_COLOR,ease:"sine.inOut",duration:3.03};
api.config={...config};
function nativeRecord(marker){
let node=marker;
while(node&&node.parentElement){
if(Array.from(node.children).some(c=>c.tagName==="SCRIPT"&&/t396_init\s*\(/.test(c.textContent)))return node;
node=node.parentElement;
}
return null;
}
function prepare(doc,url){
const existing=doc.querySelector(".sv-page");
if(existing)return existing;
const markers=Array.from(doc.querySelectorAll(".sv-section-marker"));
const discovered=Array.from(doc.querySelectorAll("script")).filter(s=>!s.src&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(s.textContent)&&/t396_init\s*\(/.test(s.textContent)).map(s=>s.parentElement);
const records=Array.from(new Set([...markers.map(nativeRecord).filter(Boolean),...discovered])).filter(n=>!n.closest("header,footer"));
if(!records.length)return null;
records.forEach(n=>n.classList.add("sv-section"));
const site=records[0].parentElement;
site.classList.add("sv-site");site.setAttribute("data-barba","wrapper");
const page=doc.createElement("main");page.className="sv-page";
page.setAttribute("data-barba","container");
page.setAttribute("data-barba-namespace",new URL(url||location.href,location.href).pathname);
const children=Array.from(site.childNodes);
site.insertBefore(page,site.firstChild);
children.forEach(n=>{if(n.nodeType===1&&["HEADER","FOOTER"].includes(n.tagName)){n.classList.add("sv-shared");return;}if(n.nodeType===1)n.classList.add("sv-native-record");page.appendChild(n)});
page.querySelectorAll("*").forEach(n=>{if(n.hasAttribute("data-animate-sbs-event"))n.classList.add("sv-native-sbs")});
return page;
}
function pageState(page){
let s=pageStates.get(page);
if(!s){s={context:null,listeners:[],timers:[],nativeReady:false,reveals:[],cleanup:[]};pageStates.set(page,s)}
return s;
}
const frame=()=>new Promise(resolve=>requestAnimationFrame(resolve));
const bounded=(p,ms)=>Promise.race([p,new Promise((_,reject)=>setTimeout(()=>reject(Error("Page readiness timeout")),ms))]);
async function fontsReady(){if(document.fonts)await bounded(document.fonts.ready,3000).catch(()=>{})}
function loadCSS(href){
const absolute=new URL(href,location.href).href;
const present=Array.from(document.querySelectorAll('link[rel="stylesheet"]')).find(n=>n.href===absolute);
if(present?.sheet)return Promise.resolve();
if(cssLoads.has(absolute))return cssLoads.get(absolute);
const p=new Promise((resolve,reject)=>{
const link=present||document.createElement("link");
link.rel="stylesheet";link.href=absolute;
link.addEventListener("load",resolve,{once:true});link.addEventListener("error",()=>reject(Error("Stylesheet failed: "+absolute)),{once:true});
if(!present){link.classList.add("sv-loaded-style");document.head.appendChild(link)}
setTimeout(()=>{if(link.sheet)resolve();else reject(Error("Stylesheet timeout: "+absolute))},8000);
});cssLoads.set(absolute,p);return p;
}
function loadScript(src,scope){
const absolute=new URL(src,location.href).href;
if(scriptLoads.has(absolute))return scriptLoads.get(absolute);
if(loadedScripts.has(absolute))return Promise.resolve();
if(/tilda-blocks-page[^/]*\.js(?:\?|$)/.test(absolute)){
const p=fetch(absolute).then(response=>{if(!response.ok)throw Error("Page bundle failed: "+absolute);return response.text()}).then(source=>{
const names=Array.from(new Set(Array.from(source.matchAll(/\bfunction\s+([A-Za-z_$][\w$]*)\s*\(/g),m=>m[1])));
const expose=names.map(name=>'if(typeof '+name+'==="function"&&typeof window['+JSON.stringify(name)+']!=="function")window['+JSON.stringify(name)+']='+name+';').join("\n");
inNative(scope,()=>Function(source+"\n;"+expose+"\n//# sourceURL="+absolute)());
});
scriptLoads.set(absolute,p);return p;
}
const p=new Promise((resolve,reject)=>{const s=document.createElement("script");s.src=absolute;if(scope)scriptOwners.set(s,scope);s.onload=()=>{loadedScripts.add(absolute);resolve()};s.onerror=()=>reject(Error("Dependency failed: "+absolute));document.head.appendChild(s)});
scriptLoads.set(absolute,p);return p;
}
async function syncAssets(html,page){
const scope=scopeFor(page);scope.formsBefore=new Set(Object.keys(window.initForms||{}));
const doc=new DOMParser().parseFromString(html,"text/html");
const source=prepare(doc,location.href)?.parentElement;
const target=document.querySelector(".sv-site");
if(source&&target)for(const a of Array.from(source.attributes))if(a.name.startsWith("data-tilda-"))target.setAttribute(a.name,a.value);
await Promise.all(Array.from(doc.querySelectorAll('link[rel="stylesheet"]')).map(n=>loadCSS(n.href)));
for(const s of Array.from(doc.querySelectorAll("script[src]"))){
if(/tilda(?:cdn|cdn\.com)|tildacdn|tilda\.ws/.test(s.src)&&!s.src.includes("tilda-events")){
const already=loadedScripts.has(s.src)||scriptLoads.has(s.src);
if(!already&&s.src.includes("tilda-animation-sbs"))scope.sbsAuto=true;
if(!already&&s.src.includes("tilda-animation-2."))scope.basicAuto=true;
await loadScript(s.src,scope);
}
}
const selector='meta[name="description"],meta[name="robots"],link[rel="canonical"],meta[property^="og:"],meta[name^="twitter:"]';
document.head.querySelectorAll(selector).forEach(n=>n.remove());
doc.head.querySelectorAll(selector).forEach(n=>document.head.appendChild(document.importNode(n,true)));
}
async function nativeInit(page){
const s=pageState(page);if(s.nativeReady)return;
const scope=scopeFor(page);
if(typeof window.t396_init!=="function")await bounded(new Promise(resolve=>window.t_onFuncLoad("t396_init",resolve)),8000);
for(const block of page.querySelectorAll(".sv-native-record")){
if(block.querySelector(".sv-bootstrap,.sv-style"))continue;
const scripts=Array.from(block.querySelectorAll("script")).filter(n=>!n.src&&!n.type?.includes("json")&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(n.textContent));
for(const script of scripts){inNative(scope,()=>Function(script.textContent)());executedScripts.add(script);api.nativeInits++;}
}
await frame();await frame();
s.nativeReady=true;
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
scope.formKeys=Object.keys(window.initForms||{}).filter(k=>!scope.formsBefore?.has(k));
window.dispatchEvent(new Event("resize"));
await fontsReady();await frame();refreshNativeCounts();
}
function scriptEnvironment(page){
const selectAll=selector=>{
if(selector==="body")return [document.body];if(selector==="html"||selector===":root")return [document.documentElement];
return [...page.querySelectorAll(selector),...Array.from(document.querySelectorAll(".sv-shared")).flatMap(n=>[...(n.matches(selector)?[n]:[]),...n.querySelectorAll(selector)])];
};
let scriptNode=null;
const doc=new Proxy(document,{get(target,key){
if(key==="currentScript")return scriptNode;
if(key==="querySelector")return selector=>selectAll(selector)[0]||null;
if(key==="querySelectorAll")return selectAll;
if(key==="getElementById")return id=>Array.from(page.querySelectorAll("[id]")).find(n=>n.id===id)||null;
const value=Reflect.get(target,key,target);return typeof value==="function"?value.bind(target):value;
}});
const win=window;
const jq=window.jQuery&&new Proxy(window.jQuery,{apply(target,thisArg,args){
if(args[0]===doc)args[0]=document;if(args[0]===win)args[0]=window;
if(typeof args[0]==="string"&&args.length===1&&!args[0].trim().startsWith("<"))return target(selectAll(args[0]));
return Reflect.apply(target,thisArg,args);
}});
return {doc,win,jq,setScript:n=>scriptNode=n};
}
async function customInit(page){
const state=pageState(page),s=scopeFor(page);if(state.customReady)return;
state.customReady=true;s.replay=true;
const env=scriptEnvironment(page);
for(const script of Array.from(page.querySelectorAll("script"))){
if(executedScripts.has(script)||script.closest(".sv-shared")||script.classList.contains("sv-bootstrap")||script.parentElement?.querySelector(":scope > .sv-bootstrap"))continue;
const type=script.type.trim().toLowerCase();
if(type&&!/^(?:module|(?:text|application)\/(?:java|ecma)script)$/.test(type))continue;
try{
if(script.src){
await loadScript(script.src,null);executedScripts.add(script);continue;
}
if(!script.textContent.trim())continue;
env.setScript(script);scriptOwners.set(script,s);
const fn=Function("window","document","$","jQuery",(type==="module"?'"use strict";\n':"")+script.textContent);
inNative(s,fn,window,[env.win,env.doc,env.jq,env.jq]);
executedScripts.add(script);s.customCount++;api.customInits=(api.customInits||0)+1;
}catch(error){report(error)}
}
flushJobs(s,"readyJobs");
diagnostics();
}
async function customAfterEnter(page){
const s=scopeFor(page);if(!s.replay)return;
await fontsReady();await frame();
flushJobs(s,"loadJobs");flushJobs(s,"readyJobs");
refreshNativeCounts();diagnostics();
}
function nativeAfterEnter(page){
const scope=scopeFor(page);
inNative(scope,()=>{
if(typeof window.t_lazyload_update==="function")window.t_lazyload_update();
if(typeof window.t_animate__init==="function"&&!scope.basicAuto)window.t_animate__init();
if(page.querySelector(".sv-native-sbs")&&typeof window.t_animationSBS__init==="function"&&!scope.sbsAuto)window.t_animationSBS__init();
});
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
refreshNativeCounts();
}
const SPIRAL_PATH="m0 0c3.36 0.06 6.6-2.82 7.07-7.07 0.59-4.19-1.79-9.6-7.07-12.93-5.18-3.4-13.27-4.43-21.21-1.21-7.92 3.09-15.48 10.7-18.79 21.21-3.42 10.46-2.3 23.68 4.64 35.36 6.83 11.64 19.57 21.35 35.36 24.64 15.69 3.43 34.14 0.2 49.5-10.5 15.38-10.52 27.21-28.47 30.5-49.5 3.43-20.92-1.92-44.6-16.36-63.64-14.2-19.1-37.37-33.1-63.64-36.36-26.16-3.45-55.05 4.06-77.78 22.22-22.82 17.9-38.98 46.25-42.22 77.78-3.48 31.43 6.2 65.49 28.08 91.92 21.58 26.55 55.16 44.87 91.92 48.08 36.66 3.5 75.94-8.33 106.07-33.93 30.27-25.28 50.74-64.07 53.93-106.07 3.53-41.9-10.46-86.4-39.79-120.21-28.97-33.99-72.97-56.62-120.21-59.79-47.13-3.56-96.85 12.6-134.35 45.65-37.71 32.65-62.51 81.88-65.65 134.35-3.55 52.4 14.72 107.29 51.51 148.49 36.35 41.41 90.75 68.41 148.49 71.51 57.63 3.58 117.75-16.86 162.63-57.37 45.14-40.03 74.29-99.66 77.37-162.63 3.62-62.86-19.02-128.21-63.22-176.78-43.73-48.85-108.57-80.17-176.78-83.22-68.13-3.64-138.65 21.15-190.92 69.08-52.57 47.43-86.06 117.45-89.08 190.92-3.66 73.36 23.29 149.1 74.94 205.06 51.12 56.3 126.35 91.94 205.06 94.94 78.6 3.69 159.56-25.42 219.2-80.8 60.03-54.8 97.82-135.26 100.8-219.2 3.72-83.84-27.56-170.01-86.65-233.35-58.51-63.77-144.14-103.69-233.35-106.65-89.07-3.71-180.46 29.68-247.49 92.51-67.51 62.18-109.54 153.08-112.51 247.49-3.74 94.33 31.82 190.91 98.37 261.63 65.88 71.23 161.96 115.43 261.63 118.37 99.57 3.76 201.36-33.95 275.77-104.23 74.96-69.57 121.31-170.86 124.23-275.77";
let veil,path;
function phase(data,part){
const site=document.querySelector(".sv-site");if(site){site.dataset.svPhase=part;site.dataset.svDirection="spiral"}
gsap.set(veil,{autoAlpha:1,pointerEvents:"auto"});
return new Promise(resolve=>{
const tl=gsap.timeline({defaults:{ease:config.ease},onComplete:()=>{if(site)site.dataset.svPhase=part==="cover"?"covered":"revealed";resolve()}});
if(part==="cover"){
gsap.set(path,{drawSVG:"0% 0%",attr:{"stroke-width":config.startWidth},opacity:0});
tl.to(path,{opacity:1,duration:config.fadeDuration},0);
tl.to(path,{drawSVG:"0% 100%",duration:config.drawDuration},0);
tl.to(path,{attr:{"stroke-width":config.coverWidth},duration:config.growDuration},config.growDelay);
}else{
tl.to(path,{attr:{"stroke-width":config.startWidth},duration:config.shrinkDuration},0);
tl.to(path,{drawSVG:"100% 100%",duration:config.eraseDuration},config.eraseDelay);
}
});
}
function cleanup(page){
const s=pageStates.get(page);if(!s)return;
disposeNative(page);s.context?.revert();s.cleanup.forEach(f=>f());
s.listeners.forEach(({target,type,listener,options})=>target.removeEventListener(type,listener,options));
pageStates.delete(page);
}
function lock(){if(state.busy)return;state.busy=true;state.oldScroll=window.scrollY;state.oldFocus=document.activeElement;document.documentElement.classList.add("sv-busy")}
function unlock(){state.busy=false;state.pending=false;document.documentElement.classList.remove("sv-busy")}
function blockScroll(e){if(state.busy)e.preventDefault()}
function blockKeys(e){if(state.busy&&["ArrowDown","ArrowUp","PageDown","PageUp","Home","End"," "].includes(e.key))e.preventDefault()}
function focusPage(page){
const heading=page.querySelector(".sv-title h1,.sv-title h2,.sv-title h3")||page,prev=heading.getAttribute("tabindex");
heading.setAttribute("tabindex","-1");heading.focus({preventScroll:true});
heading.addEventListener("blur",()=>{if(prev===null)heading.removeAttribute("tabindex");else heading.setAttribute("tabindex",prev)},{once:true});
}
function resetOverlay(){gsap.set(path,{drawSVG:"0% 0%",attr:{"stroke-width":config.startWidth},opacity:0});gsap.set(veil,{autoAlpha:0,pointerEvents:"none"})}
async function start(){
if(!window.gsap||!window.barba||!window.ScrollTrigger||!window.DrawSVGPlugin)throw Error("GSAP, DrawSVGPlugin, ScrollTrigger or Barba failed to load");
gsap.registerPlugin(ScrollTrigger,DrawSVGPlugin);gsap.ticker.lagSmoothing(0);
const first=prepare(document,location.href);if(!first)throw Error("No native Zero Blocks found");
initialPage=first;if(initialScope){initialScope.page=first;pageState(first).nativeScope=initialScope}
Array.from(document.scripts).forEach(s=>{if(s.src)loadedScripts.add(s.src)});
document.documentElement.classList.add("sv-root");pageState(first).nativeReady=true;
scopeFor(first).formKeys=Object.keys(window.initForms||{});
if(window.onpopstate)inNative(scopeFor(first),()=>{window.onpopstate=window.onpopstate});
history.scrollRestoration="manual";
veil=document.createElement("div");veil.className="sv-veil";veil.setAttribute("aria-hidden","true");
const svg=document.createElementNS("http://www.w3.org/2000/svg","svg");
svg.setAttribute("viewBox","-360 -360 760 760");svg.setAttribute("preserveAspectRatio","xMidYMid slice");
path=document.createElementNS("http://www.w3.org/2000/svg","path");
path.setAttribute("d",SPIRAL_PATH);path.setAttribute("fill","none");path.setAttribute("stroke",config.color);
path.setAttribute("stroke-width",String(config.startWidth));path.setAttribute("stroke-linecap","round");path.setAttribute("stroke-linejoin","round");path.setAttribute("vector-effect","non-scaling-stroke");
svg.appendChild(path);const drawing=document.createElement("div");drawing.className="sv-stroke";drawing.appendChild(svg);veil.appendChild(drawing);document.body.appendChild(veil);
const baseToDocument=barba.dom.toDocument.bind(barba.dom);
barba.dom.toDocument=function(html){const doc=baseToDocument(html);prepare(doc,location.href);return doc};
barba.dom.toElement=function(html){return barba.dom.toDocument(html).documentElement};
barba.hooks.before(data=>{
lock();state.epoch++;scopeFor(data.current.container).paused=true;data.current.container.inert=true;
api.lastTransition={from:data.current.url.path,to:data.next.url.path,started:performance.now(),epoch:state.epoch};
});
barba.hooks.afterLeave(data=>{cleanup(data.current.container);data.current.container.remove()});
barba.hooks.beforeEnter(async data=>{
if(!api.ready)return;
const next=data.next.container;next.inert=true;
state.oldScroll=0;window.scrollTo({top:0,left:0,behavior:"instant"});
await syncAssets(data.next.html,next);await nativeInit(next);await customInit(next);
nativeAfterEnter(next);await customAfterEnter(next);ScrollTrigger.refresh();
});
barba.hooks.afterEnter(data=>{data.next.container.inert=false;ScrollTrigger.refresh()});
barba.hooks.after(data=>{
resetOverlay();unlock();data.next.container.classList.add("sv-ready");focusPage(data.next.container);
refreshNativeCounts();api.transitions++;api.lastTransition.finished=performance.now();
api.lastTransition.duration=api.lastTransition.finished-api.lastTransition.started;diagnostics();
document.dispatchEvent(new CustomEvent("av:after",{detail:{url:location.href,count:api.transitions}}));
});
barba.init({timeout:15000,preventRunning:true,cacheIgnore:false,prefetchIgnore:false,
prevent:({el,href})=>{
if(window.innerWidth<320||!el.closest(".sv-link")||el.hasAttribute("download"))return true;
const u=new URL(href,location.href);return u.origin!==location.origin||!!u.hash;
},
requestError:(_trigger,_action,url,error)=>{report(error);if(veil)resetOverlay();unlock();return true},
transitions:[{name:"spiral-veil",sync:false,
async once(){await fontsReady();await frame();api.ready=true;diagnostics()},
leave(data){return phase(data,"cover")},enter(data){return phase(data,"uncover")}
}]
});
document.addEventListener("click",e=>{
const link=e.target.closest?.(".sv-link a,a.sv-link");if(!link||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;
if(state.busy||state.pending){e.preventDefault();e.stopImmediatePropagation();return}
if(window.innerWidth<320)return;
const href=new URL(link.href,location.href);if(href.origin!==location.origin||href.hash||link.target==="_blank")return;
if(href.pathname===location.pathname&&href.search===location.search){e.preventDefault();e.stopImmediatePropagation();return}
state.pending=true;
},true);
window.addEventListener("scroll",()=>{if(state.busy&&window.scrollY!==state.oldScroll)window.scrollTo(0,state.oldScroll)},{passive:true});
window.addEventListener("wheel",blockScroll,{passive:false});window.addEventListener("touchmove",blockScroll,{passive:false});window.addEventListener("keydown",blockKeys);
api.status=()=>({ready:api.ready,busy:state.busy,pending:state.pending,transitions:api.transitions,documentToken:api.documentToken,errors:api.errors.slice()});
}
const ready=()=>start().catch(error=>{report(error);if(veil)resetOverlay();unlock()});
if(document.readyState==="loading")raw.add.call(document,"DOMContentLoaded",ready,{once:true});else ready();
})();
</script>
Тающий переход (Dissolve Veil)
В начало страницы или шапку добавляем код, через блок T123
CSS / JS

<!--Бесшовный переход
https://mt-webdesign.ru/seamless-->
<style class="dv-style">
.dv-root{scrollbar-gutter:stable;scroll-behavior:auto!important}
.dv-root.dv-busy{overscroll-behavior:none}
.dv-page{position:relative}
.dv-veil{position:fixed;inset:0;width:100%;height:100vh;height:100dvh;overflow:hidden;z-index:2147483000;visibility:hidden;opacity:0;pointer-events:none}
.dv-canvas{display:block}
</style>
<script src="https://matilda-design.ru/library/GSAP.js"></script>
<script src="https://matilda-design.ru/library/ScrollTrigger.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@barba/core@2.10.3/dist/barba.umd.js"></script>
<script class="dv-bootstrap">
(function(){
"use strict";
// Цвет WebGL-завесы (HEX).
const TRANSITION_COLOR = "#a1ff62";
const TRANSITION_SETTINGS = {phaseDuration:1,noiseScale:5,edge:0.185,maxPixelRatio:1};
if(window.TildaDissolveVeil)return;
const api=window.TildaDissolveVeil={
version:"1.0.0",documentToken:Date.now().toString(36)+"-"+Math.random().toString(36).slice(2),
bootCount:1,transitions:0,nativeInits:0,activeNativeListeners:0,errors:[],
lastTransition:null,ready:false
};
const state={pending:false,busy:false,oldScroll:0,oldFocus:null,lockStyles:null,epoch:0};
const pageStates=new WeakMap();
const scriptLoads=new Map();
const loadedScripts=new Set(Array.from(document.scripts,s=>s.src).filter(Boolean));
const executedScripts=new WeakSet();
let initialScope=null,initialPage=null;
function makeScope(page){return {
key:"dvRuntime"+(++nativeSerial),page,disposed:false,listeners:new Set(),timers:new Set(),intervals:new Set(),
frames:new Set(),observers:new Set(),jquery:new Set(),styles:new Set(),portals:new Set(),formKeys:[],sbsAuto:false,
readyJobs:[],loadJobs:[],replay:false,customCount:0,contexts:new Set(),webgl:new Set()
}}
function lifecycleJob(s,target,type,callback,options){
if(!s?.replay||!callback||!((target===document&&type==="DOMContentLoaded")||(target===window&&type==="load")))return false;
const name=type==="load"?"loadJobs":"readyJobs",queue=s[name];
if(s[name+"Done"]){raw.timeout(()=>{try{inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?target:callback,[new Event(type)])}catch(error){report(error)}},0);return true}
if(!queue.some(j=>j.callback===callback&&j.target===target))queue.push({target,type,callback,options});
return true;
}
function flushJobs(s,name){
const jobs=s[name].splice(0);
for(const j of jobs){if(s.disposed)break;try{
const fn=typeof j.callback==="function"?j.callback:j.callback.handleEvent;
inNative(s,fn,typeof j.callback==="function"?j.target:j.callback,[new Event(j.type)]);
}catch(error){report(error)}}
s[name+"Done"]=true;
}
let nativeOwner=null,nativeSerial=0;
const scriptOwners=new WeakMap();
const raw={
add:EventTarget.prototype.addEventListener,remove:EventTarget.prototype.removeEventListener,
timeout:window.setTimeout.bind(window),clearTimeout:window.clearTimeout.bind(window),interval:window.setInterval.bind(window),clearInterval:window.clearInterval.bind(window),
raf:window.requestAnimationFrame.bind(window),caf:window.cancelAnimationFrame.bind(window),
append:Node.prototype.appendChild,insert:Node.prototype.insertBefore,
xhrSend:window.XMLHttpRequest?.prototype.send
};
let routeHistory=null;
for(const method of ["pushState","replaceState"]){
const original=history[method].bind(history);
history[method]=function(value,title,url){
if(value?.from==="barba")routeHistory=value;
else if(api.ready||owner()){
const base=history.state?.from==="barba"?history.state:routeHistory;
if(base)value={from:base.from,index:base.index,states:base.states,...(value||{})};
}
return original(value,title,url);
};
}
const popstateDescriptor=Object.getOwnPropertyDescriptor(window,"onpopstate");
if(popstateDescriptor?.get&&popstateDescriptor?.set&&popstateDescriptor.configurable){
Object.defineProperty(window,"onpopstate",{configurable:true,enumerable:popstateDescriptor.enumerable,
get(){return popstateDescriptor.get.call(window)},
set(fn){const s=owner(),wrapped=s&&typeof fn==="function"?function(event){
if(s.disposed)return;
const value=event?.state||history.state;
if(value?.storepartuid&&!value.productData){
const active=document.querySelector(".dv-page:not(.dv-incoming)");
if(active?.getAttribute("data-barba-namespace")!==location.pathname)return;
if(value.opts&&typeof window.t_catalog_loadProducts==="function"){
value.opts.isPublishedPage=true;
return inNative(s,window.t_catalog_loadProducts,window,["",value.recid,value.opts]);
}
return;
}
return inNative(s,fn,this,[event]);
}:fn;
if(s)s.popstateHandler=wrapped;
popstateDescriptor.set.call(window,wrapped);
}
});
}
const listenerMap=new WeakMap();
function owner(){
if(nativeOwner)return nativeOwner;
const script=document.currentScript;
const known=script&&scriptOwners.get(script);if(known)return known;
if(!initialPage&&((script&&!script.src&&!script.classList.contains("dv-bootstrap")&&!script.closest("header,footer"))||(!script&&document.readyState==="interactive"))){
initialScope=initialScope||makeScope(null);if(script)scriptOwners.set(script,initialScope);return initialScope;
}
return null;
}
function scopeFor(page){const s=pageState(page);if(!s.nativeScope)s.nativeScope=makeScope(page);return s.nativeScope}
function inNative(s,fn,thisArg,args){
if(s?.disposed||s?.paused)return;
const before=nativeOwner,classes=new Set(document.body?.classList||[]);nativeOwner=s;
try{
if(s&&window.gsap?.context){
if(!s.gsapContext||s.gsapOwner!==window.gsap){s.gsapOwner=window.gsap;s.gsapContext=gsap.context(()=>{});s.contexts.add(s.gsapContext)}
let result;s.gsapContext.add(()=>{result=fn.apply(thisArg,args||[])});return result;
}
return fn.apply(thisArg,args||[]);
}finally{
if(s){s.bodyClasses=s.bodyClasses||new Set();for(const name of document.body?.classList||[])if(!classes.has(name))s.bodyClasses.add(name)}
nativeOwner=before;
}
}
function owned(s,fn){if(typeof fn!=="function")return fn;return function(...args){return inNative(s,fn,this,args)}}
function refreshNativeCounts(){
let globals=0,observers=0,timers=0;
document.querySelectorAll(".dv-page").forEach(p=>{const s=pageStates.get(p)?.nativeScope;if(s&&!s.disposed){globals+=Array.from(s.listeners).filter(r=>r.target===window||r.target===document||r.target===document.body).length;observers+=s.observers.size;timers+=s.timers.size+s.intervals.size}});
api.activeNativeListeners=globals;api.nativeObservers=observers;api.nativeTimers=timers;
}
let jqueryRegistering=false;
EventTarget.prototype.addEventListener=function(type,callback,options){
const s=owner();
if(lifecycleJob(s,this,type,callback,options))return;
if(!s||!callback||jqueryRegistering)return raw.add.call(this,type,callback,options);
const capture=typeof options==="boolean"?options:!!options?.capture;
let list=listenerMap.get(this);if(!list){list=[];listenerMap.set(this,list)}
const existing=list.find(r=>r.s===s&&r.type===type&&r.callback===callback&&r.capture===capture);
if(existing)return raw.add.call(this,type,existing.wrapped,options);
const r={s,target:this,type,callback,capture,options,wrapped:null};
r.wrapped=function(...args){if(options?.once){s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)}
return inNative(s,typeof callback==="function"?callback:callback.handleEvent,typeof callback==="function"?this:callback,args)};
list.push(r);s.listeners.add(r);return raw.add.call(this,type,r.wrapped,options);
};
EventTarget.prototype.removeEventListener=function(type,callback,options){
const activeScope=owner();
if(activeScope?.replay)for(const name of ["readyJobs","loadJobs"])activeScope[name]=activeScope[name].filter(j=>!(j.target===this&&j.type===type&&j.callback===callback));
const list=listenerMap.get(this),capture=typeof options==="boolean"?options:!!options?.capture,s=owner();
const matches=list?.filter(r=>r.type===type&&r.callback===callback&&r.capture===capture&&(!s||r.s===s))||[];
if(!matches.length)return raw.remove.call(this,type,callback,options);
matches.forEach(r=>{raw.remove.call(this,type,r.wrapped,options);r.s.listeners.delete(r);const i=list.indexOf(r);if(i>=0)list.splice(i,1)});
};
window.setTimeout=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.timeout(fn,ms,...args);let id;id=raw.timeout(()=>{s.timers.delete(id);inNative(s,fn,window,args)},ms);s.timers.add(id);return id};
window.clearTimeout=function(id){const s=owner();s?.timers.delete(id);return raw.clearTimeout(id)};
window.setInterval=function(fn,ms,...args){const s=owner();if(!s||typeof fn!=="function")return raw.interval(fn,ms,...args);const id=raw.interval(owned(s,fn),ms,...args);s.intervals.add(id);return id};
window.clearInterval=function(id){const s=owner();s?.intervals.delete(id);return raw.clearInterval(id)};
window.requestAnimationFrame=function(fn){const s=owner();if(!s)return raw.raf.call(window,fn);let id;id=raw.raf.call(window,t=>{s.frames.delete(id);inNative(s,fn,window,[t])});s.frames.add(id);return id};
window.cancelAnimationFrame=function(id){owner()?.frames.delete(id);return raw.caf.call(window,id)};
for(const key of ["IntersectionObserver","ResizeObserver","MutationObserver"]){
const Original=window[key];if(!Original)continue;
window[key]=new Proxy(Original,{construct(Target,args,newTarget){const s=owner();if(s)args[0]=owned(s,args[0]);const observer=Reflect.construct(Target,args,newTarget===window[key]?Target:newTarget);if(s)s.observers.add(observer);return observer}});
}
function noteInsertion(parent,node){const s=owner();if(!s||!node)return;if(parent===document.head&&node.tagName==="STYLE")s.styles.add(node);if(parent===document.body&&node.tagName==="DIV"){node.classList.add("dv-native-portal");s.portals.add(node)}}
Node.prototype.appendChild=function(node){noteInsertion(this,node);return raw.append.call(this,node)};
Node.prototype.insertBefore=function(node,before){noteInsertion(this,node);return raw.insert.call(this,node,before)};
if(raw.xhrSend)XMLHttpRequest.prototype.send=function(...args){const s=owner();if(s)for(const name of ["onreadystatechange","onload","onerror","onloadend"]){if(typeof this[name]==="function")this[name]=owned(s,this[name])}return raw.xhrSend.apply(this,args)};
if(window.jQuery){
const $=window.jQuery,baseOn=$.fn.on,baseReady=$.fn.ready;
$.fn.ready=function(fn){const s=owner();if(!s)return baseReady.call(this,fn);
if(s.replay){lifecycleJob(s,document,"DOMContentLoaded",function(){return fn.call(document,$)});return this}
return baseReady.call(this,owned(s,fn));
};
$.fn.on=function(...args){const s=owner();if(!s)return baseOn.apply(this,args);
if(s.replay&&this.length===1&&this[0]===window&&typeof args[0]==="string"&&args[0].split(/\s+/).every(t=>t.split(".")[0]==="load")){
const callback=args.slice(1).findLast(a=>typeof a==="function");
if(callback){lifecycleJob(s,window,"load",callback);return this}
}
const ns="."+s.key;
const names=t=>t.split(/\s+/).filter(Boolean).map(t=>t+ns).join(" ");
if(typeof args[0]==="string")args[0]=names(args[0]);
else if(args[0]&&typeof args[0]==="object")args[0]=Object.fromEntries(Object.entries(args[0]).map(([k,v])=>[names(k),owned(s,v)]));
for(let i=1;i<args.length;i++)if(typeof args[i]==="function"){const original=args[i],wrapped=owned(s,original);wrapped.guid=original.guid||(original.guid=$.guid++);args[i]=wrapped}
s.jquery.add(this);const previous=jqueryRegistering;jqueryRegistering=true;try{return baseOn.apply(this,args)}finally{jqueryRegistering=previous}
};
}
function disposeNative(page){
const s=pageStates.get(page)?.nativeScope;if(!s)return;
s.disposed=true;
if(s.popstateHandler&&window.onpopstate===s.popstateHandler)window.onpopstate=null;
s.listeners.forEach(r=>{raw.remove.call(r.target,r.type,r.wrapped,r.options);const list=listenerMap.get(r.target);const i=list?.indexOf(r);if(i>=0)list.splice(i,1)});
s.timers.forEach(raw.clearTimeout);s.intervals.forEach(raw.clearInterval);s.frames.forEach(id=>raw.caf.call(window,id));
s.observers.forEach(o=>o.disconnect());s.jquery.forEach(q=>q.off("."+s.key));
s.contexts.forEach(c=>c.revert());s.webgl.forEach(gl=>gl.getExtension("WEBGL_lose_context")?.loseContext());
s.readyJobs.length=0;s.loadJobs.length=0;s.bodyClasses?.forEach(name=>document.body.classList.remove(name));
s.styles.forEach(n=>n.remove());s.portals.forEach(n=>n.remove());
if(window.initForms)s.formKeys.forEach(k=>delete window.initForms[k]);
s.listeners.clear();s.timers.clear();s.intervals.clear();s.frames.clear();s.observers.clear();s.jquery.clear();
refreshNativeCounts();
}
const rawGetContext=HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext=function(...args){const gl=rawGetContext.apply(this,args),s=owner();if(s&&gl&&/webgl/i.test(args[0]))s.webgl.add(gl);return gl};
const cssLoads=new Map();
function diagnostics(){const site=document.querySelector(".dv-site");if(!site)return;Object.assign(site.dataset,{dvDocument:api.documentToken,dvTransitions:String(api.transitions),dvNativeInits:String(api.nativeInits),dvCustomInits:String(api.customInits||0),dvVersion:api.version,dvNativeListeners:String(api.activeNativeListeners),dvErrors:String(api.errors.length),dvObservers:String(api.nativeObservers||0),dvTimers:String(api.nativeTimers||0),dvReady:String(api.ready),dvDuration:String(api.lastTransition?.duration||0)});}
function report(error){api.errors.push(String(error?.message||error));diagnostics();console.error("[Dissolve Veil]",error)}
const config={...TRANSITION_SETTINGS,color:TRANSITION_COLOR,ease:"power1.in",open:1.5,closed:-0.75,duration:TRANSITION_SETTINGS.phaseDuration*2};
api.config={...config};
function nativeRecord(marker){
let node=marker;
while(node&&node.parentElement){
if(Array.from(node.children).some(c=>c.tagName==="SCRIPT"&&/t396_init\s*\(/.test(c.textContent)))return node;
node=node.parentElement;
}
return null;
}
function prepare(doc,url){
const existing=doc.querySelector(".dv-page");
if(existing)return existing;
const markers=Array.from(doc.querySelectorAll(".dv-section-marker"));
const discovered=Array.from(doc.querySelectorAll("script")).filter(s=>!s.src&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(s.textContent)&&/t396_init\s*\(/.test(s.textContent)).map(s=>s.parentElement);
const records=Array.from(new Set([...markers.map(nativeRecord).filter(Boolean),...discovered])).filter(n=>!n.closest("header,footer"));
if(!records.length)return null;
records.forEach(n=>n.classList.add("dv-section"));
const site=records[0].parentElement;
site.classList.add("dv-site");site.setAttribute("data-barba","wrapper");
const page=doc.createElement("main");page.className="dv-page";
page.setAttribute("data-barba","container");
page.setAttribute("data-barba-namespace",new URL(url||location.href,location.href).pathname);
const children=Array.from(site.childNodes);
site.insertBefore(page,site.firstChild);
children.forEach(n=>{if(n.nodeType===1&&["HEADER","FOOTER"].includes(n.tagName)){n.classList.add("dv-shared");return;}if(n.nodeType===1)n.classList.add("dv-native-record");page.appendChild(n)});
page.querySelectorAll("*").forEach(n=>{if(n.hasAttribute("data-animate-sbs-event"))n.classList.add("dv-native-sbs")});
return page;
}
function pageState(page){
let s=pageStates.get(page);
if(!s){s={context:null,listeners:[],timers:[],nativeReady:false,reveals:[],cleanup:[]};pageStates.set(page,s)}
return s;
}
const frame=()=>new Promise(resolve=>requestAnimationFrame(resolve));
const bounded=(p,ms)=>Promise.race([p,new Promise((_,reject)=>setTimeout(()=>reject(Error("Page readiness timeout")),ms))]);
async function fontsReady(){if(document.fonts)await bounded(document.fonts.ready,3000).catch(()=>{})}
function loadCSS(href){
const absolute=new URL(href,location.href).href;
const present=Array.from(document.querySelectorAll('link[rel="stylesheet"]')).find(n=>n.href===absolute);
if(present?.sheet)return Promise.resolve();
if(cssLoads.has(absolute))return cssLoads.get(absolute);
const p=new Promise((resolve,reject)=>{
const link=present||document.createElement("link");
link.rel="stylesheet";link.href=absolute;
link.addEventListener("load",resolve,{once:true});link.addEventListener("error",()=>reject(Error("Stylesheet failed: "+absolute)),{once:true});
if(!present){link.classList.add("dv-loaded-style");document.head.appendChild(link)}
setTimeout(()=>{if(link.sheet)resolve();else reject(Error("Stylesheet timeout: "+absolute))},8000);
});cssLoads.set(absolute,p);return p;
}
function loadScript(src,scope){
const absolute=new URL(src,location.href).href;
if(scriptLoads.has(absolute))return scriptLoads.get(absolute);
if(loadedScripts.has(absolute))return Promise.resolve();
if(/tilda-blocks-page[^/]*\.js(?:\?|$)/.test(absolute)){
const p=fetch(absolute).then(response=>{if(!response.ok)throw Error("Page bundle failed: "+absolute);return response.text()}).then(source=>{
const names=Array.from(new Set(Array.from(source.matchAll(/\bfunction\s+([A-Za-z_$][\w$]*)\s*\(/g),m=>m[1])));
const expose=names.map(name=>'if(typeof '+name+'==="function"&&typeof window['+JSON.stringify(name)+']!=="function")window['+JSON.stringify(name)+']='+name+';').join("\n");
inNative(scope,()=>Function(source+"\n;"+expose+"\n//# sourceURL="+absolute)());
});
scriptLoads.set(absolute,p);return p;
}
const p=new Promise((resolve,reject)=>{const s=document.createElement("script");s.src=absolute;if(scope)scriptOwners.set(s,scope);s.onload=()=>{loadedScripts.add(absolute);resolve()};s.onerror=()=>reject(Error("Dependency failed: "+absolute));document.head.appendChild(s)});
scriptLoads.set(absolute,p);return p;
}
async function syncAssets(html,page){
const scope=scopeFor(page);scope.formsBefore=new Set(Object.keys(window.initForms||{}));
const doc=new DOMParser().parseFromString(html,"text/html");
const source=prepare(doc,location.href)?.parentElement;
const target=document.querySelector(".dv-site");
if(source&&target)for(const a of Array.from(source.attributes))if(a.name.startsWith("data-tilda-"))target.setAttribute(a.name,a.value);
await Promise.all(Array.from(doc.querySelectorAll('link[rel="stylesheet"]')).map(n=>loadCSS(n.href)));
// Keep libraries once; load missing Tilda dependencies, never a second GSAP/Barba/bootstrap.
for(const s of Array.from(doc.querySelectorAll("script[src]"))){
if(/tilda(?:cdn|cdn\.com)|tildacdn|tilda\.ws/.test(s.src)&&!s.src.includes("tilda-events")){
const already=loadedScripts.has(s.src)||scriptLoads.has(s.src);
if(!already&&s.src.includes("tilda-animation-sbs"))scope.sbsAuto=true;
if(!already&&s.src.includes("tilda-animation-2."))scope.basicAuto=true;
await loadScript(s.src,scope);
}
}
const selector='meta[name="description"],meta[name="robots"],link[rel="canonical"],meta[property^="og:"],meta[name^="twitter:"]';
document.head.querySelectorAll(selector).forEach(n=>n.remove());
doc.head.querySelectorAll(selector).forEach(n=>document.head.appendChild(document.importNode(n,true)));
}
async function nativeInit(page){
const s=pageState(page);if(s.nativeReady)return;
const scope=scopeFor(page);
if(typeof window.t396_init!=="function")await bounded(new Promise(resolve=>window.t_onFuncLoad("t396_init",resolve)),8000);
for(const block of page.querySelectorAll(".dv-native-record")){
if(block.querySelector(".dv-bootstrap,.dv-style"))continue;
const scripts=Array.from(block.querySelectorAll("script")).filter(n=>!n.src&&!n.type?.includes("json")&&/^\s*t_on(?:Ready|FuncLoad)\s*\(/.test(n.textContent));
for(const script of scripts){inNative(scope,()=>Function(script.textContent)());executedScripts.add(script);api.nativeInits++;}
}
await frame();await frame();
s.nativeReady=true;
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
scope.formKeys=Object.keys(window.initForms||{}).filter(k=>!scope.formsBefore?.has(k));
window.dispatchEvent(new Event("resize"));
await fontsReady();await frame();refreshNativeCounts();
}
function scriptEnvironment(page){
const selectAll=selector=>{
if(selector==="body")return [document.body];if(selector==="html"||selector===":root")return [document.documentElement];
return [...page.querySelectorAll(selector),...Array.from(document.querySelectorAll(".dv-shared")).flatMap(n=>[...(n.matches(selector)?[n]:[]),...n.querySelectorAll(selector)])];
};
let scriptNode=null;
const doc=new Proxy(document,{get(target,key){
if(key==="currentScript")return scriptNode;
if(key==="querySelector")return selector=>selectAll(selector)[0]||null;
if(key==="querySelectorAll")return selectAll;
if(key==="getElementById")return id=>Array.from(page.querySelectorAll("[id]")).find(n=>n.id===id)||null;
const value=Reflect.get(target,key,target);return typeof value==="function"?value.bind(target):value;
}});
const win=window;
const jq=window.jQuery&&new Proxy(window.jQuery,{apply(target,thisArg,args){
if(args[0]===doc)args[0]=document;if(args[0]===win)args[0]=window;
if(typeof args[0]==="string"&&args.length===1&&!args[0].trim().startsWith("<"))return target(selectAll(args[0]));
return Reflect.apply(target,thisArg,args);
}});
return {doc,win,jq,setScript:n=>scriptNode=n};
}
async function customInit(page){
const state=pageState(page),s=scopeFor(page);if(state.customReady)return;
state.customReady=true;s.replay=true;
const env=scriptEnvironment(page);
for(const script of Array.from(page.querySelectorAll("script"))){
if(executedScripts.has(script)||script.closest(".dv-shared")||script.classList.contains("dv-bootstrap")||script.parentElement?.querySelector(":scope > .dv-bootstrap"))continue;
const type=script.type.trim().toLowerCase();
if(type&&!/^(?:module|(?:text|application)\/(?:java|ecma)script)$/.test(type))continue;
try{
if(script.src){
await loadScript(script.src,null);executedScripts.add(script);continue;
}
if(!script.textContent.trim())continue;
env.setScript(script);scriptOwners.set(script,s);
const fn=Function("window","document","$","jQuery",(type==="module"?'"use strict";\n':"")+script.textContent);
inNative(s,fn,window,[env.win,env.doc,env.jq,env.jq]);
executedScripts.add(script);s.customCount++;api.customInits=(api.customInits||0)+1;
}catch(error){report(error)}
}
flushJobs(s,"readyJobs");
diagnostics();
}
async function customAfterEnter(page){
const s=scopeFor(page);if(!s.replay)return;
await fontsReady();await frame();
flushJobs(s,"loadJobs");flushJobs(s,"readyJobs");
refreshNativeCounts();diagnostics();
}
function nativeAfterEnter(page){
const scope=scopeFor(page);
inNative(scope,()=>{
if(typeof window.t_lazyload_update==="function")window.t_lazyload_update();
if(typeof window.t_animate__init==="function"&&!scope.basicAuto)window.t_animate__init();
if(page.querySelector(".dv-native-sbs")&&typeof window.t_animationSBS__init==="function"&&!scope.sbsAuto)window.t_animationSBS__init();
});
if(page.querySelector("form")&&typeof window.t_forms__initForms==="function")inNative(scope,window.t_forms__initForms);
refreshNativeCounts();
}
let veil,renderer;
const dissolveProgress={value:config.open};
const VERTEX_SHADER="attribute vec2 aPosition; varying vec2 vUv; void main(){vUv=(aPosition+1.0)*0.5;gl_Position=vec4(aPosition,0.0,1.0);}";
const FRAGMENT_SHADER="precision highp float;\nuniform float uNoiseScale;\nuniform float uEdge;\nvarying vec2 vUv;\nuniform float uProgress;\nuniform vec3 uColor;\n\n// Resource noise function: https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83\n\nfloat rand(vec2 n) { \n\treturn fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);\n}\n\nfloat noise(vec2 p){\n\tvec2 ip = floor(p);\n\tvec2 u = fract(p);\n\tu = u*u*(3.0-2.0*u);\n\t\n\tfloat res = mix(\n\t\tmix(rand(ip),rand(ip+vec2(1.0,0.0)),u.x),\n\t\tmix(rand(ip+vec2(0.0,1.0)),rand(ip+vec2(1.0,1.0)),u.x),u.y);\n\treturn res*res;\n}\n\nvoid main(){\n float noise = noise(vUv * uNoiseScale);\n\n float edge = uEdge;\n\n float disolve = smoothstep(1. - uProgress - edge, 1. - uProgress + edge, noise);\n \n float alpha = 1. - disolve;\n\n gl_FragColor = vec4(uColor, alpha);\n}";
function createDissolveRenderer(canvas){
const gl=canvas.getContext("webgl",{alpha:true,antialias:true,premultipliedAlpha:true});
if(!gl)throw Error("WebGL is unavailable for Dissolve Veil");
function compile(type,source){const shader=gl.createShader(type);gl.shaderSource(shader,source);gl.compileShader(shader);if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS))throw Error("Dissolve shader: "+gl.getShaderInfoLog(shader));return shader}
const vertex=compile(gl.VERTEX_SHADER,VERTEX_SHADER),fragment=compile(gl.FRAGMENT_SHADER,FRAGMENT_SHADER),program=gl.createProgram();
gl.attachShader(program,vertex);gl.attachShader(program,fragment);gl.linkProgram(program);
if(!gl.getProgramParameter(program,gl.LINK_STATUS))throw Error("Dissolve program: "+gl.getProgramInfoLog(program));
const position=gl.getAttribLocation(program,"aPosition"),buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),gl.STATIC_DRAW);
const uniforms={};for(const name of ["uProgress","uColor","uNoiseScale","uEdge"])uniforms[name]=gl.getUniformLocation(program,name);
let hex=config.color.replace(/^#/,"");if(hex.length===3)hex=hex.split("").map(c=>c+c).join("");
if(!/^[0-9a-f]{6}$/i.test(hex))throw Error("TRANSITION_COLOR must be a HEX color");
const color=[0,2,4].map(i=>parseInt(hex.slice(i,i+2),16)/255);
function render(){
if(gl.isContextLost())return;
gl.useProgram(program);gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.enableVertexAttribArray(position);gl.vertexAttribPointer(position,2,gl.FLOAT,false,0,0);
gl.uniform1f(uniforms.uProgress,dissolveProgress.value);gl.uniform3fv(uniforms.uColor,color);gl.uniform1f(uniforms.uNoiseScale,config.noiseScale);gl.uniform1f(uniforms.uEdge,config.edge);
gl.enable(gl.BLEND);gl.blendEquationSeparate(gl.FUNC_ADD,gl.FUNC_ADD);gl.blendFuncSeparate(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA,gl.ONE,gl.ONE_MINUS_SRC_ALPHA);
gl.clearColor(0,0,0,0);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES,0,6);
}
function resize(){
const w=window.innerWidth,h=window.innerHeight,dpr=Math.min(window.devicePixelRatio||1,config.maxPixelRatio);
canvas.width=Math.max(1,Math.round(w*dpr));canvas.height=Math.max(1,Math.round(h*dpr));canvas.style.width=w+"px";canvas.style.height=h+"px";
gl.viewport(0,0,canvas.width,canvas.height);render();
}
resize();return {render,resize};
}
function phase(data,part){
const site=document.querySelector(".dv-site");if(site){site.dataset.dvPhase=part;site.dataset.dvDirection="dissolve"}
gsap.set(veil,{autoAlpha:1,pointerEvents:"auto"});
dissolveProgress.value=part==="cover"?config.open:config.closed;renderer.render();
return new Promise(resolve=>{
gsap.to(dissolveProgress,{value:part==="cover"?config.closed:config.open,duration:config.phaseDuration,ease:config.ease,
onUpdate:()=>{renderer.render();if(site)site.dataset.dvProgress=String(dissolveProgress.value)},
onComplete:()=>{renderer.render();if(site)site.dataset.dvPhase=part==="cover"?"covered":"revealed";resolve()}
});
});
}
function cleanup(page){
const s=pageStates.get(page);if(!s)return;
disposeNative(page);s.context?.revert();s.cleanup.forEach(f=>f());
s.listeners.forEach(({target,type,listener,options})=>target.removeEventListener(type,listener,options));
pageStates.delete(page);
}
function lock(){if(state.busy)return;state.busy=true;state.oldScroll=window.scrollY;state.oldFocus=document.activeElement;document.documentElement.classList.add("dv-busy")}
function unlock(){state.busy=false;state.pending=false;document.documentElement.classList.remove("dv-busy")}
function blockScroll(e){if(state.busy)e.preventDefault()}
function blockKeys(e){if(state.busy&&["ArrowDown","ArrowUp","PageDown","PageUp","Home","End"," "].includes(e.key))e.preventDefault()}
function focusPage(page){
const heading=page.querySelector(".dv-title h1,.dv-title h2,.dv-title h3")||page,prev=heading.getAttribute("tabindex");
heading.setAttribute("tabindex","-1");heading.focus({preventScroll:true});
heading.addEventListener("blur",()=>{if(prev===null)heading.removeAttribute("tabindex");else heading.setAttribute("tabindex",prev)},{once:true});
}
function resetOverlay(){dissolveProgress.value=config.open;renderer?.render();veil.style.backgroundColor="";gsap.set(veil,{autoAlpha:0,pointerEvents:"none"})}
async function start(){
if(!window.gsap||!window.barba||!window.ScrollTrigger)throw Error("GSAP, ScrollTrigger or Barba failed to load");
gsap.registerPlugin(ScrollTrigger);gsap.ticker.lagSmoothing(0);
const first=prepare(document,location.href);if(!first)throw Error("No native Zero Blocks found");
initialPage=first;if(initialScope){initialScope.page=first;pageState(first).nativeScope=initialScope}
Array.from(document.scripts).forEach(s=>{if(s.src)loadedScripts.add(s.src)});
document.documentElement.classList.add("dv-root");pageState(first).nativeReady=true;
scopeFor(first).formKeys=Object.keys(window.initForms||{});
if(window.onpopstate)inNative(scopeFor(first),()=>{window.onpopstate=window.onpopstate});
history.scrollRestoration="manual";
veil=document.createElement("div");veil.className="dv-veil";veil.setAttribute("aria-hidden","true");
const canvas=document.createElement("canvas");canvas.className="dv-canvas";veil.appendChild(canvas);document.body.appendChild(veil);
renderer=createDissolveRenderer(canvas);
window.addEventListener("resize",()=>renderer.resize());
raw.add.call(canvas,"webglcontextlost",event=>{event.preventDefault();if(state.busy)veil.style.backgroundColor=config.color;report(Error("Dissolve WebGL context lost"))});
raw.add.call(canvas,"webglcontextrestored",()=>{renderer=createDissolveRenderer(canvas);veil.style.backgroundColor="";renderer.render()});
const baseToDocument=barba.dom.toDocument.bind(barba.dom);
barba.dom.toDocument=function(html){const doc=baseToDocument(html);prepare(doc,location.href);return doc};
barba.dom.toElement=function(html){return barba.dom.toDocument(html).documentElement};
barba.hooks.before(data=>{
lock();state.epoch++;scopeFor(data.current.container).paused=true;data.current.container.inert=true;
api.lastTransition={from:data.current.url.path,to:data.next.url.path,started:performance.now(),epoch:state.epoch};
});
barba.hooks.afterLeave(data=>{cleanup(data.current.container);data.current.container.remove()});
barba.hooks.beforeEnter(async data=>{
if(!api.ready)return;
const next=data.next.container;next.inert=true;
state.oldScroll=0;window.scrollTo({top:0,left:0,behavior:"instant"});
await syncAssets(data.next.html,next);await nativeInit(next);await customInit(next);
nativeAfterEnter(next);await customAfterEnter(next);ScrollTrigger.refresh();
});
barba.hooks.afterEnter(data=>{data.next.container.inert=false;ScrollTrigger.refresh()});
barba.hooks.after(data=>{
resetOverlay();unlock();data.next.container.classList.add("dv-ready");focusPage(data.next.container);
refreshNativeCounts();api.transitions++;api.lastTransition.finished=performance.now();
api.lastTransition.duration=api.lastTransition.finished-api.lastTransition.started;diagnostics();
document.dispatchEvent(new CustomEvent("av:after",{detail:{url:location.href,count:api.transitions}}));
});
barba.init({timeout:15000,preventRunning:true,cacheIgnore:false,prefetchIgnore:false,
prevent:({el,href})=>{
if(window.innerWidth<320||!el.closest(".dv-link")||el.hasAttribute("download"))return true;
const u=new URL(href,location.href);return u.origin!==location.origin||!!u.hash;
},
requestError:(_trigger,_action,url,error)=>{report(error);if(veil)resetOverlay();unlock();return true},
transitions:[{name:"dissolve-veil",sync:false,
async once(){await fontsReady();await frame();api.ready=true;diagnostics()},
leave(data){return phase(data,"cover")},enter(data){return phase(data,"uncover")}
}]
});
document.addEventListener("click",e=>{
const link=e.target.closest?.(".dv-link a,a.dv-link");if(!link||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;
if(state.busy||state.pending){e.preventDefault();e.stopImmediatePropagation();return}
if(window.innerWidth<320)return;
const href=new URL(link.href,location.href);if(href.origin!==location.origin||href.hash||link.target==="_blank")return;
if(href.pathname===location.pathname&&href.search===location.search){e.preventDefault();e.stopImmediatePropagation();return}
state.pending=true;
},true);
window.addEventListener("scroll",()=>{if(state.busy&&window.scrollY!==state.oldScroll)window.scrollTo(0,state.oldScroll)},{passive:true});
window.addEventListener("wheel",blockScroll,{passive:false});window.addEventListener("touchmove",blockScroll,{passive:false});window.addEventListener("keydown",blockKeys);
api.status=()=>({ready:api.ready,busy:state.busy,pending:state.pending,transitions:api.transitions,documentToken:api.documentToken,errors:api.errors.slice()});
}
const ready=()=>start().catch(error=>{report(error);if(veil)resetOverlay();unlock()});
if(document.readyState==="loading")raw.add.call(document,"DOMContentLoaded",ready,{once:true});else ready();
})();
</script>

Более подробные настройки, возможности взаимодействия и подключение в видео

Инструкция с копированием шаблона к себе

Создаём новую страницу на сайте
Шаг 1
Скроллим в самый низ и нажимаем кнопку «Указать ID шаблона»
Шаг 2
В графе указываем номер шаблона (ID Шаблона), нажимаем кнопку «Выбрать»
Шаг 3