Files
cv-site/prompts/done/005-pdf-download-thumbnails.md
T
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

24 KiB

Implement PDF Download Modal with Interactive Thumbnails

Transform the existing PDF export modal from a placeholder "work in progress" message into a functional PDF download interface with three interactive thumbnail previews: Short CV, Long CV, and Custom (placeholder). Each thumbnail will show a stylized representation of the CV option using skeleton/placeholder styling, allowing users to visually preview and select their preferred download format.

Key Goals:

  1. Repurpose the existing pdf-modal.html dialog to show three CV format options
  2. Create thumbnail cards that represent each option visually
  3. Use skeleton/placeholder styling (similar to animated placeholders) for visual representation
  4. Make thumbnails interactive - click to select, visual highlight on selection
  5. Prepare foundation for PDF download functionality (actual download in future phase)

Why This Matters:

  • Visual choice is easier than text: Users can see what they'll get before downloading
  • Professional UX: Modern download interfaces show previews (e.g., Canva, Figma exports)
  • Sets up extensibility: Foundation for future customization wizard
  • Reduces user errors: Clear visual indication prevents downloading wrong format
**Current State:** - Existing PDF modal at `templates/partials/modals/pdf-modal.html` shows "work in progress" message - Modal uses native `` element with hyperscript for interactions - Modal structure follows pattern from `shortcuts-modal.html` (header, body, close button) - No PDF download functionality currently exists

Desired Implementation:

Three CV Format Options:

  1. Short CV - One-page condensed version

    • Thumbnail shows simplified, compact layout representation
    • Essential info only (like current .cv-short class)
  2. Long CV - Full two-page detailed version

    • Thumbnail shows more detailed layout representation
    • All sections included (like current .cv-long class)
  3. Custom - User-configurable version (placeholder for future)

    • Thumbnail shows question mark or customization icon
    • Indicates "customize your CV" option
    • For now, just placeholder - implementation deferred to next phase

Thumbnail Design (Hybrid Approach):

  • Not full miniature renders (too heavy), not pure skeleton boxes (too abstract)
  • Stylized representations that are recognizable as CV layouts
  • Use skeleton/placeholder aesthetic: rounded boxes with subtle gradients
  • Short version: Single compact card showing header + 2-3 content sections
  • Long version: Taller card or two cards showing header + 4-6 content sections
  • Custom version: Card with large question mark or settings icon

Interaction Pattern:

  • Click thumbnail card to select it (not hover-only)
  • Selected card gets visual highlight (border, shadow, checkmark badge)
  • Only one selection at a time (radio button behavior)
  • "Download PDF" button at bottom (initially disabled until selection made)
  • Button triggers download of selected format (stub for now, implement later)

Reference Files: @templates/partials/modals/pdf-modal.html - Current modal to transform @templates/partials/modals/shortcuts-modal.html - Modal pattern reference @prompts/002-animate-language-transitions.md - Skeleton loader CSS reference

Tech Stack:

  • Native HTML <dialog> element (already in use)
  • Hyperscript for interactions (click handlers, state management)
  • CSS for thumbnail styling (skeleton gradient animations)
  • Iconify icons for visual indicators

1. Modal Structure Redesign

Update PDF Modal Layout:

