// ──────────────────────────────────────────────────────────────
// Ariane Yachting — Preparation: yacht info, preference sheet, itinerary
// ──────────────────────────────────────────────────────────────

// ── French lookup tables ─────────────────────────────────────
const HIGHLIGHT_FR = {
  'Embark · Amalfi Coast cruise':         'Embarquement · Croisière Côte Amalfitaine',
  'Path of the Gods hike':                'Sentiero degli Dei – randonnée',
  "Blue Grotto · Sant'Angelo anchorage":  "Grotte Bleue · Mouillage Sant'Angelo",
  'Cycle Ischia · sail to Procida':       'Vélo à Ischia · Navigation vers Procida',
  'Wedding day':                          'Jour du mariage',
  'Sorrento coast farewell cruise':       "Croisière d'adieu – Côte de Sorrente",
};
const KIND_FR = {
  arrival:'arrivée', departure:'départ', embark:'embarquement', disembark:'débarquement',
  transfer:'transfert', cruise:'navigation', anchor:'mouillage', mooring:'corps-mort',
  dock:'quai', overnight:'nuit', hike:'randonnée', cycle:'vélo',
  visit:'visite', lunch:'déjeuner', dinner:'dîner', cocktail:'cocktail',
  prep:'préparation', ceremony:'cérémonie', other:'autre',
};
const ROLE_FR = {
  'Captain':'Capitaine', 'Chief Stewardess':'Chef de cabine',
  'Chef':'Chef cuisinier', 'Deckhand':'Matelot',
};
const FEATURES_FR = {
  'Beach club':'Beach club', 'Pool · Jacuzzi':'Piscine · Jacuzzi',
  'Gym':'Salle de sport', 'Zero-speed stabilisers':'Stabilisateurs zéro-vitesse',
  'Master on main deck':'Suite principale', 'WiFi Onboard':'WiFi à bord',
  'E-Foil':'E-Foil', 'Seabob':'Seabob',
};

// Multi-kind helpers (backward compat: old stops may have kind string)
function getKinds(el) {
  if (!el) return ['other'];
  if (el.elementType === 'leg') return [el.mode || 'cruise'];
  if (el.elementType === 'stop') return [el.mooring, ...(el.activities||[])].filter(Boolean);
  // legacy fallback
  if (el.kinds && el.kinds.length) return el.kinds;
  if (el.kind) return [el.kind];
  return ['other'];
}
function primaryKind(el) {
  if (!el) return 'other';
  if (el.elementType === 'leg') return el.mode || 'cruise';
  if (el.elementType === 'stop') return el.mooring || (el.activities||[])[0] || 'other';
  return getKinds(el)[0] || 'other';
}
function hasNight(el) {
  if (!el) return false;
  if (el.elementType === 'stop') return !!el.overnight;
  return getKinds(el).includes('overnight');
}

// ── Toy SVG icons ─────────────────────────────────────────────
function ToyIcon({ id, size = 22, color = INK }) {
  const p = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none',
               stroke: color, strokeWidth: '1.5', strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (id) {

    // Motorboat / tender: hull tray + cabin box + angled windscreen + bow
    case 'tender': return (
      <svg {...p}>
        {/* Hull: stern wall left, keel bottom, bow angled right */}
        <path d="M2 19 L2 16 L17 16 L22 19 Z"/>
        {/* Cabin sits on deck */}
        <path d="M5 16 L5 12 L13 12 L13 16"/>
        {/* Angled windscreen */}
        <path d="M5 12 L7 10 L13 10"/>
      </svg>
    );

    // Jet ski (PWC): low rounded body + rider sitting + handlebars
    case 'jetski': return (
      <svg {...p}>
        {/* Low hull — curves up at bow (right) */}
        <path d="M2 18 L2 16 Q8 13 14 13 L20 13 L22 16 L22 18 Z"/>
        {/* Rider head */}
        <circle cx="12" cy="10" r="2"/>
        {/* Handlebars: T shape */}
        <line x1="12" y1="12" x2="12" y2="14"/>
        <path d="M9 13 L15 13"/>
      </svg>
    );

    // Seabob: horizontal torpedo body held in front, U-bar handles on top, propeller tail
    case 'seabob': return (
      <svg {...p}>
        {/* Torpedo body — wide oval, pointed at right */}
        <path d="M3 12 Q3 8 11 8 L18 8 Q22 8 22 12 Q22 16 18 16 L11 16 Q3 16 3 12 Z"/>
        {/* U-bar handles on top */}
        <path d="M8 8 L8 5 L15 5 L15 8"/>
        {/* Rear fins */}
        <path d="M4 10 L2 8 M4 14 L2 16"/>
      </svg>
    );

    // E-Foil: surfboard from side + vertical mast + horizontal foil wing underneath
    case 'efoil': return (
      <svg {...p}>
        {/* Surfboard (elongated oval, side view) */}
        <path d="M3 11 Q12 9 21 11 L21 13 Q12 15 3 13 Z"/>
        {/* Mast straight down from center */}
        <line x1="12" y1="13" x2="12" y2="20"/>
        {/* Foil wings (T bar at base of mast) */}
        <path d="M6 20 L18 20"/>
        {/* Lightning bolt on board */}
        <path d="M13 9 L11 12 L13 12 L11 15" strokeWidth="1.3"/>
      </svg>
    );

    // Stand-up paddleboard: long board + standing person + paddle
    case 'sup': return (
      <svg {...p}>
        {/* Board — long and flat */}
        <path d="M2 16 L22 16 L21 18 L3 18 Z"/>
        {/* Person: head + body */}
        <circle cx="10" cy="11" r="2"/>
        <line x1="10" y1="13" x2="10" y2="16"/>
        {/* Paddle: shaft + T-grip at top + blade at bottom */}
        <line x1="16" y1="6" x2="14" y2="17"/>
        <path d="M14 6 L18 6"/>
        <path d="M13 16 L15 17" strokeWidth="1.3"/>
      </svg>
    );

    // Inflatable sun lounger (towable sofa): reclining chair side view on water
    case 'sofa': return (
      <svg {...p}>
        {/* Float base */}
        <path d="M2 18 L22 18 L22 21 L2 21 Z"/>
        {/* Back rest (left, vertical) */}
        <path d="M3 18 L3 12 L8 12 L8 18"/>
        {/* Curved headrest top */}
        <path d="M3 12 Q5.5 10 8 12"/>
        {/* Angled foot-rest (right side) */}
        <path d="M15 15 L22 12 L22 18"/>
        {/* Seat cushion line */}
        <line x1="8" y1="16" x2="22" y2="16"/>
      </svg>
    );

    // Towable inflatable disc: donut shape + tow rope handle at top
    case 'disc': return (
      <svg {...p}>
        {/* Outer ring */}
        <circle cx="12" cy="15" r="7"/>
        {/* Inner hole */}
        <circle cx="12" cy="15" r="3"/>
        {/* Tow rope + handle */}
        <line x1="12" y1="8" x2="12" y2="4"/>
        <path d="M9 4 L15 4"/>
      </svg>
    );

    default: return null;
  }
}

