SuperShipped // Item 07

SNIPPET VIEW

Live Render

HTML CODE

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Grand Expansive Auth - Validation</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <style>
        :root {
            --bg-dark: #020202;
            --glass-bg: rgba(18, 18, 18, 0.7);
            --accent-blue: #3897f0;
            --accent-green: #34d399;
            --accent-red: #ff4b4b;
            --border-light: rgba(255, 255, 255, 0.08);
            --text-main: #ffffff;
            --text-dim: #a1a1aa;
        }

        body, html {
            margin: 0; padding: 0;
            width: 100%; height: 100%;
            background-color: var(--bg-dark);
            font-family: 'Inter', -apple-system, sans-serif;
            display: flex; justify-content: center; align-items: center;
            overflow: hidden;
            perspective: 1200px;
        }

        #bg-canvas { position: fixed; top: 0; left: 0; z-index: 0; }

        .auth-card {
            position: relative; z-index: 10;
            width: 380px;
            background: var(--glass-bg);
            backdrop-filter: blur(60px);
            -webkit-backdrop-filter: blur(60px);
            border: 1px solid var(--border-light);
            border-radius: 40px;
            padding: 50px;
            box-shadow: 0 60px 120px rgba(0,0,0,1);
            text-align: center;
            transition: transform 0.15s ease-out;
            transform-style: preserve-3d;
            will-change: transform;
        }

        /* Error Shake Animation */
        @keyframes shake {
            0%, 100% { transform: translateX(0); }
            20%, 60% { transform: translateX(-10px); }
            40%, 80% { transform: translateX(10px); }
        }
        .card-error { animation: shake 0.4s cubic-bezier(.36,.07,.19,.97) both; }

        h2 { margin: 0 0 8px 0; font-size: 32px; font-weight: 700; color: #fff; letter-spacing: -1px; }
        p.subtitle { color: var(--text-dim); font-size: 15px; margin-bottom: 40px; }

        .form-container { position: relative; min-height: 260px; }
        .auth-form {
            position: absolute; width: 100%; top: 0; left: 0;
            transition: all 0.6s cubic-bezier(0.23, 1, 0.32, 1);
            opacity: 0; pointer-events: none; transform: translateY(30px);
        }
        .auth-form.active { opacity: 1; pointer-events: all; transform: translateY(0); }

        .input-group { margin-bottom: 22px; text-align: left; }
        label { display: block; font-size: 11px; color: var(--text-dim); margin-bottom: 8px; letter-spacing: 1.2px; text-transform: uppercase; font-weight: 700; }
        input {
            width: 100%; padding: 16px; background: rgba(255, 255, 255, 0.04);
            border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 16px;
            color: white; font-size: 16px; box-sizing: border-box; outline: none; transition: 0.3s;
        }
        input:focus { border-color: var(--accent-blue); background: rgba(255, 255, 255, 0.07); }
        input.error { border-color: var(--accent-red); }

        .btn-primary {
            width: 100%; padding: 18px; margin-top: 10px;
            background: var(--accent-blue); color: white; border: none; border-radius: 16px;
            font-size: 16px; font-weight: 600; cursor: pointer; transition: 0.4s;
            display: flex; justify-content: center; align-items: center;
        }

        .btn-primary.loading { background: var(--accent-green); pointer-events: none; }
        .btn-primary.loading-error { background: var(--accent-red); pointer-events: none; }
        
        .btn-primary.loading::after, .btn-primary.loading-error::after {
            content: ""; width: 22px; height: 22px;
            border: 3px solid rgba(255,255,255,0.2);
            border-top-color: #fff; border-radius: 50%;
            animation: spin 1s linear infinite;
        }
        @keyframes spin { to { transform: rotate(360deg); } }

        .footer-link { margin-top: 35px; font-size: 14px; color: var(--text-dim); }
        .footer-link span { color: var(--accent-blue); cursor: pointer; font-weight: 600; }
    </style>
</head>
<body>

    <canvas id="bg-canvas"></canvas>

    <div class="auth-card" id="card">
        <h2 id="title">Welcome back</h2>
        <p class="subtitle" id="subtitle">Connect to your secure dashboard.</p>

        <div class="form-container">
            <div class="auth-form active" id="loginForm">
                <div class="input-group">
                    <label>Account Email</label>
                    <input type="email" id="loginEmail" placeholder="you@example.com">
                </div>
                <div class="input-group">
                    <label>Security Key</label>
                    <input type="password" id="loginPass" placeholder="••••••••">
                </div>
                <button class="btn-primary" onclick="validateAndSubmit('loginForm')">
                    <span class="btn-text">Authenticate</span>
                </button>
            </div>

            <div class="auth-form" id="signupForm">
                <div class="input-group">
                    <label>Full Name</label>
                    <input type="text" id="regName" placeholder="Alex Morgan">
                </div>
                <div class="input-group">
                    <label>Account Email</label>
                    <input type="email" id="regEmail" placeholder="you@example.com">
                </div>
                <div class="input-group">
                    <label>Security Key</label>
                    <input type="password" id="regPass" placeholder="••••••••">
                </div>
                <button class="btn-primary" onclick="validateAndSubmit('signupForm')">
                    <span class="btn-text">Get Started</span>
                </button>
            </div>
        </div>

        <div class="footer-link" id="toggleText">
            New here? <span onclick="toggleAuth(true)">Create account</span>
        </div>
    </div>

    <script>
        const canvas = document.getElementById('bg-canvas');
        const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 2000);
        camera.position.z = 22;

        const particlesCount = 18000;
        const positions = new Float32Array(particlesCount * 3);
        const randomOffsets = new Float32Array(particlesCount);

        for (let i = 0; i < particlesCount; i++) {
            const ringIndex = Math.floor(i / 1200) + 1;
            const radius = ringIndex * 5.5; 
            const angle = (i % 1200) / 1200 * Math.PI * 2;
            positions[i * 3] = Math.cos(angle) * radius;
            positions[i * 3 + 1] = Math.sin(angle) * radius;
            positions[i * 3 + 2] = (Math.random() - 0.5) * 3.0;
            randomOffsets[i] = Math.random();
        }

        const geometry = new THREE.BufferGeometry();
        geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        geometry.setAttribute('randomOffset', new THREE.BufferAttribute(randomOffsets, 1));

        const material = new THREE.ShaderMaterial({
            uniforms: { 
                uTime: { value: 0 }, 
                uWaveActive: { value: 0.0 },
                uIsError: { value: 0.0 }
            },
            vertexShader: `
                uniform float uTime;
                uniform float uWaveActive;
                attribute float randomOffset;
                varying float vColorMix;
                varying float vOpacity;

                void main() {
                    vec3 pos = position;
                    float dist = length(pos.xy);
                    pos.xy += sin(uTime * 0.1 + randomOffset * 6.28) * 0.12;
                    float wave = 0.0;
                    if (uWaveActive > 0.5) {
                        float pulse = sin(dist * 0.15 - uTime * 5.0);
                        wave = smoothstep(0.3, 1.0, pulse);
                    }
                    vColorMix = wave;
                    vec4 mvPos = modelViewMatrix * vec4(pos, 1.0);
                    gl_PointSize = (2.2 + vColorMix * 5.5) * (15.0 / -mvPos.z);
                    gl_Position = projectionMatrix * mvPos;
                    vOpacity = smoothstep(90.0, 5.0, dist);
                }
            `,
            fragmentShader: `
                uniform float uIsError;
                varying float vColorMix;
                varying float vOpacity;
                void main() {
                    if (distance(gl_PointCoord, vec2(0.5)) > 0.5) discard;
                    vec3 blueCol = vec3(0.3, 0.4, 0.55);
                    vec3 successCol = vec3(0.2, 1.0, 0.45);
                    vec3 errorCol = vec3(1.0, 0.2, 0.2);
                    
                    vec3 activeCol = mix(successCol, errorCol, uIsError);
                    vec3 color = mix(blueCol, activeCol, vColorMix);
                    gl_FragColor = vec4(color, vOpacity * 0.5);
                }
            `,
            transparent: true, blending: THREE.AdditiveBlending
        });

        const points = new THREE.Points(geometry, material);
        scene.add(points);

        function resize() {
            renderer.setSize(window.innerWidth, window.innerHeight);
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
        }
        window.addEventListener('resize', resize);
        resize();

        // VALIDATION LOGIC
        function validateAndSubmit(formId) {
            const form = document.getElementById(formId);
            const inputs = form.querySelectorAll('input');
            const btn = form.querySelector('.btn-primary');
            const card = document.getElementById('card');
            let isValid = true;

            inputs.forEach(input => {
                if (!input.value.trim()) {
                    isValid = false;
                    input.classList.add('error');
                } else {
                    input.classList.remove('error');
                }
            });

            if (!isValid) {
                // RED WAVE & SHAKE
                material.uniforms.uIsError.value = 1.0;
                material.uniforms.uWaveActive.value = 1.0;
                btn.classList.add('loading-error');
                card.classList.add('card-error');

                setTimeout(() => {
                    material.uniforms.uWaveActive.value = 0.0;
                    btn.classList.remove('loading-error');
                    card.classList.remove('card-error');
                }, 3000);
            } else {
                // GREEN WAVE
                material.uniforms.uIsError.value = 0.0;
                material.uniforms.uWaveActive.value = 1.0;
                btn.classList.add('loading');

                setTimeout(() => {
                    material.uniforms.uWaveActive.value = 0.0;
                    btn.classList.remove('loading');
                    alert("Authenticated Successfully!");
                }, 3000);
            }
        }

        function toggleAuth(isSignup) {
            const loginForm = document.getElementById('loginForm');
            const signupForm = document.getElementById('signupForm');
            const title = document.getElementById('title');
            const toggleText = document.getElementById('toggleText');

            if (isSignup) {
                loginForm.classList.remove('active');
                setTimeout(() => signupForm.classList.add('active'), 100);
                title.innerText = "Create Account";
                toggleText.innerHTML = `Member? <span onclick="toggleAuth(false)">Sign in</span>`;
            } else {
                signupForm.classList.remove('active');
                setTimeout(() => loginForm.classList.add('active'), 100);
                title.innerText = "Welcome back";
                toggleText.innerHTML = `New here? <span onclick="toggleAuth(true)">Create account</span>`;
            }
        }

        function animate(time) {
            material.uniforms.uTime.value = time * 0.001;
            points.rotation.z += 0.00008;
            renderer.render(scene, camera);
            requestAnimationFrame(animate);
        }
        requestAnimationFrame(animate);

        document.addEventListener('mousemove', (e) => {
            const mX = (e.clientX / window.innerWidth) * 2 - 1;
            const mY = -(e.clientY / window.innerHeight) * 2 + 1;
            document.getElementById('card').style.transform = `rotateX(${mY * 10}deg) rotateY(${mX * 10}deg)`;
        });
    </script>
</body>
</html>

AI PROMPT

Create a "Grand Expansive Auth - Validation" component. Use Three.js for 3D WebGL rendering. Implement custom GLSL shaders for visual effects. Apply keyframe animations, glass-morphism / backdrop blur, 3D CSS perspective, layered shadows. Color palette: #020202, #3897f0, #34d399, #ff4b4b, #ffffff, #a1a1aa. Layout: Flexbox, full-screen fixed canvas background. Interactivity: mouse tracking, click interactions, continuous animation loop, responsive resize handling. Includes form input fields. Render a particle system effect.