// Park Detail — ported (session S-D). getParkDetail() + biome templates
// deleted; real payload via getPark(slug). The localStorage-per-park plan is
// deleted entirely; the "Trip" tab now reads/writes real Supabase rows via
// getCurrentTrip/addTripItem/toggleTripItemDone/removeTripItem/tripTotals.
//
// HONEST REDESIGN, not a straight port: the prototype's Cost tab showed
// fabricated low/mid/high per-day budget tiers from BIOME_TEMPLATES. Real
// parks_data has no such structured budget data — only a real entrance fee
// string and an unstructured stay blurb ("...from $34 a night."). Rather
// than invent budget tiers, the Cost tab now shows the real entrance fee,
// a parsed lodging price when one can honestly be read from the stay's own
// blurb, and your trip's real running totals. Where the source doesn't
// support a number, the tab says so instead of guessing.

function parsePricePerNight(blurb) {
  const m = (blurb || '').match(/\$(\d+(?:\.\d+)?)\s*(?:a|\/)\s*night/i);
  return m ? Number(m[1]) : null;
}

function AddToggle({ on, onClick, size = 28 }) {
  return (
    <button onClick={(e) => { e.stopPropagation(); onClick(); }} title={on ? 'Remove from trip' : 'Add to trip'} style={{
      width: size, height: size, borderRadius: '50%', flexShrink: 0,
      border: '1px solid ' + (on ? 'var(--accent)' : 'var(--line)'),
      background: on ? 'var(--accent)' : 'transparent',
      color: on ? 'var(--bg)' : 'var(--ink-3)',
      cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
      transition: 'all 160ms ease',
    }}>{on ? I.check('var(--bg)') : I.plus()}</button>
  );
}

const SECTION_ORDER = ['do', 'hikes', 'stays', 'gear', 'cost', 'life', 'trip'];
const SECTION_LABELS = { do: 'To Do', hikes: 'Hikes', stays: 'Stays', gear: 'Gear', cost: 'Cost', life: 'Wildlife', trip: 'Trip' };
const reducedMotion = () => typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;

/** One collapsible section. Independent — opening one never closes another
 * (spec §1: force-closing a section above the user's thumb is the single
 * most disorienting accordion failure on mobile). */
function AccordionSection({ sectionKey, label, count, open, onToggle, headerRef, children }) {
  return (
    <div style={{ borderTop: '1px solid var(--line)' }}>
      <button
        ref={headerRef}
        onClick={() => onToggle(sectionKey)}
        aria-expanded={open}
        style={{
          width: '100%', minHeight: 52, padding: '14px 22px', border: 'none', background: 'none',
          cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          textAlign: 'left',
        }}
      >
        <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--ink)', display: 'flex', alignItems: 'center', gap: 8 }}>
          {label}
          {count > 0 && (
            <span style={{ display: 'inline-flex', minWidth: 16, height: 16, padding: '0 4px', borderRadius: 100, background: 'var(--accent)', color: 'var(--bg)', fontSize: 9, alignItems: 'center', justifyContent: 'center' }}>{count}</span>
          )}
        </span>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--ink-2)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
          style={{ transform: open ? 'rotate(90deg)' : 'none', transition: reducedMotion() ? 'none' : 'transform 240ms ease', flexShrink: 0 }}>
          <path d="M9 18l6-6-6-6"/>
        </svg>
      </button>
      <div style={{
        display: 'grid', gridTemplateRows: open ? '1fr' : '0fr',
        transition: reducedMotion() ? 'none' : 'grid-template-rows 240ms ease',
      }}>
        <div style={{ overflow: 'hidden' }}>
          <div style={{ padding: '0 22px 24px' }}>{children}</div>
        </div>
      </div>
    </div>
  );
}