function YachtDetail({ nav, initialTab }) {
  const [tab, setTab] = React.useState(initialTab || 'overview');
  const [selectedCrew, setSelectedCrew] = React.useState(null);
  const [assignModal, setAssignModal]   = React.useState(null); // { cabinIdx, pending: [] }
  const [cabinSaving, setCabinSaving]   = React.useState(false);
  const y = CHOSEN_YACHT;
  const { lang } = React.useContext(window.LangCtx || React.createContext({ lang: 'fr' }));
  const t = (en, fr) => lang === 'fr' ? fr : en;
  // Captain inline edit
  const captainInline = !!window._isCrewUser && window._captainMode === 'inline';
  const [showSpecsSheet, setShowSpecsSheet] = React.useState(false);
  const [editCabin, setEditCabin] = React.useState(null); // { idx, ...cabin }
  const [editCrew, setEditCrew]   = React.useState(null); // { idx, ...member }
  const [, forceRender] = React.useReducer(x => x + 1, 0);

  const TOYS = [
    { id: 'tender', name: 'Williams Tender',           note: t('Main tender for transfers & water sports', 'Annexe principale · transferts & sports nautiques') },
    { id: 'jetski', name: 'Seadoo Jetski',             note: t('High-performance personal watercraft', 'Jet-ski haute performance') },
    { id: 'seabob', name: 'Seabob Underwater Scooter', note: t('Explore below the surface', 'Explorer sous la surface') },
    { id: 'efoil',  name: 'E-Foil Board',              note: t('Electric hydrofoil surfboard', 'Planche hydrofoil électrique') },
    { id: 'sup',    name: 'Inflatable Paddleboard',    note: t('Stand-up paddleboarding', 'Stand-up paddle') },
    { id: 'sofa',   name: 'Towable Inflatable Sofa',   note: t('Relaxed fun on the water', 'Détente sur l\'eau') },
    { id: 'disc',   name: 'Towable Inflatable Disc',   note: t('Lie-on version · adrenaline fun', 'Version allongée · sensations fortes') },
  ];

  const deckMain  = t('Main deck',  'Pont principal');
  const deckLower = t('Lower deck', 'Pont inférieur');

  const DEFAULT_CABINS_RAW = [
    { name: t('Master','Master'),                deck: deckMain,  note: t('Full-beam suite · private terrace','Suite pleine largeur · terrasse privée'), capacity: 2, assignees: [] },
    { name: t('Double 1','Double 1'),            deck: deckLower, note: t('En-suite · queen bed','Salle de bain privée · lit queen'),                   capacity: 2, assignees: [] },
    { name: t('Double 2','Double 2'),            deck: deckLower, note: t('En-suite · queen bed','Salle de bain privée · lit queen'),                   capacity: 2, assignees: [] },
    { name: t('Double 3','Double 3'),            deck: deckLower, note: t('En-suite · queen bed','Salle de bain privée · lit queen'),                   capacity: 2, assignees: [] },
    { name: t('Double 4 / Twin','Double 4 / Twin'), deck: deckLower, note: t('Convertible double or twin','Convertible double ou twin'),                capacity: 2, assignees: [] },
  ];

  // Mutable cabin state — lets client reassign cabins and persist to Supabase
  const [cabinsRaw, setCabinsRaw] = React.useState(() =>
    (CHOSEN_YACHT.cabins_config && CHOSEN_YACHT.cabins_config.length > 0)
      ? CHOSEN_YACHT.cabins_config
      : DEFAULT_CABINS_RAW
  );

  // Charterers list — comes from Supabase via window.CHARTER_CHARTERERS
  const charterers = (window.CHARTER_CHARTERERS && window.CHARTER_CHARTERERS.length > 0)
    ? window.CHARTER_CHARTERERS.filter(c => c.name?.trim())
    : [];

  // Save updated cabin list back to Supabase
  async function saveCabins(updated) {
    if (!window._sbClient || !window._charterId) return;
    setCabinSaving(true);
    try {
      const config = { ...(window._charterConfig || {}), cabins: updated };
      await window._sbClient.from('charters').upsert({
        charter_id: window._charterId,
        config,
        updated_at: new Date().toISOString(),
      });
      window._charterConfig = config;
      window.CHOSEN_YACHT.cabins_config = updated;
      setCabinsRaw(updated);
    } finally {
      setCabinSaving(false);
    }
  }

  const clientFirstName = (TRIP?.client?.firstName || TRIP?.client?.name || '').split(/[\s&,]+/)[0].toLowerCase();
  const isCrew = !!window._isCrewUser;

  const CABINS = cabinsRaw.map(c => {
    const assignees = c.assignees || [];
    // Crew members see all cabins equally — no gold "your cabin" highlight
    const isYours = !isCrew && clientFirstName && assignees.some(a =>
      a.toLowerCase().includes(clientFirstName) || clientFirstName.includes(a.toLowerCase().split(/[\s&,]+/)[0])
    );
    const assignedLabel = assignees.length > 0
      ? assignees.join(' & ')
      : t('To assign', 'À attribuer');
    return {
      ...c,
      name: pickLang(c, 'name', lang) || c.name,
      note: pickLang(c, 'note', lang) || c.note,
      gold: isYours,
      guests: isYours ? t('Your cabin', 'Votre cabine') : assignedLabel,
    };
  });

  return (
    <div style={{ position: 'relative', width: '100%', height: '100%', background: BG, overflow: 'hidden', fontFamily: '"Inter", system-ui', display: 'flex', flexDirection: 'column' }}>

      {/* Hero — same width as stats bar below */}
      <div style={{ position: 'relative', height: 230, borderRadius: 20, overflow: 'hidden', flexShrink: 0, background: INK, margin: '12px 12px 0' }}>
        <img src={y.img} alt="" style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 55%', transform: 'scale(1.35)', display: 'block' }} />
        {/* bottom gradient */}
        <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(13,27,42,0.88) 0%, rgba(13,27,42,0.2) 50%, rgba(13,27,42,0.35) 100%)' }} />
        {/* side vignette */}
        <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to right, rgba(13,27,42,0.45) 0%, transparent 30%, transparent 70%, rgba(13,27,42,0.45) 100%)' }} />
        <div style={{ position: 'absolute', top: 14, right: 14, background: GOLD, color: INK, fontSize: 10, fontWeight: 700, padding: '5px 10px', borderRadius: 99, letterSpacing: 1 }}>{t('CONFIRMED','CONFIRMÉ')}</div>
        <div style={{ position: 'absolute', bottom: 18, left: 20, right: 20, color: '#fff' }}>
          <div style={{ fontSize: 34, fontWeight: 600, fontFamily: '"Cormorant Garamond", serif', fontStyle: 'italic', letterSpacing: -0.6, lineHeight: 1 }}>{CHOSEN_YACHT.name || 'EH 2'}</div>
        </div>
      </div>

      {/* Stats bar — rounded */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', background: INK, borderRadius: 16, margin: '10px 12px 0', flexShrink: 0, overflow: 'hidden' }}>
        {[
          { k: t('LENGTH','LONG.'), v: CHOSEN_YACHT.length ? `${CHOSEN_YACHT.length}m` : '36.8m' },
          { k: t('CABINS','CABINES'), v: CHOSEN_YACHT.cabins || '5' },
          { k: t('GUESTS MAX','INVITÉS MAX'), v: CHOSEN_YACHT.guests || '10' },
          { k: t('CREW','ÉQUIP.'),   v: CHOSEN_YACHT.crew || '7' },
        ].map((s, i) => (
          <div key={s.k} style={{ textAlign: 'center', padding: '12px 0', borderRight: i < 3 ? '1px solid rgba(255,255,255,0.1)' : 'none' }}>
            <div style={{ fontSize: 17, fontWeight: 600, color: '#fff' }}>{s.v}</div>
            <div style={{ fontSize: 8.5, color: 'rgba(255,255,255,0.45)', marginTop: 3, letterSpacing: 1.2 }}>{s.k}</div>
          </div>
        ))}
      </div>

      {/* Tabs */}
      <div style={{ display: 'flex', gap: 18, padding: '12px 22px 0', background: BG, flexShrink: 0, borderBottom: `1px solid ${LINE}` }}>
        {[
          { id: 'overview', label: t('Overview','Aperçu') },
          { id: 'toys',     label: t('Toys','Jouets') },
          { id: 'cabins',   label: t('Cabins','Cabines') },
          { id: 'crew',     label: t('Crew','Équipage') },
        ].map(tb => (
          <button key={tb.id} onClick={() => setTab(tb.id)} data-track={`yacht_tab:${tb.id}`} style={{
            border: 'none', background: 'none', padding: '2px 0 10px', fontSize: 13,
            fontWeight: tab === tb.id ? 600 : 500,
            color: tab === tb.id ? INK : MUTE, cursor: 'pointer', fontFamily: 'inherit',
            borderBottom: `2px solid ${tab === tb.id ? GOLD : 'transparent'}`,
          }}>{tb.label}</button>
        ))}
      </div>

      <div style={{ flex: 1, overflowY: 'auto', padding: '18px 22px 120px' }} className="no-scrollbar">

        {/* ── Overview ── */}
        {tab === 'overview' && (
          <div>
            {captainInline && (
              <button onClick={() => setShowSpecsSheet(true)}
                style={{
                  width: '100%', marginBottom: 14, padding: '12px 16px', borderRadius: 14,
                  border: `1px solid ${GOLD}`, background: 'rgba(201,168,76,0.08)',
                  cursor: 'pointer', fontFamily: 'inherit', fontSize: 13, fontWeight: 600, color: INK,
                  display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
                }}>
                <Glyph name="edit" size={16} color={INK} /> Edit yacht specs
              </button>
            )}
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 20 }}>
              {[
                { k: t('Builder','Constructeur'),        v: CHOSEN_YACHT.builder || 'Benetti' },
                { k: t('Built','Construit'),             v: CHOSEN_YACHT.year    || '2022' },
                { k: t('Cruising speed','Vitesse croisière'), v: CHOSEN_YACHT.cruisingSpeed || '12.5 kts' },
                { k: t('Max speed','Vitesse max'),      v: CHOSEN_YACHT.maxSpeed  || '18 kts' },
                { k: t('Beam','Largeur'),           v: CHOSEN_YACHT.beam      || '7.8m' },
                { k: t('Draught','Tirant d\'eau'),        v: CHOSEN_YACHT.draught   || '1.96m' },
              ].map(s => (
                <div key={s.k} style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 12, padding: '12px 14px' }}>
                  <div style={{ fontSize: 9.5, color: MUTE, letterSpacing: 0.6, textTransform: 'uppercase' }}>{s.k}</div>
                  <div style={{ fontSize: 14, fontWeight: 600, color: INK, marginTop: 4 }}>{s.v}</div>
                </div>
              ))}
            </div>

            <div style={{ fontSize: 11, letterSpacing: 1.3, textTransform: 'uppercase', color: MUTE, fontWeight: 600, marginBottom: 10 }}>{t('Features','Équipements')}</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
              {(CHOSEN_YACHT.features && CHOSEN_YACHT.features.length > 0
                ? CHOSEN_YACHT.features
                : ['Beach club', 'Pool · Jacuzzi', 'Gym', 'Zero-speed stabilisers', 'Master on main deck', 'WiFi Onboard', 'E-Foil', 'Seabob']
              ).map(m => (
                <span key={m} style={{ fontSize: 11.5, background: '#fff', border: `1px solid ${LINE}`, color: INK, padding: '6px 11px', borderRadius: 99 }}>{lang === 'fr' ? (FEATURES_FR[m] || m) : m}</span>
              ))}
            </div>

            <div style={{ marginTop: 18 }}>
              <div style={{ fontSize: 11, letterSpacing: 1.3, textTransform: 'uppercase', color: MUTE, fontWeight: 600, marginBottom: 10 }}>{t('Gallery','Galerie')}</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
                {(CHOSEN_YACHT.gallery && CHOSEN_YACHT.gallery.length > 0
                  ? CHOSEN_YACHT.gallery
                  : []
                ).map((url, i) => (
                  <div key={i} style={{ height: 120, borderRadius: 14, background: `url(${url}) center/cover`, backgroundColor: LINE }} />
                ))}
              </div>
            </div>
          </div>
        )}

        {/* ── Toys ── */}
        {tab === 'toys' && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {TOYS.map((toy, i) => (
              <div key={i} style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 14, padding: '13px 14px', display: 'flex', gap: 12, alignItems: 'center' }}>
                <div style={{ width: 44, height: 44, borderRadius: 12, background: '#F4F2EC', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                  <ToyIcon id={toy.id} size={24} color={INK} />
                </div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: INK }}>{toy.name}</div>
                  <div style={{ fontSize: 11, color: MUTE, marginTop: 2 }}>{toy.note}</div>
                </div>
              </div>
            ))}
          </div>
        )}

        {/* ── Cabins ── */}
        {tab === 'cabins' && (
          <div>
            <div style={{ height: 150, borderRadius: 16, background: `url(${CHOSEN_YACHT.cabinImg || CHOSEN_YACHT.img || ''}) center/cover`, marginBottom: 14, position: 'relative', overflow: 'hidden' }}>
              <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(13,27,42,0.5), transparent)' }} />
              <div style={{ position: 'absolute', bottom: 10, left: 12, color: '#fff', fontSize: 11, fontWeight: 600, letterSpacing: 0.5 }}>{t('MASTER CABIN · MAIN DECK','SUITE PRINCIPALE · PONT PRINCIPAL')}</div>
            </div>
            <div style={{ fontSize: 11.5, color: MUTE, marginBottom: 16 }}>
              {CABINS.length} {t('staterooms', 'cabines')}
              {CABINS.some(c => c.guests !== t('To assign','À attribuer') && !c.gold) && (
                <span> · {CABINS.filter(c => (c.assignees||[]).length > 0).length} {t('assigned','attribuées')}</span>
              )}
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {CABINS.map((c, i) => (
                <button key={c.name} data-track={`cabin:${c.name}`} onClick={() => setAssignModal({ cabinIdx: i, pending: [...(cabinsRaw[i].assignees || [])] })}
                  style={{
                    width: '100%', background: '#fff', border: `1px solid ${c.gold ? GOLD : LINE}`,
                    borderRadius: 14, padding: '14px 16px', textAlign: 'left', fontFamily: 'inherit',
                    display: 'flex', gap: 12, alignItems: 'center', cursor: 'pointer',
                    boxShadow: c.gold ? `0 4px 16px rgba(201,168,76,0.15)` : 'none',
                  }}>
                  <div style={{
                    width: 42, height: 42, borderRadius: 12, flexShrink: 0,
                    background: c.gold ? `linear-gradient(135deg, ${GOLD}, #A8861F)` : '#F4F2EC',
                    display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 18,
                  }}>
                    {c.gold ? <span style={{ color: INK, fontSize: 16 }}>★</span> : <Glyph name="bed" size={18} color={INK} />}
                  </div>
                  <div style={{ flex: 1 }}>
                    <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                      <div style={{ fontSize: 13, fontWeight: 600, color: INK }}>{c.name}</div>
                      <div style={{ fontSize: 10, color: MUTE, letterSpacing: 0.3 }}>{c.deck}</div>
                    </div>
                    <div style={{ fontSize: 12, color: c.gold ? GOLD : MUTE, fontWeight: c.gold ? 600 : 400, marginTop: 2 }}>{c.guests}</div>
                    <div style={{ fontSize: 11, color: MUTE, marginTop: 1 }}>{c.note}</div>
                  </div>
                  <svg width="6" height="10" viewBox="0 0 6 10" fill="none" style={{ opacity: 0.3, flexShrink: 0 }}>
                    <path d="M1 1l4 4-4 4" stroke={INK} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
                  </svg>
                  {captainInline && (
                    <span onClick={ev => { ev.stopPropagation(); setEditCabin({ idx: i, ...cabinsRaw[i] }); }}
                      style={{ width: 28, height: 28, borderRadius: 14, background: 'rgba(201,168,76,0.18)', border: `1px solid rgba(201,168,76,0.55)`, color: GOLD, fontSize: 12, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, marginLeft: 4 }}><Glyph name="edit" size={14} color={GOLD} /></span>
                  )}
                </button>
              ))}
              {captainInline && (
                <button onClick={() => setEditCabin({ name: '', deck: '', note: '', capacity: 2 })}
                  style={{ width: '100%', padding: '12px 16px', borderRadius: 14, border: `2px dashed ${GOLD}`, background: 'rgba(201,168,76,0.06)', cursor: 'pointer', fontFamily: 'inherit', fontSize: 13, fontWeight: 600, color: INK, marginTop: 4 }}>
                  + Add cabin
                </button>
              )}
            </div>

            {/* ── Cabin assignment bottom sheet ── */}
            {assignModal && (() => {
              const cabin    = cabinsRaw[assignModal.cabinIdx];
              const capacity = cabin.capacity || 2;
              const pending  = assignModal.pending;
              const overCap  = pending.length > capacity;

              function togglePerson(name) {
                setAssignModal(m => {
                  const has  = m.pending.includes(name);
                  return { ...m, pending: has ? m.pending.filter(n => n !== name) : [...m.pending, name] };
                });
              }

              async function confirm() {
                const updated = cabinsRaw.map((c, i) =>
                  i === assignModal.cabinIdx ? { ...c, assignees: pending } : c
                );
                setAssignModal(null);
                await saveCabins(updated);
              }

              return (
                <div style={{ position: 'absolute', inset: 0, zIndex: 100, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end' }}>
                  {/* backdrop */}
                  <div onClick={() => setAssignModal(null)} style={{ position: 'absolute', inset: 0, background: 'rgba(13,27,42,0.45)', backdropFilter: 'blur(2px)' }} />
                  {/* sheet */}
                  <div style={{
                    position: 'relative', background: '#fff', borderRadius: '22px 22px 0 0',
                    padding: '0 0 40px', animation: 'slideUp 220ms ease',
                  }}>
                    {/* handle */}
                    <div style={{ width: 36, height: 4, borderRadius: 2, background: LINE, margin: '12px auto 0' }} />
                    <div style={{ padding: '16px 22px 0' }}>
                      {/* header */}
                      <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 4 }}>
                        <div style={{ fontSize: 16, fontWeight: 700, color: INK }}>{pickLang(cabin, 'name', lang) || cabin.name}</div>
                        <div style={{ fontSize: 11, color: MUTE }}>{cabin.deck}</div>
                      </div>
                      <div style={{ fontSize: 12, color: MUTE, marginBottom: 16 }}>
                        {t('Capacity', 'Capacité')}: {capacity} {t('guest', 'pers.')}{capacity > 1 ? (lang === 'fr' ? '' : 's') : ''}
                        {pending.length > 0 && <span style={{ marginLeft: 8, color: overCap ? '#C9534C' : GOLD, fontWeight: 600 }}>· {pending.length} {t('selected', 'sélectionné')}{pending.length > 1 ? 's' : ''}</span>}
                      </div>

                      {/* charterer chips */}
                      {charterers.length === 0 ? (
                        <div style={{ fontSize: 12, color: MUTE, padding: '12px 0' }}>
                          {t('Guest list not set up yet — ask your broker.', 'La liste des invités n\'est pas encore configurée.')}
                        </div>
                      ) : (
                        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 20 }}>
                          {charterers.map(ch => {
                            const on = pending.includes(ch.name);
                            return (
                              <button key={ch.name} onClick={() => togglePerson(ch.name)} style={{
                                padding: '8px 18px', borderRadius: 99, cursor: 'pointer', fontFamily: 'inherit',
                                border: `1.5px solid ${on ? GOLD : LINE}`,
                                background: on ? 'rgba(201,168,76,0.1)' : '#FAFAF8',
                                color: on ? GOLD : MUTE,
                                fontSize: 13, fontWeight: on ? 700 : 500,
                                transition: 'all 120ms',
                              }}>
                                {on && <span style={{ marginRight: 5 }}>✓</span>}{ch.name}
                              </button>
                            );
                          })}
                        </div>
                      )}

                      {overCap && (
                        <div style={{ fontSize: 11, color: '#C9534C', marginBottom: 10, fontWeight: 500 }}>
                          ⚠ {t('Over cabin capacity', 'Capacité dépassée')} ({capacity})
                        </div>
                      )}

                      <button onClick={confirm} disabled={cabinSaving} style={{
                        width: '100%', padding: 14, borderRadius: 99, border: 'none', cursor: 'pointer',
                        background: GOLD, color: INK, fontSize: 12, fontWeight: 700,
                        letterSpacing: 1.5, textTransform: 'uppercase', fontFamily: 'inherit',
                        opacity: cabinSaving ? 0.6 : 1,
                      }}>
                        {cabinSaving ? t('Saving…', 'Enregistrement…') : t('Confirm assignment', 'Confirmer')}
                      </button>
                    </div>
                  </div>
                </div>
              );
            })()}
          </div>
        )}

        {/* ── Crew ── */}
        {tab === 'crew' && (() => {
          const members = (y.crew_members && y.crew_members.length > 0)
            ? y.crew_members
            : [y.captain, y.chief, y.chef, y.deckhand].filter(Boolean);
          return (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
              {members.map((c, i) => {
                const langs = Array.isArray(c.languages) ? c.languages
                  : (c.languages||'').split(',').map(s=>s.trim()).filter(Boolean);
                const cBio = pickLang(c, 'bio', lang);
                const hasBio = !!(cBio && cBio.trim());
                return (
                  <div key={c.name || i}
                    data-track={`crew:${c.name || 'unknown'}`}
                    onClick={() => hasBio && setSelectedCrew(c)}
                    style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 16, padding: 14,
                      display: 'flex', gap: 14, alignItems: 'center',
                      cursor: hasBio ? 'pointer' : 'default',
                      transition: 'box-shadow 120ms',
                    }}
                    onMouseEnter={e => { if (hasBio) e.currentTarget.style.boxShadow = '0 2px 12px rgba(0,0,0,0.08)'; }}
                    onMouseLeave={e => { e.currentTarget.style.boxShadow = 'none'; }}
                  >
                    <div style={{ width: 52, height: 52, borderRadius: 26, overflow: 'hidden', flexShrink: 0, background: '#F4F2EC' }}>
                      {c.photo
                        ? <img src={c.photo} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 15%' }} />
                        : <div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 22 }}><Glyph name="user" size={22} color={MUTE} /></div>
                      }
                    </div>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                        <div style={{ fontSize: 14, fontWeight: 600, color: INK }}>{c.name}</div>
                        {hasBio && <span style={{ fontSize: 14, color: MUTE, flexShrink: 0 }}>›</span>}
                      </div>
                      <div style={{ fontSize: 11.5, color: MUTE, marginTop: 1 }}>
                        {pickLang(c, 'role', lang) || (lang === 'fr' ? (ROLE_FR[c.role] || c.role) : c.role)}
                        {c.years ? ` · ${c.years} ${t('yrs','ans')} exp.` : ''}
                      </div>
                      {langs.length > 0 && (
                        <div style={{ display: 'flex', gap: 4, marginTop: 6, flexWrap: 'wrap' }}>
                          {langs.map(l => (
                            <span key={l} style={{ fontSize: 9, fontWeight: 700, background: '#F4F2EC', color: INK, padding: '2px 6px', borderRadius: 4, letterSpacing: 0.5 }}>{l}</span>
                          ))}
                        </div>
                      )}
                    </div>
                    {captainInline && (
                      <span onClick={ev => { ev.stopPropagation(); setEditCrew({ idx: i, ...c }); }}
                        style={{ width: 28, height: 28, borderRadius: 14, background: 'rgba(201,168,76,0.18)', border: `1px solid rgba(201,168,76,0.55)`, color: GOLD, fontSize: 12, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><Glyph name="edit" size={14} color={GOLD} /></span>
                    )}
                  </div>
                );
              })}

              {captainInline && (
                <button onClick={() => setEditCrew({ name: '', role: '', languages: [], bio: '', years: '' })}
                  style={{ width: '100%', padding: '12px 16px', borderRadius: 14, border: `2px dashed ${GOLD}`, background: 'rgba(201,168,76,0.06)', cursor: 'pointer', fontFamily: 'inherit', fontSize: 13, fontWeight: 600, color: INK, marginTop: 4 }}>
                  + Add crew member
                </button>
              )}

              {/* Bio bottom sheet */}
              {selectedCrew && (
                <div onClick={() => setSelectedCrew(null)}
                  style={{ position: 'fixed', inset: 0, background: 'rgba(13,27,42,0.55)', zIndex: 60,
                    display: 'flex', alignItems: 'flex-end', justifyContent: 'center' }}>
                  <div onClick={e => e.stopPropagation()}
                    style={{ background: '#fff', borderRadius: '22px 22px 0 0', padding: '0 0 env(safe-area-inset-bottom,24px)',
                      maxHeight: '78vh', width: '100%', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
                    {/* Handle */}
                    <div style={{ display: 'flex', justifyContent: 'center', padding: '10px 0 4px' }}>
                      <div style={{ width: 36, height: 4, borderRadius: 2, background: '#E0DDD6' }} />
                    </div>
                    {/* Header */}
                    <div style={{ display: 'flex', gap: 14, alignItems: 'center', padding: '12px 20px 16px' }}>
                      {selectedCrew.photo
                        ? <img src={selectedCrew.photo} alt="" style={{ width: 56, height: 56, borderRadius: 28, objectFit: 'cover', objectPosition: 'center 15%', flexShrink: 0 }} />
                        : <div style={{ width: 56, height: 56, borderRadius: 28, background: '#F4F2EC', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 24, flexShrink: 0 }}><Glyph name="user" size={24} color={MUTE} /></div>
                      }
                      <div>
                        <div style={{ fontSize: 17, fontWeight: 700, color: INK, lineHeight: 1.2 }}>{selectedCrew.name}</div>
                        <div style={{ fontSize: 12, color: MUTE, marginTop: 2 }}>{pickLang(selectedCrew, 'role', lang) || (lang === 'fr' ? (ROLE_FR[selectedCrew.role]||selectedCrew.role) : selectedCrew.role)}</div>
                        {(() => {
                          const ls = Array.isArray(selectedCrew.languages) ? selectedCrew.languages : (selectedCrew.languages||'').split(',').map(s=>s.trim()).filter(Boolean);
                          return ls.length > 0 ? (
                            <div style={{ display: 'flex', gap: 4, marginTop: 6, flexWrap: 'wrap' }}>
                              {ls.map(l => <span key={l} style={{ fontSize: 9, fontWeight: 700, background: '#F4F2EC', color: INK, padding: '2px 6px', borderRadius: 4, letterSpacing: 0.5 }}>{l}</span>)}
                            </div>
                          ) : null;
                        })()}
                      </div>
                    </div>
                    {/* Bio text */}
                    <div style={{ flex: 1, overflowY: 'auto', padding: '0 22px 28px' }} className="no-scrollbar">
                      <p style={{ fontSize: 13, color: INK, lineHeight: 1.7, margin: 0, whiteSpace: 'pre-wrap' }}>{pickLang(selectedCrew, 'bio', lang)}</p>
                    </div>
                  </div>
                </div>
              )}
            </div>
          );
        })()}

      </div>

      {/* Captain edit sheets */}
      {captainInline && showSpecsSheet && window.YachtSpecsSheet && (() => {
        const Sheet = window.YachtSpecsSheet;
        return <Sheet open={showSpecsSheet} onClose={() => { setShowSpecsSheet(false); forceRender(); }} />;
      })()}
      {captainInline && editCabin && window.CabinEditSheet && (() => {
        const Sheet = window.CabinEditSheet;
        return <Sheet open={!!editCabin} cabin={editCabin} idx={editCabin.idx}
          onClose={() => { setEditCabin(null); forceRender(); }} />;
      })()}
      {captainInline && editCrew && window.CrewEditSheet && (() => {
        const Sheet = window.CrewEditSheet;
        return <Sheet open={!!editCrew} member={editCrew} idx={editCrew.idx}
          onClose={() => { setEditCrew(null); forceRender(); }} />;
      })()}
    </div>
  );
}

