/* global React, STATUS, STATUS_ORDER, FLEET, Icon, TABS, fmtMoney, fmtMoneyD, AIRPORTS, acYear */
const { useState, useEffect } = React;

/* ============================================================
   PHONE SHELL + STATUS BAR
   ============================================================ */
function StatusBar({ bg = '#19253C', fg = '#fff' }) {
  return (
    <div style={{
      background: bg, color: fg, height: 44, flex: '0 0 44px',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      padding: '0 24px 0 28px', font: '600 15px/1 var(--font-ui)', letterSpacing: '0.02em',
    }}>
      <span>9:41</span>
      <span style={{ display: 'inline-flex', gap: 7, alignItems: 'center' }}>
        <svg width="18" height="12" viewBox="0 0 18 12" fill={fg}><rect x="0" y="7" width="3" height="5" rx="1"/><rect x="5" y="4" width="3" height="8" rx="1"/><rect x="10" y="2" width="3" height="10" rx="1"/><rect x="15" y="0" width="3" height="12" rx="1"/></svg>
        <svg width="17" height="12" viewBox="0 0 17 12" fill={fg}><path d="M8.5 2.5c2.3 0 4.4.9 6 2.4l1.4-1.5A11 11 0 0 0 8.5.5 11 11 0 0 0 1.1 3.4L2.5 4.9a8.6 8.6 0 0 1 6-2.4zM8.5 6c1.2 0 2.3.5 3.1 1.2l1.4-1.5A6.6 6.6 0 0 0 8.5 4 6.6 6.6 0 0 0 4 5.7l1.4 1.5C6.2 6.5 7.3 6 8.5 6zm0 3.5 2-2.1a2.9 2.9 0 0 0-4 0l2 2.1z"/></svg>
        <svg width="26" height="13" viewBox="0 0 26 13" fill="none"><rect x="0.5" y="0.5" width="22" height="12" rx="3.2" stroke={fg} opacity="0.5"/><rect x="2" y="2" width="17" height="9" rx="1.8" fill={fg}/><rect x="23.5" y="4" width="2" height="5" rx="1" fill={fg} opacity="0.6"/></svg>
      </span>
    </div>
  );
}

function PhoneShell({ statusBg, statusFg, children }) {
  return (
    <div style={{
      width: 393, height: 852, background: '#EEF2F5',
      fontFamily: 'var(--font-ui)', color: 'var(--baj-text)',
      display: 'flex', flexDirection: 'column', position: 'relative', overflow: 'hidden',
    }}>
      <StatusBar bg={statusBg} fg={statusFg} />
      {children}
    </div>
  );
}

/* ============================================================
   BOTTOM TAB BAR
   ============================================================ */
function TabBar({ active = 'Quotes', onTab }) {
  return (
    <nav style={{
      flex: '0 0 auto', background: 'var(--baj-navy-deep)',
      display: 'flex', justifyContent: 'space-around', alignItems: 'flex-start',
      padding: '9px 6px 26px', borderTop: '1px solid rgba(255,255,255,0.06)', zIndex: 5,
    }}>
      {TABS.map(t => {
        const on = active === t.key;
        return (
          <button key={t.key} onClick={() => onTab && onTab(t.key)} style={{
            background: 'transparent', border: 0, cursor: 'pointer',
            display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
            color: on ? '#fff' : 'rgba(255,255,255,0.46)', padding: '2px 6px', position: 'relative',
          }}>
            {on && <span style={{ position: 'absolute', top: -9, width: 22, height: 3, borderRadius: 99, background: 'var(--baj-blue-soft)' }} />}
            <i className={t.icon} style={{ fontSize: 20, lineHeight: 1 }} />
            <span style={{ font: '600 10px/1 var(--font-ui)', letterSpacing: '0.01em' }}>{t.key}</span>
          </button>
        );
      })}
    </nav>
  );
}

/* ============================================================
   STATUS PILL + DOT
   ============================================================ */
function StatusPill({ status, size = 'md' }) {
  const s = STATUS[status];
  if (!s) return null;
  const pad = size === 'sm' ? '4px 8px' : '5px 11px';
  const fs = size === 'sm' ? 10.5 : 11.5;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      background: s.bg, color: s.fg, font: `700 ${fs}px/1 var(--font-ui)`,
      letterSpacing: '0.02em', padding: pad, borderRadius: 6,
      border: s.border ? `1px solid ${s.border}` : 'none', whiteSpace: 'nowrap',
    }}>{s.label}</span>
  );
}
function StatusDot({ status, size = 8 }) {
  const s = STATUS[status];
  return <span style={{ width: size, height: size, borderRadius: 99, background: s.dot, border: s.border ? `1px solid ${s.border}` : 'none', flex: '0 0 auto' }} />;
}

/* ============================================================
   DELTA TAG  (competitor price relative to your quote)
   ============================================================ */
function DeltaTag({ delta, big }) {
  if (delta === 0 || delta == null) {
    return <span style={{ font: `600 ${big ? 14 : 12}px/1 var(--font-ui)`, color: 'var(--baj-text-mute)' }}>your quote</span>;
  }
  const below = delta < 0; // competitor cheaper than you → they threaten your rank (shown red); above → you beat them (green)
  const color = below ? '#B43A3A' : '#2E8B57';
  const ArrowEl = below ? Icon.down : Icon.up;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 2, color, font: `700 ${big ? 14 : 12}px/1 var(--font-ui)` }}>
      <ArrowEl width={big ? 14 : 12} height={big ? 14 : 12} />
      {fmtMoney(Math.abs(delta))}
    </span>
  );
}

/* ============================================================
   RANK BADGE
   ============================================================ */
