// EarthBound-inspired color palette (matches NpcInfoPanel) const EB = { bgDeep: '#0c0824', bgPanel: '#141038', borderOuter: '#7878d8', borderInner: '#5858b8', borderGap: '#1c1450', textPrimary: '#f0f0ff', textSecondary: '#9898d0', textMuted: '#6868a8', shine: 'rgba(200,200,255,0.08)', }; interface Command { key: string; label: string; } export class CommandPanel { private outerFrame: HTMLDivElement; private listContainer: HTMLDivElement; private visible = false; constructor(id = 'command-panel', title = 'COMMANDS', commands: Command[] = [{ key: '1', label: 'Spawn NPC' }]) { // Outer frame (doubled border, same as NpcInfoPanel) this.outerFrame = document.createElement('div'); this.outerFrame.id = id; this.outerFrame.style.cssText = ` position: fixed; bottom: 16px; right: 16px; min-width: 160px; border-radius: 12px; border: 3px solid ${EB.borderOuter}; background: ${EB.borderGap}; z-index: 1000; opacity: 0; transform: translateY(20px); transition: opacity 0.3s cubic-bezier(0.22, 1, 0.36, 1), transform 0.3s cubic-bezier(0.22, 1, 0.36, 1); pointer-events: none; box-shadow: 0 0 16px rgba(80, 60, 160, 0.3), 0 4px 20px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(160, 160, 255, 0.15); `; // Inner container const container = document.createElement('div'); container.style.cssText = ` margin: 3px; border-radius: 8px; border: 2px solid ${EB.borderInner}; background: ${EB.bgPanel}; overflow: hidden; position: relative; padding: 8px 12px 10px; font-family: 'Press Start 2P', monospace; `; // Shine overlay const shine = document.createElement('div'); shine.style.cssText = ` position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient( 135deg, ${EB.shine} 0%, transparent 40%, transparent 60%, rgba(0,0,0,0.05) 100% ); pointer-events: none; z-index: 1; `; container.appendChild(shine); // Title const titleEl = document.createElement('div'); titleEl.style.cssText = ` font-size: 9px; color: ${EB.textMuted}; text-align: center; letter-spacing: 4px; padding-bottom: 6px; user-select: none; position: relative; z-index: 2; `; titleEl.textContent = `\u25C6 ${title} \u25C6`; container.appendChild(titleEl); // Commands list this.listContainer = document.createElement('div'); this.listContainer.style.cssText = ` display: flex; flex-direction: column; gap: 4px; position: relative; z-index: 2; `; container.appendChild(this.listContainer); this.outerFrame.appendChild(container); document.body.appendChild(this.outerFrame); // Add commands for (const cmd of commands) { this.addCommand(cmd); } } private addCommand(cmd: Command): void { const row = document.createElement('div'); row.style.cssText = ` display: flex; align-items: center; gap: 8px; `; const keyBadge = document.createElement('div'); keyBadge.style.cssText = ` font-size: 10px; color: ${EB.bgDeep}; background: ${EB.borderOuter}; border-radius: 3px; padding: 2px 5px; min-width: 12px; text-align: center; text-shadow: none; font-weight: bold; box-shadow: 0 1px 0 rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.2); `; keyBadge.textContent = cmd.key; const label = document.createElement('div'); label.style.cssText = ` font-size: 10px; color: ${EB.textSecondary}; letter-spacing: 0.5px; `; label.textContent = cmd.label; row.appendChild(keyBadge); row.appendChild(label); this.listContainer.appendChild(row); } show(): void { if (this.visible) return; this.visible = true; this.outerFrame.style.opacity = '1'; this.outerFrame.style.transform = 'translateY(0)'; this.outerFrame.style.pointerEvents = 'auto'; } hide(): void { if (!this.visible) return; this.visible = false; this.outerFrame.style.opacity = '0'; this.outerFrame.style.transform = 'translateY(20px)'; this.outerFrame.style.pointerEvents = 'none'; } isVisible(): boolean { return this.visible; } destroy(): void { this.outerFrame.remove(); } }