// ── Preference sheet ─────────────────────────────────────────
function PreferenceSheet({ nav }) {
  const { lang } = React.useContext(window.LangCtx || React.createContext({ lang: 'fr' }));
  const t = (en, fr) => lang === 'fr' ? fr : en;
  const [data, setData] = React.useState({
    diets: ['Vegetarian (1)'], allergies: 'Shellfish — Claire',
    cuisine: 'Italian', wine: 'White + rosé', service: 'present',
    wake: 'Late (9:30)', dinner: 'Late (21:00)',
  });
  const set = (k, v) => setData({ ...data, [k]: v });

  return (
    <div style={{ position: 'relative', width: '100%', height: '100%', background: BG, overflow: 'hidden', fontFamily: '"Inter", system-ui', display: 'flex', flexDirection: 'column' }}>
      <TopBar title="Preference sheet" sub="So Elena & Luca can prepare everything" onBack={() => nav('home')} />

      <div style={{ flex: 1, overflowY: 'auto', padding: '20px 22px 120px' }} className="no-scrollbar">
        <div style={{ background: 'linear-gradient(135deg, #FAF4E2, #F4EFDE)', padding: 14, borderRadius: 16, display: 'flex', gap: 10, alignItems: 'flex-start', marginBottom: 18 }}>
          <div style={{ width: 36, height: 36, borderRadius: 18, background: GOLD, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 16 }}><Glyph name="boat" size={16} color={INK} /></div>
          <div>
            <div style={{ fontSize: 12, fontWeight: 600 }}>{t('Chief Stewardess', 'Chef de cabine')}</div>
            <div style={{ fontSize: 11.5, color: INK, opacity: 0.75, marginTop: 2, lineHeight: 1.4 }}>
              Hi Olivier & Annabel — these help me plan provisioning, cabins and service. 5 minutes tops.
            </div>
          </div>
        </div>

        <SectionLabel right={<span style={{ fontSize: 11, color: GOLD, fontWeight: 700 }}>60%</span>}>Culinary</SectionLabel>
        <div style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 16, overflow: 'hidden' }}>
          <PrefRow label="Dietary needs" value={data.diets.join(', ')} />
          <PrefRow label="Allergies" value={data.allergies} />
          <PrefRow label="Cuisine style" value={data.cuisine} />
          <PrefRow label="Wine preferences" value={data.wine} last />
        </div>

        <div style={{ height: 18 }} />
        <SectionLabel>Service style</SectionLabel>
        <div style={{ display: 'flex', gap: 8 }}>
          {[
            { id: 'discreet', label: 'Discreet', sub: 'Present when needed' },
            { id: 'present',  label: 'Present',  sub: 'Active attention' },
          ].map(o => {
            const on = data.service === o.id;
            return (
              <button key={o.id} onClick={() => set('service', o.id)} style={{
                flex: 1, padding: 14, borderRadius: 14, border: on ? `1px solid ${INK}` : `1px solid ${LINE}`,
                background: on ? INK : '#fff', color: on ? '#fff' : INK, cursor: 'pointer', fontFamily: 'inherit', textAlign: 'left',
              }}>
                <div style={{ fontSize: 13, fontWeight: 600 }}>{o.label}</div>
                <div style={{ fontSize: 11, opacity: on ? 0.7 : 0.5, marginTop: 2 }}>{o.sub}</div>
              </button>
            );
          })}
        </div>

        <div style={{ height: 18 }} />
        <SectionLabel>Daily rhythm</SectionLabel>
        <div style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 16, overflow: 'hidden' }}>
          <PrefRow label="Wake-up" value={data.wake} />
          <PrefRow label="Dinner time" value={data.dinner} last />
        </div>

        <button style={{
          marginTop: 22, width: '100%', padding: '14px 16px', borderRadius: 16,
          border: `1px dashed ${MUTE}`, background: 'transparent', cursor: 'pointer',
          fontFamily: 'inherit', display: 'flex', alignItems: 'center', gap: 10, textAlign: 'left',
        }}>
          <div style={{ fontSize: 22 }}><Glyph name="paperclip" size={22} color={INK} /></div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 13, fontWeight: 600 }}>Upload existing PDF</div>
            <div style={{ fontSize: 11, color: MUTE, marginTop: 2 }}>We'll convert it to the app format</div>
          </div>
        </button>
      </div>

      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: '14px 22px 24px',
                    background: 'linear-gradient(to top, rgba(248,247,245,1) 60%, rgba(248,247,245,0))' }}>
        <PrimaryCTA variant="gold" onClick={() => nav('home')}>Save preferences <Arrow color={INK} /></PrimaryCTA>
      </div>
    </div>
  );
}

function PrefRow({ label, value, last }) {
  return (
    <div style={{ padding: '13px 16px', borderBottom: last ? 'none' : `1px solid ${LINE}`, display: 'flex', alignItems: 'center', gap: 10 }}>
      <div style={{ flex: 1 }}>
        <div style={{ fontSize: 11, color: MUTE, letterSpacing: 0.3 }}>{label}</div>
        <div style={{ fontSize: 13, color: INK, fontWeight: 500, marginTop: 2 }}>{value}</div>
      </div>
      <svg width="14" height="14" viewBox="0 0 16 16"><path d="M6 4l4 4-4 4" stroke={MUTE} strokeWidth="1.4" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
    </div>
  );
}

