diff --git a/README.md b/README.md index bc9f96c..6bd709f 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,4 @@ This repository contains a collection of carefully engineered html5 snippets, which can be used in your own projects. -![image](/attachments/1160e58c-99cd-436c-b77f-b543430e6d08) \ No newline at end of file +![image](/attachments/a3c79d4f-ab7e-4260-9596-7ddb9fd972e5) \ No newline at end of file diff --git a/animations/3d-synth-canyon-animation/README.md b/animations/3d-synth-canyon-animation/README.md index 3d154a1..a32f5c6 100644 --- a/animations/3d-synth-canyon-animation/README.md +++ b/animations/3d-synth-canyon-animation/README.md @@ -1,5 +1,7 @@ -# [3D] Synth Canyon Animation +# 3D Synth Canyon Animation I wanted to do some experimentation with manipulating geometries and layering several simple shader effects, and this is what I came up with. The Soundcloud embed is just there for ambiance. + +![image](/attachments/2c7bac61-a6a9-40bd-89a8-909d8118a38d) \ No newline at end of file diff --git a/animations/basic-matrix-effect/README.md b/animations/basic-matrix-effect/README.md index 374399b..121b5c9 100644 --- a/animations/basic-matrix-effect/README.md +++ b/animations/basic-matrix-effect/README.md @@ -1,3 +1,5 @@ # Basic Matrix Effect Hello World in 92 Languages falling down in Matrix code rain + +![image](/attachments/0bd4f9d5-0ebf-4c8c-8100-5464f00d72d5) \ No newline at end of file diff --git a/animations/basic-matrix-effect/index.html b/animations/basic-matrix-effect/index.html index 2f37254..83d5453 100644 --- a/animations/basic-matrix-effect/index.html +++ b/animations/basic-matrix-effect/index.html @@ -10,7 +10,8 @@ - + + diff --git a/animations/floating-words/README.md b/animations/floating-words/README.md new file mode 100644 index 0000000..d162199 --- /dev/null +++ b/animations/floating-words/README.md @@ -0,0 +1,6 @@ +# Floating Words + +The words comes from song "Red like Roses part II" - RWBY Theme +size and speed determine from its frequency in lyrics + +![image](/attachments/c5fac2e6-e204-4177-b695-b86eeafc3f54) diff --git a/animations/floating-words/index.html b/animations/floating-words/index.html new file mode 100644 index 0000000..052d608 --- /dev/null +++ b/animations/floating-words/index.html @@ -0,0 +1,13 @@ + + + + + Floating Words + + + + + + + + diff --git a/animations/floating-words/script.js b/animations/floating-words/script.js new file mode 100644 index 0000000..a76e1db --- /dev/null +++ b/animations/floating-words/script.js @@ -0,0 +1,87 @@ +window.onload = function(argument) { + + // var lyric = "i couldn't take it couldn't stand another minute couldn't bear another day without you in it"; + var lyric = "i couldn't take it couldn't stand another minute couldn't bear another day without you in it all of the joy that I had known for my life was stripped away from me the minute that you died to have you in my life was all i ever wanted but now without you I'm a soul forever haunted can't help but feel that i had taken you for granted no way in hell that i can ever comprehend this i wasn't dreaming when they told me you were gone i was wide awake and feeling that they had to be wrong how could you leave me when you swore that you would stay now i'm trapped inside a nightmare every single fucking day it's like a movie but there's not a happy ending every scene fades black and there's no pretending this little fairy tale doesn't seem to end well theres no knight in shining armor who will wake me from the spell i know you didn't plan this you tried to do what's right but in the middle of this madness i'm the one you left to win this fight red like roses fills my head with dreams and finds me always closer to the emptiness and sadness that has come to take the place of you i know you're broken down by anger and by sadness you feel I left you in a world that's full of madness wish i could talk to you if only for a minute make you understand the reasons why i did it i wanna tell you that you're all that ever mattered want you to know that for eternity i'm shattered i tried so hard just to protect you but i failed to and in a prison of abandonment i've jailed you i never planned that i would leave you there alone i was sure that i would see you when i made it back home and all the times I swore that it would be okay now i'm nothing but a liar and you're thrown into the fray this bedtime story ends with misery ever after the pages are torn and there's no final chapter i didn't have a choice I did what I had to do i made a sacrifice but forced a bigger sacrifice on you i know you've lived a nightmare i caused you so much pain but baby please don't do what i did i don't want you to waste your life in vain red like roses fills my head with dreams and finds me always closer to the emptiness and sadness that has come to take the place of you you're not the only one who needed me i thought you understood you were the one i needed and you left me as I always feared you would would I change it if i could? it doesn't matter how the petals scatter now every nightmare just discloses it's your blood that's red like roses and no matter what I do nothing ever takes the place of you red like roses fills my head with dreams and finds me always closer to the emptiness and sadness that has come to take the place of you"; + var words = {}; + var words_attr = []; + string_handle(lyric); + + var canvas = document.getElementById('c'); + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + + if (canvas.getContext) { + var c = canvas.getContext('2d'), + w = canvas.width, + h = canvas.height; + + c.strokeStyle = 'red'; + c.fillStyle = 'white'; + c.lineWidth = 5; + + // constructor + Word = function(key) { + this.text = key; + this.x = Math.random() * w; + this.y = Math.random() * h; + this.font = words[key] * 10 + 'px arial' + this.speed = (words[key]); + } + for (key in words) { + words_attr.push(new Word(key)); + } + console.log(words_attr.length); + + function animation() { + for (var i = 0; i < words_attr.length; i++) { + c.font = words_attr[i].font; + c.fillText(words_attr[i].text, words_attr[i].x, words_attr[i].y); + words_attr[i].width = c.measureText(words_attr[i].text).width; + c.stroke(); + } + move(); + } + + function move() { + for (var i = 0; i < words_attr.length; i++) { + if (words_attr[i].x > w) { + words_attr[i].x = -words_attr[i].width; + words_attr[i].y = Math.random()*h; + }else{ + words_attr[i].x += words_attr[i].speed; + } + } + } + + setInterval(function() { + c.clearRect(0,0,w,h); + animation(); + },24); + + } + + function string_handle(str) { + var split_str = str.split(" "); + var word_array = []; + var word_count = []; + for (var i = 0; i < split_str.length; i++) { + check = true; + for (var j = 0; j <= word_array.length; j++) { + if (split_str[i] == word_array[j]) { + word_count[j]++; + check = false; + break; + } + } + if (check) { + word_array.push(split_str[i]); + word_count.push(1); + } + } + for (var i = 0; i < word_array.length; i++) { + words[word_array[i]] = word_count[i]; + } + return words; + } + +} \ No newline at end of file diff --git a/animations/floating-words/style.css b/animations/floating-words/style.css new file mode 100644 index 0000000..ad570ad --- /dev/null +++ b/animations/floating-words/style.css @@ -0,0 +1,4 @@ +body{ + background:#141414; + overflow:hidden; +} \ No newline at end of file diff --git a/animations/infinity-tunnel/README.md b/animations/infinity-tunnel/README.md new file mode 100644 index 0000000..e1b1936 --- /dev/null +++ b/animations/infinity-tunnel/README.md @@ -0,0 +1,3 @@ +# Inifinity Tunnel + +![image](/attachments/49ed7d89-9d9c-44c3-bd7d-ec29bad4a48d) \ No newline at end of file diff --git a/animations/infinity-tunnel/apxlmx.js b/animations/infinity-tunnel/apxlmx.js new file mode 100644 index 0000000..2b29a76 --- /dev/null +++ b/animations/infinity-tunnel/apxlmx.js @@ -0,0 +1,726 @@ +/** + * A basic Web GL class. This provides a very basic setup for GLSL shader code. + * Currently it doesn't support anything except for clip-space 3d, but this was + * done so that we could start writing fragments right out of the gate. My + * Intention is to update it with particle and polygonal 3d support later on. + * + * @class WTCGL + * @author Liam Egan + * @version 0.0.8 + * @created Jan 16, 2019 + */ +class WTCGL { + + /** + * The WTCGL Class constructor. If construction of the webGL context fails + * for any reason this will return null. + * + * @TODO make the dimension properties properly optional + * @TODO provide the ability to allow for programmable buffers + * + * @constructor + * @param {HTMLElement} el The canvas element to use as the root + * @param {string} vertexShaderSource The vertex shader source + * @param {string} fragmentShaderSource The fragment shader source + * @param {number} [width] The width of the webGL context. This will default to the canvas dimensions + * @param {number} [height] The height of the webGL context. This will default to the canvas dimensions + * @param {number} [pxratio=1] The pixel aspect ratio of the canvas + * @param {boolean} [styleElement] A boolean indicating whether to apply a style property to the canvas (resizing the canvas by the inverse of the pixel ratio) + * @param {boolean} [webgl2] A boolean indicating whether to try to create a webgl2 context instead of a regulart context + */ + constructor(el, vertexShaderSource, fragmentShaderSource, width, height, pxratio, styleElement, webgl2) { + this.run = this.run.bind(this); + + this._onRun = ()=>{}; + + // Destructure if an object is aprovided instead a series of parameters + if(el instanceof Object && el.el) { + ({el, vertexShaderSource, fragmentShaderSource, width, height, pxratio, webgl2, styleElement} = el); + } + + // If the HTML element isn't a canvas, return null + if(!el instanceof HTMLElement || el.nodeName.toLowerCase() !== 'canvas') { + console.log('Provided element should be a canvas element'); + return null; + } + + this._el = el; + // The context should be either webgl2, webgl or experimental-webgl + if(webgl2 === true) { + this.isWebgl2 = true; + this._ctx = this._el.getContext("webgl2", this.webgl_params) || this._el.getContext("webgl", this.webgl_params) || this._el.getContext("experimental-webgl", this.webgl_params); + } else { + this.isWebgl2 = false; + this._ctx = this._el.getContext("webgl", this.webgl_params) || this._el.getContext("experimental-webgl", this.webgl_params); + } + + // Set up the extensions + this._ctx.getExtension('OES_standard_derivatives'); + this._ctx.getExtension('EXT_shader_texture_lod'); + this._ctx.getExtension('OES_texture_float'); + this._ctx.getExtension('WEBGL_color_buffer_float'); + this._ctx.getExtension('OES_texture_float_linear'); + this._ctx.getExtension('EXT_color_buffer_float'); + + // We can't make the context so return an error + if (!this._ctx) { + console.log('Browser doesn\'t support WebGL '); + return null; + } + + // Create the shaders + this._vertexShader = WTCGL.createShaderOfType(this._ctx, this._ctx.VERTEX_SHADER, vertexShaderSource); + this._fragmentShader = WTCGL.createShaderOfType(this._ctx, this._ctx.FRAGMENT_SHADER, fragmentShaderSource); + + // Create the program and link the shaders + this._program = this._ctx.createProgram(); + this._ctx.attachShader(this._program, this._vertexShader); + this._ctx.attachShader(this._program, this._fragmentShader); + this._ctx.linkProgram(this._program); + + // If we can't set up the params, this means the shaders have failed for some reason + if (!this._ctx.getProgramParameter(this._program, this._ctx.LINK_STATUS)) { + console.log('Unable to initialize the shader program: ' + this._ctx.getProgramInfoLog(this._program)); + return null; + } + + // Initialise the vertex buffers + this.initBuffers([ + -1.0, 1.0, -1., + 1.0, 1.0, -1., + -1.0, -1.0, -1., + 1.0, -1.0, -1., + ]); + + // Initialise the frame buffers + this.frameBuffers = []; + + // The program information object. This is essentially a state machine for the webGL instance + this._programInfo = { + attribs: { + vertexPosition: this._ctx.getAttribLocation(this._program, 'a_position'), + }, + uniforms: { + projectionMatrix: this._ctx.getUniformLocation(this._program, 'u_projectionMatrix'), + modelViewMatrix: this._ctx.getUniformLocation(this._program, 'u_modelViewMatrix'), + resolution: this._ctx.getUniformLocation(this._program, 'u_resolution'), + time: this._ctx.getUniformLocation(this._program, 'u_time'), + }, + }; + + // Tell WebGL to use our program when drawing + this._ctx.useProgram(this._program); + + this.pxratio = pxratio; + + this.styleElement = styleElement !== true; + + this.resize(width, height); + } + + + /** + * Public methods + */ + + addFrameBuffer(w, h, tiling = 0, buffertype = 0) { + // create to render to + const gl = this._ctx; + const targetTextureWidth = w * this.pxratio; + const targetTextureHeight = h * this.pxratio; + const targetTexture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, targetTexture); + { + // define size and format of level 0 + const level = 0; + let internalFormat = gl.RGBA; + const border = 0; + let format = gl.RGBA; + let t; + if(buffertype & WTCGL.TEXTYPE_FLOAT) { + const e = gl.getExtension('OES_texture_float'); + window.extension = e; + t = e.FLOAT; + // internalFormat = gl.RGBA32F; + } else if(buffertype & WTCGL.TEXTYPE_HALF_FLOAT_OES) { + // t = gl.renderer.isWebgl2 ? e.HALF_FLOAT : e.HALF_FLOAT_OES; + // gl.renderer.extensions['OES_texture_half_float'] ? gl.renderer.extensions['OES_texture_half_float'].HALF_FLOAT_OES : + // gl.UNSIGNED_BYTE; + const e = gl.getExtension('OES_texture_half_float'); + t = this.isWebgl2 ? gl.HALF_FLOAT : e.HALF_FLOAT_OES; + // format = gl.RGBA; + if(this.isWebgl2) { + internalFormat = gl.RGBA16F; + } + // internalFormat = gl.RGB32F; + // format = gl.RGB32F; + // window.gl = gl + // t = e.HALF_FLOAT_OES; + } else { + t = gl.UNSIGNED_BYTE; + } + const type = t; + const data = null; + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, + targetTextureWidth, targetTextureHeight, border, + format, type, data); + // gl.generateMipmap(gl.TEXTURE_2D); + + // set the filtering so we don't need mips + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + + // Set the parameters based on the passed type + if(tiling === WTCGL.IMAGETYPE_TILE) { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + } else if(tiling === WTCGL.IMAGETYPE_MIRROR) { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); + } else if(tiling === WTCGL.IMAGETYPE_REGULAR) { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + } + + // Create and bind the framebuffer + const fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + // attach the texture as the first color attachment + const attachmentPoint = gl.COLOR_ATTACHMENT0; + const level = 0; + gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, targetTexture, level); + + return { + w: w * this.pxratio, + h: h * this.pxratio, + fb: fb, + frameTexture: targetTexture + }; + } + + + /** + * Resizes the canvas to a specified width and height, respecting the pixel ratio + * + * @param {number} w The width of the canvas + * @param {number} h The height of the canvas + * @return {Void} + */ + resize(w, h) { + this.width = w; + this.height = h; + this._el.width = w * this.pxratio; + this._el.height = h * this.pxratio; + this._size = [w * this.pxratio, h * this.pxratio]; + if(this.styleElement) { + this._el.style.width = w + 'px'; + this._el.style.height = h + 'px'; + } + + this._ctx.viewportWidth = w * this.pxratio; + this._ctx.viewportHeight = h * this.pxratio; + + this._ctx.uniform2fv( this._programInfo.uniforms.resolution, this._size); + + this.initBuffers(this._positions); + } + + /** + * Initialise a provided vertex buffer + * + * @param {array} positions The vertex positions to initialise + * @return {Void} + */ + initBuffers(positions) { + this._positions = positions; + this._positionBuffer = this._ctx.createBuffer(); + + this._ctx.bindBuffer(this._ctx.ARRAY_BUFFER, this._positionBuffer); + + this._ctx.bufferData(this._ctx.ARRAY_BUFFER, + new Float32Array(positions), + this._ctx.STATIC_DRAW); + } + + /** + * Add a uniform to the program. At this time the following types are supported: + * - Float - WTCGL.TYPE_FLOAT + * - Vector 2 - WTCGL.TYPE_V2 + * - Vector 3 - WTCGL.TYPE_V3 + * - Vector 4 - WTCGL.TYPE_V4 + * + * @param {string} name The name of the uniform. N.B. your name will be prepended with a `u_` in your shaders. So providing a name of `foo` here will result in a uniform named `u_foo` + * @param {WTCGL.UNIFORM_TYPE} type The unfiform type + * @param {number|array} value The unfiform value. The type depends on the uniform type being created + * @return {WebGLUniformLocation} The uniform location for later reference + */ + addUniform(name, type, value) { + let uniform = this._programInfo.uniforms[name]; + uniform = this._ctx.getUniformLocation(this._program, `u_${name}`); + switch(type) { + case WTCGL.TYPE_INT : + if(!isNaN(value)) this._ctx.uniform1i( uniform, value); + break; + case WTCGL.TYPE_FLOAT : + if(!isNaN(value)) this._ctx.uniform1f( uniform, value); + break; + case WTCGL.TYPE_V2 : + if(value instanceof Array && value.length === 2.) this._ctx.uniform2fv( uniform, value); + break; + case WTCGL.TYPE_V3 : + if(value instanceof Array && value.length === 3.) this._ctx.uniform3fv( uniform, value); + break; + case WTCGL.TYPE_V4 : + if(value instanceof Array && value.length === 4.) this._ctx.uniform4fv( uniform, value); + break; + case WTCGL.TYPE_BOOL : + if(!isNaN(value)) this._ctx.uniform1i( uniform, value); + break; + } + this._programInfo.uniforms[name] = uniform; + return uniform; + } + + /** + * Adds a texture to the program and links it to a named uniform. Providing the type changes the tiling properties of the texture. Possible values for type: + * - WTCGL.IMAGETYPE_REGULAR - No tiling, clamp to edges and doesn't need to be power of 2. + * - WTCGL.IMAGETYPE_TILE - full x and y tiling, needs to be power of 2. + * - WTCGL.IMAGETYPE_MIRROR - mirror tiling, needs to be power of 2. + * + * @public + * @param {string} name The name of the uniform. N.B. your name will be prepended with a `u_` in your shaders. So providing a name of `foo` here will result in a uniform named `u_foo` + * @param {WTCGL.TYPE_IMAGETYPE} type The type of texture to create. This is basically the tiling behaviour of the texture as described above + * @param {Image} image The image object to add to the texture + * @return {WebGLTexture} The texture object + */ + addTexture(name, type, image, liveUpdate = false) { + + var texture = this._ctx.createTexture(); + this._ctx.pixelStorei(this._ctx.UNPACK_FLIP_Y_WEBGL, true); + this._ctx.bindTexture(this._ctx.TEXTURE_2D, texture); + + // this._ctx.generateMipmap(this._ctx.TEXTURE_2D); + + // Set the parameters based on the passed type + if(type === WTCGL.IMAGETYPE_MIRROR) { + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_WRAP_S, this._ctx.MIRRORED_REPEAT); + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_WRAP_T, this._ctx.MIRRORED_REPEAT); + } else if(type === WTCGL.IMAGETYPE_REGULAR) { + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_WRAP_S, this._ctx.CLAMP_TO_EDGE); + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_WRAP_T, this._ctx.CLAMP_TO_EDGE); + } + + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_MIN_FILTER, this._ctx.LINEAR); + // this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_MAG_FILTER, this._ctx.LINEAR); + + // Upload the image into the texture. + this._ctx.texImage2D(this._ctx.TEXTURE_2D, 0, this._ctx.RGBA, this._ctx.RGBA, this._ctx.UNSIGNED_BYTE, image); + + // add the texture to the array of textures. + this.pushTexture(name, texture, image, this._ctx.TEXTURE_2D, liveUpdate); + + + return texture; + } + + pushTexture(name, texture, image, target, liveUpdate = false) { + let textures = this.textures; + + textures.push({ name: name, tex: texture, liveUpdate: liveUpdate, image: image, target: target }); + + // Finally set the this.textures (this is just to get around the funnyness of default getters) + this.textures = textures; + } + + /** + * Updates a texture location for a given WebGLTexture with an image + * + * @param {WebGLTexture} texture The texture location to update + * @param {Image} image The image object to add to the texture + * @return {Void} + */ + updateTexture(texture, image, name) { + + let uniform = this._ctx.getUniformLocation(this._program, `u_${name}`); + // Set the texture unit to the uniform + this._ctx.uniform1i(uniform, 0); + this._ctx.activeTexture(this._ctx.TEXTURE0); + + this._ctx.bindTexture(this._ctx.TEXTURE_2D, texture); + // Upload the image into the texture. + this._ctx.texImage2D(this._ctx.TEXTURE_2D, 0, this._ctx.RGBA, this._ctx.RGBA, this._ctx.UNSIGNED_BYTE, image); + } + + /** + * Initialise texture locations in the program + * + * @return {Void} + */ + initTextures() { + for(let i = 0; i < this.textures.length; i++) { + let name = this.textures[i].name; + let uniform = this._programInfo.uniforms[name]; + uniform = this._ctx.getUniformLocation(this._program, `u_${name}`); + + // Set the texture unit to the uniform + this._ctx.uniform1i(uniform, i); + + // find the active texture based on the index + this._ctx.activeTexture(this._ctx[`TEXTURE${i}`]); + + // Finally, bind the texture + this._ctx.bindTexture(this.textures[i].target, this.textures[i].tex); + } + } + + /** + * The run loop. This function is run as a part of a RaF and updates the internal + * time uniform (`u_time`). + * + * @param {number} delta The delta time provided by the RaF loop + * @return {Void} + */ + run(delta) { + this.running && requestAnimationFrame(this.run); + + const runFunction = () => { + this.time = this.startTime + delta * .0002; + this.onRun(delta); + this.render(); + } + + if(this.frameRate) { + let now = Date.now(); + let elapsed = now - this._then; + + if (elapsed > this.frameRate) { + this._then = now - (elapsed % this.frameRate); + + runFunction(); + } + } else { + runFunction(); + } + } + + /** + * Render the program + * + * @return {Void} + */ + render(buffer = {}) { + this._ctx.bindFramebuffer(this._ctx.FRAMEBUFFER, buffer.fb || null); + // Update the time uniform + this._ctx.uniform1f( this._programInfo.uniforms.time, this.time); + + this.textures.forEach((textureInfo) => { + if(textureInfo.liveUpdate === true) { + this.updateTexture(textureInfo.tex, textureInfo.image, textureInfo.name); + } + }); + + this._ctx.viewport(0, 0, buffer.w || this._ctx.viewportWidth, buffer.h || this._ctx.viewportHeight); + if(this.clearing) { + this._ctx.clearColor(1.0, 0.0, 0.0, 0.0); + // this._ctx.clearDepth(1.0); + // this._ctx.enable(this._ctx.DEPTH_TEST); + // this._ctx.depthFunc(this._ctx.LEQUAL); + + this._ctx.blendFunc(this._ctx.SRC_ALPHA, this._ctx.ONE_MINUS_SRC_ALPHA); + + this._ctx.clear( this._ctx.COLOR_BUFFER_BIT ); + } + + this._ctx.bindBuffer(this._ctx.ARRAY_BUFFER, this._positionBuffer); + this._ctx.vertexAttribPointer( + this._programInfo.attribs.vertexPosition, + 3, + this._ctx.FLOAT, + false, + 0, + 0); + this._ctx.enableVertexAttribArray(this._programInfo.attribs.vertexPosition); + + // Set the shader uniforms + this.includePerspectiveMatrix && this._ctx.uniformMatrix4fv( this._programInfo.uniforms.projectionMatrix, false, this.perspectiveMatrix); + this.includeModelViewMatrix && this._ctx.uniformMatrix4fv( this._programInfo.uniforms.modelViewMatrix, false, this.modelViewMatrix); + + this._ctx.drawArrays(this._ctx.TRIANGLE_STRIP, 0, 4); + } + + + /** + * Getters and setters + */ + + /** + * The default webGL parameters to be used for the program. + * This is read only and should only be overridden as a part of a subclass. + * + * @readonly + * @type {object} + * @default { alpha: true } + */ + get webgl_params() { + return { alpha: true }; + } + + /** + * (getter/setter) Whether the element should include styling as a part of + * its rendition. + * + * @type {boolean} + * @default true + */ + set styleElement(value) { + this._styleElement = value === true; + if(this._styleElement === false && this._el) { + this._el.style.width = ''; + this._el.style.height = ''; + } + } + get styleElement() { + return this._styleElement !== false; + } + + /** + * (getter/setter) startTime. This is a value to begin the `u_time` + * unform at. This is here in case you want `u_time` to begin at a + * specific value other than 0. + * + * @type {number} + * @default 0 + */ + set startTime(value) { + if(!isNaN(value)) { + this._startTime = value; + } + } + get startTime() { + return this._startTime || 0; + } + + /** + * (getter/setter) time. This is the time that the program currently + * sits at. By default this value is set as a part of the run loop + * however this is a public property so that we can specify time + * for rendition outside of the run loop. + * + * @type {number} + * @default 0 + */ + set time(value) { + if(!isNaN(value)) { + this._time = value; + } + } + get time() { + return this._time || 0; + } + + /** + * (getter/setter) includePerspectiveMatrix. This determines whether the + * perspecive matrix is included in the program. This doesn't really make + * a difference right now, but this is here to provide future interoperability. + * + * @type {boolean} + * @default false + */ + set includePerspectiveMatrix(value) { + this._includePerspectiveMatrix = value === true; + } + get includePerspectiveMatrix() { + return this._includePerspectiveMatrix === true; + } + + /** + * (getter/setter) includeModelViewMatrix. This determines whether the + * model view matrix is included in the program. This doesn't really make + * a difference right now, but this is here to provide future interoperability. + * + * @type {boolean} + * @default false + */ + set includeModelViewMatrix(value) { + this._includeModelViewMatrix = value === true; + } + get includeModelViewMatrix() { + return this._includeModelViewMatrix === true; + } + + /** + * (getter/setter) textures. The array of textures to initialise into the program. + * + * @private + * @type {array} + * @default [] + */ + set textures(value) { + if(value instanceof Array) { + this._textures = value; + } + } + get textures() { + return this._textures || []; + } + + /** + * (getter/setter) clearing. Specifies whether the program should clear the screen + * before drawing anew. + * + * @type {boolean} + * @default false + */ + set clearing(value) { + this._clearing = value === true; + } + get clearing() { + return this._clearing === true; + } + + /** + * (getter/setter) running. Specifies whether the programming is running. Setting + * this to true will create a RaF loop which will call the run function. + * + * @type {boolean} + * @default false + */ + set running(value) { + if(!this.running && value === true) { + + this._then = Date.now(); + + requestAnimationFrame(this.run); + } + this._running = value === true; + } + get running() { + return this._running === true; + } + + set frameRate(value) { + if(!isNaN(value)) this._frameRate = 1000 / value; + } + get frameRate() { + return this._frameRate || null; + } + + /** + * (getter/setter) pxratio. The 1-dimensional pixel ratio of the application. + * This should be used either for making a program look good on high density + * screens or for raming down pixel density for performance. + * + * @type {number} + * @default 1 + */ + set pxratio(value) { + if(value > 0) this._pxratio = value; + } + get pxratio() { + return this._pxratio || 1; + } + + /** + * (getter/setter) perspectiveMatrix. Calculate a perspective matrix, a + * special matrix that is used to simulate the distortion of perspective in + * a camera. Our field of view is 45 degrees, with a width/height ratio + * that matches the display size of the canvas and we only want to see + * objects between 0.1 units and 100 units away from the camera. + * + * @readonly + * @type {mat4} + */ + get perspectiveMatrix() { + const fieldOfView = 45 * Math.PI / 180; // in radians + const aspect = this._size.w / this._size.h; + const zNear = 0.1; + const zFar = 100.0; + const projectionMatrix = mat4.create(); + // note: glmatrix.js always has the first argument + // as the destination to receive the result. + mat4.perspective(projectionMatrix, + fieldOfView, + aspect, + zNear, + zFar); + + return projectionMatrix; + } + + /** + * (getter/setter) perspectiveMatrix. Calculate a model view matrix. + * + * @readonly + * @type {mat4} + */ + get modelViewMatrix() { + // Set the drawing position to the "identity" point, which is + // the center of the scene. + const modelViewMatrix = mat4.create(); + + // Now move the drawing position a bit to where we want to + // start drawing the square. + mat4.translate(modelViewMatrix, // destination matrix + modelViewMatrix, // matrix to translate + [-0.0, 0.0, -1.]); // amount to translate + + return modelViewMatrix; + } + + set onRun(runMethod) { + if(typeof runMethod == 'function') { + this._onRun = runMethod.bind(this); + } + } + get onRun() { + return this._onRun; + } + + get context() { + return this._ctx || null; + } + + /** + * Static Methods + */ + + /** + * Create a shader of a given type given a context, type and source. + * + * @static + * @param {WebGLContext} ctx The context under which to create the shader + * @param {WebGLShaderType} type The shader type, vertex or fragment + * @param {string} source The shader source. + * @return {WebGLShader} The created shader + */ + static createShaderOfType(ctx, type, source) { + const shader = ctx.createShader(type); + ctx.shaderSource(shader, source); + ctx.compileShader(shader); + + if (!ctx.getShaderParameter(shader, ctx.COMPILE_STATUS)) { + console.log('An error occurred compiling the shaders: ' + ctx.getShaderInfoLog(shader)); + ctx.deleteShader(shader); + return null; + } + + return shader; + } +} + +WTCGL.TYPE_INT = 0; +WTCGL.TYPE_FLOAT = 1; +WTCGL.TYPE_V2 = 2; +WTCGL.TYPE_V3 = 3; +WTCGL.TYPE_V4 = 4; +WTCGL.TYPE_BOOL = 5; + +WTCGL.IMAGETYPE_REGULAR = 0; +WTCGL.IMAGETYPE_TILE = 1; +WTCGL.IMAGETYPE_MIRROR = 2; + +WTCGL.TEXTYPE_FLOAT = 0; +WTCGL.TEXTYPE_UNSIGNED_BYTE = 1; +WTCGL.TEXTYPE_HALF_FLOAT_OES = 2; \ No newline at end of file diff --git a/animations/infinity-tunnel/index.html b/animations/infinity-tunnel/index.html new file mode 100644 index 0000000..e264ec3 --- /dev/null +++ b/animations/infinity-tunnel/index.html @@ -0,0 +1,286 @@ + + + + + Control 2 + + + + + + + + + + + + + + diff --git a/animations/infinity-tunnel/noise.png b/animations/infinity-tunnel/noise.png new file mode 100644 index 0000000..32a561c Binary files /dev/null and b/animations/infinity-tunnel/noise.png differ diff --git a/animations/infinity-tunnel/script.js b/animations/infinity-tunnel/script.js new file mode 100644 index 0000000..0f9d336 --- /dev/null +++ b/animations/infinity-tunnel/script.js @@ -0,0 +1,833 @@ +/** + * A basic Web GL class. This provides a very basic setup for GLSL shader code. + * Currently it doesn't support anything except for clip-space 3d, but this was + * done so that we could start writing fragments right out of the gate. My + * Intention is to update it with particle and polygonal 3d support later on. + * + * @class WTCGL + * @author Liam Egan + * @version 0.0.8 + * @created Jan 16, 2019 + */ +class WTCGL { + + /** + * The WTCGL Class constructor. If construction of the webGL context fails + * for any reason this will return null. + * + * @TODO make the dimension properties properly optional + * @TODO provide the ability to allow for programmable buffers + * + * @constructor + * @param {HTMLElement} el The canvas element to use as the root + * @param {string} vertexShaderSource The vertex shader source + * @param {string} fragmentShaderSource The fragment shader source + * @param {number} [width] The width of the webGL context. This will default to the canvas dimensions + * @param {number} [height] The height of the webGL context. This will default to the canvas dimensions + * @param {number} [pxratio=1] The pixel aspect ratio of the canvas + * @param {boolean} [styleElement] A boolean indicating whether to apply a style property to the canvas (resizing the canvas by the inverse of the pixel ratio) + * @param {boolean} [webgl2] A boolean indicating whether to try to create a webgl2 context instead of a regulart context + */ + constructor(el, vertexShaderSource, fragmentShaderSource, width, height, pxratio, styleElement, webgl2) { + this.run = this.run.bind(this); + + this._onRun = () => {}; + + // Destructure if an object is aprovided instead a series of parameters + if (el instanceof Object && el.el) { + ({ el, vertexShaderSource, fragmentShaderSource, width, height, pxratio, webgl2, styleElement } = el); + } + + // If the HTML element isn't a canvas, return null + if (!el instanceof HTMLElement || el.nodeName.toLowerCase() !== 'canvas') { + console.log('Provided element should be a canvas element'); + return null; + } + + this._el = el; + // The context should be either webgl2, webgl or experimental-webgl + if (webgl2 === true) { + this.isWebgl2 = true; + this._ctx = this._el.getContext("webgl2", this.webgl_params) || this._el.getContext("webgl", this.webgl_params) || this._el.getContext("experimental-webgl", this.webgl_params); + } else { + this.isWebgl2 = false; + this._ctx = this._el.getContext("webgl", this.webgl_params) || this._el.getContext("experimental-webgl", this.webgl_params); + } + + // Set up the extensions + this._ctx.getExtension('OES_standard_derivatives'); + this._ctx.getExtension('EXT_shader_texture_lod'); + this._ctx.getExtension('OES_texture_float'); + this._ctx.getExtension('WEBGL_color_buffer_float'); + this._ctx.getExtension('OES_texture_float_linear'); + this._ctx.getExtension('EXT_color_buffer_float'); + + // We can't make the context so return an error + if (!this._ctx) { + console.log('Browser doesn\'t support WebGL '); + return null; + } + + // Create the shaders + this._vertexShader = WTCGL.createShaderOfType(this._ctx, this._ctx.VERTEX_SHADER, vertexShaderSource); + this._fragmentShader = WTCGL.createShaderOfType(this._ctx, this._ctx.FRAGMENT_SHADER, fragmentShaderSource); + + // Create the program and link the shaders + this._program = this._ctx.createProgram(); + this._ctx.attachShader(this._program, this._vertexShader); + this._ctx.attachShader(this._program, this._fragmentShader); + this._ctx.linkProgram(this._program); + + // If we can't set up the params, this means the shaders have failed for some reason + if (!this._ctx.getProgramParameter(this._program, this._ctx.LINK_STATUS)) { + console.log('Unable to initialize the shader program: ' + this._ctx.getProgramInfoLog(this._program)); + return null; + } + + // Initialise the vertex buffers + this.initBuffers([ + -1.0, 1.0, -1., + 1.0, 1.0, -1., + -1.0, -1.0, -1., + 1.0, -1.0, -1.]); + + + // Initialise the frame buffers + this.frameBuffers = []; + + // The program information object. This is essentially a state machine for the webGL instance + this._programInfo = { + attribs: { + vertexPosition: this._ctx.getAttribLocation(this._program, 'a_position') }, + + uniforms: { + projectionMatrix: this._ctx.getUniformLocation(this._program, 'u_projectionMatrix'), + modelViewMatrix: this._ctx.getUniformLocation(this._program, 'u_modelViewMatrix'), + resolution: this._ctx.getUniformLocation(this._program, 'u_resolution'), + time: this._ctx.getUniformLocation(this._program, 'u_time') } }; + + + + // Tell WebGL to use our program when drawing + this._ctx.useProgram(this._program); + + this.pxratio = pxratio; + + this.styleElement = styleElement !== true; + + this.resize(width, height); + } + + + /** + * Public methods + */ + + addFrameBuffer(w, h, tiling = 0, buffertype = 0) { + // create to render to + const gl = this._ctx; + const targetTextureWidth = w * this.pxratio; + const targetTextureHeight = h * this.pxratio; + const targetTexture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, targetTexture); + { + // define size and format of level 0 + const level = 0; + let internalFormat = gl.RGBA; + const border = 0; + let format = gl.RGBA; + let t; + if (buffertype & WTCGL.TEXTYPE_FLOAT) { + const e = gl.getExtension('OES_texture_float'); + window.extension = e; + t = e.FLOAT; + // internalFormat = gl.RGBA32F; + } else if (buffertype & WTCGL.TEXTYPE_HALF_FLOAT_OES) { + // t = gl.renderer.isWebgl2 ? e.HALF_FLOAT : e.HALF_FLOAT_OES; + // gl.renderer.extensions['OES_texture_half_float'] ? gl.renderer.extensions['OES_texture_half_float'].HALF_FLOAT_OES : + // gl.UNSIGNED_BYTE; + const e = gl.getExtension('OES_texture_half_float'); + t = this.isWebgl2 ? gl.HALF_FLOAT : e.HALF_FLOAT_OES; + // format = gl.RGBA; + if (this.isWebgl2) { + internalFormat = gl.RGBA16F; + } + // internalFormat = gl.RGB32F; + // format = gl.RGB32F; + // window.gl = gl + // t = e.HALF_FLOAT_OES; + } else { + t = gl.UNSIGNED_BYTE; + } + const type = t; + const data = null; + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, + targetTextureWidth, targetTextureHeight, border, + format, type, data); + // gl.generateMipmap(gl.TEXTURE_2D); + + // set the filtering so we don't need mips + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + + // Set the parameters based on the passed type + if (tiling === WTCGL.IMAGETYPE_TILE) { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + } else if (tiling === WTCGL.IMAGETYPE_MIRROR) { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); + } else if (tiling === WTCGL.IMAGETYPE_REGULAR) { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + } + + // Create and bind the framebuffer + const fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + // attach the texture as the first color attachment + const attachmentPoint = gl.COLOR_ATTACHMENT0; + const level = 0; + gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, targetTexture, level); + + return { + w: w * this.pxratio, + h: h * this.pxratio, + fb: fb, + frameTexture: targetTexture }; + + } + + + /** + * Resizes the canvas to a specified width and height, respecting the pixel ratio + * + * @param {number} w The width of the canvas + * @param {number} h The height of the canvas + * @return {Void} + */ + resize(w, h) { + this.width = w; + this.height = h; + this._el.width = w * this.pxratio; + this._el.height = h * this.pxratio; + this._size = [w * this.pxratio, h * this.pxratio]; + if (this.styleElement) { + this._el.style.width = w + 'px'; + this._el.style.height = h + 'px'; + } + + this._ctx.viewportWidth = w * this.pxratio; + this._ctx.viewportHeight = h * this.pxratio; + + this._ctx.uniform2fv(this._programInfo.uniforms.resolution, this._size); + + this.initBuffers(this._positions); + } + + /** + * Initialise a provided vertex buffer + * + * @param {array} positions The vertex positions to initialise + * @return {Void} + */ + initBuffers(positions) { + this._positions = positions; + this._positionBuffer = this._ctx.createBuffer(); + + this._ctx.bindBuffer(this._ctx.ARRAY_BUFFER, this._positionBuffer); + + this._ctx.bufferData(this._ctx.ARRAY_BUFFER, + new Float32Array(positions), + this._ctx.STATIC_DRAW); + } + + /** + * Add a uniform to the program. At this time the following types are supported: + * - Float - WTCGL.TYPE_FLOAT + * - Vector 2 - WTCGL.TYPE_V2 + * - Vector 3 - WTCGL.TYPE_V3 + * - Vector 4 - WTCGL.TYPE_V4 + * + * @param {string} name The name of the uniform. N.B. your name will be prepended with a `u_` in your shaders. So providing a name of `foo` here will result in a uniform named `u_foo` + * @param {WTCGL.UNIFORM_TYPE} type The unfiform type + * @param {number|array} value The unfiform value. The type depends on the uniform type being created + * @return {WebGLUniformLocation} The uniform location for later reference + */ + addUniform(name, type, value) { + let uniform = this._programInfo.uniforms[name]; + uniform = this._ctx.getUniformLocation(this._program, `u_${name}`); + switch (type) { + case WTCGL.TYPE_INT: + if (!isNaN(value)) this._ctx.uniform1i(uniform, value); + break; + case WTCGL.TYPE_FLOAT: + if (!isNaN(value)) this._ctx.uniform1f(uniform, value); + break; + case WTCGL.TYPE_V2: + if (value instanceof Array && value.length === 2.) this._ctx.uniform2fv(uniform, value); + break; + case WTCGL.TYPE_V3: + if (value instanceof Array && value.length === 3.) this._ctx.uniform3fv(uniform, value); + break; + case WTCGL.TYPE_V4: + if (value instanceof Array && value.length === 4.) this._ctx.uniform4fv(uniform, value); + break; + case WTCGL.TYPE_BOOL: + if (!isNaN(value)) this._ctx.uniform1i(uniform, value); + break;} + + this._programInfo.uniforms[name] = uniform; + return uniform; + } + + /** + * Adds a texture to the program and links it to a named uniform. Providing the type changes the tiling properties of the texture. Possible values for type: + * - WTCGL.IMAGETYPE_REGULAR - No tiling, clamp to edges and doesn't need to be power of 2. + * - WTCGL.IMAGETYPE_TILE - full x and y tiling, needs to be power of 2. + * - WTCGL.IMAGETYPE_MIRROR - mirror tiling, needs to be power of 2. + * + * @public + * @param {string} name The name of the uniform. N.B. your name will be prepended with a `u_` in your shaders. So providing a name of `foo` here will result in a uniform named `u_foo` + * @param {WTCGL.TYPE_IMAGETYPE} type The type of texture to create. This is basically the tiling behaviour of the texture as described above + * @param {Image} image The image object to add to the texture + * @return {WebGLTexture} The texture object + */ + addTexture(name, type, image, liveUpdate = false) { + + var texture = this._ctx.createTexture(); + this._ctx.pixelStorei(this._ctx.UNPACK_FLIP_Y_WEBGL, true); + this._ctx.bindTexture(this._ctx.TEXTURE_2D, texture); + + // this._ctx.generateMipmap(this._ctx.TEXTURE_2D); + + // Set the parameters based on the passed type + if (type === WTCGL.IMAGETYPE_MIRROR) { + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_WRAP_S, this._ctx.MIRRORED_REPEAT); + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_WRAP_T, this._ctx.MIRRORED_REPEAT); + } else if (type === WTCGL.IMAGETYPE_REGULAR) { + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_WRAP_S, this._ctx.CLAMP_TO_EDGE); + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_WRAP_T, this._ctx.CLAMP_TO_EDGE); + } + + this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_MIN_FILTER, this._ctx.LINEAR); + // this._ctx.texParameteri(this._ctx.TEXTURE_2D, this._ctx.TEXTURE_MAG_FILTER, this._ctx.LINEAR); + + // Upload the image into the texture. + this._ctx.texImage2D(this._ctx.TEXTURE_2D, 0, this._ctx.RGBA, this._ctx.RGBA, this._ctx.UNSIGNED_BYTE, image); + + // add the texture to the array of textures. + this.pushTexture(name, texture, image, this._ctx.TEXTURE_2D, liveUpdate); + + + return texture; + } + + pushTexture(name, texture, image, target, liveUpdate = false) { + let textures = this.textures; + + textures.push({ name: name, tex: texture, liveUpdate: liveUpdate, image: image, target: target }); + + // Finally set the this.textures (this is just to get around the funnyness of default getters) + this.textures = textures; + } + + /** + * Updates a texture location for a given WebGLTexture with an image + * + * @param {WebGLTexture} texture The texture location to update + * @param {Image} image The image object to add to the texture + * @return {Void} + */ + updateTexture(texture, image, name) { + + let uniform = this._ctx.getUniformLocation(this._program, `u_${name}`); + // Set the texture unit to the uniform + this._ctx.uniform1i(uniform, 0); + this._ctx.activeTexture(this._ctx.TEXTURE0); + + this._ctx.bindTexture(this._ctx.TEXTURE_2D, texture); + // Upload the image into the texture. + this._ctx.texImage2D(this._ctx.TEXTURE_2D, 0, this._ctx.RGBA, this._ctx.RGBA, this._ctx.UNSIGNED_BYTE, image); + } + + /** + * Initialise texture locations in the program + * + * @return {Void} + */ + initTextures() { + for (let i = 0; i < this.textures.length; i++) { + let name = this.textures[i].name; + let uniform = this._programInfo.uniforms[name]; + uniform = this._ctx.getUniformLocation(this._program, `u_${name}`); + + // Set the texture unit to the uniform + this._ctx.uniform1i(uniform, i); + + // find the active texture based on the index + this._ctx.activeTexture(this._ctx[`TEXTURE${i}`]); + + // Finally, bind the texture + this._ctx.bindTexture(this.textures[i].target, this.textures[i].tex); + } + } + + /** + * The run loop. This function is run as a part of a RaF and updates the internal + * time uniform (`u_time`). + * + * @param {number} delta The delta time provided by the RaF loop + * @return {Void} + */ + run(delta) { + this.running && requestAnimationFrame(this.run); + + const runFunction = () => { + this.time = this.startTime + delta * .0002; + this.onRun(delta); + this.render(); + }; + + if (this.frameRate) { + let now = Date.now(); + let elapsed = now - this._then; + + if (elapsed > this.frameRate) { + this._then = now - elapsed % this.frameRate; + + runFunction(); + } + } else { + runFunction(); + } + } + + /** + * Render the program + * + * @return {Void} + */ + render(buffer = {}) { + this._ctx.bindFramebuffer(this._ctx.FRAMEBUFFER, buffer.fb || null); + // Update the time uniform + this._ctx.uniform1f(this._programInfo.uniforms.time, this.time); + + this.textures.forEach(textureInfo => { + if (textureInfo.liveUpdate === true) { + this.updateTexture(textureInfo.tex, textureInfo.image, textureInfo.name); + } + }); + + this._ctx.viewport(0, 0, buffer.w || this._ctx.viewportWidth, buffer.h || this._ctx.viewportHeight); + if (this.clearing) { + this._ctx.clearColor(1.0, 0.0, 0.0, 0.0); + // this._ctx.clearDepth(1.0); + // this._ctx.enable(this._ctx.DEPTH_TEST); + // this._ctx.depthFunc(this._ctx.LEQUAL); + + this._ctx.blendFunc(this._ctx.SRC_ALPHA, this._ctx.ONE_MINUS_SRC_ALPHA); + + this._ctx.clear(this._ctx.COLOR_BUFFER_BIT); + } + + this._ctx.bindBuffer(this._ctx.ARRAY_BUFFER, this._positionBuffer); + this._ctx.vertexAttribPointer( + this._programInfo.attribs.vertexPosition, + 3, + this._ctx.FLOAT, + false, + 0, + 0); + this._ctx.enableVertexAttribArray(this._programInfo.attribs.vertexPosition); + + // Set the shader uniforms + this.includePerspectiveMatrix && this._ctx.uniformMatrix4fv(this._programInfo.uniforms.projectionMatrix, false, this.perspectiveMatrix); + this.includeModelViewMatrix && this._ctx.uniformMatrix4fv(this._programInfo.uniforms.modelViewMatrix, false, this.modelViewMatrix); + + this._ctx.drawArrays(this._ctx.TRIANGLE_STRIP, 0, 4); + } + + + /** + * Getters and setters + */ + + /** + * The default webGL parameters to be used for the program. + * This is read only and should only be overridden as a part of a subclass. + * + * @readonly + * @type {object} + * @default { alpha: true } + */ + get webgl_params() { + return { alpha: true }; + } + + /** + * (getter/setter) Whether the element should include styling as a part of + * its rendition. + * + * @type {boolean} + * @default true + */ + set styleElement(value) { + this._styleElement = value === true; + if (this._styleElement === false && this._el) { + this._el.style.width = ''; + this._el.style.height = ''; + } + } + get styleElement() { + return this._styleElement !== false; + } + + /** + * (getter/setter) startTime. This is a value to begin the `u_time` + * unform at. This is here in case you want `u_time` to begin at a + * specific value other than 0. + * + * @type {number} + * @default 0 + */ + set startTime(value) { + if (!isNaN(value)) { + this._startTime = value; + } + } + get startTime() { + return this._startTime || 0; + } + + /** + * (getter/setter) time. This is the time that the program currently + * sits at. By default this value is set as a part of the run loop + * however this is a public property so that we can specify time + * for rendition outside of the run loop. + * + * @type {number} + * @default 0 + */ + set time(value) { + if (!isNaN(value)) { + this._time = value; + } + } + get time() { + return this._time || 0; + } + + /** + * (getter/setter) includePerspectiveMatrix. This determines whether the + * perspecive matrix is included in the program. This doesn't really make + * a difference right now, but this is here to provide future interoperability. + * + * @type {boolean} + * @default false + */ + set includePerspectiveMatrix(value) { + this._includePerspectiveMatrix = value === true; + } + get includePerspectiveMatrix() { + return this._includePerspectiveMatrix === true; + } + + /** + * (getter/setter) includeModelViewMatrix. This determines whether the + * model view matrix is included in the program. This doesn't really make + * a difference right now, but this is here to provide future interoperability. + * + * @type {boolean} + * @default false + */ + set includeModelViewMatrix(value) { + this._includeModelViewMatrix = value === true; + } + get includeModelViewMatrix() { + return this._includeModelViewMatrix === true; + } + + /** + * (getter/setter) textures. The array of textures to initialise into the program. + * + * @private + * @type {array} + * @default [] + */ + set textures(value) { + if (value instanceof Array) { + this._textures = value; + } + } + get textures() { + return this._textures || []; + } + + /** + * (getter/setter) clearing. Specifies whether the program should clear the screen + * before drawing anew. + * + * @type {boolean} + * @default false + */ + set clearing(value) { + this._clearing = value === true; + } + get clearing() { + return this._clearing === true; + } + + /** + * (getter/setter) running. Specifies whether the programming is running. Setting + * this to true will create a RaF loop which will call the run function. + * + * @type {boolean} + * @default false + */ + set running(value) { + if (!this.running && value === true) { + + this._then = Date.now(); + + requestAnimationFrame(this.run); + } + this._running = value === true; + } + get running() { + return this._running === true; + } + + set frameRate(value) { + if (!isNaN(value)) this._frameRate = 1000 / value; + } + get frameRate() { + return this._frameRate || null; + } + + /** + * (getter/setter) pxratio. The 1-dimensional pixel ratio of the application. + * This should be used either for making a program look good on high density + * screens or for raming down pixel density for performance. + * + * @type {number} + * @default 1 + */ + set pxratio(value) { + if (value > 0) this._pxratio = value; + } + get pxratio() { + return this._pxratio || 1; + } + + /** + * (getter/setter) perspectiveMatrix. Calculate a perspective matrix, a + * special matrix that is used to simulate the distortion of perspective in + * a camera. Our field of view is 45 degrees, with a width/height ratio + * that matches the display size of the canvas and we only want to see + * objects between 0.1 units and 100 units away from the camera. + * + * @readonly + * @type {mat4} + */ + get perspectiveMatrix() { + const fieldOfView = 45 * Math.PI / 180; // in radians + const aspect = this._size.w / this._size.h; + const zNear = 0.1; + const zFar = 100.0; + const projectionMatrix = mat4.create(); + // note: glmatrix.js always has the first argument + // as the destination to receive the result. + mat4.perspective(projectionMatrix, + fieldOfView, + aspect, + zNear, + zFar); + + return projectionMatrix; + } + + /** + * (getter/setter) perspectiveMatrix. Calculate a model view matrix. + * + * @readonly + * @type {mat4} + */ + get modelViewMatrix() { + // Set the drawing position to the "identity" point, which is + // the center of the scene. + const modelViewMatrix = mat4.create(); + + // Now move the drawing position a bit to where we want to + // start drawing the square. + mat4.translate(modelViewMatrix, // destination matrix + modelViewMatrix, // matrix to translate + [-0.0, 0.0, -1.]); // amount to translate + + return modelViewMatrix; + } + + set onRun(runMethod) { + if (typeof runMethod == 'function') { + this._onRun = runMethod.bind(this); + } + } + get onRun() { + return this._onRun; + } + + get context() { + return this._ctx || null; + } + + /** + * Static Methods + */ + + /** + * Create a shader of a given type given a context, type and source. + * + * @static + * @param {WebGLContext} ctx The context under which to create the shader + * @param {WebGLShaderType} type The shader type, vertex or fragment + * @param {string} source The shader source. + * @return {WebGLShader} The created shader + */ + static createShaderOfType(ctx, type, source) { + const shader = ctx.createShader(type); + ctx.shaderSource(shader, source); + ctx.compileShader(shader); + + if (!ctx.getShaderParameter(shader, ctx.COMPILE_STATUS)) { + console.log('An error occurred compiling the shaders: ' + ctx.getShaderInfoLog(shader)); + ctx.deleteShader(shader); + return null; + } + + return shader; + }} + + +WTCGL.TYPE_INT = 0; +WTCGL.TYPE_FLOAT = 1; +WTCGL.TYPE_V2 = 2; +WTCGL.TYPE_V3 = 3; +WTCGL.TYPE_V4 = 4; +WTCGL.TYPE_BOOL = 5; + +WTCGL.IMAGETYPE_REGULAR = 0; +WTCGL.IMAGETYPE_TILE = 1; +WTCGL.IMAGETYPE_MIRROR = 2; + +WTCGL.TEXTYPE_FLOAT = 0; +WTCGL.TEXTYPE_UNSIGNED_BYTE = 1; +WTCGL.TEXTYPE_HALF_FLOAT_OES = 2; +console.clear(); + +const twodWebGL = new WTCGL( +document.querySelector('canvas#webgl'), +document.querySelector('script#vertexShader').textContent, +document.querySelector('script#fragmentShader').textContent, +window.innerWidth, +window.innerHeight, +window.devicePixelRatio, +false); + +twodWebGL.startTime = -10; + +let debounce; +window.addEventListener('resize', () => { + clearInterval(debounce); + debounce = setInterval(() => { + twodWebGL.resize(window.innerWidth, window.innerHeight); + }, 100); +}); + + + + + + +// track mouse move +let mousepos = [0, 0]; +const u_mousepos = twodWebGL.addUniform('mouse', WTCGL.TYPE_V2, mousepos); +window.addEventListener('pointermove', e => { + let ratio = window.innerHeight / window.innerWidth; + if (window.innerHeight > window.innerWidth) { + mousepos[0] = (e.pageX - window.innerWidth / 2) / window.innerWidth; + mousepos[1] = (e.pageY - window.innerHeight / 2) / window.innerHeight * -1 * ratio; + } else { + mousepos[0] = (e.pageX - window.innerWidth / 2) / window.innerWidth / ratio; + mousepos[1] = (e.pageY - window.innerHeight / 2) / window.innerHeight * -1; + } + twodWebGL.addUniform('mouse', WTCGL.TYPE_V2, mousepos); +}); + + + + + + + + + +// Load all our textures. We only initiate the instance once all images are loaded. +const textures = [ +{ + name: 'noise', + url: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/982762/noise.png', + type: WTCGL.IMAGETYPE_TILE, + img: null }]; + + +const loadImage = function (imageObject) { + let img = document.createElement('img'); + img.crossOrigin = "anonymous"; + + return new Promise((resolve, reject) => { + img.addEventListener('load', e => { + imageObject.img = img; + resolve(imageObject); + }); + img.addEventListener('error', e => { + reject(e); + }); + img.src = imageObject.url; + }); +}; +const loadTextures = function (textures) { + return new Promise((resolve, reject) => { + const loadTexture = pointer => { + if (pointer >= textures.length || pointer > 10) { + resolve(textures); + return; + }; + const imageObject = textures[pointer]; + + const p = loadImage(imageObject); + p.then( + result => { + twodWebGL.addTexture(result.name, result.type, result.img); + }, + error => { + console.log('error', error); + }).finally(e => { + loadTexture(pointer + 1); + }); + }; + loadTexture(0); + }); + +}; + +loadTextures(textures).then( +result => { + twodWebGL.initTextures(); + // twodWebGL.render(); + twodWebGL.running = true; +}, +error => { + console.log('error'); +}); \ No newline at end of file diff --git a/animations/infinity-tunnel/style.css b/animations/infinity-tunnel/style.css new file mode 100644 index 0000000..a739a30 --- /dev/null +++ b/animations/infinity-tunnel/style.css @@ -0,0 +1,9 @@ +body { + margin:0; +} + +canvas { + height: 100vh !important; + position: fixed; + width: 100vw !important; +} \ No newline at end of file diff --git a/animations/modern-tunnel-vision/README.md b/animations/modern-tunnel-vision/README.md new file mode 100644 index 0000000..aef8116 --- /dev/null +++ b/animations/modern-tunnel-vision/README.md @@ -0,0 +1,3 @@ +# Modern Tunnel Vision + +![image](/attachments/8dc80b64-8e2c-4df4-ad9c-f3ebf4f15374) \ No newline at end of file diff --git a/animations/modern-tunnel-vision/index.html b/animations/modern-tunnel-vision/index.html new file mode 100644 index 0000000..8bc790e --- /dev/null +++ b/animations/modern-tunnel-vision/index.html @@ -0,0 +1,13 @@ + + + + + Tunnel Vision + + + + + + + + diff --git a/animations/modern-tunnel-vision/map5.png b/animations/modern-tunnel-vision/map5.png new file mode 100644 index 0000000..f9ba5d5 Binary files /dev/null and b/animations/modern-tunnel-vision/map5.png differ diff --git a/animations/modern-tunnel-vision/script.js b/animations/modern-tunnel-vision/script.js new file mode 100644 index 0000000..76bab26 --- /dev/null +++ b/animations/modern-tunnel-vision/script.js @@ -0,0 +1,85 @@ +//===================================================== Create a WebGL renderer +var renderer = new THREE.WebGLRenderer({ + canvas: document.querySelector("canvas"), + powerPreference: "high-performance" +}); +renderer.setSize(window.innerWidth, window.innerHeight); + +//===================================================== Create an empty scene +var scene = new THREE.Scene(); + +//===================================================== Create a perpsective camera +var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.001, 1000); +camera.position.z = 400; + + +//===================================================== resize +window.addEventListener("resize", function() { + renderer.setSize(window.innerWidth, window.innerHeight); + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); +}); + + +//===================================================== Array of points +var points = [ + [68.5,185.5], + [1,262.5], + [270.9,281.9], + [345.5,212.8], + [178,155.7], + [240.3,72.3], + [153.4,0.6], + [52.6,53.3], + [68.5,185.5] +]; + +//===================================================== Convert the array of points into vertices +for (var i = 0; i < points.length; i++) { + var x = points[i][0]; + var y = 0; + var z = points[i][1]; + points[i] = new THREE.Vector3(x, y, z); +} +//===================================================== Create a path from the points +var path = new THREE.CatmullRomCurve3(points); + +//===================================================== Create the tube geometry from the path +var sides = 3; +var geometry = new THREE.TubeGeometry( path, 300, 4, sides, true ); + +//===================================================== Basic material +var material = new THREE.MeshBasicMaterial({ + side : THREE.BackSide, + map: new THREE.TextureLoader().load('https://raw.githubusercontent.com/baronwatts/images/master/map5.png') +}); + material.map.wrapS = THREE.RepeatWrapping; +material.map.wrapT= THREE.RepeatWrapping; +material.map.repeat.set(10, 1) +//===================================================== Create a mesh +var tube = new THREE.Mesh( geometry, material ); +tube.matrixAutoUpdate = false;//wont be moving so no need to update +scene.add( tube ); + +//===================================================== Create a point light in our scene +var light = new THREE.PointLight(new THREE.Color("white"),1, 100); +scene.add(light); + + +//===================================================== Animate +var percentage = 0; + +function animate() { + percentage += 0.0005; + var p1 = path.getPointAt(percentage%1); + var p2 = path.getPointAt((percentage + 0.03)%1); + camera.position.set(p1.x,p1.y,p1.z); + camera.lookAt(p2); + light.position.set(p2.x, p2.y, p2.z); + + //Render the scene + renderer.render(scene, camera); + requestAnimationFrame(animate); +} + +animate(); \ No newline at end of file diff --git a/animations/modern-tunnel-vision/style.css b/animations/modern-tunnel-vision/style.css new file mode 100644 index 0000000..511682e --- /dev/null +++ b/animations/modern-tunnel-vision/style.css @@ -0,0 +1,8 @@ +html, +body { + margin: 0; + padding: 0; + background: black; + overflow: hidden; + height: 100%; +} \ No newline at end of file diff --git a/animations/time-to-drink-coffee/README.md b/animations/time-to-drink-coffee/README.md new file mode 100644 index 0000000..b7bcc39 --- /dev/null +++ b/animations/time-to-drink-coffee/README.md @@ -0,0 +1,4 @@ +# Time to Drink Coffee Animation + +![image](/attachments/dfe21f29-12a9-484b-a194-017141825c74) + diff --git a/animations/time-to-drink-coffee/index.html b/animations/time-to-drink-coffee/index.html new file mode 100644 index 0000000..5a2e4d5 --- /dev/null +++ b/animations/time-to-drink-coffee/index.html @@ -0,0 +1,72 @@ + + + + + Time to Drink Coffee Animation + + + + + + +
+
TIME TO DRINK COFFEE?
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + diff --git a/animations/time-to-drink-coffee/script.js b/animations/time-to-drink-coffee/script.js new file mode 100644 index 0000000..2268d59 --- /dev/null +++ b/animations/time-to-drink-coffee/script.js @@ -0,0 +1,18 @@ +const tl = gsap.timeline(); + +tl.to('.stroke', { + duration: 2.5, + delay: 1.8, + strokeDashoffset: 0 }). + +to('.ripple', { + duration: 4, + delay: -2, + xPercent: -50, + yPercent: -60 }). + +to('#turbulence', { + duration: 1.5, + delay: -2, + attr: { + baseFrequency: '0 0' } }); \ No newline at end of file diff --git a/animations/time-to-drink-coffee/style.css b/animations/time-to-drink-coffee/style.css new file mode 100644 index 0000000..95a55c9 --- /dev/null +++ b/animations/time-to-drink-coffee/style.css @@ -0,0 +1,75 @@ +body { + background-color: #232f3a; + height: 100vh; + display: grid; + place-items: center; +} +body .draw-box { + overflow: hidden; + position: relative; + margin-top: 60px; + width: 335px; +} +body .draw-box .typewriter-effect { + overflow: hidden; + -webkit-animation: typingEffect 1.6s steps(22) forwards, blinkTextCursor 1s infinite; + animation: typingEffect 1.6s steps(22) forwards, blinkTextCursor 1s infinite; + width: 0; + color: #e8e8e8; + height: 30px; + font-size: 34px; + white-space: nowrap; + vertical-align: middle; + line-height: 0.9; + font-family: "Barlow Semi Condensed", sans-serif; +} +@-webkit-keyframes typingEffect { + from { + width: 0; + } + to { + width: 98%; + } +} +@keyframes typingEffect { + from { + width: 0; + } + to { + width: 98%; + } +} +@-webkit-keyframes blinkTextCursor { + from { + border-right: 3px solid #f8f8f8; + } + to { + border-right: transparent; + } +} +@keyframes blinkTextCursor { + from { + border-right: 3px solid #f8f8f8; + } + to { + border-right: transparent; + } +} +body .draw-box svg { + width: 93%; + margin-top: 10px; +} +body .draw-box svg .stroke { + fill: none; + stroke: #e8e8e8; + stroke-width: 0.8; +} +body .draw-box svg .coffeeColor { + fill: #b59440; +} +body .draw-box svg .steamColor { + fill: #ddd; +} +body .draw-box svg .ripple { + transform: translate3d(-30%, 100%, 0); +} \ No newline at end of file diff --git a/buttons-and-toggles/confetti-button/README.md b/buttons-and-toggles/confetti-button/README.md new file mode 100644 index 0000000..a3b43d7 --- /dev/null +++ b/buttons-and-toggles/confetti-button/README.md @@ -0,0 +1,5 @@ +# Confetti Button + +Confetti using JS, SCSS, and a HTML5 canvas. + +![image](/attachments/037e2fe9-8348-4313-9404-246e8cdd2d7c) \ No newline at end of file diff --git a/buttons-and-toggles/confetti-button/index.html b/buttons-and-toggles/confetti-button/index.html new file mode 100644 index 0000000..adb4299 --- /dev/null +++ b/buttons-and-toggles/confetti-button/index.html @@ -0,0 +1,40 @@ + + + + + Confetti Button + + + + + + + + + + + + + + diff --git a/buttons-and-toggles/confetti-button/script.js b/buttons-and-toggles/confetti-button/script.js new file mode 100644 index 0000000..5170ac4 --- /dev/null +++ b/buttons-and-toggles/confetti-button/script.js @@ -0,0 +1,238 @@ +// ammount to add on each button press +const confettiCount = 20 +const sequinCount = 10 + +// "physics" variables +const gravityConfetti = 0.3 +const gravitySequins = 0.55 +const dragConfetti = 0.075 +const dragSequins = 0.02 +const terminalVelocity = 3 + +// init other global elements +const button = document.getElementById('button') +var disabled = false +const canvas = document.getElementById('canvas') +const ctx = canvas.getContext('2d') +canvas.width = window.innerWidth +canvas.height = window.innerHeight +let cx = ctx.canvas.width / 2 +let cy = ctx.canvas.height / 2 + +// add Confetto/Sequin objects to arrays to draw them +let confetti = [] +let sequins = [] + +// colors, back side is darker for confetti flipping +const colors = [ + { front : '#7b5cff', back: '#6245e0' }, // Purple + { front : '#b3c7ff', back: '#8fa5e5' }, // Light Blue + { front : '#5c86ff', back: '#345dd1' } // Darker Blue +] + +// helper function to pick a random number within a range +randomRange = (min, max) => Math.random() * (max - min) + min + +// helper function to get initial velocities for confetti +// this weighted spread helps the confetti look more realistic +initConfettoVelocity = (xRange, yRange) => { + const x = randomRange(xRange[0], xRange[1]) + const range = yRange[1] - yRange[0] + 1 + let y = yRange[1] - Math.abs(randomRange(0, range) + randomRange(0, range) - range) + if (y >= yRange[1] - 1) { + // Occasional confetto goes higher than the max + y += (Math.random() < .25) ? randomRange(1, 3) : 0 + } + return {x: x, y: -y} +} + +// Confetto Class +function Confetto() { + this.randomModifier = randomRange(0, 99) + this.color = colors[Math.floor(randomRange(0, colors.length))] + this.dimensions = { + x: randomRange(5, 9), + y: randomRange(8, 15), + } + this.position = { + x: randomRange(canvas.width/2 - button.offsetWidth/4, canvas.width/2 + button.offsetWidth/4), + y: randomRange(canvas.height/2 + button.offsetHeight/2 + 8, canvas.height/2 + (1.5 * button.offsetHeight) - 8), + } + this.rotation = randomRange(0, 2 * Math.PI) + this.scale = { + x: 1, + y: 1, + } + this.velocity = initConfettoVelocity([-9, 9], [6, 11]) +} +Confetto.prototype.update = function() { + // apply forces to velocity + this.velocity.x -= this.velocity.x * dragConfetti + this.velocity.y = Math.min(this.velocity.y + gravityConfetti, terminalVelocity) + this.velocity.x += Math.random() > 0.5 ? Math.random() : -Math.random() + + // set position + this.position.x += this.velocity.x + this.position.y += this.velocity.y + + // spin confetto by scaling y and set the color, .09 just slows cosine frequency + this.scale.y = Math.cos((this.position.y + this.randomModifier) * 0.09) +} + +// Sequin Class +function Sequin() { + this.color = colors[Math.floor(randomRange(0, colors.length))].back, + this.radius = randomRange(1, 2), + this.position = { + x: randomRange(canvas.width/2 - button.offsetWidth/3, canvas.width/2 + button.offsetWidth/3), + y: randomRange(canvas.height/2 + button.offsetHeight/2 + 8, canvas.height/2 + (1.5 * button.offsetHeight) - 8), + }, + this.velocity = { + x: randomRange(-6, 6), + y: randomRange(-8, -12) + } +} +Sequin.prototype.update = function() { + // apply forces to velocity + this.velocity.x -= this.velocity.x * dragSequins + this.velocity.y = this.velocity.y + gravitySequins + + // set position + this.position.x += this.velocity.x + this.position.y += this.velocity.y +} + +// add elements to arrays to be drawn +initBurst = () => { + for (let i = 0; i < confettiCount; i++) { + confetti.push(new Confetto()) + } + for (let i = 0; i < sequinCount; i++) { + sequins.push(new Sequin()) + } +} + +// draws the elements on the canvas +render = () => { + ctx.clearRect(0, 0, canvas.width, canvas.height) + + confetti.forEach((confetto, index) => { + let width = (confetto.dimensions.x * confetto.scale.x) + let height = (confetto.dimensions.y * confetto.scale.y) + + // move canvas to position and rotate + ctx.translate(confetto.position.x, confetto.position.y) + ctx.rotate(confetto.rotation) + + // update confetto "physics" values + confetto.update() + + // get front or back fill color + ctx.fillStyle = confetto.scale.y > 0 ? confetto.color.front : confetto.color.back + + // draw confetto + ctx.fillRect(-width / 2, -height / 2, width, height) + + // reset transform matrix + ctx.setTransform(1, 0, 0, 1, 0, 0) + + // clear rectangle where button cuts off + if (confetto.velocity.y < 0) { + ctx.clearRect(canvas.width/2 - button.offsetWidth/2, canvas.height/2 + button.offsetHeight/2, button.offsetWidth, button.offsetHeight) + } + }) + + sequins.forEach((sequin, index) => { + // move canvas to position + ctx.translate(sequin.position.x, sequin.position.y) + + // update sequin "physics" values + sequin.update() + + // set the color + ctx.fillStyle = sequin.color + + // draw sequin + ctx.beginPath() + ctx.arc(0, 0, sequin.radius, 0, 2 * Math.PI) + ctx.fill() + + // reset transform matrix + ctx.setTransform(1, 0, 0, 1, 0, 0) + + // clear rectangle where button cuts off + if (sequin.velocity.y < 0) { + ctx.clearRect(canvas.width/2 - button.offsetWidth/2, canvas.height/2 + button.offsetHeight/2, button.offsetWidth, button.offsetHeight) + } + }) + + // remove confetti and sequins that fall off the screen + // must be done in seperate loops to avoid noticeable flickering + confetti.forEach((confetto, index) => { + if (confetto.position.y >= canvas.height) confetti.splice(index, 1) + }) + sequins.forEach((sequin, index) => { + if (sequin.position.y >= canvas.height) sequins.splice(index, 1) + }) + + window.requestAnimationFrame(render) +} + +// cycle through button states when clicked +clickButton = () => { + if (!disabled) { + disabled = true + // Loading stage + button.classList.add('loading') + button.classList.remove('ready') + setTimeout(() => { + // Completed stage + button.classList.add('complete') + button.classList.remove('loading') + setTimeout(() => { + window.initBurst() + setTimeout(() => { + // Reset button so user can select it again + disabled = false + button.classList.add('ready') + button.classList.remove('complete') + }, 4000) + }, 320) + }, 1800) + } +} + +// re-init canvas if the window size changes +resizeCanvas = () => { + canvas.width = window.innerWidth + canvas.height = window.innerHeight + cx = ctx.canvas.width / 2 + cy = ctx.canvas.height / 2 +} + +// resize listenter +window.addEventListener('resize', () => { + resizeCanvas() +}) + +// click button on spacebar or return keypress +document.body.onkeyup = (e) => { + if (e.keyCode == 13 || e.keyCode == 32) { + clickButton() + } +} + +// Set up button text transition timings on page load +textElements = button.querySelectorAll('.button-text') +textElements.forEach((element) => { + characters = element.innerText.split('') + let characterHTML = '' + characters.forEach((letter, index) => { + characterHTML += `${letter}` + }) + element.innerHTML = characterHTML +}) + +// kick off the render loop +window.initBurst() +render() \ No newline at end of file diff --git a/buttons-and-toggles/confetti-button/style.css b/buttons-and-toggles/confetti-button/style.css new file mode 100644 index 0000000..510ed00 --- /dev/null +++ b/buttons-and-toggles/confetti-button/style.css @@ -0,0 +1,168 @@ +@keyframes loading { + 0% { + cy: 10; + } + 25% { + cy: 3; + } + 50% { + cy: 10; + } +} +body { + -webkit-font-smoothing: antialiased; + background-color: #f4f7ff; +} + +canvas { + height: 100vh; + pointer-events: none; + position: fixed; + width: 100%; + z-index: 2; +} + +button { + background: none; + border: none; + color: #f4f7ff; + cursor: pointer; + font-family: "Quicksand", sans-serif; + font-size: 14px; + font-weight: 500; + height: 40px; + left: 50%; + outline: none; + overflow: hidden; + padding: 0 10px; + position: fixed; + top: 50%; + transform: translate(-50%, -50%); + width: 190px; + -webkit-tap-highlight-color: transparent; + z-index: 1; +} +button::before { + background: #1f2335; + border-radius: 50px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4) inset; + content: ""; + display: block; + height: 100%; + margin: 0 auto; + position: relative; + transition: width 0.2s cubic-bezier(0.39, 1.86, 0.64, 1) 0.3s; + width: 100%; +} + +button.ready .submitMessage svg { + opacity: 1; + top: 1px; + transition: top 0.4s ease 600ms, opacity 0.3s linear 600ms; +} +button.ready .submitMessage .button-text span { + top: 0; + opacity: 1; + transition: all 0.2s ease calc(var(--dr) + 600ms); +} + +button.loading::before { + transition: width 0.3s ease; + width: 80%; +} +button.loading .loadingMessage { + opacity: 1; +} +button.loading .loadingCircle { + animation-duration: 1s; + animation-iteration-count: infinite; + animation-name: loading; + cy: 10; +} + +button.complete .submitMessage svg { + top: -30px; + transition: none; +} +button.complete .submitMessage .button-text span { + top: -8px; + transition: none; +} +button.complete .loadingMessage { + top: 80px; +} +button.complete .successMessage .button-text span { + left: 0; + opacity: 1; + transition: all 0.2s ease calc(var(--d) + 1000ms); +} +button.complete .successMessage svg { + stroke-dashoffset: 0; + transition: stroke-dashoffset 0.3s ease-in-out 1.4s; +} + +.button-text span { + opacity: 0; + position: relative; +} + +.message { + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + width: 100%; +} + +.message svg { + display: inline-block; + fill: none; + margin-right: 5px; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 2; +} + +.submitMessage .button-text span { + top: 8px; + transition: all 0.2s ease var(--d); +} +.submitMessage svg { + color: #5c86ff; + margin-left: -1px; + opacity: 0; + position: relative; + top: 30px; + transition: top 0.4s ease, opacity 0.3s linear; + width: 14px; +} + +.loadingMessage { + opacity: 0; + transition: opacity 0.3s linear 0.3s, top 0.4s cubic-bezier(0.22, 0, 0.41, -0.57); +} +.loadingMessage svg { + fill: #5c86ff; + margin: 0; + width: 22px; +} + +.successMessage .button-text span { + left: 5px; + transition: all 0.2s ease var(--dr); +} +.successMessage svg { + color: #5cffa1; + stroke-dasharray: 20; + stroke-dashoffset: 20; + transition: stroke-dashoffset 0.3s ease-in-out; + width: 14px; +} + +.loadingCircle:nth-child(2) { + animation-delay: 0.1s; +} + +.loadingCircle:nth-child(3) { + animation-delay: 0.2s; +} \ No newline at end of file diff --git a/buttons-and-toggles/download-button-animation/README.md b/buttons-and-toggles/download-button-animation/README.md index e87901d..5172a7c 100644 --- a/buttons-and-toggles/download-button-animation/README.md +++ b/buttons-and-toggles/download-button-animation/README.md @@ -1,6 +1,6 @@ # Download Button Animation These are animated download buttons, by clicking on them the download progress will be shown in the button. -![image](/attachments/df52f7e3-e262-44c4-b0ae-bbc2190dc9cc) +![image](/attachments/8be7d279-f31a-4428-b2a8-bb9fd254827b) \ No newline at end of file diff --git a/buttons-and-toggles/modern-toggles/README.md b/buttons-and-toggles/modern-toggles/README.md index 5cbebec..56b94c1 100644 --- a/buttons-and-toggles/modern-toggles/README.md +++ b/buttons-and-toggles/modern-toggles/README.md @@ -1,3 +1,3 @@ -# 2020 Toggles +# Modern Toggles - ![image](/attachments/38b1f3b3-374e-485c-a0b9-d88df6c75268) \ No newline at end of file +![image](/attachments/2e60b21f-3df4-4810-b0e3-1f56e7f89549) \ No newline at end of file diff --git a/buttons-and-toggles/multi-button-pill/README.md b/buttons-and-toggles/multi-button-pill/README.md index e6eca5f..d621b50 100644 --- a/buttons-and-toggles/multi-button-pill/README.md +++ b/buttons-and-toggles/multi-button-pill/README.md @@ -1,2 +1,3 @@ -# Multi-Button Pill -![image](/attachments/a027cee8-35fd-418e-85bc-9cef32796a5b) \ No newline at end of file +# Multi-Button Pill with hover effect + +![image](/attachments/fec564cf-c640-4a40-8306-8c26726f42c4) \ No newline at end of file diff --git a/buttons-and-toggles/power-switch-animation/README.md b/buttons-and-toggles/power-switch-animation/README.md index b50f3e6..d881080 100644 --- a/buttons-and-toggles/power-switch-animation/README.md +++ b/buttons-and-toggles/power-switch-animation/README.md @@ -2,4 +2,4 @@ A simple power switch animation -![image](/attachments/58131494-ccde-4473-bdb2-2f14f12dac8e) \ No newline at end of file +![image](/attachments/261f5dc6-8fbd-4a8b-ab55-e7003a5361fd) \ No newline at end of file diff --git a/buttons-and-toggles/responsive-numeric-stepper/README.md b/buttons-and-toggles/responsive-numeric-stepper/README.md index 2b48a81..1e5a5af 100644 --- a/buttons-and-toggles/responsive-numeric-stepper/README.md +++ b/buttons-and-toggles/responsive-numeric-stepper/README.md @@ -1,3 +1,5 @@ # Responsive numeric stepper Used as an example for utilising media queries with the display property to build a responsive numeric stepper. + +![image](/attachments/2cb701dc-aef5-48ac-ad50-46f5bf81ca81) \ No newline at end of file diff --git a/buttons-and-toggles/rolling-radio-buttons/README.md b/buttons-and-toggles/rolling-radio-buttons/README.md new file mode 100644 index 0000000..c93300a --- /dev/null +++ b/buttons-and-toggles/rolling-radio-buttons/README.md @@ -0,0 +1,5 @@ +# Rolling Radio Buttons + +A radio button concept where the checked button slides to the checked label while the others slide to the labels around it. + +![image](/attachments/ed83353b-5cb2-475b-b9fd-837d866df018) diff --git a/buttons-and-toggles/rolling-radio-buttons/index.html b/buttons-and-toggles/rolling-radio-buttons/index.html new file mode 100644 index 0000000..e897c8b --- /dev/null +++ b/buttons-and-toggles/rolling-radio-buttons/index.html @@ -0,0 +1,34 @@ + + + + + Rolling Radio Buttons + + + + + +
+ + + + + + + + +
+
+
+
+
+
+
+
+
+
+ + + + + diff --git a/buttons-and-toggles/rolling-radio-buttons/script.js b/buttons-and-toggles/rolling-radio-buttons/script.js new file mode 100644 index 0000000..be408e0 --- /dev/null +++ b/buttons-and-toggles/rolling-radio-buttons/script.js @@ -0,0 +1,42 @@ +document.addEventListener("DOMContentLoaded",() => { + let os = new RollingRadios("os"); +}); +class RollingRadios { + constructor(radioName) { + this.circles = document.querySelector(".circles"); + this.data_attr = "data-radio-index"; + this.last_focused_index = 0; + this.radio_name = radioName; + + this.first_focused_index(); + document.addEventListener("change",this.update_last_focused_index.bind(this)); + } + first_focused_index() { + let radios = document.getElementsByName(this.radio_name); + radios.forEach(r => { + if (r.checked) + this.update_last_focused_index(r); + }); + } + flip_delays(radioIndex) { + // flip the delays depending on which index is greater + if (this.circles) { + let lfi = this.last_focused_index, + flipClass = "circles-flip-delays"; + + if (radioIndex > lfi) + this.circles.classList.add(flipClass); + else if (radioIndex < lfi) + this.circles.classList.remove(flipClass); + } + } + update_last_focused_index(e) { + let tar = e.target || e, + radioIndex = tar.getAttribute(this.data_attr); + + if (tar.name == this.radio_name && radioIndex) { + this.flip_delays(radioIndex); + this.last_focused_index = radioIndex; + } + } +} \ No newline at end of file diff --git a/buttons-and-toggles/rolling-radio-buttons/style.css b/buttons-and-toggles/rolling-radio-buttons/style.css new file mode 100644 index 0000000..0ce19b1 --- /dev/null +++ b/buttons-and-toggles/rolling-radio-buttons/style.css @@ -0,0 +1,154 @@ +* { + border: 0; + box-sizing: border-box; + margin: 0; + padding: 0; +} +:root { + --bg: #e3e4e8; + --bgT: #e3e4e800; + --fg: #17181c; + --focused: #b6cafb; + --focusRing: #86a6f9; + --unchecked: #ffffff; + --checked: #255ff4; + font-size: calc(20px + (30 - 20) * (100vw - 320px) / (1280 - 320)); +} +body, input { + font: 1em/1.5 system-ui, -apple-system, sans-serif; +} +body { + background: var(--bg); + color: var(--fg); + display: flex; + height: 100vh; +} +form { + margin: auto; + overflow: hidden; + position: relative; + padding: 0.75em 0; +} +form:before, form:after, .circles, .circle { + position: absolute; +} +form:before, form:after { + content: ""; + left: 0; + width: 100%; + height: 0.5em; + z-index: 1; +} +form:before { + background: linear-gradient(var(--bg),var(--bgT)); + top: 0; +} +form:after { + background: linear-gradient(var(--bgT),var(--bg)); + bottom: 0; +} +input { + position: fixed; + top: -1.5em; + left: -1.5em; +} +input:checked + label { + background: var(--focused); + box-shadow: 0 0 0 2px var(--focusRing) inset; +} +input:nth-of-type(2):checked ~ .circles .circle { + transform: translateY(-6em); +} +input:nth-of-type(3):checked ~ .circles .circle { + transform: translateY(-3em); +} +input:nth-of-type(4):checked ~ .circles .circle { + transform: translateY(0); +} +label, .circle { + transition: all 0.25s ease-in-out; +} +label { + border-radius: 0.25em; + cursor: pointer; + display: block; + padding: 0.75em 1em 0.75em 2.75em; + -tap-highlight-color: transparent; +} +.circles { + padding: 0.25em 0; + top: 0; + left: 1em; +} +.circle { + background: var(--unchecked); + border-radius: 50%; + box-shadow: + -0.2em -0.2em 0.2em #0003 inset, + 0.2em 0.2em 0.2em #0003; + pointer-events: none; + top: 1.75em; + transform: translateY(-9em); + width: 1em; + height: 1em; +} +.circle:nth-child(2) { + top: 4.75em; + transition-delay: 0.05s; +} +.circle:nth-child(3) { + top: 7.75em; + transition-delay: 0.1s; +} +.circle:nth-child(4) { + top: 10.75em; + transition-delay: 0.15s; +} +.circle:nth-child(5) { + top: 13.75em; + transition-delay: 0.2s; +} +.circle:nth-child(6) { + top: 16.75em; + transition-delay: 0.25s; +} +.circle:nth-child(7) { + top: 19.75em; + transition-delay: 0.3s; +} +.circle-checked { + background: var(--checked); +} +.circles-flip-delays .circle:nth-child(1) { + transition-delay: 0.3s; +} +.circles-flip-delays .circle:nth-child(2) { + transition-delay: 0.25s; +} +.circles-flip-delays .circle:nth-child(3) { + transition-delay: 0.2s; +} +.circles-flip-delays .circle:nth-child(4) { + transition-delay: 0.15s; +} +.circles-flip-delays .circle:nth-child(5) { + transition-delay: 0.1s; +} +.circles-flip-delays .circle:nth-child(6) { + transition-delay: 0.05s; +} +.circles-flip-delays .circle:nth-child(7) { + transition-delay: 0s; +} + +/* Dark mode */ +@media (prefers-color-scheme: dark) { + :root { + --bg: #17181c; + --bgT: #17181c00; + --fg: #e3e4e8; + --focused: #062779; + --focusRing: #0936aa; + --unchecked: #5c6270; + } +} \ No newline at end of file diff --git a/buttons-and-toggles/social-media-buttons/README.md b/buttons-and-toggles/social-media-buttons/README.md index 05511aa..c651557 100644 --- a/buttons-and-toggles/social-media-buttons/README.md +++ b/buttons-and-toggles/social-media-buttons/README.md @@ -1,4 +1,4 @@ -# Social Media Buttons +# Social Media Buttons with hover effect -![image](/attachments/67546772-7c18-40c5-81f7-ffea803a61c2) +![image](/attachments/b529e81c-933c-4e72-9dcd-d8c96f54905e) diff --git a/cards/expanding-flex-cards/README.md b/cards/expanding-flex-cards/README.md index c78dc02..3a3ef70 100644 --- a/cards/expanding-flex-cards/README.md +++ b/cards/expanding-flex-cards/README.md @@ -1,2 +1,3 @@ # Expanding flex cards -![image](/attachments/a5c1bf9f-f879-4761-a47c-4847a99d56b1) \ No newline at end of file + +![image](/attachments/e783fd42-0567-41f3-a7c7-28b8b5b8c158) \ No newline at end of file diff --git a/cards/horizontal-cards-with-fade-animation/README.md b/cards/horizontal-cards-with-fade-animation/README.md index 41b9d0b..08faf86 100644 --- a/cards/horizontal-cards-with-fade-animation/README.md +++ b/cards/horizontal-cards-with-fade-animation/README.md @@ -2,4 +2,4 @@ Adding fade animation to material design horizontal cards. -![image](/attachments/d668dd81-0ec2-486f-85d9-68140682c854) \ No newline at end of file +![image](/attachments/c409f69e-ded5-4c07-bed7-a2e481d8d46a) \ No newline at end of file diff --git a/cards/horizontal-cards-with-fade-animation/index.html b/cards/horizontal-cards-with-fade-animation/index.html index 58cdb31..194ab81 100644 --- a/cards/horizontal-cards-with-fade-animation/index.html +++ b/cards/horizontal-cards-with-fade-animation/index.html @@ -4,10 +4,8 @@ Horizontal Cards with Fade Animation - - + -
diff --git a/css-effects/snow-pure-css/README.md b/css-effects/snow-pure-css/README.md index 768ea75..a1bcdf7 100644 --- a/css-effects/snow-pure-css/README.md +++ b/css-effects/snow-pure-css/README.md @@ -1,6 +1,6 @@ # Snow (Pure CSS) Snow effect as overlay for a website. -![image](/attachments/1963d6e2-c189-4453-91e2-adb67535ab6b) +![image](/attachments/c9ad4b6e-a7b5-4fc2-97ef-77b7dbe2f74a) This is a pure CSS version :) \ No newline at end of file diff --git a/css-effects/snow-pure-css/index.html b/css-effects/snow-pure-css/index.html index 9825eb3..090f999 100644 --- a/css-effects/snow-pure-css/index.html +++ b/css-effects/snow-pure-css/index.html @@ -7,7 +7,7 @@ - +
@@ -208,7 +208,6 @@
- \ No newline at end of file diff --git a/css-effects/snow-pure-css/style.css b/css-effects/snow-pure-css/style.css index 6ec7710..a5b5d44 100644 --- a/css-effects/snow-pure-css/style.css +++ b/css-effects/snow-pure-css/style.css @@ -13,2602 +13,2602 @@ body { border-radius: 50%; } .snow:nth-child(1) { - opacity: 0.3321; - transform: translate(79.5542vw, -10px) scale(0.878); - animation: fall-1 16s -5s linear infinite; + opacity: 0.3282; + transform: translate(89.1398vw, -10px) scale(0.8876); + animation: fall-1 14s -29s linear infinite; } @keyframes fall-1 { - 59.873% { - transform: translate(83.2147vw, 59.873vh) scale(0.878); + 71.205% { + transform: translate(85.0918vw, 71.205vh) scale(0.8876); } to { - transform: translate(81.38445vw, 100vh) scale(0.878); + transform: translate(87.1158vw, 100vh) scale(0.8876); } } .snow:nth-child(2) { - opacity: 0.4747; - transform: translate(38.6065vw, -10px) scale(0.2359); - animation: fall-2 29s -5s linear infinite; + opacity: 0.3985; + transform: translate(57.4151vw, -10px) scale(0.8103); + animation: fall-2 22s -5s linear infinite; } @keyframes fall-2 { - 38.555% { - transform: translate(29.625vw, 38.555vh) scale(0.2359); + 54.456% { + transform: translate(66.8037vw, 54.456vh) scale(0.8103); } to { - transform: translate(34.11575vw, 100vh) scale(0.2359); + transform: translate(62.1094vw, 100vh) scale(0.8103); } } .snow:nth-child(3) { - opacity: 0.7707; - transform: translate(52.3346vw, -10px) scale(0.5244); - animation: fall-3 15s -6s linear infinite; + opacity: 0.1027; + transform: translate(71.043vw, -10px) scale(0.335); + animation: fall-3 10s -7s linear infinite; } @keyframes fall-3 { - 35.44% { - transform: translate(49.7711vw, 35.44vh) scale(0.5244); + 67.962% { + transform: translate(65.16vw, 67.962vh) scale(0.335); } to { - transform: translate(51.05285vw, 100vh) scale(0.5244); + transform: translate(68.1015vw, 100vh) scale(0.335); } } .snow:nth-child(4) { - opacity: 0.4625; - transform: translate(79.3403vw, -10px) scale(0.5502); - animation: fall-4 12s -15s linear infinite; + opacity: 0.3945; + transform: translate(52.1082vw, -10px) scale(0.8956); + animation: fall-4 29s -11s linear infinite; } @keyframes fall-4 { - 63.052% { - transform: translate(77.3794vw, 63.052vh) scale(0.5502); + 61.507% { + transform: translate(48.3658vw, 61.507vh) scale(0.8956); } to { - transform: translate(78.35985vw, 100vh) scale(0.5502); + transform: translate(50.237vw, 100vh) scale(0.8956); } } .snow:nth-child(5) { - opacity: 0.1797; - transform: translate(0.5228vw, -10px) scale(0.3744); - animation: fall-5 15s -24s linear infinite; + opacity: 0.9045; + transform: translate(45.6104vw, -10px) scale(0.801); + animation: fall-5 16s -9s linear infinite; } @keyframes fall-5 { - 68.175% { - transform: translate(9.9995vw, 68.175vh) scale(0.3744); + 55.419% { + transform: translate(43.9766vw, 55.419vh) scale(0.801); } to { - transform: translate(5.26115vw, 100vh) scale(0.3744); + transform: translate(44.7935vw, 100vh) scale(0.801); } } .snow:nth-child(6) { - opacity: 0.3283; - transform: translate(56.4225vw, -10px) scale(0.8634); - animation: fall-6 24s -17s linear infinite; + opacity: 0.4365; + transform: translate(75.24vw, -10px) scale(0.2239); + animation: fall-6 24s -8s linear infinite; } @keyframes fall-6 { - 75.993% { - transform: translate(52.6582vw, 75.993vh) scale(0.8634); + 43.856% { + transform: translate(65.7644vw, 43.856vh) scale(0.2239); } to { - transform: translate(54.54035vw, 100vh) scale(0.8634); + transform: translate(70.5022vw, 100vh) scale(0.2239); } } .snow:nth-child(7) { - opacity: 0.8302; - transform: translate(81.1241vw, -10px) scale(0.5733); - animation: fall-7 16s -9s linear infinite; + opacity: 0.9864; + transform: translate(44.6724vw, -10px) scale(0.7267); + animation: fall-7 20s -3s linear infinite; } @keyframes fall-7 { - 41.262% { - transform: translate(88.1193vw, 41.262vh) scale(0.5733); + 77.842% { + transform: translate(38.9192vw, 77.842vh) scale(0.7267); } to { - transform: translate(84.6217vw, 100vh) scale(0.5733); + transform: translate(41.7958vw, 100vh) scale(0.7267); } } .snow:nth-child(8) { - opacity: 0.3479; - transform: translate(23.5397vw, -10px) scale(0.04); - animation: fall-8 25s -11s linear infinite; + opacity: 0.5748; + transform: translate(84.1605vw, -10px) scale(0.512); + animation: fall-8 25s -4s linear infinite; } @keyframes fall-8 { - 43.12% { - transform: translate(26.1963vw, 43.12vh) scale(0.04); + 50.735% { + transform: translate(81.281vw, 50.735vh) scale(0.512); } to { - transform: translate(24.868vw, 100vh) scale(0.04); + transform: translate(82.72075vw, 100vh) scale(0.512); } } .snow:nth-child(9) { - opacity: 0.7983; - transform: translate(2.5793vw, -10px) scale(0.5356); - animation: fall-9 28s -6s linear infinite; + opacity: 0.6782; + transform: translate(26.4493vw, -10px) scale(0.6371); + animation: fall-9 23s -6s linear infinite; } @keyframes fall-9 { - 31.482% { - transform: translate(8.1536vw, 31.482vh) scale(0.5356); + 62.353% { + transform: translate(32.3499vw, 62.353vh) scale(0.6371); } to { - transform: translate(5.36645vw, 100vh) scale(0.5356); + transform: translate(29.3996vw, 100vh) scale(0.6371); } } .snow:nth-child(10) { - opacity: 0.4828; - transform: translate(93.5824vw, -10px) scale(0.3453); - animation: fall-10 29s -23s linear infinite; + opacity: 0.8186; + transform: translate(61.6321vw, -10px) scale(0.9958); + animation: fall-10 27s -29s linear infinite; } @keyframes fall-10 { - 49.789% { - transform: translate(101.2609vw, 49.789vh) scale(0.3453); + 69.976% { + transform: translate(58.9648vw, 69.976vh) scale(0.9958); } to { - transform: translate(97.42165vw, 100vh) scale(0.3453); + transform: translate(60.29845vw, 100vh) scale(0.9958); } } .snow:nth-child(11) { - opacity: 0.6655; - transform: translate(72.9279vw, -10px) scale(0.7039); - animation: fall-11 22s -30s linear infinite; + opacity: 0.7751; + transform: translate(58.8453vw, -10px) scale(0.0456); + animation: fall-11 13s -18s linear infinite; } @keyframes fall-11 { - 69.061% { - transform: translate(76.3975vw, 69.061vh) scale(0.7039); + 41.84% { + transform: translate(62.7628vw, 41.84vh) scale(0.0456); } to { - transform: translate(74.6627vw, 100vh) scale(0.7039); + transform: translate(60.80405vw, 100vh) scale(0.0456); } } .snow:nth-child(12) { - opacity: 0.3052; - transform: translate(48.581vw, -10px) scale(0.6642); - animation: fall-12 18s -25s linear infinite; + opacity: 0.3407; + transform: translate(65.0088vw, -10px) scale(0.8444); + animation: fall-12 21s -22s linear infinite; } @keyframes fall-12 { - 33.582% { - transform: translate(47.2203vw, 33.582vh) scale(0.6642); + 61.924% { + transform: translate(67.6108vw, 61.924vh) scale(0.8444); } to { - transform: translate(47.90065vw, 100vh) scale(0.6642); + transform: translate(66.3098vw, 100vh) scale(0.8444); } } .snow:nth-child(13) { - opacity: 0.7564; - transform: translate(64.1084vw, -10px) scale(0.818); - animation: fall-13 26s -25s linear infinite; + opacity: 0.287; + transform: translate(18.2181vw, -10px) scale(0.9414); + animation: fall-13 26s -18s linear infinite; } @keyframes fall-13 { - 34.939% { - transform: translate(71.8161vw, 34.939vh) scale(0.818); + 35.757% { + transform: translate(20.0062vw, 35.757vh) scale(0.9414); } to { - transform: translate(67.96225vw, 100vh) scale(0.818); + transform: translate(19.11215vw, 100vh) scale(0.9414); } } .snow:nth-child(14) { - opacity: 0.7404; - transform: translate(75.2759vw, -10px) scale(0.6322); - animation: fall-14 15s -11s linear infinite; + opacity: 0.5248; + transform: translate(52.4835vw, -10px) scale(0.7226); + animation: fall-14 30s -15s linear infinite; } @keyframes fall-14 { - 67.053% { - transform: translate(73.6587vw, 67.053vh) scale(0.6322); + 45.43% { + transform: translate(48.7207vw, 45.43vh) scale(0.7226); } to { - transform: translate(74.4673vw, 100vh) scale(0.6322); + transform: translate(50.6021vw, 100vh) scale(0.7226); } } .snow:nth-child(15) { - opacity: 0.9338; - transform: translate(12.4005vw, -10px) scale(0.4153); - animation: fall-15 24s -21s linear infinite; + opacity: 0.414; + transform: translate(35.3485vw, -10px) scale(0.872); + animation: fall-15 23s -4s linear infinite; } @keyframes fall-15 { - 67.538% { - transform: translate(16.9804vw, 67.538vh) scale(0.4153); + 31.615% { + transform: translate(25.408vw, 31.615vh) scale(0.872); } to { - transform: translate(14.69045vw, 100vh) scale(0.4153); + transform: translate(30.37825vw, 100vh) scale(0.872); } } .snow:nth-child(16) { - opacity: 0.0219; - transform: translate(18.7115vw, -10px) scale(0.9718); - animation: fall-16 13s -3s linear infinite; + opacity: 0.566; + transform: translate(10.666vw, -10px) scale(0.936); + animation: fall-16 18s -28s linear infinite; } @keyframes fall-16 { - 53.822% { - transform: translate(14.4739vw, 53.822vh) scale(0.9718); + 31.951% { + transform: translate(9.8585vw, 31.951vh) scale(0.936); } to { - transform: translate(16.5927vw, 100vh) scale(0.9718); + transform: translate(10.26225vw, 100vh) scale(0.936); } } .snow:nth-child(17) { - opacity: 0.3597; - transform: translate(98.5747vw, -10px) scale(0.0087); - animation: fall-17 13s -3s linear infinite; + opacity: 0.0075; + transform: translate(37.6025vw, -10px) scale(0.7196); + animation: fall-17 19s -17s linear infinite; } @keyframes fall-17 { - 40.342% { - transform: translate(98.9805vw, 40.342vh) scale(0.0087); + 51.739% { + transform: translate(42.3811vw, 51.739vh) scale(0.7196); } to { - transform: translate(98.7776vw, 100vh) scale(0.0087); + transform: translate(39.9918vw, 100vh) scale(0.7196); } } .snow:nth-child(18) { - opacity: 0.6477; - transform: translate(60.1245vw, -10px) scale(0.3382); - animation: fall-18 17s -16s linear infinite; + opacity: 0.1577; + transform: translate(90.6636vw, -10px) scale(0.7653); + animation: fall-18 17s -23s linear infinite; } @keyframes fall-18 { - 68.784% { - transform: translate(62.1733vw, 68.784vh) scale(0.3382); + 73.638% { + transform: translate(81.3964vw, 73.638vh) scale(0.7653); } to { - transform: translate(61.1489vw, 100vh) scale(0.3382); + transform: translate(86.03vw, 100vh) scale(0.7653); } } .snow:nth-child(19) { - opacity: 0.0156; - transform: translate(95.3103vw, -10px) scale(0.8514); - animation: fall-19 18s -28s linear infinite; + opacity: 0.194; + transform: translate(9.1775vw, -10px) scale(0.344); + animation: fall-19 27s -25s linear infinite; } @keyframes fall-19 { - 40.317% { - transform: translate(97.04vw, 40.317vh) scale(0.8514); + 50.175% { + transform: translate(13.6028vw, 50.175vh) scale(0.344); } to { - transform: translate(96.17515vw, 100vh) scale(0.8514); + transform: translate(11.39015vw, 100vh) scale(0.344); } } .snow:nth-child(20) { - opacity: 0.1846; - transform: translate(82.391vw, -10px) scale(0.8748); - animation: fall-20 22s -24s linear infinite; + opacity: 0.6716; + transform: translate(71.003vw, -10px) scale(0.5543); + animation: fall-20 28s -16s linear infinite; } @keyframes fall-20 { - 77.387% { - transform: translate(89.3383vw, 77.387vh) scale(0.8748); + 32.979% { + transform: translate(75.0401vw, 32.979vh) scale(0.5543); } to { - transform: translate(85.86465vw, 100vh) scale(0.8748); + transform: translate(73.02155vw, 100vh) scale(0.5543); } } .snow:nth-child(21) { - opacity: 0.3866; - transform: translate(96.8061vw, -10px) scale(0.4764); - animation: fall-21 11s -19s linear infinite; + opacity: 0.2847; + transform: translate(34.5878vw, -10px) scale(0.6639); + animation: fall-21 11s -17s linear infinite; } @keyframes fall-21 { - 54.182% { - transform: translate(94.6784vw, 54.182vh) scale(0.4764); + 41.277% { + transform: translate(34.0048vw, 41.277vh) scale(0.6639); } to { - transform: translate(95.74225vw, 100vh) scale(0.4764); + transform: translate(34.2963vw, 100vh) scale(0.6639); } } .snow:nth-child(22) { - opacity: 0.8574; - transform: translate(80.0748vw, -10px) scale(0.6575); - animation: fall-22 18s -24s linear infinite; + opacity: 0.7698; + transform: translate(10.272vw, -10px) scale(0.5098); + animation: fall-22 16s -19s linear infinite; } @keyframes fall-22 { - 45.688% { - transform: translate(86.6344vw, 45.688vh) scale(0.6575); + 50.422% { + transform: translate(9.2302vw, 50.422vh) scale(0.5098); } to { - transform: translate(83.3546vw, 100vh) scale(0.6575); + transform: translate(9.7511vw, 100vh) scale(0.5098); } } .snow:nth-child(23) { - opacity: 0.9462; - transform: translate(1.1552vw, -10px) scale(0.149); - animation: fall-23 27s -29s linear infinite; + opacity: 0.6775; + transform: translate(47.9234vw, -10px) scale(0.5393); + animation: fall-23 14s -30s linear infinite; } @keyframes fall-23 { - 58.731% { - transform: translate(-0.7334vw, 58.731vh) scale(0.149); + 35.091% { + transform: translate(52.09vw, 35.091vh) scale(0.5393); } to { - transform: translate(0.2109vw, 100vh) scale(0.149); + transform: translate(50.0067vw, 100vh) scale(0.5393); } } .snow:nth-child(24) { - opacity: 0.0467; - transform: translate(92.7115vw, -10px) scale(0.2719); - animation: fall-24 27s -22s linear infinite; + opacity: 0.78; + transform: translate(34.0749vw, -10px) scale(0.1493); + animation: fall-24 27s -9s linear infinite; } @keyframes fall-24 { - 56.663% { - transform: translate(91.2837vw, 56.663vh) scale(0.2719); + 50.622% { + transform: translate(38.6728vw, 50.622vh) scale(0.1493); } to { - transform: translate(91.9976vw, 100vh) scale(0.2719); + transform: translate(36.37385vw, 100vh) scale(0.1493); } } .snow:nth-child(25) { - opacity: 0.8293; - transform: translate(11.738vw, -10px) scale(0.9781); - animation: fall-25 11s -23s linear infinite; + opacity: 0.9441; + transform: translate(51.5298vw, -10px) scale(0.731); + animation: fall-25 14s -27s linear infinite; } @keyframes fall-25 { - 63.32% { - transform: translate(3.3353vw, 63.32vh) scale(0.9781); + 78.163% { + transform: translate(51.6328vw, 78.163vh) scale(0.731); } to { - transform: translate(7.53665vw, 100vh) scale(0.9781); + transform: translate(51.5813vw, 100vh) scale(0.731); } } .snow:nth-child(26) { - opacity: 0.4034; - transform: translate(87.9732vw, -10px) scale(0.9536); - animation: fall-26 25s -17s linear infinite; + opacity: 0.6662; + transform: translate(83.3438vw, -10px) scale(0.8486); + animation: fall-26 28s -18s linear infinite; } @keyframes fall-26 { - 46.225% { - transform: translate(89.6876vw, 46.225vh) scale(0.9536); + 33.802% { + transform: translate(84.2578vw, 33.802vh) scale(0.8486); } to { - transform: translate(88.8304vw, 100vh) scale(0.9536); + transform: translate(83.8008vw, 100vh) scale(0.8486); } } .snow:nth-child(27) { - opacity: 0.9357; - transform: translate(80.6384vw, -10px) scale(0.5463); - animation: fall-27 24s -9s linear infinite; + opacity: 0.3502; + transform: translate(17.8328vw, -10px) scale(0.3293); + animation: fall-27 11s -13s linear infinite; } @keyframes fall-27 { - 49.276% { - transform: translate(90.3631vw, 49.276vh) scale(0.5463); + 35.293% { + transform: translate(13.689vw, 35.293vh) scale(0.3293); } to { - transform: translate(85.50075vw, 100vh) scale(0.5463); + transform: translate(15.7609vw, 100vh) scale(0.3293); } } .snow:nth-child(28) { - opacity: 0.9487; - transform: translate(99.7131vw, -10px) scale(0.7819); - animation: fall-28 12s -25s linear infinite; + opacity: 0.0315; + transform: translate(47.9009vw, -10px) scale(0.5468); + animation: fall-28 16s -21s linear infinite; } @keyframes fall-28 { - 67.378% { - transform: translate(104.6022vw, 67.378vh) scale(0.7819); + 35.74% { + transform: translate(43.5892vw, 35.74vh) scale(0.5468); } to { - transform: translate(102.15765vw, 100vh) scale(0.7819); + transform: translate(45.74505vw, 100vh) scale(0.5468); } } .snow:nth-child(29) { - opacity: 0.0245; - transform: translate(30.8846vw, -10px) scale(0.1986); - animation: fall-29 12s -26s linear infinite; + opacity: 0.8193; + transform: translate(26.391vw, -10px) scale(0.2634); + animation: fall-29 21s -21s linear infinite; } @keyframes fall-29 { - 40.849% { - transform: translate(37.7841vw, 40.849vh) scale(0.1986); + 49.455% { + transform: translate(35.7896vw, 49.455vh) scale(0.2634); } to { - transform: translate(34.33435vw, 100vh) scale(0.1986); + transform: translate(31.0903vw, 100vh) scale(0.2634); } } .snow:nth-child(30) { - opacity: 0.9996; - transform: translate(54.2766vw, -10px) scale(0.0363); - animation: fall-30 16s -29s linear infinite; + opacity: 0.5137; + transform: translate(54.876vw, -10px) scale(0.0143); + animation: fall-30 27s -5s linear infinite; } @keyframes fall-30 { - 34.017% { - transform: translate(54.7282vw, 34.017vh) scale(0.0363); + 55.898% { + transform: translate(61.1971vw, 55.898vh) scale(0.0143); } to { - transform: translate(54.5024vw, 100vh) scale(0.0363); + transform: translate(58.03655vw, 100vh) scale(0.0143); } } .snow:nth-child(31) { - opacity: 0.3376; - transform: translate(2.2463vw, -10px) scale(0.0402); - animation: fall-31 24s -20s linear infinite; + opacity: 0.4395; + transform: translate(43.7441vw, -10px) scale(0.1827); + animation: fall-31 21s -20s linear infinite; } @keyframes fall-31 { - 76.043% { - transform: translate(-3.559vw, 76.043vh) scale(0.0402); + 35.315% { + transform: translate(45.7112vw, 35.315vh) scale(0.1827); } to { - transform: translate(-0.65635vw, 100vh) scale(0.0402); + transform: translate(44.72765vw, 100vh) scale(0.1827); } } .snow:nth-child(32) { - opacity: 0.6195; - transform: translate(71.422vw, -10px) scale(0.0814); - animation: fall-32 27s -22s linear infinite; + opacity: 0.3212; + transform: translate(80.5039vw, -10px) scale(0.2067); + animation: fall-32 27s -27s linear infinite; } @keyframes fall-32 { - 34.818% { - transform: translate(67.822vw, 34.818vh) scale(0.0814); + 38.839% { + transform: translate(82.2749vw, 38.839vh) scale(0.2067); } to { - transform: translate(69.622vw, 100vh) scale(0.0814); + transform: translate(81.3894vw, 100vh) scale(0.2067); } } .snow:nth-child(33) { - opacity: 0.294; - transform: translate(84.8774vw, -10px) scale(0.9973); - animation: fall-33 14s -12s linear infinite; + opacity: 0.701; + transform: translate(34.3481vw, -10px) scale(0.4268); + animation: fall-33 16s -8s linear infinite; } @keyframes fall-33 { - 78.277% { - transform: translate(81.1884vw, 78.277vh) scale(0.9973); + 43.903% { + transform: translate(25.2683vw, 43.903vh) scale(0.4268); } to { - transform: translate(83.0329vw, 100vh) scale(0.9973); + transform: translate(29.8082vw, 100vh) scale(0.4268); } } .snow:nth-child(34) { - opacity: 0.7891; - transform: translate(30.2025vw, -10px) scale(0.6661); - animation: fall-34 25s -16s linear infinite; + opacity: 0.5452; + transform: translate(43.609vw, -10px) scale(0.203); + animation: fall-34 27s -4s linear infinite; } @keyframes fall-34 { - 47.107% { - transform: translate(21.6727vw, 47.107vh) scale(0.6661); + 76.657% { + transform: translate(34.3157vw, 76.657vh) scale(0.203); } to { - transform: translate(25.9376vw, 100vh) scale(0.6661); + transform: translate(38.96235vw, 100vh) scale(0.203); } } .snow:nth-child(35) { - opacity: 0.7153; - transform: translate(85.4078vw, -10px) scale(0.0952); - animation: fall-35 30s -30s linear infinite; + opacity: 0.982; + transform: translate(75.8914vw, -10px) scale(0.8194); + animation: fall-35 14s -14s linear infinite; } @keyframes fall-35 { - 73.943% { - transform: translate(89.2659vw, 73.943vh) scale(0.0952); + 44.824% { + transform: translate(69.9753vw, 44.824vh) scale(0.8194); } to { - transform: translate(87.33685vw, 100vh) scale(0.0952); + transform: translate(72.93335vw, 100vh) scale(0.8194); } } .snow:nth-child(36) { - opacity: 0.4562; - transform: translate(50.699vw, -10px) scale(0.0171); - animation: fall-36 19s -19s linear infinite; + opacity: 0.1814; + transform: translate(98.9985vw, -10px) scale(0.0327); + animation: fall-36 30s -9s linear infinite; } @keyframes fall-36 { - 69.864% { - transform: translate(50.9376vw, 69.864vh) scale(0.0171); + 54.713% { + transform: translate(99.3352vw, 54.713vh) scale(0.0327); } to { - transform: translate(50.8183vw, 100vh) scale(0.0171); + transform: translate(99.16685vw, 100vh) scale(0.0327); } } .snow:nth-child(37) { - opacity: 0.8527; - transform: translate(14.8475vw, -10px) scale(0.8091); - animation: fall-37 10s -14s linear infinite; + opacity: 0.5442; + transform: translate(92.862vw, -10px) scale(0.8734); + animation: fall-37 25s -11s linear infinite; } @keyframes fall-37 { - 62.849% { - transform: translate(8.1667vw, 62.849vh) scale(0.8091); + 63.895% { + transform: translate(102.8494vw, 63.895vh) scale(0.8734); } to { - transform: translate(11.5071vw, 100vh) scale(0.8091); + transform: translate(97.8557vw, 100vh) scale(0.8734); } } .snow:nth-child(38) { - opacity: 0.8046; - transform: translate(21.7442vw, -10px) scale(0.7675); - animation: fall-38 29s -1s linear infinite; + opacity: 0.384; + transform: translate(5.7179vw, -10px) scale(0.0101); + animation: fall-38 24s -28s linear infinite; } @keyframes fall-38 { - 45.263% { - transform: translate(23.225vw, 45.263vh) scale(0.7675); + 43.716% { + transform: translate(12.8128vw, 43.716vh) scale(0.0101); } to { - transform: translate(22.4846vw, 100vh) scale(0.7675); + transform: translate(9.26535vw, 100vh) scale(0.0101); } } .snow:nth-child(39) { - opacity: 0.387; - transform: translate(59.825vw, -10px) scale(0.3878); - animation: fall-39 19s -10s linear infinite; + opacity: 0.4543; + transform: translate(68.668vw, -10px) scale(0.8134); + animation: fall-39 21s -8s linear infinite; } @keyframes fall-39 { - 41.49% { - transform: translate(54.9819vw, 41.49vh) scale(0.3878); + 42.97% { + transform: translate(75.2054vw, 42.97vh) scale(0.8134); } to { - transform: translate(57.40345vw, 100vh) scale(0.3878); + transform: translate(71.9367vw, 100vh) scale(0.8134); } } .snow:nth-child(40) { - opacity: 0.4235; - transform: translate(79.637vw, -10px) scale(0.9873); - animation: fall-40 13s -13s linear infinite; + opacity: 0.4736; + transform: translate(16.633vw, -10px) scale(0.4543); + animation: fall-40 23s -5s linear infinite; } @keyframes fall-40 { - 43.611% { - transform: translate(77.6249vw, 43.611vh) scale(0.9873); + 30.854% { + transform: translate(10.8781vw, 30.854vh) scale(0.4543); } to { - transform: translate(78.63095vw, 100vh) scale(0.9873); + transform: translate(13.75555vw, 100vh) scale(0.4543); } } .snow:nth-child(41) { - opacity: 0.1618; - transform: translate(74.9394vw, -10px) scale(0.1023); - animation: fall-41 21s -4s linear infinite; + opacity: 0.9583; + transform: translate(66.2399vw, -10px) scale(0.7545); + animation: fall-41 20s -17s linear infinite; } @keyframes fall-41 { - 51.031% { - transform: translate(77.2245vw, 51.031vh) scale(0.1023); + 62.584% { + transform: translate(67.1525vw, 62.584vh) scale(0.7545); } to { - transform: translate(76.08195vw, 100vh) scale(0.1023); + transform: translate(66.6962vw, 100vh) scale(0.7545); } } .snow:nth-child(42) { - opacity: 0.3907; - transform: translate(94.5391vw, -10px) scale(0.3331); - animation: fall-42 16s -14s linear infinite; + opacity: 0.53; + transform: translate(30.2146vw, -10px) scale(0.1648); + animation: fall-42 26s -8s linear infinite; } @keyframes fall-42 { - 52.437% { - transform: translate(103.2216vw, 52.437vh) scale(0.3331); + 55.907% { + transform: translate(37.0674vw, 55.907vh) scale(0.1648); } to { - transform: translate(98.88035vw, 100vh) scale(0.3331); + transform: translate(33.641vw, 100vh) scale(0.1648); } } .snow:nth-child(43) { - opacity: 0.8224; - transform: translate(83.3688vw, -10px) scale(0.7112); - animation: fall-43 10s -26s linear infinite; + opacity: 0.991; + transform: translate(27.7612vw, -10px) scale(0.7066); + animation: fall-43 20s -7s linear infinite; } @keyframes fall-43 { - 79.362% { - transform: translate(87.503vw, 79.362vh) scale(0.7112); + 45.264% { + transform: translate(26.4016vw, 45.264vh) scale(0.7066); } to { - transform: translate(85.4359vw, 100vh) scale(0.7112); + transform: translate(27.0814vw, 100vh) scale(0.7066); } } .snow:nth-child(44) { - opacity: 0.9687; - transform: translate(36.9993vw, -10px) scale(0.9057); - animation: fall-44 23s -24s linear infinite; + opacity: 0.5323; + transform: translate(29.8536vw, -10px) scale(0.1951); + animation: fall-44 19s -15s linear infinite; } @keyframes fall-44 { - 59.943% { - transform: translate(32.4342vw, 59.943vh) scale(0.9057); + 76.522% { + transform: translate(32.1126vw, 76.522vh) scale(0.1951); } to { - transform: translate(34.71675vw, 100vh) scale(0.9057); + transform: translate(30.9831vw, 100vh) scale(0.1951); } } .snow:nth-child(45) { - opacity: 0.4; - transform: translate(76.3849vw, -10px) scale(0.2036); - animation: fall-45 13s -24s linear infinite; + opacity: 0.2485; + transform: translate(1.8318vw, -10px) scale(0.361); + animation: fall-45 26s -30s linear infinite; } @keyframes fall-45 { - 70.077% { - transform: translate(83.5686vw, 70.077vh) scale(0.2036); + 35.283% { + transform: translate(8.4692vw, 35.283vh) scale(0.361); } to { - transform: translate(79.97675vw, 100vh) scale(0.2036); + transform: translate(5.1505vw, 100vh) scale(0.361); } } .snow:nth-child(46) { - opacity: 0.891; - transform: translate(30.1555vw, -10px) scale(0.4239); - animation: fall-46 17s -18s linear infinite; + opacity: 0.1756; + transform: translate(98.8438vw, -10px) scale(0.4754); + animation: fall-46 26s -7s linear infinite; } @keyframes fall-46 { - 75.153% { - transform: translate(28.3965vw, 75.153vh) scale(0.4239); + 42.943% { + transform: translate(106.8698vw, 42.943vh) scale(0.4754); } to { - transform: translate(29.276vw, 100vh) scale(0.4239); + transform: translate(102.8568vw, 100vh) scale(0.4754); } } .snow:nth-child(47) { - opacity: 0.5805; - transform: translate(43.0014vw, -10px) scale(0.9021); - animation: fall-47 21s -18s linear infinite; + opacity: 0.2507; + transform: translate(2.6381vw, -10px) scale(0.7054); + animation: fall-47 16s -18s linear infinite; } @keyframes fall-47 { - 30.377% { - transform: translate(41.8239vw, 30.377vh) scale(0.9021); + 38.269% { + transform: translate(-1.6023vw, 38.269vh) scale(0.7054); } to { - transform: translate(42.41265vw, 100vh) scale(0.9021); + transform: translate(0.5179vw, 100vh) scale(0.7054); } } .snow:nth-child(48) { - opacity: 0.0043; - transform: translate(43.5763vw, -10px) scale(0.4874); - animation: fall-48 28s -29s linear infinite; + opacity: 0.9943; + transform: translate(13.3725vw, -10px) scale(0.6117); + animation: fall-48 20s -10s linear infinite; } @keyframes fall-48 { - 35.233% { - transform: translate(34.3591vw, 35.233vh) scale(0.4874); + 48.202% { + transform: translate(21.162vw, 48.202vh) scale(0.6117); } to { - transform: translate(38.9677vw, 100vh) scale(0.4874); + transform: translate(17.26725vw, 100vh) scale(0.6117); } } .snow:nth-child(49) { - opacity: 0.5528; - transform: translate(39.153vw, -10px) scale(0.4637); - animation: fall-49 18s -7s linear infinite; + opacity: 0.3955; + transform: translate(71.8538vw, -10px) scale(0.1893); + animation: fall-49 13s -7s linear infinite; } @keyframes fall-49 { - 45.433% { - transform: translate(33.8465vw, 45.433vh) scale(0.4637); + 75.663% { + transform: translate(62.6861vw, 75.663vh) scale(0.1893); } to { - transform: translate(36.49975vw, 100vh) scale(0.4637); + transform: translate(67.26995vw, 100vh) scale(0.1893); } } .snow:nth-child(50) { - opacity: 0.7105; - transform: translate(46.8778vw, -10px) scale(0.341); - animation: fall-50 12s -3s linear infinite; + opacity: 0.1284; + transform: translate(80.7992vw, -10px) scale(0.6805); + animation: fall-50 16s -3s linear infinite; } @keyframes fall-50 { - 73.97% { - transform: translate(48.4785vw, 73.97vh) scale(0.341); + 74.144% { + transform: translate(88.6035vw, 74.144vh) scale(0.6805); } to { - transform: translate(47.67815vw, 100vh) scale(0.341); + transform: translate(84.70135vw, 100vh) scale(0.6805); } } .snow:nth-child(51) { - opacity: 0.2825; - transform: translate(27.7056vw, -10px) scale(0.7188); - animation: fall-51 18s -28s linear infinite; + opacity: 0.5312; + transform: translate(3.5211vw, -10px) scale(0.6864); + animation: fall-51 13s -26s linear infinite; } @keyframes fall-51 { - 54.916% { - transform: translate(25.8573vw, 54.916vh) scale(0.7188); + 45.352% { + transform: translate(-6.3508vw, 45.352vh) scale(0.6864); } to { - transform: translate(26.78145vw, 100vh) scale(0.7188); + transform: translate(-1.41485vw, 100vh) scale(0.6864); } } .snow:nth-child(52) { - opacity: 0.2019; - transform: translate(75.0821vw, -10px) scale(0.3873); - animation: fall-52 26s -1s linear infinite; + opacity: 0.2145; + transform: translate(7.2788vw, -10px) scale(0.0534); + animation: fall-52 28s -20s linear infinite; } @keyframes fall-52 { - 41.604% { - transform: translate(71.6407vw, 41.604vh) scale(0.3873); + 74.192% { + transform: translate(13.5499vw, 74.192vh) scale(0.0534); } to { - transform: translate(73.3614vw, 100vh) scale(0.3873); + transform: translate(10.41435vw, 100vh) scale(0.0534); } } .snow:nth-child(53) { - opacity: 0.4844; - transform: translate(26.7899vw, -10px) scale(0.934); - animation: fall-53 19s -7s linear infinite; + opacity: 0.4817; + transform: translate(40.6309vw, -10px) scale(0.6608); + animation: fall-53 16s -28s linear infinite; } @keyframes fall-53 { - 44.706% { - transform: translate(23.7333vw, 44.706vh) scale(0.934); + 77.912% { + transform: translate(43.3447vw, 77.912vh) scale(0.6608); } to { - transform: translate(25.2616vw, 100vh) scale(0.934); + transform: translate(41.9878vw, 100vh) scale(0.6608); } } .snow:nth-child(54) { - opacity: 0.142; - transform: translate(0.9682vw, -10px) scale(0.9024); - animation: fall-54 18s -30s linear infinite; + opacity: 0.2782; + transform: translate(26.6245vw, -10px) scale(0.4011); + animation: fall-54 29s -21s linear infinite; } @keyframes fall-54 { - 75.319% { - transform: translate(5.8392vw, 75.319vh) scale(0.9024); + 72.82% { + transform: translate(32.8785vw, 72.82vh) scale(0.4011); } to { - transform: translate(3.4037vw, 100vh) scale(0.9024); + transform: translate(29.7515vw, 100vh) scale(0.4011); } } .snow:nth-child(55) { - opacity: 0.3168; - transform: translate(74.3567vw, -10px) scale(0.8211); - animation: fall-55 15s -18s linear infinite; + opacity: 0.9347; + transform: translate(58.7337vw, -10px) scale(0.5451); + animation: fall-55 21s -22s linear infinite; } @keyframes fall-55 { - 30.564% { - transform: translate(78.1877vw, 30.564vh) scale(0.8211); + 34.478% { + transform: translate(53.282vw, 34.478vh) scale(0.5451); } to { - transform: translate(76.2722vw, 100vh) scale(0.8211); + transform: translate(56.00785vw, 100vh) scale(0.5451); } } .snow:nth-child(56) { - opacity: 0.4294; - transform: translate(46.1072vw, -10px) scale(0.2266); - animation: fall-56 24s -25s linear infinite; + opacity: 0.6729; + transform: translate(68.1336vw, -10px) scale(0.5752); + animation: fall-56 17s -15s linear infinite; } @keyframes fall-56 { - 33.304% { - transform: translate(53.6658vw, 33.304vh) scale(0.2266); + 76.123% { + transform: translate(64.6459vw, 76.123vh) scale(0.5752); } to { - transform: translate(49.8865vw, 100vh) scale(0.2266); + transform: translate(66.38975vw, 100vh) scale(0.5752); } } .snow:nth-child(57) { - opacity: 0.8672; - transform: translate(38.031vw, -10px) scale(0.3519); - animation: fall-57 22s -16s linear infinite; + opacity: 0.6015; + transform: translate(90.8075vw, -10px) scale(0.0236); + animation: fall-57 30s -27s linear infinite; } @keyframes fall-57 { - 50.606% { - transform: translate(34.1056vw, 50.606vh) scale(0.3519); + 40.518% { + transform: translate(99.1747vw, 40.518vh) scale(0.0236); } to { - transform: translate(36.0683vw, 100vh) scale(0.3519); + transform: translate(94.9911vw, 100vh) scale(0.0236); } } .snow:nth-child(58) { - opacity: 0.5871; - transform: translate(11.9651vw, -10px) scale(0.3821); - animation: fall-58 30s -19s linear infinite; + opacity: 0.048; + transform: translate(10.4551vw, -10px) scale(0.8768); + animation: fall-58 13s -11s linear infinite; } @keyframes fall-58 { - 41.386% { - transform: translate(8.6323vw, 41.386vh) scale(0.3821); + 78.688% { + transform: translate(19.913vw, 78.688vh) scale(0.8768); } to { - transform: translate(10.2987vw, 100vh) scale(0.3821); + transform: translate(15.18405vw, 100vh) scale(0.8768); } } .snow:nth-child(59) { - opacity: 0.251; - transform: translate(5.8648vw, -10px) scale(0.0337); - animation: fall-59 12s -4s linear infinite; + opacity: 0.3662; + transform: translate(87.7795vw, -10px) scale(0.1979); + animation: fall-59 12s -2s linear infinite; } @keyframes fall-59 { - 36.084% { - transform: translate(15.7292vw, 36.084vh) scale(0.0337); + 30.387% { + transform: translate(79.1293vw, 30.387vh) scale(0.1979); } to { - transform: translate(10.797vw, 100vh) scale(0.0337); + transform: translate(83.4544vw, 100vh) scale(0.1979); } } .snow:nth-child(60) { - opacity: 0.2345; - transform: translate(47.6873vw, -10px) scale(0.0568); - animation: fall-60 19s -17s linear infinite; + opacity: 0.3605; + transform: translate(51.8349vw, -10px) scale(0.8098); + animation: fall-60 29s -25s linear infinite; } @keyframes fall-60 { - 56.093% { - transform: translate(37.7068vw, 56.093vh) scale(0.0568); + 52.48% { + transform: translate(46.7796vw, 52.48vh) scale(0.8098); } to { - transform: translate(42.69705vw, 100vh) scale(0.0568); + transform: translate(49.30725vw, 100vh) scale(0.8098); } } .snow:nth-child(61) { - opacity: 0.3462; - transform: translate(74.0916vw, -10px) scale(0.9138); - animation: fall-61 20s -20s linear infinite; + opacity: 0.7077; + transform: translate(33.7176vw, -10px) scale(0.3825); + animation: fall-61 13s -8s linear infinite; } @keyframes fall-61 { - 74.521% { - transform: translate(70.712vw, 74.521vh) scale(0.9138); + 56.526% { + transform: translate(40.8273vw, 56.526vh) scale(0.3825); } to { - transform: translate(72.4018vw, 100vh) scale(0.9138); + transform: translate(37.27245vw, 100vh) scale(0.3825); } } .snow:nth-child(62) { - opacity: 0.7806; - transform: translate(97.8937vw, -10px) scale(0.9683); - animation: fall-62 15s -6s linear infinite; + opacity: 0.0069; + transform: translate(29.1137vw, -10px) scale(0.0395); + animation: fall-62 17s -17s linear infinite; } @keyframes fall-62 { - 77.366% { - transform: translate(91.9738vw, 77.366vh) scale(0.9683); + 50.473% { + transform: translate(24.103vw, 50.473vh) scale(0.0395); } to { - transform: translate(94.93375vw, 100vh) scale(0.9683); + transform: translate(26.60835vw, 100vh) scale(0.0395); } } .snow:nth-child(63) { - opacity: 0.5731; - transform: translate(40.148vw, -10px) scale(0.9507); - animation: fall-63 17s -11s linear infinite; + opacity: 0.8893; + transform: translate(12.2673vw, -10px) scale(0.0129); + animation: fall-63 23s -16s linear infinite; } @keyframes fall-63 { - 34.535% { - transform: translate(34.1998vw, 34.535vh) scale(0.9507); + 58.212% { + transform: translate(5.8966vw, 58.212vh) scale(0.0129); } to { - transform: translate(37.1739vw, 100vh) scale(0.9507); + transform: translate(9.08195vw, 100vh) scale(0.0129); } } .snow:nth-child(64) { - opacity: 0.6394; - transform: translate(98.4609vw, -10px) scale(0.1411); - animation: fall-64 11s -7s linear infinite; + opacity: 0.9302; + transform: translate(32.0662vw, -10px) scale(0.375); + animation: fall-64 13s -5s linear infinite; } @keyframes fall-64 { - 53.372% { - transform: translate(99.3689vw, 53.372vh) scale(0.1411); + 71.269% { + transform: translate(31.8819vw, 71.269vh) scale(0.375); } to { - transform: translate(98.9149vw, 100vh) scale(0.1411); + transform: translate(31.97405vw, 100vh) scale(0.375); } } .snow:nth-child(65) { - opacity: 0.696; - transform: translate(63.7027vw, -10px) scale(0.4342); - animation: fall-65 11s -1s linear infinite; + opacity: 0.3962; + transform: translate(69.2377vw, -10px) scale(0.5844); + animation: fall-65 26s -26s linear infinite; } @keyframes fall-65 { - 37.818% { - transform: translate(59.5419vw, 37.818vh) scale(0.4342); + 76.725% { + transform: translate(71.7073vw, 76.725vh) scale(0.5844); } to { - transform: translate(61.6223vw, 100vh) scale(0.4342); + transform: translate(70.4725vw, 100vh) scale(0.5844); } } .snow:nth-child(66) { - opacity: 0.7822; - transform: translate(81.777vw, -10px) scale(0.201); - animation: fall-66 14s -11s linear infinite; + opacity: 0.8443; + transform: translate(37.2819vw, -10px) scale(0.8389); + animation: fall-66 14s -27s linear infinite; } @keyframes fall-66 { - 61.904% { - transform: translate(72.029vw, 61.904vh) scale(0.201); + 76.387% { + transform: translate(34.2963vw, 76.387vh) scale(0.8389); } to { - transform: translate(76.903vw, 100vh) scale(0.201); + transform: translate(35.7891vw, 100vh) scale(0.8389); } } .snow:nth-child(67) { - opacity: 0.1068; - transform: translate(67.2707vw, -10px) scale(0.8577); - animation: fall-67 23s -3s linear infinite; + opacity: 0.4929; + transform: translate(21.2115vw, -10px) scale(0.5848); + animation: fall-67 18s -26s linear infinite; } @keyframes fall-67 { - 33.943% { - transform: translate(61.1524vw, 33.943vh) scale(0.8577); + 76.274% { + transform: translate(30.4684vw, 76.274vh) scale(0.5848); } to { - transform: translate(64.21155vw, 100vh) scale(0.8577); + transform: translate(25.83995vw, 100vh) scale(0.5848); } } .snow:nth-child(68) { - opacity: 0.5562; - transform: translate(4.2387vw, -10px) scale(0.4865); - animation: fall-68 11s -13s linear infinite; + opacity: 0.8372; + transform: translate(56.1367vw, -10px) scale(0.8814); + animation: fall-68 26s -25s linear infinite; } @keyframes fall-68 { - 70.721% { - transform: translate(9.1182vw, 70.721vh) scale(0.4865); + 72.733% { + transform: translate(63.5358vw, 72.733vh) scale(0.8814); } to { - transform: translate(6.67845vw, 100vh) scale(0.4865); + transform: translate(59.83625vw, 100vh) scale(0.8814); } } .snow:nth-child(69) { - opacity: 0.323; - transform: translate(35.3546vw, -10px) scale(0.5789); - animation: fall-69 29s -14s linear infinite; + opacity: 0.2915; + transform: translate(18.5073vw, -10px) scale(0.2164); + animation: fall-69 24s -2s linear infinite; } @keyframes fall-69 { - 56.903% { - transform: translate(36.9199vw, 56.903vh) scale(0.5789); + 44.462% { + transform: translate(11.2393vw, 44.462vh) scale(0.2164); } to { - transform: translate(36.13725vw, 100vh) scale(0.5789); + transform: translate(14.8733vw, 100vh) scale(0.2164); } } .snow:nth-child(70) { - opacity: 0.6613; - transform: translate(18.6935vw, -10px) scale(0.3672); - animation: fall-70 11s -2s linear infinite; + opacity: 0.5051; + transform: translate(12.5266vw, -10px) scale(0.7491); + animation: fall-70 12s -15s linear infinite; } @keyframes fall-70 { - 74.238% { - transform: translate(20.2884vw, 74.238vh) scale(0.3672); + 48.344% { + transform: translate(22.3747vw, 48.344vh) scale(0.7491); } to { - transform: translate(19.49095vw, 100vh) scale(0.3672); + transform: translate(17.45065vw, 100vh) scale(0.7491); } } .snow:nth-child(71) { - opacity: 0.1339; - transform: translate(13.1767vw, -10px) scale(0.7662); - animation: fall-71 16s -28s linear infinite; + opacity: 0.9932; + transform: translate(30.6747vw, -10px) scale(0.1676); + animation: fall-71 20s -24s linear infinite; } @keyframes fall-71 { - 63.36% { - transform: translate(10.2494vw, 63.36vh) scale(0.7662); + 40.974% { + transform: translate(33.0565vw, 40.974vh) scale(0.1676); } to { - transform: translate(11.71305vw, 100vh) scale(0.7662); + transform: translate(31.8656vw, 100vh) scale(0.1676); } } .snow:nth-child(72) { - opacity: 0.932; - transform: translate(65.6101vw, -10px) scale(0.5039); - animation: fall-72 22s -21s linear infinite; + opacity: 0.3747; + transform: translate(7.5418vw, -10px) scale(0.9742); + animation: fall-72 11s -29s linear infinite; } @keyframes fall-72 { - 36.151% { - transform: translate(68.3918vw, 36.151vh) scale(0.5039); + 66.924% { + transform: translate(2.6582vw, 66.924vh) scale(0.9742); } to { - transform: translate(67.00095vw, 100vh) scale(0.5039); + transform: translate(5.1vw, 100vh) scale(0.9742); } } .snow:nth-child(73) { - opacity: 0.8102; - transform: translate(55.4522vw, -10px) scale(0.4294); - animation: fall-73 22s -23s linear infinite; + opacity: 0.302; + transform: translate(14.4381vw, -10px) scale(0.8785); + animation: fall-73 21s -15s linear infinite; } @keyframes fall-73 { - 42.733% { - transform: translate(61.3479vw, 42.733vh) scale(0.4294); + 33.914% { + transform: translate(23.7414vw, 33.914vh) scale(0.8785); } to { - transform: translate(58.40005vw, 100vh) scale(0.4294); + transform: translate(19.08975vw, 100vh) scale(0.8785); } } .snow:nth-child(74) { - opacity: 0.9973; - transform: translate(18.8395vw, -10px) scale(0.8617); - animation: fall-74 28s -21s linear infinite; + opacity: 0.6717; + transform: translate(23.0433vw, -10px) scale(0.4931); + animation: fall-74 17s -4s linear infinite; } @keyframes fall-74 { - 44.403% { - transform: translate(15.9235vw, 44.403vh) scale(0.8617); + 40.275% { + transform: translate(22.407vw, 40.275vh) scale(0.4931); } to { - transform: translate(17.3815vw, 100vh) scale(0.8617); + transform: translate(22.72515vw, 100vh) scale(0.4931); } } .snow:nth-child(75) { - opacity: 0.0194; - transform: translate(41.6491vw, -10px) scale(0.234); - animation: fall-75 12s -25s linear infinite; + opacity: 0.5724; + transform: translate(67.8429vw, -10px) scale(0.1722); + animation: fall-75 21s -15s linear infinite; } @keyframes fall-75 { - 51.915% { - transform: translate(32.9793vw, 51.915vh) scale(0.234); + 76.261% { + transform: translate(70.0258vw, 76.261vh) scale(0.1722); } to { - transform: translate(37.3142vw, 100vh) scale(0.234); + transform: translate(68.93435vw, 100vh) scale(0.1722); } } .snow:nth-child(76) { - opacity: 0.8455; - transform: translate(28.4527vw, -10px) scale(0.664); - animation: fall-76 16s -1s linear infinite; + opacity: 0.9795; + transform: translate(34.434vw, -10px) scale(0.42); + animation: fall-76 25s -24s linear infinite; } @keyframes fall-76 { - 48.569% { - transform: translate(35.5526vw, 48.569vh) scale(0.664); + 47.323% { + transform: translate(33.4099vw, 47.323vh) scale(0.42); } to { - transform: translate(32.00265vw, 100vh) scale(0.664); + transform: translate(33.92195vw, 100vh) scale(0.42); } } .snow:nth-child(77) { - opacity: 0.7993; - transform: translate(89.2541vw, -10px) scale(0.6973); - animation: fall-77 15s -15s linear infinite; + opacity: 0.8963; + transform: translate(0.4974vw, -10px) scale(0.0681); + animation: fall-77 21s -13s linear infinite; } @keyframes fall-77 { - 46.064% { - transform: translate(89.521vw, 46.064vh) scale(0.6973); + 58.421% { + transform: translate(-2.6047vw, 58.421vh) scale(0.0681); } to { - transform: translate(89.38755vw, 100vh) scale(0.6973); + transform: translate(-1.05365vw, 100vh) scale(0.0681); } } .snow:nth-child(78) { - opacity: 0.017; - transform: translate(57.1134vw, -10px) scale(0.3669); - animation: fall-78 18s -28s linear infinite; + opacity: 0.4289; + transform: translate(79.6803vw, -10px) scale(0.4218); + animation: fall-78 22s -30s linear infinite; } @keyframes fall-78 { - 64.646% { - transform: translate(65.4148vw, 64.646vh) scale(0.3669); + 46.534% { + transform: translate(72.8819vw, 46.534vh) scale(0.4218); } to { - transform: translate(61.2641vw, 100vh) scale(0.3669); + transform: translate(76.2811vw, 100vh) scale(0.4218); } } .snow:nth-child(79) { - opacity: 0.7795; - transform: translate(28.4469vw, -10px) scale(0.2106); - animation: fall-79 27s -28s linear infinite; + opacity: 0.0095; + transform: translate(90.1211vw, -10px) scale(0.2684); + animation: fall-79 21s -13s linear infinite; } @keyframes fall-79 { - 43.667% { - transform: translate(26.1338vw, 43.667vh) scale(0.2106); + 61.74% { + transform: translate(87.4836vw, 61.74vh) scale(0.2684); } to { - transform: translate(27.29035vw, 100vh) scale(0.2106); + transform: translate(88.80235vw, 100vh) scale(0.2684); } } .snow:nth-child(80) { - opacity: 0.7931; - transform: translate(89.5955vw, -10px) scale(0.64); - animation: fall-80 24s -8s linear infinite; + opacity: 0.5799; + transform: translate(75.2544vw, -10px) scale(0.6796); + animation: fall-80 19s -12s linear infinite; } @keyframes fall-80 { - 70.049% { - transform: translate(91.775vw, 70.049vh) scale(0.64); + 66.867% { + transform: translate(70.3696vw, 66.867vh) scale(0.6796); } to { - transform: translate(90.68525vw, 100vh) scale(0.64); + transform: translate(72.812vw, 100vh) scale(0.6796); } } .snow:nth-child(81) { - opacity: 0.6643; - transform: translate(44.0431vw, -10px) scale(0.2157); - animation: fall-81 27s -16s linear infinite; + opacity: 0.5047; + transform: translate(37.5482vw, -10px) scale(0.0407); + animation: fall-81 25s -21s linear infinite; } @keyframes fall-81 { - 73.164% { - transform: translate(53.4629vw, 73.164vh) scale(0.2157); + 54.005% { + transform: translate(32.6643vw, 54.005vh) scale(0.0407); } to { - transform: translate(48.753vw, 100vh) scale(0.2157); + transform: translate(35.10625vw, 100vh) scale(0.0407); } } .snow:nth-child(82) { - opacity: 0.6415; - transform: translate(14.6103vw, -10px) scale(0.6333); - animation: fall-82 15s -19s linear infinite; + opacity: 0.4379; + transform: translate(66.3032vw, -10px) scale(0.2748); + animation: fall-82 12s -27s linear infinite; } @keyframes fall-82 { - 45.506% { - transform: translate(14.3751vw, 45.506vh) scale(0.6333); + 54.228% { + transform: translate(67.1657vw, 54.228vh) scale(0.2748); } to { - transform: translate(14.4927vw, 100vh) scale(0.6333); + transform: translate(66.73445vw, 100vh) scale(0.2748); } } .snow:nth-child(83) { - opacity: 0.7605; - transform: translate(61.9638vw, -10px) scale(0.2577); - animation: fall-83 18s -10s linear infinite; + opacity: 0.7014; + transform: translate(36.4586vw, -10px) scale(0.8247); + animation: fall-83 24s -23s linear infinite; } @keyframes fall-83 { - 58.021% { - transform: translate(60.6112vw, 58.021vh) scale(0.2577); + 63.566% { + transform: translate(38.4376vw, 63.566vh) scale(0.8247); } to { - transform: translate(61.2875vw, 100vh) scale(0.2577); + transform: translate(37.4481vw, 100vh) scale(0.8247); } } .snow:nth-child(84) { - opacity: 0.9212; - transform: translate(3.1557vw, -10px) scale(0.3228); - animation: fall-84 27s -24s linear infinite; + opacity: 0.2763; + transform: translate(19.3044vw, -10px) scale(0.6402); + animation: fall-84 11s -7s linear infinite; } @keyframes fall-84 { - 32.654% { - transform: translate(-4.7739vw, 32.654vh) scale(0.3228); + 75.52% { + transform: translate(9.5125vw, 75.52vh) scale(0.6402); } to { - transform: translate(-0.8091vw, 100vh) scale(0.3228); + transform: translate(14.40845vw, 100vh) scale(0.6402); } } .snow:nth-child(85) { - opacity: 0.281; - transform: translate(4.3956vw, -10px) scale(0.0446); - animation: fall-85 11s -29s linear infinite; + opacity: 0.7579; + transform: translate(67.26vw, -10px) scale(0.905); + animation: fall-85 21s -4s linear infinite; } @keyframes fall-85 { - 39.345% { - transform: translate(-3.1693vw, 39.345vh) scale(0.0446); + 48.114% { + transform: translate(69.3234vw, 48.114vh) scale(0.905); } to { - transform: translate(0.61315vw, 100vh) scale(0.0446); + transform: translate(68.2917vw, 100vh) scale(0.905); } } .snow:nth-child(86) { - opacity: 0.8883; - transform: translate(87.1897vw, -10px) scale(0.046); - animation: fall-86 19s -10s linear infinite; + opacity: 0.9845; + transform: translate(13.3151vw, -10px) scale(0.0152); + animation: fall-86 21s -23s linear infinite; } @keyframes fall-86 { - 47.963% { - transform: translate(93.6582vw, 47.963vh) scale(0.046); + 65.693% { + transform: translate(14.921vw, 65.693vh) scale(0.0152); } to { - transform: translate(90.42395vw, 100vh) scale(0.046); + transform: translate(14.11805vw, 100vh) scale(0.0152); } } .snow:nth-child(87) { - opacity: 0.083; - transform: translate(19.5214vw, -10px) scale(0.9078); - animation: fall-87 14s -23s linear infinite; + opacity: 0.5205; + transform: translate(17.8922vw, -10px) scale(0.1598); + animation: fall-87 12s -4s linear infinite; } @keyframes fall-87 { - 71.063% { - transform: translate(29.2572vw, 71.063vh) scale(0.9078); + 32.175% { + transform: translate(8.4209vw, 32.175vh) scale(0.1598); } to { - transform: translate(24.3893vw, 100vh) scale(0.9078); + transform: translate(13.15655vw, 100vh) scale(0.1598); } } .snow:nth-child(88) { - opacity: 0.053; - transform: translate(24.6215vw, -10px) scale(0.5653); - animation: fall-88 26s -13s linear infinite; + opacity: 0.1009; + transform: translate(11.134vw, -10px) scale(0.7037); + animation: fall-88 29s -11s linear infinite; } @keyframes fall-88 { - 34.563% { - transform: translate(31.0122vw, 34.563vh) scale(0.5653); + 47.194% { + transform: translate(9.3723vw, 47.194vh) scale(0.7037); } to { - transform: translate(27.81685vw, 100vh) scale(0.5653); + transform: translate(10.25315vw, 100vh) scale(0.7037); } } .snow:nth-child(89) { - opacity: 0.8619; - transform: translate(89.6035vw, -10px) scale(0.4458); - animation: fall-89 21s -16s linear infinite; + opacity: 0.7999; + transform: translate(97.3329vw, -10px) scale(0.2199); + animation: fall-89 23s -13s linear infinite; } @keyframes fall-89 { - 33.402% { - transform: translate(83.4955vw, 33.402vh) scale(0.4458); + 57.654% { + transform: translate(105.4321vw, 57.654vh) scale(0.2199); } to { - transform: translate(86.5495vw, 100vh) scale(0.4458); + transform: translate(101.3825vw, 100vh) scale(0.2199); } } .snow:nth-child(90) { - opacity: 0.0931; - transform: translate(29.3466vw, -10px) scale(0.6943); - animation: fall-90 22s -19s linear infinite; + opacity: 0.6713; + transform: translate(37.3778vw, -10px) scale(0.8577); + animation: fall-90 20s -12s linear infinite; } @keyframes fall-90 { - 62.917% { - transform: translate(39.0599vw, 62.917vh) scale(0.6943); + 37.471% { + transform: translate(44.7409vw, 37.471vh) scale(0.8577); } to { - transform: translate(34.20325vw, 100vh) scale(0.6943); + transform: translate(41.05935vw, 100vh) scale(0.8577); } } .snow:nth-child(91) { - opacity: 0.0295; - transform: translate(58.6053vw, -10px) scale(0.7237); - animation: fall-91 12s -2s linear infinite; + opacity: 0.3981; + transform: translate(75.6631vw, -10px) scale(0.6205); + animation: fall-91 18s -16s linear infinite; } @keyframes fall-91 { - 41.331% { - transform: translate(52.6823vw, 41.331vh) scale(0.7237); + 61.737% { + transform: translate(70.722vw, 61.737vh) scale(0.6205); } to { - transform: translate(55.6438vw, 100vh) scale(0.7237); + transform: translate(73.19255vw, 100vh) scale(0.6205); } } .snow:nth-child(92) { - opacity: 0.7169; - transform: translate(70.6336vw, -10px) scale(0.7083); - animation: fall-92 14s -9s linear infinite; + opacity: 0.2757; + transform: translate(96.964vw, -10px) scale(0.1232); + animation: fall-92 12s -16s linear infinite; } @keyframes fall-92 { - 30.557% { - transform: translate(79.4422vw, 30.557vh) scale(0.7083); + 63.712% { + transform: translate(94.16vw, 63.712vh) scale(0.1232); } to { - transform: translate(75.0379vw, 100vh) scale(0.7083); + transform: translate(95.562vw, 100vh) scale(0.1232); } } .snow:nth-child(93) { - opacity: 0.1261; - transform: translate(42.2731vw, -10px) scale(0.3328); - animation: fall-93 22s -19s linear infinite; + opacity: 0.7343; + transform: translate(32.9143vw, -10px) scale(0.4596); + animation: fall-93 23s -10s linear infinite; } @keyframes fall-93 { - 49.57% { - transform: translate(38.5378vw, 49.57vh) scale(0.3328); + 55.361% { + transform: translate(30.003vw, 55.361vh) scale(0.4596); } to { - transform: translate(40.40545vw, 100vh) scale(0.3328); + transform: translate(31.45865vw, 100vh) scale(0.4596); } } .snow:nth-child(94) { - opacity: 0.179; - transform: translate(48.8517vw, -10px) scale(0.8027); - animation: fall-94 27s -12s linear infinite; + opacity: 0.8571; + transform: translate(83.2832vw, -10px) scale(0.4375); + animation: fall-94 14s -6s linear infinite; } @keyframes fall-94 { - 43.894% { - transform: translate(40.1241vw, 43.894vh) scale(0.8027); + 44.202% { + transform: translate(90.9645vw, 44.202vh) scale(0.4375); } to { - transform: translate(44.4879vw, 100vh) scale(0.8027); + transform: translate(87.12385vw, 100vh) scale(0.4375); } } .snow:nth-child(95) { - opacity: 0.8702; - transform: translate(54.6174vw, -10px) scale(0.2768); - animation: fall-95 24s -20s linear infinite; + opacity: 0.9713; + transform: translate(40.6951vw, -10px) scale(0.4513); + animation: fall-95 26s -9s linear infinite; } @keyframes fall-95 { - 30.017% { - transform: translate(60.7236vw, 30.017vh) scale(0.2768); + 47.959% { + transform: translate(42.9733vw, 47.959vh) scale(0.4513); } to { - transform: translate(57.6705vw, 100vh) scale(0.2768); + transform: translate(41.8342vw, 100vh) scale(0.4513); } } .snow:nth-child(96) { - opacity: 0.4465; - transform: translate(6.5265vw, -10px) scale(0.2235); - animation: fall-96 12s -28s linear infinite; + opacity: 0.1428; + transform: translate(82.7398vw, -10px) scale(0.8684); + animation: fall-96 30s -21s linear infinite; } @keyframes fall-96 { - 40.386% { - transform: translate(8.5615vw, 40.386vh) scale(0.2235); + 54.576% { + transform: translate(91.5364vw, 54.576vh) scale(0.8684); } to { - transform: translate(7.544vw, 100vh) scale(0.2235); + transform: translate(87.1381vw, 100vh) scale(0.8684); } } .snow:nth-child(97) { - opacity: 0.0165; - transform: translate(56.65vw, -10px) scale(0.8847); - animation: fall-97 17s -24s linear infinite; + opacity: 0.0237; + transform: translate(1.4668vw, -10px) scale(0.2614); + animation: fall-97 28s -3s linear infinite; } @keyframes fall-97 { - 52.775% { - transform: translate(65.8438vw, 52.775vh) scale(0.8847); + 54.403% { + transform: translate(-4.5293vw, 54.403vh) scale(0.2614); } to { - transform: translate(61.2469vw, 100vh) scale(0.8847); + transform: translate(-1.53125vw, 100vh) scale(0.2614); } } .snow:nth-child(98) { - opacity: 0.0222; - transform: translate(59.5725vw, -10px) scale(0.5129); - animation: fall-98 14s -7s linear infinite; + opacity: 0.1216; + transform: translate(88.351vw, -10px) scale(0.1226); + animation: fall-98 22s -25s linear infinite; } @keyframes fall-98 { - 71.929% { - transform: translate(53.6906vw, 71.929vh) scale(0.5129); + 43.983% { + transform: translate(92.0067vw, 43.983vh) scale(0.1226); } to { - transform: translate(56.63155vw, 100vh) scale(0.5129); + transform: translate(90.17885vw, 100vh) scale(0.1226); } } .snow:nth-child(99) { - opacity: 0.5548; - transform: translate(28.8671vw, -10px) scale(0.7553); - animation: fall-99 20s -9s linear infinite; + opacity: 0.7152; + transform: translate(86.4084vw, -10px) scale(0.9298); + animation: fall-99 28s -10s linear infinite; } @keyframes fall-99 { - 36.304% { - transform: translate(31.3571vw, 36.304vh) scale(0.7553); + 40.422% { + transform: translate(77.5379vw, 40.422vh) scale(0.9298); } to { - transform: translate(30.1121vw, 100vh) scale(0.7553); + transform: translate(81.97315vw, 100vh) scale(0.9298); } } .snow:nth-child(100) { - opacity: 0.3593; - transform: translate(28.9038vw, -10px) scale(0.7136); - animation: fall-100 27s -15s linear infinite; + opacity: 0.115; + transform: translate(87.1559vw, -10px) scale(0.7651); + animation: fall-100 16s -21s linear infinite; } @keyframes fall-100 { - 37.912% { - transform: translate(28.7244vw, 37.912vh) scale(0.7136); + 77.806% { + transform: translate(91.9728vw, 77.806vh) scale(0.7651); } to { - transform: translate(28.8141vw, 100vh) scale(0.7136); + transform: translate(89.56435vw, 100vh) scale(0.7651); } } .snow:nth-child(101) { - opacity: 0.7352; - transform: translate(29.9844vw, -10px) scale(0.819); - animation: fall-101 23s -24s linear infinite; + opacity: 0.2001; + transform: translate(76.857vw, -10px) scale(0.5044); + animation: fall-101 29s -14s linear infinite; } @keyframes fall-101 { - 54.125% { - transform: translate(39.2198vw, 54.125vh) scale(0.819); + 75.988% { + transform: translate(74.0871vw, 75.988vh) scale(0.5044); } to { - transform: translate(34.6021vw, 100vh) scale(0.819); + transform: translate(75.47205vw, 100vh) scale(0.5044); } } .snow:nth-child(102) { - opacity: 0.0161; - transform: translate(37.1865vw, -10px) scale(0.1167); - animation: fall-102 21s -13s linear infinite; + opacity: 0.9123; + transform: translate(51.7563vw, -10px) scale(0.4435); + animation: fall-102 27s -25s linear infinite; } @keyframes fall-102 { - 68.978% { - transform: translate(37.3265vw, 68.978vh) scale(0.1167); + 57.047% { + transform: translate(46.0567vw, 57.047vh) scale(0.4435); } to { - transform: translate(37.2565vw, 100vh) scale(0.1167); + transform: translate(48.9065vw, 100vh) scale(0.4435); } } .snow:nth-child(103) { - opacity: 0.026; - transform: translate(82.8018vw, -10px) scale(0.3979); - animation: fall-103 12s -8s linear infinite; + opacity: 0.7854; + transform: translate(73.296vw, -10px) scale(0.3228); + animation: fall-103 21s -18s linear infinite; } @keyframes fall-103 { - 75.056% { - transform: translate(80.4886vw, 75.056vh) scale(0.3979); + 79.251% { + transform: translate(66.827vw, 79.251vh) scale(0.3228); } to { - transform: translate(81.6452vw, 100vh) scale(0.3979); + transform: translate(70.0615vw, 100vh) scale(0.3228); } } .snow:nth-child(104) { - opacity: 0.518; - transform: translate(59.2555vw, -10px) scale(0.9326); - animation: fall-104 18s -1s linear infinite; + opacity: 0.88; + transform: translate(36.1281vw, -10px) scale(0.0614); + animation: fall-104 28s -21s linear infinite; } @keyframes fall-104 { - 49.426% { - transform: translate(50.3545vw, 49.426vh) scale(0.9326); + 78.904% { + transform: translate(35.602vw, 78.904vh) scale(0.0614); } to { - transform: translate(54.805vw, 100vh) scale(0.9326); + transform: translate(35.86505vw, 100vh) scale(0.0614); } } .snow:nth-child(105) { - opacity: 0.7862; - transform: translate(1.9712vw, -10px) scale(0.7748); - animation: fall-105 26s -5s linear infinite; + opacity: 0.16; + transform: translate(26.469vw, -10px) scale(0.7906); + animation: fall-105 16s -4s linear infinite; } @keyframes fall-105 { - 40.213% { - transform: translate(-0.7696vw, 40.213vh) scale(0.7748); + 46.998% { + transform: translate(18.6174vw, 46.998vh) scale(0.7906); } to { - transform: translate(0.6008vw, 100vh) scale(0.7748); + transform: translate(22.5432vw, 100vh) scale(0.7906); } } .snow:nth-child(106) { - opacity: 0.6511; - transform: translate(88.4948vw, -10px) scale(0.5622); - animation: fall-106 16s -30s linear infinite; + opacity: 0.7139; + transform: translate(66.7226vw, -10px) scale(0.2785); + animation: fall-106 25s -7s linear infinite; } @keyframes fall-106 { - 70.494% { - transform: translate(84.4934vw, 70.494vh) scale(0.5622); + 38.817% { + transform: translate(75.8206vw, 38.817vh) scale(0.2785); } to { - transform: translate(86.4941vw, 100vh) scale(0.5622); + transform: translate(71.2716vw, 100vh) scale(0.2785); } } .snow:nth-child(107) { - opacity: 0.0457; - transform: translate(50.6289vw, -10px) scale(0.5976); - animation: fall-107 26s -11s linear infinite; + opacity: 0.133; + transform: translate(47.9855vw, -10px) scale(0.7324); + animation: fall-107 15s -10s linear infinite; } @keyframes fall-107 { - 70.16% { - transform: translate(48.5838vw, 70.16vh) scale(0.5976); + 48.691% { + transform: translate(55.7693vw, 48.691vh) scale(0.7324); } to { - transform: translate(49.60635vw, 100vh) scale(0.5976); + transform: translate(51.8774vw, 100vh) scale(0.7324); } } .snow:nth-child(108) { - opacity: 0.4167; - transform: translate(49.6798vw, -10px) scale(0.6951); - animation: fall-108 16s -2s linear infinite; + opacity: 0.9863; + transform: translate(56.9825vw, -10px) scale(0.7301); + animation: fall-108 27s -29s linear infinite; } @keyframes fall-108 { - 65.347% { - transform: translate(50.1553vw, 65.347vh) scale(0.6951); + 73.827% { + transform: translate(63.4461vw, 73.827vh) scale(0.7301); } to { - transform: translate(49.91755vw, 100vh) scale(0.6951); + transform: translate(60.2143vw, 100vh) scale(0.7301); } } .snow:nth-child(109) { - opacity: 0.4478; - transform: translate(89.0264vw, -10px) scale(0.3174); - animation: fall-109 27s -20s linear infinite; + opacity: 0.2939; + transform: translate(39.6921vw, -10px) scale(0.417); + animation: fall-109 10s -10s linear infinite; } @keyframes fall-109 { - 49.162% { - transform: translate(91.4528vw, 49.162vh) scale(0.3174); + 75.307% { + transform: translate(48.5459vw, 75.307vh) scale(0.417); } to { - transform: translate(90.2396vw, 100vh) scale(0.3174); + transform: translate(44.119vw, 100vh) scale(0.417); } } .snow:nth-child(110) { - opacity: 0.7325; - transform: translate(73.1006vw, -10px) scale(0.5512); - animation: fall-110 22s -17s linear infinite; + opacity: 0.7026; + transform: translate(39.6442vw, -10px) scale(0.7085); + animation: fall-110 29s -13s linear infinite; } @keyframes fall-110 { - 65.483% { - transform: translate(77.9605vw, 65.483vh) scale(0.5512); + 59.143% { + transform: translate(47.5301vw, 59.143vh) scale(0.7085); } to { - transform: translate(75.53055vw, 100vh) scale(0.5512); + transform: translate(43.58715vw, 100vh) scale(0.7085); } } .snow:nth-child(111) { - opacity: 0.0731; - transform: translate(11.3609vw, -10px) scale(0.6406); - animation: fall-111 30s -10s linear infinite; + opacity: 0.2058; + transform: translate(19.8921vw, -10px) scale(0.4829); + animation: fall-111 13s -13s linear infinite; } @keyframes fall-111 { - 60.875% { - transform: translate(4.4901vw, 60.875vh) scale(0.6406); + 59.593% { + transform: translate(22.7754vw, 59.593vh) scale(0.4829); } to { - transform: translate(7.9255vw, 100vh) scale(0.6406); + transform: translate(21.33375vw, 100vh) scale(0.4829); } } .snow:nth-child(112) { - opacity: 0.5301; - transform: translate(52.568vw, -10px) scale(0.5604); - animation: fall-112 29s -19s linear infinite; + opacity: 0.6555; + transform: translate(82.5081vw, -10px) scale(0.5487); + animation: fall-112 23s -6s linear infinite; } @keyframes fall-112 { - 31.887% { - transform: translate(61.1722vw, 31.887vh) scale(0.5604); + 46.675% { + transform: translate(77.7456vw, 46.675vh) scale(0.5487); } to { - transform: translate(56.8701vw, 100vh) scale(0.5604); + transform: translate(80.12685vw, 100vh) scale(0.5487); } } .snow:nth-child(113) { - opacity: 0.736; - transform: translate(66.7622vw, -10px) scale(0.1933); - animation: fall-113 26s -20s linear infinite; + opacity: 0.8354; + transform: translate(22.165vw, -10px) scale(0.5893); + animation: fall-113 23s -22s linear infinite; } @keyframes fall-113 { - 31.083% { - transform: translate(63.5818vw, 31.083vh) scale(0.1933); + 54.67% { + transform: translate(13.02vw, 54.67vh) scale(0.5893); } to { - transform: translate(65.172vw, 100vh) scale(0.1933); + transform: translate(17.5925vw, 100vh) scale(0.5893); } } .snow:nth-child(114) { - opacity: 0.9156; - transform: translate(43.4836vw, -10px) scale(0.1741); - animation: fall-114 28s -17s linear infinite; + opacity: 0.5331; + transform: translate(58.4972vw, -10px) scale(0.2278); + animation: fall-114 27s -29s linear infinite; } @keyframes fall-114 { - 61.642% { - transform: translate(46.3396vw, 61.642vh) scale(0.1741); + 44.227% { + transform: translate(49.6021vw, 44.227vh) scale(0.2278); } to { - transform: translate(44.9116vw, 100vh) scale(0.1741); + transform: translate(54.04965vw, 100vh) scale(0.2278); } } .snow:nth-child(115) { - opacity: 0.6392; - transform: translate(9.5582vw, -10px) scale(0.9935); - animation: fall-115 30s -26s linear infinite; + opacity: 0.2475; + transform: translate(9.7659vw, -10px) scale(0.2921); + animation: fall-115 18s -7s linear infinite; } @keyframes fall-115 { - 47.781% { - transform: translate(16.6793vw, 47.781vh) scale(0.9935); + 75.622% { + transform: translate(18.2793vw, 75.622vh) scale(0.2921); } to { - transform: translate(13.11875vw, 100vh) scale(0.9935); + transform: translate(14.0226vw, 100vh) scale(0.2921); } } .snow:nth-child(116) { - opacity: 0.2764; - transform: translate(26.9302vw, -10px) scale(0.5486); - animation: fall-116 26s -4s linear infinite; + opacity: 0.51; + transform: translate(83.646vw, -10px) scale(0.4056); + animation: fall-116 23s -23s linear infinite; } @keyframes fall-116 { - 35.221% { - transform: translate(36.3765vw, 35.221vh) scale(0.5486); + 37.027% { + transform: translate(74.1694vw, 37.027vh) scale(0.4056); } to { - transform: translate(31.65335vw, 100vh) scale(0.5486); + transform: translate(78.9077vw, 100vh) scale(0.4056); } } .snow:nth-child(117) { - opacity: 0.5023; - transform: translate(2.7969vw, -10px) scale(0.4702); - animation: fall-117 13s -30s linear infinite; + opacity: 0.3076; + transform: translate(78.6156vw, -10px) scale(0.9191); + animation: fall-117 22s -4s linear infinite; } @keyframes fall-117 { - 53.843% { - transform: translate(-1.2691vw, 53.843vh) scale(0.4702); + 59.772% { + transform: translate(77.6021vw, 59.772vh) scale(0.9191); } to { - transform: translate(0.7639vw, 100vh) scale(0.4702); + transform: translate(78.10885vw, 100vh) scale(0.9191); } } .snow:nth-child(118) { - opacity: 0.5544; - transform: translate(52.5093vw, -10px) scale(0.507); - animation: fall-118 24s -11s linear infinite; + opacity: 0.5272; + transform: translate(15.6187vw, -10px) scale(0.4724); + animation: fall-118 26s -18s linear infinite; } @keyframes fall-118 { - 75.991% { - transform: translate(45.8513vw, 75.991vh) scale(0.507); + 57.04% { + transform: translate(19.8612vw, 57.04vh) scale(0.4724); } to { - transform: translate(49.1803vw, 100vh) scale(0.507); + transform: translate(17.73995vw, 100vh) scale(0.4724); } } .snow:nth-child(119) { - opacity: 0.0506; - transform: translate(96.775vw, -10px) scale(0.207); - animation: fall-119 24s -16s linear infinite; + opacity: 0.5246; + transform: translate(53.9914vw, -10px) scale(0.943); + animation: fall-119 30s -14s linear infinite; } @keyframes fall-119 { - 60.251% { - transform: translate(104.4393vw, 60.251vh) scale(0.207); + 77.121% { + transform: translate(59.3957vw, 77.121vh) scale(0.943); } to { - transform: translate(100.60715vw, 100vh) scale(0.207); + transform: translate(56.69355vw, 100vh) scale(0.943); } } .snow:nth-child(120) { - opacity: 0.3992; - transform: translate(48.2744vw, -10px) scale(0.7863); - animation: fall-120 19s -25s linear infinite; + opacity: 0.894; + transform: translate(75.9531vw, -10px) scale(0.794); + animation: fall-120 17s -19s linear infinite; } @keyframes fall-120 { - 50.572% { - transform: translate(56.9717vw, 50.572vh) scale(0.7863); + 77.206% { + transform: translate(76.8113vw, 77.206vh) scale(0.794); } to { - transform: translate(52.62305vw, 100vh) scale(0.7863); + transform: translate(76.3822vw, 100vh) scale(0.794); } } .snow:nth-child(121) { - opacity: 0.2255; - transform: translate(87.8295vw, -10px) scale(0.9635); - animation: fall-121 11s -4s linear infinite; + opacity: 0.6038; + transform: translate(80.5702vw, -10px) scale(0.5975); + animation: fall-121 23s -22s linear infinite; } @keyframes fall-121 { - 52.962% { - transform: translate(96.6361vw, 52.962vh) scale(0.9635); + 44.9% { + transform: translate(73.4026vw, 44.9vh) scale(0.5975); } to { - transform: translate(92.2328vw, 100vh) scale(0.9635); + transform: translate(76.9864vw, 100vh) scale(0.5975); } } .snow:nth-child(122) { - opacity: 0.5018; - transform: translate(36.332vw, -10px) scale(0.027); - animation: fall-122 17s -15s linear infinite; + opacity: 0.5396; + transform: translate(84.6704vw, -10px) scale(0.09); + animation: fall-122 19s -12s linear infinite; } @keyframes fall-122 { - 70.985% { - transform: translate(33.8104vw, 70.985vh) scale(0.027); + 68.011% { + transform: translate(79.945vw, 68.011vh) scale(0.09); } to { - transform: translate(35.0712vw, 100vh) scale(0.027); + transform: translate(82.3077vw, 100vh) scale(0.09); } } .snow:nth-child(123) { - opacity: 0.8509; - transform: translate(25.8032vw, -10px) scale(0.966); - animation: fall-123 10s -18s linear infinite; + opacity: 0.7404; + transform: translate(99.111vw, -10px) scale(0.7353); + animation: fall-123 21s -10s linear infinite; } @keyframes fall-123 { - 51.017% { - transform: translate(24.8347vw, 51.017vh) scale(0.966); + 54.415% { + transform: translate(97.7141vw, 54.415vh) scale(0.7353); } to { - transform: translate(25.31895vw, 100vh) scale(0.966); + transform: translate(98.41255vw, 100vh) scale(0.7353); } } .snow:nth-child(124) { - opacity: 0.3984; - transform: translate(10.3439vw, -10px) scale(0.2766); - animation: fall-124 21s -27s linear infinite; + opacity: 0.9508; + transform: translate(8.2978vw, -10px) scale(0.2608); + animation: fall-124 18s -7s linear infinite; } @keyframes fall-124 { - 68.937% { - transform: translate(4.1598vw, 68.937vh) scale(0.2766); + 61.416% { + transform: translate(15.2764vw, 61.416vh) scale(0.2608); } to { - transform: translate(7.25185vw, 100vh) scale(0.2766); + transform: translate(11.7871vw, 100vh) scale(0.2608); } } .snow:nth-child(125) { - opacity: 0.7943; - transform: translate(2.4852vw, -10px) scale(0.1502); - animation: fall-125 22s -18s linear infinite; + opacity: 0.9372; + transform: translate(51.8205vw, -10px) scale(0.837); + animation: fall-125 10s -23s linear infinite; } @keyframes fall-125 { - 75.408% { - transform: translate(6.8152vw, 75.408vh) scale(0.1502); + 71.556% { + transform: translate(47.0679vw, 71.556vh) scale(0.837); } to { - transform: translate(4.6502vw, 100vh) scale(0.1502); + transform: translate(49.4442vw, 100vh) scale(0.837); } } .snow:nth-child(126) { - opacity: 0.3543; - transform: translate(87.6992vw, -10px) scale(0.8729); - animation: fall-126 19s -11s linear infinite; + opacity: 0.9459; + transform: translate(66.5912vw, -10px) scale(0.6166); + animation: fall-126 16s -26s linear infinite; } @keyframes fall-126 { - 75.262% { - transform: translate(87.7907vw, 75.262vh) scale(0.8729); + 42.687% { + transform: translate(66.0965vw, 42.687vh) scale(0.6166); } to { - transform: translate(87.74495vw, 100vh) scale(0.8729); + transform: translate(66.34385vw, 100vh) scale(0.6166); } } .snow:nth-child(127) { - opacity: 0.4267; - transform: translate(73.4778vw, -10px) scale(0.4206); - animation: fall-127 14s -1s linear infinite; + opacity: 0.3686; + transform: translate(34.6706vw, -10px) scale(0.3077); + animation: fall-127 24s -4s linear infinite; } @keyframes fall-127 { - 30.769% { - transform: translate(81.9366vw, 30.769vh) scale(0.4206); + 60.177% { + transform: translate(36.8758vw, 60.177vh) scale(0.3077); } to { - transform: translate(77.7072vw, 100vh) scale(0.4206); + transform: translate(35.7732vw, 100vh) scale(0.3077); } } .snow:nth-child(128) { - opacity: 0.8137; - transform: translate(72.6216vw, -10px) scale(0.0274); - animation: fall-128 29s -13s linear infinite; + opacity: 0.6618; + transform: translate(0.7451vw, -10px) scale(0.8276); + animation: fall-128 15s -9s linear infinite; } @keyframes fall-128 { - 67.217% { - transform: translate(74.4632vw, 67.217vh) scale(0.0274); + 58.27% { + transform: translate(7.81vw, 58.27vh) scale(0.8276); } to { - transform: translate(73.5424vw, 100vh) scale(0.0274); + transform: translate(4.27755vw, 100vh) scale(0.8276); } } .snow:nth-child(129) { - opacity: 0.1338; - transform: translate(79.576vw, -10px) scale(0.5777); - animation: fall-129 18s -24s linear infinite; + opacity: 0.2008; + transform: translate(52.9819vw, -10px) scale(0.7044); + animation: fall-129 16s -8s linear infinite; } @keyframes fall-129 { - 34.573% { - transform: translate(70.0043vw, 34.573vh) scale(0.5777); + 50.307% { + transform: translate(59.7984vw, 50.307vh) scale(0.7044); } to { - transform: translate(74.79015vw, 100vh) scale(0.5777); + transform: translate(56.39015vw, 100vh) scale(0.7044); } } .snow:nth-child(130) { - opacity: 0.1907; - transform: translate(73.3082vw, -10px) scale(0.6206); - animation: fall-130 25s -1s linear infinite; + opacity: 0.5605; + transform: translate(5.8675vw, -10px) scale(0.0732); + animation: fall-130 27s -3s linear infinite; } @keyframes fall-130 { - 63.575% { - transform: translate(78.0236vw, 63.575vh) scale(0.6206); + 63.62% { + transform: translate(12.8141vw, 63.62vh) scale(0.0732); } to { - transform: translate(75.6659vw, 100vh) scale(0.6206); + transform: translate(9.3408vw, 100vh) scale(0.0732); } } .snow:nth-child(131) { - opacity: 0.7596; - transform: translate(14.0103vw, -10px) scale(0.7444); - animation: fall-131 21s -27s linear infinite; + opacity: 0.1936; + transform: translate(85.5302vw, -10px) scale(0.9906); + animation: fall-131 21s -5s linear infinite; } @keyframes fall-131 { - 33.549% { - transform: translate(6.186vw, 33.549vh) scale(0.7444); + 37.821% { + transform: translate(76.5674vw, 37.821vh) scale(0.9906); } to { - transform: translate(10.09815vw, 100vh) scale(0.7444); + transform: translate(81.0488vw, 100vh) scale(0.9906); } } .snow:nth-child(132) { - opacity: 0.3308; - transform: translate(40.6396vw, -10px) scale(0.3556); - animation: fall-132 22s -13s linear infinite; + opacity: 0.2621; + transform: translate(49.4411vw, -10px) scale(0.3074); + animation: fall-132 18s -29s linear infinite; } @keyframes fall-132 { - 66.4% { - transform: translate(42.9802vw, 66.4vh) scale(0.3556); + 71.256% { + transform: translate(46.188vw, 71.256vh) scale(0.3074); } to { - transform: translate(41.8099vw, 100vh) scale(0.3556); + transform: translate(47.81455vw, 100vh) scale(0.3074); } } .snow:nth-child(133) { - opacity: 0.9057; - transform: translate(21.6273vw, -10px) scale(0.0361); - animation: fall-133 20s -30s linear infinite; + opacity: 0.6409; + transform: translate(99.7084vw, -10px) scale(0.219); + animation: fall-133 12s -21s linear infinite; } @keyframes fall-133 { - 69.881% { - transform: translate(29.5986vw, 69.881vh) scale(0.0361); + 32.996% { + transform: translate(93.0399vw, 32.996vh) scale(0.219); } to { - transform: translate(25.61295vw, 100vh) scale(0.0361); + transform: translate(96.37415vw, 100vh) scale(0.219); } } .snow:nth-child(134) { - opacity: 0.8563; - transform: translate(42.1235vw, -10px) scale(0.3396); - animation: fall-134 18s -2s linear infinite; + opacity: 0.6089; + transform: translate(4.8057vw, -10px) scale(0.7178); + animation: fall-134 27s -7s linear infinite; } @keyframes fall-134 { - 63.344% { - transform: translate(46.9764vw, 63.344vh) scale(0.3396); + 75.245% { + transform: translate(3.3523vw, 75.245vh) scale(0.7178); } to { - transform: translate(44.54995vw, 100vh) scale(0.3396); + transform: translate(4.079vw, 100vh) scale(0.7178); } } .snow:nth-child(135) { - opacity: 0.5202; - transform: translate(38.3956vw, -10px) scale(0.4066); - animation: fall-135 15s -16s linear infinite; + opacity: 0.0094; + transform: translate(45.2929vw, -10px) scale(0.9152); + animation: fall-135 27s -15s linear infinite; } @keyframes fall-135 { - 41.757% { - transform: translate(42.9169vw, 41.757vh) scale(0.4066); + 58.636% { + transform: translate(36.7541vw, 58.636vh) scale(0.9152); } to { - transform: translate(40.65625vw, 100vh) scale(0.4066); + transform: translate(41.0235vw, 100vh) scale(0.9152); } } .snow:nth-child(136) { - opacity: 0.9495; - transform: translate(35.0662vw, -10px) scale(0.2481); - animation: fall-136 17s -22s linear infinite; + opacity: 0.6489; + transform: translate(97.5958vw, -10px) scale(0.6088); + animation: fall-136 12s -5s linear infinite; } @keyframes fall-136 { - 52.533% { - transform: translate(41.4232vw, 52.533vh) scale(0.2481); + 42.877% { + transform: translate(97.0817vw, 42.877vh) scale(0.6088); } to { - transform: translate(38.2447vw, 100vh) scale(0.2481); + transform: translate(97.33875vw, 100vh) scale(0.6088); } } .snow:nth-child(137) { - opacity: 0.2196; - transform: translate(84.1975vw, -10px) scale(0.2747); - animation: fall-137 19s -30s linear infinite; + opacity: 0.5486; + transform: translate(60.5595vw, -10px) scale(0.6457); + animation: fall-137 28s -24s linear infinite; } @keyframes fall-137 { - 79.441% { - transform: translate(78.659vw, 79.441vh) scale(0.2747); + 57.068% { + transform: translate(64.6267vw, 57.068vh) scale(0.6457); } to { - transform: translate(81.42825vw, 100vh) scale(0.2747); + transform: translate(62.5931vw, 100vh) scale(0.6457); } } .snow:nth-child(138) { - opacity: 0.6957; - transform: translate(50.2714vw, -10px) scale(0.7826); - animation: fall-138 12s -21s linear infinite; + opacity: 0.2014; + transform: translate(48.5288vw, -10px) scale(0.7755); + animation: fall-138 28s -8s linear infinite; } @keyframes fall-138 { - 59.661% { - transform: translate(59.8961vw, 59.661vh) scale(0.7826); + 54.129% { + transform: translate(43.8336vw, 54.129vh) scale(0.7755); } to { - transform: translate(55.08375vw, 100vh) scale(0.7826); + transform: translate(46.1812vw, 100vh) scale(0.7755); } } .snow:nth-child(139) { - opacity: 0.1837; - transform: translate(7.2385vw, -10px) scale(0.6418); - animation: fall-139 16s -17s linear infinite; + opacity: 0.0486; + transform: translate(94.3659vw, -10px) scale(0.1602); + animation: fall-139 10s -4s linear infinite; } @keyframes fall-139 { - 71.453% { - transform: translate(12.6159vw, 71.453vh) scale(0.6418); + 43.139% { + transform: translate(89.926vw, 43.139vh) scale(0.1602); } to { - transform: translate(9.9272vw, 100vh) scale(0.6418); + transform: translate(92.14595vw, 100vh) scale(0.1602); } } .snow:nth-child(140) { - opacity: 0.8588; - transform: translate(20.8019vw, -10px) scale(0.9765); - animation: fall-140 30s -29s linear infinite; + opacity: 0.3078; + transform: translate(60.761vw, -10px) scale(0.5753); + animation: fall-140 14s -15s linear infinite; } @keyframes fall-140 { - 36.77% { - transform: translate(23.9052vw, 36.77vh) scale(0.9765); + 36.668% { + transform: translate(56.2788vw, 36.668vh) scale(0.5753); } to { - transform: translate(22.35355vw, 100vh) scale(0.9765); + transform: translate(58.5199vw, 100vh) scale(0.5753); } } .snow:nth-child(141) { - opacity: 0.807; - transform: translate(69.2694vw, -10px) scale(0.1167); - animation: fall-141 24s -27s linear infinite; + opacity: 0.7022; + transform: translate(19.5291vw, -10px) scale(0.9412); + animation: fall-141 14s -14s linear infinite; } @keyframes fall-141 { - 34.677% { - transform: translate(74.128vw, 34.677vh) scale(0.1167); + 41.777% { + transform: translate(19.9281vw, 41.777vh) scale(0.9412); } to { - transform: translate(71.6987vw, 100vh) scale(0.1167); + transform: translate(19.7286vw, 100vh) scale(0.9412); } } .snow:nth-child(142) { - opacity: 0.4448; - transform: translate(27.7553vw, -10px) scale(0.2147); - animation: fall-142 17s -18s linear infinite; + opacity: 0.4955; + transform: translate(45.6987vw, -10px) scale(0.4224); + animation: fall-142 19s -29s linear infinite; } @keyframes fall-142 { - 60.203% { - transform: translate(20.6945vw, 60.203vh) scale(0.2147); + 34.565% { + transform: translate(38.8318vw, 34.565vh) scale(0.4224); } to { - transform: translate(24.2249vw, 100vh) scale(0.2147); + transform: translate(42.26525vw, 100vh) scale(0.4224); } } .snow:nth-child(143) { - opacity: 0.0222; - transform: translate(19.7164vw, -10px) scale(0.9889); - animation: fall-143 23s -14s linear infinite; + opacity: 0.7208; + transform: translate(33.3433vw, -10px) scale(0.6322); + animation: fall-143 29s -15s linear infinite; } @keyframes fall-143 { - 75.449% { - transform: translate(21.0072vw, 75.449vh) scale(0.9889); + 52.337% { + transform: translate(36.1029vw, 52.337vh) scale(0.6322); } to { - transform: translate(20.3618vw, 100vh) scale(0.9889); + transform: translate(34.7231vw, 100vh) scale(0.6322); } } .snow:nth-child(144) { - opacity: 0.7923; - transform: translate(1.8126vw, -10px) scale(0.4688); - animation: fall-144 13s -19s linear infinite; + opacity: 0.4312; + transform: translate(73.218vw, -10px) scale(0.3033); + animation: fall-144 26s -25s linear infinite; } @keyframes fall-144 { - 64.403% { - transform: translate(4.1566vw, 64.403vh) scale(0.4688); + 36.839% { + transform: translate(70.9729vw, 36.839vh) scale(0.3033); } to { - transform: translate(2.9846vw, 100vh) scale(0.4688); + transform: translate(72.09545vw, 100vh) scale(0.3033); } } .snow:nth-child(145) { - opacity: 0.4184; - transform: translate(99.0686vw, -10px) scale(0.7083); - animation: fall-145 21s -10s linear infinite; + opacity: 0.0939; + transform: translate(50.6979vw, -10px) scale(0.0668); + animation: fall-145 11s -29s linear infinite; } @keyframes fall-145 { - 42.074% { - transform: translate(98.9616vw, 42.074vh) scale(0.7083); + 52.288% { + transform: translate(58.2132vw, 52.288vh) scale(0.0668); } to { - transform: translate(99.0151vw, 100vh) scale(0.7083); + transform: translate(54.45555vw, 100vh) scale(0.0668); } } .snow:nth-child(146) { - opacity: 0.8464; - transform: translate(69.2123vw, -10px) scale(0.4235); - animation: fall-146 18s -30s linear infinite; + opacity: 0.2477; + transform: translate(61.0258vw, -10px) scale(0.7713); + animation: fall-146 14s -6s linear infinite; } @keyframes fall-146 { - 56.678% { - transform: translate(76.0684vw, 56.678vh) scale(0.4235); + 73.096% { + transform: translate(67.1808vw, 73.096vh) scale(0.7713); } to { - transform: translate(72.64035vw, 100vh) scale(0.4235); + transform: translate(64.1033vw, 100vh) scale(0.7713); } } .snow:nth-child(147) { - opacity: 0.3212; - transform: translate(16.5161vw, -10px) scale(0.0104); - animation: fall-147 14s -10s linear infinite; + opacity: 0.3616; + transform: translate(75.1387vw, -10px) scale(0.6391); + animation: fall-147 10s -22s linear infinite; } @keyframes fall-147 { - 75.555% { - transform: translate(13.6006vw, 75.555vh) scale(0.0104); + 68.545% { + transform: translate(69.5736vw, 68.545vh) scale(0.6391); } to { - transform: translate(15.05835vw, 100vh) scale(0.0104); + transform: translate(72.35615vw, 100vh) scale(0.6391); } } .snow:nth-child(148) { - opacity: 0.5944; - transform: translate(41.3436vw, -10px) scale(0.8408); - animation: fall-148 27s -4s linear infinite; + opacity: 0.7502; + transform: translate(37.0677vw, -10px) scale(0.5866); + animation: fall-148 18s -13s linear infinite; } @keyframes fall-148 { - 48.802% { - transform: translate(33.0156vw, 48.802vh) scale(0.8408); + 76.095% { + transform: translate(33.7853vw, 76.095vh) scale(0.5866); } to { - transform: translate(37.1796vw, 100vh) scale(0.8408); + transform: translate(35.4265vw, 100vh) scale(0.5866); } } .snow:nth-child(149) { - opacity: 0.9663; - transform: translate(12.5839vw, -10px) scale(0.9381); - animation: fall-149 23s -25s linear infinite; + opacity: 0.6071; + transform: translate(55.1413vw, -10px) scale(0.8697); + animation: fall-149 29s -15s linear infinite; } @keyframes fall-149 { - 48.13% { - transform: translate(20.8332vw, 48.13vh) scale(0.9381); + 76.972% { + transform: translate(55.0149vw, 76.972vh) scale(0.8697); } to { - transform: translate(16.70855vw, 100vh) scale(0.9381); + transform: translate(55.0781vw, 100vh) scale(0.8697); } } .snow:nth-child(150) { - opacity: 0.3338; - transform: translate(47.0537vw, -10px) scale(0.5289); - animation: fall-150 15s -21s linear infinite; + opacity: 0.1049; + transform: translate(98.1589vw, -10px) scale(0.9981); + animation: fall-150 10s -11s linear infinite; } @keyframes fall-150 { - 69.761% { - transform: translate(53.3767vw, 69.761vh) scale(0.5289); + 68.602% { + transform: translate(97.4959vw, 68.602vh) scale(0.9981); } to { - transform: translate(50.2152vw, 100vh) scale(0.5289); + transform: translate(97.8274vw, 100vh) scale(0.9981); } } .snow:nth-child(151) { - opacity: 0.93; - transform: translate(90.2847vw, -10px) scale(0.7287); - animation: fall-151 23s -28s linear infinite; + opacity: 0.0842; + transform: translate(87.9589vw, -10px) scale(0.6507); + animation: fall-151 21s -29s linear infinite; } @keyframes fall-151 { - 67.831% { - transform: translate(97.6954vw, 67.831vh) scale(0.7287); + 44.645% { + transform: translate(79.5506vw, 44.645vh) scale(0.6507); } to { - transform: translate(93.99005vw, 100vh) scale(0.7287); + transform: translate(83.75475vw, 100vh) scale(0.6507); } } .snow:nth-child(152) { - opacity: 0.8232; - transform: translate(27.0481vw, -10px) scale(0.9605); - animation: fall-152 22s -22s linear infinite; + opacity: 0.1154; + transform: translate(57.0709vw, -10px) scale(0.2345); + animation: fall-152 26s -8s linear infinite; } @keyframes fall-152 { - 42.558% { - transform: translate(27.2282vw, 42.558vh) scale(0.9605); + 62.741% { + transform: translate(52.2612vw, 62.741vh) scale(0.2345); } to { - transform: translate(27.13815vw, 100vh) scale(0.9605); + transform: translate(54.66605vw, 100vh) scale(0.2345); } } .snow:nth-child(153) { - opacity: 0.9233; - transform: translate(1.3455vw, -10px) scale(0.953); - animation: fall-153 30s -6s linear infinite; + opacity: 0.5716; + transform: translate(43.9279vw, -10px) scale(0.7877); + animation: fall-153 25s -23s linear infinite; } @keyframes fall-153 { - 77.45% { - transform: translate(-0.639vw, 77.45vh) scale(0.953); + 33.595% { + transform: translate(52.4032vw, 33.595vh) scale(0.7877); } to { - transform: translate(0.35325vw, 100vh) scale(0.953); + transform: translate(48.16555vw, 100vh) scale(0.7877); } } .snow:nth-child(154) { - opacity: 0.844; - transform: translate(96.883vw, -10px) scale(0.1575); - animation: fall-154 10s -18s linear infinite; + opacity: 0.4192; + transform: translate(75.6591vw, -10px) scale(0.9318); + animation: fall-154 20s -24s linear infinite; } @keyframes fall-154 { - 43.219% { - transform: translate(88.628vw, 43.219vh) scale(0.1575); + 64.848% { + transform: translate(73.407vw, 64.848vh) scale(0.9318); } to { - transform: translate(92.7555vw, 100vh) scale(0.1575); + transform: translate(74.53305vw, 100vh) scale(0.9318); } } .snow:nth-child(155) { - opacity: 0.6913; - transform: translate(26.814vw, -10px) scale(0.2863); - animation: fall-155 24s -30s linear infinite; + opacity: 0.1049; + transform: translate(29.0413vw, -10px) scale(0.5546); + animation: fall-155 22s -2s linear infinite; } @keyframes fall-155 { - 31.918% { - transform: translate(18.2292vw, 31.918vh) scale(0.2863); + 46.747% { + transform: translate(22.9541vw, 46.747vh) scale(0.5546); } to { - transform: translate(22.5216vw, 100vh) scale(0.2863); + transform: translate(25.9977vw, 100vh) scale(0.5546); } } .snow:nth-child(156) { - opacity: 0.5704; - transform: translate(71.8857vw, -10px) scale(0.3006); - animation: fall-156 24s -21s linear infinite; + opacity: 0.184; + transform: translate(11.2696vw, -10px) scale(0.303); + animation: fall-156 10s -12s linear infinite; } @keyframes fall-156 { - 53.139% { - transform: translate(65.0339vw, 53.139vh) scale(0.3006); + 48.824% { + transform: translate(20.4083vw, 48.824vh) scale(0.303); } to { - transform: translate(68.4598vw, 100vh) scale(0.3006); + transform: translate(15.83895vw, 100vh) scale(0.303); } } .snow:nth-child(157) { - opacity: 0.8086; - transform: translate(22.9768vw, -10px) scale(0.8096); - animation: fall-157 30s -1s linear infinite; + opacity: 0.9333; + transform: translate(8.0191vw, -10px) scale(0.4143); + animation: fall-157 12s -9s linear infinite; } @keyframes fall-157 { - 40.81% { - transform: translate(24.1332vw, 40.81vh) scale(0.8096); + 58.72% { + transform: translate(15.1959vw, 58.72vh) scale(0.4143); } to { - transform: translate(23.555vw, 100vh) scale(0.8096); + transform: translate(11.6075vw, 100vh) scale(0.4143); } } .snow:nth-child(158) { - opacity: 0.7645; - transform: translate(70.4142vw, -10px) scale(0.474); - animation: fall-158 18s -23s linear infinite; + opacity: 0.6519; + transform: translate(12.7718vw, -10px) scale(0.2159); + animation: fall-158 27s -21s linear infinite; } @keyframes fall-158 { - 51.905% { - transform: translate(69.329vw, 51.905vh) scale(0.474); + 78.596% { + transform: translate(7.3753vw, 78.596vh) scale(0.2159); } to { - transform: translate(69.8716vw, 100vh) scale(0.474); + transform: translate(10.07355vw, 100vh) scale(0.2159); } } .snow:nth-child(159) { - opacity: 0.793; - transform: translate(76.3588vw, -10px) scale(0.9521); - animation: fall-159 28s -3s linear infinite; + opacity: 0.719; + transform: translate(5.1736vw, -10px) scale(0.1207); + animation: fall-159 22s -10s linear infinite; } @keyframes fall-159 { - 36.241% { - transform: translate(77.2538vw, 36.241vh) scale(0.9521); + 33.853% { + transform: translate(-2.4007vw, 33.853vh) scale(0.1207); } to { - transform: translate(76.8063vw, 100vh) scale(0.9521); + transform: translate(1.38645vw, 100vh) scale(0.1207); } } .snow:nth-child(160) { - opacity: 0.1514; - transform: translate(95.6695vw, -10px) scale(0.5611); - animation: fall-160 21s -19s linear infinite; + opacity: 0.0715; + transform: translate(87.291vw, -10px) scale(0.6154); + animation: fall-160 24s -17s linear infinite; } @keyframes fall-160 { - 30.639% { - transform: translate(98.9525vw, 30.639vh) scale(0.5611); + 64.627% { + transform: translate(77.709vw, 64.627vh) scale(0.6154); } to { - transform: translate(97.311vw, 100vh) scale(0.5611); + transform: translate(82.5vw, 100vh) scale(0.6154); } } .snow:nth-child(161) { - opacity: 0.5532; - transform: translate(81.3525vw, -10px) scale(0.0114); - animation: fall-161 17s -2s linear infinite; + opacity: 0.8423; + transform: translate(33.1035vw, -10px) scale(0.5816); + animation: fall-161 28s -13s linear infinite; } @keyframes fall-161 { - 50.065% { - transform: translate(72.3946vw, 50.065vh) scale(0.0114); + 66.787% { + transform: translate(35.9927vw, 66.787vh) scale(0.5816); } to { - transform: translate(76.87355vw, 100vh) scale(0.0114); + transform: translate(34.5481vw, 100vh) scale(0.5816); } } .snow:nth-child(162) { - opacity: 0.1431; - transform: translate(41.9961vw, -10px) scale(0.5761); - animation: fall-162 26s -7s linear infinite; + opacity: 0.8393; + transform: translate(27.0343vw, -10px) scale(0.4831); + animation: fall-162 22s -16s linear infinite; } @keyframes fall-162 { - 32.364% { - transform: translate(33.9404vw, 32.364vh) scale(0.5761); + 71.698% { + transform: translate(31.8367vw, 71.698vh) scale(0.4831); } to { - transform: translate(37.96825vw, 100vh) scale(0.5761); + transform: translate(29.4355vw, 100vh) scale(0.4831); } } .snow:nth-child(163) { - opacity: 0.4403; - transform: translate(52.3305vw, -10px) scale(0.4692); - animation: fall-163 15s -29s linear infinite; + opacity: 0.7703; + transform: translate(81.3763vw, -10px) scale(0.2256); + animation: fall-163 28s -30s linear infinite; } @keyframes fall-163 { - 68.686% { - transform: translate(48.5432vw, 68.686vh) scale(0.4692); + 30.18% { + transform: translate(90.9446vw, 30.18vh) scale(0.2256); } to { - transform: translate(50.43685vw, 100vh) scale(0.4692); + transform: translate(86.16045vw, 100vh) scale(0.2256); } } .snow:nth-child(164) { - opacity: 0.0917; - transform: translate(62.3363vw, -10px) scale(0.88); - animation: fall-164 21s -28s linear infinite; + opacity: 0.4345; + transform: translate(2.164vw, -10px) scale(0.7088); + animation: fall-164 23s -12s linear infinite; } @keyframes fall-164 { - 66.266% { - transform: translate(62.3203vw, 66.266vh) scale(0.88); + 68.105% { + transform: translate(6.3788vw, 68.105vh) scale(0.7088); } to { - transform: translate(62.3283vw, 100vh) scale(0.88); + transform: translate(4.2714vw, 100vh) scale(0.7088); } } .snow:nth-child(165) { - opacity: 0.6016; - transform: translate(86.7134vw, -10px) scale(0.0943); - animation: fall-165 28s -27s linear infinite; + opacity: 0.0557; + transform: translate(89.3825vw, -10px) scale(0.802); + animation: fall-165 11s -21s linear infinite; } @keyframes fall-165 { - 35.111% { - transform: translate(79.3642vw, 35.111vh) scale(0.0943); + 79.953% { + transform: translate(95.8295vw, 79.953vh) scale(0.802); } to { - transform: translate(83.0388vw, 100vh) scale(0.0943); + transform: translate(92.606vw, 100vh) scale(0.802); } } .snow:nth-child(166) { - opacity: 0.7946; - transform: translate(81.74vw, -10px) scale(0.3191); - animation: fall-166 25s -20s linear infinite; + opacity: 0.4709; + transform: translate(17.1663vw, -10px) scale(0.0207); + animation: fall-166 30s -7s linear infinite; } @keyframes fall-166 { - 38.155% { - transform: translate(75.1262vw, 38.155vh) scale(0.3191); + 34.201% { + transform: translate(19.3054vw, 34.201vh) scale(0.0207); } to { - transform: translate(78.4331vw, 100vh) scale(0.3191); + transform: translate(18.23585vw, 100vh) scale(0.0207); } } .snow:nth-child(167) { - opacity: 0.3897; - transform: translate(46.559vw, -10px) scale(0.5913); - animation: fall-167 26s -18s linear infinite; + opacity: 0.2756; + transform: translate(78.6968vw, -10px) scale(0.5426); + animation: fall-167 12s -6s linear infinite; } @keyframes fall-167 { - 74.239% { - transform: translate(42.8824vw, 74.239vh) scale(0.5913); + 61.398% { + transform: translate(85.7934vw, 61.398vh) scale(0.5426); } to { - transform: translate(44.7207vw, 100vh) scale(0.5913); + transform: translate(82.2451vw, 100vh) scale(0.5426); } } .snow:nth-child(168) { - opacity: 0.7128; - transform: translate(24.7756vw, -10px) scale(0.6178); - animation: fall-168 21s -30s linear infinite; + opacity: 0.5878; + transform: translate(38.7557vw, -10px) scale(0.7825); + animation: fall-168 29s -2s linear infinite; } @keyframes fall-168 { - 36.101% { - transform: translate(26.7588vw, 36.101vh) scale(0.6178); + 61.863% { + transform: translate(33.7974vw, 61.863vh) scale(0.7825); } to { - transform: translate(25.7672vw, 100vh) scale(0.6178); + transform: translate(36.27655vw, 100vh) scale(0.7825); } } .snow:nth-child(169) { - opacity: 0.854; - transform: translate(78.0302vw, -10px) scale(0.2971); - animation: fall-169 15s -13s linear infinite; + opacity: 0.5165; + transform: translate(59.3916vw, -10px) scale(0.6278); + animation: fall-169 27s -4s linear infinite; } @keyframes fall-169 { - 34.528% { - transform: translate(72.2525vw, 34.528vh) scale(0.2971); + 39.895% { + transform: translate(54.0525vw, 39.895vh) scale(0.6278); } to { - transform: translate(75.14135vw, 100vh) scale(0.2971); + transform: translate(56.72205vw, 100vh) scale(0.6278); } } .snow:nth-child(170) { - opacity: 0.3423; - transform: translate(30.5912vw, -10px) scale(0.0943); - animation: fall-170 21s -9s linear infinite; + opacity: 0.0722; + transform: translate(88.0941vw, -10px) scale(0.591); + animation: fall-170 14s -22s linear infinite; } @keyframes fall-170 { - 47.432% { - transform: translate(23.3341vw, 47.432vh) scale(0.0943); + 38.355% { + transform: translate(79.1273vw, 38.355vh) scale(0.591); } to { - transform: translate(26.96265vw, 100vh) scale(0.0943); + transform: translate(83.6107vw, 100vh) scale(0.591); } } .snow:nth-child(171) { - opacity: 0.4479; - transform: translate(96.1579vw, -10px) scale(0.7526); - animation: fall-171 16s -18s linear infinite; + opacity: 0.3862; + transform: translate(78.2828vw, -10px) scale(0.1025); + animation: fall-171 15s -6s linear infinite; } @keyframes fall-171 { - 72.107% { - transform: translate(94.885vw, 72.107vh) scale(0.7526); + 53.445% { + transform: translate(78.5813vw, 53.445vh) scale(0.1025); } to { - transform: translate(95.52145vw, 100vh) scale(0.7526); + transform: translate(78.43205vw, 100vh) scale(0.1025); } } .snow:nth-child(172) { - opacity: 0.5268; - transform: translate(5.38vw, -10px) scale(0.2191); - animation: fall-172 28s -19s linear infinite; + opacity: 0.0677; + transform: translate(88.9308vw, -10px) scale(0.0193); + animation: fall-172 30s -18s linear infinite; } @keyframes fall-172 { - 77.896% { - transform: translate(1.8183vw, 77.896vh) scale(0.2191); + 57.614% { + transform: translate(98.2398vw, 57.614vh) scale(0.0193); } to { - transform: translate(3.59915vw, 100vh) scale(0.2191); + transform: translate(93.5853vw, 100vh) scale(0.0193); } } .snow:nth-child(173) { - opacity: 0.2074; - transform: translate(71.5823vw, -10px) scale(0.134); - animation: fall-173 17s -3s linear infinite; + opacity: 0.4026; + transform: translate(39.6932vw, -10px) scale(0.4286); + animation: fall-173 12s -30s linear infinite; } @keyframes fall-173 { - 54.571% { - transform: translate(65.9382vw, 54.571vh) scale(0.134); + 43.682% { + transform: translate(29.8736vw, 43.682vh) scale(0.4286); } to { - transform: translate(68.76025vw, 100vh) scale(0.134); + transform: translate(34.7834vw, 100vh) scale(0.4286); } } .snow:nth-child(174) { - opacity: 0.6332; - transform: translate(68.6584vw, -10px) scale(0.926); - animation: fall-174 27s -16s linear infinite; + opacity: 0.346; + transform: translate(75.4764vw, -10px) scale(0.7416); + animation: fall-174 14s -20s linear infinite; } @keyframes fall-174 { - 53.728% { - transform: translate(72.6012vw, 53.728vh) scale(0.926); + 40.355% { + transform: translate(69.5468vw, 40.355vh) scale(0.7416); } to { - transform: translate(70.6298vw, 100vh) scale(0.926); + transform: translate(72.5116vw, 100vh) scale(0.7416); } } .snow:nth-child(175) { - opacity: 0.4553; - transform: translate(12.5344vw, -10px) scale(0.8205); - animation: fall-175 29s -28s linear infinite; + opacity: 0.8715; + transform: translate(0.3364vw, -10px) scale(0.6823); + animation: fall-175 29s -5s linear infinite; } @keyframes fall-175 { - 76.691% { - transform: translate(9.2969vw, 76.691vh) scale(0.8205); + 51.323% { + transform: translate(9.2495vw, 51.323vh) scale(0.6823); } to { - transform: translate(10.91565vw, 100vh) scale(0.8205); + transform: translate(4.79295vw, 100vh) scale(0.6823); } } .snow:nth-child(176) { - opacity: 0.3064; - transform: translate(88.2428vw, -10px) scale(0.4755); - animation: fall-176 28s -7s linear infinite; + opacity: 0.055; + transform: translate(24.152vw, -10px) scale(0.6141); + animation: fall-176 23s -4s linear infinite; } @keyframes fall-176 { - 77% { - transform: translate(80.0474vw, 77vh) scale(0.4755); + 40.226% { + transform: translate(32.0344vw, 40.226vh) scale(0.6141); } to { - transform: translate(84.1451vw, 100vh) scale(0.4755); + transform: translate(28.0932vw, 100vh) scale(0.6141); } } .snow:nth-child(177) { - opacity: 0.1047; - transform: translate(93.1228vw, -10px) scale(0.9058); - animation: fall-177 10s -9s linear infinite; + opacity: 0.0385; + transform: translate(69.2529vw, -10px) scale(0.1714); + animation: fall-177 26s -11s linear infinite; } @keyframes fall-177 { - 50.121% { - transform: translate(100.1693vw, 50.121vh) scale(0.9058); + 67.878% { + transform: translate(74.3215vw, 67.878vh) scale(0.1714); } to { - transform: translate(96.64605vw, 100vh) scale(0.9058); + transform: translate(71.7872vw, 100vh) scale(0.1714); } } .snow:nth-child(178) { - opacity: 0.9543; - transform: translate(89.3495vw, -10px) scale(0.5408); - animation: fall-178 11s -13s linear infinite; + opacity: 0.6741; + transform: translate(66.9862vw, -10px) scale(0.489); + animation: fall-178 14s -5s linear infinite; } @keyframes fall-178 { - 68.763% { - transform: translate(83.1324vw, 68.763vh) scale(0.5408); + 42.329% { + transform: translate(68.1979vw, 42.329vh) scale(0.489); } to { - transform: translate(86.24095vw, 100vh) scale(0.5408); + transform: translate(67.59205vw, 100vh) scale(0.489); } } .snow:nth-child(179) { - opacity: 0.4962; - transform: translate(39.4662vw, -10px) scale(0.5709); - animation: fall-179 13s -16s linear infinite; + opacity: 0.6507; + transform: translate(71.6711vw, -10px) scale(0.6201); + animation: fall-179 23s -27s linear infinite; } @keyframes fall-179 { - 35.556% { - transform: translate(41.9417vw, 35.556vh) scale(0.5709); + 48.574% { + transform: translate(78.4175vw, 48.574vh) scale(0.6201); } to { - transform: translate(40.70395vw, 100vh) scale(0.5709); + transform: translate(75.0443vw, 100vh) scale(0.6201); } } .snow:nth-child(180) { - opacity: 0.2603; - transform: translate(1.1855vw, -10px) scale(0.2274); - animation: fall-180 14s -4s linear infinite; + opacity: 0.024; + transform: translate(20.4928vw, -10px) scale(0.2278); + animation: fall-180 10s -23s linear infinite; } @keyframes fall-180 { - 72.382% { - transform: translate(5.4394vw, 72.382vh) scale(0.2274); + 55.531% { + transform: translate(30.2504vw, 55.531vh) scale(0.2278); } to { - transform: translate(3.31245vw, 100vh) scale(0.2274); + transform: translate(25.3716vw, 100vh) scale(0.2278); } } .snow:nth-child(181) { - opacity: 0.2565; - transform: translate(97.9479vw, -10px) scale(0.5408); - animation: fall-181 14s -17s linear infinite; + opacity: 0.0884; + transform: translate(85.0439vw, -10px) scale(0.5148); + animation: fall-181 16s -10s linear infinite; } @keyframes fall-181 { - 52.482% { - transform: translate(102.3555vw, 52.482vh) scale(0.5408); + 66.253% { + transform: translate(95.0149vw, 66.253vh) scale(0.5148); } to { - transform: translate(100.1517vw, 100vh) scale(0.5408); + transform: translate(90.0294vw, 100vh) scale(0.5148); } } .snow:nth-child(182) { - opacity: 0.3054; - transform: translate(33.5562vw, -10px) scale(0.0596); - animation: fall-182 13s -7s linear infinite; + opacity: 0.1657; + transform: translate(65.4088vw, -10px) scale(0.7369); + animation: fall-182 15s -29s linear infinite; } @keyframes fall-182 { - 33.978% { - transform: translate(36.0959vw, 33.978vh) scale(0.0596); + 64.644% { + transform: translate(61.8641vw, 64.644vh) scale(0.7369); } to { - transform: translate(34.82605vw, 100vh) scale(0.0596); + transform: translate(63.63645vw, 100vh) scale(0.7369); } } .snow:nth-child(183) { - opacity: 0.5697; - transform: translate(63.3766vw, -10px) scale(0.4393); - animation: fall-183 22s -22s linear infinite; + opacity: 0.7193; + transform: translate(90.4436vw, -10px) scale(0.5208); + animation: fall-183 26s -7s linear infinite; } @keyframes fall-183 { - 52.448% { - transform: translate(71.8485vw, 52.448vh) scale(0.4393); + 76.958% { + transform: translate(97.0168vw, 76.958vh) scale(0.5208); } to { - transform: translate(67.61255vw, 100vh) scale(0.4393); + transform: translate(93.7302vw, 100vh) scale(0.5208); } } .snow:nth-child(184) { - opacity: 0.4401; - transform: translate(8.6169vw, -10px) scale(0.4951); - animation: fall-184 30s -4s linear infinite; + opacity: 0.8104; + transform: translate(15.4511vw, -10px) scale(0.0242); + animation: fall-184 28s -9s linear infinite; } @keyframes fall-184 { - 56.613% { - transform: translate(3.2258vw, 56.613vh) scale(0.4951); + 35.871% { + transform: translate(23.5618vw, 35.871vh) scale(0.0242); } to { - transform: translate(5.92135vw, 100vh) scale(0.4951); + transform: translate(19.50645vw, 100vh) scale(0.0242); } } .snow:nth-child(185) { - opacity: 0.0641; - transform: translate(79.2921vw, -10px) scale(0.1237); - animation: fall-185 26s -26s linear infinite; + opacity: 0.767; + transform: translate(18.7358vw, -10px) scale(0.0911); + animation: fall-185 24s -2s linear infinite; } @keyframes fall-185 { - 78.719% { - transform: translate(74.409vw, 78.719vh) scale(0.1237); + 51.033% { + transform: translate(10.649vw, 51.033vh) scale(0.0911); } to { - transform: translate(76.85055vw, 100vh) scale(0.1237); + transform: translate(14.6924vw, 100vh) scale(0.0911); } } .snow:nth-child(186) { - opacity: 0.85; - transform: translate(87.6256vw, -10px) scale(0.3917); - animation: fall-186 29s -14s linear infinite; + opacity: 0.4404; + transform: translate(44.1211vw, -10px) scale(0.2886); + animation: fall-186 25s -2s linear infinite; } @keyframes fall-186 { - 39.816% { - transform: translate(84.3368vw, 39.816vh) scale(0.3917); + 67.381% { + transform: translate(35.836vw, 67.381vh) scale(0.2886); } to { - transform: translate(85.9812vw, 100vh) scale(0.3917); + transform: translate(39.97855vw, 100vh) scale(0.2886); } } .snow:nth-child(187) { - opacity: 0.8072; - transform: translate(44.6405vw, -10px) scale(0.8488); - animation: fall-187 20s -22s linear infinite; + opacity: 0.917; + transform: translate(72.712vw, -10px) scale(0.7782); + animation: fall-187 26s -23s linear infinite; } @keyframes fall-187 { - 41.022% { - transform: translate(35.5771vw, 41.022vh) scale(0.8488); + 35.771% { + transform: translate(69.9484vw, 35.771vh) scale(0.7782); } to { - transform: translate(40.1088vw, 100vh) scale(0.8488); + transform: translate(71.3302vw, 100vh) scale(0.7782); } } .snow:nth-child(188) { - opacity: 0.7791; - transform: translate(54.8112vw, -10px) scale(0.9441); - animation: fall-188 19s -13s linear infinite; + opacity: 0.838; + transform: translate(80.5385vw, -10px) scale(0.5826); + animation: fall-188 24s -6s linear infinite; } @keyframes fall-188 { - 72.007% { - transform: translate(55.0495vw, 72.007vh) scale(0.9441); + 31.443% { + transform: translate(81.7557vw, 31.443vh) scale(0.5826); } to { - transform: translate(54.93035vw, 100vh) scale(0.9441); + transform: translate(81.1471vw, 100vh) scale(0.5826); } } .snow:nth-child(189) { - opacity: 0.9443; - transform: translate(46.0065vw, -10px) scale(0.1136); - animation: fall-189 20s -3s linear infinite; + opacity: 0.0692; + transform: translate(77.3413vw, -10px) scale(0.5226); + animation: fall-189 29s -24s linear infinite; } @keyframes fall-189 { - 61.8% { - transform: translate(47.2932vw, 61.8vh) scale(0.1136); + 30.402% { + transform: translate(78.5534vw, 30.402vh) scale(0.5226); } to { - transform: translate(46.64985vw, 100vh) scale(0.1136); + transform: translate(77.94735vw, 100vh) scale(0.5226); } } .snow:nth-child(190) { - opacity: 0.0404; - transform: translate(86.166vw, -10px) scale(0.5574); - animation: fall-190 16s -27s linear infinite; + opacity: 0.516; + transform: translate(50.2756vw, -10px) scale(0.9505); + animation: fall-190 24s -22s linear infinite; } @keyframes fall-190 { - 79.642% { - transform: translate(92.7971vw, 79.642vh) scale(0.5574); + 33.044% { + transform: translate(48.4963vw, 33.044vh) scale(0.9505); } to { - transform: translate(89.48155vw, 100vh) scale(0.5574); + transform: translate(49.38595vw, 100vh) scale(0.9505); } } .snow:nth-child(191) { - opacity: 0.5712; - transform: translate(83.0154vw, -10px) scale(0.577); - animation: fall-191 25s -2s linear infinite; + opacity: 0.5304; + transform: translate(86.3528vw, -10px) scale(0.1695); + animation: fall-191 25s -12s linear infinite; } @keyframes fall-191 { - 45.045% { - transform: translate(77.4547vw, 45.045vh) scale(0.577); + 52.297% { + transform: translate(92.9376vw, 52.297vh) scale(0.1695); } to { - transform: translate(80.23505vw, 100vh) scale(0.577); + transform: translate(89.6452vw, 100vh) scale(0.1695); } } .snow:nth-child(192) { - opacity: 0.4671; - transform: translate(98.8491vw, -10px) scale(0.9814); - animation: fall-192 17s -15s linear infinite; + opacity: 0.8139; + transform: translate(46.6162vw, -10px) scale(0.3994); + animation: fall-192 24s -30s linear infinite; } @keyframes fall-192 { - 55.522% { - transform: translate(105.3315vw, 55.522vh) scale(0.9814); + 40.327% { + transform: translate(41.9699vw, 40.327vh) scale(0.3994); } to { - transform: translate(102.0903vw, 100vh) scale(0.9814); + transform: translate(44.29305vw, 100vh) scale(0.3994); } } .snow:nth-child(193) { - opacity: 0.0539; - transform: translate(25.9396vw, -10px) scale(0.8912); - animation: fall-193 18s -22s linear infinite; + opacity: 0.2854; + transform: translate(61.3317vw, -10px) scale(0.9536); + animation: fall-193 23s -18s linear infinite; } @keyframes fall-193 { - 45.542% { - transform: translate(29.5295vw, 45.542vh) scale(0.8912); + 59.915% { + transform: translate(55.0848vw, 59.915vh) scale(0.9536); } to { - transform: translate(27.73455vw, 100vh) scale(0.8912); + transform: translate(58.20825vw, 100vh) scale(0.9536); } } .snow:nth-child(194) { - opacity: 0.9608; - transform: translate(31.3346vw, -10px) scale(0.5892); - animation: fall-194 11s -20s linear infinite; + opacity: 0.0243; + transform: translate(14.5993vw, -10px) scale(0.5321); + animation: fall-194 27s -14s linear infinite; } @keyframes fall-194 { - 39.159% { - transform: translate(31.0696vw, 39.159vh) scale(0.5892); + 44.097% { + transform: translate(21.0705vw, 44.097vh) scale(0.5321); } to { - transform: translate(31.2021vw, 100vh) scale(0.5892); + transform: translate(17.8349vw, 100vh) scale(0.5321); } } .snow:nth-child(195) { - opacity: 0.4438; - transform: translate(89.6813vw, -10px) scale(0.3625); - animation: fall-195 13s -30s linear infinite; + opacity: 0.0236; + transform: translate(53.5117vw, -10px) scale(0.061); + animation: fall-195 30s -10s linear infinite; } @keyframes fall-195 { - 65.096% { - transform: translate(84.4189vw, 65.096vh) scale(0.3625); + 79.601% { + transform: translate(47.9427vw, 79.601vh) scale(0.061); } to { - transform: translate(87.0501vw, 100vh) scale(0.3625); + transform: translate(50.7272vw, 100vh) scale(0.061); } } .snow:nth-child(196) { - opacity: 0.1222; - transform: translate(12.8704vw, -10px) scale(0.5352); - animation: fall-196 30s -8s linear infinite; + opacity: 0.2294; + transform: translate(55.4197vw, -10px) scale(0.3527); + animation: fall-196 22s -2s linear infinite; } @keyframes fall-196 { - 58.803% { - transform: translate(3.0742vw, 58.803vh) scale(0.5352); + 46.403% { + transform: translate(48.82vw, 46.403vh) scale(0.3527); } to { - transform: translate(7.9723vw, 100vh) scale(0.5352); + transform: translate(52.11985vw, 100vh) scale(0.3527); } } .snow:nth-child(197) { - opacity: 0.5026; - transform: translate(13.2641vw, -10px) scale(0.8857); - animation: fall-197 17s -26s linear infinite; + opacity: 0.9868; + transform: translate(25.6153vw, -10px) scale(0.545); + animation: fall-197 19s -22s linear infinite; } @keyframes fall-197 { - 56.646% { - transform: translate(16.6408vw, 56.646vh) scale(0.8857); + 72.43% { + transform: translate(35.0232vw, 72.43vh) scale(0.545); } to { - transform: translate(14.95245vw, 100vh) scale(0.8857); + transform: translate(30.31925vw, 100vh) scale(0.545); } } .snow:nth-child(198) { - opacity: 0.3704; - transform: translate(47.8359vw, -10px) scale(0.562); - animation: fall-198 28s -15s linear infinite; + opacity: 0.109; + transform: translate(22.9035vw, -10px) scale(0.9817); + animation: fall-198 28s -28s linear infinite; } @keyframes fall-198 { - 47.23% { - transform: translate(51.4788vw, 47.23vh) scale(0.562); + 35.886% { + transform: translate(27.0374vw, 35.886vh) scale(0.9817); } to { - transform: translate(49.65735vw, 100vh) scale(0.562); + transform: translate(24.97045vw, 100vh) scale(0.9817); } } .snow:nth-child(199) { - opacity: 0.6774; - transform: translate(43.0086vw, -10px) scale(0.3038); - animation: fall-199 22s -11s linear infinite; + opacity: 0.0143; + transform: translate(56.9771vw, -10px) scale(0.9492); + animation: fall-199 29s -11s linear infinite; } @keyframes fall-199 { - 76.726% { - transform: translate(49.2938vw, 76.726vh) scale(0.3038); + 56.391% { + transform: translate(54.681vw, 56.391vh) scale(0.9492); } to { - transform: translate(46.1512vw, 100vh) scale(0.3038); + transform: translate(55.82905vw, 100vh) scale(0.9492); } } .snow:nth-child(200) { - opacity: 0.0632; - transform: translate(88.2415vw, -10px) scale(0.9392); - animation: fall-200 24s -14s linear infinite; + opacity: 0.5511; + transform: translate(73.2314vw, -10px) scale(0.9654); + animation: fall-200 14s -4s linear infinite; } @keyframes fall-200 { - 76.258% { - transform: translate(86.0417vw, 76.258vh) scale(0.9392); + 54.778% { + transform: translate(65.3297vw, 54.778vh) scale(0.9654); } to { - transform: translate(87.1416vw, 100vh) scale(0.9392); + transform: translate(69.28055vw, 100vh) scale(0.9654); } } \ No newline at end of file diff --git a/error-pages/403-pages/michu-it-blockpage/README.md b/error-pages/403-pages/michu-it-blockpage/README.md new file mode 100644 index 0000000..db20668 --- /dev/null +++ b/error-pages/403-pages/michu-it-blockpage/README.md @@ -0,0 +1,3 @@ +# Michu-IT blockpage + +![image](/attachments/05ffa10e-323b-4449-89c7-83a06301639b) \ No newline at end of file diff --git a/error-pages/403-pages/michu-it-blockpage/index.html b/error-pages/403-pages/michu-it-blockpage/index.html new file mode 100644 index 0000000..a51cb7d --- /dev/null +++ b/error-pages/403-pages/michu-it-blockpage/index.html @@ -0,0 +1,157 @@ + + + + + + 403 Forbidden + + + + + + + +

403

+ +

ERROR CODE: "HTTP 403 Forbidden"

+

ERROR DESCRIPTION: "Access Denied. You Do Not Have The Permission To Access This Page On This Server"

+

ERROR POSSIBLY CAUSED BY: [execute access forbidden, read access forbidden, write access forbidden, ssl required, ssl 128 required, ip address rejected, client certificate required, site access denied, too many users, invalid configuration, password change, mapper denied access, client certificate revoked, directory listing denied, client access licenses exceeded, client certificate is untrusted or invalid, client certificate has expired or is not yet valid, passport logon failed, source access denied, infinite depth is denied, too many requests from the same client ip...]

+

----------------------------

+

SOME PAGES ON THIS SERVER YOU HAVE PERMISSION TO ACCESS: [ Homepage | About Me | Contact Me... ]

CHOOSE YOUR DESIRED DESTINATION!

+
+ + + + + + diff --git a/error-pages/403-pages/redscreen-block/README.md b/error-pages/403-pages/redscreen-block/README.md new file mode 100644 index 0000000..499125c --- /dev/null +++ b/error-pages/403-pages/redscreen-block/README.md @@ -0,0 +1,3 @@ +# RedScreen Forbidden page + +![image](/attachments/ad1f54a7-6dd6-4fb0-a5d7-9b14c9813e95) \ No newline at end of file diff --git a/error-pages/403-pages/redscreen-block/index.html b/error-pages/403-pages/redscreen-block/index.html new file mode 100644 index 0000000..b21da97 --- /dev/null +++ b/error-pages/403-pages/redscreen-block/index.html @@ -0,0 +1,200 @@ + + + +Forbidden Action Detected - 403! + + + + + + + + + + + + + + + + + + 403 Forbidden!
+ +

+ An access to a restricted area has been detected and blackgate.org has been shut down to prevent damage

+ + This happens because YOU tried to access a protected area on this server. Please leave AND USE OUR SITE AS INTENDED! Thanks +

+ +

+ Every other action YOU do here is now silently logged, for the next 48h and can legally used against you! + + +

+ +

+ Technical information:

+ + *** STOP: 0x00000050 (0xFD3094C2, 0x00000001, 0xFBFE7617, 0x00000000)

+ *** root/ - 403, DateStamp 4e6b8559

+ +

+ + +

+ + + + + + + + + + + + diff --git a/error-pages/404-pages/80s-hacker-theme-404/README.md b/error-pages/404-pages/80s-hacker-theme-404/README.md index 795e6d1..55e8ce9 100644 --- a/error-pages/404-pages/80s-hacker-theme-404/README.md +++ b/error-pages/404-pages/80s-hacker-theme-404/README.md @@ -1,4 +1,3 @@ # Error 404: Page not found – 80s hacker theme - - +![image](/attachments/4ae48f9f-288d-4c1d-9a1d-5093c63a3998) \ No newline at end of file diff --git a/error-pages/404-pages/glitched-out-404/README.md b/error-pages/404-pages/glitched-out-404/README.md index 680e63c..4f09ebc 100644 --- a/error-pages/404-pages/glitched-out-404/README.md +++ b/error-pages/404-pages/glitched-out-404/README.md @@ -1,2 +1,3 @@ # 404 - Glitched out -![image](/attachments/277d2a6b-8a83-47d2-932b-fa5e7d08ff16) \ No newline at end of file + +![image](/attachments/1ad6480d-b9f3-4056-82bb-4db12c77e984) \ No newline at end of file diff --git a/error-pages/503-pages/michu-it-system-offline/README.md b/error-pages/503-pages/michu-it-system-offline/README.md new file mode 100644 index 0000000..9ae7c97 --- /dev/null +++ b/error-pages/503-pages/michu-it-system-offline/README.md @@ -0,0 +1,3 @@ +# Michu-IT system offline + +![image](/attachments/3b545851-d425-4516-9cc0-66fb4f651f47) \ No newline at end of file diff --git a/error-pages/503-pages/michu-it-system-offline/index.html b/error-pages/503-pages/michu-it-system-offline/index.html new file mode 100644 index 0000000..ac4507a --- /dev/null +++ b/error-pages/503-pages/michu-it-system-offline/index.html @@ -0,0 +1,148 @@ + + + + + + + michu-it - offline + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + System OFFLINE. + + + + diff --git a/error-pages/503-pages/page-offline-bot/README.md b/error-pages/503-pages/page-offline-bot/README.md index 15c0550..1392cd9 100644 --- a/error-pages/503-pages/page-offline-bot/README.md +++ b/error-pages/503-pages/page-offline-bot/README.md @@ -1,3 +1,3 @@ # 503 - Page is Offline (Bot) -![image](/attachments/2888530d-72a9-4bff-bf9d-f673216b1e5f) \ No newline at end of file +![image](/attachments/4a15fa37-13f5-469e-a2c2-c11094bb7a84) \ No newline at end of file diff --git a/error-pages/503-pages/page-offline-bot/style.css b/error-pages/503-pages/page-offline-bot/style.css index 0f151b1..7622157 100644 --- a/error-pages/503-pages/page-offline-bot/style.css +++ b/error-pages/503-pages/page-offline-bot/style.css @@ -7,7 +7,7 @@ body { width: 120px; left: 50%; top: 50px; - color: #000; + color: #fff; text-transform: uppercase; margin-left: -220px; line-height: 1.3em; diff --git a/error-pages/503-pages/time-to-drink-coffee/README.md b/error-pages/503-pages/time-to-drink-coffee/README.md new file mode 100644 index 0000000..1c2a5a4 --- /dev/null +++ b/error-pages/503-pages/time-to-drink-coffee/README.md @@ -0,0 +1,3 @@ +# Time to Drink Coffee Animation + +![image](/attachments/ce9c7c8c-b540-4669-8965-dce69cf852b9) \ No newline at end of file diff --git a/error-pages/503-pages/time-to-drink-coffee/index.html b/error-pages/503-pages/time-to-drink-coffee/index.html new file mode 100644 index 0000000..6696956 --- /dev/null +++ b/error-pages/503-pages/time-to-drink-coffee/index.html @@ -0,0 +1,73 @@ + + + + + Error 503 - This server is offline! + + + + + + +
+
OOH NO.. SERVER IS OFFLINE! -- 503
+
TIME TO DRINK COFFEE?
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + diff --git a/error-pages/503-pages/time-to-drink-coffee/script.js b/error-pages/503-pages/time-to-drink-coffee/script.js new file mode 100644 index 0000000..2268d59 --- /dev/null +++ b/error-pages/503-pages/time-to-drink-coffee/script.js @@ -0,0 +1,18 @@ +const tl = gsap.timeline(); + +tl.to('.stroke', { + duration: 2.5, + delay: 1.8, + strokeDashoffset: 0 }). + +to('.ripple', { + duration: 4, + delay: -2, + xPercent: -50, + yPercent: -60 }). + +to('#turbulence', { + duration: 1.5, + delay: -2, + attr: { + baseFrequency: '0 0' } }); \ No newline at end of file diff --git a/error-pages/503-pages/time-to-drink-coffee/style.css b/error-pages/503-pages/time-to-drink-coffee/style.css new file mode 100644 index 0000000..19a7e5e --- /dev/null +++ b/error-pages/503-pages/time-to-drink-coffee/style.css @@ -0,0 +1,105 @@ +body { + background-color: #232f3a; + height: 100vh; + display: grid; + place-items: center; +} +body .draw-box { + overflow: hidden; + position: relative; + margin-top: 60px; + width: 335px; +} +body .draw-box .typewriter-effect { + overflow: hidden; + -webkit-animation: typingEffect 1.6s steps(22) forwards, blinkTextCursorRed 1s 1.7s; + animation: typingEffect 1.6s steps(22) forwards, blinkTextCursorRed 1s 1.7s; + width: 0; + color: #ff8686; + height: 19px; + margin-bottom: 6px; + font-size: 22px; + white-space: nowrap; + vertical-align: middle; + line-height: 0.9; + font-family: "Barlow Semi Condensed", sans-serif; +} +body .draw-box .typewriter-effect2 { + overflow: hidden; + -webkit-animation: typingEffect 1.6s steps(22) forwards 1.7s, blinkTextCursor 1s infinite 1.7s; + animation: typingEffect 1.6s steps(22) forwards 1.7s, blinkTextCursor 1s infinite 1.7s; + width: 0; + color: #e8e8e8; + height: 30px; + font-size: 34px; + white-space: nowrap; + vertical-align: middle; + line-height: 0.9; + font-family: "Barlow Semi Condensed", sans-serif; +} +@-webkit-keyframes typingEffect { + from { + width: 0; + } + to { + width: 98%; + } +} +@keyframes typingEffect { + from { + width: 0; + } + to { + width: 98%; + } +} +@-webkit-keyframes blinkTextCursor { + from { + border-right: 3px solid #f8f8f8; + } + to { + border-right: transparent; + } +} +@keyframes blinkTextCursor { + from { + border-right: 3px solid #f8f8f8; + } + to { + border-right: transparent; + } +} +@-webkit-keyframes blinkTextCursorRed { + from { + border-right: 3px solid #ff8686; + } + to { + border-right: transparent; + } +} +@keyframes blinkTextCursorRed { + from { + border-right: 3px solid #ff8686; + } + to { + border-right: transparent; + } +} +body .draw-box svg { + width: 93%; + margin-top: 10px; +} +body .draw-box svg .stroke { + fill: none; + stroke: #e8e8e8; + stroke-width: 0.8; +} +body .draw-box svg .coffeeColor { + fill: #b59440; +} +body .draw-box svg .steamColor { + fill: #ddd; +} +body .draw-box svg .ripple { + transform: translate3d(-30%, 100%, 0); +} \ No newline at end of file diff --git a/forms-and-login-pages/contact-form-blackboard/README.md b/forms-and-login-pages/contact-form-blackboard/README.md index ad7fadc..700d676 100644 --- a/forms-and-login-pages/contact-form-blackboard/README.md +++ b/forms-and-login-pages/contact-form-blackboard/README.md @@ -1,2 +1,3 @@ # Blackboard Contact Form -![image](/attachments/f9f7e294-b0f9-41a2-b372-7f80c732f0b5) \ No newline at end of file + +![image](/attachments/a052b075-a959-4c67-977b-4154eca4a9c8) \ No newline at end of file diff --git a/forms-and-login-pages/login-form-modern/README.md b/forms-and-login-pages/login-form-modern/README.md index 0e55e37..1d68dea 100644 --- a/forms-and-login-pages/login-form-modern/README.md +++ b/forms-and-login-pages/login-form-modern/README.md @@ -1,3 +1,3 @@ # Modern Login Form with floating placeholder and light button - +![image](/attachments/b4da4554-ccdd-47cd-8c59-3f295f13115d) \ No newline at end of file diff --git a/forms-and-login-pages/login-form-simple/README.md b/forms-and-login-pages/login-form-simple/README.md index 56c34a9..b2b8777 100644 --- a/forms-and-login-pages/login-form-simple/README.md +++ b/forms-and-login-pages/login-form-simple/README.md @@ -1,2 +1,3 @@ # Login Form -![image](/attachments/39ded713-ee72-40cb-adac-78ebe26ded7b) \ No newline at end of file + +![image](/attachments/8d6fb567-cdff-44bf-bc0e-cc771604e596) \ No newline at end of file diff --git a/layout-techniques/layouting-with-css-grid/README.md b/layout-techniques/layouting-with-css-grid/README.md new file mode 100644 index 0000000..900611a --- /dev/null +++ b/layout-techniques/layouting-with-css-grid/README.md @@ -0,0 +1,11 @@ +# Layouting with CSS Grid + +A quick exercise exploring essential layout template setup using CSS Grid and bare minimum DOM. + +For more reasons to love grid, check out this article: +https://moderncss.dev/3-css-grid-techniques-to-make-you-a-grid-convert/ + +Or additional articles that cover grid: +https://moderncss.dev/topics/#grid + +![image](/attachments/acbdf915-2405-490f-9063-010a1a28e9ba) \ No newline at end of file diff --git a/layout-techniques/layouting-with-css-grid/index.html b/layout-techniques/layouting-with-css-grid/index.html new file mode 100644 index 0000000..d0c939b --- /dev/null +++ b/layout-techniques/layouting-with-css-grid/index.html @@ -0,0 +1,48 @@ + + + + + Layouting with CSS Grid + + + + + + + + 1 + 2 + + + + 1 + 2 + + + + 1 + 2 + 3 + + + + 1 + 2 + 3 + 4 + + + + 1 + 2 + 3 + + + + 1 + 2 + 3 + + + + diff --git a/layout-techniques/layouting-with-css-grid/style.css b/layout-techniques/layouting-with-css-grid/style.css new file mode 100644 index 0000000..468c3a3 --- /dev/null +++ b/layout-techniques/layouting-with-css-grid/style.css @@ -0,0 +1,55 @@ +* { + box-sizing: border-box; +} + +span { + background: #fff; + padding: 1rem; + border-radius: 7px; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.13); + height: 30vh; + display: grid; + grid-gap: 0.5rem; +} +span b { + background-color: #7B86F5; + border-radius: 4px; + display: grid; + place-items: center; + color: #fff; + font-size: 1.5rem; +} +span.template-2col { + grid-template-columns: repeat(2, 1fr); +} +span.template-3col { + grid-template-columns: repeat(3, 1fr); +} +span.template-4up { + grid-template: repeat(2, 1fr)/repeat(2, 1fr); +} +span.template-sidebar--left { + grid-template: "sidebar mainA" "sidebar mainB"; +} +span.template-sidebar--left > :nth-child(1) { + grid-area: sidebar; +} +span.template-sidebar--right { + grid-template: "mainA sidebar" "mainB sidebar"; +} +span.template-sidebar--right > :nth-child(3) { + grid-area: sidebar; +} + +body { + background: #f9f9f9; + min-height: 100vh; + display: grid; + grid-template-columns: repeat(auto-fit, 30ch); + place-content: center; + grid-gap: 5vh; + max-width: calc((30ch * 3) + (5vh * 2) + 2rem); + margin-left: auto; + margin-right: auto; + padding: 1rem; +} \ No newline at end of file diff --git a/web-snippets/random-password-generator/README.md b/web-snippets/random-password-generator/README.md new file mode 100644 index 0000000..99daf33 --- /dev/null +++ b/web-snippets/random-password-generator/README.md @@ -0,0 +1,3 @@ +# Random Password Generator - HTML | CSS | JS + +![image](/attachments/2116d7c3-e52b-4c37-ba64-9f9dddc278bf) \ No newline at end of file diff --git a/web-snippets/random-password-generator/index.html b/web-snippets/random-password-generator/index.html new file mode 100644 index 0000000..0c5f277 --- /dev/null +++ b/web-snippets/random-password-generator/index.html @@ -0,0 +1,52 @@ + + + + + Random Password Generator + + + + + + +
+

Password Generator

+
+
Generated Password
+
click to copy
+
copied
+
CLICK GENERATE
+ +
+
+
length:
+ +
+ +
+ settings +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + + + + diff --git a/web-snippets/random-password-generator/script.js b/web-snippets/random-password-generator/script.js new file mode 100644 index 0000000..aad7a8f --- /dev/null +++ b/web-snippets/random-password-generator/script.js @@ -0,0 +1,194 @@ +// This is a simple Password Generator App that will generate random password maybe you can you them to secure your account. +// I tried my best to make the code as simple as possible please dont mind the variable names. +// Also this idea came in my mind after checking Traversy Media's latest video. + +// Clear the concole on every refresh +console.clear(); +// set the body to full height +// document.body.style.height = `${innerHeight}px` + +// Range Slider Properties. +// Fill : The trailing color that you see when you drag the slider. +// background : Default Range Slider Background +const sliderProps = { + fill: "#0B1EDF", + background: "rgba(255, 255, 255, 0.214)", +}; + +// Selecting the Range Slider container which will effect the LENGTH property of the password. +const slider = document.querySelector(".range__slider"); + +// Text which will show the value of the range slider. +const sliderValue = document.querySelector(".length__title"); + +// Using Event Listener to apply the fill and also change the value of the text. +slider.querySelector("input").addEventListener("input", event => { + sliderValue.setAttribute("data-length", event.target.value); + applyFill(event.target); +}); +// Selecting the range input and passing it in the applyFill func. +applyFill(slider.querySelector("input")); +// This function is responsible to create the trailing color and setting the fill. +function applyFill(slider) { + const percentage = (100 * (slider.value - slider.min)) / (slider.max - slider.min); + const bg = `linear-gradient(90deg, ${sliderProps.fill} ${percentage}%, ${sliderProps.background} ${percentage + + 0.1}%)`; + slider.style.background = bg; + sliderValue.setAttribute("data-length", slider.value); +} + +// Object of all the function names that we will use to create random letters of password +const randomFunc = { + lower: getRandomLower, + upper: getRandomUpper, + number: getRandomNumber, + symbol: getRandomSymbol, +}; + +// Random more secure value +function secureMathRandom() { + return window.crypto.getRandomValues(new Uint32Array(1))[0] / (Math.pow(2, 32) - 1); +} + +// Generator Functions +// All the functions that are responsible to return a random value taht we will use to create password. +function getRandomLower() { + return String.fromCharCode(Math.floor(Math.random() * 26) + 97); +} +function getRandomUpper() { + return String.fromCharCode(Math.floor(Math.random() * 26) + 65); +} +function getRandomNumber() { + return String.fromCharCode(Math.floor(secureMathRandom() * 10) + 48); +} +function getRandomSymbol() { + const symbols = '~!@#$%^&*()_+{}":?><;.,'; + return symbols[Math.floor(Math.random() * symbols.length)]; +} + +// Selecting all the DOM Elements that are necessary --> + +// The Viewbox where the result will be shown +const resultEl = document.getElementById("result"); +// The input slider, will use to change the length of the password +const lengthEl = document.getElementById("slider"); + +// Checkboxes representing the options that is responsible to create differnt type of password based on user +const uppercaseEl = document.getElementById("uppercase"); +const lowercaseEl = document.getElementById("lowercase"); +const numberEl = document.getElementById("number"); +const symbolEl = document.getElementById("symbol"); + +// Button to generate the password +const generateBtn = document.getElementById("generate"); +// Button to copy the text +const copyBtn = document.getElementById("copy-btn"); +// Result viewbox container +const resultContainer = document.querySelector(".result"); +// Text info showed after generate button is clicked +const copyInfo = document.querySelector(".result__info.right"); +// Text appear after copy button is clicked +const copiedInfo = document.querySelector(".result__info.left"); + +// if this variable is trye only then the copyBtn will appear, i.e. when the user first click generate the copyBth will interact. +let generatedPassword = false; + +// Update Css Props of the COPY button +// Getting the bounds of the result viewbox container +let resultContainerBound = { + left: resultContainer.getBoundingClientRect().left, + top: resultContainer.getBoundingClientRect().top, +}; +// This will update the position of the copy button based on mouse Position +resultContainer.addEventListener("mousemove", e => { + resultContainerBound = { + left: resultContainer.getBoundingClientRect().left, + top: resultContainer.getBoundingClientRect().top, + }; + if(generatedPassword){ + copyBtn.style.opacity = '1'; + copyBtn.style.pointerEvents = 'all'; + copyBtn.style.setProperty("--x", `${e.x - resultContainerBound.left}px`); + copyBtn.style.setProperty("--y", `${e.y - resultContainerBound.top}px`); + }else{ + copyBtn.style.opacity = '0'; + copyBtn.style.pointerEvents = 'none'; + } +}); +window.addEventListener("resize", e => { + resultContainerBound = { + left: resultContainer.getBoundingClientRect().left, + top: resultContainer.getBoundingClientRect().top, + }; +}); + +// Copy Password in clipboard +copyBtn.addEventListener("click", () => { + const textarea = document.createElement("textarea"); + const password = resultEl.innerText; + if (!password || password == "CLICK GENERATE") { + return; + } + textarea.value = password; + document.body.appendChild(textarea); + textarea.select(); + document.execCommand("copy"); + textarea.remove(); + + copyInfo.style.transform = "translateY(200%)"; + copyInfo.style.opacity = "0"; + copiedInfo.style.transform = "translateY(0%)"; + copiedInfo.style.opacity = "0.75"; +}); + +// When Generate is clicked Password id generated. +generateBtn.addEventListener("click", () => { + const length = +lengthEl.value; + const hasLower = lowercaseEl.checked; + const hasUpper = uppercaseEl.checked; + const hasNumber = numberEl.checked; + const hasSymbol = symbolEl.checked; + generatedPassword = true; + resultEl.innerText = generatePassword(length, hasLower, hasUpper, hasNumber, hasSymbol); + copyInfo.style.transform = "translateY(0%)"; + copyInfo.style.opacity = "0.75"; + copiedInfo.style.transform = "translateY(200%)"; + copiedInfo.style.opacity = "0"; +}); + +// Function responsible to generate password and then returning it. +function generatePassword(length, lower, upper, number, symbol) { + let generatedPassword = ""; + const typesCount = lower + upper + number + symbol; + const typesArr = [{ lower }, { upper }, { number }, { symbol }].filter(item => Object.values(item)[0]); + if (typesCount === 0) { + return ""; + } + for (let i = 0; i < length; i++) { + typesArr.forEach(type => { + const funcName = Object.keys(type)[0]; + generatedPassword += randomFunc[funcName](); + }); + } + return generatedPassword.slice(0, length) + .split('').sort(() => Math.random() - 0.5) + .join(''); +} + +// function that handles the checkboxes state, so at least one needs to be selected. The last checkbox will be disabled. +function disableOnlyCheckbox(){ + let totalChecked = [uppercaseEl, lowercaseEl, numberEl, symbolEl].filter(el => el.checked) + totalChecked.forEach(el => { + if(totalChecked.length == 1){ + el.disabled = true; + }else{ + el.disabled = false; + } + }) +} + +[uppercaseEl, lowercaseEl, numberEl, symbolEl].forEach(el => { + el.addEventListener('click', () => { + disableOnlyCheckbox() + }) +}) \ No newline at end of file diff --git a/web-snippets/random-password-generator/style.css b/web-snippets/random-password-generator/style.css new file mode 100644 index 0000000..2ea9de9 --- /dev/null +++ b/web-snippets/random-password-generator/style.css @@ -0,0 +1,297 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + width: 100%; + height: 100vh; + background-image: linear-gradient(to top, #dadada 100%, #383333 200%); + display: flex; + justify-content: center; + align-items: center; +} + +button { + border: 0; + outline: 0; +} + +.container { + margin: 40px 0; + width: 400px; + height: 600px; + padding: 10px 25px; + background: #0a0e31; + border-radius: 10px; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.45), 0 4px 8px rgba(0, 0, 0, 0.35), 0 8px 12px rgba(0, 0, 0, 0.15); + font-family: "Montserrat"; +} +.container h2.title { + font-size: 1.75rem; + margin: 10px -5px; + margin-bottom: 30px; + color: #fff; +} + +.result { + position: relative; + width: 100%; + height: 65px; + overflow: hidden; +} +.result__info { + position: absolute; + bottom: 4px; + color: #fff; + font-size: 0.8rem; + transition: all 150ms ease-in-out; + transform: translateY(200%); + opacity: 0; +} +.result__info.right { + right: 8px; +} +.result__info.left { + left: 8px; +} +.result__viewbox { + width: 100%; + height: 100%; + background: rgba(255, 255, 255, 0.08); + border-radius: 8px; + color: #fff; + text-align: center; + line-height: 65px; +} +.result #copy-btn { + position: absolute; + top: var(--y); + left: var(--x); + width: 38px; + height: 38px; + background: #fff; + border-radius: 50%; + opacity: 0; + transform: translate(-50%, -50%) scale(0); + transition: all 350ms cubic-bezier(0.175, 0.885, 0.32, 1.275); + cursor: pointer; + z-index: 2; +} +.result #copy-btn:active { + box-shadow: 0 0 0 200px rgba(255, 255, 255, 0.08); +} +.result:hover #copy-btn { + opacity: 1; + transform: translate(-50%, -50%) scale(1.35); +} + +.field-title { + position: absolute; + top: -10px; + left: 8px; + transform: translateY(-50%); + font-weight: 800; + color: rgba(255, 255, 255, 0.5); + text-transform: uppercase; + font-size: 0.65rem; + pointer-events: none; + user-select: none; +} + +.options { + width: 100%; + height: auto; + margin: 50px 0; +} + +.range__slider { + position: relative; + width: 100%; + height: calc(65px - 10px); + display: flex; + justify-content: center; + align-items: center; + background: rgba(255, 255, 255, 0.08); + border-radius: 8px; + margin: 30px 0; +} +.range__slider::before, .range__slider::after { + position: absolute; + color: #fff; + font-size: 0.9rem; + font-weight: bold; +} +.range__slider::before { + content: attr(data-min); + left: 10px; +} +.range__slider::after { + content: attr(data-max); + right: 10px; +} +.range__slider .length__title::after { + content: attr(data-length); + position: absolute; + right: -16px; + font-variant-numeric: tabular-nums; + color: #fff; +} + +#slider { + -webkit-appearance: none; + width: calc(100% - (70px)); + height: 2px; + border-radius: 5px; + background: rgba(255, 255, 255, 0.314); + outline: none; + padding: 0; + margin: 0; + cursor: pointer; +} +#slider::-webkit-slider-thumb { + -webkit-appearance: none; + width: 20px; + height: 20px; + border-radius: 50%; + background: white; + cursor: pointer; + transition: all 0.15s ease-in-out; +} +#slider::-webkit-slider-thumb:hover { + background: #d4d4d4; + transform: scale(1.2); +} +#slider::-moz-range-thumb { + width: 20px; + height: 20px; + border: 0; + border-radius: 50%; + background: white; + cursor: pointer; + transition: background 0.15s ease-in-out; +} +#slider::-moz-range-thumb:hover { + background: #d4d4d4; +} + +.settings { + position: relative; + height: auto; + widows: 100%; + display: flex; + flex-direction: column; +} +.settings .setting { + position: relative; + width: 100%; + height: calc(65px - 10px); + background: rgba(255, 255, 255, 0.08); + border-radius: 8px; + display: flex; + align-items: center; + padding: 10px 25px; + color: #fff; + margin-bottom: 8px; +} +.settings .setting input { + opacity: 0; + position: absolute; +} +.settings .setting input + label { + user-select: none; +} +.settings .setting input + label::before, .settings .setting input + label::after { + content: ""; + position: absolute; + transition: 150ms cubic-bezier(0.24, 0, 0.5, 1); + transform: translateY(-50%); + top: 50%; + right: 10px; + cursor: pointer; +} +.settings .setting input + label::before { + height: 30px; + width: 50px; + border-radius: 30px; + background: rgba(214, 214, 214, 0.434); +} +.settings .setting input + label::after { + height: 24px; + width: 24px; + border-radius: 60px; + right: 32px; + background: #fff; +} +.settings .setting input:checked + label:before { + background: #5d68e2; + transition: all 150ms cubic-bezier(0, 0, 0, 0.1); +} +.settings .setting input:checked + label:after { + right: 14px; +} +.settings .setting input:focus + label:before { + box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.75); +} +.settings .setting input:disabled + label:before, .settings .setting input:disabled + label:after { + cursor: not-allowed; +} +.settings .setting input:disabled + label:before { + background: #4f4f6a; +} +.settings .setting input:disabled + label:after { + background: #909090; +} + +.btn.generate { + user-select: none; + position: relative; + width: 100%; + height: 50px; + margin: 10px 0; + border-radius: 8px; + color: #fff; + border: none; + background-image: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + letter-spacing: 1px; + font-weight: bold; + text-transform: uppercase; + cursor: pointer; + transition: all 150ms ease; +} +.btn.generate:active { + transform: translateY(-3%); + box-shadow: 0 4px 8px rgba(255, 255, 255, 0.08); +} + +.support { + position: fixed; + right: 10px; + bottom: 10px; + padding: 10px; + display: flex; +} + +a { + margin: 0 20px; + color: #fff; + font-size: 2rem; + transition: all 400ms ease; +} + +a:hover { + color: #222; +} + +@keyframes octocat-wave { + 0%, 100% { + transform: rotate(0); + } + 20%, 60% { + transform: rotate(-20deg); + } + 40%, 80% { + transform: rotate(10deg); + } +} \ No newline at end of file