Commit Graph

93 Commits

Author SHA1 Message Date
juanatsap ba44b435e7 refactor: Major hyperscript refactoring and JS elimination
Inline Hyperscript Refactoring:
- Body tag keyboard handlers: 20→8 lines (using helper functions)
- Zoom control handlers: 85→35 lines (using zoom._hs)
- PDF modal card selection: 90→6 lines (3 identical blocks eliminated)

New Hyperscript Files:
- zoom._hs: handleZoomInput, handleZoomReset, initZoomControl
- pdf-modal._hs: selectPdfCard, handlePdfCardKey

JavaScript Elimination (232 lines removed):
- cv-functions.js: REMOVED - hyperscript defs are globally available
- scroll-at-bottom-handler.js: REMOVED - duplicate of handleScroll()
- footer-buttons-interaction.js: REMOVED - moved to hyperscript

Added Tests:
- 32-hyperscript-multi-src.test.mjs: Verifies multi-file loading
- 33-keyboard-shortcuts-refactored.test.mjs: Keyboard shortcuts
- 34-hyperscript-refactor-comprehensive.test.mjs: Full test suite

Key Findings:
- No hyperscript multi-file bug in 0.9.14
- Hyperscript def statements are globally accessible
- Previous refactoring failures were syntax errors, not library bugs
2025-11-30 05:58:44 +00:00
juanatsap 4a02c0a328 fix: Restore sticky action bar by using overflow-x: clip instead of hidden
Root cause: overflow-x: hidden on html/body elements breaks position: sticky
on descendant elements. This is a known CSS behavior.

Changes:
- _reset.css: Changed overflow-x from 'hidden' to 'clip' on html and body
  - 'clip' prevents horizontal scrolling WITHOUT breaking sticky positioning
- index.html: Restored hyperscript scroll handlers (initScrollBehavior, handleScroll)
- main.js: Disabled JavaScript scroll fallback in favor of hyperscript

Behavior:
- Desktop: Action bar hides on scroll down, reappears on scroll up
- Mobile (≤900px): Action bar stays visible at all times (CSS override)

Tested: Both desktop and mobile scroll behaviors work correctly
2025-11-30 04:35:16 +00:00
juanatsap cb5e72a5f2 fix: Replace hyperscript scroll handler with JavaScript implementation
The hyperscript-based scroll behavior was not working reliably across all browsers.
Replaced with a pure JavaScript implementation that:

Desktop (>900px):
- Hides action bar on scroll down (past 100px threshold)
- Shows action bar on scroll up
- Shows action bar at top of page

Mobile (≤900px):
- Always keeps action bar visible
- Actively removes header-hidden class on mobile
- Handles viewport resize for responsive testing

Changes:
- Added initScrollBehaviorJS() function to main.js
- Removed hyperscript scroll handlers from body tag in index.html
- Kept keyboard shortcut handlers in hyperscript (still working)
- Uses passive scroll listener for better performance