// ── Leaflet map sub-view ──────────────────────────────────────
function VoyageMapView({ onOpenDay }) {
  // selectedDay = which LEGS index the info card + pill show
  // selected    = which MAP_STOPS index is highlighted (derived)
  // selTick     = increments on every tap to force a map refresh even when selectedDay unchanged
  // -1 = D0 (embark/departure point, before Day 1 sailing)
  const [selectedDay, setSelectedDay] = React.useState(() => {
    if (getCurrentCharterDay() === null) return -1; // charter not started → show departure
    return MAP_STOPS[getCurrentMapStopIndex()]?.dayIdx ?? 0;
  });
  const [selTick, setSelTick] = React.useState(0);
  const embarkStop = MAP_STOPS.find(s => s.role === 'embark');

  // For a given day index, find the best map stop.
  // Use the LAST exact match (destination/overnight of that day, not the origin/embark).
  // e.g. Day 1 has both Marina d'Arechi (embark) and Positano (overnight) at dayIdx=0 —
  // we want Positano (last), not Marina d'Arechi (first).
  function getStopIdx(dayIdx) {
    let lastExact = -1;
    MAP_STOPS.forEach((p, j) => { if (p.dayIdx === dayIdx) lastExact = j; });
    if (lastExact >= 0) return lastExact;
    let best = 0;
    MAP_STOPS.forEach((p, j) => { if (p.dayIdx <= dayIdx) best = j; });
    return best;
  }
  const selected = getStopIdx(selectedDay);

  const { lang } = React.useContext(window.LangCtx || React.createContext({ lang: 'fr' }));
  const t = (en, fr) => lang === 'fr' ? fr : en;
  const mapDivRef   = React.useRef(null);
  const leafletRef  = React.useRef(null);
  const markersRef  = React.useRef([]);
  const routeRef    = React.useRef([]);

  function makeIcon(stop, isSel) {
    const L    = window.L;
    const size = stop.role === 'overnight' ? 14 : 7;
    const charterDay = getCurrentCharterDay();
    const isTonight  = charterDay !== null && (stop.role === 'overnight' || stop.role === 'dock' || stop.role === 'anchor') && stop.dayIdx === charterDay - 1;
    const bg    = isSel ? INK : isTonight ? GOLD : '#fff';
    const glow  = isSel ? '0 0 0 5px rgba(13,27,42,0.12),0 2px 6px rgba(0,0,0,0.25)' : '0 1px 3px rgba(0,0,0,0.22)';
    const tap = 32; // invisible tap target — much easier to hit on mobile
    return L.divIcon({
      className: '',
      html: `<div style="width:${tap}px;height:${tap}px;display:flex;align-items:center;justify-content:center;cursor:pointer;"><div style="width:${size}px;height:${size}px;border-radius:50%;background:${bg};border:2px solid ${INK};box-shadow:${glow};flex-shrink:0;"></div></div>`,
      iconSize: [tap, tap],
      iconAnchor: [tap / 2, tap / 2],
    });
  }

  function makeLabelIcon(stop) {
    const L = window.L;
    return L.divIcon({
      className: '',
      html: `<span style="font-family:Inter,system-ui;font-size:9px;font-weight:700;color:${INK};white-space:nowrap;letter-spacing:0.4px;text-shadow:-1px -1px 0 rgba(255,255,255,0.9),1px -1px 0 rgba(255,255,255,0.9),-1px 1px 0 rgba(255,255,255,0.9),1px 1px 0 rgba(255,255,255,0.9);">${stop.label}</span>`,
      iconSize: [140, 16],
      iconAnchor: [-10, 8],
    });
  }

  // Build the gold line up to the selected stop. Includes any waypoints
  // along the way (window.MAP_PATH preserves polyline order with waypoints).
  function buildGoldLineCoords(selIdx) {
    const fullPath = window.MAP_PATH || MAP_STOPS.map(s => [s.lat, s.lng]);
    if (selIdx < 0 || !MAP_STOPS[selIdx]) return [];
    const target = MAP_STOPS[selIdx];
    // Walk through the full path; stop after we encounter the target stop's coords
    const out = [];
    for (const pt of fullPath) {
      out.push(pt);
      if (Math.abs(pt[0] - target.lat) < 1e-6 && Math.abs(pt[1] - target.lng) < 1e-6) break;
    }
    return out;
  }
  function refreshRouteAndMarkers(sel) {
    const L   = window.L;
    const map = leafletRef.current;
    if (!L || !map) return;
    routeRef.current.forEach(l => map.removeLayer(l));
    // Full route: prefer MAP_PATH (includes waypoints) for accurate polyline shape
    const fullCoords = window.MAP_PATH || MAP_STOPS.map(s => [s.lat, s.lng]);
    const dashed   = L.polyline(fullCoords, { color: INK, weight: 1.5, dashArray: '5 6', opacity: 0.28 }).addTo(map);
    const goldLine = L.polyline(buildGoldLineCoords(sel),
                                { color: GOLD, weight: 2.6, lineCap: 'round', lineJoin: 'round' }).addTo(map);
    routeRef.current = [dashed, goldLine];
    markersRef.current.forEach((m, i) => m.setIcon(makeIcon(MAP_STOPS[i], i === sel)));
  }

  // Init map once
  React.useEffect(() => {
    const L = window.L;
    if (!L || !mapDivRef.current) return;
    const initSel = selected;

    const map = L.map(mapDivRef.current, {
      zoomControl: false, attributionControl: false,
      dragging: true, touchZoom: true,
      scrollWheelZoom: true, doubleClickZoom: true,
    }).setView([40.64, 14.28], 9);

    L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
      maxZoom: 18, subdomains: 'abcd',
    }).addTo(map);

    // Initial route — full polyline includes waypoints (MAP_PATH preserves order)
    const coords   = window.MAP_PATH || MAP_STOPS.map(s => [s.lat, s.lng]);
    const dashed   = L.polyline(coords, { color: INK, weight: 1.5, dashArray: '5 6', opacity: 0.28 }).addTo(map);
    const goldLine = L.polyline(buildGoldLineCoords(initSel),
                                { color: GOLD, weight: 2.6, lineCap: 'round' }).addTo(map);
    routeRef.current = [dashed, goldLine];

    // Markers + labels
    MAP_STOPS.forEach((stop, i) => {
      const m = L.marker([stop.lat, stop.lng], { icon: makeIcon(stop, i === initSel), zIndexOffset: 100 })
        .on('click', () => {
          // Embark dot → D0 (departure), not the same dayIdx as overnight
          setSelectedDay(MAP_STOPS[i].role === 'embark' ? -1 : MAP_STOPS[i].dayIdx);
          setSelTick(t => t + 1);
        })
        .addTo(map);
      markersRef.current.push(m);
      L.marker([stop.lat, stop.lng], {
        icon: makeLabelIcon(stop),
        interactive: false, zIndexOffset: -100,
      }).addTo(map);
    });

    leafletRef.current = map;
    return () => {
      map.remove();
      leafletRef.current = null;
      markersRef.current = [];
      routeRef.current   = [];
    };
  }, []);

  // Update on selection change (selTick ensures refresh even if same stop tapped twice)
  React.useEffect(() => {
    refreshRouteAndMarkers(selected);
  }, [selected, selTick]);

  const selStop = MAP_STOPS[selected];
  const leg     = selectedDay >= 0 ? (LEGS[selectedDay] || LEGS[0]) : LEGS[0];

  if (!leg) {
    return (
      <div style={{ position:'relative', width:'100%', height:'100%', background:BG, display:'flex', alignItems:'center', justifyContent:'center', flexDirection:'column', gap:14, padding:24, textAlign:'center', fontFamily:'"Inter",system-ui' }}>
        <div style={{ fontSize:13, color:MUTE }}>Itinerary not yet available.</div>
      </div>
    );
  }

  return (
    <div>
      {/* Day pills */}
      <div style={{ display: 'flex', gap: 6, marginBottom: 12, overflowX: 'auto', paddingBottom: 2, marginLeft: -22, marginRight: -22, paddingLeft: 22, paddingRight: 22 }} className="no-scrollbar">
        {/* D0 — departure/embark point */}
        {embarkStop && (() => {
          const on = selectedDay === -1;
          return (
            <button key="d0" onClick={() => { setSelectedDay(-1); setSelTick(t => t + 1); }} style={{
              flexShrink: 0,
              border: on ? `1.5px solid ${GOLD}` : `1px solid ${LINE}`,
              background: on ? GOLD : '#fff',
              padding: '7px 14px', borderRadius: 99,
              fontSize: 12.5, fontWeight: on ? 700 : 500,
              cursor: 'pointer', fontFamily: 'inherit',
              display: 'flex', alignItems: 'center', gap: 5,
              boxShadow: on ? `0 2px 8px rgba(201,168,76,0.35)` : 'none',
            }}>
              <span style={{ fontSize: 9.5, opacity: on ? 0.65 : 0.4, letterSpacing: 0.5, fontWeight: 700 }}>D0</span>
              {embarkStop.label}
            </button>
          );
        })()}
        {/* D1–DN — sailing days */}
        {LEGS.map((l, i) => {
          const on  = selectedDay === i;
          return (
            <button key={i} data-track={`itin_day_pill:${i+1}`} onClick={() => { setSelectedDay(i); setSelTick(t => t + 1); }} style={{
              flexShrink: 0,
              border: on ? `1.5px solid ${GOLD}` : `1px solid ${LINE}`,
              background: on ? GOLD : '#fff',
              color: on ? INK : INK,
              padding: '7px 14px', borderRadius: 99,
              fontSize: 12.5, fontWeight: on ? 700 : 500,
              cursor: 'pointer', fontFamily: 'inherit',
              display: 'flex', alignItems: 'center', gap: 5,
              boxShadow: on ? `0 2px 8px rgba(201,168,76,0.35)` : 'none',
            }}>
              <span style={{ fontSize: 9.5, opacity: on ? 0.65 : 0.4, letterSpacing: 0.5, fontWeight: 700 }}>D{i + 1}</span>
              {l.to}
              {l.pinned && <span style={{ color: on ? INK : GOLD, fontSize: 11 }}>✦</span>}
            </button>
          );
        })}
      </div>

      {/* Leaflet map */}
      <div style={{ borderRadius: 18, overflow: 'hidden', border: `1px solid ${LINE}`, height: 252, position: 'relative' }}>
        <div ref={mapDivRef} style={{ width: '100%', height: '100%' }} />
      </div>

      {/* Selected day card */}
      <div style={{ position: 'relative', paddingLeft: 24, marginTop: 14 }}>
        <div style={{ position: 'absolute', left: 4, top: 6, width: 12, height: 12, borderRadius: 6, background: leg.pinned ? GOLD : '#fff', border: `1.5px solid ${leg.pinned ? GOLD : INK}` }} />
        <button data-track={`day_pin:${leg.day}`}
          onClick={() => onOpenDay && onOpenDay(leg.day)}
          style={{ display: 'block', width: '100%', textAlign: 'left', padding: 0, border: 'none', background: 'transparent', cursor: 'pointer', fontFamily: 'inherit' }}
        >
          <div style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 16, overflow: 'hidden' }}>
            <div style={{ display: 'flex' }}>
              <div style={{ width: 96, height: 96, background: `url(${leg.img}) center/cover`, flexShrink: 0 }} />
              <div style={{ padding: '10px 12px', flex: 1, minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
                  <div style={{ fontSize: 10, letterSpacing: 1, textTransform: 'uppercase', color: MUTE, fontWeight: 700 }}>{t('Day','Jour')} {leg.day}</div>
                  <div style={{ fontSize: 10, color: MUTE }}>· {leg.date}</div>
                  {leg.pinned && <div style={{ fontSize: 9, fontWeight: 700, color: INK, background: GOLD, padding: '2px 6px', borderRadius: 99, marginLeft: 'auto' }}>{t('WEDDING ✦', 'MARIAGE ✦')}</div>}
                </div>
                <div style={{ fontSize: 14, fontWeight: 600, color: INK, marginTop: 3, letterSpacing: -0.2 }}>{leg.from} → {leg.to}</div>
                <div style={{ fontSize: 11, color: MUTE, marginTop: 2, display: 'inline-flex', alignItems: 'center', gap: 4 }}><Glyph name="boat" size={12} color={MUTE} /> {pickLang(leg, 'nav', lang) || leg.nav} · {pickLang(leg, 'highlight', lang) || (lang === 'fr' ? (HIGHLIGHT_FR[leg.highlight] || leg.highlight) : leg.highlight)}</div>
                <div style={{ fontSize: 10.5, color: GOLD, fontWeight: 600, marginTop: 4 }}>{t('Tap for full plan →','Voir le programme →')}</div>
              </div>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', borderTop: `1px solid ${LINE}` }}>
              {[
                { k: t('Distance','Distance'),    v: leg.distance },
                { k: t('Cruise time','Durée'),    v: pickLang(leg, 'nav', lang) || leg.nav },
              ].map((s, i) => (
                <div key={s.k} style={{ textAlign: 'center', padding: '10px 0', background: '#F4F2EC', borderRight: i < 1 ? `1px solid ${LINE}` : 'none' }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: INK }}>{s.v}</div>
                  <div style={{ fontSize: 9.5, color: MUTE, marginTop: 1, letterSpacing: 0.4, textTransform: 'uppercase' }}>{s.k}</div>
                </div>
              ))}
            </div>
          </div>
        </button>

        {/* Legend */}
        <div style={{ display: 'flex', gap: 12, marginTop: 12, fontSize: 10, color: MUTE, flexWrap: 'wrap' }}>
          {[
            { dot: { w: 14, bg: '#fff', border: `2px solid ${INK}` },    label: t('Overnight','Nuit') },
            { dot: { w: 7,  bg: '#fff', border: `1.2px solid ${INK}` },  label: t('Day stop','Escale') },
            { dot: { w: 14, bg: INK,    border: `2px solid ${INK}` },    label: t('Selected','Sélectionné') },
            ...(getCurrentCharterDay() !== null ? [{ dot: { w: 12, bg: GOLD, border: `1.6px solid ${GOLD}` }, label: t('Tonight','Ce soir') }] : []),
          ].map(({ dot, label }) => (
            <span key={label} style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
              <span style={{ width: dot.w, height: dot.w, borderRadius: dot.w / 2, background: dot.bg, border: dot.border, display: 'inline-block', flexShrink: 0 }}/>
              {label}
            </span>
          ))}
        </div>
      </div>
    </div>
  );
}

