const { useState, useEffect, useRef } = React;
const L = window.L;

/* ─── SwipeableItem: 左滑露出刪除鈕（iOS Mail 風格） ─── */
function SwipeableItem({ opened, onOpen, onClose, onDelete, children }) {
  const drag = useRef({ x:0, y:0, locked:null, dx:0, start:0 });
  const [tempSlide, setTempSlide] = useState(null);
  const baseSlide = opened ? -80 : 0;
  const x = tempSlide !== null ? tempSlide : baseSlide;

  const ts = (e) => {
    const t = e.touches[0];
    drag.current = { x:t.clientX, y:t.clientY, locked:null, dx:0, start:baseSlide };
  };
  const tm = (e) => {
    const t = e.touches[0];
    const d = drag.current;
    const dx = t.clientX - d.x;
    const dy = t.clientY - d.y;
    if (d.locked === null) {
      if (Math.abs(dx) > 8 || Math.abs(dy) > 8) {
        d.locked = Math.abs(dx) > Math.abs(dy) ? 'h' : 'v';
      }
    }
    if (d.locked === 'h') {
      d.dx = dx;
      setTempSlide(Math.max(-80, Math.min(0, d.start + dx)));
    }
  };
  const te = () => {
    const d = drag.current;
    if (d.locked === 'h') {
      if (d.start + d.dx < -40) onOpen(); else onClose();
    } else if (d.locked === null && opened) {
      // pure tap on opened card → close
      onClose();
    }
    setTempSlide(null);
  };

  return (
    <div style={{position:'relative',overflow:'hidden',borderRadius:16,boxShadow:'0 1px 6px rgba(0,0,0,0.05)'}}>
      <div style={{position:'absolute',inset:0,display:'flex',justifyContent:'flex-end'}}>
        <button onClick={onDelete} style={{
          background:'#EF4444',color:'#fff',border:'none',width:80,
          fontFamily:'Poppins',fontSize:13,fontWeight:700,cursor:'pointer',
          display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',gap:3
        }}>
          <i className="ri-delete-bin-line" style={{fontSize:18}}></i>
          <span>刪除</span>
        </button>
      </div>
      <div onTouchStart={ts} onTouchMove={tm} onTouchEnd={te}
           style={{transform:`translateX(${x}px)`,transition:tempSlide===null?'transform 0.22s':'none',background:'transparent',position:'relative'}}>
        {children}
      </div>
    </div>
  );
}

/* ─── LocationPicker: Nominatim 搜尋 + Leaflet 迷你地圖（可拖大頭針） ─── */
const DEFAULT_LAT = 21.0285, DEFAULT_LNG = 105.8516;
const hasCoords = (lat, lng) => Number.isFinite(Number(lat)) && Number.isFinite(Number(lng));

