AquaStudios Intro
by Sharxxy
HTML
<div class="intro-root" id="intro">
<div class="vignette"></div>
<div class="rays"></div>
<div class="ripple" id="ripple"></div>
<canvas id="bubbles"></canvas>
<div class="logo-wrap">
<!-- Wave sweep in front of the logo -->
<div class="wave-mask">
<div class="wave" id="wave">
<svg viewBox="0 0 1440 320" preserveAspectRatio="none" aria-hidden>
<defs>
<linearGradient id="waveGrad" x1="0" x2="1" y1="0" y2="0">
<stop offset="0%" stop-color="#53d3f3" stop-opacity="0.0"/>
<stop offset="30%" stop-color="#53d3f3" stop-opacity="0.6"/>
<stop offset="70%" stop-color="#47b0f0" stop-opacity="0.8"/>
<stop offset="100%" stop-color="#0ea5e9" stop-opacity="0.0"/>
</linearGradient>
</defs>
<path d="M0,192L60,197.3C120,203,240,213,360,213.3C480,213,600,203,720,176C840,149,960,107,1080,117.3C1200,128,1320,192,1380,224L1440,256L1440,0L1380,0C1320,0,1200,0,1080,0C960,0,840,0,720,0C600,0,480,0,360,0C240,0,120,0,60,0L0,0Z" fill="url(#waveGrad)"/>
</svg>
</div>
</div>
<!-- AQUASTUDIOS LOGO (stroke draw + fill) -->
<div class="logo" aria-label="AquaStudios">
<svg viewBox="0 0 1200 280" role="img">
<defs>
<linearGradient id="aquaGrad" x1="0" x2="1">
<stop offset="0%" stop-color="#a0f0ff"/>
<stop offset="50%" stop-color="#53d3f3"/>
<stop offset="100%" stop-color="#47b0f0"/>
</linearGradient>
<filter id="gel">
<feGaussianBlur in="SourceGraphic" stdDeviation="1.2" result="b"/>
<feMerge>
<feMergeNode in="b"/><feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Stylised rounded logotype drawn with paths (quick custom type) -->
<g...
CSS
/* -----------------------------
AQUASTUDIOS INTRO - STYLES
(Single-file demo; you can split into styles.css later)
------------------------------ */
:root{
--bg-deep:#03121c;
--bg-deeper:#010b11;
--aqua:#53d3f3;
--cyan:#47b0f0;
--white:#e9f7ff;
}
*{box-sizing:border-box}
html,body{height:100%;}
body{
margin:0; background:radial-gradient(1200px 800px at 50% 20%, #072639 0%, var(--bg-deep) 35%, var(--bg-deeper) 100%);
color:var(--white); font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
overflow:hidden;
}
/* Container */
.intro-root{
position:fixed; inset:0; display:grid; place-items:center; isolation:isolate;
}
/* Subtle vignette */
.vignette{position:absolute; inset:-10%; pointer-events:none; z-index:1;
background:radial-gradient(80% 60% at 50% 40%, transparent 0% 60%, rgba(0,0,0,.4) 100%);
}
/* God rays */
.rays{position:absolute; inset:0; overflow:hidden; z-index:2; mix-blend-mode:screen; opacity:.25;}
.rays::before{content:""; position:absolute; inset:-50% -20% -20% -20%;
background: conic-gradient(from 200deg, rgba(83,211,243,.18), rgba(83,211,243,0) 20% 60%, rgba(83,211,243,.18));
filter: blur(12px);
transform: rotate(-12deg) translateY(-8%);
animation: sway 10s ease-in-out infinite alternate;
}
@keyframes sway{to{transform: rotate(8deg) translateY(6%);}}
/* Water surface ripple opening */
.ripple{
position:absolute; inset:0; z-index:3; pointer-events:none; opacity:0;
background: radial-gradient(ellipse at 50% 30%, rgba(83,211,243,.35) 0 2%, rgba(83,211,243,.15) 3%, rgba(83,211,243,0) 25%);
transform: scale(0.6);
transition: opacity 1200ms ease, transform 1800ms ease;
}
.ripple.active{opacity:1; transform: scale(1.4);}
...
JavaScript
/* -----------------------------
AQUASTUDIOS INTRO - SCRIPT
(Single-file demo; you can split into app.js later)
------------------------------ */
const intro = document.getElementById('intro');
const canvas = document.getElementById('bubbles');
const ctx = canvas.getContext('2d');
const wave = document.getElementById('wave');
const ripple = document.getElementById('ripple');
const flash = document.getElementById('flash');
const fadeout = document.getElementById('fadeout');
const skipBtn = document.getElementById('skipBtn');
// Resize canvas to full viewport
function fit(){
const dpr = Math.min(window.devicePixelRatio || 1, 2);
const {innerWidth:w, innerHeight:h} = window;
canvas.width = Math.floor(w * dpr);
canvas.height = Math.floor(h * dpr);
canvas.style.width = w + 'px';
canvas.style.height = h + 'px';
ctx.setTransform(dpr,0,0,dpr,0,0);
}
window.addEventListener('resize', fit); fit();
// Bubble particles
const bubbles = [];
const MAX = 140;
function spawn(){
if (bubbles.length > MAX) return;
const x = Math.random()*window.innerWidth;
const r = Math.random()*3+1.2;
const y = window.innerHeight + r + Math.random()*100;
const s = Math.random()*0.6 + 0.3; // speed
const drift = (Math.random() - 0.5) * 0.6;
bubbles.push({x,y,r,s,drift,alpha: Math.random()*0.35+0.25});
}
// Caustic shimmer
let t = 0;
function draw(){
t += 0.016;
ctx.clearRect(0,0,canvas.width,canvas.height);
// subtle caustics
const g = ctx.createLinearGradient(0,0,0,canvas.height);
g.addColorStop(0, 'rgba(83,211,243,0.08)');
g.addColorStop(1, 'rgba(83,211,243,0.0)');
ctx.fillStyle = g;
const bars = 10;
for(let i=0;i<bars;i++){
const y = (i/bars)*canvas.height + Math.sin(t*0.6 + i)*8;
...