- Add viewport-fit=cover meta tag in nuxt.config.ts for safe area extension
- Remove CSS containment property that was blocking safe area rendering
- Replace hardcoded fallback values with proper max(env(), fallback) syntax
- Fix z-index stacking order (video: 0, footer: 2) to prevent overlays
- Enhance HTML/body background color configuration for safe area coverage
- Add ipx dependency for image optimization
Fixes white background in iOS Safari safe areas by using proper env() functions
with max() for fallbacks instead of hardcoded values that override dynamic sizing.
- Create custom hero layout without constraining wrapper div
- Remove min-h-screen and flex constraints that block video extension
- Change video to position:fixed with z-index:-1 for proper layering
- Fix overflow:clip to overflow:visible in voyage-layout.css
- Revert transparent background to black for stability
This finally solves the iOS Safari safe area issue by removing the DOM
structure constraints that were preventing the video from extending.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove invalid safe-area-max-inset-top (not a valid CSS property)
- Use standard safe-area-inset-top with iOS Safari workarounds
- Remove white background from video container (was blocking transparency)
- Change html/body background to transparent for safe area visibility
- Update status bar style to black-translucent for content under notch
- Add hardcoded fallbacks for iOS Safari portrait bug (env returns 0)
This fixes the issue where the video wasn't extending into the iPhone notch/Dynamic Island
by addressing the root causes: invalid CSS properties, blocking backgrounds, and Safari bugs.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove ClientOnly and Teleport wrappers that were causing SSR issues
- Switch to safe-area-max-inset-top which properly returns notch height on iOS
- Change position from fixed to absolute to prevent footer overlap
- Add proper fallbacks for browsers without safe-area-max support
- Simplify CSS by removing !important flags and duplicate styles
This fixes the Safari bug where env(safe-area-inset-top) returns 0 in portrait mode
by using safe-area-max-inset-top which always returns the correct notch height.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Wrapped Teleport in ClientOnly to avoid SSR/hydration issues
- Replaced env() with hardcoded -59px for Dynamic Island (Safari bug workaround)
- Added !important flags to ensure styles aren't overridden
- Set overflow: visible on hero-voyage container
- Used z-index: 0 to ensure video stays behind content
This addresses the Nuxt SSG + Teleport incompatibility and iOS Safari's env() bug
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Removed CSS contain properties that were preventing video from extending into safe area
- Implemented Vue 3 Teleport to bypass DOM containment for iOS video extension
- Video now renders at body level to properly utilize safe area insets
- Kept Safari fallbacks for env() bug workaround
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Add hardcoded fallbacks using max() function per Apple's recommendation
- Support both constant() and env() for legacy compatibility
- Use 59px fallback for Dynamic Island devices
- Add iOS-specific detection with @supports(-webkit-touch-callout)
- Create improved test page with device detection
- Update hero-content padding with same fallback approach
This works around the known Safari bug where env(safe-area-inset-top)
returns 0px in portrait mode. The video will now extend 59px above the
viewport on Dynamic Island iPhones, ensuring it covers the notch area.
- Remove overflow-x: hidden from HeroSection.vue that was clipping video
- Delete duplicate .hero-video-container styles from voyage-layout.css
- Fix navigation to use env() directly instead of CSS variables
- Remove deprecated constant() syntax
- Add safe-area-test.html for testing safe area extension
The video should now properly extend under the iOS notch/Dynamic Island
while keeping content within safe areas.
- Remove overflow:clip from .hero-voyage that was blocking video extension
- Replace hardcoded -50px with proper env(safe-area-inset-top) calculations
- Update hero-content to use env() values directly instead of CSS variables
- Video now properly extends under notch/Dynamic Island on all iOS devices
- Works with Chrome mobile's dynamic address bar using lvh units
- Content stays within safe areas for proper usability
- Use transform translateY to bypass iOS safe area constraints
- Video now extends into notch/Dynamic Island area on page load
- Removed ineffective iOS-specific negative positioning rules
The transform approach works by moving the element after layout calculations,
successfully bypassing Safari's safe area boundaries.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix hero video not displaying in notch safe area by changing z-index from -1 to 1
- Fix lucide icons not showing by installing and configuring nuxt-icon module
- Fix navigation bar bobbing by removing hysteresis thresholds and simplifying scroll handler
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove Teleport implementation that broke the page
- Use fixed positioning for video container
- Change body background to white for iOS safe area
- Maintain iOS-specific video extension rules
- Used <Teleport to='body'> to render video at root DOM level
- Bypassed layout container constraints (min-h-screen, flex-grow)
- Added ClientOnly wrapper for SSR compatibility
- Video now positioned directly at body level with fixed positioning
- Added iOS-specific styles to extend video into safe area
- Supports 100vh, 100dvh, and 100lvh for maximum compatibility
- White background fallback if video fails to load
- Object-position: center top for better notch coverage
This solution attempts to extend the video into the iOS safe area by
rendering it outside of all parent container constraints.
- Created VideoBackdrop component as global sibling layer
- Video now sits at app level behind all content (z-index: 0)
- Hero section made transparent to reveal video backdrop
- Video extends into notch with negative top positioning
- Content remains in safe areas with proper padding
- Removed video container from HeroSection component
- Added app.vue to manage global layout structure
This separation allows the video to truly extend edge-to-edge
including under the iOS notch/Dynamic Island while keeping
all interactive content within safe areas.
- Update hero tagline to "Reliable Care Above and Below the Waterline"
- Remove 5-star rating badge from hero section
- Change "Mobile Service" to "Tailored Service" with wrench icon
- Update section title from "Our Premium Services" to "Our Services"
- Merge Hull Cleaning and Anode Change services into single card
- Rename "Exterior Wash & Wax" to "Exterior Cleaning"
- Update trust indicators to show 3 badges: Years Experience, Customizable Service, Certified Experts
- Remove "Schedule Service" button from booking section
- Fix service card alignment with consistent heights and flexbox layout
- Add responsive layout for trust indicators on mobile (2+1 grid)
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Optimizations implemented:
- Added hardware acceleration for smooth animations (will-change, transform3d)
- Optimized touch targets for mobile (minimum 48x48px)
- Added explicit image dimensions to prevent CLS
- Implemented comprehensive SEO meta tags and Open Graph
- Added structured data for LocalBusiness and Service schemas
- Configured resource hints (preconnect, dns-prefetch, preload)
- Added lazy loading to non-critical images
- Improved button accessibility with touch-action: manipulation
These optimizations improve Core Web Vitals, mobile UX, and SEO visibility.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace easeInOutSine with linear easing (return t)
- Reduce duration from 1200ms to 800ms for snappier feel
- Update all component references to use new duration
Linear easing provides constant-speed scrolling without any
acceleration or deceleration, eliminating the jarring effect.
- Replace easeInOutQuad with easeInOutSine for natural motion
- Add user interruption handling (cancel on wheel/touch/keyboard)
- Add accessibility support for prefers-reduced-motion
- Optimize duration from 1800ms to 1200ms
- Add proper cleanup of event listeners and animation frames
- Update all component references to use new duration
The sine-based easing creates smooth, consistent motion throughout
the entire scroll duration without jarring speed changes.
- Changed from easeInOutCubic to easeInOutQuad for smoother motion
- Increased duration from 1.5 to 1.8 seconds
- Fixed jerky acceleration/deceleration issue
- Now provides consistent, smooth scrolling throughout entire motion
The scrolling is now properly smooth without the sudden speed changes.
Features added:
- Custom smooth scroll composable with adjustable duration (1.5 seconds)
- Replaced native browser smooth scroll with custom implementation
- Added 'Scroll to explore' text with chevron at bottom of hero
- Animated bounce effect for scroll indicator
- Chevron icon with subtle animation
- Click handler to scroll to services section
- Hidden on mobile for cleaner experience
All anchor links now scroll more slowly and smoothly for better UX.
- Remove poster image to eliminate jarring flash
- Add white gradient overlay that fades when video ready
- Implement smooth 800ms transition for premium UX
- Add video preload link tag for faster loading
- Works seamlessly on both mobile and desktop
The white overlay approach provides a clean loading experience that matches the luxury brand aesthetic while the video loads in the background.
- Add loadeddata and play events in addition to canplaythrough
- Add fallback timeout to ensure video becomes visible after 1.5s
- This ensures video will display even if autoplay events don't fire properly
- Change video preload from metadata to auto for faster loading
- Add fade-in transition for smooth video appearance
- Remove transform scale(1.1) that caused horizontal overflow
- Add comprehensive overflow-x: hidden to html, body, and hero containers
- Add max-width: 100vw constraints at multiple levels
- Add contain: layout to hero section for better overflow control
- Implement proper loading states to prevent fallback image flash
- Update viewport meta to prevent zoom-out issues
- Add video preload and smooth fallback transitions
- Implement iOS overscroll bounce prevention
- Center service offering buttons properly
- Add mobile-specific padding and touch target sizing
- Optimize video loading with canplaythrough event
- Add fade-out transition for fallback image
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix testimonial stars to display horizontally
- Make booking section buttons always visible
- Align footer Get in Touch section to the right
- Add proper video overlay gradients for text visibility
- Fix booking card visibility with white backgrounds
- Improve mobile responsiveness with smaller buttons
- Create 2x2 stats grid for mobile view
- Add Harbor Smith logo as favicon
- Remove scroll indicator from hero section
- Add animated counter for seafarers (0 to 100+)
- Center and resize mobile buttons properly
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>