1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<meta charset="UTF-8" /> 5<meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6<title>EasyLS â The ELS System for Roblox</title> 7<meta name="description" content="EasyLS is an emergency lighting plugin for Roblox. Set up ELS lighting, rotators, sirens, sounds, headlights, turn signals and keybinds on A-Chassis vehicles without writing any code." /> 8 9<meta http-equiv="Content-Security-Policy" content=" 10 default-src 'self'; 11 base-uri 'self'; 12 object-src 'none'; 13 form-action 'self'; 14 script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net; 15 style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; 16 font-src 'self' https://fonts.gstatic.com; 17 img-src 'self' data: blob: https://cdn.discordapp.com; 18 media-src 'self'; 19 connect-src 'self' https://easyls-api.easyls.workers.dev; 20 frame-src 'none'; 21 upgrade-insecure-requests 22" /> 23 24<meta name="referrer" content="strict-origin-when-cross-origin" /> 25 26<link rel="preconnect" href="https://fonts.googleapis.com" /> 27<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> 28 29<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin /> 30<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin /> 31 32<link rel="dns-prefetch" href="https://easyls-api.easyls.workers.dev" /> 33 34<link rel="preload" as="image" href="ELS_Logo_Full.webp" type="image/webp" fetchpriority="high" /> 35<link href="https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700;800&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet" /> 36<style> 37*{margin:0;padding:0;box-sizing:border-box} 38:root{ 39 --blue:#2b9bff; --blue-bright:#5cc8ff; 40 --red:#ff3b3b; --red-bright:#ff6b6b; 41 --green:#2ee06a; 42 --bg:#04060c; --bg2:#080c15; --panel:#0d1320; 43 --ink:#eef4ff; --muted:#8c99b3; --line:rgba(120,150,200,.14); 44 --maxw:1240px; 45} 46html,body{margin:0;padding:0} 47body{ 48 background:var(--bg); color:var(--ink); 49 font-family:'Inter',system-ui,sans-serif; 50 -webkit-font-smoothing:antialiased; overflow-x:hidden; line-height:1.5; 51} 52html.lenis,html.lenis body{height:auto} 53.lenis.lenis-smooth{scroll-behavior:auto!important} 54.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain} 55.lenis.lenis-stopped{overflow:hidden} 56 57h1,h2,h3,.display{font-family:'Sora',sans-serif;line-height:1.02;letter-spacing:-.02em} 58.mono{font-family:'JetBrains Mono',monospace} 59a{color:inherit;text-decoration:none} 60img{display:block;max-width:100%;height:auto} 61section{position:relative} 62.wrap{max-width:var(--maxw);margin:0 auto;padding:0 28px;position:relative;z-index:2} 63.grad-rb{background:linear-gradient(100deg,var(--blue-bright),#fff 42%,var(--red-bright));-webkit-background-clip:text;background-clip:text;color:transparent} 64.blue{color:var(--blue-bright)} .red{color:var(--red-bright)} 65@media(hover:hover) and (pointer:fine){ *{cursor:none!important} } 66.cursor,.cursor-dot{position:fixed;top:0;left:0;z-index:9000;pointer-events:none;border-radius:50%;mix-blend-mode:screen;will-change:transform} 67.cursor{width:38px;height:38px;border:1.5px solid rgba(92,200,255,.8);box-shadow:0 0 18px rgba(92,200,255,.5);transform:translate(-50%,-50%);transition:width .25s,height .25s,border-color .25s,background .25s} 68.cursor-dot{width:7px;height:7px;background:var(--red-bright);box-shadow:0 0 12px var(--red-bright);transform:translate(-50%,-50%)} 69.cursor.grow{width:74px;height:74px;border-color:rgba(255,107,107,.8);background:rgba(92,200,255,.06)} 70@media(hover:none),(pointer:coarse){.cursor,.cursor-dot{display:none}} 71.progress{position:fixed;top:0;left:0;height:3px;width:100%;z-index:300;transform-origin:0 50%;transform:scaleX(0); 72 background:linear-gradient(90deg,var(--blue),#7c4dff,var(--red));box-shadow:0 0 14px rgba(124,77,255,.6)} 73#loader{position:fixed;inset:0;background:var(--bg);z-index:9999;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:26px;transition:opacity .8s ease,visibility .8s} 74#loader.done{opacity:0;visibility:hidden} 75.load-mark{font-family:'Sora';font-weight:800;font-size:clamp(38px,9vw,84px);letter-spacing:-.03em;display:flex;gap:.12em} 76.load-mark .e{color:var(--blue-bright);text-shadow:0 0 30px rgba(92,200,255,.6)} 77.load-mark .l{color:var(--red-bright);text-shadow:0 0 30px rgba(255,107,107,.6)} 78.load-bar{width:min(340px,70vw);height:3px;background:rgba(255,255,255,.08);border-radius:99px;overflow:hidden} 79.load-bar i{display:block;height:100%;width:0%;background:linear-gradient(90deg,var(--blue),var(--red));box-shadow:0 0 18px var(--blue)} 80.load-pct{font-family:'JetBrains Mono';font-size:12px;color:var(--muted);letter-spacing:.3em} 81#bg3d{position:fixed;inset:0;z-index:0;pointer-events:none} 82.vignette{position:fixed;inset:0;z-index:1;pointer-events:none; 83 background:radial-gradient(120% 90% at 50% 6%,transparent 38%,rgba(2,4,9,.5) 76%,#02040a 100%)} 84.ambient{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden;mix-blend-mode:screen;opacity:.5} 85.ambient .orb{position:absolute;width:60vw;
85height:60vw;border-radius:50%;filter:blur(95px)} 86.ambient .b{background:radial-gradient(circle,rgba(43,155,255,.55),transparent 65%);left:-15vw;top:8vh;animation:floatA 18s ease-in-out infinite} 87.ambient .r{background:radial-gradient(circle,rgba(255,59,59,.55),transparent 65%);right:-15vw;top:34vh;animation:floatB 21s ease-in-out infinite} 88@keyframes floatA{0%,100%{transform:translate(0,0)}50%{transform:translate(18vw,16vh)}} 89@keyframes floatB{0%,100%{transform:translate(0,0)}50%{transform:translate(-20vw,-12vh)}} 90.deco{position:absolute;z-index:1;pointer-events:none;border-radius:8px;opacity:.85;will-change:transform} 91.deco.bar{width:54px;height:16px;background:var(--blue);box-shadow:0 0 16px var(--blue),0 0 30px rgba(43,155,255,.5);animation:pulsed 2.4s ease-in-out infinite} 92.deco.bar.r{background:var(--red);box-shadow:0 0 16px var(--red),0 0 30px rgba(255,59,59,.5)} 93.deco.dotg{width:14px;height:14px;border-radius:50%;background:radial-gradient(circle,#fff,var(--blue-bright));box-shadow:0 0 20px var(--blue-bright)} 94.deco.ringd{width:46px;height:46px;border:2px solid rgba(255,107,107,.6);background:transparent;box-shadow:0 0 18px rgba(255,59,59,.35);border-radius:50%} 95.deco.plus{width:24px;height:24px;border:0;background: 96 linear-gradient(var(--blue-bright),var(--blue-bright)) center/100% 2px no-repeat, 97 linear-gradient(var(--blue-bright),var(--blue-bright)) center/2px 100% no-repeat;opacity:.5} 98@keyframes pulsed{0%,100%{opacity:.5}50%{opacity:1}} 99.boost-bar{position:fixed;top:0;left:0;right:0;z-index:210;display:none;align-items:center;justify-content:center; 100 gap:12px;height:32px;padding:0 18px;font-size:12.5px;color:#cdc2e6;white-space:nowrap;overflow:hidden; 101 background:linear-gradient(90deg,rgba(74,38,132,.62),rgba(52,30,104,.58),rgba(74,38,132,.62)); 102 border-bottom:1px solid rgba(155,92,255,.2);backdrop-filter:blur(10px)} 103.boost-bar.on{display:flex} 104.boost-bar .pip{flex:none;width:6px;height:6px;border-radius:50%;background:#c79bff;box-shadow:0 0 8px #9b5cff;animation:blink 1.6s infinite} 105.boost-bar .names{overflow:hidden;text-overflow:ellipsis;min-width:0} 106.boost-bar b{color:#fff;font-weight:600} 107.boost-bar .cta{flex:none;color:#d3c2ff;border-bottom:1px solid rgba(211,194,255,.32);transition:.2s} 108.boost-bar .cta:hover{color:#fff;border-bottom-color:#fff} 109.boost-bar.scrolling{justify-content:flex-start} 110.boost-bar .label{flex:none} 111.boost-bar .mq{position:relative;flex:1;min-width:0;height:100%;overflow:hidden; 112 -webkit-mask-image:linear-gradient(90deg,transparent,#000 24px,#000 calc(100% - 24px),transparent); 113 mask-image:linear-gradient(90deg,transparent,#000 24px,#000 calc(100% - 24px),transparent)} 114.boost-bar .track{display:flex;align-items:center;height:100%;width:max-content;will-change:transform; 115 animation-name:boostSlide;animation-timing-function:linear;animation-iteration-count:infinite} 116.boost-bar .seq{display:flex;align-items:center;white-space:nowrap} 117.boost-bar .sep{flex:none;margin:0 15px;font-style:normal;font-size:8px;color:rgba(199,155,255,.5);transform:translateY(-1px)} 118@keyframes boostSlide{from{transform:translateX(0)}to{transform:translateX(-50%)}} 119@media(prefers-reduced-motion:reduce){.boost-bar .track{animation:none}} 120body.has-boostbar nav{top:32px} 121body.has-boostbar .nav-mobile{top:94px} 122body.has-boostbar .progress{top:32px} 123@media(max-width:640px){.boost-bar .cta{display:none}} 124nav{position:fixed;top:0;left:0;right:0;z-index:200;display:flex;align-items:center;justify-content:space-between; 125 padding:18px 28px;transition:top .4s,background .4s,padding .4s} 126nav.solid{background:rgba(5,8,15,.7);backdrop-filter:blur(14px);border-bottom:1px solid var(--line);padding:12px 28px} 127.nav-logo{display:flex;align-items:center;gap:10px;font-family:'Sora';font-weight:800;font-size:19px;letter-spacing:-.02em} 128.nav-logo .e{color:var(--blue-bright)} .nav-logo .l{color:var(--red-bright)} 129.nav-dot{width:9px;height:9px;border-radius:50%;background:var(--green);box-shadow:0 0 12px var(--green);animation:blink 1.6s infinite} 130@keyframes blink{0%,100%{opacity:1}50%{opacity:.3}} 131.nav-links{display:flex;gap:30px;font-size:14px;font-weight:500} 132.nav-links a{color:var(--muted);transition:.25s;position:relative} 133.nav-links a:hover{color:var(--ink)} 134.nav-links a::after{content:"";position:absolute;
134left:0;bottom:-6px;width:0;height:2px;background:linear-gradient(90deg,var(--blue),var(--red));transition:.3s} 135.nav-links a:hover::after{width:100%} 136.btn{display:inline-flex;align-items:center;gap:9px;font-weight:600;font-size:14px;padding:11px 20px;border-radius:11px;border:none;transition:background-position .4s,box-shadow .3s;position:relative;overflow:hidden} 137.btn-primary{color:#fff;background:linear-gradient(100deg,var(--blue),#7c4dff 55%,var(--red));background-size:220% 100%;box-shadow:0 6px 26px rgba(43,155,255,.32),0 6px 26px rgba(255,59,59,.2)} 138.btn-primary:hover{background-position:100% 0;box-shadow:0 12px 40px rgba(124,77,255,.55)} 139.btn-ghost{color:var(--ink);background:rgba(255,255,255,.05);border:1px solid var(--line)} 140.btn-ghost:hover{background:rgba(255,255,255,.1)} 141@media(max-width:920px){.nav-links{display:none}} 142.hero{min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:120px 20px 90px;position:relative;z-index:2} 143.hero-badge{display:inline-flex;align-items:center;gap:9px;font-size:12.5px;font-weight:600;letter-spacing:.04em;color:var(--muted); 144 border:1px solid var(--line);background:rgba(255,255,255,.03);padding:8px 16px;border-radius:99px;margin-bottom:30px} 145.hero-badge .pip{width:7px;height:7px;border-radius:50%;background:var(--green);box-shadow:0 0 10px var(--green)} 146.hero-logo{width:min(620px,86vw);filter:drop-shadow(0 0 60px rgba(43,155,255,.35)) drop-shadow(0 0 70px rgba(255,59,59,.25))} 147.hero h1{font-size:clamp(30px,5.4vw,62px);font-weight:800;margin:16px 0 18px;max-width:16ch} 148.hero p.sub{font-size:clamp(15px,2vw,20px);color:var(--muted);max-width:54ch;margin:0 auto 36px} 149.hero-cta{display:flex;gap:16px;flex-wrap:wrap;justify-content:center} 150.hero-cta .btn{padding:15px 28px;font-size:15.5px} 151.lightbar{position:relative;width:min(560px,80vw);height:18px;margin:44px auto 0;border-radius:99px;overflow:hidden;background:#0a0e18;border:1px solid var(--line);display:flex} 152.lightbar .cell{flex:1;position:relative} 153.lightbar .cell::after{content:"";position:absolute;inset:3px;border-radius:4px;background:#0d1422} 154.lightbar .cell.on-b::after{background:var(--blue);box-shadow:0 0 14px var(--blue),0 0 26px var(--blue)} 155.lightbar .cell.on-r::after{background:var(--red);box-shadow:0 0 14px var(--red),0 0 26px var(--red)} 156.scrollcue{position:absolute;bottom:24px;left:50%;transform:translateX(-50%);display:flex;flex-direction:column;align-items:center;gap:8px;color:var(--muted);font-size:11px;letter-spacing:.3em;z-index:3} 157.scrollcue .m{width:22px;height:36px;border:2px solid var(--line);border-radius:14px;position:relative} 158.scrollcue .m::after{content:"";position:absolute;top:6px;left:50%;transform:translateX(-50%);width:4px;height:8px;border-radius:3px;background:var(--blue-bright);animation:scrolldot 1.6s infinite} 159@keyframes scrolldot{0%{opacity:0;transform:translate(-50%,0)}40%{opacity:1}100%{opacity:0;transform:translate(-50%,14px)}} 160.marquee{position:relative;z-index:2;border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:rgba(5,8,15,.55);overflow:hidden;padding:20px 0} 161.marquee .track{display:flex;gap:46px;white-space:nowrap;width:max-content;font-family:'Sora';font-weight:800;font-size:30px;letter-spacing:-.01em;will-change:transform} 162.marquee .track span{color:transparent;-webkit-text-stroke:1.3px rgba(160,185,225,.5)} 163.marquee .track .fill{color:var(--blue-bright);-webkit-text-stroke:0} 164.marquee .track .fill.r{color:var(--red-bright)} 165.marquee .dot{color:var(--red-bright);-webkit-text-stroke:0;display:inline-flex;align-items:center} 166.marquee .dot svg{width:15px;height:15px} 167.sec{padding:140px 0;position:relative;z-index:2} 168.eyebrow{display:inline-flex;align-items:center;gap:10px;font-family:'Sora';font-weight:700;font-size:13px;letter-spacing:.18em;text-transform:uppercase;color:var(--blue-bright);margin-bottom:20px} 169.eyebrow::before{content:"";width:26px;height:2px;background:linear-gradient(90deg,var(--blue),var(--red))} 170.sec h2{font-size:clamp(28px,4.6vw,52px);font-weight:800;max-width:18ch;margin-bottom:22px} 171.sec .lead{font-size:clamp(15px,1.6vw,18.5px);color:var(--muted);max-width:56ch} 172.tag{display:inline-block;font-family:'Sora';font-weight:700;font-size:11.5px;letter-spacing:.14em;text-transform:uppercase; 173 color:var(--red-bright);background:rgba(255,59,59,.1);border:1px solid rgba(255,59,59,.25);padding:6px 13px;border-radius:8px;margin-bottom:18px} 174.tag.b{color:var(--blue-bright);background:rgba(43,155,255,.1);border-color:rgba(43,155,255,.25)} 175.lines .line{overflow:hidden;display:block} 176.lines .line >
176 span{display:block;will-change:transform} 177.statement{min-height:100vh;display:flex;align-items:center;justify-content:center;text-align:center;z-index:2} 178.statement .big{font-family:'Sora';font-weight:800;font-size:clamp(34px,7vw,92px);line-height:1.04;max-width:15ch} 179.statement .big .w{display:inline-block;opacity:.12} 180.statement .big .hl{background:linear-gradient(100deg,var(--blue-bright),var(--red-bright));-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent} 181.feature{display:grid;grid-template-columns:1fr 1.05fr;gap:64px;align-items:center} 182.feature.rev{grid-template-columns:1.05fr 1fr} 183.feature.rev .f-copy{order:2} 184.f-list{margin-top:26px;display:flex;flex-direction:column;gap:14px} 185.f-list .item{display:flex;gap:13px;align-items:flex-start;font-size:15px;color:#cdd7ea} 186.f-list .item .ic{flex:none;width:26px;height:26px;border-radius:8px;display:grid;place-items:center;font-size:13px;font-weight:800; 187 background:linear-gradient(135deg,rgba(43,155,255,.25),rgba(255,59,59,.25));border:1px solid var(--line);color:var(--blue-bright)} 188@media(max-width:860px){.feature,.feature.rev{grid-template-columns:1fr;gap:34px}.feature.rev .f-copy{order:0}} 189.device{position:relative;border-radius:16px;overflow:hidden;border:1px solid var(--line);background:#05080f;box-shadow:0 30px 80px rgba(0,0,0,.6);will-change:transform;transform-style:preserve-3d} 190.device .bar{display:flex;align-items:center;gap:7px;padding:11px 14px;background:#0a0f1a;border-bottom:1px solid var(--line);position:relative;z-index:3} 191.device .bar i{width:11px;height:11px;border-radius:50%;display:block} 192.device .bar .r{background:#ff5f56} .device .bar .y{background:#ffbd2e} .device .bar .g{background:#27c93f} 193.device .bar span{margin-left:8px;font-family:'JetBrains Mono';font-size:11px;color:var(--muted)} 194.pimg{position:relative;overflow:hidden} 195.pimg .pimg-inner{will-change:transform} 196.pimg .pimg-inner img{width:100%;height:auto;display:block} 197.pimg .pimg-inner picture{display:block} 198.pimg .pimg-inner video{width:100%;height:auto;display:block} 199.f-glow{position:absolute;inset:-30% -10%;z-index:-1;filter:blur(70px);opacity:.55;border-radius:50%;will-change:transform} 200.f-glow.b{background:radial-gradient(circle,rgba(43,155,255,.7),transparent 60%)} 201.f-glow.r{background:radial-gradient(circle,rgba(255,59,59,.7),transparent 60%)} 202.ring-viz{position:relative;width:min(300px,72%);aspect-ratio:1;margin:0;border-radius:50%; 203 box-shadow:0 0 60px rgba(43,155,255,.4),0 0 60px rgba(255,59,59,.3);cursor:pointer;touch-action:none;user-select:none;-webkit-user-select:none} 204.ring-rot{position:absolute;inset:0;border-radius:50%;will-change:transform} 205.ring-disc{position:absolute;inset:0;border-radius:50%;background:conic-gradient(var(--blue) 0deg 180deg,var(--red) 180deg 360deg)} 206.ring-nodes{position:absolute;inset:0;z-index:3} 207.ring-node{position:absolute;inset:0;pointer-events:none;transform-origin:center center} 208.ring-node .dot{position:absolute;top:0;left:50%;width:19px;height:19px;border-radius:50%;background:#fff;border:2px solid rgba(0,0,0,.28);box-shadow:0 0 12px rgba(255,255,255,.85);transform:translate(-50%,-50%);pointer-events:auto;cursor:grab} 209.ring-node .dot:active{cursor:grabbing} 210.ring-viz::after{content:"";position:absolute;inset:26%;border-radius:50%;background:var(--bg2);box-shadow:inset 0 0 30px #000;z-index:2;pointer-events:none} 211@keyframes spin{to{transform:rotate(360deg)}} 212.ring-stage{position:relative;width:min(300px,72%)} 213.ring-stage .ring-viz{width:100%} 214.ring-hint{position:absolute;top:-50px;right:-22px;display:flex;flex-direction:column;align-items:center;gap:0;z-index:6;pointer-events:none;animation:hintBob 1.9s ease-in-out infinite;transition:opacity .45s ease,transform .45s ease} 215.ring-hint-txt{font-weight:800;font-size:19px;color:#fff;white-space:nowrap;transform:rotate(-7deg);text-shadow:0 2px 12px rgba(43,155,255,.75),0 0 16px rgba(255,59,59,.5)} 216.ring-hint-arrow{width:78px;height:auto;color:#fff;margin-top:-2px;filter:drop-shadow(0 0 8px rgba(43,155,255,.7))} 217.ring-hint-gone{opacity:0;transform:scale(.8) translateY(-8px);animation:none} 218@keyframes hintBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-7px)}} 219.siren-wave{display:flex;align-items:flex-end;
219gap:6px;height:120px} 220.siren-wave i{width:8px;border-radius:6px;background:linear-gradient(var(--blue-bright),var(--blue));box-shadow:0 0 12px rgba(43,155,255,.6)} 221.siren-wave i:nth-child(even){background:linear-gradient(var(--red-bright),var(--red));box-shadow:0 0 12px rgba(255,59,59,.6)} 222.hscroll{height:100vh;overflow:hidden;position:relative;z-index:2} 223.hscroll .hhead{position:absolute;top:104px;left:0;right:0;text-align:center;z-index:5} 224.hscroll-track{display:flex;gap:34px;height:100%;align-items:center;width:max-content;padding:90px 8vw 0;will-change:transform} 225.hpanel{position:relative;width:min(78vw,540px);height:58vh;border-radius:22px;overflow:hidden;flex:none; 226 border:1px solid var(--line);background:linear-gradient(160deg,rgba(255,255,255,.05),rgba(255,255,255,.01)); 227 display:flex;flex-direction:column;justify-content:flex-end;padding:40px;box-shadow:0 30px 80px rgba(0,0,0,.5)} 228.hpanel .pn{position:absolute;top:28px;left:36px;font-family:'Sora';font-weight:800;font-size:90px;line-height:1; 229 color:transparent;-webkit-text-stroke:1.5px rgba(160,185,225,.25)} 230.hpanel .pglow{position:absolute;width:60%;height:60%;border-radius:50%;filter:blur(70px);top:-10%;right:-10%} 231.hpanel.b .pglow{background:radial-gradient(circle,rgba(43,155,255,.5),transparent 65%)} 232.hpanel.r .pglow{background:radial-gradient(circle,rgba(255,59,59,.5),transparent 65%)} 233.hpanel .pico{margin-bottom:18px;line-height:0} 234.hpanel .pico svg{width:38px;height:38px} 235.hpanel.b .pico{color:var(--blue-bright)} 236.hpanel.r .pico{color:var(--red-bright)} 237.hpanel h3{font-size:30px;font-weight:800;margin-bottom:12px} 238.hpanel p{color:var(--muted);font-size:15.5px;max-width:34ch} 239.hpanel .ptag{position:absolute;top:34px;right:34px;font-family:'Sora';font-weight:700;font-size:11px;letter-spacing:.14em;color:var(--muted);text-transform:uppercase} 240.hpanel .pchips{display:flex;flex-wrap:wrap;gap:8px;margin-top:20px} 241.hpanel .pchips span{font-size:12px;font-weight:600;color:#cdd7ea;padding:5px 11px;border-radius:99px;border:1px solid var(--line);background:rgba(255,255,255,.04)} 242.hpanel > .pn,.hpanel > .ptag{z-index:2} 243.hpanel > .pico,.hpanel > h3,.hpanel > p,.hpanel > .pchips{position:relative;z-index:2} 244.hpanel .pvis{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden} 245.hpanel .pvis::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 40%,rgba(8,12,20,.5) 74%,rgba(8,12,20,.84) 100%)} 246.pv-bar{position:absolute;inset:0;display:flex;gap:18px;padding:0 30px; 247 -webkit-mask-image:linear-gradient(180deg,#000 0,#000 52%,transparent 92%);mask-image:linear-gradient(180deg,#000 0,#000 52%,transparent 92%)} 248.pv-bar i{flex:1;border-radius:0 0 44px 44px} 249.pv-bar i:nth-child(odd){background:linear-gradient(180deg,var(--blue),transparent 92%);color:var(--blue);animation:pvFlash 1.2s steps(1) infinite} 250.pv-bar i:nth-child(even){background:linear-gradient(180deg,var(--red),transparent 92%);color:var(--red);animation:pvFlash 1.2s steps(1) .6s infinite} 251@keyframes pvFlash{0%,49%{opacity:.3;box-shadow:0 0 36px currentColor}50%,100%{opacity:.06}} 252.pv-ring{position:absolute;width:500px;height:500px;top:0;bottom:0;right:-160px;left:auto;margin:auto 0;border-radius:50%;opacity:.17; 253 background:conic-gradient(var(--blue) 0 50%,var(--red) 50% 100%);animation:spin 8s linear infinite; 254 -webkit-mask-image:radial-gradient(circle,#000 18%,transparent 60%);mask-image:radial-gradient(circle,#000 18%,transparent 60%)} 255.pv-wave{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:11px; 256 -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)} 257/* scaleY, not height: animating height ran a full layout pass every frame 258 on all 26 bars. No will-change here on purpose â the browser promotes a 259 transform animation while it runs and drops the layer when it's paused, 260 which is what we want for 26 elements. */ 261.pv-wave i{width:8px;height:78%;border-radius:7px;background:linear-gradient(var(--blue-bright),transparent);opacity:.32; 262 transform:scaleY(.14);animation:pvEq 1.3s ease-in-out infinite} 263.pv-wave i:nth-child(even){background:linear-gradient(var(--red-bright),transparent)} 264.pv-wave i:nth-child(3n){animation-delay:-.15s}.pv-wave i:nth-child(3n+1){animation-delay:-.4s}.pv-wave i:nth-child(4n){animation-delay:-.65s}.pv-wave i:nth-child(5n){animation-delay:-.9s} 265@keyframes pvEq{0%,100%{transform:scaleY(.14)}50%{transform:scaleY(1)}} 266.pv-keys{position:absolute;inset:0;display:grid;grid-template-columns:repeat(6,1fr);gap:13px;padding:24px;align-content:start;opacity:.34; 267 -webkit-mask-image:linear-gradient(180deg,#000 0,#000 46%,transparent 82%);mask-image:linear-gradient(180deg,#000 0,#000 46%,transparent 82%)} 268.pv-keys span{aspect-ratio:1;display:grid;place-items:center;border-radius:12px;background:linear-gradient(180deg,rgba(28,37,55,.8),rgba(13,19,30,.32));border:1px solid var(--line);border-bottom:3px solid rgba(0,0,0,.5);font-family:'Sora';font-weight:700;font-size:18px;color:#aebbd4;transition:color .4s,border-color .4s,box-shadow .4s} 269.pv-keys span.lit{color:#fff;border-color:var(--red-bright);box-shadow:0 0 26px rgba(255,59,59,.45);background:linear-gradient(180deg,rgba(255,59,59,.22),rgba(13,19,30,.3))} 270.pv-config{position:absolute;inset:0;display:flex;flex-direction:column;gap:13px;justify-content:center;padding:0;opacity:.4; 271 -webkit-mask-image:linear-gradient(180deg,#000 0,#000 46%,transparent 82%);mask-image:linear-gradient(180deg,#000 0,#000 46%,transparent 82%)} 272.pv-config .crow{display:flex;width:max-content;will-change:transform} 273.pv-config .crow.l{animation:cSlideL 26s linear infinite} 274.pv-config .crow.r{animation:cSlideR 32s linear infinite} 275.pv-config .crow i{width:52px;height:52px;margin-right:13px;border-radius:12px;flex:none;box-shadow:0 0 16px rgba(0,0,0,.35)} 276@keyframes cSlideL{from{transform:translateX(0)}to{transform:translateX(-50%)}} 277@keyframes cSlideR{from{transform:translateX(-50%)}to{transform:translateX(0)}} 278@media(max-width:860px){.hscroll{height:auto;overflow:visible;padding:120px 0}.hscroll-track{flex-direction:column;width:auto;padding:0 24px;gap:22px;transform:none!important}.hpanel{width:auto;height:auto;min-height:340px}.hpanel .pn{font-size:60px}.hscroll .hhead{position:static;margin-bottom:30px}} 279.dash{position:relative;z-index:2;text-align:center} 280.dash-shot{position:relative;max-width:1000px;margin:46px auto 0;border-radius:20px;overflow:hidden;border:1px solid var(--line); 281 box-shadow:0 40px 120px rgba(0,0,0,.7),0 0 80px rgba(43,155,255,.12)} 282.dash-shot img{width:100%} 283.els-dash{--d-menubar:#1b1b20;--d-tabbar:#0e0e13;--d-card:#17171c;--d-cardb:#27272e;--d-title:#f2f2f4;--d-desc:#8d8d96;--d-mbg:#26262d;--d-mtext:#5a98e0;--d-green:#27d24a;--d-track:#3a3a43;--d-knoboff:#6c6c75;font-family:'Inter',system-ui,sans-serif;color:var(--d-title);text-align:left;line-height:1.5} 284.els-dash *{box-sizing:border-box} 285.els-dash .studio{width:100%;background:linear-gradient(180deg,#101015 0%,#0c0c11 22%,#0b0b10 100%)} 286.els-dash .menubar{height:22px;background:var(--d-menubar);display:flex;align-items:center;padding:0 9px;font-size:12px;color:#cfcfd4;gap:16px;border-bottom:1px solid #000} 287.els-dash .menubar .mleft{display:flex;gap:16px} 288.els-dash .menubar .mright{margin-left:auto;display:flex;gap:26px;font-family:'JetBrains Mono',monospace;font-size:11px;
288color:#dadade;padding-right:4px} 289.els-dash .menubar .mright b{font-weight:500} 290.els-dash .tabbar{background:var(--d-tabbar);height:34px;display:flex;align-items:center;padding:0 14px;border-bottom:1px solid #16161b;position:relative} 291.els-dash .tabs{display:flex;align-items:center;gap:26px;height:100%} 292.els-dash .d-tab{font-size:13.5px;font-weight:700;color:#fbfbfc;height:100%;display:flex;align-items:center;cursor:pointer;position:relative;text-transform:uppercase;background:none;border:none;font-family:inherit;letter-spacing:.01em} 293.els-dash .d-tab.active::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:#fff} 294.els-dash .d-tab:hover{opacity:.85} 295.els-dash .tab-icons{margin-left:auto;display:flex;align-items:center;gap:14px} 296.els-dash .tab-icons .ic{width:26px;height:26px;display:grid;place-items:center;cursor:pointer;opacity:.92} 297.els-dash .tab-icons .ic:hover{opacity:1} 298.els-dash .tab-icons svg{display:block} 299.els-dash .plus-tab{position:absolute;right:14px;top:50%;transform:translateY(-50%);color:#5a5a62;font-size:22px} 300.els-dash .d-content{padding:29px 14px 34px} 301.els-dash .d-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:21px;max-width:818px;margin:0 auto} 302.els-dash .d-card{background:var(--d-card);border:1px solid var(--d-cardb);border-radius:8px;padding:16px 17px 14px;min-height:118px;display:flex;flex-direction:column;position:relative;transition:border-color .2s} 303.els-dash .d-card:hover{border-color:#34343c} 304.els-dash .d-card .head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px} 305.els-dash .d-card h3{font-size:18px;font-weight:700;color:var(--d-title);font-family:'Inter',sans-serif;letter-spacing:0;line-height:1.1;margin:0} 306.els-dash .d-card .desc{font-size:12px;line-height:1.32;color:var(--d-desc);margin-top:8px} 307.els-dash .d-card .foot{margin-top:auto;display:flex;justify-content:flex-end;padding-top:11px} 308.els-dash .d-toggle{position:relative;width:34px;height:16px;flex:none;margin-top:4px;cursor:pointer} 309.els-dash .d-toggle input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer;z-index:2} 310.els-dash .d-toggle .track{position:absolute;inset:0;border-radius:99px;background:var(--d-track);transition:background .22s} 311.els-dash .d-toggle .knob{position:absolute;top:50%;left:27px;transform:translate(-50%,-50%);width:19px;height:19px;border-radius:50%;border:2.5px solid var(--d-green);background:#101015;transition:left .22s,border-color .22s,box-shadow .22s;box-shadow:0 0 6px rgba(39,210,74,.5)} 312.els-dash .d-toggle input:not(:checked) ~ .knob{left:7px;border-color:var(--d-knoboff);box-shadow:none} 313.els-dash .d-toggle input:not(:checked) ~ .track{background:#2c2c33} 314.els-dash .d-modify{background:var(--d-mbg);color:var(--d-mtext);border:none;font-family:'Inter',sans-serif;font-size:13px;font-weight:600;padding:6px 26px;border-radius:6px;cursor:pointer;transition:background .2s,transform .05s} 315.els-dash .d-modify:hover{background:#34343d} 316.els-dash .d-modify:active{transform:scale(.97)} 317.dash-live-badge{position:absolute;left:16px;bottom:14px;z-index:6;display:inline-flex;align-items:center;gap:7px;font-size:11.5px;font-weight:600;color:#cfe8ff;background:rgba(8,12,20,.6);border:1px solid var(--line);padding:6px 12px;border-radius:99px;backdrop-filter:blur(6px);pointer-events:none} 318.dash-live-badge i{width:7px;height:7px;border-radius:50%;background:var(--green);box-shadow:0 0 8px var(--green);animation:blink 1.6s infinite} 319.dash-note{text-align:center;max-width:54ch;margin:18px auto 0;font-size:12.5px;color:var(--muted);font-style:italic} 320.els-dash .lighting-view{padding:0} 321.els-dash .le{display:flex;min-height:520px;background:#090910;overflow-x:auto} 322.els-dash .le-side{width:226px;flex:none;margin:12px;border:2px solid #e23b3b;border-radius:12px;background:#0c0c12;display:flex;flex-direction:column;align-items:center;padding:18px 16px;box-shadow:0 0 20px rgba(226,59,59,.22)} 323.els-dash .le-logo{font-family:'Sora',sans-serif;font-weight:800;font-size:25px;letter-spacing:-.02em;margin-top:4px} 324.els-dash .le-logo .e{color:#5cc8ff}.els-dash .le-logo .l{color:#ff5e5e} 325.els-dash .le-subtabs{display:flex;gap:18px;margin:14px 0 18px;font-size:13px;font-weight:700;letter-spacing:.03em;color:#cfd6e6} 326.els-dash .le-subtabs span{cursor:pointer;padding-bottom:3px} 327.els-dash .le-subtabs .active{border-bottom:2px solid #fff;color:#fff} 328.els-dash .le-colorbox{width:100%;border:1px solid #2a2a33;border-radius:9px;background:#0e0e14;display:flex;align-items:center;justify-content:space-between;padding:7px 8px;gap:5px} 329.els-dash .le-arrow{width:26px;height:26px;border-radius:50%;border:1px solid #3a3a45;background:#15151c;color:#cfd6e6;display:grid;place-items:center;cursor:pointer;font-size:14px;flex:none;line-height:1} 330.els-dash .le-arrow:hover{background:#1e1e28} 331.els-dash .le-key{font-size:12px;color:#8089a0;width:13px;text-align:center;flex:none} 332.els-dash .le-color{font-size:14px;font-weight:600;color:#fff;flex:1;text-align:center} 333.els-dash .le-ps-label{font-size:13px;font-weight:700;color:#e7ebf4;margin:14px 0 8px;align-self:flex-start} 334.els-dash .le-pselect{width:100%;border:1px solid #2a2a33;border-radius:8px;background:#0e0e14;display:flex;align-items:center;gap:8px;padding:8px 10px;font-size:13px;color:#cfd6e6;
334cursor:pointer} 335.els-dash .le-pselect .chev{margin-left:auto;color:#7c8395} 336.els-dash .le-play{margin-top:auto;width:60px;height:60px;border-radius:50%;border:2px solid #cfd6e6;background:transparent;color:#eef2ff;display:grid;place-items:center;cursor:pointer;font-size:22px;transition:.2s;margin-bottom:4px} 337.els-dash .le-play:hover{border-color:#fff;box-shadow:0 0 16px rgba(255,255,255,.16)} 338.els-dash .le-main{flex:1;padding:14px 16px 18px;min-width:560px} 339.els-dash .le-stage{font-size:15px;font-weight:700;color:#fff;border-bottom:2px solid #fff;display:inline-block;padding-bottom:2px;margin-bottom:12px} 340.els-dash .le-groupname{width:100%;background:#10131c;border:1px solid #232838;border-radius:7px;padding:9px 12px;color:#cfd6e6;font-size:13px;font-family:inherit;margin-bottom:14px;outline:none} 341.els-dash .le-groupname:focus{border-color:#3a4a6a} 342.els-dash .le-board{display:flex;gap:14px;align-items:flex-start} 343.els-dash .le-grid{flex:1;min-width:0} 344.els-dash .le-controls{flex:none;width:74px;display:flex;flex-direction:column;gap:13px;padding-top:4px} 345.els-dash .le-ctrl{background:#10131c;border:1px solid #232838;border-radius:7px;padding:6px 4px} 346.els-dash .le-ctrl .t{font-size:11.5px;color:#aeb6c8;text-align:center;margin-bottom:2px} 347.els-dash .le-ctrl .row{display:flex;align-items:center;justify-content:space-between;padding:0 5px} 348.els-dash .le-ctrl button{background:none;border:none;color:#cfd6e6;font-size:16px;cursor:pointer;width:14px;line-height:1;padding:0} 349.els-dash .le-ctrl button:hover{color:#fff} 350.els-dash .le-ctrl .v{font-size:14px;font-weight:700;color:#fff} 351.els-dash .le-head-row{display:flex;gap:8px;margin-bottom:6px} 352.els-dash .le-rowlabel{width:34px;flex:none;display:flex;align-items:center;justify-content:flex-end;gap:5px} 353.els-dash .le-cols{flex:1;display:grid;gap:6px} 354.els-dash .le-colhead{text-align:center;min-width:0} 355.els-dash .le-colnum{background:#181820;border:1px solid #2a2a33;border-radius:5px;font-size:11px;color:#dfe4ee;padding:2px 0;margin-bottom:4px} 356.els-dash .le-live{height:9px;border-radius:4px;background:#15151c;margin-bottom:5px;transition:background .04s,box-shadow .04s} 357.els-dash .le-colname{font-size:11px;color:#8089a0;margin-bottom:3px} 358.els-dash .le-colicons{display:flex;justify-content:center;gap:9px;color:#7c8395;font-size:11px} 359.els-dash .le-grid-rows{display:flex;flex-direction:column;gap:6px} 360.els-dash .le-row{display:flex;align-items:center;gap:8px;border-radius:6px} 361.els-dash .le-rownum{font-size:12px;color:#8089a0} 362.els-dash .le-rowarrow{color:#7c8395;font-size:12px} 363.els-dash .le-cells{flex:1;display:grid;gap:6px} 364.els-dash .le-cell{height:20px;border-radius:5px;background:#12131a;border:1px solid #20232e;cursor:pointer;transition:background .12s,box-shadow .12s,border-color .12s} 365.els-dash .le-cell:hover{border-color:#3a4156} 366.els-dash .le-row.playing .le-rownum{color:#fff;font-weight:700} 367.els-dash .le-row.playing{background:rgba(255,255,255,.035)} 368@media(max-width:720px){.els-dash .d-grid{grid-template-columns:1fr;max-width:420px}.els-dash .menubar .mright{gap:12px}} 369.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;text-align:center} 370.stat{padding:34px 18px;border-radius:16px;border:1px solid var(--line);background:rgba(255,255,255,.02)} 371.stat .num{font-family:'Sora';font-weight:800;font-size:clamp(34px,5vw,56px); 372 background:linear-gradient(120deg,var(--blue-bright),var(--red-bright));-webkit-background-clip:text;background-clip:text;color:transparent} 373.stat .lbl{color:var(--muted);font-size:13.5px;margin-top:8px} 374@media(max-width:720px){.stats{grid-template-columns:repeat(2,1fr)}} 375.why-grid{display:flex;flex-wrap:wrap;justify-content:center;gap:20px;margin-top:50px} 376.why-card{flex:1 1 300px;max-width:calc((100% - 40px)/3);padding:28px 24px;border-radius:16px;border:1px solid var(--line);background:linear-gradient(180deg,rgba(255,255,255,.03),rgba(255,255,255,0));transition:transform .3s,border-color .3s} 377.why-card:hover{transform:translateY(-6px);border-color:rgba(255,59,59,.35)} 378.why-card .ic{margin-bottom:16px;display:block;line-height:0} 379.why-card .ic svg{width:28px;height:28px} 380.why-grid .why-card:nth-child(odd) .ic{color:var(--blue-bright)} 381.why-grid .why-card:nth-child(even) .ic{color:var(--red-bright)} 382.why-card h4{font-family:'Sora';font-weight:700;font-size:18px;margin-bottom:10px} 383.why-card p{color:var(--muted);font-size:14.5px;line-height:1.55} 384@media(max-width:820px){.why-card{max-width:100%;flex-basis:100%}} 385.cta{min-height:100vh;display:flex;align-items:center;justify-content:center;text-align:center;position:relative;z-index:2;overflow:hidden} 386.cta .flash{position:absolute;inset:0;z-index:-1;mix-blend-mode:screen;pointer-events:none;-webkit-mask-image:linear-gradient(to bottom,transparent 0%,#000 36%,#000 78%,transparent 100%);mask-image:linear-gradient(to bottom,transparent 0%,#000 36%,#000 78%,transparent 100%)} 387.cta .flash::before,.cta .flash::after{content:"";position:absolute;width:70vw;height:70vw;border-radius:50%;filter:blur(110px);top:50%;left:50%} 388.cta .flash::before{background:radial-gradient(circle,rgba(43,155,255,.7),transparent 60%);transform:translate(-90%,-50%);animation:ctaB 2.2s ease-in-out infinite} 389.cta .flash::after{background:radial-gradient(circle,rgba(255,59,59,.7),transparent 60%);transform:translate(-10%,-50%);animation:ctaR 2.2s ease-in-out infinite} 390@keyframes ctaB{0%,100%{opacity:.35}50%{opacity:.9}} 391@keyframes ctaR{0%,100%{opacity:.9}50%{opacity:.35}} 392.cta h2{font-size:clamp(38px,8vw,104px);font-weight:800;line-height:1.08;margin-bottom:26px} 393.cta p{color:var(--muted);font-size:clamp(16px,2vw,21px);max-width:50ch;margin:0 auto 40px} 394.cta .btn{padding:18px 40px;font-size:17px} 395.cta-mark{font-family:'Sora';font-weight:800} 396footer{position:relative;z-index:2;border-top:1px solid var(--line);background:rgba(4,6,12,.85);padding:60px 0 40px} 397.foot{display:flex;justify-content:space-between;flex-wrap:wrap;gap:30px;align-items:flex-start} 398.foot .brand{font-family:'Sora';font-weight:800;font-size:22px} 399.foot .brand .e{color:var(--blue-bright)} .foot .brand .l{color:var(--red-bright)} 400.foot p{color:var(--muted);font-size:13.5px;max-width:34ch;margin-top:12px} 401.foot-links{display:flex;gap:60px;flex-wrap:wrap} 402.foot-col h5{font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);margin-bottom:16px;font-family:'Sora';font-weight:700} 403.foot-col a{display:block;color:#c4cee0;font-size:14px;margin-bottom:11px;transition:.2s} 404.foot-col a:hover{color:var(--blue-bright)} 405.foot-bottom{margin-top:46px;padding-top:24px;border-top:1px solid var(--line);display:flex;justify-content:space-between;flex-wrap:wrap;gap:12px;color:var(--muted);font-size:12.5px} 406 407.reveal{opacity:0;transform:translateY(34px)} 408.nav-burger{display:none;flex-direction:column;align-items:center;justify-content:center;gap:5px;width:42px;height:42px;background:rgba(255,255,255,.05);border:1px solid var(--line);border-radius:11px;cursor:pointer;padding:0} 409.nav-burger span{width:18px;height:2px;background:var(--ink);border-radius:2px;transition:transform .3s,opacity .2s} 410.nav-burger.open span:nth-child(1){transform:translateY(7px) rotate(45deg)} 411.nav-burger.open span:nth-child(2){opacity:0}
411 412.nav-burger.open span:nth-child(3){transform:translateY(-7px) rotate(-45deg)} 413.nav-mobile{position:fixed;top:62px;left:12px;right:12px;z-index:199;background:rgba(8,11,18,.96);backdrop-filter:blur(16px);border:1px solid var(--line);border-radius:16px;padding:12px;display:flex;flex-direction:column;gap:4px;transform:translateY(-14px);opacity:0;visibility:hidden;transition:.3s;box-shadow:0 24px 60px rgba(0,0,0,.6)} 414.nav-mobile.open{transform:translateY(0);opacity:1;visibility:visible} 415.nav-mobile a:not(.btn){padding:13px 14px;border-radius:10px;font-size:15px;font-weight:600;color:#dbe4f2} 416.nav-mobile a:not(.btn):active{background:rgba(255,255,255,.07)} 417.nav-mobile .btn{justify-content:center;margin-top:6px;padding:13px} 418.nav-cta{display:flex;align-items:center;gap:10px} 419.nav-cta .btn{white-space:nowrap} 420@media(max-width:1120px){.nav-cta .btn-ghost{display:none}} 421@media(max-width:920px){ 422 .nav-burger{display:flex} 423 nav .nav-cta{display:none} 424} 425@media(max-width:640px){ 426 .wrap{padding:0 20px} 427 .sec{padding:84px 0} 428 .hero{padding:104px 18px 72px} 429 .hero h1{margin-top:10px} 430 .statement{min-height:auto;padding:92px 0} 431 .statement .big{font-size:clamp(30px,8.5vw,52px)} 432 .feature,.feature.rev{gap:26px} 433 .cta{min-height:86vh} 434 .marquee{padding:16px 0} 435 .marquee .track{font-size:22px;gap:32px} 436 nav{padding:11px 16px} 437 .dash-shot{margin-top:34px} 438 .els-dash .menubar{gap:9px;padding:0 8px} 439 .els-dash .menubar .mright{gap:9px;font-size:10px} 440 .els-dash .menubar .mright span:first-child{display:none} 441 .els-dash .tabbar{overflow-x:auto;scrollbar-width:none;padding:0 12px} 442 .els-dash .tabbar::-webkit-scrollbar{display:none} 443 .els-dash .tabs{flex:none;gap:17px} 444 .els-dash .tab-icons,.els-dash .plus-tab{display:none} 445 .els-dash .d-content{padding:18px 12px 22px} 446 .els-dash .d-card{min-height:0} 447 .els-dash .le{flex-direction:column;min-height:0;overflow-x:hidden} 448 .els-dash .le-side{width:auto;margin:10px 10px 0;padding:14px 14px 16px} 449 .els-dash .le-logo{font-size:22px} 450 .els-dash .le-play{margin-top:14px;width:52px;height:52px;font-size:18px} 451 .els-dash .le-main{min-width:0;padding:12px} 452 .els-dash .le-board{flex-direction:column;gap:12px} 453 .els-dash .le-grid{overflow-x:auto;scrollbar-width:none} 454 .els-dash .le-grid::-webkit-scrollbar{display:none} 455 .els-dash .le-controls{flex-direction:row;width:auto;padding-top:4px;gap:10px} 456 .els-dash .le-ctrl{flex:1} 457 .dash-live-badge{font-size:10px;left:12px;bottom:10px;padding:5px 10px} 458} 459@media(max-width:430px){ 460 .els-dash .le-cell{height:18px} 461 .els-dash .menubar .mleft{gap:12px} 462} 463html{-webkit-text-size-adjust:100%;text-size-adjust:100%} 464/* svh, not dvh: dvh tracks the iOS URL bar as it collapses, which changes 465 the document height mid-scroll and invalidates every ScrollTrigger 466 position. svh is the stable small-viewport height. */ 467@supports(min-height:100svh){ 468 .hero{min-height:100svh} 469 .cta{min-height:100svh} 470 @media(max-width:640px){ .cta{min-height:86svh} } 471} 472@media(max-width:820px){ 473 .deco{display:none!important} 474} 475@media(max-width:860px){ 476 .hpanel{padding:30px 24px 28px} 477 .hpanel .pn{top:22px;left:24px;font-size:56px} 478 .hpanel .ptag{top:26px;right:22px;font-size:12px} 479 .hpanel .pvis::after{background:linear-gradient(180deg,rgba(8,12,20,.42) 0,rgba(8,12,20,.76) 44%,rgba(8,12,20,.94) 100%)} 480 .pv-bar{gap:10px;padding:0 18px} 481 .pv-ring{width:290px;height:290px;right:-96px;opacity:.13} 482 .pv-wave{gap:7px} 483 .pv-wave i{width:6px} 484 .pv-keys{grid-template-columns:repeat(5,1fr);gap:9px;padding:16px;opacity:.18; 485 -webkit-mask-image:linear-gradient(180deg,#000 0,rgba(0,0,0,.45) 30%,transparent 58%); 486 mask-image:linear-gradient(180deg,#000 0,rgba(0,0,0,.45) 30%,transparent 58%)} 487 .pv-keys span{font-size:12px;border-radius:9px;border-bottom-width:2px} 488 .pv-config{opacity:.24} 489 .pv-config .crow i{width:38px;height:38px;margin-right:9px} 490} 491@media(max-width:720px){ 492 .device .pimg-inner{overflow-x:auto;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;scrollbar-width:none} 493 .device .pimg-inner::-webkit-scrollbar{display:none} 494 .device .pimg-inner picture img,.device .pimg-inner video{min-width:620px} 495 .device:has(picture)::after,.device:has(video)::after{content:"swipe to explore";position:absolute;right:10px;bottom:10px;z-index:4; 496 font-family:'JetBrains Mono';font-size:10.5px;letter-spacing:.06em;color:#cdd8ea; 497 background:rgba(8,12,20,.8);border:1px solid var(--line);border-radius:99px;padding:5px 11px;pointer-events:none} 498} 499@media(max-width:920px){ 500 .nav-logo{padding:8px 0} 501 .foot-col a{padding:12px 0;margin-bottom:0} 502 .els-dash .tabbar{height:42px}
503 .els-dash .d-modify{padding:9px 26px} 504} 505@media(max-width:640px){ 506 .tag{font-size:12px;letter-spacing:.12em} 507 .scrollcue{font-size:12px;letter-spacing:.22em} 508 .hpanel .pchips span{font-size:12.5px} 509} 510@media(max-width:720px){ 511 .feature,.feature.rev{grid-template-columns:minmax(0,1fr)} 512 .f-copy,.f-media{min-width:0;max-width:100%} 513 .device{min-width:0;max-width:100%} 514 .device .pimg{min-width:0;max-width:100%} 515 .device .pimg-inner{width:100%;max-width:100%;min-width:0} 516} 517@media(max-width:920px){ 518 .nav-burger{width:44px;height:44px} 519 .btn{min-height:44px;padding:12px 20px} 520} 521@media(max-width:640px){ 522 .device .bar span{font-size:12px} 523 .dash-live-badge{font-size:12px} 524} 525 526/* ââ mobile performance âââââââââââââââââââââââââââââââââââââââââââââ 527 iOS Safari: full-viewport fixed layers with mix-blend-mode force a 528 re-blend of the whole page on every scrolled frame, and large 529 animated blurs re-rasterize constantly. Both are dropped below 860px. 530 The backdrop under these layers is near-black (#04060c) and #bg3d is 531 disabled on mobile, so screen-blend â normal-blend here: the look is 532 effectively unchanged, the compositing cost is not. */ 533@media(max-width:860px){ 534 .ambient{mix-blend-mode:normal;opacity:.45} 535 .ambient .orb{width:70vw;height:70vw;filter:blur(45px)} 536 .cta .flash{mix-blend-mode:normal} 537 .cta .flash::before,.cta .flash::after{filter:blur(55px);animation:none;opacity:.6} 538} 539 540/* Offscreen module panels are parked rather than left ticking. Applied 541 by IntersectionObserver; if JS never runs, nothing is paused. */ 542.hpanel.pv-idle,.hpanel.pv-idle *, 543.hpanel.pv-idle *::before,.hpanel.pv-idle *::after{animation-play-state:paused!important} 544 545/* The loader is a full-screen overlay; without this the page scrolls 546 underneath it while its content is still opacity:0. */ 547html.is-loading,html.is-loading body{overflow:hidden} 548 549@media(prefers-reduced-motion:reduce){ 550 .ambient .orb,.cta .flash::before,.cta .flash::after, 551 .pv-wave i,.pv-bar i,.pv-ring,.pv-config .crow,.deco.bar,.scrollcue .m::after{animation:none!important} 552} 553</style> 554</head> 555<body> 556 557<div class="boost-bar" id="boostBar"></div> 558 559<div class="cursor" id="cursor"></div> 560<div class="cursor-dot" id="cursorDot"></div> 561<div class="progress" id="progress"></div> 562 563<div id="loader"> 564 <div class="load-mark"><span class="e">EASY</span><span class="l">LS</span></div> 565 <div class="load-bar"><i id="loadFill"></i></div> 566 <div class="load-pct mono" id="loadPct">INITIALIZING 0%</div> 567</div> 568 569<canvas id="bg3d"></canvas> 570<div class="ambient"><div class="orb b"></div><div class="orb r"></div></div> 571<div class="vignette"></div> 572 573<nav id="nav"> 574 <a class="nav-logo" data-link href="#top"><span class="nav-dot"></span><span class="e">EASY</span><span class="l">LS</span></a> 575 <div class="nav-links"> 576 <a data-link href="#lighting">Lighting</a> 577 <a data-link href="#rotators">Rotators</a> 578 <a data-link href="#modules-h">Modules</a> 579 <a data-link href="#why">Why EasyLS</a> 580 <a href="about.html">About</a> 581 <a data-group href="#">Roblox Group</a> 582 </div> 583 <div class="nav-cta"> 584 <a class="btn btn-ghost" data-discord data-magnetic href="#">Discord</a> 585 <a class="btn btn-primary" data-magnetic href="get.html">Get EasyLS</a> 586 </div> 587 <button class="nav-burger" id="navBurger" aria-label="Open menu"><span></span><span></span><span></span></button> 588</nav> 589<div class="nav-mobile" id="navMobile"> 590 <a data-link href="#lighting">Lighting</a> 591 <a data-link href="#rotators">Rotators</a> 592 <a data-link href="#modules-h">Modules</a> 593 <a data-link href="#why">Why EasyLS</a> 594 <a href="about.html">About</a> 595 <a data-group href="#">Roblox Group</a> 596 <a class="btn btn-ghost" data-discord href="#">Join the Discord</a> 597 <a class="btn btn-primary" href="get.html">Get EasyLS →</a> 598</div> 599 600<header class="hero" id="top"> 601 <div class="hero-badge" data-speed="1.25">EMERGENCY LIGHTING SYSTEM · ROBLOX</div> 602 603 <picture> 604 <source srcset="ELS_Logo_Full.webp" type="image/webp" /> 605 <img class="hero-logo" id="heroLogo" src="[email protected]" 606 width="1240" height="536" alt="EasyLS logo" 607 decoding="async" fetchpriority="high" data-speed="1.15" /> 608 </picture> 609 <h1 data-speed="1.4">The whole <span class="grad-rb">ELS system</span>, none of the scripting.</h1> 610 <p class="sub" data-speed="1.55">Lighting, rotators, sirens, sounds, headlights, turn signals and ke
610ybinds for any A-Chassis vehicle, all from one plugin inside Roblox Studio.</p> 611 <div class="hero-cta" data-speed="1.7"> 612 <a class="btn btn-primary" data-magnetic href="get.html">Get EasyLS â</a> 613 <a class="btn btn-ghost" data-link data-magnetic href="#lighting">See it in action</a> 614 </div> 615 <div class="lightbar" id="lightbar" data-speed="1.85"></div> 616 <div class="scrollcue"><div class="m"></div>SCROLL</div> 617 618 <div class="deco bar" data-speed="0.5" style="left:8%;top:24%"></div> 619 <div class="deco bar r" data-speed="0.7" style="right:10%;top:30%"></div> 620 <div class="deco dotg" data-speed="0.4" style="left:16%;top:62%"></div> 621 <div class="deco ringd" data-speed="0.6" style="right:14%;top:60%"></div> 622 <div class="deco plus" data-speed="0.45" style="left:78%;top:20%"></div> 623 <div class="deco plus" data-speed="0.55" style="left:22%;top:40%"></div> 624</header> 625 626<div class="marquee"><div class="track" id="marqueeTrack"></div></div> 627 628<section class="statement sec"> 629 <div class="wrap"> 630 <p class="big" id="statementText">If you can <span class="hl">picture the pattern</span>, you can build it.</p> 631 <div class="deco bar" data-speed="0.55" style="left:6%;top:30%"></div> 632 <div class="deco bar r" data-speed="0.65" style="right:8%;top:64%"></div> 633 <div class="deco dotg" data-speed="0.4" style="right:18%;top:24%"></div> 634 </div> 635</section> 636 637<section class="sec" id="lighting"> 638 <div class="deco bar" data-speed="0.5" style="left:3%;top:18%"></div> 639 <div class="deco ringd" data-speed="0.65" style="left:6%;top:74%"></div> 640 <div class="wrap feature"> 641 <div class="f-copy reveal"> 642 <span class="tag">Module 01 · Lighting</span> 643 <div class="eyebrow">Pattern Editor</div> 644 <h2>Design any pattern, light by light.</h2> 645 <p class="lead">The lighting editor is a step sequencer. Each row is a step, each column is a light, and clicking a cell sets that light's color on that step. Add as many groups and stages as you need, then hit play to watch the pattern run before you test it in game.</p> 646 <div class="f-list"> 647 <div class="item"><span class="ic"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.2"/><rect x="14" y="3" width="7" height="7" rx="1.2"/><rect x="3" y="14" width="7" height="7" rx="1.2"/><rect x="14" y="14" width="7" height="7" rx="1.2"/></svg></span><div>Set the color of every light on every step</div></div> 648 <div class="item"><span class="ic"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="13" r="8"/><path d="M12 13V8.5"/><path d="M9.5 2.5h5"/></svg></span><div>Change the tempo and step count to speed a pattern up or slow it down</div></div> 649 <div class="item"><span class="ic"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V5a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h3"/></svg></span><div>Save light groups and switch between stages</div></div> 650 </div> 651 </div> 652 <div class="f-copy"> 653 <div class="device tilt" id="tilt1"> 654 <div class="bar"><i class="r"></i><i class="y"></i><i class="g"></i><span>EasyLS â Lighting Editor</span></div> 655 <div class="pimg"><div class="pimg-inner"><picture> 656 <source srcset="lighting_page.webp" type="image/webp" /> 657 <img src="lighting_page.png" width="1022" height="705" loading="lazy" decoding="async" alt="EasyLS lighting pattern editor" /> 658 </picture></div></div> 659 <div class="f-glow r" style="top:auto;bottom:-30%"></div> 660 </div> 661 </div> 662 </div> 663</section> 664 665<section class="sec" style="padding-top:0"> 666 <div class="wrap" style="text-align:center"> 667 <span class="tag b reveal">Live Preview</span> 668 <h2 class="reveal" style="margin:0 auto 14px">Watch the pattern run, live in Studio.</h2> 669 <p class="lead reveal" style="margin:0 auto 40px">The preview renders in real time, so what you see here is what shows up in game.</p> 670 <div class="device tilt" id="gifFrame" style="max-width:900px;margin:0 auto"> 671 <div class="bar"><i class="r"></i><i class="y"></i><i class="g"></i><span>EasyLS â Live ELS Render</span></div> 672 673 <div class="pimg"><div class="pimg-inner"> 674 <video class="livegif" width="1022" height="708" autoplay loop muted playsinline 675 preload="none" poster="LightingGif_poster.jpg" 676 aria-label="EasyLS lighting in action"> 677 <source src="LightingGif.webm" type="video/webm" /> 678 <source src="LightingGif.mp4" type="video/mp4" /> 679 <img src="LightingGif_poster.jpg" width="1022" height="708" loading="lazy" 680 decoding="async" alt="EasyLS lighting in action" /> 681 </video> 682 </div></div> 683 </div> 684 </div> 685</section> 686 687<section class="sec" id="rotators"> 688 <div class="deco bar r" data-speed="0.5" style="right:4%;top:20%"></div> 689 <div class="deco dotg" data-speed="0.7" style="right:9%;top:70%"></div> 690 <div class="wrap feature rev"> 691 <div class="f-copy"> 692 <div class="device tilt" id="tilt2"> 693 <div class="bar"><i class="r"></i><i class="y"></i><i class="g"></i><span>EasyLS â Rotators</span></div> 694 <div class="pimg"><div class="pimg-inner"><picture> 695 <source srcset="Rotators_page.webp" type="image/webp" /> 696 <img src="Rotators_page.png" width="1057" height="727" loading="lazy" decoding="async" alt="EasyLS rotator angle color regions" /> 697 </picture></div></div> 698 <div class="f-glow b"></div> 699 </div> 700 </div> 701 <div class="f-copy reveal">
702 <span class="tag b">Module 02 · Rotators</span> 703 <div class="eyebrow">Angle Color Regions</div> 704 <h2>Beacons that actually rotate.</h2> 705 <p class="lead">Split the rotation ring into colored sections, then set the top speed, acceleration, deceleration and direction. As the beacon turns it picks up the color of whichever section it's pointing at.</p> 706 <div class="f-list"> 707 <div class="item"><span class="ic"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 12V3"/><path d="M12 12l7.8 4.5"/></svg></span><div>Click anywhere on the ring to add a color region</div></div> 708 <div class="item"><span class="ic"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3.2"/><path d="M12 2.5v3M12 18.5v3M2.5 12h3M18.5 12h3M5.2 5.2l2.1 2.1M16.7 16.7l2.1 2.1M18.8 5.2l-2.1 2.1M7.3 16.7l-2.1 2.1"/></svg></span><div>Control top speed, acceleration, deceleration and direction</div></div> 709 <div class="item"><span class="ic"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M5 20L15 10"/><path d="M16 3.5l1 2 2 1-2 1-1 2-1-2-2-1 2-1z"/><path d="M6 4.5l.6 1.2 1.2.6-1.2.6L6 8.1l-.6-1.2L4.2 6.3l1.2-.6z"/></svg></span><div>A setup wizard that finds the beacons on your vehicle for you</div></div> 710 </div> 711 <div style="margin-top:48px"><div class="ring-stage"> 712 <div class="ring-hint" id="ringHint"> 713 <span class="ring-hint-txt">Click me!</span>
714 <svg class="ring-hint-arrow" viewBox="0 0 140 120" fill="none" aria-hidden="true"><path d="M120 14 C 140 48, 98 62, 80 50 C 66 41, 78 24, 90 34 C 98 41, 88 62, 58 76 C 42 84, 30 94, 24 106" stroke="currentColor" stroke-width="4" stroke-linecap="round"/><path d="M24 106 L 41 100 M24 106 L 30 89" stroke="currentColor" stroke-width="4" stroke-linecap="round"/></svg> 715 </div> 716 <div class="ring-viz" id="ringViz"><div class="ring-rot" id="ringRot"><div class="ring-disc" id="ringDisc"></div><div class="ring-nodes" id="ringNodes"></div></div></div> 717 </div></div> 718 </div> 719 </div> 720</section> 721 722<section class="hscroll" id="modules-h"> 723 <div class="hhead"> 724 <div class="eyebrow" style="justify-content:center">One Plugin · Five Modules</div> 725 <h2 style="font-size:clamp(26px,4vw,44px);font-weight:800">Everything in the box.</h2> 726 </div> 727 <div class="hscroll-track" id="htrack"> 728 <div class="hpanel b"><div class="pglow"></div><div class="pn">01</div><span class="ptag">Lighting</span><div class="pvis"><div class="pv-bar"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div></div><div class="pico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18h6"/><path d="M10 21.5h4"/><path d="M12 2.5a6.5 6.5 0 0 0-4 11.6c.8.7 1 1.4 1 2.4h6c0-1 .2-1.7 1-2.4A6.5 6.5 0 0 0 12 2.5z"/></svg></div><h3>Lighting</h3><p>A pattern sequencer for ELS, headlights and any other lighting you put on the car.</p><div class="pchips"><span>Per-step color</span><span>Multi-stage</span><span>Live preview</span></div></div> 729 <div class="hpanel r"><div class="pglow"></div><div class="pn">02</div><span class="ptag">Rotators</span><div class="pvis"><div class="pv-ring"></div></div><div class="pico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 3.5V9h-5.5"/></svg></div><h3>Rotators</h3><p>Rotating warning lights that change color by angle, with a wizard to get them set up.</p><div class="pchips"><span>Angle-based</span><span>Speed control</span><span>Setup wizard</span></div></div> 730 <div class="hpanel b"><div class="pglow"></div><div class="pn">03</div><span class="ptag">Sirens & Sounds</span><div class="pvis"><div class="pv-wave"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div></div><div class="pico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 9v6h3.5L13 19.5V4.5L7.5 9H4z"/><path d="M16.5 8.5a5 5 0 0 1 0 7"/><path d="M19 6a8.5 8.5 0 0 1 0 12"/></svg></div><h3>Sirens & Sounds</h3><p>Add siren tones and your own vehicle sounds, running off the same system as the lights.</p><div class="pchips"><span>Custom tones</span><span>Per-vehicle</span><span>Light-synced</span></div></div> 731 <div class="hpanel r"><div class="pglow"></div><div class="pn">04</div><span class="ptag">Keybinds</span><div class="pvis"><div class="pv-keys" id="pvKeys"></div></div><div class="pico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="6" width="20" height="12" rx="2.2"/><path d="M6 10h.01M10 10h.01M14 10h.01M18 10h.01M6.5 14h11"/></svg></div><h3>Keybinds</h3><p>Assign any key to any function: lights, stages, sirens, rotators, headlights and turn signals.</p><div class="pchips"><span>Any key</span><span>Every function</span><span>Per-car</span></div></div> 732 <div class="hpanel b"><div class="pglow"></div><div class="pn">05</div><span class="ptag">Configuration</span><div class="pvis"><div class="pv-config" id="pvConfig"></div></div><div class="pico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3.2"/>
732<path d="M19.4 15a1.6 1.6 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.6 1.6 0 0 0-1.8-.3 1.6 1.6 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.6 1.6 0 0 0-1-1.5 1.6 1.6 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.6 1.6 0 0 0 .3-1.8 1.6 1.6 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.6 1.6 0 0 0 1.5-1 1.6 1.6 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.6 1.6 0 0 0 1.8.3H9a1.6 1.6 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.6 1.6 0 0 0 1 1.5 1.6 1.6 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.6 1.6 0 0 0-.3 1.8V9a1.6 1.6 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.6 1.6 0 0 0-1.5 1z"/></svg></div><h3>Configuration</h3><p>Set the color palette, lighting method and other settings that apply to the whole vehicle.</p><div class="pchips"><span>Color palette</span><span>Lighting method</span><span>Reusable</span></div></div> 733 </div> 734</section> 735 736<section class="sec dash" id="modules"> 737 <div class="wrap"> 738 <div class="eyebrow" style="justify-content:center">The Dashboard</div> 739 <h2 style="margin:0 auto 16px;max-width:20ch">It all lives in one panel.</h2> 740 <p class="lead" style="margin:0 auto">Turn on the modules a vehicle needs, then open each one to edit it. Everything for that car stays in the same place instead of spread across scripts and settings.</p> 741 <div class="dash-shot" id="dashShot"> 742 <div class="els-dash"> 743 <div class="studio"> 744 <div class="menubar"> 745 <div class="mleft"><span>File</span><span>Edit</span><span>Help</span></div> 746 <div class="mright"></div> 747 </div> 748 <div class="tabbar"> 749 <div class="tabs"> 750 <button class="d-tab active">Modules</button> 751 <button class="d-tab">Lighting</button> 752 <button class="d-tab">Rotators</button> 753 <button class="d-tab">Sirens</button> 754 <button class="d-tab">Keybinds</button> 755 <button class="d-tab">Configuration</button> 756 </div> 757 <div class="tab-icons"> 758 <div class="ic" title="Plugin"><svg width="22" height="24" viewBox="0 0 22 24" fill="none"><path d="M11 1.6 20 6.6v10.8L11 22.4 2 17.4V6.6z" stroke="#c2c2c8" stroke-width="1.6" stroke-linejoin="round"/><path d="M11 7.2 15.5 9.8v5.2L11 17.6 6.5 15V9.8z" stroke="#c2c2c8" stroke-width="1.3" stroke-linejoin="round"/></svg></div> 759 <div class="ic" title="Team"><svg width="26" height="22" viewBox="0 0 26 22" fill="none"><circle cx="9" cy="7" r="3.4" stroke="#c2c2c8" stroke-width="1.6"/><path d="M3 18.5c0-3.3 2.7-6 6-6s6 2.7 6 6" stroke="#c2c2c8" stroke-width="1.6" stroke-linecap="round"/><circle cx="17.5" cy="7.6" r="2.8" stroke="#c2c2c8" stroke-width="1.5"/><path d="M16 13c3 .1 6 2.3 6 5.5" stroke="#c2c2c8" stroke-width="1.5" stroke-linecap="round"/></svg></div> 760 <div class="ic" title="Home"><svg width="26" height="24" viewBox="0 0 26 24" fill="none"><path d="M4 11 13 3.5 22 11" stroke="#c2c2c8" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/><path d="M6 10v9.5h14V10" stroke="#c2c2c8" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg></div> 761 </div> 762 <div class="plus-tab">+</div> 763 </div> 764 <div class="d-content modules-view"> 765 <div class="d-grid"> 766 <div class="d-card"><div class="head"><h3>Lighting</h3><label class="d-toggle"><input type="checkbox" checked><span class="track"></span><span class="knob"></span></label></div><p class="desc">Modify this vehicle's ELS, headlights, or other lighting</p><div class="foot"><button class="d-modify">Modify</button></div></div> 767 <div class="d-card"><div class="head"><h3>Rotators</h3><label class="d-toggle"><input type="checkbox" checked><span class="track"></span><span class="knob"></span></label></div><p class="desc">Configure rotating warning lights and angle-based color overrides</p><div class="foot"><button class="d-modify">Modify</button></div></div> 768 <div class="d-card"><div class="head"><h3>Sirens</h3><label class="d-toggle"><input type="checkbox" checked><span class="track"></span><span class="knob"></span></label></div><p class="desc">Modify this vehicle's sirens</p><div class="foot"><button class="d-modify">Modify</button></div></div> 769 <div class="d-card"><div class="head"><h3>Keybinds</h3></div><p class="desc">Map all keybinds for all functions of this car.</p><div class="foot"><button class="d-modify">Modify</button></div></div> 770 <div class="d-card"><div class="head"><h3>Car Configuration</h3></div><p class="desc">Modify this vehicles color palette, lighting method, etc</p><div class="foot"><button class="d-modify">Modify</button></div></div> 771 </div> 772 </div> 773 <div class="d-content lighting-view" hidden> 774 <div class="le"> 775 <div class="le-side"> 776 <div class="le-logo"><span class="e">EASY</span> <span class="l">LS</span></div> 777 <div class="le-subtabs"><span class="active">EDITOR</span><span>GROUPS</span></div> 778 <div class="le-colorbox"> 779 <button class="le-arrow" id="leColorPrev">‹</button>
780 <span class="le-key">Q</span> 781 <span class="le-color" id="leColorName">Red</span> 782 <span class="le-key">E</span> 783 <button class="le-arrow" id="leColorNext">›</button> 784 </div> 785 <div class="le-ps-label">Pattern Selector</div> 786 <div class="le-pselect"><svg width="13" height="13" viewBox="0 0 24 24" fill="none"><circle cx="11" cy="11" r="7" stroke="#7c8395" stroke-width="2"/><path d="M16 16l5 5" stroke="#7c8395" stroke-width="2" stroke-linecap="round"/></svg> Stage 1 <span class="chev">▾</span></div> 787 <button class="le-play" id="lePlay" aria-label="Play / Pause">▶</button> 788 </div> 789 <div class="le-main"> 790 <div class="le-stage">Stage 1</div> 791 <input class="le-groupname" placeholder="Light Group Name"> 792 <div class="le-board"> 793 <div class="le-grid"> 794 <div class="le-head-row"><div class="le-rowlabel"></div><div class="le-cols" id="leCols"></div></div> 795 <div class="le-grid-rows" id="leRows"></div> 796 </div> 797 <div class="le-controls"> 798 <div class="le-ctrl"><div class="t">Lights</div><div class="row"><button data-ctrl="lights" data-d="-1">−</button><span class="v" id="leLights">8</span><button data-ctrl="lights" data-d="1">+</button></div></div> 799 <div class="le-ctrl"><div class="t">Tempo</div><div class="row"><button data-ctrl="tempo" data-d="-1">−</button><span class="v" id="leTempo">600</span><button data-ctrl="tempo" data-d="1">+</button></div></div> 800 <div class="le-ctrl"><div class="t">Steps</div><div class="row"><button data-ctrl="steps" data-d="-1">−</button><span class="v" id="leSteps">16</span><button data-ctrl="steps" data-d="1">+</button></div></div> 801 </div> 802 </div> 803 </div> 804 </div> 805 </div> 806 </div> 807 </div> 808 <span class="dash-live-badge"><i></i>Live demo, try the toggles</span> 809 </div> 810 <p class="dash-note">This dashboard is a web recreation for the site. The real one runs inside Roblox Studio.</p> 811 </div> 812</section> 813 814<section class="sec" style="padding:90px 0"> 815 <div class="wrap"> 816 <div class="stats"> 817 <div class="stat"><div class="num" data-count="5">0</div><div class="lbl">Modules</div></div> 818 <div class="stat"><div class="num">â</div><div class="lbl">Light groups per vehicle</div></div> 819 <div class="stat"><div class="num">â</div><div class="lbl">Pattern steps per stage</div></div> 820 <div class="stat"><div class="num" data-count="100" data-suffix="%">0</div><div class="lbl">No-code setup</div></div> 821 <div class="stat"><div class="num" data-count="80" data-suffix="%">0</div><div class="lbl">Less time building patterns</div></div> 822 <div class="stat"><div class="num">1k+</div><div class="lbl">Purchases to date</div></div> 823 </div> 824 </div> 825</section> 826 827<section class="sec" id="why"> 828 <div class="wrap" style="text-align:center"> 829 <div class="eyebrow" style="justify-content:center">Why EasyLS</div> 830 <h2 style="margin:0 auto;max-width:20ch">Why people keep using it.</h2> 831 <div class="why-grid"> 832 <div class="why-card"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 8l-4 4 4 4"/><path d="M16 8l4 4-4 4"/><path d="M14 5l-4 14"/></svg></span><h4>Actually zero code</h4><p>Plenty of plugins call themselves no-code and still leave you a couple of scripts to wire up at the end. With EasyLS you never open <em>one</em>.</p></div> 833 <div class="why-card"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19a8 8 0 0 1 16 0"/><path d="M12 19l4.5-6.5"/><circle cx="12" cy="19" r="1.4"/></svg></span><h4>Easy on your server</h4><p>The runtime is written to keep overhead low, so a car loaded with lights and effects won't drag your server down.</p></div> 834 <div class="why-card"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 16.5V13l2-5.5A2 2 0 0 1 6.9 6h10.2a2 2 0 0 1 1.9 1.5L21 13v3.5"/><path d="M3 16.5h18v2.5a1 1 0 0 1-1 1h-1.5a1 1 0 0 1-1-1v-1H6.5v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1z"/><path d="M6 13h3M15 13h3"/></svg></span><h4>More than lighting</h4><p>It's built for A-Chassis vehicles, so alongside the ELS you get sirens, sounds, headlights, turn signals and ke
834ybinds in the same interface.</p></div> 835 <div class="why-card"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 14.5a2 2 0 0 1-2 2h-9L5 20.5v-4h-.5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/><path d="M8 9h8M8 12h5"/></svg></span><h4>An active Discord</h4><p>Ask questions, show off builds and request features alongside everyone else using it. There's a marketplace channel too, where members post the cars they've made.</p></div> 836 <div class="why-card"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2.8l2.6 5.6 6.1.8-4.5 4.2 1.2 6-5.4-3-5.4 3 1.2-6L3.3 9.2l6.1-.8z"/></svg></span><h4>What you make is yours</h4><p>Rather than paying someone to build assets for you, you build your own at no extra cost. Anything you make with EasyLS belongs to you: redistribute it, resell it, upload it to Roblox.</p></div> 837 <div class="why-card"><span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7.4v4.9l3.4 2"/></svg></span><h4>Support, 24/7</h4><p>Help with the plugin costs nothing extra and it's there around the clock. If something breaks or a feature won't behave, ask and someone will work through it with you.</p></div> 838 </div> 839 </div> 840</section> 841 842<section class="cta" id="join"> 843 <div class="flash"></div> 844 <div class="wrap"> 845 <h2 data-speed="1.3"><span class="cta-mark blue">EASY</span><span class="cta-mark red">LS</span><br>Light it up.</h2> 846 <p data-speed="1.45">Grab the plugin, then join the Discord if you want a hand setting up your first car.</p> 847 <div class="hero-cta" style="justify-content:center" data-speed="1.6"> 848 <a class="btn btn-primary" data-magnetic href="get.html">Get EasyLS â</a> 849 <a class="btn btn-ghost" data-discord data-magnetic href="#">Join the Discord</a> 850 </div> 851 </div> 852</section> 853 854<footer> 855 <div class="wrap"> 856 <div class="foot"> 857 <div> 858 <div class="brand"><span class="e">EASY</span><span class="l">LS</span></div> 859 <p>An emergency lighting plugin for Roblox, plus the rest of what an A-Chassis vehicle needs: sirens, sounds, headlights, turn signals and keybinds. No scripting required.</p> 860 </div> 861 <div class="foot-links"> 862 <div class="foot-col"><h5>Modules</h5> 863 <a data-link href="#lighting">Lighting</a><a data-link href="#rotators">Rotators</a><a data-link href="#modules-h">Sirens & Sounds</a><a data-link href="#modules-h">Keybinds</a><a data-link href="#modules-h">Configuration</a> 864 </div> 865 <div class="foot-col"><h5>Community</h5> 866 <a data-discord href="#">Discord</a><a data-group href="#">Roblox Group</a><a href="about.html">About</a><a data-link href="#why">Why EasyLS</a> 867 </div> 868 <div class="foot-col"><h5>Get EasyLS</h5> 869 <a href="get.html">Pricing</a><a href="get.html#buy">How to buy</a><a href="get.html#install">Installation</a> 870 </div> 871 </div> 872 </div> 873 <div class="foot-bottom"> 874 <span>© <span id="year"></span> EasyLS. Not affiliated with Roblox Corporation.</span> 875 </div> 876 </div> 877</footer> 878
879<script> 880/* three.js (~580KB parse+compile) is only ever used by the desktop starfield. 881 It used to load unconditionally and render-block ahead of GSAP/Lenis on 882 phones, where the consumer bailed out immediately. Now it is fetched 883 async, and only when it will actually be used. */ 884(function(){ 885 var reduce = matchMedia('(prefers-reduced-motion: reduce)').matches; 886 var lowPower = matchMedia('(max-width:860px)').matches || 887 matchMedia('(hover:none) and (pointer:coarse)').matches; 888 if (reduce || lowPower) { 889 var c = document.getElementById('bg3d'); 890 if (c) c.style.display = 'none'; 891 return; 892 } 893 var s = document.createElement('script'); 894 s.src = 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js'; 895 s.integrity = 'sha384-CI3ELBVUz9XQO+97x6nwMDPosPR5XvsxW2ua7N1Xeygeh1IxtgqtCkGfQY9WWdHu'; 896 s.crossOrigin = 'anonymous'; 897 s.referrerPolicy = 'no-referrer'; 898 s.async = true; 899 s.onload = function(){ 900 window.__threeReady = true; 901 if (window.__initBg3d) window.__initBg3d(); 902 }; 903 document.head.appendChild(s); 904})(); 905</script>
vendor: 1 bytes, line 905
905
906<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js" 907 integrity="sha384-g4NTh/Iv5PPU4xPyhEWqPcwtNXOvdaDI8LLnyYfyNZOjKJeYQyjzQ9X5275eBjpt" 908 crossorigin="anonymous" referrerpolicy="no-referrer"></script>
vendor: 1 bytes, line 908
908
909<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js" 910 integrity="sha384-Z3REaz79l2IaAZqJsSABtTbhjgOUYyV3p90XNnAPCSHg3EMTz1fouunq9WZRtj3d" 911 crossorigin="anonymous" referrerpolicy="no-referrer"></script>
vendor: 1 bytes, line 911
911
912<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/lenis.min.js" 913 integrity="sha384-O55L/6rhHr9CFvrxqv5luxOCcmVaBmETbZbJDP+Do8T0pztTACsFBD/IXCNkj7DV" 914 crossorigin="anonymous" referrerpolicy="no-referrer"></script>
vendor: 1 bytes, line 914
914
915<script> 916var DISCORD_URL = "https://discord.gg/NbKz94hMcA"; 917var GROUP_URL = "https://www.roblox.com/communities/12392211/EasyLS#!/about"; 918document.querySelectorAll('[data-discord]').forEach(function(a){ a.href=DISCORD_URL; a.target="_blank"; a.rel="noopener"; }); 919document.querySelectorAll('[data-group]').forEach(function(a){ a.href=GROUP_URL; a.target="_blank"; a.rel="noopener"; }); 920document.getElementById('year').textContent=new Date().getFullYear(); 921 922(function(){ 923 var c=document.getElementById('cursor'), d=document.getElementById('cursorDot'); 924 var x=innerWidth/2,y=innerHeight/2,cx=x,cy=y; 925 if(!matchMedia('(hover:hover) and (pointer:fine)').matches){c.style.display='none';d.style.display='none';return;} 926 addEventListener('mousemove',function(e){ x=e.clientX;y=e.clientY; d.style.transform='translate('+x+'px,'+y+'px) translate(-50%,-50%)'; },{passive:true}); 927 (function loop(){ cx+=(x-cx)*0.18; cy+=(y-cy)*0.18; c.style.transform='translate('+cx+'px,'+cy+'px) translate(-50%,-50%)'; requestAnimationFrame(loop); })(); 928 document.addEventListener('mouseover',function(e){ 929 if(e.target.closest('a,button,[data-magnetic],.why-card,.hpanel,.stat,.d-toggle')) c.classList.add('grow'); }); 930 document.addEventListener('mouseout',function(e){ 931 if(e.target.closest('a,button,[data-magnetic],.why-card,.hpanel,.stat,.d-toggle')) c.classList.remove('grow'); }); 932})(); 933 934(function(){ 935 var fill=document.getElementById('loadFill'),pct=document.getElementById('loadPct'); 936 var MIN_MS=450, MAX_MS=3500, started=Date.now(), p=0, done=false; 937 938 function paint(){ fill.style.width=p+'%'; pct.textContent='INITIALIZING '+Math.floor(p)+'%'; } 939 940 document.documentElement.classList.add('is-loading'); 941 942 var iv=setInterval(function(){ if(done)return; p+=(90-p)*0.12;
942 paint(); },90); 943 944 function finish(){ 945 if(done)return; done=true; 946 document.documentElement.classList.remove('is-loading'); 947 clearInterval(iv); 948 p=100; paint(); 949 var wait=Math.max(0, MIN_MS-(Date.now()-started)); 950 setTimeout(function(){ 951 document.getElementById('loader').classList.add('done'); 952 init(); 953 }, wait+180); 954 } 955 956 if(document.readyState==='complete') finish(); 957 else addEventListener('load',finish); 958 setTimeout(finish, MAX_MS); 959})(); 960 961(function(){ 962 var bar=document.getElementById('lightbar'),n=14,cells=[]; 963 for(var i=0;i<n;i++){var el=document.createElement('div');el.className='cell';bar.appendChild(el);cells.push(el);} 964 var t=0,timer=null; 965 function step(){ t++; cells.forEach(function(c,i){ c.classList.remove('on-b','on-r'); 966 var on=(t%4<2); if(i<n/2){ if(on)c.classList.add('on-b'); } else { if(!on)c.classList.add('on-r'); } }); } 967 function startBar(){ if(!timer) timer=setInterval(step,180); } 968 function stopBar(){ if(timer){ clearInterval(timer); timer=null; } } 969 if('IntersectionObserver' in window){ new IntersectionObserver(function(es){ es[0].isIntersecting?startBar():stopBar(); },{threshold:0}).observe(bar); } 970 else startBar(); 971})(); 972 973(function(){ 974 var words=['LIGHTING','ROTATORS','SIRENS','KEYBINDS','CONFIGURATION']; 975 function block(){var s='';words.forEach(function(w,i){s+='<span class="'+(i%2?'fill r':'fill')+'">'+w+'</span><span class="dot"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 1.5l2.4 8.1 8.1 2.4-8.1 2.4L12 22.5l-2.4-8.1L1.5 12l8.1-2.4z"/></svg></span>';});return s;} 976 document.getElementById('marqueeTrack').innerHTML=block()+block()+block()+block(); 977})(); 978 979/* Called by the async three.js loader above; the gating (mobile / 980 reduced-motion) already happened there, so this only runs on desktop. */ 981window.__initBg3d=function(){ 982 if(!window.THREE || window.__bg3dStarted) return; 983 window.__bg3dStarted=true; 984 var canvas=document.getElementById('bg3d'); 985 if(!canvas) return; 986 987 var renderer=new THREE.WebGLRenderer({canvas:canvas,alpha:true,antialias:true,powerPreference:'low-power'}); 988 renderer.setPixelRatio(Math.min(devicePixelRatio,1.5)); renderer.setSize(innerWidth,innerHeight); 989 var scene=new THREE.Scene(), camera=new THREE.PerspectiveCamera(60,innerWidth/innerHeight,0.1,1000); camera.position.z=60; 990 function glowTex(){var cv=document.createElement('canvas');cv.width=cv.height=128;var x=cv.getContext('2d'); 991 var g=x.createRadialGradient(64,64,0,64,64,64);g.addColorStop(0,'rgba(255,255,255,1)');g.addColorStop(.25,'rgba(255,255,255,.65)'); 992 g.addColorStop(.5,'rgba(255,255,255,.18)');g.addColorStop(1,'rgba(255,255,255,0)');x.fillStyle=g;x.fillRect(0,0,128,128); 993 return new THREE.CanvasTexture(cv);} 994 var tex=glowTex(), group=new THREE.Group(); scene.add(group); 995 996 var COUNT=innerWidth>1600?300:(innerWidth>1200?200:140); 997 var mats=[],data=[],blue=new THREE.Color(0x3aa6ff),red=new THREE.Color(0xff3b3b),white=new THREE.Color(0xbfe4ff); 998 for(var i=0;i<COUNT;i++){var r=Math.random(),col=r<0.45?blue:(r<0.9?red:white); 999 var m=new THREE.SpriteMaterial({map:tex,color:col,transparent:true,blending:THREE.AdditiveBlending,opacity:0,depthWrite:false}); 1000 var s=new THREE.Sprite(m),sc=Math.random()*4+1.4;s.scale.set(sc,sc,1); 1001 s.position.set((Math.random()-.5)*160,(Math.random()-.5)*120,(Math.random()-.5)*130); 1002 data.push({base:s.position.clone(),sp:Math.random()*0.4+0.1,ph:Math.random()*6.28,tw:Math.random()*0.8+0.2,bo:Math.random()*0.5+0.25}); 1003 group.add(s);mats.push(m);} 1004 for(var j=0;j<6;j++){var col2=j%2?red:blue; 1005 var m2=new THREE.SpriteMaterial({map:tex,color:col2,transparent:true,blending:THREE.AdditiveBlending,opacity:0.18,depthWrite:false}); 1006 var s2=new THREE.Sprite(m2),sc2=Math.random()*32+26;s2.scale.set(sc2,sc2,1); 1007 s2.position.set((Math.random()-.5)*120,(Math.random()-.5)*80,-40-Math.random()*40);group.add(s2);} 1008 var mx=0,my=0,tmx=0,tmy=0,scrollY=0,intro=0,clock=new THREE.Clock(); 1009 addEventListener('mousemove',function(e){tmx=e.clientX/innerWidth-.5;tmy=e.clientY/innerHeight-.5;},{passive:true}); 1010 window.__setScroll=function(v){scrollY=v;}; 1011 (function anim(){requestAnimationFrame(anim);var t=clock.getElapsedTime();intro=Math.min(intro+0.012,1); 1012 mx+=(tmx-mx)*0.04;my+=(tmy-my)*0.04; 1013 group.rotation.y=t*0.03+mx*0.6; group.rotation.x=my*0.45; 1014 camera.position.z=60+scrollY*0.004; camera.position.y=-scrollY*0.003; 1015 for(var i=0;i<data.length;i++){var dd=data[i],sp=group.children[i]; 1016 sp.position.y=dd.base.y+Math.sin(t*dd.sp+dd.ph)*4; sp.position.x=dd.base.x+Math.cos(t*dd.sp*0.7+dd.ph)*3; 1017 mats[i].opacity=(dd.bo*(0.5+0.5*Math.sin(t*dd.tw*2+dd.ph)))*intro;} 1018 renderer.render(scene,camera);})(); 1019 addEventListener('resize',function(){camera.aspect=innerWidth/innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth,innerHeight);},{passive:true}); 1020}; 1021if(window.__threeReady) window.__initBg3d(); 1022 1023(function(){ 1024 var v=document.querySelector('video.livegif'); if(!v) return; 1025 if(matchMedia('(prefers-reduced-motion: reduce)').matches){ v.removeAttribute('autoplay'); v.controls=true; return; } 1026 if(!('IntersectionObserver' in window)){ v.play().catch(function(){}); return; } 1027 new IntersectionObserver(function(es){ 1028 if(es[0].isIntersecting) v.play().catch(function(){}); 1029 else v.pause(); 1030 },{threshold:0.15}).observe(v); 1031})(); 1032 1033var __navEl=document.getElementById('nav'), __navSolid=false; 1034function navUpdate(s){ var solid=s>60; if(solid!==__navSolid){ __navSolid=solid; __navEl.classList.toggle('solid',solid); } } 1035
1036function init(){ 1037 if(!window.gsap){ document.querySelectorAll('.reveal').forEach(function(e){e.style.opacity=1;e.style.transform='none';}); return; } 1038 gsap.registerPlugin(ScrollTrigger); 1039 1040 /* THE mobile fix. iOS collapses/expands the URL bar as you scroll, which 1041 fires `resize`. Without this, every one of those fires a full 1042 ScrollTrigger.refresh() â re-measuring ~45 triggers synchronously 1043 mid-scroll. That is the lag spike. Orientation changes still refresh. */ 1044 ScrollTrigger.config({ignoreMobileResize:true}); 1045 1046 var scrollIdleT=null; 1047 function markScrolling(){ window.__isScrolling=true; if(scrollIdleT)clearTimeout(scrollIdleT); scrollIdleT=setTimeout(function(){window.__isScrolling=false;},140); } 1048 addEventListener('wheel',markScrolling,{passive:true}); 1049 addEventListener('touchmove',markScrolling,{passive:true}); 1050 1051 var lenis=null; 1052 if(window.Lenis){ 1053 lenis=new Lenis({duration:1.15,easing:function(t){return Math.min(1,1.001-Math.pow(2,-10*t));},smoothWheel:true,lerp:0.1}); 1054 lenis.on('scroll',function(e){ markScrolling();
1054 ScrollTrigger.update(); window.__setScroll&&window.__setScroll(e.animatedScroll||e.scroll||window.scrollY); navUpdate(e.scroll||window.scrollY); }); 1055 gsap.ticker.add(function(time){ lenis.raf(time*1000); }); 1056 /* lagSmoothing(0) was here. With it off, any blocked frame made every 1057 scrub tween apply its whole accumulated delta at once â turning a 1058 stall into a visible snap. Left at the GSAP default (500, 33). */ 1059 } else { 1060 addEventListener('scroll',function(){ markScrolling(); window.__setScroll&&window.__setScroll(window.scrollY); navUpdate(window.scrollY); },{passive:true}); 1061 } 1062 1063 gsap.to('#progress',{scaleX:1,ease:'none',scrollTrigger:{trigger:document.body,start:'top top',end:'bottom bottom',scrub:true}}); 1064 1065 gsap.utils.toArray('.reveal').forEach(function(el){ 1066 gsap.to(el,{opacity:1,y:0,duration:1,ease:'power3.out',scrollTrigger:{trigger:el,start:'top 88%'}}); 1067 }); 1068 1069 /* .deco elements are display:none below 820px, but all 13 still carried 1070 data-speed â 13 scrub triggers doing nothing but getting re-measured. */ 1071 var decoHidden=matchMedia('(max-width:820px)').matches; 1072 gsap.utils.toArray('[data-speed]').forEach(function(el){ 1073 if(decoHidden && el.classList.contains('deco')) return; 1074 var sp=parseFloat(el.dataset.speed)||1; var amt=(sp-1)*220; 1075 gsap.fromTo(el,{y:amt},{y:-amt,ease:'none', 1076 scrollTrigger:{trigger:el.closest('section,header')||el,start:'top bottom',end:'bottom top',scrub:true}}); 1077 }); 1078 1079 gsap.utils.toArray('.pimg').forEach(function(frame){ 1080 var inner=frame.querySelector('.pimg-inner'); 1081 gsap.fromTo(frame,{clipPath:'inset(8% 0% 8% 0% round 16px)'},{clipPath:'inset(0% 0% 0% 0% round 16px)',ease:'power2.out', 1082 scrollTrigger:{trigger:frame,start:'top 92%',end:'top 50%',scrub:true}}); 1083 }); 1084 1085 gsap.utils.toArray('.tilt').forEach(function(el,k){ 1086 gsap.fromTo(el,{rotateY:(k%2?-14:14),rotateX:8,y:60,opacity:0.4}, 1087 {rotateY:0,rotateX:0,y:0,opacity:1,ease:'power2.out', 1088 scrollTrigger:{trigger:el,start:'top 90%',end:'top 45%',scrub:true}}); 1089 el.addEventListener('mousemove',function(e){ if(window.__isScrolling) return; var r=el.getBoundingClientRect(); 1090 gsap.to(el,{rotateX:((e.clientY-r.top)/r.height-.5)*-9,rotateY:((e.clientX-r.left)/r.width-.5)*9, 1091 duration:.5,transformPerspective:1000,ease:'power2.out'});}); 1092 el.addEventListener('mouseleave',function(){gsap.to(el,{rotateX:0,rotateY:0,duration:.6});}); 1093 }); 1094 1095 gsap.utils.toArray('.f-glow').forEach(function(g){ 1096 gsap.fromTo(g,{y:-60},{y:60,ease:'none',scrollTrigger:{trigger:g.closest('section'),start:'top bottom',end:'bottom top',scrub:true}}); 1097 }); 1098 1099 gsap.to('#heroLogo',{scale:0.9,opacity:0.7,ease:'none',scrollTrigger:{trigger:'.hero',start:'top top',end:'bottom top',scrub:true}}); 1100 1101 (function(){ 1102 var el=document.getElementById('statementText'),frag=[]; 1103 el.childNodes.forEach(function(node){ 1104 if(node.nodeType===3){ node.textContent.split(/(\s+)/).forEach(function(tk){ 1105 if(tk.trim()==='')frag.push(document.createTextNode(tk)); 1106 else{var s=document.createElement('span');s.className='w';s.textContent=tk;frag.push(s);} }); 1107 } else { node.classList.add('w'); frag.push(node); }}); 1108 el.innerHTML=''; frag.forEach(function(f){el.appendChild(f);}); 1109 gsap.to(el.querySelectorAll('.w'),{opacity:1,stagger:0.08,ease:'none', 1110 scrollTrigger:{trigger:el,start:'top 78%',end:'bottom 58%',scrub:true}}); 1111 })(); 1112 1113 (function(){ 1114 var track=document.getElementById('marqueeTrack'); 1115 var loop=gsap.to(track,{xPercent:-50,repeat:-1,duration:24,ease:'none'}); 1116 var vSkew=gsap.quickTo(track,'skewX',{duration:0.4,ease:'power2'}); 1117 ScrollTrigger.create({onUpdate:function(self){ 1118 var v=gsap.utils.clamp(-0.6,0.6,self.getVelocity()/-3000); 1119 var ts=gsap.utils.clamp(0.2,4,1+Math.abs(self.getVelocity())/2200); 1120 loop.timeScale(ts); vSkew(v*14); 1121 }}); 1122 })(); 1123 1124 (function(){ 1125 if(matchMedia('(max-width:860px)').matches) return; 1126 var track=document.getElementById('htrack'); 1127 var endLen=function(){return track.scrollWidth-innerWidth+40;}; 1128 gsap.to(track,{x:function(){return -endLen();},ease:'none', 1129 scrollTrigger:{trigger:'#modules-h',start:'top top',end:function(){return '+='+endLen();}, 1130 pin:true,scrub:1,invalidateOnRefresh:true}}); 1131 })(); 1132 1133 gsap.fromTo('#dashShot',{y:80,rotateX:12,scale:0.94},{y:0,rotateX:0,scale:1,ease:'power2.out', 1134 scrollTrigger:{trigger:'#dashShot',start:'top 90%',end:'top 45%',scrub:true}}); 1135 1136 gsap.utils.toArray('.num[data-count]').forEach(function(el){ 1137 var end=+el.getAttribute('data-count'),suf=el.getAttribute('data-suffix')||'',obj={v:0}; 1138 gsap.to(obj,{v:end,duration:1.6,ease:'power2.out',scrollTrigger:{trigger:el,start:'top 90%'}, 1139 onUpdate:function(){el.textContent=Math.floor(obj.v)+suf;}}); 1140 }); 1141 gsap.from('.stat',{y:40,opacity:0,stagger:0.1,duration:.7,ease:'power2.out',scrollTrigger:{trigger:'.stats',start:'top 85%'}}); 1142 gsap.from('.why-card',{y:40,opacity:0,stagger:0.08,duration:.7,ease:'power2.out',scrollTrigger:{trigger:'.why-grid',start:'top 85%'}}); 1143 1144 gsap.utils.toArray('[data-magnetic]').forEach(function(el){ 1145 el.addEventListener('mousemove',function(e){ if(window.__isScrolling) return; var r=el.getBoundingClientRect(); 1146 gsap.to(el,{x:(e.clientX-r.left-r.width/2)*0.4,y:(e.clientY-r.top-r.height/2)*0.5,duration:.4,ease:'power2.out'});}); 1147 el.addEventListener('mouseleave',function(){gsap.to(el,{x:0,y:0,duration:.5,ease:'elastic.out(1,0.4)'});}); 1148 }); 1149 1150 document.querySelectorAll('a[data-link]').forEach(function(a){ 1151 a.addEventListener('click',function(e){ 1152 var id=a.getAttribute('href'); if(!id||id.length<2)return; 1153 var t=document.querySelector(id); if(!t)return; e.preventDefault(); 1154 if(lenis) lenis.scrollTo(t,{offset:-60,duration:1.2}); 1155 else t.scrollIntoView({behavior:'smooth'}); 1156 }); 1157 }); 1158 1159 ScrollTrigger.refresh(); 1160 addEventListener('load',function(){ScrollTrigger.refresh();}); 1161 setTimeout(function(){ScrollTrigger.refresh();},900); 1162} 1163</script>
vendor: 1 bytes, line 1163
1163
1164<script> 1165(function(){ 1166 var dash=document.querySelector('.els-dash'); if(!dash) return; 1167 1168 var COLORS=[['Red','#ff3b3b'],['Blue','#2b9bff'],['Green','#2ee06a'],['Amber','#ffb13b'],['White','#eef2ff']]; 1169 var ci=0, lights=8, steps=16, tempo=600, grid=[], liveEls=[], playingRow=null; 1170 var colsEl=dash.querySelector('#leCols'), rowsEl=dash.querySelector('#leRows'), playBtn=dash.querySelector('#lePlay'), colorNameEl=dash.querySelector('#leColorName'); 1171 function hexA(hex,a){var n=parseInt(hex.slice(1),16);return 'rgba('+((n>>16)&255)+','+((n>>8)&255)+','+(n&255)+','+a+')';} 1172 function build(){ 1173 var old=grid; grid=[]; 1174 for(var s=0;s<steps;s++){var row=[];for(var c=0;c<lights;c++){ 1175 if(old[s]&&old[s][c]) row.push(old[s][c]); 1176 else row.push({on:((Math.floor(s/2)+c)%2===0),color:COLORS[0][1]}); 1177 } grid.push(row);} 1178 } 1179 function paintCell(el,cell){ 1180 if(cell.on){el.style.background=hexA(cell.color,0.30);el.style.borderColor=hexA(cell.color,0.55);el.style.boxShadow='inset 0 0 6px '+hexA(cell.color,0.28);} 1181 else{el.style.background='';el.style.borderColor='';el.style.boxShadow='';} 1182 } 1183 function render(){ 1184 colsEl.style.gridTemplateColumns='repeat('+lights+',1fr)'; 1185 var h=''; 1186 for(var c=0;c<lights;c++){h+='<div class="le-colhead"><div class="le-colnum">'+(c+1)+'</div><div class="le-live" data-live="'+c+'"></div><div class="le-colname">Name</div><div class="le-colicons"><span>⚙</span><span>🗑</span></div></div>';} 1187 colsEl.innerHTML=h; 1188 var r=''; 1189 for(var st=0;st<steps;st++){ 1190 r+='<div class="le-row" data-step="'+st+'"><div class="le-rowlabel"><span class="le-rownum">'+(st+1)+'</span><span class="le-rowarrow">›</span></div><div class="le-cells" style="grid-template-columns:repeat('+lights+',1fr)">'; 1191 for(var c2=0;c2<lights;c2++){r+='<div class="le-cell" data-s="'+st+'" data-c="'+c2+'"></div>';} 1192 r+='</div></div>'; 1193 } 1194 rowsEl.innerHTML=r; 1195 liveEls=[].slice.call(colsEl.querySelectorAll('.le-live')); 1196 playingRow=null; 1197 dash.querySelectorAll('.le-cell').forEach(function(el){paintCell(el,grid[+el.dataset.s][+el.dataset.c]);}); 1198 } 1199 rowsEl.addEventListener('click',function(e){ 1200 var el=e.target.closest('.le-cell'); if(!el) return; 1201 var cell=grid[+el.dataset.s][+el.dataset.c], col=COLORS[ci][1]; 1202 if(!cell.on){cell.on=true;cell.color=col;} 1203 else if(cell.color===col){cell.on=false;} 1204 else{cell.color=col;} 1205 paintCell(el,cell); 1206 }); 1207 function setColor(d){ci=(ci+d+COLORS.length)%COLORS.length;colorNameEl.textContent=COLORS[ci][0];} 1208 dash.querySelector('#leColorPrev').addEventListener('click',function(){setColor(-1);}); 1209 dash.querySelector('#leColorNext').addEventListener('click',function(){setColor(1);}); 1210 dash.querySelectorAll('[data-ctrl]').forEach(function(b){ 1211 b.addEventListener('click',function(){ 1212 var k=b.dataset.ctrl, d=+b.dataset.d; 1213 if(k==='lights'){lights=Math.max(1,Math.min(12,lights+d));dash.querySelector('#leLights').textContent=lights;build();render();} 1214 else if(k==='steps'){steps=Math.max(4,Math.min(32,steps+d));dash.querySelector('#leSteps').textContent=steps;build();render();if(playing){restart();}} 1215 else if(k==='tempo'){tempo=Math.max(100,Math.min(1500,tempo+d*50));dash.querySelector('#leTempo').textContent=tempo;if(playing){restart();}} 1216 }); 1217 }); 1218 var playing=false, timer=null, head=0; 1219 function tick(){ 1220 if(playingRow) playingRow.classList.remove('playing'); 1221 playingRow=rowsEl.children[head]||null; if(playingRow) playingRow.classList.add('playing'); 1222 for(var c=0;c<lights;c++){ 1223 var live=liveEls[c]; if(!live) continue; 1224 var cell=grid[head][c]; 1225 if(cell.on){live.style.background=cell.color;live.style.boxShadow='0 0 8px '+cell.color+',0 0 15px '+hexA(cell.color,0.6);} 1226 else{live.style.background='';live.style.boxShadow='';} 1227 } 1228 head=(head+1)%steps; 1229 } 1230 function start(){if(playing)return;playing=true;playBtn.innerHTML='❙❙';head=0;tick();timer=setInterval(tick,Math.round(132000/tempo));} 1231 function stop(){playing=false;playBtn.innerHTML='▶';clearInterval(timer); 1232 if(playingRow){playingRow.classList.remove('playing');playingRow=null;} 1233 for(var i=0;i<liveEls.length;i++){liveEls[i].style.background='';liveEls[i].style.boxShadow='';} 1234 } 1235 function restart(){clearInterval(timer);timer=setInterval(tick,Math.round(132000/tempo));} 1236 playBtn.addEventListener('click',function(){playing?stop():start();}); 1237 build(); render(); setColor(0); 1238 1239 var modulesView=dash.querySelector('.modules-view'), lightingView=dash.querySelector('.lighting-view'); 1240 function show(lighting){ 1241 modulesView.hidden=lighting; lightingView.hidden=!lighting; 1242 if(lighting) start(); else stop(); 1243 if(window.ScrollTrigger){try{ScrollTrigger.refresh();}catch(e){}} 1244 } 1245 function activate(tab){dash.querySelectorAll('.d-tab').forEach(function(x){x.classList.remove('active');});if(tab)tab.classList.add('active');} 1246 dash.querySelectorAll('.d-tab').forEach(function(t){ 1247 t.addEventListener('click',function(){activate(t);show(t.textContent.trim().toLowerCase()==='lighting');}); 1248 }); 1249 dash.querySelectorAll('.d-card').forEach(function(card){ 1250 var h=card.querySelector('h3'); 1251 if(h && h.textContent.trim()==='Lighting'){ 1252 var m=card.querySelector('.d-modify'); 1253 if(m) m.addEventListener('click',function(){ 1254 var lt=null; dash.querySelectorAll('.d-tab').forEach(function(x){if(x.textContent.trim()==='Lighting')lt=x;}); 1255 activate(lt); show(true); 1256 }); 1257 } 1258 }); 1259})(); 1260</script>
vendor: 1 bytes, line 1260
1260
1261<script> 1262(function(){ 1263 var burger=document.getElementById('navBurger'), menu=document.getElementById('navMobile'); 1264 if(!burger||!menu) return; 1265 function close(){burger.classList.remove('open');menu.classList.remove('open');} 1266 burger.addEventListener('click',function(e){e.stopPropagation();burger.classList.toggle('open');menu.classList.toggle('open');}); 1267 menu.querySelectorAll('a').forEach(function(a){a.addEventListener('click',close);}); 1268 document.addEventListener('click',function(e){if(menu.classList.contains('open')&&!menu.contains(e.target)&&e.target!==burger&&!burger.contains(e.target))close();}); 1269})(); 1270</script>
vendor: 1 bytes, line 1270
1270
1271<script> 1272(function(){ 1273 var kg=document.getElementById('pvKeys'); 1274 if(kg){ 1275 var letters='QWERTYUIOPASDFGHJKLZXCVBNM'.split(''); 1276 var labels=['Q','W','E','R','T','Y','A','S','D','F','G','H','J','K','L','Z','X','C','V','B','N','M','â','â','Ctrl','Shift','Alt','Tab','1','2']; 1277 var keys=[]; 1278 for(var i=0;i<30;i++){ var s=document.createElement('span'); s.textContent=labels[i%labels.length]; kg.appendChild(s); keys.push(s); } 1279 var lit=-1; 1280 function hop(){ if(lit>=0) keys[lit].classList.remove('lit'); 1281 lit=Math.floor(Math.random()*keys.length); 1282 keys[lit].textContent=letters[Math.floor(Math.random()*letters.length)]; 1283 keys[lit].classList.add('lit'); } 1284 hop(); 1285 setInterval(function(){ 1286 var p=kg.closest('.hpanel'); 1287 if(p && p.classList.contains('pv-idle')) return; /* offscreen: skip */ 1288 hop(); 1289 },2600); 1290 } 1291 1292 var cf=document.getElementById('pvConfig'); 1293 if(cf){ 1294 var palette=['#2b9bff','#ff3b3b','#ffb13b','#eef2ff','#2ee06a','#9b6bff','#ff6bd6','#5cc8ff']; 1295 for(var r=0;r<6;r++){ 1296 var row=document.createElement('div'); row.className='crow '+(r%2?'r':'l'); 1297 var html=''; 1298 for(var c=0;c<10;c++){ var col=palette[(c+r)%palette.length]; html+='<i style="background:'+col+'"></i>'; } 1299 row.innerHTML=html+html; 1300 cf.appendChild(row); 1301 } 1302 } 1303 1304 /* Below 860px the five module panels stack vertically, so every one of 1305 them used to animate continuously whether onscreen or not: 26 wave 1306 bars, 8 box-shadow flashers, a spinning conic-gradient ring and 6 1307 marquee rows, all at once, forever. Park the offscreen ones. */ 1308 var panels=[].slice.call(document.querySelectorAll('.hpanel')); 1309 if(panels.length && 'IntersectionObserver' in window){ 1310 panels.forEach(function(p){ p.classList.add('pv-idle'); }); 1311 var pio=new IntersectionObserver(function(entries){ 1312 entries.forEach(function(e){ 1313 e.target.classList.toggle('pv-idle', !e.isIntersecting); 1314 }); 1315 },{rootMargin:'150px 0px'}); 1316 panels.forEach(function(p){ pio.observe(p); }); 1317 } 1318})(); 1319</script>
vendor: 1 bytes, line 1319
1319
1320<script> 1321(function(){ 1322 var viz=document.getElementById('ringViz'); if(!viz) return; 1323 var rot=document.getElementById('ringRot'), disc=document.getElementById('ringDisc'), nodesEl=document.getElementById('ringNodes'), hint=document.getElementById('ringHint'); 1324 function hideHint(){ if(hint) hint.classList.add('ring-hint-gone'); } 1325 var COLORS=['#ff3b3b','#2b9bff','#ffb13b','#eef2ff']; 1326 var GAP=12, count=2, regions=[]; 1327 function norm(a){a%=360; if(a<0)a+=360; return a;} 1328 function distribute(){ regions=[]; for(var i=0;i<count;i++) regions.push({color:COLORS[i],start:i*(360/count)}); } 1329 function renderDisc(){ 1330 var rs=regions.slice().sort(function(a,b){return a.start-b.start;}), n=rs.length, parts=[]; 1331 parts.push(rs[n-1].color+' 0deg '+rs[0].start.toFixed(2)+'deg'); 1332 for(var i=0;i<n;i++){ var a=rs[i].start, b=(i<n-1?rs[i+1].start:360); parts.push(rs[i].color+' '+a.toFixed(2)+'deg '+b.toFixed(2)+'deg'); } 1333 disc.style.background='conic-gradient('+parts.join(',')+')'; 1334 } 1335 function renderNodes(){ 1336 nodesEl.innerHTML=''; 1337 regions.forEach(function(r,i){ 1338 var node=document.createElement('div'); node.className='ring-node'; node.style.transform='rotate('+r.start+'deg)'; 1339 var dot=document.createElement('div'); dot.className='dot'; node.appendChild(dot); 1340 dot.addEventListener('mousedown',startDrag(i)); 1341 dot.addEventListener('touchstart',startDrag(i),{passive:false}); 1342 nodesEl.appendChild(node); 1343 }); 1344 } 1345 function renderAll(){ renderDisc(); renderNodes(); } 1346 1347 var SPIN=0.4; 1348 var rotation=0, speed=SPIN, target=SPIN, dragging=false, hovering=false, raf=null; 1349 function frame(){ if(!dragging){ speed+=(target-speed)*0.05; if(target===0&&speed<0.012)speed=0; rotation=norm(rotation+speed); rot.style.transform='rotate('+rotation+'deg)'; } raf=requestAnimationFrame(frame); } 1350 viz.addEventListener('mouseenter',function(){ hovering=true; target=0; }); 1351 viz.addEventListener('mouseleave',function(){ hovering=false; if(!dragging) target=SPIN; }); 1352 1353 var dragIdx=-1, moved=false, downPt=null, lowerB=0, upperB=0, lastInteract=0; 1354 function pt(ev){ var t=ev.touches&&ev.touches[0]; return {x:(t?t.clientX:ev.clientX), y:(t?t.clientY:ev.clientY)}; } 1355 function angleAt(p){ var rc=viz.getBoundingClientRect(), cx=rc.left+rc.width/2, cy=rc.top+rc.height/2; var a=Math.atan2(p.x-cx,-(p.y-cy))*180/Math.PI; return norm(a); } 1356 function startDrag(i){ return function(ev){ ev.preventDefault(); ev.stopPropagation(); hideHint(); 1357 dragIdx=i; dragging=true; speed=0; moved=false; downPt=pt(ev); 1358 1359 var cur=regions[i].start, upD=999, loD=999; lowerB=cur; upperB=cur; 1360 for(var k=0;k<regions.length;k++){ if(k===i) continue; 1361 var dCW=norm(regions[k].start-cur); if(dCW<upD){upD=dCW; upperB=regions[k].start;} 1362 var dCCW=norm(cur-regions[k].start); if(dCCW<loD){loD=dCCW; lowerB=regions[k].start;} 1363 } 1364 document.addEventListener('mousemove',onMove); document.addEventListener('mouseup',onUp); 1365 document.addEventListener('touchmove',onMove,{passive:false}); document.addEventListener('touchend',onUp); 1366 }; } 1367 function onMove(ev){ if(dragIdx<0) return; ev.preventDefault(); var p=pt(ev); 1368 if(downPt && (Math.abs(p.x-downPt.x)+Math.abs(p.y-downPt.y))>3) moved=true; 1369 var local=norm(angleAt(p)-rotation); 1370 var span=norm(upperB-lowerB); if(span===0) span=360; 1371 var rel=norm(local-lowerB); 1372 if(rel>span){ 1373 rel = (rel > (span+360)/2) ? GAP : (span-GAP); 1374 } else { 1375 rel = Math.max(GAP, Math.min(span-GAP, rel)); 1376 } 1377 var ns=norm(lowerB+rel); regions[dragIdx].start=ns; 1378 nodesEl.children[dragIdx].style.transform='rotate('+ns+'deg)'; 1379 renderDisc(); 1380 } 1381 function onUp(){ 1382 document.removeEventListener('mousemove',onMove); document.removeEventListener('mouseup',onUp); 1383 document.removeEventListener('touchmove',onMove); document.removeEventListener('touchend',onUp); 1384 if(!moved) cycle(); 1385 lastInteract=Date.now(); 1386 dragIdx=-1; dragging=false; if(!hovering) target=SPIN; 1387 } 1388 viz.addEventListener('click',function(e){ if(Date.now()-lastInteract<400) return; cycle(); }); 1389 function cycle(){ hideHint(); count=count>=4?2:count+1; distribute(); renderAll(); } 1390 1391 distribute(); renderAll(); 1392 if('IntersectionObserver' in window){ 1393 new IntersectionObserver(function(es){ if(es[0].isIntersecting){ if(!raf) raf=requestAnimationFrame(frame); } else if(raf){ cancelAnimationFrame(raf); raf=null; } },{threshold:0}).observe(viz); 1394 } else raf=requestAnimationFrame(frame); 1395})(); 1396</script>
vendor: 1 bytes, line 1396
1396
1397<script src="boosters.js"></script>
vendor: 1 bytes, line 1397
1397
1398<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"3071eb0ef69f49ad9e8d8ac6d6fbc075","r":1,"spa":2}' crossorigin="anonymous"></script>
1398 1399</body> 1400</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.