- Convert relative CSS URLs to absolute URLs using current origin
- Ensure translated pages can load original blog CSS in new window
- Maintain modal functionality with external CSS files
- Skip URLs that are already absolute (http/https or protocol-relative)
- Add logging to see how many CSS links are found
- Log each CSS file being inlined and success/failure
- Help diagnose why translated pages may not have modal styling
- Fetch external uncloseai CSS files and inline them as <style> tags
- Replace body content with translated version while preserving page structure
- Ensure new window is self-contained and doesn't need external CSS requests
- Maintain new window approach to avoid breaking current page
The CSS refactoring broke translated page rendering. The original function
was working correctly by translating the complete HTML document structure.
Translated pages don't need modal CSS, just the original page styling.
- Update translateCurrentPage() to preserve original page HTML structure
- Extract only text content for translation while keeping head/styles
- Create properly formatted translated page with clean typography
- Fix issue where translated pages opened in new windows lacked CSS styling
- Change CSS loading logic to detect actual PicoCSS link tags on page
- Blog sites without PicoCSS now correctly load uncloseai-modal-builtin.css
- PicoCSS sites load uncloseai-modal-pico.css with proper overrides
- Fix modal appearing full-screen on blog sites that don't use PicoCSS
- Remove all inline CSS from translate-modal.js, tts-modal.js, and widget-library.js
- Replace inline styles with CSS classes in both builtin and pico CSS files
- Eliminate USE_CUSTOM_STYLING conditionals from styling code
- Add proper CSS classes: translate-modal-*, tts-modal-*, widget-*
- Maintain all functionality while achieving clean separation of concerns
- Fix modal sizing issues on large displays through proper PicoCSS overrides
- Support responsive design with mobile-first approach (≤480px full screen)
- Pass all tests: formatting, exports, translations, and integration
- Create uncloseai-modal-builtin.css for blog versions
- Create uncloseai-modal-pico.css for PicoCSS override
- Add conditional CSS loading to all modal JavaScript files
- Remove inline styles from main modal, translate modal, TTS modal, and widget library
- Fix modal full-screen issue on large displays with proper PicoCSS overrides
- Maintain mobile-first responsive design (≤480px full screen)
- Support both USE_CUSTOM_STYLING modes for maximum compatibility
Changed mobile detection threshold from 768px to 480px to ensure
centered modal behavior on desktop/laptop screens while preserving
full-screen experience on actual mobile devices.
- Restore handleFileUpload import in widget-library.js to fix ReferenceError
- Keep all upload functionality code intact for future development
- Disable upload features in demo.html with "Under Development" messaging
- Remove upload from feature button examples but preserve the code
- Style disabled upload demo with greyed-out appearance
- Fix demo page functionality while maintaining upload code for future fixes
- Detect when model streaming is complete in all streaming locations
- Add syntax highlighting (hljs) to code blocks after streaming finishes
- Add copy buttons to code blocks after highlighting is applied
- Prevent duplicate copy buttons with CSS class detection
- Optimize performance by doing syntax highlighting and copy buttons only once per message
- Apply improvements to both modal streaming and standalone chat
- Add copy buttons to intro message generation as well
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add enforceModalTextColors() function with high CSS specificity
- Use !important declarations to override blog CSS
- Force dark text (#212529) on inputs, buttons, and general content
- Keep white text on user messages for proper contrast
- Add user-message class to user messages for targeted styling
- Prevents unreadable white text on white backgrounds on blog
- All delete buttons now call loadConversationHistory/saveConversationHistory
- Update both localStorage and chat.js module for consistency
- User message delete: filters by content match
- AI message delete: removes both user and AI messages in pair
- Historical message delete: removes by array index
- Intro message delete: filters by assistant role and content
- No more localStorage sync issues with deleted messages
- Chat TTS now uses speakTextDirect (no Hermes preprocessing, faster)
- Add download buttons (💾) next to all TTS buttons after processing
- Download buttons use generateTitleForTTS for smart filenames
- Read Page download now uses title generator instead of document.title
- Download buttons appear for user messages, AI responses, and historical messages
- Fallback filenames if title generation fails
- All TTS processing is now direct without Hermes delay
- Add try/catch with detailed error logging
- Check if sendMessage exists in imported module
- Log module contents if function not found
- Helps diagnose 'sendMessage(...) is not iterable' error
- Enhanced system prompt: MUST generate title, NEVER refuse
- Clear instructions for edge cases (empty, inappropriate, nonsensical text)
- Added fallback logic if Hermes returns empty or refusal messages
- Fallback uses first 30 chars of text or 'audio-file' as last resort
- Ensures downloads always have a valid filename
- Change sendMessage to async generator function with yield*
- Fixes 'Error: sendMessage(...) is not iterable' error
- Restores chat functionality in Hermes modal
- Fix TTS speed control: change default to 0.9, step by 0.05, max 2.0
- Apply playbackRate to audio element so speed actually works
- Add refreshModalUI() function to update UI when language changes
- Re-add upstream tokenizer API with simplified token counting
- Format token counts with commas (e.g., 8,432 tokens)
- Add getTokenCount() for simple integer token counts
- Language switching now refreshes modal UI without hard refresh
- extractSpokenTokens now detects if input is already markdown format
- Updated prompt to handle both markdown and HTML input
- Added markdown to plain text conversion in prompt (bold, links)
- processContentWithHermes now delegates to extractSpokenTokens
- Consistent processing pipeline whether from Batman button or Read Page
- Better reuse of extractWebpageContent markdown format
- Pre-clean HTML before sending to Hermes (remove scripts, styles, ads, iframes)
- Decode HTML entities ( & etc.) before Hermes processing
- Simplified, clearer system prompt focused on extraction tasks
- Post-process Hermes output with cleanTextForTTS() for final cleanup
- Reduces Hermes workload and improves extraction quality
- Three-stage pipeline: JS pre-clean → Hermes extraction → JS post-clean
- TTS modal now uses speakTextDirect() with simple JavaScript text cleaning
- No more Hermes preprocessing for modal text (faster, simpler)
- Read Page button still uses speakText() with Hermes for article extraction
- Reduced textarea height from 240px to 100px with vertical resize
- Added cleanTextForTTS() to remove markdown, HTML, and excess whitespace
- Modal gets instant TTS while Read Page gets intelligent content extraction
- Remove top, left, and transform properties
- Let dialog element use native browser centering
- Fixes positioning issues across different viewports
- Cleaner solution that works better with dialog element
- Enhanced system prompt to generate 5-10 word descriptive filenames
- Added robust text cleaning to remove quotes, special characters
- Limit filename length to 50 chars for filesystem compatibility
- Better dash-separated filename format like 'javascript-array-methods-guide.mp3'
- Enhanced system prompt to generate 3-5 word descriptive filenames
- Added robust text cleaning to remove quotes, special characters
- Limit filename length to 50 chars for filesystem compatibility
- Better dash-separated filename format like 'javascript-tutorial.mp3'
- Use generateTitleForTTS to create dash-separated filenames based on textarea content
- Hermes analyzes the text and generates descriptive filenames like 'hello-world-tts.mp3'
- Fallback to default filename if generation fails
- Add missing blobUrl to speakText return value
- TTS modal now correctly receives blobUrl for audio playback and download
- Fixes missing MP3 download and autoplay functionality