function LocationPicker({ form, set }) {
  const mapDiv    = useRef(null);
  const mapInst   = useRef(null);
  const markerInst= useRef(null);
  const wrapRef   = useRef(null);
  const debounceRef = useRef(null);

  const [q,         setQ]        = useState(form.location || '');
  const [results,   setResults]  = useState([]);
  const [searching, setSearching]= useState(false);
  const [geocoded,  setGeocoded] = useState(hasCoords(form.lat, form.lng));
  const mapLat = hasCoords(form.lat, form.lng) ? Number(form.lat) : DEFAULT_LAT;
  const mapLng = hasCoords(form.lat, form.lng) ? Number(form.lng) : DEFAULT_LNG;

  // Init map once
  useEffect(() => {
    if (!mapDiv.current || !L) return;
    const m = L.map(mapDiv.current, { zoomControl:false, attributionControl:false })
      .setView([mapLat, mapLng], 14);
    L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom:19 }).addTo(m);
    const mk = L.marker([mapLat, mapLng], { draggable:true }).addTo(m);
    mk.on('dragend', () => {
      const ll = mk.getLatLng();
      set('lat', +ll.lat.toFixed(6));
      set('lng', +ll.lng.toFixed(6));
      setGeocoded(true);
    });
    m.on('click', (e) => {
      mk.setLatLng(e.latlng);
      set('lat', +e.latlng.lat.toFixed(6));
      set('lng', +e.latlng.lng.toFixed(6));
      setGeocoded(true);
    });
    mapInst.current  = m;
    markerInst.current = mk;
    setTimeout(() => m.invalidateSize(), 120);
    return () => { m.remove(); mapInst.current = null; markerInst.current = null; };
  }, []);

  // Sync marker when lat/lng changes (e.g., after pick)
  useEffect(() => {
    if (!markerInst.current || !mapInst.current) return;
    if (!hasCoords(form.lat, form.lng)) return;
    markerInst.current.setLatLng([Number(form.lat), Number(form.lng)]);
    mapInst.current.setView([Number(form.lat), Number(form.lng)]);
  }, [form.lat, form.lng]);

  // Two-stage Nominatim search with Vietnamese abbreviation expansion
  const doSearch = async (raw) => {
    const expanded = raw
      .replace(/\b\d{5,6}\b/g, '')   // strip postal codes
      .replace(/\bTP\.\s*/gi,  'Thành phố ')
      .replace(/\bQ\.\s*/gi,   'Quận ')
      .replace(/\bPh\.\s*/gi,  'Phường ')
      .replace(/\bP\.\s*/gi,   'Phố ')
      .replace(/\bTT\.\s*/gi,  'Thị trấn ')
      .replace(/\s+/g, ' ').trim();

    if (!expanded || expanded.length < 2) return [];

    const base = 'https://nominatim.openstreetmap.org/search?format=json&limit=6&countrycodes=vn&accept-language=vi,en';
    const cjkStripped = expanded.replace(/[一-鿿぀-ヿ＀-￯]/g, ' ').replace(/\s+/g, ' ').trim();
    const commaShort = expanded.split(',').slice(0, 2).join(',').trim();
    const candidates = [...new Set([
      expanded,
      `${expanded}, Hanoi, Vietnam`,
      commaShort,
      cjkStripped,
      cjkStripped && `${cjkStripped}, Hanoi, Vietnam`,
    ].filter(q => q && q.length >= 2))];

    try {
      for (const q of candidates) {
        const arr = await fetch(`${base}&q=${encodeURIComponent(q)}`).then(r => r.json());
        if (Array.isArray(arr) && arr.length > 0) return arr;
      }
    } catch {}
    return [];
  };

  const onQChange = (v) => {
    setQ(v);
    set('location', v);
    set('lat', null);
    set('lng', null);
    setGeocoded(false);
    setResults([]);
    clearTimeout(debounceRef.current);
    if (!v || v.length < 2) { setSearching(false); return; }
    setSearching(true);
    debounceRef.current = setTimeout(async () => {
      const arr = await doSearch(v);
      setResults(arr);
      setSearching(false);
    }, 500);
  };

  const pick = (r) => {
    const lat  = +parseFloat(r.lat).toFixed(6), lng = +parseFloat(r.lon).toFixed(6);
    const name = (r.display_name || '').split(',').slice(0, 2).join(', ');
    set('lat', lat); set('lng', lng); set('location', name);
    setQ(name); setResults([]); setGeocoded(true);
  };

  // Scroll input into view when keyboard opens on mobile
  const onFocus = () => setTimeout(() => wrapRef.current?.scrollIntoView({ behavior:'smooth', block:'nearest' }), 300);

  const borderColor = geocoded ? '#10B981' : '#E5E7EB';

  return (
    <div>
      <div ref={wrapRef}>
        <div style={{position:'relative'}}>
          <input type="text" value={q}
            onChange={e => onQChange(e.target.value)}
            onFocus={onFocus}
            placeholder="搜尋地點名稱或地址..."
            style={{
              width:'100%', padding:'10px 36px 10px 14px',
              border:`1.5px solid ${borderColor}`,
              background: geocoded ? '#F0FDF4' : '#fff',
              borderRadius:12, fontFamily:'Poppins', boxSizing:'border-box', outline:'none'
            }}/>
          <i className={searching ? 'ri-loader-4-line' : geocoded ? 'ri-map-pin-fill' : 'ri-search-line'}
             style={{
               position:'absolute', right:12, top:'50%', transform:'translateY(-50%)',
               color: geocoded ? '#10B981' : '#9CA3AF', fontSize:16,
               animation: searching ? 'spin 1s linear infinite' : 'none'
             }}></i>
        </div>

        {/* 結果列表：inline 排列（非 absolute），避免手機鍵盤遮住 */}
        {results.length > 0 && (
          <div style={{
            background:'#fff', border:'1px solid #E5E7EB', borderRadius:12,
            marginTop:4, maxHeight:180, overflowY:'auto',
            boxShadow:'0 4px 16px rgba(0,0,0,0.10)'
          }}>
            {results.map((r,i) => (
              <button key={i}
                onMouseDown={e => e.preventDefault()} // prevent input blur before click
                onClick={() => pick(r)}
                style={{
                  display:'block', width:'100%', textAlign:'left',
                  background:'none', border:'none', cursor:'pointer',
                  padding:'10px 14px', fontSize:12.5, fontFamily:'Poppins',
                  borderBottom: i < results.length-1 ? '1px solid #F3F4F6' : 'none',
                  color:'#1C1C1E', lineHeight:1.4
                }}>
                <i className="ri-map-pin-2-line" style={{color:'#9CA3AF', marginRight:6}}></i>
                {r.display_name}
              </button>
            ))}
          </div>
        )}
      </div>

      <div ref={mapDiv} style={{height:150, borderRadius:12, marginTop:8, overflow:'hidden', border:`1px solid ${borderColor}`}}/>
      <div style={{fontSize:11, color:geocoded?'#10B981':'#9CA3AF', marginTop:5, display:'flex', alignItems:'center', gap:4}}>
        <i className={geocoded ? 'ri-checkbox-circle-line' : 'ri-information-line'}></i>
        {geocoded ? '已定位 · 可拖曳大頭針微調' : '搜尋後點選結果即可定位，或直接拖曳大頭針'}
      </div>
    </div>
  );
}

