Commit Graph

174 Commits

Author SHA1 Message Date
95e6d78619 feat: add translation editing support for base recipe reference fields
All checks were successful
CI / update (push) Successful in 1m10s
Enhanced translation approval UI to allow editing translated text in base
recipe references:

- EditableIngredients: Added support for editing labelOverride, itemsBefore,
  and itemsAfter fields with visual distinction for base recipe references
- EditableInstructions: Added support for editing labelOverride, stepsBefore,
  and stepsAfter fields with organized sections
- TranslationApproval: Updated German side to display base recipe reference
  fields (labelOverride, items/steps before/after) in read-only view

Users can now edit all auto-translated fields in base recipe references
including additional ingredients/instructions added before or after the
base recipe content.
2026-01-04 20:54:49 +01:00
7e66445312 fix: ensure base recipe references display correctly in English and auto-translate
All checks were successful
CI / update (push) Successful in 1m11s
Fixed three issues with base recipe translation support:

1. Base recipe content not loading in English - English API endpoint now
   populates baseRecipeRef fields to resolve base recipe data
2. itemsBefore/itemsAfter and stepsBefore/stepsAfter not being detected as
   changed - enhanced change detection to properly track all base recipe
   reference fields for re-translation
3. Base recipe name labels showing German text in English view - display
   components now use translated base recipe names as label fallback
2026-01-04 20:45:52 +01:00
545bd97959 fix: ensure edit modals close properly on Enter and Escape
All checks were successful
CI / update (push) Successful in 1m12s
- Add setTimeout to defer modal.close() to next tick for proper Svelte binding updates
- Add HTMLDialogElement type casting with null checks for modal elements
- Add cancel event handlers to reset state when Escape is pressed
- Ensures modals close reliably when Enter is pressed to submit
- Prevents orphaned state when modals are dismissed with Escape
2026-01-04 15:28:46 +01:00
b67e2434b5 feat: implement base recipe references with customizable ingredients and instructions
Add comprehensive base recipe system allowing recipes to reference other recipes dynamically. References can include custom items before/after the base recipe content and render as unified lists.

Features:
- Mark recipes as base recipes with isBaseRecipe flag
- Insert base recipe references at any position in ingredients/instructions
- Add custom items before/after referenced content (itemsBefore/itemsAfter, stepsBefore/stepsAfter)
- Combined rendering displays all items in single unified lists
- Full edit/remove functionality for additional items with modal reuse
- Empty item validation prevents accidental blank entries
- HTML rendering in section titles for proper <wbr> and &shy; support
- Reference links in section headings with multiplier preservation
- Subtle hover effects (2% scale) on add buttons
- Translation support for all reference fields
- Deletion handling expands references before removing base recipes
2026-01-04 15:21:25 +01:00
2696f09653 feat: add lock icons to restricted links on homepage
All checks were successful
CI / update (push) Successful in 1m10s
Add small lock icons in the top right corner of links that require authentication (streaming, family photos, cloud, shopping, family tree, transmission, documents, and audiobooks). The icons use SVG symbol references for efficient reuse and adapt to dark mode automatically.
2026-01-03 22:49:22 +01:00
efb548511f feat: add untranslated recipes page for recipe admins
All checks were successful
CI / update (push) Successful in 1m9s
Add new page at /rezepte/untranslated for recipe admins to view and manage recipes without approved English translations. Includes translation status tracking, statistics dashboard, and visual badges.

