Commit Graph

66 Commits

Author SHA1 Message Date
juanatsap 6970606c42 refactor: simplify contact form timestamp with hyperscript + minimal JS
Replace 34-line IIFE/MutationObserver with:
- Hyperscript: on toggle if me.open call resetContactForm()
- 11-line resetContactForm() function

Also dispatches 'show' event from openModal() for ninja-keys integration.
All 7 contact form tests pass.
2025-12-02 16:00:00 +00:00
juanatsap 9a848e8c53 feat: Add CMD+K command palette with ninja-keys integration
Implement a command palette accessible via CMD+K/Ctrl+K using the ninja-keys
web component. Features include:

- New /api/cmd-k endpoint serving dynamic CV entries (experiences, projects, courses)
- Language-aware responses with 1-hour cache headers
- Scroll-to-section functionality for quick navigation
- Enhanced keyboard shortcuts modal with CMD+K documentation
- Comprehensive test coverage for API and UI interactions

Also includes cleanup of deprecated debug test files and various UI polish
improvements to contact form, themes, and action bar components.
2025-12-01 13:03:06 +00:00
juanatsap c834919a3c fix: Default to light theme for all first-time visitors
First-time visitors now always see light theme (paper aesthetic)
regardless of their system dark mode preference.

Users can still switch to dark or auto mode, and their preference
is saved to localStorage for future visits.

This maintains the professional CV paper appearance as the default
experience while giving users full control over their preference.
2025-11-30 09:35:31 +00:00
juanatsap eb92f64e93 fix: Mobile hamburger menu and iPad sidebar visibility
Mobile fixes:
- Add click toggle handler for hamburger menu (was hover-only)
- Menu now opens/closes on tap and closes when clicking outside
- Keep hover support for desktop

iPad fixes:
- Sidebar content now visible on touch devices (901-1280px)
- Added (hover: hover) media query to prevent hide-on-hover on tablets

Security improvements:
- Replace exec.CommandContext with go-git library for git operations
- Add path traversal and command injection prevention
- Fix race condition in template hot reload
- Add environment-based cookie Secure flag

Code quality:
- Add constants.go for magic numbers
- Remove unused code (ParsePreferenceToggleRequest, DomainError)
- Add FOUC prevention with inline critical CSS
- Add Makefile dev/run/clean targets
- Fix README git clone URL
- Add doc/DECISIONS.md for architectural decisions

Tests:
- Add hamburger menu click toggle tests
- Add iPad sidebar visibility tests
- Update security tests for go-git implementation
- Add cookie Secure flag tests
2025-11-30 09:29:35 +00:00
juanatsap cf6b825bde refactor: Add scrollToSection and fix missing functions
- Add scrollToSection() to utils._hs (was missing after cv-functions.js removal)
- Move error toast close handler to inline hyperscript
- Remove initMenuCloseOnClick() - now integrated into scrollToSection()
- Remove initErrorToastClose() - now hyperscript inline handler
- Remove unused initScrollBehaviorJS() fallback (~70 lines dead code)

This fixes the navigation menu scroll functionality and eliminates
more JavaScript in favor of hyperscript.
2025-11-30 06:06:10 +00:00
juanatsap 7ab150a48e refactor: Migrate zoom control and expand/collapse to hyperscript
- Move initZoomControlButtons() from main.js to hyperscript handlers
  - zoom-toggle-button: on click call toggleZoomControl()
  - zoom-close: on click call hideZoomControl()
  - show-zoom-menu-btn: on click call showZoomControl()
- Move expandAllSections/collapseAllSections from JS to utils._hs
- Add zoom visibility functions to zoom._hs:
  - showZoomControl(), hideZoomControl(), toggleZoomControl()
- Update hamburger menu links to use hyperscript calls

Eliminates ~75 more lines of JavaScript in favor of declarative
hyperscript, continuing the pattern of moving behavior to ._hs files.
2025-11-30 06:03:45 +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 da483ae9f1 fix: Differentiate zoom and info button colors, fix button visibility in responsive mode
Issues fixed:
1. Zoom button now uses purple color (rgba(155, 89, 182, 0.7)) instead of blue
2. Info button keeps blue color (rgba(52, 152, 219, 0.7))
3. Both buttons now show distinct colors in default state, not just on hover
4. Device detection now considers viewport width, not just user agent
5. Buttons no longer hide in responsive mode at desktop viewport sizes

