export class FeedbackUI { constructor(parentContainer, game) { this.parentContainer = parentContainer; this.game = game; this.logContainer = null; this.initLogContainer(); } initLogContainer() { this.logContainer = document.createElement('div'); Object.assign(this.logContainer.style, { position: 'absolute', top: '20%', // Leave space for top HUD right: '20px', width: '350px', height: '60vh', // Fixed height or max height? User said "muy pequeño". Let's give it good vertical space. maxHeight: 'none', overflowY: 'auto', display: 'flex', flexDirection: 'column', alignItems: 'flex-start', // Align text to left pointerEvents: 'none', // Allow clicking through if needed, but 'auto' for scroll? // We need pointerEvents auto for scrolling. pointerEvents: 'auto', zIndex: '400', fontFamily: '"Cinzel", serif', scrollbarWidth: 'thin', scrollbarColor: '#444 #222' }); // Add a subtle background this.logContainer.style.background = 'linear-gradient(to left, rgba(0,0,0,0.8), rgba(0,0,0,0))'; this.logContainer.style.padding = '10px'; this.logContainer.style.borderRadius = '8px'; this.logContainer.style.borderRight = '2px solid #555'; this.parentContainer.appendChild(this.logContainer); } addLogMessage(message, type = 'info') { const entry = document.createElement('div'); Object.assign(entry.style, { width: '100%', marginBottom: '6px', fontSize: '14px', color: '#ccc', textShadow: '1px 1px 0 #000', opacity: '0', transition: 'opacity 0.3s', lineHeight: '1.4' }); // Color coding based on type if (type === 'combat-hit') entry.style.color = '#ff6666'; if (type === 'combat-miss') entry.style.color = '#aaaaaa'; if (type === 'combat-kill') entry.style.color = '#ff3333'; if (type === 'success') entry.style.color = '#66ff66'; if (type === 'warning') entry.style.color = '#ffcc00'; if (type === 'system') entry.style.color = '#88ccff'; if (type === 'event-log') entry.style.color = '#44ff44'; // Bright Green entry.innerHTML = message; this.logContainer.appendChild(entry); // Auto scroll to bottom this.logContainer.scrollTop = this.logContainer.scrollHeight; // Fade In requestAnimationFrame(() => { entry.style.opacity = '1'; }); // Optional: Fade out very old messages? Or keep history? // Let's keep history for now, maybe limit children coune if (this.logContainer.children.length > 50) { this.logContainer.removeChild(this.logContainer.firstChild); } } showModal(title, message, onClose) { const overlay = document.createElement('div'); Object.assign(overlay.style, { position: 'absolute', top: '0', left: '0', width: '100%', height: '100%', backgroundColor: 'rgba(0, 0, 0, 0.7)', display: 'flex', justifyContent: 'center', alignItems: 'center', pointerEvents: 'auto', zIndex: '1000' }); const content = document.createElement('div'); Object.assign(content.style, { backgroundColor: '#222', border: '2px solid #888', borderRadius: '8px', padding: '20px', width: '300px', textAlign: 'center', color: '#fff', fontFamily: 'sans-serif' }); const titleEl = document.createElement('h2'); titleEl.textContent = title; Object.assign(titleEl.style, { marginTop: '0', color: '#f44' }); content.appendChild(titleEl); const msgEl = document.createElement('p'); msgEl.innerHTML = message; Object.assign(msgEl.style, { fontSize: '16px', lineHeight: '1.5' }); content.appendChild(msgEl); const btn = document.createElement('button'); btn.textContent = 'Entendido'; Object.assign(btn.style, { marginTop: '20px', padding: '10px 20px', fontSize: '16px', cursor: 'pointer', backgroundColor: '#444', color: '#fff', border: '1px solid #888' }); btn.onclick = () => { if (overlay.parentNode) this.parentContainer.removeChild(overlay); if (onClose) onClose(); }; content.appendChild(btn); overlay.appendChild(content); this.parentContainer.appendChild(overlay); } showConfirm(title, message, onConfirm) { const overlay = document.createElement('div'); Object.assign(overlay.style, { position: 'absolute', top: '0', left: '0', width: '100%', height: '100%', backgroundColor: 'rgba(0, 0, 0, 0.7)', display: 'flex', justifyContent: 'center', alignItems: 'center', pointerEvents: 'auto', zIndex: '1000' }); const content = document.createElement('div'); Object.assign(content.style, { backgroundColor: '#222', border: '2px solid #888', borderRadius: '8px', padding: '20px', width: '300px', textAlign: 'center', color: '#fff', fontFamily: 'sans-serif' }); const titleEl = document.createElement('h2'); titleEl.textContent = title; Object.assign(titleEl.style, { marginTop: '0', color: '#f44' }); content.appendChild(titleEl); const msgEl = document.createElement('p'); msgEl.innerHTML = message; Object.assign(msgEl.style, { fontSize: '16px', lineHeight: '1.5' }); content.appendChild(msgEl); const buttons = document.createElement('div'); Object.assign(buttons.style, { display: 'flex', justifyContent: 'space-around', marginTop: '20px' }); const cancelBtn = document.createElement('button'); cancelBtn.textContent = 'Cancelar'; Object.assign(cancelBtn.style, { padding: '10px 20px', fontSize: '16px', cursor: 'pointer', backgroundColor: '#555', color: '#fff', border: '1px solid #888' }); cancelBtn.onclick = () => { this.parentContainer.removeChild(overlay); }; buttons.appendChild(cancelBtn); const confirmBtn = document.createElement('button'); confirmBtn.textContent = 'Aceptar'; Object.assign(confirmBtn.style, { padding: '10px 20px', fontSize: '16px', cursor: 'pointer', backgroundColor: '#2a5', color: '#fff', border: '1px solid #888' }); confirmBtn.onclick = () => { if (onConfirm) onConfirm(); this.parentContainer.removeChild(overlay); }; buttons.appendChild(confirmBtn); content.appendChild(buttons); overlay.appendChild(content); this.parentContainer.appendChild(overlay); } showEventCard(cardData, callback) { const overlay = document.createElement('div'); Object.assign(overlay.style, { position: 'absolute', top: '0', left: '0', width: '100%', height: '100%', backgroundColor: 'rgba(0, 0, 0, 0.85)', display: 'flex', justifyContent: 'center', alignItems: 'center', pointerEvents: 'auto', zIndex: '2000' }); // Card Container const card = document.createElement('div'); Object.assign(card.style, { backgroundColor: '#1a1a1a', backgroundImage: 'repeating-linear-gradient(45deg, #222 25%, transparent 25%, transparent 75%, #222 75%, #222), repeating-linear-gradient(45deg, #222 25%, #1a1a1a 25%, #1a1a1a 75%, #222 75%, #222)', backgroundPosition: '0 0, 10px 10px', backgroundSize: '20px 20px', border: '4px solid #8b0000', borderRadius: '12px', padding: '30px', width: '320px', textAlign: 'center', color: '#fff', fontFamily: '"Cinzel", serif', boxShadow: '0 0 30px rgba(139, 0, 0, 0.6), inset 0 0 50px rgba(0,0,0,0.8)', position: 'relative' }); // Title const titleEl = document.createElement('h2'); titleEl.textContent = cardData.titulo || "Evento"; Object.assign(titleEl.style, { marginTop: '0', marginBottom: '10px', color: '#ff4444', textTransform: 'uppercase', letterSpacing: '2px', fontSize: '24px', textShadow: '2px 2px 0 #000' }); card.appendChild(titleEl); // Subtitle/Type if (cardData.tipo) { const typeEl = document.createElement('div'); typeEl.textContent = cardData.tipo; Object.assign(typeEl.style, { fontSize: '12px', color: '#aaa', marginBottom: '20px', textTransform: 'uppercase', borderBottom: '1px solid #444', paddingBottom: '5px' }); card.appendChild(typeEl); } // Image Placeholder (Optional) // const img = document.createElement('div'); ... // Message const msgEl = document.createElement('p'); // If it's pure text or HTML msgEl.innerHTML = cardData.descripcion || cardData.texto || ""; Object.assign(msgEl.style, { fontSize: '16px', lineHeight: '1.6', color: '#ddd', textAlign: 'justify', fontStyle: 'italic', marginBottom: '25px' }); card.appendChild(msgEl); // Action Button const btn = document.createElement('button'); btn.textContent = 'CONTINUAR'; Object.assign(btn.style, { padding: '12px 30px', fontSize: '16px', cursor: 'pointer', backgroundColor: '#8b0000', color: '#fff', border: '2px solid #ff4444', borderRadius: '4px', fontFamily: 'inherit', fontWeight: 'bold', textTransform: 'uppercase', boxShadow: '0 4px 0 #440000', transition: 'transform 0.1s' }); btn.onmousedown = () => btn.style.transform = 'translateY(2px)'; btn.onmouseup = () => btn.style.transform = 'translateY(0)'; btn.onclick = () => { if (overlay.parentNode) this.parentContainer.removeChild(overlay); if (callback) callback(); }; card.appendChild(btn); overlay.appendChild(card); this.parentContainer.appendChild(overlay); } showTemporaryMessage(title, message, duration = 2000) { const modal = document.createElement('div'); Object.assign(modal.style, { position: 'absolute', top: '25%', left: '50%', transform: 'translate(-50%, -50%)', backgroundColor: 'rgba(139, 0, 0, 0.9)', color: '#fff', padding: '15px 30px', borderRadius: '8px', border: '2px solid #ff4444', fontFamily: '"Cinzel", serif', fontSize: '20px', textShadow: '2px 2px 4px black', zIndex: '2000', pointerEvents: 'none', opacity: '0', transition: 'opacity 0.5s ease-in-out' }); modal.innerHTML = `