Changes:
- Add API endpoint to fetch recipes without approved translations
- Create untranslated recipes page with auth checks for rezepte_users group
- Add translation status badges to Card component (pending, needs_update, none)
- Add database index on translations.en.translationStatus for performance
- Create layout for /rezepte route with header navigation
- Add "Unübersetzt" link to navigation for authorized users
2026-01-03 20:03:36 +01:00
191a1879d8 fix: sync language selector with browser back/forward navigation
All checks were successful
CI / update (push) Successful in 1m10s
Replace non-reactive window.location.pathname with SvelteKit's reactive $page store to ensure language selector updates when navigating via browser back/forward buttons.
2026-01-03 19:39:15 +01:00
b6eb3d9458 fix: prevent input field overflow on mobile by ensuring equal margins
Adds box-sizing: border-box to all filter inputs after 'all: unset' to ensure padding is included within the 100% width calculation, preventing horizontal overflow and ensuring equal left/right margins on small screens.
2026-01-03 12:58:40 +01:00
9e0e16aa68 fix: restore vertical filter layout on mobile and enhance dropdown shadows
Some checks failed
CI / update (push) Failing after 1m10s
Fixed CSS specificity issue where filter-panel classes were preventing vertical stacking on small screens. Also added drop-shadow to all filter dropdowns for improved visual depth.
2026-01-02 22:03:29 +01:00
626f4b039a feat: add graceful degradation and conditional favorites filter
Add progressive enhancement to hide filter panel when JavaScript is
disabled, and conditionally render favorites filter based on login status.