Changes:
- Updated zoom-toggle-btn to use purple background color
- Updated info-button to use blue background color (explicit, not var)
- Modified device-detection.js to check viewport width (≤900px) in addition to UA
- Added resize listener to update device class dynamically
- Created test (67-button-colors-and-visibility-test.mjs) to verify fixes

Testing:
- Desktop (1278px): All buttons visible with distinct colors
- Mobile (375px): Zoom/shortcuts hidden, core buttons visible
- Device detection now viewport-aware (prevents hiding at desktop sizes)
2025-11-25 06:41:56 +00:00
juanatsap 76d80edd7e fix: Remove unused cookie helper functions and fix desktop sidebar visibility
1. Removed unused getPreferenceCookie and setPreferenceCookie functions
   - These were flagged by golangci-lint as unused
   - Cookie preferences now handled client-side via localStorage
   - Removed unused net/http import

2. Fixed desktop sidebar accordion auto-opening
   - Updated handleLandscapeAccordions() to open accordions in desktop view (≥769px)
   - Sidebars now show content in desktop, landscape mobile, and portrait mobile
   - Only keep accordions collapsed in portrait mobile for space saving

3. Created comprehensive multi-viewport test (66-comprehensive-all-viewports-test.mjs)
   - Tests desktop (1278px), portrait mobile (375×667), landscape mobile (667×375)
   - Validates sidebars, accordion state, content visibility, AND all buttons
   - Checks button backdrop visibility in mobile views
   - Every feature now has corresponding test coverage

Fixes golangci-lint errors:
- internal/handlers/cv_helpers.go:366: func getPreferenceCookie is unused
- internal/handlers/cv_helpers.go:375: func setPreferenceCookie is unused
- internal/handlers/cv_helpers.go:7: net/http imported and not used
2025-11-25 06:00:39 +00:00
juanatsap 82f73cf724 fix: CRITICAL - Restore sidebar visibility in landscape mode
Fixed critical issue where sidebars were completely collapsed/hidden
in landscape mode, showing only 33px accordion headers instead of full content.

ROOT CAUSE:
- Sidebar accordions (<details> elements) were collapsed by default
- Native <details> browser behavior prevented CSS-only expansion
- Sidebar content was present but hidden behind collapsed accordion

SOLUTION:
1. JavaScript: Added handleLandscapeAccordions() to auto-open sidebar
   accordions when in landscape orientation (≤915px width)
   - Runs on DOMContentLoaded, orientationchange, and resize events
   - Uses matchMedia to detect landscape mode
   - Sets 'open' attribute on all .sidebar-accordion elements

2. CSS: Enhanced sidebar container styles in landscape mode
   - Set overflow: visible on sidebars (was hidden)
   - Set height: auto on sidebars and .actual-content wrappers
   - Forced accordion content visibility with !important rules
   - Made summary non-clickable in landscape (pointer-events: none)

3. Tests: Updated landscape test to validate sidebar visibility
   - Now checks sidebar visible/hidden state
   - Validates sidebar height (should be >100px, not 33px)
   - Added debug tests for troubleshooting

RESULTS:
- Sidebar height: 1387px (Android) / 1536px (iPhone) ✓
- Accordion state: OPEN ✓
- All sidebar content fully visible ✓
- No horizontal scroll ✓

Test files:
- tests/mjs/54-landscape-mode-test.mjs (updated with sidebar checks)
- tests/mjs/60-sidebar-content-debug.mjs (new debug test)
- tests/mjs/61-sidebar-positioning-debug.mjs (positioning debug)
- tests/mjs/62-sidebar-computed-height-debug.mjs (height debug)
- tests/mjs/63-media-query-match-test.mjs (media query validation)
2025-11-25 05:44:40 +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 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 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 9f3b8853a3 docs: Cleanup and consolidate PDF documentation
## Documentation Cleanup
- Moved PDF-EXPORT-FEATURE.md → doc/11-PDF-EXPORT.md
- Added shortcut URL documentation section
- Updated changelog to v2.1.0 with shortcut URL feature
- Removed ephemeral reports (validation, shortcut implementation)

## Removed Backup Files
- Deleted static/css/main.css.backup
- Deleted static/js/main.js.backup

## Consolidated PDF Documentation
The comprehensive PDF export documentation now includes:
- Year-aware shortcut URLs (/cv-jamr-{year}-{lang}.pdf)
- Automatic year validation and updates
- Default CV modal integration
- All PDF export options and features
- Complete API reference