function ParkDetailScreen({ parkSlug, back, persona, openPark, openSection }) {
  const [loading, setLoading] = React.useState(true);
  const [park, setPark] = React.useState(null);
  const [visited, setVisited] = React.useState(false);
  const [trip, setTrip] = React.useState(null);
  const [items, setItems] = React.useState([]);
  const [stampBusy, setStampBusy] = React.useState(false);

  const storageKey = 'fieldbook.sections.' + parkSlug;
  const [openSet, setOpenSet] = React.useState(() => {
    let base;
    try {
      const stored = sessionStorage.getItem(storageKey);
      base = stored ? JSON.parse(stored) : ['do'];
    } catch { base = ['do']; }
    if (openSection && !base.includes(openSection)) base = [...base, openSection];
    return new Set(base);
  });
  const headerRefs = React.useRef({});

  const load = React.useCallback(async () => {
    const [p, visits] = await Promise.all([window.PH.getPark(parkSlug), window.PH.listVisits()]);
    setPark(p);
    setVisited(visits.some(v => v.park_slug === parkSlug));
    const t = await window.PH.getCurrentTrip(parkSlug);
    const { items: its } = await window.PH.getTrip(t.id);
    setTrip(t); setItems(its);
  }, [parkSlug]);

  React.useEffect(() => { (async () => { setLoading(true); await load(); setLoading(false); })(); }, [load]);

  React.useEffect(() => {
    try { sessionStorage.setItem(storageKey, JSON.stringify([...openSet])); } catch {}
  }, [openSet, storageKey]);

  // Deep-link: scroll the requested section into view once the park has loaded.
  React.useEffect(() => {
    if (!openSection || loading) return;
    const el = headerRefs.current[openSection];
    if (el) el.scrollIntoView({ block: 'start', behavior: reducedMotion() ? 'auto' : 'smooth' });
  }, [openSection, loading]);

  const toggleSection = (key) => {
    setOpenSet(prev => {
      const next = new Set(prev);
      const wasOpen = next.has(key);
      if (wasOpen) next.delete(key); else next.add(key);
      // scroll the just-opened section under the sticky mini-header
      if (!wasOpen) {
        requestAnimationFrame(() => {
          const el = headerRefs.current[key];
          if (el) el.scrollIntoView({ block: 'start', behavior: reducedMotion() ? 'auto' : 'smooth' });
        });
      }
      return next;
    });
  };

  const itemKeySet = React.useMemo(() => {
    const s = new Set();
    for (const it of items) s.add(it.category + ':' + it.item_key);
    return s;
  }, [items]);
  const inPlan = (cat, itemKey) => itemKeySet.has(cat + ':' + itemKey);

  const toggleItem = async (cat, itemKey, title, meta) => {
    const existing = items.find(it => it.category === cat && it.item_key === itemKey);
    if (existing) {
      await window.PH.removeTripItem(existing.id);
      setItems(prev => prev.filter(it => it.id !== existing.id));
    } else {
      const row = await window.PH.addTripItem(trip.id, { category: cat, item_key: itemKey, title, meta: meta || {} });
      setItems(prev => [...prev, row]);
    }
  };

  const toggleStamp = async () => {
    setStampBusy(true);
    try {
      if (visited) { await window.PH.unstampPark(parkSlug); setVisited(false); }
      else {
        const res = await window.PH.stampPark(parkSlug);
        setVisited(true);
        if (res.newBadges.length) alert('Badge earned: ' + res.newBadges.map(b => b.badge_key).join(', '));
      }
    } finally { setStampBusy(false); }
  };

  if (loading || !park) {
    return <div style={{ background: 'var(--bg)', minHeight: '100%', padding: '58px 22px' }}>
      <button onClick={back} style={{ border: 'none', background: 'none', cursor: 'pointer', color: 'var(--ink-2)', display: 'flex', alignItems: 'center', gap: 6, padding: 0 }}>{I.back()} <Caps s={10}>Back</Caps></button>
      <div style={{ marginTop: 30, fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: 'var(--ink-3)', letterSpacing: '0.1em', textTransform: 'uppercase' }}>Loading…</div>
    </div>;
  }

  const totals = window.PH.tripTotals(items);
  const planCount = items.length;
  const counts = { do: park.do.length, hikes: park.hikes.length, stays: park.stays.length, gear: park.gear.length, cost: 0, life: park.wildlife.length, trip: planCount };

  const sectionBody = (key) => {
    switch (key) {
      case 'do': return <TabDo park={park} inPlan={inPlan} toggle={toggleItem}/>;
      case 'hikes': return <TabHikes park={park} inPlan={inPlan} toggle={toggleItem}/>;
      case 'stays': return <TabStays park={park} inPlan={inPlan} toggle={toggleItem}/>;
      case 'gear': return <TabGear park={park} inPlan={inPlan} toggle={toggleItem}/>;
      case 'cost': return <TabCost park={park} items={items} totals={totals}/>;
      case 'life': return <TabLife park={park} inPlan={inPlan} toggle={toggleItem}/>;
      case 'trip': return <TabTrip park={park} items={items} totals={totals} toggle={toggleItem} trip={trip} setTrip={setTrip}/>;
      default: return null;
    }
  };

  return (
    <div style={{ background: 'var(--bg)', minHeight: '100%', paddingBottom: 110 }}>

      <div style={{ position: 'relative', height: 420, background: 'var(--ink)', overflow: 'hidden' }}>
        {park.photos && park.photos.hero && (
          <img src={park.photos.hero} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', filter: 'brightness(0.78)' }}/>
        )}
        <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, rgba(30,24,20,0.35) 0%, transparent 30%, transparent 55%, rgba(30,24,20,0.9) 100%)' }}/>

        <div style={{ position: 'absolute', top: 58, left: 16, right: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center', zIndex: 5 }}>
          <button onClick={back} style={{ width: 38, height: 38, borderRadius: '50%', border: '1px solid rgba(242,236,223,0.35)', background: 'rgba(30,24,20,0.35)', backdropFilter: 'blur(8px)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', color: '#F2ECDF' }}>{I.back('#F2ECDF')}</button>
          <button onClick={toggleStamp} disabled={stampBusy} style={{
            padding: '9px 16px', borderRadius: 100, border: '1px solid rgba(242,236,223,0.5)',
            background: visited ? 'var(--accent)' : 'rgba(30,24,20,0.35)', backdropFilter: 'blur(8px)',
            cursor: stampBusy ? 'default' : 'pointer', color: '#F2ECDF',
            fontFamily: 'JetBrains Mono, monospace', fontSize: 10, letterSpacing: '0.1em', textTransform: 'uppercase',
            display: 'flex', alignItems: 'center', gap: 6, opacity: stampBusy ? 0.6 : 1,
          }}>{visited ? (<>{I.check('#F2ECDF')} Stamped</>) : 'Stamp this park'}</button>
        </div>

        <div style={{ position: 'absolute', top: 110, left: 22, right: 22, display: 'flex', justifyContent: 'space-between', color: '#F2ECDF', zIndex: 4 }}>
          <Caps s={9} c="rgba(242,236,223,0.75)">{park.state}</Caps>
          <Caps s={9} c="rgba(242,236,223,0.75)">Stamp {String(park.stamp_no).padStart(2, '0')} / 63</Caps>
        </div>

        <div style={{ position: 'absolute', bottom: 22, left: 22, right: 22, color: '#F2ECDF', zIndex: 4 }}>
          <Caps s={10} c="rgba(242,236,223,0.7)">Field Guide №{String(park.stamp_no).padStart(2, '0')}</Caps>
          <h1 style={{ margin: '8px 0 0', fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 54, lineHeight: 0.92, letterSpacing: '-0.03em' }}>{park.name}</h1>
          {park.story_intro && <div style={{ fontFamily: 'DM Sans, sans-serif', fontSize: 15, marginTop: 8, color: 'rgba(242,236,223,0.78)', lineHeight: 1.35 }}>{park.story_intro}</div>}
        </div>
        <CornerMarks c="rgba(242,236,223,0.4)" pad={14} len={14}/>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', padding: '18px 22px', borderBottom: '1px solid var(--line)', gap: 8 }}>
        <Metric n={park.best_window ? park.best_window.split(/[–-]/)[0].trim() : '—'} l="Best time"/>
        <Metric n={park.fee || '—'} l="Entry fee"/>
        <Metric n={park.hikes.length} l="Hikes"/>
        <Metric n={park.wildlife.length} l="Species"/>
      </div>

      <div style={{ padding: '22px 22px 0' }}>
        <ProgressBar pct={Math.min(100, Math.round((planCount / 6) * 100))} label="Trip planning" right={`${planCount} item${planCount === 1 ? '' : 's'} added`} showPct={false} height={6}/>
      </div>

      {park.getting_there && (
        <div style={{ padding: '22px 22px 0' }}>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 18, lineHeight: 1.4, color: 'var(--ink)' }}>{park.getting_there}</div>
        </div>
      )}

      {/* Slim sticky mini-header replaces the old tab strip. Jumps to/opens Trip on tap. */}
      <div style={{
        margin: '20px 0 0', position: 'sticky', top: 0, zIndex: 3, background: 'var(--bg)',
        borderTop: '1px solid var(--line)', borderBottom: '1px solid var(--line)',
        padding: '10px 22px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      }}>
        <span style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 15, color: 'var(--ink)', fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{park.name}</span>
        <button onClick={() => { if (!openSet.has('trip')) toggleSection('trip'); else headerRefs.current.trip?.scrollIntoView({ block: 'start', behavior: reducedMotion() ? 'auto' : 'smooth' }); }} style={{
          border: 'none', borderRadius: 100, background: 'var(--ink)', color: 'var(--bg)', padding: '7px 14px',
          cursor: 'pointer', fontFamily: 'JetBrains Mono, monospace', fontSize: 10, letterSpacing: '0.1em', textTransform: 'uppercase', flexShrink: 0,
        }}>Trip &middot; {planCount}</button>
      </div>

      <div>
        {SECTION_ORDER.map((key) => (
          <AccordionSection
            key={key}
            sectionKey={key}
            label={SECTION_LABELS[key]}
            count={counts[key]}
            open={openSet.has(key)}
            onToggle={toggleSection}
            headerRef={(el) => { headerRefs.current[key] = el; }}
          >
            {sectionBody(key)}
          </AccordionSection>
        ))}
        <div style={{ borderTop: '1px solid var(--line)' }}/>
      </div>
    </div>
  );
}

function TabDo({ park, inPlan, toggle }) {
  return (
    <div>
      <Caps s={10} c="var(--accent)">Essentials</Caps>
      <h3 style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 26, fontWeight: 400, margin: '4px 0 18px', color: 'var(--ink)' }}>Things worth the walk</h3>
      {park.do.map((d, i) => (
        <div key={d.id} style={{ padding: '16px 0', borderTop: '1px solid var(--line)', display: 'grid', gridTemplateColumns: '28px 1fr auto', gap: 12, alignItems: 'center' }}>
          <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: 'var(--ink-3)' }}>№{String(i + 1).padStart(2, '0')}</span>
          <div>
            <Caps s={9} style={{ display: 'block', marginBottom: 2 }}>{d.kind}{d.tag ? ' · ' + d.tag : ''}</Caps>
            <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 19, color: 'var(--ink)', lineHeight: 1.2 }}>{d.title}</div>
            <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 13, color: 'var(--ink-2)', marginTop: 4 }}>{d.blurb}</div>
          </div>
          <AddToggle on={inPlan('do', d.id)} onClick={() => toggle('do', d.id, d.title, { kind: d.kind })}/>
        </div>
      ))}
      <div style={{ borderTop: '1px solid var(--line)' }}/>
    </div>
  );
}

