/* ============================================================
   UI primitives — Red Sea Pulse
   Exposes components on window for other babel scripts.
   ============================================================ */
const { useState, useEffect, useRef } = React;

/* ---------- ICONS ---------- */
const Ic = {
  wa: (p) => <svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M.06 24l1.68-6.13A11.86 11.86 0 0 1 .14 11.9C.14 5.33 5.5 0 12.07 0a11.83 11.83 0 0 1 8.42 3.49 11.78 11.78 0 0 1 3.48 8.42c0 6.56-5.37 11.9-11.95 11.9a12 12 0 0 1-5.7-1.45L.06 24zM6.6 20.2l.36.21a9.9 9.9 0 0 0 5.05 1.38h.01c5.45 0 9.9-4.43 9.9-9.88a9.82 9.82 0 0 0-2.9-6.99 9.79 9.79 0 0 0-6.99-2.9c-5.46 0-9.9 4.43-9.9 9.88a9.85 9.85 0 0 0 1.51 5.26l.24.38-1 3.64 3.72-.98zm11.39-5.62c-.07-.12-.27-.2-.56-.34-.3-.15-1.76-.87-2.03-.97-.27-.1-.47-.15-.67.15-.2.3-.77.96-.94 1.16-.17.2-.35.22-.64.07-.3-.15-1.25-.46-2.38-1.47-.88-.78-1.47-1.75-1.64-2.05-.17-.3-.02-.46.13-.6.13-.14.3-.35.45-.52.15-.17.2-.3.3-.5.1-.2.05-.37-.02-.52-.07-.15-.67-1.6-.92-2.2-.24-.58-.49-.5-.67-.5l-.57-.01c-.2 0-.52.07-.79.37-.27.3-1.04 1.01-1.04 2.46 0 1.45 1.06 2.86 1.21 3.06.15.2 2.1 3.2 5.08 4.49.71.3 1.26.49 1.69.63.71.22 1.36.19 1.87.12.57-.09 1.76-.72 2-1.41.25-.7.25-1.29.18-1.41z"/></svg>,
  clock: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>,
  van: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 17h2c.6 0 1-.4 1-1v-3c0-.9-.7-1.7-1.5-1.9C18.7 10.6 16 10 16 10s-1.3-1.4-2.2-2.3c-.5-.4-1.1-.7-1.8-.7H5c-.6 0-1.1.4-1.4.9l-1.4 2.9A3.7 3.7 0 0 0 2 12v4c0 .6.4 1 1 1h2"/><circle cx="7" cy="17" r="2"/><path d="M9 17h6"/><circle cx="17" cy="17" r="2"/></svg>,
  bag: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 8h14l-1 12H6z"/><path d="M9 8V6a3 3 0 0 1 6 0v2"/></svg>,
  mask: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M4 7h12a1 1 0 0 1 1 1v4.5a2.5 2.5 0 0 1-2.5 2.5H14a2 2 0 0 1-2-2a2 2 0 1 0-4 0a2 2 0 0 1-2 2h-.5A2.5 2.5 0 0 1 3 12.5V8a1 1 0 0 1 1-1"/><path d="M10 17a2 2 0 0 0 2 2h3.5a5.5 5.5 0 0 0 5.5-5.5V4"/></svg>,
  family: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M16 3.128a4 4 0 0 1 0 7.744M22 21v-2a4 4 0 0 0-3-3.87"/><circle cx="9" cy="7" r="4"/></svg>,
  chat: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M4 5h16v11H9l-4 3z"/></svg>,
  mail: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/></svg>,
  wave: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M2 9c2 0 2.5 2 4.5 2S9 9 11 9s2.5 2 4.5 2S18 9 20 9"/><path d="M2 14c2 0 2.5 2 4.5 2S9 14 11 14s2.5 2 4.5 2S18 14 20 14"/></svg>,
  check: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 6L9 17l-5-5"/></svg>,
  x: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M18 6L6 18M6 6l12 12"/></svg>,
  arrow: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14M13 6l6 6-6 6"/></svg>,
  plus: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 5v14M5 12h14"/></svg>,
  bolt: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M13 2L4 14h7l-1 8 9-12h-7z"/></svg>,
  users: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="9" cy="8" r="3"/><path d="M3 20v-1.5a5 5 0 0 1 5-5h2a5 5 0 0 1 5 5V20"/><path d="M16 5.5a3 3 0 0 1 0 5.5M18.5 20v-1.5a5 5 0 0 0-2.5-4.3"/></svg>,
  shield: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="m9 12l2 2l4-4"/></svg>,
  leaf: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M11 20A7 7 0 0 1 4 13c0-5 5-9 16-9 0 9-4 14-9 14z"/><path d="M8 17c2-4 5-6 9-7"/></svg>,
  dolphin: (p)=> <svg viewBox="0 0 512 512" fill="currentColor" {...p}><path d="M123.22 47.23c29.498 15.152 55.025 36.05 55.53 67.366c-93.62 83.867-83.862 179.356-97.002 270.34c-67.68 55.552-67.57 90.948-60.9 101.227c3.94.743 29.11-25.94 48.326-30.397c14.23-4.094 12.284-15.99 16.273-25.275c2.438 14.55 7.17 22.612 17.133 25.485c12.874 3.36 44.932 28.15 51.53 25.504c1.374-20.382-26.01-63.854-48.028-90.087c41.012-63.28 81.365-136.458 211.162-207.77c-3.21-3.706-6.216-6.45-8.8-7.986l9.198-15.472c11.617 6.907 20.522 19.56 29.248 35.033c5.94 10.532 11.528 22.644 16.96 35.117c15.682-32.87 22.983-66.406 16.402-90.254l17.35-4.786a87 87 0 0 1 1.927 8.83c33.29-4.253 55.718-13.083 85.11-29.322c3.744-2.068 19.054-13.012-.117-16.03c12.62-9.017 7.54-12.063 1.973-15.152c-6.486-3.6-20.302-8.948-35.758-8.556c-12.124-27.863-39.63-47.772-82.225-47.696c-28.532.052-63.842 9.086-105.828 30.688C217.895 27.64 164.92 20.468 123.22 47.23m286.942 28.74a9 9 0 1 1 0 18a9 9 0 0 1 0-18"/></svg>,
  dolphinSearch: (p)=> <svg viewBox="0 0 512 512" fill="currentColor" {...p}><path d="M123.22 47.23c29.498 15.152 55.025 36.05 55.53 67.366c-93.62 83.867-83.862 179.356-97.002 270.34c-67.68 55.552-67.57 90.948-60.9 101.227c3.94.743 29.11-25.94 48.326-30.397c14.23-4.094 12.284-15.99 16.273-25.275c2.438 14.55 7.17 22.612 17.133 25.485c12.874 3.36 44.932 28.15 51.53 25.504c1.374-20.382-26.01-63.854-48.028-90.087c41.012-63.28 81.365-136.458 211.162-207.77c-3.21-3.706-6.216-6.45-8.8-7.986l9.198-15.472c11.617 6.907 20.522 19.56 29.248 35.033c5.94 10.532 11.528 22.644 16.96 35.117c15.682-32.87 22.983-66.406 16.402-90.254l17.35-4.786a87 87 0 0 1 1.927 8.83c33.29-4.253 55.718-13.083 85.11-29.322c3.744-2.068 19.054-13.012-.117-16.03c12.62-9.017 7.54-12.063 1.973-15.152c-6.486-3.6-20.302-8.948-35.758-8.556c-12.124-27.863-39.63-47.772-82.225-47.696c-28.532.052-63.842 9.086-105.828 30.688C217.895 27.64 164.92 20.468 123.22 47.23m286.942 28.74a9 9 0 1 1 0 18a9 9 0 0 1 0-18"/></svg>,
  speedboat: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M2 17h14.4a3 3 0 0 0 2.5-1.34L22 11h-6.23a4 4 0 0 0-1.49.29l-3.56 1.42a4 4 0 0 1-1.49.29H3.5zm4-4l1.5-5"/><path d="M6 8h8l2 3"/></svg>,
  guide: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M4 7h12a1 1 0 0 1 1 1v4.5a2.5 2.5 0 0 1-2.5 2.5H14a2 2 0 0 1-2-2a2 2 0 1 0-4 0a2 2 0 0 1-2 2h-.5A2.5 2.5 0 0 1 3 12.5V8a1 1 0 0 1 1-1"/><path d="M10 17a2 2 0 0 0 2 2h3.5a5.5 5.5 0 0 0 5.5-5.5V4"/></svg>,
  diver: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 12a1 1 0 1 0 2 0a1 1 0 0 0-2 0M2 2l3 3l1.5 4l3.5 2l6 2l1 4l2.5 3M11 8l4.5 1.5"/></svg>,
  plate: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3.4"/></svg>,
  cup: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M6 8h11l-1 11a2 2 0 0 1-2 1.8H9A2 2 0 0 1 7 19z"/><path d="M17 8h1.6a2.2 2.2 0 0 1 0 4.4H16.6"/><path d="M9 4.5c0 1 1 1 1 2M13 4c0 1.2 1 1.2 1 2.2"/></svg>,
  fruit: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 8c-1.4-1.5-4-1.7-5.6-.1C4.6 9.6 4.7 13 6.5 15.7 7.8 17.7 9.8 19 12 19s4.2-1.3 5.5-3.3c1.8-2.7 1.9-6.1.1-7.8C16 6.3 13.4 6.5 12 8z"/><path d="M12 8c.3-2 1.5-3.4 3.5-4"/></svg>,
  lifejacket: (p)=> <svg viewBox="0 0 512 512" fill="currentColor" {...p}><path d="M141 35c-13 0-26.9.98-38.6 2.88c-8.3 1.36-15.6 3.39-20.5 5.33c3.4 24.58 4.8 57.69 0 90.09c-4.9 33.5-16.3 66.4-40.9 85.3V294h142v-25h64V139.2c-16-9.8-27.4-25.9-36.9-42.8c-10.4-18.72-18.4-38.91-26.2-54.37l-.7-1.53c-1.4-.74-4.4-1.84-8.4-2.7c-8.4-1.78-20.7-2.8-33.8-2.8m230 0c-13.1 0-25.4 1.02-33.8 2.8c-4 .86-7 1.96-8.4 2.7l-.7 1.53c-7.8 15.46-15.8 35.65-26.2 54.37c-9.5 16.9-20.9 33-36.9 42.8V269h64v25h142v-75.4c-24.6-18.9-36-51.8-40.9-85.3c-4.8-32.4-3.4-65.51 0-90.09c-4.9-1.94-12.1-3.97-20.5-5.33C397.9 35.98 384 35 371 35M201 287v62h110v-62zm23 14h64v18h-64zM41 344v62c0 1.3.3 3.8.8 7h204.6c.4-2.5.6-4.8.6-7v-39h-64v-23zm288 0v23h-64v39c0 2.2.2 4.5.6 7h204.6c.5-3.2.8-5.7.8-7v-62zM45.4 431c1.5 6 3.2 12.3 5.1 18.2c2.9 8.6 6.3 16.6 9.5 21.9c1.5 2.7 3.1 4.6 4.1 5.4c.4.4.4.5.5.5H208c-.5 0 3.6-1.2 8-5.5c4.5-4.3 9.7-10.8 14.4-18.3c4.3-6.8 8.1-14.6 11-22.2zm225.2 0c2.9 7.6 6.7 15.4 11 22.2c4.7 7.5 9.9 14 14.4 18.3c4.4 4.3 8.5 5.5 8 5.5h143.4l.5-.5c1-.8 2.5-2.7 4.1-5.4c3.2-5.3 6.6-13.3 9.5-21.9c1.9-5.9 3.7-12.2 5.1-18.2z"/></svg>,
  fish: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M6.5 12c.94-3.46 4.94-6 8.5-6s6.06 2.54 7 6c-.94 3.47-3.44 6-7 6s-7.56-2.53-8.5-6M18 12v.5"/><path d="M16 17.93a9.77 9.77 0 0 1 0-11.86m-9 4.6C7 8 5.58 5.97 2.73 5.5c-1 1.5-1 5 .23 6.5c-1.24 1.5-1.24 5-.23 6.5C5.58 18.03 7 16 7 13.33"/><path d="M10.46 7.26C10.2 5.88 9.17 4.24 8 3h5.8a2 2 0 0 1 1.98 1.67l.23 1.4m0 11.86l-.23 1.4A2 2 0 0 1 13.8 21H9.5a5.96 5.96 0 0 0 1.49-3.98"/></svg>,
  coral: (p)=> <svg viewBox="0 0 512 512" fill="currentColor" {...p}><path d="M292.5 25.06c-.4 9.84-.9 19.71-1.4 29.59c-3.8-.38-7.7-2.4-12.3-5.8c-6.9-5.12-14-13.21-21.2-20.3L245 41.43c6.4 6.27 13.9 15 23 21.84c6.3 4.69 14.1 8.57 22.6 9.22c-1.1 37.51-.4 74.91 6.9 111.21c-10.9 14.4-19.6 31-26 48.2c-1 2.7-1.9 5.4-2.9 8.1c-13.4-6-27.7-15.6-41.6-26.8c-13.7-34-14.6-68.6 5-95.7c9.8-6 14.6-17.76 16-29.81l-17.9-2.09c-1 9.34-6.4 16.3-8.9 17.1c-.2.1-.4.1-.6.2l-.1-.1c0 .1-.1.1-.1.2c-1 .2-2.1-.1-4.5-1.7c-3-2.06-7.3-6.96-11.9-15.69l-16 8.32c5.4 10.37 11.1 17.57 17.6 22.17c1.5 1 3 1.8 4.5 2.5c-11.5 22.1-13.4 47.1-8.5 72c-.9-.8-1.7-1.7-2.6-2.5c-24.7-24.5-43.3-48.2-56.6-60.1c-.9-9.9-1.5-17.9-.9-24.5c.9-10.73 3.7-17.78 12.9-26.71l-12.6-12.88c-11.6 11.36-17.1 24.16-18.3 38.09c-.7 9.3.1 19.7 1.3 31c-21.3-11.9-41.34-21.2-66.46-27.5L54 123c25.1 6.3 44.29 15.5 66.7 28.4c6.9 6.1 29.3 33.1 55.8 59.4c24.2 24 52.8 48.7 84.8 60.8c-3.2 23.7-.9 47.2 9.9 67c-6.4 6.7-12 13.8-16.9 21.2c-2.7 4.1-5.1 8.2-7.4 12.4c-22.2-7.7-52.1-26.6-76.8-47.8c-.7-.6-1.4-1.3-2.2-1.9c.3-7.2 3.2-15.7 7.8-24c5.8-10.5 14.2-20.4 21.6-27.1L185.2 258c-8.9 8.1-18.3 19.2-25.2 31.7c-3.2 5.8-6 11.9-7.8 18.2c-7.1-7-13.5-13.9-18.7-20.2c-9.3-11.4-14.6-22.2-15-24.5c-7.3-38.6-10.7-51.1-40.03-90.9l-25.77 19c7.18 9.7 12.44 17.1 16.43 23.2c-13.82 1.5-29.01-2.2-37.78-10.2l-12.1 13.4c15.54 14.1 38.51 18.3 58.95 13.6c3.77 9.4 5.25 19.2 8.8 37.9c.28 1.5.64 2.9 1.05 4.4h-1.03c-19.91.8-37.54 11.6-51.15 26.6l13.32 12.1c14.08-15.5 29.07-23.8 47.67-20.2c3.34 5.2 7.34 10.3 11.84 15.8c10.9 13.3 24.9 27.4 40.5 40.8c10.9 9.3 22.5 18.3 34.3 26.4c-21.2 8.1-52.6 12.5-76.5 8.5l-3 17.7c11.6 2 24 2.6 36.3 1.8c-1.3 4.7-1.4 9.6-.5 14.1c2 10.1 8.7 18.7 17.7 24.8l10.1-14.8c-5.8-4-9.3-9.2-10.2-13.6s-.2-8.3 4.8-13.1c14.7-2.8 28.5-7.4 39.7-13.8c10.7 6.1 21.5 11.3 32.1 15c-11.2 32.6-13 64.6-13.7 84.6h32c.9-27.3 4.6-72.3 28.7-108.8c9.8-14.8 22.6-28.5 40.5-39.3c23.6 4.6 46.6 9.7 67.6 17c-1.8 9.6-7.9 14.5-15.2 22.9c-3.8 4.5-7.9 10-9.8 17.3c-2 7.3-1.7 16 1.5 25.9l17.2-5.4c-2.5-7.6-2.3-12.2-1.4-15.8c1-3.6 3-6.6 6.2-10.2c5.4-6.3 14.8-14.4 18.4-28c10.2 4.5 19.8 9.7 28.6 16l10.4-14.7c-28-20-61.5-30.2-96-37.7c22.6-7.8 50.9-11.8 86.9-10.6c5.4 11.5 16.1 21.7 29.2 30l9.7-15.2c-17.3-11-25.5-23.9-24.7-32.6c.5-4.4 2.9-8.9 9.4-13.9c6.6-5 17.4-10.1 33.3-14l-4.4-17.5c-17.4 4.3-30.4 10-39.9 17.2c-5.2 4.1-9.5 8.8-12.2 13.9c-4.9-.1-9.4-.2-13.9-.1c-13.4.1-26 1-37.9 2.5c19.8-24 31.8-51.9 36.1-83l-17.7-2.5c-1.9 13-5.1 25.2-9.9 36.8c-5.5-.6-10.4-2.9-14.6-6.2c-5.8-4.7-9.9-11.6-11.1-17.7l-17.7 3.6c2.2 10.7 8.4 20.8 17.5 28.1c5 4 11.2 7.2 17.7 8.9c-7.8 13.8-18.1 26.4-30.9 38.1c-22.5 5.9-41.5 14.8-57.4 25.6c-6.7-19.3-5-47 4.9-73.8c10.6-28.4 29.9-54.2 49.9-66.7c4.9 2.1 10.4 3.1 15.7 3.4c11 .6 22.7-1.3 33.7-4c22.1-5.3 41.6-13.9 41.6-13.9l-7.2-16.5s-18.5 8.1-38.6 12.9c-10 2.4-20.4 4-28.5 3.5c-8-.4-12.5-2.5-14.6-5.7c-.8-1.3-1.2-3.8.6-8.6c1.8-4.9 5.6-11 9.9-16.7c8.5-11.3 18.6-20.8 18.6-20.8l-12.2-13.16S359.2 107.1 349.5 120c-4.9 6.5-9.5 13.6-12.3 21.2c-.9 2.4-1.6 4.9-2 7.5c-8.1 4.8-15.7 10.7-22.6 17.5c-6.8-44.5-4.3-92.12-2.2-140.32z"/></svg>,
  calendar: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M8 2v4m8-4v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg>,
  wallet: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1"/><path d="M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4"/></svg>,
  tag: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"/><circle cx="7.5" cy="7.5" r=".5" fill="currentColor"/></svg>,
  help: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3m.08 4h.01"/></svg>,
  fins: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M7 3c-1.2 0-2 .8-2 2v8c-1.4.5-2.5 1.8-2.5 3.4C2.5 19.4 4 21 6 21s3.5-1.6 3.5-3.6c0-1.6-1.1-2.9-2.5-3.4V5"/><path d="M16 3c1.2 0 2 .8 2 2v8c1.4.5 2.5 1.8 2.5 3.4 0 2-1.5 3.6-3.5 3.6s-3.5-1.6-3.5-3.6c0-1.6 1.1-2.9 2.5-3.4V5"/></svg>,
  snorkel: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M4 7h12a1 1 0 0 1 1 1v4.5a2.5 2.5 0 0 1-2.5 2.5H14a2 2 0 0 1-2-2a2 2 0 1 0-4 0a2 2 0 0 1-2 2h-.5A2.5 2.5 0 0 1 3 12.5V8a1 1 0 0 1 1-1"/><path d="M10 17a2 2 0 0 0 2 2h3.5a5.5 5.5 0 0 0 5.5-5.5V4"/></svg>,
  pin: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/></svg>,
  star: (p)=> <svg viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M12 2l2.9 6.3 6.8.7-5.1 4.6 1.4 6.7L12 17.8 6 20.6l1.4-6.7L2.3 9l6.8-.7z"/></svg>,
  boat: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 10.189V14m0-12v3m7 8V7a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v6"/><path d="M19.38 20A11.6 11.6 0 0 0 21 14l-8.188-3.639a2 2 0 0 0-1.624 0L3 14a11.6 11.6 0 0 0 2.81 7.76"/><path d="M2 21c.6.5 1.2 1 2.5 1c2.5 0 2.5-2 5-2c1.3 0 1.9.5 2.5 1s1.2 1 2.5 1c2.5 0 2.5-2 5-2c1.3 0 1.9.5 2.5 1"/></svg>,
  menu: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><path d="M4 7h16M4 12h16M4 17h16"/></svg>,
  sun: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2M5 5l1.5 1.5M17.5 17.5L19 19M19 5l-1.5 1.5M6.5 17.5L5 19"/></svg>,
  anchor: (p)=> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 6v16m7-9l2-1a9 9 0 0 1-18 0l2 1m4-2h6"/><circle cx="12" cy="4" r="2"/></svg>,
};

