1<!doctype html><html lang=en><head><meta name=generator content="Hugo 0.123.7"><meta charset=utf-8><title>Offshift | Privacy on Ethereum L1</title> 2<meta name=description content="XFT and zkAssets â powered by the Momiji protocol"><meta name=viewport content="width=device-width,initial-scale=1"><meta property="og:title" content="Offshift | Privacy on Ethereum L1"><meta property="og:description" content="XFT and zkAssets â powered by the Momiji protocol"><meta property="og:type" content="website"><meta property="og:url" content="https://offshift.io/"><meta property="og:image" content="https://offshift.io/images/og-default.png"><meta name=twitter:card content="summary_large_image"><meta name=twitter:site content="@OffshiftXFT"><meta name=twitter:image content="https://offshift.io/images/og-default.png"><link rel=icon type=image/png href=/images/favicons/favicon.png><link rel=preload href=/fonts/Satoshi/Satoshi-Variable.woff2 as=font type=font/woff2 crossorigin><link rel=stylesheet href=/fonts/Satoshi/Satoshi.css><link rel=preconnect href=https://fonts.googleapis.com><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel=stylesheet><link rel=stylesheet href=/css/design-system.css><link rel=stylesheet href=/css/components.css></head><body class=void-theme><a href="https://offshift.io/cdn-cgi/content?id=ktM.3A5a60v5OmgMCLb70kCN9IhwUDU.enTEn.TBmP8-1790870654.2577882-1.2.1.1-0ojiXj0twpwBm2G5wBfpcEUJlBmh1jHYTpdLHz7ySKiRZ2G7TaqtK2_DuFN6EEKx" aria-hidden="true" rel="nofollow noopener" style="display: none !important; visibility: hidden !important"></a><header class=header-void id=header><div class=header-content><a href=/ class=header-logo-link><img src=/images/promo/logo-momiji.png alt=Offshift class=header-logo></a><nav class=header-nav id=headerNav><a href=/analytics class=header-link>Analytics</a> 3<a href=/blog class=header-link>Blog</a> 4<a href=/press-and-media class=header-link>Press & Media</a><div class=header-dropdown><button class="header-link header-dropdown-trigger"> 5Resources<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></button><div class=header-dropdown-menu><a href=/momiji-litepaper class=header-dropdown-item>Momiji Litepaper</a> 6<a href=https://open.offshift.io target=_blank class=header-dropdown-item>GitLab</a> 7<a href=/#resources class=header-dropdown-item>Community</a></div></div><div class=header-dropdown><button class="header-link header-dropdown-trigger"> 8Buy XFT<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></button><div class=header-dropdown-menu><a href=https://swap.cow.fi/#/1/swap/ETH/0x76BC677d444f1E9d57dAf5187ee2b7dC852745aE target=_blank class=header-dropdown-item>Buy on CoW Swap</a> 9<a href=https://app.uniswap.org/tokens/ethereum/0x76bc677d444f1e9d57daf5187ee2b7dc852745ae target=_blank class=header-dropdown-item>Buy on Uniswap</a> 10<a href="https://www.sushi.com/ethereum/swap?token0=NATIVE&token1=0x76BC677d444f1E9d57dAf5187ee2b7dC852745aE" target=_blank class=header-dropdown-item>Buy on SushiSwap</a></div></div><div class=header-dropdown><button class="header-apps-btn header-dropdown-trigger"> 11Apps<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></button><div class=header-dropdown-menu><a href=https://momiji.offshift.io class=header-dropdown-item>Momiji</a> 12<a href=https://stake.offshift.io class=header-dropdown-item>Stake LP Tokens</a></div></div><span class=header-cta></span></nav><div class=header-actions><div class=mobile-wallet-blockie></div><button class=mobile-menu-toggle id=mobileMenuToggle aria-label="Toggle menu"> 13<span class=hamburger-line></span> 14<span class=hamburger-line></span> 15<span class=hamburger-line></span></button></div></div></header><div class=mobile-menu id=mobileMenu><nav class=mobile-nav><a href=/analytics class=mobile-nav-link>Analytics</a> 16<a href=/blog class=mobile-nav-link>Blog</a> 17<a href=/press-and-media class=mobile-nav-link>Press & Media</a><div class=mobile-nav-divider></div><a href=/momiji-litepaper class=mobile-nav-link>Momiji Litepaper</a>
18<a href=https://open.offshift.io target=_blank class=mobile-nav-link>GitLab</a> 19<a href=/#resources class=mobile-nav-link>Community</a><div class=mobile-nav-divider></div><a href=/#trade class=mobile-nav-link>Buy XFT</a> 20<a href=https://stake.offshift.io class=mobile-nav-link>Stake LP Tokens</a><div class=mobile-nav-divider></div><a href=https://momiji.offshift.io class=mobile-nav-cta>Launch Momiji</a></nav></div><style>.header-void{position:fixed;top:0;left:0;right:0;z-index:var(--z-sticky);padding:.25rem 1.25rem;padding-top:calc(.25rem + env(safe-area-inset-top));-webkit-user-select:none;user-select:none;background:rgba(3,1,8,.35);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);border:none;transition:background var(--transition-base),box-shadow var(--transition-base)}.header-void.scrolled{background:rgba(3,1,8,.7);box-shadow:0 4px 30px rgba(0,0,0,.3)}.header-content{display:flex;align-items:center;justify-content:space-between;max-width:var(--container-xl);margin:0 auto}.header-logo-link{flex-shrink:0}.header-logo{height:32px;width:auto}.header-nav{display:none;align-items:center;gap:var(--space-6)}.header-void .header-link{display:inline-flex;align-items:center;gap:var(--space-1);font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--text-secondary);text-decoration:none;background:0 0;border:none;cursor:pointer;padding:var(--space-2)0;transition:color var(--transition-fast)}.header-link svg{transition:transform var(--transition-fast)}.header-cta{display:inline-flex;align-items:center;justify-content:center;min-width:150px;font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--text-primary);text-decoration:none;padding:var(--space-2)var(--space-4);border:1px solid var(--lum-purple);border-radius:var(--radius-lg);transition:all var(--transition-fast)}.header-cta:empty{width:32px;min-width:32px;height:32px;border:none;padding:0;visibility:hidden}.header-apps-btn{display:inline-flex;align-items:center;gap:var(--space-1);font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--text-primary);background:0 0;cursor:pointer;padding:var(--space-2)var(--space-4);border:1px solid var(--lum-purple);border-radius:var(--radius-lg);transition:all var(--transition-fast)}.header-apps-btn svg{transition:transform var(--transition-fast)}.header-dropdown{position:relative}.header-dropdown-menu{position:absolute;top:100%;left:50%;transform:translateX(-50%)translateY(8px);
20min-width:200px;background:var(--void-elevated);border:1px solid var(--glass-border);border-radius:var(--radius-lg);padding:var(--space-2);opacity:0;visibility:hidden;transition:all var(--transition-fast);box-shadow:var(--shadow-xl)}.header-dropdown-menu::before{content:'';position:absolute;top:-12px;left:0;right:0;height:12px}.header-dropdown-item{display:block;padding:var(--space-3)var(--space-4);font-size:var(--text-sm);color:var(--text-secondary);text-decoration:none;border-radius:var(--radius-md);transition:all var(--transition-fast)}.mobile-wallet-blockie{display:none}.mobile-wallet-blockie.has-content{display:flex;align-items:center}.header-actions{display:flex;align-items:center;gap:var(--space-4)}.mobile-menu-toggle{display:flex;flex-direction:column;justify-content:center;align-items:center;gap:4px;width:36px;height:36px;background:0 0;border:none;cursor:pointer;padding:6px;-webkit-tap-highlight-color:transparent;touch-action:manipulation}.hamburger-line{display:block;width:100%;height:2px;background:var(--text-primary);border-radius:2px;transition:transform var(--transition-fast),opacity var(--transition-fast)}.mobile-menu-toggle.active .hamburger-line:nth-child(1){transform:rotate(45deg)translate(5px,5px)}.mobile-menu-toggle.active .hamburger-line:nth-child(2){opacity:0}.mobile-menu-toggle.active .hamburger-line:nth-child(3){transform:rotate(-45deg)translate(5px,-5px)}.mobile-menu{position:fixed;inset:0;z-index:199;background:var(--void-abyss);display:flex;flex-direction:column;align-items:center;padding:6rem 2rem 2rem;padding-top:calc(6rem + env(safe-area-inset-top));padding-bottom:calc(2rem + env(safe-area-inset-bottom));overflow-y:auto;-webkit-overflow-scrolling:touch;opacity:0;pointer-events:none;transition:opacity .3s ease}.mobile-menu.active{opacity:1;pointer-events:all}.mobile-nav{display:flex;flex-direction:column;align-items:center;gap:var(--space-3);width:100%;max-width:320px}.mobile-nav-link{display:flex;align-items:center;justify-content:center;width:100%;min-height:44px;padding:var(--space-3)var(--space-4);font-family:var(--font-display);font-size:1.25rem;font-weight:var(--font-medium);color:var(--text-primary);text-decoration:none;border-radius:var(--radius-lg);transition:color var(--transition-fast),background var(--transition-fast);-webkit-tap-highlight-color:transparent}.mobile-nav-link:active{background:var(--void-surface)}.mobile-nav-divider{width:60%;height:1px;background:var(--glass-border);margin:var(--space-2)0}.mobile-nav-cta{display:flex;align-items:center;justify-content:center;width:100%;min-height:52px;padding:var(--space-4);font-family:var(--font-display);font-size:1rem;font-weight:var(--font-semibold);color:var(--text-primary);text-decoration:none;text-align:center;border:1px solid var(--lum-purple);border-radius:var(--radius-lg);transition:all var(--transition-fast);-webkit-tap-highlight-color:transparent}.mobile-nav-cta:active{background:rgba(124,58,237,.15)}@media(hover:hover){.header-void .header-link:hover{color:var(--text-primary)}.header-cta:hover{background:rgba(124,58,237,.15);border-color:var(--lum-cyan);color:var(--text-primary)}.header-apps-btn:hover{background:rgba(124,58,237,.15);border-color:var(--lum-cyan);color:var(--text-primary)}.header-dropdown:hover .header-apps-btn svg{transform:rotate(180deg)}.header-dropdown:hover .header-dropdown-menu{opacity:1;visibility:visible;transform:translateX(-50%)translateY(4px)}.header-dropdown:hover .header-dropdown-trigger svg{transform:rotate(180deg)}.header-dropdown-item:hover{background:var(--void-overlay);color:var(--text-primary)}.mobile-nav-link:hover{background:var(--void-surface);color:var(--text-primary)}.mobile-nav-cta:hover{background:rgba(124,58,237,.15);border-color:var(--lum-cyan);color:var(--lum-cyan)}}@media(min-width:1024px){.header-void{padding:var(--space-2)var(--space-6)}.header-nav{display:flex}.header-actions{display:none}.mobile-menu{display:none}}</style>
20<script>const header=document.getElementById("header");window.addEventListener("scroll",()=>{header.classList.toggle("scrolled",window.scrollY>50)},{passive:!0});const mobileMenuToggle=document.getElementById("mobileMenuToggle"),mobileMenu=document.getElementById("mobileMenu");function closeMenu(){mobileMenuToggle.classList.remove("active"),mobileMenu.classList.remove("active"),mobileMenuToggle.setAttribute("aria-expanded","false"),document.body.style.overflow="";var e=document.querySelector(".fluid-canvas");e&&e._resumeAutoSplats&&e._resumeAutoSplats()}function openMenu(){mobileMenuToggle.classList.add("active"),mobileMenu.classList.add("active"),mobileMenuToggle.setAttribute("aria-expanded","true"),document.body.style.overflow="hidden";var e=document.querySelector(".fluid-canvas");e&&e._pauseAutoSplats&&e._pauseAutoSplats()}mobileMenuToggle&&mobileMenu&&(mobileMenuToggle.setAttribute("aria-expanded","false"),mobileMenuToggle.addEventListener("click",()=>{mobileMenu.classList.contains("active")?closeMenu():openMenu()}),mobileMenu.querySelectorAll("a").forEach(e=>{e.addEventListener("click",closeMenu)}),document.addEventListener("keydown",e=>{e.key==="Escape"&&mobileMenu.classList.contains("active")&&(closeMenu(),mobileMenuToggle.focus())}))</script>
20<main class=main-content><section class="hero-fluid hero-immersive" aria-label="Offshift â Privacy on Ethereum Layer 1"><canvas class=fluid-canvas aria-hidden=true></canvas><div class=fluid-touch-zone aria-hidden=true></div><div class=fluid-content><h1 class=fluid-headline>Privacy on<br>Ethereum L1</h1><div class=fluid-actions><a href=#about class=fluid-btn-ghost>Learn More</a></div></div></section><style>.hero-fluid{position:relative;height:100svh;background:0 0;overflow:hidden;-webkit-user-select:none;user-select:none}.fluid-touch-zone{position:absolute;z-index:3;border-radius:50%;background:rgba(0,0,0,.1%);touch-action:none;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;cursor:pointer}.fluid-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:2;pointer-events:none;-webkit-mask-image:url(/images/promo/offshift-o-mask.svg);mask-image:url(/images/promo/offshift-o-mask.svg);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.fluid-content{position:relative;z-index:10;height:100%;display:flex;flex-direction:column;width:100%;max-width:var(--container-xl);margin:0 auto;padding:0 var(--space-6);padding-bottom:calc(env(safe-area-inset-bottom,0px) + 3rem);pointer-events:none}.fluid-actions{pointer-events:auto}.hero-split .fluid-canvas{-webkit-mask-size:65vw;mask-size:65vw;-webkit-mask-position:50% 35%;mask-position:50% 35%}.hero-split .fluid-content{justify-content:flex-end;align-items:flex-start;max-width:100%;padding-bottom:calc(env(safe-area-inset-bottom,0px) + clamp(2rem,6vh,4rem))}@media(min-width:768px){.hero-split .fluid-canvas{-webkit-mask-size:min(52vw,82vh);mask-size:min(52vw,82vh);-webkit-mask-position:68% 50%;mask-position:68% 50%}.hero-split .fluid-content{justify-content:center;max-width:45%}}.hero-immersive .fluid-canvas{-webkit-mask-size:min(110vw,88vh);mask-size:min(110vw,88vh);-webkit-mask-position:50% calc(50% + 32px);mask-position:50% calc(50% + 32px)}.hero-immersive .fluid-touch-zone{width:min(110vw,88vh);height:min(110vw,88vh);left:50%;top:calc(50% + 32px);transform:translate(-50%,-50%)}.hero-immersive .fluid-content{justify-content:flex-end;align-items:flex-start;padding-bottom:calc(env(safe-area-inset-bottom,0px) + clamp(4rem,15vh,10rem))}.hero-immersive .fluid-actions{flex-wrap:nowrap}.fluid-headline{font-family:var(--font-display);font-size:clamp(1rem,3vw,1.75rem);font-weight:var(--font-bold);line-height:var(--leading-tight);color:var(--text-primary);white-space:nowrap}.fluid-actions{display:flex;gap:1rem;margin-top:.4rem;flex-wrap:wrap}.fluid-btn-primary{display:inline-flex;align-items:center;justify-content:center;padding:.7rem 1.5rem;min-height:40px;white-space:nowrap;font-family:var(--font-display);font-size:clamp(.7rem,2.5vw,.875rem);font-weight:var(--font-semibold);color:var(--void-abyss);background:var(--lum-violet);border:none;border-radius:var(--radius-md);text-decoration:none;transition:all var(--transition-fast)}.fluid-btn-ghost{display:inline-flex;align-items:center;justify-content:center;padding:.7rem 1.5rem;min-height:40px;white-space:nowrap;font-family:var(--font-display);font-size:clamp(.7rem,2.5vw,.875rem);font-weight:var(--font-semibold);color:var(--lum-violet);background:0 0;border:1px solid rgba(107,57,250,.3);border-radius:var(--radius-md);text-decoration:none;transition:all var(--transition-fast)}.hero-fluid::before{content:'';position:absolute;inset:0;z-index:1;background:radial-gradient(ellipse at 50% calc(50% + 32px),rgba(107,57,250,.25) 0%,rgba(86,0,172,.12) 25%,transparent 55%);-webkit-mask-image:url(/images/promo/offshift-o-mask.svg);mask-image:url(/images/promo/offshift-o-mask.svg);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;pointer-events:none}.hero-immersive::before{-webkit-mask-size:min(110vw,88vh);mask-size:min(110vw,88vh);-webkit-mask-position:50% calc(50% + 32px);mask-position:50% calc(50% + 32px)}.hero-split::before{-webkit-mask-size:65vw;mask-size:65vw;-webkit-mask-position:50% 35%;mask-position:50% 35%}@media(min-width:768px){.hero-split::before{-webkit-mask-size:min(52vw,82vh);mask-size:min(52vw,82vh);-webkit-mask-position:68% 50%;
20mask-position:68% 50%}}.hero-fluid.fluid-active::before{display:none}@media(hover:hover){.fluid-btn-primary:hover{background:var(--lum-purple-bright);box-shadow:0 0 20px var(--purple-glow)}.fluid-btn-ghost:hover{background:rgba(107,57,250,.1);border-color:var(--lum-violet)}}</style>
20<script>(function(){"use strict";var e,t,n,o,a,r,l,d,u,h,m,f,g,v,b,j,_,w,x,C,E,k,S,M,F,z,D,N,L,R,P,H,B,$,W,q,Y,Q,Z,J,s=document.querySelector(".fluid-canvas"),te,ee,me,ue,ae,ke,Ee,Ce,ve,re,ie,_e,oe,ce,de,Ae,pe,fe,Be,le;if(!s)return;n={SIM_RESOLUTION:128,DYE_RESOLUTION:1024,DENSITY_DISSIPATION:.97,VELOCITY_DISSIPATION:.98,PRESSURE:.8,PRESSURE_ITERATIONS:20,CURL:30,SPLAT_RADIUS:.25,SPLAT_FORCE:6e3,SHADING:!0,BLOOM:!0,BLOOM_ITERATIONS:8,BLOOM_RESOLUTION:256,BLOOM_INTENSITY:.3,BLOOM_THRESHOLD:.6,BLOOM_SOFT_KNEE:.7,BACK_COLOR:{r:3,g:1,b:8}},q=[{r:.48,g:.38,b:1},{r:.35,g:.25,b:.85},{r:0,g:1,b:1},{r:.55,g:.45,b:1},{r:.1,g:.6,b:.8}],Y=0;function T(){var e=q[Y%q.length];return Y++,{r:e.r*.15,g:e.g*.15,b:e.b*.15}}function He(){return/Mobi|Android/i.test(navigator.userAgent)}if(He()&&(n.DYE_RESOLUTION=512,n.BLOOM_RESOLUTION=128),je(),F={alpha:!0,depth:!1,stencil:!1,antialias:!1,preserveDrawingBuffer:!1},e=s.getContext("webgl2",F),M=!!e,M||(e=s.getContext("webgl",F)||s.getContext("experimental-webgl",F)),!e)return;if(s._gl=e,M?(e.getExtension("EXT_color_buffer_float"),h=e.getExtension("OES_texture_float_linear")):(H=e.getExtension("OES_texture_half_float"),h=e.getExtension("OES_texture_half_float_linear")),e.clearColor(0,0,0,0),b=M?e.HALF_FLOAT:H?H.HALF_FLOAT_OES:e.UNSIGNED_BYTE,M?(g=y(e.RGBA16F,e.RGBA,b),te=y(e.RG16F,e.RG,b),ee=y(e.R16F,e.RED,b)):(g=y(e.RGBA,e.RGBA,b),te=g,ee=g),!g)return;h||(n.DYE_RESOLUTION=512,n.SHADING=!1,n.BLOOM=!1);function y(t,n,s){return Ie(t,n,s)?{internalFormat:t,format:n}:t===e.R16F?y(e.RG16F,e.RG,s):t===e.RG16F?y(e.RGBA16F,e.RGBA,s):null}function Ie(t,n,s){var i,a,o=e.createTexture();return e.bindTexture(e.TEXTURE_2D,o),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texImage2D(e.TEXTURE_2D,0,t,4,4,0,n,s,null),i=e.createFramebuffer(),e.bindFramebuffer(e.FRAMEBUFFER,i),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,o,0),a=e.checkFramebufferStatus(e.FRAMEBUFFER),e.deleteFramebuffer(i),e.deleteTexture(o),a===e.FRAMEBUFFER_COMPLETE}function i(t,n,s){if(s){for(var o,a="",i=0;i<s.length;i++)a+="#define "+s[i]+` 21`;n=a+n}return o=e.createShader(t),e.shaderSource(o,n),e.compileShader(o),o}function be(t,n){var s=e.createProgram();return e.attachShader(s,t),e.attachShader(s,n),e.linkProgram(s),s}function xe(t){for(var s,o={},i=e.getProgramParameter(t,e.ACTIVE_UNIFORMS),n=0;n<i;n++)s=e.getActiveUniform(t,n).name,o[s]=e.getUniformLocation(t,s);return o}function c(e,t){this.program=be(e,t),this.uniforms=xe(this.program)}c.prototype.bind=function(){e.useProgram(this.program)};function U(e,t){this.vs=e,this.fragSource=t,this.programs={},this.activeProgram=null,this.uniforms={}}U.prototype.setKeywords=function(t){for(var n,o,r,c,s=0,a=0;a<t.length;a++)for(r=t[a],o=0;o<r.length;o++)s=(s<<5)-s+r.charCodeAt(o)|0;if(n=this.programs[s],n||(c=i(e.FRAGMENT_SHADER,this.fragSource,t),n=be(this.vs,c),this.programs[s]=n),n===this.activeProgram)return;this.uniforms=xe(n),this.activeProgram=n},U.prototype.bind=function(){e.useProgram(this.activeProgram)},r=i(e.VERTEX_SHADER,` 22 precision highp float; 23 attribute vec2 aPosition; 24 varying vec2 vUv; 25 varying vec2 vL; 26 varying vec2 vR; 27 varying vec2 vT; 28 varying vec2 vB; 29 uniform vec2 texelSize; 30 void main () { 31 vUv = aPosition * 0.5 + 0.5; 32 vL = vUv - vec2(texelSize.x, 0.0); 33 vR = vUv + vec2(texelSize.x, 0.0); 34 vT = vUv + vec2(0.0, texelSize.y); 35 vB = vUv - vec2(0.0, texelSize.y); 36 gl_Position = vec4(aPosition, 0.0, 1.0); 37 } 38 `),me=i(e.VERTEX_SHADER,` 39 precision highp float; 40 attribute vec2 aPosition; 41 varying vec2 vUv; 42 varying vec2 vL; 43 varying vec2 vR; 44 uniform vec2 texelSize; 45 void main () { 46 vUv = aPosition * 0.5 + 0.5; 47 float offset = 1.33333333; 48 vL = vUv - texelSize * offset; 49 vR = vUv + texelSize * offset; 50 gl_Position = vec4(aPosition, 0.0, 1.0); 51 } 52 `),ue=i(e.FRAGMENT_SHADER,` 53 precision mediump float; 54 precision mediump sampler2D; 55 varying vec2 vUv; 56 varying vec2 vL; 57 varying vec2 vR; 58 uniform sampler2D uTexture; 59 void main () { 60 vec4 sum = texture2D(uTexture, vUv) * 0.29411764; 61 sum += texture2D(uTexture, vL) * 0.35294117; 62 sum += texture2D(uTexture, vR) * 0.35294117; 63 gl_FragColor = sum; 64 } 65 `),ae=i(e.FRAGMENT_SHADER,` 66 precision mediump float; 67 precision mediump sampler2D; 68 varying highp vec2 vUv; 69 uniform sampler2D uTexture; 70 void main () { gl_FragColor = texture2D(uTexture, vUv); } 71 `),ke=i(e.FRAGMENT_SHADER,` 72 precision mediump float; 73 precision mediump sampler2D; 74 varying highp vec2 vUv; 75 uniform sampler2D uTexture; 76 uniform float value; 77 void main () { gl_FragColor = value * texture2D(uTexture, vUv); } 78 `),Ee=i(e.FRAGMENT_SHADER,` 79 precision mediump float; 80 uniform vec4 color; 81 void main () { gl_FragColor = color; } 82 `),Ce=` 83 precision highp float; 84 precision highp sampler2D; 85 varying vec2 vUv; 86 varying vec2 vL; 87 varying vec2 vR; 88 varying vec2 vT; 89 varying vec2 vB; 90 uniform sampler2D uTexture; 91 uniform sampler2D uBloom; 92 uniform vec2 texelSize; 93 vec3 linearToGamma (vec3 color) { 94 color = max(color, vec3(0)); 95 return max(1.055 * pow(color, vec3(0.416666667)) - 0.055, vec3(0)); 96 } 97 void main () { 98 vec3 c = texture2D(uTexture, vUv).rgb; 99 #ifdef SHADING 100 vec3 lc = texture2D(uTexture, vL).rgb; 101 vec3 rc = texture2D(uTexture, vR).rgb; 102 vec3 tc = texture2D(uTexture, vT).rgb; 103 vec3 bc = texture2D(uTexture, vB).rgb; 104 float dx = length(rc) - length(lc); 105 float dy = length(tc) - length(bc); 106 vec3 n = normalize(vec3(dx, dy, length(texelSize))); 107 vec3 l = vec3(0.0, 0.0, 1.0); 108 float diffuse = clamp(dot(n, l) + 0.7, 0.7, 1.0); 109 c *= diffuse; 110 #endif 111 #ifdef BLOOM 112 vec3 bloom = texture2D(uBloom, vUv).rgb; 113 bloom = linearToGamma(bloom); 114 c += bloom; 115 #endif 116 float a = clamp(max(c.r, max(c.g, c.b)) * 3.0, 0.0, 1.0); 117 gl_FragColor = vec4(c, a); 118 } 119 `,ve=i(e.FRAGMENT_SHADER,` 120 precision mediump float; 121 precision mediump sampler2D; 122 varying vec2 vUv; 123 uniform sampler2D uTexture; 124 uniform vec3 curve; 125 uniform float threshold; 126 void main () { 127 vec3 c = texture2D(uTexture, vUv).rgb; 128 float br = max(c.r, max(c.g, c.b)); 129 float rq = clamp(br - curve.x, 0.0, curve.y); 130 rq = curve.z * rq * rq; 131 c *= max(rq, br - threshold) / max(br, 0.0001); 132 gl_FragColor = vec4(c, 0.0); 133 } 134 `),re=i(e.FRAGMENT_SHADER,` 135 precision mediump float; 136 precision mediump sampler2D; 137 varying vec2 vL; 138 varying vec2 vR; 139 varying vec2 vT; 140 varying vec2 vB; 141 uniform sampler2D uTexture; 142 void main () { 143 vec4 sum = vec4(0.0); 144 sum += texture2D(uTexture, vL); 145 sum += texture2D(uTexture, vR); 146 sum += texture2D(uTexture, vT); 147 sum += texture2D(uTexture, vB); 148 sum *= 0.25; 149 gl_FragColor = sum; 150 } 151 `),ie=i(e.FRAGMENT_SHADER,` 152 precision mediump float; 153 precision mediump sampler2D; 154 varying vec2 vL; 155 varying vec2 vR; 156 varying vec2 vT; 157 varying vec2 vB; 158 uniform sampler2D uTexture; 159 uniform float intensity; 160 void main () { 161 vec4 sum = vec4(0.0); 162 sum += texture2D(uTexture, vL); 163 sum += texture2D(uTexture, vR); 164 sum += texture2D(uTexture, vT); 165 sum += texture2D(uTexture, vB); 166 sum *= 0.25; 167 gl_FragColor = sum * intensity; 168 } 169 `),_e=i(e.FRAGMENT_SHADER,` 170 precision highp float; 171 precision highp sampler2D; 172 varying vec2 vUv; 173 uniform sampler2D uTarget; 174 uniform float aspectRatio; 175 uniform vec3 color; 176 uniform vec2 point; 177 uniform float radius; 178 void main () { 179 vec2 p = vUv - point.xy; 180 p.x *= aspectRatio; 181 vec3 splat = exp(-dot(p, p) / radius) * color; 182 vec3 base = texture2D(uTarget, vUv).xyz; 183 gl_FragColor = vec4(base + splat, 1.0); 184 } 185 `),oe=i(e.FRAGMENT_SHADER,` 186 precision highp float; 187 precision highp sampler2D; 188 varying vec2 vUv; 189 uniform sampler2D uVelocity; 190 uniform sampler2D uSource; 191 uniform vec2 texelSize; 192 uniform vec2 dyeTexelSize; 193 uniform float dt; 194 uniform float dissipation; 195 vec4 bilerp (sampler2D sam, vec2 uv, vec2 tsize) { 196 vec2 st = uv / tsize - 0.5; 197 vec2 iuv = floor(st); 198 vec2 fuv = fract(st); 199 vec4 a = texture2D(sam, (iuv + vec2(0.5, 0.5)) * tsize); 200 vec4 b = texture2D(sam, (iuv + vec2(1.5, 0.5)) * tsize); 201 vec4 c = texture2D(sam, (iuv + vec2(0.5, 1.5)) * tsize); 202 vec4 d = texture2D(sam, (iuv + vec2(1.5, 1.5)) * tsize); 203 return mix(mix(a, b, fuv.x), mix(c, d, fuv.x), fuv.y); 204 } 205 void main () {
206 #ifdef MANUAL_FILTERING 207 vec2 coord = vUv - dt * bilerp(uVelocity, vUv, texelSize).xy * texelSize; 208 vec4 result = bilerp(uSource, coord, dyeTexelSize); 209 #else 210 vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize; 211 vec4 result = texture2D(uSource, coord); 212 #endif 213 float decay = 1.0 + dissipation * dt; 214 gl_FragColor = result / decay; 215 } 216 `,h?null:["MANUAL_FILTERING"]),ce=i(e.FRAGMENT_SHADER,` 217 precision mediump float; 218 precision mediump sampler2D; 219 varying highp vec2 vUv; 220 varying highp vec2 vL; 221 varying highp vec2 vR; 222 varying highp vec2 vT; 223 varying highp vec2 vB; 224 uniform sampler2D uVelocity; 225 void main () { 226 float L = texture2D(uVelocity, vL).x; 227 float R = texture2D(uVelocity, vR).x; 228 float T = texture2D(uVelocity, vT).y; 229 float B = texture2D(uVelocity, vB).y; 230 vec2 C = texture2D(uVelocity, vUv).xy; 231 if (vL.x < 0.0) { L = -C.x; } 232 if (vR.x > 1.0) { R = -C.x; } 233 if (vT.y > 1.0) { T = -C.y; } 234 if (vB.y < 0.0) { B = -C.y; } 235 float div = 0.5 * (R - L + T - B); 236 gl_FragColor = vec4(div, 0.0, 0.0, 1.0); 237 } 238 `),de=i(e.FRAGMENT_SHADER,` 239 precision mediump float; 240 precision mediump sampler2D; 241 varying highp vec2 vUv; 242 varying highp vec2 vL; 243 varying highp vec2 vR; 244 varying highp vec2 vT; 245 varying highp vec2 vB; 246 uniform sampler2D uVelocity; 247 void main () { 248 float L = texture2D(uVelocity, vL).y; 249 float R = texture2D(uVelocity, vR).y; 250 float T = texture2D(uVelocity, vT).x; 251 float B = texture2D(uVelocity, vB).x; 252 float vorticity = R - L - T + B; 253 gl_FragColor = vec4(0.5 * vorticity, 0.0, 0.0, 1.0); 254 } 255 `),Ae=i(e.FRAGMENT_SHADER,` 256 precision highp float; 257 precision highp sampler2D; 258 varying vec2 vUv; 259 varying vec2 vL; 260 varying vec2 vR; 261 varying vec2 vT; 262 varying vec2 vB; 263 uniform sampler2D uVelocity; 264 uniform sampler2D uCurl; 265 uniform float curl; 266 uniform float dt; 267 void main () { 268 float L = texture2D(uCurl, vL).x; 269 float R = texture2D(uCurl, vR).x; 270 float T = texture2D(uCurl, vT).x; 271 float B = texture2D(uCurl, vB).x; 272 float C = texture2D(uCurl, vUv).x; 273 vec2 force = 0.5 * vec2(abs(T) - abs(B), abs(R) - abs(L)); 274 force /= length(force) + 0.0001; 275 force *= curl * C; 276 force.y *= -1.0; 277 vec2 velocity = texture2D(uVelocity, vUv).xy; 278 velocity += force * dt; 279 velocity = min(max(velocity, -1000.0), 1000.0); 280 gl_FragColor = vec4(velocity, 0.0, 1.0); 281 } 282 `),pe=i(e.FRAGMENT_SHADER,` 283 precision mediump float; 284 precision mediump sampler2D; 285 varying highp vec2 vUv; 286 varying highp vec2 vL; 287 varying highp vec2 vR; 288 varying highp vec2 vT; 289 varying highp vec2 vB; 290 uniform sampler2D uPressure; 291 uniform sampler2D uDivergence; 292 void main () { 293 float L = texture2D(uPressure, vL).x; 294 float R = texture2D(uPressure, vR).x; 295 float T = texture2D(uPressure, vT).x; 296 float B = texture2D(uPressure, vB).x; 297 float divergence = texture2D(uDivergence, vUv).x; 298 float pressure = (L + R + B + T - divergence) * 0.25; 299 gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0); 300 } 301 `),fe=i(e.FRAGMENT_SHADER,` 302 precision mediump float; 303 precision mediump sampler2D; 304 varying highp vec2 vUv; 305 varying highp vec2 vL; 306 varying highp vec2 vR; 307 varying highp vec2 vT; 308 varying highp vec2 vB; 309 uniform sampler2D uPressure; 310 uniform sampler2D uVelocity; 311 void main () { 312 float L = texture2D(uPressure, vL).x; 313 float R = texture2D(uPressure, vR).x; 314 float T = texture2D(uPressure, vT).x; 315 float B = texture2D(uPressure, vB).x; 316 vec2 velocity = texture2D(uVelocity, vUv).xy; 317 velocity.xy -= vec2(R - L, T - B); 318 gl_FragColor = vec4(velocity, 0.0, 1.0); 319 } 320 `),o=function(){return e.bindBuffer(e.ARRAY_BUFFER,e.createBuffer()),e.bufferData(e.ARRAY_BUFFER,new Float32Array([-1,-1,-1,1,1,1,1,-1]),e.STATIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,e.createBuffer()),e.bufferData(e.ELEMENT_ARRAY_BUFFER,new Uint16Array([0,1,2,0,2,3]),e.STATIC_DRAW),e.vertexAttribPointer(0,2,e.FLOAT,!1,0,0),e.enableVertexAttribArray(0),function(t,n){t==null?(e.viewport(0,0,e.drawingBufferWidth,e.drawingBufferHeight),e.bindFramebuffer(e.FRAMEBUFFER,null)):(e.viewport(0,0,t.width,t.height),e.bindFramebuffer(e.FRAMEBUFFER,t.fbo)),n&&(e.clearColor(0,0,0,1),e.clear(e.COLOR_BUFFER_BIT)),e.drawElements(e.TRIANGLES,6,e.UNSIGNED_SHORT,0)}}(),Be=new c(me,ue),P=new c(r,ae),z=new c(r,ke),$=new c(r,Ee),C=new c(r,ve),_=new c(r,re),E=new c(r,ie),u=new c(r,_e),d=new c(r,oe),N=new c(r,ce),D=new c(r,de),v=new c(r,Ae),x=new c(r,pe),S=new c(r,fe),j=new U(r,Ce),f=[];function X(t){var s,o,n=e.drawingBufferWidth/e.drawingBufferHeight;return n<1&&(n=1/n),s=Math.round(t),o=Math.round(t*n),e.drawingBufferWidth>e.drawingBufferHeight?{width:o,height:s}:{width:s,height:o}}function p(t,n,s,o,i,a){e.activeTexture(e.TEXTURE0);var c,l,d,r=e.createTexture();return e.bindTexture(e.TEXTURE_2D,r),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,a),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,a),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texImage2D(e.TEXTURE_2D,0,s,t,n,0,o,i,null),c=e.createFramebuffer(),e.bindFramebuffer(e.FRAMEBUFFER,c),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,r,0),e.viewport(0,0,t,n),e.clear(e.COLOR_BUFFER_BIT),l=1/t,d=1/n,{texture:r,fbo:c,width:t,height:n,texelSizeX:l,texelSizeY:d,attach:function(t){return e.activeTexture(e.TEXTURE0+t),e.bindTexture(e.TEXTURE_2D,r),t}}}function G(e,t,n,s,o,i){var a=p(e,t,n,s,o,i),r=p(e,t,n,s,o,i);return{width:e,height:t,texelSizeX:a.texelSizeX,texelSizeY:a.texelSizeY,get read(){return a},set read(e){a=e},get write(){return r},set write(e){r=e},swap:function(){var e=a;a=r,r=e}}}function Pe(t,n,s,i,a,r,c){var l=p(n,s,i,a,r,c);return P.bind(),e.uniform1i(P.uniforms.uTexture,t.attach(0)),o(l),l}function he(e,t,n,s,o,i,a){return e.width===t&&e.height===n?e:(e.read=Pe(e.read,t,n,s,o,i,a),e.write=p(t,n,s,o,i,a),e.width=t,e.height=n,e.texelSizeX=1/t,e.texelSizeY=1/n,e)}function ne(){var s=X(n.SIM_RESOLUTION),a=X(n.DYE_RESOLUTION),o=b,r=g,c=te,i=ee,d=h?e.LINEAR:e.NEAREST;e.disable(e.BLEND),l?l=he(l,a.width,a.height,r.internalFormat,r.format,o,d):l=G(a.width,a.height,r.internalFormat,r.format,o,d),t?t=he(t,s.width,s.height,c.internalFormat,c.format,o,d):t=G(s.width,s.height,c.internalFormat,c.format,o,d),J=p(s.width,s.height,i.internalFormat,i.format,o,e.NEAREST),Z=p(s.width,s.height,i.internalFormat,i.format,o,e.NEAREST),m=G(s.width,s.height,i.internalFormat,i.format,o,e.NEAREST),Re()}function Re(){var t,i,a,s=X(n.BLOOM_RESOLUTION),r=b,o=g,c=h?e.LINEAR:e.NEAREST;Q=p(s.width,s.height,o.internalFormat,o.format,r,c),f.length=0;for(t=0;t<n.BLOOM_ITERATIONS;t++){if(i=s.width>>t+1,a=s.height>>t+1,i<2||a<2)break;f.push(p(i,a,o.internalFormat,o.format,r,c))}}function Le(){var e=[];n.SHADING&&e.push("SHADING"),n.BLOOM&&e.push("BLOOM"),j.setKeywords(e)}Le(),ne();function ge(){this.id=-1,this.texcoordX=0,this.texcoordY=0,this.prevTexcoordX=0,this.prevTexcoordY=0,this.deltaX=0,this.deltaY=0,this.down=!1,this.moved=!1,this.color=T()}a=[new ge];function O(e){return Math.floor(e*(window.devicePixelRatio||1))}function Se(e){var t=s.width/s.height;return t<1&&(e*=t),e}function Fe(e){var t=s.width/s.height;return t>1&&(e/=t),e}function se(e,t,n,o){e.id=t,e.down=!0,e.moved=!1,e.texcoordX=n/s.width,e.texcoordY=1-o/s.height,e.prevTexcoordX=e.texcoordX,e.prevTexcoordY=e.texcoordY,e.deltaX=0,e.deltaY=0,e.color=T()}function we(e,t,n){e.prevTexcoordX=e.texcoordX,e.prevTexcoordY=e.texcoordY,e.texcoordX=t/s.width,e.texcoordY=1-n/s.height,e.deltaX=Se(e.texcoordX-e.prevTexcoordX),e.deltaY=Fe(e.texcoordY-e.prevTexcoordY),e.moved=Math.abs(e.deltaX)>0||Math.abs(e.deltaY)>0}function Oe(e){e.down=!1}w=s.parentElement;function A(e,t){var n=s.getBoundingClientRect();return{x:O(e-n.left),y:O(t-n.top)}}w.addEventListener("mousedown",function(e){var t=A(e.clientX,e.clientY);se(a[0],-1,t.x,t.y)}),w.addEventListener("mousemove",function(e){if(!a[0].down)return;var t=A(e.clientX,e.clientY);we(a[0],t.x,t.y)}),window.addEventListener("mouseup",function(){Oe(a[0])}),k=w.querySelector(".fluid-touch-zone"),L=!1,k.addEventListener("touchstart",function(e){L=!1;for(var t,s,n=e.targetTouches;n.length>=a.length;)a.push(new ge);for(t=0;t<n.length;t++)s=A(n[t].clientX,n[t].clientY),se(a[t+1],n[t].identifier,s.x,s.y)},{passive:!1}),k.addEventListener("touchmove",function(e){e.preventDefault(),L=!0;for(var n,o,s=e.targetTouches,t=0;t<s.length;t++){if(n=a[t+1],!n||!n.down)continue;o=A(s[t].clientX,s[t].clientY),we(n,o.x,o.y)}},{passive:!1}),k.addEventListener("touchend",function(e){for(var n,o,r,c,l,d,u,i=e.changedTouches,t=0;t<i.length;t++)for(n=0;n<a.length;n++)a[n].id===i[t].identifier&&(L||(o=T(),o.r*=10,o.g*=10,o.b*=10,r=A(i[t].clientX,i[t].clientY),c=r.x/s.width,l=1-r.y/s.height,d=1e3*(Math.random()-.5),u=1e3*(Math.random()-.5),K(c,l,d,u,o)),Oe(a[n]))}),k.addEventListener("contextmenu",function(e){e.preventDefault()});function Ne(e){var t=s.width/s.height;return t>1&&(e*=t),e}function K(i,a,r,c,d){var h=Ne(n.SPLAT_RADIUS/100),m=s.width/s.height;u.bind(),e.uniform1i(u.uniforms.uTarget,t.read.attach(0)),e.uniform1f(u.uniforms.aspectRatio,m),e.uniform2f(u.uniforms.point,i,a),e.uniform3f(u.uniforms.color,r,c,0),e.uniform1f(u.uniforms.radius,h),o(t.write),t.swap(),e.uniform1i(u.uniforms.uTarget,l.read.attach(0)),e.uniform3f(u.uniforms.color,d.r,d.g,d.b),o(l.write),l.swap()}function Me(e){var t=e.deltaX*n.SPLAT_FORCE,s=e.deltaY*n.SPLAT_FORCE;K(e.texcoordX,e.texcoordY,t,s,e.color)}function ye(e,t){for(var n=0,s=0;s<e;s++)(function(){n+=50+Math.random()*120;var e=n;setTimeout(function(){var n,s,o,i,e=T();e.r*=10,e.g*=10,e.b*=10,n=.15+Math.random()*.7,s=.15+Math.random()*.7,o=t*(Math.random()-.5),i=t*(Math.random()-.5),K(n,s,o,i,e)},e)})()}function Te(s){e.disable(e.BLEND),D.bind(),e.uniform2f(D.uniforms.texelSize,t.texelSizeX,t.texelSizeY),e.uniform1i(D.uniforms.uVelocity,t.read.attach(0)),o(Z),v.bind(),e.uniform2f(v.uniforms.texelSize,t.texelSizeX,t.texelSizeY),e.uniform1i(v.uniforms.uVelocity,t.read.attach(0)),e.uniform1i(v.uniforms.uCurl,Z.attach(1)),e.uniform1f(v.uniforms.curl,n.CURL),e.uniform1f(v.uniforms.dt,s),o(t.write),t.swap(),N.bind(),e.uniform2f(N.uniforms.texelSize,t.texelSizeX,t.texelSizeY),e.uniform1i(N.uniforms.uVelocity,t.read.attach(0)),o(J),z.bind(),e.uniform1i(z.uniforms.uTexture,m.read.attach(0)),e.uniform1f(z.uniforms.value,n.PRESSURE),o(m.write),m.swap(),x.bind(),e.uniform2f(x.uniforms.texelSize,t.texelSizeX,t.texelSizeY),e.uniform1i(x.uniforms.uDivergence,J.attach(0));for(var i,a=0;a<n.PRESSURE_ITERATIONS;a++)e.uniform1i(x.uniforms.uPressure,m.read.attach(1)),o(m.write),m.swap();S.bind(),e.uniform2f(S.uniforms.texelSize,t.texelSizeX,t.texelSizeY),e.uniform1i(S.uniforms.uPressure,m.read.attach(0)),e.uniform1i(S.uniforms.uVelocity,t.read.attach(1)),o(t.write),t.swap(),d.bind(),e.uniform2f(d.uniforms.texelSize,t.texelSizeX,t.texelSizeY),h||e.uniform2f(d.uniforms.dyeTexelSize,t.texelSizeX,t.texelSizeY),i=t.read.attach(0),e.uniform1i(d.uniforms.uVelocity,i),e.uniform1i(d.uniforms.uSource,i),e.uniform1f(d.uniforms.dt,s),e.uniform1f(d.uniforms.dissipation,n.VELOCITY_DISSIPATION),o(t.write),t.swap(),h||e.uniform2f(d.uniforms.dyeTexelSize,l.texelSizeX,l.texelSizeY),e.uniform1i(d.uniforms.uVelocity,t.read.attach(0)),e.uniform1i(d.uniforms.uSource,l.read.attach(1)),e.uniform1f(d.uniforms.dissipation,n.DENSITY_DISSIPATION),o(l.write),l.swap()}function ze(t,s){if(f.length<2)return;var a,r,c,l,i=s;e.disable(e.BLEND),C.bind(),c=n.BLOOM_THRESHOLD*n.BLOOM_SOFT_KNEE+1e-4,e.uniform3f(C.uniforms.curve,n.BLOOM_THRESHOLD-c,c*2,.25/c),e.uniform1f(C.uniforms.threshold,n.BLOOM_THRESHOLD),e.uniform1i(C.uniforms.uTexture,t.attach(0)),o(i),_.bind();for(a=0;a<f.length;a++)l=f[a],e.uniform2f(_.uniforms.texelSize,i.texelSizeX,i.texelSizeY),e.uniform1i(_.uniforms.uTexture,i.attach(0)),o(l),i=l;e.blendFunc(e.ONE,e.ONE),e.enable(e.BLEND);for(a=f.length-2;a>=0;a--)r=f[a],e.uniform2f(_.uniforms.texelSize,i.texelSizeX,i.texelSizeY),e.uniform1i(_.uniforms.uTexture,i.attach(0)),e.viewport(0,0,r.width,r.height),o(r),i=r;e.disable(e.BLEND),E.bind(),e.uniform2f(E.uniforms.texelSize,i.texelSizeX,i.texelSizeY),e.uniform1i(E.uniforms.uTexture,i.attach(0)),e.uniform1f(E.uniforms.intensity,n.BLOOM_INTENSITY),o(s)}function De(t){if(n.BLOOM&&ze(l.read,Q),e.blendFunc(e.ONE,e.ONE_MINUS_SRC_ALPHA),e.enable(e.BLEND),t==null)e.bindFramebuffer(e.FRAMEBUFFER,null),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT);else{var i,a,s=n.BACK_COLOR;$.bind(),e.uniform4f($.uniforms.color,s.r/255,s.g/255,s.b/255,1),o(t)}j.bind(),i=t==null?e.drawingBufferWidth:t.width,a=t==null?e.drawingBufferHeight:t.height,n.SHADING&&e.uniform2f(j.uniforms.texelSize,1/i,1/a),e.uniform1i(j.uniforms.uTexture,l.read.attach(0)),n.BLOOM&&e.uniform1i(j.uniforms.uBloom,Q.attach(1)),o(t)}function je(){var e=O(s.clientWidth),t=O(s.clientHeight);return(s.width!==e||s.height!==t)&&(s.width=e,s.height=t,!0)}function O(e){return Math.floor(e*(window.devicePixelRatio||1))}w.classList.add("fluid-active"),ye(10+Math.floor(Math.random()*4),1e3),W=null;function V(){W=setTimeout(function(){ye(6+Math.floor(Math.random()*4),500),V()},4e3+Math.random()*2e3)}V(),s._pauseAutoSplats=function(){clearTimeout(W)}
320,s._resumeAutoSplats=function(){V()},B=!0,le=new IntersectionObserver(function(e){B=e[0].isIntersecting},{threshold:0}),le.observe(w),R=Date.now();function I(){var e,t,n=Date.now();if(!B){R=n,requestAnimationFrame(I);return}t=(n-R)/1e3,t=Math.min(t,.016666),R=n,je()&&ne();for(e=0;e<a.length;e++)a[e].moved&&(a[e].moved=!1,Me(a[e]));Te(t),De(null),requestAnimationFrame(I)}I()})()</script>
320<section class=section-void id=about><div class=container><header class=section-header><h2 class=section-title><span class=text-gradient>Private DeFi Has Arrived</span></h2></header><div class=features-grid><div class="feature-card card-glass"><div class=feature-icon><img src=/images/promo/icon-zk-nobg.svg alt="True Privacy"></div><h3 class=feature-title>True Privacy</h3><p class=feature-description><strong>Offshift Momiji enables complete anonymity and confidentiality on Ethereum L1. Hidden assets, hidden balances.</strong></p></div><div class="feature-card card-glass"><div class=feature-icon><img src=/images/promo/icon-asset-diversity-nobg.svg alt="Asset Diversity"></div><h3 class=feature-title>zkAssets</h3><p class=feature-description><strong>Momiji's private zkAssets are designed to track a variety of digital and real-world assets 1:1 using Chainlink oracles.</strong></p></div><div class="feature-card card-glass"><div class=feature-icon><img src=/images/promo/icon-spinner-nobg.svg alt=Shifting></div><h3 class=feature-title>XFT</h3><p class=feature-description><strong>XFT is Momiji's native public token. Burn XFT to mint zkAssets. Burn zkAssets to mint XFT. Shift â« in and out of privacy.</strong></p></div></div></div></section><style>.section-void{padding:var(--space-24)0;background:var(--void-abyss);position:relative}.features-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-6)}@media(max-width:768px){.features-grid{grid-template-columns:1fr}}.feature-card{text-align:center;padding:var(--space-8)}.feature-icon{display:inline-flex;align-items:center;justify-content:center;width:80px;height:80px;background:linear-gradient(135deg,rgba(124,58,237,.2),rgba(107,57,250,.1));border-radius:var(--radius-xl);margin-bottom:var(--space-6)}.feature-icon img{width:48px;height:48px}.feature-title{font-family:var(--font-display);font-size:var(--text-xl);font-weight:var(--font-semibold);color:var(--text-primary);margin:0 0 var(--space-4)}.feature-description{font-size:var(--text-base);color:var(--text-secondary);line-height:var(--leading-relaxed);margin:0}.feature-description strong{color:var(--text-primary)}</style><section class=section-features id=features><div class=container><header class=section-header><h2 class=section-title><span class=text-gradient>Features</span></h2></header><div class=features-list><div class=feature-row><div class=feature-item><div class=feature-item-icon><img src=/images/promo/icon-coins.svg alt="1:1 Collateral"></div><div class=feature-item-content><h3 class=feature-item-title>Value In = Value Out</h3><p class=feature-item-text><strong>Mint $1 of private assets with $1 of XFT, and vice versa. No over-collateralization. Maximum capital efficiency.</strong></p></div></div><div class=feature-item><div class=feature-item-icon><img src=/images/promo/icon-orbit.svg alt="Elastic Supply Model"></div><div class=feature-item-content><h3 class=feature-item-title>Zero Liquidation Risk</h3><p class=feature-item-text><strong>XFT's total supply adjusts automatically as value flows in and out of the protocol. No margin calls, no liquidations.</strong></p></div></div><div class=feature-item><div class=feature-item-icon><img src=/images/promo/icon-not-allowed.svg alt="Zero Slippage"></div><div class=feature-item-content><h3 class=feature-item-title>Zero Slippage</h3><p class=feature-item-text><strong>Shift in and out 1:1 at current asset price. No slippage. No order books. No liquidity concerns.</strong></p></div></div></div></div></div></section><style>.section-features{padding:var(--space-24)0;background:var(--void-abyss);position:relative}.features-list{display:flex;flex-direction:column;gap:var(--space-6)}.feature-row{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-6)}@media(max-width:840px){.feature-row{grid-template-columns:1fr}}.feature-item{display:flex;align-items:flex-start;gap:var(--space-5);padding:var(--space-6);background:var(--void-surface);border:1px solid var(--glass-border);border-radius:var(--radius-xl);transition:all var(--transition-base)}.feature-item:hover{border-color:var(--glass-border-hover);transform:translateY(-2px);box-shadow:var(--shadow-ambient)}.feature-item-icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:64px;
320height:64px;background:linear-gradient(135deg,rgba(124,58,237,.2),rgba(107,57,250,.1));border-radius:var(--radius-lg)}.feature-item-icon img{width:40px;height:40px}.feature-item-content{flex:1;min-width:0}.feature-item-title{font-family:var(--font-display);font-size:var(--text-lg);font-weight:var(--font-semibold);color:var(--text-primary);margin:0 0 var(--space-2)}.feature-item-text{font-size:var(--text-sm);color:var(--text-secondary);line-height:var(--leading-relaxed);margin:0}.feature-item-text strong{color:var(--text-primary);font-weight:var(--font-normal)}</style><section class=section-trade id=trade><div class=container><div class=trade-header><h2 class=trade-title><span class=text-gradient>Trade XFT On These DEXs</span></h2></div><div class=trade-exchanges><a href=https://swap.cow.fi/#/1/swap/ETH/0x76BC677d444f1E9d57dAf5187ee2b7dC852745aE target=_blank class="exchange-card card-glass"><img src=/images/logo-cowswap.svg alt="CoW Swap" class=exchange-logo> 321<span class=exchange-pair>MEV Protected</span> 322</a><a href=https://app.uniswap.org/tokens/ethereum/0x76bc677d444f1e9d57daf5187ee2b7dc852745ae target=_blank class="exchange-card card-glass"><img src=/images/logo-uniswap.svg alt=Uniswap class=exchange-logo> 323<span class=exchange-pair>XFT/ETH</span> 324</a><a href="https://www.sushi.com/ethereum/swap?token0=NATIVE&token1=0x76BC677d444f1E9d57dAf5187ee2b7dC852745aE" target=_blank class="exchange-card card-glass"><img src=/images/logo-sushiswap.svg alt=SushiSwap class=exchange-logo> 325<span class=exchange-pair>XFT/ETH</span></a></div></div></section><style>.section-trade{padding:var(--space-24)0;background:var(--void-abyss);position:relative}.trade-header{text-align:center;max-width:640px;margin:0 auto var(--space-12)}.trade-title{font-family:var(--font-display);font-size:var(--text-4xl);font-weight:var(--font-bold);color:var(--text-primary);line-height:var(--leading-tight);margin:0}.text-gradient{background:linear-gradient(135deg,var(--lum-purple),var(--lum-cyan));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.trade-exchanges{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-4)}.exchange-card{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-4);padding:var(--space-8)var(--space-4);text-decoration:none;transition:all var(--transition-base)}.exchange-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-ambient-hover);border-color:var(--lum-purple)}.exchange-logo{width:auto;height:56px;object-fit:contain;filter:brightness(0)invert(1);opacity:.85;transition:opacity var(--transition-fast)}.exchange-card:hover .exchange-logo{opacity:1}.exchange-pair{font-size:var(--text-xs);color:var(--text-tertiary);text-transform:uppercase;letter-spacing:var(--tracking-wider)}@media(max-width:840px){.trade-title{font-size:var(--text-3xl)}.trade-exchanges{grid-template-columns:1fr}.exchange-logo{height:44px}}</style><section class=section-community id=resources><div class=container><header class=section-header><h2 class=section-title><span class=text-gradient>Community Resources</span></h2></header><div class=community-cards><a href=https://t.me/offshiftxft target=_blank class="community-card card-glass"><div class=community-icon style=--icon-color:#0088cc><svg width="32" height="32" viewBox="0 0 24 24" fill="currentcolor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69a.2.2.0 00-.05-.18c-.06-.05-.14-.03-.21-.02-.09.02-1.49.95-4.22 2.79-.4.27-.76.41-1.08.4-.36-.01-1.04-.2-1.55-.37-.63-.2-1.12-.31-1.08-.66.02-.18.27-.36.74-.55 2.92-1.27 4.86-2.11 5.83-2.51 2.78-1.16 3.35-1.36 3.73-1.36.08.0.27.02.39.12.1.08.13.19.14.27-.01.06.01.24.0.38z"/></svg></div><span class=community-name>Telegram</span> 326<span class=community-action>Join</span> 327</a><a href=https://twitter.com/OffshiftXFT target=_blank class="community-card card-glass"><div class=community-icon style=--icon-color:#1DA1F2><svg width="32" height="32" viewBox="0 0 24 24" fill="currentcolor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg></div><span class=community-name>X</span> 328<span class=community-action>Follow</span> 329</a><a href=https://www.youtube.com/@OffshiftXFT target=_blank class="community-card card-glass"><div class=community-icon style=--icon-color:#FF0000><svg width="32" height="32" viewBox="0 0 24 24" fill="currentcolor"><path d="M23.498 6.186A3.016 3.016.0 0021.376 4.05C19.505 3.545 12 3.545 12 3.545s-7.505.0-9.377.505A3.017 3.017.0 00.502 6.186C0 8.07.0 12 0 12s0 3.93.502 5.814a3.016 3.016.0 002.122 2.136c1.871.505 9.376.505 9.376.505s7.505.0 9.377-.505a3.015 3.015.0 002.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg></div><span class=community-name>YouTube</span> 330<span class=community-action>Watch</span></a></div></div></section><style>.section-community{padding:var(--space-24)0;background:var(--void-abyss)}.community-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-4)}.community-card{display:flex;flex-direction:column;align-items:center;gap:var(--space-3);padding:var(--space-8)var(--space-6);text-decoration:none;text-align:center;transition:all var(--transition-base)}.community-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-ambient-hover)}.community-icon{display:flex;align-items:center;justify-content:center;width:64px;
330height:64px;background:linear-gradient(135deg,rgba(124,58,237,.2),rgba(107,57,250,.1));border-radius:var(--radius-xl);color:var(--text-primary);transition:all var(--transition-base)}.community-card:hover .community-icon{background:rgba(255,255,255,.1);transform:scale(1.05)}.community-name{font-family:var(--font-display);font-size:var(--text-lg);font-weight:var(--font-semibold);color:var(--text-primary)}.community-action{font-size:var(--text-sm);color:var(--text-tertiary);transition:color var(--transition-fast)}.community-card:hover .community-action{color:var(--lum-cyan)}@media(max-width:640px){.community-cards{grid-template-columns:1fr}}</style></main><footer class=footer-void><div class=container><div class=footer-content><div class=footer-brand><a href=/ class=footer-logo-link><img src=/images/promo/logo-white.png alt=Offshift class=footer-logo></a><p class=footer-tagline>Privacy on Ethereum L1</p><div class=footer-socials><a href=https://t.me/offshiftxft target=_blank class=footer-social aria-label=Telegram><svg width="20" height="20" viewBox="0 0 24 24" fill="currentcolor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69a.2.2.0 00-.05-.18c-.06-.05-.14-.03-.21-.02-.09.02-1.49.95-4.22 2.79-.4.27-.76.41-1.08.4-.36-.01-1.04-.2-1.55-.37-.63-.2-1.12-.31-1.08-.66.02-.18.27-.36.74-.55 2.92-1.27 4.86-2.11 5.83-2.51 2.78-1.16 3.35-1.36 3.73-1.36.08.0.27.02.39.12.1.08.13.19.14.27-.01.06.01.24.0.38z"/></svg> 331</a><a href=https://twitter.com/OffshiftXFT target=_blank class=footer-social aria-label="X (Twitter)"><svg width="20" height="20" viewBox="0 0 24 24" fill="currentcolor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg> 332</a><a href=https://open.offshift.io/ target=_blank class=footer-social aria-label=GitLab><svg width="20" height="20" viewBox="0 0 24 24" fill="currentcolor"><path d="M22.65 14.39 12 22.13 1.35 14.39a.84.84.0 01-.3-.94l1.22-3.78 2.44-7.51A.42.42.0 014.82 2a.43.43.0 01.58.0.42.42.0 01.11.18l2.44 7.49h8.1l2.44-7.51A.42.42.0 0118.6 2a.43.43.0 01.58.0.42.42.0 01.11.18l2.44 7.51L23 13.45a.84.84.0 01-.35.94z"/></svg> 333</a><a href=https://www.youtube.com/@OffshiftXFT target=_blank class=footer-social aria-label=YouTube><svg width="20" height="20" viewBox="0 0 24 24" fill="currentcolor"><path d="M23.498 6.186A3.016 3.016.0 0021.376 4.05C19.505 3.545 12 3.545 12 3.545s-7.505.0-9.377.505A3.017 3.017.0 00.502 6.186C0 8.07.0 12 0 12s0 3.93.502 5.814a3.016 3.016.0 002.122 2.136c1.871.505 9.376.505 9.376.505s7.505.0 9.377-.505a3.015 3.015.0 002.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg></a></div></div><div class=footer-token><a href=https://www.coingecko.com/en/coins/offshift target=_blank class=footer-coingecko aria-label="View on CoinGecko"><img src=/images/logo-coingecko.svg alt=CoinGecko class=footer-coingecko-logo></a><div class=footer-contract><span class=footer-contract-label>Contract:</span> 334<a href=https://etherscan.io/address/0x76bc677d444f1e9d57daf5187ee2b7dc852745ae target=_blank class=footer-contract-link>0x76bc677d444f1e9d57daf5187ee2b7dc852745ae</a></div><p class=footer-copyright>© 2026 Offshift. All rights reserved.</p></div></div></div></footer><style>.footer-void{background:var(--void-abyss);border-top:1px solid var(--glass-border);padding:var(--space-12)0 var(--space-6)}.footer-content{display:flex;justify-content:space-between;align-items:flex-end;gap:var(--space-8)}.footer-brand{display:flex;flex-direction:column}.footer-logo{height:36px;width:auto;margin-bottom:var(--space-3)}.footer-tagline{font-size:var(--text-sm);color:var(--text-tertiary);margin:0 0 var(--space-4);line-height:var(--leading-relaxed)}.footer-socials{display:flex;gap:var(--space-3)}.footer-social{display:flex;align-items:center;justify-content:center;width:36px;height:36px;background:var(--void-surface);border:1px solid var(--glass-border);border-radius:var(--radius-lg);color:var(--text-secondary);transition:all var(--transition-fast)}.footer-social:hover{background:var(--void-elevated);border-color:var(--lum-purple);color:var(--lum-purple)}.footer-token{display:flex;flex-direction:column;align-items:flex-end;
334gap:var(--space-3)}.footer-coingecko{display:inline-block;opacity:.5;transition:opacity var(--transition-fast)}.footer-coingecko:hover{opacity:.8}.footer-coingecko-logo{height:24px;width:auto}.footer-contract{display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-xs);color:var(--text-muted)}.footer-contract-label{color:var(--text-tertiary)}.footer-contract-link{font-family:var(--font-mono);color:var(--text-tertiary);text-decoration:none;transition:color var(--transition-fast)}.footer-contract-link:hover{color:var(--lum-cyan)}.footer-copyright{font-size:var(--text-xs);color:var(--text-muted);margin:0}@media(max-width:640px){.footer-content{flex-direction:column;align-items:center;text-align:center;gap:var(--space-6)}.footer-brand{align-items:center}.footer-token{align-items:center}.footer-contract{flex-direction:column}.footer-contract-link{font-size:10px;word-break:break-all}}</style></body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.