function RankBadge({ rank, total, win, size = 'md' }) {
  const dim = size === 'lg' ? 56 : size === 'sm' ? 34 : 44;
  return (
    <div style={{
      width: dim, height: dim, borderRadius: 14, flex: '0 0 auto',
      background: win ? 'linear-gradient(160deg,#F3A617,#E08D00)' : 'var(--baj-navy)',
      color: win ? '#19253C' : '#fff',
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      boxShadow: win ? '0 4px 14px rgba(243,166,23,0.4)' : '0 2px 8px rgba(25,37,60,0.25)',
    }}>
      {win
        ? <Icon.trophy width={size === 'lg' ? 26 : 20} height={size === 'lg' ? 26 : 20} />
        : <>
            <span style={{ font: `800 ${size === 'lg' ? 22 : 17}px/1 var(--font-ui)` }}>{rank}</span>
            <span style={{ font: '600 9px/1 var(--font-ui)', opacity: 0.62, marginTop: 2 }}>of {total}</span>
          </>}
    </div>
  );
}

/* ============================================================
   PRICE SPREAD BAR — visualizes your position in the field
   ============================================================ */
function SpreadBar({ rows }) {
  const prices = rows.map(r => r.price);
  const min = Math.min(...prices), max = Math.max(...prices);
  const span = max - min || 1;
  const pos = (p) => `${((p - min) / span) * 100}%`;
  const you = rows.find(r => r.you);
  return (
    <div style={{ padding: '4px 2px 2px' }}>
      <div style={{ position: 'relative', height: 8, borderRadius: 99, background: 'linear-gradient(90deg,#2E8B57,#F3A617,#B43A3A)', opacity: 0.85 }}>
        {rows.map((r, i) => !r.you && (
          <span key={i} style={{ position: 'absolute', top: '50%', left: pos(r.price), width: 6, height: 6, borderRadius: 99, background: 'rgba(255,255,255,0.9)', transform: 'translate(-50%,-50%)', boxShadow: '0 0 0 1px rgba(15,27,45,0.25)' }} />
        ))}
        {you && (
          <span style={{ position: 'absolute', top: '50%', left: pos(you.price), transform: 'translate(-50%,-50%)', width: 16, height: 16, borderRadius: 99, background: '#19253C', border: '3px solid #fff', boxShadow: '0 2px 6px rgba(15,27,45,0.4)' }} />
        )}
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 7, font: '600 10px/1 var(--font-ui)', color: 'var(--baj-text-mute)' }}>
        <span>Lowest {fmtMoney(min)}</span>
        <span>Highest {fmtMoney(max)}</span>
      </div>
    </div>
  );
}

/* ============================================================
   COMPETITOR LADDER  (with Trip / Leg switch)
   ============================================================ */
