Commit Graph

236 Commits

Author SHA1 Message Date
juanatsap 0671955280 feat: Add new background patterns for light and dark themes
Light theme:
- Change background from #b8bbbe to #d6d6d6 (light gray)
- Add concentric squares pattern with 4 gradient layers
- Creates subtle geometric texture on gray background

Dark theme:
- Change background from rgb(82, 86, 89) to #3a3a3a (medium gray)
- Add diagonal grid pattern with green glow (rgba(0, 255, 128, 0.15))
- 45deg and -45deg crosshatch creates retro tech aesthetic

Both patterns use CSS custom properties (--page-bg-pattern) and are
applied via background-image in _reset.css. Patterns are fixed and
maintain visibility across theme switches.
2025-11-20 13:50:53 +00:00
juanatsap efdc4bd88d test: Add new background patterns for light and dark themes
**TESTING** - These patterns can be easily reverted or modified

Light Theme (Woven Fabric Pattern):
- Subtle gray crosshatch pattern
- Multiple gradients creating woven texture
- Professional and clean appearance

Dark Theme (Diagonal Grid with Green Glow):
- 45° and -45° diagonal lines
- Green glow (rgba(0, 255, 128, 0.1))
- Cyberpunk/tech aesthetic
- 40px grid spacing

Implementation:
- Added --page-bg-pattern CSS variables to color-theme.css
- Applied patterns via body background-image in _reset.css
- OLD pattern commented out and preserved for easy restoration
- Patterns work with light, dark, and auto themes

Files changed:
- static/css/color-theme.css: Added pattern variables
- static/css/01-foundation/_reset.css: Applied patterns to body

To revert: Uncomment old pattern and remove --page-bg-pattern usage
2025-11-20 13:10:11 +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 c88879b180 feat: Add loading overlay feedback for PDF downloads
UX Improvement:
- Added visual feedback during PDF generation process
- Users now see immediate response when clicking download button
- Clear communication about what's happening during the wait

New Features:
- Loading overlay with animated spinner
- Format-specific estimated generation times (Short: ~3s, Default: ~4s, Long: ~8s)
- Blur effect on modal background during loading
- Bilingual support (English/Spanish)
- Automatic modal close after download completes

CSS Updates (static/css/04-interactive/_modals.css):
- Added .pdf-loading-overlay with glassmorphism effect
- Spinning animation for loader (1s linear infinite)
- Fade-in animation (300ms)
- Accessibility: respects prefers-reduced-motion
- Background blur when loading active

HTML Updates (templates/partials/modals/pdf-modal.html):
- Loading overlay structure with spinner
- Dynamic loading messages based on selected format
- Enhanced downloadPDF() function with timing logic

Before: Click → silence → download appears
After: Click → overlay + spinner + estimate → download appears
2025-11-20 12:52:16 +00:00
juanatsap 1258d61d05 refactor: Modularize CSS into ITCSS architecture + update documentation
CSS Refactoring:
- Split 2,287-line monolith into 6 focused modules
- New structure: Navigation, Scroll, Buttons, Modals, Zoom, Breakpoints
- Organized by ITCSS layers (Interactive + Responsive)
- 245 lines saved through better organization
- Site verified working at localhost:1999

New CSS Files:
- 04-interactive/_navigation.css (357 lines, 8.2KB)
- 04-interactive/_scroll-behavior.css (200 lines, 5.0KB)
- 04-interactive/_buttons.css (184 lines, 4.7KB)
- 04-interactive/_modals.css (487 lines, 16KB)
- 04-interactive/_zoom-control.css (253 lines, 6.3KB)
- 05-responsive/_breakpoints.css (561 lines, 14KB)

Documentation Updates:
- Added doc/12-CSS-ARCHITECTURE.md (comprehensive CSS guide)
- Updated doc/README.md (new entry + correct numbering)
- Updated tests/README.md (test count 8 → 27)
- Updated tests/TEST-SUMMARY.md (coverage expansion)
- Rewrote tests/mjs/README.md (complete test listing)