const TYPE_CFG = {
  transport:     { color:'#3B82F6', label:'交通', icon:'ri-flight-takeoff-line' },
  hotel:         { color:'#8B5CF6', label:'住宿', icon:'ri-hotel-line' },
  food:          { color:'#F5841E', label:'餐廳', icon:'ri-restaurant-2-line' },
  attraction:    { color:'#10B981', label:'景點', icon:'ri-ancient-gate-line' },
  shopping:      { color:'#EC4899', label:'購物', icon:'ri-shopping-bag-2-line' },
  entertainment: { color:'#F59E0B', label:'娛樂', icon:'ri-film-line' },
};
window.TYPE_CFG = TYPE_CFG;

function EditItemModal({ item, dayIdx, onSave, onDelete, onClose, accent }) {
  const isNew = !item?.id;
  const [form, setForm] = useState({
    time: item?.time||'09:00', title: item?.title||'',
    type: item?.type||'attraction', location: item?.location||'',
    note: item?.note||'',
    lat: hasCoords(item?.lat, item?.lng) ? Number(item.lat) : null,
    lng: hasCoords(item?.lat, item?.lng) ? Number(item.lng) : null,
  });
  const [err, setErr] = useState({ field:'', msg:'' });
  const set = (k,v) => {
    if (err.msg) setErr({ field:'', msg:'' });
    setForm(p=>({...p,[k]:v}));
  };

  const tryStop = (e) => e.stopPropagation();
  const handleSave = () => {
    if (!form.title.trim()) {
      setErr({ field:'title', msg:'行程名稱必填' });
      return;
    }
    if (form.location.trim() && !hasCoords(form.lat, form.lng)) {
      setErr({ field:'location', msg:'請先從搜尋結果選擇地點，或拖曳地圖大頭針完成定位' });
      return;
    }
    onSave(dayIdx, {
      ...form,
      title: form.title.trim(),
      location: form.location.trim(),
      note: form.note.trim(),
      lat: hasCoords(form.lat, form.lng) ? Number(form.lat) : null,
      lng: hasCoords(form.lat, form.lng) ? Number(form.lng) : null,
    }, item?.id);
    onClose();
  };

  return (
    <div onClick={onClose} style={{position:'absolute',inset:0,background:'rgba(0,0,0,0.55)',zIndex:200,display:'flex',alignItems:'flex-end'}}>
      <div onClick={tryStop} style={{background:'#fff',borderRadius:'28px 28px 0 0',padding:'20px 20px calc(96px + env(safe-area-inset-bottom))',width:'100%',maxHeight:'92%',overflowY:'auto'}}>
        <div style={{width:36,height:4,background:'#E5E7EB',borderRadius:4,margin:'0 auto 18px'}}/>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:18}}>
          <span style={{fontSize:18,fontWeight:700,display:'flex',alignItems:'center',gap:7}}><i className={isNew?'ri-add-circle-line':'ri-edit-line'}></i>{isNew?'新增行程':'編輯行程'}</span>
          <button onClick={onClose} style={{background:'#F3F4F6',border:'none',borderRadius:10,width:32,height:32,cursor:'pointer',display:'flex',alignItems:'center',justifyContent:'center'}}><i className="ri-close-line" style={{fontSize:16}}></i></button>
        </div>

        {/* Time */}
        <div style={{marginBottom:13}}>
          <div style={{fontSize:12,color:'#6B7280',marginBottom:4}}>時間</div>
          <input type="time" value={form.time} onChange={e=>set('time',e.target.value)}
            style={{width:'100%',padding:'10px 14px',border:'1.5px solid #E5E7EB',borderRadius:12,fontFamily:'Poppins',boxSizing:'border-box',outline:'none'}}/>
        </div>

        {/* Title */}
        <div style={{marginBottom:13}}>
          <div style={{fontSize:12,color:'#6B7280',marginBottom:4}}>行程名稱 <span style={{color:'#EF4444'}}>*</span></div>
          <input type="text" value={form.title}
            onChange={e=>set('title',e.target.value)}
            placeholder="輸入行程名稱..."
            style={{width:'100%',padding:'10px 14px',border:`1.5px solid ${err.field==='title'?'#EF4444':'#E5E7EB'}`,borderRadius:12,fontFamily:'Poppins',boxSizing:'border-box',outline:'none'}}/>
          {err.field==='title' && <div style={{fontSize:11,color:'#EF4444',marginTop:4}}><i className="ri-error-warning-line"></i> {err.msg}</div>}
        </div>

        {/* Type chips */}
        <div style={{marginBottom:13}}>
          <div style={{fontSize:12,color:'#6B7280',marginBottom:6}}>類型</div>
          <div style={{display:'flex',flexWrap:'wrap',gap:7}}>
            {Object.entries(TYPE_CFG).map(([key,cfg])=>(
              <button key={key} onClick={()=>set('type',key)} style={{
                background:form.type===key?cfg.color:'#F3F4F6',
                color:form.type===key?'#fff':'#6B7280',
                border:'none',borderRadius:20,padding:'6px 13px',fontSize:12.5,cursor:'pointer',
                fontWeight:form.type===key?600:400,fontFamily:'Poppins',transition:'all 0.15s'
              }}><i className={cfg.icon}></i>{' '}{cfg.label}</button>
            ))}
          </div>
        </div>

        {/* Location (search + mini map) */}
        <div style={{marginBottom:13}}>
          <div style={{fontSize:12,color:'#6B7280',marginBottom:4}}>地點</div>
          <LocationPicker form={form} set={set}/>
          {err.field==='location' && <div style={{fontSize:11,color:'#EF4444',marginTop:5}}><i className="ri-error-warning-line"></i> {err.msg}</div>}
        </div>

        {/* Note */}
        <div style={{marginBottom:20}}>
          <div style={{fontSize:12,color:'#6B7280',marginBottom:4}}>備註</div>
          <textarea value={form.note} onChange={e=>set('note',e.target.value)} placeholder="備註..."
            style={{width:'100%',padding:'10px 14px',border:'1.5px solid #E5E7EB',borderRadius:12,fontFamily:'Poppins',resize:'none',height:64,boxSizing:'border-box',outline:'none'}}/>
        </div>

        <div style={{display:'flex',gap:10}}>
          {!isNew&&(
            <button onClick={()=>{onDelete(dayIdx,item.id);onClose();}} style={{
              flex:1,padding:'13px',background:'#FEE2E2',color:'#EF4444',border:'none',
              borderRadius:16,fontWeight:600,cursor:'pointer',fontSize:14,fontFamily:'Poppins'
            }}><i className="ri-delete-bin-line"></i>{' 刪除'}</button>
          )}
          <button onClick={handleSave} style={{
            flex:2,padding:'13px',background:'#1C1C1E',color:'#fff',border:'none',
            borderRadius:16,fontWeight:700,cursor:'pointer',fontSize:14,fontFamily:'Poppins'
          }}>儲存</button>
        </div>
      </div>
    </div>
  );
}

