# Mobile App Visual Integration Guide

**Last Updated:** 2026-03-26

## Overview

This guide provides instructions for integrating the 4 app visual files into the scroll-based visual switching layout on the mobile app product page.

**Shared layout contract** (also used on `/branchen/gastronomie`): [mobile-app-features-layout.md](mobile-app-features-layout.md).

## Visual File Requirements

### File Format
- **Preferred:** WebP format (best compression, modern browser support)
- **Alternative:** PNG format (if WebP not available)
- **Not Recommended:** JPEG (lossy compression not ideal for UI screenshots)

### Dimensions
- **Base Width:** 360px (matches mobile device frame max-width)
- **Aspect Ratio:** Maintain mobile device proportions (approximately 9:16 or similar)
- **Responsive Sizes:** Create multiple sizes for srcset:
  - 360w (base)
  - 720w (retina/2x)
  - 1080w (3x if needed)

### File Naming Convention
- `schichtplanung-visual.webp` (and `-360w.webp`, `-720w.webp` variants)
- `zeiterfassung-visual.webp` (and variants)
- `urlaub-visual.webp` (and variants)
- `dokumente-visual.webp` (and variants)

### Storage Location
- **Recommended:** `/v2/img/mobile-app/visuals/`
- Create directory if it doesn't exist: `mkdir -p v2/img/mobile-app/visuals`

## Visual Mapping

Each visual corresponds to one text section:

| Visual ID | Text Section | File Name |
|-----------|--------------|-----------|
| `visual-schichtplanung` | Schichtplanung ohne Rückfragen | `schichtplanung-visual.webp` |
| `visual-zeiterfassung` | Minutengenauer Zeiterfassung | `zeiterfassung-visual.webp` |
| `visual-urlaub` | Urlaub mit einem Klick beantragen | `urlaub-visual.webp` |
| `visual-dokumente` | Dokumente & Nachrichten erreichen alle | `dokumente-visual.webp` |

## Integration Steps

### Step 1: Prepare Images

1. **Optimize Images:**
   - Use image optimization tool (e.g., Squoosh, ImageOptim)
   - Target file size: <200KB per image
   - Maintain quality: 85-90% for WebP

2. **Create Responsive Variants:**
   - Generate 360w, 720w versions
   - Use consistent naming: `{name}-{width}w.webp`

3. **Upload Files:**
   - Place all files in `/v2/img/mobile-app/visuals/`
   - Verify file permissions (readable)

### Step 2: Update HTML Structure

**File:** `v2/pages/product_mobile_app.php`

**For each visual placeholder**, replace the placeholder content:

**Before:**
```php
<div id="visual-schichtplanung" class="mobile-visual active" data-visual-id="schichtplanung">
    <div class="mobile-visual-placeholder">
        <div class="mobile-status-bar">...</div>
        <div class="mobile-visual-placeholder-content">
            <p class="text-center text-gray-400 py-12">Schichtplanung Visual</p>
        </div>
    </div>
</div>
```

**After:**
```php
<div id="visual-schichtplanung" class="mobile-visual active" data-visual-id="schichtplanung">
    <img 
        src="/v2/img/mobile-app/visuals/schichtplanung-visual-360w.webp"
        srcset="/v2/img/mobile-app/visuals/schichtplanung-visual-360w.webp 360w,
                /v2/img/mobile-app/visuals/schichtplanung-visual-720w.webp 720w"
        sizes="(max-width: 1023px) 100vw, 360px"
        alt="Ordio Mitarbeiter-App: Schichtplanung ohne Rückfragen - Dein Team sieht den Schichtplan, setzt Verfügbarkeiten und bewirbt sich auf offene Schichten."
        width="360"
        height="640"
        loading="lazy"
        decoding="async"
        class="mobile-visual-image"
    />
</div>
```

### Step 3: Add CSS for Images

**File:** `v2/css/mobile-app-components.css`

Add styles for visual images (if not already present):

```css
.mobile-visual img.mobile-visual-image {
    width: 100%;
    height: auto;
    display: block;
    object-fit: contain;
}
```

### Step 4: Remove Placeholder Content

After adding images, remove:
- `.mobile-visual-placeholder` divs
- `.mobile-visual-placeholder-content` divs
- Placeholder text

Keep only:
- Visual container structure
- Image tags
- Mobile status bar (if needed for visual context)

### Step 5: Test Integration

1. **Visual Loading:**
   - Verify all 4 images load correctly
   - Check responsive sizes load appropriately
   - Verify no broken image icons

2. **Scroll Behavior:**
   - Test slow scroll (visuals switch smoothly)
   - Test fast scroll (no flickering)
   - Verify correct visual shows for each section

3. **Crossfade Transitions:**
   - Verify smooth opacity transitions
   - Check no layout shift during transitions
   - Ensure transitions complete before next switch

4. **Responsive Behavior:**
   - Test mobile viewport (sticky disabled, visuals stack)
   - Test tablet viewport (sticky enabled)
   - Test desktop viewport (full sticky behavior)

5. **Performance:**
   - Check image loading performance
   - Verify lazy loading works
   - Test with slow network (throttle in DevTools)

## Image Optimization Checklist