Benefits:
- Single source of truth for PDF feature documentation
- Removed temporary/ephemeral documentation files
- Cleaner repository structure
- Updated versioning to 2.1.0
2025-11-20 12:25:41 +00:00
juanatsap 66e06a6cb0 feat: Add year-aware PDF shortcut URLs + Default CV modal option
## Shortcut URLs
- New routes: /cv-jamr-{year}-{lang}.pdf (e.g., /cv-jamr-2025-en.pdf)
- Year validation: Only current year accepted, returns 404 for past/future
- Auto-redirects (301) to: /export/pdf?lang={lang}&length=short&icons=show&version=with_skills
- Both languages supported: en and es

## PDF Modal Updates
- Replaced "Current View" option with "Default CV (Recommended)"
- Visual highlighting: purple gradient badge, star emoji , bold text
- Uses shortcut URL with dynamic year detection
- Clear recommendation for users (5 pages, short with skills)

## Technical Details
- Handler: DefaultCVShortcut() in internal/handlers/cv.go
- Pattern check in Home() handler for proper routing
- Helper function: window.openPdfModal() for references section
- Documentation: PDF-SHORTCUT-IMPLEMENTATION.md

Benefits:
- Memorable, shareable URLs (juan.andres.morenorub.io/cv-jamr-2025-en.pdf)
- Auto-updates yearly without code changes
- Clear user guidance for recommended CV format
2025-11-20 12:14:53 +00:00
juanatsap b44f9b9a99 refactor: Rename 'extended' → 'long' + add compact sidebar fonts
BREAKING CHANGE: API parameter renamed from 'extended' to 'long'

## Breaking Change: Terminology Standardization

Renamed 'extended' to 'long' across entire codebase for consistency:

**Backend (Go):**
- internal/handlers/cv.go (7 locations)
  - Migration logic to auto-convert 'extended' → 'long' cookies
  - API validation now rejects 'extended', requires 'long'
  - Toggle state logic updated
- internal/handlers/pdf_test.go (17 occurrences)
  - Test function renamed: TestExportPDF_ExtendedWithSkills → TestExportPDF_LongWithSkills
  - All test cases, parameters, and expected filenames updated
- internal/pdf/generator.go (2 comment updates)

**Frontend:**
- PDF-EXPORT-FEATURE.md (3 occurrences)
- doc/3-API.md (parameter documentation)
- doc/7-CUSTOMIZATION.md (examples updated)
- templates/partials/modals/pdf-modal.html (button text, URLs)
- static/js/main.js (migration logic)
- static/hyperscript/toggles._hs (toggle logic)
- tests/mjs/24-pdf-download-params.test.mjs (test expectations)
- tests/mjs/test-preference-migration.test.mjs (NEW)
- tests/mjs/verify-migration.test.mjs (NEW)

**PDFs Renamed:**
- cv-extended-with_skills-jamr-2025-en.pdf → cv-long-with_skills-jamr-2025-en.pdf
- cv-extended-with_skills-jamr-2025-es.pdf → cv-long-with_skills-jamr-2025-es.pdf

**Migration:** Automatic cookie migration from 'extended' → 'long' for seamless UX

## New Feature: Compact Sidebar Fonts

Reduces page count for short CV with skills from 6 → 5 pages:

**Implementation:**
- Location: internal/pdf/generator.go (lines 154-215)
- Cookie detection: `cookies["cv-length"] == "short"`
- Font reduction: 2-6% (0.94-0.98em) - very subtle
- Only activates for: `length=short` + `version=with_skills`
- Long version: Always uses full-size fonts

**Impact:**
- Page count: 6 pages → 5 pages (16.7% reduction)
- Readability: Maintained - fonts remain professional
- Design philosophy: Subtle, natural content flow

**Testing:**
- New test: TestPDFGenerator_CompactSidebarFonts
- Comprehensive coverage of cookie detection and PDF generation
- Manual verification: 5-page PDF with compact but readable fonts

**Documentation:**
- doc/LONG-PDF-GENERATION.md (NEW, 13 KB)
  - Complete feature documentation
  - Implementation details with code examples
  - Font size breakdown table
  - Testing and troubleshooting guides
  - Compact sidebar fonts section (comprehensive)