<dialog id="pdf-modal" class="info-modal pdf-download-modal">
  <div class="info-modal-content">
    <!-- Close button (keep existing pattern) -->
    <button class="info-modal-close">...</button>

    <!-- Header -->
    <div class="info-modal-header">
      <h2>Download PDF</h2>
      <p class="subtitle">Choose your preferred CV format</p>
    </div>

    <!-- Body: Three thumbnail cards -->
    <div class="pdf-options-grid">
      <!-- Short CV Card -->
      <div class="pdf-option-card" data-cv-format="short">
        <div class="pdf-thumbnail thumbnail-short">
          <!-- Stylized short CV representation -->
        </div>
        <div class="pdf-option-info">
          <h3>Short CV</h3>
          <p>One page, essential info</p>
        </div>
        <div class="pdf-option-badge">
          <iconify-icon icon="mdi:check-circle"></iconify-icon>
        </div>
      </div>

      <!-- Long CV Card -->
      <div class="pdf-option-card" data-cv-format="long">
        <div class="pdf-thumbnail thumbnail-long">
          <!-- Stylized long CV representation -->
        </div>
        <div class="pdf-option-info">
          <h3>Long CV</h3>
          <p>Full version, all details</p>
        </div>
        <div class="pdf-option-badge">
          <iconify-icon icon="mdi:check-circle"></iconify-icon>
        </div>
      </div>

      <!-- Custom CV Card (placeholder) -->
      <div class="pdf-option-card" data-cv-format="custom">
        <div class="pdf-thumbnail thumbnail-custom">
          <!-- Question mark or customize icon -->
        </div>
        <div class="pdf-option-info">
          <h3>Custom</h3>
          <p>Customize sections</p>
        </div>
        <div class="pdf-option-badge">
          <iconify-icon icon="mdi:check-circle"></iconify-icon>
        </div>
      </div>
    </div>

    <!-- Footer: Download button -->
    <div class="pdf-modal-footer">
      <button class="pdf-download-btn" disabled>
        <iconify-icon icon="mdi:download"></iconify-icon>
        Download PDF
      </button>
    </div>
  </div>
</dialog>

Grid Layout:

  • Three columns on desktop (≥768px)
  • Single column on mobile (<768px) with cards stacked
  • Equal height cards for visual consistency
  • Adequate spacing between cards (16-24px gap)

2. Thumbnail Visual Design

Skeleton/Placeholder Aesthetic:

Use the skeleton loader pattern from prompt 002 to create stylized CV representations:

/* Base thumbnail container */
.pdf-thumbnail {
  background: #ffffff;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 16px;
  height: 280px; /* Adjust based on content */
  display: flex;
  flex-direction: column;
  gap: 12px;
  position: relative;
  overflow: hidden;
}

/* Skeleton elements inside thumbnails */
.skeleton-block {
  background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 2s ease-in-out infinite;
  border-radius: 4px;
}

@keyframes skeleton-shimmer {
  0%, 100% { background-position: 200% 0; }
  50% { background-position: 0 0; }
}

Short CV Thumbnail Structure:

<div class="pdf-thumbnail thumbnail-short">
  <!-- Header representation -->
  <div class="skeleton-block" style="height: 48px;"></div>

  <!-- Content sections (compact) -->
  <div class="skeleton-block" style="height: 60px;"></div>
  <div class="skeleton-block" style="height: 60px;"></div>
  <div class="skeleton-block" style="height: 60px;"></div>

  <!-- Badge overlay -->
  <div class="thumbnail-badge">1 Page</div>
</div>

Long CV Thumbnail Structure:

<div class="pdf-thumbnail thumbnail-long">
  <!-- Header representation -->
  <div class="skeleton-block" style="height: 48px;"></div>

  <!-- More content sections (detailed) -->
  <div class="skeleton-block" style="height: 40px;"></div>
  <div class="skeleton-block" style="height: 40px;"></div>
  <div class="skeleton-block" style="height: 40px;"></div>
  <div class="skeleton-block" style="height: 40px;"></div>
  <div class="skeleton-block" style="height: 40px;"></div>

  <!-- Badge overlay -->
  <div class="thumbnail-badge">2 Pages</div>
</div>

Custom CV Thumbnail Structure:

<div class="pdf-thumbnail thumbnail-custom">
  <!-- Centered icon instead of skeleton blocks -->
  <div class="custom-placeholder">
    <iconify-icon icon="mdi:help-circle-outline" width="80" height="80"></iconify-icon>
    <p>Customize</p>
  </div>

  <!-- Badge overlay -->
  <div class="thumbnail-badge">Coming Soon</div>
</div>