/* ---------- price formatting ---------- */
function PriceChip({ trip, coral, float, className }) {
  const pl = DATA.priceLabel(trip);
  return (
    <span className={'chip' + (coral ? ' coral' : '') + (float ? ' float' : '') + (className ? ' ' + className : '')}>
      <span className="from">{pl.isFixed ? 'flat' : 'from'}</span>
      <span className="amt">{pl.main}</span>
      <span className="usd">{pl.note}</span>
    </span>
  );
}

/* ---------- meta pill ---------- */
function Pill({ icon, children, dark, solid }) {
  const I = icon ? Ic[icon] : null;
  return <span className={'pill' + (dark ? ' dark' : '') + (solid ? ' solid' : '')}>{I && <I/>}{children}</span>;
}

function Tag({ children, tone }) {
  return <span className={'tag' + (tone ? ' ' + tone : '')}>{children}</span>;
}

/* ---------- buttons ---------- */
function Btn({ kind = 'teal', size, block, href, onClick, children, icon, newTab }) {
  const I = icon ? Ic[icon] : null;
  const cls = `btn btn-${kind}${size ? ' btn-' + size : ''}${block ? ' btn-block' : ''}`;
  const inner = <>{kind === 'wa' && <Ic.wa/>}{children}{I && <I/>}</>;
  if (href) return <a className={cls} href={href} onClick={onClick} target={newTab ? '_blank' : undefined} rel={newTab ? 'noopener' : undefined}>{inner}</a>;
  return <button className={cls} onClick={onClick}>{inner}</button>;
}

/* WhatsApp CTA that opens a prefilled message */
function WAButton({ msg, size = 'lg', block, children }) {
  return <Btn kind="wa" size={size} block={block} icon={null} href={DATA.waLink(msg)} newTab>{children || 'Book via WhatsApp'}</Btn>;
}

/* ---------- PHOTO SLOT (placeholder for real photography) ---------- */
function PhotoSlot({ label, g1, g2, ratio, radius, className, children, overlay, imgSrc, alt }) {
  const [imgFailed, setImgFailed] = useState(false);
  // A real photo is present only when we have a src that hasn't failed to load.
  // `has-image` lets CSS drop the placeholder sheen/stripe overlay for real photos
  // while keeping the full gradient placeholder as a fallback when no/failed image.
  const hasImage = imgSrc && !imgFailed;
  const style = { '--g1': g1 || '#1e6fae', '--g2': g2 || '#0e3a56' };
  if (ratio) style.aspectRatio = ratio;
  if (radius) style.borderRadius = radius;
  return (
    <div className={'photo' + (hasImage ? ' has-image' : '') + (className ? ' ' + className : '')} style={style}>
      {hasImage
        ? <img src={imgSrc} alt={alt || label || ''} onError={() => setImgFailed(true)}
            style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', zIndex: 0 }}/>
        : null}
      <svg className="ph-wave" viewBox="0 0 1200 120" preserveAspectRatio="none" style={{ height: 70 }} aria-hidden="true">
        <path d="M0 70 C 180 20 320 110 540 70 C 760 30 900 100 1200 60 L1200 120 L0 120 Z" fill="rgba(255,255,255,.10)"/>
        <path d="M0 90 C 200 50 360 120 600 88 C 840 56 980 116 1200 86 L1200 120 L0 120 Z" fill="rgba(255,255,255,.07)"/>
      </svg>
      {overlay}
      {children}
      <span className="ph-label">{label}</span>
    </div>
  );
}