**Files Changed:**
- 11 modified (backend + frontend + docs)
- 5 new files (2 PDFs, 1 doc, 2 tests)
- 2 files renamed (PDFs)

**Tests:** All Go tests passing, API validation verified, PDF generation tested
2025-11-20 11:21:43 +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 4df0360202 fix: Sync view switcher initialization with container target
The toggleTheme() function targets .cv-container but initPreferences()
was adding theme-clean to document.body, causing state mismatch.
First click would do nothing because toggle state was inverted.

- Change initPreferences() to target .cv-container
- Fix HTMX swap handler to check .cv-container instead of body
- Now first click works immediately in both directions
2025-11-19 14:49:28 +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 35a836adf3 fix: restore zoom level persistence on page load
Zoom level persistence was broken because hyperscript was setting the
container's value instead of the slider's value on page load.

Changes:
- Fix zoom-control.html line 10: set #zoom-slider's value (not 'my value')
- Add comprehensive zoom persistence test (10-zoom-persistence.test.mjs)
- Update cv-functions.js documentation to clarify hyperscript interop
- Add zoom control feature to README

Test results: 5/5 tests pass
- Zoom saves to localStorage when changed 
- Zoom restores correctly on page reload 
- Reset to 100% works and persists 

Architecture note:
- Hyperscript 'call' within _="" attributes requires global JS scope
- JavaScript wrappers bridge window exposure to hyperscript evaluate()
- Pattern: window.fn() → _hyperscript.evaluate('hyperscriptFn()')
2025-11-17 16:56:01 +00:00
juanatsap 491aa66920 fix: add JavaScript wrappers for hyperscript functions to enable 'call' syntax
Problem: Hover sync not working after migration to hyperscript
Root cause: Hyperscript 'call' command requires functions in global JavaScript scope
- Hyperscript def functions are NOT automatically exposed to window
- Templates use _="on mouseenter call syncPdfHover(true)"
- This syntax expects a JavaScript function

Solution: Thin JavaScript wrappers that delegate to hyperscript implementations
- Wrappers use _hyperscript.evaluate() API to call hyperscript defs
- Functions exposed to window.* for global access
- Implementation stays in hyperscript, wrappers just bridge the gap

Affected functions:
- toggleCVLength, toggleIcons, toggleTheme (toggles._hs)
- syncPdfHover, syncPrintHover, highlightZoomControl (hover-sync._hs)

Why test didn't catch this:
- Test 8 dispatches events programmatically in JavaScript
- This triggers hyperscript handlers directly
- Real browser hover calls JavaScript functions which were missing
2025-11-17 16:40:29 +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 f87a1a5c28 fix: implement complete hover synchronization for PDF/Print buttons
CRITICAL BUG FIX: Hover states now sync between action bar and hamburger menu

Changes:
1. Added mouseenter/mouseleave handlers to menu PDF button
   - templates/partials/navigation/hamburger-menu.html:178-181
   - Added .menu-pdf-btn class for targeting
   - Added hyperscript hover sync events

2. Updated syncPdfHover() function
   - static/js/cv-functions.js:71-82
   - Now selects both .pdf-btn and .menu-pdf-btn
   - Both buttons get .pdf-hover-sync class on hover

3. Updated syncPrintHover() function
   - static/js/cv-functions.js:88-99
   - Now selects both .print-btn and .menu-print-btn
   - Both buttons get .print-hover-sync class on hover

4. Added CSS for menu PDF button hover sync
   - static/css/main.css:2690-2700
   - .menu-pdf-btn.pdf-hover-sync styling (white bg, red icon)
   - Matches action bar PDF button hover state

5. Created comprehensive hover sync test
   - tests/mjs/8-hover-sync.test.mjs
   - Tests all 4 hover scenarios (bar→menu, menu→bar for both buttons)
   - Validates event handlers and CSS class application
   - Manual verification instructions included

Behavior now correct:
 Hovering action bar PDF button highlights menu PDF button
 Hovering action bar Print button highlights menu Print button
 Hovering menu PDF button highlights action bar PDF button
 Hovering menu Print button highlights action bar Print button