This fixes the bug where:
- Desktop: bar would hide but not show again on scroll up
- Mobile: bar was incorrectly hiding despite CSS override
2025-11-30 04:13:50 +00:00
juanatsap da81a0b148 feat: iOS-specific blur bar and hide keyboard shortcuts on real mobile devices
Issue 1: Blur bar compatibility (Android doesn't always show at bottom)
 Solution: Wrap blur bar in @supports query for backdrop-filter
- Only shows on devices that support backdrop-filter (primarily iOS)
- Android devices without support won't see the bar
- Prevents layout issues on non-iOS devices

Issue 2: Keyboard shortcuts button on real mobile (no physical keyboard)
 Solution: Device detection + conditional hiding
- Added device-detection.js: Detects real mobile vs desktop browser
- Checks user agent (Android, iPhone, iPad, etc.) + touch support
- Adds 'is-mobile-device' or 'is-desktop' class to <html>
- CSS hides shortcuts button only on real mobile devices
- Desktop browser in mobile view: shortcuts button still visible (for testing)

Implementation Details:
1. Device Detection (static/js/device-detection.js):
   - User agent detection: /Android|iPhone|iPad|etc./
   - Touch support check: ontouchstart + maxTouchPoints
   - Class added to <html>: is-mobile-device or is-desktop

2. Blur Bar (@supports query):
   - Detects backdrop-filter support before applying
   - iOS: Shows blur bar with backdrop-filter
   - Android (most): No blur bar (no backdrop-filter support)
   - Prevents empty/broken bar on incompatible devices

3. CSS Hiding Rules:
   - .is-mobile-device .shortcuts-btn { display: none !important; }
   - Also hides zoom-toggle-btn and zoom-control on real mobile
   - Desktop mobile view: shortcuts button remains visible

Files Modified:
- static/js/device-detection.js: NEW - Device detection logic
- templates/index.html: Load device-detection.js early
- static/css/05-responsive/_breakpoints.css: @supports wrapper for blur bar
- static/css/04-interactive/_scroll-behavior.css: Hide shortcuts on real mobile
- tests/mjs/52-mobile-device-detection-test.mjs: Comprehensive device detection test

Test Results:
 iPhone (real mobile): is-mobile-device class, shortcuts hidden
 Desktop browser (mobile view): is-desktop class, shortcuts visible
 Blur bar: Only shows on devices with backdrop-filter support
2025-11-24 20:48:12 +00:00
juanatsap 2f466e46bc feat: Default to light theme on mobile devices on first visit
Implements device-aware theme defaults:
- Mobile devices (≤768px): Default to light theme
- Desktop devices (>768px): Default to auto theme
- Saved preferences: Always respected regardless of device

Implementation:
1. FOUC Prevention Script (templates/index.html):
   - Detects device type using window.innerWidth/clientWidth/screen.width
   - Sets initial theme before page render to prevent flash
   - Mobile: 'light', Desktop: 'auto'

2. Theme Initialization (static/js/color-theme.js):
   - Modified initColorTheme() to respect FOUC-detected theme
   - Saves FOUC-detected theme to localStorage for persistence
   - Prevents overwriting mobile detection with 'auto' default

Test Coverage:
- Test 1: Mobile first visit → light theme 
- Test 2: Desktop first visit → auto theme 
- Test 3: Saved preference honored → dark theme 

Files Modified:
- templates/index.html: Added mobile detection in FOUC prevention
- static/js/color-theme.js: Respect FOUC-detected theme
- tests/mjs/49-mobile-light-theme-default.mjs: Comprehensive test suite

Screenshots:
- tests/screenshots/mobile-light-theme-default.png
- tests/screenshots/desktop-auto-theme-default.png
2025-11-23 08:37:29 +00:00
juanatsap dab21f753d feat: Add iOS-style blur bar for mobile buttons and landscape optimizations
Mobile Portrait Enhancements:
- Added iOS-style blur backdrop behind fixed buttons
- Frosted glass effect with backdrop-filter: blur(20px) saturate(180%)
- Semi-transparent background with border-top separator
- Dark mode variant for theme consistency
- Z-index 98 (below buttons at 99)
- pointer-events: none to maintain button animations and clicks

Landscape Orientation Fixes:
- Hide profile photo to maximize vertical space
- Compact header with reduced font sizes (1.2rem)
- Reduced padding on action bar, sidebar, and sections
- Optimized button sizes (40x40px) and positions
- Fixed hamburger menu positioning in landscape

Files Modified:
- static/css/05-responsive/_breakpoints.css: Added blur backdrop and landscape styles
- templates/index.html: Added fixed-buttons-backdrop element
- tests/mjs/48-mobile-landscape-and-blur-test.mjs: Comprehensive test suite

Test Results:
 Blur backdrop exists with correct blur effect
 Fixed position at bottom with 90px height
 Border separator visible (0.5px)
 Photo hidden in landscape mode
 Compact sizing applied in landscape
 All animations maintained (backdrop separate from buttons)

Screenshots:
- tests/screenshots/mobile-portrait-blur-bar.png
- tests/screenshots/mobile-landscape-optimized.png
2025-11-23 08:21:12 +00:00
juanatsap 2eafb78954 fix: Mobile view improvements - accordion styling and modal centering
Fixed two critical mobile view issues:

1. Extended CV Sidebar Accordion:
   - Updated sidebar.html to use native <details> element (was div with onclick)
   - Styled accordion header to match CV title badges dark theme (#303030)
   - Applied consistent styling: dark gray background, light text, uppercase, no spacing
   - Result: Sidebars now collapse/expand properly with native HTML functionality

2. PDF Download Modal Centering:
   - Added JavaScript-based centering for mobile viewports (≤768px)
   - Uses inline styles with !important flag to override browser defaults
   - Updated download button to call openPdfModal() function
   - Result: Modal is perfectly centered on mobile (0px offset)

Technical notes:
   - Modal centering required setProperty() with 'important' flag
   - Accordion matches cv-title-badges-header style exactly
   - All tests passing: accordion toggle, modal centering

Files modified:
   - templates/partials/cv/sidebar.html
   - static/css/05-responsive/_breakpoints.css
   - static/js/main.js
   - templates/partials/widgets/download-button.html

Tests added:
   - tests/mjs/43-mobile-accordion-and-modal-test.mjs
   - tests/mjs/46-visual-accordion-style-test.mjs
2025-11-22 16:23:05 +00:00
juanatsap 7b60fdcf9c refactor: Separate CV domain and UI presentation models into distinct packages
**Main Changes:**

1. **Package Restructuring** - Separated mixed concerns into focused packages:
   - Created `internal/models/cv/` for CV domain logic (CV, Personal, Experience, etc.)
   - Created `internal/models/ui/` for UI presentation logic (InfoModal, ShortcutsModal, etc.)
   - Removed monolithic `internal/models/cv.go` (300+ lines → organized packages)

2. **Testing** - Added comprehensive unit tests:
   - `internal/models/cv/loader_test.go` - CV data loading and validation
   - `internal/models/ui/loader_test.go` - UI translations loading
   - All tests passing 

3. **Documentation** - Added Go learning knowledge base:
   - `_go-learning/architecture/server-design.md` - Goroutines, graceful shutdown explained
   - `_go-learning/refactorings/001-cv-model-separation.md` - This refactoring documented
   - Public documentation showcasing Go expertise (README.md kept private)

4. **Handler Updates** - Updated imports to use new package structure:
   - `internal/handlers/cv.go` - Uses `cvmodel` and `uimodel` aliases

**Benefits:**
-  Clear separation of concerns (domain vs presentation)
-  Better testability (isolated package testing)
-  Improved maintainability (smaller, focused files)
-  Scalability (each domain can evolve independently)
-  Follows Go best practices (small, cohesive packages)

**Other Updates:**
- Updated middleware security checks
- Template improvements
- Organized completed prompts

**Testing:**
- All Go unit tests pass (cv, ui, handlers)
- Server verified with curl tests (English, Spanish, Health endpoints)
- Frontend functionality unchanged (refactoring is transparent to UI)
2025-11-20 16:17:56 +00:00
juanatsap 810ee7955b fix: References section link corruption and download filename issues
**Issue 1: URL corruption in "See this CV in..." links**
- Bug: replaceYearPlaceholder used fmt.Sprintf on ALL URLs
- URLs like "/?lang=es" were corrupted to "/?lang=es%!(EXTRA string=2025)"
- Fix: Changed to strings.ReplaceAll("{{YEAR}}", year)
- Result: Only replaces actual {{YEAR}} placeholders, leaves other URLs intact

**Issue 2: Download filename not respected**
- Bug: Shortcut URLs (cv-jamr-2025-en.pdf) redirected with HTTP 301
- Browsers used original URL filename instead of Content-Disposition header
- Fix: Generate PDF directly in DefaultCVShortcut handler
- Result: Returns PDF with correct filename in Content-Disposition header

Files changed:
- internal/models/cv.go: Fixed replaceYearPlaceholder function
- internal/handlers/cv.go: Changed redirect to direct PDF generation

Both fixes verified:
- "See this CV in Spanish" link: href="/?lang=es" ✓
- Download link: filename=cv-jamr-2025-en.pdf ✓
2025-11-20 13:00:06 +00:00
juanatsap 925a95c1b4 refactor: externalize navigation handlers and fix hyperscript syntax errors
- Created keyboard._hs as reference documentation (inline handler in body tag)
- Externalized 9 hamburger menu navigation links to scrollToSection()
- Added scrollToSection() as JavaScript function (CSP-safe, no eval needed)
- Restored original keyboard handler format in body tag (working correctly)
- Removed problematic navigation._hs (had syntax/CSP issues)
- Added Rule 4 to HYPERSCRIPT-RULES.md on event handler externalization
- Updated PROJECT-MEMORY.md with externalization guidelines

Key learnings:
- Complex event handlers that inspect event properties must stay inline
- JavaScript functions avoid CSP unsafe-eval restrictions
- Navigation successfully externalized: 9 links → 1 function (91% reduction)
2025-11-20 09:46:06 +00:00
juanatsap f7cda5dba3 refactor: Modularize CSS and fix theme-aware text colors
CSS Restructuring:
- Reorganize monolithic main.css into modular architecture
- Create foundation/ (reset, variables, typography, themes)
- Create layout/ (container, page, grid, paper)
- Create components/ (8 component files)
- Create interactive/ (toggles, remaining for future split)
- Create effects/ (skeleton loading)
- Create contexts/ (print styles)

Theme Support Fixes:
- Replace all hardcoded text colors with CSS variables
- Fix .section-title: rgb(51,51,51) → var(--text-primary)
- Fix .cv-name, .intro-text: hardcoded → theme-aware
- Fix .experience-period, .duration-text: #555/#aaa → variables
- Fix course/project/experience text colors
- Support proper light/dark theme text contrast

Icon & Layout Fixes:
- Standardize all icon sizes to 80×80px
- Change all icon backgrounds to transparent
- Fix award section layout (missing flexbox)
- Update HTML templates (experience.html, awards.html) to width='80'
- Fix default icon sizing conflicts

View Switcher Fix:
- Fix toggleTheme() to target .cv-container instead of body
- Ensures clean/default theme toggle works correctly

Files: 40+ CSS files modularized, 3 templates updated, 7 tests added
2025-11-19 14:31:17 +00:00
juanatsap 8c0328357b fix: remove CSPNonce from Matomo script (not implemented in backend)
ISSUE: Matomo analytics not loading in production

ROOT CAUSE:
- Matomo script had nonce="{{.CSPNonce}}" attribute
- Go backend doesn't generate CSPNonce template variable
- Empty nonce attribute caused CSP to block the script in production

FIX:
- Removed nonce attribute from Matomo script tag
- CSP header already includes 'unsafe-inline' so nonces not needed
- Script now loads correctly in both localhost and production

VERIFICATION:
- Matomo will now load and track pageviews in production
- Check browser console for _paq object
- Verify tracking in Matomo dashboard
2025-11-18 19:47:38 +00:00
juanatsap 1f6f8e417e docs: Update skeleton loader implementation from hyperscript to JavaScript
MIGRATION SUMMARY:
- Moved skeleton loader logic from hyperscript to JavaScript (main.js)
- Changed from htmx:oobAfterSwap to htmx:afterSettle event
- Changed OOB swap from innerHTML to outerHTML for proper element replacement
- Added languageSwitching flag for state tracking
- Added 100ms delay after afterSettle for final render completion

DOCUMENTATION UPDATES:
- 2-MODERN-WEB-TECHNIQUES.md: Updated skeleton loader section with
2025-11-18 19:32:28 +00:00
juanatsap f3cce51fb3 feat: implement color theme switcher with dynamic button colors
Complete color theme system (light/dark/auto) with dynamic UI:

Features:
- Color theme switcher with auto/light/dark modes
- Dynamic button colors on hover (purple/yellow/blue per theme)
- localStorage persistence across sessions
- Proper button positioning (desktop and mobile)
- Mobile: 5-button layout with theme before info button

Fixes:
- CSP updated to allow jsDelivr CDN for iconify icons
- Button repositioning: Download PDF and Print Friendly at top
- Hover-only colors (not persistent)
- Mobile button order corrected

Files:
- static/css/color-theme.css - Theme system with CSS variables
- static/js/color-theme.js - Theme switching logic
- templates/partials/color-theme-switcher.html - Button component
- internal/middleware/security.go - CSP fix for jsDelivr
- tests/mjs/13-color-theme-switcher.test.mjs - Comprehensive test
- tests/TEST-SUMMARY.md - Updated test documentation
2025-11-18 15:49:30 +00:00
juanatsap e90e7f0a15 feat: implement skeleton loaders for language transitions
Implements component-level skeleton loaders that display during language
transitions, providing visual feedback while content swaps.

**Implementation:**
- Dual-state structure: each component has actual-content + skeleton-content
- CSS toggles visibility via opacity transitions (250ms)
- Global hyperscript listener on <body> for language button clicks
- Adds .loading class to parent containers that persist across OOB swaps
- Skeleton shapes mimic actual components (header, name, photo, intro)

**Key Technical Solutions:**
- Event delegation using event.target.matches('.selector-btn')
- Parent container targeting to survive HTMX OOB innerHTML swaps
- CSS descendant selector .loading .component-wrapper for triggering
- Shimmer animation with GPU acceleration (1.8s infinite)

**Files Modified:**
- static/css/skeleton.css: Complete skeleton system with shimmer animation
- templates/index.html: Global hyperscript for .loading class management
- templates/partials/sections/header.html: Dual-state component structure
- templates/partials/navigation/language-selector.html: Removed local hyperscript

**Tests:**
- test-skeleton-verify.mjs: Validates skeleton across 4 language switches
- All tests passing:  Consistent activation on every language change
2025-11-18 12:40:52 +00:00
juanatsap c1f2f89555 feat: add skeleton shimmer effect during language transitions
Implements smooth skeleton loader animations during language switching:
- Uses HTMX's built-in .htmx-swapping class (no hyperscript needed)
- Content fades to 30% opacity during swap
- Shimmer animation overlays content during transition
- Respects prefers-reduced-motion accessibility setting
- Total transition: 500ms (250ms fade-out + 250ms fade-in)

Implementation approach:
- Simple CSS-only solution using ::before pseudo-element
- No overlay div - skeleton appears INSIDE content wrappers
- Works automatically with HTMX swap timing already configured
- GPU-accelerated shimmer animation (background-position)

Files changed:
- static/css/skeleton.css (NEW) - Shimmer animation styles
- templates/index.html - Added skeleton.css reference
2025-11-18 08:22:30 +00:00
juanatsap 52e97f1411 fix: exclude footer from zoom by moving it outside zoom-wrapper
The footer was being zoomed along with CV content because it was
inside the #zoom-wrapper div. This fix moves the footer outside the
zoom-wrapper so it remains at normal size regardless of zoom level.

Changes:
- Move footer template outside zoom-wrapper in index.html
- Add UI exclusion test (11-zoom-ui-exclusion.test.mjs)

Test coverage:
- Verify footer, action bar, and menu are outside zoom-wrapper (DOM)
- Verify UI elements remain unchanged when zooming to 200%
- Verify CV content properly zooms while UI stays fixed

Before: Footer inside zoom-wrapper (zoomed with content)
After: Footer outside zoom-wrapper (stays normal size)
2025-11-17 17:10:46 +00:00
juanatsap d2330f5d48 refactor: migrate toggle and hover sync functions from JavaScript to Hyperscript
BREAKING: Removed JavaScript toggle functions in favor of organized Hyperscript architecture

Changes:
- Created organized Hyperscript file structure (no def limit with latest version):
  • static/hyperscript/utils._hs (utility functions)
  • static/hyperscript/toggles._hs (CV length, icons, theme toggles)
  • static/hyperscript/hover-sync._hs (PDF/Print hover sync + zoom highlight)

- Removed functions._hs (renamed to utils._hs for better organization)

- Emptied static/js/cv-functions.js (kept file with migration notice)
  • toggleCVLength, toggleIcons, toggleTheme → toggles._hs
  • syncPdfHover, syncPrintHover, highlightZoomControl → hover-sync._hs

- Updated templates/index.html to load all 3 new hyperscript files

- Updated tests/mjs/1-toggles.test.mjs for responsive design
  • Added viewport detection for desktop vs mobile toggles
  • Tests now adapt to screen size

Rationale:
- Test 9 confirmed NO def limit with latest hyperscript (tested up to 5 defs)
- Better separation of concerns with category-based file organization
- Aligns with server-side hypermedia pattern (HTMX + Hyperscript)
- Eliminates workaround JavaScript duplication
- 9 total def statements across 3 files (proving no limit)

Verified:
 All hyperscript files load successfully (HTTP 200)
 Hyperscript library loads without errors
 Functions work correctly in browser
 No console errors
 Test 9 (def limit) passes with 5 def statements

Related: Test 9 verification (tests/mjs/9-hyperscript-def-limit.test.mjs)
2025-11-17 16:28:52 +00:00
juanatsap 3f77fedeaf fix: icon toggle real-time rendering + hyperscript architecture cleanup
CRITICAL FIX: Icon toggle now works without page refresh
- Changed class name from 'show-logos' to 'show-icons' (CSS mismatch bug)
- Updated localStorage key from 'cv-logos' to 'cv-icons'
- Fixed toggleIcons() function in cv-functions.js

HYPERSCRIPT ARCHITECTURE:
- Moved 6 toggle functions from hyperscript to JavaScript (cv-functions.js)
- Solves hyperscript 0.9.14 parser limitation (max 3 def statements total)
- Upgraded hyperscript from 0.9.12 to 0.9.14
- Fixed operator precedence in keyboard shortcuts
- Cleaned view-controls.html templates (inline → function calls)

NEW FILES:
- static/js/cv-functions.js - Global toggle functions (6 functions)
- HYPERSCRIPT-RULES.md - Permanent architecture documentation
- tests/mjs/0-zoom.test.mjs - Zoom functionality test
- tests/mjs/1-toggles.test.mjs - Comprehensive toggle test with real-time verification
- tests/TEST-SUMMARY.md - Test suite documentation

TESTS:
- Real-time DOM update verification (no refresh required)
- Screenshot capture for visual regression
- localStorage persistence validation
- Toggle synchronization between action bar and menu

BREAKING CHANGE: localStorage key changed from 'cv-logos' to 'cv-icons'
Users may need to re-toggle icons preference on first load after update.
2025-11-17 13:00:03 +00:00
juanatsap 7fc4f76706 monday last fixes before printing 2025-11-17 08:34:50 +00:00
juanatsap 0edcf8c221 fix: correct button order and restore smooth transitions
Fixes:
1.  Reversed button order - Info at bottom, Download at top
   - Desktop (bottom→top): Info → Shortcuts → Zoom → Print → Download
   - Mobile (left→right): Download → Print → Shortcuts → Info

2.  Restored smooth morphing transitions
   - Added transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1)
   - Container smoothly transforms from vertical to horizontal
   - Buttons smoothly reposition during responsive transition

3.  Preserved all special hover behaviors
   - Zoom button: Blue hover + highlights zoom control
   - Print button: White bg + green icon on hover (synchronized)
   - Download button: Red bg on hover (synchronized)
   - All sync functions working: syncPdfHover, syncPrintHover, highlightZoomControl

The flexbox container now has the correct button order AND smooth animations!
2025-11-16 14:26:49 +00:00
juanatsap 8eea5a660a feat: implement flexbox container for fixed buttons
Major architectural improvement for button management:

Desktop Layout (left side, vertical):
- Created .fixed-buttons-container positioned left: 2rem, bottom: 2rem
- Buttons stack vertically with flex-direction: column
- Order (bottom to top): Info → Shortcuts → Zoom → Print → Download
- 1rem (16px) gap between buttons
- All buttons 50×50px with consistent styling
- Easy to add/remove buttons - just add template to container

Mobile Layout (bottom center, horizontal):
- Container switches to flex-direction: row at @media (max-width: 900px)
- Centered with left: 50% and transform: translateX(-50%)
- 10px gap between buttons
- Zoom button hidden on mobile (display: none)
- 4 visible buttons: Info, Shortcuts, Print, Download

Benefits:
 Single source of truth - container manages all buttons
 Easy to add/remove buttons - no manual position calculations
 Responsive - automatic reflow from vertical to horizontal
 Maintainable - changes in one place affect all buttons
 Consistent spacing - gap property ensures even distribution
 Future-proof - adding button = adding template to container

Technical Implementation:
- Container uses position: fixed with flexbox
- Buttons use position: relative inside container (not fixed individually)
- All positioning managed by flexbox (gap, flex-direction, align-items)
- Hover states preserved with color-coded backgrounds per button
- Back-to-top button remains separate (not in container)

This replaces individual fixed positioning with a scalable flex layout.
2025-11-16 14:21:11 +00:00
juanatsap bfb7b35c50 feat: add synchronized hover effect for PDF and print-friendly buttons
- PDF buttons (fixed, action bar, menu) now sync hover states across all instances
- Print-friendly buttons (fixed, action bar, menu) sync green hover states
- White PDF icon with red hover background (#cd6060)
- Green print button hover (#27ae60)
- Implemented using hyperscript with .pdf-hover-sync and .print-hover-sync classes
- Creates cool visual feedback showing all related buttons simultaneously
2025-11-16 13:19:56 +00:00
juanatsap ac0cf15eb9 added zoom in buttons 2025-11-16 12:48:12 +00:00
juanatsap 25e9ebafe7 bf fixes 2025-11-16 10:11:58 +00:00
juanatsap 6510036193 feat: implement HTMX loading indicators and skeleton loader transitions
Implement comprehensive loading feedback system with two phases:

Phase 1: HTMX Loading Indicators
- Add spinning indicators to language selector buttons (EN/ES)
- Add indicators to all toggle controls (length, icons, theme)
- Implement both desktop and mobile menu indicators
- Create reusable CSS system with size/color variants
- Total: 8 HTMX interactions now have visual feedback

Phase 2: Skeleton Loader Transitions
- Implement three-phase language switch transition:
  * Fade out current content (250ms)
  * Show skeleton overlay with pulse animation
  * Fade in new content (250ms)
- Create skeleton-loader.html matching CV layout structure
- Add responsive skeleton grid (adapts to mobile/tablet/desktop)
- Integrate with HTMX swap timing modifiers

Technical Implementation:
- CSS: +237 lines (indicators + skeleton + animations)
- HTML: New skeleton-loader.html partial (60 lines)
- Hyperscript: beforeRequest/afterSwap event handlers
- HTMX: swap:250ms settle:250ms timing modifiers
- Zero JavaScript overhead (pure HTMX + Hyperscript + CSS)

Performance:
- GPU-accelerated animations (opacity, transform only)
- 60fps smooth transitions verified
- Total transition time: 500-700ms (optimal UX)
- <3KB CSS impact (minified)

Accessibility:
- prefers-reduced-motion support (disables pulse/spin)
- ARIA labels on all indicators
- Keyboard navigation preserved
- Screen reader compatible

Files Modified:
- static/css/main.css - HTMX indicators + skeleton loader CSS
- templates/partials/navigation/language-selector.html - Indicators + timing
- templates/language-switch.html - Server response with indicators
- templates/partials/navigation/view-controls.html - Desktop indicators
- templates/partials/navigation/hamburger-menu.html - Mobile indicators
- templates/index.html - Skeleton loader include

Files Created:
- templates/partials/skeleton-loader.html - Skeleton HTML structure
- BROWSER-TESTING-GUIDE.md - Comprehensive manual testing guide
- HTMX-LOADING-INDICATORS-TESTING.md - Technical documentation

Testing:
- Backend verification: 8/9 automated tests passed (88.9%)
- Manual browser testing guide provided
- Network throttling tested (Slow 3G)
- Cross-browser compatibility verified

Resolves: Prompts 002 and 003
2025-11-15 19:01:15 +00:00
juanatsap 1f7757c848 good 2025-11-15 15:59:54 +00:00
juanatsap 06eb490950 more htmx 2025-11-14 21:38:09 +00:00
juanatsap 15b73a915d wip 2025-11-12 23:07:44 +00:00
juanatsap c99bb5590b bf 6 2025-11-12 22:54:46 +00:00
juanatsap f48ae9388e bf phase v 2025-11-12 19:54:56 +00:00
juanatsap 8f2704e10a phase ii and phase iii 2025-11-12 18:55:06 +00:00
juanatsap d36b67d1f1 templating phase i 2025-11-12 18:26:18 +00:00
juanatsap c50287a4a6 fix: center zoom at 100% by adjusting range to 25-175% 2025-11-12 16:35:31 +00:00
juanatsap 94ba177220 fix: restore zoom range to 50-200% with 100% centered 2025-11-12 16:34:03 +00:00
juanatsap bef0b94add feat: expand zoom range from 50-200% to 10-500% for unlimited scaling 2025-11-12 16:19:30 +00:00
juanatsap 994716e452 refactor: wrap content in zoom-wrapper to fix footer gap issue
- Created zoom-wrapper div around cv-container
- Zoom now applies to wrapper only, footer adjusts naturally below
- Footer no longer scaled, stays at normal size
- Fixes gap between content and footer at low zoom levels
- Reduced back-to-top button size (35px default, grows to 50px on hover)
- Cleaner separation of concerns for zoom functionality
2025-11-12 15:24:09 +00:00
juanatsap 3ea0d5598e refactor: move zoom toggle to hamburger menu and make close button subtle
- Moved "Zoom" button from action bar to hamburger menu under "Acciones Rápidas"
- Close button (X) now grey/subtle by default (opacity: 0.7)
- Close button turns red only on hover for clear indication
- Updated JavaScript to reference show-zoom-menu-btn instead of show-zoom-btn
- Added preventDefault to showZoomControl to prevent link navigation
2025-11-12 15:16:21 +00:00
juanatsap 1c00421bd2 feat: add draggable zoom control with close button and menu toggle
- Add close button (X) to zoom control widget
- Make zoom control draggable anywhere on screen
- Persist dragged position in localStorage (cv-zoom-position)
- Add "Zoom" button to action bar to show control when hidden
- Persist visibility state in localStorage (cv-zoom-visible)
- Cursor changes to "move" to indicate draggability
- Interactive elements (slider, buttons) don't trigger drag
- Position stays within viewport bounds
- All features work on desktop only (zoom hidden on mobile)
2025-11-12 15:09:27 +00:00
juanatsap c1506a4d1e feat: smooth analog zoom with solid blue hover
UX improvements for more responsive, fluid zoom experience:

1. Smooth analog response:
   - Removed 50ms debounce - applies zoom immediately
   - Changed step from 5 to 1 for ultra-smooth increments
   - Updated transition: 0.08s linear (was 0.3s cubic-bezier)
   - Real-time transform updates for analog feel vs digital jumps

2. Solid blue hover (no gradient):
   - Changed from multi-color gradient to solid #3b82f6 blue
   - Maintains gray when not hovering
   - Clean, simple visual feedback matching reference design

3. Visual enhancement:
   - Keyboard shortcuts now use step 10 for faster adjustments
   - Instant response eliminates "digital" feeling
   - Smooth, continuous zoom matching analog controls

Technical changes:
- HTML: step="1" instead of step="5"
- CSS: solid color hover, 0.08s linear transition
- JS: removed debounce timeout, immediate applyZoom()
2025-11-12 11:46:19 +00:00
juanatsap b6aeb697fe feat: improve zoom control UX - circular button with colorful hover
Design improvements based on user feedback:
- Move current zoom value inside circular reset button
- Add colorful gradient (red→orange→blue→green) to slider on hover
- Make reset button perfectly circular (44px diameter)
- Dynamic value display updates in real-time inside button
- Maintains gray monochrome when not hovering
- Enhanced visual feedback with smooth color transitions
- Mobile responsive with smaller circular button (38px)

Technical changes:
- HTML: Moved #zoom-value-current span inside button
- CSS: border-radius 50%, min-width/min-height for perfect circle
- CSS: Gradient hover for both WebKit and Firefox sliders
- JavaScript: Already compatible (targets same element ID)
2025-11-12 11:37:40 +00:00
juanatsap 1c20a22522 refactor: simplify zoom control - transparent, monochrome, minimal
UI Changes:
- Made control transparent by default (opacity: 0.3), fully visible on hover
- Removed all colors - pure monochrome gray design
- Removed search icon (magnify) - no search functionality
- Changed reset icon to simple "100" text button
- Simplified layout: just 50 - slider - 100 - 200 - reset
- Moved higher: bottom 70px (desktop), 50px (tablet), 40px (mobile)

Visual Design:
- Transparent gray background with subtle blur
- Gray slider track (no rainbow gradient)
- Smaller, minimal sizing
- Numbers without % symbol for cleaner look
- Reset button shows "100" instead of circular arrows

Code Cleanup:
- Removed .zoom-label and icon markup
- Removed .zoom-slider-container wrapper
- Updated updateZoomDisplay() to use correct ID
- Simplified CSS - removed unused label styles
- Updated mobile responsive breakpoints
2025-11-12 11:09:42 +00:00
juanatsap 93b471b7e3 feat: add zoom control with accessibility and persistence
UI Components:
- Fixed bottom-center zoom slider (50%-200% range, step 5%)
- Modern glass-morphism design with gradient slider track
- Reset button with smooth rotation animation
- Real-time zoom percentage display
- Fully responsive (desktop/tablet/mobile)

Functionality:
- CSS transform-based zoom (GPU accelerated)
- localStorage persistence across sessions
- Keyboard shortcuts: Ctrl/Cmd +/-/0
- Smooth transitions with debouncing (50ms)
- Scroll position preservation during zoom
- Print mode: Temporarily resets to 100%

Accessibility (WCAG AA):
- Complete ARIA labels and live regions
- Keyboard navigation support
- Focus indicators on all interactive elements
- Screen reader compatible (announces zoom level)
- Touch-friendly (44px+ targets)

Integration:
- Follows existing toggle patterns (length, logos, theme)
- Initializes in initPreferences()
- Works with print-friendly mode
- Hidden in print (.no-print class)
- Bilingual support (English/Spanish)

Performance:
- will-change: transform for compositor layer
- Debounced slider input for smooth dragging
- requestAnimationFrame for scroll preservation
- No layout thrashing (transform-only changes)

Technical Details:
- Range: 50-200 (prevents unusability, allows 2x mag)
- Transform origin: top center (maintains alignment)
- Transition: 300ms cubic-bezier (material design)
- Storage key: 'cv-zoom'
- Default: 100% (normal view)
2025-11-12 11:00:29 +00:00
juanatsap 92dffe8c60 feat: add comprehensive testing infrastructure and security hardening
- Enhanced CI/CD pipeline with coverage reporting, benchmarks, and artifact uploads
- Implemented rate limiter IP validation with proxy support and spoofing protection
- Added extensive Makefile test targets for coverage, benchmarks, and continuous testing
- Expanded middleware chain with request validation, size limits, and suspicious activity logging
2025-11-11 21:43:12 +00:00
juanatsap 1f5aeb1c4c feat: exclude PSD files from version control 2025-11-11 13:53:14 +00:00
juanatsap 1ad6251a8c fix: redirect to lang parameter when loading from localStorage
- Change from HTMX partial update to full page redirect
- Ensures modal and all UI elements render in correct language
- Uses window.location.replace() to avoid history pollution
2025-11-10 19:32:20 +00:00
juanatsap cf8adfd0e2 refactor: swap order of collapse/expand menu buttons
- Collapse All now appears before Expand All
- More logical order: collapse first, expand second
2025-11-10 19:29:55 +00:00
juanatsap 4522d47a7e fix: reload entire page when changing language
- Changed selectLanguage() to reload full page instead of HTMX partial update
- Fixes issue where info modal content stayed in original language
- Ensures all UI elements (including modals) update correctly on language change
2025-11-10 19:29:22 +00:00
juanatsap 125b3e2c81 refactor: improve modal CTA layout with better spacing
- Swap order: subtext now appears above the button
- Add more breathing room with increased margins (1.5rem top, 1rem bottom)
- Creates clearer visual hierarchy and improved readability
2025-11-10 19:26:54 +00:00
juanatsap 4d28cb6968 feat: enhance modal photo with curly brackets and engaging CTA
- Replace blue border with green curly brackets { } using CSS pseudo-elements
- Add proper spacing and vertical centering with inline-flex
- Add engaging subtext below GitHub button: "Want to know how it's built?"
- Bilingual support for subtext (EN/ES)
2025-11-10 19:19:41 +00:00