// Coastal Cruise — soft seafoam + deep navy, breezy serif, wave accents // One iOS app, full state, persists packing + tab to localStorage. const C = { // soft seafoam → cream gradient body, with deep navy ink bg: '#EAF1EE', paper: '#FFFFFF', ink: '#0F2A3F', ink2: '#3D5A6C', muted: '#7A8E99', hair: '#D8E2DC', // primary water blue; warm sand accent sea: '#3F6A82', seaDk: '#234357', sand: '#E8C9A0', coral: '#D26E5E', green: '#4F8A7A', red: '#B94A3C', serif: '"Cormorant Garamond", "Cormorant", "Playfair Display", Georgia, serif', sans: '-apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif', }; // ── Wave SVG (animated subtle horizontal drift) ──────────────────────── function CoastalWave({ height = 28, color = C.sea, opacity = 0.18, speed = 18 }) { const id = React.useId(); return ( ); } function CoastalCompass({ size = 14, color = C.muted }) { return ( ); } function CoastalShip({ size = 16, color = C.sea }) { return ( ); } // ── Helpers ──────────────────────────────────────────────────────────── function CoastalChip({ children, color = C.sea, light, style }) { return ( {children} ); } function CoastalCountdown({ label, dateIso, color }) { const days = window.daysUntil(dateIso); const text = days < 0 ? 'In progress' : days === 0 ? 'Today' : `${days} days`; return (
{label}
{days >= 0 ? days : '·'}
{text}
); } // ── HOME / TODAY ─────────────────────────────────────────────────────── function CoastalToday({ leg }) { const T = window.TRIP; const cruiseDays = window.daysUntil(T.legs.cruise.start); const gradDays = window.daysUntil(T.legs.grad.start); return (
{/* hero */}
Summer 2026
Two weeks at sea &
shore.
Logan, Bonich & Baby Kai · May 10 – 23
{/* countdown row */}
{/* "What's next" card */}
Setting sail
Quantum of the Seas
4 nights · Catalina + Ensenada
Dep. Port of LA · May 11
Stateroom
Interior · ZI GTY
Reservation
#366640
{/* highlights */}
Highlights of the trip
{[ { icon: '⚓︎', t: 'Catalina Island', d: 'May 12 · 7AM – 6PM' }, { icon: '✦', t: 'Ensenada port day', d: 'May 13 · use Costco Visa' }, { icon: '🎓', t: "Bonich's JHU graduation", d: 'May 18 · Homewood Field' }, { icon: '✺', t: 'Family in Williamsburg', d: 'May 19 – 22' }, ].map((h, i) => (
{h.icon}
{h.t}
{h.d}
))}
); } // ── TIMELINE ─────────────────────────────────────────────────────────── function CoastalTimeline({ leg, onPickDay }) { const T = window.TRIP; const days = T.days.filter(d => leg === 'all' || d.leg === leg); return (
{/* vertical rope */}
{days.map((d, i) => { const dotColor = d.leg === 'cruise' ? C.sea : C.coral; const status = d.status; return ( ); })}
); } // ── DAY DETAIL SHEET ─────────────────────────────────────────────────── function CoastalDaySheet({ day, onClose }) { if (!day) return null; const dotColor = day.leg === 'cruise' ? C.sea : C.coral; const [allNotes, setAllNotes] = window.tripSync.useShared('notes', {}); const note = allNotes[day.date] || ''; const setNote = (v) => setAllNotes(prev => ({ ...prev, [day.date]: v })); return (
e.stopPropagation()} style={{ background: '#fff', width: '100%', borderRadius: '22px 22px 0 0', padding: '8px 0 38px', maxHeight: '80%', overflow: 'auto', animation: 'coastalSheet 280ms cubic-bezier(.2,.8,.3,1)', position: 'relative', }}>
{day.leg === 'cruise' ? 'The Cruise' : 'Graduation'}
{window.formatDate(day.date, { long: true })}
{day.title}
{day.sub}
Where
{day.where}
Cost
{day.cost > 0 ? `$${day.cost.toLocaleString()}` : '—'}
    {day.details.map((d, i) => (
  • {d}
  • ))}
{/* Notes / journal */}
Journal · shared