SuperShipped // Item 11

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, maximum-scale=1.0, user-scalable=no">
    <title>AI Grid - Geist Color Lab</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/geist@1.3.0/dist/fonts/geist.css">
    <style>
        :root {
            --bg-dark: #070707;
            --corner-radius: 45px;
            --grid-gap: 12px;
        }

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

        .grid-wrapper {
            display: grid;
            grid-template-columns: repeat(3, 340px);
            grid-template-rows: repeat(3, 340px);
            gap: var(--grid-gap);
            padding: 20px;
            transform-origin: center center;
        }

        .tile {
            position: relative;
            background-size: cover;
            background-position: center;
            padding: 45px;
            display: flex;
            flex-direction: column;
            mask-image: radial-gradient(circle at var(--corner-radius) var(--corner-radius), black 100%, transparent 0);
            mask-position: calc(var(--corner-radius) * -1) calc(var(--corner-radius) * -1);
            border-radius: var(--corner-radius);
            overflow: hidden;
            transition: color 0.4s ease;
        }

        /* Color Tiles */
        .black-tile { background-color: #0b0b0a; grid-column: 1; grid-row: 1; color: #fff; }
        .purple-tile { background-color: #afa1ea; color: #000; grid-column: 3; grid-row: 1; }
        .blue-tile { background-color: #0404e9; grid-column: 1; grid-row: 2 / 4; color: #fff; }
        .white-tile { background-color: #ffffff; color: #000; grid-column: 2; grid-row: 2; }
        .lime-tile { background-color: #c0bf34; color: #000; grid-column: 3; grid-row: 3; }

        /* People Images */
        .person-1 { grid-column: 2; grid-row: 1; background-image: url('https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?auto=format&fit=crop&q=80&w=800'); }
        .person-2 { grid-column: 3; grid-row: 2; background-image: url('https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=crop&q=80&w=800'); }
        .person-3 { grid-column: 2; grid-row: 3; background-image: url('https://images.unsplash.com/photo-1539571696357-5a69c17a67c6?auto=format&fit=crop&q=80&w=800'); }

        .title-input {
            font-size: 32px;
            font-weight: 900; 
            margin-bottom: 24px;
            background: transparent;
            border: none;
            color: inherit;
            font-family: 'Geist Sans', sans-serif;
            outline: none;
            width: 100%;
            cursor: text;
            letter-spacing: -0.04em;
            text-transform: capitalize;
        }

        .title-input::placeholder {
            color: inherit;
            opacity: 0.2;
        }

        .stats {
            font-family: 'Geist Mono', monospace;
            font-size: 14px; 
            font-weight: 500;
            line-height: 2;
            text-transform: uppercase;
            pointer-events: none;
            letter-spacing: 0.02em;
        }
    </style>
</head>
<body>

    <div class="grid-wrapper" id="mainGrid">
        <div class="tile color-tile black-tile">
            <input type="text" class="title-input" value="Black" spellcheck="false">
            <div class="stats">
                <div class="hex-val">HEX : #0b0b0a</div>
                <div class="rgb-val">RGB : 11, 10, 11</div>
            </div>
        </div>
        <div class="tile person-1"></div>
        <div class="tile color-tile purple-tile">
            <input type="text" class="title-input" value="Cold Purple" spellcheck="false">
            <div class="stats">
                <div class="hex-val">HEX : #afa1ea</div>
                <div class="rgb-val">RGB : 175, 234, 161</div>
            </div>
        </div>

        <div class="tile color-tile blue-tile">
            <input type="text" class="title-input" value="Medium Blue" spellcheck="false">
            <div class="stats">
                <div class="hex-val">HEX : #0404e9</div>
                <div class="rgb-val">RGB : 4, 233, 4</div>
            </div>
        </div>
        <div class="tile color-tile white-tile">
            <input type="text" class="title-input" value="White" spellcheck="false">
            <div class="stats">
                <div class="hex-val">HEX : #ffffff</div>
                <div class="rgb-val">RGB : 255, 255, 255</div>
            </div>
        </div>
        <div class="tile person-2"></div>

        <div class="tile person-3"></div>
        <div class="tile color-tile lime-tile">
            <input type="text" class="title-input" value="Key Lime" spellcheck="false">
            <div class="stats">
                <div class="hex-val">HEX : #c0bf34</div>
                <div class="rgb-val">RGB : 192, 52, 191</div>
            </div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
    <script>
        const grid = document.getElementById('mainGrid');

        function scaleToFit() {
            const padding = 60;
            const size = 1020 + 24;
            const scale = Math.min((window.innerWidth - padding) / size, (window.innerHeight - padding) / size, 1);
            gsap.to(grid, { scale: scale, duration: 0.3 });
        }
        window.addEventListener('resize', scaleToFit);
        scaleToFit();

        const hexToRgb = (hex) => {
            if(!/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) return null;
            let c = hex.substring(1).split('');
            if(c.length == 3) c = [c[0], c[0], c[1], c[1], c[2], c[2]];
            c = '0x' + c.join('');
            return [(c>>16)&255, (c>>8)&255, c&255].join(', ');
        };

        const getBrightness = (rgbStr) => {
            const [r, g, b] = rgbStr.split(',').map(Number);
            return (r * 299 + g * 587 + b * 114) / 1000;
        };

        const generateRandomHex = () => '#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0');

        async function fetchColorName(hex) {
            try {
                const cleanHex = hex.replace('#', '');
                const response = await fetch(`https://api.color.pizza/v1/${cleanHex}`);
                const data = await response.json();
                return data.colors[0].name;
            } catch (e) { return "Custom Color"; }
        }

        // Spacebar Logic
        window.addEventListener('keydown', (e) => {
            if (e.code === 'Space') {
                e.preventDefault(); 
                if (document.activeElement.tagName === 'INPUT') return;

                document.querySelectorAll('.color-tile').forEach((tile, index) => {
                    const newHex = generateRandomHex();
                    setTimeout(async () => {
                        const rgb = hexToRgb(newHex);
                        const brightness = getBrightness(rgb);
                        
                        gsap.to(tile, {
                            backgroundColor: newHex,
                            color: brightness > 125 ? "#000" : "#fff",
                            duration: 0.8,
                            ease: "expo.out"
                        });

                        tile.querySelector('.hex-val').textContent = `HEX : ${newHex}`;
                        tile.querySelector('.rgb-val').textContent = `RGB : ${rgb}`;
                        
                        const name = await fetchColorName(newHex);
                        tile.querySelector('.title-input').value = name;
                    }, index * 60);
                });
            }
        });

        // Input Logic
        document.querySelectorAll('.title-input').forEach(input => {
            let originalName = "";

            input.addEventListener('focus', function() {
                originalName = this.value;
                this.value = '';
                const currentHex = this.closest('.tile').querySelector('.hex-val').textContent.split(': ')[1];
                this.placeholder = currentHex;
            });

            input.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') input.blur();
            });

            input.addEventListener('blur', async function() {
                const tile = this.closest('.tile');
                const currentHex = tile.querySelector('.hex-val').textContent.split(': ')[1];
                
                // If the user cleared it or didn't type a valid hex, revert to the name before focus
                // Otherwise, get the name for the current hex in the tile
                if (this.value.trim() === "") {
                    this.value = originalName;
                } else {
                    const name = await fetchColorName(currentHex);
                    this.value = name;
                }
            });

            input.addEventListener('input', function() {
                let val = this.value;
                if (val && !val.startsWith('#')) val = '#' + val;
                
                const rgb = hexToRgb(val);
                
                // Update visuals only if hex is valid 3 or 6 chars
                if (rgb && (val.length === 7 || val.length === 4)) {
                    const tile = this.closest('.tile');
                    const brightness = getBrightness(rgb);

                    gsap.to(tile, {
                        backgroundColor: val,
                        color: brightness > 125 ? "#000" : "#fff",
                        duration: 0.5,
                        ease: "power2.out"
                    });

                    tile.querySelector('.hex-val').textContent = `HEX : ${val}`;
                    tile.querySelector('.rgb-val').textContent = `RGB : ${rgb}`;
                }
            });
        });

        // Initial Entry Animation
        gsap.from(".tile", {
            duration: 1.4,
            scale: 0.7,
            opacity: 0,
            stagger: { grid: [3, 3], from: "center", amount: 0.6 },
            ease: "expo.out"
        });
    </script>
</body>
</html>

AI PROMPT

Create a "AI Grid - Geist Color Lab" component. Use GSAP for advanced animations. Apply gradients. Color palette: #070707. Layout: CSS Grid, Flexbox. Interactivity: responsive resize handling. Includes form input fields.