// Client feedback on the captain's itinerary (overall or per-day). Writes to
// the 'itinerary' message channel → captain console + broker cockpit Messages.
function ItineraryFeedback({ dayLabel = null, marginTop = 14 }) {
  const { lang } = React.useContext(window.LangCtx || React.createContext({ lang: 'fr' }));
  const t = (en, fr) => lang === 'fr' ? fr : en;
  const [open, setOpen] = React.useState(false);
  const [text, setText] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [sent, setSent] = React.useState(false);
  async function send() {
    if (busy || !text.trim()) return;
    setBusy(true);
    const prefix = dayLabel != null ? `${t('Day', 'Jour')} ${dayLabel} · ` : '';
    const r = await (window.sendItineraryFeedback ? window.sendItineraryFeedback(prefix + text.trim()) : { ok: false });
    setBusy(false);
    if (r && r.ok) { setSent(true); setText(''); setOpen(false); }
  }
  const label = dayLabel != null
    ? `${t('Comment on Day', 'Commenter le Jour')} ${dayLabel}`
    : t('Give feedback on this itinerary', 'Donner votre avis sur cet itinéraire');
  const cta = dayLabel != null ? t('Send', 'Envoyer') : t('Comment', 'Commenter');
  return (
    <div style={{ marginTop, borderRadius: 16, background: '#fff', border: `1px solid ${LINE}`, overflow: 'hidden' }}>
      <div style={{ padding: '14px 16px', display: 'flex', gap: 10, alignItems: 'center' }}>
        <Glyph name="chat" size={20} color={INK} />
        <div style={{ flex: 1, fontSize: 13, color: INK }}>{sent ? t('Thank you — your feedback was sent', 'Merci — votre avis a été transmis') : label}</div>
        {!sent && (
          <button onClick={() => setOpen(o => !o)} style={{ fontSize: 11, fontWeight: 600, color: INK, padding: '8px 14px', borderRadius: 99, border: `1px solid ${LINE}`, background: '#fff', cursor: 'pointer', fontFamily: 'inherit', flexShrink: 0 }}>
            {open ? t('Close', 'Fermer') : cta}
          </button>
        )}
      </div>
      {open && !sent && (
        <div style={{ padding: '0 16px 14px', display: 'flex', flexDirection: 'column', gap: 8 }}>
          <textarea value={text} onChange={e => setText(e.target.value)} rows={3}
            placeholder={t('Your comment for the captain & your broker…', 'Votre commentaire pour le capitaine et votre courtier…')}
            style={{ width: '100%', boxSizing: 'border-box', padding: '10px 12px', borderRadius: 12, border: `1px solid ${LINE}`, fontFamily: 'inherit', fontSize: 13, color: INK, resize: 'vertical' }} />
          <button onClick={send} disabled={busy || !text.trim()}
            style={{ alignSelf: 'flex-end', fontSize: 12, fontWeight: 700, color: INK, padding: '9px 18px', borderRadius: 99, border: 'none', background: GOLD, cursor: (busy || !text.trim()) ? 'default' : 'pointer', opacity: (busy || !text.trim()) ? 0.5 : 1, fontFamily: 'inherit' }}>
            {busy ? t('Sending…', 'Envoi…') : t('Send', 'Envoyer')}
          </button>
        </div>
      )}
    </div>
  );
}

function ItineraryScreen({ nav, initialTab = 'timeline' }) {
  const [tab, setTab] = React.useState(initialTab);
  const openDay = (dayNum) => nav && nav('day', { day: dayNum });
  const { lang } = React.useContext(window.LangCtx || React.createContext({ lang: 'fr' }));
  const t = (en, fr) => lang === 'fr' ? fr : en;
  // Captain inline edit
  const captainInline = !!window._isCrewUser && window._captainMode === 'inline';
  const [editLegIdx, setEditLegIdx] = React.useState(null);
  const [, forceRender] = React.useReducer(x => x + 1, 0);

  async function handleAddLeg() {
    if (!window.captainAddLeg) return;
    try {
      const newIdx = await window.captainAddLeg();
      forceRender();
      setEditLegIdx(newIdx);
    } catch (e) { alert('Error: ' + e.message); }
  }

  return (
    <div style={{ position: 'relative', width: '100%', height: '100%', background: BG, overflow: 'hidden', fontFamily: '"Inter", system-ui', display: 'flex', flexDirection: 'column' }}>
      <TopBar title={t('Your itinerary','Votre itinéraire')} sub={`${TRIP.zone || t('Amalfi Coast & Bay of Naples','Côte Amalfitaine & Baie de Naples')} · ${TRIP.dates.start}–${TRIP.dates.end}`} />

      <div style={{ display: 'flex', gap: 18, padding: '12px 22px 0', background: BG, flexShrink: 0 }}>
        {[
          { id: 'timeline', label: t('Timeline','Chronologie') },
          { id: 'map',      label: t('Map','Carte') },
        ].map(tb => (
          <button key={tb.id} onClick={() => setTab(tb.id)} data-track={`itinerary_tab:${tb.id}`} style={{
            border: 'none', background: 'none', padding: '6px 0 10px', fontSize: 13, fontWeight: tab === tb.id ? 600 : 500,
            color: tab === tb.id ? INK : MUTE, cursor: 'pointer', fontFamily: 'inherit',
            borderBottom: `2px solid ${tab === tb.id ? GOLD : 'transparent'}`,
          }}>{tb.label}</button>
        ))}
      </div>
      <div style={{ borderBottom: `1px solid ${LINE}`, flexShrink: 0 }} />

      <div style={{ flex: 1, overflowY: 'auto', padding: '16px 22px 110px' }} className="no-scrollbar">
        {tab === 'map' && <VoyageMapView onOpenDay={openDay} />}

        {tab === 'timeline' && LEGS.map((leg, i) => (
          <div key={i} style={{ position: 'relative', paddingLeft: 30, paddingBottom: 16 }}>
            {/* Vertical rail */}
            {i < LEGS.length - 1 && <div style={{ position: 'absolute', left: 12, top: 28, bottom: 0, width: 1, background: LINE }} />}
            {/* Day number badge */}
            <div style={{
              position: 'absolute', left: 0, top: 4,
              width: 26, height: 26, borderRadius: 13,
              background: INK,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <span style={{ fontSize: 9.5, fontWeight: 700, color: '#fff', letterSpacing: 0 }}>{leg.day}</span>
            </div>
            <button data-track={`open_day:${leg.day}`}
              onClick={() => openDay(leg.day)}
              style={{ display: 'block', width: '100%', textAlign: 'left', padding: 0, border: 'none', background: 'transparent', cursor: 'pointer', fontFamily: 'inherit' }}
            >
              <div style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 16, overflow: 'hidden', position: 'relative' }}>
                <div style={{ display: 'flex' }}>
                  <div style={{ width: 120, minHeight: 110, background: `url(${leg.img}) center/cover`, flexShrink: 0 }} />
                  <div style={{ padding: '12px 14px', flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
                      <div style={{ fontSize: 10, letterSpacing: 0.8, textTransform: 'uppercase', color: MUTE, fontWeight: 700 }}>{leg.date}</div>
                    </div>
                    <div style={{ fontSize: 15, fontWeight: 700, color: INK, letterSpacing: -0.3, lineHeight: 1.25 }}>{leg.from} → {leg.to}</div>
                    <div style={{ fontSize: 11.5, color: MUTE, marginTop: 5, lineHeight: 1.4 }}>{pickLang(leg, 'highlight', lang) || (lang === 'fr' ? (HIGHLIGHT_FR[leg.highlight] || leg.highlight) : leg.highlight)}</div>
                    <div style={{ fontSize: 11, color: MUTE, marginTop: 6, display: 'flex', alignItems: 'center', gap: 3 }}>
                      {leg.distance} · {pickLang(leg, 'nav', lang) || leg.nav}
                      <svg width="10" height="10" viewBox="0 0 16 16"><path d="M6 4l4 4-4 4" stroke={MUTE} strokeWidth="1.4" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
                    </div>
                  </div>
                </div>
                {/* Captain edit pin (top-right of card) */}
                {captainInline && (
                  <span onClick={ev => { ev.stopPropagation(); ev.preventDefault(); setEditLegIdx(i); }}
                    style={{
                      position: 'absolute', top: 8, right: 8,
                      width: 30, height: 30, borderRadius: 15,
                      background: 'rgba(13,27,42,0.85)', backdropFilter: 'blur(6px)',
                      color: GOLD, fontSize: 13, cursor: 'pointer',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                      border: '1px solid rgba(201,168,76,0.5)',
                    }}><Glyph name="edit" size={14} color={GOLD} /></span>
                )}
              </div>
            </button>
          </div>
        ))}

        {/* Captain: + Add day button */}
        {tab === 'timeline' && captainInline && (
          <button onClick={handleAddLeg}
            style={{
              width: '100%', marginTop: 8, padding: '14px 16px',
              borderRadius: 14, border: `2px dashed ${GOLD}`,
              background: 'rgba(201,168,76,0.06)', cursor: 'pointer',
              fontFamily: 'inherit', fontSize: 13, fontWeight: 600, color: INK,
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            }}>
            <Glyph name="calendar" size={18} color={INK} /> Add a day
          </button>
        )}

        {tab === 'timeline' && !captainInline && (
          <ItineraryFeedback marginTop={6} />
        )}
      </div>

      {/* Captain leg editor overlay */}
      {captainInline && editLegIdx != null && window.LegEditorOverlay && (() => {
        const Editor = window.LegEditorOverlay;
        return <Editor legs={LEGS} legIdx={editLegIdx}
          onClose={() => { setEditLegIdx(null); forceRender(); }} />;
      })()}
    </div>
  );
}

// ── Voyage Map (standalone artboard wrapper) ────────────────
// Reuses ItineraryScreen with the Map tab pre-selected, so the
// toggle the user already knows controls everything.
function VoyageMapScreen({ nav }) {
  return <ItineraryScreen nav={nav} initialTab="map" />;
}

// ── Day Detail — full plan for one day ──────────────────────
// Vocabulary borrows from PreferenceSheet (sectioned card list)
// and the timeline pin (vertical rail with dots).
function DayDetailScreen({ nav, day = 5 }) {
  const leg = LEGS.find(l => l.day === day) || LEGS[0];
  const { lang } = React.useContext(window.LangCtx || React.createContext({ lang: 'fr' }));
  const t = (en, fr) => lang === 'fr' ? fr : en;
  const captainInline = !!window._isCrewUser && window._captainMode === 'inline';
  // Guard: empty itinerary (broker hasn't set legs yet)
  if (!leg) {
    return (
      <div style={{ position:'relative', width:'100%', height:'100%', background:BG, display:'flex', alignItems:'center', justifyContent:'center', flexDirection:'column', gap:14, padding:24, textAlign:'center', fontFamily:'"Inter",system-ui' }}>
        <div style={{ fontSize:13, color:MUTE }}>{t('Itinerary not yet available.', 'Itinéraire pas encore disponible.')}</div>
        <button onClick={() => nav('home')} style={{ padding:'10px 20px', borderRadius:99, border:`1px solid ${LINE}`, background:'#fff', cursor:'pointer', fontSize:12, fontWeight:600, color:INK, fontFamily:'inherit' }}>{t('Back home', 'Retour accueil')}</button>
      </div>
    );
  }

  // Stop kind → category color
  const KIND_COLOR = {
    arrival:'#3B6FA0', departure:'#3B6FA0', embark:'#3B6FA0', disembark:'#3B6FA0', transfer:'#3B6FA0', cruise:'#3B6FA0',
    anchor:'#2A7B6F',  mooring:'#2A7B6F', dock:'#2A7B6F',   overnight:'#1A2F4A',
    hike:'#B05C3A',    cycle:'#B05C3A',  visit:'#B05C3A',
    lunch:'#4A7C59',   dinner:'#4A7C59', cocktail:'#4A7C59',
    prep:'#9B7A2F',    ceremony:'#9B7A2F', other:'#9B7A2F',
  };

  return (
    <div style={{ position: 'relative', width: '100%', height: '100%', background: BG, overflow: 'hidden', fontFamily: '"Inter", system-ui', display: 'flex', flexDirection: 'column' }}>

      <div style={{ flex: 1, overflowY: 'auto', padding: '0 0 110px' }} className="no-scrollbar">
      {/* Hero — rounded card */}
      <div style={{ padding: '12px 12px 0', flexShrink: 0 }}>
        <div style={{ position: 'relative', height: 220, background: `url(${leg.img}) center/cover`, borderRadius: 20, overflow: 'hidden' }}>
          <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(13,27,42,0.72) 0%, rgba(13,27,42,0.08) 55%)' }} />
          <button onClick={() => nav && nav('itinerary')} style={{
            position: 'absolute', top: 14, left: 14, width: 34, height: 34, borderRadius: 17, border: 'none',
            background: 'rgba(255,255,255,0.92)', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'inherit',
          }}>
            <svg width="16" height="16" viewBox="0 0 16 16"><path d="M10 4L6 8l4 4" stroke={INK} strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </button>
          <div style={{ position: 'absolute', left: 18, right: 18, bottom: 16, color: '#fff' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div style={{ fontSize: 10, letterSpacing: 1.6, textTransform: 'uppercase', opacity: 0.85, fontWeight: 600 }}>{t('Day','Jour')} {leg.day} · {leg.date}</div>
              {leg.pinned && <div style={{ fontSize: 9, fontWeight: 700, color: INK, background: GOLD, padding: '2px 6px', borderRadius: 99 }}>{t('WEDDING ✦', 'MARIAGE ✦')}</div>}
            </div>
            <div style={{ fontSize: 22, fontWeight: 600, letterSpacing: -0.4, marginTop: 4, fontFamily: '"Cormorant Garamond", serif', fontStyle: 'italic' }}>
              {leg.from} → {leg.to}
            </div>
            <div style={{ fontSize: 12, opacity: 0.85, marginTop: 2 }}>{pickLang(leg, 'highlight', lang) || (lang === 'fr' ? (HIGHLIGHT_FR[leg.highlight] || leg.highlight) : leg.highlight)}</div>
          </div>
        </div>
      </div>

      {/* Stat pills */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: 8, padding: '10px 12px 0', flexShrink: 0 }}>
        {[
          { k: t('Distance','Distance'),    v: leg.distance },
          { k: t('Cruise time','Durée croisière'), v: pickLang(leg, 'nav', lang) || leg.nav },
        ].map(s => (
          <div key={s.k} style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 14, padding: '12px 0', textAlign: 'center' }}>
            <div style={{ fontSize: 15, fontWeight: 700, color: INK }}>{s.v}</div>
            <div style={{ fontSize: 9.5, color: MUTE, marginTop: 2, letterSpacing: 0.5, textTransform: 'uppercase' }}>{s.k}</div>
          </div>
        ))}
      </div>

      <div style={{ padding: '20px 12px 0' }}>
        <div style={{ fontSize: 11, letterSpacing: 1.6, textTransform: 'uppercase', color: MUTE, fontWeight: 700, marginBottom: 14 }}>{t('The day','La journée')}</div>

        {/* Vertical timeline of stops */}
        <div style={{ position: 'relative' }}>
          {/* Rail */}
          <div style={{ position: 'absolute', left: 15, top: 8, bottom: 8, width: 1, background: LINE }} />
          {(leg.stops || []).map((s, i) => {
            return (
              <div key={i} style={{ position: 'relative', paddingLeft: 44, paddingBottom: 16 }}>
                <div style={{
                  position: 'absolute', left: 4, top: 4, width: 24, height: 24, borderRadius: 12,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                }}>
                  <KindIcon kind={primaryKind(s)} color={KIND_COLOR[primaryKind(s)] || '#9CA3AF'} size={16} />
                </div>
                <div style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 14, padding: '10px 14px' }}>
                  <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                    <div style={{ fontSize: 12.5, fontWeight: 700, color: INK, fontVariantNumeric: 'tabular-nums' }}>{s.time}</div>
                    <div style={{ fontSize: 9.5, letterSpacing: 0.8, textTransform: 'uppercase', fontWeight: 600, color: KIND_COLOR[primaryKind(s)] || '#9CA3AF' }}>{lang === 'fr' ? getKinds(s).map(k => KIND_FR[k] || k).join(' · ') : getKinds(s).join(' · ')}</div>
                  </div>
                  <div style={{ fontSize: 14, fontWeight: 600, color: INK, marginTop: 3, letterSpacing: -0.2 }}>{s.place}</div>
                  {pickLang(s, 'note', lang) && <div style={{ fontSize: 12, color: MUTE, marginTop: 3, lineHeight: 1.45 }}>{pickLang(s, 'note', lang)}</div>}
                </div>
              </div>
            );
          })}
        </div>

        {/* Practical card */}
        <div style={{ marginTop: 18, background: '#fff', border: `1px solid ${LINE}`, borderRadius: 16, padding: '14px 16px' }}>
          <div style={{ fontSize: 11, letterSpacing: 1.4, textTransform: 'uppercase', color: MUTE, fontWeight: 700 }}>{t('Practical','Pratique')}</div>
          <div style={{ marginTop: 10, display: 'flex', flexDirection: 'column', gap: 8, fontSize: 13, color: INK }}>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: MUTE }}>{t('Departure','Départ')}</span><span style={{ fontWeight: 600 }}>{leg.from}</span></div>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: MUTE }}>{t('Anchorage / dock','Mouillage / quai')}</span><span style={{ fontWeight: 600 }}>{leg.to}</span></div>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: MUTE }}>{t('Distance · time','Distance · durée')}</span><span style={{ fontWeight: 600 }}>{leg.distance} · {pickLang(leg, 'nav', lang) || leg.nav}</span></div>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: MUTE }}>{t('Cruise speed','Vitesse croisière')}</span><span style={{ fontWeight: 600 }}>{leg.speed}</span></div>
          </div>
        </div>

        {/* Feedback row */}
        {!captainInline && <ItineraryFeedback dayLabel={leg.day} />}
      </div>
      </div>
    </div>
  );
}


