diff --git a/projects/calculator/index.html b/projects/calculator/index.html index d6626a4..ff7ddc2 100644 --- a/projects/calculator/index.html +++ b/projects/calculator/index.html @@ -1,48 +1,76 @@ - + - - - Calculator - + + + Premium Calculator with History + + -
-
-
-
0
+
+
- -
- - - - - - - - - - - - - - - - - - - - - - - - + +
+
+
+ +
+ +
+
+
+
0
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
-
- diff --git a/projects/calculator/main.js b/projects/calculator/main.js index 1347028..1b903cb 100644 --- a/projects/calculator/main.js +++ b/projects/calculator/main.js @@ -1,224 +1,484 @@ -const currentOperandElement = document.getElementById('currentOperand'); -const previousOperandElement = document.getElementById('previousOperand'); -const buttons = document.querySelectorAll('button'); - -let currentOperand = '0'; -let previousOperand = ''; -let operation = null; -let shouldResetScreen = false; - -function init() { - buttons.forEach(button => { - button.addEventListener('click', () => { - button.classList.add('press-animation'); - setTimeout(() => button.classList.remove('press-animation'), 200); - - handleButtonClick(button); - }); - }); - - document.addEventListener('keydown', handleKeyboardInput); - - updateDisplay(); -} - -function handleButtonClick(button) { - if (button.dataset.number !== undefined) { - appendNumber(button.dataset.number); - } else if (button.dataset.action === 'operator') { - chooseOperation(button.dataset.operator); - } else if (button.dataset.action === 'decimal') { - appendDecimal(); - } else if (button.dataset.action === 'equals') { - compute(); - } else if (button.dataset.action === 'clear') { - clear(); - } else if (button.dataset.action === 'backspace') { - backspace(); - } else if (button.dataset.action === 'toggle-sign') { - toggleSign(); - } else if (button.dataset.action === 'percentage') { - percentage(); - } -} - -function handleKeyboardInput(e) { - if (e.key === 'Enter' || e.key === 'Escape' || e.key === 'Backspace') { - e.preventDefault(); - } - - if (e.key >= '0' && e.key <= '9') { - appendNumber(e.key); - } - else if (e.key === '.') { - appendDecimal(); - } - else if (e.key === '+' || e.key === '-' || e.key === '*' || e.key === '/') { - const operatorMap = { - '+': '+', - '-': '−', - '*': '×', - '/': '÷' - }; - chooseOperation(operatorMap[e.key]); - } - else if (e.key === 'Enter' || e.key === '=') { - compute(); - } - else if (e.key === 'Escape') { - clear(); - } - else if (e.key === 'Backspace') { - backspace(); - } -} - -function appendNumber(number) { - if (shouldResetScreen) { - currentOperand = ''; - shouldResetScreen = false; - } - - if (currentOperand === '0') { - currentOperand = number; - } else if (currentOperand.length < 12) { - currentOperand += number; - } - - updateDisplay(); -} - -function appendDecimal() { - if (shouldResetScreen) { - currentOperand = '0'; - shouldResetScreen = false; - } - - if (!currentOperand.includes('.')) { - currentOperand += '.'; - } - - updateDisplay(); -} - -function chooseOperation(op) { - if (currentOperand === '') return; - - if (previousOperand !== '') { - compute(); - } - - operation = op; - previousOperand = currentOperand; - shouldResetScreen = true; - updateDisplay(); -} - -function compute() { - if (operation === null || previousOperand === '') return; - - let computation; - const prev = parseFloat(previousOperand); - const current = parseFloat(currentOperand); - - if (isNaN(prev) || isNaN(current)) { - clear(); - return; - } - - switch (operation) { - case '+': computation = prev + current; break; - case '−': computation = prev - current; break; - case '×': computation = prev * current; break; - case '÷': - if (current === 0) { - currentOperand = 'Error'; - previousOperand = ''; - operation = null; - shouldResetScreen = true; - updateDisplay(); - return; - } - computation = prev / current; - break; - default: return; - } - - currentOperand = roundResult(computation); - operation = null; - previousOperand = ''; - shouldResetScreen = true; - updateDisplay(); -} - -function clear() { - currentOperand = '0'; - previousOperand = ''; - operation = null; - shouldResetScreen = false; - updateDisplay(); -} - -function backspace() { - if (currentOperand.length > 1) { - currentOperand = currentOperand.slice(0, -1); - } else { - currentOperand = '0'; - } - updateDisplay(); -} - -function toggleSign() { - if (currentOperand !== '0') { - currentOperand = currentOperand.startsWith('-') - ? currentOperand.slice(1) - : '-' + currentOperand; - } - updateDisplay(); -} - -function percentage() { - currentOperand = (parseFloat(currentOperand) / 100).toString(); - shouldResetScreen = true; - updateDisplay(); -} - -function roundResult(number) { - const strNumber = number.toExponential(12); - const roundedNumber = parseFloat(strNumber); - - return Number.isInteger(roundedNumber) - ? roundedNumber.toString() - : roundedNumber.toString(); -} - -function formatNumber(number) { - if (number === 'Error') return number; - - const stringNumber = number.toString(); - - if (stringNumber.length > 12) { - return parseFloat(number).toExponential(6); - } - - return stringNumber; -} - -function updateDisplay() { - currentOperandElement.textContent = formatNumber(currentOperand); - - if (operation != null) { - previousOperandElement.textContent = `${previousOperand} ${operation}`; - } else { - previousOperandElement.textContent = ''; - } - - if (currentOperand === 'Error') { - currentOperandElement.classList.add('error'); - } else { - currentOperandElement.classList.remove('error'); - } -} - -init(); + // ===== DOM ELEMENTS ===== + const currentOperandElement = document.getElementById('currentOperand'); + const previousOperandElement = document.getElementById('previousOperand'); + const historyContainer = document.getElementById('historyContainer'); + const calculatorWrapper = document.getElementById('calculatorWrapper'); + const calculator = document.getElementById('calculator'); + const themeIcon = document.getElementById('themeIcon'); + const buttons = document.querySelectorAll('button'); + + // ===== CALCULATOR STATE ===== + let currentOperand = '0'; + let previousOperand = ''; + let operation = null; + let shouldResetScreen = false; + let calculationHistory = []; + + // ===== LOCAL STORAGE KEYS ===== */ + const STORAGE_KEYS = { + CALCULATOR_STATE: 'calculatorState', + CALCULATION_HISTORY: 'calculationHistory', + THEME: 'theme' + }; + + // ===== INITIALIZATION ===== */ + function init() { + // Load saved state and history from localStorage + loadCalculatorState(); + loadHistory(); + + // Button click handlers + buttons.forEach(button => { + button.addEventListener('click', (e) => { + handleButtonClick(button, e); + }); + }); + + // Keyboard support + document.addEventListener('keydown', handleKeyboardInput); + + // Auto-save on window close + window.addEventListener('beforeunload', saveCalculatorState); + + updateDisplay(); + } + + // ===== BUTTON CLICK HANDLER ===== */ + function handleButtonClick(button, event) { + // Add visual feedback + button.style.transform = 'scale(0.95)'; + setTimeout(() => { + button.style.transform = ''; + }, 100); + + if (button.dataset.number !== undefined) { + appendNumber(button.dataset.number); + } else if (button.dataset.action === 'operator') { + chooseOperation(button.dataset.operator); + } else if (button.dataset.action === 'decimal') { + appendDecimal(); + } else if (button.dataset.action === 'equals') { + compute(); + } else if (button.dataset.action === 'clear') { + clear(); + } else if (button.dataset.action === 'backspace') { + backspace(); + } else if (button.dataset.action === 'toggle-sign') { + toggleSign(); + } else if (button.dataset.action === 'percentage') { + percentage(); + } + } + + // ===== KEYBOARD SUPPORT ===== */ + function handleKeyboardInput(e) { + // Prevent default for calculator keys + if (['Enter', 'Escape', 'Backspace', '+', '-', '*', '/', '.', '%'].includes(e.key)) { + e.preventDefault(); + } + + // Number keys + if (e.key >= '0' && e.key <= '9') { + appendNumber(e.key); + } + // Decimal point + else if (e.key === '.') { + appendDecimal(); + } + // Operator keys + else if (e.key === '+' || e.key === '-' || e.key === '*' || e.key === '/') { + const operatorMap = { + '+': '+', + '-': '−', + '*': '×', + '/': '÷' + }; + chooseOperation(operatorMap[e.key]); + } + // Equals + else if (e.key === 'Enter' || e.key === '=') { + compute(); + } + // Clear (AC) + else if (e.key === 'Escape') { + clear(); + } + // Backspace + else if (e.key === 'Backspace') { + backspace(); + } + // Percentage + else if (e.key === '%') { + percentage(); + } + } + + // ===== NUMBER FUNCTIONS ===== */ + function appendNumber(number) { + if (shouldResetScreen) { + currentOperand = ''; + shouldResetScreen = false; + } + + if (currentOperand === '0') { + currentOperand = number; + } else if (currentOperand.length < 12) { + currentOperand += number; + } + + updateDisplay(); + saveCalculatorState(); + } + + function appendDecimal() { + if (shouldResetScreen) { + currentOperand = '0'; + shouldResetScreen = false; + } + + // Prevent multiple decimal points + if (!currentOperand.includes('.')) { + currentOperand += '.'; + } + + updateDisplay(); + saveCalculatorState(); + } + + // ===== OPERATION FUNCTIONS ===== */ + function chooseOperation(op) { + if (currentOperand === '') return; + + if (previousOperand !== '') { + compute(); + } + + operation = op; + previousOperand = currentOperand; + shouldResetScreen = true; + updateDisplay(); + saveCalculatorState(); + } + + function compute() { + if (operation === null || previousOperand === '') return; + + let computation; + const prev = parseFloat(previousOperand); + const current = parseFloat(currentOperand); + + if (isNaN(prev) || isNaN(current)) { + clear(); + return; + } + + switch (operation) { + case '+': + computation = prev + current; + break; + case '−': + computation = prev - current; + break; + case '×': + computation = prev * current; + break; + case '÷': + if (current === 0) { + currentOperand = 'Error'; + previousOperand = ''; + operation = null; + shouldResetScreen = true; + updateDisplay(); + saveCalculatorState(); + return; + } + computation = prev / current; + break; + default: + return; + } + + // Create expression for history + const expression = `${previousOperand} ${operation} ${currentOperand}`; + const result = roundResult(computation); + + // Add to history + addToHistory(expression, result); + + currentOperand = result; + operation = null; + previousOperand = ''; + shouldResetScreen = true; + + // Add success animation + currentOperandElement.classList.add('success'); + setTimeout(() => { + currentOperandElement.classList.remove('success'); + }, 500); + + updateDisplay(); + saveCalculatorState(); + } + + // ===== UTILITY FUNCTIONS ===== */ + function clear() { + currentOperand = '0'; + previousOperand = ''; + operation = null; + shouldResetScreen = false; + updateDisplay(); + saveCalculatorState(); + } + + function backspace() { + if (currentOperand === 'Error') { + clear(); + return; + } + + if (currentOperand.length > 1) { + currentOperand = currentOperand.slice(0, -1); + } else { + currentOperand = '0'; + } + updateDisplay(); + saveCalculatorState(); + } + + function toggleSign() { + if (currentOperand === 'Error') return; + + if (currentOperand !== '0') { + currentOperand = currentOperand.startsWith('-') + ? currentOperand.slice(1) + : '-' + currentOperand; + } + updateDisplay(); + saveCalculatorState(); + } + + function percentage() { + if (currentOperand === 'Error') return; + + currentOperand = (parseFloat(currentOperand) / 100).toString(); + shouldResetScreen = true; + updateDisplay(); + saveCalculatorState(); + } + + function roundResult(number) { + // Handle very large or very small numbers + if (Math.abs(number) > 1e10 || (Math.abs(number) < 1e-10 && number !== 0)) { + return number.toExponential(6); + } + + // Round to 10-12 significant digits + const rounded = Math.round(number * 1e10) / 1e10; + + // Remove trailing zeros after decimal + let result = rounded.toString(); + if (result.includes('.')) { + result = result.replace(/\.?0+$/, ''); + } + + return result; + } + + function formatNumber(number) { + if (number === 'Error') return number; + + const stringNumber = number.toString(); + + // Handle very long numbers + if (stringNumber.length > 12) { + const num = parseFloat(number); + if (Math.abs(num) > 1e10 || (Math.abs(num) < 1e-10 && num !== 0)) { + return num.toExponential(6); + } + return stringNumber.substring(0, 12); + } + + return stringNumber; + } + + // ===== DISPLAY UPDATE ===== */ + function updateDisplay() { + // Add transition effect + currentOperandElement.style.transform = 'scale(0.98)'; + setTimeout(() => { + currentOperandElement.style.transform = 'scale(1)'; + }, 100); + + currentOperandElement.textContent = formatNumber(currentOperand); + + if (operation != null) { + previousOperandElement.textContent = `${previousOperand} ${operation}`; + } else { + previousOperandElement.textContent = ''; + } + + // Handle error state + if (currentOperand === 'Error') { + currentOperandElement.classList.add('error'); + } else { + currentOperandElement.classList.remove('error'); + } + } + + // ===== HISTORY FUNCTIONS ===== */ + function addToHistory(expression, result) { + const historyItem = { + expression: expression, + result: result, + timestamp: new Date().toISOString() + }; + + calculationHistory.unshift(historyItem); + + // Keep only the last 20 calculations + if (calculationHistory.length > 20) { + calculationHistory = calculationHistory.slice(0, 20); + } + + saveHistory(); + renderHistory(); + } + + function renderHistory() { + if (calculationHistory.length === 0) { + historyContainer.innerHTML = '
No history yet
'; + return; + } + + historyContainer.innerHTML = calculationHistory.map((item, index) => ` +
+ ${item.expression} = ${item.result} +
+ `).join(''); + } + + function useHistoryItem(index) { + const item = calculationHistory[index]; + currentOperand = item.result; + previousOperand = ''; + operation = null; + shouldResetScreen = true; + updateDisplay(); + saveCalculatorState(); + } + + function clearHistory() { + calculationHistory = []; + saveHistory(); + renderHistory(); + } + + function saveHistory() { + try { + localStorage.setItem(STORAGE_KEYS.CALCULATION_HISTORY, JSON.stringify(calculationHistory)); + } catch (e) { + console.warn('Failed to save history:', e); + } + } + + function loadHistory() { + try { + const savedHistory = localStorage.getItem(STORAGE_KEYS.CALCULATION_HISTORY); + if (savedHistory) { + calculationHistory = JSON.parse(savedHistory); + renderHistory(); + } + } catch (e) { + console.warn('Failed to load history:', e); + } + } + + // ===== LOCAL STORAGE FUNCTIONS ===== */ + function saveCalculatorState() { + const state = { + currentOperand, + previousOperand, + operation, + shouldResetScreen, + timestamp: new Date().toISOString() + }; + + try { + localStorage.setItem(STORAGE_KEYS.CALCULATOR_STATE, JSON.stringify(state)); + } catch (e) { + console.warn('Failed to save calculator state:', e); + } + } + + function loadCalculatorState() { + try { + const savedState = localStorage.getItem(STORAGE_KEYS.CALCULATOR_STATE); + if (savedState) { + const state = JSON.parse(savedState); + + // Only restore if saved within last 24 hours + const savedTime = new Date(state.timestamp); + const now = new Date(); + const hoursDiff = (now - savedTime) / (1000 * 60 * 60); + + if (hoursDiff < 24) { + currentOperand = state.currentOperand || '0'; + previousOperand = state.previousOperand || ''; + operation = state.operation || null; + shouldResetScreen = state.shouldResetScreen || false; + } + } + } catch (e) { + console.warn('Failed to load calculator state:', e); + } + } + + // ===== THEME TOGGLE ===== */ + function toggleTheme() { + document.body.classList.toggle('light'); + const theme = document.body.classList.contains('light') ? 'light' : 'dark'; + localStorage.setItem(STORAGE_KEYS.THEME, theme); + + // Update theme icon + updateThemeIcon(theme); + } + + function updateThemeIcon(theme) { + if (theme === 'light') { + // Sun icon for light theme + themeIcon.innerHTML = ` + + + + + + + + + + `; + themeIcon.classList.remove('icon-moon'); + themeIcon.classList.add('icon-sun'); + } else { + // Moon icon for dark theme + themeIcon.innerHTML = ` + + `; + themeIcon.classList.remove('icon-sun'); + themeIcon.classList.add('icon-moon'); + } + } + + // Load saved theme + const savedTheme = localStorage.getItem(STORAGE_KEYS.THEME); + if (savedTheme === 'light') { + document.body.classList.add('light'); + } + + // Initialize theme icon based on current theme + updateThemeIcon(savedTheme === 'light' ? 'light' : 'dark'); + + // ===== START CALCULATOR ===== */ + init(); + \ No newline at end of file diff --git a/projects/calculator/styles.css b/projects/calculator/styles.css index 8e71aa5..d280b25 100644 --- a/projects/calculator/styles.css +++ b/projects/calculator/styles.css @@ -1,56 +1,252 @@ -* { margin: 0; padding: 0; box-sizing: border-box; } - + + /* ===== GLOBAL STYLES ===== */ + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + body { - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - background: #1a1a1a; - color: #f0f0f0; + font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; display: flex; justify-content: center; align-items: center; - min-height: 100vh; - padding: 20px; + padding: 15px; + position: relative; + overflow-x: hidden; + transition: background 1s ease; + } + + /* Animated background particles */ + body::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: radial-gradient(circle, rgba(255,255,255,0.1) 1px, transparent 1px); + background-size: 50px 50px; + animation: backgroundMove 20s linear infinite; + opacity: 0.3; + z-index: 0; + transition: opacity 1s ease; + } + + @keyframes backgroundMove { + 0% { transform: translate(0, 0); } + 100% { transform: translate(50px, 50px); } + } + + /* ===== THEME TOGGLE ===== */ + .theme-toggle-container { + position: absolute; + top: 20px; + right: 20px; + z-index: 100; + } + + .theme-toggle { + background: rgba(255, 255, 255, 0.2); + border: none; + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.5s ease; + color: white; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); + } + + .theme-toggle:hover { + background: rgba(255, 255, 255, 0.3); + transform: rotate(180deg); + } + + .theme-toggle:active { + transform: rotate(180deg) scale(0.95); + } + + .theme-toggle svg { + width: 24px; + height: 24px; + transition: all 0.5s ease; } /* ===== CALCULATOR CONTAINER ===== */ + .calculator-wrapper { + position: relative; + z-index: 1; + width: 100%; + max-width: 380px; + margin: 0 auto; + } + .calculator { - background: #2d2d2d; - border-radius: 20px; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); + background: linear-gradient(145deg, rgba(30, 30, 40, 0.95), rgba(20, 20, 30, 0.95)); + backdrop-filter: blur(20px); + border-radius: 30px; + box-shadow: + 0 20px 60px rgba(0, 0, 0, 0.3), + 0 0 120px rgba(102, 126, 234, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.1); width: 100%; - max-width: 360px; padding: 25px; + animation: slideUp 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); + transition: all 1s ease; + } + + @keyframes slideUp { + 0% { + opacity: 0; + transform: translateY(30px); + } + 100% { + opacity: 1; + transform: translateY(0); + } } - /* ===== DISPLAY ===== */ + /* ===== DISPLAY WITH HISTORY ===== */ .display { - background: #1a1a1a; - border-radius: 10px; - padding: 20px; + background: linear-gradient(145deg, #1a1a2e, #16213e); + border-radius: 20px; + padding: 15px; margin-bottom: 20px; - text-align: right; - min-height: 80px; + min-height: 120px; + max-height: 200px; display: flex; flex-direction: column; - justify-content: flex-end; + position: relative; + overflow: hidden; + box-shadow: + inset 0 2px 10px rgba(0, 0, 0, 0.3), + 0 1px 0 rgba(255, 255, 255, 0.05); + transition: all 1s ease; + } + + .display::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.05), transparent); + animation: shimmer 3s infinite; + } + + @keyframes shimmer { + 0% { left: -100%; } + 100% { left: 100%; } + } + + .history-container { + flex: 1; + overflow-y: auto; + margin-bottom: 10px; + min-height: 60px; + max-height: 120px; + } + + .history-container::-webkit-scrollbar { + width: 4px; + } + + .history-container::-webkit-scrollbar-track { + background: rgba(255, 255, 255, 0.05); + border-radius: 10px; + } + + .history-container::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.2); + border-radius: 10px; + } + + .history-item { + color: rgba(255, 255, 255, 0.6); + font-size: 0.85rem; + margin-bottom: 5px; + padding: 3px 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + cursor: pointer; + transition: all 0.3s ease; + animation: fadeInHistory 0.3s ease; + } + + @keyframes fadeInHistory { + from { + opacity: 0; + transform: translateY(-5px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + .history-item:hover { + color: rgba(255, 255, 255, 0.9); + background: rgba(255, 255, 255, 0.05); + padding-left: 5px; + } + + .history-item:last-child { + border-bottom: none; + } + + .current-calculation { + border-top: 1px solid rgba(255, 255, 255, 0.2); + padding-top: 10px; + margin-top: 5px; } .previous-operand { - color: #888; - font-size: 1.2rem; + color: rgba(255, 255, 255, 0.5); + font-size: 0.9rem; margin-bottom: 5px; - height: 1.5rem; + height: 1.2rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + transition: color 1s ease; } .current-operand { - color: #f0f0f0; - font-size: 2.5rem; + color: #ffffff; + font-size: 2.2rem; font-weight: 300; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + letter-spacing: -1px; + transition: color 1s ease; + text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); + } + + .clear-history { + position: absolute; + top: 10px; + right: 10px; + background: rgba(255, 255, 255, 0.1); + border: none; + border-radius: 10px; + color: rgba(255, 255, 255, 0.7); + padding: 3px 8px; + font-size: 0.7rem; + cursor: pointer; + transition: all 0.3s ease; + z-index: 10; + } + + .clear-history:hover { + background: rgba(255, 255, 255, 0.2); + color: white; } /* ===== BUTTON GRID ===== */ @@ -62,51 +258,358 @@ /* ===== BUTTON STYLES ===== */ button { - background: #333; + background: linear-gradient(145deg, #2d2d3f, #1f1f2e); border: none; border-radius: 50%; - color: #f0f0f0; + color: #ffffff; cursor: pointer; - font-size: 1.5rem; - height: 70px; - width: 70px; - transition: all 0.2s ease; + font-size: 1.4rem; + font-weight: 400; + height: 65px; + width: 65px; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 1s ease, color 1s ease; outline: none; + position: relative; + overflow: hidden; + box-shadow: + 0 4px 15px rgba(0, 0, 0, 0.2), + inset 0 1px 0 rgba(255, 255, 255, 0.1); } - button:focus { - box-shadow: 0 0 0 3px rgba(255, 165, 0, 0.5); + button:hover { + transform: translateY(-2px); + box-shadow: + 0 6px 20px rgba(0, 0, 0, 0.3), + inset 0 1px 0 rgba(255, 255, 255, 0.15); + } + + button:active { + transform: translateY(0) scale(0.95); + box-shadow: + 0 2px 10px rgba(0, 0, 0, 0.2), + inset 0 1px 0 rgba(255, 255, 255, 0.05); } - button:hover { background: #444; } - button:active { transform: scale(0.95); } + button:focus { + box-shadow: + 0 0 0 3px rgba(102, 126, 234, 0.5), + 0 4px 15px rgba(0, 0, 0, 0.2); + } /* ===== SPECIAL BUTTONS ===== */ - .operator { background: #ff9500; color: white; } - .operator:hover { background: #ffad33; } - - .equals { background: #4caf50; color: white; } - .equals:hover { background: #66bb6a; } - - .function { background: #a5a5a5; color: #333; } - .function:hover { background: #bfbfbf; } - - /* ===== ANIMATIONS ===== */ - @keyframes press { + .operator { + background: linear-gradient(145deg, #ff6b6b, #ee5a24); + color: white; + font-weight: 500; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 1s ease; + } + + .operator:hover { + background: linear-gradient(145deg, #ff7979, #f5635f); + box-shadow: + 0 6px 20px rgba(238, 90, 36, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.2); + } + + .equals { + background: linear-gradient(145deg, #4ecdc4, #44a3aa); + color: white; + font-weight: 500; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 1s ease; + } + + .equals:hover { + background: linear-gradient(145deg, #5ed9d0, #4fb3b9); + box-shadow: + 0 6px 20px rgba(78, 205, 196, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.2); + } + + .function { + background: linear-gradient(145deg, #636e72, #2d3436); + color: white; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 1s ease; + } + + .function:hover { + background: linear-gradient(145deg, #747d81, #3d4447); + box-shadow: + 0 6px 20px rgba(99, 110, 114, 0.3), + inset 0 1px 0 rgba(255, 255, 255, 0.15); + } + + .clear { + background: linear-gradient(145deg, #e74c3c, #c0392b); + color: white; + font-weight: 500; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 1s ease; + } + + .clear:hover { + background: linear-gradient(145deg, #ec7063, #cd6155); + box-shadow: + 0 6px 20px rgba(231, 76, 60, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.2); + } + + .backspace { + background: linear-gradient(145deg, #f39c12, #e67e22); + color: white; + font-weight: 500; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 1s ease; + } + + .backspace:hover { + background: linear-gradient(145deg, #f5b041, #eb984e); + box-shadow: + 0 6px 20px rgba(243, 156, 18, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.2); + } + + .percentage { + background: linear-gradient(145deg, #9b59b6, #8e44ad); + color: white; + font-weight: 500; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 1s ease; + } + + .percentage:hover { + background: linear-gradient(145deg, #a569bd, #9c88a8); + box-shadow: + 0 6px 20px rgba(155, 89, 182, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.2); + } + + .sign-toggle { + background: linear-gradient(145deg, #3498db, #2980b9); + color: white; + font-weight: 500; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 1s ease; + } + + .sign-toggle:hover { + background: linear-gradient(145deg, #5dade2, #3498db); + box-shadow: + 0 6px 20px rgba(52, 152, 219, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.2); + } + + /* ===== ENTRANCE ANIMATIONS ===== */ + button { + opacity: 0; + animation: fadeInUp 0.5s ease forwards; + } + + button:nth-child(1) { animation-delay: 0.1s; } + button:nth-child(2) { animation-delay: 0.12s; } + button:nth-child(3) { animation-delay: 0.14s; } + button:nth-child(4) { animation-delay: 0.16s; } + button:nth-child(5) { animation-delay: 0.18s; } + button:nth-child(6) { animation-delay: 0.2s; } + button:nth-child(7) { animation-delay: 0.22s; } + button:nth-child(8) { animation-delay: 0.24s; } + button:nth-child(9) { animation-delay: 0.26s; } + button:nth-child(10) { animation-delay: 0.28s; } + button:nth-child(11) { animation-delay: 0.3s; } + button:nth-child(12) { animation-delay: 0.32s; } + button:nth-child(13) { animation-delay: 0.34s; } + button:nth-child(14) { animation-delay: 0.36s; } + button:nth-child(15) { animation-delay: 0.38s; } + button:nth-child(16) { animation-delay: 0.4s; } + button:nth-child(17) { animation-delay: 0.42s; } + button:nth-child(18) { animation-delay: 0.44s; } + + @keyframes fadeInUp { + 0% { + opacity: 0; + transform: translateY(20px); + } + 100% { + opacity: 1; + transform: translateY(0); + } + } + + /* ===== ERROR STATE ===== */ + .error { + color: #ff6b6b !important; + animation: shake 0.5s ease; + } + + @keyframes shake { + 0%, 100% { transform: translateX(0); } + 10%, 30%, 50%, 70%, 90% { transform: translateX(-2px); } + 20%, 40%, 60%, 80% { transform: translateX(2px); } + } + + /* ===== SUCCESS ANIMATION ===== */ + .success { + animation: pulse 0.5s ease; + } + + @keyframes pulse { 0% { transform: scale(1); } - 50% { transform: scale(0.95); } + 50% { transform: scale(1.05); } 100% { transform: scale(1); } } - .press-animation { animation: press 0.2s ease; } + /* ===== RESPONSIVE DESIGN ===== */ + @media (max-width: 480px) { + body { + padding: 10px; + } + + .calculator { + padding: 15px; + border-radius: 20px; + } + + button { + height: 55px; + width: 55px; + font-size: 1.2rem; + } + + .current-operand { + font-size: 2rem; + } + + .previous-operand { + font-size: 0.9rem; + } + + .theme-toggle { + width: 45px; + height: 45px; + } + + .theme-toggle-container { + top: 15px; + right: 15px; + } + } - /* ===== RESPONSIVE ===== */ - @media (max-width: 400px) { - .calculator { padding: 15px; } - button { height: 60px; width: 60px; font-size: 1.3rem; } - .current-operand { font-size: 2rem; } - .previous-operand { font-size: 1rem; } + @media (max-width: 320px) { + button { + height: 50px; + width: 50px; + font-size: 1.1rem; + } + + .current-operand { + font-size: 1.8rem; + } + + .buttons { + gap: 10px; + } } - /* ===== ERROR STATE ===== */ - .error { color: #ff5252; } \ No newline at end of file + /* ===== LIGHT THEME ===== */ + body.light { + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + } + + body.light .calculator { + background: linear-gradient(145deg, rgba(255, 255, 255, 0.95), rgba(240, 240, 245, 0.95)); + box-shadow: + 0 20px 60px rgba(0, 0, 0, 0.1), + 0 0 120px rgba(102, 126, 234, 0.05); + } + + body.light .display { + background: linear-gradient(145deg, #f8f9fa, #e9ecef); + } + + body.light .previous-operand { + color: rgba(0, 0, 0, 0.5); + } + + body.light .current-operand { + color: #212529; + } + + body.light .history-item { + color: rgba(0, 0, 0, 0.6); + border-bottom-color: rgba(0, 0, 0, 0.1); + } + + body.light .history-item:hover { + color: rgba(0, 0, 0, 0.9); + background: rgba(0, 0, 0, 0.05); + } + + body.light .current-calculation { + border-top-color: rgba(0, 0, 0, 0.2); + } + + body.light .clear-history { + background: rgba(0, 0, 0, 0.1); + color: rgba(0, 0, 0, 0.7); + } + + body.light .clear-history:hover { + background: rgba(0, 0, 0, 0.2); + color: #000; + } + + body.light button { + background: linear-gradient(145deg, #e9ecef, #dee2e6); + color: #212529; + } + + body.light .operator { + background: linear-gradient(145deg, #ff9a9e, #fad0c4); + } + + body.light .equals { + background: linear-gradient(145deg, #a8edea, #fed6e3); + } + + body.light .function { + background: linear-gradient(145deg, #dfe6e9, #b2bec3); + } + + body.light .clear { + background: linear-gradient(145deg, #f5b7b1, #f1948a); + } + + body.light .backspace { + background: linear-gradient(145deg, #fdebd0, #fad7a0); + } + + body.light .percentage { + background: linear-gradient(145deg, #e8daef, #d7bde2); + } + + body.light .sign-toggle { + background: linear-gradient(145deg, #d6eaf8, #aed6f1); + } + + body.light .theme-toggle { + background: rgba(0, 0, 0, 0.2); + color: #333; + } + + body.light .theme-toggle:hover { + background: rgba(0, 0, 0, 0.3); + } + + /* ===== ICON ANIMATIONS ===== */ + .icon-sun { + animation: rotateSun 20s linear infinite; + } + + @keyframes rotateSun { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } + } + + .icon-moon { + animation: floatMoon 3s ease-in-out infinite; + } + + @keyframes floatMoon { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-3px); } + }