From f1faedf60482f5cd7067550519164cffde117c31 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Jan 2026 16:53:20 +0000 Subject: [PATCH 1/3] Initial plan From 3a992ef23856e2bce7543ec5fa52ab4486839415 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Jan 2026 16:58:39 +0000 Subject: [PATCH 2/3] Implement Lord of the Rings themed scientific calculator with dark/light mode Co-authored-by: haslam93 <36418598+haslam93@users.noreply.github.com> --- public/client.js | 68 +++++++- public/default.css | 378 +++++++++++++++++++++++++++++++++------------ public/index.html | 49 ++++-- 3 files changed, 384 insertions(+), 111 deletions(-) diff --git a/public/client.js b/public/client.js index 1c60f86..d8d3a63 100644 --- a/public/client.js +++ b/public/client.js @@ -15,11 +15,77 @@ var state = states.start; var operand1 = 0; var operand2 = 0; var operation = null; +var pendingScientific = null; + +// Theme toggle function +function toggleTheme() { + const body = document.body; + const themeIcon = document.querySelector('.theme-icon'); + + if (body.classList.contains('dark-mode')) { + body.classList.remove('dark-mode'); + body.classList.add('light-mode'); + themeIcon.textContent = '🌙'; + } else { + body.classList.remove('light-mode'); + body.classList.add('dark-mode'); + themeIcon.textContent = '☀️'; + } +} + +// Scientific functions handler +function scientificPressed(func) { + var currentValue = getValue(); + var result; + + switch (func) { + case 'sin': + result = Math.sin(currentValue * Math.PI / 180); + break; + case 'cos': + result = Math.cos(currentValue * Math.PI / 180); + break; + case 'tan': + result = Math.tan(currentValue * Math.PI / 180); + break; + case 'log': + result = Math.log10(currentValue); + break; + case 'sqrt': + result = Math.sqrt(currentValue); + break; + case 'square': + result = currentValue * currentValue; + break; + case 'exp': + result = Math.exp(currentValue); + break; + case 'pi': + result = Math.PI; + break; + case 'power': + // Store for power operation (x^y) + operand1 = currentValue; + operation = '^'; + state = states.operator; + return; + default: + return; + } + + setValue(result); + state = states.complete; +} function calculate(operand1, operand2, operation) { + // Handle power operation locally + if (operation === '^') { + setValue(Math.pow(operand1, operand2)); + return; + } + var uri = location.origin + "/arithmetic"; - // TODO: Add operator switch (operation) { case '+': uri += "?operation=add"; diff --git a/public/default.css b/public/default.css index c652a2b..69b5869 100644 --- a/public/default.css +++ b/public/default.css @@ -1,44 +1,128 @@ +/* Root Variables for Dark Mode (Mordor Theme) */ +:root { + --bg-primary: #1a1612; + --bg-secondary: #2a2218; + --bg-tertiary: #3a3028; + --text-primary: #d4af37; + --text-secondary: #c19a6b; + --text-display: #ffd700; + --border-color: #8b4513; + --button-bg: #3e2723; + --button-hover: #5d4037; + --button-operator: #8b4513; + --button-operator-hover: #a0522d; + --button-equals: #d4af37; + --button-equals-hover: #ffd700; + --button-scientific: #4a3728; + --shadow-color: rgba(0, 0, 0, 0.5); +} + +/* Light Mode Variables (Shire/Rivendell Theme) */ +BODY.light-mode { + --bg-primary: #f5f0e8; + --bg-secondary: #e8ddc8; + --bg-tertiary: #dcd0b8; + --text-primary: #3e2723; + --text-secondary: #5d4037; + --text-display: #2e1810; + --border-color: #d4af37; + --button-bg: #e8ddc8; + --button-hover: #dcd0b8; + --button-operator: #d4af37; + --button-operator-hover: #c19a6b; + --button-equals: #8b4513; + --button-equals-hover: #a0522d; + --button-scientific: #f5e6d3; + --shadow-color: rgba(0, 0, 0, 0.2); +} + BODY { - height: 100%; - width: 100%; + height: 100vh; + width: 100vw; padding: 0; margin: 0; - background-color: #1b4076; + background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 50%, var(--bg-tertiary) 100%); + font-family: 'Cinzel', serif; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + position: relative; + transition: background 0.3s ease; } -@media screen and (min-device-width: 500px) and (min-device-height: 1024px) { - BODY { - transform: scale(1.75); - transform-origin: 50% 0; - height: 50%; - } +/* Theme Toggle Button */ +.theme-toggle { + position: fixed; + top: 20px; + right: 20px; + width: 60px; + height: 60px; + border-radius: 50%; + background: var(--button-operator); + border: 3px solid var(--border-color); + cursor: pointer; + z-index: 1000; + font-size: 28px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + box-shadow: 0 4px 10px var(--shadow-color); } -@media screen and (min-device-width: 1024px) and (min-device-height: 1366px) { - BODY { - transform: scale(2.0); - transform-origin: 50% 0; - height: 50%; - } +.theme-toggle:hover { + transform: scale(1.1) rotate(15deg); + background: var(--button-operator-hover); +} + +.theme-icon { + transition: transform 0.3s ease; } .container { - min-width: 250px; - min-height: 531px; - width: 250px; - padding: 25px; + width: 90vw; + max-width: 600px; + height: 90vh; + max-height: 800px; + padding: 30px; margin: 0 auto; position: relative; - background-image: url(background.png); - background-size: 300px 531px; - background-repeat: no-repeat; - background-position: center top; + background: var(--bg-secondary); + border: 5px solid var(--border-color); + border-radius: 20px; + box-shadow: 0 10px 50px var(--shadow-color), + inset 0 0 20px rgba(212, 175, 55, 0.1); + display: flex; + flex-direction: column; + transition: all 0.3s ease; +} + +.header { + text-align: center; + margin-bottom: 20px; + color: var(--text-primary); +} + +.header h1 { + font-family: 'Uncial Antiqua', cursive; + font-size: 2.5rem; + margin: 0 0 5px 0; + text-shadow: 2px 2px 4px var(--shadow-color); + letter-spacing: 2px; +} + +.header .subtitle { + font-size: 0.9rem; + font-style: italic; + margin: 0; + opacity: 0.8; + letter-spacing: 1px; } #results { position: relative; - top: 0; - left: 0; + margin-bottom: 20px; } #buttons { @@ -46,30 +130,41 @@ BODY { } #result { - background-color: #9b9b9b; - width: 226px; - height: 63px; + background: var(--bg-tertiary); + width: 100%; + height: 80px; margin: 0; - padding: 0 12px; - position: absolute; - border: 0; - left: 0; - top: 32px; - font-family: system-ui; - font-size: 25px; + padding: 20px; + border: 3px solid var(--border-color); + border-radius: 10px; + font-family: 'Cinzel', serif; + font-size: 32px; text-align: right; + color: var(--text-display); + box-shadow: inset 0 2px 10px var(--shadow-color); + display: flex; + align-items: center; + justify-content: flex-end; + box-sizing: border-box; + overflow: hidden; } -/*BUTTON { - background-color: #d5d5d5; - border: 0; - border-radius: 0; - width: 55px; - height: 42px; +#loading { position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 40px; + height: 40px; + border: 4px solid var(--border-color); + border-top-color: transparent; + border-radius: 50%; + animation: spin 1s linear infinite; +} - font-size: 22px; -}*/ +@keyframes spin { + to { transform: translate(-50%, -50%) rotate(360deg); } +} #sign, #clear { @@ -92,95 +187,184 @@ BODY { display: inline-block; width: 25px; height: 45px; - background: url('digits.png') 0 0 no-repeat; - background-size: cover; - margin-top: 10px; - font: 0/0 Arial; - color: rgba(255, 255, 255, 0); - text-indent: -9999px; + margin-top: 0; + font: inherit; + color: var(--text-display); + text-indent: 0; z-index: 1; } -.digit0 { - background-position: 0 0; +.digit0, .digit1, .digit2, .digit3, .digit4, +.digit5, .digit6, .digit7, .digit8, .digit9 { + color: var(--text-display); } -.digit1 { - background-position: -25px 0; +.resultchar.decimal { + width: 10px; + color: var(--text-display); +} + +.resultchar.negative { + width: 17px; + color: var(--text-display); } -.digit2 { - background-position: -50px 0; +.resultchar.exponent { + width: 25px; + color: var(--text-display); } -.digit3 { - background-position: -75px 0; +.box { + box-sizing: border-box; + width: 100%; + flex: 1; + display: flex; + flex-direction: column; } -.digit4 { - background-position: -100px 0; +.span-2 { + grid-column: span 2; } -.digit5 { - background-position: -125px 0; +.calculator-buttons { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 8px; + border: 0; + height: 100%; } -.digit6 { - background-position: -150px 0; +.calculator { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; } -.digit7 { - background-position: -175px 0; +.btn { + font-family: 'Cinzel', serif; + font-size: 1.2em; + font-weight: 600; + min-height: 60px; + border: 2px solid var(--border-color); + background: var(--button-bg); + color: var(--text-primary); + margin: 0; + border-radius: 8px; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 3px 8px var(--shadow-color); + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); } -.digit8 { - background-position: -200px 0; +.btn:hover { + background: var(--button-hover); + transform: translateY(-2px); + box-shadow: 0 5px 12px var(--shadow-color); } -.digit9 { - background-position: -225px 0; +.btn:active { + transform: translateY(0); + box-shadow: 0 2px 4px var(--shadow-color); } -.resultchar.decimal { - width: 7px; - background-position: -250px 0; +.btn-operator { + background: var(--button-operator); + font-weight: 700; + font-size: 1.4em; } -.resultchar.negative { - background-position: -257px 0; - width: 17px; +.btn-operator:hover { + background: var(--button-operator-hover); } -.resultchar.exponent { - background-position: -275px 0; - width: 25px; +.btn-equals { + background: var(--button-equals); + font-weight: 700; + font-size: 1.4em; } -.box { - box-sizing: border-box; - top: 220px; - width: 250px; - position: absolute; +.btn-equals:hover { + background: var(--button-equals-hover); } -.span-2 { - grid-column: span 2; +.btn-scientific { + background: var(--button-scientific); + font-size: 1em; } -.calculator-buttons { - display: grid; - grid-template-columns: repeat(4, 1fr); - border: 0; +.btn-scientific:hover { + background: var(--button-hover); } -.calculator { - max-width: 320px; +/* Responsive Design */ +@media screen and (max-width: 768px) { + .container { + width: 95vw; + height: 95vh; + padding: 20px; + } + + .header h1 { + font-size: 1.8rem; + } + + .header .subtitle { + font-size: 0.8rem; + } + + #result { + height: 60px; + font-size: 24px; + padding: 15px; + } + + .btn { + font-size: 1em; + min-height: 50px; + } + + .theme-toggle { + width: 50px; + height: 50px; + font-size: 24px; + } } -.btn { - font-size: 1em; - height: 45px; - border: 1px solid black; - background-color: #d5d5d5; - margin: 4px; +@media screen and (max-height: 700px) { + .container { + padding: 15px; + } + + .header h1 { + font-size: 1.5rem; + margin-bottom: 2px; + } + + .header .subtitle { + font-size: 0.7rem; + } + + .header { + margin-bottom: 10px; + } + + #result { + height: 50px; + font-size: 20px; + padding: 10px; + } + + #results { + margin-bottom: 10px; + } + + .calculator-buttons { + gap: 5px; + } + + .btn { + font-size: 0.9em; + min-height: 40px; + } } diff --git a/public/index.html b/public/index.html index 400c454..680739c 100644 --- a/public/index.html +++ b/public/index.html @@ -1,12 +1,20 @@ - Calculator + The One Calculator + - + +
+
+