Removed:
- static/css/04-interactive/_remaining.css (replaced by modules)
2025-11-20 12:34:42 +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 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 709a91c652 fix: Project responsibility icons - 60px + color unset
Applied same fix to project icons (like Mobbeel security icon):
- 60px × 60px size
- color: unset !important for inline styles
- Matches course icons styling exactly
2025-11-19 17:21:00 +00:00
juanatsap a56212fc79 fix: Course icons 60px + unset color for inline styles
- Changed from 24px back to 60px (matching projects structure)
- Used color: unset !important to reset CSS color override
- Allows inline color styles (style='color: #9333EA') to work
- Matches the project list icon styling exactly
2025-11-19 17:18:52 +00:00
juanatsap 2e90653d31 fix: Course list icons - 24px size + attempt color preservation
- Reduced course responsibility icons to 24px (was 80px)
- Added color: inherit !important to try preserving inline color styles
- Removed borders, backgrounds, and padding for cleaner inline appearance

Note: color: inherit may inherit from parent theme color rather than
preserving individual icon colors. May need adjustment.
2025-11-19 17:14:27 +00:00
juanatsap 0f5137ddcb fix: Restore visibility of course list icons (keep at 60px)
Removed overly broad selector that was shrinking ALL course
responsibility icons to 1.2em. Now only targets truly inline
icons within .course-desc text, not the main 60px list icons.
2025-11-19 16:57:12 +00:00
juanatsap 43414b79ac fix: Override inline icon sizes to 1.2em across all sections
Problem: Inline icons embedded in responsibilities, courses, and
projects had explicit width='60' height='60' attributes that made
them too large (60px instead of ~16px).

Solution:
- Added CSS with !important to override inline width/height attributes
- Targeted inline icons in:
  * Course responsibilities and descriptions
  * Project descriptions and technologies
  * Experience responsibilities (within divs)
- Preserved large icons (80px) for main company/course/project logos

Changes:
- static/css/03-components/_courses.css: Override to 1.2em
- static/css/03-components/_projects.css: Override to 1.2em
- static/css/03-components/_cv-section.css: Override to 1.2em

Test Results:
 7 course inline icons: 16px × 16px
 Main company icons: 80px × 80px (preserved)
2025-11-19 16:30:18 +00:00
juanatsap 06ec9b9f20 fix: Restore inline icon styling in course descriptions
- Added font-size: 1.2em for smaller icons
- Added vertical-align: middle for proper alignment
- Added margin: 0 0.15em for spacing
- Added color: inherit !important to preserve icon colors
- Lost during CSS modularization refactor
2025-11-19 16:04:40 +00:00
juanatsap 617a8e1643 fix: Correct LIV Golf border color for invert filter
Calculation: #5e5e5e inverted = #a1a1a1
- Set LIV Golf border to #a1a1a1 in dark theme
- After invert(1) filter → appears as #5e5e5e (correct gray)
- Light theme: resets to normal var(--icon-border)

Filter inverts ENTIRE element including borders, so we
pre-compensate by using the inverse color.
2025-11-19 15:52:01 +00:00
juanatsap 93e7b81061 fix: Change dark theme icon border to #5e5e5e medium gray
- Changed from transparent to #5e5e5e (rgb(94,94,94))
- Visible but subtle medium gray border in dark theme
- Updated test to verify new border color
- Note: CSS filter on LIV Golf only affects image pixels, not border
2025-11-19 15:49:55 +00:00
juanatsap 0947e19c70 fix: Replace ALL remaining hardcoded #ddd borders with theme variable
Replaced 12 hardcoded borders across 5 files:
- _cv-section.css: 2 borders (company icons)
- _projects.css: 2 borders (project icons)
- _courses.css: 2 borders (course icons)
- _toggles.css: 3 borders (logo containers)
- logo-toggle.css: 3 borders (logo containers)

All icon borders now use var(--icon-border):
- Light theme: #ddd (visible)
- Dark theme: transparent (invisible)

