Initial import of HarborSmith website
Some checks failed
build-website / build (push) Failing after 1m2s

This commit is contained in:
2025-09-18 22:20:01 +02:00
commit ec72c5d62b
168 changed files with 65020 additions and 0 deletions

BIN
website-mockups/Anodes.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 MiB

View File

@@ -0,0 +1,327 @@
# HarborSmith Client Portal - Implementation Guide
## Completed Components
### ✅ Core Infrastructure
1. **portal-styles.css** - Complete CSS framework for the portal
- Dashboard layouts and cards
- Form styles and validation states
- Tables and data displays
- Status badges and indicators
- Responsive design breakpoints
- Theme support (4 themes)
2. **portal-login.html** - Unified login page
- Role selection (Maintenance/Charter)
- OAuth integration placeholders
- Demo credentials system
- Video background with brand messaging
3. **maintenance-dashboard.html** - Main maintenance dashboard
- Fleet overview with health scores
- Upcoming services calendar
- Invoice status tracking
- Recent activity timeline
- Quick action buttons
4. **maintenance-vessels.html** - Vessel management page
- Grid view of registered vessels
- Add new vessel modal
- Health score visualization
- Quick schedule buttons
## Remaining Pages to Implement
### Maintenance Portal Pages
#### 1. **maintenance-schedule.html**
**Features:**
- Interactive calendar view (monthly/weekly/daily)
- Service type selector dropdown
- Available time slots display
- Vessel selection with current status
- Service urgency levels (Emergency/Urgent/Routine)
- Preferred technician selection
- Special instructions text area
- Confirmation and reminder settings
#### 2. **maintenance-documents.html**
**Features:**
- Document categories sidebar
- Registration documents
- Insurance policies
- Service warranties
- Safety certificates
- Owner manuals
- Drag-and-drop upload zone
- Document preview modal
- Expiry date tracking with alerts
- Search and filter functionality
- Bulk download option
- Document sharing controls
#### 3. **maintenance-reports.html**
**Features:**
- Filterable report list (by date, vessel, service type)
- Detailed report viewer with sections:
- Service summary
- Parts replaced
- Labor performed
- Before/after photos
- Technician recommendations
- Next service suggestions
- Comment/note addition
- PDF export functionality
- Service rating and feedback
#### 4. **maintenance-invoices.html**
**Features:**
- Invoice list with status filters (Paid/Pending/Overdue)
- Detailed invoice view with line items
- Payment method selection
- Credit card form
- ACH transfer details
- Wire instructions
- Payment history table
- Auto-pay configuration
- Dispute/question form
- Download receipts
### Charter Portal Pages
#### 5. **charter-dashboard.html**
**Features:**
- Current charter countdown timer
- Weather widget for charter date
- Itinerary preview card
- Guest list summary
- Payment status indicator
- Recommended add-ons carousel
- Recent messages from crew
- Pre-charter checklist
#### 6. **charter-packages.html**
**Features:**
- Current package details card
- Available upgrades grid:
- Gourmet catering tiers
- Water sports equipment
- Photography/videography
- Special occasion decorations
- Extended hours
- Additional crew
- Package comparison table
- Pricing calculator with real-time updates
- Save package as template
#### 7. **charter-itinerary.html**
**Features:**
- Interactive map with waypoints
- Draggable timeline editor
- Activity cards:
- Departure/arrival times
- Anchor locations
- Meal times
- Activity slots
- Sunset viewing spots
- Weather overlay on timeline
- Share itinerary via email/link
- Print-friendly version
- Captain's notes section
#### 8. **charter-payments.html**
**Features:**
- Payment summary breakdown:
- Base charter fee
- Add-ons and upgrades
- Additional guests
- Taxes and fees
- Gratuity calculator
- Guest addition form ($150/guest)
- Payment schedule display
- Saved payment methods
- Transaction history
- Refund policy accordion
- Split payment option
#### 9. **charter-documents.html**
**Features:**
- Required documents checklist:
- Photo IDs for all guests
- Signed waivers
- Insurance proof
- Medical/dietary forms
- Emergency contacts
- Upload progress tracker
- Document status badges
- Secure preview modal
- Download all as ZIP
- Missing document alerts
#### 10. **charter-profile.html**
**Features:**
- Personal information form
- Emergency contacts (primary/secondary)
- Preferences section:
- Dietary restrictions
- Allergies
- Music preferences
- Beverage selections
- Activity interests
- Previous charters gallery
- Favorite vessels
- Saved itineraries
- Communication preferences
- Photo memories timeline
## Implementation Details
### Navigation Structure
All pages share consistent sidebar navigation with:
- Collapsible sidebar toggle
- Active state highlighting
- Role-based menu items
- User profile dropdown
- Notification badge
### Common Components
- **Header**: Breadcrumb navigation, search, notifications, user menu
- **Cards**: Consistent shadow, hover effects, border radius
- **Forms**: Validation states, required field indicators, help text
- **Modals**: Overlay, close button, responsive sizing
- **Tables**: Sortable headers, hover states, responsive scroll
### Interactive Features
1. **Form Validation**
- Real-time field validation
- Error message display
- Success confirmation toasts
2. **Data Tables**
- Column sorting
- Pagination
- Search/filter
- Export options
3. **File Uploads**
- Drag-and-drop zones
- Progress indicators
- File type validation
- Preview generation
4. **Calendar Integration**
- Date picker widgets
- Time slot selection
- Availability checking
- Reminder settings
### Mock Data Structure
```javascript
// Sample user data
const maintenanceUser = {
name: "John Smith",
email: "maintenance@demo.com",
role: "maintenance",
vessels: [
{
id: 1,
name: "Sea Breeze",
type: "Sailboat",
model: "Beneteau Oceanis 45",
year: 2019,
healthScore: 95,
lastService: "2024-11-10",
nextService: "2024-12-15"
}
],
invoices: [
{
id: "INV-1247",
amount: 2850,
status: "paid",
date: "2024-11-15"
}
]
};
const charterUser = {
name: "Sarah Johnson",
email: "charter@demo.com",
role: "charter",
currentBooking: {
vessel: "Bay Dreamer",
date: "2024-12-20",
duration: "4 hours",
guests: 8,
package: "Premium Sunset"
}
};
```
### Responsive Breakpoints
- **Mobile**: < 768px (stacked layout, hidden sidebar)
- **Tablet**: 768px - 1024px (condensed sidebar, 2-column grids)
- **Desktop**: > 1024px (full sidebar, multi-column layouts)
### Security Considerations
- Session management with localStorage
- Secure document handling
- Input sanitization
- HTTPS enforcement (production)
- Two-factor authentication ready
### Performance Optimizations
- Lazy loading for images
- Pagination for large datasets
- Debounced search inputs
- Skeleton loaders for async content
- Minified CSS/JS (production)
## Next Steps for Full Implementation
1. **Backend Integration**
- API endpoints for CRUD operations
- Authentication system
- File upload handling
- Payment processing
- Email notifications
2. **Database Schema**
- Users table with roles
- Vessels table with specifications
- Services table with scheduling
- Documents table with metadata
- Invoices table with line items
3. **Third-Party Integrations**
- Stripe/PayPal for payments
- SendGrid for emails
- AWS S3 for document storage
- Google Calendar API
- Weather API
4. **Testing Requirements**
- Unit tests for form validation
- Integration tests for workflows
- Accessibility testing (WCAG 2.1)
- Cross-browser compatibility
- Performance benchmarks
5. **Deployment Considerations**
- SSL certificates
- CDN for static assets
- Database backups
- Monitoring and logging
- Support ticket system
## Design Consistency Notes
All pages maintain:
- Warm, inviting color palette from main site
- Inter + Playfair Display typography
- Consistent spacing using CSS variables
- Smooth transitions and hover effects
- Professional yet approachable tone
- Mobile-first responsive design
This comprehensive portal system provides a complete solution for both maintenance and charter clients while maintaining the HarborSmith brand identity and user experience standards.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

View File

@@ -0,0 +1,814 @@
# HarborSmith Design System
## Voyage Theme Standard
### Version 1.0
Last Updated: December 2024
---
## 🎨 Core Design Philosophy
The HarborSmith Voyage theme embodies the spirit of maritime adventure with warm, inviting colors that evoke feelings of sunset voyages and golden horizons. Our design system combines nautical heritage with modern luxury, creating an experience that is both timeless and contemporary.
### Design Principles
1. **Warmth & Welcome** - Every element should feel inviting and aspirational
2. **Maritime Heritage** - Subtle nautical references without being cliché
3. **Premium Experience** - Convey luxury through spacing, typography, and imagery
4. **Emotional Connection** - Use warm gradients and cinematic visuals to inspire adventure
5. **Accessibility** - Maintain WCAG AA compliance across all color combinations
---
## 🎨 Color Palette
### Primary Colors
#### Classic Nautical (Default Theme)
```css
--primary-blue: #001f3f; /* Deep Navy - Headers, Primary Text */
--warm-orange: #dc143c; /* Crimson Red - CTAs, Accents */
--warm-amber: #b91c3c; /* Deep Crimson - Hover States */
--warm-yellow: #ef4444; /* Coral Red - Highlights */
--soft-cream: #f0f4f8; /* Light Blue-Gray - Backgrounds */
--text-dark: #0a1628; /* Near Black - Body Text */
--text-light: #4a5568; /* Gray - Secondary Text */
--white: #ffffff; /* Pure White - Cards, Contrast */
```
### Gradients
```css
--gradient-warm: linear-gradient(135deg, #dc143c 0%, #ef4444 100%);
--gradient-sunset: linear-gradient(135deg, #b91c3c 0%, #dc143c 50%, #ef4444 100%);
--gradient-ocean: linear-gradient(135deg, #001f3f 0%, #003366 100%);
```
### Semantic Colors
```css
--success: #10B981; /* Emerald Green */
--warning: #F59E0B; /* Amber */
--error: #EF4444; /* Red */
--info: #3B82F6; /* Blue */
```
### Usage Guidelines
- **Primary Blue (#001f3f)**: Main headers, navigation (scrolled state), footer backgrounds
- **Warm Orange (#dc143c)**: Primary CTA buttons, active states, important accents
- **Warm Amber (#b91c3c)**: Hover states for primary actions
- **Soft Cream (#f0f4f8)**: Section backgrounds, alternate row colors
- **Gradients**: Hero sections, premium features, CTA buttons
---
## 📝 Typography
### Font Families
```css
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
--font-display: 'Playfair Display', serif;
```
### Type Scale
```css
/* Display - Hero Headlines */
.display-1 {
font-size: clamp(3rem, 8vw, 5rem);
font-family: var(--font-display);
font-weight: 900;
line-height: 1.1;
}
/* Headings */
h1 {
font-size: clamp(2.5rem, 5vw, 3.5rem);
font-family: var(--font-display);
font-weight: 700;
line-height: 1.2;
}
h2 {
font-size: clamp(2rem, 4vw, 2.5rem);
font-family: var(--font-display);
font-weight: 700;
line-height: 1.3;
}
h3 {
font-size: clamp(1.5rem, 3vw, 1.875rem);
font-family: var(--font-sans);
font-weight: 600;
line-height: 1.4;
}
h4 {
font-size: 1.25rem;
font-family: var(--font-sans);
font-weight: 600;
line-height: 1.5;
}
/* Body Text */
.body-large {
font-size: 1.125rem;
line-height: 1.7;
}
.body-regular {
font-size: 1rem;
line-height: 1.6;
}
.body-small {
font-size: 0.875rem;
line-height: 1.5;
}
```
### Typography Usage
- **Playfair Display**: Hero headlines, section titles, brand name
- **Inter**: Body text, navigation, buttons, forms
- **Font Weights**: 300 (light), 400 (regular), 500 (medium), 600 (semibold), 700 (bold), 800 (extrabold), 900 (black)
---
## 📐 Spacing System
### Base Unit: 8px
```css
--space-xs: 0.5rem; /* 8px */
--space-sm: 1rem; /* 16px */
--space-md: 2rem; /* 32px */
--space-lg: 3rem; /* 48px */
--space-xl: 4rem; /* 64px */
--space-2xl: 6rem; /* 96px */
--space-3xl: 8rem; /* 128px */
```
### Container Widths
```css
--container-sm: 640px;
--container-md: 768px;
--container-lg: 1024px;
--container-xl: 1200px;
--container-2xl: 1400px;
```
### Section Padding
- Mobile: `padding: var(--space-lg) var(--space-md);`
- Tablet: `padding: var(--space-xl) var(--space-md);`
- Desktop: `padding: var(--space-2xl) var(--space-md);`
---
## 🎯 Components
### Buttons
#### Primary Button (Warm Gradient)
```css
.btn-primary {
background: var(--gradient-warm);
color: white;
padding: 0.875rem 2rem;
border-radius: 50px;
font-weight: 600;
font-size: 1rem;
border: none;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(220, 20, 60, 0.3);
}
```
#### Secondary Button (Ghost)
```css
.btn-secondary {
background: transparent;
color: var(--warm-orange);
padding: 0.875rem 2rem;
border: 2px solid var(--warm-orange);
border-radius: 50px;
font-weight: 600;
transition: all 0.3s ease;
}
.btn-secondary:hover {
background: var(--warm-orange);
color: white;
transform: translateY(-2px);
}
```
### Cards
#### Standard Card
```css
.card {
background: white;
border-radius: 16px;
padding: var(--space-md);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}
```
#### Premium Card (with gradient border)
```css
.card-premium {
background: white;
border-radius: 20px;
padding: 3px;
background: var(--gradient-warm);
}
.card-premium-inner {
background: white;
border-radius: 17px;
padding: var(--space-md);
}
```
### Navigation
#### Fixed Navigation Bar
```css
.navigation {
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Transparent state (hero) */
.navigation {
background: rgba(255, 255, 255, 0);
backdrop-filter: blur(0);
}
/* Scrolled state */
.navigation.scrolled {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}
```
### Forms
#### Input Fields
```css
.form-input {
width: 100%;
padding: 0.875rem 1.25rem;
border: 2px solid #E5E7EB;
border-radius: 12px;
font-size: 1rem;
transition: all 0.3s ease;
}
.form-input:focus {
outline: none;
border-color: var(--warm-orange);
box-shadow: 0 0 0 3px rgba(220, 20, 60, 0.1);
}
```
#### Dropdown Menus
```jsx
// React Component with Framer Motion
// Standard dropdown pattern for consistent interactions across the platform
import { motion, AnimatePresence } from 'framer-motion';
import { ChevronDown } from 'lucide-react';
import { useState } from 'react';
const DropdownMenu = ({
label = "Select Option",
options = [],
value,
onChange,
placeholder = "Choose...",
icon = null
}) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="dropdown-container">
<button
className="dropdown-trigger"
onClick={() => setIsOpen(!isOpen)}
aria-expanded={isOpen}
aria-haspopup="listbox"
>
{icon && <span className="dropdown-icon">{icon}</span>}
<span className="dropdown-value">
{value || placeholder}
</span>
<ChevronDown
className={`dropdown-chevron ${isOpen ? 'rotate-180' : ''}`}
size={20}
/>
</button>
<AnimatePresence>
{isOpen && (
<motion.div
className="dropdown-menu"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
{options.map((option) => (
<motion.button
key={option.value}
className="dropdown-option"
onClick={() => {
onChange(option);
setIsOpen(false);
}}
whileHover={{ x: 4 }}
transition={{ type: "spring", stiffness: 300 }}
>
{option.icon && (
<span className="option-icon">{option.icon}</span>
)}
<span className="option-label">{option.label}</span>
{option.badge && (
<span className="option-badge">{option.badge}</span>
)}
</motion.button>
))}
</motion.div>
)}
</AnimatePresence>
</div>
);
};
```
##### Dropdown Styles (CSS)
```css
.dropdown-container {
position: relative;
width: 100%;
}
.dropdown-trigger {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 0.875rem 1.25rem;
background: white;
border: 2px solid rgba(220, 20, 60, 0.1);
border-radius: 12px;
font-size: 1rem;
font-weight: 500;
color: #0a1628;
cursor: pointer;
transition: all 0.3s ease;
}
.dropdown-trigger:hover {
border-color: rgba(220, 20, 60, 0.2);
box-shadow: 0 4px 12px rgba(0, 31, 63, 0.08);
}
.dropdown-trigger:focus {
outline: none;
border-color: #dc143c;
box-shadow: 0 0 0 3px rgba(220, 20, 60, 0.1);
}
.dropdown-icon {
display: flex;
align-items: center;
color: #dc143c;
}
.dropdown-value {
flex: 1;
text-align: left;
}
.dropdown-chevron {
color: #64748b;
transition: transform 0.3s ease;
}
.dropdown-chevron.rotate-180 {
transform: rotate(180deg);
}
.dropdown-menu {
position: absolute;
top: calc(100% + 8px);
left: 0;
right: 0;
max-height: 320px;
overflow-y: auto;
background: white;
border: 1px solid rgba(220, 20, 60, 0.08);
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0, 31, 63, 0.12);
z-index: 1000;
}
.dropdown-option {
width: 100%;
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.875rem 1.25rem;
background: transparent;
border: none;
font-size: 0.95rem;
color: #4a5568;
cursor: pointer;
transition: all 0.2s ease;
text-align: left;
}
.dropdown-option:hover {
background: linear-gradient(90deg, rgba(220, 20, 60, 0.05), rgba(239, 68, 68, 0.05));
color: #0a1628;
}
.dropdown-option:focus {
outline: none;
background: rgba(220, 20, 60, 0.08);
}
.option-icon {
display: flex;
align-items: center;
color: #dc143c;
width: 20px;
}
.option-label {
flex: 1;
}
.option-badge {
padding: 0.25rem 0.5rem;
background: linear-gradient(135deg, #dc143c, #ef4444);
color: white;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
}
/* Dark Mode Variant */
.dark .dropdown-trigger {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.1);
color: white;
}
.dark .dropdown-menu {
background: #1a1a2e;
border-color: rgba(255, 255, 255, 0.1);
}
.dark .dropdown-option {
color: rgba(255, 255, 255, 0.8);
}
.dark .dropdown-option:hover {
background: rgba(220, 20, 60, 0.2);
color: white;
}
```
##### Usage Examples
```jsx
// Basic Dropdown
<DropdownMenu
label="Select Yacht"
options={[
{ value: 'azure', label: 'Azure Dream' },
{ value: 'seastar', label: 'Sea Star' },
{ value: 'windwhisper', label: 'Wind Whisper' }
]}
value={selectedYacht}
onChange={(option) => setSelectedYacht(option.value)}
/>
// Dropdown with Icons and Badges
<DropdownMenu
label="Choose Route"
icon={<MapPin />}
options={[
{
value: 'golden-gate',
label: 'Golden Gate Tour',
icon: <Bridge />,
badge: 'Popular'
},
{
value: 'alcatraz',
label: 'Alcatraz Circle',
icon: <Anchor />
},
{
value: 'sunset',
label: 'Sunset Cruise',
icon: <Sun />,
badge: 'Romantic'
}
]}
value={selectedRoute}
onChange={(option) => setSelectedRoute(option.value)}
/>
```
##### Accessibility Guidelines
- Always include proper ARIA attributes (`aria-expanded`, `aria-haspopup`)
- Ensure keyboard navigation works (Tab, Enter, Escape keys)
- Maintain focus management when opening/closing
- Provide clear visual focus indicators
- Support screen readers with semantic HTML
---
## 🎬 Animations
### Standard Transitions
```css
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--transition-slow: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
--transition-fast: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
```
### Animation Classes
```css
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fade-up {
animation: fadeInUp 0.8s ease forwards;
}
.animate-fade-up-delay {
animation: fadeInUp 0.8s ease 0.2s forwards;
opacity: 0;
}
.animate-fade-up-delay-2 {
animation: fadeInUp 0.8s ease 0.4s forwards;
opacity: 0;
}
```
### Hover Effects
- **Lift**: `transform: translateY(-4px);`
- **Scale**: `transform: scale(1.05);`
- **Glow**: `box-shadow: 0 10px 30px rgba(220, 20, 60, 0.3);`
---
## 🖼️ Imagery Guidelines
### Hero Images
- **Aspect Ratio**: 16:9 for desktop, 4:3 for mobile
- **Overlay**: Dark gradient overlay (40-60% opacity) for text legibility
- **Quality**: Minimum 1920x1080 for desktop, optimized for web
### Content Images
- **Border Radius**: 16px for standard images, 20px for featured
- **Shadow**: `box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);`
- **Hover Effect**: Scale 1.05 with transition
### Image Overlays
```css
.image-overlay {
background: linear-gradient(
to bottom,
rgba(0, 31, 63, 0.3) 0%,
rgba(0, 31, 63, 0.7) 100%
);
}
```
---
## 📱 Responsive Breakpoints
```css
/* Mobile First Approach */
--breakpoint-sm: 640px; /* Small tablets */
--breakpoint-md: 768px; /* Tablets */
--breakpoint-lg: 1024px; /* Small laptops */
--breakpoint-xl: 1280px; /* Desktop */
--breakpoint-2xl: 1536px; /* Large screens */
```
### Media Query Usage
```css
/* Mobile (default) */
.element { }
/* Tablet and up */
@media (min-width: 768px) {
.element { }
}
/* Desktop and up */
@media (min-width: 1024px) {
.element { }
}
```
---
## 🌟 Special Effects
### Gradient Text
```css
.gradient-text {
background: var(--gradient-warm);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
```
### Glass Morphism
```css
.glass {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 16px;
}
```
### Warm Glow Effect
```css
.warm-glow {
box-shadow:
0 0 20px rgba(220, 20, 60, 0.1),
0 0 40px rgba(220, 20, 60, 0.05);
}
```
---
## 🎯 Icon System
### Lucide Icons Configuration
```css
[data-lucide] {
width: 24px;
height: 24px;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
```
### Icon Sizes
- **Small**: 16px (inline text)
- **Default**: 24px (buttons, navigation)
- **Medium**: 32px (feature icons)
- **Large**: 48px (hero icons)
---
## ✅ Accessibility Standards
### Color Contrast
- **Normal Text**: Minimum 4.5:1 contrast ratio
- **Large Text**: Minimum 3:1 contrast ratio
- **Interactive Elements**: Minimum 3:1 contrast ratio
### Focus States
```css
:focus-visible {
outline: 3px solid var(--warm-orange);
outline-offset: 2px;
border-radius: 4px;
}
```
### Touch Targets
- Minimum size: 44x44px
- Spacing between targets: minimum 8px
---
## 🚀 Implementation Checklist
### For Each Page
- [ ] Use correct color palette variables
- [ ] Apply consistent typography scale
- [ ] Maintain spacing system
- [ ] Include smooth transitions
- [ ] Implement hover states
- [ ] Ensure mobile responsiveness
- [ ] Add proper focus states
- [ ] Use semantic HTML
- [ ] Include meta descriptions
- [ ] Optimize images
### Component Consistency
- [ ] Buttons match design system
- [ ] Forms use standard inputs
- [ ] Cards follow shadow/radius standards
- [ ] Navigation transitions properly
- [ ] Footer matches other pages
- [ ] Icons use Lucide consistently
---
## 📋 Quick Reference
### CSS Variables to Include
```css
<link rel="stylesheet" href="css/voyage-layout.css">
<link rel="stylesheet" href="css/themes.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
```
### Standard Page Structure
```html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Meta tags -->
<!-- Font imports -->
<!-- CSS files -->
</head>
<body>
<!-- Navigation -->
<nav class="voyage-nav">...</nav>
<!-- Hero Section -->
<section class="hero-voyage">...</section>
<!-- Content Sections -->
<section class="section-name">
<div class="container">
<!-- Content -->
</div>
</section>
<!-- Footer -->
<footer class="voyage-footer">...</footer>
<!-- Scripts -->
<script>lucide.createIcons();</script>
</body>
</html>
```
---
## 🔄 Version History
### Version 1.0 (December 2024)
- Initial design system documentation
- Voyage theme standardization
- Color palette definition
- Typography scale
- Component library
- Animation guidelines
---
## 📝 Notes
This design system is optimized for:
- Modern browsers (Chrome, Firefox, Safari, Edge)
- Mobile-first responsive design
- WCAG AA accessibility standards
- Performance (lazy loading, optimized assets)
- SEO best practices
For questions or updates, contact the HarborSmith development team.

View File

@@ -0,0 +1,2 @@
## Client Portal ##
User experience: Details, Number of Guests, Packages, Special Occassions, Dog Friendly or not, etc. --> Boat selection, and day and time slots, pickup time and place --> Checkout

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

View File

@@ -0,0 +1,272 @@
# HarborSmith Platform Definition Document
## Executive Summary
HarborSmith is a comprehensive marine services platform that bridges the gap between yacht owners and maritime service providers. The platform operates through two primary service verticals: **Maintenance Services** and **Charter Services**, unified through an integrated client portal system designed to evolve into dedicated mobile and web applications.
## Company Vision
To become the premier digital platform for luxury yacht services, providing seamless connections between vessel owners, charter clients, and marine service providers while ensuring exceptional service quality, transparency, and convenience.
## Platform Structure
### Core Service Verticals
#### 1. Maintenance Services Division
**Target Audience:** Yacht owners, vessel managers, and marine facilities
**Key Services:**
- Scheduled preventive maintenance
- Emergency repair coordination
- Parts procurement and inventory management
- Service provider vetting and management
- Maintenance history tracking
- Compliance and documentation management
- Cost estimation and budget planning
- Real-time service status updates
**Value Proposition:**
- Centralized maintenance management
- Vetted and certified service providers
- Transparent pricing and scheduling
- Digital maintenance logs and records
- Predictive maintenance recommendations
- 24/7 emergency support coordination
#### 2. Charter Services Division
**Target Audience:** Charter clients, yacht owners offering vessels for charter, charter brokers
**Key Services:**
- Vessel availability and booking management
- Charter agreement facilitation
- Crew coordination and management
- Itinerary planning and customization
- Provisioning and catering coordination
- Real-time communication with crew
- Payment processing and invoicing
- Charter history and preferences tracking
**Value Proposition:**
- Curated selection of luxury vessels
- Transparent pricing and availability
- Personalized charter experiences
- Simplified booking and payment process
- Comprehensive trip planning tools
- Post-charter feedback and ratings
## Client Portal Architecture
### Current Phase: Unified Web Portal
#### Portal Features
**For Maintenance Clients:**
- Dashboard with vessel overview
- Service request submission
- Work order tracking
- Invoice and payment management
- Document repository
- Service history timeline
- Communication center
- Vendor ratings and reviews
**For Charter Clients:**
- Vessel search and filtering
- Availability calendar
- Booking management
- Trip planning tools
- Communication with crew/captain
- Payment and contract management
- Personal preferences profile
- Charter history and favorites
**For Service Providers:**
- Job assignment dashboard
- Work order management
- Time and materials tracking
- Invoice generation
- Client communication tools
- Certification management
- Performance metrics
- Payment tracking
### Future Phase: Dedicated Applications
#### Mobile Applications (iOS & Android)
**Maintenance App Features:**
- Push notifications for service reminders
- Photo/video upload for issue reporting
- GPS-based emergency service locator
- Offline mode for vessel documentation
- QR code scanning for parts/equipment
- Digital signature for work approvals
**Charter App Features:**
- Interactive vessel tours (AR/VR capable)
- Real-time vessel tracking during charter
- In-app messaging with crew
- Digital concierge services
- Weather and navigation updates
- Social sharing capabilities
#### Enhanced Web Applications
- Advanced analytics and reporting
- Multi-vessel fleet management
- Integration with marine industry APIs
- AI-powered maintenance predictions
- Virtual consultation capabilities
- Blockchain-based documentation
## Technical Infrastructure
### Platform Requirements
- Cloud-based architecture (AWS/Azure)
- Microservices design pattern
- RESTful API architecture
- Real-time data synchronization
- Multi-tenant database structure
- Enterprise-grade security
- GDPR/privacy compliance
- Scalable infrastructure
### Integration Capabilities
- Marina management systems
- Marine parts suppliers
- Payment gateways
- Shipping and logistics providers
- Weather and navigation services
- Insurance providers
- Regulatory compliance databases
- Accounting software
## User Journey Flows
### Maintenance Service Flow
1. **Registration/Onboarding**
- Vessel registration and documentation
- Service preferences setup
- Preferred vendor selection
2. **Service Request**
- Issue identification and reporting
- Automated vendor matching
- Quote review and approval
3. **Service Execution**
- Real-time status tracking
- Direct communication with providers
- Progress photo/video updates
4. **Completion**
- Digital work order sign-off
- Invoice review and payment
- Service rating and feedback
### Charter Service Flow
1. **Discovery**
- Browse available vessels
- Filter by preferences and requirements
- View detailed vessel information
2. **Booking**
- Check availability
- Customize itinerary
- Review and sign charter agreement
3. **Pre-Charter**
- Provisioning preferences
- Crew communication
- Final preparations
4. **During Charter**
- Real-time support
- Itinerary adjustments
- Concierge services
5. **Post-Charter**
- Feedback and ratings
- Photo sharing
- Rebooking options
## Revenue Model
### Maintenance Services
- Transaction fees on service bookings (10-15%)
- Premium subscription tiers for vessel owners
- Featured listing fees for service providers
- Data analytics and insights packages
- Emergency service coordination fees
### Charter Services
- Charter booking commissions (15-20%)
- Premium listing fees for yacht owners
- Concierge service fees
- Travel insurance partnerships
- Provisioning markup
## Success Metrics
### Key Performance Indicators (KPIs)
- Monthly Active Users (MAU)
- Service completion rate
- Average transaction value
- Customer satisfaction score (NPS)
- Provider response time
- Platform uptime
- Revenue per user
- User retention rate
### Growth Targets
- Year 1: 500+ vessels, 100+ service providers
- Year 2: 2,000+ vessels, 500+ service providers
- Year 3: 5,000+ vessels, 1,500+ service providers
- Geographic expansion: 5 major yachting hubs by Year 3
## Competitive Advantages
1. **Unified Platform**: Single solution for both maintenance and charter needs
2. **Verified Network**: Pre-vetted service providers and vessels
3. **Transparency**: Clear pricing, real-time updates, and comprehensive documentation
4. **Technology-First**: Modern UI/UX, mobile-first design, AI-powered features
5. **Industry Expertise**: Deep understanding of maritime operations and regulations
6. **Scalability**: Platform designed to grow from regional to global operations
## Implementation Roadmap
### Phase 1: Foundation (Months 1-6)
- Core platform development
- Basic client portal launch
- Initial service provider onboarding
- Beta testing with select clients
### Phase 2: Expansion (Months 7-12)
- Full portal feature deployment
- Payment system integration
- Marketing campaign launch
- Geographic expansion to 2 regions
### Phase 3: Mobile Development (Months 13-18)
- iOS application development and launch
- Android application development and launch
- API expansion for third-party integrations
- Advanced analytics implementation
### Phase 4: Scale and Optimize (Months 19-24)
- AI/ML feature integration
- International expansion
- Enterprise features for fleet management
- Strategic partnership development
## Risk Management
### Identified Risks and Mitigation Strategies
- **Technology Risk**: Maintain redundant systems and regular backups
- **Market Risk**: Continuous market research and agile development
- **Regulatory Risk**: Legal compliance team and regular audits
- **Competition Risk**: Focus on unique value propositions and user experience
- **Operational Risk**: Robust vetting process for service providers
## Conclusion
HarborSmith represents a transformative approach to yacht services management, combining cutting-edge technology with deep industry expertise. By focusing on both maintenance and charter services through an integrated platform, HarborSmith is positioned to become the definitive solution for yacht owners and charter clients worldwide.
The evolution from a unified web portal to dedicated applications ensures that the platform can meet users where they are, providing the right tools and features for each user segment while maintaining a cohesive ecosystem that benefits all stakeholders in the luxury yachting industry.

BIN
website-mockups/Helm.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 MiB

View File

@@ -0,0 +1,212 @@
# HarborSmith Website Mockups - Project Status
## 🎯 Project Overview
A modern, responsive website for HarborSmith Yacht Services featuring:
- Custom yacht chartering services
- Yacht maintenance services
- Theme switcher with 4 color schemes
- Fully connected click-through demo
- Google Inter font throughout
- Modern animations and interactions
## ✅ Completed Components
### 1. **Homepage (index.html)** ✓
- Hero section with gradient background and wave animation
- Dual service cards (Charter & Maintenance)
- Fleet showcase with 3 yachts (Bay Dreamer, Golden Gate Spirit, Pacific Explorer)
- Animated statistics section
- Testimonial slider (3 testimonials)
- Call-to-action section
- Full footer with contact info and links
### 2. **Navigation System** ✓
- Sticky header with scroll effects
- Dropdown mega menu for services
- Mobile responsive hamburger menu
- Theme switcher with 4 color schemes
- Active page highlighting
### 3. **Theme System** ✓
Four complete color themes:
- **Classic Nautical** (Navy blue + Red)
- **Sunset Bay** (Dark blue + Yellow)
- **Ocean Breeze** (Teal + Coral)
- **Harbor Lights** (Slate + Amber)
### 4. **Charter Service Page (charter.html)** ✓
- Service hero section
- Detailed fleet information (3 yachts)
- Pricing packages (Half Day, Full Day, Sunset Special)
- Popular routes section (4 routes)
- Individual yacht details with features
### 5. **Charter Booking Flow - Step 1 (charter-booking-1.html)** ✓
- 4-step progress indicator
- Calendar date picker
- Time selection dropdown
- Duration options (2, 3, 4, 8 hours)
- Guest number input
- Booking summary sidebar
- Help section with phone contact
### 6. **CSS Architecture** ✓
- **styles.css** - Main styles, components, layout
- **themes.css** - Color scheme definitions
- **animations.css** - Keyframes and animation utilities
- **booking.css** - Booking flow specific styles
### 7. **JavaScript Functionality** ✓
- **main.js** - Theme switcher, navigation, testimonials, counters
- **animations.js** - Scroll animations, parallax, page transitions
- **booking.js** - Calendar, form validation, selection handlers
## 🚧 Pages That Need to Be Created
### Charter Booking Flow (Remaining)
1. **charter-booking-2.html** - Yacht Selection
- Display 3 yacht options with availability
- Selection interface
- Price calculation based on duration
2. **charter-booking-3.html** - Customize Experience
- Add-on services (catering, water sports, etc.)
- Special requests
- Route selection
3. **charter-booking-4.html** - Contact & Confirmation
- Contact form
- Payment options
- Terms acceptance
- Final summary
### Maintenance Section
4. **maintenance.html** - Maintenance Services Main
- Service categories
- Pricing structure
- Service area coverage
- Booking CTA
5. **maintenance-booking-1.html** - Service Selection
- Service type checkboxes
- Problem description
6. **maintenance-booking-2.html** - Boat Details
- Boat information form
- Location details
- Photo upload
7. **maintenance-booking-3.html** - Schedule & Confirm
- Calendar for scheduling
- Contact information
- Quote request
### Additional Pages
8. **about.html** - About Page
- Company history
- Team/crew profiles
- Certifications
- Marina location
9. **faq.html** - FAQ Page
- Tabbed sections (Charter/Maintenance)
- Searchable accordion
- Common questions
10. **contact.html** - Contact Page
- Dual contact forms
- Location map
- Business hours
- Emergency contacts
## 🔗 Current Link Structure
### Working Links:
- Homepage → Charter Service Page ✓
- Homepage → Charter Booking Step 1 ✓
- Charter Page → Charter Booking Step 1 ✓
- Navigation between Home and Charter ✓
### Broken Links (pages not yet created):
- Homepage → Maintenance Services
- Homepage → About
- Homepage → FAQ
- Homepage → Contact
- Charter Booking Step 1 → Step 2
- All maintenance-related links
- Footer links to non-existent pages
## 🎨 Design Features Implemented
### Animations:
- Fade-in animations on scroll
- Counter animations for statistics
- Testimonial auto-rotation
- Button hover effects with transforms
- Wave animation in hero
- Floating yacht icons
### Interactive Elements:
- Theme switcher with localStorage persistence
- Calendar date picker
- Duration selection cards
- Dropdown menus
- Mobile navigation toggle
### Responsive Design:
- Mobile: 320px - 768px ✓
- Tablet: 769px - 1024px ✓
- Desktop: 1025px - 1440px ✓
- Wide: 1441px+ ✓
## 📋 To Complete the Click-Through Demo
### Priority 1 (Essential for Demo):
1. Create remaining charter booking pages (2, 3, 4)
2. Create maintenance.html main page
3. Create at least one maintenance booking page
4. Create contact.html
### Priority 2 (Nice to Have):
5. Complete all maintenance booking flow
6. Create about.html
7. Create faq.html
### Priority 3 (Polish):
8. Add form submission handling
9. Add loading states
10. Add success/error messages
11. Add 404 page
## 🐛 Known Issues
1. Some links point to non-existent pages
2. Form submissions don't actually submit anywhere
3. Calendar functionality is visual only
4. Mobile menu might overlap on very small screens
## 💡 Recommendations for Completion
1. Focus on completing the charter booking flow first (most important user journey)
2. Create a simplified maintenance page with basic booking
3. Add contact page for credibility
4. Test all navigation paths
5. Ensure theme switcher works on all pages
## 📊 Project Statistics
- **Total Files Created**: 10
- **HTML Pages**: 3 of ~14 needed
- **CSS Files**: 4 (complete)
- **JS Files**: 3 (complete)
- **Color Themes**: 4 (complete)
- **Responsive Breakpoints**: 4 (complete)
## 🚀 Next Steps
1. Complete charter booking flow (3 pages)
2. Create maintenance service page
3. Create contact page
4. Test complete user journey
5. Fix any broken links
---
*Last Updated: Current Session*
*Status: ~30% Complete for full demo*

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

BIN
website-mockups/QRCode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

BIN
website-mockups/Waxing.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

914
website-mockups/about.html Normal file
View File

@@ -0,0 +1,914 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About HarborSmith - Our Story</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="css/voyage-layout.css">
<link rel="stylesheet" href="css/themes.css">
<style>
.about-hero {
position: relative;
min-height: 70vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%);
}
.about-hero::before {
content: '';
position: absolute;
inset: 0;
background-image: url('golden_gate.jpg');
background-size: cover;
background-position: center;
opacity: 0.4;
}
.about-hero-content {
position: relative;
z-index: 1;
text-align: center;
padding: 2rem;
max-width: 900px;
}
.about-hero h1 {
font-family: 'Playfair Display', serif;
font-size: 4rem;
font-weight: 900;
color: white;
margin-bottom: 1rem;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.about-hero p {
font-size: 1.5rem;
color: rgba(255, 255, 255, 0.95);
font-weight: 300;
line-height: 1.6;
}
.story-section {
padding: 5rem 0;
background: var(--bg-primary);
}
.story-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
margin-bottom: 4rem;
}
.story-content.reverse {
direction: rtl;
}
.story-content.reverse .story-text {
direction: ltr;
}
.story-text h2 {
font-family: 'Playfair Display', serif;
font-size: 2.5rem;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 1rem;
}
.story-text h3 {
font-size: 1.125rem;
color: var(--accent-primary);
font-weight: 600;
margin-bottom: 1rem;
}
.story-text p {
color: var(--text-secondary);
line-height: 1.8;
margin-bottom: 1.5rem;
}
.story-image {
position: relative;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
}
.story-image img {
width: 100%;
height: auto;
display: block;
}
.story-image-caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
color: white;
padding: 1.5rem;
font-size: 0.875rem;
}
.values-section {
background: linear-gradient(135deg, rgba(30, 58, 95, 0.05) 0%, rgba(30, 58, 95, 0.02) 100%);
padding: 5rem 0;
}
.values-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-top: 3rem;
}
.value-card {
background: var(--card-bg);
border-radius: 12px;
padding: 2rem;
text-align: center;
transition: all 0.3s ease;
}
.value-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.value-icon {
width: 80px;
height: 80px;
margin: 0 auto 1.5rem;
background: linear-gradient(135deg, var(--accent-primary) 0%, var(--accent-dark) 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.value-icon svg {
width: 40px;
height: 40px;
}
.value-title {
font-size: 1.5rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 1rem;
}
.value-description {
color: var(--text-secondary);
line-height: 1.6;
}
.team-section {
padding: 5rem 0;
}
.team-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
margin-top: 3rem;
}
.team-member {
background: var(--card-bg);
border-radius: 12px;
overflow: hidden;
transition: all 0.3s ease;
}
.team-member:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.team-member-image {
height: 300px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 4rem;
font-weight: 700;
}
.team-member-info {
padding: 1.5rem;
}
.team-member-name {
font-size: 1.25rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.25rem;
}
.team-member-role {
color: var(--accent-primary);
font-weight: 500;
margin-bottom: 1rem;
}
.team-member-bio {
color: var(--text-secondary);
font-size: 0.875rem;
line-height: 1.6;
margin-bottom: 1rem;
}
.team-member-credentials {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.credential-badge {
padding: 0.25rem 0.75rem;
background: rgba(30, 58, 95, 0.1);
border-radius: 20px;
font-size: 0.75rem;
color: var(--text-secondary);
}
.milestones-section {
background: var(--card-bg);
padding: 5rem 0;
}
.timeline {
position: relative;
max-width: 1000px;
margin: 3rem auto;
}
.timeline::before {
content: '';
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 2px;
height: 100%;
background: var(--accent-primary);
opacity: 0.3;
}
.timeline-item {
display: flex;
align-items: center;
margin-bottom: 3rem;
position: relative;
}
.timeline-item:nth-child(even) {
flex-direction: row-reverse;
}
.timeline-content {
flex: 1;
padding: 1.5rem;
background: var(--bg-primary);
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
}
.timeline-item:nth-child(odd) .timeline-content {
margin-right: 2rem;
text-align: right;
}
.timeline-item:nth-child(even) .timeline-content {
margin-left: 2rem;
}
.timeline-dot {
width: 20px;
height: 20px;
background: var(--accent-primary);
border-radius: 50%;
position: absolute;
left: 50%;
transform: translateX(-50%);
border: 4px solid var(--card-bg);
}
.timeline-year {
font-size: 1.5rem;
font-weight: 700;
color: var(--accent-primary);
margin-bottom: 0.5rem;
}
.timeline-title {
font-size: 1.125rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.5rem;
}
.timeline-description {
color: var(--text-secondary);
font-size: 0.875rem;
line-height: 1.6;
}
.certifications-section {
padding: 5rem 0;
text-align: center;
}
.cert-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 2rem;
margin-top: 3rem;
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
.cert-item {
background: var(--card-bg);
border-radius: 12px;
padding: 2rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 150px;
transition: all 0.3s ease;
}
.cert-item:hover {
transform: scale(1.05);
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.cert-logo {
font-size: 1.5rem;
font-weight: 700;
color: var(--accent-primary);
margin-bottom: 0.5rem;
}
.cert-name {
font-size: 0.875rem;
color: var(--text-secondary);
}
.location-section {
background: linear-gradient(135deg, var(--accent-primary) 0%, var(--accent-dark) 100%);
padding: 5rem 0;
color: white;
}
.location-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
}
.location-info h2 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 1rem;
}
.location-info p {
font-size: 1.125rem;
line-height: 1.8;
margin-bottom: 2rem;
opacity: 0.95;
}
.location-details {
display: grid;
gap: 1rem;
}
.location-item {
display: flex;
align-items: center;
gap: 1rem;
}
.location-item svg {
width: 24px;
height: 24px;
opacity: 0.9;
}
.map-container {
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
height: 400px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
opacity: 0.9;
}
@media (max-width: 768px) {
.about-hero h1 {
font-size: 2.5rem;
}
.story-content,
.story-content.reverse {
grid-template-columns: 1fr;
direction: ltr;
}
.timeline::before {
left: 20px;
}
.timeline-item,
.timeline-item:nth-child(even) {
flex-direction: row;
}
.timeline-item:nth-child(odd) .timeline-content,
.timeline-item:nth-child(even) .timeline-content {
margin-left: 3rem;
margin-right: 0;
text-align: left;
}
.timeline-dot {
left: 20px;
}
.location-content {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="voyage-nav visible" id="voyageNav">
<div class="nav-container">
<div class="nav-brand">
<img src="logo.jpg" alt="HarborSmith" class="nav-logo">
<span>HarborSmith</span>
</div>
<div class="nav-links">
<a href="index.html" class="nav-link">Home</a>
<a href="charter.html" class="nav-link">Charters</a>
<a href="maintenance.html" class="nav-link">Maintenance</a>
<a href="about.html" class="nav-link active">About</a>
<a href="contact.html" class="nav-link">Contact</a>
</div>
</div>
</nav>
<!-- Hero Section -->
<section class="about-hero">
<div class="about-hero-content">
<h1>Our Story</h1>
<p>Three generations of maritime excellence, serving the San Francisco Bay since 2009</p>
</div>
</section>
<!-- Story Section -->
<section class="story-section">
<div class="container">
<div class="story-content">
<div class="story-text">
<h3>Est. 2009</h3>
<h2>Born from Passion</h2>
<p>
HarborSmith began as a dream shared by Captain James Harbor and master technician Sarah Smith.
Both maritime enthusiasts with decades of combined experience, they saw an opportunity to create
something special in San Francisco Bay.
</p>
<p>
What started as a single boat and a small workshop has grown into the Bay Area's most trusted
name in yacht services. Our commitment to excellence, safety, and unforgettable experiences has
remained unchanged since day one.
</p>
<p>
Today, we're proud to be a family-owned business that treats every customer like family,
every yacht like our own, and every voyage like an adventure worth remembering.
</p>
</div>
<div class="story-image">
<img src="golden_gate.jpg" alt="Our journey">
<div class="story-image-caption">
Our flagship yacht passing under the Golden Gate Bridge
</div>
</div>
</div>
<div class="story-content reverse">
<div class="story-text">
<h3>The HarborSmith Difference</h3>
<h2>More Than a Service</h2>
<p>
We believe that yachting is about more than just boats it's about freedom, adventure, and
creating memories that last a lifetime. That's why we go beyond simply providing services.
</p>
<p>
Our charter captains are storytellers who know every hidden cove and spectacular view. Our
maintenance technicians are craftsmen who treat every vessel with the care it deserves. And our
entire team shares a genuine passion for helping you experience the magic of life on the water.
</p>
<p>
Whether you're celebrating a special occasion, maintaining your prized vessel, or simply escaping
the everyday, we're here to make it extraordinary.
</p>
</div>
<div class="story-image">
<img src="yacht_party_couple_holding_hands.jpg" alt="Happy customers">
<div class="story-image-caption">
Creating unforgettable moments for our clients
</div>
</div>
</div>
</div>
</section>
<!-- Values Section -->
<section class="values-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Our Core Values</h2>
<p class="section-subtitle">The principles that guide everything we do</p>
</div>
<div class="values-grid">
<div class="value-card">
<div class="value-icon">
<i data-lucide="shield"></i>
</div>
<h3 class="value-title">Safety First</h3>
<p class="value-description">
Your safety is our top priority. Every vessel is meticulously maintained, every crew member
is fully certified, and every journey follows the highest safety standards.
</p>
</div>
<div class="value-card">
<div class="value-icon">
<i data-lucide="star"></i>
</div>
<h3 class="value-title">Excellence</h3>
<p class="value-description">
We don't just meet expectations we exceed them. From our premium fleet to our expert
technicians, we deliver nothing but the best.
</p>
</div>
<div class="value-card">
<div class="value-icon">
<i data-lucide="heart"></i>
</div>
<h3 class="value-title">Passion</h3>
<p class="value-description">
We love what we do, and it shows. Our enthusiasm for maritime life is contagious, making
every interaction a pleasure.
</p>
</div>
<div class="value-card">
<div class="value-icon">
<i data-lucide="users"></i>
</div>
<h3 class="value-title">Family</h3>
<p class="value-description">
As a family business, we treat our customers, employees, and community like family. Your
trust is our most valuable asset.
</p>
</div>
</div>
</div>
</section>
<!-- Team Section -->
<section class="team-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Meet Our Crew</h2>
<p class="section-subtitle">The experienced professionals behind your perfect day on the water</p>
</div>
<div class="team-grid">
<div class="team-member">
<div class="team-member-image">JH</div>
<div class="team-member-info">
<h3 class="team-member-name">Captain James Harbor</h3>
<p class="team-member-role">Founder & Head Captain</p>
<p class="team-member-bio">
With over 30 years of sailing experience and a Coast Guard Master's license, James has
navigated waters around the world before making San Francisco Bay his home.
</p>
<div class="team-member-credentials">
<span class="credential-badge">USCG Licensed</span>
<span class="credential-badge">30+ Years Experience</span>
<span class="credential-badge">CPR Certified</span>
</div>
</div>
</div>
<div class="team-member">
<div class="team-member-image">SS</div>
<div class="team-member-info">
<h3 class="team-member-name">Sarah Smith</h3>
<p class="team-member-role">Co-Founder & Service Director</p>
<p class="team-member-bio">
A master technician with certifications from all major marine manufacturers, Sarah ensures
every yacht in our care receives the best possible service.
</p>
<div class="team-member-credentials">
<span class="credential-badge">ABYC Certified</span>
<span class="credential-badge">Mercury Master Tech</span>
<span class="credential-badge">Volvo Specialist</span>
</div>
</div>
</div>
<div class="team-member">
<div class="team-member-image">MH</div>
<div class="team-member-info">
<h3 class="team-member-name">Michael Harbor</h3>
<p class="team-member-role">Charter Captain</p>
<p class="team-member-bio">
Following in his father's footsteps, Michael brings youthful energy and extensive local
knowledge to every charter, ensuring guests have an unforgettable experience.
</p>
<div class="team-member-credentials">
<span class="credential-badge">USCG Licensed</span>
<span class="credential-badge">10+ Years Experience</span>
<span class="credential-badge">Dive Master</span>
</div>
</div>
</div>
<div class="team-member">
<div class="team-member-image">RT</div>
<div class="team-member-info">
<h3 class="team-member-name">Roberto Torres</h3>
<p class="team-member-role">Lead Technician</p>
<p class="team-member-bio">
Roberto's expertise in marine electronics and engine systems makes him invaluable. His
attention to detail ensures every yacht runs perfectly.
</p>
<div class="team-member-credentials">
<span class="credential-badge">NMEA Certified</span>
<span class="credential-badge">Yamaha Specialist</span>
<span class="credential-badge">15+ Years Experience</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Milestones Section -->
<section class="milestones-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Our Journey</h2>
<p class="section-subtitle">Milestones that shaped who we are today</p>
</div>
<div class="timeline">
<div class="timeline-item">
<div class="timeline-content">
<div class="timeline-year">2009</div>
<div class="timeline-title">HarborSmith Founded</div>
<div class="timeline-description">
James and Sarah start HarborSmith with one boat and a dream
</div>
</div>
<div class="timeline-dot"></div>
</div>
<div class="timeline-item">
<div class="timeline-content">
<div class="timeline-year">2012</div>
<div class="timeline-title">Fleet Expansion</div>
<div class="timeline-description">
Added two more yachts and opened our maintenance facility
</div>
</div>
<div class="timeline-dot"></div>
</div>
<div class="timeline-item">
<div class="timeline-content">
<div class="timeline-year">2015</div>
<div class="timeline-title">100th Charter</div>
<div class="timeline-description">
Celebrated our 100th successful charter with a community event
</div>
</div>
<div class="timeline-dot"></div>
</div>
<div class="timeline-item">
<div class="timeline-content">
<div class="timeline-year">2018</div>
<div class="timeline-title">Award Recognition</div>
<div class="timeline-description">
Named "Best Yacht Services" by Bay Area Boating Magazine
</div>
</div>
<div class="timeline-dot"></div>
</div>
<div class="timeline-item">
<div class="timeline-content">
<div class="timeline-year">2020</div>
<div class="timeline-title">Community Support</div>
<div class="timeline-description">
Provided free maintenance to first responders during pandemic
</div>
</div>
<div class="timeline-dot"></div>
</div>
<div class="timeline-item">
<div class="timeline-content">
<div class="timeline-year">2024</div>
<div class="timeline-title">15 Years Strong</div>
<div class="timeline-description">
Celebrating 15 years of service with our biggest fleet yet
</div>
</div>
<div class="timeline-dot"></div>
</div>
</div>
</div>
</section>
<!-- Certifications Section -->
<section class="certifications-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Certified Excellence</h2>
<p class="section-subtitle">Recognized by leading maritime organizations</p>
</div>
<div class="cert-grid">
<div class="cert-item">
<div class="cert-logo">USCG</div>
<div class="cert-name">US Coast Guard</div>
</div>
<div class="cert-item">
<div class="cert-logo">ABYC</div>
<div class="cert-name">American Boat & Yacht Council</div>
</div>
<div class="cert-item">
<div class="cert-logo">NMEA</div>
<div class="cert-name">National Marine Electronics</div>
</div>
<div class="cert-item">
<div class="cert-logo">BBB</div>
<div class="cert-name">Better Business Bureau</div>
</div>
</div>
</div>
</section>
<!-- Location Section -->
<section class="location-section">
<div class="container">
<div class="location-content">
<div class="location-info">
<h2>Find Us at Pier 39</h2>
<p>
Located at the heart of San Francisco's waterfront, our marina offers easy access, ample parking,
and stunning views. We're just minutes from downtown and perfectly positioned for Bay adventures.
</p>
<div class="location-details">
<div class="location-item">
<i data-lucide="map-pin"></i>
<span>Pier 39, Dock J, San Francisco, CA 94133</span>
</div>
<div class="location-item">
<i data-lucide="clock"></i>
<span>Open 7 days a week, 8:00 AM - 8:00 PM</span>
</div>
<div class="location-item">
<i data-lucide="car"></i>
<span>Free parking for charter guests</span>
</div>
<div class="location-item">
<i data-lucide="train"></i>
<span>BART and Muni accessible</span>
</div>
</div>
</div>
<div class="map-container">
<i data-lucide="map" style="width: 60px; height: 60px;"></i>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="booking-cta">
<div class="booking-container">
<div class="booking-content">
<h2 class="booking-title">Ready to Experience the HarborSmith Difference?</h2>
<p class="booking-subtitle">
Join our family of satisfied customers and discover why we're the Bay Area's premier yacht service
</p>
<div class="booking-options">
<div class="booking-card">
<span class="booking-icon">
<i data-lucide="sailboat"></i>
</span>
<h3>Book a Charter</h3>
<p>Start your adventure today</p>
<button class="btn-booking" onclick="window.location.href='charter.html'">
Explore Charters
</button>
</div>
<div class="booking-card featured">
<span class="booking-icon">
<i data-lucide="phone"></i>
</span>
<h3>Call Us</h3>
<p>Speak with our friendly team</p>
<button class="btn-booking primary" onclick="window.location.href='tel:4155550123'">
(415) 555-0123
</button>
</div>
<div class="booking-card">
<span class="booking-icon">
<i data-lucide="wrench"></i>
</span>
<h3>Schedule Service</h3>
<p>Keep your yacht pristine</p>
<button class="btn-booking" onclick="window.location.href='maintenance.html'">
View Services
</button>
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="voyage-footer">
<div class="footer-container">
<div class="footer-content">
<div class="footer-brand">
<img src="logo.jpg" alt="HarborSmith" class="footer-logo">
<h3>HarborSmith</h3>
<p>Your trusted partner for Bay Area yacht services since 2009</p>
</div>
<div class="footer-links">
<h4>Quick Links</h4>
<a href="index.html">Home</a>
<a href="charter.html">Charters</a>
<a href="maintenance.html">Maintenance</a>
<a href="about.html">About</a>
<a href="contact.html">Contact</a>
</div>
<div class="footer-contact">
<h4>Get in Touch</h4>
<p><i data-lucide="map-pin" class="footer-icon"></i> Pier 39, San Francisco, CA</p>
<p><i data-lucide="phone" class="footer-icon"></i> (415) 555-0123</p>
<p><i data-lucide="mail" class="footer-icon"></i> hello@harborsmith.com</p>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2024 HarborSmith Yacht Services. All rights reserved.</p>
</div>
</div>
</footer>
<script>
// Initialize Lucide icons
lucide.createIcons();
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1358
website-mockups/charter.html Normal file

File diff suppressed because it is too large Load Diff

1012
website-mockups/contact.html Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,435 @@
/* HarborSmith - Animation Styles */
/* ========================= */
/* Fade Animations */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInLeft {
from {
opacity: 0;
transform: translateX(-30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes fadeInRight {
from {
opacity: 0;
transform: translateX(30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
/* Scale Animations */
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
/* Rotate Animations */
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Slide Animations */
@keyframes slideInLeft {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
@keyframes slideInRight {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
@keyframes slideInUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
@keyframes slideInDown {
from {
transform: translateY(-100%);
}
to {
transform: translateY(0);
}
}
/* Special Effects */
@keyframes shimmer {
0% {
background-position: -1000px 0;
}
100% {
background-position: 1000px 0;
}
}
@keyframes ripple {
0% {
transform: scale(0);
opacity: 1;
}
100% {
transform: scale(4);
opacity: 0;
}
}
@keyframes wave {
0%, 100% {
transform: translateX(0);
}
25% {
transform: translateX(-25px);
}
75% {
transform: translateX(25px);
}
}
@keyframes float {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-20px);
}
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
/* Loading Animation */
@keyframes loading {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid var(--border);
border-top-color: var(--primary);
border-radius: 50%;
animation: loading 1s linear infinite;
}
/* Utility Classes */
.animate-fade-in {
animation: fadeIn 0.5s ease-out;
}
.animate-fade-up {
animation: fadeInUp 0.6s ease-out;
}
.animate-fade-up-delay {
animation: fadeInUp 0.6s ease-out 0.2s both;
}
.animate-fade-up-delay-2 {
animation: fadeInUp 0.6s ease-out 0.4s both;
}
.animate-scale-in {
animation: scaleIn 0.5s ease-out;
}
.animate-pulse {
animation: pulse 2s ease-in-out infinite;
}
.animate-float {
animation: float 3s ease-in-out infinite;
}
.animate-bounce {
animation: bounce 2s ease-in-out infinite;
}
/* Scroll Animations */
.scroll-animate {
opacity: 0;
transform: translateY(30px);
transition: all 0.6s ease-out;
}
.scroll-animate.visible {
opacity: 1;
transform: translateY(0);
}
.scroll-animate-left {
opacity: 0;
transform: translateX(-30px);
transition: all 0.6s ease-out;
}
.scroll-animate-left.visible {
opacity: 1;
transform: translateX(0);
}
.scroll-animate-right {
opacity: 0;
transform: translateX(30px);
transition: all 0.6s ease-out;
}
.scroll-animate-right.visible {
opacity: 1;
transform: translateX(0);
}
.scroll-animate-scale {
opacity: 0;
transform: scale(0.9);
transition: all 0.6s ease-out;
}
.scroll-animate-scale.visible {
opacity: 1;
transform: scale(1);
}
/* Parallax Effects */
.parallax {
transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.parallax-slow {
transition: transform 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.parallax-fast {
transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* Hover Effects */
.hover-lift {
transition: transform 0.3s ease;
}
.hover-lift:hover {
transform: translateY(-5px);
}
.hover-grow {
transition: transform 0.3s ease;
}
.hover-grow:hover {
transform: scale(1.05);
}
.hover-shrink {
transition: transform 0.3s ease;
}
.hover-shrink:hover {
transform: scale(0.95);
}
.hover-rotate {
transition: transform 0.3s ease;
}
.hover-rotate:hover {
transform: rotate(5deg);
}
/* Text Effects */
.text-gradient-animate {
background: linear-gradient(
90deg,
var(--primary) 0%,
var(--accent) 25%,
var(--primary) 50%,
var(--accent) 75%,
var(--primary) 100%
);
background-size: 200% auto;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
animation: shimmer 3s linear infinite;
}
/* Page Transitions */
.page-transition-fade {
animation: fadeIn 0.5s ease-out;
}
.page-transition-slide-up {
animation: slideInUp 0.5s ease-out;
}
.page-transition-slide-left {
animation: slideInLeft 0.5s ease-out;
}
/* Stagger Animations */
.stagger-animate > * {
opacity: 0;
transform: translateY(20px);
animation: fadeInUp 0.5s ease-out forwards;
}
.stagger-animate > *:nth-child(1) { animation-delay: 0.1s; }
.stagger-animate > *:nth-child(2) { animation-delay: 0.2s; }
.stagger-animate > *:nth-child(3) { animation-delay: 0.3s; }
.stagger-animate > *:nth-child(4) { animation-delay: 0.4s; }
.stagger-animate > *:nth-child(5) { animation-delay: 0.5s; }
.stagger-animate > *:nth-child(6) { animation-delay: 0.6s; }
/* Skeleton Loading */
.skeleton {
background: linear-gradient(
90deg,
var(--surface) 25%,
var(--border) 50%,
var(--surface) 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
/* Progress Bar Animation */
.progress-bar-fill {
animation: fillProgress 2s ease-out forwards;
}
@keyframes fillProgress {
from {
width: 0%;
}
to {
width: var(--progress, 100%);
}
}
/* Counter Animation */
.counter-animate {
animation: countUp 2s ease-out;
}
@keyframes countUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Water Wave Effect */
@keyframes waterWave {
0% {
transform: translateX(0) translateZ(0) scaleY(1);
}
50% {
transform: translateX(-25%) translateZ(0) scaleY(0.8);
}
100% {
transform: translateX(-50%) translateZ(0) scaleY(1);
}
}
.water-wave {
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 120' preserveAspectRatio='none'%3E%3Cpath d='M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z' fill='%23ffffff' fill-opacity='0.3'%3E%3C/path%3E%3C/svg%3E");
background-size: 200% 100%;
animation: waterWave 10s linear infinite;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,586 @@
/* HarborSmith - Booking Styles */
/* ============================= */
/* Progress Bar */
.booking-progress {
padding: 100px 0 40px;
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.progress-steps {
display: flex;
align-items: center;
justify-content: center;
max-width: 600px;
margin: 0 auto;
}
.progress-step {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
.step-number {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--background);
border: 2px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
color: var(--text-secondary);
transition: all var(--transition-base);
}
.progress-step.active .step-number {
background: var(--primary);
color: white;
border-color: var(--primary);
}
.progress-step.completed .step-number {
background: var(--accent);
color: white;
border-color: var(--accent);
}
.step-label {
margin-top: 8px;
font-size: var(--text-sm);
color: var(--text-secondary);
white-space: nowrap;
}
.progress-step.active .step-label {
color: var(--primary);
font-weight: 600;
}
.progress-line {
width: 80px;
height: 2px;
background: var(--border);
margin: 0 10px;
position: relative;
top: -20px;
}
.progress-step.completed + .progress-line {
background: var(--accent);
}
/* Booking Section */
.booking-section {
padding: 60px 0;
min-height: calc(100vh - 200px);
}
.booking-header {
text-align: center;
margin-bottom: 40px;
}
.booking-header h1 {
font-size: var(--text-4xl);
margin-bottom: 10px;
}
.booking-header p {
color: var(--text-secondary);
font-size: var(--text-lg);
}
.booking-content {
display: grid;
grid-template-columns: 1fr 350px;
gap: 40px;
}
.booking-main {
display: flex;
flex-direction: column;
gap: 30px;
}
.booking-card {
background: var(--background);
border: 1px solid var(--border);
border-radius: var(--radius-xl);
padding: 30px;
box-shadow: var(--shadow-sm);
}
.booking-card h3 {
font-size: var(--text-xl);
margin-bottom: 20px;
}
/* Calendar */
.calendar-container {
background: var(--surface);
border-radius: var(--radius-lg);
padding: 20px;
}
.calendar-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.calendar-nav {
width: 32px;
height: 32px;
border-radius: var(--radius-md);
border: 1px solid var(--border);
background: var(--background);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
transition: all var(--transition-fast);
}
.calendar-nav:hover {
background: var(--primary);
color: white;
border-color: var(--primary);
}
.calendar-month {
font-size: var(--text-lg);
font-weight: 600;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
}
.calendar-day-header {
text-align: center;
font-size: var(--text-sm);
font-weight: 600;
color: var(--text-secondary);
padding: 10px 0;
}
.calendar-day {
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-md);
cursor: pointer;
font-weight: 500;
transition: all var(--transition-fast);
}
.calendar-day.other-month {
color: var(--text-secondary);
opacity: 0.3;
}
.calendar-day.available {
background: var(--background);
color: var(--text);
}
.calendar-day.available:hover {
background: var(--primary);
color: white;
}
.calendar-day.unavailable {
background: var(--surface);
color: var(--text-secondary);
cursor: not-allowed;
text-decoration: line-through;
}
.calendar-day.selected {
background: var(--primary);
color: white;
}
.calendar-legend {
display: flex;
gap: 20px;
margin-top: 20px;
font-size: var(--text-sm);
}
.legend-dot {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 5px;
}
.legend-dot.available {
background: var(--background);
border: 2px solid var(--primary);
}
.legend-dot.unavailable {
background: var(--text-secondary);
}
.legend-dot.selected {
background: var(--primary);
}
/* Form Elements */
.form-group {
margin-bottom: 25px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: var(--text);
}
.form-control {
width: 100%;
padding: 12px 15px;
border: 1px solid var(--border);
border-radius: var(--radius-md);
font-size: var(--text-base);
font-family: inherit;
transition: all var(--transition-fast);
background: var(--background);
}
.form-control:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.1);
}
.form-text {
display: block;
margin-top: 5px;
font-size: var(--text-sm);
color: var(--text-secondary);
}
/* Duration Options */
.duration-options {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
}
.duration-option input {
display: none;
}
.duration-card {
display: flex;
flex-direction: column;
padding: 20px;
border: 2px solid var(--border);
border-radius: var(--radius-lg);
cursor: pointer;
transition: all var(--transition-base);
position: relative;
}
.duration-option input:checked + .duration-card {
border-color: var(--primary);
background: var(--surface);
}
.duration-card:hover {
border-color: var(--primary);
transform: translateY(-2px);
}
.duration-time {
font-size: var(--text-lg);
font-weight: 600;
margin-bottom: 5px;
}
.duration-price {
color: var(--primary);
font-size: var(--text-xl);
font-weight: 700;
}
.duration-badge {
position: absolute;
top: 10px;
right: 10px;
padding: 4px 8px;
background: var(--accent);
color: white;
font-size: var(--text-xs);
border-radius: var(--radius-full);
font-weight: 600;
}
/* Booking Sidebar */
.booking-sidebar {
display: flex;
flex-direction: column;
gap: 30px;
}
.booking-summary {
background: var(--surface);
border-radius: var(--radius-xl);
padding: 30px;
position: sticky;
top: 100px;
}
.booking-summary h3 {
font-size: var(--text-xl);
margin-bottom: 20px;
}
.summary-item {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
font-size: var(--text-base);
}
.summary-item span {
color: var(--text-secondary);
}
.summary-item strong {
color: var(--text);
}
.summary-divider {
height: 1px;
background: var(--border);
margin: 20px 0;
}
.summary-total {
font-size: var(--text-lg);
}
.summary-total strong {
color: var(--primary);
font-size: var(--text-2xl);
}
.summary-note {
font-size: var(--text-sm);
color: var(--text-secondary);
font-style: italic;
margin-top: 15px;
}
.booking-help {
background: var(--background);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 20px;
text-align: center;
}
.booking-help h4 {
font-size: var(--text-lg);
margin-bottom: 10px;
}
.booking-help p {
color: var(--text-secondary);
margin-bottom: 15px;
font-size: var(--text-sm);
}
/* Navigation */
.booking-navigation {
display: flex;
justify-content: space-between;
margin-top: 40px;
padding-top: 30px;
border-top: 1px solid var(--border);
}
/* Yacht Selection Grid */
.yacht-selection-grid {
display: grid;
gap: 30px;
}
.yacht-select-card {
display: grid;
grid-template-columns: 300px 1fr;
background: var(--background);
border: 2px solid var(--border);
border-radius: var(--radius-xl);
overflow: hidden;
transition: all var(--transition-base);
cursor: pointer;
}
.yacht-select-card:hover {
border-color: var(--primary);
box-shadow: var(--shadow-lg);
}
.yacht-select-card.selected {
border-color: var(--primary);
background: var(--surface);
}
.yacht-select-image {
height: 200px;
background: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: var(--text-xl);
}
.yacht-select-info {
padding: 30px;
}
.yacht-select-header {
display: flex;
justify-content: space-between;
align-items: start;
margin-bottom: 15px;
}
.yacht-select-name {
font-size: var(--text-2xl);
font-weight: 700;
margin-bottom: 5px;
}
.yacht-select-type {
color: var(--text-secondary);
}
.yacht-select-price {
text-align: right;
}
.yacht-select-specs {
display: flex;
gap: 30px;
margin: 20px 0;
}
.spec-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-secondary);
font-size: var(--text-sm);
}
/* Customization Options */
.customization-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
.addon-card {
border: 2px solid var(--border);
border-radius: var(--radius-lg);
padding: 20px;
transition: all var(--transition-base);
cursor: pointer;
}
.addon-card:hover {
border-color: var(--primary);
}
.addon-card.selected {
border-color: var(--primary);
background: var(--surface);
}
.addon-header {
display: flex;
justify-content: space-between;
align-items: start;
margin-bottom: 10px;
}
.addon-name {
font-weight: 600;
}
.addon-price {
color: var(--primary);
font-weight: 700;
}
.addon-description {
font-size: var(--text-sm);
color: var(--text-secondary);
}
/* Responsive */
@media (max-width: 1024px) {
.booking-content {
grid-template-columns: 1fr;
}
.booking-sidebar {
order: -1;
}
.booking-summary {
position: static;
}
}
@media (max-width: 768px) {
.progress-steps {
overflow-x: auto;
padding: 0 20px;
}
.progress-line {
width: 40px;
}
.step-label {
font-size: var(--text-xs);
}
.duration-options {
grid-template-columns: 1fr;
}
.yacht-select-card {
grid-template-columns: 1fr;
}
.booking-navigation {
flex-direction: column;
gap: 15px;
}
.booking-navigation .btn {
width: 100%;
justify-content: center;
}
}

View File

@@ -0,0 +1,747 @@
/* Enhanced Maintenance Portal Styles */
/* ================================== */
:root {
/* Modern Color Palette */
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
--success-gradient: linear-gradient(135deg, #0ba360 0%, #3cba92 100%);
--warning-gradient: linear-gradient(135deg, #f2994a 0%, #f2c94c 100%);
--danger-gradient: linear-gradient(135deg, #eb3349 0%, #f45c43 100%);
/* Enhanced shadows */
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.06);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);
--shadow-xl: 0 12px 48px rgba(0, 0, 0, 0.16);
--shadow-glow: 0 0 20px rgba(102, 126, 234, 0.4);
/* Spacing */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 1.5rem;
--spacing-xl: 2rem;
--spacing-2xl: 3rem;
/* Border radius */
--radius-sm: 6px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 20px;
--radius-full: 9999px;
/* Transitions */
--transition-fast: 0.15s ease;
--transition-base: 0.3s ease;
--transition-slow: 0.5s ease;
}
/* Global Enhancements */
body {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
}
/* Enhanced Dashboard Cards */
.dashboard-card, .card, .portal-card {
background: white;
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
box-shadow: var(--shadow-md);
border: 1px solid rgba(255, 255, 255, 0.8);
transition: all var(--transition-base);
position: relative;
overflow: hidden;
}
.dashboard-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--primary-gradient);
opacity: 0;
transition: opacity var(--transition-base);
}
.dashboard-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-xl);
}
.dashboard-card:hover::before {
opacity: 1;
}
/* Enhanced Stats Cards */
.stat-card {
background: white;
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
position: relative;
overflow: hidden;
transition: all var(--transition-base);
border: 1px solid #e5e7eb;
}
.stat-card::after {
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 200%;
height: 200%;
background: var(--primary-gradient);
opacity: 0.05;
border-radius: 50%;
transition: all var(--transition-slow);
}
.stat-card:hover::after {
top: -75%;
right: -75%;
opacity: 0.1;
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
border-color: #667eea;
}
.stat-value {
font-size: 2.5rem;
font-weight: 700;
background: var(--primary-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin: var(--spacing-sm) 0;
}
.stat-label {
color: #6b7280;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
font-weight: 600;
}
.stat-change {
display: inline-flex;
align-items: center;
gap: var(--spacing-xs);
padding: var(--spacing-xs) var(--spacing-sm);
border-radius: var(--radius-full);
font-size: 0.875rem;
font-weight: 600;
margin-top: var(--spacing-sm);
}
.stat-change.positive {
background: #dcfce7;
color: #16a34a;
}
.stat-change.negative {
background: #fee2e2;
color: #dc2626;
}
/* Enhanced Tables */
.table-container {
background: white;
border-radius: var(--radius-lg);
overflow: hidden;
box-shadow: var(--shadow-md);
}
table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
}
thead {
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
}
thead th {
padding: var(--spacing-md) var(--spacing-lg);
text-align: left;
font-weight: 600;
color: #374151;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
border-bottom: 2px solid #e5e7eb;
}
tbody tr {
transition: all var(--transition-fast);
border-bottom: 1px solid #f3f4f6;
}
tbody tr:hover {
background: linear-gradient(90deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
}
tbody td {
padding: var(--spacing-md) var(--spacing-lg);
color: #4b5563;
}
/* Enhanced Status Badges */
.status-badge, .badge {
display: inline-flex;
align-items: center;
gap: var(--spacing-xs);
padding: var(--spacing-xs) var(--spacing-sm);
border-radius: var(--radius-full);
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: all var(--transition-fast);
}
.status-badge.active, .badge.success {
background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
color: #065f46;
}
.status-badge.scheduled, .badge.warning {
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
color: #92400e;
}
.status-badge.overdue, .badge.danger {
background: linear-gradient(135deg, #ffeaa7 0%, #fdcb6e 100%);
color: #dc2626;
}
.status-badge.completed, .badge.info {
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
color: #1e40af;
}
/* Enhanced Buttons */
.btn, .portal-btn, button[type="submit"] {
padding: var(--spacing-sm) var(--spacing-lg);
border-radius: var(--radius-md);
font-weight: 600;
transition: all var(--transition-base);
cursor: pointer;
border: none;
display: inline-flex;
align-items: center;
gap: var(--spacing-sm);
position: relative;
overflow: hidden;
}
.btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width var(--transition-base), height var(--transition-base);
}
.btn:hover::before {
width: 300px;
height: 300px;
}
.btn-primary {
background: var(--primary-gradient);
color: white;
box-shadow: 0 4px 6px rgba(102, 126, 234, 0.25);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.35);
}
.btn-secondary {
background: white;
color: #4b5563;
border: 2px solid #e5e7eb;
}
.btn-secondary:hover {
background: #f9fafb;
border-color: #667eea;
color: #667eea;
transform: translateY(-2px);
}
.btn-success {
background: var(--success-gradient);
color: white;
box-shadow: 0 4px 6px rgba(16, 185, 129, 0.25);
}
.btn-danger {
background: var(--danger-gradient);
color: white;
box-shadow: 0 4px 6px rgba(239, 68, 68, 0.25);
}
/* Enhanced Form Elements */
.form-group {
margin-bottom: var(--spacing-lg);
}
.form-label {
display: block;
margin-bottom: var(--spacing-sm);
font-weight: 600;
color: #374151;
font-size: 0.875rem;
letter-spacing: 0.025em;
}
.form-input, .form-select, .form-textarea,
input[type="text"], input[type="email"], input[type="number"],
input[type="date"], input[type="time"], select, textarea {
width: 100%;
padding: var(--spacing-sm) var(--spacing-md);
border: 2px solid #e5e7eb;
border-radius: var(--radius-md);
background: #f9fafb;
transition: all var(--transition-base);
font-family: inherit;
}
.form-input:focus, .form-select:focus, .form-textarea:focus,
input:focus, select:focus, textarea:focus {
outline: none;
border-color: #667eea;
background: white;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
transform: translateY(-1px);
}
/* Enhanced Sidebar */
.portal-sidebar {
background: linear-gradient(180deg, #1f2937 0%, #111827 100%);
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.1);
}
.sidebar-nav-item {
margin: var(--spacing-xs) var(--spacing-md);
border-radius: var(--radius-md);
transition: all var(--transition-base);
}
.sidebar-nav-item a {
display: flex;
align-items: center;
gap: var(--spacing-md);
padding: var(--spacing-sm) var(--spacing-md);
color: #9ca3af;
text-decoration: none;
transition: all var(--transition-base);
position: relative;
}
.sidebar-nav-item a::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 0;
background: var(--primary-gradient);
transition: height var(--transition-base);
border-radius: 0 3px 3px 0;
}
.sidebar-nav-item:hover {
background: rgba(255, 255, 255, 0.05);
}
.sidebar-nav-item:hover a {
color: white;
}
.sidebar-nav-item.active {
background: rgba(102, 126, 234, 0.1);
}
.sidebar-nav-item.active a {
color: white;
}
.sidebar-nav-item.active a::before {
height: 24px;
}
/* Enhanced Header */
.portal-header {
background: white;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
border-bottom: 1px solid #e5e7eb;
}
.header-search {
position: relative;
}
.header-search input {
padding-left: 2.5rem;
background: #f3f4f6;
border: 2px solid transparent;
border-radius: var(--radius-full);
}
.header-search input:focus {
background: white;
border-color: #667eea;
}
.header-search i {
position: absolute;
left: var(--spacing-md);
top: 50%;
transform: translateY(-50%);
color: #9ca3af;
}
/* Enhanced Charts Container */
.chart-container {
background: white;
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
box-shadow: var(--shadow-md);
position: relative;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--spacing-lg);
padding-bottom: var(--spacing-md);
border-bottom: 2px solid #f3f4f6;
}
.chart-title {
font-size: 1.125rem;
font-weight: 700;
color: #1f2937;
}
/* Enhanced Progress Bars */
.progress-bar {
width: 100%;
height: 8px;
background: #e5e7eb;
border-radius: var(--radius-full);
overflow: hidden;
position: relative;
}
.progress-bar-fill {
height: 100%;
background: var(--primary-gradient);
border-radius: var(--radius-full);
transition: width var(--transition-slow);
position: relative;
overflow: hidden;
}
.progress-bar-fill::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.3),
transparent
);
animation: shimmer 2s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
/* Enhanced Notifications */
.notification {
padding: var(--spacing-md);
border-radius: var(--radius-md);
margin-bottom: var(--spacing-md);
display: flex;
align-items: flex-start;
gap: var(--spacing-md);
animation: slideIn var(--transition-base);
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.notification.info {
background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
border-left: 4px solid #3b82f6;
}
.notification.success {
background: linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%);
border-left: 4px solid #22c55e;
}
.notification.warning {
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
border-left: 4px solid #f59e0b;
}
.notification.error {
background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
border-left: 4px solid #ef4444;
}
/* Enhanced Modals */
.modal-overlay {
background: rgba(0, 0, 0, 0.5);
-webkit-backdrop-filter: blur(5px);
backdrop-filter: blur(5px);
}
.modal-content {
background: white;
border-radius: var(--radius-xl);
box-shadow: var(--shadow-xl);
animation: modalSlideIn var(--transition-base);
}
@keyframes modalSlideIn {
from {
opacity: 0;
transform: translateY(-30px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
/* Enhanced Timeline */
.timeline-item {
position: relative;
padding-left: 3rem;
padding-bottom: 2rem;
}
.timeline-item::before {
content: '';
position: absolute;
left: 1rem;
top: 0.5rem;
bottom: -2rem;
width: 2px;
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
}
.timeline-item:last-child::before {
display: none;
}
.timeline-dot {
position: absolute;
left: 0.5rem;
top: 0.5rem;
width: 1rem;
height: 1rem;
background: white;
border: 3px solid #667eea;
border-radius: 50%;
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1);
}
/* Enhanced Tooltips */
.tooltip {
position: relative;
}
.tooltip::after {
content: attr(data-tooltip);
position: absolute;
bottom: 125%;
left: 50%;
transform: translateX(-50%);
padding: var(--spacing-sm) var(--spacing-md);
background: #1f2937;
color: white;
font-size: 0.875rem;
border-radius: var(--radius-md);
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity var(--transition-base);
box-shadow: var(--shadow-lg);
}
.tooltip:hover::after {
opacity: 1;
}
/* Enhanced Loading States */
.skeleton {
background: linear-gradient(
90deg,
#f3f4f6 25%,
#e5e7eb 50%,
#f3f4f6 75%
);
background-size: 200% 100%;
animation: loading 1.5s infinite;
border-radius: var(--radius-md);
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e5e7eb;
border-top-color: #667eea;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* Smooth Scrollbar */
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
background: var(--gray-100);
}
::-webkit-scrollbar-thumb {
background: var(--gray-400);
border-radius: var(--radius-full);
}
::-webkit-scrollbar-thumb:hover {
background: var(--gray-500);
}
/* Focus Visible Enhancement */
:focus-visible {
outline: 2px solid var(--primary-orange);
outline-offset: 2px;
}
/* Selection Color */
::selection {
background: rgba(220, 20, 60, 0.2);
color: var(--gray-900);
}
/* Responsive Adjustments */
@media (max-width: 768px) {
.dashboard-grid {
grid-template-columns: 1fr;
}
.portal-content {
padding: var(--space-md);
}
table {
font-size: var(--text-sm);
}
.table-wrapper {
overflow-x: auto;
}
}
/* Print Styles */
@media print {
.portal-sidebar,
.portal-header,
.btn,
.no-print {
display: none !important;
}
.portal-main {
margin-left: 0 !important;
}
.portal-content {
margin: 0;
padding: 0;
}
.dashboard-card,
.card {
box-shadow: none;
border: 1px solid var(--gray-300);
page-break-inside: avoid;
}
}
/* Accessibility Improvements */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Skip to content link */
.skip-to-content {
position: absolute;
top: -40px;
left: 0;
background: var(--primary-blue);
color: var(--white);
padding: var(--space-sm) var(--space-md);
text-decoration: none;
z-index: 9999;
}
.skip-to-content:focus {
top: 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,160 @@
/* HarborSmith - Theme Styles */
/* ========================= */
/* Classical Nautical Theme (Default) - Navy & Crimson */
[data-theme="nautical"] {
--primary: #001f3f; /* Classic navy blue */
--accent: #dc143c; /* Nautical red/crimson */
--background: #ffffff;
--surface: #f0f4f8;
--text: #0a1628;
--text-secondary: #4a5568;
--border: #cbd5e0;
--overlay: rgba(0, 31, 63, 0.7);
--gradient-start: #001f3f;
--gradient-end: #003366;
}
/* Coastal Dawn Theme - Soft & Serene Luxury */
[data-theme="coastal-dawn"] {
--primary: #A9B4C2; /* Cadet Blue */
--accent: #D4AF37; /* Gilded Gold */
--background: #F8F7F4; /* Alabaster White */
--surface: #FFFFFF;
--text: #333745; /* Charcoal Slate */
--text-secondary: #6B7280;
--border: #E5E7EB;
--overlay: rgba(169, 180, 194, 0.4);
--gradient-start: #A9B4C2;
--gradient-end: #C5D3E0;
}
/* Deep Sea Slate Theme - Modern & Technical */
[data-theme="deep-sea"] {
--primary: #1E2022; /* Gunmetal Grey */
--accent: #00BFFF; /* Deep Sky Blue */
--background: #1E2022; /* Dark background */
--surface: #2A2D30;
--text: #E5E4E2; /* Platinum text */
--text-secondary: #C0C0C0; /* Silver */
--border: #3A3D40;
--overlay: rgba(30, 32, 34, 0.8);
--gradient-start: #1E2022;
--gradient-end: #2A2D30;
}
/* Monaco White Theme - Pristine & Minimalist */
[data-theme="monaco-white"] {
--primary: #2C3E50; /* Midnight Blue */
--accent: #E74C3C; /* Pomegranate Red */
--background: #FFFFFF;
--surface: #F8F9FA;
--text: #2C3E50;
--text-secondary: #7F8C8D;
--border: #ECF0F1;
--overlay: rgba(44, 62, 80, 0.05);
--gradient-start: #FFFFFF;
--gradient-end: #F8F9FA;
}
/* Update hero gradient for all themes */
[data-theme] .hero-background {
background: linear-gradient(135deg, var(--gradient-start) 0%, var(--gradient-end) 100%);
}
/* Ensure good contrast for nav items */
[data-theme] .nav-link {
color: var(--text);
font-weight: 500;
}
[data-theme] .nav-link:hover {
color: var(--accent);
}
/* Theme switcher button styling */
[data-theme] .theme-switcher {
background: var(--surface);
border: 2px solid var(--border);
color: var(--text);
}
[data-theme] .theme-switcher:hover {
background: var(--accent);
color: white;
border-color: var(--accent);
}
/* Better button contrast */
[data-theme] .btn-primary {
background: var(--accent);
color: white;
border: 2px solid var(--accent);
}
[data-theme] .btn-primary:hover {
background: var(--primary);
border-color: var(--primary);
}
/* Schedule Service button - make it filled */
[data-theme] .btn-secondary {
background: var(--primary);
color: white;
border: 2px solid var(--primary);
}
[data-theme] .btn-secondary:hover {
background: var(--accent);
border-color: var(--accent);
color: white;
}
/* Card improvements */
[data-theme] .service-card {
background: var(--surface);
border: 1px solid var(--border);
}
[data-theme] .yacht-card {
background: white;
border: 1px solid var(--border);
}
/* Stats section contrast */
[data-theme] .stats-section {
background: var(--surface);
}
/* Footer styling */
[data-theme] footer {
background: var(--primary);
color: white;
}
[data-theme] footer a {
color: rgba(255, 255, 255, 0.8);
}
[data-theme] footer a:hover {
color: var(--accent);
}
/* Special styling for Classical Nautical theme */
[data-theme="nautical"] .btn-primary {
background: var(--accent);
box-shadow: 0 4px 6px rgba(220, 20, 60, 0.2);
}
[data-theme="nautical"] .btn-secondary {
background: var(--primary);
box-shadow: 0 4px 6px rgba(0, 31, 63, 0.2);
}
[data-theme="nautical"] .service-card {
border-color: var(--primary);
}
[data-theme="nautical"] .yacht-card {
border-top: 3px solid var(--accent);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,435 @@
/* HarborSmith - Animation Styles */
/* ========================= */
/* Fade Animations */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInLeft {
from {
opacity: 0;
transform: translateX(-30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes fadeInRight {
from {
opacity: 0;
transform: translateX(30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
/* Scale Animations */
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
/* Rotate Animations */
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Slide Animations */
@keyframes slideInLeft {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
@keyframes slideInRight {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
@keyframes slideInUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
@keyframes slideInDown {
from {
transform: translateY(-100%);
}
to {
transform: translateY(0);
}
}
/* Special Effects */
@keyframes shimmer {
0% {
background-position: -1000px 0;
}
100% {
background-position: 1000px 0;
}
}
@keyframes ripple {
0% {
transform: scale(0);
opacity: 1;
}
100% {
transform: scale(4);
opacity: 0;
}
}
@keyframes wave {
0%, 100% {
transform: translateX(0);
}
25% {
transform: translateX(-25px);
}
75% {
transform: translateX(25px);
}
}
@keyframes float {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-20px);
}
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
/* Loading Animation */
@keyframes loading {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid var(--border);
border-top-color: var(--primary);
border-radius: 50%;
animation: loading 1s linear infinite;
}
/* Utility Classes */
.animate-fade-in {
animation: fadeIn 0.5s ease-out;
}
.animate-fade-up {
animation: fadeInUp 0.6s ease-out;
}
.animate-fade-up-delay {
animation: fadeInUp 0.6s ease-out 0.2s both;
}
.animate-fade-up-delay-2 {
animation: fadeInUp 0.6s ease-out 0.4s both;
}
.animate-scale-in {
animation: scaleIn 0.5s ease-out;
}
.animate-pulse {
animation: pulse 2s ease-in-out infinite;
}
.animate-float {
animation: float 3s ease-in-out infinite;
}
.animate-bounce {
animation: bounce 2s ease-in-out infinite;
}
/* Scroll Animations */
.scroll-animate {
opacity: 0;
transform: translateY(30px);
transition: all 0.6s ease-out;
}
.scroll-animate.visible {
opacity: 1;
transform: translateY(0);
}
.scroll-animate-left {
opacity: 0;
transform: translateX(-30px);
transition: all 0.6s ease-out;
}
.scroll-animate-left.visible {
opacity: 1;
transform: translateX(0);
}
.scroll-animate-right {
opacity: 0;
transform: translateX(30px);
transition: all 0.6s ease-out;
}
.scroll-animate-right.visible {
opacity: 1;
transform: translateX(0);
}
.scroll-animate-scale {
opacity: 0;
transform: scale(0.9);
transition: all 0.6s ease-out;
}
.scroll-animate-scale.visible {
opacity: 1;
transform: scale(1);
}
/* Parallax Effects */
.parallax {
transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.parallax-slow {
transition: transform 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.parallax-fast {
transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* Hover Effects */
.hover-lift {
transition: transform 0.3s ease;
}
.hover-lift:hover {
transform: translateY(-5px);
}
.hover-grow {
transition: transform 0.3s ease;
}
.hover-grow:hover {
transform: scale(1.05);
}
.hover-shrink {
transition: transform 0.3s ease;
}
.hover-shrink:hover {
transform: scale(0.95);
}
.hover-rotate {
transition: transform 0.3s ease;
}
.hover-rotate:hover {
transform: rotate(5deg);
}
/* Text Effects */
.text-gradient-animate {
background: linear-gradient(
90deg,
var(--primary) 0%,
var(--accent) 25%,
var(--primary) 50%,
var(--accent) 75%,
var(--primary) 100%
);
background-size: 200% auto;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
animation: shimmer 3s linear infinite;
}
/* Page Transitions */
.page-transition-fade {
animation: fadeIn 0.5s ease-out;
}
.page-transition-slide-up {
animation: slideInUp 0.5s ease-out;
}
.page-transition-slide-left {
animation: slideInLeft 0.5s ease-out;
}
/* Stagger Animations */
.stagger-animate > * {
opacity: 0;
transform: translateY(20px);
animation: fadeInUp 0.5s ease-out forwards;
}
.stagger-animate > *:nth-child(1) { animation-delay: 0.1s; }
.stagger-animate > *:nth-child(2) { animation-delay: 0.2s; }
.stagger-animate > *:nth-child(3) { animation-delay: 0.3s; }
.stagger-animate > *:nth-child(4) { animation-delay: 0.4s; }
.stagger-animate > *:nth-child(5) { animation-delay: 0.5s; }
.stagger-animate > *:nth-child(6) { animation-delay: 0.6s; }
/* Skeleton Loading */
.skeleton {
background: linear-gradient(
90deg,
var(--surface) 25%,
var(--border) 50%,
var(--surface) 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
/* Progress Bar Animation */
.progress-bar-fill {
animation: fillProgress 2s ease-out forwards;
}
@keyframes fillProgress {
from {
width: 0%;
}
to {
width: var(--progress, 100%);
}
}
/* Counter Animation */
.counter-animate {
animation: countUp 2s ease-out;
}
@keyframes countUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Water Wave Effect */
@keyframes waterWave {
0% {
transform: translateX(0) translateZ(0) scaleY(1);
}
50% {
transform: translateX(-25%) translateZ(0) scaleY(0.8);
}
100% {
transform: translateX(-50%) translateZ(0) scaleY(1);
}
}
.water-wave {
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 120' preserveAspectRatio='none'%3E%3Cpath d='M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z' fill='%23ffffff' fill-opacity='0.3'%3E%3C/path%3E%3C/svg%3E");
background-size: 200% 100%;
animation: waterWave 10s linear infinite;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,586 @@
/* HarborSmith - Booking Styles */
/* ============================= */
/* Progress Bar */
.booking-progress {
padding: 100px 0 40px;
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.progress-steps {
display: flex;
align-items: center;
justify-content: center;
max-width: 600px;
margin: 0 auto;
}
.progress-step {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
.step-number {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--background);
border: 2px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
color: var(--text-secondary);
transition: all var(--transition-base);
}
.progress-step.active .step-number {
background: var(--primary);
color: white;
border-color: var(--primary);
}
.progress-step.completed .step-number {
background: var(--accent);
color: white;
border-color: var(--accent);
}
.step-label {
margin-top: 8px;
font-size: var(--text-sm);
color: var(--text-secondary);
white-space: nowrap;
}
.progress-step.active .step-label {
color: var(--primary);
font-weight: 600;
}
.progress-line {
width: 80px;
height: 2px;
background: var(--border);
margin: 0 10px;
position: relative;
top: -20px;
}
.progress-step.completed + .progress-line {
background: var(--accent);
}
/* Booking Section */
.booking-section {
padding: 60px 0;
min-height: calc(100vh - 200px);
}
.booking-header {
text-align: center;
margin-bottom: 40px;
}
.booking-header h1 {
font-size: var(--text-4xl);
margin-bottom: 10px;
}
.booking-header p {
color: var(--text-secondary);
font-size: var(--text-lg);
}
.booking-content {
display: grid;
grid-template-columns: 1fr 350px;
gap: 40px;
}
.booking-main {
display: flex;
flex-direction: column;
gap: 30px;
}
.booking-card {
background: var(--background);
border: 1px solid var(--border);
border-radius: var(--radius-xl);
padding: 30px;
box-shadow: var(--shadow-sm);
}
.booking-card h3 {
font-size: var(--text-xl);
margin-bottom: 20px;
}
/* Calendar */
.calendar-container {
background: var(--surface);
border-radius: var(--radius-lg);
padding: 20px;
}
.calendar-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.calendar-nav {
width: 32px;
height: 32px;
border-radius: var(--radius-md);
border: 1px solid var(--border);
background: var(--background);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
transition: all var(--transition-fast);
}
.calendar-nav:hover {
background: var(--primary);
color: white;
border-color: var(--primary);
}
.calendar-month {
font-size: var(--text-lg);
font-weight: 600;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
}
.calendar-day-header {
text-align: center;
font-size: var(--text-sm);
font-weight: 600;
color: var(--text-secondary);
padding: 10px 0;
}
.calendar-day {
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-md);
cursor: pointer;
font-weight: 500;
transition: all var(--transition-fast);
}
.calendar-day.other-month {
color: var(--text-secondary);
opacity: 0.3;
}
.calendar-day.available {
background: var(--background);
color: var(--text);
}
.calendar-day.available:hover {
background: var(--primary);
color: white;
}
.calendar-day.unavailable {
background: var(--surface);
color: var(--text-secondary);
cursor: not-allowed;
text-decoration: line-through;
}
.calendar-day.selected {
background: var(--primary);
color: white;
}
.calendar-legend {
display: flex;
gap: 20px;
margin-top: 20px;
font-size: var(--text-sm);
}
.legend-dot {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 5px;
}
.legend-dot.available {
background: var(--background);
border: 2px solid var(--primary);
}
.legend-dot.unavailable {
background: var(--text-secondary);
}
.legend-dot.selected {
background: var(--primary);
}
/* Form Elements */
.form-group {
margin-bottom: 25px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: var(--text);
}
.form-control {
width: 100%;
padding: 12px 15px;
border: 1px solid var(--border);
border-radius: var(--radius-md);
font-size: var(--text-base);
font-family: inherit;
transition: all var(--transition-fast);
background: var(--background);
}
.form-control:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.1);
}
.form-text {
display: block;
margin-top: 5px;
font-size: var(--text-sm);
color: var(--text-secondary);
}
/* Duration Options */
.duration-options {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
}
.duration-option input {
display: none;
}
.duration-card {
display: flex;
flex-direction: column;
padding: 20px;
border: 2px solid var(--border);
border-radius: var(--radius-lg);
cursor: pointer;
transition: all var(--transition-base);
position: relative;
}
.duration-option input:checked + .duration-card {
border-color: var(--primary);
background: var(--surface);
}
.duration-card:hover {
border-color: var(--primary);
transform: translateY(-2px);
}
.duration-time {
font-size: var(--text-lg);
font-weight: 600;
margin-bottom: 5px;
}
.duration-price {
color: var(--primary);
font-size: var(--text-xl);
font-weight: 700;
}
.duration-badge {
position: absolute;
top: 10px;
right: 10px;
padding: 4px 8px;
background: var(--accent);
color: white;
font-size: var(--text-xs);
border-radius: var(--radius-full);
font-weight: 600;
}
/* Booking Sidebar */
.booking-sidebar {
display: flex;
flex-direction: column;
gap: 30px;
}
.booking-summary {
background: var(--surface);
border-radius: var(--radius-xl);
padding: 30px;
position: sticky;
top: 100px;
}
.booking-summary h3 {
font-size: var(--text-xl);
margin-bottom: 20px;
}
.summary-item {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
font-size: var(--text-base);
}
.summary-item span {
color: var(--text-secondary);
}
.summary-item strong {
color: var(--text);
}
.summary-divider {
height: 1px;
background: var(--border);
margin: 20px 0;
}
.summary-total {
font-size: var(--text-lg);
}
.summary-total strong {
color: var(--primary);
font-size: var(--text-2xl);
}
.summary-note {
font-size: var(--text-sm);
color: var(--text-secondary);
font-style: italic;
margin-top: 15px;
}
.booking-help {
background: var(--background);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 20px;
text-align: center;
}
.booking-help h4 {
font-size: var(--text-lg);
margin-bottom: 10px;
}
.booking-help p {
color: var(--text-secondary);
margin-bottom: 15px;
font-size: var(--text-sm);
}
/* Navigation */
.booking-navigation {
display: flex;
justify-content: space-between;
margin-top: 40px;
padding-top: 30px;
border-top: 1px solid var(--border);
}
/* Yacht Selection Grid */
.yacht-selection-grid {
display: grid;
gap: 30px;
}
.yacht-select-card {
display: grid;
grid-template-columns: 300px 1fr;
background: var(--background);
border: 2px solid var(--border);
border-radius: var(--radius-xl);
overflow: hidden;
transition: all var(--transition-base);
cursor: pointer;
}
.yacht-select-card:hover {
border-color: var(--primary);
box-shadow: var(--shadow-lg);
}
.yacht-select-card.selected {
border-color: var(--primary);
background: var(--surface);
}
.yacht-select-image {
height: 200px;
background: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: var(--text-xl);
}
.yacht-select-info {
padding: 30px;
}
.yacht-select-header {
display: flex;
justify-content: space-between;
align-items: start;
margin-bottom: 15px;
}
.yacht-select-name {
font-size: var(--text-2xl);
font-weight: 700;
margin-bottom: 5px;
}
.yacht-select-type {
color: var(--text-secondary);
}
.yacht-select-price {
text-align: right;
}
.yacht-select-specs {
display: flex;
gap: 30px;
margin: 20px 0;
}
.spec-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-secondary);
font-size: var(--text-sm);
}
/* Customization Options */
.customization-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
.addon-card {
border: 2px solid var(--border);
border-radius: var(--radius-lg);
padding: 20px;
transition: all var(--transition-base);
cursor: pointer;
}
.addon-card:hover {
border-color: var(--primary);
}
.addon-card.selected {
border-color: var(--primary);
background: var(--surface);
}
.addon-header {
display: flex;
justify-content: space-between;
align-items: start;
margin-bottom: 10px;
}
.addon-name {
font-weight: 600;
}
.addon-price {
color: var(--primary);
font-weight: 700;
}
.addon-description {
font-size: var(--text-sm);
color: var(--text-secondary);
}
/* Responsive */
@media (max-width: 1024px) {
.booking-content {
grid-template-columns: 1fr;
}
.booking-sidebar {
order: -1;
}
.booking-summary {
position: static;
}
}
@media (max-width: 768px) {
.progress-steps {
overflow-x: auto;
padding: 0 20px;
}
.progress-line {
width: 40px;
}
.step-label {
font-size: var(--text-xs);
}
.duration-options {
grid-template-columns: 1fr;
}
.yacht-select-card {
grid-template-columns: 1fr;
}
.booking-navigation {
flex-direction: column;
gap: 15px;
}
.booking-navigation .btn {
width: 100%;
justify-content: center;
}
}

View File

@@ -0,0 +1,747 @@
/* Enhanced Maintenance Portal Styles */
/* ================================== */
:root {
/* Modern Color Palette */
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
--success-gradient: linear-gradient(135deg, #0ba360 0%, #3cba92 100%);
--warning-gradient: linear-gradient(135deg, #f2994a 0%, #f2c94c 100%);
--danger-gradient: linear-gradient(135deg, #eb3349 0%, #f45c43 100%);
/* Enhanced shadows */
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.06);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);
--shadow-xl: 0 12px 48px rgba(0, 0, 0, 0.16);
--shadow-glow: 0 0 20px rgba(102, 126, 234, 0.4);
/* Spacing */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 1.5rem;
--spacing-xl: 2rem;
--spacing-2xl: 3rem;
/* Border radius */
--radius-sm: 6px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 20px;
--radius-full: 9999px;
/* Transitions */
--transition-fast: 0.15s ease;
--transition-base: 0.3s ease;
--transition-slow: 0.5s ease;
}
/* Global Enhancements */
body {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
}
/* Enhanced Dashboard Cards */
.dashboard-card, .card, .portal-card {
background: white;
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
box-shadow: var(--shadow-md);
border: 1px solid rgba(255, 255, 255, 0.8);
transition: all var(--transition-base);
position: relative;
overflow: hidden;
}
.dashboard-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--primary-gradient);
opacity: 0;
transition: opacity var(--transition-base);
}
.dashboard-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-xl);
}
.dashboard-card:hover::before {
opacity: 1;
}
/* Enhanced Stats Cards */
.stat-card {
background: white;
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
position: relative;
overflow: hidden;
transition: all var(--transition-base);
border: 1px solid #e5e7eb;
}
.stat-card::after {
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 200%;
height: 200%;
background: var(--primary-gradient);
opacity: 0.05;
border-radius: 50%;
transition: all var(--transition-slow);
}
.stat-card:hover::after {
top: -75%;
right: -75%;
opacity: 0.1;
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
border-color: #667eea;
}
.stat-value {
font-size: 2.5rem;
font-weight: 700;
background: var(--primary-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin: var(--spacing-sm) 0;
}
.stat-label {
color: #6b7280;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
font-weight: 600;
}
.stat-change {
display: inline-flex;
align-items: center;
gap: var(--spacing-xs);
padding: var(--spacing-xs) var(--spacing-sm);
border-radius: var(--radius-full);
font-size: 0.875rem;
font-weight: 600;
margin-top: var(--spacing-sm);
}
.stat-change.positive {
background: #dcfce7;
color: #16a34a;
}
.stat-change.negative {
background: #fee2e2;
color: #dc2626;
}
/* Enhanced Tables */
.table-container {
background: white;
border-radius: var(--radius-lg);
overflow: hidden;
box-shadow: var(--shadow-md);
}
table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
}
thead {
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
}
thead th {
padding: var(--spacing-md) var(--spacing-lg);
text-align: left;
font-weight: 600;
color: #374151;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
border-bottom: 2px solid #e5e7eb;
}
tbody tr {
transition: all var(--transition-fast);
border-bottom: 1px solid #f3f4f6;
}
tbody tr:hover {
background: linear-gradient(90deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
}
tbody td {
padding: var(--spacing-md) var(--spacing-lg);
color: #4b5563;
}
/* Enhanced Status Badges */
.status-badge, .badge {
display: inline-flex;
align-items: center;
gap: var(--spacing-xs);
padding: var(--spacing-xs) var(--spacing-sm);
border-radius: var(--radius-full);
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: all var(--transition-fast);
}
.status-badge.active, .badge.success {
background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
color: #065f46;
}
.status-badge.scheduled, .badge.warning {
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
color: #92400e;
}
.status-badge.overdue, .badge.danger {
background: linear-gradient(135deg, #ffeaa7 0%, #fdcb6e 100%);
color: #dc2626;
}
.status-badge.completed, .badge.info {
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
color: #1e40af;
}
/* Enhanced Buttons */
.btn, .portal-btn, button[type="submit"] {
padding: var(--spacing-sm) var(--spacing-lg);
border-radius: var(--radius-md);
font-weight: 600;
transition: all var(--transition-base);
cursor: pointer;
border: none;
display: inline-flex;
align-items: center;
gap: var(--spacing-sm);
position: relative;
overflow: hidden;
}
.btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width var(--transition-base), height var(--transition-base);
}
.btn:hover::before {
width: 300px;
height: 300px;
}
.btn-primary {
background: var(--primary-gradient);
color: white;
box-shadow: 0 4px 6px rgba(102, 126, 234, 0.25);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.35);
}
.btn-secondary {
background: white;
color: #4b5563;
border: 2px solid #e5e7eb;
}
.btn-secondary:hover {
background: #f9fafb;
border-color: #667eea;
color: #667eea;
transform: translateY(-2px);
}
.btn-success {
background: var(--success-gradient);
color: white;
box-shadow: 0 4px 6px rgba(16, 185, 129, 0.25);
}
.btn-danger {
background: var(--danger-gradient);
color: white;
box-shadow: 0 4px 6px rgba(239, 68, 68, 0.25);
}
/* Enhanced Form Elements */
.form-group {
margin-bottom: var(--spacing-lg);
}
.form-label {
display: block;
margin-bottom: var(--spacing-sm);
font-weight: 600;
color: #374151;
font-size: 0.875rem;
letter-spacing: 0.025em;
}
.form-input, .form-select, .form-textarea,
input[type="text"], input[type="email"], input[type="number"],
input[type="date"], input[type="time"], select, textarea {
width: 100%;
padding: var(--spacing-sm) var(--spacing-md);
border: 2px solid #e5e7eb;
border-radius: var(--radius-md);
background: #f9fafb;
transition: all var(--transition-base);
font-family: inherit;
}
.form-input:focus, .form-select:focus, .form-textarea:focus,
input:focus, select:focus, textarea:focus {
outline: none;
border-color: #667eea;
background: white;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
transform: translateY(-1px);
}
/* Enhanced Sidebar */
.portal-sidebar {
background: linear-gradient(180deg, #1f2937 0%, #111827 100%);
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.1);
}
.sidebar-nav-item {
margin: var(--spacing-xs) var(--spacing-md);
border-radius: var(--radius-md);
transition: all var(--transition-base);
}
.sidebar-nav-item a {
display: flex;
align-items: center;
gap: var(--spacing-md);
padding: var(--spacing-sm) var(--spacing-md);
color: #9ca3af;
text-decoration: none;
transition: all var(--transition-base);
position: relative;
}
.sidebar-nav-item a::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 0;
background: var(--primary-gradient);
transition: height var(--transition-base);
border-radius: 0 3px 3px 0;
}
.sidebar-nav-item:hover {
background: rgba(255, 255, 255, 0.05);
}
.sidebar-nav-item:hover a {
color: white;
}
.sidebar-nav-item.active {
background: rgba(102, 126, 234, 0.1);
}
.sidebar-nav-item.active a {
color: white;
}
.sidebar-nav-item.active a::before {
height: 24px;
}
/* Enhanced Header */
.portal-header {
background: white;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
border-bottom: 1px solid #e5e7eb;
}
.header-search {
position: relative;
}
.header-search input {
padding-left: 2.5rem;
background: #f3f4f6;
border: 2px solid transparent;
border-radius: var(--radius-full);
}
.header-search input:focus {
background: white;
border-color: #667eea;
}
.header-search i {
position: absolute;
left: var(--spacing-md);
top: 50%;
transform: translateY(-50%);
color: #9ca3af;
}
/* Enhanced Charts Container */
.chart-container {
background: white;
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
box-shadow: var(--shadow-md);
position: relative;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--spacing-lg);
padding-bottom: var(--spacing-md);
border-bottom: 2px solid #f3f4f6;
}
.chart-title {
font-size: 1.125rem;
font-weight: 700;
color: #1f2937;
}
/* Enhanced Progress Bars */
.progress-bar {
width: 100%;
height: 8px;
background: #e5e7eb;
border-radius: var(--radius-full);
overflow: hidden;
position: relative;
}
.progress-bar-fill {
height: 100%;
background: var(--primary-gradient);
border-radius: var(--radius-full);
transition: width var(--transition-slow);
position: relative;
overflow: hidden;
}
.progress-bar-fill::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.3),
transparent
);
animation: shimmer 2s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
/* Enhanced Notifications */
.notification {
padding: var(--spacing-md);
border-radius: var(--radius-md);
margin-bottom: var(--spacing-md);
display: flex;
align-items: flex-start;
gap: var(--spacing-md);
animation: slideIn var(--transition-base);
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.notification.info {
background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
border-left: 4px solid #3b82f6;
}
.notification.success {
background: linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%);
border-left: 4px solid #22c55e;
}
.notification.warning {
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
border-left: 4px solid #f59e0b;
}
.notification.error {
background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
border-left: 4px solid #ef4444;
}
/* Enhanced Modals */
.modal-overlay {
background: rgba(0, 0, 0, 0.5);
-webkit-backdrop-filter: blur(5px);
backdrop-filter: blur(5px);
}
.modal-content {
background: white;
border-radius: var(--radius-xl);
box-shadow: var(--shadow-xl);
animation: modalSlideIn var(--transition-base);
}
@keyframes modalSlideIn {
from {
opacity: 0;
transform: translateY(-30px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
/* Enhanced Timeline */
.timeline-item {
position: relative;
padding-left: 3rem;
padding-bottom: 2rem;
}
.timeline-item::before {
content: '';
position: absolute;
left: 1rem;
top: 0.5rem;
bottom: -2rem;
width: 2px;
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
}
.timeline-item:last-child::before {
display: none;
}
.timeline-dot {
position: absolute;
left: 0.5rem;
top: 0.5rem;
width: 1rem;
height: 1rem;
background: white;
border: 3px solid #667eea;
border-radius: 50%;
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1);
}
/* Enhanced Tooltips */
.tooltip {
position: relative;
}
.tooltip::after {
content: attr(data-tooltip);
position: absolute;
bottom: 125%;
left: 50%;
transform: translateX(-50%);
padding: var(--spacing-sm) var(--spacing-md);
background: #1f2937;
color: white;
font-size: 0.875rem;
border-radius: var(--radius-md);
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity var(--transition-base);
box-shadow: var(--shadow-lg);
}
.tooltip:hover::after {
opacity: 1;
}
/* Enhanced Loading States */
.skeleton {
background: linear-gradient(
90deg,
#f3f4f6 25%,
#e5e7eb 50%,
#f3f4f6 75%
);
background-size: 200% 100%;
animation: loading 1.5s infinite;
border-radius: var(--radius-md);
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e5e7eb;
border-top-color: #667eea;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* Smooth Scrollbar */
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
background: var(--gray-100);
}
::-webkit-scrollbar-thumb {
background: var(--gray-400);
border-radius: var(--radius-full);
}
::-webkit-scrollbar-thumb:hover {
background: var(--gray-500);
}
/* Focus Visible Enhancement */
:focus-visible {
outline: 2px solid var(--primary-orange);
outline-offset: 2px;
}
/* Selection Color */
::selection {
background: rgba(220, 20, 60, 0.2);
color: var(--gray-900);
}
/* Responsive Adjustments */
@media (max-width: 768px) {
.dashboard-grid {
grid-template-columns: 1fr;
}
.portal-content {
padding: var(--space-md);
}
table {
font-size: var(--text-sm);
}
.table-wrapper {
overflow-x: auto;
}
}
/* Print Styles */
@media print {
.portal-sidebar,
.portal-header,
.btn,
.no-print {
display: none !important;
}
.portal-main {
margin-left: 0 !important;
}
.portal-content {
margin: 0;
padding: 0;
}
.dashboard-card,
.card {
box-shadow: none;
border: 1px solid var(--gray-300);
page-break-inside: avoid;
}
}
/* Accessibility Improvements */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Skip to content link */
.skip-to-content {
position: absolute;
top: -40px;
left: 0;
background: var(--primary-blue);
color: var(--white);
padding: var(--space-sm) var(--space-md);
text-decoration: none;
z-index: 9999;
}
.skip-to-content:focus {
top: 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,174 @@
/* HarborSmith - Theme Styles */
/* ========================= */
/* Classical Nautical Theme (Default) - Navy & Crimson */
[data-theme="nautical"] {
--primary: #001f3f; /* Classic navy blue */
--accent: #dc143c; /* Nautical red/crimson */
--background: #ffffff;
--surface: #f0f4f8;
--text: #0a1628;
--text-secondary: #4a5568;
--border: #cbd5e0;
--overlay: rgba(0, 31, 63, 0.7);
--gradient-start: #001f3f;
--gradient-end: #003366;
}
/* Gold Theme - Navy with Gold accents */
[data-theme="gold"] {
--primary: #001f3f; /* Classic navy blue */
--accent: #bc970c; /* Gold */
--background: #ffffff;
--surface: #f0f4f8;
--text: #0a1628;
--text-secondary: #4a5568;
--border: #cbd5e0;
--overlay: rgba(0, 31, 63, 0.7);
--gradient-start: #001f3f;
--gradient-end: #003366;
}
/* Coastal Dawn Theme - Soft & Serene Luxury */
[data-theme="coastal-dawn"] {
--primary: #A9B4C2; /* Cadet Blue */
--accent: #D4AF37; /* Gilded Gold */
--background: #F8F7F4; /* Alabaster White */
--surface: #FFFFFF;
--text: #333745; /* Charcoal Slate */
--text-secondary: #6B7280;
--border: #E5E7EB;
--overlay: rgba(169, 180, 194, 0.4);
--gradient-start: #A9B4C2;
--gradient-end: #C5D3E0;
}
/* Deep Sea Slate Theme - Modern & Technical */
[data-theme="deep-sea"] {
--primary: #1E2022; /* Gunmetal Grey */
--accent: #00BFFF; /* Deep Sky Blue */
--background: #1E2022; /* Dark background */
--surface: #2A2D30;
--text: #E5E4E2; /* Platinum text */
--text-secondary: #C0C0C0; /* Silver */
--border: #3A3D40;
--overlay: rgba(30, 32, 34, 0.8);
--gradient-start: #1E2022;
--gradient-end: #2A2D30;
}
/* Monaco White Theme - Pristine & Minimalist */
[data-theme="monaco-white"] {
--primary: #2C3E50; /* Midnight Blue */
--accent: #E74C3C; /* Pomegranate Red */
--background: #FFFFFF;
--surface: #F8F9FA;
--text: #2C3E50;
--text-secondary: #7F8C8D;
--border: #ECF0F1;
--overlay: rgba(44, 62, 80, 0.05);
--gradient-start: #FFFFFF;
--gradient-end: #F8F9FA;
}
/* Update hero gradient for all themes */
[data-theme] .hero-background {
background: linear-gradient(135deg, var(--gradient-start) 0%, var(--gradient-end) 100%);
}
/* Ensure good contrast for nav items */
[data-theme] .nav-link {
color: var(--text);
font-weight: 500;
}
[data-theme] .nav-link:hover {
color: var(--accent);
}
/* Theme switcher button styling */
[data-theme] .theme-switcher {
background: var(--surface);
border: 2px solid var(--border);
color: var(--text);
}
[data-theme] .theme-switcher:hover {
background: var(--accent);
color: white;
border-color: var(--accent);
}
/* Better button contrast */
[data-theme] .btn-primary {
background: var(--accent);
color: white;
border: 2px solid var(--accent);
}
[data-theme] .btn-primary:hover {
background: var(--primary);
border-color: var(--primary);
}
/* Schedule Service button - make it filled */
[data-theme] .btn-secondary {
background: var(--primary);
color: white;
border: 2px solid var(--primary);
}
[data-theme] .btn-secondary:hover {
background: var(--accent);
border-color: var(--accent);
color: white;
}
/* Card improvements */
[data-theme] .service-card {
background: var(--surface);
border: 1px solid var(--border);
}
[data-theme] .yacht-card {
background: white;
border: 1px solid var(--border);
}
/* Stats section contrast */
[data-theme] .stats-section {
background: var(--surface);
}
/* Footer styling */
[data-theme] footer {
background: var(--primary);
color: white;
}
[data-theme] footer a {
color: rgba(255, 255, 255, 0.8);
}
[data-theme] footer a:hover {
color: var(--accent);
}
/* Special styling for Classical Nautical theme */
[data-theme="nautical"] .btn-primary {
background: var(--accent);
box-shadow: 0 4px 6px rgba(220, 20, 60, 0.2);
}
[data-theme="nautical"] .btn-secondary {
background: var(--primary);
box-shadow: 0 4px 6px rgba(0, 31, 63, 0.2);
}
[data-theme="nautical"] .service-card {
border-color: var(--primary);
}
[data-theme="nautical"] .yacht-card {
border-top: 3px solid var(--accent);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

BIN
website-mockups/diver.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 MiB

872
website-mockups/faq.html Normal file
View File

@@ -0,0 +1,872 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Frequently Asked Questions - HarborSmith</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="css/voyage-layout.css">
<link rel="stylesheet" href="css/themes.css">
<style>
.faq-hero {
background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%);
padding: 5rem 0;
color: white;
text-align: center;
position: relative;
overflow: hidden;
}
.faq-hero::before {
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255,255,255,0.05) 0%, transparent 70%);
animation: rotate 30s linear infinite;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.faq-hero-content {
position: relative;
z-index: 1;
}
.faq-hero h1 {
font-size: 3rem;
font-weight: 700;
margin-bottom: 1rem;
}
.faq-hero p {
font-size: 1.25rem;
opacity: 0.95;
max-width: 600px;
margin: 0 auto 2rem;
}
.search-box {
max-width: 600px;
margin: 0 auto;
position: relative;
}
.search-input {
width: 100%;
padding: 1rem 3rem 1rem 1.5rem;
border: none;
border-radius: 50px;
font-size: 1rem;
background: white;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
.search-input:focus {
outline: none;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
}
.search-icon {
position: absolute;
right: 1.5rem;
top: 50%;
transform: translateY(-50%);
color: var(--accent-primary);
}
.faq-categories {
padding: 3rem 0;
background: var(--bg-primary);
}
.category-tabs {
display: flex;
justify-content: center;
gap: 1rem;
flex-wrap: wrap;
margin-bottom: 3rem;
}
.category-tab {
padding: 0.75rem 1.5rem;
background: var(--card-bg);
border: 2px solid var(--border-color);
border-radius: 50px;
font-weight: 500;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.5rem;
}
.category-tab:hover {
border-color: var(--accent-primary);
color: var(--text-primary);
transform: translateY(-2px);
}
.category-tab.active {
background: var(--accent-primary);
border-color: var(--accent-primary);
color: white;
}
.category-tab svg {
width: 18px;
height: 18px;
}
.faq-content {
max-width: 900px;
margin: 0 auto;
}
.faq-section {
display: none;
}
.faq-section.active {
display: block;
}
.faq-item {
background: var(--card-bg);
border-radius: 12px;
margin-bottom: 1rem;
overflow: hidden;
border: 2px solid transparent;
transition: all 0.3s ease;
}
.faq-item:hover {
border-color: var(--accent-primary);
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
}
.faq-question {
padding: 1.5rem;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
transition: all 0.3s ease;
}
.faq-question:hover {
background: rgba(30, 58, 95, 0.03);
}
.faq-item.active .faq-question {
background: rgba(30, 58, 95, 0.05);
}
.faq-question-text {
font-weight: 600;
color: var(--text-primary);
font-size: 1.125rem;
flex: 1;
padding-right: 1rem;
}
.faq-toggle {
width: 30px;
height: 30px;
background: var(--accent-primary);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
transition: all 0.3s ease;
flex-shrink: 0;
}
.faq-toggle svg {
width: 18px;
height: 18px;
transition: transform 0.3s ease;
}
.faq-item.active .faq-toggle svg {
transform: rotate(180deg);
}
.faq-answer {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.faq-item.active .faq-answer {
max-height: 1000px;
}
.faq-answer-content {
padding: 0 1.5rem 1.5rem;
color: var(--text-secondary);
line-height: 1.8;
}
.faq-answer-content ul {
margin: 1rem 0;
padding-left: 1.5rem;
}
.faq-answer-content li {
margin: 0.5rem 0;
}
.faq-answer-content strong {
color: var(--text-primary);
}
.quick-links {
padding: 5rem 0;
background: linear-gradient(135deg, rgba(30, 58, 95, 0.05) 0%, rgba(30, 58, 95, 0.02) 100%);
}
.links-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.link-card {
background: var(--card-bg);
border-radius: 12px;
padding: 2rem;
text-align: center;
transition: all 0.3s ease;
cursor: pointer;
}
.link-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.link-icon {
width: 60px;
height: 60px;
margin: 0 auto 1rem;
background: linear-gradient(135deg, var(--accent-primary) 0%, var(--accent-dark) 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.link-icon svg {
width: 30px;
height: 30px;
}
.link-title {
font-size: 1.25rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.5rem;
}
.link-description {
color: var(--text-secondary);
font-size: 0.875rem;
margin-bottom: 1rem;
}
.link-button {
color: var(--accent-primary);
font-weight: 600;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.link-button svg {
width: 16px;
height: 16px;
transition: transform 0.3s ease;
}
.link-card:hover .link-button svg {
transform: translateX(5px);
}
.no-results {
text-align: center;
padding: 3rem;
color: var(--text-secondary);
}
.highlight {
background: rgba(255, 193, 7, 0.2);
padding: 0 2px;
}
@media (max-width: 768px) {
.faq-hero h1 {
font-size: 2rem;
}
.category-tabs {
justify-content: flex-start;
overflow-x: auto;
padding-bottom: 1rem;
}
.faq-question-text {
font-size: 1rem;
}
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="voyage-nav visible" id="voyageNav">
<div class="nav-container">
<div class="nav-brand">
<img src="logo.jpg" alt="HarborSmith" class="nav-logo">
<span>HarborSmith</span>
</div>
<div class="nav-links">
<a href="index.html" class="nav-link">Home</a>
<a href="charter.html" class="nav-link">Charters</a>
<a href="maintenance.html" class="nav-link">Maintenance</a>
<a href="about.html" class="nav-link">About</a>
<a href="contact.html" class="nav-link">Contact</a>
</div>
</div>
</nav>
<!-- Hero Section -->
<section class="faq-hero">
<div class="faq-hero-content">
<h1>Frequently Asked Questions</h1>
<p>Find answers to common questions about our yacht charters and maintenance services</p>
<div class="search-box">
<input type="text" class="search-input" id="faqSearch" placeholder="Search for answers...">
<i data-lucide="search" class="search-icon"></i>
</div>
</div>
</section>
<!-- FAQ Categories -->
<section class="faq-categories">
<div class="container">
<!-- Category Tabs -->
<div class="category-tabs">
<button class="category-tab active" data-category="all">
<i data-lucide="list"></i>
All Questions
</button>
<button class="category-tab" data-category="charter">
<i data-lucide="sailboat"></i>
Charter Services
</button>
<button class="category-tab" data-category="maintenance">
<i data-lucide="wrench"></i>
Maintenance
</button>
<button class="category-tab" data-category="booking">
<i data-lucide="calendar"></i>
Booking & Pricing
</button>
<button class="category-tab" data-category="safety">
<i data-lucide="shield"></i>
Safety & Requirements
</button>
</div>
<!-- FAQ Content -->
<div class="faq-content">
<!-- All Questions Section -->
<div class="faq-section active" id="all">
<!-- Charter Questions -->
<div class="faq-item" data-category="charter">
<div class="faq-question">
<span class="faq-question-text">What is included in a yacht charter?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
Our yacht charters include:
<ul>
<li>Fully fueled yacht for your charter duration</li>
<li>Licensed and experienced captain</li>
<li>Safety equipment and life jackets for all passengers</li>
<li>Basic amenities (water, ice, coolers)</li>
<li>Bluetooth sound system</li>
<li>Complimentary parking at our marina</li>
</ul>
Additional services like catering, photographer, and water sports equipment can be added for an extra fee.
</div>
</div>
</div>
<div class="faq-item" data-category="charter booking">
<div class="faq-question">
<span class="faq-question-text">How far in advance should I book?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
We recommend booking <strong>at least 2-4 weeks in advance</strong> for weekend charters and <strong>1-2 weeks</strong> for weekday charters. During peak season (May through October), booking 4-6 weeks ahead is advisable. For major holidays and special events like Fleet Week, we suggest booking 2-3 months in advance to secure your preferred yacht and time.
</div>
</div>
</div>
<div class="faq-item" data-category="charter booking">
<div class="faq-question">
<span class="faq-question-text">What is your cancellation policy?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
Our cancellation policy is designed to be fair and flexible:
<ul>
<li><strong>48+ hours before charter:</strong> Full refund</li>
<li><strong>24-48 hours before:</strong> 50% refund or full credit for rescheduling</li>
<li><strong>Less than 24 hours:</strong> No refund, but 50% credit toward future charter</li>
<li><strong>Weather cancellations:</strong> Full refund or rescheduling at no charge</li>
</ul>
We understand plans change, so we try to work with our customers whenever possible.
</div>
</div>
</div>
<div class="faq-item" data-category="charter safety">
<div class="faq-question">
<span class="faq-question-text">Do I need boating experience to charter a yacht?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
<strong>No boating experience is required!</strong> All of our charters come with a licensed, experienced captain who will handle all navigation and sailing. You and your guests can simply relax and enjoy the experience. If you're interested in learning, our captains are happy to share their knowledge and even let you take the helm under supervision.
</div>
</div>
</div>
<div class="faq-item" data-category="charter">
<div class="faq-question">
<span class="faq-question-text">Can we bring our own food and drinks?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
<strong>Yes, absolutely!</strong> You're welcome to bring your own food and beverages, including alcohol (for passengers 21+). We provide coolers with ice, and our yachts have refrigeration available. We also offer catering packages if you prefer to have everything prepared for you, ranging from light snacks to full gourmet meals.
</div>
</div>
</div>
<div class="faq-item" data-category="charter safety">
<div class="faq-question">
<span class="faq-question-text">What happens if the weather is bad?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
Safety is our top priority. If weather conditions are unsafe for sailing (high winds, storms, heavy fog), we will:
<ul>
<li>Contact you as early as possible (usually the day before)</li>
<li>Offer to reschedule to another available date</li>
<li>Provide a full refund if rescheduling isn't possible</li>
</ul>
Light rain or overcast conditions typically don't affect charters, and many guests find sailing in light mist quite romantic!
</div>
</div>
</div>
<div class="faq-item" data-category="maintenance">
<div class="faq-question">
<span class="faq-question-text">How often should I service my yacht?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
Regular maintenance schedules depend on usage, but we recommend:
<ul>
<li><strong>Oil & filter changes:</strong> Every 100 hours or annually</li>
<li><strong>Bottom cleaning:</strong> Every 1-3 months depending on water conditions</li>
<li><strong>Engine service:</strong> Every 100 hours or annually</li>
<li><strong>Hull inspection:</strong> Every 6 months</li>
<li><strong>Complete service:</strong> Annually before peak season</li>
</ul>
We offer customized maintenance plans based on your yacht's specific needs and usage patterns.
</div>
</div>
</div>
<div class="faq-item" data-category="maintenance">
<div class="faq-question">
<span class="faq-question-text">Do you work on all yacht brands?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
<strong>Yes!</strong> Our certified technicians are trained to work on all major yacht and engine brands including:
<ul>
<li>Mercury, Yamaha, Volvo Penta, Caterpillar engines</li>
<li>Beneteau, Jeanneau, Catalina, Hunter sailboats</li>
<li>Sea Ray, Bayliner, Carver, Azimut motor yachts</li>
<li>And many more...</li>
</ul>
We have specialized certifications for Mercury, Yamaha, and Volvo marine systems.
</div>
</div>
</div>
<div class="faq-item" data-category="maintenance booking">
<div class="faq-question">
<span class="faq-question-text">How much does maintenance cost?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
Maintenance costs vary based on yacht size and services needed. Here are typical ranges:
<ul>
<li><strong>Basic maintenance package:</strong> From $299/month</li>
<li><strong>Oil change:</strong> $200-400</li>
<li><strong>Hull cleaning:</strong> $200-500</li>
<li><strong>Engine service:</strong> $450-1,200</li>
<li><strong>Bottom paint:</strong> $1,500-4,000</li>
</ul>
We provide free inspections and detailed quotes before any work begins. No surprises!
</div>
</div>
</div>
<div class="faq-item" data-category="charter safety">
<div class="faq-question">
<span class="faq-question-text">Are children allowed on charters?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
<strong>Yes, we love having families aboard!</strong> Children of all ages are welcome. We provide:
<ul>
<li>Child-sized life jackets (required for all children under 13)</li>
<li>Safety briefing appropriate for young passengers</li>
<li>Family-friendly routes with calmer waters</li>
<li>Recommendations for kid-friendly activities</li>
</ul>
Children under 18 must be accompanied by a parent or guardian. We recommend our morning or early afternoon charters for families with young children.
</div>
</div>
</div>
<div class="faq-item" data-category="booking">
<div class="faq-question">
<span class="faq-question-text">What forms of payment do you accept?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
We accept multiple payment methods for your convenience:
<ul>
<li>All major credit cards (Visa, Mastercard, Amex, Discover)</li>
<li>Debit cards</li>
<li>PayPal and Venmo</li>
<li>Wire transfers for large bookings</li>
<li>Company checks (with prior approval)</li>
</ul>
Full payment is required to confirm charter bookings. For maintenance services over $1,000, we offer payment plans.
</div>
</div>
</div>
<div class="faq-item" data-category="charter">
<div class="faq-question">
<span class="faq-question-text">What are the best routes for first-time visitors?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
For first-time visitors, we highly recommend:
<ul>
<li><strong>Golden Gate Tour:</strong> Sail under the iconic bridge, around Alcatraz, with views of the city skyline</li>
<li><strong>Sunset Cruise:</strong> Perfect timing for golden hour photos with all major landmarks</li>
<li><strong>Bay Complete:</strong> Comprehensive 4-hour tour covering all highlights</li>
</ul>
Our captains will customize the route based on weather conditions and your interests. Don't forget your camera!
</div>
</div>
</div>
<div class="faq-item" data-category="maintenance">
<div class="faq-question">
<span class="faq-question-text">Do you offer emergency repair services?</span>
<span class="faq-toggle">
<i data-lucide="chevron-down"></i>
</span>
</div>
<div class="faq-answer">
<div class="faq-answer-content">
<strong>Yes, we offer 24/7 emergency services!</strong> Call our emergency line at (415) 555-0911 for:
<ul>
<li>Engine failures</li>
<li>Electrical emergencies</li>
<li>Taking on water</li>
<li>Towing services</li>
<li>On-water repairs</li>
</ul>
Our emergency response team can reach most Bay Area locations within 45 minutes. Emergency rates apply, but your safety is our priority.
</div>
</div>
</div>
</div>
<!-- Charter Section (Hidden) -->
<div class="faq-section" id="charter">
<!-- Charter-specific questions will be filtered here -->
</div>
<!-- Maintenance Section (Hidden) -->
<div class="faq-section" id="maintenance">
<!-- Maintenance-specific questions will be filtered here -->
</div>
<!-- Booking Section (Hidden) -->
<div class="faq-section" id="booking">
<!-- Booking-specific questions will be filtered here -->
</div>
<!-- Safety Section (Hidden) -->
<div class="faq-section" id="safety">
<!-- Safety-specific questions will be filtered here -->
</div>
</div>
</div>
</section>
<!-- Quick Links -->
<section class="quick-links">
<div class="container">
<div class="section-header">
<h2 class="section-title">Still Have Questions?</h2>
<p class="section-subtitle">We're here to help in whatever way works best for you</p>
</div>
<div class="links-grid">
<div class="link-card" onclick="window.location.href='contact.html'">
<div class="link-icon">
<i data-lucide="message-circle"></i>
</div>
<div class="link-title">Contact Us</div>
<div class="link-description">Send us a message and we'll respond within 24 hours</div>
<a href="contact.html" class="link-button">
Get in Touch
<i data-lucide="arrow-right"></i>
</a>
</div>
<div class="link-card" onclick="window.location.href='tel:4155550123'">
<div class="link-icon">
<i data-lucide="phone"></i>
</div>
<div class="link-title">Call Us</div>
<div class="link-description">Speak directly with our team for immediate help</div>
<a href="tel:4155550123" class="link-button">
(415) 555-0123
<i data-lucide="arrow-right"></i>
</a>
</div>
<div class="link-card" onclick="window.location.href='charter-booking-1.html'">
<div class="link-icon">
<i data-lucide="calendar"></i>
</div>
<div class="link-title">Book Now</div>
<div class="link-description">Ready to book? Start your adventure here</div>
<a href="charter-booking-1.html" class="link-button">
Start Booking
<i data-lucide="arrow-right"></i>
</a>
</div>
<div class="link-card" onclick="window.location.href='about.html'">
<div class="link-icon">
<i data-lucide="info"></i>
</div>
<div class="link-title">About Us</div>
<div class="link-description">Learn more about our story and team</div>
<a href="about.html" class="link-button">
Our Story
<i data-lucide="arrow-right"></i>
</a>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="voyage-footer">
<div class="footer-container">
<div class="footer-content">
<div class="footer-brand">
<img src="logo.jpg" alt="HarborSmith" class="footer-logo">
<h3>HarborSmith</h3>
<p>Your trusted partner for Bay Area yacht services</p>
</div>
<div class="footer-links">
<h4>Quick Links</h4>
<a href="index.html">Home</a>
<a href="charter.html">Charters</a>
<a href="maintenance.html">Maintenance</a>
<a href="about.html">About</a>
<a href="contact.html">Contact</a>
</div>
<div class="footer-contact">
<h4>Get in Touch</h4>
<p><i data-lucide="map-pin" class="footer-icon"></i> Pier 39, San Francisco, CA</p>
<p><i data-lucide="phone" class="footer-icon"></i> (415) 555-0123</p>
<p><i data-lucide="mail" class="footer-icon"></i> hello@harborsmith.com</p>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2024 HarborSmith Yacht Services. All rights reserved.</p>
</div>
</div>
</footer>
<script>
// Initialize Lucide icons
lucide.createIcons();
// FAQ Accordion
const faqItems = document.querySelectorAll('.faq-item');
faqItems.forEach(item => {
const question = item.querySelector('.faq-question');
question.addEventListener('click', () => {
const isActive = item.classList.contains('active');
// Close all items
faqItems.forEach(i => i.classList.remove('active'));
// Toggle current item
if (!isActive) {
item.classList.add('active');
}
});
});
// Category Filter
const categoryTabs = document.querySelectorAll('.category-tab');
const allFaqItems = document.querySelectorAll('#all .faq-item');
categoryTabs.forEach(tab => {
tab.addEventListener('click', function() {
// Update active tab
categoryTabs.forEach(t => t.classList.remove('active'));
this.classList.add('active');
const category = this.dataset.category;
// Filter FAQs
if (category === 'all') {
allFaqItems.forEach(item => {
item.style.display = 'block';
});
} else {
allFaqItems.forEach(item => {
if (item.dataset.category.includes(category)) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
});
}
// Re-initialize Lucide icons
lucide.createIcons();
});
});
// Search Functionality
const searchInput = document.getElementById('faqSearch');
searchInput.addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
if (searchTerm.length > 0) {
// Reset category to "All"
categoryTabs.forEach(t => t.classList.remove('active'));
document.querySelector('[data-category="all"]').classList.add('active');
// Search through FAQs
allFaqItems.forEach(item => {
const question = item.querySelector('.faq-question-text').textContent.toLowerCase();
const answer = item.querySelector('.faq-answer-content').textContent.toLowerCase();
if (question.includes(searchTerm) || answer.includes(searchTerm)) {
item.style.display = 'block';
// Highlight search term
if (searchTerm.length > 2) {
// This is simplified - in production you'd want proper highlighting
item.classList.add('search-match');
}
} else {
item.style.display = 'none';
}
});
// Check if no results
const visibleItems = Array.from(allFaqItems).filter(item => item.style.display !== 'none');
if (visibleItems.length === 0) {
// Show no results message (you'd add this element to the HTML)
console.log('No results found');
}
} else {
// Reset to show all
allFaqItems.forEach(item => {
item.style.display = 'block';
item.classList.remove('search-match');
});
}
});
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@@ -0,0 +1,584 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HarborSmith - Your Adventure Awaits</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<!-- Lucide Icons -->
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="css/voyage-layout.css">
<link rel="stylesheet" href="css/themes.css">
</head>
<body>
<!-- Navigation (Minimal, appears on scroll) -->
<nav class="voyage-nav" id="voyageNav">
<div class="nav-container">
<div class="nav-brand">
<img src="logo.jpg" alt="HarborSmith" class="nav-logo">
<span>HarborSmith</span>
</div>
<div class="nav-links">
<a href="#fleet" class="nav-link">Fleet</a>
<a href="#services" class="nav-link">Services</a>
<a href="#experiences" class="nav-link">Experiences</a>
<a href="about.html" class="nav-link">About</a>
<a href="portal-login.html" class="nav-link">Client Portal</a>
<a href="charter-booking-1.html" class="nav-link nav-cta">Book Now</a>
<!-- Theme Switcher -->
<div class="theme-switcher">
<button class="theme-btn" id="themeToggle" aria-label="Change theme">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<circle cx="10" cy="10" r="8" stroke="currentColor" stroke-width="2"/>
<path d="M10 2 L10 18 M2 10 L18 10" stroke="currentColor" stroke-width="1" opacity="0.3"/>
</svg>
</button>
<div class="theme-dropdown" id="themeDropdown">
<button class="theme-option" data-theme="nautical">
<span class="theme-colors">
<span style="background: #1e3a5f"></span>
<span style="background: #dc2626"></span>
<span style="background: #ffffff"></span>
</span>
<span>Classic Nautical</span>
</button>
<button class="theme-option" data-theme="coastal-dawn">
<span class="theme-colors">
<span style="background: #A9B4C2"></span>
<span style="background: #D4AF37"></span>
<span style="background: #F8F7F4"></span>
</span>
<span>Coastal Dawn</span>
</button>
<button class="theme-option" data-theme="deep-sea">
<span class="theme-colors">
<span style="background: #1E2022"></span>
<span style="background: #00BFFF"></span>
<span style="background: #2A2D30"></span>
</span>
<span>Deep Sea</span>
</button>
<button class="theme-option" data-theme="monaco-white">
<span class="theme-colors">
<span style="background: #2C3E50"></span>
<span style="background: #E74C3C"></span>
<span style="background: #FFFFFF"></span>
</span>
<span>Monaco White</span>
</button>
</div>
</div>
</div>
</div>
</nav>
<!-- Hero Section with Video Background -->
<section class="hero-voyage" id="heroSection">
<!-- Video Background with local fallback -->
<div class="hero-video-container">
<video autoplay loop muted playsinline class="hero-video">
<source src="https://videos.pexels.com/video-files/3571264/3571264-uhd_2560_1440_30fps.mp4" type="video/mp4">
</video>
<!-- Fallback image if video fails -->
<div class="hero-image-fallback" style="background-image: url('public/golden_gate.jpg');"></div>
<!-- Warm gradient overlays -->
<div class="hero-overlay gradient-warm"></div>
<div class="hero-overlay gradient-depth"></div>
</div>
<!-- Hero Content -->
<div class="hero-content">
<!-- Trust Indicators -->
<div class="trust-badge animate-fade-in">
<div class="stars">
<span class="stars-icons">
<i data-lucide="star" class="star-filled"></i>
<i data-lucide="star" class="star-filled"></i>
<i data-lucide="star" class="star-filled"></i>
<i data-lucide="star" class="star-filled"></i>
<i data-lucide="star" class="star-filled"></i>
</span>
</div>
<span>Trusted by 0+ adventurers</span>
</div>
<!-- Main Headline -->
<h1 class="hero-headline animate-fade-up">
<span class="gradient-text">Your Adventure Awaits</span>
</h1>
<!-- Subtext -->
<p class="hero-subtext animate-fade-up-delay">
Create unforgettable memories sailing through the stunning San Francisco Bay.<br>
Experience the freedom of the open water with our premium yacht charters designed for every occasion.
</p>
<!-- CTA Buttons -->
<div class="hero-actions animate-fade-up-delay-2">
<button class="btn-primary-warm" onclick="window.location.href='charter-booking-1.html'">
<i data-lucide="anchor" class="btn-icon"></i>
Start Your Journey
</button>
<button class="btn-secondary-warm" onclick="window.location.href='charter.html'">
<i data-lucide="sailboat" class="btn-icon"></i>
View Our Fleet
</button>
</div>
<!-- Scroll Indicator -->
<div class="scroll-indicator">
<span>Scroll to explore</span>
<div class="scroll-arrow">
<i data-lucide="chevron-down"></i>
</div>
</div>
</div>
</section>
<!-- Welcome Section -->
<section class="welcome-section">
<div class="container">
<div class="welcome-content">
<div class="welcome-text">
<h2 class="section-title warm">Welcome Aboard!</h2>
<p class="lead-text">
We're not just a yacht charter service we're your gateway to extraordinary moments on the water.
Our family-owned business has been creating magical experiences in San Francisco Bay for over 15 years.
</p>
<div class="feature-list">
<div class="feature-item">
<span class="feature-icon">
<i data-lucide="waves"></i>
</span>
<div>
<h4>Local Expertise</h4>
<p>Our captains know every hidden cove and perfect sunset spot</p>
</div>
</div>
<div class="feature-item">
<span class="feature-icon">
<i data-lucide="users"></i>
</span>
<div>
<h4>Family Friendly</h4>
<p>Safe, fun experiences for all ages and skill levels</p>
</div>
</div>
<div class="feature-item">
<span class="feature-icon">
<i data-lucide="sparkles"></i>
</span>
<div>
<h4>Tailored to You</h4>
<p>Every charter is customized to create your perfect day</p>
</div>
</div>
</div>
</div>
<div class="welcome-image">
<img src="yacht_party_couple_holding_hands.jpg" alt="Happy customers on yacht" class="rounded-image">
<div class="image-badge">
<span>15+ Years</span>
<span>of Excellence</span>
</div>
</div>
</div>
</div>
</section>
<!-- Interactive Fleet Showcase -->
<section class="fleet-showcase" id="fleet">
<div class="container">
<div class="section-header">
<h2 class="section-title">Meet Your Perfect Yacht</h2>
<p class="section-subtitle">Each vessel in our fleet offers a unique experience</p>
</div>
<div class="fleet-carousel">
<!-- Yacht Card 1 -->
<div class="yacht-card active">
<div class="yacht-image-container">
<img src="yacht_party_couple_holding_hands.jpg" alt="Bay Dreamer">
<div class="yacht-badge premium">Premium</div>
</div>
<div class="yacht-details">
<h3 class="yacht-name">Bay Dreamer</h3>
<p class="yacht-description">
Our flagship yacht, perfect for special celebrations and corporate events.
Luxurious amenities meet breathtaking views.
</p>
<div class="yacht-specs">
<div class="spec">
<i data-lucide="users-2" class="spec-icon"></i>
<span>Up to 12 guests</span>
</div>
<div class="spec">
<i data-lucide="ruler" class="spec-icon"></i>
<span>45ft luxury motor yacht</span>
</div>
<div class="spec">
<i data-lucide="star" class="spec-icon"></i>
<span>Full crew & catering</span>
</div>
</div>
<div class="yacht-pricing">
<span class="price-from">From</span>
<span class="price-amount">$450/hour</span>
</div>
<button class="btn-book-yacht" onclick="window.location.href='charter-booking-1.html'">Book Bay Dreamer</button>
</div>
</div>
<!-- Yacht Card 2 -->
<div class="yacht-card">
<div class="yacht-image-container">
<img src="golden_gate.jpg" alt="Golden Gate Spirit">
<div class="yacht-badge adventure">Adventure</div>
</div>
<div class="yacht-details">
<h3 class="yacht-name">Golden Gate Spirit</h3>
<p class="yacht-description">
Experience true sailing with our beautiful sailboat. Feel the wind in your hair
as you glide past the Golden Gate Bridge.
</p>
<div class="yacht-specs">
<div class="spec">
<i data-lucide="users-2" class="spec-icon"></i>
<span>Up to 8 guests</span>
</div>
<div class="spec">
<i data-lucide="ruler" class="spec-icon"></i>
<span>38ft sailing yacht</span>
</div>
<div class="spec">
<i data-lucide="sailboat" class="spec-icon"></i>
<span>Authentic sailing experience</span>
</div>
</div>
<div class="yacht-pricing">
<span class="price-from">From</span>
<span class="price-amount">$350/hour</span>
</div>
<button class="btn-book-yacht" onclick="window.location.href='charter-booking-1.html'">Book Golden Gate Spirit</button>
</div>
</div>
<!-- Yacht Card 3 -->
<div class="yacht-card">
<div class="yacht-image-container">
<img src="diver.jpg" alt="Ocean Explorer">
<div class="yacht-badge premium">Explorer</div>
</div>
<div class="yacht-details">
<h3 class="yacht-name">Ocean Explorer</h3>
<p class="yacht-description">
Dive into adventure with our fully-equipped exploration yacht. Perfect for
water sports enthusiasts and underwater discovery.
</p>
<div class="yacht-specs">
<div class="spec">
<i data-lucide="users-2" class="spec-icon"></i>
<span>Up to 10 guests</span>
</div>
<div class="spec">
<i data-lucide="ruler" class="spec-icon"></i>
<span>42ft dive yacht</span>
</div>
<div class="spec">
<i data-lucide="anchor" class="spec-icon"></i>
<span>Full diving equipment included</span>
</div>
</div>
<div class="yacht-pricing">
<span class="price-from">From</span>
<span class="price-amount">$550/hour</span>
</div>
<button class="btn-book-yacht" onclick="window.location.href='charter-booking-1.html'">Book Ocean Explorer</button>
</div>
</div>
<!-- Navigation -->
<div class="fleet-nav">
<button class="fleet-prev"></button>
<div class="fleet-dots">
<span class="dot active"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
<button class="fleet-next"></button>
</div>
</div>
</div>
</section>
<!-- Services Section - Charters & Maintenance -->
<section class="services-section" id="services">
<div class="container">
<div class="section-header">
<h2 class="section-title">Complete Yacht Services</h2>
<p class="section-subtitle">From unforgettable charters to expert maintenance</p>
</div>
<div class="services-grid">
<!-- Charter Services -->
<div class="service-card charter-service">
<div class="service-icon-wrapper">
<i data-lucide="sailboat" class="service-icon"></i>
</div>
<h3>Premium Charters</h3>
<p>Experience the Bay like never before with our luxury yacht charters.</p>
<ul class="service-features">
<li><i data-lucide="check" class="check-icon"></i> Private celebrations</li>
<li><i data-lucide="check" class="check-icon"></i> Corporate events</li>
<li><i data-lucide="check" class="check-icon"></i> Romantic cruises</li>
<li><i data-lucide="check" class="check-icon"></i> Family adventures</li>
</ul>
<button class="btn-service" onclick="window.location.href='charter.html'">Explore Charters</button>
</div>
<!-- Maintenance Services -->
<div class="service-card maintenance-service">
<div class="service-icon-wrapper">
<i data-lucide="wrench" class="service-icon"></i>
</div>
<h3>Expert Maintenance</h3>
<p>Keep your vessel in pristine condition with our professional services.</p>
<ul class="service-features">
<li><i data-lucide="check" class="check-icon"></i> Regular maintenance</li>
<li><i data-lucide="check" class="check-icon"></i> Engine services</li>
<li><i data-lucide="check" class="check-icon"></i> Hull cleaning</li>
<li><i data-lucide="check" class="check-icon"></i> Emergency repairs</li>
</ul>
<button class="btn-service" onclick="window.location.href='maintenance.html'">Maintenance Services</button>
</div>
<!-- Client Portal -->
<div class="service-card" style="background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%); color: white;">
<div class="service-icon-wrapper" style="background: rgba(255,255,255,0.2);">
<i data-lucide="user" class="service-icon" style="color: white;"></i>
</div>
<h3 style="color: white;">Client Portal</h3>
<p style="color: rgba(255,255,255,0.9);">Access your personalized dashboard for bookings and services.</p>
<ul class="service-features">
<li style="color: rgba(255,255,255,0.9);"><i data-lucide="check" class="check-icon" style="color: white;"></i> Manage bookings</li>
<li style="color: rgba(255,255,255,0.9);"><i data-lucide="check" class="check-icon" style="color: white;"></i> Service history</li>
<li style="color: rgba(255,255,255,0.9);"><i data-lucide="check" class="check-icon" style="color: white;"></i> Pay invoices</li>
<li style="color: rgba(255,255,255,0.9);"><i data-lucide="check" class="check-icon" style="color: white;"></i> View documents</li>
</ul>
<button class="btn-service" style="background: white; color: #1e3a5f;" onclick="window.location.href='portal-login.html'">Login to Portal</button>
</div>
</div>
<!-- Trust Indicators -->
<div class="service-stats">
<div class="stat-item">
<i data-lucide="ship" class="stat-icon"></i>
<span class="stat-number">50+</span>
<span class="stat-label">Vessels Maintained</span>
</div>
<div class="stat-item">
<i data-lucide="award" class="stat-icon"></i>
<span class="stat-number">15+</span>
<span class="stat-label">Years Experience</span>
</div>
<div class="stat-item">
<i data-lucide="users" class="stat-icon"></i>
<span class="stat-number">500+</span>
<span class="stat-label">Happy Clients</span>
</div>
<div class="stat-item">
<i data-lucide="shield-check" class="stat-icon"></i>
<span class="stat-number">100%</span>
<span class="stat-label">Certified Technicians</span>
</div>
</div>
</div>
</section>
<!-- Experience Stories -->
<section class="experience-stories" id="experiences">
<div class="story-container">
<h2 class="section-title center">Stories from the Bay</h2>
<div class="stories-grid">
<!-- Story 1 -->
<div class="story-card">
<div class="story-image">
<img src="yacht_party_couple_holding_hands.jpg" alt="Romantic sunset">
<div class="story-overlay">
<span class="story-category">Romance</span>
</div>
</div>
<div class="story-content">
<h3>The Perfect Proposal</h3>
<p>"He proposed as the sun set behind the Golden Gate. The crew was so discrete and helpful.
It was absolutely magical!" - Sarah & Mike</p>
<a href="about.html#testimonials" class="story-link">Read their story →</a>
</div>
</div>
<!-- Story 2 -->
<div class="story-card">
<div class="story-image">
<img src="diver.jpg" alt="Team building">
<div class="story-overlay">
<span class="story-category">Corporate</span>
</div>
</div>
<div class="story-content">
<h3>Team Building Success</h3>
<p>"Our team had an incredible day on the water. It brought everyone together in a way
no conference room ever could." - TechStart Inc.</p>
<a href="about.html#testimonials" class="story-link">Read their story →</a>
</div>
</div>
<!-- Story 3 -->
<div class="story-card">
<div class="story-image">
<img src="golden_gate.jpg" alt="Family adventure">
<div class="story-overlay">
<span class="story-category">Family</span>
</div>
</div>
<div class="story-content">
<h3>Three Generations at Sea</h3>
<p>"From grandma to the kids, everyone had a blast. The crew made sure everyone felt safe
and included." - The Johnson Family</p>
<a href="about.html#testimonials" class="story-link">Read their story →</a>
</div>
</div>
</div>
</div>
</section>
<!-- Gallery Section -->
<section class="gallery-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Life on the Water</h2>
<p class="section-subtitle">Moments captured from our adventures</p>
</div>
<div class="image-gallery">
<div class="gallery-item large">
<img src="golden_gate.jpg" alt="Golden Gate Bridge view">
<div class="gallery-overlay">
<span class="gallery-caption">Sailing the Bay</span>
</div>
</div>
<div class="gallery-item">
<img src="yacht_party_couple_holding_hands.jpg" alt="Romantic moments">
<div class="gallery-overlay">
<span class="gallery-caption">Unforgettable Moments</span>
</div>
</div>
<div class="gallery-item">
<img src="diver.jpg" alt="Underwater adventures">
<div class="gallery-overlay">
<span class="gallery-caption">Dive Deep</span>
</div>
</div>
<div class="gallery-item">
<img src="logo.jpg" alt="HarborSmith">
<div class="gallery-overlay">
<span class="gallery-caption">Your Trusted Partner</span>
</div>
</div>
</div>
</div>
</section>
<!-- Interactive Booking CTA -->
<section class="booking-cta">
<div class="booking-container">
<div class="booking-content">
<h2 class="booking-title">Ready to Create Your Story?</h2>
<p class="booking-subtitle">
Join hundreds of happy adventurers who've discovered the magic of San Francisco Bay
</p>
<div class="booking-options">
<div class="booking-card">
<span class="booking-icon">
<i data-lucide="calendar"></i>
</span>
<h3>Plan Your Charter</h3>
<p>Choose your perfect date and yacht</p>
<button class="btn-booking" onclick="window.location.href='charter-booking-1.html'">Start Planning</button>
</div>
<div class="booking-card featured">
<span class="booking-icon">
<i data-lucide="message-circle"></i>
</span>
<h3>Talk to a Captain</h3>
<p>Get personalized recommendations</p>
<button class="btn-booking primary" onclick="window.location.href='tel:415-555-0123'">Call (415) 555-0123</button>
</div>
<div class="booking-card">
<span class="booking-icon">
<i data-lucide="gift"></i>
</span>
<h3>Gift a Charter</h3>
<p>Give the gift of adventure</p>
<button class="btn-booking" onclick="window.location.href='charter.html'">Buy Gift Card</button>
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="voyage-footer">
<div class="footer-container">
<div class="footer-content">
<div class="footer-brand">
<img src="logo.jpg" alt="HarborSmith" class="footer-logo">
<h3>HarborSmith</h3>
<p>Your trusted partner for unforgettable Bay Area yacht experiences since 2009</p>
<div class="social-links">
<a href="#" aria-label="Facebook"><i data-lucide="facebook"></i></a>
<a href="#" aria-label="Instagram"><i data-lucide="instagram"></i></a>
<a href="#" aria-label="Twitter"><i data-lucide="twitter"></i></a>
</div>
</div>
<div class="footer-links">
<h4>Quick Links</h4>
<a href="charter.html">Our Fleet</a>
<a href="charter.html#pricing">Pricing</a>
<a href="about.html#safety">Safety</a>
<a href="faq.html">FAQ</a>
</div>
<div class="footer-contact">
<h4>Get in Touch</h4>
<p><i data-lucide="map-pin" class="footer-icon"></i> Pier 39, San Francisco, CA</p>
<p><i data-lucide="phone" class="footer-icon"></i> (415) 555-0123</p>
<p><i data-lucide="mail" class="footer-icon"></i> hello@harborsmith.com</p>
<p><i data-lucide="clock" class="footer-icon"></i> Open 7 days, 8am-8pm</p>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2024 HarborSmith Yacht Services. All rights reserved.</p>
</div>
</div>
</footer>
<!-- Layout Switcher -->
<script src="js/voyage-layout.js"></script>
<script>
// Initialize Lucide icons after DOM is ready
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
});
</script>
</body>
</html>

464
website-mockups/index.html Normal file
View File

@@ -0,0 +1,464 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Harbor Smith - Personalized Service Maintenance For Your Boat</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<!-- Lucide Icons -->
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="css/voyage-layout.css">
<link rel="stylesheet" href="css/themes.css">
</head>
<body>
<!-- Navigation (Minimal, appears on scroll) -->
<nav class="voyage-nav" id="voyageNav">
<div class="nav-container">
<div class="nav-brand">
<img src="HARBOR-SMITH-white.png" alt="Harbor Smith" class="nav-logo" id="navLogo">
<span>HARBOR SMITH</span>
</div>
<div class="nav-links">
<a href="#services" class="nav-link">Services</a>
<a href="#testimonials" class="nav-link">Testimonials</a>
<a href="#contact" class="nav-link">Contact</a>
<a href="tel:510-701-2535" class="nav-link nav-cta">Call Now</a>
</div>
</div>
</nav>
<!-- Hero Section with Video Background -->
<section class="hero-voyage" id="heroSection">
<!-- Video Background with local fallback -->
<div class="hero-video-container">
<video autoplay loop muted playsinline class="hero-video">
<source src="https://videos.pexels.com/video-files/3571264/3571264-uhd_2560_1440_30fps.mp4" type="video/mp4">
</video>
<!-- Fallback image if video fails -->
<div class="hero-image-fallback" style="background-image: url('public/golden_gate.jpg');"></div>
<!-- Warm gradient overlays -->
<div class="hero-overlay gradient-warm"></div>
<div class="hero-overlay gradient-depth"></div>
</div>
<!-- Hero Content -->
<div class="hero-content">
<!-- Logo (bigger) -->
<div class="hero-logo animate-fade-in">
<img src="HARBOR-SMITH-white.png" alt="Harbor Smith" style="height: 250px; margin: 40px 0;">
</div>
<!-- Trust Indicators -->
<div class="trust-badge animate-fade-in">
<div class="stars">
<span class="stars-icons">
<i data-lucide="star" class="star-filled"></i>
<i data-lucide="star" class="star-filled"></i>
<i data-lucide="star" class="star-filled"></i>
<i data-lucide="star" class="star-filled"></i>
<i data-lucide="star" class="star-filled"></i>
</span>
</div>
<span>Trusted by 0+ seafarers</span>
</div>
<!-- Subtext -->
<p class="hero-subtext animate-fade-up-delay">
<span style="font-size: 1.5rem; font-weight: 500; text-transform: none; letter-spacing: normal; margin-bottom: 10px; display: block;">
Personalized Service Maintenance for Your Boat
</span>
Keep your vessel pristine with San Francisco Bay's premier mobile boat maintenance service.
</p>
<!-- CTA Buttons -->
<div class="hero-actions animate-fade-up-delay-2">
<button class="btn-primary-warm" onclick="window.location.href='tel:510-701-2535'">
<i data-lucide="phone" class="btn-icon"></i>
Call (510) 701-2535
</button>
<button class="btn-secondary-warm" onclick="window.location.href='#services'">
<i data-lucide="wrench" class="btn-icon"></i>
View Our Services
</button>
</div>
<!-- Scroll Indicator -->
<div class="scroll-indicator">
<span>Scroll to explore</span>
<div class="scroll-arrow">
<i data-lucide="chevron-down"></i>
</div>
</div>
</div>
</section>
<!-- Welcome Section -->
<section class="welcome-section">
<div class="container">
<div class="welcome-content">
<div class="welcome-text">
<h2 class="section-title warm">Why Choose Harbor Smith?</h2>
<p class="lead-text">
We're the San Francisco Bay Area's premier mobile boat maintenance service.
Our professional team brings expert care directly to your dock, ensuring your vessel stays in pristine condition year-round.
</p>
<div class="feature-list">
<div class="feature-item">
<span class="feature-icon">
<i data-lucide="truck"></i>
</span>
<div>
<h4>Mobile Service</h4>
<p>We come to you - convenient service at your dock or marina</p>
</div>
</div>
<div class="feature-item">
<span class="feature-icon">
<i data-lucide="shield-check"></i>
</span>
<div>
<h4>Certified Professionals</h4>
<p>Experienced technicians with marine industry certifications</p>
</div>
</div>
<div class="feature-item">
<span class="feature-icon">
<i data-lucide="calendar-check"></i>
</span>
<div>
<h4>Reliable & Consistent</h4>
<p>Regular maintenance schedules tailored to your needs</p>
</div>
</div>
</div>
</div>
<div class="welcome-image">
<img src="leah_1.jpeg" alt="Harbor Smith team member" class="rounded-image">
<div class="image-badge">
<span>10+ Years</span>
<span>of Excellence</span>
</div>
</div>
</div>
</div>
</section>
<!-- Our Services Section -->
<section class="fleet-showcase" id="services">
<div class="container">
<div class="section-header">
<h2 class="section-title">Our Premium Services</h2>
<p class="section-subtitle">Professional boat maintenance tailored to your needs</p>
</div>
<div class="services-grid" style="display: flex; flex-wrap: wrap; gap: 30px; max-width: 1200px; margin: 0 auto; justify-content: center;">
<!-- Service 1: Hull Cleaning -->
<div class="service-card" style="background: white; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); padding: 0; overflow: hidden; text-align: center; flex: 0 1 350px; min-width: 280px;">
<div style="width: 100%; height: 200px; overflow: hidden;">
<img src="diver_cleaning.jpg" alt="Professional hull cleaning service" style="width: 100%; height: 100%; object-fit: cover;">
</div>
<div style="padding: 30px;">
<h3 style="font-size: 24px; margin-bottom: 15px; color: #1e3a5f;">Hull Cleaning</h3>
<p style="color: #666; margin-bottom: 20px;">
Professional underwater hull cleaning to maintain your boat's performance and fuel efficiency.
</p>
<ul style="list-style: none; padding: 0; margin: 20px 0; text-align: left;">
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Removes marine growth</li>
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Improves fuel efficiency</li>
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Extends hull life</li>
</ul>
<button class="btn-primary-warm" onclick="window.location.href='tel:510-701-2535'" style="width: 100%;">Get Quote</button>
</div>
</div>
<!-- Service 2: Exterior Wash & Wax -->
<div class="service-card" style="background: white; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); padding: 0; overflow: hidden; text-align: center; flex: 0 1 350px; min-width: 280px;">
<div style="width: 100%; height: 200px; overflow: hidden;">
<img src="Washdown.jpg" alt="Professional boat wash and wax service" style="width: 100%; height: 100%; object-fit: cover;">
</div>
<div style="padding: 30px;">
<h3 style="font-size: 24px; margin-bottom: 15px; color: #1e3a5f;">Exterior Wash & Wax</h3>
<p style="color: #666; margin-bottom: 20px;">
Complete exterior detailing to keep your boat looking pristine and protected.
</p>
<ul style="list-style: none; padding: 0; margin: 20px 0; text-align: left;">
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Deep cleaning wash</li>
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> UV protection wax</li>
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Gel coat restoration</li>
</ul>
<button class="btn-primary-warm" onclick="window.location.href='tel:510-701-2535'" style="width: 100%;">Get Quote</button>
</div>
</div>
<!-- Service 3: Anode Changes -->
<div class="service-card" style="background: white; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); padding: 0; overflow: hidden; text-align: center; flex: 0 1 350px; min-width: 280px;">
<div style="width: 100%; height: 200px; overflow: hidden;">
<img src="Anodes.jpg" alt="Zinc anode replacement service" style="width: 100%; height: 100%; object-fit: cover;">
</div>
<div style="padding: 30px;">
<h3 style="font-size: 24px; margin-bottom: 15px; color: #1e3a5f;">Anode Changes</h3>
<p style="color: #666; margin-bottom: 20px;">
Essential corrosion protection with regular zinc anode inspection and replacement.
</p>
<ul style="list-style: none; padding: 0; margin: 20px 0; text-align: left;">
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Prevents corrosion</li>
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Regular inspection</li>
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Marine-grade materials</li>
</ul>
<button class="btn-primary-warm" onclick="window.location.href='tel:510-701-2535'" style="width: 100%;">Get Quote</button>
</div>
</div>
<!-- Service 4: Interior Detailing -->
<div class="service-card" style="background: white; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); padding: 0; overflow: hidden; text-align: center; flex: 0 1 350px; min-width: 280px;">
<div style="width: 100%; height: 200px; overflow: hidden;">
<img src="Interior.jpg" alt="Professional interior detailing service" style="width: 100%; height: 100%; object-fit: cover;">
</div>
<div style="padding: 30px;">
<h3 style="font-size: 24px; margin-bottom: 15px; color: #1e3a5f;">Interior Detailing</h3>
<p style="color: #666; margin-bottom: 20px;">
Thorough interior cleaning and conditioning for a fresh, comfortable cabin.
</p>
<ul style="list-style: none; padding: 0; margin: 20px 0; text-align: left;">
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Upholstery cleaning</li>
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Mold & mildew treatment</li>
<li style="padding: 8px 0;"><i data-lucide="check" style="color: #4b7cb8; width: 16px; display: inline-block; margin-right: 8px;"></i> Surface conditioning</li>
</ul>
<button class="btn-primary-warm" onclick="window.location.href='tel:510-701-2535'" style="width: 100%;">Get Quote</button>
</div>
</div>
</div>
</div>
</section>
<!-- Trust Indicators Section -->
<section class="services-section">
<div class="container">
<div class="service-stats">
<div class="stat-item">
<i data-lucide="ship" class="stat-icon"></i>
<span class="stat-number">200+</span>
<span class="stat-label">Vessels Maintained</span>
</div>
<div class="stat-item">
<i data-lucide="award" class="stat-icon"></i>
<span class="stat-number">10+</span>
<span class="stat-label">Years Experience</span>
</div>
<div class="stat-item">
<i data-lucide="users" class="stat-icon"></i>
<span class="stat-number">500+</span>
<span class="stat-label">Happy Clients</span>
</div>
<div class="stat-item">
<i data-lucide="shield-check" class="stat-icon"></i>
<span class="stat-number">100%</span>
<span class="stat-label">Mobile Service</span>
</div>
</div>
</div>
</section>
<!-- Testimonials Section -->
<section class="experience-stories" id="testimonials">
<div class="story-container">
<h2 class="section-title center">What Our Customers Say</h2>
<div class="testimonial-highlight" style="max-width: 800px; margin: 40px auto; padding: 40px; background: white; border-radius: 15px; box-shadow: 0 8px 30px rgba(0,0,0,0.1); text-align: center;">
<div class="stars" style="margin-bottom: 20px;">
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 24px; height: 24px; display: inline-block;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 24px; height: 24px; display: inline-block;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 24px; height: 24px; display: inline-block;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 24px; height: 24px; display: inline-block;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 24px; height: 24px; display: inline-block;"></i>
</div>
<blockquote style="font-size: 22px; color: #1e3a5f; font-style: italic; line-height: 1.6; margin-bottom: 20px;">
"They do an amazing job and are always reliable! I never have to worry about my boat's condition."
</blockquote>
<cite style="font-weight: 600; color: #4b7cb8; font-size: 18px;">— John D.</cite>
</div>
<div class="stories-grid" style="display: flex; flex-wrap: wrap; gap: 30px; justify-content: center; max-width: 1200px; margin: 0 auto;">
<!-- Additional testimonial cards -->
<div class="story-card" style="flex: 0 1 350px; min-width: 280px;">
<div class="story-content">
<div class="stars" style="margin-bottom: 15px;">
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
</div>
<h3>Professional Service</h3>
<p>"Harbor Smith keeps my boat in pristine condition. Their attention to detail is unmatched."</p>
<span style="color: #4b7cb8; font-weight: 600;">— Michael R.</span>
</div>
</div>
<div class="story-card" style="flex: 0 1 350px; min-width: 280px;">
<div class="story-content">
<div class="stars" style="margin-bottom: 15px;">
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
</div>
<h3>Convenient & Reliable</h3>
<p>"Mobile service that comes to my dock - it doesn't get better than that! Highly recommended."</p>
<span style="color: #4b7cb8; font-weight: 600;">— Sarah L.</span>
</div>
</div>
<div class="story-card" style="flex: 0 1 350px; min-width: 280px;">
<div class="story-content">
<div class="stars" style="margin-bottom: 15px;">
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
<i data-lucide="star" style="color: #fbbf24; fill: #fbbf24; width: 18px; height: 18px;"></i>
</div>
<h3>Excellent Value</h3>
<p>"Fair pricing and exceptional quality. They've been maintaining my yacht for 5 years now."</p>
<span style="color: #4b7cb8; font-weight: 600;">— David K.</span>
</div>
</div>
</div>
</div>
</section>
<!-- Gallery Section -->
<section class="gallery-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Our Work in Action</h2>
<p class="section-subtitle">Professional maintenance services delivered with care</p>
</div>
<div class="image-gallery">
<div class="gallery-item large">
<img src="diver_cleaning_2.jpg" alt="Professional hull cleaning">
<div class="gallery-overlay">
<span class="gallery-caption">Expert Hull Cleaning</span>
</div>
</div>
<div class="gallery-item">
<img src="ExtCleaning.jpg" alt="Exterior cleaning service">
<div class="gallery-overlay">
<span class="gallery-caption">Detailed Cleaning</span>
</div>
</div>
<div class="gallery-item">
<img src="Washdown2.jpg" alt="Professional washdown">
<div class="gallery-overlay">
<span class="gallery-caption">Thorough Washdown</span>
</div>
</div>
<div class="gallery-item">
<img src="Helm.jpg" alt="Interior maintenance">
<div class="gallery-overlay">
<span class="gallery-caption">Interior Care</span>
</div>
</div>
<div class="gallery-item">
<img src="Foredeck.jpg" alt="Deck maintenance">
<div class="gallery-overlay">
<span class="gallery-caption">Deck Service</span>
</div>
</div>
<div class="gallery-item">
<img src="Waxing.jpg" alt="Boat waxing service">
<div class="gallery-overlay">
<span class="gallery-caption">Protective Waxing</span>
</div>
</div>
</div>
</div>
</section>
<!-- Interactive Booking CTA -->
<section class="booking-cta" style="background: linear-gradient(135deg, rgba(30, 58, 95, 0.9), rgba(75, 124, 184, 0.85)), url('sf_bay_exposure.jpg') center/cover no-repeat; position: relative;">
<div class="booking-container">
<div class="booking-content">
<h2 class="booking-title">Ready to Schedule Your Service?</h2>
<p class="booking-subtitle">
Join hundreds of boat owners who trust Harbor Smith for professional maintenance
</p>
<div class="booking-options">
<div class="booking-card">
<span class="booking-icon">
<i data-lucide="calendar"></i>
</span>
<h3>Schedule Service</h3>
<p>Book your maintenance appointment</p>
<button class="btn-booking" onclick="window.location.href='maintenance-booking.html'">Book Now</button>
</div>
<div class="booking-card featured">
<span class="booking-icon">
<i data-lucide="phone"></i>
</span>
<h3>Call Us Today</h3>
<p>Get a personalized quote</p>
<button class="btn-booking primary" onclick="window.location.href='tel:510-701-2535'">Call (510) 701-2535</button>
</div>
<div class="booking-card">
<span class="booking-icon">
<i data-lucide="mail"></i>
</span>
<h3>Email Us</h3>
<p>Send us your service request</p>
<button class="btn-booking" onclick="window.location.href='mailto:hello@harborsmith.co'">Contact Us</button>
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="voyage-footer" id="contact">
<div class="footer-container">
<div class="footer-content">
<div class="footer-brand">
<img src="HARBOR-SMITH-white.png" alt="Harbor Smith" class="footer-logo">
<h3>HARBOR SMITH</h3>
<p>Your trusted partner for professional boat maintenance in the San Francisco Bay Area</p>
<div class="social-links">
<a href="#" aria-label="Facebook"><i data-lucide="facebook"></i></a>
<a href="#" aria-label="Instagram"><i data-lucide="instagram"></i></a>
<a href="#" aria-label="Twitter"><i data-lucide="twitter"></i></a>
</div>
</div>
<div class="footer-contact">
<h4>Get in Touch</h4>
<p><i data-lucide="map-pin" class="footer-icon"></i> San Francisco Bay Area</p>
<p><i data-lucide="phone" class="footer-icon"></i> (510) 701-2535</p>
<p><i data-lucide="mail" class="footer-icon"></i> hello@harborsmith.co</p>
<p><i data-lucide="clock" class="footer-icon"></i> Mobile Service Available 7 Days</p>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2025 Harbor Smith Boat Maintenance Services. All rights reserved.</p>
</div>
</div>
</footer>
<!-- Layout Switcher -->
<script src="js/voyage-layout.js"></script>
<script>
// Initialize Lucide icons after DOM is ready
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
});
</script>
</body>
</html>

View File

@@ -0,0 +1,349 @@
// HarborSmith - Animation Scripts
// ================================
// Scroll Animation Observer
const scrollAnimations = {
init() {
this.observeElements();
this.initProgressBars();
this.initTextAnimations();
},
observeElements() {
const options = {
threshold: 0.1,
rootMargin: '0px 0px -100px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
// Trigger specific animations
if (entry.target.classList.contains('counter-animate')) {
this.animateValue(entry.target);
}
// Only animate once
if (!entry.target.classList.contains('repeat-animation')) {
observer.unobserve(entry.target);
}
}
});
}, options);
// Observe all animated elements
const animatedElements = document.querySelectorAll('.scroll-animate, .scroll-animate-left, .scroll-animate-right, .scroll-animate-scale, .counter-animate');
animatedElements.forEach(el => observer.observe(el));
},
animateValue(element) {
const target = parseInt(element.dataset.target);
const duration = parseInt(element.dataset.duration) || 2000;
const start = 0;
const increment = target / (duration / 16);
let current = start;
const updateValue = () => {
current += increment;
if (current < target) {
element.textContent = Math.floor(current);
requestAnimationFrame(updateValue);
} else {
element.textContent = target;
}
};
updateValue();
},
initProgressBars() {
const progressBars = document.querySelectorAll('.progress-bar-fill');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const progressBar = entry.target;
const targetWidth = progressBar.dataset.progress || '100';
progressBar.style.setProperty('--progress', targetWidth + '%');
progressBar.classList.add('animate');
observer.unobserve(progressBar);
}
});
}, { threshold: 0.5 });
progressBars.forEach(bar => observer.observe(bar));
},
initTextAnimations() {
const textElements = document.querySelectorAll('.text-animate');
textElements.forEach(element => {
const text = element.textContent;
element.textContent = '';
[...text].forEach((char, index) => {
const span = document.createElement('span');
span.textContent = char === ' ' ? '\u00A0' : char;
span.style.animationDelay = `${index * 0.05}s`;
span.classList.add('char-animate');
element.appendChild(span);
});
});
}
};
// Cursor Effects
const cursorEffects = {
init() {
this.cursor = document.createElement('div');
this.cursor.className = 'custom-cursor';
document.body.appendChild(this.cursor);
this.follower = document.createElement('div');
this.follower.className = 'cursor-follower';
document.body.appendChild(this.follower);
this.initEventListeners();
},
initEventListeners() {
document.addEventListener('mousemove', (e) => {
this.cursor.style.left = e.clientX + 'px';
this.cursor.style.top = e.clientY + 'px';
setTimeout(() => {
this.follower.style.left = e.clientX + 'px';
this.follower.style.top = e.clientY + 'px';
}, 100);
});
// Add hover effects
const interactiveElements = document.querySelectorAll('a, button, .clickable');
interactiveElements.forEach(el => {
el.addEventListener('mouseenter', () => {
this.cursor.classList.add('hover');
this.follower.classList.add('hover');
});
el.addEventListener('mouseleave', () => {
this.cursor.classList.remove('hover');
this.follower.classList.remove('hover');
});
});
}
};
// Ripple Effect
const rippleEffect = {
init() {
const buttons = document.querySelectorAll('.btn, .ripple');
buttons.forEach(button => {
button.addEventListener('click', (e) => {
const ripple = document.createElement('span');
ripple.className = 'ripple-effect';
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
button.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 600);
});
});
}
};
// Magnetic Buttons
const magneticButtons = {
init() {
const magneticElements = document.querySelectorAll('.magnetic');
magneticElements.forEach(element => {
element.addEventListener('mousemove', (e) => {
const rect = element.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
element.style.transform = `translate(${x * 0.2}px, ${y * 0.2}px)`;
});
element.addEventListener('mouseleave', () => {
element.style.transform = 'translate(0, 0)';
});
});
}
};
// Page Loader
const pageLoader = {
init() {
const loader = document.createElement('div');
loader.className = 'page-loader';
loader.innerHTML = `
<div class="loader-content">
<div class="loader-ship">
<svg width="60" height="60" viewBox="0 0 60 60">
<path d="M30 10 L45 40 L15 40 Z" fill="none" stroke="currentColor" stroke-width="2"/>
<path d="M30 40 L30 50" stroke="currentColor" stroke-width="2"/>
<path d="M20 50 L40 50" stroke="currentColor" stroke-width="2"/>
</svg>
</div>
<div class="loader-text">Setting Sail...</div>
</div>
`;
document.body.appendChild(loader);
window.addEventListener('load', () => {
setTimeout(() => {
loader.classList.add('fade-out');
setTimeout(() => {
loader.remove();
}, 500);
}, 1000);
});
}
};
// Smooth Page Transitions
const pageTransitions = {
init() {
const links = document.querySelectorAll('a[href^="/"], a[href^="./"], a[href$=".html"]');
links.forEach(link => {
link.addEventListener('click', (e) => {
const href = link.getAttribute('href');
// Skip if it's an anchor link or external link
if (href.startsWith('#') || href.startsWith('http')) return;
e.preventDefault();
document.body.classList.add('page-transition');
setTimeout(() => {
window.location.href = href;
}, 500);
});
});
}
};
// Initialize animations
document.addEventListener('DOMContentLoaded', () => {
scrollAnimations.init();
rippleEffect.init();
magneticButtons.init();
// Uncomment these for production
// cursorEffects.init();
// pageLoader.init();
// pageTransitions.init();
});
// Add some CSS for the loader (normally would be in a separate file)
const loaderStyles = `
<style>
.page-loader {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
transition: opacity 0.5s;
}
.page-loader.fade-out {
opacity: 0;
pointer-events: none;
}
.loader-content {
text-align: center;
color: white;
}
.loader-ship {
animation: float 2s ease-in-out infinite;
margin-bottom: 20px;
}
.loader-text {
font-size: 1.5rem;
font-weight: 600;
animation: pulse 2s ease-in-out infinite;
}
.custom-cursor {
width: 10px;
height: 10px;
background: var(--primary);
border-radius: 50%;
position: fixed;
pointer-events: none;
z-index: 9998;
transform: translate(-50%, -50%);
transition: transform 0.2s, background 0.2s;
}
.cursor-follower {
width: 30px;
height: 30px;
border: 2px solid var(--primary);
border-radius: 50%;
position: fixed;
pointer-events: none;
z-index: 9997;
transform: translate(-50%, -50%);
transition: transform 0.3s, border-color 0.2s;
}
.custom-cursor.hover,
.cursor-follower.hover {
transform: translate(-50%, -50%) scale(1.5);
}
.ripple-effect {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
animation: ripple 0.6s ease-out;
pointer-events: none;
}
.char-animate {
display: inline-block;
opacity: 0;
animation: fadeInUp 0.5s ease-out forwards;
}
.page-transition {
animation: fadeOut 0.5s ease-out;
}
@keyframes fadeOut {
to {
opacity: 0;
transform: translateY(20px);
}
}
</style>
`;
// Inject loader styles
document.head.insertAdjacentHTML('beforeend', loaderStyles);

View File

@@ -0,0 +1,375 @@
// Bento Grid Layout JavaScript
document.addEventListener('DOMContentLoaded', function() {
// Menu Toggle
const menuToggle = document.getElementById('menuToggle');
const menuOverlay = document.getElementById('menuOverlay');
const menuClose = document.getElementById('menuClose');
menuToggle.addEventListener('click', () => {
menuOverlay.classList.add('active');
});
menuClose.addEventListener('click', () => {
menuOverlay.classList.remove('active');
});
// Filter Toggle
const filterToggle = document.getElementById('filterToggle');
const filterBar = document.getElementById('filterBar');
filterToggle.addEventListener('click', () => {
filterBar.classList.toggle('active');
});
// Filter Functionality
const filterChips = document.querySelectorAll('.filter-chip');
const bentoTiles = document.querySelectorAll('.bento-tile');
filterChips.forEach(chip => {
chip.addEventListener('click', () => {
// Update active state
filterChips.forEach(c => c.classList.remove('active'));
chip.classList.add('active');
const filter = chip.dataset.filter;
// Filter tiles
bentoTiles.forEach(tile => {
if (filter === 'all' || tile.dataset.category === filter) {
tile.classList.remove('hiding');
tile.classList.add('showing');
} else {
tile.classList.add('hiding');
tile.classList.remove('showing');
}
});
});
});
// FAB Menu
const fabBtn = document.getElementById('fabBtn');
const fabMenu = document.getElementById('fabMenu');
fabBtn.addEventListener('click', () => {
fabMenu.classList.toggle('active');
});
// FAB Options
const fabOptions = document.querySelectorAll('.fab-option');
fabOptions.forEach(option => {
option.addEventListener('click', () => {
const action = option.dataset.action;
switch(action) {
case 'chat':
alert('Opening chat...');
break;
case 'call':
window.location.href = 'tel:4155550123';
break;
case 'book':
window.location.href = 'charter.html';
break;
}
fabMenu.classList.remove('active');
});
});
// Quick View for Yachts
const quickViewBtns = document.querySelectorAll('.quick-view-btn');
quickViewBtns.forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const yachtTile = btn.closest('.tile-yacht');
const yachtName = yachtTile.querySelector('.yacht-name').textContent;
// Create modal
const modal = document.createElement('div');
modal.className = 'yacht-modal';
modal.innerHTML = `
<div class="modal-content">
<button class="modal-close">&times;</button>
<h2>${yachtName}</h2>
<div class="modal-gallery">
<img src="${yachtTile.querySelector('img').src}" alt="${yachtName}">
</div>
<div class="modal-details">
<h3>Specifications</h3>
<ul>
<li>Length: 120ft</li>
<li>Capacity: 12 Guests</li>
<li>Cabins: 5</li>
<li>Crew: Full Professional Crew</li>
<li>Amenities: Jacuzzi, Water Toys, Full Bar</li>
</ul>
<div class="modal-actions">
<button class="btn-primary">Book Now</button>
<button class="btn-secondary">Request Info</button>
</div>
</div>
</div>
`;
document.body.appendChild(modal);
// Add styles
const modalStyles = `
.yacht-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 300;
animation: fadeIn 0.3s ease;
}
.modal-content {
background: white;
border-radius: 20px;
padding: 2rem;
max-width: 600px;
width: 90%;
max-height: 90vh;
overflow-y: auto;
position: relative;
animation: slideUp 0.3s ease;
}
.modal-close {
position: absolute;
top: 1rem;
right: 1rem;
background: transparent;
border: none;
font-size: 2rem;
cursor: pointer;
}
.modal-gallery img {
width: 100%;
border-radius: 10px;
margin: 1rem 0;
}
.modal-details h3 {
margin: 1.5rem 0 1rem;
}
.modal-details ul {
list-style: none;
padding: 0;
}
.modal-details li {
padding: 0.5rem 0;
border-bottom: 1px solid #e2e8f0;
}
.modal-actions {
display: flex;
gap: 1rem;
margin-top: 2rem;
}
.modal-actions button {
flex: 1;
padding: 0.75rem;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`;
if (!document.getElementById('modal-styles')) {
const styleSheet = document.createElement('style');
styleSheet.id = 'modal-styles';
styleSheet.textContent = modalStyles;
document.head.appendChild(styleSheet);
}
// Close modal
modal.querySelector('.modal-close').addEventListener('click', () => {
modal.remove();
});
modal.addEventListener('click', (e) => {
if (e.target === modal) {
modal.remove();
}
});
});
});
// Wishlist functionality
let wishlist = [];
const wishlistSidebar = document.getElementById('wishlistSidebar');
const wishlistContent = document.getElementById('wishlistContent');
// Add to wishlist buttons (would be added to tiles)
bentoTiles.forEach(tile => {
if (tile.classList.contains('tile-yacht') || tile.classList.contains('tile-experience')) {
const wishlistBtn = document.createElement('button');
wishlistBtn.className = 'wishlist-add';
wishlistBtn.innerHTML = '♡';
wishlistBtn.style.cssText = `
position: absolute;
top: 1rem;
left: 1rem;
background: white;
border: none;
width: 40px;
height: 40px;
border-radius: 50%;
font-size: 1.5rem;
cursor: pointer;
z-index: 10;
transition: all 0.3s ease;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
`;
tile.appendChild(wishlistBtn);
wishlistBtn.addEventListener('click', (e) => {
e.stopPropagation();
const itemName = tile.querySelector('h3').textContent;
if (wishlistBtn.innerHTML === '♡') {
wishlistBtn.innerHTML = '❤️';
wishlist.push(itemName);
updateWishlist();
} else {
wishlistBtn.innerHTML = '♡';
wishlist = wishlist.filter(item => item !== itemName);
updateWishlist();
}
});
}
});
function updateWishlist() {
if (wishlist.length === 0) {
wishlistContent.innerHTML = '<p class="wishlist-empty">Select yachts and experiences to build your dream charter</p>';
} else {
wishlistContent.innerHTML = `
<h4>Selected Items (${wishlist.length})</h4>
<ul style="list-style: none; padding: 0;">
${wishlist.map(item => `
<li style="padding: 0.75rem; background: #f8fafc; margin-bottom: 0.5rem; border-radius: 8px;">
${item}
</li>
`).join('')}
</ul>
`;
}
}
// Show wishlist
document.addEventListener('keydown', (e) => {
if (e.key === 'w' && e.ctrlKey) {
e.preventDefault();
wishlistSidebar.classList.toggle('active');
}
});
document.getElementById('wishlistClose').addEventListener('click', () => {
wishlistSidebar.classList.remove('active');
});
// Parallax effect on scroll
let ticking = false;
function updateParallax() {
const scrolled = window.pageYOffset;
const heroTile = document.querySelector('.tile-hero');
if (heroTile) {
const heroVisual = heroTile.querySelector('.hero-visual');
if (heroVisual) {
heroVisual.style.transform = `translateY(${scrolled * 0.3}px)`;
}
}
ticking = false;
}
function requestTick() {
if (!ticking) {
window.requestAnimationFrame(updateParallax);
ticking = true;
}
}
window.addEventListener('scroll', requestTick);
// Auto-play/pause videos on visibility
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const video = entry.target.querySelector('video');
if (video) {
if (entry.isIntersecting) {
video.play();
} else {
video.pause();
}
}
});
}, { threshold: 0.5 });
document.querySelectorAll('.tile-video, .tile-hero').forEach(tile => {
observer.observe(tile);
});
// Tile click navigation
bentoTiles.forEach(tile => {
if (!tile.classList.contains('tile-yacht')) {
tile.addEventListener('click', () => {
if (tile.classList.contains('tile-service')) {
window.location.href = 'maintenance.html';
} else if (tile.classList.contains('tile-experience')) {
window.location.href = 'charter.html';
} else if (tile.classList.contains('tile-cta')) {
window.location.href = 'charter.html';
}
});
}
});
// Smooth hover effects
bentoTiles.forEach(tile => {
tile.addEventListener('mouseenter', () => {
tile.style.zIndex = '10';
});
tile.addEventListener('mouseleave', () => {
setTimeout(() => {
tile.style.zIndex = '';
}, 300);
});
});
});

View File

@@ -0,0 +1,89 @@
// HarborSmith - Booking JavaScript
// ================================
// Calendar functionality
document.addEventListener('DOMContentLoaded', () => {
// Calendar day selection
const calendarDays = document.querySelectorAll('.calendar-day.available');
calendarDays.forEach(day => {
day.addEventListener('click', function() {
// Remove previous selection
document.querySelector('.calendar-day.selected')?.classList.remove('selected');
// Add selection to clicked day
this.classList.add('selected');
// Update summary
updateBookingSummary();
});
});
// Duration selection
const durationOptions = document.querySelectorAll('input[name="duration"]');
durationOptions.forEach(option => {
option.addEventListener('change', updateBookingSummary);
});
// Guest number input
const guestInput = document.querySelector('input[type="number"]');
if (guestInput) {
guestInput.addEventListener('change', updateBookingSummary);
}
// Yacht selection (for booking page 2)
const yachtCards = document.querySelectorAll('.yacht-select-card');
yachtCards.forEach(card => {
card.addEventListener('click', function() {
// Remove previous selection
document.querySelector('.yacht-select-card.selected')?.classList.remove('selected');
// Add selection
this.classList.add('selected');
updateBookingSummary();
});
});
// Addon selection (for booking page 3)
const addonCards = document.querySelectorAll('.addon-card');
addonCards.forEach(card => {
card.addEventListener('click', function() {
this.classList.toggle('selected');
updateBookingSummary();
});
});
});
// Update booking summary
function updateBookingSummary() {
// This would normally update the summary sidebar with selected options
console.log('Updating booking summary...');
}
// Form validation for final step
function validateBookingForm() {
const form = document.getElementById('bookingForm');
if (!form) return true;
const inputs = form.querySelectorAll('[required]');
let isValid = true;
inputs.forEach(input => {
if (!input.value.trim()) {
input.classList.add('error');
isValid = false;
} else {
input.classList.remove('error');
}
});
return isValid;
}
// Handle form submission
const bookingForm = document.getElementById('bookingForm');
if (bookingForm) {
bookingForm.addEventListener('submit', (e) => {
e.preventDefault();
if (validateBookingForm()) {
alert('Thank you for your booking request! We will contact you shortly to confirm your charter.');
// In production, this would submit to a server
}
});
}

View File

@@ -0,0 +1,339 @@
// HarborSmith - Main JavaScript
// ========================
// Theme Management
const themeManager = {
init() {
this.themeToggle = document.getElementById('themeToggle');
this.themeDropdown = document.getElementById('themeDropdown');
this.themeOptions = document.querySelectorAll('.theme-option');
// Load saved theme or default to nautical
const savedTheme = localStorage.getItem('harborsmith-theme') || 'nautical';
this.setTheme(savedTheme);
// Event listeners
this.themeToggle?.addEventListener('click', (e) => {
e.stopPropagation();
this.themeDropdown.classList.toggle('active');
});
this.themeOptions.forEach(option => {
option.addEventListener('click', (e) => {
const theme = e.currentTarget.dataset.theme;
this.setTheme(theme);
this.themeDropdown.classList.remove('active');
});
});
// Close dropdown when clicking outside
document.addEventListener('click', () => {
this.themeDropdown?.classList.remove('active');
});
},
setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('harborsmith-theme', theme);
// Update active state
this.themeOptions.forEach(option => {
option.classList.toggle('active', option.dataset.theme === theme);
});
}
};
// Navigation
const navigation = {
init() {
this.navbar = document.getElementById('navbar');
this.navToggle = document.getElementById('navToggle');
this.navMenu = document.getElementById('navMenu');
this.navLinks = document.querySelectorAll('.nav-link');
// Mobile menu toggle
this.navToggle?.addEventListener('click', () => {
this.navToggle.classList.toggle('active');
this.navMenu.classList.toggle('active');
});
// Close mobile menu on link click
this.navLinks.forEach(link => {
link.addEventListener('click', () => {
this.navToggle?.classList.remove('active');
this.navMenu?.classList.remove('active');
});
});
// Scroll behavior
window.addEventListener('scroll', () => {
if (window.scrollY > 50) {
this.navbar?.classList.add('scrolled');
} else {
this.navbar?.classList.remove('scrolled');
}
});
// Active link highlighting
this.updateActiveLink();
},
updateActiveLink() {
const currentPath = window.location.pathname.split('/').pop() || 'index.html';
this.navLinks.forEach(link => {
const href = link.getAttribute('href');
if (href === currentPath) {
link.classList.add('active');
}
});
}
};
// Smooth Scrolling
const smoothScroll = {
init() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', (e) => {
e.preventDefault();
const target = document.querySelector(anchor.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
};
// Testimonial Slider
const testimonialSlider = {
init() {
this.cards = document.querySelectorAll('.testimonial-card');
this.dots = document.querySelectorAll('.dot');
this.currentIndex = 0;
if (this.cards.length === 0) return;
// Auto-play
this.startAutoPlay();
// Dot navigation
this.dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
this.goToSlide(index);
this.resetAutoPlay();
});
});
},
goToSlide(index) {
this.cards[this.currentIndex]?.classList.remove('active');
this.dots[this.currentIndex]?.classList.remove('active');
this.currentIndex = index;
this.cards[this.currentIndex]?.classList.add('active');
this.dots[this.currentIndex]?.classList.add('active');
},
nextSlide() {
const nextIndex = (this.currentIndex + 1) % this.cards.length;
this.goToSlide(nextIndex);
},
startAutoPlay() {
this.autoPlayInterval = setInterval(() => {
this.nextSlide();
}, 5000);
},
resetAutoPlay() {
clearInterval(this.autoPlayInterval);
this.startAutoPlay();
}
};
// Counter Animation
const counterAnimation = {
init() {
this.counters = document.querySelectorAll('.stat-number');
this.animated = false;
if (this.counters.length === 0) return;
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting && !this.animated) {
this.animateCounters();
this.animated = true;
}
});
}, { threshold: 0.5 });
const statsSection = document.querySelector('.stats-section');
if (statsSection) {
observer.observe(statsSection);
}
},
animateCounters() {
this.counters.forEach(counter => {
const target = parseInt(counter.dataset.count);
const duration = 2000;
const increment = target / (duration / 16);
let current = 0;
const updateCounter = () => {
current += increment;
if (current < target) {
counter.textContent = Math.floor(current);
requestAnimationFrame(updateCounter);
} else {
counter.textContent = target;
}
};
updateCounter();
});
}
};
// Form Validation
const formValidation = {
init() {
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', (e) => {
if (!this.validateForm(form)) {
e.preventDefault();
}
});
// Real-time validation
const inputs = form.querySelectorAll('input, textarea, select');
inputs.forEach(input => {
input.addEventListener('blur', () => {
this.validateField(input);
});
});
});
},
validateForm(form) {
const inputs = form.querySelectorAll('[required]');
let isValid = true;
inputs.forEach(input => {
if (!this.validateField(input)) {
isValid = false;
}
});
return isValid;
},
validateField(field) {
const value = field.value.trim();
const type = field.type;
let isValid = true;
// Remove previous error
field.classList.remove('error');
const errorMsg = field.parentElement.querySelector('.error-message');
if (errorMsg) {
errorMsg.remove();
}
// Required field
if (field.hasAttribute('required') && !value) {
this.showError(field, 'This field is required');
return false;
}
// Email validation
if (type === 'email' && value) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
this.showError(field, 'Please enter a valid email address');
return false;
}
}
// Phone validation
if (type === 'tel' && value) {
const phoneRegex = /^[\d\s\-\+\(\)]+$/;
if (!phoneRegex.test(value)) {
this.showError(field, 'Please enter a valid phone number');
return false;
}
}
return isValid;
},
showError(field, message) {
field.classList.add('error');
const errorElement = document.createElement('div');
errorElement.className = 'error-message';
errorElement.textContent = message;
field.parentElement.appendChild(errorElement);
}
};
// Yacht Quick View Modal
const yachtModal = {
init() {
const viewButtons = document.querySelectorAll('.yacht-view-btn');
viewButtons.forEach(btn => {
btn.addEventListener('click', (e) => {
e.preventDefault();
this.openModal();
});
});
},
openModal() {
// For now, just alert - in production, would open a modal
alert('Quick view modal would open here with yacht details and 360° view');
}
};
// Parallax Effects
const parallaxEffects = {
init() {
this.elements = document.querySelectorAll('.parallax');
if (this.elements.length === 0) return;
window.addEventListener('scroll', () => {
this.updateParallax();
});
},
updateParallax() {
const scrolled = window.pageYOffset;
this.elements.forEach(element => {
const rate = element.dataset.rate || 0.5;
const yPos = -(scrolled * rate);
element.style.transform = `translateY(${yPos}px)`;
});
}
};
// Initialize everything when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
themeManager.init();
navigation.init();
smoothScroll.init();
testimonialSlider.init();
counterAnimation.init();
formValidation.init();
yachtModal.init();
parallaxEffects.init();
// Log successful initialization
console.log('HarborSmith website initialized successfully!');
});

View File

@@ -0,0 +1,355 @@
// Voyage Layout JavaScript - Smooth, Interactive, Engaging
document.addEventListener('DOMContentLoaded', function() {
// Theme Switcher
const themeToggle = document.getElementById('themeToggle');
const themeDropdown = document.getElementById('themeDropdown');
const themeOptions = document.querySelectorAll('.theme-option');
if (themeToggle && themeDropdown) {
themeToggle.addEventListener('click', (e) => {
e.stopPropagation();
themeDropdown.classList.toggle('active');
});
themeOptions.forEach(option => {
option.addEventListener('click', () => {
const theme = option.dataset.theme;
document.body.className = theme === 'nautical' ? '' : `theme-${theme}`;
localStorage.setItem('selectedTheme', theme);
themeDropdown.classList.remove('active');
});
});
// Close dropdown when clicking outside
document.addEventListener('click', () => {
themeDropdown.classList.remove('active');
});
// Load saved theme
const savedTheme = localStorage.getItem('selectedTheme');
if (savedTheme && savedTheme !== 'nautical') {
document.body.className = `theme-${savedTheme}`;
}
}
// Navigation scroll effect
const nav = document.getElementById('voyageNav');
let lastScroll = 0;
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 50) {
nav.classList.add('scrolled');
} else {
nav.classList.remove('scrolled');
}
lastScroll = currentScroll;
});
// Smooth scroll for navigation links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Parallax effect for hero video
const heroSection = document.getElementById('heroSection');
const heroVideo = document.querySelector('.hero-video-container');
window.addEventListener('scroll', () => {
const scrolled = window.pageYOffset;
const rate = scrolled * 0.5;
if (heroVideo) {
heroVideo.style.transform = `translateY(${rate}px)`;
}
});
// Fleet Carousel
const yachtCards = document.querySelectorAll('.yacht-card');
const dots = document.querySelectorAll('.dot');
const prevBtn = document.querySelector('.fleet-prev');
const nextBtn = document.querySelector('.fleet-next');
let currentYacht = 0;
function showYacht(index) {
yachtCards.forEach(card => card.classList.remove('active'));
dots.forEach(dot => dot.classList.remove('active'));
yachtCards[index].classList.add('active');
dots[index].classList.add('active');
}
if (prevBtn && nextBtn) {
prevBtn.addEventListener('click', () => {
currentYacht = (currentYacht - 1 + yachtCards.length) % yachtCards.length;
showYacht(currentYacht);
});
nextBtn.addEventListener('click', () => {
currentYacht = (currentYacht + 1) % yachtCards.length;
showYacht(currentYacht);
});
}
dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
currentYacht = index;
showYacht(currentYacht);
});
});
// Auto-rotate fleet carousel
setInterval(() => {
if (document.visibilityState === 'visible') {
currentYacht = (currentYacht + 1) % yachtCards.length;
showYacht(currentYacht);
}
}, 5000);
// CTA Button interactions
document.querySelectorAll('.btn-primary-warm, .btn-secondary-warm').forEach(btn => {
btn.addEventListener('click', function(e) {
// Create ripple effect
const ripple = document.createElement('span');
ripple.classList.add('ripple');
this.appendChild(ripple);
const rect = this.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
setTimeout(() => ripple.remove(), 600);
});
});
// Add ripple styles
const style = document.createElement('style');
style.textContent = `
.ripple {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.6);
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
}
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
.btn-primary-warm,
.btn-secondary-warm {
position: relative;
overflow: hidden;
}
`;
document.head.appendChild(style);
// Animate elements on scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -100px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe elements for animation
document.querySelectorAll('.welcome-content, .story-card, .booking-card').forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
el.style.transition = 'all 0.6s ease';
observer.observe(el);
});
// Interactive booking cards
document.querySelectorAll('.booking-card').forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-10px) scale(1.02)';
});
card.addEventListener('mouseleave', function() {
if (this.classList.contains('featured')) {
this.style.transform = 'scale(1.05)';
} else {
this.style.transform = 'translateY(0) scale(1)';
}
});
});
// Phone number click handler
document.querySelectorAll('.btn-booking.primary').forEach(btn => {
if (btn.textContent.includes('415')) {
btn.addEventListener('click', () => {
window.location.href = 'tel:4155550123';
});
}
});
// Video optimization - pause when not visible
const video = document.querySelector('.hero-video');
if (video) {
const videoObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
video.play();
} else {
video.pause();
}
});
}, { threshold: 0.25 });
videoObserver.observe(video);
}
// Story cards hover effect
document.querySelectorAll('.story-card').forEach(card => {
const img = card.querySelector('img');
card.addEventListener('mouseenter', () => {
if (img) {
img.style.transform = 'scale(1.1)';
img.style.transition = 'transform 0.6s ease';
}
});
card.addEventListener('mouseleave', () => {
if (img) {
img.style.transform = 'scale(1)';
}
});
});
// Dynamic trust badge counter - starts from 0
// Target the white text span specifically (the second span in trust-badge)
const trustBadge = document.querySelector('.trust-badge > span:last-child');
if (trustBadge) {
let count = 0;
const targetCount = 500;
const duration = 2000; // 2 seconds
const steps = 50;
const increment = targetCount / steps;
const stepDuration = duration / steps;
// Start with 0
trustBadge.textContent = `Trusted by 0+ adventurers`;
const counter = setInterval(() => {
count += increment;
if (count >= targetCount) {
count = targetCount;
clearInterval(counter);
trustBadge.textContent = `Trusted by 500+ adventurers`;
} else {
trustBadge.textContent = `Trusted by ${Math.floor(count)}+ adventurers`;
}
}, stepDuration);
}
// Remove any duplicate red text that might exist
const allSpans = document.querySelectorAll('.hero-content span');
allSpans.forEach(span => {
// Check if this is the red duplicate text (not inside trust-badge)
if (span.textContent.includes('Trusted by') &&
span.textContent.includes('adventurers') &&
!span.closest('.trust-badge')) {
span.style.display = 'none';
}
});
// Smooth hover for navigation links
document.querySelectorAll('.nav-link').forEach(link => {
link.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-2px)';
});
link.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0)';
});
});
// Mobile menu (would need to add hamburger menu for production)
const mobileMenuBtn = document.createElement('button');
mobileMenuBtn.className = 'mobile-menu-btn';
mobileMenuBtn.innerHTML = '<span></span><span></span><span></span>';
mobileMenuBtn.style.cssText = `
display: none;
flex-direction: column;
gap: 4px;
background: transparent;
border: none;
cursor: pointer;
padding: 0.5rem;
`;
// Add mobile menu styles
const mobileStyles = document.createElement('style');
mobileStyles.textContent = `
@media (max-width: 768px) {
.mobile-menu-btn {
display: flex !important;
}
.mobile-menu-btn span {
width: 24px;
height: 2px;
background: white;
transition: all 0.3s ease;
}
.voyage-nav.scrolled .mobile-menu-btn span {
background: var(--primary-blue);
}
}
`;
document.head.appendChild(mobileStyles);
// Add mobile menu button to nav
const navContainer = document.querySelector('.nav-container');
if (navContainer && window.innerWidth <= 768) {
navContainer.appendChild(mobileMenuBtn);
}
// Loading animation for images
document.querySelectorAll('img').forEach(img => {
// Check if image is already loaded
if (img.complete && img.naturalHeight !== 0) {
img.style.opacity = '1';
} else {
img.style.opacity = '0';
img.addEventListener('load', function() {
this.style.opacity = '1';
});
}
img.style.transition = 'opacity 0.6s ease';
});
console.log('Voyage layout initialized successfully!');
});

View File

@@ -0,0 +1,349 @@
// HarborSmith - Animation Scripts
// ================================
// Scroll Animation Observer
const scrollAnimations = {
init() {
this.observeElements();
this.initProgressBars();
this.initTextAnimations();
},
observeElements() {
const options = {
threshold: 0.1,
rootMargin: '0px 0px -100px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
// Trigger specific animations
if (entry.target.classList.contains('counter-animate')) {
this.animateValue(entry.target);
}
// Only animate once
if (!entry.target.classList.contains('repeat-animation')) {
observer.unobserve(entry.target);
}
}
});
}, options);
// Observe all animated elements
const animatedElements = document.querySelectorAll('.scroll-animate, .scroll-animate-left, .scroll-animate-right, .scroll-animate-scale, .counter-animate');
animatedElements.forEach(el => observer.observe(el));
},
animateValue(element) {
const target = parseInt(element.dataset.target);
const duration = parseInt(element.dataset.duration) || 2000;
const start = 0;
const increment = target / (duration / 16);
let current = start;
const updateValue = () => {
current += increment;
if (current < target) {
element.textContent = Math.floor(current);
requestAnimationFrame(updateValue);
} else {
element.textContent = target;
}
};
updateValue();
},
initProgressBars() {
const progressBars = document.querySelectorAll('.progress-bar-fill');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const progressBar = entry.target;
const targetWidth = progressBar.dataset.progress || '100';
progressBar.style.setProperty('--progress', targetWidth + '%');
progressBar.classList.add('animate');
observer.unobserve(progressBar);
}
});
}, { threshold: 0.5 });
progressBars.forEach(bar => observer.observe(bar));
},
initTextAnimations() {
const textElements = document.querySelectorAll('.text-animate');
textElements.forEach(element => {
const text = element.textContent;
element.textContent = '';
[...text].forEach((char, index) => {
const span = document.createElement('span');
span.textContent = char === ' ' ? '\u00A0' : char;
span.style.animationDelay = `${index * 0.05}s`;
span.classList.add('char-animate');
element.appendChild(span);
});
});
}
};
// Cursor Effects
const cursorEffects = {
init() {
this.cursor = document.createElement('div');
this.cursor.className = 'custom-cursor';
document.body.appendChild(this.cursor);
this.follower = document.createElement('div');
this.follower.className = 'cursor-follower';
document.body.appendChild(this.follower);
this.initEventListeners();
},
initEventListeners() {
document.addEventListener('mousemove', (e) => {
this.cursor.style.left = e.clientX + 'px';
this.cursor.style.top = e.clientY + 'px';
setTimeout(() => {
this.follower.style.left = e.clientX + 'px';
this.follower.style.top = e.clientY + 'px';
}, 100);
});
// Add hover effects
const interactiveElements = document.querySelectorAll('a, button, .clickable');
interactiveElements.forEach(el => {
el.addEventListener('mouseenter', () => {
this.cursor.classList.add('hover');
this.follower.classList.add('hover');
});
el.addEventListener('mouseleave', () => {
this.cursor.classList.remove('hover');
this.follower.classList.remove('hover');
});
});
}
};
// Ripple Effect
const rippleEffect = {
init() {
const buttons = document.querySelectorAll('.btn, .ripple');
buttons.forEach(button => {
button.addEventListener('click', (e) => {
const ripple = document.createElement('span');
ripple.className = 'ripple-effect';
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
button.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 600);
});
});
}
};
// Magnetic Buttons
const magneticButtons = {
init() {
const magneticElements = document.querySelectorAll('.magnetic');
magneticElements.forEach(element => {
element.addEventListener('mousemove', (e) => {
const rect = element.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
element.style.transform = `translate(${x * 0.2}px, ${y * 0.2}px)`;
});
element.addEventListener('mouseleave', () => {
element.style.transform = 'translate(0, 0)';
});
});
}
};
// Page Loader
const pageLoader = {
init() {
const loader = document.createElement('div');
loader.className = 'page-loader';
loader.innerHTML = `
<div class="loader-content">
<div class="loader-ship">
<svg width="60" height="60" viewBox="0 0 60 60">
<path d="M30 10 L45 40 L15 40 Z" fill="none" stroke="currentColor" stroke-width="2"/>
<path d="M30 40 L30 50" stroke="currentColor" stroke-width="2"/>
<path d="M20 50 L40 50" stroke="currentColor" stroke-width="2"/>
</svg>
</div>
<div class="loader-text">Setting Sail...</div>
</div>
`;
document.body.appendChild(loader);
window.addEventListener('load', () => {
setTimeout(() => {
loader.classList.add('fade-out');
setTimeout(() => {
loader.remove();
}, 500);
}, 1000);
});
}
};
// Smooth Page Transitions
const pageTransitions = {
init() {
const links = document.querySelectorAll('a[href^="/"], a[href^="./"], a[href$=".html"]');
links.forEach(link => {
link.addEventListener('click', (e) => {
const href = link.getAttribute('href');
// Skip if it's an anchor link or external link
if (href.startsWith('#') || href.startsWith('http')) return;
e.preventDefault();
document.body.classList.add('page-transition');
setTimeout(() => {
window.location.href = href;
}, 500);
});
});
}
};
// Initialize animations
document.addEventListener('DOMContentLoaded', () => {
scrollAnimations.init();
rippleEffect.init();
magneticButtons.init();
// Uncomment these for production
// cursorEffects.init();
// pageLoader.init();
// pageTransitions.init();
});
// Add some CSS for the loader (normally would be in a separate file)
const loaderStyles = `
<style>
.page-loader {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
transition: opacity 0.5s;
}
.page-loader.fade-out {
opacity: 0;
pointer-events: none;
}
.loader-content {
text-align: center;
color: white;
}
.loader-ship {
animation: float 2s ease-in-out infinite;
margin-bottom: 20px;
}
.loader-text {
font-size: 1.5rem;
font-weight: 600;
animation: pulse 2s ease-in-out infinite;
}
.custom-cursor {
width: 10px;
height: 10px;
background: var(--primary);
border-radius: 50%;
position: fixed;
pointer-events: none;
z-index: 9998;
transform: translate(-50%, -50%);
transition: transform 0.2s, background 0.2s;
}
.cursor-follower {
width: 30px;
height: 30px;
border: 2px solid var(--primary);
border-radius: 50%;
position: fixed;
pointer-events: none;
z-index: 9997;
transform: translate(-50%, -50%);
transition: transform 0.3s, border-color 0.2s;
}
.custom-cursor.hover,
.cursor-follower.hover {
transform: translate(-50%, -50%) scale(1.5);
}
.ripple-effect {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
animation: ripple 0.6s ease-out;
pointer-events: none;
}
.char-animate {
display: inline-block;
opacity: 0;
animation: fadeInUp 0.5s ease-out forwards;
}
.page-transition {
animation: fadeOut 0.5s ease-out;
}
@keyframes fadeOut {
to {
opacity: 0;
transform: translateY(20px);
}
}
</style>
`;
// Inject loader styles
document.head.insertAdjacentHTML('beforeend', loaderStyles);

View File

@@ -0,0 +1,375 @@
// Bento Grid Layout JavaScript
document.addEventListener('DOMContentLoaded', function() {
// Menu Toggle
const menuToggle = document.getElementById('menuToggle');
const menuOverlay = document.getElementById('menuOverlay');
const menuClose = document.getElementById('menuClose');
menuToggle.addEventListener('click', () => {
menuOverlay.classList.add('active');
});
menuClose.addEventListener('click', () => {
menuOverlay.classList.remove('active');
});
// Filter Toggle
const filterToggle = document.getElementById('filterToggle');
const filterBar = document.getElementById('filterBar');
filterToggle.addEventListener('click', () => {
filterBar.classList.toggle('active');
});
// Filter Functionality
const filterChips = document.querySelectorAll('.filter-chip');
const bentoTiles = document.querySelectorAll('.bento-tile');
filterChips.forEach(chip => {
chip.addEventListener('click', () => {
// Update active state
filterChips.forEach(c => c.classList.remove('active'));
chip.classList.add('active');
const filter = chip.dataset.filter;
// Filter tiles
bentoTiles.forEach(tile => {
if (filter === 'all' || tile.dataset.category === filter) {
tile.classList.remove('hiding');
tile.classList.add('showing');
} else {
tile.classList.add('hiding');
tile.classList.remove('showing');
}
});
});
});
// FAB Menu
const fabBtn = document.getElementById('fabBtn');
const fabMenu = document.getElementById('fabMenu');
fabBtn.addEventListener('click', () => {
fabMenu.classList.toggle('active');
});
// FAB Options
const fabOptions = document.querySelectorAll('.fab-option');
fabOptions.forEach(option => {
option.addEventListener('click', () => {
const action = option.dataset.action;
switch(action) {
case 'chat':
alert('Opening chat...');
break;
case 'call':
window.location.href = 'tel:4155550123';
break;
case 'book':
window.location.href = 'charter.html';
break;
}
fabMenu.classList.remove('active');
});
});
// Quick View for Yachts
const quickViewBtns = document.querySelectorAll('.quick-view-btn');
quickViewBtns.forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const yachtTile = btn.closest('.tile-yacht');
const yachtName = yachtTile.querySelector('.yacht-name').textContent;
// Create modal
const modal = document.createElement('div');
modal.className = 'yacht-modal';
modal.innerHTML = `
<div class="modal-content">
<button class="modal-close">&times;</button>
<h2>${yachtName}</h2>
<div class="modal-gallery">
<img src="${yachtTile.querySelector('img').src}" alt="${yachtName}">
</div>
<div class="modal-details">
<h3>Specifications</h3>
<ul>
<li>Length: 120ft</li>
<li>Capacity: 12 Guests</li>
<li>Cabins: 5</li>
<li>Crew: Full Professional Crew</li>
<li>Amenities: Jacuzzi, Water Toys, Full Bar</li>
</ul>
<div class="modal-actions">
<button class="btn-primary">Book Now</button>
<button class="btn-secondary">Request Info</button>
</div>
</div>
</div>
`;
document.body.appendChild(modal);
// Add styles
const modalStyles = `
.yacht-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 300;
animation: fadeIn 0.3s ease;
}
.modal-content {
background: white;
border-radius: 20px;
padding: 2rem;
max-width: 600px;
width: 90%;
max-height: 90vh;
overflow-y: auto;
position: relative;
animation: slideUp 0.3s ease;
}
.modal-close {
position: absolute;
top: 1rem;
right: 1rem;
background: transparent;
border: none;
font-size: 2rem;
cursor: pointer;
}
.modal-gallery img {
width: 100%;
border-radius: 10px;
margin: 1rem 0;
}
.modal-details h3 {
margin: 1.5rem 0 1rem;
}
.modal-details ul {
list-style: none;
padding: 0;
}
.modal-details li {
padding: 0.5rem 0;
border-bottom: 1px solid #e2e8f0;
}
.modal-actions {
display: flex;
gap: 1rem;
margin-top: 2rem;
}
.modal-actions button {
flex: 1;
padding: 0.75rem;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`;
if (!document.getElementById('modal-styles')) {
const styleSheet = document.createElement('style');
styleSheet.id = 'modal-styles';
styleSheet.textContent = modalStyles;
document.head.appendChild(styleSheet);
}
// Close modal
modal.querySelector('.modal-close').addEventListener('click', () => {
modal.remove();
});
modal.addEventListener('click', (e) => {
if (e.target === modal) {
modal.remove();
}
});
});
});
// Wishlist functionality
let wishlist = [];
const wishlistSidebar = document.getElementById('wishlistSidebar');
const wishlistContent = document.getElementById('wishlistContent');
// Add to wishlist buttons (would be added to tiles)
bentoTiles.forEach(tile => {
if (tile.classList.contains('tile-yacht') || tile.classList.contains('tile-experience')) {
const wishlistBtn = document.createElement('button');
wishlistBtn.className = 'wishlist-add';
wishlistBtn.innerHTML = '♡';
wishlistBtn.style.cssText = `
position: absolute;
top: 1rem;
left: 1rem;
background: white;
border: none;
width: 40px;
height: 40px;
border-radius: 50%;
font-size: 1.5rem;
cursor: pointer;
z-index: 10;
transition: all 0.3s ease;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
`;
tile.appendChild(wishlistBtn);
wishlistBtn.addEventListener('click', (e) => {
e.stopPropagation();
const itemName = tile.querySelector('h3').textContent;
if (wishlistBtn.innerHTML === '♡') {
wishlistBtn.innerHTML = '❤️';
wishlist.push(itemName);
updateWishlist();
} else {
wishlistBtn.innerHTML = '♡';
wishlist = wishlist.filter(item => item !== itemName);
updateWishlist();
}
});
}
});
function updateWishlist() {
if (wishlist.length === 0) {
wishlistContent.innerHTML = '<p class="wishlist-empty">Select yachts and experiences to build your dream charter</p>';
} else {
wishlistContent.innerHTML = `
<h4>Selected Items (${wishlist.length})</h4>
<ul style="list-style: none; padding: 0;">
${wishlist.map(item => `
<li style="padding: 0.75rem; background: #f8fafc; margin-bottom: 0.5rem; border-radius: 8px;">
${item}
</li>
`).join('')}
</ul>
`;
}
}
// Show wishlist
document.addEventListener('keydown', (e) => {
if (e.key === 'w' && e.ctrlKey) {
e.preventDefault();
wishlistSidebar.classList.toggle('active');
}
});
document.getElementById('wishlistClose').addEventListener('click', () => {
wishlistSidebar.classList.remove('active');
});
// Parallax effect on scroll
let ticking = false;
function updateParallax() {
const scrolled = window.pageYOffset;
const heroTile = document.querySelector('.tile-hero');
if (heroTile) {
const heroVisual = heroTile.querySelector('.hero-visual');
if (heroVisual) {
heroVisual.style.transform = `translateY(${scrolled * 0.3}px)`;
}
}
ticking = false;
}
function requestTick() {
if (!ticking) {
window.requestAnimationFrame(updateParallax);
ticking = true;
}
}
window.addEventListener('scroll', requestTick);
// Auto-play/pause videos on visibility
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const video = entry.target.querySelector('video');
if (video) {
if (entry.isIntersecting) {
video.play();
} else {
video.pause();
}
}
});
}, { threshold: 0.5 });
document.querySelectorAll('.tile-video, .tile-hero').forEach(tile => {
observer.observe(tile);
});
// Tile click navigation
bentoTiles.forEach(tile => {
if (!tile.classList.contains('tile-yacht')) {
tile.addEventListener('click', () => {
if (tile.classList.contains('tile-service')) {
window.location.href = 'maintenance.html';
} else if (tile.classList.contains('tile-experience')) {
window.location.href = 'charter.html';
} else if (tile.classList.contains('tile-cta')) {
window.location.href = 'charter.html';
}
});
}
});
// Smooth hover effects
bentoTiles.forEach(tile => {
tile.addEventListener('mouseenter', () => {
tile.style.zIndex = '10';
});
tile.addEventListener('mouseleave', () => {
setTimeout(() => {
tile.style.zIndex = '';
}, 300);
});
});
});

View File

@@ -0,0 +1,89 @@
// HarborSmith - Booking JavaScript
// ================================
// Calendar functionality
document.addEventListener('DOMContentLoaded', () => {
// Calendar day selection
const calendarDays = document.querySelectorAll('.calendar-day.available');
calendarDays.forEach(day => {
day.addEventListener('click', function() {
// Remove previous selection
document.querySelector('.calendar-day.selected')?.classList.remove('selected');
// Add selection to clicked day
this.classList.add('selected');
// Update summary
updateBookingSummary();
});
});
// Duration selection
const durationOptions = document.querySelectorAll('input[name="duration"]');
durationOptions.forEach(option => {
option.addEventListener('change', updateBookingSummary);
});
// Guest number input
const guestInput = document.querySelector('input[type="number"]');
if (guestInput) {
guestInput.addEventListener('change', updateBookingSummary);
}
// Yacht selection (for booking page 2)
const yachtCards = document.querySelectorAll('.yacht-select-card');
yachtCards.forEach(card => {
card.addEventListener('click', function() {
// Remove previous selection
document.querySelector('.yacht-select-card.selected')?.classList.remove('selected');
// Add selection
this.classList.add('selected');
updateBookingSummary();
});
});
// Addon selection (for booking page 3)
const addonCards = document.querySelectorAll('.addon-card');
addonCards.forEach(card => {
card.addEventListener('click', function() {
this.classList.toggle('selected');
updateBookingSummary();
});
});
});
// Update booking summary
function updateBookingSummary() {
// This would normally update the summary sidebar with selected options
console.log('Updating booking summary...');
}
// Form validation for final step
function validateBookingForm() {
const form = document.getElementById('bookingForm');
if (!form) return true;
const inputs = form.querySelectorAll('[required]');
let isValid = true;
inputs.forEach(input => {
if (!input.value.trim()) {
input.classList.add('error');
isValid = false;
} else {
input.classList.remove('error');
}
});
return isValid;
}
// Handle form submission
const bookingForm = document.getElementById('bookingForm');
if (bookingForm) {
bookingForm.addEventListener('submit', (e) => {
e.preventDefault();
if (validateBookingForm()) {
alert('Thank you for your booking request! We will contact you shortly to confirm your charter.');
// In production, this would submit to a server
}
});
}

339
website-mockups/js/main.js Normal file
View File

@@ -0,0 +1,339 @@
// HarborSmith - Main JavaScript
// ========================
// Theme Management
const themeManager = {
init() {
this.themeToggle = document.getElementById('themeToggle');
this.themeDropdown = document.getElementById('themeDropdown');
this.themeOptions = document.querySelectorAll('.theme-option');
// Load saved theme or default to nautical
const savedTheme = localStorage.getItem('harborsmith-theme') || 'nautical';
this.setTheme(savedTheme);
// Event listeners
this.themeToggle?.addEventListener('click', (e) => {
e.stopPropagation();
this.themeDropdown.classList.toggle('active');
});
this.themeOptions.forEach(option => {
option.addEventListener('click', (e) => {
const theme = e.currentTarget.dataset.theme;
this.setTheme(theme);
this.themeDropdown.classList.remove('active');
});
});
// Close dropdown when clicking outside
document.addEventListener('click', () => {
this.themeDropdown?.classList.remove('active');
});
},
setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('harborsmith-theme', theme);
// Update active state
this.themeOptions.forEach(option => {
option.classList.toggle('active', option.dataset.theme === theme);
});
}
};
// Navigation
const navigation = {
init() {
this.navbar = document.getElementById('navbar');
this.navToggle = document.getElementById('navToggle');
this.navMenu = document.getElementById('navMenu');
this.navLinks = document.querySelectorAll('.nav-link');
// Mobile menu toggle
this.navToggle?.addEventListener('click', () => {
this.navToggle.classList.toggle('active');
this.navMenu.classList.toggle('active');
});
// Close mobile menu on link click
this.navLinks.forEach(link => {
link.addEventListener('click', () => {
this.navToggle?.classList.remove('active');
this.navMenu?.classList.remove('active');
});
});
// Scroll behavior
window.addEventListener('scroll', () => {
if (window.scrollY > 50) {
this.navbar?.classList.add('scrolled');
} else {
this.navbar?.classList.remove('scrolled');
}
});
// Active link highlighting
this.updateActiveLink();
},
updateActiveLink() {
const currentPath = window.location.pathname.split('/').pop() || 'index.html';
this.navLinks.forEach(link => {
const href = link.getAttribute('href');
if (href === currentPath) {
link.classList.add('active');
}
});
}
};
// Smooth Scrolling
const smoothScroll = {
init() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', (e) => {
e.preventDefault();
const target = document.querySelector(anchor.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
};
// Testimonial Slider
const testimonialSlider = {
init() {
this.cards = document.querySelectorAll('.testimonial-card');
this.dots = document.querySelectorAll('.dot');
this.currentIndex = 0;
if (this.cards.length === 0) return;
// Auto-play
this.startAutoPlay();
// Dot navigation
this.dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
this.goToSlide(index);
this.resetAutoPlay();
});
});
},
goToSlide(index) {
this.cards[this.currentIndex]?.classList.remove('active');
this.dots[this.currentIndex]?.classList.remove('active');
this.currentIndex = index;
this.cards[this.currentIndex]?.classList.add('active');
this.dots[this.currentIndex]?.classList.add('active');
},
nextSlide() {
const nextIndex = (this.currentIndex + 1) % this.cards.length;
this.goToSlide(nextIndex);
},
startAutoPlay() {
this.autoPlayInterval = setInterval(() => {
this.nextSlide();
}, 5000);
},
resetAutoPlay() {
clearInterval(this.autoPlayInterval);
this.startAutoPlay();
}
};
// Counter Animation
const counterAnimation = {
init() {
this.counters = document.querySelectorAll('.stat-number');
this.animated = false;
if (this.counters.length === 0) return;
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting && !this.animated) {
this.animateCounters();
this.animated = true;
}
});
}, { threshold: 0.5 });
const statsSection = document.querySelector('.stats-section');
if (statsSection) {
observer.observe(statsSection);
}
},
animateCounters() {
this.counters.forEach(counter => {
const target = parseInt(counter.dataset.count);
const duration = 2000;
const increment = target / (duration / 16);
let current = 0;
const updateCounter = () => {
current += increment;
if (current < target) {
counter.textContent = Math.floor(current);
requestAnimationFrame(updateCounter);
} else {
counter.textContent = target;
}
};
updateCounter();
});
}
};
// Form Validation
const formValidation = {
init() {
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', (e) => {
if (!this.validateForm(form)) {
e.preventDefault();
}
});
// Real-time validation
const inputs = form.querySelectorAll('input, textarea, select');
inputs.forEach(input => {
input.addEventListener('blur', () => {
this.validateField(input);
});
});
});
},
validateForm(form) {
const inputs = form.querySelectorAll('[required]');
let isValid = true;
inputs.forEach(input => {
if (!this.validateField(input)) {
isValid = false;
}
});
return isValid;
},
validateField(field) {
const value = field.value.trim();
const type = field.type;
let isValid = true;
// Remove previous error
field.classList.remove('error');
const errorMsg = field.parentElement.querySelector('.error-message');
if (errorMsg) {
errorMsg.remove();
}
// Required field
if (field.hasAttribute('required') && !value) {
this.showError(field, 'This field is required');
return false;
}
// Email validation
if (type === 'email' && value) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
this.showError(field, 'Please enter a valid email address');
return false;
}
}
// Phone validation
if (type === 'tel' && value) {
const phoneRegex = /^[\d\s\-\+\(\)]+$/;
if (!phoneRegex.test(value)) {
this.showError(field, 'Please enter a valid phone number');
return false;
}
}
return isValid;
},
showError(field, message) {
field.classList.add('error');
const errorElement = document.createElement('div');
errorElement.className = 'error-message';
errorElement.textContent = message;
field.parentElement.appendChild(errorElement);
}
};
// Yacht Quick View Modal
const yachtModal = {
init() {
const viewButtons = document.querySelectorAll('.yacht-view-btn');
viewButtons.forEach(btn => {
btn.addEventListener('click', (e) => {
e.preventDefault();
this.openModal();
});
});
},
openModal() {
// For now, just alert - in production, would open a modal
alert('Quick view modal would open here with yacht details and 360° view');
}
};
// Parallax Effects
const parallaxEffects = {
init() {
this.elements = document.querySelectorAll('.parallax');
if (this.elements.length === 0) return;
window.addEventListener('scroll', () => {
this.updateParallax();
});
},
updateParallax() {
const scrolled = window.pageYOffset;
this.elements.forEach(element => {
const rate = element.dataset.rate || 0.5;
const yPos = -(scrolled * rate);
element.style.transform = `translateY(${yPos}px)`;
});
}
};
// Initialize everything when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
themeManager.init();
navigation.init();
smoothScroll.init();
testimonialSlider.init();
counterAnimation.init();
formValidation.init();
yachtModal.init();
parallaxEffects.init();
// Log successful initialization
console.log('HarborSmith website initialized successfully!');
});

View File

@@ -0,0 +1,350 @@
// Voyage Layout JavaScript - Smooth, Interactive, Engaging
document.addEventListener('DOMContentLoaded', function() {
// Theme is now gold by default - no switcher needed
// Navigation scroll effect and logo switching
const nav = document.getElementById('voyageNav');
const navLogo = document.getElementById('navLogo');
const navBrandText = document.querySelector('.nav-brand span');
let lastScroll = 0;
// Set initial logo state
if (navLogo) {
navLogo.src = 'HARBOR-SMITH-white.png';
}
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 50) {
nav.classList.add('scrolled');
// Switch to navy logo when scrolled (white background)
if (navLogo) {
navLogo.src = 'HARBOR-SMITH_navy.png';
navLogo.alt = 'Harbor Smith Navy Logo';
}
// Also change text color to match
if (navBrandText) {
navBrandText.style.color = '#1e3a5f';
}
} else {
nav.classList.remove('scrolled');
// Switch to white logo when at top (over video)
if (navLogo) {
navLogo.src = 'HARBOR-SMITH-white.png';
navLogo.alt = 'Harbor Smith White Logo';
}
// Reset text color to white
if (navBrandText) {
navBrandText.style.color = 'white';
}
}
lastScroll = currentScroll;
});
// Smooth scroll for navigation links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Parallax effect for hero video
const heroSection = document.getElementById('heroSection');
const heroVideo = document.querySelector('.hero-video-container');
window.addEventListener('scroll', () => {
const scrolled = window.pageYOffset;
const rate = scrolled * 0.5;
if (heroVideo) {
heroVideo.style.transform = `translateY(${rate}px)`;
}
});
// Fleet Carousel
const yachtCards = document.querySelectorAll('.yacht-card');
const dots = document.querySelectorAll('.dot');
const prevBtn = document.querySelector('.fleet-prev');
const nextBtn = document.querySelector('.fleet-next');
let currentYacht = 0;
function showYacht(index) {
yachtCards.forEach(card => card.classList.remove('active'));
dots.forEach(dot => dot.classList.remove('active'));
yachtCards[index].classList.add('active');
dots[index].classList.add('active');
}
if (prevBtn && nextBtn) {
prevBtn.addEventListener('click', () => {
currentYacht = (currentYacht - 1 + yachtCards.length) % yachtCards.length;
showYacht(currentYacht);
});
nextBtn.addEventListener('click', () => {
currentYacht = (currentYacht + 1) % yachtCards.length;
showYacht(currentYacht);
});
}
dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
currentYacht = index;
showYacht(currentYacht);
});
});
// Auto-rotate fleet carousel
setInterval(() => {
if (document.visibilityState === 'visible') {
currentYacht = (currentYacht + 1) % yachtCards.length;
showYacht(currentYacht);
}
}, 5000);
// CTA Button interactions
document.querySelectorAll('.btn-primary-warm, .btn-secondary-warm').forEach(btn => {
btn.addEventListener('click', function(e) {
// Create ripple effect
const ripple = document.createElement('span');
ripple.classList.add('ripple');
this.appendChild(ripple);
const rect = this.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
setTimeout(() => ripple.remove(), 600);
});
});
// Add ripple styles
const style = document.createElement('style');
style.textContent = `
.ripple {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.6);
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
}
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
.btn-primary-warm,
.btn-secondary-warm {
position: relative;
overflow: hidden;
}
`;
document.head.appendChild(style);
// Animate elements on scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -100px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe elements for animation
document.querySelectorAll('.welcome-content, .story-card, .booking-card').forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
el.style.transition = 'all 0.6s ease';
observer.observe(el);
});
// Interactive booking cards
document.querySelectorAll('.booking-card').forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-10px) scale(1.02)';
});
card.addEventListener('mouseleave', function() {
if (this.classList.contains('featured')) {
this.style.transform = 'scale(1.05)';
} else {
this.style.transform = 'translateY(0) scale(1)';
}
});
});
// Phone number click handler
document.querySelectorAll('.btn-booking.primary').forEach(btn => {
if (btn.textContent.includes('415')) {
btn.addEventListener('click', () => {
window.location.href = 'tel:4155550123';
});
}
});
// Video optimization - pause when not visible
const video = document.querySelector('.hero-video');
if (video) {
const videoObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
video.play();
} else {
video.pause();
}
});
}, { threshold: 0.25 });
videoObserver.observe(video);
}
// Story cards hover effect
document.querySelectorAll('.story-card').forEach(card => {
const img = card.querySelector('img');
card.addEventListener('mouseenter', () => {
if (img) {
img.style.transform = 'scale(1.1)';
img.style.transition = 'transform 0.6s ease';
}
});
card.addEventListener('mouseleave', () => {
if (img) {
img.style.transform = 'scale(1)';
}
});
});
// Dynamic trust badge counter - starts from 0
// Target the white text span specifically (the second span in trust-badge)
const trustBadge = document.querySelector('.trust-badge > span:last-child');
if (trustBadge) {
let count = 0;
const targetCount = 100;
const duration = 2000; // 2 seconds
const steps = 50;
const increment = targetCount / steps;
const stepDuration = duration / steps;
// Start with 0
trustBadge.textContent = `Trusted by 0+ seafarers`;
const counter = setInterval(() => {
count += increment;
if (count >= targetCount) {
count = targetCount;
clearInterval(counter);
trustBadge.textContent = `Trusted by 100+ seafarers`;
} else {
trustBadge.textContent = `Trusted by ${Math.floor(count)}+ seafarers`;
}
}, stepDuration);
}
// Remove any duplicate red text that might exist
const allSpans = document.querySelectorAll('.hero-content span');
allSpans.forEach(span => {
// Check if this is the red duplicate text (not inside trust-badge)
if (span.textContent.includes('Trusted by') &&
span.textContent.includes('adventurers') &&
!span.closest('.trust-badge')) {
span.style.display = 'none';
}
});
// Smooth hover for navigation links
document.querySelectorAll('.nav-link').forEach(link => {
link.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-2px)';
});
link.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0)';
});
});
// Mobile menu (would need to add hamburger menu for production)
const mobileMenuBtn = document.createElement('button');
mobileMenuBtn.className = 'mobile-menu-btn';
mobileMenuBtn.innerHTML = '<span></span><span></span><span></span>';
mobileMenuBtn.style.cssText = `
display: none;
flex-direction: column;
gap: 4px;
background: transparent;
border: none;
cursor: pointer;
padding: 0.5rem;
`;
// Add mobile menu styles
const mobileStyles = document.createElement('style');
mobileStyles.textContent = `
@media (max-width: 768px) {
.mobile-menu-btn {
display: flex !important;
}
.mobile-menu-btn span {
width: 24px;
height: 2px;
background: white;
transition: all 0.3s ease;
}
.voyage-nav.scrolled .mobile-menu-btn span {
background: var(--primary-blue);
}
}
`;
document.head.appendChild(mobileStyles);
// Add mobile menu button to nav
const navContainer = document.querySelector('.nav-container');
if (navContainer && window.innerWidth <= 768) {
navContainer.appendChild(mobileMenuBtn);
}
// Loading animation for images
document.querySelectorAll('img').forEach(img => {
// Check if image is already loaded
if (img.complete && img.naturalHeight !== 0) {
img.style.opacity = '1';
} else {
img.style.opacity = '0';
img.addEventListener('load', function() {
this.style.opacity = '1';
});
}
img.style.transition = 'opacity 0.6s ease';
});
console.log('Voyage layout initialized successfully!');
});

BIN
website-mockups/kid_1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
website-mockups/leah_1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
website-mockups/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,884 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Schedule Maintenance Service - HarborSmith</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="css/voyage-layout.css">
<link rel="stylesheet" href="css/themes.css">
<link rel="stylesheet" href="css/booking.css">
<style>
.maintenance-booking-header {
background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%);
color: white;
padding: 3rem 0;
text-align: center;
}
.maintenance-booking-header h1 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.maintenance-booking-header p {
font-size: 1.125rem;
opacity: 0.95;
}
.service-selection-section {
background: var(--card-bg);
border-radius: 12px;
padding: 2rem;
margin-bottom: 2rem;
}
.service-selection-section h2 {
font-size: 1.5rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.service-selection-section h2 svg {
width: 24px;
height: 24px;
color: var(--accent-primary);
}
.service-type-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.service-type-card {
border: 2px solid var(--border-color);
border-radius: 8px;
padding: 1.5rem;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
}
.service-type-card:hover {
border-color: var(--accent-primary);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.service-type-card.selected {
background: rgba(30, 58, 95, 0.05);
border-color: var(--accent-primary);
}
.service-type-card.selected::after {
content: '✓';
position: absolute;
top: 1rem;
right: 1rem;
background: var(--accent-primary);
color: white;
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
}
.service-type-icon {
width: 50px;
height: 50px;
background: linear-gradient(135deg, var(--accent-primary) 0%, var(--accent-dark) 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
margin-bottom: 1rem;
}
.service-type-icon svg {
width: 24px;
height: 24px;
}
.service-type-name {
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.5rem;
}
.service-type-description {
font-size: 0.875rem;
color: var(--text-secondary);
line-height: 1.4;
}
.service-checkboxes {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
}
.service-checkbox {
display: flex;
align-items: start;
gap: 0.75rem;
padding: 1rem;
border: 1px solid var(--border-color);
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
}
.service-checkbox:hover {
background: rgba(30, 58, 95, 0.03);
border-color: var(--accent-primary);
}
.service-checkbox input[type="checkbox"] {
width: 20px;
height: 20px;
margin-top: 2px;
cursor: pointer;
}
.service-checkbox-content {
flex: 1;
}
.service-checkbox-title {
font-weight: 500;
color: var(--text-primary);
margin-bottom: 0.25rem;
}
.service-checkbox-price {
font-size: 0.875rem;
color: var(--accent-primary);
font-weight: 600;
}
.vessel-info-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
}
.form-group {
display: flex;
flex-direction: column;
}
.form-label {
font-size: 0.875rem;
font-weight: 500;
color: var(--text-secondary);
margin-bottom: 0.5rem;
}
.form-label.required::after {
content: ' *';
color: var(--accent-primary);
}
.form-input,
.form-select,
.form-textarea {
padding: 0.75rem;
border: 1px solid var(--border-color);
border-radius: 6px;
font-size: 1rem;
font-family: 'Inter', sans-serif;
transition: all 0.3s ease;
}
.form-input:focus,
.form-select:focus,
.form-textarea:focus {
outline: none;
border-color: var(--accent-primary);
box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.1);
}
.form-textarea {
min-height: 120px;
resize: vertical;
}
.photo-upload {
border: 2px dashed var(--border-color);
border-radius: 8px;
padding: 2rem;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.photo-upload:hover {
border-color: var(--accent-primary);
background: rgba(30, 58, 95, 0.03);
}
.photo-upload-icon {
width: 60px;
height: 60px;
margin: 0 auto 1rem;
background: rgba(30, 58, 95, 0.1);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: var(--accent-primary);
}
.photo-upload-icon svg {
width: 30px;
height: 30px;
}
.urgency-options {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.urgency-option {
padding: 1rem;
border: 2px solid var(--border-color);
border-radius: 8px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.urgency-option:hover {
border-color: var(--accent-primary);
}
.urgency-option.selected {
border-color: var(--accent-primary);
background: rgba(30, 58, 95, 0.05);
}
.urgency-option.emergency {
border-color: #ef4444;
}
.urgency-option.emergency.selected {
background: rgba(239, 68, 68, 0.05);
border-color: #dc2626;
}
.urgency-label {
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.25rem;
}
.urgency-description {
font-size: 0.875rem;
color: var(--text-secondary);
}
.schedule-calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 0.5rem;
margin-top: 1rem;
}
.calendar-day {
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid var(--border-color);
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
}
.calendar-day:hover:not(.disabled) {
background: rgba(30, 58, 95, 0.05);
border-color: var(--accent-primary);
}
.calendar-day.selected {
background: var(--accent-primary);
color: white;
border-color: var(--accent-primary);
}
.calendar-day.disabled {
opacity: 0.3;
cursor: not-allowed;
}
.time-slots {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: 0.5rem;
margin-top: 1rem;
}
.time-slot {
padding: 0.75rem;
text-align: center;
border: 1px solid var(--border-color);
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
}
.time-slot:hover:not(.unavailable) {
border-color: var(--accent-primary);
background: rgba(30, 58, 95, 0.05);
}
.time-slot.selected {
background: var(--accent-primary);
color: white;
border-color: var(--accent-primary);
}
.time-slot.unavailable {
opacity: 0.3;
cursor: not-allowed;
}
.summary-card {
background: linear-gradient(135deg, rgba(30, 58, 95, 0.05) 0%, rgba(30, 58, 95, 0.02) 100%);
border-radius: 12px;
padding: 1.5rem;
margin-top: 2rem;
}
.summary-item {
display: flex;
justify-content: space-between;
margin-bottom: 0.75rem;
padding-bottom: 0.75rem;
border-bottom: 1px solid var(--border-color);
}
.summary-item:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.summary-label {
color: var(--text-secondary);
}
.summary-value {
font-weight: 600;
color: var(--text-primary);
}
.summary-total {
font-size: 1.25rem;
color: var(--accent-primary);
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="voyage-nav visible" id="voyageNav">
<div class="nav-container">
<div class="nav-brand">
<img src="logo.jpg" alt="HarborSmith" class="nav-logo">
<span>HarborSmith</span>
</div>
<div class="nav-links">
<a href="index.html" class="nav-link">Home</a>
<a href="charter.html" class="nav-link">Charters</a>
<a href="maintenance.html" class="nav-link">Maintenance</a>
<a href="about.html" class="nav-link">About</a>
<a href="contact.html" class="nav-link">Contact</a>
</div>
</div>
</nav>
<!-- Header -->
<div class="maintenance-booking-header">
<h1>Schedule Your Service</h1>
<p>Professional yacht maintenance tailored to your needs</p>
</div>
<!-- Main Content -->
<main class="booking-main">
<div class="container">
<div class="booking-layout">
<!-- Main Content Area -->
<div class="booking-content">
<!-- Service Type Selection -->
<div class="service-selection-section">
<h2><i data-lucide="wrench"></i> Select Service Type</h2>
<div class="service-type-cards">
<div class="service-type-card" data-type="routine">
<div class="service-type-icon">
<i data-lucide="calendar-check"></i>
</div>
<div class="service-type-name">Routine Maintenance</div>
<div class="service-type-description">
Regular scheduled service to keep your yacht in top condition
</div>
</div>
<div class="service-type-card" data-type="repair">
<div class="service-type-icon">
<i data-lucide="wrench"></i>
</div>
<div class="service-type-name">Repairs & Fixes</div>
<div class="service-type-description">
Address specific issues or problems with your vessel
</div>
</div>
<div class="service-type-card" data-type="inspection">
<div class="service-type-icon">
<i data-lucide="clipboard-check"></i>
</div>
<div class="service-type-name">Inspection Only</div>
<div class="service-type-description">
Comprehensive inspection with detailed report
</div>
</div>
<div class="service-type-card" data-type="emergency">
<div class="service-type-icon">
<i data-lucide="alert-triangle"></i>
</div>
<div class="service-type-name">Emergency Service</div>
<div class="service-type-description">
Urgent repairs needed as soon as possible
</div>
</div>
</div>
</div>
<!-- Specific Services -->
<div class="service-selection-section">
<h2><i data-lucide="list-checks"></i> Select Specific Services Needed</h2>
<div class="service-checkboxes">
<label class="service-checkbox">
<input type="checkbox" value="oil-change">
<div class="service-checkbox-content">
<div class="service-checkbox-title">Oil & Filter Change</div>
<div class="service-checkbox-price">From $299</div>
</div>
</label>
<label class="service-checkbox">
<input type="checkbox" value="hull-cleaning">
<div class="service-checkbox-content">
<div class="service-checkbox-title">Hull Cleaning</div>
<div class="service-checkbox-price">From $200</div>
</div>
</label>
<label class="service-checkbox">
<input type="checkbox" value="engine-service">
<div class="service-checkbox-content">
<div class="service-checkbox-title">Engine Service</div>
<div class="service-checkbox-price">From $450</div>
</div>
</label>
<label class="service-checkbox">
<input type="checkbox" value="electrical">
<div class="service-checkbox-content">
<div class="service-checkbox-title">Electrical System Check</div>
<div class="service-checkbox-price">From $350</div>
</div>
</label>
<label class="service-checkbox">
<input type="checkbox" value="bottom-paint">
<div class="service-checkbox-content">
<div class="service-checkbox-title">Bottom Paint</div>
<div class="service-checkbox-price">From $1,500</div>
</div>
</label>
<label class="service-checkbox">
<input type="checkbox" value="zinc-replacement">
<div class="service-checkbox-content">
<div class="service-checkbox-title">Zinc Replacement</div>
<div class="service-checkbox-price">From $150</div>
</div>
</label>
<label class="service-checkbox">
<input type="checkbox" value="upholstery">
<div class="service-checkbox-content">
<div class="service-checkbox-title">Upholstery Cleaning</div>
<div class="service-checkbox-price">From $250</div>
</div>
</label>
<label class="service-checkbox">
<input type="checkbox" value="other">
<div class="service-checkbox-content">
<div class="service-checkbox-title">Other (Describe Below)</div>
<div class="service-checkbox-price">Quote Required</div>
</div>
</label>
</div>
</div>
<!-- Vessel Information -->
<div class="service-selection-section">
<h2><i data-lucide="sailboat"></i> Vessel Information</h2>
<div class="vessel-info-grid">
<div class="form-group">
<label class="form-label required">Vessel Name</label>
<input type="text" class="form-input" placeholder="e.g., Sea Breeze" required>
</div>
<div class="form-group">
<label class="form-label required">Make & Model</label>
<input type="text" class="form-input" placeholder="e.g., Beneteau Oceanis 45" required>
</div>
<div class="form-group">
<label class="form-label required">Year</label>
<input type="text" class="form-input" placeholder="e.g., 2018" required>
</div>
<div class="form-group">
<label class="form-label required">Length (feet)</label>
<input type="text" class="form-input" placeholder="e.g., 45" required>
</div>
<div class="form-group">
<label class="form-label">Hull Number</label>
<input type="text" class="form-input" placeholder="Optional">
</div>
<div class="form-group">
<label class="form-label required">Current Location</label>
<select class="form-select" required>
<option value="">Select Marina...</option>
<option>Pier 39 Marina</option>
<option>South Beach Harbor</option>
<option>Sausalito Yacht Harbor</option>
<option>Berkeley Marina</option>
<option>Emeryville Marina</option>
<option>Other (specify below)</option>
</select>
</div>
</div>
<div class="form-group" style="margin-top: 1rem;">
<label class="form-label">Problem Description / Additional Information</label>
<textarea class="form-textarea" placeholder="Please describe any specific issues or additional information about your service needs..."></textarea>
</div>
<!-- Photo Upload -->
<div class="form-group" style="margin-top: 1rem;">
<label class="form-label">Upload Photos (Optional)</label>
<div class="photo-upload">
<div class="photo-upload-icon">
<i data-lucide="camera"></i>
</div>
<p style="color: var(--text-primary); font-weight: 500; margin-bottom: 0.5rem;">
Click to upload photos
</p>
<p style="color: var(--text-secondary); font-size: 0.875rem;">
Upload photos of any damage or areas of concern
</p>
<input type="file" multiple accept="image/*" style="display: none;">
</div>
</div>
</div>
<!-- Urgency & Scheduling -->
<div class="service-selection-section">
<h2><i data-lucide="clock"></i> Service Urgency</h2>
<div class="urgency-options">
<div class="urgency-option" data-urgency="routine">
<div class="urgency-label">Routine Service</div>
<div class="urgency-description">Schedule within 2 weeks</div>
</div>
<div class="urgency-option" data-urgency="soon">
<div class="urgency-label">Soon</div>
<div class="urgency-description">Within 1 week</div>
</div>
<div class="urgency-option" data-urgency="urgent">
<div class="urgency-label">Urgent</div>
<div class="urgency-description">Within 48 hours</div>
</div>
<div class="urgency-option emergency" data-urgency="emergency">
<div class="urgency-label" style="color: #dc2626;">Emergency</div>
<div class="urgency-description">Need help today</div>
</div>
</div>
<div style="margin-top: 2rem;">
<h3 style="font-size: 1.125rem; margin-bottom: 1rem;">Preferred Service Date</h3>
<div class="form-group">
<label class="form-label">Select Date</label>
<input type="date" class="form-input">
</div>
<div class="form-group" style="margin-top: 1rem;">
<label class="form-label">Preferred Time</label>
<div class="time-slots">
<div class="time-slot">8:00 AM</div>
<div class="time-slot">9:00 AM</div>
<div class="time-slot">10:00 AM</div>
<div class="time-slot">11:00 AM</div>
<div class="time-slot">12:00 PM</div>
<div class="time-slot">1:00 PM</div>
<div class="time-slot">2:00 PM</div>
<div class="time-slot">3:00 PM</div>
</div>
</div>
</div>
</div>
<!-- Contact Information -->
<div class="service-selection-section">
<h2><i data-lucide="user"></i> Contact Information</h2>
<div class="vessel-info-grid">
<div class="form-group">
<label class="form-label required">First Name</label>
<input type="text" class="form-input" placeholder="John" required>
</div>
<div class="form-group">
<label class="form-label required">Last Name</label>
<input type="text" class="form-input" placeholder="Smith" required>
</div>
<div class="form-group">
<label class="form-label required">Email</label>
<input type="email" class="form-input" placeholder="john@example.com" required>
</div>
<div class="form-group">
<label class="form-label required">Phone</label>
<input type="tel" class="form-input" placeholder="(415) 555-0123" required>
</div>
</div>
<div class="form-group" style="margin-top: 1rem;">
<label class="form-label">Preferred Contact Method</label>
<div style="display: flex; gap: 1rem; margin-top: 0.5rem;">
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="radio" name="contact-method" value="phone" checked>
<span>Phone</span>
</label>
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="radio" name="contact-method" value="email">
<span>Email</span>
</label>
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="radio" name="contact-method" value="text">
<span>Text Message</span>
</label>
</div>
</div>
</div>
<!-- Submit Button -->
<div class="booking-navigation">
<button class="btn-secondary" onclick="window.location.href='maintenance.html'">
<i data-lucide="arrow-left"></i>
Back to Services
</button>
<button class="btn-primary" id="submitRequest">
<i data-lucide="send"></i>
Submit Service Request
</button>
</div>
</div>
<!-- Sidebar Summary -->
<aside class="booking-sidebar">
<div class="booking-summary">
<h3 class="summary-title">
<i data-lucide="clipboard-list"></i>
Service Summary
</h3>
<div class="summary-section">
<h4>Selected Services</h4>
<div id="selectedServices" style="color: var(--text-secondary);">
No services selected yet
</div>
</div>
<div class="summary-card">
<div class="summary-item">
<span class="summary-label">Estimated Total</span>
<span class="summary-value summary-total" id="estimatedTotal">$0</span>
</div>
<p style="font-size: 0.875rem; color: var(--text-secondary); margin-top: 0.5rem;">
* Final quote will be provided after inspection
</p>
</div>
<div class="help-section">
<h4>Need Immediate Help?</h4>
<p>Our service team is ready to assist</p>
<button class="btn-contact" onclick="window.location.href='tel:4155550123'">
<i data-lucide="phone"></i>
(415) 555-0123
</button>
<button class="btn-contact" style="background: #dc2626; color: white; margin-top: 0.5rem;" onclick="window.location.href='tel:4155550911'">
<i data-lucide="alert-circle"></i>
Emergency: (415) 555-0911
</button>
</div>
</div>
</aside>
</div>
</div>
</main>
<!-- Footer -->
<footer class="voyage-footer">
<div class="footer-container">
<div class="footer-content">
<div class="footer-brand">
<img src="logo.jpg" alt="HarborSmith" class="footer-logo">
<h3>HarborSmith</h3>
<p>Your trusted partner for Bay Area yacht services</p>
</div>
<div class="footer-links">
<h4>Quick Links</h4>
<a href="index.html">Home</a>
<a href="charter.html">Charters</a>
<a href="maintenance.html">Maintenance</a>
<a href="about.html">About</a>
<a href="contact.html">Contact</a>
</div>
<div class="footer-contact">
<h4>Get in Touch</h4>
<p><i data-lucide="map-pin" class="footer-icon"></i> Pier 39, San Francisco, CA</p>
<p><i data-lucide="phone" class="footer-icon"></i> (415) 555-0123</p>
<p><i data-lucide="alert-circle" class="footer-icon"></i> Emergency: (415) 555-0911</p>
<p><i data-lucide="mail" class="footer-icon"></i> service@harborsmith.com</p>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2024 HarborSmith Yacht Services. All rights reserved.</p>
</div>
</div>
</footer>
<script>
// Initialize Lucide icons
lucide.createIcons();
// Service type selection
const serviceTypeCards = document.querySelectorAll('.service-type-card');
serviceTypeCards.forEach(card => {
card.addEventListener('click', function() {
serviceTypeCards.forEach(c => c.classList.remove('selected'));
this.classList.add('selected');
// Show emergency message if emergency selected
if (this.dataset.type === 'emergency') {
alert('For emergency service, please call our 24/7 hotline at (415) 555-0911');
}
});
});
// Service checkboxes and price calculation
const serviceCheckboxes = document.querySelectorAll('.service-checkbox input');
const selectedServicesDiv = document.getElementById('selectedServices');
const estimatedTotalDiv = document.getElementById('estimatedTotal');
function updateSummary() {
const selected = [];
let total = 0;
serviceCheckboxes.forEach(checkbox => {
if (checkbox.checked) {
const label = checkbox.parentElement.querySelector('.service-checkbox-title').textContent;
const price = checkbox.parentElement.querySelector('.service-checkbox-price').textContent;
selected.push(`${label} - ${price}`);
// Extract price for calculation (simplified)
const priceMatch = price.match(/\$(\d+)/);
if (priceMatch) {
total += parseInt(priceMatch[1]);
}
}
});
if (selected.length > 0) {
selectedServicesDiv.innerHTML = selected.map(s => `<p style="margin: 0.5rem 0; font-size: 0.875rem;">${s}</p>`).join('');
estimatedTotalDiv.textContent = `From $${total}`;
} else {
selectedServicesDiv.innerHTML = 'No services selected yet';
estimatedTotalDiv.textContent = '$0';
}
}
serviceCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', updateSummary);
});
// Urgency selection
const urgencyOptions = document.querySelectorAll('.urgency-option');
urgencyOptions.forEach(option => {
option.addEventListener('click', function() {
urgencyOptions.forEach(o => o.classList.remove('selected'));
this.classList.add('selected');
});
});
// Time slot selection
const timeSlots = document.querySelectorAll('.time-slot');
timeSlots.forEach(slot => {
slot.addEventListener('click', function() {
if (!this.classList.contains('unavailable')) {
timeSlots.forEach(s => s.classList.remove('selected'));
this.classList.add('selected');
}
});
});
// Photo upload
const photoUpload = document.querySelector('.photo-upload');
const fileInput = photoUpload.querySelector('input[type="file"]');
photoUpload.addEventListener('click', () => {
fileInput.click();
});
fileInput.addEventListener('change', function(e) {
const files = e.target.files;
if (files.length > 0) {
photoUpload.querySelector('p').textContent = `${files.length} photo(s) selected`;
}
});
// Submit button
document.getElementById('submitRequest').addEventListener('click', function(e) {
e.preventDefault();
// Simple validation
const requiredInputs = document.querySelectorAll('input[required]');
let valid = true;
requiredInputs.forEach(input => {
if (!input.value) {
input.style.borderColor = '#ef4444';
valid = false;
} else {
input.style.borderColor = '';
}
});
if (valid) {
alert('Thank you for your service request! We will contact you within 24 hours to confirm your appointment and provide a detailed quote.');
window.location.href = 'maintenance.html';
} else {
alert('Please fill in all required fields.');
}
});
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 KiB

View File

@@ -0,0 +1,818 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Yacht Maintenance Services - HarborSmith</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="css/voyage-layout.css">
<link rel="stylesheet" href="css/themes.css">
<style>
.maintenance-hero {
position: relative;
min-height: 60vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%);
}
.maintenance-hero::before {
content: '';
position: absolute;
inset: 0;
background-image: url('diver.jpg');
background-size: cover;
background-position: center;
opacity: 0.3;
}
.maintenance-hero-content {
position: relative;
z-index: 1;
text-align: center;
padding: 2rem;
max-width: 800px;
}
.maintenance-hero h1 {
font-size: 3rem;
font-weight: 800;
color: white;
margin-bottom: 1rem;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.maintenance-hero p {
font-size: 1.25rem;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 2rem;
}
.services-overview {
padding: 5rem 0;
background: var(--bg-primary);
}
.services-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 3rem;
}
.service-card {
background: var(--card-bg);
border-radius: 12px;
padding: 2rem;
text-align: center;
transition: all 0.3s ease;
border: 2px solid transparent;
}
.service-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
border-color: var(--accent-primary);
}
.service-icon {
width: 80px;
height: 80px;
margin: 0 auto 1.5rem;
background: linear-gradient(135deg, var(--accent-primary) 0%, var(--accent-dark) 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.service-icon svg {
width: 40px;
height: 40px;
}
.service-title {
font-size: 1.5rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 1rem;
}
.service-description {
color: var(--text-secondary);
margin-bottom: 1.5rem;
line-height: 1.6;
}
.service-features {
text-align: left;
margin: 1.5rem 0;
}
.service-feature {
display: flex;
align-items: center;
gap: 0.5rem;
margin: 0.75rem 0;
color: var(--text-secondary);
}
.service-feature svg {
width: 16px;
height: 16px;
color: var(--accent-primary);
flex-shrink: 0;
}
.pricing-section {
background: linear-gradient(135deg, rgba(30, 58, 95, 0.05) 0%, rgba(30, 58, 95, 0.02) 100%);
padding: 5rem 0;
}
.pricing-table {
background: var(--card-bg);
border-radius: 12px;
overflow: hidden;
margin-top: 2rem;
}
.pricing-header {
background: var(--accent-primary);
color: white;
padding: 1.5rem;
text-align: center;
}
.pricing-row {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
padding: 1rem 1.5rem;
border-bottom: 1px solid var(--border-color);
align-items: center;
}
.pricing-row:last-child {
border-bottom: none;
}
.pricing-row:hover {
background: rgba(30, 58, 95, 0.03);
}
.pricing-service {
font-weight: 500;
color: var(--text-primary);
}
.pricing-frequency {
text-align: center;
color: var(--text-secondary);
font-size: 0.875rem;
}
.pricing-amount {
text-align: right;
font-weight: 600;
color: var(--accent-primary);
}
.process-section {
padding: 5rem 0;
}
.process-steps {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-top: 3rem;
}
.process-step {
text-align: center;
position: relative;
}
.process-step::after {
content: '';
position: absolute;
top: 40px;
right: -1rem;
width: 2rem;
height: 2px;
background: var(--accent-primary);
opacity: 0.3;
}
.process-step:last-child::after {
display: none;
}
.process-number {
width: 80px;
height: 80px;
margin: 0 auto 1rem;
background: var(--accent-primary);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
font-weight: 700;
}
.process-title {
font-size: 1.25rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.5rem;
}
.process-description {
color: var(--text-secondary);
font-size: 0.875rem;
}
.certifications {
background: var(--card-bg);
border-radius: 12px;
padding: 3rem;
margin: 3rem 0;
text-align: center;
}
.cert-logos {
display: flex;
justify-content: center;
align-items: center;
gap: 3rem;
margin-top: 2rem;
flex-wrap: wrap;
}
.cert-logo {
width: 100px;
height: 100px;
background: rgba(30, 58, 95, 0.1);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
color: var(--accent-primary);
}
.emergency-banner {
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
color: white;
padding: 2rem;
border-radius: 12px;
margin: 3rem 0;
text-align: center;
}
.emergency-banner h3 {
font-size: 1.5rem;
margin-bottom: 0.5rem;
}
.emergency-banner p {
margin-bottom: 1rem;
opacity: 0.95;
}
.emergency-button {
background: white;
color: #dc2626;
padding: 0.75rem 2rem;
border-radius: 6px;
font-weight: 600;
border: none;
cursor: pointer;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.emergency-button:hover {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
@media (max-width: 768px) {
.maintenance-hero h1 {
font-size: 2rem;
}
.process-step::after {
display: none;
}
.pricing-row {
grid-template-columns: 1fr;
text-align: left;
}
.pricing-frequency,
.pricing-amount {
text-align: left;
margin-top: 0.5rem;
}
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="voyage-nav visible" id="voyageNav">
<div class="nav-container">
<div class="nav-brand">
<img src="logo.jpg" alt="HarborSmith" class="nav-logo">
<span>HarborSmith</span>
</div>
<div class="nav-links">
<a href="index.html" class="nav-link">Home</a>
<a href="charter.html" class="nav-link">Charters</a>
<a href="maintenance.html" class="nav-link active">Maintenance</a>
<a href="about.html" class="nav-link">About</a>
<a href="contact.html" class="nav-link">Contact</a>
</div>
</div>
</nav>
<!-- Hero Section -->
<section class="maintenance-hero">
<div class="maintenance-hero-content">
<h1>Expert Yacht Maintenance</h1>
<p>Keep your vessel in pristine condition with our professional maintenance services</p>
<div style="display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap;">
<button class="btn-primary-warm" onclick="window.location.href='portal-login.html'">
<i data-lucide="user"></i>
Client Portal
</button>
<button class="btn-secondary-warm" onclick="window.location.href='maintenance-booking.html'">
<i data-lucide="calendar"></i>
Schedule Service
</button>
<button class="btn-secondary-warm" onclick="document.getElementById('emergency').scrollIntoView()">
<i data-lucide="alert-circle"></i>
Emergency Repair
</button>
</div>
</div>
</section>
<!-- Services Overview -->
<section class="services-overview">
<div class="container">
<div class="section-header">
<h2 class="section-title">Comprehensive Maintenance Services</h2>
<p class="section-subtitle">From routine care to major repairs, we've got you covered</p>
</div>
<div class="services-grid">
<!-- Regular Maintenance -->
<div class="service-card">
<div class="service-icon">
<i data-lucide="wrench"></i>
</div>
<h3 class="service-title">Regular Maintenance</h3>
<p class="service-description">
Keep your yacht running smoothly with our scheduled maintenance programs
</p>
<div class="service-features">
<div class="service-feature">
<i data-lucide="check"></i>
<span>Oil changes & filter replacements</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Belt & hose inspections</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Battery maintenance</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Fluid level checks</span>
</div>
</div>
<button class="btn-service" onclick="window.location.href='maintenance-booking.html'">
Schedule Maintenance
</button>
</div>
<!-- Engine Services -->
<div class="service-card">
<div class="service-icon">
<i data-lucide="settings"></i>
</div>
<h3 class="service-title">Engine Services</h3>
<p class="service-description">
Complete engine diagnostics, repairs, and rebuilds by certified technicians
</p>
<div class="service-features">
<div class="service-feature">
<i data-lucide="check"></i>
<span>Engine diagnostics</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Fuel system service</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Cooling system repairs</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Transmission service</span>
</div>
</div>
<button class="btn-service" onclick="window.location.href='maintenance-booking.html'">
Book Engine Service
</button>
</div>
<!-- Hull & Bottom -->
<div class="service-card">
<div class="service-icon">
<i data-lucide="droplets"></i>
</div>
<h3 class="service-title">Hull & Bottom Services</h3>
<p class="service-description">
Professional hull cleaning, painting, and bottom maintenance
</p>
<div class="service-features">
<div class="service-feature">
<i data-lucide="check"></i>
<span>Bottom cleaning</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Anti-fouling paint</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Zinc replacement</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Gel coat repairs</span>
</div>
</div>
<button class="btn-service" onclick="window.location.href='maintenance-booking.html'">
Schedule Hull Service
</button>
</div>
<!-- Electrical Systems -->
<div class="service-card">
<div class="service-icon">
<i data-lucide="zap"></i>
</div>
<h3 class="service-title">Electrical Systems</h3>
<p class="service-description">
Complete electrical system maintenance and upgrades
</p>
<div class="service-features">
<div class="service-feature">
<i data-lucide="check"></i>
<span>Wiring inspections</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Battery installation</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Navigation electronics</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Solar panel installation</span>
</div>
</div>
<button class="btn-service" onclick="window.location.href='maintenance-booking.html'">
Book Electrical Service
</button>
</div>
<!-- Interior & Upholstery -->
<div class="service-card">
<div class="service-icon">
<i data-lucide="palette"></i>
</div>
<h3 class="service-title">Interior & Upholstery</h3>
<p class="service-description">
Interior refurbishment, upholstery repair, and detailing services
</p>
<div class="service-features">
<div class="service-feature">
<i data-lucide="check"></i>
<span>Upholstery cleaning</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Canvas & cover repairs</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Carpet replacement</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Wood refinishing</span>
</div>
</div>
<button class="btn-service" onclick="window.location.href='maintenance-booking.html'">
Schedule Interior Service
</button>
</div>
<!-- Emergency Repairs -->
<div class="service-card">
<div class="service-icon">
<i data-lucide="alert-triangle"></i>
</div>
<h3 class="service-title">Emergency Repairs</h3>
<p class="service-description">
24/7 emergency repair service to get you back on the water fast
</p>
<div class="service-features">
<div class="service-feature">
<i data-lucide="check"></i>
<span>24/7 availability</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Mobile service</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>Towing assistance</span>
</div>
<div class="service-feature">
<i data-lucide="check"></i>
<span>On-water repairs</span>
</div>
</div>
<button class="btn-service" style="background: #dc2626;" onclick="window.location.href='tel:4155550123'">
Call Emergency Line
</button>
</div>
</div>
</div>
</section>
<!-- Pricing Section -->
<section class="pricing-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Transparent Pricing</h2>
<p class="section-subtitle">Clear, competitive rates for all services</p>
</div>
<div class="pricing-table">
<div class="pricing-header">
<h3>Service Pricing Guide</h3>
</div>
<div class="pricing-row">
<div class="pricing-service">Basic Maintenance Package</div>
<div class="pricing-frequency">Monthly</div>
<div class="pricing-amount">From $299</div>
</div>
<div class="pricing-row">
<div class="pricing-service">Engine Service</div>
<div class="pricing-frequency">Per Service</div>
<div class="pricing-amount">From $450</div>
</div>
<div class="pricing-row">
<div class="pricing-service">Hull Cleaning</div>
<div class="pricing-frequency">Per Cleaning</div>
<div class="pricing-amount">From $200</div>
</div>
<div class="pricing-row">
<div class="pricing-service">Bottom Paint</div>
<div class="pricing-frequency">Per Application</div>
<div class="pricing-amount">From $1,500</div>
</div>
<div class="pricing-row">
<div class="pricing-service">Electrical Diagnostics</div>
<div class="pricing-frequency">Per Hour</div>
<div class="pricing-amount">$125</div>
</div>
<div class="pricing-row">
<div class="pricing-service">Emergency Service</div>
<div class="pricing-frequency">Per Call</div>
<div class="pricing-amount">From $350</div>
</div>
</div>
<p style="text-align: center; margin-top: 2rem; color: var(--text-secondary);">
* Prices vary based on vessel size and specific requirements. Contact us for a detailed quote.
</p>
</div>
</section>
<!-- Process Section -->
<section class="process-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">How It Works</h2>
<p class="section-subtitle">Simple steps to professional yacht maintenance</p>
</div>
<div class="process-steps">
<div class="process-step">
<div class="process-number">1</div>
<h3 class="process-title">Request Service</h3>
<p class="process-description">Fill out our online form or call us to schedule</p>
</div>
<div class="process-step">
<div class="process-number">2</div>
<h3 class="process-title">Free Inspection</h3>
<p class="process-description">We assess your yacht and provide a detailed quote</p>
</div>
<div class="process-step">
<div class="process-number">3</div>
<h3 class="process-title">Professional Service</h3>
<p class="process-description">Our certified technicians complete the work</p>
</div>
<div class="process-step">
<div class="process-number">4</div>
<h3 class="process-title">Quality Check</h3>
<p class="process-description">We ensure everything meets our high standards</p>
</div>
</div>
</div>
</section>
<!-- Certifications -->
<section class="container">
<div class="certifications">
<h2 class="section-title">Certified Excellence</h2>
<p class="section-subtitle">Our technicians are certified by leading marine organizations</p>
<div class="cert-logos">
<div class="cert-logo">ABYC</div>
<div class="cert-logo">NMEA</div>
<div class="cert-logo">Mercury</div>
<div class="cert-logo">Yamaha</div>
<div class="cert-logo">Volvo</div>
</div>
</div>
</section>
<!-- Emergency Banner -->
<section class="container" id="emergency">
<div class="emergency-banner">
<h3>24/7 Emergency Service</h3>
<p>Engine failure? Taking on water? We're here to help, day or night.</p>
<button class="emergency-button" onclick="window.location.href='tel:4155550911'">
<i data-lucide="phone"></i>
Call Emergency Line: (415) 555-0911
</button>
</div>
</section>
<!-- Client Portal Section -->
<section class="booking-cta" style="margin-top: 5rem; background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%);">
<div class="booking-container">
<div class="booking-content">
<h2 class="booking-title" style="color: white;">Existing Clients - Access Your Portal</h2>
<p class="booking-subtitle" style="color: rgba(255,255,255,0.9);">
Manage your vessels, schedule services, view reports, and pay invoices online
</p>
<div class="booking-options">
<div class="booking-card" style="background: rgba(255,255,255,0.1); border: 2px solid rgba(255,255,255,0.3);">
<span class="booking-icon" style="background: rgba(255,255,255,0.2);">
<i data-lucide="user" style="color: white;"></i>
</span>
<h3 style="color: white;">Client Portal</h3>
<p style="color: rgba(255,255,255,0.9);">Access your maintenance dashboard</p>
<button class="btn-booking" style="background: white; color: #1e3a5f;" onclick="window.location.href='portal-login.html'">
Login Now
</button>
</div>
<div class="booking-card" style="background: rgba(255,255,255,0.1); border: 2px solid rgba(255,255,255,0.3);">
<span class="booking-icon" style="background: rgba(255,255,255,0.2);">
<i data-lucide="eye" style="color: white;"></i>
</span>
<h3 style="color: white;">View Demo</h3>
<p style="color: rgba(255,255,255,0.9);">See the portal in action</p>
<button class="btn-booking" style="background: rgba(255,255,255,0.2); color: white; border: 1px solid white;" onclick="window.location.href='maintenance/maintenance-dashboard.html'">
Demo Access
</button>
</div>
<div class="booking-card" style="background: rgba(255,255,255,0.1); border: 2px solid rgba(255,255,255,0.3);">
<span class="booking-icon" style="background: rgba(255,255,255,0.2);">
<i data-lucide="user-plus" style="color: white;"></i>
</span>
<h3 style="color: white;">New Client?</h3>
<p style="color: rgba(255,255,255,0.9);">Register for portal access</p>
<button class="btn-booking" style="background: rgba(255,255,255,0.2); color: white; border: 1px solid white;" onclick="window.location.href='contact.html'">
Get Started
</button>
</div>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="booking-cta" style="margin-top: 3rem;">
<div class="booking-container">
<div class="booking-content">
<h2 class="booking-title">Ready to Schedule Your Service?</h2>
<p class="booking-subtitle">
Keep your yacht in perfect condition with regular professional maintenance
</p>
<div class="booking-options">
<div class="booking-card">
<span class="booking-icon">
<i data-lucide="calendar"></i>
</span>
<h3>Schedule Service</h3>
<p>Book your maintenance online</p>
<button class="btn-booking" onclick="window.location.href='maintenance-booking.html'">
Book Now
</button>
</div>
<div class="booking-card featured">
<span class="booking-icon">
<i data-lucide="phone"></i>
</span>
<h3>Call Us</h3>
<p>Speak with a service advisor</p>
<button class="btn-booking primary" onclick="window.location.href='tel:4155550123'">
(415) 555-0123
</button>
</div>
<div class="booking-card">
<span class="booking-icon">
<i data-lucide="file-text"></i>
</span>
<h3>Get a Quote</h3>
<p>Free estimates for all services</p>
<button class="btn-booking" onclick="window.location.href='contact.html'">
Request Quote
</button>
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="voyage-footer">
<div class="footer-container">
<div class="footer-content">
<div class="footer-brand">
<img src="logo.jpg" alt="HarborSmith" class="footer-logo">
<h3>HarborSmith</h3>
<p>Your trusted partner for Bay Area yacht services</p>
</div>
<div class="footer-links">
<h4>Quick Links</h4>
<a href="index.html">Home</a>
<a href="charter.html">Charters</a>
<a href="maintenance.html">Maintenance</a>
<a href="about.html">About</a>
<a href="contact.html">Contact</a>
</div>
<div class="footer-contact">
<h4>Get in Touch</h4>
<p><i data-lucide="map-pin" class="footer-icon"></i> Pier 39, San Francisco, CA</p>
<p><i data-lucide="phone" class="footer-icon"></i> (415) 555-0123</p>
<p><i data-lucide="alert-circle" class="footer-icon"></i> Emergency: (415) 555-0911</p>
<p><i data-lucide="mail" class="footer-icon"></i> service@harborsmith.com</p>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2024 HarborSmith Yacht Services. All rights reserved.</p>
</div>
</div>
</footer>
<script>
// Initialize Lucide icons
lucide.createIcons();
</script>
</body>
</html>

View File

@@ -0,0 +1,405 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Maintenance Dashboard - HarborSmith Portal</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="../css/voyage-layout.css">
<link rel="stylesheet" href="../css/themes.css">
<link rel="stylesheet" href="../css/portal-styles.css">
<link rel="stylesheet" href="../css/maintenance-enhanced.css">
</head>
<body class="portal">
<div class="portal-wrapper">
<!-- Sidebar -->
<aside class="portal-sidebar" id="sidebar">
<div class="sidebar-header">
<a href="maintenance-dashboard.html" class="sidebar-logo">
<img src="../logo.jpg" alt="HarborSmith">
<span>HarborSmith</span>
</a>
<button class="sidebar-toggle" onclick="toggleSidebar()">
<i data-lucide="menu"></i>
</button>
</div>
<nav class="sidebar-nav">
<div class="sidebar-section">
<div class="sidebar-section-title">Main</div>
<a href="maintenance-dashboard.html" class="sidebar-link active">
<i data-lucide="layout-dashboard"></i>
<span>Dashboard</span>
</a>
<a href="maintenance-vessels.html" class="sidebar-link">
<i data-lucide="ship"></i>
<span>My Vessels</span>
</a>
<a href="maintenance-schedule.html" class="sidebar-link">
<i data-lucide="calendar"></i>
<span>Schedule Service</span>
</a>
</div>
<div class="sidebar-section">
<div class="sidebar-section-title">Records</div>
<a href="maintenance-documents.html" class="sidebar-link">
<i data-lucide="file-text"></i>
<span>Documents</span>
</a>
<a href="maintenance-reports.html" class="sidebar-link">
<i data-lucide="clipboard-list"></i>
<span>Service Reports</span>
</a>
<a href="maintenance-invoices.html" class="sidebar-link">
<i data-lucide="receipt"></i>
<span>Invoices</span>
</a>
</div>
<div class="sidebar-section">
<div class="sidebar-section-title">Account</div>
<a href="#" class="sidebar-link">
<i data-lucide="settings"></i>
<span>Settings</span>
</a>
<a href="../portal-login.html" class="sidebar-link" onclick="logout()">
<i data-lucide="log-out"></i>
<span>Logout</span>
</a>
</div>
</nav>
</aside>
<!-- Main Content -->
<main class="portal-main">
<!-- Header -->
<header class="portal-header">
<div class="portal-breadcrumb">
<span>Maintenance Portal</span>
<span class="breadcrumb-separator">/</span>
<span>Dashboard</span>
</div>
<div class="portal-header-actions">
<div class="header-search">
<i data-lucide="search"></i>
<input type="text" placeholder="Search...">
</div>
<button class="header-notifications" style="background: none; border: none; cursor: pointer; position: relative;">
<i data-lucide="bell"></i>
<span class="notification-badge">3</span>
</button>
<div class="header-user">
<div class="user-avatar">JS</div>
<div>
<div style="font-weight: 600;">John Smith</div>
<div style="font-size: 0.875rem; color: var(--text-light);">Maintenance Client</div>
</div>
</div>
</div>
</header>
<!-- Content -->
<div class="portal-content">
<!-- Welcome Section -->
<div class="portal-page-header">
<h1 class="portal-page-title">Welcome back, John!</h1>
<p class="portal-page-subtitle">Here's an overview of your fleet maintenance status</p>
</div>
<!-- Stats Cards -->
<div class="dashboard-grid">
<div class="dashboard-card">
<div class="card-header">
<h3 class="card-title">Active Vessels</h3>
<div class="card-icon">
<i data-lucide="ship"></i>
</div>
</div>
<div class="card-value">3</div>
<div class="card-change positive">
<i data-lucide="trending-up"></i>
+1 this month
</div>
</div>
<div class="dashboard-card">
<div class="card-header">
<h3 class="card-title">Upcoming Services</h3>
<div class="card-icon" style="background: linear-gradient(135deg, #f59e0b 0%, #fbbf24 100%);">
<i data-lucide="wrench"></i>
</div>
</div>
<div class="card-value">2</div>
<p style="color: var(--text-light); font-size: 0.875rem;">Next: Dec 15, 2024</p>
</div>
<div class="dashboard-card">
<div class="card-header">
<h3 class="card-title">Open Invoices</h3>
<div class="card-icon" style="background: linear-gradient(135deg, #3b82f6 0%, #60a5fa 100%);">
<i data-lucide="receipt"></i>
</div>
</div>
<div class="card-value">$4,250</div>
<span class="status-badge warning">1 overdue</span>
</div>
<div class="dashboard-card">
<div class="card-header">
<h3 class="card-title">Service Score</h3>
<div class="card-icon" style="background: linear-gradient(135deg, #10b981 0%, #34d399 100%);">
<i data-lucide="award"></i>
</div>
</div>
<div class="card-value">98%</div>
<div class="card-change positive">
<i data-lucide="trending-up"></i>
Excellent
</div>
</div>
</div>
<!-- Two Column Layout -->
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); margin-bottom: var(--space-lg);">
<!-- Upcoming Services -->
<div class="data-table">
<div class="table-header">
<h3 class="card-title">Upcoming Services</h3>
<div class="table-actions">
<button class="btn-portal-secondary" onclick="window.location.href='maintenance-schedule.html'">
<i data-lucide="plus"></i>
Schedule New
</button>
</div>
</div>
<table>
<thead>
<tr>
<th>Vessel</th>
<th>Service</th>
<th>Date</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Sea Breeze</strong></td>
<td>Annual Inspection</td>
<td>Dec 15, 2024</td>
<td><span class="status-badge warning">Scheduled</span></td>
</tr>
<tr>
<td><strong>Wave Runner</strong></td>
<td>Engine Service</td>
<td>Dec 22, 2024</td>
<td><span class="status-badge info">Confirmed</span></td>
</tr>
<tr>
<td><strong>Ocean Spirit</strong></td>
<td>Hull Cleaning</td>
<td>Jan 5, 2025</td>
<td><span class="status-badge success">Scheduled</span></td>
</tr>
</tbody>
</table>
</div>
<!-- Recent Activity Timeline -->
<div class="dashboard-card">
<h3 class="card-title" style="margin-bottom: var(--space-md);">Recent Activity</h3>
<div class="timeline">
<div class="timeline-item">
<div class="timeline-marker"></div>
<div class="timeline-content">
<div class="timeline-date">2 hours ago</div>
<p><strong>Invoice #1247 paid</strong></p>
<p style="color: var(--text-light); font-size: 0.875rem;">Payment received for Wave Runner engine service</p>
</div>
</div>
<div class="timeline-item">
<div class="timeline-marker"></div>
<div class="timeline-content">
<div class="timeline-date">Yesterday</div>
<p><strong>Service report uploaded</strong></p>
<p style="color: var(--text-light); font-size: 0.875rem;">Sea Breeze monthly maintenance complete</p>
</div>
</div>
<div class="timeline-item">
<div class="timeline-marker"></div>
<div class="timeline-content">
<div class="timeline-date">3 days ago</div>
<p><strong>New document added</strong></p>
<p style="color: var(--text-light); font-size: 0.875rem;">Insurance renewal certificate for Ocean Spirit</p>
</div>
</div>
</div>
</div>
</div>
<!-- Fleet Overview -->
<div class="data-table">
<div class="table-header">
<h3 class="card-title">Fleet Overview</h3>
<div class="table-actions">
<button class="btn-portal-secondary" onclick="window.location.href='maintenance-vessels.html'">
View All
</button>
</div>
</div>
<table>
<thead>
<tr>
<th>Vessel Name</th>
<th>Type</th>
<th>Last Service</th>
<th>Next Service</th>
<th>Health Score</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div style="display: flex; align-items: center; gap: 0.75rem;">
<img src="../yacht_party_couple_holding_hands.jpg" alt="Sea Breeze" style="width: 40px; height: 40px; border-radius: 8px; object-fit: cover;">
<div>
<strong>Sea Breeze</strong>
<div style="font-size: 0.875rem; color: var(--text-light);">2019 Beneteau 45</div>
</div>
</div>
</td>
<td>Sailboat</td>
<td>Nov 10, 2024</td>
<td>Dec 15, 2024</td>
<td>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<div style="width: 100px; height: 8px; background: var(--soft-cream); border-radius: 4px; overflow: hidden;">
<div style="width: 95%; height: 100%; background: var(--success);"></div>
</div>
<span>95%</span>
</div>
</td>
<td>
<button class="btn-portal-secondary" style="padding: 0.5rem 1rem; font-size: 0.875rem;">
View Details
</button>
</td>
</tr>
<tr>
<td>
<div style="display: flex; align-items: center; gap: 0.75rem;">
<img src="../golden_gate.jpg" alt="Wave Runner" style="width: 40px; height: 40px; border-radius: 8px; object-fit: cover;">
<div>
<strong>Wave Runner</strong>
<div style="font-size: 0.875rem; color: var(--text-light);">2021 Sea Ray 350</div>
</div>
</div>
</td>
<td>Motor Yacht</td>
<td>Oct 28, 2024</td>
<td>Dec 22, 2024</td>
<td>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<div style="width: 100px; height: 8px; background: var(--soft-cream); border-radius: 4px; overflow: hidden;">
<div style="width: 88%; height: 100%; background: var(--warning);"></div>
</div>
<span>88%</span>
</div>
</td>
<td>
<button class="btn-portal-secondary" style="padding: 0.5rem 1rem; font-size: 0.875rem;">
View Details
</button>
</td>
</tr>
<tr>
<td>
<div style="display: flex; align-items: center; gap: 0.75rem;">
<img src="../diver.jpg" alt="Ocean Spirit" style="width: 40px; height: 40px; border-radius: 8px; object-fit: cover;">
<div>
<strong>Ocean Spirit</strong>
<div style="font-size: 0.875rem; color: var(--text-light);">2020 Catalina 425</div>
</div>
</div>
</td>
<td>Sailboat</td>
<td>Nov 5, 2024</td>
<td>Jan 5, 2025</td>
<td>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<div style="width: 100px; height: 8px; background: var(--soft-cream); border-radius: 4px; overflow: hidden;">
<div style="width: 92%; height: 100%; background: var(--success);"></div>
</div>
<span>92%</span>
</div>
</td>
<td>
<button class="btn-portal-secondary" style="padding: 0.5rem 1rem; font-size: 0.875rem;">
View Details
</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Quick Actions -->
<div style="margin-top: var(--space-lg);">
<h3 class="card-title" style="margin-bottom: var(--space-md);">Quick Actions</h3>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-md);">
<button class="dashboard-card" style="cursor: pointer; text-align: center; padding: var(--space-md);" onclick="window.location.href='maintenance-schedule.html'">
<i data-lucide="calendar-plus" style="width: 32px; height: 32px; margin: 0 auto var(--space-sm); color: var(--warm-orange);"></i>
<div style="font-weight: 600;">Schedule Service</div>
</button>
<button class="dashboard-card" style="cursor: pointer; text-align: center; padding: var(--space-md);" onclick="window.location.href='maintenance-documents.html'">
<i data-lucide="upload" style="width: 32px; height: 32px; margin: 0 auto var(--space-sm); color: var(--warm-orange);"></i>
<div style="font-weight: 600;">Upload Document</div>
</button>
<button class="dashboard-card" style="cursor: pointer; text-align: center; padding: var(--space-md);" onclick="window.location.href='maintenance-invoices.html'">
<i data-lucide="credit-card" style="width: 32px; height: 32px; margin: 0 auto var(--space-sm); color: var(--warm-orange);"></i>
<div style="font-weight: 600;">Pay Invoice</div>
</button>
<button class="dashboard-card" style="cursor: pointer; text-align: center; padding: var(--space-md);" onclick="window.location.href='maintenance-reports.html'">
<i data-lucide="file-text" style="width: 32px; height: 32px; margin: 0 auto var(--space-sm); color: var(--warm-orange);"></i>
<div style="font-weight: 600;">View Reports</div>
</button>
</div>
</div>
</div>
</main>
</div>
<script>
// Initialize Lucide icons
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
// Check authentication
if (!localStorage.getItem('isLoggedIn')) {
window.location.href = '../portal-login.html';
}
});
// Toggle sidebar
function toggleSidebar() {
const sidebar = document.getElementById('sidebar');
sidebar.classList.toggle('collapsed');
}
// Logout
function logout() {
localStorage.removeItem('isLoggedIn');
localStorage.removeItem('userEmail');
localStorage.removeItem('userName');
localStorage.removeItem('userRole');
}
</script>
</body>
</html>

View File

@@ -0,0 +1,415 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documents - HarborSmith Portal</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../css/portal-styles.css">
<link rel="stylesheet" href="../css/maintenance-enhanced.css">
</head>
<body>
<div class="portal-container">
<!-- Sidebar -->
<aside class="portal-sidebar" id="sidebar">
<a href="maintenance-dashboard.html" class="portal-logo">
<img src="../logo.jpg" alt="HarborSmith">
<span>HarborSmith</span>
</a>
<nav class="portal-nav">
<div class="nav-section">
<div class="nav-section-title">Main</div>
<a href="maintenance-dashboard.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
</svg>
<span>Dashboard</span>
</a>
<a href="maintenance-vessels.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"></path>
</svg>
<span>My Vessels</span>
</a>
<a href="maintenance-schedule.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
<span>Schedule Service</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-title">Records</div>
<a href="maintenance-documents.html" class="nav-link active">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<span>Documents</span>
</a>
<a href="maintenance-reports.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v1a1 1 0 001 1h4a1 1 0 001-1v-1m3-2V8a2 2 0 00-2-2H8a2 2 0 00-2 2v8m5-4h4"></path>
</svg>
<span>Service Reports</span>
</a>
<a href="maintenance-invoices.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
<span>Invoices</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-title">Account</div>
<a href="#" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
<span>Settings</span>
</a>
<a href="../portal-login.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
</svg>
<span>Logout</span>
</a>
</div>
</nav>
</aside>
<!-- Main Content -->
<main class="portal-main">
<!-- Header -->
<header class="portal-header">
<div class="breadcrumb">
<span>Maintenance Portal</span>
<span>/</span>
<span>Documents</span>
</div>
<div class="header-actions">
<div class="search-box">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<input type="text" placeholder="Search documents...">
</div>
<div class="notifications">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"></path>
</svg>
<span class="notification-badge">3</span>
</div>
<div class="user-profile">
<div class="user-avatar">JS</div>
<div class="user-info">
<span class="user-name">John Smith</span>
<span class="user-role">Maintenance Client</span>
</div>
</div>
</div>
</header>
<!-- Content -->
<div class="portal-content">
<div class="page-header">
<h1>Documents</h1>
<p>Manage your vessel documentation and certificates</p>
</div>
<div class="document-layout">
<!-- Left Sidebar -->
<div class="document-sidebar">
<!-- Categories -->
<div class="categories-card">
<h3>Categories</h3>
<div class="category-item active">
<div class="category-icon">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</div>
<span class="category-name">All Documents</span>
<span class="category-count">24</span>
</div>
<div class="category-item">
<div class="category-icon">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"></path>
</svg>
</div>
<span class="category-name">Registration</span>
<span class="category-count">3</span>
</div>
<div class="category-item">
<div class="category-icon">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path>
</svg>
</div>
<span class="category-name">Insurance</span>
<span class="category-count">4</span>
</div>
<div class="category-item">
<div class="category-icon">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path>
</svg>
</div>
<span class="category-name">Warranties</span>
<span class="category-count">6</span>
</div>
<div class="category-item">
<div class="category-icon">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path>
</svg>
</div>
<span class="category-name">Safety Certificates</span>
<span class="category-count">5</span>
</div>
<div class="category-item">
<div class="category-icon">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
</svg>
</div>
<span class="category-name">Owner Manuals</span>
<span class="category-count">8</span>
</div>
<div class="category-item">
<div class="category-icon">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
</div>
<span class="category-name">Service History</span>
<span class="category-count">12</span>
</div>
</div>
<!-- Upload Zone -->
<div class="upload-card">
<div class="upload-zone">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path>
</svg>
<h4>Drop files here to upload</h4>
<p>or click to browse files</p>
<p style="margin-top: 0.5rem; font-size: 0.75rem;">Supported formats: PDF, JPG, PNG, DOC, DOCX (Max 10MB)</p>
</div>
</div>
</div>
<!-- Main Documents Area -->
<div class="documents-main">
<!-- Actions Bar -->
<div class="actions-bar">
<div class="filter-group">
<select class="filter-select">
<option>All Documents</option>
<option>Expiring Soon</option>
<option>Recently Added</option>
<option>By Vessel</option>
</select>
</div>
<button class="upload-btn">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path>
</svg>
Upload Document
</button>
</div>
<!-- Documents Grid -->
<div class="documents-grid">
<div class="document-card">
<div class="document-icon">
<svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</div>
<div class="document-info">
<div class="document-name">Vessel Registration - Sea Breeze</div>
<div class="document-meta">
<span>2.3 MB</span>
<span></span>
<span>Uploaded Nov 15, 2024</span>
</div>
</div>
<div class="document-status valid">Valid until Dec 2025</div>
<div class="document-actions">
<button class="doc-action-btn" title="View document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Download document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Delete document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
</button>
</div>
</div>
<div class="document-card">
<div class="document-icon">
<svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</div>
<div class="document-info">
<div class="document-name">Insurance Policy - Marine Coverage</div>
<div class="document-meta">
<span>1.8 MB</span>
<span></span>
<span>Uploaded Oct 20, 2024</span>
</div>
</div>
<div class="document-status expiring">Expires in 30 days</div>
<div class="document-actions">
<button class="doc-action-btn" title="View document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Download document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Delete document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
</button>
</div>
</div>
<div class="document-card">
<div class="document-icon">
<svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
</div>
<div class="document-info">
<div class="document-name">Safety Equipment Certificate</div>
<div class="document-meta">
<span>856 KB</span>
<span></span>
<span>Uploaded Sep 5, 2024</span>
</div>
</div>
<div class="document-status valid">Valid until Jun 2025</div>
<div class="document-actions">
<button class="doc-action-btn" title="View document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Download document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Delete document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
</button>
</div>
</div>
<div class="document-card">
<div class="document-icon">
<svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</div>
<div class="document-info">
<div class="document-name">Engine Warranty Documentation</div>
<div class="document-meta">
<span>524 KB</span>
<span></span>
<span>Uploaded Aug 12, 2024</span>
</div>
</div>
<div class="document-status valid">Valid until 2026</div>
<div class="document-actions">
<button class="doc-action-btn" title="View document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Download document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Delete document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
</button>
</div>
</div>
<div class="document-card">
<div class="document-icon">
<svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</div>
<div class="document-info">
<div class="document-name">Radio License</div>
<div class="document-meta">
<span>342 KB</span>
<span></span>
<span>Uploaded Jun 15, 2024</span>
</div>
</div>
<div class="document-status expired">Expired</div>
<div class="document-actions">
<button class="doc-action-btn" style="background: #fef3c7; border-color: #f59e0b;" title="Document expired warning">
<svg fill="none" stroke="#f59e0b" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Download document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</button>
<button class="doc-action-btn" title="Delete document">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</body>
</html>

View File

@@ -0,0 +1,391 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Invoices - HarborSmith Portal</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../css/portal-styles.css">
<link rel="stylesheet" href="../css/maintenance-enhanced.css">
</head>
<body>
<div class="portal-container">
<!-- Sidebar -->
<aside class="portal-sidebar" id="sidebar">
<a href="maintenance-dashboard.html" class="portal-logo">
<img src="../logo.jpg" alt="HarborSmith">
<span>HarborSmith</span>
</a>
<nav class="portal-nav">
<div class="nav-section">
<div class="nav-section-title">Main</div>
<a href="maintenance-dashboard.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
</svg>
<span>Dashboard</span>
</a>
<a href="maintenance-vessels.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"></path>
</svg>
<span>My Vessels</span>
</a>
<a href="maintenance-schedule.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
<span>Schedule Service</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-title">Records</div>
<a href="maintenance-documents.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<span>Documents</span>
</a>
<a href="maintenance-reports.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v1a1 1 0 001 1h4a1 1 0 001-1v-1m3-2V8a2 2 0 00-2-2H8a2 2 0 00-2 2v8m5-4h4"></path>
</svg>
<span>Service Reports</span>
</a>
<a href="maintenance-invoices.html" class="nav-link active">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
<span>Invoices</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-title">Account</div>
<a href="#" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
<span>Settings</span>
</a>
<a href="../portal-login.html" class="nav-link">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
</svg>
<span>Logout</span>
</a>
</div>
</nav>
</aside>
<!-- Main Content -->
<main class="portal-main">
<!-- Header -->
<header class="portal-header">
<div class="breadcrumb">
<span>Maintenance Portal</span>
<span>/</span>
<span>Invoices</span>
</div>
<div class="header-actions">
<div class="search-box">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<input type="text" placeholder="Search invoices...">
</div>
<div class="notifications">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"></path>
</svg>
<span class="notification-badge">3</span>
</div>
<div class="user-profile">
<div class="user-avatar">JS</div>
<div class="user-info">
<span class="user-name">John Smith</span>
<span class="user-role">Maintenance Client</span>
</div>
</div>
</div>
</header>
<!-- Content -->
<div class="portal-content">
<div class="page-header">
<h1>Invoices & Payments</h1>
<p>Manage your service invoices and payment history</p>
</div>
<!-- Stats Row -->
<div class="stats-row">
<div class="stat-card">
<div class="stat-value">$12,450</div>
<div class="stat-label">Paid This Year</div>
</div>
<div class="stat-card pending">
<div class="stat-value">$2,850</div>
<div class="stat-label">Pending Payment</div>
</div>
<div class="stat-card overdue">
<div class="stat-value">$0</div>
<div class="stat-label">Overdue</div>
</div>
<div class="stat-card">
<div class="stat-value">18</div>
<div class="stat-label">Total Invoices</div>
</div>
</div>
<!-- Auto-pay Settings -->
<div class="autopay-section">
<div class="autopay-header">
<h3 class="autopay-title">🔄 Auto-Pay Settings</h3>
<div class="toggle-switch active"></div>
</div>
<div class="autopay-settings">
<div class="filter-group">
<select class="filter-select" title="Select payment method">
<option>Visa ending in 4242</option>
<option>Bank Account ending in 6789</option>
<option>Add new payment method...</option>
</select>
</div>
<div class="filter-group">
<input type="text" class="filter-select" placeholder="Max amount: $5,000">
</div>
<div class="filter-group">
<select class="filter-select" title="Select notification preference">
<option>Email me before charging</option>
<option>Email me after charging</option>
<option>Both</option>
</select>
</div>
</div>
</div>
<!-- Filters -->
<div class="filters-row">
<div class="filter-group">
<select class="filter-select" title="Filter by invoice status">
<option>All Invoices</option>
<option>Paid</option>
<option>Pending</option>
<option>Overdue</option>
</select>
<select class="filter-select" title="Filter by vessel">
<option>All Vessels</option>
<option>Sea Breeze</option>
<option>Wave Runner</option>
<option>Ocean Spirit</option>
</select>
<select class="filter-select" title="Filter by date range">
<option>Last 30 Days</option>
<option>Last 3 Months</option>
<option>Last 6 Months</option>
<option>This Year</option>
</select>
</div>
<button class="export-btn">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
Export
</button>
</div>
<!-- Invoices Grid -->
<div class="invoices-grid">
<div class="invoice-card">
<div>
<div class="invoice-header">
<div>
<div class="invoice-number">INV-2024-1247</div>
<div class="invoice-vessel">Sea Breeze</div>
</div>
<span class="invoice-status pending">Pending</span>
</div>
<div class="invoice-details">
<div class="invoice-detail">
<span class="invoice-detail-label">Date</span>
<span class="invoice-detail-value">Nov 15, 2024</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Service</span>
<span class="invoice-detail-value">Annual Maintenance</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Amount</span>
<span class="invoice-detail-value">$2,850.00</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Due Date</span>
<span class="invoice-detail-value">Nov 30, 2024</span>
</div>
</div>
</div>
<div class="invoice-actions">
<button class="action-btn primary">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
Pay Now
</button>
<button class="action-btn secondary">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
View
</button>
</div>
</div>
<div class="invoice-card">
<div>
<div class="invoice-header">
<div>
<div class="invoice-number">INV-2024-1235</div>
<div class="invoice-vessel">Wave Runner</div>
</div>
<span class="invoice-status paid">Paid</span>
</div>
<div class="invoice-details">
<div class="invoice-detail">
<span class="invoice-detail-label">Date</span>
<span class="invoice-detail-value">Oct 28, 2024</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Service</span>
<span class="invoice-detail-value">Hull Cleaning</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Amount</span>
<span class="invoice-detail-value">$450.00</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Paid On</span>
<span class="invoice-detail-value">Oct 30, 2024</span>
</div>
</div>
</div>
<div class="invoice-actions">
<button class="action-btn secondary">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
Receipt
</button>
<button class="action-btn secondary">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
View
</button>
</div>
</div>
<div class="invoice-card">
<div>
<div class="invoice-header">
<div>
<div class="invoice-number">INV-2024-1221</div>
<div class="invoice-vessel">Sea Breeze</div>
</div>
<span class="invoice-status paid">Paid</span>
</div>
<div class="invoice-details">
<div class="invoice-detail">
<span class="invoice-detail-label">Date</span>
<span class="invoice-detail-value">Oct 10, 2024</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Service</span>
<span class="invoice-detail-value">Engine Service</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Amount</span>
<span class="invoice-detail-value">$1,200.00</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Paid On</span>
<span class="invoice-detail-value">Oct 12, 2024</span>
</div>
</div>
</div>
<div class="invoice-actions">
<button class="action-btn secondary">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
Receipt
</button>
<button class="action-btn secondary">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
View
</button>
</div>
</div>
<div class="invoice-card">
<div>
<div class="invoice-header">
<div>
<div class="invoice-number">INV-2024-1198</div>
<div class="invoice-vessel">Ocean Spirit</div>
</div>
<span class="invoice-status paid">Paid</span>
</div>
<div class="invoice-details">
<div class="invoice-detail">
<span class="invoice-detail-label">Date</span>
<span class="invoice-detail-value">Sep 15, 2024</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Service</span>
<span class="invoice-detail-value">Electronics Update</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Amount</span>
<span class="invoice-detail-value">$3,200.00</span>
</div>
<div class="invoice-detail">
<span class="invoice-detail-label">Paid On</span>
<span class="invoice-detail-value">Sep 18, 2024</span>
</div>
</div>
</div>
<div class="invoice-actions">
<button class="action-btn secondary">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
Receipt
</button>
<button class="action-btn secondary">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
View
</button>
</div>
</div>
</div>
</div>
</main>
</div>
</body>
</html>

View File

@@ -0,0 +1,579 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Service Reports - HarborSmith Portal</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="../css/voyage-layout.css">
<link rel="stylesheet" href="../css/themes.css">
<link rel="stylesheet" href="../css/portal-styles.css">
<link rel="stylesheet" href="../css/maintenance-enhanced.css">
<style>
.reports-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.report-card {
background: white;
border-radius: 16px;
padding: 1.5rem;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
transition: all 0.3s ease;
cursor: pointer;
border: 2px solid transparent;
}
.report-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
border-color: #667eea;
}
.report-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 1rem;
}
.report-status {
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
}
.report-status.completed {
background: linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%);
color: #16a34a;
}
.report-status.pending {
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
color: #d97706;
}
.report-status.in-progress {
background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
color: #2563eb;
}
.report-details {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid #e5e7eb;
}
.report-detail-row {
display: flex;
justify-content: space-between;
font-size: 0.875rem;
}
.filter-tabs {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
border-bottom: 2px solid #e5e7eb;
}
.filter-tab {
padding: 0.75rem 1.5rem;
background: none;
border: none;
color: #6b7280;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
}
.filter-tab:hover {
color: #667eea;
}
.filter-tab.active {
color: #667eea;
}
.filter-tab.active::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
}
.stats-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.stat-box {
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
padding: 1.5rem;
border-radius: 12px;
text-align: center;
}
.stat-value {
font-size: 2rem;
font-weight: 700;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.stat-label {
color: #6b7280;
font-size: 0.875rem;
margin-top: 0.5rem;
}
</style>
</head>
<body class="portal">
<div class="portal-wrapper">
<!-- Sidebar -->
<aside class="portal-sidebar" id="sidebar">
<div class="sidebar-header">
<a href="maintenance-dashboard.html" class="sidebar-logo">
<img src="../logo.jpg" alt="HarborSmith">
<span>HarborSmith</span>
</a>
<button class="sidebar-toggle" onclick="toggleSidebar()">
<i data-lucide="menu"></i>
</button>
</div>
<nav class="sidebar-nav">
<div class="sidebar-section">
<div class="sidebar-section-title">Main</div>
<a href="maintenance-dashboard.html" class="sidebar-link">
<i data-lucide="layout-dashboard"></i>
<span>Dashboard</span>
</a>
<a href="maintenance-vessels.html" class="sidebar-link">
<i data-lucide="ship"></i>
<span>My Vessels</span>
</a>
<a href="maintenance-schedule.html" class="sidebar-link">
<i data-lucide="calendar"></i>
<span>Schedule Service</span>
</a>
</div>
<div class="sidebar-section">
<div class="sidebar-section-title">Records</div>
<a href="maintenance-documents.html" class="sidebar-link">
<i data-lucide="file-text"></i>
<span>Documents</span>
</a>
<a href="maintenance-reports.html" class="sidebar-link active">
<i data-lucide="clipboard-list"></i>
<span>Service Reports</span>
</a>
<a href="maintenance-invoices.html" class="sidebar-link">
<i data-lucide="receipt"></i>
<span>Invoices</span>
</a>
</div>
<div class="sidebar-section">
<div class="sidebar-section-title">Account</div>
<a href="#" class="sidebar-link">
<i data-lucide="settings"></i>
<span>Settings</span>
</a>
<a href="../portal-login.html" class="sidebar-link" onclick="logout()">
<i data-lucide="log-out"></i>
<span>Logout</span>
</a>
</div>
</nav>
</aside>
<!-- Main Content -->
<main class="portal-main">
<!-- Header -->
<header class="portal-header">
<div class="portal-breadcrumb">
<span>Maintenance Portal</span>
<span class="breadcrumb-separator">/</span>
<span>Service Reports</span>
</div>
<div class="portal-header-actions">
<div class="header-search">
<i data-lucide="search"></i>
<input type="text" placeholder="Search reports...">
</div>
<button class="header-notifications" style="background: none; border: none; cursor: pointer; position: relative;">
<i data-lucide="bell"></i>
<span class="notification-badge">3</span>
</button>
<div class="header-user">
<div class="user-avatar">JS</div>
<div>
<div style="font-weight: 600;">John Smith</div>
<div style="font-size: 0.875rem; color: var(--text-light);">Maintenance Client</div>
</div>
</div>
</div>
</header>
<!-- Page Content -->
<div class="portal-content">
<div class="page-header">
<h1>Service Reports</h1>
<p>View and download your maintenance service reports</p>
</div>
<!-- Statistics -->
<div class="stats-row">
<div class="stat-box">
<div class="stat-value">24</div>
<div class="stat-label">Total Reports</div>
</div>
<div class="stat-box">
<div class="stat-value">18</div>
<div class="stat-label">Completed Services</div>
</div>
<div class="stat-box">
<div class="stat-value">3</div>
<div class="stat-label">Pending Reviews</div>
</div>
<div class="stat-box">
<div class="stat-value">98%</div>
<div class="stat-label">Satisfaction Rate</div>
</div>
</div>
<!-- Filter Tabs -->
<div class="filter-tabs">
<button class="filter-tab active" onclick="filterReports('all')">All Reports</button>
<button class="filter-tab" onclick="filterReports('completed')">Completed</button>
<button class="filter-tab" onclick="filterReports('pending')">Pending</button>
<button class="filter-tab" onclick="filterReports('scheduled')">Scheduled</button>
</div>
<!-- Action Bar -->
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;">
<div style="display: flex; gap: 1rem;">
<select class="form-select" style="width: 200px;">
<option>All Vessels</option>
<option>Sea Breeze</option>
<option>Wave Runner</option>
<option>Ocean Spirit</option>
</select>
<select class="form-select" style="width: 200px;">
<option>Last 30 Days</option>
<option>Last 3 Months</option>
<option>Last 6 Months</option>
<option>Last Year</option>
</select>
</div>
<button class="btn btn-primary">
<i data-lucide="download"></i>
Export All
</button>
</div>
<!-- Reports Grid -->
<div class="reports-grid">
<!-- Report Card 1 -->
<div class="report-card">
<div class="report-header">
<div>
<h4>Annual Inspection</h4>
<p style="color: #6b7280; font-size: 0.875rem;">Sea Breeze</p>
</div>
<span class="report-status completed">Completed</span>
</div>
<div class="report-details">
<div class="report-detail-row">
<span style="color: #6b7280;">Report #</span>
<strong>SR-2024-089</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Date</span>
<strong>Nov 10, 2024</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Technician</span>
<strong>Mike Johnson</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Duration</span>
<strong>5.5 hours</strong>
</div>
</div>
<div style="display: flex; gap: 0.5rem; margin-top: 1rem;">
<button class="btn btn-sm btn-secondary" style="flex: 1;">
<i data-lucide="eye"></i>
View
</button>
<button class="btn btn-sm btn-primary" style="flex: 1;">
<i data-lucide="download"></i>
Download
</button>
</div>
</div>
<!-- Report Card 2 -->
<div class="report-card">
<div class="report-header">
<div>
<h4>Engine Service</h4>
<p style="color: #6b7280; font-size: 0.875rem;">Wave Runner</p>
</div>
<span class="report-status completed">Completed</span>
</div>
<div class="report-details">
<div class="report-detail-row">
<span style="color: #6b7280;">Report #</span>
<strong>SR-2024-087</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Date</span>
<strong>Oct 28, 2024</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Technician</span>
<strong>Sarah Williams</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Duration</span>
<strong>3.5 hours</strong>
</div>
</div>
<div style="display: flex; gap: 0.5rem; margin-top: 1rem;">
<button class="btn btn-sm btn-secondary" style="flex: 1;">
<i data-lucide="eye"></i>
View
</button>
<button class="btn btn-sm btn-primary" style="flex: 1;">
<i data-lucide="download"></i>
Download
</button>
</div>
</div>
<!-- Report Card 3 -->
<div class="report-card">
<div class="report-header">
<div>
<h4>Hull Cleaning</h4>
<p style="color: #6b7280; font-size: 0.875rem;">Ocean Spirit</p>
</div>
<span class="report-status pending">Pending Review</span>
</div>
<div class="report-details">
<div class="report-detail-row">
<span style="color: #6b7280;">Report #</span>
<strong>SR-2024-086</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Date</span>
<strong>Nov 5, 2024</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Technician</span>
<strong>Tom Davis</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Duration</span>
<strong>2.5 hours</strong>
</div>
</div>
<div style="display: flex; gap: 0.5rem; margin-top: 1rem;">
<button class="btn btn-sm btn-secondary" style="flex: 1;">
<i data-lucide="eye"></i>
Review
</button>
<button class="btn btn-sm" style="flex: 1; background: #fbbf24; color: #78350f;">
<i data-lucide="message-circle"></i>
Feedback
</button>
</div>
</div>
<!-- Report Card 4 -->
<div class="report-card">
<div class="report-header">
<div>
<h4>Electronics Check</h4>
<p style="color: #6b7280; font-size: 0.875rem;">Sea Breeze</p>
</div>
<span class="report-status completed">Completed</span>
</div>
<div class="report-details">
<div class="report-detail-row">
<span style="color: #6b7280;">Report #</span>
<strong>SR-2024-085</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Date</span>
<strong>Oct 15, 2024</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Technician</span>
<strong>Tom Davis</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Duration</span>
<strong>4.0 hours</strong>
</div>
</div>
<div style="display: flex; gap: 0.5rem; margin-top: 1rem;">
<button class="btn btn-sm btn-secondary" style="flex: 1;">
<i data-lucide="eye"></i>
View
</button>
<button class="btn btn-sm btn-primary" style="flex: 1;">
<i data-lucide="download"></i>
Download
</button>
</div>
</div>
<!-- Report Card 5 -->
<div class="report-card">
<div class="report-header">
<div>
<h4>Quarterly Maintenance</h4>
<p style="color: #6b7280; font-size: 0.875rem;">Wave Runner</p>
</div>
<span class="report-status in-progress">In Progress</span>
</div>
<div class="report-details">
<div class="report-detail-row">
<span style="color: #6b7280;">Report #</span>
<strong>SR-2024-090</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Date</span>
<strong>Dec 22, 2024</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Technician</span>
<strong>Mike Johnson</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Status</span>
<strong>Scheduled</strong>
</div>
</div>
<div style="display: flex; gap: 0.5rem; margin-top: 1rem;">
<button class="btn btn-sm btn-secondary" style="flex: 1;">
<i data-lucide="calendar"></i>
Details
</button>
<button class="btn btn-sm" style="flex: 1; background: #ef4444; color: white;">
<i data-lucide="x-circle"></i>
Cancel
</button>
</div>
</div>
<!-- Report Card 6 -->
<div class="report-card">
<div class="report-header">
<div>
<h4>Safety Equipment</h4>
<p style="color: #6b7280; font-size: 0.875rem;">Ocean Spirit</p>
</div>
<span class="report-status completed">Completed</span>
</div>
<div class="report-details">
<div class="report-detail-row">
<span style="color: #6b7280;">Report #</span>
<strong>SR-2024-084</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Date</span>
<strong>Sep 20, 2024</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Technician</span>
<strong>Sarah Williams</strong>
</div>
<div class="report-detail-row">
<span style="color: #6b7280;">Duration</span>
<strong>2.0 hours</strong>
</div>
</div>
<div style="display: flex; gap: 0.5rem; margin-top: 1rem;">
<button class="btn btn-sm btn-secondary" style="flex: 1;">
<i data-lucide="eye"></i>
View
</button>
<button class="btn btn-sm btn-primary" style="flex: 1;">
<i data-lucide="download"></i>
Download
</button>
</div>
</div>
</div>
<!-- Pagination -->
<div style="display: flex; justify-content: center; gap: 0.5rem; margin-top: 3rem;">
<button class="btn btn-sm" disabled style="opacity: 0.5;">
<i data-lucide="chevron-left"></i>
</button>
<button class="btn btn-sm btn-primary">1</button>
<button class="btn btn-sm">2</button>
<button class="btn btn-sm">3</button>
<button class="btn btn-sm">4</button>
<button class="btn btn-sm">
<i data-lucide="chevron-right"></i>
</button>
</div>
</div>
</main>
</div>
<script>
// Initialize Lucide icons
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
});
// Toggle sidebar
function toggleSidebar() {
document.getElementById('sidebar').classList.toggle('collapsed');
}
// Logout function
function logout() {
localStorage.clear();
window.location.href = '../portal-login.html';
}
// Filter reports
function filterReports(type) {
document.querySelectorAll('.filter-tab').forEach(tab => {
tab.classList.remove('active');
});
event.target.classList.add('active');
// In a real app, this would filter the reports
}
</script>
</body>
</html>

View File

@@ -0,0 +1,507 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Schedule Service - HarborSmith Portal</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="../css/voyage-layout.css">
<link rel="stylesheet" href="../css/themes.css">
<link rel="stylesheet" href="../css/portal-styles.css">
<link rel="stylesheet" href="../css/maintenance-enhanced.css">
<style>
.schedule-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
margin-bottom: 2rem;
}
.calendar-widget {
background: white;
border-radius: 16px;
padding: 1.5rem;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.calendar-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 0.5rem;
}
.calendar-day {
aspect-ratio: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
background: #f9fafb;
}
.calendar-day:hover {
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
transform: translateY(-2px);
}
.calendar-day.available {
background: linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%);
}
.calendar-day.selected {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.time-slots {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
.time-slot {
padding: 1rem;
border-radius: 12px;
background: #f3f4f6;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
border: 2px solid transparent;
}
.time-slot:hover {
background: white;
border-color: #667eea;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.time-slot.selected {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-color: transparent;
}
.service-type-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.service-type-card {
padding: 1.5rem;
border-radius: 12px;
background: white;
border: 2px solid #e5e7eb;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
}
.service-type-card:hover {
border-color: #667eea;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
}
.service-type-card.selected {
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
border-color: #667eea;
}
.booking-summary {
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
border-radius: 16px;
padding: 2rem;
border-left: 4px solid #667eea;
}
.summary-row {
display: flex;
justify-content: space-between;
padding: 0.75rem 0;
border-bottom: 1px solid #e5e7eb;
}
.summary-row:last-child {
border-bottom: none;
}
@media (max-width: 1024px) {
.schedule-container {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body class="portal">
<div class="portal-wrapper">
<!-- Sidebar -->
<aside class="portal-sidebar" id="sidebar">
<div class="sidebar-header">
<a href="maintenance-dashboard.html" class="sidebar-logo">
<img src="../logo.jpg" alt="HarborSmith">
<span>HarborSmith</span>
</a>
<button class="sidebar-toggle" onclick="toggleSidebar()">
<i data-lucide="menu"></i>
</button>
</div>
<nav class="sidebar-nav">
<div class="sidebar-section">
<div class="sidebar-section-title">Main</div>
<a href="maintenance-dashboard.html" class="sidebar-link">
<i data-lucide="layout-dashboard"></i>
<span>Dashboard</span>
</a>
<a href="maintenance-vessels.html" class="sidebar-link">
<i data-lucide="ship"></i>
<span>My Vessels</span>
</a>
<a href="maintenance-schedule.html" class="sidebar-link active">
<i data-lucide="calendar"></i>
<span>Schedule Service</span>
</a>
</div>
<div class="sidebar-section">
<div class="sidebar-section-title">Records</div>
<a href="maintenance-documents.html" class="sidebar-link">
<i data-lucide="file-text"></i>
<span>Documents</span>
</a>
<a href="maintenance-reports.html" class="sidebar-link">
<i data-lucide="clipboard-list"></i>
<span>Service Reports</span>
</a>
<a href="maintenance-invoices.html" class="sidebar-link">
<i data-lucide="receipt"></i>
<span>Invoices</span>
</a>
</div>
<div class="sidebar-section">
<div class="sidebar-section-title">Account</div>
<a href="#" class="sidebar-link">
<i data-lucide="settings"></i>
<span>Settings</span>
</a>
<a href="../portal-login.html" class="sidebar-link" onclick="logout()">
<i data-lucide="log-out"></i>
<span>Logout</span>
</a>
</div>
</nav>
</aside>
<!-- Main Content -->
<main class="portal-main">
<!-- Header -->
<header class="portal-header">
<div class="portal-breadcrumb">
<span>Maintenance Portal</span>
<span class="breadcrumb-separator">/</span>
<span>Schedule Service</span>
</div>
<div class="portal-header-actions">
<div class="header-search">
<i data-lucide="search"></i>
<input type="text" placeholder="Search...">
</div>
<button class="header-notifications" style="background: none; border: none; cursor: pointer; position: relative;">
<i data-lucide="bell"></i>
<span class="notification-badge">3</span>
</button>
<div class="header-user">
<div class="user-avatar">JS</div>
<div>
<div style="font-weight: 600;">John Smith</div>
<div style="font-size: 0.875rem; color: var(--text-light);">Maintenance Client</div>
</div>
</div>
</div>
</header>
<!-- Page Content -->
<div class="portal-content">
<div class="page-header">
<h1>Schedule Service</h1>
<p>Book maintenance services for your vessels</p>
</div>
<!-- Step 1: Select Vessel and Service -->
<div class="dashboard-card fade-in" style="margin-bottom: 2rem;">
<h3 style="margin-bottom: 1.5rem;">
<i data-lucide="ship" style="width: 20px; height: 20px; display: inline; margin-right: 0.5rem;"></i>
Select Vessel & Service Type
</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 2rem;">
<div class="form-group">
<label class="form-label">Select Vessel</label>
<select class="form-select">
<option>Sea Breeze - 2019 Beneteau 45</option>
<option>Wave Runner - 2021 Sea Ray 350</option>
<option>Ocean Spirit - 2020 Catalina 425</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Priority Level</label>
<select class="form-select">
<option>Routine (Within 2 weeks)</option>
<option>Urgent (Within 3 days)</option>
<option>Emergency (Within 24 hours)</option>
</select>
</div>
</div>
<h4 style="margin-bottom: 1rem;">Service Type</h4>
<div class="service-type-grid">
<div class="service-type-card selected">
<i data-lucide="wrench" style="width: 32px; height: 32px; margin-bottom: 0.5rem;"></i>
<h5>Annual Maintenance</h5>
<p style="font-size: 0.875rem; color: var(--text-light);">Complete inspection</p>
</div>
<div class="service-type-card">
<i data-lucide="zap" style="width: 32px; height: 32px; margin-bottom: 0.5rem;"></i>
<h5>Engine Service</h5>
<p style="font-size: 0.875rem; color: var(--text-light);">Engine maintenance</p>
</div>
<div class="service-type-card">
<i data-lucide="droplet" style="width: 32px; height: 32px; margin-bottom: 0.5rem;"></i>
<h5>Hull Cleaning</h5>
<p style="font-size: 0.875rem; color: var(--text-light);">Bottom cleaning</p>
</div>
<div class="service-type-card">
<i data-lucide="cpu" style="width: 32px; height: 32px; margin-bottom: 0.5rem;"></i>
<h5>Electronics</h5>
<p style="font-size: 0.875rem; color: var(--text-light);">System check</p>
</div>
</div>
</div>
<!-- Step 2: Select Date and Time -->
<div class="schedule-container">
<div class="calendar-widget">
<div class="calendar-header">
<h3>Select Date</h3>
<div style="display: flex; gap: 0.5rem;">
<button class="btn btn-sm" style="padding: 0.5rem;">
<i data-lucide="chevron-left"></i>
</button>
<button class="btn btn-sm btn-primary">Today</button>
<button class="btn btn-sm" style="padding: 0.5rem;">
<i data-lucide="chevron-right"></i>
</button>
</div>
</div>
<h4 style="text-align: center; margin-bottom: 1rem;">December 2024</h4>
<div class="calendar-grid">
<div style="text-align: center; font-weight: 600; font-size: 0.875rem;">Sun</div>
<div style="text-align: center; font-weight: 600; font-size: 0.875rem;">Mon</div>
<div style="text-align: center; font-weight: 600; font-size: 0.875rem;">Tue</div>
<div style="text-align: center; font-weight: 600; font-size: 0.875rem;">Wed</div>
<div style="text-align: center; font-weight: 600; font-size: 0.875rem;">Thu</div>
<div style="text-align: center; font-weight: 600; font-size: 0.875rem;">Fri</div>
<div style="text-align: center; font-weight: 600; font-size: 0.875rem;">Sat</div>
<div class="calendar-day">1</div>
<div class="calendar-day available">2</div>
<div class="calendar-day">3</div>
<div class="calendar-day">4</div>
<div class="calendar-day available">5</div>
<div class="calendar-day available">6</div>
<div class="calendar-day">7</div>
<div class="calendar-day">8</div>
<div class="calendar-day available selected">9</div>
<div class="calendar-day">10</div>
<div class="calendar-day">11</div>
<div class="calendar-day available">12</div>
<div class="calendar-day available">13</div>
<div class="calendar-day">14</div>
<div class="calendar-day">15</div>
<div class="calendar-day available">16</div>
<div class="calendar-day">17</div>
<div class="calendar-day">18</div>
<div class="calendar-day available">19</div>
<div class="calendar-day available">20</div>
<div class="calendar-day">21</div>
</div>
</div>
<div class="calendar-widget">
<h3 style="margin-bottom: 1.5rem;">Available Time Slots - Dec 9</h3>
<div class="time-slots">
<div class="time-slot">8:00 AM</div>
<div class="time-slot selected">10:00 AM</div>
<div class="time-slot">12:00 PM</div>
<div class="time-slot" style="opacity: 0.5; cursor: not-allowed;">2:00 PM</div>
<div class="time-slot">4:00 PM</div>
<div class="time-slot">6:00 PM</div>
</div>
</div>
</div>
<!-- Step 3: Additional Details -->
<div class="dashboard-card" style="margin-bottom: 2rem;">
<h3 style="margin-bottom: 1.5rem;">
<i data-lucide="user" style="width: 20px; height: 20px; display: inline; margin-right: 0.5rem;"></i>
Technician Preference
</h3>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem;">
<div class="service-type-card">
<div style="font-weight: 600;">Any Available</div>
<p style="font-size: 0.875rem; color: var(--text-light);">First available tech</p>
</div>
<div class="service-type-card selected">
<div style="font-weight: 600;">Mike Johnson</div>
<div style="color: #fbbf24;">★★★★★</div>
<p style="font-size: 0.875rem; color: var(--text-light);">Your regular technician</p>
</div>
<div class="service-type-card">
<div style="font-weight: 600;">Sarah Williams</div>
<div style="color: #fbbf24;">★★★★★</div>
<p style="font-size: 0.875rem; color: var(--text-light);">Engine specialist</p>
</div>
</div>
<div class="form-group" style="margin-top: 2rem;">
<label class="form-label">Special Instructions</label>
<textarea class="form-textarea" rows="4" placeholder="Any special instructions or concerns..."></textarea>
</div>
<div style="display: flex; gap: 2rem; margin-top: 1rem;">
<label style="display: flex; align-items: center; gap: 0.5rem;">
<input type="checkbox" checked> Send SMS reminders
</label>
<label style="display: flex; align-items: center; gap: 0.5rem;">
<input type="checkbox" checked> Send email confirmation
</label>
<label style="display: flex; align-items: center; gap: 0.5rem;">
<input type="checkbox"> Add to my calendar
</label>
</div>
</div>
<!-- Booking Summary -->
<div class="dashboard-card">
<h3 style="margin-bottom: 1.5rem;">
<i data-lucide="file-text" style="width: 20px; height: 20px; display: inline; margin-right: 0.5rem;"></i>
Booking Summary
</h3>
<div class="booking-summary">
<div class="summary-row">
<span style="color: var(--text-light);">Vessel:</span>
<strong>Sea Breeze - 2019 Beneteau 45</strong>
</div>
<div class="summary-row">
<span style="color: var(--text-light);">Service:</span>
<strong>Annual Maintenance</strong>
</div>
<div class="summary-row">
<span style="color: var(--text-light);">Date:</span>
<strong>December 9, 2024</strong>
</div>
<div class="summary-row">
<span style="color: var(--text-light);">Time:</span>
<strong>10:00 AM</strong>
</div>
<div class="summary-row">
<span style="color: var(--text-light);">Technician:</span>
<strong>Mike Johnson</strong>
</div>
<div class="summary-row">
<span style="color: var(--text-light);">Estimated Duration:</span>
<strong>4-6 hours</strong>
</div>
<div class="summary-row" style="font-size: 1.125rem; padding-top: 1rem;">
<span style="color: var(--text-light);">Estimated Cost:</span>
<strong style="color: var(--primary-600);">$1,200 - $1,500</strong>
</div>
</div>
<div style="display: flex; gap: 1rem; margin-top: 2rem; justify-content: flex-end;">
<button class="btn btn-secondary">
<i data-lucide="save"></i>
Save as Draft
</button>
<button class="btn btn-primary">
<i data-lucide="check-circle"></i>
Confirm Booking
</button>
</div>
</div>
</div>
</main>
</div>
<script>
// Initialize Lucide icons
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
});
// Toggle sidebar
function toggleSidebar() {
document.getElementById('sidebar').classList.toggle('collapsed');
}
// Logout function
function logout() {
localStorage.clear();
window.location.href = '../portal-login.html';
}
// Service type selection
document.querySelectorAll('.service-type-card').forEach(card => {
card.addEventListener('click', function() {
document.querySelectorAll('.service-type-card').forEach(c => c.classList.remove('selected'));
this.classList.add('selected');
});
});
// Calendar day selection
document.querySelectorAll('.calendar-day').forEach(day => {
day.addEventListener('click', function() {
if (!this.classList.contains('available')) return;
document.querySelectorAll('.calendar-day').forEach(d => d.classList.remove('selected'));
this.classList.add('selected');
});
});
// Time slot selection
document.querySelectorAll('.time-slot').forEach(slot => {
slot.addEventListener('click', function() {
if (this.style.opacity === '0.5') return;
document.querySelectorAll('.time-slot').forEach(s => s.classList.remove('selected'));
this.classList.add('selected');
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,418 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Vessels - HarborSmith Portal</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="../css/voyage-layout.css">
<link rel="stylesheet" href="../css/themes.css">
<link rel="stylesheet" href="../css/portal-styles.css">
<link rel="stylesheet" href="../css/maintenance-enhanced.css">
</head>
<body class="portal">
<div class="portal-wrapper">
<!-- Sidebar (Same as dashboard) -->
<aside class="portal-sidebar" id="sidebar">
<div class="sidebar-header">
<a href="maintenance-dashboard.html" class="sidebar-logo">
<img src="../logo.jpg" alt="HarborSmith">
<span>HarborSmith</span>
</a>
<button class="sidebar-toggle" onclick="toggleSidebar()">
<i data-lucide="menu"></i>
</button>
</div>
<nav class="sidebar-nav">
<div class="sidebar-section">
<div class="sidebar-section-title">Main</div>
<a href="maintenance-dashboard.html" class="sidebar-link">
<i data-lucide="layout-dashboard"></i>
<span>Dashboard</span>
</a>
<a href="maintenance-vessels.html" class="sidebar-link active">
<i data-lucide="ship"></i>
<span>My Vessels</span>
</a>
<a href="maintenance-schedule.html" class="sidebar-link">
<i data-lucide="calendar"></i>
<span>Schedule Service</span>
</a>
</div>
<div class="sidebar-section">
<div class="sidebar-section-title">Records</div>
<a href="maintenance-documents.html" class="sidebar-link">
<i data-lucide="file-text"></i>
<span>Documents</span>
</a>
<a href="maintenance-reports.html" class="sidebar-link">
<i data-lucide="clipboard-list"></i>
<span>Service Reports</span>
</a>
<a href="maintenance-invoices.html" class="sidebar-link">
<i data-lucide="receipt"></i>
<span>Invoices</span>
</a>
</div>
<div class="sidebar-section">
<div class="sidebar-section-title">Account</div>
<a href="#" class="sidebar-link">
<i data-lucide="settings"></i>
<span>Settings</span>
</a>
<a href="../portal-login.html" class="sidebar-link" onclick="logout()">
<i data-lucide="log-out"></i>
<span>Logout</span>
</a>
</div>
</nav>
</aside>
<!-- Main Content -->
<main class="portal-main">
<!-- Header -->
<header class="portal-header">
<div class="portal-breadcrumb">
<span>Maintenance Portal</span>
<span class="breadcrumb-separator">/</span>
<span>My Vessels</span>
</div>
<div class="portal-header-actions">
<div class="header-search">
<i data-lucide="search"></i>
<input type="text" placeholder="Search vessels...">
</div>
<button class="header-notifications" style="background: none; border: none; cursor: pointer; position: relative;">
<i data-lucide="bell"></i>
<span class="notification-badge">3</span>
</button>
<div class="header-user">
<div class="user-avatar">JS</div>
<div>
<div style="font-weight: 600;">John Smith</div>
<div style="font-size: 0.875rem; color: var(--text-light);">Maintenance Client</div>
</div>
</div>
</div>
</header>
<!-- Content -->
<div class="portal-content">
<!-- Page Header -->
<div class="portal-page-header">
<h1 class="portal-page-title">My Vessels</h1>
<p class="portal-page-subtitle">Manage your fleet and vessel information</p>
</div>
<!-- Actions Bar -->
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-lg);">
<div style="display: flex; gap: var(--space-sm);">
<button class="btn-portal-secondary">
<i data-lucide="filter"></i>
Filter
</button>
<button class="btn-portal-secondary">
<i data-lucide="download"></i>
Export
</button>
</div>
<button class="btn-portal-primary" onclick="showAddVesselModal()">
<i data-lucide="plus"></i>
Add New Vessel
</button>
</div>
<!-- Vessels Grid -->
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); gap: var(--space-md);">
<!-- Vessel Card 1 -->
<div class="dashboard-card">
<div style="position: relative; height: 200px; margin: calc(-1 * var(--space-md)) calc(-1 * var(--space-md)) var(--space-md); overflow: hidden; border-radius: 12px 12px 0 0;">
<img src="../yacht_party_couple_holding_hands.jpg" alt="Sea Breeze" style="width: 100%; height: 100%; object-fit: cover;">
<span class="status-badge success" style="position: absolute; top: 1rem; right: 1rem;">Active</span>
</div>
<h3 style="font-size: 1.25rem; margin-bottom: 0.5rem;">Sea Breeze</h3>
<p style="color: var(--text-light); margin-bottom: var(--space-md);">2019 Beneteau Oceanis 45</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-sm); margin-bottom: var(--space-md);">
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Registration</div>
<div style="font-weight: 600;">CA-1234-SB</div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Length</div>
<div style="font-weight: 600;">45 ft</div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Last Service</div>
<div style="font-weight: 600;">Nov 10, 2024</div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Next Service</div>
<div style="font-weight: 600;">Dec 15, 2024</div>
</div>
</div>
<div style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: var(--space-md);">
<div style="flex: 1; height: 8px; background: var(--soft-cream); border-radius: 4px; overflow: hidden;">
<div style="width: 95%; height: 100%; background: var(--success);"></div>
</div>
<span style="font-weight: 600;">95% Health</span>
</div>
<div style="display: flex; gap: var(--space-sm);">
<button class="btn-portal-primary" style="flex: 1;">
<i data-lucide="eye"></i>
View Details
</button>
<button class="btn-portal-secondary" style="flex: 1;">
<i data-lucide="calendar"></i>
Schedule
</button>
</div>
</div>
<!-- Vessel Card 2 -->
<div class="dashboard-card">
<div style="position: relative; height: 200px; margin: calc(-1 * var(--space-md)) calc(-1 * var(--space-md)) var(--space-md); overflow: hidden; border-radius: 12px 12px 0 0;">
<img src="../golden_gate.jpg" alt="Wave Runner" style="width: 100%; height: 100%; object-fit: cover;">
<span class="status-badge success" style="position: absolute; top: 1rem; right: 1rem;">Active</span>
</div>
<h3 style="font-size: 1.25rem; margin-bottom: 0.5rem;">Wave Runner</h3>
<p style="color: var(--text-light); margin-bottom: var(--space-md);">2021 Sea Ray Sundancer 350</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-sm); margin-bottom: var(--space-md);">
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Registration</div>
<div style="font-weight: 600;">CA-5678-WR</div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Length</div>
<div style="font-weight: 600;">35 ft</div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Last Service</div>
<div style="font-weight: 600;">Oct 28, 2024</div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Next Service</div>
<div style="font-weight: 600;">Dec 22, 2024</div>
</div>
</div>
<div style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: var(--space-md);">
<div style="flex: 1; height: 8px; background: var(--soft-cream); border-radius: 4px; overflow: hidden;">
<div style="width: 88%; height: 100%; background: var(--warning);"></div>
</div>
<span style="font-weight: 600;">88% Health</span>
</div>
<div style="display: flex; gap: var(--space-sm);">
<button class="btn-portal-primary" style="flex: 1;">
<i data-lucide="eye"></i>
View Details
</button>
<button class="btn-portal-secondary" style="flex: 1;">
<i data-lucide="calendar"></i>
Schedule
</button>
</div>
</div>
<!-- Vessel Card 3 -->
<div class="dashboard-card">
<div style="position: relative; height: 200px; margin: calc(-1 * var(--space-md)) calc(-1 * var(--space-md)) var(--space-md); overflow: hidden; border-radius: 12px 12px 0 0;">
<img src="../diver.jpg" alt="Ocean Spirit" style="width: 100%; height: 100%; object-fit: cover;">
<span class="status-badge success" style="position: absolute; top: 1rem; right: 1rem;">Active</span>
</div>
<h3 style="font-size: 1.25rem; margin-bottom: 0.5rem;">Ocean Spirit</h3>
<p style="color: var(--text-light); margin-bottom: var(--space-md);">2020 Catalina 425</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-sm); margin-bottom: var(--space-md);">
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Registration</div>
<div style="font-weight: 600;">CA-9012-OS</div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Length</div>
<div style="font-weight: 600;">42.5 ft</div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Last Service</div>
<div style="font-weight: 600;">Nov 5, 2024</div>
</div>
<div>
<div style="font-size: 0.875rem; color: var(--text-light);">Next Service</div>
<div style="font-weight: 600;">Jan 5, 2025</div>
</div>
</div>
<div style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: var(--space-md);">
<div style="flex: 1; height: 8px; background: var(--soft-cream); border-radius: 4px; overflow: hidden;">
<div style="width: 92%; height: 100%; background: var(--success);"></div>
</div>
<span style="font-weight: 600;">92% Health</span>
</div>
<div style="display: flex; gap: var(--space-sm);">
<button class="btn-portal-primary" style="flex: 1;">
<i data-lucide="eye"></i>
View Details
</button>
<button class="btn-portal-secondary" style="flex: 1;">
<i data-lucide="calendar"></i>
Schedule
</button>
</div>
</div>
<!-- Add New Vessel Card -->
<div class="dashboard-card" style="border: 2px dashed var(--border); background: var(--soft-cream); display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 400px; cursor: pointer;" onclick="showAddVesselModal()">
<i data-lucide="plus-circle" style="width: 48px; height: 48px; color: var(--text-light); margin-bottom: var(--space-sm);"></i>
<h3 style="color: var(--text-dark); margin-bottom: 0.5rem;">Add New Vessel</h3>
<p style="color: var(--text-light); text-align: center;">Register a new vessel for maintenance services</p>
</div>
</div>
</div>
</main>
</div>
<!-- Add Vessel Modal (Hidden by default) -->
<div id="addVesselModal" style="display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); z-index: 2000; align-items: center; justify-content: center;">
<div class="portal-form" style="max-width: 600px; max-height: 90vh; overflow-y: auto; margin: var(--space-lg);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-lg);">
<h2 class="form-section-title" style="margin: 0; border: none;">Add New Vessel</h2>
<button onclick="hideAddVesselModal()" style="background: none; border: none; cursor: pointer;">
<i data-lucide="x"></i>
</button>
</div>
<form>
<div class="form-section">
<h3 class="form-section-title">Basic Information</h3>
<div class="form-grid">
<div class="form-group">
<label class="form-label required">Vessel Name</label>
<input type="text" class="form-input" placeholder="Enter vessel name">
</div>
<div class="form-group">
<label class="form-label required">Registration Number</label>
<input type="text" class="form-input" placeholder="CA-XXXX-XX">
</div>
<div class="form-group">
<label class="form-label required">Manufacturer</label>
<input type="text" class="form-input" placeholder="e.g., Beneteau">
</div>
<div class="form-group">
<label class="form-label required">Model</label>
<input type="text" class="form-input" placeholder="e.g., Oceanis 45">
</div>
<div class="form-group">
<label class="form-label required">Year</label>
<input type="number" class="form-input" placeholder="2024">
</div>
<div class="form-group">
<label class="form-label required">Type</label>
<select class="form-select">
<option>Sailboat</option>
<option>Motor Yacht</option>
<option>Catamaran</option>
<option>Sport Fishing</option>
<option>Other</option>
</select>
</div>
</div>
</div>
<div class="form-section">
<h3 class="form-section-title">Specifications</h3>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Length (ft)</label>
<input type="number" class="form-input" placeholder="45">
</div>
<div class="form-group">
<label class="form-label">Beam (ft)</label>
<input type="number" class="form-input" placeholder="14">
</div>
<div class="form-group">
<label class="form-label">Draft (ft)</label>
<input type="number" class="form-input" placeholder="6">
</div>
<div class="form-group">
<label class="form-label">Engine Type</label>
<select class="form-select">
<option>Inboard</option>
<option>Outboard</option>
<option>Inboard/Outboard</option>
<option>Sail Only</option>
</select>
</div>
</div>
</div>
<div class="form-section">
<h3 class="form-section-title">Photos</h3>
<div class="upload-area">
<i data-lucide="upload-cloud" class="upload-icon"></i>
<p>Drag and drop photos here, or click to browse</p>
<p style="font-size: 0.875rem; color: var(--text-light);">Maximum file size: 10MB</p>
</div>
</div>
<div style="display: flex; gap: var(--space-sm); justify-content: flex-end;">
<button type="button" class="btn-portal-secondary" onclick="hideAddVesselModal()">Cancel</button>
<button type="submit" class="btn-portal-primary">Add Vessel</button>
</div>
</form>
</div>
</div>
<script>
// Initialize Lucide icons
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
// Check authentication
if (!localStorage.getItem('isLoggedIn')) {
window.location.href = '../portal-login.html';
}
});
// Toggle sidebar
function toggleSidebar() {
const sidebar = document.getElementById('sidebar');
sidebar.classList.toggle('collapsed');
}
// Show/Hide Add Vessel Modal
function showAddVesselModal() {
document.getElementById('addVesselModal').style.display = 'flex';
lucide.createIcons();
}
function hideAddVesselModal() {
document.getElementById('addVesselModal').style.display = 'none';
}
// Logout
function logout() {
localStorage.removeItem('isLoggedIn');
localStorage.removeItem('userEmail');
localStorage.removeItem('userName');
localStorage.removeItem('userRole');
}
</script>
</body>
</html>

View File

@@ -0,0 +1,479 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HarborSmith Portal - Login</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<link rel="stylesheet" href="css/voyage-layout.css">
<link rel="stylesheet" href="css/themes.css">
<link rel="stylesheet" href="css/portal-styles.css">
<style>
/* Enhanced Login Page Styles */
.login-container {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.login-right {
background: #f8fafc;
}
.login-form-container {
background: white;
padding: 2.5rem;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}
/* Enhanced Form Fields */
.form-group {
margin-bottom: 1.5rem;
}
.form-label {
display: block;
margin-bottom: 0.75rem;
font-weight: 600;
color: #1f2937;
font-size: 0.95rem;
letter-spacing: 0.025em;
}
.form-input {
width: 100%;
padding: 0.875rem 1rem;
font-size: 1rem;
border: 2px solid #e5e7eb;
border-radius: 12px;
background: #f9fafb;
transition: all 0.3s ease;
font-family: 'Inter', sans-serif;
}
.form-input:focus {
outline: none;
border-color: #6366f1;
background: white;
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
transform: translateY(-2px);
}
.form-input::placeholder {
color: #9ca3af;
}
/* Enhanced Primary Button */
.btn-portal-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 1rem 2rem;
border: none;
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
width: 100%;
margin-top: 0.5rem;
box-shadow: 0 4px 6px rgba(99, 102, 241, 0.25);
}
.btn-portal-primary:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(99, 102, 241, 0.35);
}
.btn-portal-primary:active {
transform: translateY(-1px);
}
/* Enhanced Role Selector */
.role-selector {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
padding: 0.5rem;
background: #f3f4f6;
border-radius: 16px;
}
.role-option {
flex: 1;
padding: 1rem;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
font-weight: 500;
color: #6b7280;
background: transparent;
}
.role-option:hover {
background: white;
color: #4b5563;
}
.role-option.active {
background: white;
color: #6366f1;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
/* Enhanced OAuth Buttons */
.oauth-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
padding: 0.875rem 1.5rem;
background: white;
border: 2px solid #e5e7eb;
border-radius: 12px;
font-weight: 500;
color: #374151;
transition: all 0.3s ease;
cursor: pointer;
flex: 1;
}
.oauth-btn:hover {
background: #f9fafb;
border-color: #6366f1;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.oauth-buttons {
display: flex;
gap: 1rem;
margin-top: 1.5rem;
}
/* Enhanced Checkbox */
input[type="checkbox"] {
width: 20px;
height: 20px;
border: 2px solid #e5e7eb;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
}
input[type="checkbox"]:checked {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-color: #6366f1;
}
/* Enhanced Links */
a {
color: #6366f1;
text-decoration: none;
font-weight: 500;
transition: color 0.3s ease;
}
a:hover {
color: #764ba2;
}
/* Divider Enhancement */
.divider {
text-align: center;
margin: 2rem 0;
position: relative;
}
.divider::before {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 1px;
background: #e5e7eb;
}
.divider span {
background: white;
padding: 0 1rem;
position: relative;
color: #9ca3af;
font-size: 0.875rem;
}
/* Demo Credentials Box Enhancement */
.demo-box {
margin-top: 2rem;
padding: 1.25rem;
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
border-radius: 12px;
border-left: 4px solid #f59e0b;
}
/* Password Input with Toggle */
.password-wrapper {
position: relative;
}
.password-toggle {
position: absolute;
right: 1rem;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
color: #9ca3af;
transition: color 0.3s ease;
}
.password-toggle:hover {
color: #6366f1;
}
/* Loading State */
.btn-portal-primary.loading {
pointer-events: none;
opacity: 0.8;
}
.btn-portal-primary.loading::after {
content: '';
width: 16px;
height: 16px;
border: 2px solid white;
border-top-color: transparent;
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin-left: 0.5rem;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* Form animations */
.form-group {
animation: slideUp 0.5s ease forwards;
opacity: 0;
}
.form-group:nth-child(1) { animation-delay: 0.1s; }
.form-group:nth-child(2) { animation-delay: 0.2s; }
.form-group:nth-child(3) { animation-delay: 0.3s; }
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
</head>
<body>
<div class="login-container">
<!-- Left Side - Video/Brand -->
<div class="login-left">
<video autoplay loop muted playsinline class="login-video">
<source src="https://videos.pexels.com/video-files/3571264/3571264-uhd_2560_1440_30fps.mp4" type="video/mp4">
</video>
<div class="login-overlay">
<div class="login-brand">
<img src="logo.jpg" alt="HarborSmith">
<h1>HarborSmith</h1>
<p class="login-tagline">Your trusted partner in yacht services</p>
</div>
<div class="login-features">
<div class="feature-item" style="color: white; margin-bottom: 1rem;">
<i data-lucide="shield-check" style="display: inline; width: 20px; height: 20px; margin-right: 0.5rem;"></i>
Secure & Protected
</div>
<div class="feature-item" style="color: white; margin-bottom: 1rem;">
<i data-lucide="clock" style="display: inline; width: 20px; height: 20px; margin-right: 0.5rem;"></i>
24/7 Access to Your Account
</div>
<div class="feature-item" style="color: white;">
<i data-lucide="users" style="display: inline; width: 20px; height: 20px; margin-right: 0.5rem;"></i>
Personalized Dashboard
</div>
</div>
</div>
</div>
<!-- Right Side - Login Form -->
<div class="login-right">
<div class="login-form-container">
<div class="login-form-header">
<h2 class="login-form-title">Welcome Back</h2>
<p class="login-form-subtitle">Sign in to your HarborSmith account</p>
</div>
<!-- Role Selector -->
<div class="role-selector">
<div class="role-option active" onclick="selectRole(this, 'maintenance')">
<i data-lucide="wrench"></i>
<span>Maintenance</span>
</div>
<div class="role-option" onclick="selectRole(this, 'charter')">
<i data-lucide="sailboat"></i>
<span>Charter</span>
</div>
</div>
<!-- Login Form -->
<form id="loginForm" onsubmit="handleLogin(event)">
<div class="form-group">
<label class="form-label" for="email">Email Address</label>
<input type="email" id="email" class="form-input" placeholder="your@email.com" required>
</div>
<div class="form-group">
<label class="form-label" for="password">Password</label>
<div class="password-wrapper">
<input type="password" id="password" class="form-input" placeholder="Enter your password" required>
<span class="password-toggle" onclick="togglePassword()">
<i data-lucide="eye" id="toggleIcon"></i>
</span>
</div>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" id="remember" style="width: 18px; height: 18px;">
<span style="color: var(--text-light);">Remember me</span>
</label>
<a href="#" style="color: var(--warm-orange); text-decoration: none; font-weight: 500;">Forgot password?</a>
</div>
<button type="submit" class="btn-portal-primary" style="width: 100%; justify-content: center;">
<i data-lucide="log-in"></i>
Sign In
</button>
</form>
<div class="divider">
<span>or continue with</span>
</div>
<!-- OAuth Options -->
<div class="oauth-buttons">
<button class="oauth-btn" onclick="oauthLogin('google')">
<svg width="20" height="20" viewBox="0 0 24 24">
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
<path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
<path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
<path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
</svg>
Sign in with Google
</button>
<button class="oauth-btn" onclick="oauthLogin('apple')">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M17.05 20.28c-.98.95-2.05.88-3.08.36-1.09-.55-2.08-.56-3.24 0-1.44.68-2.2.53-3.06-.36C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.75 1.18-.24 2.31-.91 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.53 4.13zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.53-3.74 4.25z"/>
</svg>
Sign in with Apple
</button>
</div>
<div style="text-align: center; margin-top: 2rem;">
<p style="color: var(--text-light);">
Don't have an account?
<a href="#" style="color: var(--warm-orange); text-decoration: none; font-weight: 500;">Contact Sales</a>
</p>
</div>
<!-- Demo Credentials Notice -->
<div class="demo-box">
<p style="font-size: 0.875rem; color: #92400e; margin-bottom: 0.5rem;">
<strong>Demo Credentials:</strong>
</p>
<p style="font-size: 0.875rem; color: #78350f; margin-bottom: 0.25rem;">
Maintenance: maintenance@demo.com / demo123
</p>
<p style="font-size: 0.875rem; color: #78350f;">
Charter: charter@demo.com / demo123
</p>
</div>
</div>
</div>
</div>
<script>
// Initialize Lucide icons
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
});
// Role selection
function selectRole(element, role) {
document.querySelectorAll('.role-option').forEach(opt => {
opt.classList.remove('active');
});
element.classList.add('active');
// Store selected role
localStorage.setItem('userRole', role);
}
// Handle login
function handleLogin(event) {
event.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const role = localStorage.getItem('userRole') || 'maintenance';
// Demo authentication
if ((email === 'maintenance@demo.com' && password === 'demo123' && role === 'maintenance') ||
(email === 'charter@demo.com' && password === 'demo123' && role === 'charter')) {
// Store user session
localStorage.setItem('isLoggedIn', 'true');
localStorage.setItem('userEmail', email);
localStorage.setItem('userName', role === 'maintenance' ? 'John Smith' : 'Sarah Johnson');
// Redirect to appropriate dashboard
if (role === 'maintenance') {
window.location.href = 'maintenance/maintenance-dashboard.html';
} else {
window.location.href = 'charter/charter-dashboard.html';
}
} else {
alert('Invalid credentials. Please use the demo credentials provided.');
}
}
// OAuth login handler
function oauthLogin(provider) {
alert(`OAuth login with ${provider} would be implemented here in production.`);
}
// Password visibility toggle
function togglePassword() {
const passwordInput = document.getElementById('password');
const toggleIcon = document.getElementById('toggleIcon');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
toggleIcon.setAttribute('data-lucide', 'eye-off');
} else {
passwordInput.type = 'password';
toggleIcon.setAttribute('data-lucide', 'eye');
}
lucide.createIcons();
}
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB