diff --git a/src/ui.js b/src/ui.js
index 984aa60..d58247d 100644
--- a/src/ui.js
+++ b/src/ui.js
@@ -467,6 +467,323 @@ function setupFloatingButtonHandler(floatingButton) {
};
}
+// New mobile-first Hermes modal
+async function openHermesModalNew() {
+ const modal = document.createElement("dialog");
+ modal.id = "hermes-modal";
+
+ // Mobile-first: full screen on mobile, centered on desktop
+ const isMobile = window.innerWidth <= 768;
+
+ modal.style.cssText = \`
+ position: fixed;
+ margin: 0;
+ padding: 0;
+ border: none;
+ background: white;
+ z-index: 2000;
+ \${isMobile ? \`
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ max-width: 100vw;
+ max-height: 100vh;
+ border-radius: 0;
+ \` : \`
+ width: 90vw;
+ max-width: 800px;
+ height: 90vh;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ border-radius: 16px;
+ box-shadow: 0 20px 40px rgba(0,0,0,0.3);
+ \`}
+ \`;
+
+ // Simple container with flex layout
+ const container = document.createElement("div");
+ container.style.cssText = \`
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ \`;
+
+ // Header
+ const header = document.createElement("header");
+ header.style.cssText = \`
+ flex-shrink: 0;
+ padding: 16px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ \`;
+
+ const title = document.createElement("h2");
+ title.textContent = "🤖 Hermes AI";
+ title.style.cssText = \`
+ margin: 0;
+ font-size: \${isMobile ? '18px' : '20px'};
+ font-weight: 600;
+ \`;
+
+ const closeBtn = document.createElement("button");
+ closeBtn.textContent = "✕";
+ closeBtn.style.cssText = \`
+ background: rgba(255,255,255,0.2);
+ border: none;
+ color: white;
+ font-size: 20px;
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: background 0.2s;
+ \`;
+ closeBtn.onmouseover = () => closeBtn.style.background = 'rgba(255,255,255,0.3)';
+ closeBtn.onmouseout = () => closeBtn.style.background = 'rgba(255,255,255,0.2)';
+ closeBtn.onclick = () => {
+ modal.close();
+ document.body.removeChild(modal);
+ hermesModalOpen = false;
+ };
+
+ header.appendChild(title);
+ header.appendChild(closeBtn);
+
+ // Chat area
+ const chatArea = document.createElement("div");
+ chatArea.style.cssText = \`
+ flex: 1;
+ overflow-y: auto;
+ padding: 16px;
+ background: #f8f9fa;
+ -webkit-overflow-scrolling: touch;
+ \`;
+
+ const chatBox = document.createElement("div");
+ chatBox.id = "modal-chat-box";
+ chatBox.style.cssText = \`
+ max-width: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ \`;
+ chatArea.appendChild(chatBox);
+
+ // Quick action buttons (minimal on mobile)
+ if (!isMobile) {
+ const controls = document.createElement("div");
+ controls.style.cssText = \`
+ flex-shrink: 0;
+ padding: 8px 16px;
+ background: white;
+ border-top: 1px solid #e9ecef;
+ border-bottom: 1px solid #e9ecef;
+ display: flex;
+ gap: 8px;
+ overflow-x: auto;
+ \`;
+
+ const actions = [
+ { text: "📖 Read", action: () => window.readPageWithHermes() },
+ { text: "🔊 TTS", action: () => window.openTTSModal() },
+ { text: "🌐 Translate", action: () => window.openTranslateModal() }
+ ];
+
+ actions.forEach(({ text, action }) => {
+ const btn = document.createElement("button");
+ btn.textContent = text;
+ btn.style.cssText = \`
+ padding: 8px 16px;
+ background: #f8f9fa;
+ border: 1px solid #dee2e6;
+ border-radius: 20px;
+ cursor: pointer;
+ white-space: nowrap;
+ font-size: 14px;
+ transition: all 0.2s;
+ \`;
+ btn.onmouseover = () => {
+ btn.style.background = '#e9ecef';
+ btn.style.borderColor = '#adb5bd';
+ };
+ btn.onmouseout = () => {
+ btn.style.background = '#f8f9fa';
+ btn.style.borderColor = '#dee2e6';
+ };
+ btn.onclick = action;
+ controls.appendChild(btn);
+ });
+
+ container.appendChild(header);
+ container.appendChild(chatArea);
+ container.appendChild(controls);
+ } else {
+ container.appendChild(header);
+ container.appendChild(chatArea);
+ }
+
+ // Input area
+ const inputArea = document.createElement("div");
+ inputArea.style.cssText = \`
+ flex-shrink: 0;
+ padding: 16px;
+ background: white;
+ display: flex;
+ gap: 12px;
+ align-items: flex-end;
+ box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
+ \`;
+
+ const input = document.createElement("textarea");
+ input.id = "modal-user-input";
+ input.placeholder = "Ask about this page...";
+ input.style.cssText = \`
+ flex: 1;
+ min-height: 44px;
+ max-height: 120px;
+ padding: 12px;
+ border: 1px solid #dee2e6;
+ border-radius: 24px;
+ resize: none;
+ font-size: 16px;
+ font-family: inherit;
+ line-height: 1.4;
+ outline: none;
+ transition: border-color 0.2s;
+ \`;
+ input.onfocus = () => input.style.borderColor = '#667eea';
+ input.onblur = () => input.style.borderColor = '#dee2e6';
+
+ // Auto-resize textarea
+ input.oninput = () => {
+ input.style.height = 'auto';
+ input.style.height = Math.min(input.scrollHeight, 120) + 'px';
+ };
+
+ const sendBtn = document.createElement("button");
+ sendBtn.textContent = "→";
+ sendBtn.style.cssText = \`
+ width: 44px;
+ height: 44px;
+ padding: 0;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ border: none;
+ border-radius: 50%;
+ cursor: pointer;
+ font-size: 20px;
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: transform 0.2s;
+ flex-shrink: 0;
+ \`;
+ sendBtn.onmouseover = () => sendBtn.style.transform = 'scale(1.05)';
+ sendBtn.onmouseout = () => sendBtn.style.transform = 'scale(1)';
+
+ // Handle message sending
+ const sendMessage = async () => {
+ const message = input.value.trim();
+ if (!message) return;
+
+ input.value = '';
+ input.style.height = '44px';
+
+ // Add user message
+ const userMsg = document.createElement("div");
+ userMsg.style.cssText = \`
+ align-self: flex-end;
+ background: #667eea;
+ color: white;
+ padding: 12px 16px;
+ border-radius: 18px 18px 4px 18px;
+ max-width: 80%;
+ word-wrap: break-word;
+ \`;
+ userMsg.textContent = message;
+ chatBox.appendChild(userMsg);
+
+ // Add AI response placeholder
+ const aiMsg = document.createElement("div");
+ aiMsg.style.cssText = \`
+ align-self: flex-start;
+ background: white;
+ padding: 12px 16px;
+ border-radius: 18px 18px 18px 4px;
+ max-width: 80%;
+ box-shadow: 0 1px 2px rgba(0,0,0,0.1);
+ \`;
+ aiMsg.innerHTML = 'Thinking...';
+ chatBox.appendChild(aiMsg);
+
+ chatArea.scrollTop = chatArea.scrollHeight;
+
+ try {
+ let response = '';
+ for await (const chunk of sendMessage(message)) {
+ response += chunk;
+ aiMsg.innerHTML = marked.parse(response);
+ }
+ } catch (error) {
+ aiMsg.innerHTML = \`Error: \${error.message}\`;
+ }
+
+ chatArea.scrollTop = chatArea.scrollHeight;
+ };
+
+ sendBtn.onclick = sendMessage;
+ input.onkeydown = (e) => {
+ if (e.key === 'Enter' && !e.shiftKey) {
+ e.preventDefault();
+ sendMessage();
+ }
+ };
+
+ inputArea.appendChild(input);
+ inputArea.appendChild(sendBtn);
+ container.appendChild(inputArea);
+ modal.appendChild(container);
+
+ document.body.appendChild(modal);
+ modal.showModal();
+
+ modal.addEventListener('click', (e) => {
+ if (e.target === modal) {
+ modal.close();
+ document.body.removeChild(modal);
+ hermesModalOpen = false;
+ }
+ });
+
+ input.focus();
+
+ // Add intro message
+ const introMsg = document.createElement("div");
+ introMsg.style.cssText = \`
+ align-self: flex-start;
+ background: white;
+ padding: 12px 16px;
+ border-radius: 18px 18px 18px 4px;
+ max-width: 80%;
+ box-shadow: 0 1px 2px rgba(0,0,0,0.1);
+ color: #495057;
+ \`;
+ introMsg.innerHTML = \`👋 Hi! I'm Hermes AI. I can help you understand this page, answer questions, or assist with various tasks. How can I help you today?\`;
+ chatBox.appendChild(introMsg);
+}
+
// Function to toggle Hermes modal
export async function toggleHermesModal() {
const existingModal = document.getElementById("hermes-modal");
@@ -474,7 +791,7 @@ export async function toggleHermesModal() {
document.body.removeChild(existingModal);
hermesModalOpen = false;
} else {
- await openHermesModal();
+ await openHermesModalNew();
hermesModalOpen = true;
}
}