Visual Distinctions:

  • Short thumbnail: Fewer, larger blocks (compact feel)
  • Long thumbnail: More, smaller blocks (detailed feel)
  • Custom thumbnail: No skeleton blocks, just icon + text
  • All thumbnails: Page count or status badge in corner

3. Interactive Selection Behavior

Click to Select Pattern:

Use hyperscript to manage selection state:

-- On each PDF option card
on click
  -- Remove selected class from all cards
  set cards to .pdf-option-card in #pdf-modal
  for card in cards
    remove .selected from card
  end

  -- Add selected class to clicked card
  add .selected to me

  -- Enable download button
  set downloadBtn to .pdf-download-btn in #pdf-modal
  remove @disabled from downloadBtn

  -- Store selected format for later
  set :selectedFormat to my @data-cv-format
end

CSS Selection States:

/* Default card state */
.pdf-option-card {
  border: 2px solid transparent;
  border-radius: 12px;
  padding: 16px;
  cursor: pointer;
  transition: all 250ms ease;
  position: relative;
  background: #ffffff;
}

/* Hover state */
.pdf-option-card:hover {
  border-color: #e0e0e0;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  transform: translateY(-2px);
}

/* Selected state */
.pdf-option-card.selected {
  border-color: #4caf50; /* or brand color */
  box-shadow: 0 6px 16px rgba(76, 175, 80, 0.2);
  background: #f9fff9; /* subtle tint */
}

/* Selected badge (checkmark) */
.pdf-option-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  opacity: 0;
  transform: scale(0.8);
  transition: all 250ms ease;
  color: #4caf50;
}

.pdf-option-card.selected .pdf-option-badge {
  opacity: 1;
  transform: scale(1);
}

Download Button State:

/* Disabled state (default) */
.pdf-download-btn:disabled {
  background: #e0e0e0;
  color: #999999;
  cursor: not-allowed;
  opacity: 0.6;
}

/* Enabled state (after selection) */
.pdf-download-btn:not(:disabled) {
  background: #4caf50;
  color: white;
  cursor: pointer;
}

.pdf-download-btn:not(:disabled):hover {
  background: #45a049;
  box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3);
}

4. Multilingual Support

Update Template with Language Conditionals:

<h2>{{if eq .Lang "es"}}Descargar PDF{{else}}Download PDF{{end}}</h2>
<p class="subtitle">
  {{if eq .Lang "es"}}Elige tu formato preferido{{else}}Choose your preferred format{{end}}
</p>

<!-- Short CV Card -->
<h3>{{if eq .Lang "es"}}CV Corto{{else}}Short CV{{end}}</h3>
<p>{{if eq .Lang "es"}}Una página, información esencial{{else}}One page, essential info{{end}}</p>

<!-- Long CV Card -->
<h3>{{if eq .Lang "es"}}CV Completo{{else}}Long CV{{end}}</h3>
<p>{{if eq .Lang "es"}}Versión completa, todos los detalles{{else}}Full version, all details{{end}}</p>

<!-- Custom CV Card -->
<h3>{{if eq .Lang "es"}}Personalizado{{else}}Custom{{end}}</h3>
<p>{{if eq .Lang "es"}}Personaliza secciones{{else}}Customize sections{{end}}</p>

<!-- Download Button -->
<button class="pdf-download-btn" disabled>
  <iconify-icon icon="mdi:download"></iconify-icon>
  {{if eq .Lang "es"}}Descargar PDF{{else}}Download PDF{{end}}
</button>

5. Responsive Design

Mobile Optimizations:

/* Desktop: Three columns */
@media (min-width: 768px) {
  .pdf-options-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
  }
}

/* Tablet: Two columns */
@media (min-width: 480px) and (max-width: 767px) {
  .pdf-options-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
  }

  /* Custom card spans full width */
  .pdf-option-card[data-cv-format="custom"] {
    grid-column: 1 / -1;
  }
}

