<!DOCTYPE html>

<html lang="es">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Calculadora Científica Cuántica</title>

    <style>

        @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Roboto+Mono:wght@300;500&display=swap');


        :root {

            --primary-glow: #00f3ff;

            --secondary-glow: #bc13fe;

            --bg-color: #050510;

            --glass-bg: rgba(20, 20, 35, 0.7);

            --glass-border: rgba(255, 255, 255, 0.1);

            --text-main: #e0e0e0;

        }


        * {

            box-sizing: border-box;

            margin: 0;

            padding: 0;

            user-select: none; /* Evita selección de texto al tocar rápido */

        }


        body {

            background-color: var(--bg-color);

            color: var(--text-main);

            font-family: 'Roboto Mono', monospace;

            overflow: hidden; /* Para el canvas de fondo */

            height: 100vh;

            display: flex;

            justify-content: center;

            align-items: center;

        }


        /* Fondo Animado (Canvas) */

        #bg-canvas {

            position: absolute;

            top: 0;

            left: 0;

            width: 100%;

            height: 100%;

            z-index: 0;

        }


        /* Contenedor Principal */

        .calculator-container {

            position: relative;

            z-index: 10;

            width: 100%;

            max-width: 400px;

            background: var(--glass-bg);

            backdrop-filter: blur(15px);

            -webkit-backdrop-filter: blur(15px);

            border: 1px solid var(--glass-border);

            border-radius: 20px;

            box-shadow: 0 0 30px rgba(0, 243, 255, 0.1), inset 0 0 20px rgba(0, 0, 0, 0.5);

            padding: 20px;

            animation: slideUp 0.8s ease-out;

        }


        @keyframes slideUp {

            from { transform: translateY(50px); opacity: 0; }

            to { transform: translateY(0); opacity: 1; }

        }


        /* Pantalla */

        .display-screen {

            background: rgba(0, 0, 0, 0.6);

            border: 1px solid var(--primary-glow);

            border-radius: 10px;

            padding: 15px;

            margin-bottom: 20px;

            text-align: right;

            box-shadow: inset 0 0 10px rgba(0, 243, 255, 0.2);

            position: relative;

            overflow: hidden;

        }


        .history {

            font-size: 0.8rem;

            color: #888;

            min-height: 1.2rem;

            margin-bottom: 5px;

            font-family: 'Orbitron', sans-serif;

        }


        .current-input {

            font-size: 2rem;

            font-weight: 500;

            color: var(--primary-glow);

            word-wrap: break-word;

            text-shadow: 0 0 5px var(--primary-glow);

            font-family: 'Orbitron', sans-serif;

            min-height: 2.4rem;

        }


        /* Grid de Botones */

        .buttons-grid {

            display: grid;

            grid-template-columns: repeat(4, 1fr);

            gap: 12px;

        }


        button {

            background: rgba(255, 255, 255, 0.05);

            border: 1px solid rgba(255, 255, 255, 0.1);

            color: #fff;

            padding: 15px 0;

            font-size: 1.1rem;

            border-radius: 12px;

            cursor: pointer;

            transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);

            font-family: 'Roboto Mono', monospace;

            position: relative;

            overflow: hidden;

        }


        button:active {

            transform: scale(0.95);

        }


        button::after {

            content: '';

            position: absolute;

            top: 50%;

            left: 50%;

            width: 0;

            height: 0;

            background: rgba(255, 255, 255, 0.2);

            border-radius: 50%;

            transform: translate(-50%, -50%);

            transition: width 0.3s ease, height 0.3s ease;

        }


        button:active::after {

            width: 100px;

            height: 100px;

        }


        /* Estilos específicos de botones */

        .btn-op {

            color: var(--primary-glow);

            font-weight: bold;

        }


        .btn-sci {

            font-size: 0.9rem;

            color: var(--secondary-glow);

        }


        .btn-eq {

            background: linear-gradient(135deg, rgba(0, 243, 255, 0.2), rgba(188, 19, 254, 0.2));

            border-color: var(--primary-glow);

            grid-column: span 2;

            color: #fff;

            text-shadow: 0 0 5px #fff;

        }


        .btn-clear {

            color: #ff4d4d;

            border-color: rgba(255, 77, 77, 0.3);

        }


        .btn-del {

            color: #ff9e4d;

        }


        /* Indicador de modo (DEG/RAD) */

        .mode-indicator {

            position: absolute;

            top: 5px;

            left: 10px;

            font-size: 0.6rem;

            color: var(--secondary-glow);

            cursor: pointer;

            border: 1px solid var(--secondary-glow);

            padding: 2px 5px;

            border-radius: 4px;

        }


        /* Efecto de Scanline en pantalla */

        .display-screen::before {

            content: " ";

            display: block;

            position: absolute;

            top: 0;

            left: 0;

            bottom: 0;

            right: 0;

            background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));

            z-index: 2;

            background-size: 100% 2px, 3px 100%;

            pointer-events: none;

        }


        /* Responsivo */

        @media (max-width: 400px) {

            .calculator-container {

                width: 95%;

                padding: 15px;

            }

            button {

                padding: 12px 0;

                font-size: 1rem;

            }

        }

    </style>