Verified with Playwright: rgba(0,0,0,0) in dark theme
2025-11-19 15:47:19 +00:00
juanatsap df77a269c0 fix: Make icon borders completely transparent in dark theme
- Changed from rgba(255,255,255,0.05) to 'transparent'
- Previous attempt used WHITE transparent which was still visible
- Now borders are rgba(0,0,0,0) - completely invisible
- Verified with Playwright test showing transparent borders
- All icons (OBS, LIV Golf, etc.) now have no visible borders
2025-11-19 15:41:36 +00:00
juanatsap 5dc5a98269 fix: Make icon borders nearly transparent in dark theme
- Changed from #1e1e1e to rgba(255, 255, 255, 0.05)
- Borders now 95% transparent, virtually invisible
- Applies to ALL icon borders (OBS, LIV Golf, etc.)
- Invert filter remains ONLY for LIV Golf logo
2025-11-19 15:39:00 +00:00
juanatsap 82df6849bd fix: Make icon borders nearly invisible in dark theme
- Changed --icon-border from #2a2a2a to #1e1e1e (rgb(30,30,30))
- Background is #1a1a1a (rgb(26,26,26)), only 4 RGB units difference
- Borders now barely visible, creating cleaner dark theme appearance
2025-11-19 15:30:39 +00:00
juanatsap ac73b49d8d feat: Darker icon borders/separators in dark theme + invert LIV Golf logo
- Add --icon-border variable: #ddd (light) / #2a2a2a (dark)
- Add --item-separator variable: rgba(0,0,0,0.1) / rgba(255,255,255,0.05)
- Replace 6 hardcoded icon borders with var(--icon-border)
- Replace 3 hardcoded separators with var(--item-separator)
- Add CSS filter to invert LIV Golf logo in dark themes for visibility
- LIV Golf logo filter: invert(1) in dark/auto(dark), none in light
2025-11-19 15:26:19 +00:00
juanatsap 85de5b621f fix: Sync auto theme sidebar color with explicit dark theme
- Auto theme dark mode now uses #3a3d3e (matches explicit dark)
- Previously used #2a2a2a causing visible difference when switching
- Ensures only two visual states (light/dark) regardless of theme mode
2025-11-19 15:08:03 +00:00
juanatsap 59a16ce1e0 fix: Theme-aware sidebar with dark mode support
Light theme sidebar:
- Background: #d1d4d2 (light gray)
- Text: dark colors

Dark theme sidebar:
- Background: #3a3d3e (darker gray, between page bg and content)
- Text: light colors (using CSS variables)
- Titles: light colors

Changes:
- Revert sidebar bg to use var(--sidebar-bg) for theme switching
- Update dark theme sidebar color to #3a3d3e
- Replace all hardcoded text colors with CSS variables
- Sidebar titles, content, and arrows now adapt to theme
2025-11-19 15:01:48 +00:00
juanatsap 35a802cbd5 fix: Keep sidebar background consistent across themes
Change sidebar background from var(--sidebar-bg) to fixed #d1d4d2
so it remains the same light gray color in both light and dark themes.