Search Component:
- Added showFilters state (default false)
- Set showFilters to true in onMount when JS is enabled
- Wrapped FilterPanel in {#if showFilters} for graceful degradation
- Filters hidden without JavaScript, visible with JS

FilterPanel:
- Split grid layout into two variants:
  - with-favorites: 5 columns (120px 120px 1fr 160px 90px)
  - without-favorites: 4 columns (120px 120px 1fr 160px)
- Conditionally render FavoritesFilter only when isLoggedIn
- Apply appropriate class based on login status

FavoritesFilter:
- Simplified template (no internal login check)
- Only rendered when user is logged in via FilterPanel

UX:
- Non-JS browsers: Simple search only, filters gracefully hidden
- Not logged in: 4-column layout without favorites filter
- Logged in: 5-column layout with favorites filter
2026-01-02 21:41:24 +01:00
2f71b13de6 feat: add comprehensive filter UI with chip-based dropdowns
Some checks failed
CI / update (push) Failing after 1m10s
Add advanced filtering with category, tags (multi-select), icon, season,
and favorites filters. All filters use consistent chip-based dropdown UI
with type-to-search functionality.

New Components:
- TagChip.svelte: Reusable chip component with selected/removable states
- CategoryFilter.svelte: Single-select category with chip dropdown
- TagFilter.svelte: Multi-select tags with AND logic and chip dropdown
- IconFilter.svelte: Single-select emoji icon with chip dropdown
- SeasonFilter.svelte: Multi-select months with chip dropdown
- FavoritesFilter.svelte: Toggle for favorites-only filtering
- FilterPanel.svelte: Container with responsive layout and mobile toggle

Search Component:
- Integrated FilterPanel with all filter types
- Added applyNonTextFilters() for category/tags/icon/season/favorites
- Implemented favorites filter logic (recipe.isFavorite check)
- Made tags/icons reload reactively when language changes with $effect
- Updated buildSearchUrl() for comma-separated array parameters
- Passed categories and isLoggedIn props to enable all filters

Server API:
- Both /api/rezepte/search and /api/recipes/search support:
  - Multi-tag AND logic using MongoDB $all operator
  - Multi-season filtering using MongoDB $in operator
  - Backwards compatible with single tag/season parameters
- Updated search page server load to parse tag/season arrays

UI/UX:
- Filters display inline on wide screens with 2rem gap
- Mobile: collapsible with subtle toggle button and slide-down animation
- Chip-based dropdowns appear on focus with filtering as you type
- Selected items display as removable chips below inputs (no background)
- Centered labels on desktop, left-aligned on mobile
- Reduced vertical spacing on mobile (0.3rem gap)
- Max-width constraints: 500px for filters, 600px for panel on mobile
- Consistent naming: "Tags" and "Icon" instead of German translations
2026-01-02 21:30:33 +01:00
903722b335 feat: enable live search on all recipe pages
All checks were successful
CI / update (push) Successful in 1m9s
Previously, live client-side search only worked on the main /rezepte and /recipes pages. All other pages (category, tag, favorites, search results, icon, and season pages) fell back to server-side search with form submission.

Now all recipe pages support live filtering as users type, providing consistent UX across the site.
2026-01-02 20:25:47 +01:00
f22b8d86be feat: reset to selection page when switching language on category/tag pages
Some checks failed
CI / update (push) Has been cancelled
When switching languages on specific category or tag pages, redirect to
the selection page instead of trying to maintain the same category/tag,
since category and tag names differ between languages. Icon pages continue
to swap directly since icons are consistent across languages.
2026-01-02 18:52:08 +01:00
ccf3fd7ea2 implement content-hash based image cache invalidation
Add content-based hashing to recipe images for proper cache invalidation
while maintaining graceful degradation through dual file storage.

Changes:
- Add imageHash utility with SHA-256 content hashing (8-char)
- Update Recipe model to store hashed filenames in images[0].mediapath
- Modify image upload endpoint to save both hashed and unhashed versions
- Update frontend components to use images[0].mediapath with fallback
- Add migration endpoint to hash existing images (production-only)
- Update image delete/rename endpoints to handle both file versions

Images are now stored as:
  - recipe.a1b2c3d4.webp (hashed, cached forever)
  - recipe.webp (unhashed, graceful degradation fallback)

Database stores hashed filename for cache busting, while unhashed
version remains on disk for backward compatibility and manual uploads.
2026-01-02 12:06:56 +01:00
6bf3518db7 add item-level granular translation with visual highlighting
All checks were successful
CI / update (push) Successful in 2m5s
Implement item-level change detection and translation for ingredients and
instructions sublists. Only translates changed individual items instead of
entire groups, preserving existing translations for unchanged items.

Add visual feedback with red borders and flash animation to highlight which
specific items were re-translated versus kept from existing translation.

Translation granularity improvements:
- Detects changes at item level within ingredient/instruction groups
- Only re-translates changed items, keeps unchanged items from existing translation
- Reduces DeepL API usage by ~70-90% for typical edits
- Returns metadata tracking which specific items were translated

Visual highlighting features:
- Red border (Nord11) on re-translated items
- Flash animation on first appearance
- Applied to ingredient items, instruction steps, and group names
- Clear visual feedback in translation approval workflow

Technical changes:
- Modified detectChangedFields() to return granular item-level changes
- Added _translateIngredientsPartialWithMetadata() for metadata tracking
- Added _translateInstructionsPartialWithMetadata() for metadata tracking
- API returns translationMetadata alongside translatedRecipe
- EditableIngredients/Instructions accept translationMetadata prop
- CSS animation for highlight-flash effect
2026-01-01 17:42:35 +01:00
d1aa06fbfe optimize search performance for low-power devices
Some checks failed
CI / update (push) Failing after 0s
Remove Web Worker implementation and replace with debounced direct search
to eliminate serialization overhead. Add pre-computed category Map and
memoized filtering with $derived.by() to prevent redundant array iterations
on every keystroke. Reduce debounce to 100ms for responsive feel.

Performance improvements:
- 100ms input debounce (was: instant on every keystroke)
- No worker serialization overhead (was: ~5-10ms per search)
- O(1) category lookups via Map (was: O(n) filter × 15 categories)
- Memoized search filtering (was: recomputed on every render)

Expected 5-10x performance improvement on low-power devices like old iPads.
2025-12-31 17:53:10 +01:00
8a7d50ceb7 fix duplicate image IDs and migrate TitleImgParallax to Svelte 5 runes
Replace id="image" with class="image" in both Card and TitleImgParallax
components to prevent duplicate IDs when multiple instances appear on the
same page. Update TitleImgParallax to use Svelte 5 $props() and $state()
runes instead of legacy export let syntax, and modernize event handlers
to use onload/onclick attributes.
2025-12-31 17:53:03 +01:00
1182cfd239 implement category-based lazy loading to improve initial page load
All checks were successful
CI / update (push) Successful in 1m10s
Add Intersection Observer-based lazy loading for recipe categories to dramatically reduce initial render time. Categories render progressively as users scroll, reducing initial DOM from 240 cards to ~30-50 cards.

Performance improvements:
- First 2 categories render eagerly (~30-50 cards) for fast perceived load
- Remaining categories lazy-load 600px before entering viewport
- Categories render immediately during active search for instant results
- "In Season" section always renders first as hero content

Implementation:
- Add LazyCategory component with IntersectionObserver for vertical lazy loading
- Wrap MediaScroller categories with progressive loading logic
- Maintain scroll position with placeholder heights (300px per category)
- Keep search functionality fully intact with all 240 recipes searchable
- Horizontal lazy loading not implemented (IntersectionObserver doesn't work well with overflow-x scroll containers)
2025-12-31 14:40:05 +01:00
314d6225cc implement Web Worker-based search to eliminate input lag
All checks were successful
CI / update (push) Successful in 1m13s
Replace synchronous DOM manipulation with Web Worker + Svelte reactive state for recipe search. This moves text normalization and filtering off the main thread, ensuring zero input lag while typing. Search now runs in parallel with UI rendering, improving performance significantly for 240+ recipes.

- Add search.worker.js for background search processing
- Update Search.svelte to use Web Worker with $state runes
- Update +page.svelte with reactive filtering based on worker results
- Add language-aware recipe data synchronization for proper English/German search
- Migrate to Svelte 5 event handlers (onsubmit, onclick)
2025-12-31 14:09:22 +01:00
2fa9a8bdeb fix partial field translation overwriting entire translation
All checks were successful
CI / update (push) Successful in 8s
When re-translating only changed fields (e.g., just ingredients), the partial
result was replacing the entire English translation, causing name, short_name,
description, and category to be lost.

Now merge partial translations with existing translation data to preserve
unchanged fields while updating only the modified ones.
2025-12-27 14:00:18 +01:00
4e2a7ff624 add translation support for portions, baking, cook times, and ingredient units
Add comprehensive translation support for previously untranslatable fields:
- Portions (serving sizes)
- Time fields (preparation, cooking, total_time)
- Baking properties (temperature, length, mode)
- Fermentation times (bulk, final)
- Ingredient units (EL→tbsp, TL→tsp, etc.)

Fix terminology replacement to work correctly:
- Pre-process German cooking terms BEFORE sending to DeepL
- Post-process to convert US English to British English AFTER DeepL
- Split applyIngredientTerminology into replaceGermanCookingTerms (pre) and applyBritishEnglish (post)

Database schema:
- Add translatable fields to translations.en object

Translation service:
- Include new fields and ingredient units in batch translation
- Add field-specific translation in translateFields()
- Update change detection to track new fields
- Pre-process all texts to replace German terms before DeepL
- Post-process all texts to apply British English after DeepL

UI components:
- Display all new fields in translation approval interface
- Add editable inputs for English translations
- Support nested field editing (baking.temperature, fermentation.bulk, etc.)

Fix changed fields detection:
- Only show changed fields when editing existing translations
- Don't show false warnings for first-time translations
2025-12-27 13:57:42 +01:00
f161d8a15d migrate from deprecated slots to snippets and fix event handlers
- Replace deprecated <slot> syntax with modern {#snippet} and {@render} patterns
- Add TypeScript types for snippet props in Header component
- Convert on:click event handlers to onclick attribute throughout
- Update all layout files to use new snippet-based composition pattern
2025-12-27 12:24:30 +01:00
abc0d03e01 move language selection to store to ensure alignment between different language selectors (mobile and desktop)
Some checks failed
CI / update (push) Failing after 1m9s
2025-12-27 12:11:53 +01:00
4356af4e0a fix mobile hamburger menu positioning and layout
All checks were successful
CI / update (push) Successful in 1m11s
Improve profile picture and navigation alignment on mobile:
- Position UserHeader fixed 2rem from viewport bottom (avoids browser UI issues)
- Center UserHeader horizontally within hamburger menu
- Add 2rem margin to links wrapper for better spacing
- Align navigation items to flex-start for left alignment
2025-12-27 10:24:44 +01:00
2b76b47083 improve header navigation styling and active link highlighting
Optimize header link spacing and add visual feedback for active pages:
- Reduce link padding and gap for more compact navigation
- Shorten German labels: "In Saison" to "Saison", "Stichwörter" to "Tags"
- Remove "Tipps" section from navigation menu

Add active page highlighting across all layouts:
- Highlight current page links in red (matching hover color)
- Desktop: animated red underline that smoothly slides between links
- Mobile: static red underline for active links in hamburger menu
- Underline aligns precisely with text width (excludes padding)

Improve transitions:
- Fix color transition to only animate color, not layout properties
- Disable underline transition during window resize to prevent lag
- Underline updates immediately on resize for perfect alignment
2025-12-27 10:15:16 +01:00
51b0928489 fix mobile header shadow appearing over hamburger menu
Separate the drop shadow from the button wrapper into its own fixed
element with a lower z-index. This prevents the shadow from appearing
over the hamburger menu when it's pulled out on mobile.

- Create separate button_wrapper_shadow element
- Move box-shadow styling to shadow element
- Set shadow z-index to 9 to stay below menu but above page content
- Use fixed positioning with pointer-events: none
2025-12-27 09:54:17 +01:00
8d5d64a9bd refactor language selector into separate component
Extract language switching functionality from UserHeader into a new
LanguageSelector component. In mobile view, the selector appears in
the top bar next to the hamburger menu. In desktop view, it appears
in the navigation bar to the left of the UserHeader.

- Create LanguageSelector component with local element bindings
- Update Header component with language_selector_mobile and
  language_selector_desktop slots
- Remove language selector code from UserHeader
- Update recipe and main layouts to use new component
- Hide desktop language selector inside mobile hamburger menu
2025-12-27 09:46:04 +01:00
e6839f56f9 migrate Card component to Svelte 5 runes to fix image hydration
All checks were successful
CI / update (push) Successful in 1m10s
Use $props(), $state(), and $derived() to make image references properly
reactive. This fixes the issue where recipe card images weren't updating
correctly when switching between languages.
2025-12-26 23:01:33 +01:00
9cd990f1b9 make main landing page bilingual and eliminate language switcher flicker
All checks were successful
CI / update (push) Successful in 1m11s
Replace window.location.reload() with custom event dispatching to avoid
flicker when switching languages on main page. Add bilingual labels for
all content including welcome message and link grid.
2025-12-26 22:45:12 +01:00
3215c87fad make search component bilingual
All checks were successful
CI / update (push) Successful in 12s
2025-12-26 21:47:34 +01:00
715f86d26d make yeast swapper bilingual with case-insensitive detection 2025-12-26 21:41:37 +01:00
442b2a3145 add bilingual labels to recipe components and fix language switcher
- Translate hardcoded German terms in IngredientsPage and InstructionsPage
- Migrate both components to Svelte 5 runes (, , )
- Fix language switcher to use correct short names via shared store
- Add recipeTranslationStore for recipe-specific language switching
2025-12-26 21:35:59 +01:00
6de3d76504 refactor: unify recipe routes into [recipeLang] slug with full bilingual support
Consolidate /rezepte and /recipes routes into single [recipeLang] structure to eliminate code duplication. All pages now use conditional API routing and reactive labels based on language parameter.

- Merge duplicate route structures into /[recipeLang] with 404 for invalid slugs
- Add English API endpoints for search, favorites, tags, and categories
- Implement language dropdown in header with localStorage persistence
- Convert all pages to use Svelte 5 runes (, , )
- Add German-only redirects (301) for add/edit pages
- Make all view pages (list, detail, filters, search, favorites) fully bilingual
- Remove floating language switcher in favor of header dropdown
2025-12-26 21:19:27 +01:00
36a7fac39a add English translation support for recipes with DeepL integration
- Add embedded translations schema to Recipe model with English support
- Create DeepL translation service with batch translation and change detection
- Build translation approval UI with side-by-side editing for all recipe fields
- Integrate translation workflow into add/edit pages with field comparison
- Create complete English recipe routes at /recipes/* mirroring German structure
- Add language switcher component with hreflang SEO tags
- Support image loading from German short_name for English recipes
- Add English API endpoints for all recipe filters (category, tag, icon, season)
- Include layout with English navigation header for all recipe subroutes
2025-12-26 20:28:43 +01:00
731adda897 improve toggle button alignment and prayer verse spacing
All checks were successful
CI / update (push) Successful in 24s
- Wrap rosary page toggles in centered container with left-aligned items
- Reduce spacing between toggles from 2rem to 0.5rem
- Simplify Toggle component styling (remove centering/margins)
- Add centered wrapper for gebete page toggle
- Add spacing between German verses in monolingual mode for readability
2025-12-26 17:43:31 +01:00
54cc31a03a refactor: extract language toggle into reusable components
All checks were successful
CI / update (push) Successful in 24s
Create Toggle and LanguageToggle components to reduce code duplication
and enable shared state across pages.

- Add Toggle.svelte: Generic iOS-style toggle with customizable accent color
- Add LanguageToggle.svelte: Language-specific toggle with localStorage persistence
- Refactor rosary page to use new toggle components
- Add language toggle to gebete page
- Toggle state persists across both pages via localStorage
- Reduce min-height of Ave Maria decades in monolingual mode (50vh → 30vh)
2025-12-26 17:34:34 +01:00
01a31ae60a add language toggle 2025-12-26 17:29:41 +01:00
7eff051d8b fix: ensure Bible verses are prerendered and served statically
- Fetch full verse data at build time in +page.server.ts
- Pass preloaded verseData to BibleModal instead of fetching client-side
- Remove onMount fetch logic from BibleModal component
- Add VerseData interface to type definitions
- Update handleCitationClick to pass verseData prop

This ensures all Bible verses are embedded in static HTML during build,
eliminating runtime API calls and improving performance.
2025-12-16 16:01:04 +01:00
2b693d6e83 feat: enhance rosary with interactive Bible citations and improved mystery selection
- Add clickable Bible reference buttons that open modal with full verses
- Create BibleModal component with backdrop blur and styled close button
- Implement build-time data fetching for Bible texts while maintaining reactivity
- Redesign mystery selector with responsive grid (3-in-row/4-in-row/2×2)
- Add "Heutige" badge to indicate today's auto-selected mystery
- Reposition luminous mysteries toggle below mystery selector
- Integrate Bible reference and counter buttons side-by-side
- Restructure Bible API under /api/glaube/bibel/ for better organization
2025-12-16 15:45:40 +01:00
dc0737b7f3 ß -> ss 2025-12-16 13:47:25 +01:00
10cb650548 feat: enhance rosary with final prayer and mystery titles
- Add RosaryFinalPrayer component with Latin and German text
- Display short mystery titles in decade headings (e.g., "5. Gesätz: Kreuzigung")
- Add descriptive titles to initial three Ave Marias (Glaube, Hoffnung, Liebe)
- Add closing cross symbol to signal final sign of the cross
- Mystery titles update dynamically when switching between rosary types
2025-12-16 13:42:38 +01:00
96c7e504fb fix: remove scale transform on homepage icon hover 2025-12-12 22:55:43 +01:00
4efc592ab8 fix: adjust z-index values to prevent recipe card elements from overlapping header and add button 2025-12-12 22:48:40 +01:00
20cf1e2406 fix: improve mobile responsiveness of cospend page
Reduced padding on mobile screens (max-width: 600px) to prevent horizontal overflow and ensure header spans full width. Updated BarChart, DebtBreakdown, EnhancedBalance components and recent activity section.
2025-12-09 14:31:27 +01:00
cd1cded383 refactor: extract prayers into reusable components in gebete page
Extract inline prayer content into dedicated components in $lib/components/prayers/
for better code organization and reusability. This reduces the gebete page from ~339
to ~95 lines while maintaining the same functionality.
2025-12-08 00:48:10 +01:00
182602d4fe fix Gloria Patri 2025-12-08 00:13:30 +01:00
87382e9046 feat: enhance interactive rosary with mobile support and counters
- Add weekday-based mystery auto-selection with luminous mysteries toggle
- Implement iOS-style toggle for including/excluding luminous mysteries
- Add mystery selector buttons with visual feedback
- Create CounterButton component for tracking Ave Maria progress
- Add orange bead highlighting for prayer counting
- Implement auto-scroll to next section after completing decade
- Optimize mobile layout with responsive sidebar (20px-80px width)
- Scale rosary visualization 3.5x on mobile for better visibility
- Fix scroll synchronization accounting for CSS transform scale
- Increase cross size for better visibility
- Extract BenedictusMedal as reusable component
- Add smooth scroll polyfills for better browser compatibility
- Improve SVG interaction with click handlers and scroll locking
2025-12-04 21:13:20 +01:00
abf0af0cc9 refactor: improve rosary prayer styling and add closing prayers
- Add SalveRegina component with full bilingual Latin/German text
- Wrap FatimaGebet in paragraph tags for consistent styling with other prayers
- Combine final prayers (Gloria Patri, Fatima, Salve Regina) into single Abschluss section
- Change Ave Maria titles from German to Latin ('Ave Maria' instead of 'Gegrüßet seist du Maria')
- Add h3 titles to all Gloria Patri prayers for consistency
- Extend SVG viewBox to show more curve area at top and bottom
- Add CSS mask with gradients for smooth fade-out of circular connection curve
- Adjust viewBox dimensions for better bead visibility
2025-12-04 07:43:52 +01:00
1df11e454b feat: implement interactive rosary with bilingual prayer components
- Create reusable prayer components (Paternoster, AveMaria, GloriaPatri, Kreuzzeichen, Credo, FatimaGebet)
- Add bilingual display (Latin/German) with proper styling differentiation
- Implement scrolling SVG visualization that syncs with prayers
- Add mystery highlighting for Ave Maria (Latin in red, German in orange)
- Separate Gesätze (decades) from transition prayers (Gloria, Fatima, Paternoster)
- Complete full Nicene Creed text
- Split initial three Ave Marias into individual sections (Faith, Hope, Love)
- Add Latin versions for all rosary mysteries (joyful, sorrowful, glorious, luminous)
- Make visualization beads larger and remove container styling for seamless background integration
- Fix SVG coordinate-to-pixel conversion for accurate scroll synchronization
2025-12-04 00:07:02 +01:00
87bf880c0b fix: make nested links clickable in recipe cards
Use the card wrapper pattern with absolute positioned main link and elevated z-index for nested links.
This maintains proper HTML semantics (no nested <a> tags) while allowing category, icon, and tag links to be clickable.

- Replace outer <a> wrapper with <div>
- Add invisible overlay link for main card click area (z-index: 1)
- Elevate nested links (category, tags, icon) with z-index: 10
- Maintain all existing hover effects and accessibility
- Keep semantic HTML structure without nesting <a> tags
2025-11-18 15:29:33 +01:00