/* ---------- ROUTE / DAY TIMELINE ---------- */
function RouteMap({ stops, dark }) {
  return (
    <div className="route">
      {stops.map((s, i) => (
        <div className={'route-stop' + (dark ? ' dark' : '')} key={i}>
          <span className="route-dot"></span>
          <div className="route-time">{s[0]}</div>
          <div style={{ fontFamily: 'var(--display)', fontWeight: 700, fontSize: 18, marginTop: 2, color: dark ? '#fff' : 'var(--ink)' }}>{s[1]}</div>
          <div style={{ color: dark ? 'rgba(234,246,247,.72)' : 'var(--ink-soft)', fontSize: 15, marginTop: 3, maxWidth: '52ch' }}>{s[2]}</div>
        </div>
      ))}
    </div>
  );
}

/* ---------- ACCORDION ---------- */
function Accordion({ q, a, defaultOpen, icon }) {
  const [open, setOpen] = useState(!!defaultOpen);
  const ref = useRef(null);
  return (
    <div className={'acc' + (open ? ' open' : '') + (icon && Ic[icon] ? ' acc-has-ico' : '')}>
      <button className="acc-q" onClick={() => setOpen(o => !o)} aria-expanded={open}>
        {icon && Ic[icon] ? <span className="acc-badge" aria-hidden="true">{React.createElement(Ic[icon], { width: 18, height: 18 })}</span> : null}
        <span className="acc-qtext">{q}</span>
        <span className="acc-ico"><Ic.plus width="15" height="15"/></span>
      </button>
      <div className="acc-a" ref={ref} style={{ maxHeight: open ? (ref.current ? ref.current.scrollHeight : 600) : 0 }}>
        <div className="acc-a-inner">{a}</div>
      </div>
    </div>
  );
}