function ItineraryScreen({ days, setDays, activeDay, setActiveDay, accent }) {
  const [modal, setModal] = useState(null);
  const [tipsOpen, setTipsOpen] = useState(false);
  const [swipedId, setSwipedId] = useState(null);
  const today = days[activeDay];

  const listRef = useRef(null);
  const activeDayRef = useRef(activeDay);
  useEffect(() => { activeDayRef.current = activeDay; }, [activeDay]);

  // Close any open swipe when switching days
  useEffect(() => { setSwipedId(null); }, [activeDay]);

  // Initialize SortableJS once; onEnd reorders the active day's items
  useEffect(() => {
    if (!listRef.current || !window.Sortable) return;
    const s = window.Sortable.create(listRef.current, {
      handle: '.drag-handle',
      draggable: '[data-itin-item]',
      animation: 180,
      ghostClass: 'sortable-ghost',
      chosenClass: 'sortable-chosen',
      dragClass: 'sortable-drag',
      forceFallback: true,
      fallbackTolerance: 5,
      scroll: true,
      bubbleScroll: true,
      onStart: () => setSwipedId(null),
      onEnd: (evt) => {
        const { oldIndex, newIndex } = evt;
        if (oldIndex == null || newIndex == null || oldIndex === newIndex) return;
        const di = activeDayRef.current;
        setDays(prev => prev.map((d, idx) => {
          if (idx !== di) return d;
          const items = [...d.items];
          const [moved] = items.splice(oldIndex, 1);
          items.splice(newIndex, 0, moved);
          return { ...d, items };
        }));
      },
    });
    return () => s.destroy();
  }, []);

  const handleSave = (dayIdx, form, existingId) => {
    setDays(prev => prev.map((d,di) => {
      if (di!==dayIdx) return d;
      let items = existingId
        ? d.items.map(it => it.id===existingId ? {...it,...form} : it)
        : [...d.items, {...form, id:Date.now()}];
      // 按時間排序（HH:MM 字串比較即可正確排序）
      items = items.slice().sort((a, b) => a.time.localeCompare(b.time));
      return {...d, items};
    }));
  };

  const handleDelete = (dayIdx, id) => {
    setDays(prev => prev.map((d,di) => di!==dayIdx ? d : {...d,items:d.items.filter(it=>it.id!==id)}));
  };

  return (
    <div style={{height:'100%',display:'flex',flexDirection:'column',background:'#F5F5F7',position:'relative'}}>
      {/* Header */}
      <div style={{background:'#fff',padding:'16px 20px 0',borderBottom:'1px solid #F0F0F0'}}>
        <div style={{fontSize:20,fontWeight:700,color:'#1C1C1E',marginBottom:12,display:'flex',alignItems:'center',gap:8}}><i className="ri-route-line"></i>行程規劃</div>
        <div style={{display:'grid',gridTemplateColumns:`repeat(${days.length},1fr)`,gap:6,paddingBottom:12}}>
          {days.map((day,idx)=>{
            const d = new Date(day.date+'T12:00:00');
            const isActive = idx===activeDay;
            return (
              <button key={day.id} onClick={()=>setActiveDay(idx)} style={{
                background:isActive?'#1C1C1E':'#F3F4F6',
                color:isActive?'#fff':'#6B7280',border:'none',borderRadius:14,
                padding:'8px 4px',cursor:'pointer',fontFamily:'Poppins',transition:'all 0.2s',textAlign:'center',minWidth:0
              }}>
                <div style={{fontSize:10,opacity:0.7,marginBottom:1}}>Day {idx+1}</div>
                <div style={{fontSize:13,fontWeight:700}}>{d.getMonth()+1}/{d.getDate()}</div>
                <div style={{fontSize:9,opacity:0.6,marginTop:1}}>{day.items.length} 項</div>
              </button>
            );
          })}
        </div>
      </div>

      {/* Day label */}
      <div style={{padding:'8px 20px 4px',background:'#F5F5F7'}}>
        <div style={{fontSize:12,color:'#6B7280'}}>
          {today.label} · {new Date(today.date+'T12:00:00').toLocaleDateString('zh-TW',{month:'long',day:'numeric',weekday:'short'})}
          <span style={{marginLeft:8,fontSize:11,color:'#9CA3AF'}}>{today.items.length} 個行程</span>
        </div>
      </div>

      {/* Lodging */}
      {today.lodging && (
        <div style={{padding:'4px 16px 0',background:'#F5F5F7'}}>
          <div style={{background:'#fff',borderRadius:14,padding:'10px 14px',display:'flex',alignItems:'center',gap:10,boxShadow:'0 1px 6px rgba(0,0,0,0.05)'}}>
            <div style={{width:32,height:32,borderRadius:10,background:'#8B5CF615',color:'#8B5CF6',display:'flex',alignItems:'center',justifyContent:'center',flexShrink:0,fontSize:16}}>
              <i className="ri-hotel-line"></i>
            </div>
            <div style={{flex:1,minWidth:0}}>
              <div style={{fontSize:11,color:'#9CA3AF',marginBottom:1}}>今晚住</div>
              <div style={{fontSize:13,fontWeight:700,color:'#1C1C1E',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{today.lodging.name}</div>
              <div style={{fontSize:11,color:'#6B7280',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{today.lodging.addr}</div>
            </div>
          </div>
        </div>
      )}

      {/* Day Tips — collapsible */}
      {today.tips && today.tips.length>0 && (
        <div style={{padding:'8px 16px 0',background:'#F5F5F7'}}>
          <div style={{background:'#FFF7ED',borderRadius:14,border:`1px solid ${accent}25`,overflow:'hidden'}}>
            <button onClick={()=>setTipsOpen(v=>!v)} style={{
              width:'100%',background:'none',border:'none',cursor:'pointer',
              padding:'8px 14px',display:'flex',alignItems:'center',justifyContent:'space-between',
              fontFamily:'Poppins'
            }}>
              <span style={{display:'flex',alignItems:'center',gap:6}}>
                <i className="ri-lightbulb-flash-line" style={{color:accent,fontSize:14}}></i>
                <span style={{fontSize:11,fontWeight:700,color:accent}}>本日提醒 · {today.tips.length} 則</span>
              </span>
              <i className={tipsOpen?'ri-arrow-up-s-line':'ri-arrow-down-s-line'} style={{color:accent,fontSize:16}}></i>
            </button>
            {tipsOpen && (
              <div style={{padding:'0 14px 10px'}}>
                {today.tips.map((tip,i)=>(
                  <div key={i} style={{display:'flex',gap:6,fontSize:11.5,color:'#4B5563',lineHeight:1.6,paddingTop:i===0?2:3}}>
                    <span style={{color:accent,flexShrink:0}}>·</span>
                    <span style={{flex:1}}>{tip}</span>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      )}

      {/* Items list */}
      <div ref={listRef} style={{flex:1,overflowY:'auto',padding:'4px 16px 100px'}}>
        {today.items.length===0&&(
          <div style={{textAlign:'center',padding:'40px 20px',color:'#9CA3AF'}}>
            <i className="ri-file-list-3-line" style={{fontSize:36,marginBottom:8,display:'block',color:'#D1D5DB'}}></i>
            <div>尚無行程，點擊下方新增</div>
          </div>
        )}
        {today.items.map((item,idx)=>{
          const cfg = TYPE_CFG[item.type]||TYPE_CFG.attraction;
          const isLast = idx===today.items.length-1;
          return (
            <div key={item.id} data-itin-item="" style={{display:'flex',gap:10}}>
              <div style={{display:'flex',flexDirection:'column',alignItems:'center',width:28,flexShrink:0,paddingTop:10}}>
                <div style={{width:28,height:28,borderRadius:'50%',background:cfg.color+'18',display:'flex',alignItems:'center',justifyContent:'center',fontSize:13,flexShrink:0,border:`1.5px solid ${cfg.color}30`,color:cfg.color}}><i className={cfg.icon}></i></div>
                {!isLast&&<div style={{width:2,flex:1,background:'#E5E7EB',margin:'4px 0',minHeight:20}}/>}
              </div>
              <div style={{flex:1,paddingBottom:isLast?0:10,paddingTop:4,minWidth:0}}>
                <SwipeableItem
                  opened={swipedId===item.id}
                  onOpen={()=>setSwipedId(item.id)}
                  onClose={()=>setSwipedId(null)}
                  onDelete={()=>{handleDelete(activeDay,item.id);setSwipedId(null);}}
                >
                  <div style={{background:'#fff',borderRadius:16,padding:'12px 14px'}}>
                    <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:6}}>
                      <div style={{flex:1,minWidth:0}}>
                        <div style={{display:'flex',alignItems:'center',gap:7,marginBottom:4}}>
                          <span style={{fontSize:11,color:cfg.color,fontWeight:600,background:cfg.color+'15',borderRadius:10,padding:'2px 8px'}}>{cfg.label}</span>
                          <span style={{fontSize:12,color:'#9CA3AF',fontWeight:600}}>{item.time}</span>
                        </div>
                        <div style={{fontSize:15,fontWeight:700,color:'#1C1C1E',marginBottom:item.location?4:0}}>{item.title}</div>
                        {item.location&&<div style={{fontSize:12,color:'#6B7280',display:'flex',alignItems:'center',gap:3}}><i className="ri-map-pin-2-fill"></i>{item.location}</div>}
                        {item.note&&<div style={{fontSize:11,color:'#9CA3AF',marginTop:4,fontStyle:'italic'}}>{item.note}</div>}
                      </div>
                      <div style={{display:'flex',gap:4,alignItems:'flex-start',flexShrink:0}}>
                        <button className="drag-handle" aria-label="拖曳排序" style={{
                          background:'transparent',border:'none',width:30,height:32,
                          display:'flex',alignItems:'center',justifyContent:'center',
                          color:'#C7CACF',fontSize:18,padding:0
                        }}><i className="ri-draggable"></i></button>
                        <button onClick={()=>setModal({item,dayIdx:activeDay})} aria-label="編輯" style={{
                          background:'#F3F4F6',border:'none',borderRadius:10,width:32,height:32,
                          cursor:'pointer',display:'flex',alignItems:'center',justifyContent:'center'
                        }}><i className="ri-edit-line" style={{fontSize:14}}></i></button>
                      </div>
                    </div>
                  </div>
                </SwipeableItem>
              </div>
            </div>
          );
        })}
      </div>

      {/* FAB — 新增行程 */}
      <button onClick={()=>setModal({item:null,dayIdx:activeDay})} aria-label="新增行程" style={{
        position:'absolute',right:18,bottom:'calc(max(10px, env(safe-area-inset-bottom)) + 76px)',zIndex:90,
        width:56,height:56,borderRadius:'50%',
        background:accent,color:'#fff',border:'none',cursor:'pointer',
        boxShadow:`0 8px 24px ${accent}55, 0 2px 6px rgba(0,0,0,0.18)`,
        display:'flex',alignItems:'center',justifyContent:'center',
        fontSize:28,fontWeight:300,lineHeight:1,fontFamily:'Poppins',paddingBottom:3
      }}>+</button>

      {modal&&(
        <EditItemModal
          item={modal.item} dayIdx={modal.dayIdx} accent={accent}
          onSave={handleSave} onDelete={handleDelete} onClose={()=>setModal(null)}
        />
      )}
    </div>
  );
}

window.ItineraryScreen = ItineraryScreen;