function TabHikes({ park, inPlan, toggle }) {
  const diffColor = (d) => ({
    'Easy': 'var(--olive)', 'Easy–Mod': 'var(--olive)', 'Moderate': 'var(--accent)',
    'Strenuous': '#9c3d13', 'Technical': '#5a1f0c', 'Extreme': '#5a1f0c',
  }[d] || 'var(--ink-2)');
  return (
    <div>
      <Caps s={10} c="var(--accent)">Selected Trails</Caps>
      <h3 style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 26, fontWeight: 400, margin: '4px 0 18px', color: 'var(--ink)' }}>Where the feet go</h3>
      {park.hikes.map((h) => (
        <div key={h.id} style={{ padding: '18px 0', borderTop: '1px solid var(--line)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <div style={{ flex: 1, fontFamily: 'Space Grotesk, sans-serif', fontSize: 20, color: 'var(--ink)', lineHeight: 1.2 }}>{h.title}</div>
            <Caps s={9} c={diffColor(h.difficulty)}>{h.difficulty}</Caps>
            <AddToggle on={inPlan('hike', h.id)} onClick={() => toggle('hike', h.id, h.title, { miles: h.miles, elevation_ft: h.elevation_ft, difficulty: h.difficulty })}/>
          </div>
          <div style={{ display: 'flex', gap: 18, marginTop: 10, flexWrap: 'wrap' }}>
            <div><Caps s={9}>Distance</Caps><div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 18, marginTop: 2 }}>{h.distance}</div></div>
            <div><Caps s={9}>Elevation</Caps><div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 18, marginTop: 2 }}>{h.elevation}</div></div>
            <div><Caps s={9}>Time</Caps><div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 18, marginTop: 2 }}>{h.duration}</div></div>
          </div>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 14, color: 'var(--ink-2)', marginTop: 8, lineHeight: 1.4 }}>{h.blurb}</div>
        </div>
      ))}
      {park.hikes_permit_note && (
        <div style={{ padding: '14px 0 0' }}>
          <Caps s={9} style={{ display: 'block', textTransform: 'none', letterSpacing: 0, color: 'var(--ink-2)' }}>Permits: {park.hikes_permit_note}</Caps>
        </div>
      )}
      <div style={{ borderTop: '1px solid var(--line)', marginTop: 14 }}/>
    </div>
  );
}