- [ ] Images optimized (WebP format, <200KB each)
- [ ] Responsive variants created (360w, 720w)
- [ ] Proper srcset and sizes attributes
- [ ] Explicit width and height attributes (prevents CLS)
- [ ] Descriptive alt text (benefit-focused, includes keywords)
- [ ] Lazy loading enabled (below fold)
- [ ] Async decoding enabled
- [ ] Files uploaded to correct directory
- [ ] File permissions correct

## Accessibility Checklist

- [ ] All images have descriptive alt text
- [ ] Alt text includes feature name and benefit
- [ ] Alt text is concise (<125 characters)
- [ ] Images don't convey critical information without alt text
- [ ] Visual switching doesn't interfere with screen readers

## Performance Checklist

- [ ] Images optimized (WebP, compressed)
- [ ] Responsive images (srcset) implemented
- [ ] Lazy loading enabled
- [ ] Explicit dimensions (prevents layout shift)
- [ ] File sizes reasonable (<200KB per image)
- [ ] No layout thrashing during transitions

## Troubleshooting

### Images Not Loading
- Check file paths (absolute paths from root)
- Verify file permissions
- Check browser console for 404 errors
- Verify file extensions match (.webp)

### Visuals Not Switching

**Common Causes:**

1. **Scroll handler / reference line:**
   - Check browser console for JavaScript errors
   - Confirm `mobile-app-visual-switcher.min.js` loads (cache-bust via `filemtime`)
   - Active section is chosen from scroll position: reference line at `CONFIG.referenceLineRatio × innerHeight` (see `v2/js/mobile-app-visual-switcher.js`)
   - Verify each `.mobile-app-text-section` has `data-visual-id` and a matching `#visual-{id}` element

2. **CSS Conflicts:**
   - Ensure no CSS fallback is showing first visual by default
   - All visuals should start with `opacity: 0`
   - Only `.active` class should set `opacity: 1`
   - Check for conflicting CSS rules using browser DevTools

3. **Missing Attributes:**
   - Verify text sections have correct `data-visual-id` attributes
   - Verify visual containers have matching IDs (`visual-{id}`)
   - Check that all 4 sections and visuals exist
   - Verify first section has class `.mobile-app-text-section-first`
   - Verify last section has class `.mobile-app-text-section-last`

4. **Debug Mode:**
   - Enable debug mode in `mobile-app-visual-switcher.js`: Set `CONFIG.debug = true`
   - Check console for intersection updates and visual switching logs
   - Use debug script: `v2/scripts/dev-helpers/debug-visual-switcher.js`

5. **Initialization Issues:**
   - Verify script loads after DOM is ready
   - Check that features section (`#mobile-app-features`) exists
   - Verify visual container (`.mobile-visual-container-wrapper`) exists
   - Check that first and last sections are properly identified

### Visual Not Scrolling Correctly

**Common Causes:**

1. **Boundary Detection Issues:**
   - Visual should only appear when first section (`.mobile-app-text-section-first`) enters viewport
   - Visual should disappear when last section (`.mobile-app-text-section-last`) exits viewport
   - Verify features section (`#mobile-app-features`) is in viewport
   - Check boundary detection logic in `updateVisualPosition()` function

2. **Transform Calculation:**
   - Visual wrapper uses `position: sticky; top: 50%; transform: translateY(-50%)` in CSS
   - JavaScript applies additional offset: `translateY(calc(-50% + ${offset}px))`
   - Offset calculation: `sectionCenter - viewportCenter`
   - Verify active section is correctly identified

3. **Scroll Direction:**
   - When scrolling down, visual should move down (positive translateY)
   - When scrolling up, visual should move up (negative translateY)
   - Visual should center with active section's center
   - Check that `requestAnimationFrame` is being used for smooth updates

### Transitions Not Smooth
- Check CSS transitions are applied
- Verify `will-change: opacity` is set
- Check for conflicting CSS
- Test with browser DevTools Performance tab

### Sticky Not Working
- Verify viewport width > 1024px
- Check parent container doesn't have `overflow: hidden`
- Verify `position: sticky` is supported
- Check z-index conflicts

## Component Restoration (Future)

After visual integration, consider restoring/enhancing original components:

1. **calendar-component.php** - Can be enhanced with new visual
2. **timer-component.php** - Can be enhanced with new visual
3. **absence-form-component.php** - Can be enhanced with new visual
4. **documents-broadcast-component.php** - Can be enhanced with new visual

**Restoration Steps:**
1. Uncomment component includes in PHP
2. Remove placeholder content
3. Integrate components with new visual structure
4. Test component functionality
5. Update documentation

## Related Files

- **PHP:** `v2/pages/product_mobile_app.php` (lines 391-633)
- **JavaScript:** `v2/js/mobile-app-visual-switcher.js`
- **CSS:** `v2/css/mobile-app-components.css` (scroll-based visual switching styles)
- **Documentation:** `docs/content/pages/product-pages/mobile-app-documentation.md`

## Support

For questions or issues:
- Review Intersection Observer implementation in `mobile-app-visual-switcher.js`
- Check CSS sticky positioning in `mobile-app-components.css`
- Refer to scroll-based visual switching pattern documentation