// ── Chef's Menu — week overview (24a) ───────────────────────
function MenuScreen({ nav }) {
  const { lang } = React.useContext(window.LangCtx || React.createContext({ lang: 'fr' }));
  const t = (en, fr) => lang === 'fr' ? fr : en;
  const menu  = window.CHARTER_MENU;
  const chef  = CHOSEN_YACHT.crew_members?.find(m =>
    m.role?.toLowerCase().includes('chef') || m.role?.toLowerCase().includes('cook')
  ) || { name: t('Your Chef', 'Votre chef'), role: t('Private Chef', 'Chef privé'), photo: '' };

  if (!menu || !menu.days || menu.days.length === 0) return (
    <div style={{ position: 'relative', width: '100%', height: '100%', background: BG, display: 'flex', flexDirection: 'column', fontFamily: '"Inter", system-ui' }}>
      <TopBar title={t("Chef's menu", "Menu du chef")} />
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: '0 32px', gap: 12 }}>
        <div style={{ fontSize: 32, marginBottom: 4 }}><Glyph name="chef" size={32} color={MUTE} /></div>
        <div style={{ fontSize: 16, fontWeight: 600, color: INK, fontFamily: '"Cormorant Garamond", serif', fontStyle: 'italic' }}>{t('Menu coming soon', 'Menu bientôt disponible')}</div>
        <div style={{ fontSize: 13, color: MUTE, textAlign: 'center', lineHeight: 1.5 }}>{t('Your chef is preparing something special. Check back soon.', 'Votre chef prépare quelque chose de spécial. Revenez bientôt.')}</div>
      </div>
    </div>
  );

  return (
    <div style={{ position: 'relative', width: '100%', height: '100%', background: BG, overflow: 'hidden', fontFamily: '"Inter", system-ui', display: 'flex', flexDirection: 'column' }}>
      <TopBar title={t("Chef's menu", "Menu du chef")} sub={`${menu.days.length} ${t('days · by', 'jours · par')} ${chef.name}`} />

      <div style={{ flex: 1, overflowY: 'auto', padding: '0 0 110px' }} className="no-scrollbar">

        {/* Hero card — clickable → Day 1 */}
        <button onClick={() => nav('menu-day', { day: 1 })} data-track="menu_day:1" style={{ display: 'block', width: '100%', padding: 0, border: 'none', background: 'none', cursor: 'pointer', fontFamily: 'inherit' }}>
          <div style={{ margin: '12px 16px 0', borderRadius: 22, background: INK, padding: '32px 24px', minHeight: 210, position: 'relative', overflow: 'hidden', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
            <div style={{ position: 'absolute', top: -30, right: -20, width: 130, height: 130, borderRadius: 65, background: 'rgba(255,255,255,0.03)' }} />
            <div style={{ fontSize: 8.5, letterSpacing: 2, textTransform: 'uppercase', color: GOLD, fontWeight: 700, marginBottom: 8 }}>{t('THE CHARTER MENU', 'LE MENU DU CHARTER')}</div>
            <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>
              <div style={{ fontSize: 42, fontWeight: 600, fontFamily: '"Cormorant Garamond", serif', fontStyle: 'italic', color: '#fff', lineHeight: 1.05, letterSpacing: -0.5, maxWidth: '72%' }}>
                {menu.days.length} {t('days,', 'jours,')}<br/>{t('at the table.', 'à table.')}
              </div>
              <div style={{ color: 'rgba(255,255,255,0.35)', fontSize: 15, fontWeight: 700, fontFamily: '"Cormorant Garamond", serif', fontStyle: 'italic', letterSpacing: 1, flexShrink: 0, marginTop: 4 }}>eh²</div>
            </div>
            <div style={{ marginTop: 18, display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderTop: '1px solid rgba(255,255,255,0.1)', paddingTop: 14 }}>
              <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.5)', letterSpacing: 0.4 }}>{TRIP?.dates?.start} — {TRIP?.dates?.end}</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.6)', letterSpacing: 1, fontWeight: 600, textTransform: 'uppercase' }}>{t('Discover', 'Découvrir')}</div>
                <svg width="14" height="14" viewBox="0 0 16 16"><path d="M6 4l4 4-4 4" stroke="rgba(255,255,255,0.4)" strokeWidth="1.4" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
              </div>
            </div>
          </div>
        </button>

        <div style={{ padding: '14px 16px 0' }}>

          {/* Chef card */}
          <div style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 18, padding: '14px 16px', display: 'flex', gap: 12, alignItems: 'center' }}>
            <div style={{ width: 50, height: 50, borderRadius: 25, overflow: 'hidden', flexShrink: 0, background: '#F4F2EC' }}>
              {chef.photo
                ? <img src={chef.photo} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 15%' }} />
                : <div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 22 }}><Glyph name="chef" size={22} color={MUTE} /></div>
              }
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 14, fontWeight: 600, color: INK }}>{chef.name}</div>
              <div style={{ fontSize: 11, color: MUTE, marginTop: 1 }}>
                {chef.years ? `${chef.years} ${t('years at sea', 'ans en mer')}` : (pickLang(chef, 'role', lang) || chef.role || t('Private Chef', 'Chef privé'))}
              </div>
            </div>
            <button
              onClick={() => nav('chat', { who: 'chief_stew', from: 'menu' })}
              style={{ padding: '8px 16px', borderRadius: 99, border: `1px solid ${INK}`, background: 'transparent', fontSize: 12, fontWeight: 600, color: INK, cursor: 'pointer', fontFamily: 'inherit', flexShrink: 0 }}>
              {t('Message', 'Message')}
            </button>
          </div>

          {/* Dietary preferences CTA */}
          <button
            onClick={() => nav('dietary')}
            data-track="open_dietary"
            style={{ marginTop: 10, width: '100%', padding: '13px 16px', background: 'linear-gradient(135deg, #FAF4E2, #F4EFDE)', border: `1px solid ${GOLD}`, borderRadius: 16, cursor: 'pointer', fontFamily: 'inherit', display: 'flex', alignItems: 'center', gap: 12, textAlign: 'left', boxSizing: 'border-box' }}>
            <div style={{ width: 34, height: 34, borderRadius: 17, background: GOLD, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><Glyph name="chef" size={17} color={INK} /></div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: INK }}>{t('See your dietary preferences', 'Voir vos préférences alimentaires')}</div>
              <div style={{ fontSize: 11, color: MUTE, marginTop: 2 }}>{t('Allergies, diet & favourites', 'Allergies, régimes & préférences')}</div>
            </div>
            <svg width="14" height="14" viewBox="0 0 16 16"><path d="M6 4l4 4-4 4" stroke={MUTE} strokeWidth="1.4" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </button>


        </div>
      </div>
    </div>
  );
}

// ── Chef's Menu — day detail (24b) ───────────────────────────
// ── Course label → French translation map ────────────────────
const COURSE_LABEL_FR = {
  'main':        'Plat',
  'starter':     'Entrée',
  'appetizer':   'Entrée',
  'dessert':     'Dessert',
  'cheese':      'Fromages',
  'fish':        'Poisson',
  'meat':        'Viande',
  'pasta':       'Pâtes',
  'salad':       'Salade',
  'soup':        'Soupe',
  'amuse-bouche':'Amuse-bouche',
  'pre-dessert': 'Pré-dessert',
  'cocktail':    'Apéritif',
  'bread':       'Pain',
  'snack':       'Encas',
};

// ── Dish name → French fallback (for data saved before dish_fr was added) ──
const DISH_FR_FALLBACK = {
  'Quinoa and Veggies Salad':                                  'Salade de quinoa et légumes',
  'White Fish Ceviche':                                        'Ceviche de poisson blanc',
  'Fruit Salad / Ice Cream':                                   'Salade de fruits / Glace',
  'Bresaola Ravioli stuffed with Robiola and Lemon Zest':      'Raviolis bresaola farcis à la robiola et zeste de citron',
  'Risotto with Asparagus and Goat Cheese':                    'Risotto aux asperges et fromage de chèvre',
  'Tiramisu':                                                  'Tiramisu',
  'Plate of Cheese':                                           'Plateau de fromages',
  'Gazpacho':                                                  'Gaspacho',
  'Monkfish in Foil with Mediterranean Veggies':               'Lotte en papillote et légumes méditerranéens',
  'Apple Tarte with Ice Cream':                                'Tarte aux pommes et glace',
  'Artichoke Flan with Pecorino Fondue':                       "Flan d'artichaut et fondue de pecorino",
  'Filet Mignon Grilled with Baby Potatoes and Baked Asparagus': 'Filet mignon grillé, grenaille et asperges rôties',
  'Panna Cotta':                                               'Panna cotta',
  'Courgette Flower stuffed with Mozzarella and Sundried Tomatoes': 'Fleurs de courgette farcies à la mozzarella et tomates séchées',
  'Caprese Salad with Bufala Mozzarella':                      'Salade caprese à la mozzarella di bufala',
  'Strawberries with Ice Cream':                               'Fraises et glace',
  'Spaghetti with Clams':                                      'Spaghetti aux palourdes',
  'Seabream Filet in a Potatoes Crust with Baked Cherry Tomatoes': 'Filet de daurade en croûte de pommes de terre et tomates cerises rôties',
  'Chocolate Fondant with Ice Cream':                          'Fondant au chocolat et glace',
  'Octopus Salad':                                             'Salade de poulpe',
  'Sorrentina Gnocchi':                                        'Gnocchi à la sorrentine',
  'Fruit Salad':                                               'Salade de fruits',
  'Home Made Pasta with Truffles':                             'Pâtes maison aux truffes',
  'Seabass in Salty Crust with Baked Aubergine and Tomatoes':  'Bar en croûte de sel, aubergine et tomates rôties',
  'Crème Brûlée':                                              'Crème brûlée',
  'Greek Salad or Niçoise Salad':                              'Salade grecque ou niçoise',
  'Carbonara':                                                 'Carbonara',
  'Ice Cream':                                                 'Glace',
};