/* Mobile: Single column */
@media (max-width: 479px) {
  .pdf-options-grid {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  .pdf-thumbnail {
    height: 200px; /* Shorter on mobile */
  }
}

6. Accessibility

ARIA Attributes:

<div class="pdf-option-card"
     data-cv-format="short"
     role="radio"
     aria-checked="false"
     aria-label="Short CV - One page, essential information"
     tabindex="0">
  ...
</div>

Keyboard Navigation:

-- On PDF option cards
on keydown
  if event.key is 'Enter' or event.key is ' '
    halt the event
    trigger click on me
  end
end

Screen Reader Announcements:

<div class="sr-only" aria-live="polite" id="selection-announcement"></div>

<!-- Update on selection -->
<script>
  document.getElementById('selection-announcement').textContent =
    'Selected: Short CV - One page format';
</script>

7. PDF Download Stub (Future Implementation)

For Now:

  • Download button triggers a function that logs selected format
  • Shows a toast/alert: "PDF download coming soon!"
  • Stores selection in variable for when backend is ready

Hyperscript Stub:

-- On download button
on click
  if :selectedFormat is not null
    log 'Download requested for format:', :selectedFormat
    -- TODO: Trigger actual PDF download when backend ready
    call alert('PDF download coming soon! Selected format: ' + :selectedFormat)
  end
end

Preparation for Real Implementation:

  • Format selection stored in :selectedFormat variable
  • Can easily be sent to backend: hx-get="/download-pdf?format={format}"
  • Modal can stay open or close after download
  • Consider adding loading spinner during download

Step-by-Step Implementation Plan

Phase 1: Update PDF Modal Structure

  1. Modify templates/partials/modals/pdf-modal.html:

    • Remove "work in progress" placeholder content
    • Add new modal structure with header, options grid, footer
    • Include multilingual text with {{if eq .Lang}} conditionals
    • Add close button (keep existing pattern)
  2. Create Thumbnail HTML Structures:

    • Short CV thumbnail with 3-4 skeleton blocks
    • Long CV thumbnail with 5-6 skeleton blocks
    • Custom CV thumbnail with centered icon
    • Add page count badges to each thumbnail

Phase 2: Create CSS Styles

  1. Add Modal Layout Styles to static/css/main.css:

    • .pdf-options-grid - responsive grid layout
    • .pdf-option-card - card container styles
    • Card states: default, hover, selected
    • .pdf-option-badge - checkmark badge positioning
  2. Add Thumbnail Styles:

    • .pdf-thumbnail - base thumbnail container
    • .skeleton-block - reuse skeleton loader pattern from prompt 002
    • @keyframes skeleton-shimmer - shimmer animation
    • .thumbnail-badge - page count badge overlay
    • Responsive thumbnail heights
  3. Add Footer/Button Styles:

    • .pdf-modal-footer - footer layout
    • .pdf-download-btn - button base styles
    • Button states: disabled, enabled, hover
    • Icon + text layout

Phase 3: Implement Selection Logic

  1. Add Hyperscript to Cards:

    • Click handler to select card
    • Remove selection from other cards
    • Add .selected class to clicked card
    • Store selected format in variable
    • Enable download button
  2. Add Keyboard Support:

    • Tab navigation between cards
    • Enter/Space to select card
    • ESC to close modal (already handled by dialog)
  3. Add Selection State Management:

    • ARIA attributes for screen readers
    • Visual feedback (border, shadow, badge)
    • Announcement for screen readers

Phase 4: Implement Download Button (Stub)

  1. Add Click Handler to Download Button:

    • Check if format is selected
    • Log selected format (for debugging)
    • Show alert/toast: "Coming soon!"
    • Prepare structure for real implementation
  2. Prepare for Backend Integration:

    • Document expected API endpoint: /download-pdf?format={format}
    • Document expected response: PDF file download
    • Add TODO comments for future implementation

Phase 5: Testing and Refinement

  1. Visual Testing:

    • Three thumbnails display correctly
    • Skeleton shimmer animations are smooth
    • Cards respond to hover and selection
    • Badge appears on selection
    • Download button enables/disables correctly
  2. Interaction Testing:

    • Click to select works on all three cards
    • Only one card selected at a time
    • Download button requires selection
    • Keyboard navigation works (tab, enter, space)
  3. Responsive Testing:

    • Desktop: Three columns side-by-side
    • Tablet: Two columns with custom spanning
    • Mobile: Single column stacked
    • Thumbnails adapt height appropriately
  4. Multilingual Testing:

    • Switch to Spanish: All text translates
    • Switch to English: All text translates
    • No hardcoded text in templates

What to Prioritize:

  1. Core modal structure and thumbnail layout
  2. Selection interaction (click to highlight)
  3. Visual polish (skeleton shimmer, badges)
  4. Responsive design
  5. Accessibility features

What to Avoid:

  • Don't implement actual PDF generation yet (out of scope)
  • Don't make thumbnails too complex (keep stylized and simple)
  • Don't use images for thumbnails (pure CSS/HTML)
  • Don't forget mobile UX (touch targets, stacked layout)
  • Don't hardcode text (use multilingual template conditionals)

Why These Constraints Matter:

  • Stylized over realistic: Faster to render, easier to maintain, loads instantly
  • Skeleton aesthetic: Consistent with existing placeholder patterns, modern UX
  • Interactive selection: Better UX than radio buttons, visual feedback is immediate
  • Stub download: Allows testing full flow without backend dependency
  • Accessibility: Ensures all users can navigate and select options
Modify/create the following files:
  1. ./templates/partials/modals/pdf-modal.html

    • Transform from placeholder to functional modal
    • Add three thumbnail cards (short, long, custom)
    • Add selection interaction with hyperscript
    • Add download button (stub functionality)
    • Include multilingual support
  2. ./static/css/main.css (add PDF modal styles section)

    • Modal layout and grid styles
    • Card styles (default, hover, selected states)
    • Thumbnail container and skeleton block styles
    • Skeleton shimmer animation keyframes
    • Badge and button styles
    • Responsive breakpoints

Optional: 3. ./static/css/pdf-modal.css (NEW - if you prefer separate file)

  • Dedicated stylesheet for PDF modal component
  • Import in main CSS or link in template
  1. Add UI text to data/ui-en.json and data/ui-es.json (if using centralized UI strings)
    • PDF modal title and subtitle
    • Option names and descriptions
    • Button text
Before declaring complete, perform these comprehensive tests:

1. Visual Verification:

  • Modal opens with three thumbnail cards displayed
  • Short CV thumbnail shows 3-4 skeleton blocks (compact)
  • Long CV thumbnail shows 5-6 skeleton blocks (detailed)
  • Custom CV thumbnail shows question mark/icon
  • Skeleton blocks have subtle shimmer animation
  • Page count badges visible on thumbnails ("1 Page", "2 Pages", "Coming Soon")
  • Download button initially disabled (grayed out)

2. Selection Interaction:

  • Click Short CV card: Border highlights, checkmark badge appears
  • Click Long CV card: Previous selection clears, new card highlights
  • Click Custom CV card: Selection transfers correctly
  • Only one card selected at any time (radio button behavior)
  • Download button enables after selection
  • Download button disables if no selection (edge case testing)

3. Download Button (Stub):

  • Button disabled when modal first opens
  • Button enables after selecting any option
  • Click button: Shows "Coming soon" alert (or console log)
  • Selected format is stored and retrievable
  • Button styling changes between disabled/enabled states

4. Responsive Design:

  • Desktop (≥768px): Three columns, equal width
  • Tablet (480-767px): Two columns, custom card spans full width
  • Mobile (<480px): Single column, cards stacked vertically
  • Thumbnails resize appropriately on different screens
  • Modal remains centered and scrollable on small screens

5. Multilingual Support:

  • English: All text in English
  • Spanish: All text in Spanish
  • Toggle language: Modal text updates correctly
  • No untranslated or hardcoded English text

6. Accessibility:

  • Tab navigation: Can tab through all three cards
  • Enter key: Selects focused card
  • Space key: Selects focused card
  • Screen reader: Announces card selection
  • ARIA attributes: role="radio", aria-checked updates
  • Focus indicators visible on cards
  • Download button keyboard accessible

7. Animation Performance:

  • Skeleton shimmer is smooth (60fps, no jank)
  • Selection transition is smooth (border, shadow appear smoothly)
  • Hover effects are responsive (no delay or lag)
  • Animations respect prefers-reduced-motion

8. Modal Behavior:

  • Modal opens when triggered (test trigger button)
  • Close button (X) closes modal
  • Click outside modal closes it (backdrop click)
  • ESC key closes modal
  • Selection state persists while modal is open
  • Selection resets when modal reopens (or persists - decide which)

9. Edge Cases:

  • Rapidly click different cards - no broken states
  • Close modal and reopen - state resets correctly
  • Switch language while modal open - text updates
  • Very long text doesn't break layout (test with Spanish)

Success Indicators: PDF modal transformed from placeholder to functional interface Three thumbnail cards with stylized CV representations Skeleton shimmer animations working smoothly Click-to-select interaction with visual feedback Download button enables/disables based on selection Responsive layout adapts to mobile/tablet/desktop Multilingual support for English and Spanish Keyboard navigation and screen reader support Professional, polished visual design Foundation prepared for future PDF download implementation

<success_criteria>

  1. PDF modal displays three interactive thumbnail options
  2. Thumbnails use skeleton/placeholder styling with shimmer animation
  3. Short CV thumbnail shows compact layout (fewer blocks)
  4. Long CV thumbnail shows detailed layout (more blocks)
  5. Custom CV thumbnail shows placeholder icon/message
  6. Click-to-select interaction highlights chosen option
  7. Visual selection feedback: border, shadow, checkmark badge
  8. Download button enabled only when option selected
  9. Responsive grid layout: 3 columns desktop, 2 tablet, 1 mobile
  10. Multilingual support in English and Spanish
  11. Keyboard accessible with proper ARIA attributes
  12. Smooth animations (60fps shimmer, 250ms transitions)
  13. Modal follows existing project patterns (dialog element, hyperscript)
  14. Code is maintainable and well-documented
  15. Foundation ready for backend PDF generation integration </success_criteria>
**Files to Examine:** @templates/partials/modals/pdf-modal.html - Current modal structure @templates/partials/modals/shortcuts-modal.html - Modal pattern reference @prompts/002-animate-language-transitions.md - Skeleton loader CSS pattern @static/css/main.css - Existing modal and skeleton styles

Questions to Answer:

  1. What skeleton/placeholder styles already exist?
  2. How are other modals styled (pattern consistency)?
  3. What multilingual pattern is used for UI text?
  4. What iconify icons are available for badges/buttons?
  5. What hyperscript patterns are used elsewhere?

<additional_notes> Design Philosophy:

  • Stylized over realistic: Faster, lighter, easier to maintain
  • Progressive disclosure: Show options first, download later
  • Visual feedback first: Don't make users guess what they selected
  • Mobile-friendly: Touch targets, stacked layout, clear labels

Future Extension Points:

  • Custom option will eventually open customization wizard
  • Download button will trigger server-side PDF generation
  • Could add "Preview" button to show full-size before download
  • Could add "Email PDF" option alongside download
  • Could remember last selection in localStorage

Technical Decisions:

  • Use skeleton blocks instead of miniature renders (performance)
  • Use CSS animations instead of JavaScript (smooth, performant)
  • Use native dialog element (accessibility, browser features)
  • Use hyperscript for state management (consistent with project)

Visual Design Notes:

  • Skeleton shimmer should be subtle (not distracting)
  • Selected state should be obvious (green border + checkmark)
  • Thumbnails should be recognizable as CV layouts
  • Cards should feel clickable (cursor, hover effects)
  • Download button should be prominent when enabled </additional_notes>