Fixes documented bug from PROJECT-MEMORY.md Section 3.
2025-11-17 14:35:32 +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 c456bb1637 fix: remove blue active state from zoom button and restore Show Zoom menu item
- Removed .zoom-active CSS class and JavaScript logic
- Zoom button stays same gray color whether zoom is on or off
- Fixed Show Zoom menu button visibility (changed inline style to zoom-hidden class)
- Menu item now correctly appears when zoom is hidden
2025-11-16 13:32:57 +00:00
juanatsap ac0cf15eb9 added zoom in buttons 2025-11-16 12:48:12 +00:00
juanatsap a8d6805e27 feat: enhance shortcuts modal and complete logos-to-icons rename
This commit includes graphical keyboard icons integration, modal styling
improvements, and comprehensive "Logos" to "Icons" terminology update.

Changes:
- Add graphical keyboard icons using Iconify MDI (Tab, Ctrl, Cmd, Esc, etc.)
- Implement color scheme: black title, green subtitle/headers, blue kbd elements
- Add visual boxes with borders and shadows for section grouping
- Change modal from 3-column to 2-column grid layout (900px width)
- Fix critical bug: all 5 sections now render (was only showing 2)

Rename "Logos" to "Icons" across entire codebase:
- Go models: ToggleLogos → ToggleIcons, ShowLogos → ShowIcons
- Routes: /toggle/logos → /toggle/icons
- Templates: desktop-logo-toggle → desktop-icon-toggle, #logoToggle → #iconToggle
- JavaScript: logoToggles → iconToggles, sync logic updated
- CSS: .show-logos → .show-icons
- UI JSON: toggleLogos → toggleIcons
- Comments and labels updated

Technical details:
- Rebuilt Go binary to fix template rendering error
- Fixed JSON struct tag: json:"toggleLogos" → json:"toggleIcons"
- Updated kbd element styling for icon alignment (inline-flex)
- Added margin-bottom to subtitle (0.5rem)
- Grid now 2 columns for better 5-section layout

All 5 sections now render correctly:
1. Zoom Control
2. View Controls
3. Navigation
4. Actions
5. Browser Defaults
2025-11-15 18:42:35 +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 81f8161dd2 refactor: simplify menu and toast interactions with CSS-driven animations
- Moved menu hover logic from JavaScript to CSS selectors, reducing JS to minimal bridge code
- Replaced JavaScript-based toast timing with pure CSS animation lifecycle (slide in → stay → fade out)
- Removed unnecessary event handlers and legacy compatibility code for cleaner implementation
2025-11-12 19:23:46 +00:00
juanatsap fda034ca78 phase iv -ii 2025-11-12 19:13:52 +00:00
juanatsap d35a1decc7 phase iv - i 2025-11-12 18:59:48 +00:00
juanatsap 8f2704e10a phase ii and phase iii 2025-11-12 18:55:06 +00:00
juanatsap be04b2dbc2 first commit 2025-11-12 18:14:48 +00:00
juanatsap 3a381ee111 fix: apply inverse zoom to fixed buttons to maintain constant size 2025-11-12 16:55:28 +00:00
juanatsap ff93a3f314 fix: allow horizontal scroll and content expansion when zoomed beyond viewport 2025-11-12 16:53:28 +00:00
juanatsap 3aeaf3db43 fix: revert to CSS zoom property for proper layout-affecting zoom 2025-11-12 16:51:05 +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 15834a6d6b fix: switch from CSS zoom to transform scale for true unlimited zoom
- Replace CSS zoom with transform: scale() for proper viewport extension
- Add dynamic margin-bottom to position footer correctly
- Remove zoom: 1 reset from fixed buttons (no longer needed)
- Enables true zoom from 10% to 500% that extends beyond viewport
2025-11-12 16:24:21 +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 25c69a1356 feat: add dynamic green highlighting for bottom scroll and zoom controls
- Add green background (#27ae60) to info and back-to-top buttons when at page bottom
- Implement bottom detection (within 50px threshold) in scroll handler
- Add conditional green hover to zoom reset button (only when zoom ≠ 100%)
- Enhance UX with visual feedback for scroll position and zoom state
2025-11-12 16:07:19 +00:00
juanatsap 4fcade2207 fix: use CSS zoom on wrapper to eliminate footer gap
Switched from transform: scale() to CSS zoom property on zoom-wrapper.
CSS zoom changes actual layout space, not just visual rendering:
- At 50% zoom, wrapper takes 50% space (no reserved empty space)
- Footer naturally follows right after zoomed content
- At 200% zoom, content extends beyond viewport with scrolling
- Fixes the large gray gap between content and footer
2025-11-12 15:33:02 +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