The One Calculator

+

One Calculator to rule them all

+
0
@@ -16,31 +24,46 @@
- - - + + + + + + + + + + + + + + + + + + - + + - + + - + - + + - - - - +
From c276c0fd4cc16e95b599d6cd4c4369f2bb2ab380 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:03:06 +0000 Subject: [PATCH 3/3] Add HTML5 DOCTYPE, theme persistence, input validation, and type attributes to buttons Co-authored-by: haslam93 <36418598+haslam93@users.noreply.github.com> --- public/client.js | 51 +++++++++++++++++++++++++++++++++++--- public/index.html | 62 ++++++++++++++++++++++++----------------------- 2 files changed, 80 insertions(+), 33 deletions(-) diff --git a/public/client.js b/public/client.js index d8d3a63..0be1fc3 100644 --- a/public/client.js +++ b/public/client.js @@ -15,9 +15,14 @@ var state = states.start; var operand1 = 0; var operand2 = 0; var operation = null; -var pendingScientific = null; -// Theme toggle function +// Initialize calculator on load +function initCalculator() { + setValue(0); + loadThemePreference(); +} + +// Theme toggle function with localStorage persistence function toggleTheme() { const body = document.body; const themeIcon = document.querySelector('.theme-icon'); @@ -26,14 +31,34 @@ function toggleTheme() { body.classList.remove('dark-mode'); body.classList.add('light-mode'); themeIcon.textContent = '🌙'; + localStorage.setItem('calculatorTheme', 'light'); } else { body.classList.remove('light-mode'); body.classList.add('dark-mode'); themeIcon.textContent = '☀️'; + localStorage.setItem('calculatorTheme', 'dark'); } } -// Scientific functions handler +// Load saved theme preference +function loadThemePreference() { + const savedTheme = localStorage.getItem('calculatorTheme'); + const body = document.body; + const themeIcon = document.querySelector('.theme-icon'); + + if (savedTheme === 'light') { + body.classList.remove('dark-mode'); + body.classList.add('light-mode'); + themeIcon.textContent = '🌙'; + } else { + // Default to dark mode + body.classList.remove('light-mode'); + body.classList.add('dark-mode'); + themeIcon.textContent = '☀️'; + } +} + +// Scientific functions handler with input validation function scientificPressed(func) { var currentValue = getValue(); var result; @@ -46,12 +71,26 @@ function scientificPressed(func) { result = Math.cos(currentValue * Math.PI / 180); break; case 'tan': + // Check for tan(90) and other problematic angles + var angle = currentValue % 360; + if (angle === 90 || angle === 270 || angle === -90 || angle === -270) { + setError(); + return; + } result = Math.tan(currentValue * Math.PI / 180); break; case 'log': + if (currentValue <= 0) { + setError(); + return; + } result = Math.log10(currentValue); break; case 'sqrt': + if (currentValue < 0) { + setError(); + return; + } result = Math.sqrt(currentValue); break; case 'square': @@ -73,6 +112,12 @@ function scientificPressed(func) { return; } + // Check for invalid results + if (!isFinite(result) || isNaN(result)) { + setError(); + return; + } + setValue(result); state = states.complete; } diff --git a/public/index.html b/public/index.html index 680739c..cabef93 100644 --- a/public/index.html +++ b/public/index.html @@ -1,13 +1,15 @@ - + + + The One Calculator - -
@@ -25,45 +27,45 @@

The One Calculator

- - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + +