1/*! 2 * Webflow: Front-end site library 3 * @license MIT 4 * Inline scripts may access the api using an async handler: 5 * var Webflow = Webflow || []; 6 * Webflow.push(readyFunction); 7 */ 8/******/ (function(modules) { // webpackBootstrap 9/******/ // The module cache 10/******/ var installedModules = {}; 11 12/******/ // The require function 13/******/ function __webpack_require__(moduleId) { 14 15/******/ // Check if module is in cache 16/******/ if(installedModules[moduleId]) 17/******/ return installedModules[moduleId].exports; 18 19/******/ // Create a new module (and put it into the cache) 20/******/ var module = installedModules[moduleId] = { 21/******/ exports: {}, 22/******/ id: moduleId, 23/******/ loaded: false 24/******/ }; 25 26/******/ // Execute the module function 27/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 28 29/******/ // Flag the module as loaded 30/******/ module.loaded = true; 31 32/******/ // Return the exports of the module 33/******/ return module.exports; 34/******/ } 35 36 37/******/ // expose the modules object (__webpack_modules__) 38/******/ __webpack_require__.m = modules; 39 40/******/ // expose the module cache 41/******/ __webpack_require__.c = installedModules; 42 43/******/ // __webpack_public_path__ 44/******/ __webpack_require__.p = "/"; 45 46/******/ // Load entry module and return exports 47/******/ return __webpack_require__(0); 48/******/ }) 49/************************************************************************/ 50/******/ ([ 51/* 0 */ 52/***/ function(module, exports, __webpack_require__) { 53 54 __webpack_require__(5); 55 __webpack_require__(6); 56 __webpack_require__(7); 57 __webpack_require__(8); 58 __webpack_require__(9); 59 __webpack_require__(10); 60 __webpack_require__(11); 61 __webpack_require__(12); 62 __webpack_require__(1); 63 __webpack_require__(13); 64 __webpack_require__(14); 65 __webpack_require__(15); 66 __webpack_require__(16); 67 __webpack_require__(17); 68 __webpack_require__(18); 69 __webpack_require__(19); 70 module.exports = __webpack_require__(20); 71 72 73/***/ }, 74/* 1 */ 75/***/ function(module, exports, __webpack_require__) { 76 77 /* WEBPACK VAR INJECTION */(function(process) {'use strict'; 78 79 /** 80 * Webflow: Core site library 81 */ 82 83 var Webflow = {}; 84 var modules = {}; 85 var primary = []; 86 var secondary = window.Webflow || []; 87 var $ = window.jQuery; 88 var $win = $(window); 89 var $doc = $(document); 90 var isFunction = $.isFunction; 91 var _ = Webflow._ = __webpack_require__(21); 92 var tram = __webpack_require__(3) && $.tram; 93 var domready = false; 94 var destroyed = false; 95 var Modernizr = window.Modernizr; 96 tram.config.hideBackface = false; 97 tram.config.keepInherited = true; 98 99 /** 100 * Webflow.define - Define a named module 101 * @param {string} name 102 * @param {function} factory 103 * @param {object} options 104 * @return {object} 105 */ 106 Webflow.define = function(name, factory, options) { 107 if (modules[name]) unbindModule(modules[name]); 108 var instance = modules[name] = factory($, _, options) || {}; 109 bindModule(instance); 110 return instance; 111 }; 112 113 /** 114 * Webflow.require - Require a named module 115 * @param {string} name 116 * @return {object} 117 */ 118 Webflow.require = function(name) { 119 return modules[name]; 120 }; 121 122 function bindModule(module) { 123 // If running in Webflow app, subscribe to design/preview events 124 if (Webflow.env()) { 125 isFunction(module.design) && $win.on('__wf_design', module.design); 126 isFunction(module.preview) && $win.on('__wf_preview', module.preview); 127 } 128 // Subscribe to front-end destroy event 129 isFunction(module.destroy) && $win.on('__wf_destroy', module.destroy); 130 // Look for ready method on module 131 if (module.ready && isFunction(module.ready)) { 132 addReady(module); 133 } 134 } 135 136 function addReady(module) { 137 // If domready has already happened, run ready method 138 if (domready) { 139 module.ready(); 140 return; 141 } 142 // Otherwise add ready method to the primary queue (only once) 143 if (_.contains(primary, module.ready)) return; 144 primary.push(module.ready); 145 } 146 147 function unbindModule(module) { 148 // Unsubscribe module from window events 149 isFunction(module.design) && $win.off('__wf_design', module.design); 150 isFunction(module.preview) && $win.off('__wf_preview', module.preview); 151 isFunction(module.destroy) && $win.off('__wf_destroy', module.destroy); 152 // Remove ready method from primary queue 153 if (module.ready && isFunction(module.ready)) { 154 removeReady(module); 155 } 156 } 157 158 function removeReady(module) { 159 primary = _.filter(primary, function(readyFn) { 160 return readyFn !== module.ready; 161 }); 162 } 163 164 /** 165 * Webflow.push - Add a ready handler into secondary queue 166 * @param {function} ready Callback to invoke on domready 167 */ 168 Webflow.push = function(ready) { 169 // If domready has already happened, invoke handler 170 if (domready) { 171 isFunction(ready) && ready(); 172 return; 173 } 174 // Otherwise push into secondary queue 175 secondary.push(ready); 176 }; 177 178 /** 179 * Webflow.env - Get the state of the Webflow app 180 * @param {string} mode [optional] 181 * @return {boolean} 182 */ 183 Webflow.env = function(mode) { 184 var designFlag = window.__wf_design; 185 var inApp = typeof designFlag !== 'undefined'; 186 if (!mode) return inApp; 187 if (mode === 'design') return inApp && designFlag; 188 if (mode === 'preview') return inApp && !designFlag; 189 if (mode === 'slug') return inApp && window.__wf_slug; 190 if (mode === 'editor') return window.WebflowEditor; 191 if (mode === 'test') return process.env.NODE_ENV === 'test' || window.__wf_test; 192 if (mode === 'frame') return window !== window.top; 193 }; 194 195 // Feature detects + browser sniffs ಠ_ಠ196 var userAgent = navigator.userAgent.toLowerCase(); 197 var appVersion = navigator.appVersion.toLowerCase(); 198 var touch = Webflow.env.touch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch; 199 var chrome = Webflow.env.chrome = /chrome/.test(userAgent) && /Google/.test(navigator.vendor) && parseInt(appVersion.match(/chrome\/(\d+)\./)[1], 10); 200 var ios = Webflow.env.ios = Modernizr && Modernizr.ios; 201 Webflow.env.safari = /safari/.test(userAgent) && !chrome && !ios; 202 203 // Maintain current touch target to prevent late clicks on touch devices 204 var touchTarget; 205 // Listen for both events to support touch/mouse hybrid devices 206 touch && $doc.on('touchstart mousedown', function(evt) { 207 touchTarget = evt.target; 208 }); 209 210 /** 211 * Webflow.validClick - validate click target against current touch target 212 * @param {HTMLElement} clickTarget Element being clicked 213 * @return {Boolean} True if click target is valid (always true on non-touch) 214 */ 215 Webflow.validClick = touch ? function(clickTarget) { 216 return clickTarget === touchTarget || $.contains(clickTarget, touchTarget); 217 } : function() { return true; }; 218 219 /** 220 * Webflow.resize, Webflow.scroll - throttled event proxies 221 */ 222 var resizeEvents = 'resize.webflow orientationchange.webflow load.webflow';
223 var scrollEvents = 'scroll.webflow ' + resizeEvents; 224 Webflow.resize = eventProxy($win, resizeEvents); 225 Webflow.scroll = eventProxy($win, scrollEvents); 226 Webflow.redraw = eventProxy(); 227 228 // Create a proxy instance for throttled events 229 function eventProxy(target, types) { 230 231 // Set up throttled method (using custom frame-based _.throttle) 232 var handlers = []; 233 var proxy = {}; 234 proxy.up = _.throttle(function(evt) { 235 _.each(handlers, function(h) { h(evt); }); 236 }); 237 238 // Bind events to target 239 if (target && types) target.on(types, proxy.up); 240 241 /** 242 * Add an event handler 243 * @param {function} handler 244 */ 245 proxy.on = function(handler) { 246 if (typeof handler !== 'function') return; 247 if (_.contains(handlers, handler)) return; 248 handlers.push(handler); 249 }; 250 251 /** 252 * Remove an event handler 253 * @param {function} handler 254 */ 255 proxy.off = function(handler) { 256 // If no arguments supplied, clear all handlers 257 if (!arguments.length) { 258 handlers = []; 259 return; 260 } 261 // Otherwise, remove handler from the list 262 handlers = _.filter(handlers, function(h) { 263 return h !== handler; 264 }); 265 }; 266 267 return proxy; 268 } 269 270 // Webflow.location - Wrap window.location in api 271 Webflow.location = function(url) { 272 window.location = url; 273 }; 274 275 // Webflow.app - Designer-specific methods 276 Webflow.app = Webflow.env() ? {} : null; 277 if (Webflow.app) { 278 279 // Trigger redraw for specific elements 280 var redraw = new Event('__wf_redraw'); 281 Webflow.app.redrawElement = function(i, el) { el.dispatchEvent(redraw); }; 282 283 // Webflow.location - Re-route location change to trigger an event 284 Webflow.location = function(url) { 285 window.dispatchEvent(new CustomEvent('__wf_location', { detail: url })); 286 }; 287 } 288 289 // Webflow.ready - Call primary and secondary handlers 290 Webflow.ready = function() { 291 domready = true; 292 293 // Restore modules after destroy 294 if (destroyed) { 295 restoreModules(); 296 297 // Otherwise run primary ready methods 298 } else { 299 _.each(primary, callReady); 300 } 301 302 // Run secondary ready methods 303 _.each(secondary, callReady); 304 305 // Trigger resize 306 Webflow.resize.up(); 307 }; 308 309 function callReady(readyFn) { 310 isFunction(readyFn) && readyFn(); 311 } 312 313 function restoreModules() { 314 destroyed = false; 315 _.each(modules, bindModule); 316 } 317 318 /** 319 * Webflow.load - Add a window load handler that will run even if load event has already happened 320 * @param {function} handler 321 */ 322 var deferLoad; 323 Webflow.load = function(handler) { 324 deferLoad.then(handler); 325 }; 326 327 function bindLoad() { 328 // Reject any previous deferred (to support destroy) 329 if (deferLoad) { 330 deferLoad.reject(); 331 $win.off('load', deferLoad.resolve); 332 } 333 // Create deferred and bind window load event 334 deferLoad = new $.Deferred(); 335 $win.on('load', deferLoad.resolve); 336 } 337 338 // Webflow.destroy - Trigger a destroy event for all modules 339 Webflow.destroy = function(options) { 340 options = options || {}; 341 destroyed = true; 342 $win.triggerHandler('__wf_destroy'); 343 344 // Allow domready reset for tests 345 if (options.domready != null) { 346 domready = options.domready; 347 } 348 349 // Unbind modules 350 _.each(modules, unbindModule); 351 352 // Clear any proxy event handlers 353 Webflow.resize.off(); 354 Webflow.scroll.off(); 355 Webflow.redraw.off(); 356 357 // Clear any queued ready methods 358 primary = []; 359 secondary = []; 360 361 // If load event has not yet fired, replace the deferred 362 if (deferLoad.state() === 'pending') bindLoad(); 363 }; 364 365 // Listen for domready 366 $(Webflow.ready); 367 368 // Listen for window.onload and resolve deferred 369 bindLoad(); 370 371 // Export commonjs module 372 module.exports = window.Webflow = Webflow; 373 374 /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4))) 375 376/***/ }, 377/* 2 */ 378/***/ function(module, exports) { 379 380 'use strict'; 381 382 /** 383 * Webflow: IX Event triggers for other modules 384 */ 385 386 var $ = window.jQuery; 387 var api = {}; 388 var eventQueue = []; 389 var namespace = '.w-ix'; 390 391 var eventTriggers = { 392 reset: function(i, el) { 393 el.__wf_intro = null; 394 }, 395 intro: function(i, el) { 396 if (el.__wf_intro) return; 397 el.__wf_intro = true; 398 $(el).triggerHandler(api.types.INTRO); 399 }, 400 outro: function(i, el) { 401 if (!el.__wf_intro) return; 402 el.__wf_intro = null; 403 $(el).triggerHandler(api.types.OUTRO); 404 } 405 }; 406 407 api.triggers = {}; 408 409 api.types = { 410 INTRO: 'w-ix-intro' + namespace, 411 OUTRO: 'w-ix-outro' + namespace 412 }; 413 414 // Trigger any events in queue + restore trigger methods 415 api.init = function() { 416 var count = eventQueue.length; 417 for (var i = 0; i < count; i++) { 418 var memo = eventQueue[i]; 419 memo[0](0, memo[1]); 420 } 421 eventQueue = []; 422 $.extend(api.triggers, eventTriggers); 423 }; 424 425 // Replace all triggers with async wrapper to queue events until init 426 api.async = function() { 427 for (var key in eventTriggers) { 428 var func = eventTriggers[key]; 429 if (!eventTriggers.hasOwnProperty(key)) continue; 430 431 // Replace trigger method with async wrapper 432 api.triggers[key] = function(i, el) { 433 eventQueue.push([func, el]); 434 }; 435 } 436 }; 437 438 // Default triggers to async queue 439 api.async(); 440 441 module.exports = api; 442 443 444/***/ }, 445/* 3 */
446/***/ function(module, exports) { 447 448 /*! 449 * tram.js v0.8.1-global 450 * Cross-browser CSS3 transitions in JavaScript 451 * https://github.com/bkwld/tram 452 * MIT License 453 */ 454 window.tram=function(a){function b(a,b){var c=new L.Bare;return c.init(a,b)}function c(a){return a.replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()})}function d(a){var b=parseInt(a.slice(1),16),c=b>>16&255,d=b>>8&255,e=255&b;return[c,d,e]}function e(a,b,c){return"#"+(1<<24|a<<16|b<<8|c).toString(16).slice(1)}function f(){}function g(a,b){_("Type warning: Expected: ["+a+"] Got: ["+typeof b+"] "+b)}function h(a,b,c){_("Units do not match ["+a+"]: "+b+", "+c)}function i(a,b,c){if(void 0!==b&&(c=b),void 0===a)return c;var d=c;return Z.test(a)||!$.test(a)?d=parseInt(a,10):$.test(a)&&(d=1e3*parseFloat(a)),0>d&&(d=0),d===d?d:c}function j(a){for(var b=-1,c=a?a.length:0,d=[];++b<c;){var e=a[b];e&&d.push(e)}return d}var k=function(a,b,c){function d(a){return"object"==typeof a}function e(a){return"function"==typeof a}function f(){}function g(h,i){function j(){var a=new k;return e(a.init)&&a.init.apply(a,arguments),a}function k(){}i===c&&(i=h,h=Object),j.Bare=k;var l,m=f[a]=h[a],n=k[a]=j[a]=new f;return n.constructor=j,j.mixin=function(b){return k[a]=j[a]=g(j,b)[a],j},j.open=function(a){if(l={}
454,e(a)?l=a.call(j,n,m,j,h):d(a)&&(l=a),d(l))for(var c in l)b.call(l,c)&&(n[c]=l[c]);return e(n.init)||(n.init=h),j},j.open(i)}return g}("prototype",{}.hasOwnProperty),l={ease:["ease",function(a,b,c,d){var e=(a/=d)*a,f=e*a;return b+c*(-2.75*f*e+11*e*e+-15.5*f+8*e+.25*a)}],"ease-in":["ease-in",function(a,b,c,d){var e=(a/=d)*a,f=e*a;return b+c*(-1*f*e+3*e*e+-3*f+2*e)}],"ease-out":["ease-out",function(a,b,c,d){var e=(a/=d)*a,f=e*a;return b+c*(.3*f*e+-1.6*e*e+2.2*f+-1.8*e+1.9*a)}],"ease-in-out":["ease-in-out",function(a,b,c,d){var e=(a/=d)*a,f=e*a;return b+c*(2*f*e+-5*e*e+2*f+2*e)}],linear:["linear",function(a,b,c,d){return c*a/d+b}],"ease-in-quad":["cubic-bezier(0.550, 0.085, 0.680, 0.530)",function(a,b,c,d){return c*(a/=d)*a+b}],"ease-out-quad":["cubic-bezier(0.250, 0.460, 0.450, 0.940)",function(a,b,c,d){return-c*(a/=d)*(a-2)+b}],"ease-in-out-quad":["cubic-bezier(0.455, 0.030, 0.515, 0.955)",function(a,b,c,d){return(a/=d/2)<1?c/2*a*a+b:-c/2*(--a*(a-2)-1)+b}],"ease-in-cubic":["cubic-bezier(0.550, 0.055, 0.675, 0.190)",function(a,b,c,d){return c*(a/=d)*a*a+b}],"ease-out-cubic":["cubic-bezier(0.215, 0.610, 0.355, 1)",function(a,b,c,d){return c*((a=a/d-1)*a*a+1)+b}],"ease-in-out-cubic":["cubic-bezier(0.645, 0.045, 0.355, 1)",function(a,b,c,d){return(a/=d/2)<1?c/2*a*a*a+b:c/2*((a-=2)*a*a+2)+b}],"ease-in-quart":["cubic-bezier(0.895, 0.030, 0.685, 0.220)",function(a,b,c,d){return c*(a/=d)*a*a*a+b}],"ease-out-quart":["cubic-bezier(0.165, 0.840, 0.440, 1)",function(a,b,c,d){return-c*((a=a/d-1)*a*a*a-1)+b}],"ease-in-out-quart":["cubic-bezier(0.770, 0, 0.175, 1)",function(a,b,c,d){return(a/=d/2)<1?c/2*a*a*a*a+b:-c/2*((a-=2)*a*a*a-2)+b}],"ease-in-quint":["cubic-bezier(0.755, 0.050, 0.855, 0.060)",function(a,b,c,d){return c*(a/=d)*a*a*a*a+b}],"ease-out-quint":["cubic-bezier(0.230, 1, 0.320, 1)",function(a,b,c,d){return c*((a=a/d-1)*a*a*a*a+1)+b}],"ease-in-out-quint":["cubic-bezier(0.860, 0, 0.070, 1)",function(a,b,c,d){return(a/=d/2)<1?c/2*a*a*a*a*a+b:c/2*((a-=2)*a*a*a*a+2)+b}],"ease-in-sine":["cubic-bezier(0.470, 0, 0.745, 0.715)",function(a,b,c,d){return-c*Math.cos(a/d*(Math.PI/2))+c+b}],"ease-out-sine":["cubic-bezier(0.390, 0.575, 0.565, 1)",function(a,b,c,d){return c*Math.sin(a/d*(Math.PI/2))+b}],"ease-in-out-sine":["cubic-bezier(0.445, 0.050, 0.550, 0.950)",function(a,b,c,d){return-c/2*(Math.cos(Math.PI*a/d)-1)+b}],"ease-in-expo":["cubic-bezier(0.950, 0.050, 0.795, 0.035)",function(a,b,c,d){return 0===a?b:c*Math.pow(2,10*(a/d-1))+b}],"ease-out-expo":["cubic-bezier(0.190, 1, 0.220, 1)",function(a,b,c,d){return a===d?b+c:c*(-Math.pow(2,-10*a/d)+1)+b}],"ease-in-out-expo":["cubic-bezier(1, 0, 0, 1)",function(a,b,c,d){return 0===a?b:a===d?b+c:(a/=d/2)<1?c/2*Math.pow(2,10*(a-1))+b:c/2*(-Math.pow(2,-10*--a)+2)+b}],"ease-in-circ":["cubic-bezier(0.600, 0.040, 0.980, 0.335)",function(a,b,c,d){return-c*(Math.sqrt(1-(a/=d)*a)-1)+b}],"ease-out-circ":["cubic-bezier(0.075, 0.820, 0.165, 1)",function(a,b,c,d){return c*Math.sqrt(1-(a=a/d-1)*a)+b}],"ease-in-out-circ":["cubic-bezier(0.785, 0.135, 0.150, 0.860)",function(a,b,c,d){return(a/=d/2)<1?-c/2*(Math.sqrt(1-a*a)-1)+b:c/2*(Math.sqrt(1-(a-=2)*a)+1)+b}],"ease-in-back":["cubic-bezier(0.600, -0.280, 0.735, 0.045)",function(a,b,c,d,e){return void 0===e&&(e=1.70158),c*(a/=d)*a*((e+1)*a-e)+b}],"ease-out-back":["cubic-bezier(0.175, 0.885, 0.320, 1.275)",function(a,b,c,d,e){return void 0===e&&(e=1.70158),c*((a=a/d-1)*a*((e+1)*a+e)+1)+b}],"ease-in-out-back":["cubic-bezier(0.680, -0.550, 0.265, 1.550)",function(a,b,c,d,e){return void 0===e&&(e=1.70158),(a/=d/2)<1?c/2*a*a*(((e*=1.525)+1)*a-e)+b:c/2*((a-=2)*a*(((e*=1.525)+1)*a+e)+2)+b}]},m={"ease-in-back":"cubic-bezier(0.600, 0, 0.735, 0.045)","ease-out-back":"cubic-bezier(0.175, 0.885, 0.320, 1)","ease-in-out-back":"cubic-bezier(0.680, 0, 0.265, 1)"},n=document,o=window,p="bkwld-tram",q=/[\-\.0-9]/g,r=/[A-Z]/,s="number",t=/^(rgb|#)/,u=/(em|cm|mm|in|pt|pc|px)$/,v=/(em|cm|mm|in|pt|pc|px|%)$/,w=/(deg|rad|turn)$/,x="unitless",y=/(all|none) 0s ease 0s/,z=/^(width|height)$/,A=" ",B=n.createElement("a"),C=["Webkit","Moz","O","ms"],D=["-webkit-","-moz-","-o-","-ms-"],E=function(a){if
454(a in B.style)return{dom:a,css:a};var b,c,d="",e=a.split("-");for(b=0;b<e.length;b++)d+=e[b].charAt(0).toUpperCase()+e[b].slice(1);for(b=0;b<C.length;b++)if(c=C[b]+d,c in B.style)return{dom:c,css:D[b]+a}},F=b.support={bind:Function.prototype.bind,transform:E("transform"),transition:E("transition"),backface:E("backface-visibility"),timing:E("transition-timing-function")};if(F.transition){var G=F.timing.dom;if(B.style[G]=l["ease-in-back"][0],!B.style[G])for(var H in m)l[H][0]=m[H]}var I=b.frame=function(){var a=o.requestAnimationFrame||o.webkitRequestAnimationFrame||o.mozRequestAnimationFrame||o.oRequestAnimationFrame||o.msRequestAnimationFrame;return a&&F.bind?a.bind(o):function(a){o.setTimeout(a,16)}}(),J=b.now=function(){var a=o.performance,b=a&&(a.now||a.webkitNow||a.msNow||a.mozNow);return b&&F.bind?b.bind(a):Date.now||function(){return+new Date}}(),K=k(function(b){function d(a,b){var c=j((""+a).split(A)),d=c[0];b=b||{};var e=X[d];if(!e)return _("Unsupported property: "+d);if(!b.weak||!this.props[d]){var f=e[0],g=this.props[d];return g||(g=this.props[d]=new f.Bare),g.init(this.$el,c,e,b),g}}function e(a,b,c){if(a){var e=typeof a;if(b||(this.timer&&this.timer.destroy(),this.queue=[],this.active=!1),"number"==e&&b)return this.timer=new R({duration:a,context:this,complete:h}),void(this.active=!0);if("string"==e&&b){switch(a){case"hide":n.call(this);break;case"stop":k.call(this);break;case"redraw":o.call(this);break;default:d.call(this,a,c&&c[1])}return h.call(this)}if("function"==e)return void a.call(this,this);if("object"==e){var f=0;t.call(this,a,function(a,b){a.span>f&&(f=a.span),a.stop(),a.animate(b)},function(a){"wait"in a&&(f=i(a.wait,0))}),s.call(this),f>0&&(this.timer=new R({duration:f,context:this}),this.active=!0,b&&(this.timer.complete=h));var g=this,j=!1,l={};I(function(){t.call(g,a,function(a){a.active&&(j=!0,l[a.name]=a.nextStyle)}),j&&g.$el.css(l)})}}}function f(a){a=i(a,0),this.active?this.queue.push({options:a}):(this.timer=new R({duration:a,context:this,complete:h}),this.active=!0)}function g(a){return this.active?(this.queue.push({options:a,args:arguments}),void(this.timer.complete=h)):_("No active transition timer. Use start() or wait() before then().")}function h(){if(this.timer&&this.timer.destroy(),this.active=!1,this.queue.length){var a=this.queue.shift();e.call(this,a.options,!0,a.args)}}function k(a){this.timer&&this.timer.destroy(),this.queue=[],this.active=!1;var b;"string"==typeof a?(b={},b[a]=1):b="object"==typeof a&&null!=a?a:this.props,t.call(this,b,u),s.call(this)}function l(a){k.call(this,a),t.call(this,a,v,w)}function m(a){"string"!=typeof a&&(a="block"),this.el.style.display=a}function n(){k.call(this),this.el.style.display="none"}function o(){this.el.offsetHeight}function q(){k.call(this),a.removeData(this.el,p),this.$el=this.el=null}function s(){var a,b,c=[];this.upstream&&c.push(this.upstream);for(a in this.props)b=this.props[a],b.active&&c.push(b.string);c=c.join(","),this.style!==c&&(this.style=c,this.el.style[F.transition.dom]=c)}function t(a,b,e){var f,g,h,i,j=b!==u,k={};for(f in a)h=a[f],f in Y?(k.transform||(k.transform={}),k.transform[f]=h):(r.test(f)&&(f=c(f)),f in X?k[f]=h:(i||(i={}),i[f]=h));for(f in k){if(h=k[f],g=this.props[f],!g){if(!j)continue;g=d.call(this,f)}b.call(this,g,h)}e&&i&&e.call(this,i)}function u(a){a.stop()}function v(a,b){a.set(b)}function w(a){this.$el.css(a)}function x(a,c){b[a]=function(){return this.children?z.call(this,c,arguments):(this.el&&c.apply(this,arguments),this)}}function z(a,b){var c,d=this.children.length;for(c=0;d>c;c++)a.apply(this.children[c],b);return this}b.init=function(b){if(this.$el=a(b),this.el=this.$el[0],this.props={},this.queue=[],this.style="",this.active=!1,T.keepInherited&&!T.fallback){var c=V(this.el,"transition");c&&!y.test(c)&&(this.upstream=c)}F.backface&&T.hideBackface&&U(this.el,F.backface.css,"hidden")},x("add",d),x("start",e),x("wait",f),x("then",g),x("next",h),x("stop",k),x("set",l),x("show",m),x("hide",n),x("redraw",o),x("destroy",q)}),L=k(K,function(b){function c(b,c){var d=a.data(b,p)||a.data(b,p,new K.Bare);return d.el||d.init(b),c?d.start(c):d}b.init=function(b,d){var e=a(b);if(!e.length)return this;if(1===e.length)return c(e[0],d);var f=[];return e.each(function(a,b){f.push(c(b,d))}),this.children=f,this}}),M=k(function(a){function b(){var a=this.get();this.update("auto");var b=this.get();return this.update(a),b}function c(a,b,c){return void 0!==b&&(c=b),a in l?a:c}function d(a){var b=/rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(a);return(b?e(b[1],b[2],b[3]):a).replace(/#(\w)(\w)(\w)$/,"#$1$1$2$2$3$3")}var f={duration:500,ease:"ease",delay:0};a.init=function(a,b,d,e){this.$el=a,this.el=a[0];var g=b[0];d[2]&&(g=d[2]),W[g]&&(g=W[g]),this.name=g,this.type=d[1],this.duration=i(b[1],this.duration,f.duration),this.ease=c(b[2],this.ease,f.ease),this.delay=i(b[3],this.delay,f.delay),this.span=this.duration+this.delay,this.active=!1,this.nextStyle=null,this.auto=z.test(this.name),this.unit=e.unit||this.unit||T.defaultUnit,this.angle=e.angle||this.angle||T.defaultAngle,T.fallback||e.fallback?this.animate=this.fallback:(this.animate=this.transition,this.string=this.name+A+this.duration+"ms"+("ease"!=this.ease?A+l[this.ease][0]:"")+(this.delay?A+this.delay+"ms":""))},a.set=function(a){a=this.convert(a,this.type),this.update(a),this.redraw()},a.transition=function(a){this.active=!0,a=this.convert(a,this.type),this.auto&&("auto"==this.el.style[this.name]&&(this.update(this.get()),this.redraw()),"auto"==a&&(a=b.call(this))),this.nextStyle=a},a.fallback=function(a){var c=this.el.style[this.name]||this.convert(this.get(),this.type);a=this.convert(a,this.type),this.auto&&("auto"==c&&(c=this.convert(this.get(),this.type)),"auto"==a&&(a=b.call(this))),this.tween=new Q({from:c,to:a,duration:this.duration,delay:this.delay,ease:this.ease,update:this.update,context:this})},a.get=function(){return V(this.el,this.name)},a.update=function(a){U(this.el,this.name,a)},a.stop=function(){(this.active||this.nextStyle)&&(this.active=!1,this.nextStyle=null,U(this.el,this.name,this.get()));var a=this.tween;a&&a.context&&a.destroy()},a.convert=function(a,b){if("auto"==a&&this.auto)return a;var c,e="number"==typeof a,f="string"==typeof a;switch(b){case s:if(e)return a;
454if(f&&""===a.replace(q,""))return+a;c="number(unitless)";break;case t:if(f){if(""===a&&this.original)return this.original;if(b.test(a))return"#"==a.charAt(0)&&7==a.length?a:d(a)}c="hex or rgb string";break;case u:if(e)return a+this.unit;if(f&&b.test(a))return a;c="number(px) or string(unit)";break;case v:if(e)return a+this.unit;if(f&&b.test(a))return a;c="number(px) or string(unit or %)";break;case w:if(e)return a+this.angle;if(f&&b.test(a))return a;c="number(deg) or string(angle)";break;case x:if(e)return a;if(f&&v.test(a))return a;c="number(unitless) or string(unit or %)"}return g(c,a),a},a.redraw=function(){this.el.offsetHeight}}),N=k(M,function(a,b){a.init=function(){b.init.apply(this,arguments),this.original||(this.original=this.convert(this.get(),t))}}),O=k(M,function(a,b){a.init=function(){b.init.apply(this,arguments),this.animate=this.fallback},a.get=function(){return this.$el[this.name]()},a.update=function(a){this.$el[this.name](a)}}),P=k(M,function(a,b){function c(a,b){var c,d,e,f,g;for(c in a)f=Y[c],e=f[0],d=f[1]||c,g=this.convert(a[c],e),b.call(this,d,g,e)}a.init=function(){b.init.apply(this,arguments),this.current||(this.current={},Y.perspective&&T.perspective&&(this.current.perspective=T.perspective,U(this.el,this.name,this.style(this.current)),this.redraw()))},a.set=function(a){c.call(this,a,function(a,b){this.current[a]=b}),U(this.el,this.name,this.style(this.current)),this.redraw()},a.transition=function(a){var b=this.values(a);this.tween=new S({current:this.current,values:b,duration:this.duration,delay:this.delay,ease:this.ease});var c,d={};for(c in this.current)d[c]=c in b?b[c]:this.current[c];this.active=!0,this.nextStyle=this.style(d)},a.fallback=function(a){var b=this.values(a);this.tween=new S({current:this.current,values:b,duration:this.duration,delay:this.delay,ease:this.ease,update:this.update,context:this})},a.update=function(){U(this.el,this.name,this.style(this.current))},a.style=function(a){var b,c="";for(b in a)c+=b+"("+a[b]+") ";return c},a.values=function(a){var b,d={};return c.call(this,a,function(a,c,e){d[a]=c,void 0===this.current[a]&&(b=0,~a.indexOf("scale")&&(b=1),this.current[a]=this.convert(b,e))}),d}}),Q=k(function(b){function c(a){1===n.push(a)&&I(g)}function g(){var a,b,c,d=n.length;if(d)for(I(g),b=J(),a=d;a--;)c=n[a],c&&c.render(b)}function i(b){var c,d=a.inArray(b,n);d>=0&&(c=n.slice(d+1),n.length=d,c.length&&(n=n.concat(c)))}function j(a){return Math.round(a*o)/o}function k(a,b,c){return e(a[0]+c*(b[0]-a[0]),a[1]+c*(b[1]-a[1]),a[2]+c*(b[2]-a[2]))}var m={ease:l.ease[1],from:0,to:1};b.init=function(a){this.duration=a.duration||0,this.delay=a.delay||0;var b=a.ease||m.ease;l[b]&&(b=l[b][1]),"function"!=typeof b&&(b=m.ease),this.ease=b,this.update=a.update||f,this.complete=a.complete||f,this.context=a.context||this,this.name=a.name;var c=a.from,d=a.to;void 0===c&&(c=m.from),void 0===d&&(d=m.to),this.unit=a.unit||"","number"==typeof c&&"number"==typeof d?(this.begin=c,this.change=d-c):this.format(d,c),this.value=this.begin+this.unit,this.start=J(),a.autoplay!==!1&&this.play()},b.play=function(){this.active||(this.start||(this.start=J()),this.active=!0,c(this))},b.stop=function(){this.active&&(this.active=!1,i(this))},b.render=function(a){var b,c=a-this.start;if(this.delay){if(c<=this.delay)return;c-=this.delay}if(c<this.duration){var d=this.ease(c,0,1,this.duration);return b=this.startRGB?k(this.startRGB,this.endRGB,d):j(this.begin+d*this.change),this.value=b+this.unit,void this.update.call(this.context,this.value)}b=this.endHex||this.begin+this.change,this.value=b+this.unit,this.update.call(this.context,this.value),this.complete.call(this.context),this.destroy()},b.format=function(a,b){if(b+="",a+="","#"==a.charAt(0))return this.startRGB=d(b),this.endRGB=d(a),this.endHex=a,this.begin=0,void(this.change=1);if(!this.unit){var c=b.replace(q,""),e=a.replace(q,"");c!==e&&h("tween",b,a),this.unit=c}b=parseFloat(b),a=parseFloat(a),this.begin=this.value=b,this.change=a-b},b.destroy=function(){this.stop(),this.context=null,this.ease=this.update=this.complete=f};var n=[],o=1e3}),R=k(Q,function(a){a.init=function(a){this.duration=a.duration||0,this.complete=a.complete||f,this.context=a.context,this.play()},a.render=function(a){var b=a-this.start;b<this.duration||(this.complete.call(this.context),this.destroy())}}),S=k(Q,function(a,b){a.init=function(a){this.context=a.context,this.update=a.update,this.tweens=[],this.current=a.current;var b,c;for(b in a.values)c=a.values[b],this.current[b]!==c&&this.tweens.push(new Q({name:b,from:this.current[b],to:c,duration:a.duration,delay:a.delay,ease:a.ease,autoplay:!1}));this.play()},a.render=function(a){var b,c,d=this.tweens.length,e=!1;for(b=d;b--;)c=this.tweens[b],c.context&&(c.render(a),this.current[c.name]=c.value,e=!0);return e?void(this.update&&this.update.call(this.context)):this.destroy()},a.destroy=function(){if(b.destroy.call(this),this.tweens){var a,c=this.tweens.length;for(a=c;a--;)this.tweens[a].destroy();this.tweens=null,this.current=null}}}),T=b.config={defaultUnit:"px",defaultAngle:"deg",keepInherited:!1,hideBackface:!1,perspective:"",fallback:!F.transition,agentTests:[]};
454b.fallback=function(a){if(!F.transition)return T.fallback=!0;T.agentTests.push("("+a+")");var b=new RegExp(T.agentTests.join("|"),"i");T.fallback=b.test(navigator.userAgent)},b.fallback("6.0.[2-5] Safari"),b.tween=function(a){return new Q(a)},b.delay=function(a,b,c){return new R({complete:b,duration:a,context:c})},a.fn.tram=function(a){return b.call(null,this,a)};var U=a.style,V=a.css,W={transform:F.transform&&F.transform.css},X={color:[N,t],background:[N,t,"background-color"],"outline-color":[N,t],"border-color":[N,t],"border-top-color":[N,t],"border-right-color":[N,t],"border-bottom-color":[N,t],"border-left-color":[N,t],"border-width":[M,u],"border-top-width":[M,u],"border-right-width":[M,u],"border-bottom-width":[M,u],"border-left-width":[M,u],"border-spacing":[M,u],"letter-spacing":[M,u],margin:[M,u],"margin-top":[M,u],"margin-right":[M,u],"margin-bottom":[M,u],"margin-left":[M,u],padding:[M,u],"padding-top":[M,u],"padding-right":[M,u],"padding-bottom":[M,u],"padding-left":[M,u],"outline-width":[M,u],opacity:[M,s],top:[M,v],right:[M,v],bottom:[M,v],left:[M,v],"font-size":[M,v],"text-indent":[M,v],"word-spacing":[M,v],width:[M,v],"min-width":[M,v],"max-width":[M,v],height:[M,v],"min-height":[M,v],"max-height":[M,v],"line-height":[M,x],"scroll-top":[O,s,"scrollTop"],"scroll-left":[O,s,"scrollLeft"]},Y={};F.transform&&(X.transform=[P],Y={x:[v,"translateX"],y:[v,"translateY"],rotate:[w],rotateX:[w],rotateY:[w],scale:[s],scaleX:[s],scaleY:[s],skew:[w],skewX:[w],skewY:[w]}),F.transform&&F.backface&&(Y.z=[v,"translateZ"],Y.rotateZ=[w],Y.scaleZ=[s],Y.perspective=[u]);var Z=/ms/,$=/s|\./,_=function(){var a="warn",b=window.console;return b&&b[a]?function(c){b[a](c)}:f}();return a.tram=b}(window.jQuery); 455 456 457/***/ }, 458/* 4 */ 459/***/ function(module, exports) { 460 461 // shim for using process in browser 462 463 var process = module.exports = {}; 464 var queue = []; 465 var draining = false; 466 var currentQueue; 467 var queueIndex = -1; 468 469 function cleanUpNextTick() { 470 draining = false; 471 if (currentQueue.length) { 472 queue = currentQueue.concat(queue); 473 } else { 474 queueIndex = -1; 475 } 476 if (queue.length) { 477 drainQueue(); 478 } 479 } 480 481 function drainQueue() { 482 if (draining) { 483 return; 484 } 485 var timeout = setTimeout(cleanUpNextTick); 486 draining = true; 487 488 var len = queue.length; 489 while(len) { 490 currentQueue = queue; 491 queue = []; 492 while (++queueIndex < len) { 493 if (currentQueue) { 494 currentQueue[queueIndex].run(); 495 } 496 } 497 queueIndex = -1; 498 len = queue.length; 499 } 500 currentQueue = null; 501 draining = false; 502 clearTimeout(timeout); 503 } 504 505 process.nextTick = function (fun) { 506 var args = new Array(arguments.length - 1); 507 if (arguments.length > 1) { 508 for (var i = 1; i < arguments.length; i++) { 509 args[i - 1] = arguments[i]; 510 } 511 } 512 queue.push(new Item(fun, args)); 513 if (queue.length === 1 && !draining) { 514 setTimeout(drainQueue, 0); 515 } 516 }; 517 518 // v8 likes predictible objects 519 function Item(fun, array) { 520 this.fun = fun; 521 this.array = array; 522 } 523 Item.prototype.run = function () { 524 this.fun.apply(null, this.array); 525 }; 526 process.title = 'browser'; 527 process.browser = true; 528 process.env = {}; 529 process.argv = []; 530 process.version = ''; // empty string to avoid regexp issues 531 process.versions = {}; 532 533 function noop() {} 534 535 process.on = noop; 536 process.addListener = noop; 537 process.once = noop; 538 process.off = noop; 539 process.removeListener = noop; 540 process.removeAllListeners = noop; 541 process.emit = noop; 542 543 process.binding = function (name) { 544 throw new Error('process.binding is not supported'); 545 }; 546 547 process.cwd = function () { return '/' }; 548 process.chdir = function (dir) { 549 throw new Error('process.chdir is not supported'); 550 }; 551 process.umask = function() { return 0; }; 552 553 554/***/ }, 555/* 5 */ 556/***/ function(module, exports, __webpack_require__) { 557 558 'use strict'; 559 560 /** 561 * Webflow: Background Video component 562 */ 563 564 var Webflow = __webpack_require__(1); 565 566 Webflow.define('backgroundVideo', module.exports = function ($, _) { 567 var namespace = '.w-background-video'; 568 var doc = $(document); 569 570 function ready () { 571 var backgroundVideoNodes = $(document).find('.w-background-video'); 572 if (backgroundVideoNodes.length === 0) { 573 return; 574 } 575 576 backgroundVideoNodes.each(function (_, node) { 577 $(node).prepend(createVideoNode(node)); 578 }); 579 } 580 581 function createVideoNode (nativeNode) { 582 var nodeData = nativeNode.dataset; 583 584 if (!nodeData.videoUrls) { 585 return $('<video />
585'); 586 } 587 588 // Prevent loading the videos on mobile browsers as its likely that they 589 // are on low-bandwidth connections. 590 if (Webflow.isMobile()) { 591 return $('<video />').css('background-image', 'url(' + nodeData.posterUrl + ')'); 592 } 593 594 var videoURLs = nodeData.videoUrls.split(','); 595 var sourceNodes = videoURLs.map(function (url) { 596 return $('<source />').attr({ 597 src: url, 598 'data-wf-ignore': '', 599 }); 600 }); 601 602 var videoNode = $('<video />').attr({ 603 autoplay: nodeData.autoplay, 604 loop: nodeData.loop, 605 }) 606 .css('background-image', 'url(' + nodeData.posterUrl + ')'); 607 608 videoNode.append(sourceNodes); 609 610 return videoNode; 611 } 612 613 return { ready: ready }; 614 }); 615 616 617/***/ }, 618/* 6 */ 619/***/ function(module, exports, __webpack_require__) { 620 621 'use strict'; 622 623 /** 624 * Webflow: Brand pages on the subdomain 625 */ 626 627 var Webflow = __webpack_require__(1); 628 629 Webflow.define('brand', module.exports = function($, _) { 630 var api = {}; 631 var $html = $('html'); 632 var $body = $('body'); 633 var location = window.location; 634 var inApp = Webflow.env(); 635 636 // ----------------------------------- 637 // Module methods 638 639 api.ready = function() { 640 var doBranding = $html.attr('data-wf-status'); 641 var publishedDomain = $html.attr('data-wf-domain') || ''; 642 643 if (/\.webflow\.io$/i.test(publishedDomain) && location.hostname !== publishedDomain) { 644 doBranding = true; 645 } 646 647 if (doBranding) { 648 var $branding = $('<div></div>'); 649 var $link = $('<a></a>'); 650 $link.attr('href', 'http://webflow.com?utm_campaign=brandjs'); 651 652 $branding.css({ 653 position: 'fixed', 654 bottom: 0, 655 right: 0, 656 borderTopLeftRadius: '5px', 657 backgroundColor: '#2b3239', 658 padding: '8px 12px 5px 15px', 659 fontFamily: 'Arial', 660 fontSize: '10px', 661 textTransform: 'uppercase', 662 opacity: '0', 663 transition: 'opacity 0.50s ease-in-out' 664 }); 665 666 $link.css({ 667 color: '#AAADB0', 668 textDecoration: 'none' 669 }); 670 671 var $webflowLogo = $('<img>'); 672 $webflowLogo.attr('src', 'https://daks2k3a4ib2z.cloudfront.net/54153e6a3d25f2755b1f14ed/5445a4b1944ecdaa4df86d3e_subdomain-brand.svg'); 673 $webflowLogo.css({ 674 opacity: 0.9, 675 width: '57px', 676 verticalAlign: 'middle', 677 paddingLeft: '4px', 678 paddingBottom: '3px' 679 }); 680 681 $branding.text('Built with'); 682 $branding.append($webflowLogo); 683 $link.append($branding); 684 685 $body.append($link); 686 687 if (/PhantomJS/.test(window.navigator.userAgent)) { 688 return; 689 } 690 691 $branding.css({ 692 opacity: '1.0' 693 }); 694 } 695 }; 696 697 // Export module 698 return api; 699 }); 700 701 702/***/ }, 703/* 7 */ 704/***/ function(module, exports, __webpack_require__) { 705 706 'use strict'; 707 708 /** 709 * Webflow: Dropdown component 710 */ 711 712 var Webflow = __webpack_require__(1); 713 var IXEvents = __webpack_require__(2); 714 715 Webflow.define('dropdown', module.exports = function($, _) { 716 var api = {}; 717 var $doc = $(document); 718 var $dropdowns; 719 var designer; 720 var inApp = Webflow.env(); 721 var touch = Webflow.env.touch; 722 var namespace = '.w-dropdown'; 723 var stateOpen = 'w--open'; 724 var closeEvent = 'w-close' + namespace; 725 var ix = IXEvents.triggers; 726 727 // ----------------------------------- 728 // Module methods 729 730 api.ready = api.design = api.preview = init; 731 732 // ----------------------------------- 733 // Private methods 734 735 function init() { 736 designer = inApp && Webflow.env('design'); 737 738 // Find all instances on the page 739 $dropdowns = $doc.find(namespace); 740 $dropdowns.each(build); 741 } 742 743 function build(i, el) { 744 var $el = $(el); 745 746 // Store state in data 747 var data = $.data(el, namespace); 748 if (!data) data = $.data(el, namespace, { open: false, el: $el, config: {} }); 749 data.list = $el.children('.w-dropdown-list'); 750 data.toggle = $el.children('.w-dropdown-toggle'); 751 data.links = data.list.children('.w-dropdown-link'); 752 data.outside = outside(data); 753 data.complete = complete(data); 754 data.leave = leave(data); 755 756 // Remove old events 757 $el.off(namespace); 758 data.toggle.off(namespace); 759 760 // Set config from data attributes 761 configure(data); 762 763 if (data.nav) data.nav.off(namespace); 764 data.nav = $el.closest('.w-nav'); 765 data.nav.on(closeEvent, handler(data)); 766 767 // Add events based on mode 768 if (designer) { 769 $el.on('setting' + namespace, handler(data)); 770 } else { 771 data.toggle.on('tap' + namespace, toggle(data)); 772 if (data.config.hover) { 773 data.toggle.on('mouseenter' + namespace, enter(data)); 774 } 775 $el.on(closeEvent, handler(data)); 776 // Close in preview mode 777 inApp && close(data); 778 } 779 } 780 781 function configure(data) { 782 data.config = { 783 hover: Boolean(data.el.attr('data-hover')) && !touch, 784 delay: Number(data.el.attr('data-delay')) || 0 785 }; 786 } 787 788 function handler(data) { 789 return function(evt, options) { 790 options = options || {}; 791 792 if (evt.type === 'w-close') { 793 return close(data); 794 } 795 796 if (evt.type === 'setting') { 797 configure(data); 798 options.open === true && open(data, true); 799 options.open === false && close(data, true); 800 return; 801 } 802 }; 803 } 804 805 function toggle(data) { 806 return _.debounce(function() { 807 data.open ? close(data) : open(data); 808 }); 809 } 810 811 function open(data) { 812 if (data.open) return; 813 closeOthers(data); 814 data.open = true; 815 data.list.addClass(stateOpen); 816 data.toggle.addClass(stateOpen); 817 ix.intro(0, data.el[0]); 818 Webflow.redraw.up(); 819 820 // Listen for tap outside events 821 if (!designer) $doc.on('tap' + namespace, data.outside); 822 if (data.hovering) data.el.on('mouseleave' + namespace, data.leave); 823 824 // Clear previous delay 825 window.clearTimeout(data.delayId); 826 } 827 828 function close(data, immediate) { 829 if (!data.open) return; 830
831 // Do not close hover-based menus if currently hovering 832 if (data.config.hover && data.hovering) return; 833 834 data.open = false; 835 var config = data.config; 836 ix.outro(0, data.el[0]); 837 838 // Stop listening for tap outside events 839 $doc.off('tap' + namespace, data.outside); 840 data.el.off('mouseleave' + namespace, data.leave); 841 842 // Clear previous delay 843 window.clearTimeout(data.delayId); 844 845 // Skip delay during immediate 846 if (!config.delay || immediate) return data.complete(); 847 848 // Optionally wait for delay before close 849 data.delayId = window.setTimeout(data.complete, config.delay); 850 } 851 852 function closeOthers(data) { 853 var self = data.el[0]; 854 $dropdowns.each(function(i, other) { 855 var $other = $(other); 856 if ($other.is(self) || $other.has(self).length) return; 857 $other.triggerHandler(closeEvent); 858 }); 859 } 860 861 function outside(data) { 862 // Unbind previous tap handler if it exists 863 if (data.outside) $doc.off('tap' + namespace, data.outside); 864 865 // Close menu when tapped outside 866 return _.debounce(function(evt) { 867 if (!data.open) return; 868 var $target = $(evt.target); 869 if ($target.closest('.w-dropdown-toggle').length) return; 870 if (!data.el.is($target.closest(namespace))) { 871 close(data); 872 } 873 }); 874 } 875 876 function complete(data) { 877 return function() { 878 data.list.removeClass(stateOpen); 879 data.toggle.removeClass(stateOpen); 880 }; 881 } 882 883 function enter(data) { 884 return function() { 885 data.hovering = true; 886 open(data); 887 }; 888 } 889 890 function leave(data) { 891 return function() { 892 data.hovering = false; 893 close(data); 894 }; 895 } 896 897 // Export module 898 return api; 899 }); 900 901 902/***/ }, 903/* 8 */ 904/***/ function(module, exports, __webpack_require__) { 905 906 'use strict'; 907 908 /** 909 * Webflow: Editor loader 910 */ 911 912 var Webflow = __webpack_require__(1); 913 914 Webflow.define('edit', module.exports = function($, _, options) { 915 options = options || {}; 916 917 // Exit early in test env or when inside an iframe 918 if (Webflow.env('test') || Webflow.env('frame')) { 919 // Allow test fixtures to continue 920 if (!options.fixture) { 921 return {exit: 1}; 922 } 923 } 924 925 var api = {}; 926 var $win = $(window); 927 var $html = $(document.documentElement); 928 var location = document.location; 929 var hashchange = 'hashchange'; 930 var loaded; 931 var loadEditor = options.load || load; 932 var hasLocalStorage = false; 933 934 try { 935 // Check localStorage for editor data 936 hasLocalStorage = localStorage && localStorage.getItem && localStorage.getItem('WebflowEditor'); 937 } catch (e) { 938 // SecurityError: browser storage has been disabled 939 } 940 941 if (hasLocalStorage) { 942 loadEditor(); 943 944 } else if (location.search) { 945 // Check url query for `edit` parameter or any url ending in `?edit` 946 if (/[?&](edit)(?:[=&?]|$)/.test(location.search) || /\?edit$/.test(location.href)) { 947 loadEditor(); 948 } 949 950 } else { 951 // Check hash fragment to support `#hash?edit` 952 $win.on(hashchange, checkHash).triggerHandler(hashchange); 953 } 954 955 function checkHash() { 956 if (loaded) return; 957 // Load editor when hash contains `?edit` 958 if (/\?edit/.test(location.hash)) loadEditor(); 959 } 960 961 function load() { 962 loaded = true; 963 // Predefine global immediately to benefit Webflow.env 964 window.WebflowEditor = true; 965 $win.off(hashchange, checkHash); 966 $.ajax({ 967 url: cleanSlashes(("https://editor-api.webflow.com") + '/api/editor/view'), 968 data: { siteId: $html.attr('data-wf-site') }, 969 xhrFields: { withCredentials: true }, 970 dataType: 'json', 971 crossDomain: true, 972 success: success 973 }); 974 } 975 976 function success(data) { 977 if (!data) { 978 console.error('Could not load editor data'); 979 return; 980 } 981 getScript(prefix(data.scriptPath), function () { 982 window.WebflowEditor(data); 983 }); 984 } 985 986 function getScript(url, done) { 987 $.ajax({ type: 'GET', url: url, dataType: 'script', cache: true }).then(done, error); 988 } 989 990 function error(jqXHR, textStatus, errorThrown) { 991 console.error('Could not load editor script: ' + textStatus); 992 throw errorThrown; 993 } 994 995 function prefix(url) { 996 return (url.indexOf('//') >= 0) ? url : cleanSlashes(("https://editor-api.webflow.com") + url); 997 } 998 999 function cleanSlashes(url) { 1000 return url.replace(/([^:])\/\//g, '$1/'); 1001 } 1002 1003 // Export module 1004 return api; 1005 }); 1006 1007 1008/***/ }, 1009/* 9 */
1010/***/ function(module, exports) { 1011 1012 /** 1013 * Returns a Boolean representing whether or not the client is a mobile browser. 1014 * 1015 * NOTE: Many thanks to detectmobilebrowsers.com for this user agent detection 1016 * regex, without which the mobile internet probably wouldn't exist. 1017 */ 1018 Webflow.isMobile = function () { 1019 var userAgent = navigator.userAgent || navigator.vendor || window.opera; 1020 return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i 1021 .test(userAgent) || 1022 /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i 1023 .test(userAgent.substr(0, 4)); 1024 } 1025 1026 1027/***/ }, 1028/* 10 */ 1029/***/ function(module, exports, __webpack_require__) { 1030 1031 /** 1032 * Webflow: Forms 1033 */ 1034 1035 var Webflow = __webpack_require__(1); 1036 1037 Webflow.define('forms', module.exports = function($, _) { 1038 var api = {}; 1039 1040 // Cross-Domain AJAX for IE8 1041 __webpack_require__(22); 1042 1043 var $doc = $(document); 1044 var $forms; 1045 var loc = window.location; 1046 var retro = window.XDomainRequest && !window.atob; 1047 var namespace = '.w-form'; 1048 var siteId; 1049 var emailField = /e(\-)?mail/i; 1050 var emailValue = /^\S+@\S+$/; 1051 var alert = window.alert; 1052 var listening; 1053 1054 // MailChimp domains: list-manage.com + mirrors 1055 var chimpRegex = /list-manage[1-9]?.com/i; 1056 1057 var disconnected = _.debounce(function() { 1058 alert('Oops! This page has improperly configured forms. Please contact your website administrator to fix this issue.'); 1059 }, 100); 1060 1061 api.ready = function() { 1062 // Init forms 1063 init(); 1064 1065 // Wire document events once 1066 if (!listening) addListeners(); 1067 }; 1068 1069 api.preview = api.design = function() { 1070 init(); 1071 }; 1072 1073 function init() { 1074 siteId = $('html').attr('data-wf-site'); 1075 1076 $forms = $(namespace + ' form'); 1077 if (!$forms.length) return; 1078 $forms.each(build); 1079 } 1080 1081 function build(i, el) { 1082 // Store form state using namespace 1083 var $el = $(el); 1084 var data = $.data(el, namespace); 1085 if (!data) data = $.data(el, namespace, { form: $el }); // data.form 1086 1087 reset(data); 1088 var wrap = $el.closest('div.w-form'); 1089 data.done = wrap.find('> .w-form-done'); 1090 data.fail = wrap.find('> .w-form-fail'); 1091 1092 var action = data.action = $el.attr('action'); 1093 data.handler = null; 1094 data.redirect = $el.attr('data-redirect'); 1095 1096 // MailChimp form 1097 if (chimpRegex.test(action)) { data.handler = submitMailChimp; return; } 1098 1099 // Custom form action 1100 if (action) return; 1101 1102 // Webflow form 1103 if (siteId) { data.handler = submitWebflow; return; } 1104 1105 // Alert for disconnected Webflow forms 1106 disconnected(); 1107 } 1108 1109 function addListeners() { 1110 listening = true; 1111 1112 // Handle form submission for Webflow forms 1113 $doc.on('submit', namespace + ' form', function(evt) { 1114 var data = $.data(this, namespace); 1115 if (data.handler) { 1116 data.evt = evt; 1117 data.handler(data); 1118 } 1119 }); 1120 } 1121 1122 // Reset data common to all submit handlers 1123 function reset(data) { 1124 var btn = data.btn = data.form.find(':input[type="submit"]'); 1125 data.wait = data.btn.attr('data-wait') || null; 1126 data.success = false;
1127 btn.prop('disabled', false); 1128 data.label && btn.val(data.label); 1129 } 1130 1131 // Disable submit button 1132 function disableBtn(data) { 1133 var btn = data.btn; 1134 var wait = data.wait; 1135 btn.prop('disabled', true); 1136 // Show wait text and store previous label 1137 if (wait) { 1138 data.label = btn.val(); 1139 btn.val(wait); 1140 } 1141 } 1142 1143 // Find form fields, validate, and set value pairs 1144 function findFields(form, result) { 1145 var status = null; 1146 result = result || {}; 1147 1148 // The ":input" selector is a jQuery shortcut to select all inputs, selects, textareas 1149 form.find(':input:not([type="submit"])').each(function(i, el) { 1150 var field = $(el); 1151 var type = field.attr('type'); 1152 var name = field.attr('data-name') || field.attr('name') || ('Field ' + (i + 1)); 1153 var value = field.val(); 1154 1155 if (type === 'checkbox') { 1156 value = field.is(':checked'); 1157 } if (type === 'radio') { 1158 // Radio group value already processed 1159 if (result[name] === null || typeof result[name] === 'string') { 1160 return; 1161 } 1162 1163 value = form.find('input[name="' + field.attr('name') + '"]:checked').val() || null; 1164 } 1165 1166 if (typeof value === 'string') value = $.trim(value); 1167 result[name] = value; 1168 status = status || getStatus(field, type, name, value); 1169 }); 1170 1171 return status; 1172 } 1173 1174 function getStatus(field, type, name, value) { 1175 var status = null; 1176 1177 if (type === 'password') { 1178 status = 'Passwords cannot be submitted.'; 1179 } else if (field.attr('required')) { 1180 if (!value) { 1181 status = 'Please fill out the required field: ' + name; 1182 } else if (emailField.test(name) || emailField.test(field.attr('type'))) { 1183 if (!emailValue.test(value)) status = 'Please enter a valid email address for: ' + name; 1184 } 1185 } 1186 1187 return status; 1188 } 1189 1190 // Submit form to Webflow 1191 function submitWebflow(data) { 1192 reset(data); 1193 1194 var form = data.form; 1195 var payload = { 1196 name: form.attr('data-name') || form.attr('name') || 'Untitled Form', 1197 source: loc.href, 1198 test: Webflow.env(), 1199 fields: {}, 1200 dolphin: /pass[\s-_]?(word|code)|secret|login|credentials/i.test(form.html()) 1201 }; 1202 1203 preventDefault(data); 1204 1205 // Find & populate all fields 1206 var status = findFields(form, payload.fields); 1207 if (status) return alert(status); 1208 1209 // Disable submit button 1210 disableBtn(data); 1211 1212 // Read site ID 1213 // NOTE: If this site is exported, the HTML tag must retain the data-wf-site attribute for forms to work 1214 if (!siteId) { afterSubmit(data); return; } 1215 var url = ("https://webflow.com") + '/api/v1/form/' + siteId; 1216 1217 // Work around same-protocol IE XDR limitation - without this IE9 and below forms won't submit 1218 if (retro && url.indexOf(("https://webflow.com")) >= 0) { 1219 url = url.replace(("https://webflow.com"), ("http://formdata.webflow.com")); 1220 } 1221 1222 $.ajax({ 1223 url: url, 1224 type: 'POST', 1225 data: payload, 1226 dataType: 'json', 1227 crossDomain: true 1228 }).done(function() { 1229 data.success = true; 1230 afterSubmit(data); 1231 }).fail(function(response, textStatus, jqXHR) { 1232 afterSubmit(data); 1233 }); 1234 } 1235 1236 // Submit form to MailChimp 1237 function submitMailChimp(data) { 1238 reset(data); 1239 1240 var form = data.form; 1241 var payload = {}; 1242 1243 // Skip Ajax submission if http/s mismatch, fallback to POST instead 1244 if (/^https/.test(loc.href) && !/^https/.test(data.action)) { 1245 form.attr('method', 'post'); 1246 return; 1247 } 1248 1249 preventDefault(data); 1250 1251 // Find & populate all fields 1252 var status = findFields(form, payload); 1253 if (status) return alert(status); 1254 1255 // Disable submit button 1256 disableBtn(data); 1257 1258 // Use special format for MailChimp params 1259 var fullName; 1260 _.each(payload, function(value, key) { 1261 if (emailField.test(key)) payload.EMAIL = value; 1262 if (/^((full[ _-]?)?name)$/i.test(key)) fullName = value; 1263 if (/^(first[ _-]?name)$/i.test(key)) payload.FNAME = value; 1264 if (/^(last[ _-]?name)$/i.test(key)) payload.LNAME = value; 1265 }); 1266 1267 if (fullName && !payload.FNAME) { 1268 fullName = fullName.split(' '); 1269 payload.FNAME = fullName[0]; 1270 payload.LNAME = payload.LNAME || fullName[1]; 1271 } 1272 1273 // Use the (undocumented) MailChimp jsonp api 1274 var url = data.action.replace('/post?', '/post-json?') + '&c=?'; 1275 // Add special param to prevent bot signups 1276 var userId = url.indexOf('u=') + 2; 1277 userId = url.substring(userId, url.indexOf('&', userId)); 1278 var listId = url.indexOf('id=') + 3; 1279 listId = url.substring(listId, url.indexOf('&', listId)); 1280 payload['b_' + userId + '_' + listId] = ''; 1281 1282 $.ajax({ 1283 url: url, 1284 data: payload, 1285 dataType: 'jsonp' 1286 }).done(function(resp) { 1287 data.success = (resp.result === 'success' || /already/.test(resp.msg)); 1288 if (!data.success) console.info('MailChimp error: ' + resp.msg); 1289 afterSubmit(data); 1290 }).fail(function(response, textStatus, jqXHR) { 1291 afterSubmit(data); 1292 }); 1293 } 1294 1295 // Common callback which runs after all Ajax submissions 1296 function afterSubmit(data) { 1297 var form = data.form; 1298 var wrap = form.closest('div.w-form'); 1299 var redirect = data.redirect; 1300 var success = data.success; 1301 1302 // Redirect to a success url if defined 1303 if (success && redirect) { 1304 Webflow.location(redirect); 1305 return; 1306 } 1307 1308 // Show or hide status divs 1309 data.done.toggle(success); 1310 data.fail.toggle(!success); 1311 1312 // Hide form on success 1313 form.toggle(!success); 1314 1315 // Reset data and enable submit button 1316 reset(data); 1317 } 1318 1319 function preventDefault(data) { 1320 data.evt && data.evt.preventDefault(); 1321 data.evt = null; 1322 } 1323 1324 // Export module 1325 return api; 1326 }); 1327 1328 1329/***/ }, 1330/* 11 */ 1331/***/ function(module, exports, __webpack_require__) { 1332 1333 'use strict'; 1334 1335 /** 1336 * Webflow: Google+ widget 1337 */ 1338 1339 var Webflow = __webpack_require__(1); 1340 1341 Webflow.define('gplus', module.exports = function($, _) { 1342 var $doc = $(document); 1343 var api = {}; 1344 var loaded; 1345 1346 api.ready = function() { 1347 // Load Google+ API on the front-end 1348 if (!Webflow.env() && !loaded) init(); 1349 }; 1350
1351 function init() { 1352 $doc.find('.w-widget-gplus').length && load(); 1353 } 1354 1355 function load() { 1356 loaded = true; 1357 $.getScript('https://apis.google.com/js/plusone.js'); 1358 } 1359 1360 // Export module 1361 return api; 1362 }); 1363 1364 1365/***/ }, 1366/* 12 */ 1367/***/ function(module, exports, __webpack_require__) { 1368 1369 'use strict'; 1370 /*eslint no-self-compare:0 */ 1371 1372 /** 1373 * Webflow: Interactions 1374 */ 1375 1376 var Webflow = __webpack_require__(1); 1377 var IXEvents = __webpack_require__(2); 1378 1379 Webflow.define('ix', module.exports = function($, _) { 1380 var api = {}; 1381 var designer; 1382 var $win = $(window); 1383 var namespace = '.w-ix'; 1384 var tram = $.tram; 1385 var env = Webflow.env; 1386 var inApp = env(); 1387 var emptyFix = env.chrome && env.chrome < 35; 1388 var transNone = 'none 0s ease 0s'; 1389 var $subs = $(); 1390 var config = {}; 1391 var anchors = []; 1392 var loads = []; 1393 var readys = []; 1394 var destroyed; 1395 var readyDelay = 1; 1396 1397 // Component types and proxy selectors 1398 var components = { 1399 tabs: '.w-tab-link, .w-tab-pane', 1400 dropdown: '.w-dropdown', 1401 slider: '.w-slide', 1402 navbar: '.w-nav' 1403 }; 1404 1405 // ----------------------------------- 1406 // Module methods 1407 1408 api.init = function(list) { 1409 setTimeout(function() { configure(list); }, 1); 1410 }; 1411 1412 api.preview = function() { 1413 designer = false;
1414 readyDelay = 100; 1415 setTimeout(function() { configure(window.__wf_ix); }, 1); 1416 }; 1417 1418 api.design = function() { 1419 designer = true; 1420 api.destroy(); 1421 }; 1422 1423 api.destroy = function() { 1424 destroyed = true; 1425 $subs.each(teardown); 1426 Webflow.scroll.off(scroll); 1427 IXEvents.async(); 1428 anchors = []; 1429 loads = []; 1430 readys = []; 1431 }; 1432 1433 api.ready = function() { 1434 // Ready should only be used after destroy, as a way to re-init 1435 if (config && destroyed) { 1436 destroyed = false; 1437 init(); 1438 } 1439 }; 1440 1441 api.run = run; 1442 api.style = inApp ? styleApp : stylePub; 1443 1444 // ----------------------------------- 1445 // Private methods 1446 1447 function configure(list) { 1448 if (!list) return; 1449 1450 // Map all interactions by slug 1451 config = {}; 1452 _.each(list, function(item) { 1453 config[item.slug] = item.value; 1454 }); 1455 1456 // Init ix after config 1457 init(); 1458 } 1459 1460 function init() { 1461 // Build each element's interaction keying from data attribute 1462 var els = $('[data-ix]'); 1463 if (!els.length) return; 1464 els.each(teardown); 1465 els.each(build); 1466 1467 // Listen for scroll events if any anchors exist 1468 if (anchors.length) { 1469 Webflow.scroll.on(scroll); 1470 setTimeout(scroll, 1); 1471 } 1472 1473 // Handle loads or readys if they exist 1474 if (loads.length) Webflow.load(runLoads); 1475 if (readys.length) setTimeout(runReadys, readyDelay); 1476 1477 // Trigger queued events, must happen after init 1478 IXEvents.init(); 1479 1480 // Trigger a redraw to ensure all IX intros play 1481 Webflow.redraw.up(); 1482 } 1483 1484 function build(i, el) { 1485 var $el = $(el); 1486 var id = $el.attr('data-ix'); 1487 var ix = config[id]; 1488 if (!ix) return; 1489 var triggers = ix.triggers; 1490 if (!triggers) return; 1491 1492 // Set styles immediately to provide tram with starting transform values 1493 api.style($el, ix.style); 1494 1495 _.each(triggers, function(trigger) { 1496 var state = {}; 1497 var type = trigger.type; 1498 var stepsB = trigger.stepsB && trigger.stepsB.length; 1499 1500 function runA() { run(trigger, $el, { group: 'A' }); } 1501 function runB() { run(trigger, $el, { group: 'B' }); } 1502 1503 if (type === 'load') { 1504 (trigger.preload && !inApp) ? loads.push(runA) : readys.push(runA); 1505 return; 1506 } 1507 1508 if (type === 'click') { 1509 $el.on('click' + namespace, function(evt) { 1510 // Avoid late clicks on touch devices 1511 if (!Webflow.validClick(evt.currentTarget)) return; 1512 1513 // Prevent default on empty hash urls 1514 if ($el.attr('href') === '#') evt.preventDefault(); 1515 1516 run(trigger, $el, { group: state.clicked ? 'B' : 'A' }); 1517 if (stepsB) state.clicked = !state.clicked; 1518 }); 1519 $subs = $subs.add($el); 1520 return; 1521 } 1522 1523 if (type === 'hover') { 1524 $el.on('mouseenter' + namespace, runA); 1525 $el.on('mouseleave' + namespace, runB); 1526 $subs = $subs.add($el); 1527 return; 1528 } 1529 1530 if (type === 'scroll') { 1531 anchors.push({ 1532 el: $el, trigger: trigger, state: { active: false }, 1533 offsetTop: convert(trigger.offsetTop), 1534 offsetBot: convert(trigger.offsetBot) 1535 }); 1536 return; 1537 } 1538 1539 // Check for a proxy component selector 1540 // type == [tabs, dropdown, slider, navbar] 1541 var proxy = components[type]; 1542 if (proxy) { 1543 var $proxy = $el.closest(proxy); 1544 $proxy.on(IXEvents.types.INTRO, runA).on(IXEvents.types.OUTRO, runB); 1545 $subs = $subs.add($proxy); 1546 return; 1547 } 1548 }); 1549 } 1550 1551 function convert(offset) { 1552 if (!offset) return 0; 1553 offset = String(offset); 1554 var result = parseInt(offset, 10); 1555 if (result !== result) return 0; 1556 if (offset.indexOf('%') > 0) { 1557 result /= 100; 1558 if (result >= 1) result = 0.999; 1559 } 1560 return result; 1561 } 1562 1563 function teardown(i, el) { 1564 $(el).off(namespace); 1565 } 1566 1567 function scroll() { 1568 var viewTop = $win.scrollTop(); 1569 var viewHeight = $win.height(); 1570 1571 // Check each anchor for a valid scroll trigger 1572 var count = anchors.length; 1573 for (var i = 0; i < count; i++) { 1574 var anchor = anchors[i]; 1575 var $el = anchor.el; 1576 var trigger = anchor.trigger; 1577 var stepsB = trigger.stepsB && trigger.stepsB.length; 1578 var state = anchor.state; 1579 var top = $el.offset().top; 1580 var height = $el.outerHeight(); 1581 var offsetTop = anchor.offsetTop; 1582 var offsetBot = anchor.offsetBot; 1583 if (offsetTop < 1 && offsetTop > 0) offsetTop *= viewHeight; 1584 if (offsetBot < 1 && offsetBot > 0) offsetBot *= viewHeight; 1585 var active = (top + height - offsetTop >= viewTop && top + offsetBot <= viewTop + viewHeight); 1586 if (active === state.active) continue; 1587 if (active === false && !stepsB) continue; 1588 state.active = active; 1589 run(trigger, $el, { group: active ? 'A' : 'B' }); 1590 } 1591 } 1592 1593 function runLoads() { 1594 var count = loads.length; 1595 for (var i = 0; i < count; i++) { 1596 loads[i](); 1597 } 1598 } 1599 1600 function runReadys() { 1601 var count = readys.length; 1602 for (var i = 0; i < count; i++) { 1603 readys[i](); 1604 } 1605 } 1606 1607 function run(trigger, $el, opts, replay) { 1608 opts = opts || {}; 1609 var done = opts.done; 1610
1611 // Do not run in designer unless forced 1612 if (designer && !opts.force) return; 1613 1614 // Operate on a set of grouped steps 1615 var group = opts.group || 'A'; 1616 var loop = trigger['loop' + group]; 1617 var steps = trigger['steps' + group]; 1618 if (!steps || !steps.length) return; 1619 if (steps.length < 2) loop = false; 1620 1621 // One-time init before any loops 1622 if (!replay) { 1623 1624 // Find selector within element descendants, siblings, or query whole document 1625 var selector = trigger.selector; 1626 if (selector) { 1627 if (trigger.descend) { 1628 $el = $el.find(selector); 1629 } else if (trigger.siblings) { 1630 $el = $el.siblings(selector); 1631 } else { 1632 $el = $(selector); 1633 } 1634 if (inApp) $el.attr('data-ix-affect', 1); 1635 } 1636 1637 // Apply empty fix for certain Chrome versions 1638 if (emptyFix) $el.addClass('w-ix-emptyfix'); 1639 1640 // Set preserve3d for triggers with transforms 1641 if (trigger.preserve3d) $el.css('transform-style', 'preserve-3d'); 1642 } 1643 1644 var _tram = tram($el); 1645 1646 // Add steps 1647 var meta = {}; 1648 for (var i = 0; i < steps.length; i++) { 1649 addStep(_tram, steps[i], meta); 1650 } 1651 1652 function fin() { 1653 // Run trigger again if looped 1654 if (loop) return run(trigger, $el, opts, true); 1655 1656 // Reset any 'auto' values 1657 if (meta.width === 'auto') _tram.set({ width: 'auto' }); 1658 if (meta.height === 'auto') _tram.set({ height: 'auto' }); 1659 1660 // Run callback 1661 done && done(); 1662 } 1663 1664 // Add final step to queue if tram has started 1665 meta.start ? _tram.then(fin) : fin(); 1666 } 1667 1668 function addStep(_tram, step, meta) { 1669 var addMethod = 'add'; 1670 var startMethod = 'start'; 1671 1672 // Once the transition has started, we will always use then() to add to the queue. 1673 if (meta.start) addMethod = startMethod = 'then'; 1674 1675 // Parse transitions string on the current step 1676 var transitions = step.transition; 1677 if (transitions) { 1678 transitions = transitions.split(','); 1679 for (var i = 0; i < transitions.length; i++) { 1680 var transition = transitions[i]; 1681 _tram[addMethod](transition); 1682 } 1683 } 1684 1685 // Build a clean object to pass to the tram method 1686 var clean = tramify(step) || {}; 1687 1688 // Store last width and height values 1689 if (clean.width != null) meta.width = clean.width; 1690 if (clean.height != null) meta.height = clean.height; 1691 1692 // When transitions are not present, set values immediately and continue queue. 1693 if (transitions == null) { 1694 1695 // If we have started, wrap set() in then() and reset queue 1696 if (meta.start) { 1697 _tram.then(function() { 1698 var queue = this.queue; 1699 this.set(clean); 1700 if (clean.display) { 1701 _tram.redraw(); 1702 Webflow.redraw.up(); 1703 } 1704 this.queue = queue; 1705 this.next(); 1706 }); 1707 } else { 1708 _tram.set(clean); 1709 1710 // Always redraw after setting display 1711 if (clean.display) { 1712 _tram.redraw(); 1713 Webflow.redraw.up(); 1714 } 1715 } 1716 1717 // Use the wait() method to kick off queue in absence of transitions. 1718 var wait = clean.wait; 1719 if (wait != null) { 1720 _tram.wait(wait); 1721 meta.start = true; 1722 } 1723 1724 // Otherwise, when transitions are present 1725 } else { 1726 1727 // If display is present, handle it separately 1728 if (clean.display) { 1729 var display = clean.display; 1730 delete clean.display; 1731 1732 // If we've already started, we need to wrap it in a then() 1733 if (meta.start) { 1734 _tram.then(function() { 1735 var queue = this.queue; 1736 this.set({ display: display }).redraw(); 1737 Webflow.redraw.up(); 1738 this.queue = queue; 1739 this.next(); 1740 }); 1741 } else { 1742 _tram.set({ display: display }).redraw(); 1743 Webflow.redraw.up(); 1744 } 1745 } 1746 1747 // Otherwise, start a transition using the current start method. 1748 _tram[startMethod](clean); 1749 meta.start = true; 1750 } 1751 } 1752 1753 // (In app) Set styles immediately and manage upstream transition
1754 function styleApp(el, data) { 1755 var _tram = tram(el); 1756 1757 // Get computed transition value 1758 el.css('transition', ''); 1759 var computed = el.css('transition'); 1760 1761 // If computed is set to none, clear upstream 1762 if (computed === transNone) computed = _tram.upstream = null; 1763 1764 // Set upstream transition to none temporarily 1765 _tram.upstream = transNone; 1766 1767 // Set values immediately 1768 _tram.set(tramify(data)); 1769 1770 // Only restore upstream in preview mode 1771 _tram.upstream = computed; 1772 } 1773 1774 // (Published) Set styles immediately on specified jquery element 1775 function stylePub(el, data) { 1776 tram(el).set(tramify(data)); 1777 } 1778 1779 // Build a clean object for tram 1780 function tramify(obj) { 1781 var result = {}; 1782 var found = false; 1783 for (var x in obj) { 1784 if (x === 'transition') continue; 1785 result[x] = obj[x]; 1786 found = true; 1787 } 1788 // If empty, return null for tram.set/stop compliance 1789 return found ? result : null; 1790 } 1791 1792 // Export module 1793 return api; 1794 }); 1795 1796 1797/***/ }, 1798/* 13 */ 1799/***/ function(module, exports, __webpack_require__) { 1800 1801 'use strict'; 1802 /*eslint 1803 no-use-before-define: 0, 1804 no-shadow: 0 1805 */ 1806 1807 /** 1808 * Webflow: Lightbox component 1809 */ 1810 1811 var Webflow = __webpack_require__(1); 1812 1813 function createLightbox(window, document, $) { 1814 var tram = $.tram; 1815 var isArray = Array.isArray; 1816 var namespace = 'w-lightbox'; 1817 var prefix = namespace + '-'; 1818 var prefixRegex = /(^|\s+)/g; 1819 1820 // Array of objects describing items to be displayed. 1821 var items = []; 1822 1823 // Index of the currently displayed item. 1824 var currentIndex; 1825 1826 // Object holding references to jQuery wrapped nodes. 1827 var $refs; 1828 1829 // Instance of Spinner 1830 var spinner; 1831 1832 function lightbox(thing, index) { 1833 items = isArray(thing) ? thing : [thing]; 1834 1835 if (!$refs) { 1836 lightbox.build(); 1837 } 1838 1839 if (items.length > 1) { 1840 $refs.items = $refs.empty; 1841 1842 items.forEach(function (item) { 1843 var $thumbnail = dom('thumbnail'); 1844 var $item = dom('item').append($thumbnail); 1845 1846 $refs.items = $refs.items.add($item); 1847 1848 loadImage(item.thumbnailUrl || item.url, function ($image) { 1849 if ($image.prop('width') > $image.prop('height')) { 1850 addClass($image, 'wide'); 1851 } else { 1852 addClass($image, 'tall'); 1853 } 1854 $thumbnail.append(addClass($image, 'thumbnail-image')); 1855 }); 1856 }); 1857 1858 $refs.strip.empty().append($refs.items); 1859 addClass($refs.content, 'group'); 1860 } 1861 1862 tram( 1863 // Focus the lightbox to receive keyboard events. 1864 removeClass($refs.lightbox, 'hide').focus() 1865 ) 1866 .add('opacity .3s') 1867 .start({opacity: 1}); 1868 1869 // Prevent document from scrolling while lightbox is active. 1870 addClass($refs.html, 'noscroll'); 1871 1872 return lightbox.show(index || 0); 1873 } 1874 1875 /** 1876 * Creates the DOM structure required by the lightbox. 1877 */ 1878 lightbox.build = function () { 1879 // In case `build` is called more than once. 1880 lightbox.destroy(); 1881 1882 $refs = { 1883 html: $(document.documentElement), 1884 // Empty jQuery object can be used to build new ones using `.add`. 1885 empty: $() 1886 }; 1887 1888 $refs.arrowLeft = dom('control left inactive'); 1889 $refs.arrowRight = dom('control right inactive'); 1890 $refs.close = dom('control close'); 1891 1892 $refs.spinner = dom('spinner'); 1893 $refs.strip = dom('strip'); 1894 1895 spinner = new Spinner($refs.spinner, prefixed('hide')); 1896 1897 $refs.content = dom('content') 1898 .append($refs.spinner, $refs.arrowLeft, $refs.arrowRight, $refs.close); 1899 1900 $refs.container = dom('container') 1901 .append($refs.content, $refs.strip); 1902 1903 $refs.lightbox = dom('backdrop hide') 1904 .append($refs.container); 1905 1906 // We are delegating events for performance reasons and also 1907 // to not have to reattach handlers when images change. 1908 $refs.strip.on('tap', selector('item'), itemTapHandler); 1909 $refs.content 1910 .on('swipe', swipeHandler) 1911 .on('tap', selector('left'), handlerPrev) 1912 .on('tap', selector('right'), handlerNext) 1913 .on('tap', selector('close'), handlerHide) 1914 .on('tap', selector('image, caption'), handlerNext); 1915 $refs.container 1916 .on('tap', selector('view, strip'), handlerHide) 1917 // Prevent images from being dragged around. 1918 .on('dragstart', selector('img'), preventDefault); 1919 $refs.lightbox 1920 .on('keydown', keyHandler) 1921 // IE loses focus to inner nodes without letting us know. 1922 .on('focusin', focusThis); 1923 1924 // The `tabindex` attribute is needed to enable non-input elements 1925 // to receive keyboard events. 1926 $('body').append($refs.lightbox.prop('tabIndex', 0)); 1927 1928 return lightbox; 1929 }; 1930 1931 /**
1932 * Dispose of DOM nodes created by the lightbox. 1933 */ 1934 lightbox.destroy = function () { 1935 if (!$refs) { 1936 return; 1937 } 1938 1939 // Event handlers are also removed. 1940 removeClass($refs.html, 'noscroll'); 1941 $refs.lightbox.remove(); 1942 $refs = undefined; 1943 }; 1944 1945 /** 1946 * Show a specific item. 1947 */ 1948 lightbox.show = function (index) { 1949 // Bail if we are already showing this item. 1950 if (index === currentIndex) { 1951 return; 1952 } 1953 1954 var item = items[index]; 1955 if (!item) { return lightbox.hide(); } 1956 1957 var previousIndex = currentIndex; 1958 currentIndex = index; 1959 spinner.show(); 1960 1961 // For videos, load an empty SVG with the video dimensions to preserve 1962 // the videoâs aspect ratio while being responsive. 1963 var url = item.html && svgDataUri(item.width, item.height) || item.url; 1964 loadImage(url, function ($image) { 1965 // Make sure this is the last item requested to be shown since 1966 // images can finish loading in a different order than they were 1967 // requested in. 1968 if (index !== currentIndex) { 1969 return; 1970 } 1971 1972 var $figure = dom('figure', 'figure').append(addClass($image, 'image')); 1973 var $frame = dom('frame').append($figure); 1974 var $newView = dom('view').append($frame); 1975 var $html, isIframe; 1976 1977 if (item.html) { 1978 $html = $(item.html); 1979 isIframe = $html.is('iframe'); 1980 1981 if (isIframe) { 1982 $html.on('load', transitionToNewView); 1983 } 1984 1985 $figure.append(addClass($html, 'embed')); 1986 } 1987 1988 if (item.caption) { 1989 $figure.append(dom('caption', 'figcaption').text(item.caption)); 1990 } 1991 1992 $refs.spinner.before($newView); 1993 1994 if (!isIframe) { 1995 transitionToNewView(); 1996 } 1997 1998 function transitionToNewView() { 1999 spinner.hide(); 2000 2001 if (index !== currentIndex) { 2002 $newView.remove(); 2003 return; 2004 } 2005 2006 2007 toggleClass($refs.arrowLeft, 'inactive', index <= 0); 2008 toggleClass($refs.arrowRight, 'inactive', index >= items.length - 1); 2009 2010 if ($refs.view) { 2011 tram($refs.view) 2012 .add('opacity .3s') 2013 .start({opacity: 0}) 2014 .then(remover($refs.view)); 2015 2016 tram($newView) 2017 .add('opacity .3s') 2018 .add('transform .3s') 2019 .set({x: index > previousIndex ? '80px' : '-80px'}) 2020 .start({opacity: 1, x: 0}); 2021 } else { 2022 $newView.css('opacity', 1); 2023 } 2024 2025 $refs.view = $newView; 2026 2027 if ($refs.items) { 2028 // Mark proper thumbnail as active 2029 addClass(removeClass($refs.items, 'active').eq(index), 'active'); 2030 } 2031 } 2032 }); 2033 2034 return lightbox; 2035 }; 2036 2037 /** 2038 * Hides the lightbox. 2039 */ 2040 lightbox.hide = function () { 2041 tram($refs.lightbox) 2042 .add('opacity .3s') 2043 .start({opacity: 0}) 2044 .then(hideLightbox); 2045 2046 return lightbox; 2047 }; 2048 2049 lightbox.prev = function () { 2050 if (currentIndex > 0) { 2051 lightbox.show(currentIndex - 1); 2052 } 2053 }; 2054 2055 lightbox.next = function () { 2056 if (currentIndex < items.length - 1) { 2057 lightbox.show(currentIndex + 1); 2058 } 2059 }; 2060 2061 function createHandler(action) { 2062 return function (event) { 2063 // We only care about events triggered directly on the bound selectors. 2064 if (this !== event.target) { 2065 return; 2066 } 2067 2068 event.stopPropagation(); 2069 event.preventDefault(); 2070 2071 action(); 2072 }; 2073 } 2074 2075 var handlerPrev = createHandler(lightbox.prev); 2076 var handlerNext = createHandler(lightbox.next); 2077 var handlerHide = createHandler(lightbox.hide); 2078 2079 var itemTapHandler = function(event) { 2080 var index = $(this).index(); 2081 2082 event.preventDefault(); 2083 lightbox.show(index); 2084 }; 2085 2086 var swipeHandler = function (event, data) { 2087 // Prevent scrolling. 2088 event.preventDefault(); 2089 2090 if (data.direction === 'left') { 2091 lightbox.next(); 2092 } else if (data.direction === 'right') { 2093 lightbox.prev(); 2094 } 2095 }; 2096 2097 var focusThis = function () { 2098 this.focus(); 2099 }; 2100 2101 function preventDefault(event) { 2102 event.preventDefault(); 2103 } 2104 2105 function keyHandler(event) { 2106 var keyCode = event.keyCode; 2107 2108 // [esc] 2109 if (keyCode === 27) { 2110 lightbox.hide(); 2111 } 2112 2113 // [â] 2114 else if (keyCode === 37) { 2115 lightbox.prev(); 2116 } 2117 2118 // [â¶] 2119 else if (keyCode === 39) { 2120 lightbox.next(); 2121 } 2122 } 2123 2124 function hideLightbox() { 2125 // If the lightbox hasn't been destroyed already 2126 if ($refs) { 2127 removeClass($refs.html, 'noscroll'); 2128 addClass($refs.lightbox, 'hide'); 2129 $refs.strip.empty(); 2130 $refs.view && $refs.view.remove(); 2131 2132 // Reset some stuff 2133 removeClass($refs.content, 'group'); 2134 addClass($refs.arrowLeft, 'inactive'); 2135 addClass($refs.arrowRight, 'inactive'); 2136 2137 currentIndex = $refs.view = undefined; 2138 } 2139 } 2140 2141 function loadImage(url, callback) { 2142 var $image = dom('img', 'img'); 2143 2144 $image.one('load', function () { 2145 callback($image); 2146 }); 2147 2148 // Start loading image. 2149 $image.attr('src', url); 2150 2151 return $image; 2152 } 2153 2154 function remover($element) { 2155 return function () { 2156 $element.remove(); 2157 }; 2158 } 2159 2160 /** 2161 * Spinner 2162 */ 2163 function Spinner($spinner, className, delay) { 2164 this.$element = $spinner; 2165 this.className = className; 2166 this.delay = delay || 200; 2167 this.hide(); 2168 } 2169 2170 Spinner.prototype.show = function () { 2171 var spinner = this; 2172 2173 // Bail if we are already showing the spinner. 2174 if (spinner.timeoutId) { 2175 return; 2176 } 2177 2178 spinner.timeoutId = setTimeout(function () { 2179 spinner.$element.removeClass(spinner.className); 2180 delete spinner.timeoutId; 2181 }, spinner.delay); 2182 }; 2183 2184 Spinner.prototype.hide = function () { 2185 var spinner = this; 2186 if (spinner.timeoutId) { 2187 clearTimeout(spinner.timeoutId); 2188 delete spinner.timeoutId; 2189 return; 2190 } 2191 2192 spinner.$element.addClass(spinner.className); 2193 }; 2194 2195 function prefixed(string, isSelector) { 2196 return string.replace(prefixRegex, (isSelector ? ' .' : ' ') + prefix); 2197 } 2198 2199 function selector(string) { 2200 return prefixed(string, true); 2201 } 2202 2203 /** 2204 * jQuery.addClass with auto-prefixing 2205 * @param {jQuery} Element to add class to 2206 * @param {string}
2206 Class name that will be prefixed and added to element 2207 * @return {jQuery} 2208 */ 2209 function addClass($element, className) { 2210 return $element.addClass(prefixed(className)); 2211 } 2212 2213 /** 2214 * jQuery.removeClass with auto-prefixing 2215 * @param {jQuery} Element to remove class from 2216 * @param {string} Class name that will be prefixed and removed from element 2217 * @return {jQuery} 2218 */ 2219 function removeClass($element, className) { 2220 return $element.removeClass(prefixed(className)); 2221 } 2222 2223 /** 2224 * jQuery.toggleClass with auto-prefixing 2225 * @param {jQuery} Element where class will be toggled 2226 * @param {string} Class name that will be prefixed and toggled 2227 * @param {boolean} Optional boolean that determines if class will be added or removed 2228 * @return {jQuery} 2229 */ 2230 function toggleClass($element, className, shouldAdd) { 2231 return $element.toggleClass(prefixed(className), shouldAdd); 2232 } 2233 2234 /** 2235 * Create a new DOM element wrapped in a jQuery object, 2236 * decorated with our custom methods. 2237 * @param {string} className 2238 * @param {string} [tag] 2239 * @return {jQuery} 2240 */ 2241 function dom(className, tag) { 2242 return addClass($(document.createElement(tag || 'div')), className); 2243 } 2244 2245 function isObject(value) { 2246 return typeof value === 'object' && value != null && !isArray(value); 2247 } 2248 2249 function svgDataUri(width, height) { 2250 var svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' + width + '" height="' + height + '"/>'; 2251 return 'data:image/svg+xml;charset=utf-8,' + encodeURI(svg); 2252 } 2253 2254 // Compute some dimensions manually for iOS < 8, because of buggy support for VH. 2255 // Also, Android built-in browser does not support viewport units. 2256 (function () { 2257 var ua = window.navigator.userAgent; 2258 var iOSRegex = /(iPhone|iPad|iPod);[^OS]*OS (\d)/; 2259 var iOSMatches = ua.match(iOSRegex); 2260 var android = ua.indexOf('Android ') > -1 && ua.indexOf('Chrome') === -1; 2261 2262 if (!android && (!iOSMatches || iOSMatches[2] > 7)) { 2263 return; 2264 } 2265 2266 var styleNode = document.createElement('style'); 2267 document.head.appendChild(styleNode); 2268 window.addEventListener('orientationchange', refresh, true); 2269 2270 function refresh() { 2271 var vh = window.innerHeight; 2272 var vw = window.innerWidth; 2273 var content = 2274 '.w-lightbox-content, .w-lightbox-view, .w-lightbox-view:before {' + 2275 'height:' + vh + 'px' + 2276 '}' + 2277 '.w-lightbox-view {' + 2278 'width:' + vw + 'px' + 2279 '}' + 2280 '.w-lightbox-group, .w-lightbox-group .w-lightbox-view, .w-lightbox-group .w-lightbox-view:before {' + 2281 'height:' + (0.86 * vh) + 'px' + 2282 '}' + 2283 '.w-lightbox-image {' + 2284 'max-width:' + vw + 'px;' + 2285 'max-height:' + vh + 'px' + 2286 '}' + 2287 '.w-lightbox-group .w-lightbox-image {' + 2288 'max-height:' + (0.86 * vh) + 'px' + 2289 '}' + 2290 '.w-lightbox-strip {' + 2291 'padding: 0 ' + (0.01 * vh) + 'px' + 2292 '}' + 2293 '.w-lightbox-item {' + 2294 'width:' + (0.1 * vh) + 'px;' + 2295 'padding:' + (0.02 * vh) + 'px ' + (0.01 * vh) + 'px' + 2296 '}' + 2297 '.w-lightbox-thumbnail {' + 2298 'height:' + (0.1 * vh) + 'px' + 2299 '}' + 2300 '@media (min-width: 768px) {' + 2301 '.w-lightbox-content, .w-lightbox-view, .w-lightbox-view:before {' + 2302 'height:' + (0.96 * vh) + 'px' + 2303 '}' + 2304 '.w-lightbox-content {' + 2305 'margin-top:' + (0.02 * vh) + 'px' + 2306 '}' + 2307 '.w-lightbox-group, .w-lightbox-group .w-lightbox-view, .w-lightbox-group .w-lightbox-view:before {' + 2308 'height:' + (0.84 * vh) + 'px' + 2309 '}' + 2310 '.w-lightbox-image {' + 2311 'max-width:' + (0.96 * vw) + 'px;' + 2312 'max-height:' + (0.96 * vh) + 'px' + 2313 '}' + 2314 '.w-lightbox-group .w-lightbox-image {' + 2315 'max-width:' + (0.823 * vw) + 'px;' + 2316 'max-height:' + (0.84 * vh) + 'px' + 2317 '}' + 2318 '}'; 2319 2320 styleNode.textContent = content; 2321 } 2322 2323 refresh(); 2324 })(); 2325 2326 return lightbox; 2327 } 2328 2329 Webflow.define('lightbox', module.exports = function($, _) { 2330 var api = {}; 2331 var lightbox = createLightbox(window, document, $); 2332 var $doc = $(document); 2333 var $body; 2334 var $lightboxes; 2335 var designer; 2336 var inApp = Webflow.env(); 2337 var namespace = '.w-lightbox'; 2338 var groups; 2339 2340 // ----------------------------------- 2341 // Module methods 2342 2343 api.ready = api.design = api.preview = init; 2344 2345 // ----------------------------------- 2346 // Private methods 2347
2348 function init() { 2349 designer = inApp && Webflow.env('design'); 2350 $body = $(document.body); 2351 2352 // Reset Lightbox 2353 lightbox.destroy(); 2354 2355 // Reset groups 2356 groups = {}; 2357 2358 // Find all instances on the page 2359 $lightboxes = $doc.find(namespace); 2360 2361 // Instantiate all lighboxes 2362 $lightboxes.webflowLightBox(); 2363 } 2364 2365 jQuery.fn.extend({ 2366 webflowLightBox: function() { 2367 var $el = this; 2368 $.each($el, function(i, el) { 2369 // Store state in data 2370 var data = $.data(el, namespace); 2371 if (!data) { 2372 data = $.data(el, namespace, { 2373 el: $(el), 2374 mode: 'images', 2375 images: [], 2376 embed: '' 2377 }); 2378 } 2379 2380 // Remove old events 2381 data.el.off(namespace); 2382 2383 // Set config from json script tag 2384 configure(data); 2385 2386 // Add events based on mode 2387 if (designer) { 2388 data.el.on('setting' + namespace, configure.bind(null, data)); 2389 } else { 2390 data.el 2391 .on('tap' + namespace, tapHandler(data)) 2392 // Prevent page scrolling to top when clicking on lightbox triggers. 2393 .on('click' + namespace, function (e) { e.preventDefault(); }); 2394 } 2395 }); 2396 } 2397 }); 2398 2399 function configure(data) { 2400 var json = data.el.children('.w-json').html(); 2401 var groupName, groupItems; 2402 2403 if (!json) { 2404 data.items = []; 2405 return; 2406 } 2407 2408 try { 2409 json = JSON.parse(json); 2410 } catch(e) { 2411 console.error('Malformed lightbox JSON configuration.', e); 2412 } 2413 2414 supportOldLightboxJson(json); 2415 2416 groupName = json.group; 2417 2418 if (groupName) { 2419 groupItems = groups[groupName]; 2420 if (!groupItems) { 2421 groupItems = groups[groupName] = []; 2422 } 2423 2424 data.items = groupItems; 2425 2426 if (json.items.length) { 2427 data.index = groupItems.length; 2428 groupItems.push.apply(groupItems, json.items); 2429 } 2430 } else { 2431 data.items = json.items; 2432 } 2433 } 2434 2435 function tapHandler(data) { 2436 return function () { 2437 data.items.length && lightbox(data.items, data.index || 0); 2438 }; 2439 } 2440 2441 function supportOldLightboxJson(data) { 2442 if (data.images) { 2443 data.images.forEach(function (item) { 2444 item.type = 'image'; 2445 }); 2446 data.items = data.images; 2447 } 2448 2449 if (data.embed) { 2450 data.embed.type = 'video'; 2451 data.items = [data.embed]; 2452 } 2453 2454 if (data.groupId) { 2455 data.group = data.groupId; 2456 } 2457 } 2458 2459 // Export module 2460 return api; 2461 }); 2462 2463 2464/***/ }, 2465/* 14 */ 2466/***/ function(module, exports, __webpack_require__) { 2467 2468 'use strict'; 2469 2470 /** 2471 * Webflow: Auto-select links to current page or section 2472 */ 2473 2474 var Webflow = __webpack_require__(1); 2475 2476 Webflow.define('links', module.exports = function($, _) { 2477 var api = {}; 2478 var $win = $(window); 2479 var designer; 2480 var inApp = Webflow.env(); 2481 var location = window.location; 2482 var tempLink = document.createElement('a'); 2483 var linkCurrent = 'w--current'; 2484 var validHash = /^#[a-zA-Z][\w:.-]*$/; 2485 var indexPage = /index\.(html|php)$/; 2486 var dirList = /\/$/; 2487 var anchors; 2488 var slug; 2489 2490 // ----------------------------------- 2491 // Module methods 2492 2493 api.ready = api.design = api.preview = init; 2494 2495 // ----------------------------------- 2496 // Private methods 2497 2498 function init() { 2499 designer = inApp && Webflow.env('design'); 2500 slug = Webflow.env('slug') || location.pathname || ''; 2501 2502 // Reset scroll listener, init anchors 2503 Webflow.scroll.off(scroll); 2504 anchors = []; 2505 2506 // Test all links for a selectable href 2507 var links = document.links; 2508 for (var i = 0; i < links.length; ++i) { 2509 select(links[i]); 2510 } 2511 2512 // Listen for scroll if any anchors exist 2513 if (anchors.length) { 2514 Webflow.scroll.on(scroll); 2515 scroll(); 2516 } 2517 } 2518 2519 function select(link) { 2520 var href = (designer && link.getAttribute('href-disabled')) || link.getAttribute('href'); 2521 tempLink.href = href; 2522 2523 // Ignore any hrefs with a colon to safely avoid all uri schemes 2524 if (href.indexOf(':') >= 0) return; 2525 2526 var $link = $(link); 2527 2528 // Check for valid hash links w/ sections and use scroll anchor 2529 if (href.indexOf('#') === 0 && validHash.test(href)) { 2530 var $section = $(href); 2531 $section.length && anchors.push({ link: $link, sec: $section, active: false }); 2532 return; 2533 } 2534 2535 // Ignore empty # links 2536 if (href === '#') return; 2537 2538 // Determine whether the link should be selected 2539 var match = (tempLink.href === location.href) || (href === slug) || (indexPage.test(href) && dirList.test(slug)); 2540 setClass($link, linkCurrent, match); 2541 } 2542 2543 function scroll() { 2544 var viewTop = $win.scrollTop(); 2545 var viewHeight = $win.height(); 2546 2547 // Check each anchor for a section in view 2548 _.each(anchors, function(anchor) { 2549 var $link = anchor.link; 2550 var $section = anchor.sec; 2551 var top = $section.offset().top; 2552 var height = $section.outerHeight(); 2553 var offset = viewHeight * 0.5; 2554 var active = ($section.is(':visible') && 2555 top + height - offset >= viewTop && 2556 top + offset <= viewTop + viewHeight); 2557 if (anchor.active === active) return; 2558 anchor.active = active; 2559 setClass($link, linkCurrent, active); 2560 if (designer) $link[0].__wf_current = active; 2561 }); 2562 } 2563 2564 function setClass($elem, className, add) { 2565 var exists = $elem.hasClass(className); 2566 if (add && exists) return; 2567 if (!add && !exists) return; 2568 add ? $elem.addClass(className) : $elem.removeClass(className); 2569 } 2570 2571 // Export module 2572 return api; 2573 }); 2574 2575 2576/***/ }, 2577/* 15 */ 2578/***/ function(module, exports, __webpack_require__) { 2579 2580 'use strict'; 2581 2582 /** 2583 * Webflow: Maps widget 2584 */ 2585 2586 var Webflow = __webpack_require__(1); 2587 2588 Webflow.define('maps', module.exports = function($, _) { 2589 var api = {}; 2590 var $doc = $(document); 2591 var google = null; 2592 var $maps; 2593 var namespace = '.w-widget-map'; 2594 2595 // ----------------------------------- 2596 // Module methods 2597 2598 api.ready = function() { 2599 // Init Maps on the front-end 2600 if (!Webflow.env()) initMaps(); 2601 }; 2602 2603 api.preview = function() { 2604 // Update active map nodes 2605 $maps = $doc.find(namespace); 2606 // Listen for resize events 2607 Webflow.resize.off(triggerRedraw); 2608 if ($maps.length) { 2609 Webflow.resize.on(triggerRedraw); 2610 triggerRedraw(); 2611 } 2612 }; 2613 2614 api.design = function(evt) { 2615 // Update active map nodes 2616 $maps = $doc.find(namespace); 2617 // Stop listening for resize events 2618 Webflow.resize.off(triggerRedraw); 2619 // Redraw to account for page changes 2620 $maps.length && _.defer(triggerRedraw); 2621 }; 2622 2623 api.destroy = removeListeners; 2624 2625 // ----------------------------------- 2626 // Private methods 2627 2628 // Trigger redraw in designer or preview mode 2629 function triggerRedraw() { 2630 if ($maps.length && Webflow.app) { 2631 $maps.each(Webflow.app.redrawElement); 2632 } 2633 } 2634 2635 function initMaps() { 2636 $maps = $doc.find(namespace); 2637 if (!$maps.length) return; 2638 2639 if (google === null) {
2640 $.getScript('https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&callback=_wf_maps_loaded'); 2641 window._wf_maps_loaded = mapsLoaded; 2642 } else { 2643 mapsLoaded(); 2644 } 2645 2646 function mapsLoaded() { 2647 window._wf_maps_loaded = function() {}; 2648 google = window.google; 2649 $maps.each(renderMap); 2650 removeListeners(); 2651 addListeners(); 2652 } 2653 } 2654 2655 function removeListeners() { 2656 Webflow.resize.off(resizeMaps); 2657 Webflow.redraw.off(resizeMaps); 2658 } 2659 2660 function addListeners() { 2661 Webflow.resize.on(resizeMaps); 2662 Webflow.redraw.on(resizeMaps); 2663 } 2664 2665 // Render map onto each element 2666 function renderMap(i, el) { 2667 var data = $(el).data(); 2668 getState(el, data); 2669 } 2670 2671 function resizeMaps() { 2672 $maps.each(resizeMap); 2673 } 2674 2675 // Resize map when window changes 2676 function resizeMap(i, el) { 2677 var state = getState(el); 2678 google.maps.event.trigger(state.map, 'resize'); 2679 state.setMapPosition(); 2680 } 2681 2682 // Store state on element data 2683 var store = 'w-widget-map'; 2684 function getState(el, data) { 2685 2686 var state = $.data(el, store); 2687 if (state) return state; 2688 2689 var $el = $(el); 2690 state = $.data(el, store, { 2691 // Default options 2692 latLng: '51.511214,-0.119824', 2693 tooltip: '', 2694 style: 'roadmap', 2695 zoom: 12, 2696 2697 // Marker 2698 marker: new google.maps.Marker({ 2699 draggable: false 2700 }), 2701 2702 // Tooltip infowindow 2703 infowindow: new google.maps.InfoWindow({ 2704 disableAutoPan: true 2705 }) 2706 }); 2707 2708 // LatLng center point 2709 var latLng = data.widgetLatlng || state.latLng; 2710 state.latLng = latLng; 2711 var coords = latLng.split(','); 2712 var latLngObj = new google.maps.LatLng(coords[0], coords[1]); 2713 state.latLngObj = latLngObj; 2714 2715 // Disable touch events 2716 var mapDraggable = (Webflow.env.touch && data.disableTouch) ? false : true; 2717 2718 // Map instance 2719 state.map = new google.maps.Map(el, { 2720 center: state.latLngObj, 2721 zoom: state.zoom, 2722 maxZoom: 18, 2723 mapTypeControl: false, 2724 panControl: false, 2725 streetViewControl: false, 2726 scrollwheel: !data.disableScroll, 2727 draggable: mapDraggable, 2728 zoomControl: true, 2729 zoomControlOptions: { 2730 style: google.maps.ZoomControlStyle.SMALL 2731 }, 2732 mapTypeId: state.style 2733 }); 2734 state.marker.setMap(state.map); 2735 2736 // Set map position and offset 2737 state.setMapPosition = function() { 2738 state.map.setCenter(state.latLngObj); 2739 var offsetX = 0; 2740 var offsetY = 0; 2741 var padding = $el.css(['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft']); 2742 offsetX -= parseInt(padding.paddingLeft, 10); 2743 offsetX += parseInt(padding.paddingRight, 10); 2744 offsetY -= parseInt(padding.paddingTop, 10); 2745 offsetY += parseInt(padding.paddingBottom, 10); 2746 if (offsetX || offsetY) { 2747 state.map.panBy(offsetX, offsetY); 2748 } 2749 $el.css('position', ''); // Remove injected position 2750 }; 2751 2752 // Fix position after first tiles have loaded 2753 google.maps.event.addListener(state.map, 'tilesloaded', function() { 2754 google.maps.event.clearListeners(state.map, 'tilesloaded'); 2755 state.setMapPosition(); 2756 }); 2757 2758 // Set initial position 2759 state.setMapPosition(); 2760 state.marker.setPosition(state.latLngObj); 2761 state.infowindow.setPosition(state.latLngObj); 2762 2763 // Draw tooltip 2764 var tooltip = data.widgetTooltip; 2765 if (tooltip) { 2766 state.tooltip = tooltip; 2767 state.infowindow.setContent(tooltip); 2768 if (!state.infowindowOpen) { 2769 state.infowindow.open(state.map, state.marker); 2770 state.infowindowOpen = true; 2771 } 2772 } 2773 2774 // Map style - options.style 2775 var style = data.widgetStyle; 2776 if (style) { 2777 state.map.setMapTypeId(style); 2778 } 2779 2780 // Zoom - options.zoom 2781 var zoom = data.widgetZoom; 2782 if (zoom != null) { 2783 state.zoom = zoom; 2784 state.map.setZoom(+zoom); 2785 } 2786 2787 // Click marker to open in google maps 2788 google.maps.event.addListener(state.marker, 'click', function() { 2789 window.open('https://maps.google.com/?z=' + state.zoom + '&daddr=' + state.latLng); 2790 }); 2791 2792 return state; 2793 } 2794 2795 // Export module 2796 return api; 2797 }); 2798 2799 2800/***/ }, 2801/* 16 */ 2802/***/ function(module, exports, __webpack_require__) { 2803 2804 'use strict'; 2805 2806 /** 2807 * Webflow: Navbar component 2808 */ 2809 2810 var Webflow = __webpack_require__(1); 2811 var IXEvents = __webpack_require__(2); 2812 2813 Webflow.define('navbar', module.exports = function($, _) { 2814 var api = {}; 2815 var tram = $.tram; 2816 var $win = $(window); 2817 var $doc = $(document); 2818 var $body;
2819 var $navbars; 2820 var designer; 2821 var inApp = Webflow.env(); 2822 var overlay = '<div class="w-nav-overlay" data-wf-ignore />'; 2823 var namespace = '.w-nav'; 2824 var buttonOpen = 'w--open'; 2825 var menuOpen = 'w--nav-menu-open'; 2826 var linkOpen = 'w--nav-link-open'; 2827 var ix = IXEvents.triggers; 2828 var menuSibling = $(); 2829 2830 // ----------------------------------- 2831 // Module methods 2832 2833 api.ready = api.design = api.preview = init; 2834 2835 api.destroy = function() { 2836 menuSibling = $(); 2837 removeListeners(); 2838 if ($navbars && $navbars.length) { 2839 $navbars.each(teardown); 2840 } 2841 }; 2842 2843 // ----------------------------------- 2844 // Private methods 2845 2846 function init() { 2847 designer = inApp && Webflow.env('design'); 2848 $body = $(document.body); 2849 2850 // Find all instances on the page 2851 $navbars = $doc.find(namespace); 2852 if (!$navbars.length) return; 2853 $navbars.each(build); 2854 2855 // Wire events 2856 removeListeners(); 2857 addListeners(); 2858 } 2859 2860 function removeListeners() { 2861 Webflow.resize.off(resizeAll); 2862 } 2863 2864 function addListeners() { 2865 Webflow.resize.on(resizeAll); 2866 } 2867 2868 function resizeAll() { 2869 $navbars.each(resize); 2870 } 2871 2872 function build(i, el) { 2873 var $el = $(el); 2874 2875 // Store state in data 2876 var data = $.data(el, namespace); 2877 if (!data) data = $.data(el, namespace, { open: false, el: $el, config: {} }); 2878 data.menu = $el.find('.w-nav-menu'); 2879 data.links = data.menu.find('.w-nav-link'); 2880 data.dropdowns = data.menu.find('.w-dropdown'); 2881 data.button = $el.find('.w-nav-button'); 2882 data.container = $el.find('.w-container'); 2883 data.outside = outside(data); 2884 2885 // Remove old events 2886 data.el.off(namespace); 2887 data.button.off(namespace); 2888 data.menu.off(namespace); 2889 2890 // Set config from data attributes 2891 configure(data); 2892 2893 // Add events based on mode 2894 if (designer) { 2895 removeOverlay(data); 2896 data.el.on('setting' + namespace, handler(data)); 2897 } else { 2898 addOverlay(data); 2899 data.button.on('tap' + namespace, toggle(data)); 2900 data.menu.on('click' + namespace, 'a', navigate(data)); 2901 } 2902 2903 // Trigger initial resize 2904 resize(i, el); 2905 } 2906 2907 function teardown(i, el) { 2908 var data = $.data(el, namespace); 2909 if (data) { 2910 removeOverlay(data); 2911 $.removeData(el, namespace); 2912 } 2913 } 2914 2915 function removeOverlay(data) { 2916 if (!data.overlay) return; 2917 close(data, true); 2918 data.overlay.remove(); 2919 data.overlay = null; 2920 } 2921 2922 function addOverlay(data) { 2923 if (data.overlay) return; 2924 data.overlay = $(overlay).appendTo(data.el); 2925 data.parent = data.menu.parent(); 2926 close(data, true); 2927 } 2928 2929 function configure(data) { 2930 var config = {}; 2931 var old = data.config || {}; 2932 2933 // Set config options from data attributes 2934 var animation = config.animation = data.el.attr('data-animation') || 'default'; 2935 config.animOver = /^over/.test(animation); 2936 config.animDirect = /left$/.test(animation) ? -1 : 1; 2937 2938 // Re-open menu if the animation type changed 2939 if (old.animation !== animation) { 2940 data.open && _.defer(reopen, data); 2941 } 2942 2943 config.easing = data.el.attr('data-easing') || 'ease'; 2944 config.easing2 = data.el.attr('data-easing2') || 'ease'; 2945 2946 var duration = data.el.attr('data-duration'); 2947 config.duration = duration != null ? Number(duration) : 400; 2948 2949 config.docHeight = data.el.attr('data-doc-height'); 2950 2951 // Store config in data 2952 data.config = config; 2953 } 2954 2955 function handler(data) { 2956 return function(evt, options) { 2957 options = options || {}; 2958 var winWidth = $win.width(); 2959 configure(data); 2960 options.open === true && open(data, true); 2961 options.open === false && close(data, true); 2962 // Reopen if media query changed after setting 2963 data.open && _.defer(function() { 2964 if (winWidth !== $win.width()) reopen(data); 2965 }); 2966 }; 2967 } 2968 2969 function reopen(data) { 2970 if (!data.open) return; 2971 close(data, true); 2972 open(data, true); 2973 } 2974 2975 function toggle(data) { 2976 // Debounce toggle to wait for accurate open state 2977 return _.debounce(function() { 2978 data.open ? close(data) : open(data); 2979 }); 2980 } 2981 2982 function navigate(data) { 2983 return function(evt) { 2984 var link = $(this); 2985 var href = link.attr('href'); 2986 2987 // Avoid late clicks on touch devices 2988 if (!Webflow.validClick(evt.currentTarget)) { 2989 evt.preventDefault(); 2990 return; 2991 } 2992 2993 // Close when navigating to an in-page anchor 2994 if (href && href.indexOf('#') === 0 && data.open) { 2995 close(data); 2996 } 2997 }; 2998 } 2999 3000 function outside(data) { 3001 // Unbind previous tap handler if it exists 3002 if (data.outside) $doc.off('tap' + namespace, data.outside); 3003 3004 // Close menu when tapped outside, debounced to wait for state 3005 return _.debounce(function(evt) { 3006 if (!data.open) return; 3007 var menu = $(evt.target).closest('.w-nav-menu'); 3008 if (!data.menu.is(menu)) { 3009 close(data); 3010 } 3011 }); 3012 } 3013 3014 function resize(i, el) { 3015 var data = $.data(el, namespace);
3016 // Check for collapsed state based on button display 3017 var collapsed = data.collapsed = data.button.css('display') !== 'none'; 3018 // Close menu if button is no longer visible (and not in designer) 3019 if (data.open && !collapsed && !designer) close(data, true); 3020 // Set max-width of links + dropdowns to match container 3021 if (data.container.length) { 3022 var updateEachMax = updateMax(data); 3023 data.links.each(updateEachMax); 3024 data.dropdowns.each(updateEachMax); 3025 } 3026 // If currently open, update height to match body 3027 if (data.open) { 3028 setOverlayHeight(data); 3029 } 3030 } 3031 3032 var maxWidth = 'max-width'; 3033 function updateMax(data) { 3034 // Set max-width of each element to match container 3035 var containMax = data.container.css(maxWidth); 3036 if (containMax === 'none') containMax = ''; 3037 return function(i, link) { 3038 link = $(link); 3039 link.css(maxWidth, ''); 3040 // Don't set the max-width if an upstream value exists 3041 if (link.css(maxWidth) === 'none') link.css(maxWidth, containMax); 3042 }; 3043 } 3044 3045 function open(data, immediate) { 3046 if (data.open) return; 3047 data.open = true; 3048 data.menu.addClass(menuOpen); 3049 data.links.addClass(linkOpen); 3050 data.button.addClass(buttonOpen); 3051 var config = data.config; 3052 var animation = config.animation; 3053 if (animation === 'none' || !tram.support.transform) immediate = true; 3054 var bodyHeight = setOverlayHeight(data); 3055 var menuHeight = data.menu.outerHeight(true); 3056 var menuWidth = data.menu.outerWidth(true); 3057 var navHeight = data.el.height(); 3058 var navbarEl = data.el[0]; 3059 resize(0, navbarEl); 3060 ix.intro(0, navbarEl); 3061 Webflow.redraw.up(); 3062 3063 // Listen for tap outside events 3064 if (!designer) $doc.on('tap' + namespace, data.outside); 3065 3066 // No transition for immediate 3067 if (immediate) return; 3068 3069 var transConfig = 'transform ' + config.duration + 'ms ' + config.easing; 3070 3071 // Add menu to overlay 3072 if (data.overlay) { 3073 menuSibling = data.menu.prev(); 3074 data.overlay.show().append(data.menu); 3075 } 3076 3077 // Over left/right 3078 if (config.animOver) { 3079 tram(data.menu) 3080 .add(transConfig) 3081 .set({ x: config.animDirect * menuWidth, height: bodyHeight }).start({ x: 0 }); 3082 data.overlay && data.overlay.width(menuWidth); 3083 return; 3084 } 3085 3086 // Drop Down 3087 var offsetY = navHeight + menuHeight; 3088 tram(data.menu) 3089 .add(transConfig) 3090 .set({ y: -offsetY }).start({ y: 0 }); 3091 } 3092 3093 function setOverlayHeight(data) { 3094 var config = data.config; 3095 var bodyHeight = config.docHeight ? $doc.height() : $body.height(); 3096 if (config.animOver) { 3097 data.menu.height(bodyHeight); 3098 } else if (data.el.css('position') !== 'fixed') { 3099 bodyHeight -= data.el.height(); 3100 } 3101 data.overlay && data.overlay.height(bodyHeight); 3102 return bodyHeight; 3103 } 3104 3105 function close(data, immediate) { 3106 if (!data.open) return; 3107 data.open = false; 3108 data.button.removeClass(buttonOpen); 3109 var config = data.config; 3110 if (config.animation === 'none' || !tram.support.transform) immediate = true; 3111 ix.outro(0, data.el[0]); 3112 3113 // Stop listening for tap outside events 3114 $doc.off('tap' + namespace, data.outside); 3115 3116 if (immediate) { 3117 tram(data.menu).stop(); 3118 complete(); 3119 return; 3120 } 3121 3122 var transConfig = 'transform ' + config.duration + 'ms ' + config.easing2; 3123 var menuHeight = data.menu.outerHeight(true); 3124 var menuWidth = data.menu.outerWidth(true); 3125 var navHeight = data.el.height(); 3126 3127 // Over left/right 3128 if (config.animOver) { 3129 tram(data.menu) 3130 .add(transConfig) 3131 .start({ x: menuWidth * config.animDirect }).then(complete); 3132 return; 3133 } 3134 3135 // Drop Down 3136 var offsetY = navHeight + menuHeight; 3137 tram(data.menu) 3138 .add(transConfig) 3139 .start({ y: -offsetY }).then(complete); 3140 3141 function complete() { 3142 data.menu.height(''); 3143 tram(data.menu).set({ x: 0, y: 0 }); 3144 data.menu.removeClass(menuOpen); 3145 data.links.removeClass(linkOpen); 3146 if (data.overlay && data.overlay.children().length) { 3147 // Move menu back to parent at the original location 3148 menuSibling.length ? data.menu.insertAfter(menuSibling) : data.menu.prependTo(data.parent); 3149 data.overlay.attr('style', '').hide(); 3150 } 3151 3152 // Trigger event so other components can hook in (dropdown) 3153 data.el.triggerHandler('w-close'); 3154 } 3155 } 3156 3157 // Export module 3158 return api; 3159 }); 3160 3161 3162/***/ }, 3163/* 17 */ 3164/***/ function(module, exports, __webpack_require__) { 3165 3166 'use strict'; 3167 3168 /** 3169 * Webflow: Smooth scroll 3170 */ 3171 3172 var Webflow = __webpack_require__(1); 3173 3174 Webflow.define('scroll', module.exports = function($, _) { 3175 var $doc = $(document); 3176 var win = window; 3177 var loc = win.location; 3178 var history = inIframe() ? null : win.history;
3179 var validHash = /^[a-zA-Z0-9][\w:.-]*$/; 3180 3181 function inIframe() { 3182 try { 3183 return !!win.frameElement; 3184 } catch (e) { 3185 return true; 3186 } 3187 } 3188 3189 function ready() { 3190 // If hash is already present on page load, scroll to it right away 3191 if (loc.hash) { 3192 findEl(loc.hash.substring(1)); 3193 } 3194 3195 // The current page url without the hash part. 3196 var locHref = loc.href.split('#')[0]; 3197 3198 // When clicking on a link, check if it links to another part of the page 3199 $doc.on('click', 'a', function(e) { 3200 if (Webflow.env('design')) { 3201 return; 3202 } 3203 3204 // Ignore links being used by jQuery mobile 3205 if (window.$.mobile && $(e.currentTarget).hasClass('ui-link')) return; 3206 3207 // Ignore empty # links 3208 if (this.getAttribute('href') === '#') { 3209 e.preventDefault(); 3210 return; 3211 } 3212 3213 // The href property always contains the full url so we can compare 3214 // with the documentâs location to only target links on this page. 3215 var parts = this.href.split('#'); 3216 var hash = parts[0] === locHref ? parts[1] : null; 3217 if (hash) { 3218 findEl(hash, e); 3219 } 3220 }); 3221 } 3222 3223 function findEl(hash, e) { 3224 if (!validHash.test(hash)) return; 3225 3226 var el = $('#' + hash); 3227 if (!el.length) { 3228 return; 3229 } 3230 3231 if (e) { 3232 e.preventDefault(); 3233 e.stopPropagation(); 3234 } 3235 3236 // Push new history state 3237 if ( 3238 loc.hash !== hash && 3239 history && history.pushState && 3240 // Navigation breaks Chrome when the protocol is `file:`. 3241 !(Webflow.env.chrome && loc.protocol === 'file:') 3242 ) { 3243 var oldHash = history.state && history.state.hash; 3244 if (oldHash !== hash) { 3245 history.pushState({ hash: hash }, '', '#' + hash); 3246 } 3247 } 3248 3249 // If a fixed header exists, offset for the height 3250 var rootTag = Webflow.env('editor') ? '.w-editor-body' : 'body'; 3251 var header = $('header, ' + rootTag + ' > .header, ' + rootTag + ' > .w-nav:not([data-no-scroll])'); 3252 var offset = header.css('position') === 'fixed' ? header.outerHeight() : 0; 3253 3254 win.setTimeout(function() { 3255 scroll(el, offset); 3256 }, e ? 0 : 300); 3257 } 3258 3259 function scroll(el, offset){ 3260 var start = $(win).scrollTop(); 3261 var end = el.offset().top - offset; 3262 3263 // If specified, scroll so that the element ends up in the middle of the viewport 3264 if (el.data('scroll') === 'mid') { 3265 var available = $(win).height() - offset; 3266 var elHeight = el.outerHeight(); 3267 if (elHeight < available) { 3268 end -= Math.round((available - elHeight) / 2); 3269 } 3270 } 3271 3272 var mult = 1; 3273 3274 // Check for custom time multiplier on the body and the element 3275 $('body').add(el).each(function(i) { 3276 var time = parseFloat($(this).attr('data-scroll-time'), 10); 3277 if (!isNaN(time) && (time === 0 || time > 0)) { 3278 mult = time; 3279 } 3280 }); 3281 3282 // Shim for IE8 and below 3283 if (!Date.now) { 3284 Date.now = function() { return new Date().getTime(); }; 3285 } 3286 3287 var clock = Date.now(); 3288 var animate = win.requestAnimationFrame || win.mozRequestAnimationFrame || win.webkitRequestAnimationFrame || function(fn) { win.setTimeout(fn, 15); }; 3289 var duration = (472.143 * Math.log(Math.abs(start - end) +125) - 2000) * mult; 3290 3291 var step = function() { 3292 var elapsed = Date.now() - clock; 3293 win.scroll(0, getY(start, end, elapsed, duration)); 3294 3295 if (elapsed <= duration) { 3296 animate(step); 3297 } 3298 }; 3299 3300 step(); 3301 } 3302 3303 function getY(start, end, elapsed, duration) { 3304 if (elapsed > duration) { 3305 return end; 3306 } 3307 3308 return start + (end - start) * ease(elapsed / duration); 3309 } 3310 3311 function ease(t) { 3312 return t<0.5 ? 4 * t * t * t : (t-1) * (2 * t-2) * (2 * t-2)+1; 3313 } 3314 3315 // Export module 3316 return { ready: ready }; 3317 }); 3318 3319 3320/***/ }, 3321/* 18 */ 3322/***/ function(module, exports, __webpack_require__) { 3323 3324 'use strict'; 3325 3326 /** 3327 * Webflow: Slider component 3328 */ 3329 3330 var Webflow = __webpack_require__(1); 3331 var IXEvents = __webpack_require__(2); 3332 3333 Webflow.define('slider', module.exports = function($, _) { 3334 var api = {}; 3335 var tram = $.tram; 3336 var $doc = $(document); 3337 var $sliders; 3338 var designer; 3339 var inApp = Webflow.env(); 3340 var namespace = '.w-slider'; 3341 var dot = '<div class="w-slider-dot" data-wf-ignore />'; 3342 var ix = IXEvents.triggers; 3343 var fallback; 3344 var inRedraw; 3345 3346 // ----------------------------------- 3347 // Module methods 3348 3349 api.ready = function() { 3350 init(); 3351 }; 3352 3353 api.design = function() { 3354 designer = true; 3355 init(); 3356 }; 3357 3358 api.preview = function() { 3359 designer = false;
3360 init(); 3361 }; 3362 3363 api.redraw = function() { 3364 inRedraw = true; 3365 init(); 3366 }; 3367 3368 api.destroy = removeListeners; 3369 3370 // ----------------------------------- 3371 // Private methods 3372 3373 function init() { 3374 // Find all sliders on the page 3375 $sliders = $doc.find(namespace); 3376 if (!$sliders.length) return; 3377 $sliders.filter(':visible').each(build); 3378 inRedraw = null; 3379 if (fallback) return; 3380 3381 removeListeners(); 3382 addListeners(); 3383 } 3384 3385 function removeListeners() { 3386 Webflow.resize.off(renderAll); 3387 Webflow.redraw.off(api.redraw); 3388 } 3389 3390 function addListeners() { 3391 Webflow.resize.on(renderAll); 3392 Webflow.redraw.on(api.redraw); 3393 } 3394 3395 function renderAll() { 3396 $sliders.filter(':visible').each(render); 3397 } 3398 3399 function build(i, el) { 3400 var $el = $(el); 3401 3402 // Store slider state in data 3403 var data = $.data(el, namespace); 3404 if (!data) { 3405 data = $.data(el, namespace, { 3406 index: 0, 3407 depth: 1, 3408 el: $el, 3409 config: {} 3410 }); 3411 } 3412 data.mask = $el.children('.w-slider-mask'); 3413 data.left = $el.children('.w-slider-arrow-left'); 3414 data.right = $el.children('.w-slider-arrow-right'); 3415 data.nav = $el.children('.w-slider-nav'); 3416 data.slides = data.mask.children('.w-slide'); 3417 data.slides.each(ix.reset); 3418 if (inRedraw) data.maskWidth = 0; 3419 3420 // Disable in old browsers 3421 if (!tram.support.transform) { 3422 data.left.hide(); 3423 data.right.hide(); 3424 data.nav.hide(); 3425 fallback = true; 3426 return; 3427 } 3428 3429 // Remove old events 3430 data.el.off(namespace); 3431 data.left.off(namespace); 3432 data.right.off(namespace); 3433 data.nav.off(namespace); 3434 3435 // Set config from data attributes 3436 configure(data); 3437 3438 // Add events based on mode 3439 if (designer) { 3440 data.el.on('setting' + namespace, handler(data)); 3441 stopTimer(data); 3442 data.hasTimer = false; 3443 } else { 3444 data.el.on('swipe' + namespace, handler(data)); 3445 data.left.on('tap' + namespace, previousFunction(data)); 3446 data.right.on('tap' + namespace, next(data)); 3447 3448 // Start timer if autoplay is true, only once 3449 if (data.config.autoplay && !data.hasTimer) { 3450 data.hasTimer = true; 3451 data.timerCount = 1; 3452 startTimer(data); 3453 } 3454 } 3455 3456 // Listen to nav events 3457 data.nav.on('tap' + namespace, '> div', handler(data)); 3458 3459 // Remove gaps from formatted html (for inline-blocks) 3460 if (!inApp) { 3461 data.mask.contents().filter(function() { 3462 return this.nodeType === 3; 3463 }).remove(); 3464 } 3465 3466 // Run first render 3467 render(i, el); 3468 } 3469 3470 function configure(data) { 3471 var config = {}; 3472 3473 config.crossOver = 0; 3474 3475 // Set config options from data attributes 3476 config.animation = data.el.attr('data-animation') || 'slide'; 3477 if (config.animation === 'outin') { 3478 config.animation = 'cross'; 3479 config.crossOver = 0.5; 3480 } 3481 config.easing = data.el.attr('data-easing') || 'ease'; 3482 3483 var duration = data.el.attr('data-duration'); 3484 config.duration = duration != null ? +duration : 500; 3485 3486 if (+data.el.attr('data-infinite')) config.infinite = true; 3487 if (+data.el.attr('data-disable-swipe')) config.disableSwipe = true; 3488 3489 if (+data.el.attr('data-hide-arrows')) { 3490 config.hideArrows = true; 3491 } else if (data.config.hideArrows) { 3492 data.left.show(); 3493 data.right.show(); 3494 } 3495 3496 if (+data.el.attr('data-autoplay')) { 3497 config.autoplay = true; 3498 config.delay = +data.el.attr('data-delay') || 2000; 3499 config.timerMax = +data.el.attr('data-autoplay-limit'); 3500 // Disable timer on first touch or mouse down 3501 var touchEvents = 'mousedown' + namespace + ' touchstart' + namespace; 3502 if (!designer) { 3503 data.el.off(touchEvents).one(touchEvents, function() { 3504 stopTimer(data); 3505 }); 3506 } 3507 } 3508 3509 // Use edge buffer to help calculate page count 3510 var arrowWidth = data.right.width(); 3511 config.edge = arrowWidth ? arrowWidth + 40 : 100; 3512 3513 // Store config in data 3514 data.config = config; 3515 } 3516 3517 function previousFunction(data) { 3518 return function(evt) { 3519 change(data, { index: data.index - 1, vector: -1 }); 3520 }; 3521 } 3522 3523 function next(data) { 3524 return function(evt) { 3525 change(data, { index: data.index + 1, vector: 1 }); 3526 }; 3527 } 3528 3529 function select(data, value) { 3530 // Select page based on slide element index 3531 var found = null; 3532 if (value === data.slides.length) { 3533 init(); layout(data); // Rebuild and find new slides 3534 } 3535 _.each(data.anchors, function(anchor, index) { 3536 $(anchor.els).each(function(i, el) { 3537 if ($(el).index() === value) found = index; 3538 }); 3539 }); 3540 if (found != null) change(data, { index: found, immediate: true }); 3541 } 3542 3543 function startTimer(data) { 3544 stopTimer(data); 3545 var config = data.config; 3546 var timerMax = config.timerMax; 3547 if (timerMax && data.timerCount++ > timerMax) return; 3548 data.timerId = window.setTimeout(function() { 3549 if (data.timerId == null || designer) return; 3550 next(data)(); 3551 startTimer(data); 3552 }, config.delay); 3553 } 3554 3555 function stopTimer(data) { 3556 window.clearTimeout(data.timerId); 3557 data.timerId = null; 3558 } 3559 3560 function handler(data) { 3561 return function(evt, options) { 3562 options = options || {}; 3563 var config = data.config; 3564 3565 // Designer settings 3566 if (designer && evt.type === 'setting') { 3567 if (options.select === 'prev') return previousFunction(data)(); 3568 if (options.select === 'next') return next(data)(); 3569 configure(data); 3570 layout(data); 3571 if (options.select == null) return; 3572 select(data, options.select); 3573 return; 3574 } 3575 3576 // Swipe event 3577 if (evt.type === 'swipe') { 3578 if (config.disableSwipe) return; 3579 if (Webflow.env('editor')) return; 3580 if (options.direction === 'left') return next(data)(); 3581 if (options.direction === 'right') return previousFunction(data)(); 3582 return; 3583 } 3584 3585 // Page buttons 3586 if (data.nav.has(evt.target).length) { 3587 change(data, { index: $(evt.target).index() }); 3588 } 3589 }; 3590 } 3591 3592 function change(data, options) { 3593 options = options || {}; 3594 var config = data.config; 3595 var anchors = data.anchors; 3596 3597 // Set new index 3598 data.previous = data.index; 3599 var index = options.index; 3600 var shift = {}; 3601 if (index < 0) { 3602 index = anchors.length - 1; 3603 if (config.infinite) { 3604 // Shift first slide to the end 3605 shift.x = -data.endX; 3606 shift.from = 0; 3607 shift.to = anchors[0].width; 3608 } 3609 } else if (index >= anchors.length) { 3610 index = 0; 3611 if (config.infinite) { 3612 // Shift last slide to the start
3613 shift.x = anchors[anchors.length - 1].width; 3614 shift.from = -anchors[anchors.length - 1].x; 3615 shift.to = shift.from - shift.x; 3616 } 3617 } 3618 data.index = index; 3619 3620 // Select page nav 3621 var active = data.nav.children().eq(data.index).addClass('w-active'); 3622 data.nav.children().not(active).removeClass('w-active'); 3623 3624 // Hide arrows 3625 if (config.hideArrows) { 3626 data.index === anchors.length - 1 ? data.right.hide() : data.right.show(); 3627 data.index === 0 ? data.left.hide() : data.left.show(); 3628 } 3629 3630 // Get page offset from anchors 3631 var lastOffsetX = data.offsetX || 0; 3632 var offsetX = data.offsetX = -anchors[data.index].x; 3633 var resetConfig = { x: offsetX, opacity: 1, visibility: '' }; 3634 3635 // Transition slides 3636 var targets = $(anchors[data.index].els); 3637 var prevTargs = $(anchors[data.previous] && anchors[data.previous].els); 3638 var others = data.slides.not(targets); 3639 var animation = config.animation; 3640 var easing = config.easing; 3641 var duration = Math.round(config.duration); 3642 var vector = options.vector || (data.index > data.previous ? 1 : -1); 3643 var fadeRule = 'opacity ' + duration + 'ms ' + easing; 3644 var slideRule = 'transform ' + duration + 'ms ' + easing; 3645 3646 // Trigger IX events 3647 if (!designer) { 3648 targets.each(ix.intro); 3649 others.each(ix.outro); 3650 } 3651 3652 // Set immediately after layout changes (but not during redraw) 3653 if (options.immediate && !inRedraw) { 3654 tram(targets).set(resetConfig); 3655 resetOthers(); 3656 return; 3657 } 3658 3659 // Exit early if index is unchanged 3660 if (data.index === data.previous) return; 3661 3662 // Cross Fade / Out-In 3663 if (animation === 'cross') { 3664 var reduced = Math.round(duration - duration * config.crossOver); 3665 var wait = Math.round(duration - reduced); 3666 fadeRule = 'opacity ' + reduced + 'ms ' + easing; 3667 tram(prevTargs) 3668 .set({ visibility: '' }) 3669 .add(fadeRule) 3670 .start({ opacity: 0 }); 3671 tram(targets) 3672 .set({ visibility: '', x: offsetX, opacity: 0, zIndex: data.depth++ }) 3673 .add(fadeRule) 3674 .wait(wait) 3675 .then({ opacity: 1 }) 3676 .then(resetOthers); 3677 return; 3678 } 3679 3680 // Fade Over 3681 if (animation === 'fade') { 3682 tram(prevTargs) 3683 .set({ visibility: '' }) 3684 .stop(); 3685 tram(targets) 3686 .set({ visibility: '', x: offsetX, opacity: 0, zIndex: data.depth++ }) 3687 .add(fadeRule) 3688 .start({ opacity: 1 }) 3689 .then(resetOthers); 3690 return; 3691 } 3692 3693 // Slide Over 3694 if (animation === 'over') { 3695 resetConfig = { x: data.endX }; 3696 tram(prevTargs) 3697 .set({ visibility: '' }) 3698 .stop(); 3699 tram(targets) 3700 .set({ visibility: '', zIndex: data.depth++, x: offsetX + anchors[data.index].width * vector }) 3701 .add(slideRule) 3702 .start({ x: offsetX }) 3703 .then(resetOthers); 3704 return; 3705 } 3706 3707 // Slide - infinite scroll 3708 if (config.infinite && shift.x) { 3709 tram(data.slides.not(prevTargs)) 3710 .set({ visibility: '', x: shift.x }) 3711 .add(slideRule) 3712 .start({ x: offsetX }); 3713 tram(prevTargs) 3714 .set({ visibility: '', x: shift.from }) 3715 .add(slideRule) 3716 .start({ x: shift.to }); 3717 data.shifted = prevTargs; 3718 3719 } else { 3720 if (config.infinite && data.shifted) { 3721 tram(data.shifted).set({ visibility: '', x: lastOffsetX }); 3722 data.shifted = null; 3723 } 3724 3725 // Slide - basic scroll 3726 tram(data.slides) 3727 .set({ visibility: '' }) 3728 .add(slideRule) 3729 .start({ x: offsetX }); 3730 } 3731 3732 // Helper to move others out of view 3733 function resetOthers() { 3734 targets = $(anchors[data.index].els); 3735 others = data.slides.not(targets); 3736 if (animation !== 'slide') resetConfig.visibility = 'hidden'; 3737 tram(others).set(resetConfig); 3738 } 3739 } 3740 3741 function render(i, el) { 3742 var data = $.data(el, namespace); 3743 if (maskChanged(data)) return layout(data); 3744 if (designer && slidesChanged(data)) layout(data); 3745 } 3746 3747 function layout(data) { 3748 // Determine page count from width of slides 3749 var pages = 1; 3750 var offset = 0; 3751 var anchor = 0; 3752 var width = 0; 3753 var maskWidth = data.maskWidth; 3754 var threshold = maskWidth - data.config.edge; 3755 if (threshold < 0) threshold = 0; 3756 data.anchors = [{ els: [], x: 0, width: 0 }]; 3757 data.slides.each(function(i, el) { 3758 if (anchor - offset > threshold) { 3759 pages++; 3760 offset += maskWidth; 3761 // Store page anchor for transition 3762 data.anchors[pages - 1] = { els: [], x: anchor, width: 0 }; 3763 } 3764 // Set next anchor using current width + margin 3765 width = $(el).outerWidth(true); 3766 anchor += width; 3767 data.anchors[pages - 1].width += width; 3768 data.anchors[pages - 1].els.push(el); 3769 }); 3770 data.endX = anchor; 3771 3772 // Build dots if nav exists and needs updating 3773 if (designer) data.pages = null; 3774 if (data.nav.length && data.pages !== pages){ 3775 data.pages = pages; 3776 buildNav(data); 3777 } 3778 3779 // Make sure index is still within range and call change handler 3780 var index = data.index; 3781 if (index >= pages) index = pages - 1; 3782 change(data, { immediate: true, index: index }); 3783 } 3784 3785 function buildNav(data) { 3786 var dots = []; 3787 var $dot; 3788 var spacing = data.el.attr('data-nav-spacing'); 3789 if (spacing) spacing = parseFloat(spacing) + 'px'; 3790 for (var i = 0; i < data.pages; i++) { 3791 $dot = $(dot); 3792 if (data.nav.hasClass('w-num')) $dot.text(i + 1); 3793 if (spacing != null) { 3794 $dot.css({ 3795 'margin-left': spacing, 3796 'margin-right': spacing 3797 }); 3798 } 3799 dots.push($dot); 3800 } 3801 data.nav.empty().append(dots); 3802 } 3803 3804 function maskChanged(data) { 3805 var maskWidth = data.mask.width(); 3806 if (data.maskWidth !== maskWidth) { 3807 data.maskWidth = maskWidth; 3808 return true; 3809 } 3810 return false;
3811 } 3812 3813 function slidesChanged(data) { 3814 var slidesWidth = 0; 3815 data.slides.each(function(i, el) { 3816 slidesWidth += $(el).outerWidth(true); 3817 }); 3818 if (data.slidesWidth !== slidesWidth) { 3819 data.slidesWidth = slidesWidth; 3820 return true; 3821 } 3822 return false; 3823 } 3824 3825 // Export module 3826 return api; 3827 }); 3828 3829 3830/***/ }, 3831/* 19 */ 3832/***/ function(module, exports, __webpack_require__) { 3833 3834 'use strict'; 3835 3836 /** 3837 * Webflow: Tabs component 3838 */ 3839 3840 var Webflow = __webpack_require__(1); 3841 var IXEvents = __webpack_require__(2); 3842 3843 Webflow.define('tabs', module.exports = function($, _) { 3844 var api = {}; 3845 var tram = $.tram; 3846 var $win = $(window); 3847 var $doc = $(document); 3848 var $tabs; 3849 var design; 3850 var env = Webflow.env; 3851 var safari = env.safari; 3852 var inApp = env(); 3853 var tabAttr = 'data-w-tab'; 3854 var namespace = '.w-tabs'; 3855 var linkCurrent = 'w--current'; 3856 var tabActive = 'w--tab-active'; 3857 var ix = IXEvents.triggers; 3858 var inRedraw; 3859 3860 // ----------------------------------- 3861 // Module methods 3862 3863 api.ready = api.design = api.preview = init; 3864 3865 api.redraw = function() { 3866 inRedraw = true; 3867 init(); 3868 }; 3869 3870 api.destroy = function() { 3871 $tabs = $doc.find(namespace); 3872 if (!$tabs.length) return; 3873 $tabs.each(resetIX); 3874 removeListeners(); 3875 }; 3876 3877 // ----------------------------------- 3878 // Private methods 3879 3880 function init() { 3881 design = inApp && Webflow.env('design'); 3882 3883 // Find all instances on the page 3884 $tabs = $doc.find(namespace); 3885 if (!$tabs.length) return; 3886 $tabs.each(build); 3887 Webflow.env('preview') && $tabs.each(resetIX); 3888 inRedraw = null; 3889 3890 removeListeners(); 3891 addListeners(); 3892 } 3893 3894 function removeListeners() { 3895 Webflow.redraw.off(api.redraw); 3896 } 3897 3898 function addListeners() { 3899 Webflow.redraw.on(api.redraw); 3900 } 3901 3902 function resetIX(i, el) { 3903 var $el = $(el); 3904 var data = $.data(el, namespace); 3905 if (!data) return; 3906 data.links && data.links.each(ix.reset); 3907 data.panes && data.panes.each(ix.reset); 3908 } 3909 3910 function build(i, el) { 3911 var $el = $(el); 3912 3913 // Store state in data 3914 var data = $.data(el, namespace); 3915 if (!data) data = $.data(el, namespace, { el: $el, config: {} }); 3916 data.current = null; 3917 data.menu = $el.children('.w-tab-menu'); 3918 data.links = data.menu.children('.w-tab-link'); 3919 data.content = $el.children('.w-tab-content'); 3920 data.panes = data.content.children('.w-tab-pane'); 3921 3922 // Remove old events 3923 data.el.off(namespace); 3924 data.links.off(namespace); 3925 3926 // Set config from data attributes 3927 configure(data); 3928 3929 // Wire up events when not in design mode 3930 if (!design) { 3931 data.links.on('click' + namespace, linkSelect(data)); 3932 3933 // Trigger first intro event from current tab 3934 var $link = data.links.filter('.' + linkCurrent); 3935 var tab = $link.attr(tabAttr); 3936 tab && changeTab(data, { tab: tab, immediate: true }); 3937 } 3938 } 3939 3940 function configure(data) { 3941 var config = {}; 3942 var old = data.config || {}; 3943 3944 // Set config options from data attributes 3945 config.easing = data.el.attr('data-easing') || 'ease'; 3946 3947 var intro = +data.el.attr('data-duration-in'); 3948 intro = config.intro = intro === intro ? intro : 0; 3949 3950 var outro = +data.el.attr('data-duration-out'); 3951 outro = config.outro = outro === outro ? outro : 0; 3952 3953 config.immediate = !intro && !outro; 3954 3955 // Store config in data 3956 data.config = config; 3957 } 3958 3959 function linkSelect(data) { 3960 return function(evt) { 3961 var tab = evt.currentTarget.getAttribute(tabAttr); 3962 tab && changeTab(data, { tab: tab }); 3963 }; 3964 } 3965 3966 function changeTab(data, options) { 3967 options = options || {}; 3968 3969 var config = data.config; 3970 var easing = config.easing; 3971 var tab = options.tab; 3972 3973 // Don't select the same tab twice 3974 if (tab === data.current) return; 3975 data.current = tab; 3976 3977 // Select the current link 3978 data.links.each(function(i, el) { 3979 var $el = $(el); 3980 if (el.getAttribute(tabAttr) === tab) $el.addClass(linkCurrent).each(ix.intro); 3981 else if ($el.hasClass(linkCurrent)) $el.removeClass(linkCurrent).each(ix.outro); 3982 }); 3983 3984 // Find the new tab panes and keep track of previous 3985 var targets = []; 3986 var previous = []; 3987 data.panes.each(function(i, el) { 3988 var $el = $(el); 3989 if (el.getAttribute(tabAttr) === tab) { 3990 targets.push(el); 3991 } else if ($el.hasClass(tabActive)) { 3992 previous.push(el); 3993 } 3994 }); 3995 3996 var $targets = $(targets); 3997 var $previous = $(previous); 3998 3999 // Switch tabs immediately and bypass transitions 4000 if (options.immediate || config.immediate) { 4001 $targets.addClass(tabActive).each(ix.intro); 4002 $previous.removeClass(tabActive); 4003 // Redraw to benefit components in the hidden tab pane 4004 // But only if not currently in the middle of a redraw 4005 if (!inRedraw) Webflow.redraw.up(); 4006 return; 4007 } 4008 4009 // Fade out the currently active tab before intro 4010 if ($previous.length && config.outro) { 4011 $previous.each(ix.outro); 4012 tram($previous) 4013 .add('opacity ' + config.outro + 'ms ' + easing, { fallback: safari }) 4014 .start({ opacity: 0 }) 4015 .then(intro); 4016 } else { 4017 // Skip the outro and play intro 4018 intro(); 4019 } 4020 4021 // Fade in the new target 4022 function intro() { 4023 // Clear previous active class + styles touched by tram
4024 // We cannot remove the whole inline style because it could be dynamically bound 4025 $previous.removeClass(tabActive).css({ 4026 opacity: '', 4027 transition: '', 4028 transform: '', 4029 width: '', 4030 height: '' 4031 }); 4032 4033 // Add active class to new target 4034 $targets.addClass(tabActive).each(ix.intro); 4035 Webflow.redraw.up(); 4036 4037 // Set opacity immediately if intro is zero 4038 if (!config.intro) return tram($targets).set({ opacity: 1 }); 4039 4040 // Otherwise fade in opacity 4041 tram($targets) 4042 .set({ opacity: 0 }) 4043 .redraw() 4044 .add('opacity ' + config.intro + 'ms ' + easing, { fallback: safari }) 4045 .start({ opacity: 1 }); 4046 } 4047 } 4048 4049 // Export module 4050 return api; 4051 }); 4052 4053 4054/***/ }, 4055/* 20 */ 4056/***/ function(module, exports, __webpack_require__) { 4057 4058 'use strict'; 4059 4060 /** 4061 * Webflow: Touch events 4062 */ 4063 4064 var Webflow = __webpack_require__(1); 4065 4066 Webflow.define('touch', module.exports = function($, _) { 4067 var api = {}; 4068 var fallback = !document.addEventListener; 4069 var getSelection = window.getSelection; 4070 4071 // Fallback to click events in old IE 4072 if (fallback) { 4073 $.event.special.tap = { bindType: 'click', delegateType: 'click' }; 4074 } 4075 4076 api.init = function(el) { 4077 if (fallback) return null; 4078 el = typeof el === 'string' ? $(el).get(0) : el; 4079 return el ? new Touch(el) : null; 4080 }; 4081 4082 function Touch(el) { 4083 var active = false; 4084 var dirty = false; 4085 var useTouch = false; 4086 var thresholdX = Math.min(Math.round(window.innerWidth * 0.04), 40); 4087 var startX, startY, lastX; 4088 4089 el.addEventListener('touchstart', start, false); 4090 el.addEventListener('touchmove', move, false); 4091 el.addEventListener('touchend', end, false); 4092 el.addEventListener('touchcancel', cancel, false); 4093 el.addEventListener('mousedown', start, false); 4094 el.addEventListener('mousemove', move, false); 4095 el.addEventListener('mouseup', end, false); 4096 el.addEventListener('mouseout', cancel, false); 4097 4098 function start(evt) { 4099 // We donât handle multi-touch events yet. 4100 var touches = evt.touches; 4101 if (touches && touches.length > 1) { 4102 return; 4103 } 4104 4105 active = true; 4106 dirty = false; 4107 4108 if (touches) { 4109 useTouch = true; 4110 startX = touches[0].clientX; 4111 startY = touches[0].clientY; 4112 } else { 4113 startX = evt.clientX; 4114 startY = evt.clientY; 4115 } 4116 4117 lastX = startX; 4118 } 4119 4120 function move(evt) { 4121 if (!active) return; 4122 4123 if (useTouch && evt.type === 'mousemove') { 4124 evt.preventDefault(); 4125 evt.stopPropagation(); 4126 return; 4127 } 4128 4129 var touches = evt.touches; 4130 var x = touches ? touches[0].clientX : evt.clientX; 4131 var y = touches ? touches[0].clientY : evt.clientY; 4132 4133 var velocityX = x - lastX; 4134 lastX = x; 4135 4136 // Allow swipes while pointer is down, but prevent them during text selection 4137 if (Math.abs(velocityX) > thresholdX && getSelection && getSelection() + '' === '') { 4138 triggerEvent('swipe', evt, { direction: velocityX > 0 ? 'right' : 'left' }); 4139 cancel(); 4140 } 4141 4142 // If pointer moves more than 10px flag to cancel tap 4143 if (Math.abs(x - startX) > 10 || Math.abs(y - startY) > 10) { 4144 dirty = true; 4145 } 4146 } 4147 4148 function end(evt) { 4149 if (!active) return; 4150 active = false; 4151 4152 if (useTouch && evt.type === 'mouseup') { 4153 evt.preventDefault(); 4154 evt.stopPropagation(); 4155 useTouch = false; 4156 return; 4157 } 4158 4159 if (!dirty) triggerEvent('tap', evt); 4160 } 4161 4162 function cancel(evt) { 4163 active = false; 4164 } 4165 4166 function destroy() { 4167 el.removeEventListener('touchstart', start, false); 4168 el.removeEventListener('touchmove', move, false); 4169 el.removeEventListener('touchend', end, false); 4170 el.removeEventListener('touchcancel', cancel, false); 4171 el.removeEventListener('mousedown', start, false); 4172 el.removeEventListener('mousemove', move, false); 4173 el.removeEventListener('mouseup', end, false);
4174 el.removeEventListener('mouseout', cancel, false); 4175 el = null; 4176 } 4177 4178 // Public instance methods 4179 this.destroy = destroy; 4180 } 4181 4182 // Wrap native event to supoprt preventdefault + stopPropagation 4183 function triggerEvent(type, evt, data) { 4184 var newEvent = $.Event(type, { originalEvent: evt }); 4185 $(evt.target).trigger(newEvent, data); 4186 } 4187 4188 // Listen for touch events on all nodes by default. 4189 api.instance = api.init(document); 4190 4191 // Export module 4192 return api; 4193 }); 4194 4195 4196/***/ }, 4197/* 21 */ 4198/***/ function(module, exports, __webpack_require__) { 4199 4200 'use strict'; 4201 4202 /*jshint -W054 */ 4203 4204 // Include tram for frame-throttling 4205 var $ = window.$; 4206 var tram = __webpack_require__(3) && $.tram; 4207 4208 /*! 4209 * Webflow._ (aka) Underscore.js 1.6.0 (custom build) 4210 * _.each 4211 * _.map 4212 * _.find 4213 * _.filter 4214 * _.any 4215 * _.contains 4216 * _.delay 4217 * _.defer 4218 * _.throttle (webflow) 4219 * _.debounce 4220 * _.keys 4221 * _.has 4222 * _.now 4223 * 4224 * http://underscorejs.org 4225 * (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 4226 * Underscore may be freely distributed under the MIT license. 4227 * @license MIT 4228 */ 4229 module.exports = (function() { 4230 var _ = {}; 4231 4232 // Current version. 4233 _.VERSION = '1.6.0-Webflow'; 4234 4235 // Establish the object that gets returned to break out of a loop iteration. 4236 var breaker = {}; 4237 4238 // Save bytes in the minified (but not gzipped) version: 4239 var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; 4240 4241 // Create quick reference variables for speed access to core prototypes. 4242 var 4243 push = ArrayProto.push, 4244 slice = ArrayProto.slice, 4245 concat = ArrayProto.concat, 4246 toString = ObjProto.toString, 4247 hasOwnProperty = ObjProto.hasOwnProperty; 4248 4249 // All **ECMAScript 5** native function implementations that we hope to use 4250 // are declared here. 4251 var 4252 nativeForEach = ArrayProto.forEach, 4253 nativeMap = ArrayProto.map, 4254 nativeReduce = ArrayProto.reduce, 4255 nativeReduceRight = ArrayProto.reduceRight, 4256 nativeFilter = ArrayProto.filter, 4257 nativeEvery = ArrayProto.every, 4258 nativeSome = ArrayProto.some, 4259 nativeIndexOf = ArrayProto.indexOf, 4260 nativeLastIndexOf = ArrayProto.lastIndexOf, 4261 nativeIsArray = Array.isArray, 4262 nativeKeys = Object.keys, 4263 nativeBind = FuncProto.bind; 4264 4265 // Collection Functions 4266 // -------------------- 4267 4268 // The cornerstone, an `each` implementation, aka `forEach`. 4269 // Handles objects with the built-in `forEach`, arrays, and raw objects. 4270 // Delegates to **ECMAScript 5**'s native `forEach` if available. 4271 var each = _.each = _.forEach = function(obj, iterator, context) { 4272 /* jshint shadow:true */ 4273 if (obj == null) return obj; 4274 if (nativeForEach && obj.forEach === nativeForEach) { 4275 obj.forEach(iterator, context); 4276 } else if (obj.length === +obj.length) { 4277 for (var i = 0, length = obj.length; i < length; i++) { 4278 if (iterator.call(context, obj[i], i, obj) === breaker) return; 4279 } 4280 } else { 4281 var keys = _.keys(obj); 4282 for (var i = 0, length = keys.length; i < length; i++) { 4283 if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; 4284 } 4285 } 4286 return obj; 4287 }; 4288 4289 // Return the results of applying the iterator to each element. 4290 // Delegates to **ECMAScript 5**'s native `map` if available. 4291 _.map = _.collect = function(obj, iterator, context) { 4292 var results = []; 4293 if (obj == null) return results; 4294 if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); 4295 each(obj, function(value, index, list) { 4296 results.push(iterator.call(context, value, index, list)); 4297 }); 4298 return results; 4299 }; 4300 4301 // Return the first value which passes a truth test. Aliased as `detect`. 4302 _.find = _.detect = function(obj, predicate, context) { 4303 var result; 4304 any(obj, function(value, index, list) { 4305 if (predicate.call(context, value, index, list)) { 4306 result = value; 4307 return true; 4308 } 4309 }); 4310 return result; 4311 }; 4312 4313 // Return all the elements that pass a truth test. 4314 // Delegates to **ECMAScript 5**'s native `filter` if available. 4315 // Aliased as `select`. 4316 _.filter = _.select = function(obj, predicate, context) { 4317 var results = []; 4318 if (obj == null) return results; 4319 if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); 4320 each(obj, function(value, index, list) { 4321 if (predicate.call(context, value, index, list)) results.push(value); 4322 }); 4323 return results; 4324 }; 4325 4326 // Determine if at least one element in the object matches a truth test. 4327 // Delegates to **ECMAScript 5**'s native `some` if available. 4328 // Aliased as `any`. 4329 var any = _.some = _.any = function(obj, predicate, context) { 4330 predicate || (predicate = _.identity); 4331 var result = false;
4332 if (obj == null) return result; 4333 if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); 4334 each(obj, function(value, index, list) { 4335 if (result || (result = predicate.call(context, value, index, list))) return breaker; 4336 }); 4337 return !!result; 4338 }; 4339 4340 // Determine if the array or object contains a given value (using `===`). 4341 // Aliased as `include`. 4342 _.contains = _.include = function(obj, target) { 4343 if (obj == null) return false; 4344 if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; 4345 return any(obj, function(value) { 4346 return value === target; 4347 }); 4348 }; 4349 4350 // Function (ahem) Functions 4351 // -------------------- 4352 4353 // Delays a function for the given number of milliseconds, and then calls 4354 // it with the arguments supplied. 4355 _.delay = function(func, wait) { 4356 var args = slice.call(arguments, 2); 4357 return setTimeout(function(){ return func.apply(null, args); }, wait); 4358 }; 4359 4360 // Defers a function, scheduling it to run after the current call stack has 4361 // cleared. 4362 _.defer = function(func) { 4363 return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); 4364 }; 4365 4366 // Returns a function, that, when invoked, will only be triggered once every 4367 // browser animation frame - using tram's requestAnimationFrame polyfill. 4368 _.throttle = function(func) { 4369 var wait, args, context; 4370 return function() { 4371 if (wait) return; 4372 wait = true; 4373 args = arguments; 4374 context = this; 4375 tram.frame(function() { 4376 wait = false; 4377 func.apply(context, args); 4378 }); 4379 }; 4380 }; 4381 4382 // Returns a function, that, as long as it continues to be invoked, will not 4383 // be triggered. The function will be called after it stops being called for 4384 // N milliseconds. If `immediate` is passed, trigger the function on the 4385 // leading edge, instead of the trailing. 4386 _.debounce = function(func, wait, immediate) { 4387 var timeout, args, context, timestamp, result; 4388 4389 var later = function() { 4390 var last = _.now() - timestamp; 4391 if (last < wait) { 4392 timeout = setTimeout(later, wait - last); 4393 } else { 4394 timeout = null; 4395 if (!immediate) { 4396 result = func.apply(context, args); 4397 context = args = null; 4398 } 4399 } 4400 }; 4401 4402 return function() { 4403 context = this; 4404 args = arguments; 4405 timestamp = _.now(); 4406 var callNow = immediate && !timeout; 4407 if (!timeout) { 4408 timeout = setTimeout(later, wait); 4409 } 4410 if (callNow) { 4411 result = func.apply(context, args); 4412 context = args = null; 4413 } 4414 4415 return result; 4416 }; 4417 }; 4418 4419 // Object Functions 4420 // ---------------- 4421 4422 // Fill in a given object with default properties. 4423 _.defaults = function(obj) { 4424 if (!_.isObject(obj)) return obj; 4425 for (var i = 1, length = arguments.length; i < length; i++) { 4426 var source = arguments[i]; 4427 for (var prop in source) { 4428 if (obj[prop] === void 0) obj[prop] = source[prop]; 4429 } 4430 } 4431 return obj; 4432 }; 4433 4434 // Retrieve the names of an object's properties. 4435 // Delegates to **ECMAScript 5**'s native `Object.keys` 4436 _.keys = function(obj) { 4437 if (!_.isObject(obj)) return []; 4438 if (nativeKeys) return nativeKeys(obj); 4439 var keys = []; 4440 for (var key in obj) if (_.has(obj, key)) keys.push(key); 4441 return keys; 4442 }; 4443 4444 // Shortcut function for checking if an object has a given property directly 4445 // on itself (in other words, not on a prototype). 4446 _.has = function(obj, key) { 4447 return hasOwnProperty.call(obj, key); 4448 }; 4449 4450 // Is a given variable an object? 4451 _.isObject = function(obj) { 4452 return obj === Object(obj); 4453 }; 4454 4455 // Utility Functions 4456 // ----------------- 4457 4458 // A (possibly faster) way to get the current timestamp as an integer. 4459 _.now = Date.now || function() { return new Date().getTime(); }; 4460 4461 // By default, Underscore uses ERB-style template delimiters, change the 4462 // following template settings to use alternative delimiters. 4463 _.templateSettings = { 4464 evaluate : /<%([\s\S]+?)%>/g, 4465 interpolate : /<%=([\s\S]+?)%>/g, 4466 escape : /<%-([\s\S]+?)%>/g 4467 }; 4468 4469 // When customizing `templateSettings`, if you don't want to define an 4470 // interpolation, evaluation or escaping regex, we need one that is 4471 // guaranteed not to match. 4472 var noMatch = /(.)^/; 4473 4474 // Certain characters need to be escaped so that they can be put into a 4475 // string literal. 4476 var escapes = { 4477 "'": "'", 4478 '\\': '\\', 4479 '\r': 'r', 4480 '\n': 'n', 4481 '\u2028': 'u2028', 4482 '\u2029': 'u2029' 4483 }; 4484 4485 var escaper = /\\|'|\r|\n|\u2028|\u2029/g; 4486 4487 var escapeChar = function(match) { 4488 return '\\' + escapes[match]; 4489 }; 4490 4491 // JavaScript micro-templating, similar to John Resig's implementation. 4492 // Underscore templating handles arbitrary delimiters, preserves whitespace, 4493 // and correctly escapes quotes within interpolated code. 4494 // NB: `oldSettings` only exists for backwards compatibility. 4495 _.template = function(text, settings, oldSettings) { 4496 if (!settings && oldSettings) settings = oldSettings; 4497 settings = _.defaults({}, settings, _.templateSettings); 4498 4499 // Combine delimiters into one regular expression via alternation. 4500 var matcher = RegExp([
4501 (settings.escape || noMatch).source, 4502 (settings.interpolate || noMatch).source, 4503 (settings.evaluate || noMatch).source 4504 ].join('|') + '|$', 'g'); 4505 4506 // Compile the template source, escaping string literals appropriately. 4507 var index = 0; 4508 var source = "__p+='"; 4509 text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { 4510 source += text.slice(index, offset).replace(escaper, escapeChar); 4511 index = offset + match.length; 4512 4513 if (escape) { 4514 source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; 4515 } else if (interpolate) { 4516 source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; 4517 } else if (evaluate) { 4518 source += "';\n" + evaluate + "\n__p+='"; 4519 } 4520 4521 // Adobe VMs need the match returned to produce the correct offest. 4522 return match; 4523 }); 4524 source += "';\n"; 4525 4526 // If a variable is not specified, place data values in local scope. 4527 if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; 4528 4529 source = "var __t,__p='',__j=Array.prototype.join," + 4530 "print=function(){__p+=__j.call(arguments,'');};\n" + 4531 source + 'return __p;\n'; 4532 4533 try { 4534 var render = new Function(settings.variable || 'obj', '_', source); 4535 } catch (e) { 4536 e.source = source; 4537 throw e; 4538 } 4539 4540 var template = function(data) { 4541 return render.call(this, data, _); 4542 }; 4543 4544 // Provide the compiled source as a convenience for precompilation. 4545 var argument = settings.variable || 'obj'; 4546 template.source = 'function(' + argument + '){\n' + source + '}'; 4547 4548 return template; 4549 }; 4550 4551 // Export underscore 4552 return _; 4553 }()); 4554 4555 4556/***/ }, 4557/* 22 */ 4558/***/ function(module, exports) { 4559 4560 /*! 4561 * jQuery-ajaxTransport-XDomainRequest - v1.0.3 4562 * 2014-12-16 WEBFLOW - Removed UMD wrapper 4563 * https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest 4564 * Copyright (c) 2014 Jason Moon (@JSONMOON) 4565 * @license MIT (/blob/master/LICENSE.txt) 4566 */ 4567 module.exports=function($){if($.support.cors||!$.ajaxTransport||!window.XDomainRequest){return}var httpRegEx=/^https?:\/\//i;var getOrPostRegEx=/^get|post$/i;var sameSchemeRegEx=new RegExp("^"+location.protocol,"i");$.ajaxTransport("* text html xml json",function(options,userOptions,jqXHR){if(!options.crossDomain||!options.async||!getOrPostRegEx.test(options.type)||!httpRegEx.test(options.url)||!sameSchemeRegEx.test(options.url)){return}var xdr=null;return{send:function(headers,complete){var postData="";var userType=(userOptions.dataType||"").toLowerCase();xdr=new XDomainRequest;if(/^\d+$/.test(userOptions.timeout)){xdr.timeout=userOptions.timeout}xdr.ontimeout=function(){complete(500,"timeout")};xdr.onload=function(){var allResponseHeaders="Content-Length: "+xdr.responseText.length+"\r\nContent-Type: "+xdr.contentType;var status={code:200,message:"success"};var responses={text:xdr.responseText};try{if(userType==="html"||/text\/html/i.test(xdr.contentType)){responses.html=xdr.responseText}else if(userType==="json"||userType!=="text"&&/\/json/i.test(xdr.contentType)){try{responses.json=$.parseJSON(xdr.responseText)}catch(e){status.code=500;status.message="parseerror"}}else if(userType==="xml"||userType!=="text"&&/\/xml/i.test(xdr.contentType)){var doc=new ActiveXObject("Microsoft.XMLDOM");doc.async=false;try{doc.loadXML(xdr.responseText)}catch(e){doc=undefined}if(!doc||!doc.documentElement||doc.getElementsByTagName("parsererror").length){status.code=500;status.message="parseerror";throw"Invalid XML: "+xdr.responseText}responses.xml=doc}}catch(parseMessage){throw parseMessage}finally{complete(status.code,status.message,responses,allResponseHeaders)}};xdr.onprogress=function(){};xdr.onerror=function(){complete(500,"error",{text:xdr.responseText})};if(userOptions.data){postData=$.type(userOptions.data)==="string"?userOptions.data:$.param(userOptions.data)}xdr.open(options.type,options.url);xdr.send(postData)},abort:function(){if(xdr){xdr.abort()}}}})}(window.jQuery); 4568 4569/***/ } 4570/******/ ]);/** 4571 * ---------------------------------------------------------------------- 4572 * Webflow: Interactions: Init 4573 */ 4574Webflow.require('ix').init([ 4575 {"slug":"fade-in-bottom-page-loads","name":"Fade in bottom (page loads)","value":{"style":{"opacity":0,"x":"0px","y":"50px","z":"0px"},"triggers":[{"type":"load","stepsA":[{"opacity":1,"transition":"transform 1000ms ease 0ms, opacity 1000ms ease 0ms","x":"0px","y":"0px","z":"0px"}],"stepsB":[]}]}}, 4576 {"slug":"fade-in-left-scroll-in","name":"Fade in left (scroll in)","value":{"style":{"opacity":0,"x":"-50px","y":"0px","z":"0px"},"triggers":[{"type":"scroll","stepsA":[{"opacity":1,"transition":"transform 1000ms ease 0ms, opacity 1000ms ease 0ms","x":"0px","y":"0px","z":"0px"}],"stepsB":[]}]}}, 4577 {"slug":"fade-in-right-scroll-in","name":"Fade in right (scroll in)","value":{"style":{"opacity":0,"x":"50px","y":"0px","z":"0px"},"triggers":[{"type":"scroll","stepsA":[{"opacity":1,"transition":"transform 1000ms ease 0ms, opacity 1000ms ease 0ms","x":"0px","y":"0px","z":"0px"}],"stepsB":[]}]}}, 4578 {"slug":"fade-in-top-scroll-in","name":"Fade in top (scroll in)","value":{"style":{"opacity":0,"x":"0px","y":"-50px","z":"0px"},"triggers":[{"type":"scroll","stepsA":[{"opacity":1,"transition":"transform 1000ms ease 0ms, opacity 1000ms ease 0ms","x":"0px","y":"0px","z":"0px"}],"stepsB":[]}]}}, 4579 {"slug":"fade-in-bottom-scroll-in","name":"Fade in bottom (scroll in)","value":{"style":{"opacity":0,"x":"0px","y":"50px","z":"0px"},"triggers":[{"type":"scroll","stepsA":[{"opacity":1,"transition":"transform 1000ms ease 0ms, opacity 1000ms ease 0ms","x":"0px","y":"0px","z":"0px"}],"stepsB":[]}]}}, 4580 {"slug":"bounce-in-scroll-in","name":"Bounce in (scroll in)","value":{"style":{"opacity":0,"scaleX":0.6000000000000001,"scaleY":0.6000000000000001,"scaleZ":1},"triggers":[{"type":"scroll","stepsA":[{"opacity":1,"transition":"transform 600ms ease 0ms, opacity 600ms ease 0ms","scaleX":1.08,"scaleY":1.08,"scaleZ":1},{"transition":"transform 150ms ease-out-cubic 0ms","scaleX":1,"scaleY":1,"scaleZ":1}],"stepsB":[]}]}}, 4581 {"slug":"scale-on-scroll","name":"Scale on Scroll","value":{"style":{"opacity":0,"scaleX":0.01,"scaleY":0.01,"scaleZ":1},"triggers":[{"type":"scroll","stepsA":[{"opacity":1,"transition":"transform 600ms ease 0ms, opacity 600ms ease 0ms","scaleX":1,"scaleY":1,"scaleZ":1}],"stepsB":[]}]}}, 4582 {"slug":"new-interaction","name":"New Interaction","value":{"style":{},"triggers":[]}} 4583]);
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.