The sidebar should provide a consistent visual anchor regardless
of the main content theme.
2025-11-19 14:57:38 +00:00
juanatsap 4886a36f2c fix: Make CV main content area theme-aware
Change .cv-main background from var(--paper-white) to var(--paper-bg)
so it adapts to theme:
- Light theme: white (#ffffff)
- Dark theme: cool dark gray (#1a1a1a)

Now the entire CV paper is dark in dark theme, not just the page background.
2025-11-19 14:54:10 +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 ddd09f9a16 fix: Improve color theme button colors for better distinction
**Issue**: Color theme button colors were too similar to other buttons
- Light mode (sun): Orange #f39c12 - same as keyboard button
- Dark mode (moon): Blue #3498db - same as zoom button

**Fix**: Updated to more distinctive colors

Light mode (sun):
- Was: Orange #f39c12 (same as keyboard)
- Now: Gold/Bright Yellow #ffd700 (distinct sun color)

Dark mode (moon):
- Was: Bright Blue #3498db (same as zoom)
- Now: Dark Slate Blue #2c3e50 (darker "nighty" blue)

Auto mode:
- Kept: Purple #9b59b6 (already distinctive)

**Result**: Color theme button now has unique, semantic colors that
clearly represent sun (bright yellow) and moon (dark night blue) without
conflicting with other buttons.

Updated both hover and at-bottom states for consistency.
2025-11-19 09:38:24 +00:00
juanatsap 2ebb9f5293 fix: Use each button's hover color for at-bottom state + add zoom button
**Bug 1: Wrong at-bottom colors**
- All buttons were showing orange (#f39c12) when at bottom
- User wanted each button to use its own hover color

**Bug 2: Zoom button missing at-bottom state**
- Zoom/search button wasn't changing color at bottom

**Fix - Updated .at-bottom styles to match hover colors:**

Download PDF button:
- Was: Orange (#f39c12)
- Now: PDF Red (#cd6060) - matches hover

Print Friendly button:
- Was: Orange (#f39c12)
- Now: White background + Green icon (#27ae60) - matches hover

Shortcuts button:
- Kept: Orange (#f39c12) - already correct

Color Theme Switcher:
- Was: Uniform orange
- Now: Dynamic colors based on theme mode
  - Light mode: Yellow (#f39c12)
  - Dark mode: Blue (#3498db)
  - Auto mode: Purple (#9b59b6)

Info button:
- Already correct: Green (#27ae60)

Back-to-top button:
- Already correct: Green (#27ae60)

Zoom button:
- Added: Blue (#3498db) - matches hover
- Added to scroll handler in utils._hs

**Result**: Each button now shows its characteristic color when page
is scrolled to bottom, providing consistent visual feedback that matches
the hover state.

Files changed:
- static/hyperscript/utils._hs: Added zoom button
- static/css/main.css: Updated 3 button colors
- static/css/color-theme.css: Dynamic theme colors
2025-11-19 09:35:17 +00:00
juanatsap f9ce37b6d0 fix: Apply at-bottom color to ALL buttons consistently
**Issue**: Only info and shortcuts buttons were showing orange color when
scrolled to bottom of page. Download PDF, Print Friendly, and Color Theme
buttons were missing this visual feedback.

**Fix**:
1. Added all buttons to at-bottom class logic in utils._hs:
   - #download-button
   - #print-friendly-button
   - .color-theme-switcher

2. Added CSS .at-bottom styles for missing buttons:
   - .download-btn.at-bottom
   - .print-friendly-btn.at-bottom
   - .color-theme-switcher.at-bottom

**Result**: All fixed buttons now show unified orange (#f39c12) background
when page is scrolled to bottom (within 50px), providing consistent visual
feedback across all controls.

Files changed:
- static/hyperscript/utils._hs: Added 3 buttons to scroll handler
- static/css/main.css: Added 2 .at-bottom styles
- static/css/color-theme.css: Added 1 .at-bottom style
2025-11-19 09:29:10 +00:00
juanatsap d220546d02 fix: Bidirectional hover sync + theme-aware CV text colors
**Bug 1: Bidirectional Hover Sync**
- Fixed hover sync to work in BOTH directions
- Hovering left buttons → highlights menu buttons (was working)
- Hovering menu buttons → highlights left buttons (NOW WORKING)
- Added .download-btn and .print-friendly-btn to syncPdfHover/syncPrintHover selectors

**Bug 2: Theme-Aware CV Text Colors**
- CV content text now adapts to light/dark themes
- Light theme: Dark text (#1a1a1a, #333333) for readability
- Dark theme: Light text (#e0e0e0, #d0d0d0) for readability
- Added theme-specific overrides for --text-dark and --text-gray variables
- Solution uses CSS variables (not hardcoded) for future flexibility

Changes:
- static/hyperscript/hover-sync._hs: Added left-side button selectors
- static/css/color-theme.css: Added legacy variable overrides for all themes
2025-11-19 09:24:29 +00:00
juanatsap b8bd0b5c3c fix: Keep back-to-top button on RIGHT side in narrow mobile (<483px)
Corrected positioning - button now stays on RIGHT side, just moved UP:
- right: 1.5rem (stays on right)
- bottom: 5.5rem (moved higher to avoid overlap)

This prevents overlap with bottom button row while maintaining
right-side positioning as requested.
2025-11-18 21:51:44 +00:00
juanatsap 8da442b248 fix: Back-to-top button position on very narrow screens (<483px)
**Problem:**
On screens narrower than 483px, the horizontal button layout caused overlap
between back-to-top button and other buttons due to limited width.

**Solution:**
Added media query for max-width: 483px to vertically stack back-to-top button:
- Moved back-to-top to LEFT side (left: 1.5rem)
- Positioned ABOVE info button (bottom: 5.5rem)
- Maintains 4rem vertical spacing between buttons (same as desktop)

**Layout behavior:**
- Above 900px: All buttons vertical on left side (desktop)
- 483px - 900px: Buttons horizontal at bottom center + back-to-top at bottom-right
- Below 483px: Buttons horizontal at bottom center + back-to-top stacked above info button (left side)

This prevents button overlap on narrow mobile devices while maintaining
consistent spacing and positioning.

Files modified: static/css/main.css
2025-11-18 21:48:41 +00:00
juanatsap cc6ca6e6ba fix: Back-to-top button positioning in mobile + consistent hover effects
Fixed two UI bugs in button styling:

**1. Back-to-top button position in mobile:**
- BEFORE: Button was included in flexbox layout but not positioned (defaulted to left)
- AFTER: Excluded from flexbox layout, positioned at bottom-right (1.5rem) - same as desktop
- Mobile flexbox layout now has 5 buttons (download, print, shortcuts, theme, info)
- Back-to-top stays independently positioned at bottom-right corner

**2. Consistent hover effects for all buttons:**
- BEFORE: Only info and shortcuts buttons had enhanced box-shadow on hover
- AFTER: All buttons (download, print, shortcuts, info, back-to-top) have consistent hover effects
- Added `box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4) !important` to mobile hover states
- Creates unified "edge glow" effect across all button hovers

**Technical changes:**
- Split mobile button reset into two groups (flexbox buttons vs back-to-top)
- Enhanced mobile hover effect with box-shadow for visual consistency
- Maintains desktop behavior (back-to-top at bottom-right: 2rem)

Files modified: static/css/main.css
2025-11-18 21:42:01 +00:00
juanatsap 6e2b042c8d feat(pdf-modal): implement interactive thumbnail selection
Transform PDF modal from placeholder to functional UI with three
interactive thumbnail cards using skeleton/placeholder styling.

Features:
- Three thumbnail options: Short CV (1 page), Long CV (2 pages), Custom (coming soon)
- Skeleton shimmer animations (1.8s, 60fps, GPU-accelerated)
- Click-to-select with visual feedback (green border, shadow, checkmark)
- Radio button behavior (only one selection at a time)
- Download button with enable/disable state management
- Keyboard navigation support (Tab, Enter, Space, ESC)
- Full ARIA attributes for screen reader accessibility
- Responsive layout (3 cols desktop, 2 cols tablet, 1 col mobile)
- Multilingual support (EN/ES) using Go template conditionals
- Download stub (shows alert, ready for backend integration)

Implementation:
- templates/partials/modals/pdf-modal.html: Complete rewrite (244 lines)
- static/css/main.css: Add PDF modal section (+290 lines)
- tests/mjs/14-pdf-modal.test.mjs: Comprehensive E2E test suite (570 lines)
- prompts/005-pdf-download-thumbnails-IMPLEMENTATION.md: Documentation

Tests:  12/12 PASSED
- Modal structure validation
- Three thumbnail cards display
- Selection interaction (click, keyboard)
- Download button state management
- ESC key closes modal
- Accessibility compliance (ARIA, roles, tabindex)
- Responsive layout (375px, 768px, 1920px)
- Multilingual support validation
- No console errors

Screenshots:
- tests/screenshots/pdf-modal-initial.png
- tests/screenshots/pdf-modal-short-selected.png
- tests/screenshots/pdf-modal-long-selected.png

Technical Details:
- Uses Hyperscript for state management (consistent with project)
- Native <dialog> element for accessibility
- Reuses skeleton.css patterns for shimmer animation
- Follows existing modal patterns (shortcuts-modal.html)
- Performance: <5KB gzipped overhead
- Browser support: 95%+ (all modern browsers)

Next Steps:
- Backend PDF generation (/download-pdf endpoint)
- Custom wizard implementation (Phase 3)
- PDF preview feature (Phase 4)

Refs: prompts/005-pdf-download-thumbnails.md
2025-11-18 20:25:49 +00:00
juanatsap 2ca13a218e feat: Extend skeleton loaders to all 13 CV sections with structural fidelity
Implemented comprehensive skeleton loaders for the entire CV curriculum,
providing smooth loading animations during language transitions across
all sections.

**Sections Implemented (13 total):**
- Header (title-badges + personal info)
- Education
- Skills Summary
- Experience (with company logos, descriptions, responsibilities)
- Awards (with logos, issuers, descriptions)
- Projects (with icons, descriptions, tech stacks)
- Courses (with icons, institutions, dates)
- Languages
- References
- Other Information
- Skills Sidebars (left and right)
- Footer

**Key Features:**
- Structural fidelity: Skeletons mirror exact HTML structure of actual content
- Each section has realistic placeholders (e.g., 3 experience items, 2 projects)
- Smooth CSS transitions with shimmer animations
- Zero layout shift
- Component-level architecture allows independent loading states

**Technical Implementation:**
- Modified all section templates in templates/partials/sections/
- Added .component-wrapper with .actual-content + .skeleton-content structure
- Extended skeleton.css with structural skeleton classes
- JavaScript event handlers in main.js already handle all sections via CSS cascade

**Testing:**
- Manual Playwright test: 13/13 component wrappers verified
- Automated test: 7/7 tests passing
- All skeleton loaders show during language switches
- No stuck loading states

**Documentation:**
- Updated tests/TEST-SUMMARY.md with all 13 sections
- Updated doc/2-MODERN-WEB-TECHNIQUES.md with comprehensive details
- Added structural fidelity table showing skeleton elements for each section

Files modified: 14 templates + CSS + 2 docs
2025-11-18 20:18: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 481003fcf8 refactor: update skeleton header to pixel-perfect match actual layout
Updates skeleton header to exactly match the actual CV header layout with
photo absolutely positioned on the right side.

**Layout Changes:**
- Photo: 150x200px positioned absolutely (top: 15px, right: 15px)
- Name: 40px height (h1 size)
- Subtitle: 24px height (larger)
- Intro text: 90px height (3-4 lines)
- Header has padding-right: 185px to accommodate photo
- Removed flex layout, using absolute positioning like actual

**Visual Improvements:**
- Photo border: 3px solid #e8e8e8 (matches actual white border)
- No border-radius on photo (matches actual)
- Larger text blocks for better visual match
- Proper spacing between elements

**Tests:**
- test-skeleton-verify.mjs:  All 4 language switches pass
- Skeleton displays correctly on every transition
2025-11-18 13:03:15 +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 534e0f16e5 feat: implement component-level skeleton loaders for language transitions
Implemented dual-state skeleton system as specified in prompt:
- Each component has actual-content + skeleton-content structure
- CSS toggles visibility via .loading class on component-wrapper
- Individual skeleton boxes (name, photo, intro, etc.) with shimmer animation
- Hyperscript triggers loading state during language switch

Changes:
- skeleton.css: Complete component-level skeleton CSS system with shimmer
- language-selector.html: Hyperscript to add/remove .loading class
- header.html: Dual-state structure with skeleton placeholders

Behavior:
- Click language button → .loading class added to components
- Actual content fades out (opacity → 0) in 250ms
- Skeleton boxes appear and shimmer
- After HTMX swap + 100ms delay → .loading class removed
- New content fades in (opacity → 1) in 250ms

Test Results:
 Component wrapper structure verified
 Dual-state toggle working correctly
 Skeleton elements present and animated
 Shimmer animation active (1.8s infinite loop)
 Accessibility: respects prefers-reduced-motion
 Print: skeletons hidden, content always visible

Next: Add skeleton structure to remaining components (experience, education, skills, projects)
2025-11-18 11:32:12 +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 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 7fc4f76706 monday last fixes before printing 2025-11-17 08:34:50 +00:00
juanatsap d4ef91b742 fix: use CSS Grid for true staggered button animations
Switched from Flexbox to CSS Grid to enable true staggered animations.

Why Grid works better:
- Grid children maintain their grid cell during layout changes
- Buttons can transition individually within their cells
- grid-auto-flow change doesn't force simultaneous repositioning

Changes:
- Container: display: grid with grid-auto-flow
- Desktop: grid-auto-flow: row (vertical stack)
- Mobile: grid-auto-flow: column (horizontal row)
- Buttons: transition: all 0.5s with staggered delays (0s, 0.08s, 0.16s, 0.24s, 0.32s)

Result: Each button now cascades independently when resizing between
desktop and mobile layouts, creating the smooth wave effect.
2025-11-16 14:45:13 +00:00
juanatsap 5a99c0026e fix: enable staggered button animations with specific property transitions
The issue was that 'transition: all' on the container was forcing all
buttons to move together. Fixed by:

1. Container now transitions only: left, bottom, gap, transform
   (NOT flex-direction or all properties)

2. Buttons transition only: transform, opacity, background-color, box-shadow, color
   (NOT all properties)

3. Increased stagger delays for better visual effect:
   - Button 1: 0s (instant)
   - Button 2: 0.08s
   - Button 3: 0.16s
   - Button 4: 0.24s
   - Button 5: 0.32s

4. Added flex-direction: 0s transition in mobile to instant switch direction
   while buttons still cascade to new positions

Result: Each button now animates independently with cascading wave effect
when switching between desktop (vertical) and mobile (horizontal) layouts.
2025-11-16 14:42:40 +00:00
juanatsap 268cd00fc7 feat: add staggered cascade animation to buttons
Implemented beautiful cascading animation effect where each button
animates individually with a staggered delay.

Changes:
- Each button now has transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1)
- Added nth-child selectors with progressive delays:
  * Button 1: 0.05s delay
  * Button 2: 0.10s delay
  * Button 3: 0.15s delay
  * Button 4: 0.20s delay
  * Button 5: 0.25s delay

Effect:
When viewport changes (desktop ↔ mobile), buttons don't move as a group.
Instead, they cascade one by one creating a wave-like animation:
- Desktop→Mobile: Buttons flow from vertical to horizontal sequentially
- Mobile→Desktop: Buttons stack from horizontal to vertical one by one

This creates a much cooler, more polished animation than moving all
buttons simultaneously. The 50ms stagger creates perfect visual rhythm.
2025-11-16 14:39:03 +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 a7cc899832 fix: redesign mobile button layout for consistency and flexibility
Changes:
- Replaced fixed positioning with flexible layout for mobile buttons
- Now shows 4 buttons on mobile: Download, Print, Shortcuts, Info
- Hide only Zoom button on mobile (accessible via hamburger menu)
- All buttons now 50×50px (consistent size, info button was smaller)
- Even 10px spacing between buttons
- Perfectly centered as a group in viewport
- Future-proof: easy to add/remove buttons without breaking layout

Layout details:
- Total width: 4 buttons × 50px + 3 gaps × 10px = 230px
- Centered using calc(50% - offset) for each button
- Maintains smooth hover effects with translateY only
- All buttons at same vertical position (bottom: 1.5rem)

Benefits:
- Consistent button sizes across mobile/desktop
- Maintainable: adding/removing buttons only requires adjusting calculations
- Better UX: users can access all main actions from bottom bar
- Shortcuts and info buttons now easily accessible on mobile
2025-11-16 14:14:06 +00:00
juanatsap 585f620bd6 refactor: organize hyperscript code and implement mobile button layout
This commit includes two major improvements:

1. Hyperscript Code Organization:
   - Extracted all hyperscript blocks >3 lines into reusable functions
   - Created 6 new functions in functions._hs:
     * toggleCVLength(isLong) - CV length toggle sync
     * toggleIcons(showIcons) - Icons toggle sync
     * toggleTheme(isClean) - Theme toggle sync
     * syncPdfHover(show) - PDF button synchronized hover
     * syncPrintHover(show) - Print button synchronized hover
     * highlightZoomControl(show) - Zoom control highlight effect
   - Reduced inline hyperscript from 11+ lines to 1-2 lines per element
   - Updated 8 template files to use function calls:
     * hamburger-menu.html
     * view-controls.html
     * action-buttons.html
     * download-button.html
     * print-friendly-button.html
     * zoom-toggle-button.html

2. Mobile Button Layout (max-width: 900px):
   - Repositioned three fixed buttons (PDF, Print, Info) horizontally at bottom center
   - Print button perfectly centered in viewport
   - Download button on left, Info button on right
   - Hidden zoom and shortcuts buttons on mobile (available in hamburger menu)
   - Removed conflicting old mobile styles that were hiding print button
   - Smooth hover transitions maintained with proper transform calculations

Technical details:
- Used CSS transform with calc() for precise horizontal positioning
- Maintained hover effects with combined translateX/translateY transforms
- Ensured accessibility with proper ARIA labels and spacing
- All functions check element existence before manipulation
- LocalStorage sync maintained across desktop/mobile toggles
2025-11-16 14:03:22 +00:00
juanatsap 671f06cd21 feat: add smooth color transitions to action bar buttons
- Added 0.3s ease transitions for background-color and color
- Icons now smoothly transition color as well
- Matches the smooth animations on fixed buttons
- Applies to PDF and Print Friendly buttons in top action bar
2025-11-16 13:48:54 +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