// Reverse maps for FR → EN lookup (built from the EN→FR maps above)
const DISH_EN_FALLBACK = Object.fromEntries(
  Object.entries(DISH_FR_FALLBACK).map(([en, fr]) => [fr, en])
);
const COURSE_LABEL_EN_FALLBACK = Object.fromEntries(
  Object.entries(COURSE_LABEL_FR).map(([en, fr]) => [fr.toLowerCase(), en])
);

function MenuDayScreen({ nav, day = 1 }) {
  const { lang } = React.useContext(window.LangCtx || React.createContext({ lang: 'fr' }));
  const t = (en, fr) => lang === 'fr' ? fr : en;
  // Captain inline edit
  const captainInline = !!window._isCrewUser && window._captainMode === 'inline';
  const [showMenuEdit, setShowMenuEdit] = React.useState(false);
  const [, forceRender] = React.useReducer(x => x + 1, 0);
  const menu = window.CHARTER_MENU;
  if (!menu || !menu.days || menu.days.length === 0) {
    return (
      <div style={{ position:'relative', width:'100%', height:'100%', background:BG, display:'flex', alignItems:'center', justifyContent:'center', flexDirection:'column', gap:14, padding:24, textAlign:'center', fontFamily:'"Inter",system-ui' }}>
        <div style={{ fontSize:13, color:MUTE }}>{t('Menu not yet available.', 'Menu pas encore disponible.')}</div>
        <button onClick={() => nav('menu')} style={{ padding:'10px 20px', borderRadius:99, border:`1px solid ${LINE}`, background:'#fff', cursor:'pointer', fontSize:12, fontWeight:600, color:INK, fontFamily:'inherit' }}>{t('Back', 'Retour')}</button>
      </div>
    );
  }

  const dayData = menu.days.find(d => d.day === day) || menu.days[0];
  const leg     = typeof LEGS !== 'undefined' && LEGS ? LEGS[dayData.day - 1] : null;
  const dayLabel = dayData.day === 1 ? t('Embarkation', 'Embarquement') : (leg?.to || `${t('Day', 'Jour')} ${dayData.day}`);
  const romans   = ['I','II','III','IV','V','VI'];

  // Translate a course label: use FR map when lang=fr, raw label otherwise
  function courseLabel(raw) {
    if (!raw) return '';
    const lc = raw.toLowerCase();
    if (lang === 'fr') return COURSE_LABEL_FR[lc] || raw;
    return COURSE_LABEL_EN_FALLBACK[lc] || raw;
  }

  // Pick the right dish name: dish_<lang> via pickLang > fallback map > original
  function dishName(c) {
    const picked = pickLang(c, 'dish', lang);
    if (picked) return picked;
    if (lang === 'fr') return DISH_FR_FALLBACK[c.dish] || c.dish;
    return DISH_EN_FALLBACK[c.dish] || c.dish;
  }

  function MealSection({ meal, label }) {
    if (!meal) return null;
    return (
      <div style={{ marginTop: 22 }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
          <div style={{ fontSize: 9.5, letterSpacing: 2, textTransform: 'uppercase', color: GOLD, fontWeight: 700 }}>{label}</div>
          <button
            onClick={() => nav('chat', { who: 'chief_stew', from: 'menu-day' })}
            style={{ padding: '6px 12px', borderRadius: 99, border: `1px solid ${LINE}`, background: '#fff', fontSize: 11, fontWeight: 600, color: INK, cursor: 'pointer', fontFamily: 'inherit' }}>
            {t('Adjust', 'Modifier')}
          </button>
        </div>
        <div style={{ background: '#fff', border: `1px solid ${LINE}`, borderRadius: 16, overflow: 'hidden' }}>
          {meal.courses.map((c, i) => {
            const isAppetizer = c.label?.toLowerCase() === 'appetizer' && !c.dish;
            return (
              <div key={i} style={{ padding: '12px 16px', borderBottom: i < meal.courses.length - 1 ? `1px solid ${LINE}` : 'none', display: 'flex', gap: 14, alignItems: 'flex-start' }}>
                <div style={{ fontSize: 11, fontStyle: 'italic', color: GOLD, width: 16, flexShrink: 0, paddingTop: 2, fontFamily: '"Cormorant Garamond", serif', fontWeight: 600 }}>{romans[i]}</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 9, letterSpacing: 1.2, textTransform: 'uppercase', color: MUTE, fontWeight: 600 }}>{courseLabel(c.label)}</div>
                  {isAppetizer
                    ? <div style={{ fontSize: 12.5, fontStyle: 'italic', color: MUTE, marginTop: 3, lineHeight: 1.35 }}>{t("Chef's surprise", 'Surprise du chef')}</div>
                    : <div style={{ fontSize: 13.5, fontWeight: 500, color: INK, marginTop: 3, lineHeight: 1.35 }}>{dishName(c)}</div>
                  }
                </div>
              </div>
            );
          })}
        </div>
      </div>
    );
  }

  return (
    <div style={{ position: 'relative', width: '100%', height: '100%', background: BG, overflow: 'hidden', fontFamily: '"Inter", system-ui', display: 'flex', flexDirection: 'column' }}>
      <TopBar title={`${t('Day', 'Jour')} ${dayData.day} · ${dayLabel}`} sub={dayData.date} onBack={() => nav('menu')} />

      <div style={{ flex: 1, overflowY: 'auto', padding: '4px 20px 40px' }} className="no-scrollbar">
        <MealSection meal={dayData.lunch}  label={t('Lunch', 'Déjeuner')} />
        <MealSection meal={dayData.dinner} label={t('Dinner', 'Dîner')} />

        {/* Day navigation */}
        <div style={{ marginTop: 30, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <button
            onClick={() => dayData.day > 1 && nav('menu-day', { day: dayData.day - 1 })}
            disabled={dayData.day <= 1}
            style={{ width: 44, height: 44, borderRadius: 22, border: `1px solid ${LINE}`, background: '#fff', cursor: dayData.day > 1 ? 'pointer' : 'default', display: 'flex', alignItems: 'center', justifyContent: 'center', opacity: dayData.day <= 1 ? 0.3 : 1, flexShrink: 0 }}>
            <svg width="16" height="16" viewBox="0 0 16 16"><path d="M10 4L6 8l4 4" stroke={INK} strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </button>
          {/* Dot indicators */}
          <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
            {menu.days.map(d => (
              <div key={d.day} data-track={`menu_day:${d.day}`} onClick={() => nav('menu-day', { day: d.day })} style={{
                width: dayData.day === d.day ? 20 : 6, height: 6, borderRadius: 3,
                background: dayData.day === d.day ? GOLD : LINE,
                cursor: 'pointer', transition: 'width 180ms ease',
              }} />
            ))}
          </div>
          <button
            onClick={() => dayData.day < menu.days.length && nav('menu-day', { day: dayData.day + 1 })}
            disabled={dayData.day >= menu.days.length}
            style={{ width: 44, height: 44, borderRadius: 22, border: 'none', background: dayData.day < menu.days.length ? INK : '#E0DDD6', cursor: dayData.day < menu.days.length ? 'pointer' : 'default', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <svg width="16" height="16" viewBox="0 0 16 16"><path d="M6 4l4 4-4 4" stroke="#fff" strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </button>
        </div>

        {captainInline && (
          <button onClick={() => setShowMenuEdit(true)}
            style={{ width: '100%', marginTop: 16, padding: '12px 16px', borderRadius: 14, border: `1px solid ${GOLD}`, background: 'rgba(201,168,76,0.08)', cursor: 'pointer', fontFamily: 'inherit', fontSize: 13, fontWeight: 600, color: INK, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}>
            <Glyph name="edit" size={16} color={INK} /> Edit menu for this day
          </button>
        )}
      </div>

      {captainInline && showMenuEdit && window.MenuDayEditSheet && (() => {
        const Sheet = window.MenuDayEditSheet;
        return <Sheet open={showMenuEdit} day={dayData.day} onClose={() => { setShowMenuEdit(false); forceRender(); }} />;
      })()}
    </div>
  );
}

// ── Dietary preferences — full display from CHARTER_PREFERENCES ──
function DietaryScreen({ nav }) {
  const { lang } = React.useContext(window.LangCtx || React.createContext({ lang: 'fr' }));
  const t = (en, fr) => lang === 'fr' ? fr : en;
  const prefs = window.CHARTER_PREFERENCES || {};
  const guests = prefs.guests || [];

  const isCrew = !!window._isCrewUser;
  const captainInline = isCrew && window._captainMode === 'inline';
  const [showPrefsEdit, setShowPrefsEdit] = React.useState(false);
  const [, forcePrefsRender] = React.useReducer(x => x + 1, 0);
  // Auto-match to the logged-in client's first name (guests only; crew see all equally)
  const clientName = (TRIP.client.firstName || '').toLowerCase();
  const defaultGuest = isCrew ? 0 : Math.max(0, guests.findIndex(g => g.name?.toLowerCase() === clientName));
  const [activeGuest, setActiveGuest] = React.useState(defaultGuest);

  // Split a comma-separated string into trimmed chips
  function chips(str) { return (str||'').split(',').map(s => s.trim()).filter(Boolean); }

  // Chip component
  function Chip({ label, bg, color }) {
    return (
      <span style={{ display:'inline-block', fontSize: 10.5, fontWeight: 600, padding: '3px 10px', borderRadius: 99, background: bg, color, margin: '2px 3px 2px 0', letterSpacing: 0.2 }}>
        {label}
      </span>
    );
  }

  // Info row in a card
  function InfoRow({ label, value, last }) {
    if (!value) return null;
    return (
      <div style={{ padding: '11px 0', borderBottom: last ? 'none' : `1px solid ${LINE}`, display: 'flex', gap: 12, alignItems: 'flex-start' }}>
        <div style={{ width: 6, height: 6, borderRadius: 3, background: GOLD, flexShrink: 0, marginTop: 6 }} />
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 9.5, letterSpacing: 1, textTransform: 'uppercase', color: MUTE, fontWeight: 700, marginBottom: 4 }}>{label}</div>
          <div style={{ fontSize: 13, color: INK, lineHeight: 1.55 }}>{value}</div>
        </div>
      </div>
    );
  }

  const hasPrefs = guests.length > 0 || pickLang(prefs,'breakfast_style',lang) || pickLang(prefs,'drinks_water',lang) || pickLang(prefs,'desserts_favorites',lang);

  if (!hasPrefs) {
    return (
      <div style={{ position:'relative', width:'100%', height:'100%', background:BG, overflow:'hidden', fontFamily:'"Inter", system-ui', display:'flex', flexDirection:'column' }}>
        <TopBar title={t('Food preferences', 'Préférences alimentaires')} sub={t('Shared with your crew', 'Partagées avec l\'équipage')} onBack={() => nav('menu')} />
        <div style={{ flex:1, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', padding:32, gap:12 }}>
          <div style={{ fontSize: 32 }}><Glyph name="chef" size={32} color={MUTE} /></div>
          <div style={{ fontSize: 15, fontWeight: 600, color: INK, textAlign: 'center' }}>{t('Preferences coming soon', 'Préférences bientôt disponibles')}</div>
          <div style={{ fontSize: 12.5, color: MUTE, textAlign: 'center', lineHeight: 1.6, maxWidth: 260 }}>{t('Your broker is finalising your preference profile. Check back soon.', 'Votre courtier finalise votre profil. Revenez bientôt.')}</div>
        </div>
      </div>
    );
  }

  return (
    <div style={{ position:'relative', width:'100%', height:'100%', background:BG, overflow:'hidden', fontFamily:'"Inter", system-ui', display:'flex', flexDirection:'column' }}>
      <TopBar
        title={t('Food preferences', 'Préférences alimentaires')}
        sub={isCrew
          ? t('All guests · crew view', 'Tous les invités · vue équipage')
          : t('Shared with your crew', 'Partagées avec l\'équipage')}
        onBack={() => nav('menu')}
      />

      <div style={{ flex:1, overflowY:'auto', padding:'0 0 40px' }} className="no-scrollbar">

        {/* ── Header banner ── */}
        {guests.length > 0 && (
          <div style={{ margin:'16px 20px 0', background:INK, borderRadius:20, padding:'20px 20px 18px', position:'relative', overflow:'hidden' }}>
            <div style={{ position:'absolute', top:-20, right:-20, width:80, height:80, borderRadius:40, background:'rgba(201,168,76,0.12)' }} />
            {isCrew ? (
              <>
                <div style={{ fontSize:11, letterSpacing:0.5, color:'rgba(255,255,255,0.5)', marginBottom:6, fontWeight:500 }}>
                  {t('Guest preferences', 'Préférences des invités')}
                </div>
                <div style={{ fontSize:19, fontWeight:700, color:'#fff', letterSpacing:-0.3, marginBottom:10 }}>
                  {guests.length} {t(guests.length > 1 ? 'guests' : 'guest', guests.length > 1 ? 'invités' : 'invité')} <Glyph name="users" size={18} color="#fff" />
                </div>
                <div style={{ fontSize:12, color:'rgba(255,255,255,0.6)', lineHeight:1.55 }}>
                  {t('All dietary preferences for this charter. Select a guest tab to see their details.', 'Préférences alimentaires de tous les invités. Sélectionnez un onglet pour voir le détail.')}
                </div>
              </>
            ) : (
              <>
                <div style={{ fontSize:11, letterSpacing:0.5, color:'rgba(255,255,255,0.5)', marginBottom:6, fontWeight:500 }}>
                  {t('Your preferences on board', 'Vos préférences à bord')}
                </div>
                <div style={{ fontSize:19, fontWeight:700, color:'#fff', letterSpacing:-0.3, marginBottom:10 }}>
                  {t('Hello', 'Bonjour')}, {guests[defaultGuest]?.name || TRIP.client.firstName}
                </div>
                <div style={{ fontSize:12, color:'rgba(255,255,255,0.6)', lineHeight:1.55 }}>
                  {t('Your food preferences have been shared with your chef and chief stewardess. If anything has changed, message the team.', 'Vos préférences alimentaires ont été transmises à votre chef et votre chef de cabine. Si quelque chose a changé, contactez l\'équipe.')}
                </div>
              </>
            )}
          </div>
        )}

        {/* ── Guest tabs (crew: always show; guests: only if multiple) ── */}
        {(isCrew ? guests.length > 0 : guests.length > 1) && (
          <div style={{ margin:'14px 20px 0', display:'flex', gap:8, flexWrap:'wrap' }}>
            {guests.map((g, i) => {
              const hasSevere = !!(pickLang(g, 'allergies_severe', lang));
              return (
                <button key={i} onClick={() => setActiveGuest(i)} data-track={`dietary_guest:${g.name || i}`} style={{
                  padding:'7px 16px', borderRadius:99, cursor:'pointer', fontFamily:'inherit',
                  background: activeGuest === i ? INK : '#fff',
                  color: activeGuest === i ? '#fff' : MUTE,
                  fontSize:12, fontWeight:600,
                  border: `1px solid ${activeGuest === i ? INK : LINE}`,
                  display:'flex', alignItems:'center', gap:6,
                }}>
                  {g.name || t(`Guest ${i+1}`, `Invité ${i+1}`)}
                  {hasSevere && <span style={{ width:7, height:7, borderRadius:4, background: activeGuest===i ? '#FCA5A5' : '#EF4444', display:'inline-block' }} />}
                </button>
              );
            })}
          </div>
        )}

        {/* ── Active guest detail ── */}
        {guests[activeGuest] && (() => {
          const g = guests[activeGuest];
          const severeChips = chips(pickLang(g, 'allergies_severe', lang));
          const intoleranceChips = chips(pickLang(g, 'intolerances', lang));
          const gDislikes  = pickLang(g, 'dislikes', lang);
          const gFavorites = pickLang(g, 'favorites', lang);
          const gDrinks    = pickLang(g, 'drinks', lang);
          const gDiet      = pickLang(g, 'diet', lang);
          return (
            <div style={{ margin:'12px 20px 0', display:'flex', flexDirection:'column', gap:12 }}>

              {/* Severe allergy banner */}
              {severeChips.length > 0 && (
                <div style={{ background:'#FEF2F2', border:'1.5px solid #FCA5A5', borderRadius:16, padding:'14px 16px', display:'flex', gap:12, alignItems:'flex-start' }}>
                  <div style={{ fontSize:20, flexShrink:0 }}>⚠</div>
                  <div>
                    <div style={{ fontSize:12, fontWeight:700, color:'#B91C1C', marginBottom:8 }}>
                      {t('Severe allergies — your chef has been notified', 'Allergies sévères — votre chef en est informé')}
                    </div>
                    <div style={{ display:'flex', flexWrap:'wrap' }}>
                      {severeChips.map(a => <Chip key={a} label={a} bg='#FEE2E2' color='#B91C1C' />)}
                    </div>
                  </div>
                </div>
              )}

              {/* Diet + intolerances row */}
              {(gDiet || intoleranceChips.length > 0) && (
                <div style={{ background:'#fff', border:`1px solid ${LINE}`, borderRadius:18, padding:'14px 18px', display:'flex', flexWrap:'wrap', gap:8, alignItems:'center', boxShadow:'0 1px 8px rgba(13,27,42,0.04)' }}>
                  {gDiet && <span style={{ fontSize:12.5, fontWeight:600, color:INK }}>{gDiet}</span>}
                  {intoleranceChips.map(it => <Chip key={it} label={`⚠ ${it}`} bg='#FEF3C7' color='#B45309' />)}
                </div>
              )}

              {/* Dislikes */}
              {gDislikes && (
                <div style={{ background:'#fff', border:`1px solid ${LINE}`, borderRadius:18, padding:'16px 18px', boxShadow:'0 1px 8px rgba(13,27,42,0.04)' }}>
                  <div style={{ fontSize:9.5, letterSpacing:1.2, textTransform:'uppercase', color:'#C0392B', fontWeight:700, marginBottom:8, display:'flex', alignItems:'center', gap:6 }}>
                    {t('Dislikes & avoid', 'N\'aime pas / à éviter')}
                  </div>
                  <div style={{ fontSize:13, color:INK, lineHeight:1.65 }}>{gDislikes}</div>
                </div>
              )}

              {/* Favourites */}
              {gFavorites && (
                <div style={{ background:'#fff', border:`1px solid ${LINE}`, borderRadius:18, padding:'16px 18px', boxShadow:'0 1px 8px rgba(13,27,42,0.04)' }}>
                  <div style={{ fontSize:9.5, letterSpacing:1.2, textTransform:'uppercase', color:'#2C5E3F', fontWeight:700, marginBottom:8, display:'flex', alignItems:'center', gap:6 }}>
                    <span>✦</span> {t('Favourites', 'Préférences & favoris')}
                  </div>
                  <div style={{ fontSize:13, color:INK, lineHeight:1.65 }}>{gFavorites}</div>
                </div>
              )}

              {/* Personal drinks */}
              {gDrinks && (
                <div style={{ background:'#fff', border:`1px solid ${LINE}`, borderRadius:18, padding:'16px 18px', boxShadow:'0 1px 8px rgba(13,27,42,0.04)' }}>
                  <div style={{ fontSize:9.5, letterSpacing:1.2, textTransform:'uppercase', color:MUTE, fontWeight:700, marginBottom:8, display:'flex', alignItems:'center', gap:6 }}>
                    {t('Drinks', 'Boissons personnelles')}
                  </div>
                  <div style={{ fontSize:13, color:INK, lineHeight:1.65 }}>{gDrinks}</div>
                </div>
              )}
            </div>
          );
        })()}

        {/* ── Service ── */}
        {(pickLang(prefs,'breakfast_style',lang) || pickLang(prefs,'lunch_style',lang) || pickLang(prefs,'dinner_style',lang)) && (
          <div style={{ margin:'20px 20px 0', background:'#fff', border:`1px solid ${LINE}`, borderRadius:18, padding:'16px 18px', boxShadow:'0 2px 12px rgba(13,27,42,0.05)' }}>
            <div style={{ fontSize:10, letterSpacing:1.4, textTransform:'uppercase', color:MUTE, fontWeight:700, marginBottom:14 }}>{t('Meal service', 'Service à table')}</div>
            {[
              { label:t('Breakfast','Petit-déjeuner'), style:pickLang(prefs,'breakfast_style',lang), time:prefs.breakfast_time },
              { label:t('Lunch','Déjeuner'),      style:[pickLang(prefs,'lunch_style',lang), pickLang(prefs,'lunch_format',lang)].filter(Boolean).join(' · '), time:prefs.lunch_time },
              { label:t('Dinner','Dîner'),        style:[pickLang(prefs,'dinner_style',lang), pickLang(prefs,'dinner_format',lang), prefs.dinner_starters ? t('with starters','avec hors-d\'œuvres') : ''].filter(Boolean).join(' · '), time:prefs.dinner_time },
            ].map((m, i, arr) => (m.style || m.time) && (
              <div key={i} style={{ display:'flex', alignItems:'center', gap:12, padding:'10px 0', borderBottom: i < arr.length-1 ? `1px solid ${LINE}` : 'none' }}>
                <div style={{ width:6, height:6, borderRadius:3, background:GOLD, flexShrink:0 }} />
                <div style={{ flex:1 }}>
                  <div style={{ fontSize:11, fontWeight:700, color:MUTE, letterSpacing:0.5, textTransform:'uppercase' }}>{m.label}</div>
                  {m.style && <div style={{ fontSize:12.5, color:INK, marginTop:2 }}>{m.style}</div>}
                </div>
                {m.time && <div style={{ fontSize:12, color:MUTE, fontWeight:600, flexShrink:0 }}>{m.time}</div>}
              </div>
            ))}
          </div>
        )}

        {/* ── Drinks ── */}
        {(pickLang(prefs,'drinks_water',lang) || pickLang(prefs,'drinks_wine',lang) || pickLang(prefs,'drinks_coffee',lang)) && (
          <div style={{ margin:'14px 20px 0', background:'#fff', border:`1px solid ${LINE}`, borderRadius:18, padding:'16px 18px', boxShadow:'0 2px 12px rgba(13,27,42,0.05)' }}>
            <div style={{ fontSize:10, letterSpacing:1.4, textTransform:'uppercase', color:MUTE, fontWeight:700, marginBottom:4 }}>{t('Drinks', 'Boissons')}</div>
            {[
              { k:'drinks_water',   label:t('Water','Eau') },
              { k:'drinks_juices',  label:t('Juices','Jus') },
              { k:'drinks_soft',    label:t('Soft drinks','Soft drinks') },
              { k:'drinks_coffee',  label:t('Coffee','Café') },
              { k:'drinks_tea',     label:t('Tea','Thé') },
              { k:'drinks_wine',    label:t('Wine','Vins') },
              { k:'drinks_beer',    label:t('Beer','Bière') },
            ].filter(f => pickLang(prefs, f.k, lang)).map((f, i, arr) => (
              <InfoRow key={f.k} label={f.label} value={pickLang(prefs, f.k, lang)} last={i === arr.length-1 && !pickLang(prefs,'drinks_notes',lang)} />
            ))}
            {pickLang(prefs,'drinks_notes',lang) && <InfoRow label={t('Notes','Notes')} value={pickLang(prefs,'drinks_notes',lang)} last />}
          </div>
        )}

        {/* ── Desserts ── */}
        {(pickLang(prefs,'desserts_favorites',lang) || pickLang(prefs,'desserts_avoid',lang)) && (
          <div style={{ margin:'14px 20px 0', background:'#fff', border:`1px solid ${LINE}`, borderRadius:18, padding:'16px 18px', boxShadow:'0 2px 12px rgba(13,27,42,0.05)' }}>
            <div style={{ fontSize:10, letterSpacing:1.4, textTransform:'uppercase', color:MUTE, fontWeight:700, marginBottom:4 }}>{t('Desserts & cheese', 'Desserts & fromages')}</div>
            <InfoRow label={t('Favourites','Adore')} value={pickLang(prefs,'desserts_favorites',lang)} last={!pickLang(prefs,'desserts_avoid',lang)} />
            <InfoRow label={t('Avoid','À éviter')} value={pickLang(prefs,'desserts_avoid',lang)} last />
          </div>
        )}

        {/* ── Chef notes ── */}
        {pickLang(prefs,'chef_notes',lang) && (
          <div style={{ margin:'14px 20px 0', background:'linear-gradient(135deg,#FAF4E2,#F4EFDE)', border:`1px solid ${GOLD}`, borderRadius:18, padding:'16px 18px' }}>
            <div style={{ fontSize:10, letterSpacing:1.4, textTransform:'uppercase', color:'#8A6E1F', fontWeight:700, marginBottom:8 }}>{t('Chef notes', 'Notes chef')}</div>
            <div style={{ fontSize:12.5, color:INK, lineHeight:1.7 }}>{pickLang(prefs,'chef_notes',lang)}</div>
          </div>
        )}

        {/* ── Contact CTA (guests only) ── */}
        {!isCrew && (
          <div style={{ margin:'20px 20px 0', padding:'14px 16px', background:'#fff', border:`1px solid ${LINE}`, borderRadius:16, display:'flex', gap:12, alignItems:'center' }}>
            <div style={{ fontSize:12, color:MUTE, lineHeight:1.5, flex:1 }}>{t('Something to update? Message your chief stewardess.', 'Quelque chose à modifier ? Contactez votre chef de cabine.')}</div>
            <button onClick={() => nav('chat', { who: 'chief_stew', from: 'dietary' })} style={{ padding:'8px 14px', borderRadius:99, border:`1px solid ${INK}`, background:'transparent', fontSize:12, fontWeight:600, color:INK, cursor:'pointer', fontFamily:'inherit', flexShrink:0 }}>
              {t('Message', 'Message')}
            </button>
          </div>
        )}

        {captainInline && (
          <button onClick={() => setShowPrefsEdit(true)}
            style={{ width: '100%', marginTop: 16, padding: '12px 16px', borderRadius: 14, border: `1px solid ${GOLD}`, background: 'rgba(201,168,76,0.08)', cursor: 'pointer', fontFamily: 'inherit', fontSize: 13, fontWeight: 600, color: INK, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}>
            <Glyph name="edit" size={16} color={INK} /> Edit preferences
          </button>
        )}

      </div>

      {captainInline && showPrefsEdit && window.PrefsEditSheet && (() => {
        const Sheet = window.PrefsEditSheet;
        return <Sheet open={showPrefsEdit} onClose={() => { setShowPrefsEdit(false); forcePrefsRender(); }} />;
      })()}
    </div>
  );
}

Object.assign(window, { YachtDetail, PreferenceSheet, ItineraryScreen, VoyageMapScreen, DayDetailScreen, MenuScreen, MenuDayScreen, DietaryScreen });