/* ---------- SCROLL REVEAL ---------- */
function Reveal({ children, delay = 0, className, style, as = 'div' }) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((es) => {
      es.forEach(e => { if (e.isIntersecting) { setTimeout(() => el.classList.add('in'), delay); io.unobserve(el); } });
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
    io.observe(el);
    return () => io.disconnect();
  }, [delay]);
  const Tag = as;
  return <Tag ref={ref} className={'reveal' + (className ? ' ' + className : '')} style={style}>{children}</Tag>;
}

/* ---------- section heading block ---------- */
function SecHead({ kicker, title, lead, center, dark, max }) {
  return (
    <div style={{ maxWidth: max || (center ? 720 : 760), margin: center ? '0 auto' : undefined, textAlign: center ? 'center' : 'left' }}>
      {kicker && <div className={'kicker' + (dark ? ' on-dark' : '') + (center ? ' center' : '')} style={{ marginBottom: 16 }}>{kicker}</div>}
      <h2 className="h-1">{title}</h2>
      {lead && <p className="lead" style={{ marginTop: 18, marginLeft: center ? 'auto' : 0, marginRight: center ? 'auto' : 0 }}>{lead}</p>}
    </div>
  );
}

Object.assign(window, { Ic, PriceChip, Pill, Tag, Btn, WAButton, PhotoSlot, RouteMap, Accordion, Reveal, SecHead });
