
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/png" href="https://i.ibb.co/9H8VYJTj/0eb873a548fc8391b6072914e7d93bde.png" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Expires" content="0" />
    
    <!-- Primary Meta Tags -->
    <title>Yellow Radio</title>
    <meta name="title" content="Yellow Radio">
    <meta name="description" content="Découvrez et écoutez des radios du monde entier en direct. Créez des salons, partagez de la musique et vibrez ensemble.">

    <!-- Open Graph / Facebook / Discord -->
    <meta property="og:type" content="website">
    <meta property="og:url" content="https://yellow-radio.netlify.app/">
    <meta property="og:title" content="Yellow Radio">
    <meta property="og:description" content="Découvrez et écoutez des radios du monde entier en direct. Créez des salons, partagez de la musique et vibrez ensemble.">
    <meta property="og:image" content="https://i.ibb.co/9H8VYJTj/0eb873a548fc8391b6072914e7d93bde.png">

    <!-- Twitter -->
    <meta property="twitter:card" content="summary_large_image">
    <meta property="twitter:url" content="https://yellow-radio.netlify.app/">
    <meta property="twitter:title" content="Yellow Radio">
    <meta property="twitter:description" content="Découvrez et écoutez des radios du monde entier en direct. Créez des salons, partagez de la musique et vibrez ensemble.">
    <meta property="twitter:image" content="https://i.ibb.co/9H8VYJTj/0eb873a548fc8391b6072914e7d93bde.png">

    <!-- Shield & Native WebRTC Protector (Guarantees constructible RTCPeerConnection, RTCSessionDescription, RTCIceCandidate) -->
    <script>
        (function() {
            function isConstructor(fn, testArg) {
                if (typeof fn !== 'function') return false;
                try {
                    new fn(testArg);
                    return true;
                } catch(e) {
                    if (!e || !e.message || (!e.message.includes('not a constructor') && !e.message.includes('is not a constructor'))) {
                        return true;
                    }
                    return false;
                }
            }

            var sandboxIframe = null;
            function getSandbox() {
                try {
                    if (sandboxIframe && sandboxIframe.contentWindow) return sandboxIframe.contentWindow;
                    sandboxIframe = document.createElement('iframe');
                    sandboxIframe.id = 'yellow-p2p-clean-sandbox';
                    sandboxIframe.style.display = 'none';
                    sandboxIframe.src = 'about:blank';
                    (document.head || document.documentElement).appendChild(sandboxIframe);
                    return sandboxIframe.contentWindow;
                } catch(e) {
                    return null;
                }
            }

            var cleanWin = getSandbox();
            var cleanRTC = (cleanWin && (cleanWin.RTCPeerConnection || cleanWin.webkitRTCPeerConnection || cleanWin.mozRTCPeerConnection)) || null;
            var cleanDesc = (cleanWin && (cleanWin.RTCSessionDescription || cleanWin.webkitRTCSessionDescription || cleanWin.mozRTCSessionDescription)) || null;
            var cleanCand = (cleanWin && (cleanWin.RTCIceCandidate || cleanWin.webkitRTCIceCandidate || cleanWin.mozRTCIceCandidate)) || null;

            // Safe constructor wrappers that can always be invoked with `new`
            function SafeRTCSessionDescription(init) {
                if (!init) init = {};
                if (cleanDesc && isConstructor(cleanDesc, { type: 'offer', sdp: '' })) {
                    try {
                        return new cleanDesc(init);
                    } catch(e) {}
                }
                this.type = (init && init.type) ? init.type : 'offer';
                this.sdp = (init && init.sdp) ? init.sdp : '';
            }
            SafeRTCSessionDescription.prototype.toJSON = function() {
                return { type: this.type, sdp: this.sdp };
            };

            function SafeRTCIceCandidate(init) {
                if (!init) init = {};
                if (cleanCand && isConstructor(cleanCand, { candidate: '' })) {
                    try {
                        return new cleanCand(init);
                    } catch(e) {}
                }
                this.candidate = (init && init.candidate !== undefined) ? String(init.candidate) : '';
                this.sdpMid = (init && init.sdpMid !== undefined) ? init.sdpMid : null;
                this.sdpMLineIndex = (init && init.sdpMLineIndex !== undefined) ? init.sdpMLineIndex : null;
                this.usernameFragment = (init && init.usernameFragment !== undefined) ? init.usernameFragment : null;
            }
            SafeRTCIceCandidate.prototype.toJSON = function() {
                return {
                    candidate: this.candidate,
                    sdpMid: this.sdpMid,
                    sdpMLineIndex: this.sdpMLineIndex,
                    usernameFragment: this.usernameFragment
                };
            };

            function getBestRTC() {
                if (isConstructor(window.RTCPeerConnection, { iceServers: [] })) return window.RTCPeerConnection;
                if (isConstructor(window.webkitRTCPeerConnection, { iceServers: [] })) return window.webkitRTCPeerConnection;
                if (cleanRTC && isConstructor(cleanRTC, { iceServers: [] })) return cleanRTC;
                var sb = getSandbox();
                if (sb && sb.RTCPeerConnection && isConstructor(sb.RTCPeerConnection, { iceServers: [] })) return sb.RTCPeerConnection;
                return cleanRTC;
            }

            function getBestDesc() {
                if (isConstructor(window.RTCSessionDescription, { type: 'offer', sdp: '' })) return window.RTCSessionDescription;
                if (isConstructor(window.webkitRTCSessionDescription, { type: 'offer', sdp: '' })) return window.webkitRTCSessionDescription;
                if (cleanDesc && isConstructor(cleanDesc, { type: 'offer', sdp: '' })) return cleanDesc;
                var sb = getSandbox();
                if (sb && sb.RTCSessionDescription && isConstructor(sb.RTCSessionDescription, { type: 'offer', sdp: '' })) return sb.RTCSessionDescription;
                return SafeRTCSessionDescription;
            }

            function getBestCand() {
                if (isConstructor(window.RTCIceCandidate, { candidate: '' })) return window.RTCIceCandidate;
                if (isConstructor(window.webkitRTCIceCandidate, { candidate: '' })) return window.webkitRTCIceCandidate;
                if (cleanCand && isConstructor(cleanCand, { candidate: '' })) return cleanCand;
                var sb = getSandbox();
                if (sb && sb.RTCIceCandidate && isConstructor(sb.RTCIceCandidate, { candidate: '' })) return sb.RTCIceCandidate;
                return SafeRTCIceCandidate;
            }

            function armorProperty(propName, getBestFn, testArg, fallback) {
                var current = getBestFn();
                try {
                    Object.defineProperty(window, propName, {
                        configurable: true,
                        enumerable: true,
                        get: function() {
                            if (isConstructor(current, testArg)) return current;
                            current = getBestFn();
                            if (isConstructor(current, testArg)) return current;
                            return fallback;
                        },
                        set: function(val) {
                            if (isConstructor(val, testArg)) {
                                current = val;
                                return;
                            }
                            console.warn('[P2P Shield] Blocked non-constructor assignment to window.' + propName + '. Valid constructor preserved.');
                        }
                    });
                } catch(e) {
                    try { window[propName] = current || fallback; } catch(err) {}
                }
            }

            armorProperty('RTCPeerConnection', getBestRTC, { iceServers: [] }, cleanRTC);
            armorProperty('webkitRTCPeerConnection', getBestRTC, { iceServers: [] }, cleanRTC);

            armorProperty('RTCSessionDescription', getBestDesc, { type: 'offer', sdp: '' }, SafeRTCSessionDescription);
            armorProperty('webkitRTCSessionDescription', getBestDesc, { type: 'offer', sdp: '' }, SafeRTCSessionDescription);

            armorProperty('RTCIceCandidate', getBestCand, { candidate: '' }, SafeRTCIceCandidate);
            armorProperty('webkitRTCIceCandidate', getBestCand, { candidate: '' }, SafeRTCIceCandidate);

            console.log('[P2P Shield] WebRTC constructors (RTCPeerConnection, RTCSessionDescription, RTCIceCandidate) fortified.');
        })();
    </script>
    <script src="https://unpkg.com/peerjs@1.5.2/dist/peerjs.min.js"></script>
    <script src="https://unpkg.com/mqtt@5.3.5/dist/mqtt.min.js"></script>
    <script id="cf-turnstile-script" src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Orbitron:wght@400;600;800;900&display=swap" rel="stylesheet">
    <style>
        /* Base and Fonts */
        :root {
            --c-primary: 250 204 21; /* yellow-400 */
            --c-primary-light: 252 211 77; /* yellow-300 */
            --c-bg-dark: 5 5 5;
            --c-bg-light: 18 18 18;
        }

        .theme-yellow { --c-primary: 250 204 21; --c-primary-light: 252 211 77; }
        .theme-blue { --c-primary: 59 130 246; --c-primary-light: 96 165 250; }
        .theme-purple { --c-primary: 139 92 246; --c-primary-light: 167 139 250; }

        body {
            background-color: rgb(var(--c-bg-dark));
            color: white;
            overflow-x: hidden;
            -webkit-font-smoothing: antialiased;
            margin: 0;
        }
        
        /* --- NEW BACKGROUND: Multi-Color Nebula Atmosphere --- */
        .cyber-grid {
            position: fixed;
            top: 0; left: 0; width: 100%; height: 100vh;
            z-index: -2;
            background: rgb(2, 2, 3);
            overflow: hidden;
            transition: background 0.5s ease;
        }

        /* Ambient Spotlights - Massive blur for "Nebula" effect */
        .cyber-orb {
            position: absolute;
            border-radius: 50%;
            filter: blur(140px);
            opacity: 0.35;
            mix-blend-mode: screen;
            animation: float-orb 20s infinite ease-in-out alternate;
            pointer-events: none;
        }
        
        /* Orb 1: User Theme Color (Anchor) */
        .cyber-orb.one {
            width: 70vw; height: 70vw;
            background: radial-gradient(circle, rgba(var(--c-primary), 0.25), transparent 70%);
            top: -20%; left: -20%;
            animation-duration: 25s;
        }
        
        /* Orb 2: Deep Violet (Depth) */
        .cyber-orb.two {
            width: 60vw; height: 60vw;
            background: radial-gradient(circle, rgba(124, 58, 237, 0.2), transparent 70%); /* Violet-600 */
            bottom: -10%; right: -10%;
            animation-duration: 30s;
            animation-delay: -5s;
        }
        
        /* Orb 3: Hot Pink / Magenta (Vibrancy) */
        .cyber-orb.three {
            width: 50vw; height: 50vw;
            background: radial-gradient(circle, rgba(219, 39, 119, 0.15), transparent 60%); /* Pink-600 */
            top: 40%; right: 20%;
            animation: float-vertical 35s infinite ease-in-out;
            opacity: 0.25;
        }

        /* Orb 4: Cyan / Teal (Cool accent) */
        .cyber-orb.four {
            width: 65vw; height: 65vw;
            background: radial-gradient(circle, rgba(8, 145, 178, 0.15), transparent 60%); /* Cyan-600 */
            bottom: 20%; left: 10%;
            animation: float-horizontal 40s infinite ease-in-out;
            animation-delay: -10s;
            opacity: 0.2;
        }
        
        /* Fog Overlay */
        .cyber-grid::after {
            content: '';
            position: absolute;
            inset: 0;
            background: url('/noise.svg');
            opacity: 0.03;
            mix-blend-mode: overlay;
            pointer-events: none;
        }

        @keyframes float-orb {
            0% { transform: translate(0, 0) scale(1); }
            100% { transform: translate(50px, 80px) scale(1.1); }
        }

        @keyframes float-vertical {
            0% { transform: translateY(0) rotate(0deg); }
            50% { transform: translateY(-50px) rotate(5deg); }
            100% { transform: translateY(0) rotate(0deg); }
        }

        @keyframes float-horizontal {
            0% { transform: translateX(0) scale(1); }
            50% { transform: translateX(40px) scale(1.05); }
            100% { transform: translateX(0) scale(1); }
        }
        
        /* Cinematic Intro Animations */
        @keyframes cinematic-slam {
            0% { transform: scale(3); opacity: 0; letter-spacing: 1em; }
            100% { transform: scale(1); opacity: 1; letter-spacing: -0.05em; }
        }
        
        @keyframes text-shimmer {
            0% { background-position: -200% 0; }
            100% { background-position: 200% 0; }
        }

        /* Custom Scrollbar */
        ::-webkit-scrollbar { width: 8px; }
        ::-webkit-scrollbar-track { background: transparent; }
        ::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); border-radius: 4px; }
        ::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.4); }

        .font-sans { font-family: 'Inter', sans-serif; }
        .font-orbitron { font-family: 'Orbitron', sans-serif; }

        /* Glassmorphism Premium */
        .glass-panel {
            background: rgba(10, 10, 15, 0.6);
            backdrop-filter: blur(20px) saturate(180%);
            -webkit-backdrop-filter: blur(20px) saturate(180%);
            border: 1px solid rgba(255, 255, 255, 0.08);
            box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
        }
        
        .glass-border {
            border: 1px solid rgba(255, 255, 255, 0.08);
        }

        /* Animations */
        @keyframes fade-in-app {
            from { opacity: 0; transform: scale(0.98); }
            to { opacity: 1; transform: scale(1); }
        }
        .animate-fade-in-app { animation: fade-in-app 0.6s cubic-bezier(0.2, 0.8, 0.2, 1) forwards; }

        @keyframes item-fade-in {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }
        .animate-item-fade-in { animation: item-fade-in 0.4s ease-out forwards; }

        @keyframes heart-burst {
            0% { transform: scale(1); }
            50% { transform: scale(1.5); }
            100% { transform: scale(1); }
        }
        .animate-heart-burst { animation: heart-burst 0.3s ease-in-out; }

        @keyframes equalizer-bar {
            0%, 100% { height: 10%; }
            50% { height: 100%; }
        }
        
        @keyframes float {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-10px); }
        }
        .animate-float { animation: float 6s ease-in-out infinite; }

        /* Selection */
        ::-moz-selection { background: rgba(var(--c-primary), 0.3); color: white; }
        ::selection { background: rgba(var(--c-primary), 0.3); color: white; }
    </style>

<script type="importmap">
{
  "imports": {
    "react": "https://aistudiocdn.com/react@^19.2.0",
    "react/": "https://aistudiocdn.com/react@^19.2.0/",
    "@vitejs/plugin-react": "https://aistudiocdn.com/@vitejs/plugin-react@^5.1.1",
    "vite": "https://aistudiocdn.com/vite@^7.2.4",
    "react-dom/": "https://aistudiocdn.com/react-dom@^19.2.0/",
    "url": "https://aistudiocdn.com/url@^0.11.4",
    "@google/genai": "https://aistudiocdn.com/@google/genai@^1.31.0"
  }
}
</script>
  <script type="module" crossorigin src="/assets/index-CxhtWmuS.js"></script>
  <link rel="stylesheet" crossorigin href="/assets/index-KMRW51wT.css">
</head>
<body>
    <div id="root"></div>
</body>
</html>
