diff --git a/samples/hp48/index.html b/samples/hp48/index.html
index a4b3bd1..53caab0 100644
--- a/samples/hp48/index.html
+++ b/samples/hp48/index.html
@@ -16,6 +16,20 @@
--key-text: #f2f2f2;
--accent: #8cff6d;
--border: #111;
+ --key-number: #5a5a5a;
+ --key-number-2: #444;
+ --key-arithmetic: #7f5c24;
+ --key-arithmetic-2: #5f4216;
+ --key-trig: #2d6d73;
+ --key-trig-2: #1f4f54;
+ --key-stack: #6b4a8f;
+ --key-stack-2: #4f356b;
+ --key-special: #3d5d8a;
+ --key-special-2: #2c4464;
+ --key-danger: #8a3f3f;
+ --key-danger-2: #632d2d;
+ --key-enter: #5d8a3d;
+ --key-enter-2: #45662e;
}
* { box-sizing: border-box; }
@@ -124,34 +138,6 @@
padding: 14px;
}
- .title {
- color: #fff;
- margin: 0 0 10px;
- font-size: 14px;
- text-transform: uppercase;
- letter-spacing: 0.08em;
- }
-
- .keypad-labels {
- display: grid;
- grid-template-columns: 4fr 3fr 2fr;
- gap: 12px;
- margin-bottom: 10px;
- }
-
- .keypad-label {
- color: #d8d8d8;
- font-size: 11px;
- font-weight: bold;
- letter-spacing: 0.08em;
- text-transform: uppercase;
- text-align: center;
- padding: 6px 8px;
- border-radius: 999px;
- background: rgba(255, 255, 255, 0.05);
- border: 1px solid rgba(255, 255, 255, 0.08);
- }
-
.keypad-wrap {
display: grid;
grid-template-columns: minmax(0, 4fr) minmax(0, 3fr) minmax(0, 2fr);
@@ -185,11 +171,41 @@
min-height: 46px;
}
- .keypad button.active-toggle {
+ .keypad button.active-toggle,
+ .active-toggle {
background: linear-gradient(180deg, #6a8c52, #49693a);
color: #fff;
}
+ .key-number {
+ background: linear-gradient(180deg, var(--key-number), var(--key-number-2));
+ }
+
+ .key-arithmetic {
+ background: linear-gradient(180deg, var(--key-arithmetic), var(--key-arithmetic-2));
+ }
+
+ .key-trigonometry {
+ background: linear-gradient(180deg, var(--key-trig), var(--key-trig-2));
+ }
+
+ .key-stack {
+ background: linear-gradient(180deg, var(--key-stack), var(--key-stack-2));
+ }
+
+ .key-special {
+ background: linear-gradient(180deg, var(--key-special), var(--key-special-2));
+ }
+
+ .key-danger {
+ background: linear-gradient(180deg, var(--key-danger), var(--key-danger-2));
+ }
+
+ .key-enter {
+ background: linear-gradient(180deg, var(--key-enter), var(--key-enter-2));
+ font-weight: bold;
+ }
+
.keypad-group button.enter-tall {
grid-row: span 2;
}
@@ -230,12 +246,9 @@
min-height: 40px;
}
- .error {
- margin-top: 10px;
- min-height: 20px;
- color: #ff8a8a;
- font-family: "Courier New", monospace;
- font-size: 13px;
+ .display-error {
+ color: #8a2a1c;
+ font-weight: bold;
}
@@ -244,7 +257,6 @@
padding: 16px;
}
- .keypad-labels,
.keypad-wrap {
gap: 8px;
}
@@ -265,7 +277,6 @@
border-radius: 16px;
}
- .keypad-labels,
.keypad-wrap {
grid-template-columns: 1fr;
}
@@ -297,12 +308,6 @@
-
Calculator Keys
-
-
Functions
-
Numbers
-
Operators
-
-
@@ -331,7 +335,6 @@
const stackEl = document.getElementById('stack');
const displayEl = document.getElementById('display');
- const errorEl = document.getElementById('error');
const modeLabel = document.getElementById('modeLabel');
const functionsKeypadEl = document.getElementById('functionsKeypad');
const numbersKeypadEl = document.getElementById('numbersKeypad');
@@ -344,6 +347,7 @@
let openMenuName = null;
let isMovingStackItem = false;
let stackSnapshotBeforeMove = null;
+ let currentErrorMessage = '';
function getKeypadLayout() {
return {
@@ -427,6 +431,42 @@
};
}
+ function getKeyClassName(key) {
+ if (key.type === 'input') {
+ return 'key-number';
+ }
+
+ if (key.value === 'clear') {
+ return 'key-danger';
+ }
+
+ if (key.value === 'enter') {
+ return 'key-enter';
+ }
+
+ if (key.type === 'special') {
+ return 'key-special';
+ }
+
+ const stackCommands = new Set(['neg']);
+ const arithmeticCommands = new Set(['add', 'sub', 'mul', 'div', 'mod', 'pow', 'sqr', 'sqrt', 'recip', 'log', 'ln']);
+ const trigonometryCommands = new Set(['sin', 'cos', 'tan', 'asin', 'acos', 'atan']);
+
+ if (stackCommands.has(key.value)) {
+ return 'key-stack';
+ }
+
+ if (arithmeticCommands.has(key.value)) {
+ return 'key-arithmetic';
+ }
+
+ if (trigonometryCommands.has(key.value)) {
+ return 'key-trigonometry';
+ }
+
+ return '';
+ }
+
function renderKeypadGroup(groupEl, layout) {
groupEl.innerHTML = '';
const occupied = new Set();
@@ -449,6 +489,10 @@
const button = document.createElement('button');
button.textContent = key.label;
+ const keyClassName = getKeyClassName(key);
+ if (keyClassName) {
+ button.classList.add(keyClassName);
+ }
button.style.gridColumn = String(colIndex + 1);
button.style.gridRow = `${rowIndex + 1} / span ${key.rowspan || 1}`;
if (key.rowspan && key.rowspan > 1) {
@@ -591,7 +635,8 @@
execute(key.value);
}
} catch (error) {
- errorEl.textContent = error.message;
+ currentErrorMessage = error.message;
+ render();
}
}
@@ -719,17 +764,23 @@
}
stackEl.innerHTML = lines.join('');
- if (calc.isEditing) {
+ if (currentErrorMessage) {
+ displayEl.textContent = `ERROR: ${currentErrorMessage}`;
+ displayEl.classList.add('display-error');
+ } else if (calc.isEditing) {
displayEl.textContent = `ENTERING: ${calc.inputValue}`;
+ displayEl.classList.remove('display-error');
} else if (isMovingStackItem && hasStackSelection()) {
displayEl.textContent = `MOVING: ${['X', 'Y', 'Z', 'T'][stackCursor] || '?'}`;
+ displayEl.classList.remove('display-error');
} else if (hasStackSelection()) {
displayEl.textContent = `SELECTED: ${['X', 'Y', 'Z', 'T'][stackCursor] || '?'}`;
+ displayEl.classList.remove('display-error');
} else {
displayEl.textContent = 'READY';
+ displayEl.classList.remove('display-error');
}
modeLabel.textContent = calc.angleMode;
- errorEl.textContent = '';
renderKeypad();
}
@@ -773,10 +824,12 @@
clearStackSelection();
calc.command(name);
}
+ currentErrorMessage = '';
syncInputFromState();
render();
} catch (error) {
- errorEl.textContent = error.message;
+ currentErrorMessage = error.message;
+ render();
}
}
@@ -960,7 +1013,8 @@
execute(action.value);
}
} catch (error) {
- errorEl.textContent = error.message;
+ currentErrorMessage = error.message;
+ render();
}
}