function CompetitorLadder({ trip, showSpread, onAddQuote }) {
  const legCount = trip.legCount || 0;
  const views = [{ key: 'trip', label: 'Trip' }];
  for (let i = 1; i <= legCount; i++) views.push({ key: `leg${i}`, label: `Leg ${i}` });

  const [view, setView] = useState('trip');
  const rows = (trip.ladder && trip.ladder[view]) || [];
  const you = rows.find(r => r.you);
  const yourPrice = you ? you.price : null;
  const hasYourQuote = rows.some(r => r.you);

  const quoteCountFor = (key) => {
    if (!trip.quotes) return 0;
    if (key === 'trip') return trip.quotes.filter(q => q.you && q.type === 'Trip').length;
    const legNum = parseInt(key.replace('leg', ''), 10);
    return trip.quotes.filter(q => q.you && q.type === 'Leg' && q.legNum === legNum).length;
  };

  const addBtnLabel = view === 'trip' ? 'Add Trip Quote' : `Add Leg ${view.replace('leg', '')} Quote`;
  const lockViewLabel = view === 'trip' ? 'a trip' : `a leg ${view.replace('leg', '')}`;

  return (
    <div>
      <div style={{ display: 'flex', gap: 6, marginBottom: 14 }}>
        {views.map(v => {
          const on = v.key === view;
          const count = quoteCountFor(v.key);
          return (
            <button key={v.key} onClick={() => setView(v.key)} style={{
              flex: 1, padding: '9px 4px', border: 0, cursor: 'pointer', borderRadius: 9,
              font: '700 12.5px/1 var(--font-ui)', letterSpacing: '0.02em',
              background: on ? 'var(--baj-blue)' : 'var(--baj-surface-2)',
              color: on ? '#fff' : 'var(--baj-text-mute)',
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5,
            }}>
              {v.label}
              {count > 0 && (
                <span style={{
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                  minWidth: 17, height: 17, borderRadius: 99, padding: '0 4px',
                  background: on ? 'rgba(255,255,255,0.28)' : 'var(--baj-blue)',
                  color: '#fff', font: '700 9px/1 var(--font-ui)',
                }}>{count}</span>
              )}
            </button>
          );
        })}
      </div>

      {showSpread && you && <div style={{ marginBottom: 16 }}><SpreadBar rows={rows} /></div>}

      <div style={{ position: 'relative', minHeight: !hasYourQuote ? 200 : 0 }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {(() => {
            const acHash = (s) => { let h = 5381; for (let c of s) h = ((h << 5) + h + c.charCodeAt(0)) & 0x7fffffff; return h; };
            const rowAmenities = rows.map(r => { const h = acHash(r.ac || ''); return { hasWifi: (h & 1) === 1, hasPaw: ((h >> 1) & 1) === 1 }; });
            if (rowAmenities.every(a => a.hasWifi)) rowAmenities[0].hasWifi = false;
            return rows.map((r, i) => {
            const rank = i + 1;
            const delta = yourPrice != null && !r.you ? r.price - yourPrice : null;
            const { hasWifi, hasPaw } = rowAmenities[i];
            return (
              <div key={i} style={{
                display: 'flex', alignItems: 'center', gap: 12, padding: '12px 13px', borderRadius: 12,
                background: r.you ? 'var(--baj-navy-hi)' : '#fff',
                border: r.you ? '1px solid var(--baj-navy-hi)' : '1px solid var(--baj-line)',
                color: r.you ? '#fff' : 'var(--baj-text)',
              }}>
                <div style={{
                  width: 26, height: 26, borderRadius: 8, flex: '0 0 auto',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  font: '800 13px/1 var(--font-ui)',
                  background: r.you ? 'rgba(255,255,255,0.16)' : (rank === 1 ? '#F3A617' : 'var(--baj-surface-2)'),
                  color: r.you ? '#fff' : (rank === 1 ? '#19253C' : 'var(--baj-text-mute)'),
                }}>{rank}</div>

                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
                    <span style={{ font: '700 14px/1.15 var(--font-ui)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{acYear(r.ac)} {r.ac}</span>
                    {r.you && <span style={{ font: '700 8.5px/1 var(--font-ui)', letterSpacing: '0.1em', background: 'var(--baj-blue)', color: '#fff', padding: '3px 6px', borderRadius: 4 }}>YOU</span>}
                  </div>
                  <div style={{ font: '500 11px/1.3 var(--font-ui)', color: r.you ? 'rgba(255,255,255,0.65)' : 'var(--baj-text-mute)', marginTop: 3 }}>
                    {r.cat}{r.refurbInt != null ? ` · Int '${String(r.refurbInt).slice(2)} · Ext '${String(r.refurbExt).slice(2)}` : ''}
                  </div>
                  <div style={{ display: 'flex', gap: 7, marginTop: 6, alignItems: 'center' }}>
                    {(() => {
                      const wifiColor = hasWifi
                        ? (r.you ? '#fff' : 'var(--baj-blue)')
                        : (r.you ? 'rgba(255,255,255,0.22)' : '#C7CFDA');
                      const pawColor = hasPaw
                        ? (r.you ? '#fff' : 'var(--baj-blue)')
                        : (r.you ? 'rgba(255,255,255,0.22)' : '#C7CFDA');
                      return (<>
                        <span style={{ position: 'relative', display: 'inline-flex', alignItems: 'center' }}>
                          <i className="fa-solid fa-wifi" style={{ fontSize: 11, color: wifiColor }} />
                          {!hasWifi && (
                            <span style={{
                              position: 'absolute', top: '50%', left: -1, right: -1, height: 1.5,
                              background: r.you ? 'rgba(255,255,255,0.22)' : '#C7CFDA',
                              transform: 'translateY(-50%) rotate(-35deg)',
                              borderRadius: 1, display: 'block',
                            }} />
                          )}
                        </span>
                        <i className="fa-solid fa-paw" style={{ fontSize: 11, color: pawColor }} />
                      </>);
                    })()}
                  </div>
                </div>

                <div style={{ textAlign: 'right', flex: '0 0 auto' }}>
                  <div style={{ font: '800 15px/1 var(--font-ui)' }}>{fmtMoney(r.price)}</div>
                  <div style={{ marginTop: 5 }}>
                    {r.you ? <span style={{ font: '600 10.5px/1 var(--font-ui)', color: 'rgba(255,255,255,0.7)' }}>your quote</span> : <DeltaTag delta={delta} />}
                  </div>
                </div>
              </div>
            );
          });
          })()}
        </div>

        {!hasYourQuote && (
          <div style={{
            position: 'absolute', inset: 0, borderRadius: 12,
            backdropFilter: 'blur(7px)', WebkitBackdropFilter: 'blur(7px)',
            background: 'rgba(238,242,245,0.65)',
            display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
            gap: 10, padding: '24px 20px', textAlign: 'center',
          }}>
            <div style={{
              width: 50, height: 50, borderRadius: 14, background: 'var(--baj-navy)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              boxShadow: '0 4px 16px rgba(25,37,60,0.32)',
            }}>
              <Icon.lock width={22} height={22} style={{ color: '#fff' }} />
            </div>
            <div style={{ font: '700 14.5px/1.3 var(--font-ui)', color: 'var(--baj-text)' }}>
              Submit {lockViewLabel} quote to participate
            </div>
            <div style={{ font: '500 12px/1.5 var(--font-ui)', color: 'var(--baj-text-mute)', maxWidth: 210 }}>
              Add {lockViewLabel} quote to unlock live rankings and compete in this bidding.
            </div>
            {onAddQuote && (
              <button
                onClick={() => onAddQuote(view)}
                style={{
                  marginTop: 4, padding: '12px 22px', borderRadius: 10, border: 0, cursor: 'pointer',
                  background: 'var(--baj-blue)', color: '#fff',
                  font: '700 12.5px/1 var(--font-ui)', letterSpacing: '0.04em',
                  display: 'inline-flex', alignItems: 'center', gap: 7,
                  boxShadow: '0 2px 12px rgba(38,135,194,0.4)',
                }}
              >
                <Icon.plus width={14} height={14} />
                {addBtnLabel}
              </button>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

/* ============================================================
   BOTTOM SHEET  (slide-up, backdrop)
   ============================================================ */
function Sheet({ open, onClose, children, maxH = 660 }) {
  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 40,
      pointerEvents: open ? 'auto' : 'none',
    }}>
      <div onClick={onClose} style={{
        position: 'absolute', inset: 0, background: 'rgba(15,27,45,0.5)',
        opacity: open ? 1 : 0, transition: 'opacity 260ms var(--ease-out)',
      }} />
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0,
        background: '#fff', borderTopLeftRadius: 24, borderTopRightRadius: 24,
        maxHeight: maxH, display: 'flex', flexDirection: 'column',
        transform: open ? 'translateY(0)' : 'translateY(101%)',
        transition: 'transform 320ms var(--ease-out)',
        boxShadow: '0 -18px 48px rgba(15,27,45,0.28)',
      }}>
        <div style={{ padding: '12px 0 4px', flex: '0 0 auto', display: 'flex', justifyContent: 'center' }}>
          <span style={{ width: 40, height: 4, borderRadius: 99, background: 'var(--baj-line)' }} />
        </div>
        {children}
      </div>
    </div>
  );
}

/* ============================================================
   COMPETITOR SHEET  (ladder in a sheet, with header)
   ============================================================ */
function CompetitorSheet({ trip, open, onClose, onAddQuote }) {
  return (
    <Sheet open={open} onClose={onClose}>
      {trip && (
        <>
          <div style={{ padding: '6px 20px 14px', flex: '0 0 auto', borderBottom: '1px solid var(--baj-line)' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
              <div>
                <div style={{ font: '600 11px/1 var(--font-ui)', letterSpacing: '0.16em', color: 'var(--baj-text-mute)', textTransform: 'uppercase', marginBottom: 6 }}>Flight Marketplace · live</div>
                <div style={{ font: '800 19px/1.1 var(--font-ui)', color: 'var(--baj-text)' }}>{trip.from} → {trip.to}</div>
                <div style={{ font: '500 12.5px/1.3 var(--font-ui)', color: 'var(--baj-text-mute)', marginTop: 3 }}>{AIRPORTS[trip.from].city} → {AIRPORTS[trip.to].city} · {trip.date}</div>
              </div>
              <button onClick={onClose} style={{ background: 'var(--baj-surface-2)', border: 0, borderRadius: 99, width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', color: 'var(--baj-text-mute)' }}><Icon.close width={16} height={16} /></button>
            </div>
          </div>
          <div style={{ padding: '16px 20px 28px', overflowY: 'auto' }}>
            <CompetitorLadder trip={trip} showSpread onAddQuote={onAddQuote} />
          </div>
        </>
      )}
    </Sheet>
  );
}

/* ============================================================
   SUBMIT / REQUOTE SHEET  (price stepper)
   ============================================================ */
function QuoteSheet({ trip, mode, open, onClose, onConfirm, startPrice }) {
  const [price, setPrice] = useState(startPrice || 0);
  const [raw, setRaw] = useState('');
  const [tail, setTail] = useState('');
  const [notes, setNotes] = useState('');
  const [pdfFile, setPdfFile] = useState(null);
  const fileRef = React.useRef(null);

  useEffect(() => {
    if (open) {
      const p = startPrice || 0;
      setPrice(p);
      setRaw(p > 0 ? String(p) : '');
      setTail('');
      setNotes('');
      setPdfFile(null);
    }
  }, [open, startPrice]);
  if (!trip) return <Sheet open={open} onClose={onClose}>{null}</Sheet>;

  const isRequote = mode === 'requote';
  const ladder = trip.ladder && trip.ladder.trip;
  const lowest = ladder ? Math.min(...ladder.map(r => r.price)) : null;
  const beats = lowest != null && price > 0 ? price <= lowest : false;

  function handleChange(e) {
    const digits = e.target.value.replace(/[^0-9]/g, '');
    setRaw(digits);
    setPrice(digits === '' ? 0 : parseInt(digits, 10));
  }

  const fieldLabel = { font: '600 11px/1 var(--font-ui)', letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--baj-text-mute)', marginBottom: 7 };

  return (
    <Sheet open={open} onClose={onClose}>
      <div style={{ padding: '6px 20px 12px', flex: '0 0 auto' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
          <div>
            <div style={{ font: '600 11px/1 var(--font-ui)', letterSpacing: '0.16em', color: 'var(--baj-text-mute)', textTransform: 'uppercase', marginBottom: 6 }}>Submit a quote</div>
            <div style={{ font: '800 19px/1.1 var(--font-ui)', color: 'var(--baj-text)' }}>{trip.from} → {trip.to}</div>
            <div style={{ font: '500 12.5px/1.3 var(--font-ui)', color: 'var(--baj-text-mute)', marginTop: 3 }}>{trip.type === 'Leg' ? 'Per leg' : 'Whole trip'} · {trip.legCount} leg{trip.legCount > 1 ? 's' : ''} · {trip.pax} pax</div>
          </div>
          <button onClick={onClose} style={{ background: 'var(--baj-surface-2)', border: 0, borderRadius: 99, width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', color: 'var(--baj-text-mute)' }}><Icon.close width={16} height={16} /></button>
        </div>
      </div>

      <div style={{ padding: '8px 20px 26px', overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 12 }}>
        {/* aircraft dropdown */}
        <div>
          <div style={fieldLabel}>Aircraft</div>
          <div style={{ position: 'relative' }}>
            <select value={tail} onChange={e => setTail(e.target.value)} style={{
              width: '100%', padding: '11px 36px 11px 13px', borderRadius: 10,
              border: '1px solid var(--baj-line)', background: '#fff',
              font: '600 13px/1 var(--font-ui)', color: tail ? 'var(--baj-text)' : 'var(--baj-text-mute)',
              appearance: 'none', WebkitAppearance: 'none', cursor: 'pointer', outline: 'none',
            }}>
              <option value="">Select aircraft…</option>
              {FLEET.map(f => (
                <option key={f.tail} value={f.tail}>{f.tail} · {acYear(f.ac)} {f.ac} · {f.cat}</option>
              ))}
            </select>
            <span style={{ position: 'absolute', right: 12, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none', color: 'var(--baj-text-mute)' }}>
              <Icon.chevD width={14} height={14} />
            </span>
          </div>
        </div>

        {/* amount field */}
        <div style={{ background: 'var(--baj-surface)', borderRadius: 16, padding: '18px 18px 20px', border: '1px solid var(--baj-line)' }}>
          <div style={{ font: '600 11px/1 var(--font-ui)', letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--baj-text-mute)', textAlign: 'center', marginBottom: 12 }}>Your quote amount</div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}>
            <span style={{ font: '800 34px/1 var(--font-ui)', color: raw ? 'var(--baj-text)' : 'var(--baj-text-mute)', letterSpacing: '-0.01em' }}>$</span>
            <input
              inputMode="numeric"
              value={raw}
              onChange={handleChange}
              placeholder="0"
              style={{
                font: '800 34px/1 var(--font-ui)', color: 'var(--baj-text)', background: 'transparent',
                border: 0, outline: 'none', width: 160, letterSpacing: '-0.01em',
                caretColor: 'var(--baj-blue)',
              }}
            />
          </div>
          {isRequote && lowest != null && (
            <div style={{ marginTop: 16, padding: '11px 14px', borderRadius: 10, background: beats ? 'rgba(46,139,87,0.1)' : 'var(--baj-blue-tint)', display: 'flex', alignItems: 'center', gap: 9 }}>
              <Icon.bolt width={15} height={15} style={{ color: beats ? '#2E8B57' : 'var(--baj-blue)', flex: '0 0 auto' }} />
              <span style={{ font: '600 12.5px/1.35 var(--font-ui)', color: beats ? '#2E8B57' : 'var(--baj-blue-hover)' }}>
                {beats ? `You'd take the #1 spot — lowest in field is ${fmtMoney(lowest)}.` : `Field's lowest is ${fmtMoney(lowest)}. Price at or below to win rank #1.`}
              </span>
            </div>
          )}
        </div>

        {/* notes */}
        <div>
          <div style={fieldLabel}>Notes</div>
          <textarea
            value={notes}
            onChange={e => setNotes(e.target.value)}
            placeholder="Internal notes…"
            rows={3}
            style={{
              width: '100%', padding: '11px 13px', borderRadius: 10,
              border: '1px solid var(--baj-line)', background: '#fff',
              font: '500 13px/1.45 var(--font-ui)', color: 'var(--baj-text)',
              resize: 'vertical', outline: 'none', boxSizing: 'border-box',
            }}
          />
        </div>

        {/* pdf uploader */}
        <div>
          <div style={fieldLabel}>Quote document</div>
          <input ref={fileRef} type="file" accept=".pdf,application/pdf" style={{ display: 'none' }}
            onChange={e => setPdfFile(e.target.files[0] || null)} />
          {pdfFile ? (
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '11px 13px', borderRadius: 10, border: '1px solid var(--baj-line)', background: 'var(--baj-surface)' }}>
              <Icon.doc width={16} height={16} style={{ color: 'var(--baj-blue)', flex: '0 0 auto' }} />
              <span style={{ flex: 1, font: '500 12.5px/1.3 var(--font-ui)', color: 'var(--baj-text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{pdfFile.name}</span>
              <button onClick={() => setPdfFile(null)} style={{ background: 'none', border: 0, cursor: 'pointer', color: 'var(--baj-text-mute)', display: 'flex', padding: 2 }}>
                <Icon.close width={14} height={14} />
              </button>
            </div>
          ) : (
            <button onClick={() => fileRef.current && fileRef.current.click()} style={{
              width: '100%', padding: '11px 13px', borderRadius: 10,
              border: '1.5px dashed var(--baj-line)', background: '#fff',
              font: '600 12.5px/1 var(--font-ui)', color: 'var(--baj-text-mute)',
              cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7,
            }}>
              <Icon.doc width={14} height={14} style={{ color: 'var(--baj-blue)' }} />Attach PDF
            </button>
          )}
        </div>

        <button onClick={() => onConfirm && onConfirm({ price, tail, notes, file: pdfFile })} style={{
          width: '100%', marginTop: 4, padding: '16px 0', border: 0, borderRadius: 12, cursor: 'pointer',
          background: 'var(--baj-blue)', color: '#fff', font: '700 14px/1 var(--font-ui)', letterSpacing: '0.08em', textTransform: 'uppercase',
        }}>Submit quote</button>
        <button onClick={onClose} style={{ width: '100%', marginTop: 4, padding: '13px 0', border: 0, background: 'transparent', cursor: 'pointer', color: 'var(--baj-text-mute)', font: '600 13px/1 var(--font-ui)' }}>Cancel</button>
      </div>
    </Sheet>
  );
}

/* ============================================================
   COLLAPSIBLE MAP PANEL
   ============================================================ */
function MapPanel({ trip, defaultOpen = false }) {
  const [open, setOpen] = useState(defaultOpen);
  const from = AIRPORTS[trip.from], to = AIRPORTS[trip.to];
  return (
    <div style={{ background: '#fff', borderRadius: 16, border: '1px solid var(--baj-line)', overflow: 'hidden' }}>
      <button onClick={() => setOpen(o => !o)} style={{
        width: '100%', display: 'flex', alignItems: 'center', gap: 11, padding: '13px 15px',
        background: 'transparent', border: 0, cursor: 'pointer', textAlign: 'left',
      }}>
        <span style={{ width: 34, height: 34, borderRadius: 9, background: 'var(--baj-blue-tint)', color: 'var(--baj-blue)', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 auto' }}><Icon.pin width={17} height={17} /></span>
        <span style={{ flex: 1 }}>
          <span style={{ display: 'block', font: '700 13.5px/1.2 var(--font-ui)', color: 'var(--baj-text)' }}>Route map</span>
          <span style={{ display: 'block', font: '500 11.5px/1.2 var(--font-ui)', color: 'var(--baj-text-mute)', marginTop: 2 }}>{from.city}, {from.st} → {to.city}, {to.st} · {trip.distance} nm</span>
        </span>
        <span style={{ color: 'var(--baj-text-mute)', transform: open ? 'rotate(180deg)' : 'none', transition: 'transform 240ms var(--ease-out)' }}><Icon.chevD width={18} height={18} /></span>
      </button>
      <div style={{ maxHeight: open ? 220 : 0, transition: 'max-height 320ms var(--ease-out)', overflow: 'hidden' }}>
        <MapGraphic trip={trip} />
      </div>
    </div>
  );
}

function MapGraphic({ trip }) {
  const from = AIRPORTS[trip.from], to = AIRPORTS[trip.to];
  return (
    <div style={{ position: 'relative', height: 200, background: 'linear-gradient(160deg,#cfe0d6 0%,#bcd3c6 38%,#a9cbe0 100%)', borderTop: '1px solid var(--baj-line)' }}>
      {/* faux terrain */}
      <svg width="100%" height="100%" viewBox="0 0 360 200" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0 }}>
        <rect width="360" height="200" fill="#bcd3c6"/>
        <path d="M0 120 Q60 90 120 110 T240 100 T360 120 V200 H0 Z" fill="#b0cbbb" opacity="0.7"/>
        <path d="M0 150 Q90 130 180 150 T360 150 V200 H0 Z" fill="#a7c3d6" opacity="0.55"/>
        <g stroke="#9fb6a8" strokeWidth="1" opacity="0.5">
          <path d="M40 0 V200 M120 0 V200 M200 0 V200 M280 0 V200"/>
          <path d="M0 50 H360 M0 110 H360 M0 160 H360"/>
        </g>
        {/* route */}
        <path d="M70 140 Q180 60 290 96" fill="none" stroke="#19253C" strokeWidth="2.4" strokeDasharray="2 6" strokeLinecap="round"/>
        <g transform="translate(290 96)"><circle r="6" fill="#9C1D20"/><circle r="11" fill="none" stroke="#9C1D20" strokeWidth="2" opacity="0.4"/></g>
        <g transform="translate(70 140)"><circle r="6" fill="#19253C"/><circle r="11" fill="none" stroke="#19253C" strokeWidth="2" opacity="0.4"/></g>
      </svg>
      <i className="fa-solid fa-plane" style={{ position: 'absolute', left: '50%', top: '44.5%', transform: 'translate(-50%,-50%) rotate(-11deg)', fontSize: 18, color: '#19253C', pointerEvents: 'none' }} />
      <div style={{ position: 'absolute', left: 56, top: 150, font: '700 11px/1 var(--font-ui)', color: '#19253C', background: 'rgba(255,255,255,0.85)', padding: '3px 6px', borderRadius: 5 }}>{trip.from}</div>
      <div style={{ position: 'absolute', left: 270, top: 70, font: '700 11px/1 var(--font-ui)', color: '#9C1D20', background: 'rgba(255,255,255,0.85)', padding: '3px 6px', borderRadius: 5 }}>{trip.to}</div>
      <div style={{ position: 'absolute', right: 8, bottom: 6, font: '500 8px/1 var(--font-ui)', color: 'rgba(15,27,45,0.5)' }}>Map data ©2026</div>
    </div>
  );
}

/* ============================================================
   QUOTE EDIT + REQUOTE SHEET — tap a submitted quote row
   ============================================================ */
function QuoteEditSheet({ trip, quote, open, onClose, onRequote }) {
  const [price, setPrice] = useState(0);
  const [raw, setRaw] = useState('');
  const [tail, setTail] = useState('');
  const [inputFocused, setInputFocused] = useState(false);
  useEffect(() => {
    if (open && quote) {
      const p = quote.amount || 0;
      setPrice(p);
      setRaw(p > 0 ? p.toLocaleString() : '');
      setTail(quote.tail || (FLEET[0] && FLEET[0].tail));
    }
  }, [open, quote && quote.id]);

  function handleChange(e) {
    const digits = e.target.value.replace(/[^0-9]/g, '');
    const num = digits === '' ? 0 : parseInt(digits, 10);
    setRaw(digits === '' ? '' : num.toLocaleString());
    setPrice(num);
  }

  const ladder = trip && trip.ladder && trip.ladder.trip;
  const lowest = ladder ? Math.min(...ladder.map(r => r.price)) : null;
  const youLead = lowest != null && price > 0 && price <= lowest;
  const selectedFleet = FLEET.find(f => f.tail === tail) || (FLEET[0] || {});

  return (
    <Sheet open={open} onClose={onClose} maxH={700}>
      {trip && quote && (
        <>
          {/* header */}
          <div style={{ padding: '6px 20px 14px', flex: '0 0 auto', borderBottom: '1px solid var(--baj-line)' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
              <div>
                <div style={{ font: '600 11px/1 var(--font-ui)', letterSpacing: '0.16em', color: 'var(--baj-text-mute)', textTransform: 'uppercase', marginBottom: 6 }}>Edit quote</div>
                <div style={{ font: '800 20px/1.05 var(--font-ui)', color: 'var(--baj-text)' }}>{trip.from} → {trip.to}</div>
              </div>
              <button onClick={onClose} style={{ background: 'var(--baj-surface-2)', border: 0, borderRadius: 99, width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', color: 'var(--baj-text-mute)' }}><Icon.close width={16} height={16} /></button>
            </div>
          </div>

          <div style={{ padding: '14px 20px 28px', overflowY: 'auto' }}>
            {/* itinerary info strip */}
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 16 }}>
              {[
                { icon: Icon.takeoff, label: `${trip.from} → ${trip.to}` },
                { icon: Icon.clock,   label: `${trip.legCount} leg${trip.legCount > 1 ? 's' : ''}` },
                { icon: Icon.pax,     label: `${trip.pax} pax` },
                { icon: Icon.pin,     label: trip.date },
              ].map((chip, i) => (
                <span key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: 'var(--baj-surface)', border: '1px solid var(--baj-line)', borderRadius: 8, padding: '6px 10px', font: '600 11.5px/1 var(--font-ui)', color: 'var(--baj-text-mute)' }}>
                  <chip.icon width={13} height={13} />{chip.label}
                </span>
              ))}
            </div>

            {/* tail / aircraft selector */}
            <div style={{ marginBottom: 14 }}>
              <div style={{ font: '600 10px/1 var(--font-ui)', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--baj-text-mute)', marginBottom: 7 }}>Aircraft / Tail</div>
              <div style={{ position: 'relative' }}>
                <select
                  value={tail}
                  onChange={e => setTail(e.target.value)}
                  style={{
                    width: '100%', padding: '13px 40px 13px 14px', borderRadius: 11,
                    border: '1.5px solid var(--baj-line)', background: '#fff',
                    font: '600 13.5px/1 var(--font-ui)', color: 'var(--baj-text)',
                    appearance: 'none', WebkitAppearance: 'none', cursor: 'pointer', outline: 'none',
                  }}
                >
                  {FLEET.map(f => (
                    <option key={f.tail} value={f.tail}>{f.tail} — {acYear(f.ac)} {f.ac} · {f.cat}</option>
                  ))}
                </select>
                <span style={{ position: 'absolute', right: 13, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none', color: 'var(--baj-text-mute)' }}>
                  <Icon.chevD width={16} height={16} />
                </span>
              </div>
            </div>

            {/* typed amount field */}
            <div style={{ background: 'var(--baj-surface)', borderRadius: 14, padding: '16px 16px 18px', border: '1px solid var(--baj-line)', marginBottom: 14 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
                <span style={{ font: '600 11px/1 var(--font-ui)', letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--baj-text-mute)' }}>Quote amount</span>
                {quote && quote.amount > 0 && (
                  <span style={{ font: '600 11px/1 var(--font-ui)', color: 'var(--baj-text-mute)' }}>
                    PREV: <span style={{ color: 'var(--baj-text)', fontWeight: 700 }}>{fmtMoney(quote.amount)}</span>
                  </span>
                )}
              </div>

              {/* editable input */}
              <div style={{
                background: '#fff', borderRadius: 12, padding: '12px 14px',
                border: `2px solid ${inputFocused ? 'var(--baj-blue)' : 'var(--baj-line)'}`,
                display: 'flex', alignItems: 'center', gap: 4,
                transition: 'border-color 150ms',
                marginBottom: 16,
              }}>
                <span style={{ font: '800 32px/1 var(--font-ui)', color: raw ? 'var(--baj-text)' : 'var(--baj-text-mute)', letterSpacing: '-0.01em', flex: '0 0 auto' }}>$</span>
                <input
                  inputMode="numeric"
                  value={raw}
                  onChange={handleChange}
                  onFocus={() => setInputFocused(true)}
                  onBlur={() => setInputFocused(false)}
                  placeholder="0"
                  style={{
                    font: '800 32px/1 var(--font-ui)', color: 'var(--baj-text)', background: 'transparent',
                    border: 0, outline: 'none', flex: 1, minWidth: 0, letterSpacing: '-0.01em',
                    caretColor: 'var(--baj-blue)',
                  }}
                />
                <Icon.pencil width={15} height={15} style={{ color: inputFocused ? 'var(--baj-blue)' : 'var(--baj-text-mute)', flex: '0 0 auto', opacity: 0.6, transition: 'color 150ms' }} />
              </div>

              {/* suggestion / status pill */}
              {lowest != null && youLead && (
                <div style={{ padding: '10px 12px', borderRadius: 9, background: 'rgba(46,139,87,0.1)', display: 'flex', alignItems: 'center', gap: 8 }}>
                  <Icon.bolt width={14} height={14} style={{ color: '#2E8B57', flex: '0 0 auto' }} />
                  <span style={{ font: '600 12px/1.35 var(--font-ui)', color: '#2E8B57' }}>
                    You'd lead the field — current low is {fmtMoney(lowest)}.
                  </span>
                </div>
              )}
              {/* beat button — commented out
              {lowest != null && !youLead && (
                <button
                  onClick={() => { const v = lowest - 1; setPrice(v); setRaw(String(v)); }}
                  style={{
                    width: '100%', padding: '10px 12px', borderRadius: 9, cursor: 'pointer',
                    background: 'var(--baj-blue-tint)', border: '1.5px solid var(--baj-blue)',
                    display: 'flex', alignItems: 'center', gap: 8, textAlign: 'left',
                  }}>
                  <Icon.bolt width={14} height={14} style={{ color: 'var(--baj-blue)', flex: '0 0 auto' }} />
                  <span style={{ font: '600 12px/1.35 var(--font-ui)', color: 'var(--baj-blue-hover)', flex: 1 }}>
                    Field's lowest is {fmtMoney(lowest)}.
                  </span>
                  <span style={{ font: '700 11px/1 var(--font-ui)', color: 'var(--baj-blue)', whiteSpace: 'nowrap' }}>
                    Beat at {fmtMoney(lowest - 1)} →
                  </span>
                </button>
              )}
              */}
            </div>

            {/* CTAs */}
            <button
              onClick={() => { onRequote && onRequote({ tail, price }); onClose(); }}
              style={{
                width: '100%', padding: '16px 0', border: 0, borderRadius: 12, cursor: 'pointer',
                background: 'var(--baj-success)', color: '#fff', font: '700 14px/1 var(--font-ui)', letterSpacing: '0.06em', textTransform: 'uppercase',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
              }}><Icon.refresh width={16} height={16} />Requote</button>
            <button
              onClick={onClose}
              style={{ width: '100%', marginTop: 10, padding: '13px 0', border: 0, background: 'transparent', cursor: 'pointer', color: 'var(--baj-text-mute)', font: '600 13px/1 var(--font-ui)' }}>Cancel — don't update this quote</button>
          </div>
        </>
      )}
    </Sheet>
  );
}

function LegendSheet({ open, onClose }) {
  return (
    <Sheet open={open} onClose={onClose} maxH={560}>
      <div style={{ padding: '6px 20px 14px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ font: '800 18px/1.1 var(--font-ui)', color: 'var(--baj-text)' }}>Quote status legend</div>
        <button onClick={onClose} style={{ background: 'var(--baj-surface-2)', border: 0, borderRadius: 99, width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', color: 'var(--baj-text-mute)' }}><Icon.close width={16} height={16} /></button>
      </div>
      <div style={{ padding: '4px 20px 28px', overflowY: 'auto', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        {STATUS_ORDER.map(k => (
          <div key={k} style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
            <StatusDot status={k} size={12} />
            <span style={{ font: '600 13px/1.2 var(--font-ui)', color: 'var(--baj-text)' }}>{STATUS[k].label}</span>
          </div>
        ))}
      </div>
    </Sheet>
  );
}

/* ============================================================
   ATTACHMENTS SHEET — quote PDFs + trip request for a flight
   ============================================================ */
function attachmentsFor(trip) {
  const items = [{ name: `Trip Request — ${trip.ref}.pdf`, meta: `${trip.from} → ${trip.to} · ${trip.date}`, size: '88 KB', kind: 'request' }];
  trip.quotes.forEach(q => items.push({
    name: `Quote — ${q.tail}.pdf`,
    meta: `${acYear(q.ac)} ${q.ac} · ${fmtMoney(q.amount)} · ${STATUS[q.status].label}`,
    size: '124 KB', kind: 'quote',
  }));
  return items;
}

function AttachmentsSheet({ trip, open, onClose }) {
  const items = trip ? attachmentsFor(trip) : [];
  return (
    <Sheet open={open} onClose={onClose} maxH={560}>
      {trip && (
        <>
          <div style={{ padding: '6px 20px 14px', flex: '0 0 auto', borderBottom: '1px solid var(--baj-line)' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
              <div>
                <div style={{ font: '600 11px/1 var(--font-ui)', letterSpacing: '0.16em', color: 'var(--baj-text-mute)', textTransform: 'uppercase', marginBottom: 6 }}>Attachments</div>
                <div style={{ font: '800 19px/1.1 var(--font-ui)', color: 'var(--baj-text)' }}>{trip.from} → {trip.to}</div>
                <div style={{ font: '500 12.5px/1.3 var(--font-ui)', color: 'var(--baj-text-mute)', marginTop: 3 }}>{items.length} document{items.length > 1 ? 's' : ''} on file</div>
              </div>
              <button onClick={onClose} style={{ background: 'var(--baj-surface-2)', border: 0, borderRadius: 99, width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', color: 'var(--baj-text-mute)' }}><Icon.close width={16} height={16} /></button>
            </div>
          </div>
          <div style={{ padding: '12px 20px 26px', overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 9 }}>
            {items.map((it, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 13px', borderRadius: 12, background: '#fff', border: '1px solid var(--baj-line)' }}>
                <span style={{ width: 38, height: 38, borderRadius: 9, flex: '0 0 auto', display: 'flex', alignItems: 'center', justifyContent: 'center', background: it.kind === 'request' ? 'var(--baj-blue-tint)' : 'var(--baj-surface-2)', color: it.kind === 'request' ? 'var(--baj-blue)' : 'var(--baj-text-mute)' }}><Icon.doc width={18} height={18} /></span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ font: '700 13px/1.2 var(--font-ui)', color: 'var(--baj-text)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{it.name}</div>
                  <div style={{ font: '500 11px/1.3 var(--font-ui)', color: 'var(--baj-text-mute)', marginTop: 3, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{it.meta} · {it.size}</div>
                </div>
                <span style={{ color: 'var(--baj-blue)', flex: '0 0 auto' }}><Icon.chevR width={16} height={16} /></span>
              </div>
            ))}
            <button style={{ marginTop: 5, width: '100%', padding: '13px 0', border: '1px dashed var(--baj-line)', borderRadius: 12, background: 'transparent', cursor: 'pointer', color: 'var(--baj-blue)', font: '700 12.5px/1 var(--font-ui)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 7 }}><Icon.plus width={15} height={15} />Upload a document</button>
          </div>
        </>
      )}
    </Sheet>
  );
}

Object.assign(window, {
  StatusBar, PhoneShell, TabBar, StatusPill, StatusDot, DeltaTag, RankBadge,
  SpreadBar, CompetitorLadder, Sheet, CompetitorSheet, QuoteSheet, QuoteEditSheet, MapPanel, MapGraphic, LegendSheet,
  AttachmentsSheet, attachmentsFor,
});