function TabStays({ park, inPlan, toggle }) {
  return (
    <div>
      <Caps s={10} c="var(--accent)">Lodging</Caps>
      <h3 style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 26, fontWeight: 400, margin: '4px 0 18px', color: 'var(--ink)' }}>Where to put your head down</h3>
      {park.stays.map((s) => (
        <div key={s.id} style={{ padding: '18px 0', borderTop: '1px solid var(--line)', display: 'grid', gridTemplateColumns: '1fr auto', gap: 12, alignItems: 'center' }}>
          <div>
            <Caps s={9} style={{ textTransform: 'capitalize' }}>{s.kind}</Caps>
            <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 19, color: 'var(--ink)', marginTop: 3, lineHeight: 1.2 }}>{s.title}</div>
            <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 14, color: 'var(--ink-2)', marginTop: 4 }}>{s.blurb}</div>
          </div>
          <AddToggle on={inPlan('stay', s.id)} onClick={() => toggle('stay', s.id, s.title, { kind: s.kind, price_night: parsePricePerNight(s.blurb) })}/>
        </div>
      ))}
      <div style={{ borderTop: '1px solid var(--line)' }}/>
      <Caps s={9} style={{ display: 'block', marginTop: 14, textTransform: 'none', letterSpacing: 0, color: 'var(--ink-3)' }}>More lodging options (campgrounds, cabins, hotels) are on the way.</Caps>
    </div>
  );
}