</head>

<body>


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


    <div class="calculator-container">

        <div class="display-screen">

            <div id="mode-toggle" class="mode-indicator" onclick="toggleMode()">RAD</div>

            <div class="history" id="history"></div>

            <div class="current-input" id="display">0</div>

        </div>


        <div class="buttons-grid">

            <!-- Fila 1 -->

            <button class="btn-sci" onclick="handleSci('sin')">sin</button>

            <button class="btn-sci" onclick="handleSci('cos')">cos</button>

            <button class="btn-sci" onclick="handleSci('tan')">tan</button>

            <button class="btn-clear" onclick="clearDisplay()">AC</button>


            <!-- Fila 2 -->

            <button class="btn-sci" onclick="handleSci('log')">log</button>

            <button class="btn-sci" onclick="handleSci('ln')">ln</button>

            <button class="btn-sci" onclick="insert('(')">(</button>

            <button class="btn-sci" onclick="insert(')')">)</button>


            <!-- Fila 3 -->

            <button class="btn-sci" onclick="handleSci('pow')">x^y</button>

            <button class="btn-sci" onclick="handleSci('sqrt')">√</button>

            <button class="btn-sci" onclick="insert('Math.PI')">π</button>

            <button class="btn-op" onclick="insert('/')">÷</button>


            <!-- Fila 4 -->

            <button onclick="insert('7')">7</button>

            <button onclick="insert('8')">8</button>

            <button onclick="insert('9')">9</button>

            <button class="btn-op" onclick="insert('*')">×</button>


            <!-- Fila 5 -->

            <button onclick="insert('4')">4</button>

            <button onclick="insert('5')">5</button>

            <button onclick="insert('6')">6</button>

            <button class="btn-op" onclick="insert('-')">-</button>


            <!-- Fila 6 -->

            <button onclick="insert('1')">1</button>

            <button onclick="insert('2')">2</button>

            <button onclick="insert('3')">3</button>

            <button class="btn-op" onclick="insert('+')">+</button>


            <!-- Fila 7 -->

            <button onclick="insert('0')">0</button>

            <button onclick="insert('.')">.</button>

            <button class="btn-del" onclick="backspace()">⌫</button>

            <button class="btn-eq" onclick="calculate()">CALCULAR</button>

        </div>

    </div>


    <script>

        /* ----------------------------------------------------

           1. SISTEMA DE AUDIO (Web Audio API)

           Genera sonidos de ciencia ficción sin archivos mp3

        ---------------------------------------------------- */

        const AudioContext = window.AudioContext || window.webkitAudioContext;

        const audioCtx = new AudioContext();


        function playSound(type) {

            if (audioCtx.state === 'suspended') {

                audioCtx.resume();

            }


            const oscillator = audioCtx.createOscillator();

            const gainNode = audioCtx.createGain();


            oscillator.connect(gainNode);

            gainNode.connect(audioCtx.destination);


            const now = audioCtx.currentTime;


            if (type === 'number') {

                // Tono corto y agudo (High-tech blip)

                oscillator.type = 'sine';

                oscillator.frequency.setValueAtTime(800, now);

                oscillator.frequency.exponentialRampToValueAtTime(300, now + 0.1);

                gainNode.gain.setValueAtTime(0.1, now);

                gainNode.gain.exponentialRampToValueAtTime(0.01, now + 0.1);

                oscillator.start(now);

                oscillator.stop(now + 0.1);

            } 

            else if (type === 'operator') {

                // Tono metálico suave

                oscillator.type = 'square';

                oscillator.frequency.setValueAtTime(200, now);

                gainNode.gain.setValueAtTime(0.05, now);

                gainNode.gain.linearRampToValueAtTime(0, now + 0.15);

                oscillator.start(now);

                oscillator.stop(now + 0.15);

            }

            else if (type === 'clear') {

                // Sonido de borrado (barrido hacia abajo)

                oscillator.type = 'sawtooth';

                oscillator.frequency.setValueAtTime(400, now);

                oscillator.frequency.exponentialRampToValueAtTime(50, now + 0.3);

                gainNode.gain.setValueAtTime(0.1, now);

                gainNode.gain.linearRampToValueAtTime(0, now + 0.3);

                oscillator.start(now);

                oscillator.stop(now + 0.3);

            }

            else if (type === 'calc') {

                // Sonido de éxito/computación

                oscillator.type = 'triangle';

                oscillator.frequency.setValueAtTime(440, now);

                oscillator.frequency.setValueAtTime(880, now + 0.1);

                gainNode.gain.setValueAtTime(0.1, now);

                gainNode.gain.linearRampToValueAtTime(0, now + 0.4);

                oscillator.start(now);

                oscillator.stop(now + 0.4);

            }

            else if (type === 'error') {

                // Sonido de error

                oscillator.type = 'sawtooth';

                oscillator.frequency.setValueAtTime(150, now);

                gainNode.gain.setValueAtTime(0.2, now);

                gainNode.gain.linearRampToValueAtTime(0, now + 0.3);

                oscillator.start(now);

                oscillator.stop(now + 0.3);

            }

        }


        /* ----------------------------------------------------

           2. LÓGICA DE LA CALCULADORA

        ---------------------------------------------------- */

        let displayValue = '0';

        let isResult = false;

        let angleMode = 'RAD'; // RAD o DEG


        const display = document.getElementById('display');

        const historyDisplay = document.getElementById('history');

        const modeBtn = document.getElementById('mode-toggle');


        function updateDisplay() {

            display.innerText = displayValue;

        }


        function toggleMode() {

            angleMode = angleMode === 'RAD' ? 'DEG' : 'RAD';

            modeBtn.innerText = angleMode;

            playSound('operator');

        }


        function insert(val) {

            playSound(isNaN(val) ? 'operator' : 'number');


            if (isResult) {

                // Si acabamos de calcular, y presionan un número, reseteamos.

                // Si es un operador, continuamos con el resultado anterior.

                if (!isNaN(val) || val === 'Math.PI') {

                    displayValue = '';

                }

                isResult = false;

            }


            if (displayValue === '0' && val !== '.') {

                displayValue = '';

            }


            displayValue += val;

            updateDisplay();

        }


        function clearDisplay() {

            playSound('clear');

            displayValue = '0';

            historyDisplay.innerText = '';

            isResult = false;

            updateDisplay();

        }


        function backspace() {

            playSound('operator');

            if (isResult) {

                clearDisplay();

                return;

            }

            if (displayValue.length > 1) {

                displayValue = displayValue.slice(0, -1);

            } else {

                displayValue = '0';

            }

            updateDisplay();

        }


        function handleSci(func) {

            playSound('operator');

            if (isResult) {

                isResult = false;

                displayValue = '';

            }

            if (displayValue === '0') displayValue = '';


            switch(func) {

                case 'sin': displayValue += 'sin('; break;

                case 'cos': displayValue += 'cos('; break;

                case 'tan': displayValue += 'tan('; break;

                case 'log': displayValue += 'log10('; break;

                case 'ln': displayValue += 'log('; break; // Math.log es ln en JS

                case 'sqrt': displayValue += 'sqrt('; break;

                case 'pow': displayValue += '^'; break;

            }

            updateDisplay();

        }


        function calculate() {

            try {

                let expression = displayValue;

                historyDisplay.innerText = expression + ' =';


                // Reemplazos para sintaxis de JavaScript

                // 1. Manejo de potencias (^)

                expression = expression.replace(/\^/g, '**');


                // 2. Funciones trigonométricas con modo DEG/RAD

                // Creamos una función wrapper temporal para inyectar conversión

                const toRad = (angleMode === 'DEG') ? '* (Math.PI/180)' : '';


                // Usamos regex para encontrar funciones trigonométricas y aplicar conversión si es DEG

                // Nota: Esta es una implementación simplificada.

                // Para una robustez total se necesitaría un parser real.

                // Aquí, asumimos Math.sin(x) directo.

                // Si es DEG, el usuario visualmente ve sin(90), pero JS ejecuta Math.sin(90 * PI/180)

                

                // Vamos a inyectar las funciones matemáticas globales al eval

                // Pero primero limpiamos tokens visuales

                expression = expression.replace(/sin\(/g, `Math.sin(`);

                expression = expression.replace(/cos\(/g, `Math.cos(`);

                expression = expression.replace(/tan\(/g, `Math.tan(`);

                expression = expression.replace(/log10\(/g, `Math.log10(`);

                expression = expression.replace(/log\(/g, `Math.log(`); // ln

                expression = expression.replace(/sqrt\(/g, `Math.sqrt(`);

                

                // Ajuste muy básico para Grados: Si estamos en DEG, intentamos envolver argumentos numéricos

                // NOTA: Modificar argumentos dentro de strings con regex es complejo. 

                // Para este demo, si está en DEG, aplicamos factor de conversión al resultado final si es trigonométrica pura es difícil.

                // Solución: Advertencia visual o conversión manual es mejor para este alcance.

                // Pero intentaremos un truco: Redefinir las funciones Math temporalmente si es necesario.

                

                let result;

                if (angleMode === 'DEG') {

                   // Sobreescribimos temporalmente para el eval

                   const originalSin = Math.sin;

                   const originalCos = Math.cos;

                   const originalTan = Math.tan;

                   

                   Math.sin = (x) => originalSin(x * (Math.PI / 180));

                   Math.cos = (x) => originalCos(x * (Math.PI / 180));

                   Math.tan = (x) => originalTan(x * (Math.PI / 180));

                   

                   result = eval(expression);

                   

                   // Restaurar

                   Math.sin = originalSin;

                   Math.cos = originalCos;

                   Math.tan = originalTan;

                } else {

                   result = eval(expression);

                }


                // Formateo del resultado

                if (!isFinite(result) || isNaN(result)) {

                    throw new Error("Error Matemático");

                }


                // Redondear decimales excesivos

                result = parseFloat(result.toFixed(8)).toString();


                displayValue = result;

                playSound('calc');

                isResult = true;

            } catch (e) {

                displayValue = "Error";

                playSound('error');

                isResult = true;

                setTimeout(() => {

                    if(displayValue === "Error") displayValue = "0";

                    updateDisplay();

                }, 1500);

            }

            updateDisplay();

        }


        /* ----------------------------------------------------

           3. FONDO ANIMADO (Canvas)

           Red de partículas estilo "Ciencia/Neurológico"

        ---------------------------------------------------- */

        const canvas = document.getElementById('bg-canvas');

        const ctx = canvas.getContext('2d');

        let width, height;

        let particles = [];


        function resize() {

            width = canvas.width = window.innerWidth;

            height = canvas.height = window.innerHeight;

        }


        class Particle {

            constructor() {

                this.x = Math.random() * width;

                this.y = Math.random() * height;

                this.vx = (Math.random() - 0.5) * 0.5;

                this.vy = (Math.random() - 0.5) * 0.5;

                this.size = Math.random() * 2 + 1;

                this.color = Math.random() > 0.5 ? '#00f3ff' : '#bc13fe'; // Cian o Violeta

            }


            update() {

                this.x += this.vx;

                this.y += this.vy;


                // Rebotar en bordes

                if (this.x < 0 || this.x > width) this.vx *= -1;

                if (this.y < 0 || this.y > height) this.vy *= -1;

            }


            draw() {

                ctx.beginPath();

                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);

                ctx.fillStyle = this.color;

                ctx.fill();

            }

        }


        function initParticles() {

            particles = [];

            const particleCount = Math.floor(window.innerWidth / 10); // Densidad adaptable

            for (let i = 0; i < particleCount; i++) {

                particles.push(new Particle());

            }

        }


        function animate() {

            ctx.clearRect(0, 0, width, height);

            

            // Dibujar líneas de conexión

            for (let i = 0; i < particles.length; i++) {

                particles[i].update();

                particles[i].draw();


                for (let j = i; j < particles.length; j++) {

                    const dx = particles[i].x - particles[j].x;

                    const dy = particles[i].y - particles[j].y;

                    const distance = Math.sqrt(dx * dx + dy * dy);


                    if (distance < 100) {

                        ctx.beginPath();

                        ctx.strokeStyle = `rgba(100, 100, 255, ${1 - distance / 100})`;

                        ctx.lineWidth = 0.5;

                        ctx.moveTo(particles[i].x, particles[i].y);

                        ctx.lineTo(particles[j].x, particles[j].y);

                        ctx.stroke();

                    }

                }

            }

            requestAnimationFrame(animate);

        }


        window.addEventListener('resize', () => {

            resize();

            initParticles();

        });


        // Inicialización

        resize();

        initParticles();

        animate();


    </script>

</body>

</html>