function TabGear({ park, inPlan, toggle }) {
  return (
    <div>
      <Caps s={10} c="var(--accent)">The Kit</Caps>
      <h3 style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 26, fontWeight: 400, margin: '4px 0 18px', color: 'var(--ink)' }}>What you will need</h3>
      <div style={{ borderTop: '1px solid var(--line)' }}>
        {park.gear.map((g) => (
          <div key={g.id} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '14px 0', borderBottom: '1px solid var(--line)' }}>
            <span style={{ flex: 1, fontFamily: 'Space Grotesk, sans-serif', fontSize: 18, color: 'var(--ink)' }}>{g.title}</span>
            <Caps s={9}>{g.vendor}</Caps>
            <AddToggle on={inPlan('gear', g.id)} onClick={() => toggle('gear', g.id, g.title, { vendor: g.vendor })} size={26}/>
          </div>
        ))}
      </div>
    </div>
  );
}

function TabCost({ park, items, totals }) {
  return (
    <div>
      <Caps s={10} c="var(--accent)">What This Runs</Caps>
      <h3 style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 26, fontWeight: 400, margin: '4px 0 18px', color: 'var(--ink)' }}>Real numbers, not a guess</h3>

      <div style={{ padding: '16px 0', borderTop: '1px solid var(--line)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between' }}>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 20, color: 'var(--ink)' }}>Entrance fee</div>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 22, color: 'var(--ink)' }}>{park.fee || '—'}</div>
        </div>
      </div>

      <div style={{ padding: '16px 0', borderTop: '1px solid var(--line)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between' }}>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 20, color: 'var(--ink)' }}>Lodging (from your trip)</div>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 22, color: 'var(--ink)' }}>{totals.stay_per_night ? '$' + totals.stay_per_night + '/night' : '—'}</div>
        </div>
        {!totals.stay_per_night && <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 13, color: 'var(--ink-2)', marginTop: 4 }}>Add a stay from the Stays tab to see a real nightly cost here.</div>}
      </div>

      <div style={{ padding: '16px 0', borderTop: '1px solid var(--line)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between' }}>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 20, color: 'var(--ink)' }}>Trail miles planned</div>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 22, color: 'var(--ink)' }}>{totals.miles || '—'}</div>
        </div>
      </div>

      <div style={{ borderTop: '1px solid var(--line)' }}/>
      <Caps s={9} style={{ display: 'block', marginTop: 14, textTransform: 'none', letterSpacing: 0 }}>
        Consider the $80 America the Beautiful Annual Pass if you're visiting 3 or more parks this year.
      </Caps>
    </div>
  );
}

function TabLife({ park, inPlan, toggle }) {
  return (
    <div>
      <Caps s={10} c="var(--accent)">Flora & Fauna</Caps>
      <h3 style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 26, fontWeight: 400, margin: '4px 0 18px', color: 'var(--ink)' }}>What lives here</h3>
      {park.wildlife.map((w) => (
        <div key={w.id} style={{ padding: '18px 0', borderTop: '1px solid var(--line)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <div style={{ flex: 1, fontFamily: 'Space Grotesk, sans-serif', fontSize: 22, color: 'var(--ink)', lineHeight: 1.1 }}>{w.title}</div>
            <Caps s={9} style={{ textTransform: 'capitalize' }}>{w.kind}</Caps>
            <AddToggle on={inPlan('wildlife', w.id)} onClick={() => toggle('wildlife', w.id, w.title, { kind: w.kind })}/>
          </div>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 14, color: 'var(--ink-2)', marginTop: 4 }}>{w.blurb}</div>
          <Caps s={9} style={{ display: 'block', marginTop: 8 }}>{w.tag}</Caps>
        </div>
      ))}
      <div style={{ borderTop: '1px solid var(--line)' }}/>
    </div>
  );
}

function itemLabel(it) {
  const parts = [];
  if (it.meta) {
    if (it.meta.miles) parts.push(it.meta.miles + ' mi');
    if (it.meta.elevation_ft) parts.push(it.meta.elevation_ft + '′');
    if (it.meta.difficulty) parts.push(it.meta.difficulty);
    if (it.meta.price_night) parts.push('$' + it.meta.price_night + '/night');
    if (it.meta.vendor) parts.push(it.meta.vendor);
  }
  return parts.join(' · ');
}

function TabTrip({ park, items, totals, toggle, trip, setTrip }) {
  const [goals, setGoals] = React.useState(trip.goals || '');
  const [saving, setSaving] = React.useState(false);
  const [justSaved, setJustSaved] = React.useState(false);
  const saveGoals = async () => {
    setSaving(true);
    try {
      const updated = await window.PH.updateTrip(trip.id, { goals });
      setTrip(updated);
      setJustSaved(true);
      setTimeout(() => setJustSaved(false), 2000);
    } finally { setSaving(false); }
  };

  const groups = { do: 'To do', hike: 'Hikes', stay: 'Stays', gear: 'Pack list', wildlife: 'Wildlife to spot' };

  return (
    <div>
      <Caps s={10} c="var(--accent)">Your Expedition</Caps>
      <h3 style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 26, fontWeight: 400, margin: '4px 0 18px', color: 'var(--ink)' }}>The plan, assembled</h3>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8, padding: '4px 0 20px', borderBottom: '1px solid var(--line)' }}>
        <Metric n={items.length} l="Items"/>
        <Metric n={totals.miles || 0} l="Trail mi"/>
        <Metric n={totals.ascent_ft || 0} l="Ascent′"/>
        <Metric n={totals.stay_per_night ? '$' + totals.stay_per_night : '—'} l="Lodging/nt"/>
      </div>

      <div style={{ padding: '20px 0 0' }}>
        <Caps s={10} c="var(--accent)" style={{ display: 'block', marginBottom: 10 }}>Goals & intentions</Caps>
        <textarea value={goals} onChange={e => setGoals(e.target.value)} placeholder="What do you want out of this trip? e.g. Sunrise from the summit"
          style={{ width: '100%', minHeight: 70, padding: '12px 14px', border: '1px solid var(--line)', background: 'var(--paper)', borderRadius: 2, fontFamily: 'DM Sans, sans-serif', fontSize: 14, color: 'var(--ink)', outline: 'none', resize: 'vertical' }}/>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 8 }}>
          <button onClick={saveGoals} disabled={saving} style={{ padding: '8px 16px', background: 'var(--ink)', color: 'var(--bg)', border: 'none', borderRadius: 100, cursor: saving ? 'default' : 'pointer', fontFamily: 'JetBrains Mono, monospace', fontSize: 10, letterSpacing: '0.1em', textTransform: 'uppercase', opacity: saving ? 0.6 : 1 }}>{saving ? 'Saving…' : 'Save'}</button>
          {justSaved && <Caps s={9} c="var(--accent)">Saved</Caps>}
        </div>
      </div>

      {Object.entries(groups).map(([cat, title]) => {
        const list = items.filter(it => it.category === cat);
        if (!list.length) return null;
        return (
          <div key={cat} style={{ padding: '24px 0 0' }}>
            <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 4 }}>
              <Caps s={10} c="var(--accent)">{title}</Caps>
              <Caps s={9}>{list.length}</Caps>
            </div>
            {list.map((it) => (
              <div key={it.id} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 0', borderTop: '1px solid var(--line)' }}>
                <div style={{ flex: 1 }}>
                  <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 17, color: 'var(--ink)', lineHeight: 1.2 }}>{it.title}</div>
                  {itemLabel(it) && <Caps s={9} style={{ display: 'block', marginTop: 3, textTransform: 'none', letterSpacing: 0 }}>{itemLabel(it)}</Caps>}
                </div>
                <button onClick={() => toggle(it.category, it.item_key)} title="Remove" style={{ width: 26, height: 26, borderRadius: '50%', border: '1px solid var(--line)', background: 'transparent', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--ink-3)', flexShrink: 0 }}>
                  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>
                </button>
              </div>
            ))}
          </div>
        );
      })}

      {items.length === 0 && (
        <div style={{ padding: '28px 0 8px', textAlign: 'center' }}>
          <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontSize: 18, color: 'var(--ink-2)', lineHeight: 1.45, maxWidth: 280, margin: '0 auto' }}>
            Nothing packed yet. Browse the tabs and tap <span style={{ color: 'var(--accent)' }}>+</span> to build your expedition.
          </div>
        </div>
      )}

      <div style={{ borderTop: '1px solid var(--line)', marginTop: 24, paddingTop: 14 }}>
        <Caps s={9} style={{ textTransform: 'none', letterSpacing: 0 }}>Synced to your account · {park.name}</Caps>
      </div>
    </div>
  );
}

Object.assign(window, { ParkDetailScreen });
