import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { createRoot } from 'react-dom/client';

    // ==========================================
    // 🔐 คุยกับ Google Sheets ผ่าน /api/* บน Vercel เท่านั้น
    // URL ของ Apps Script ไม่อยู่ในหน้าเว็บอีกแล้ว (view-source ก็ไม่เจอ)
    // ==========================================
    const API_DATA = '/api/data';
    const API_LOGIN = '/api/login';

    const TOKEN_KEY = 'checkq_admin_token';
    const getToken = () => { try { return localStorage.getItem(TOKEN_KEY); } catch (e) { return null; } };
    const saveToken = (t) => { try { localStorage.setItem(TOKEN_KEY, t); } catch (e) {} };
    const clearToken = () => { try { localStorage.removeItem(TOKEN_KEY); } catch (e) {} };

    const isTokenValid = () => {
      const t = getToken();
      if (!t) return false;
      try {
        const payload = JSON.parse(atob(t.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
        return typeof payload.exp === 'number' && (Date.now() / 1000) < payload.exp;
      } catch (e) { return false; }
    };

    // ยิงคำสั่งของแอดมิน — แนบ token ทุกครั้ง ถ้าโดนปฏิเสธแปลว่าหมดอายุ ให้เตะออกจากโหมดแอดมิน
    const postAPI = async (payload) => {
      const token = getToken();
      const headers = { 'Content-Type': 'application/json' };
      if (token) headers['Authorization'] = 'Bearer ' + token;

      const res = await fetch(API_DATA, { method: 'POST', headers, body: JSON.stringify(payload) });

      if (res.status === 401) { clearToken(); throw new Error('Unauthorized'); }
      if (res.status === 429) throw new Error('RATE_LIMIT');
      if (!res.ok) throw new Error('API error ' + res.status);

      return res.json();
    };

    const IconPlus = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className={className}><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>;
    const IconHome = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>;
    const IconSearch = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className={className}><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>;
    const IconCheck = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="4" strokeLinecap="round" strokeLinejoin="round" className={className}><polyline points="20 6 9 17 4 12"></polyline></svg>;
    const IconX = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className={className}><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>;
    const IconFileText = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><line x1="10" y1="9" x2="8" y2="9"></line></svg>;
    const IconCalendar = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>;
    const IconLoader = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className={className}><line x1="12" y1="2" x2="12" y2="6"></line><line x1="12" y1="18" x2="12" y2="22"></line><line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line><line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line><line x1="2" y1="12" x2="6" y2="12"></line><line x1="18" y1="12" x2="22" y2="12"></line><line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line><line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line></svg>;
    const IconEye = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>;
    const IconEyeOff = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>;
    const IconImage = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>;
    const IconList = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className={className}><line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><line x1="3" y1="6" x2="3.01" y2="6"></line><line x1="3" y1="12" x2="3.01" y2="12"></line><line x1="3" y1="18" x2="3.01" y2="18"></line></svg>;
    const IconChevronLeft = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className={className}><polyline points="15 18 9 12 15 6"></polyline></svg>;
    const IconChevronRight = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className={className}><polyline points="9 18 15 12 9 6"></polyline></svg>;
    const IconTrash = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>;
    const IconAlertTriangle = ({size=24, className=""}) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>;

    const COLORS = {
      blue: '#E0F4F7',
      pink: '#FFE1E8',
      purple: '#FCEB9E',
      orange: '#EBF5DD',
      bg: '#fff5f9',
      white: '#FFFFFF',
      pinkDeep: '#ED6D5D',
      textMain: '#7A5B53',
      textSoft: '#B39A94',
      blueDeep: '#79B4C2',
      purpleDeep: '#D4AF37',
      orangeDeep: '#A4CC63',
    };

    const FluffyCloud = React.memo(({ top, left, right, bottom, scale = 1, opacity = 0.7, delay = '0s', reverse = false }) => (
      <div className="absolute pointer-events-none drop-shadow-sm z-0" style={{ top, left, right, bottom, opacity, transform: `scale(${scale})` }}>
        <div className={reverse ? 'animate-float-reverse' : 'animate-float'} style={{ animationDelay: delay }}>
          <div className="relative w-40 h-16">
            <div className="absolute bottom-0 left-4 w-32 h-10 bg-white/90 rounded-full"></div>
            <div className="absolute bottom-2 left-2 w-14 h-14 bg-white/90 rounded-full"></div>
            <div className="absolute bottom-5 left-10 w-16 h-16 bg-white/90 rounded-full"></div>
            <div className="absolute bottom-1 right-2 w-14 h-14 bg-white/90 rounded-full"></div>
          </div>
        </div>
      </div>
    ));

    const DynamicBackground = React.memo(() => (
      <div className="fixed inset-0 overflow-hidden pointer-events-none z-0">
        <div className="absolute top-[10%] left-[-10%] w-72 h-72 rounded-full blur-[90px] opacity-40 animate-float" style={{ backgroundColor: COLORS.pink }}></div>
        <div className="absolute bottom-[10%] right-[-10%] w-80 h-80 rounded-full blur-[100px] opacity-30 animate-float-reverse" style={{ backgroundColor: COLORS.blue }}></div>
        <div className="absolute top-[40%] right-[10%] w-48 h-48 rounded-full blur-[80px] opacity-20 animate-float" style={{ backgroundColor: COLORS.purple }}></div>
        <FluffyCloud top="8%" left="-5%" scale={1.5} opacity={0.6} delay="0s" />
        <FluffyCloud top="35%" left="-15%" scale={2.5} opacity={0.3} delay="2.5s" />
        <FluffyCloud bottom="20%" left="5%" scale={1.6} opacity={0.6} delay="3s" />
        <FluffyCloud top="50%" right="-5%" scale={1.8} opacity={0.5} delay="1s" reverse={true} />
      </div>
    ));

    const Header = React.memo(({ isAdmin, onLogout, setShowAuthModal, handleImageUpload, profileImage }) => (
      <div className="px-5 pt-6 pb-2 relative z-10">
        <div className="bg-white/40 backdrop-blur-md rounded-[32px] px-4 pt-5 pb-4 shadow-xl shadow-[#E0F4F7]/50 border border-white/50 flex items-center justify-between relative overflow-hidden group" style={{ minHeight: '88px' }}>
          <div className="absolute left-6 top-1/2 -translate-y-1/2 w-24 h-8 bg-[#FFE1E8]/60 blur-xl rounded-full pointer-events-none"></div>
          <div className="flex flex-col justify-center ml-2 relative z-10">
            <div className="flex items-center gap-1.5 pb-1">

                       <h1 className="text-2xl font-black italic tracking-tighter flex">
             {"namnuengstore".split('').map((char, index) => (
                <span key={index} className={`drop-shadow-sm inline-block animate-text-wave pb-2 ${char === ' ' ? 'w-2.5' : 'pr-[1.5px]'}`} style={{ animationDelay: `${index * 0.1}s`, color: '#ffb6e3' }}>{char}</span>
              ))}
            </h1>

              <button onClick={() => isAdmin ? onLogout() : setShowAuthModal(true)} className={`px-1.5 py-0.5 ml-1 rounded-full text-[7px] font-black uppercase tracking-widest border shadow-sm transition-all active:scale-95 ${isAdmin ? 'bg-white/60 text-[#7A5B53] border-[#D1BEB8]' : 'bg-gray-100/80 text-gray-400 border-gray-200'}`}>
                {isAdmin ? 'Admin' : 'Guest'}
              </button>
            </div>
            <div className="flex items-center gap-1.5 opacity-70">
              <div className="w-3 h-[1px]" style={{ backgroundColor: COLORS.pinkDeep }}></div>
              <p className="text-[10px] font-black tracking-[0.5em] uppercase" style={{ color: COLORS.purpleDeep }}>APP PREMIUM</p>
            </div>
          </div>
          <div onClick={isAdmin ? handleImageUpload : undefined} className={`w-16 h-16 rounded-[1.25rem] bg-white border-2 border-white flex items-center justify-center relative overflow-hidden transition-transform ${isAdmin ? 'cursor-pointer hover:scale-105 active:scale-95' : ''}`}>
            {profileImage ? (
              <img src={profileImage} alt="Profile" className="w-full h-full object-cover" />
            ) : (
              <>
                <div className="absolute inset-0 opacity-40" style={{ background: `linear-gradient(to top right, ${COLORS.pink}, ${COLORS.blue})` }}></div>
                <span className="text-2xl relative z-10 select-none">🐰</span>
              </>
            )}
          </div>
        </div>
      </div>
    ));

    const CheckDateCard = React.memo(({ checkDays, dueInXTasksLength, onOpenDaysModal, onCardClick, isActive }) => (
      <div onClick={onCardClick} className={`bg-white/80 backdrop-blur-sm rounded-[28px] p-4 flex flex-col justify-between relative overflow-hidden transition-all cursor-pointer h-full group ${isActive ? 'border-2 border-[#ED6D5D] shadow-md shadow-[#ED6D5D]/30 bg-[#FFFDF2] scale-[0.98]' : 'border border-white shadow-lg shadow-[#FCEB9E]/30 hover:shadow-[#FCEB9E]/50 hover:scale-[1.01]'}`}>
        <div className={`absolute -right-2 -bottom-4 transition-transform duration-500 pointer-events-none ${isActive ? 'scale-110 opacity-20' : 'opacity-10 group-hover:scale-110 group-hover:-rotate-6'}`} style={{ color: COLORS.textMain }}><IconCalendar size={75} /></div>
        {isActive && (
            <div className="absolute top-4 left-4 flex items-center justify-center">
              <span className="animate-ping absolute inline-flex h-2 w-2 rounded-full bg-[#ED6D5D] opacity-75"></span>
              <span className="relative inline-flex rounded-full h-1.5 w-1.5 bg-[#A4CC63]"></span>
            </div>
        )}
        <div className="flex justify-between items-start relative z-10">
            <div className={`flex flex-col ${isActive ? 'ml-3' : 'ml-0'} transition-all`}>
                <span className="text-[9px] font-black text-[#B39A94] uppercase tracking-wider mb-0.5">Advance</span>
                <span className="text-[11px] font-black text-[#7A5B53]">เช็ครายการต่ออายุเมล</span>
            </div>
            <button onClick={(e) => { e.stopPropagation(); onOpenDaysModal(); }} className="bg-white/90 backdrop-blur-sm px-2.5 py-1 rounded-full text-[9px] font-black shadow-sm border border-[#ED6D5D] text-[#7A5B53] hover:bg-[#FFFDF2] active:scale-95 transition-all flex items-center gap-1 z-20" title="เปลี่ยนจำนวนวัน">อีก {checkDays} วัน <span className="text-[7px] opacity-60 ml-0.5">▾</span></button>
        </div>
        <div className="relative z-10 mt-1 flex items-baseline gap-1.5">
            <span className="text-[11px] font-bold text-[#7A5B53]">พบ</span>
            <span className="text-3xl font-black leading-none" style={{ color: COLORS.pinkDeep }}>{dueInXTasksLength}</span>
            <span className="text-[11px] font-bold text-[#7A5B53]">รายการ</span>
        </div>
      </div>
    ));

    const OverdueCard = React.memo(({ overdueTasksLength, triggerBounce, isBouncing }) => (
      <div onClick={triggerBounce} className={`bg-white/80 backdrop-blur-sm rounded-[28px] p-2 flex flex-col items-center justify-center shadow-lg shadow-rose-500/10 border border-white h-full relative overflow-hidden transition-all duration-300 cursor-pointer ${isBouncing ? 'scale-95' : 'hover:scale-[1.02]'}`}>
        <div className="absolute top-2 left-1/2 -translate-x-1/2 px-2 py-0.5 rounded-md text-[7px] font-black bg-white shadow-sm border border-rose-200 uppercase tracking-wider whitespace-nowrap z-10 text-rose-400 flex items-center gap-1"><IconAlertTriangle size={8} /> เลยกำหนด</div>
        <div className="relative mt-5 flex flex-col items-center">
           <div className="relative">
             <div className="absolute inset-0 blur-lg rounded-full opacity-50 scale-125 bg-rose-300"></div>
             <div className="w-12 h-12 rounded-full bg-white flex flex-col items-center justify-center shadow-[inset_0_2px_8px_rgba(0,0,0,0.02)] border-2 border-rose-100 relative z-10">
                <span className="text-2xl font-black leading-none text-rose-400">{overdueTasksLength}</span>
             </div>
           </div>
           <span className="text-[8px] font-black opacity-70 uppercase mt-2 relative z-10 text-rose-400">เมล</span>
        </div>
      </div>
    ));

    const TaskCard = React.memo(({ task, isAdmin, onEdit, onChangeStatus }) => {
      const today = new Date();
      today.setHours(0,0,0,0);
      const due = new Date(task.dueDate);
      due.setHours(0,0,0,0);
      const daysDiff = Math.ceil((due - today) / (1000 * 60 * 60 * 24));

      let statusBadge = null;
      if (task.status === 'done') {
          statusBadge = <span className="text-[9px] font-bold bg-gray-50 text-gray-400 px-2 py-0.5 rounded-full border border-gray-100">ต่ออายุแล้ว</span>;
      } else if (task.status === 'cancelled') {
          statusBadge = <span className="text-[9px] font-bold bg-gray-50 text-gray-400 px-2 py-0.5 rounded-full border border-gray-100">ไม่ต่ออายุ</span>;
      } else if (daysDiff < 0) {
          statusBadge = <span className="text-[9px] font-bold bg-rose-50 text-rose-500 px-2 py-0.5 rounded-full animate-pulse border border-rose-200">เลยกำหนดมาแล้ว {Math.abs(daysDiff)} วัน</span>;
      } else if (daysDiff >= 0 && daysDiff <= 3) {
          statusBadge = <span className="text-[9px] font-bold bg-yellow-50 text-[#7A5B53] px-2 py-0.5 rounded-full border border-[#FCEB9E]">{daysDiff === 0 ? 'ถึงกำหนดชำระวันนี้' : `ถึงกำหนดชำระใน ${daysDiff} วัน`}</span>;
      } else {
          statusBadge = <span className="text-[9px] font-bold bg-[#E0F4F7] text-[#79B4C2] px-2 py-0.5 rounded-full border border-[#E0F4F7]">อีก {daysDiff} วันถึงกำหนด</span>;
      }

      let iconUrl = "https://i.ibb.co/3P6dXy7/image.png";
      if (task.status === 'done') iconUrl = "https://i.ibb.co/3P6dXy7/image.png";
      else if (task.status === 'todo') {
          if (daysDiff < 0) iconUrl = "https://i.ibb.co/FLQYmmGN/image.png";
          else if (daysDiff >= 0 && daysDiff <= 3) iconUrl = "https://i.ibb.co/yncYDdbp/image.png";
      }
      else if (task.status === 'cancelled') iconUrl = "https://i.ibb.co/Q7Nm4VWG/image.png";

      return (
        <div className="flex items-center gap-1 mb-2 w-full relative">
          <div className="w-[70px] h-[70px] -ml-1 flex-shrink-0 flex items-center justify-center relative z-20">
              <img src={iconUrl} alt="Status Icon" className="w-full h-full object-contain animate-float-icon drop-shadow-md" />
          </div>
          
          <div onClick={() => isAdmin && onEdit(task)} className={`relative flex-1 z-0 rounded-[20px] py-2 px-3 transition-all border shadow-sm group overflow-hidden ${isAdmin ? 'active:scale-[0.98] cursor-pointer' : ''} bg-white/90`} style={{ backgroundColor: (task.status === 'done' || task.status === 'cancelled') ? 'rgba(255,255,255,0.6)' : 'rgba(255,255,255,0.95)', borderColor: ((task.status === 'done' || task.status === 'cancelled') ? 'transparent' : COLORS.white), opacity: (task.status === 'done' || task.status === 'cancelled') ? 0.7 : 1 }}>
            <div className="absolute left-2 top-2 bottom-2 w-1 rounded-full shadow-sm z-10" style={{ backgroundColor: COLORS.purpleDeep }}></div>
            <div className="pl-3 pr-0.5 relative z-10">
              <div className="flex justify-between items-start gap-2">
                <div className="flex flex-col min-w-0 flex-1">
                  <span className="font-bold text-sm truncate w-full block" style={{ color: COLORS.textMain }}>{task.email}</span>
                  {isAdmin && (task.firstPassword || task.currentPassword) && (
                    <div className="flex gap-2 mt-0.5">
                      <span className="text-[9px] text-gray-400 truncate">พาส 1: {task.firstPassword || '-'}</span>
                      <span className="text-[9px] text-gray-400 truncate">ปัจจุบัน: {task.currentPassword || '-'}</span>
                    </div>
                  )}
                </div>
                <div className="flex flex-col items-end gap-0.5 flex-shrink-0">
                  {statusBadge}
                  <div className="flex items-center gap-1 text-[8px] font-black bg-[#FFFDF2] px-1.5 py-0.5 rounded-lg border border-[#ED6D5D] shadow-sm" style={{ color: COLORS.pinkDeep }}>
                      <IconCalendar size={8} style={{ color: COLORS.pinkDeep }} />
                      {new Date(task.dueDate).toLocaleDateString('th-TH', { day: '2-digit', month: '2-digit', year: '2-digit' })}
                  </div>
                </div>
              </div>
              <div className="flex justify-between items-end mt-1">
                <div className="flex-1 min-w-0 flex items-center gap-1.5">
                  <span className={`text-[11px] font-bold truncate ${(task.status === 'done' || task.status === 'cancelled') ? 'line-through text-gray-300' : 'text-[#7A5B53]'}`}>{task.app}</span>
                </div>
                {isAdmin ? (
                  <div className="flex flex-shrink-0 ml-2 relative z-30" onClick={(e) => e.stopPropagation()}>
                    <select
                        value={task.status}
                        onChange={(e) => onChangeStatus(e, task, e.target.value)}
                        className={`text-[9px] font-black rounded-[8px] border-[2px] outline-none px-1.5 py-1 shadow-sm transition-all cursor-pointer text-center
                        ${task.status === 'done' ? 'bg-[#FFE1E8] border-white text-[#ED6D5D]' :
                          task.status === 'cancelled' ? 'bg-[#FFFDF2] border-white text-[#B39A94]' :
                          'bg-white border-white text-[#B0BEC5]'}`}
                    >
                        <option value="todo">รอต่ออายุ</option>
                        <option value="done">ต่ออายุแล้ว</option>
                        <option value="cancelled">ไม่ต่ออายุ</option>
                    </select>
                  </div>
                ) : (
                  <div className="flex items-center flex-shrink-0">
                    {task.status === 'done' && <span className="text-[9px] font-bold text-[#7A5B53] flex items-center gap-1 bg-white px-2 py-1 rounded-md border border-[#FFE1E8] shadow-sm"><IconCheck size={10} /> ต่ออายุแล้ว</span>}
                    {task.status === 'cancelled' && <span className="text-[9px] font-bold text-[#B39A94] flex items-center gap-1 bg-[#FFFDF2] px-2 py-1 rounded-md border border-[#FCEB9E] shadow-sm"><IconX size={10} /> ไม่ต่ออายุ</span>}
                  </div>
                )}
              </div>
            </div>
          </div>
        </div>
      );
    });

    const CalendarView = React.memo(({ currentMonth, setCurrentMonth, selectedDate, setSelectedDate, today, tasks }) => {
      const year = currentMonth.getFullYear();
      const month = currentMonth.getMonth();
      const daysInMonth = new Date(year, month + 1, 0).getDate();
      const firstDay = new Date(year, month, 1).getDay();

      const days = [];
      for (let i = 0; i < firstDay; i++) days.push(null);
      for (let i = 1; i <= daysInMonth; i++) days.push(i);

      const monthNames = ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม"];

      return (
        <div className="bg-white/90 backdrop-blur-xl rounded-[32px] p-5 shadow-[0_12px_30px_rgba(252,235,158,0.5)] border-[4px] border-white mb-5 animate-fadeIn">
          <div className="flex justify-between items-center mb-4 px-2">
            <button onClick={() => setCurrentMonth(new Date(year, month - 1, 1))} className="p-1.5 hover:bg-[#FFFDF2] rounded-full transition-colors text-[#B39A94]"><IconChevronLeft size={20}/></button>
            <h3 className="font-black text-[15px] text-[#7A5B53] tracking-widest">{monthNames[month]} {year}</h3>
            <button onClick={() => setCurrentMonth(new Date(year, month + 1, 1))} className="p-1.5 hover:bg-[#FFFDF2] rounded-full transition-colors text-[#B39A94]"><IconChevronRight size={20}/></button>
          </div>
          <div className="grid grid-cols-7 gap-1 text-center mb-3">
            {['อา', 'จ', 'อ', 'พ', 'พฤ', 'ศ', 'ส'].map(d => (
              <div key={d} className="text-[10px] font-black text-[#B39A94] opacity-60 uppercase">{d}</div>
            ))}
          </div>
          <div className="grid grid-cols-7 gap-y-3 gap-x-1 text-center">
            {days.map((day, index) => {
              if (!day) return <div key={`empty-${index}`} className="h-10"></div>;
              const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
              const isSelected = selectedDate === dateStr;
              const isToday = today === dateStr;
              const hasTasks = tasks.some(t => t.dueDate === dateStr);
              return (
                <div key={dateStr} className="flex justify-center items-center h-10">
                  <div
                    onClick={() => setSelectedDate(dateStr)}
                    className={`relative w-10 h-10 flex flex-col items-center justify-center cursor-pointer transition-all ${
                      isSelected
                        ? 'bg-[#ED6D5D] text-white rounded-full font-black shadow-md scale-105'
                        : isToday
                          ? 'text-[#7A5B53] font-black bg-[#FFFDF2] rounded-full border-[2px] border-[#ED6D5D]'
                          : 'text-[#B39A94] font-bold hover:bg-[#FFFDF2] hover:border-[2px] hover:border-white hover:shadow-sm rounded-full'
                    }`}
                  >
                    <span className="text-[13px] z-10 leading-none">{day}</span>
                    {hasTasks && (
                      <div className="absolute bottom-1 w-1.5 h-1.5 rounded-full" style={{ backgroundColor: isSelected ? COLORS.white : COLORS.purpleDeep }}></div>
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      );
    });

    function App() {
      const [tasks, setTasks] = useState([]);
      const [appTypes, setAppTypes] = useState([]);
      const [isLoading, setIsLoading] = useState(true);
      const [isSaving, setIsSaving] = useState(false);
      const [view, setView] = useState('dashboard');
      const [isCalendarView, setIsCalendarView] = useState(false);
      const [currentMonth, setCurrentMonth] = useState(new Date());
      const [selectedDate, setSelectedDate] = useState(() => {
        const d = new Date();
        return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
      });
      const [showModal, setShowModal] = useState(false);
      const [editingTask, setEditingTask] = useState(null);
      const [taskToDelete, setTaskToDelete] = useState(null);
      const [showAuthModal, setShowAuthModal] = useState(false);
      const [showBannerModal, setShowBannerModal] = useState(false);
      const [showImageModal, setShowImageModal] = useState(false);
      const [showDaysModal, setShowDaysModal] = useState(false);
      const [showRenewModal, setShowRenewModal] = useState(false);
      const [renewingTask, setRenewingTask] = useState(null);
      const [newDueDate, setNewDueDate] = useState('');
      const [searchQuery, setSearchQuery] = useState('');
      const [filterType, setFilterType] = useState('all');
      const [todayFilter, setTodayFilter] = useState('all');
      const [isAdmin, setIsAdmin] = useState(false);
      const [password, setPassword] = useState('');
      const [rememberDevice, setRememberDevice] = useState(false);
      const [profileImage, setProfileImage] = useState(null);
      const [bannerImage, setBannerImage] = useState(null);
      const [isBannerVisible, setIsBannerVisible] = useState(true);
      const [tempImageUrl, setTempImageUrl] = useState('');
      const [checkDays, setCheckDays] = useState(3);
      const [tempDays, setTempDays] = useState(3);
      const [isViewingAdvance, setIsViewingAdvance] = useState(false);
      const [isBouncing, setIsBouncing] = useState(false);

      // asAdmin = true จะยิงแบบ POST พร้อม token เพื่อให้ได้รหัสผ่าน (คอลัมน์ K/L) ติดมาด้วย
      // คำขอสาธารณะจะโดน /api/data ตัดรหัสผ่านทิ้งก่อนถึงเบราว์เซอร์เสมอ
      const loadData = async (asAdmin) => {
        try {
          const result = asAdmin
            ? await postAPI({ action: 'getInitialData' })
            : await (await fetch(API_DATA + "?action=getInitialData")).json();

          if (result.status === 'success') {
            setTasks(result.data.tasks || []);
            if(result.data.appTypes && result.data.appTypes.length > 0) setAppTypes(result.data.appTypes);
            setProfileImage(result.data.profileImage);
            setBannerImage(result.data.bannerImage);
            setIsBannerVisible(result.data.bannerVisible);
          }
        } catch (e) {
          console.error("Error loading data:", e);
        } finally {
          setIsLoading(false);
        }
      };

      useEffect(() => {
        document.title = "namnuengstore";

        const admin = isTokenValid();
        if (admin) setIsAdmin(true); else clearToken();
        loadData(admin);
      }, []);

      const handleAdminLogin = async (e) => {
        e.preventDefault();
        setIsSaving(true);
        try {
           const res = await fetch(API_LOGIN, {
               method: 'POST',
               headers: { 'Content-Type': 'application/json' },
               body: JSON.stringify({ password: password, remember: rememberDevice })
           });

           if (res.status === 429) { alert("ลองบ่อยเกินไป รอสักครู่แล้วลองใหม่"); return; }
           if (!res.ok) { alert("รหัสผ่านไม่ถูกต้อง!"); return; }

           const result = await res.json();
           if (!result || !result.token) { alert("รหัสผ่านไม่ถูกต้อง!"); return; }

           saveToken(result.token);
           setIsAdmin(true);
           setShowAuthModal(false);
           setPassword('');
           loadData(true);
        } catch (e) {
           alert("เกิดข้อผิดพลาดในการตรวจสอบรหัสผ่าน");
        } finally {
           setIsSaving(false);
        }
      };

      const handleLogout = useCallback(() => {
        clearToken();
        setIsAdmin(false);
        // ล้างรหัสผ่านที่โหลดมาตอนเป็นแอดมินออกจากหน่วยความจำ
        setTasks(prev => prev.map(({ firstPassword, currentPassword, ...rest }) => rest));
      }, []);

      const todayStr = useMemo(() => {
        const d = new Date();
        return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
      }, []);

      const overdueTasks = useMemo(() => {
        const tObj = new Date(); tObj.setHours(0,0,0,0);
        return tasks.filter(t => {
           if(!t.dueDate) return false;
           const dObj = new Date(t.dueDate); dObj.setHours(0,0,0,0);
           return dObj < tObj && t.status !== 'done' && t.status !== 'cancelled';
        });
      }, [tasks]);

      const dueInXTasks = useMemo(() => {
        const tObj = new Date(); tObj.setHours(0,0,0,0);
        return tasks.filter(t => {
           if(!t.dueDate) return false;
           const dObj = new Date(t.dueDate); dObj.setHours(0,0,0,0);
           const diff = Math.ceil((dObj - tObj) / (1000 * 60 * 60 * 24));
           return diff === checkDays && t.status !== 'done' && t.status !== 'cancelled';
        });
      }, [tasks, checkDays]);

      const currentDashboardTasks = useMemo(() => {
        let base = isViewingAdvance ? dueInXTasks : tasks.filter(t => t.dueDate === todayStr);
        if (todayFilter !== 'all') {
            base = base.filter(t => t.app === todayFilter);
        }
        return base;
      }, [isViewingAdvance, dueInXTasks, tasks, todayStr, todayFilter]);

      const changeTaskStatus = useCallback((e, task, newStatus) => {
        e.stopPropagation();
        if (newStatus === 'done' && task.status !== 'done') {
           setRenewingTask(task);
           let currentDue = new Date();
           if(task.dueDate) currentDue = new Date(task.dueDate);
           currentDue.setMonth(currentDue.getMonth() + 1);
           const nextMonthStr = `${currentDue.getFullYear()}-${String(currentDue.getMonth() + 1).padStart(2, '0')}-${String(currentDue.getDate()).padStart(2, '0')}`;
           setNewDueDate(nextMonthStr);
           setShowRenewModal(true);
        } else {
           setTasks(prev => prev.map(t => t.id === task.id ? { ...t, status: newStatus } : t));
           postAPI({ action: 'updateTaskStatus', taskId: task.id, newStatus: newStatus }).catch(() => {});
        }
      }, []);

      const handleRenewSubmit = async () => {
        setIsSaving(true);
        const updatedTask = { ...renewingTask, dueDate: newDueDate, status: 'done' };
        setTasks(prev => prev.map(t => t.id === updatedTask.id ? updatedTask : t));
        setShowRenewModal(false);
        setRenewingTask(null);
        await postAPI({ action: 'saveOrUpdateTask', task: updatedTask });
        setIsSaving(false);
      };

      const handleEditTask = useCallback((task) => {
        setEditingTask(task);
        setShowModal(true);
      }, []);

      const handleSaveTask = async (e) => {
        e.preventDefault();
        setIsSaving(true);
        const formData = new FormData(e.target);
        const taskData = {
          id: editingTask ? editingTask.id : Date.now(),
          email: formData.get('email'),
          firstPassword: formData.get('firstPassword'),
          currentPassword: formData.get('currentPassword'),
          app: formData.get('app'),
          dueDate: formData.get('dueDate'),
          details: formData.get('details'),
          status: editingTask ? editingTask.status : 'todo'
        };
        try {
           await postAPI({ action: 'saveOrUpdateTask', task: taskData });
           setTasks(prev => editingTask ? prev.map(t => t.id === taskData.id ? taskData : t) : [...prev, taskData]);
        } catch(e) {
           console.error(e);
        } finally {
           setIsSaving(false); setShowModal(false); setEditingTask(null);
        }
      };

      const executeDeleteTask = async () => {
        if (!taskToDelete) return;
        setIsSaving(true);
        try {
            await postAPI({ action: 'deleteTask', taskId: taskToDelete });
            setTasks(prev => prev.filter(t => t.id !== taskToDelete));
        } catch(e) {
            console.error(e);
        } finally {
            setIsSaving(false); setShowModal(false); setEditingTask(null); setTaskToDelete(null);
        }
      };

      const toggleBannerVisibility = (visible) => {
         setIsBannerVisible(visible);
         postAPI({ action: 'saveBannerVisibility', isVisible: visible }).catch(() => {});
      };

      const triggerBounce = useCallback(() => { setIsBouncing(true); setTimeout(() => setIsBouncing(false), 500); }, []);

      const handleImageUpload = useCallback(() => {
         setTempImageUrl(profileImage || "");
         setShowImageModal(true);
      }, [profileImage]);

      const handleBannerUpload = useCallback(() => {
         setTempImageUrl(bannerImage || "");
         setShowBannerModal(true);
      }, [bannerImage]);

      const handleDaysSubmit = () => {
        setCheckDays(Number(tempDays));
        setShowDaysModal(false);
        setIsViewingAdvance(true);
      };

      const filteredAllTasks = useMemo(() => tasks.filter(t => {
        const appStr = (t.app || "").toLowerCase();
        const emailStr = (t.email || "").toLowerCase();
        const queryStr = (searchQuery || "").toLowerCase();
        const matchSearch = appStr.includes(queryStr) || emailStr.includes(queryStr);
        const todayObj = new Date(); todayObj.setHours(0,0,0,0);
        const dueObj = t.dueDate ? new Date(t.dueDate) : new Date();
        dueObj.setHours(0,0,0,0);
        let matchFilter = false;
        if (filterType === 'all') matchFilter = true;
        else if (filterType === 'done') matchFilter = t.status === 'done';
        else if (filterType === 'overdue') matchFilter = (dueObj < todayObj && t.status !== 'done' && t.status !== 'cancelled');
        return matchSearch && matchFilter;
      }), [tasks, searchQuery, filterType]);

      const displayedTasks = isCalendarView
        ? filteredAllTasks.filter(t => t.dueDate === selectedDate)
        : filteredAllTasks;

      if (isLoading) {
        return (
          <div className="min-h-screen flex flex-col items-center justify-center relative overflow-hidden" style={{ backgroundColor: COLORS.bg }}>
             <DynamicBackground />
             <div className="flex flex-col items-center z-10 animate-breathe">
               <div className="flex items-center gap-1.5 px-6 py-2.5 bg-white/60 backdrop-blur-sm rounded-full border-[2px] border-white shadow-sm">
                 <p className="text-[12px] font-black tracking-widest" style={{ color: COLORS.textMain }}>กำลังโหลดข้อมูล</p>
                 <div className="flex gap-1 pt-1 ml-1">
                   <span className="w-1.5 h-1.5 rounded-full animate-bounce" style={{ backgroundColor: COLORS.pinkDeep, animationDelay: '0s' }}></span>
                   <span className="w-1.5 h-1.5 rounded-full animate-bounce" style={{ backgroundColor: COLORS.blueDeep, animationDelay: '0.15s' }}></span>
                   <span className="w-1.5 h-1.5 rounded-full animate-bounce" style={{ backgroundColor: COLORS.purpleDeep, animationDelay: '0.3s' }}></span>
                 </div>
               </div>
             </div>
          </div>
        );
      }

      return (
        <div className="min-h-screen font-sans relative" style={{ backgroundColor: COLORS.bg, color: COLORS.textMain }}>
          <DynamicBackground />
          <div className="max-w-md mx-auto min-h-screen relative pb-28">
            <Header isAdmin={isAdmin} onLogout={handleLogout} setShowAuthModal={setShowAuthModal} handleImageUpload={handleImageUpload} profileImage={profileImage} />

            <div className="px-5 relative z-10 mb-4">
               {bannerImage && isBannerVisible && (
                 <div className="relative group w-full h-32 rounded-[24px] overflow-hidden shadow-sm border-[3px] border-white bg-white/40 backdrop-blur-sm">
                    <img src={bannerImage} alt="Shop Banner" className="w-full h-full object-cover" />
                    <div className="absolute top-2 right-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
                       {isAdmin && <button onClick={handleBannerUpload} className="p-1.5 bg-white/90 backdrop-blur-md rounded-full shadow-sm text-gray-500 hover:text-[#7A5B53] transition-colors"><IconImage size={16} /></button>}
                       {isAdmin && <button onClick={() => toggleBannerVisibility(false)} className="p-1.5 bg-white/90 backdrop-blur-md rounded-full shadow-sm text-gray-500 hover:text-[#B39A94] transition-colors"><IconEyeOff size={16} /></button>}
                    </div>
                 </div>
               )}
               {bannerImage && !isBannerVisible && isAdmin && (
                 <div className="flex justify-end mb-1">
                    <button onClick={() => toggleBannerVisibility(true)} className="text-[10px] font-bold flex items-center gap-1 bg-white/60 backdrop-blur-sm px-3 py-1.5 rounded-full border border-white shadow-sm hover:bg-white transition-colors" style={{ color: COLORS.textSoft }}>
                       <IconEye size={12} /> แสดงแบนเนอร์
                    </button>
                 </div>
               )}
               {!bannerImage && isAdmin && (
                 <div onClick={handleBannerUpload} className="w-full h-16 rounded-[24px] border-[3px] border-dashed border-white bg-white/40 backdrop-blur-sm flex items-center justify-center cursor-pointer hover:bg-white/60 transition-colors">
                    <span className="text-[11px] font-bold flex items-center gap-2" style={{ color: COLORS.textSoft }}><IconPlus size={16}/> เพิ่มรูปแบนเนอร์ร้าน</span>
                 </div>
               )}
            </div>

            <div className="px-5 relative z-10">
              {view === 'dashboard' ? (
                <div className="animate-fadeIn">
                  <div className="flex gap-3 h-[100px] mb-5">
                    <div className="flex-[2]">
                      <CheckDateCard checkDays={checkDays} dueInXTasksLength={dueInXTasks.length} onOpenDaysModal={() => { setTempDays(checkDays); setShowDaysModal(true); }} onCardClick={() => setIsViewingAdvance(true)} isActive={isViewingAdvance} />
                    </div>
                    <div className="flex-1">
                      <OverdueCard overdueTasksLength={overdueTasks.length} triggerBounce={triggerBounce} isBouncing={isBouncing} />
                    </div>
                  </div>

                  <div className="flex items-start justify-between mb-2.5 ml-1">
                    <div className="flex flex-col">
                      <h2 className="text-[11px] font-black text-[#7A5B53] uppercase tracking-[0.1em] mt-1">
                        {isViewingAdvance ? `ครบกำหนดในอีก ${checkDays} วัน` : 'ครบกำหนดชำระวันนี้'}
                      </h2>
                      {isViewingAdvance && (
                        <button onClick={() => setIsViewingAdvance(false)} className="text-[9px] font-bold text-[#B39A94] flex items-center gap-1 mt-1 hover:text-[#7A5B53] transition-colors w-fit px-2 py-0.5 bg-white rounded-md shadow-sm border border-white">
                          <IconChevronLeft size={10} /> กลับไปดูของวันนี้
                        </button>
                      )}
                    </div>
                    <select value={todayFilter} onChange={e => setTodayFilter(e.target.value)} className="text-[10px] font-bold bg-white/80 backdrop-blur-sm border border-white rounded-xl px-3 py-1.5 outline-none text-[#7A5B53] shadow-sm cursor-pointer hover:bg-white transition-colors">
                        <option value="all">ทั้งหมด</option>
                        {appTypes.map(type => (
                            <option key={type} value={type}>{type}</option>
                        ))}
                    </select>
                  </div>

                  <div className="space-y-1">
                    {currentDashboardTasks.length > 0 ? currentDashboardTasks.map(t => <TaskCard key={t.id} task={t} isAdmin={isAdmin} onEdit={handleEditTask} onChangeStatus={changeTaskStatus} />) : (
                      <div className="text-center py-10 bg-white/30 rounded-[28px] border-[4px] border-dashed border-white shadow-sm mt-2">
                        <p className="text-[10px] font-black uppercase tracking-widest opacity-60" style={{ color: COLORS.textSoft }}>
                          {isViewingAdvance ? `ไม่มีรายการในอีก ${checkDays} วัน ✨` : 'วันนี้ไม่มีรายการครบกำหนด ✨'}
                        </p>
                      </div>
                    )}
                  </div>
                </div>
              ) : (
                <div className="animate-fadeIn">
                  <div className="relative mb-4">
                    <div className="absolute left-4 top-1/2 -translate-y-1/2 opacity-50" style={{ color: COLORS.blueDeep }}><IconSearch size={16} /></div>
                    <input type="text" placeholder="ค้นหารายการ, ชื่อแอป, หรืออีเมล..." value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} className="w-full bg-white/80 border-2 rounded-[22px] py-3 pl-10 pr-4 outline-none text-xs shadow-lg shadow-[#FCEB9E]/30 focus:border-[#ED6D5D] transition-all backdrop-blur-sm" style={{ borderColor: COLORS.blue }} />
                  </div>

                  <div className="flex gap-1 mb-3 bg-white/50 p-1.5 rounded-full backdrop-blur-md border-[3px] border-white shadow-sm overflow-x-auto scrollbar-hide">
                      <button onClick={() => setFilterType('all')} className={`flex-1 whitespace-nowrap px-2 text-[9px] font-black py-2 rounded-full transition-all tracking-wider ${filterType === 'all' ? 'bg-white shadow-sm' : 'text-gray-400 hover:bg-white/30'}`} style={{ color: filterType === 'all' ? COLORS.pinkDeep : '' }}>ทั้งหมด</button>
                      <button onClick={() => setFilterType('done')} className={`flex-1 whitespace-nowrap px-2 text-[9px] font-black py-2 rounded-full transition-all tracking-wider ${filterType === 'done' ? 'bg-white shadow-sm' : 'text-gray-400 hover:bg-white/30'}`} style={{ color: filterType === 'done' ? COLORS.blueDeep : '' }}>ต่ออายุแล้ว</button>
                      <button onClick={() => setFilterType('overdue')} className={`flex-1 whitespace-nowrap px-2 text-[9px] font-black py-2 rounded-full transition-all tracking-wider ${filterType === 'overdue' ? 'bg-white shadow-sm' : 'text-gray-400 hover:bg-white/30'}`} style={{ color: filterType === 'overdue' ? '#ef4444' : '' }}>เลยกำหนด</button>
                  </div>

                  <div className="flex justify-end mb-4 pr-1">
                    <button onClick={() => {
                      const newView = !isCalendarView;
                      setIsCalendarView(newView);
                      if(newView) setFilterType('all');
                    }} className="flex items-center gap-1.5 px-3 py-1.5 bg-white/80 backdrop-blur-md rounded-full shadow-[0_4px_10px_rgba(252,235,158,0.5)] border-[2px] border-white text-[9px] font-black uppercase tracking-widest hover:text-[#ED6D5D] transition-all active:scale-95" style={{ color: COLORS.textSoft }}>
                      {isCalendarView ? <><IconList size={14} /> รูปแบบรายการ</> : <><IconCalendar size={14} /> รูปแบบปฏิทิน</>}
                    </button>
                  </div>

                  {isCalendarView && <CalendarView currentMonth={currentMonth} setCurrentMonth={setCurrentMonth} selectedDate={selectedDate} setSelectedDate={setSelectedDate} today={todayStr} tasks={tasks} />}

                  <div className="space-y-1">
                    {displayedTasks.length > 0 ? displayedTasks.map(t => <TaskCard key={t.id} task={t} isAdmin={isAdmin} onEdit={handleEditTask} onChangeStatus={changeTaskStatus} />) : (
                      <div className="text-center py-10 bg-white/30 rounded-[28px] border-[4px] border-dashed border-white shadow-sm mt-4">
                        <p className="text-[10px] font-black uppercase tracking-widest opacity-60" style={{ color: COLORS.textSoft }}>
                          {isCalendarView ? "วันนี้ไม่มีคิว ✨" : "ไม่พบรายการ ✨"}
                        </p>
                      </div>
                    )}
                  </div>
                </div>
              )}
            </div>

            <div className="fixed bottom-6 left-1/2 -translate-x-1/2 w-full max-w-[210px] z-50">
              <div className="bg-white/60 backdrop-blur-xl rounded-full h-14 shadow-2xl shadow-[#FCEB9E]/30 border border-white flex items-center justify-between px-6 relative">
                  <button onClick={() => setView('dashboard')} className={`p-1 transition-all ${view === 'dashboard' ? 'scale-110' : 'text-gray-300 opacity-60'}`} style={{ color: view === 'dashboard' ? COLORS.pinkDeep : '' }}><IconHome size={22} /></button>
                  <div className="w-8"></div>
                  <button onClick={() => setView('all')} className={`p-1 transition-all ${view === 'all' ? 'scale-110' : 'text-gray-300 opacity-60'}`} style={{ color: view === 'all' ? COLORS.blueDeep : '' }}><IconFileText size={22} /></button>
                  {isAdmin && (
                    <div className="absolute left-1/2 -translate-x-1/2 -top-6">
                      <button onClick={() => { setEditingTask(null); setShowModal(true); }} className="w-14 h-14 rounded-full text-white flex items-center justify-center shadow-xl shadow-[#ED6D5D]/50 active:scale-90 transition-transform border-[4px] border-white" style={{ background: `linear-gradient(to bottom right, #ED6D5D, #FFB0A3)` }}>
                        <IconPlus size={24} />
                      </button>
                    </div>
                  )}
              </div>
            </div>

            {showDaysModal && (
              <div className="fixed inset-0 z-[150] flex items-center justify-center p-6 bg-black/20 backdrop-blur-[2px] animate-fadeIn">
                <div className="bg-white/95 backdrop-blur-xl w-full max-w-[260px] rounded-[30px] p-6 shadow-2xl border border-white animate-slideUp text-center">
                  <h3 className="text-[14px] font-black mb-4 text-[#7A5B53]">ตรวจสอบล่วงหน้า (วัน)</h3>
                  <input type="number" min="0" value={tempDays} onChange={e => setTempDays(e.target.value)} className="w-full text-center text-3xl font-black p-3 bg-white rounded-2xl border-2 border-[#FCEB9E] outline-none focus:border-[#ED6D5D] text-[#ED6D5D] mb-5 shadow-inner" />
                  <div className="flex gap-2">
                    <button onClick={() => setShowDaysModal(false)} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-gray-500 bg-gray-100 active:scale-95 transition-all">ยกเลิก</button>
                    <button onClick={handleDaysSubmit} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-white bg-[#ED6D5D] hover:bg-[#A4CC63] active:scale-95 transition-all shadow-md">ตกลง</button>
                  </div>
                </div>
              </div>
            )}

            {showModal && (
              <div className="fixed inset-0 z-[100] flex items-center justify-center p-6 bg-black/10 backdrop-blur-[2px] animate-fadeIn">
                <form onSubmit={handleSaveTask} className="bg-white/95 backdrop-blur-xl w-full max-w-xs rounded-[35px] p-6 shadow-2xl border border-white animate-slideUp">
                   <h3 className="text-sm font-black mb-4 text-center text-gray-800">{editingTask ? 'แก้ไขรายการ ✨' : 'เพิ่มรายการใหม่ ✨'}</h3>
                   <div className="space-y-2 relative">
                     {isSaving && (
                        <div className="absolute inset-0 bg-white/80 z-50 flex flex-col items-center justify-center rounded-2xl backdrop-blur-sm">
                           <IconLoader size={32} className="animate-spin-slow" style={{ color: COLORS.pinkDeep }} />
                           <span className="text-[10px] font-black mt-2 text-gray-500">กำลังบันทึก...</span>
                        </div>
                     )}
                     <input name="email" type="email" required defaultValue={editingTask?.email || ''} className="w-full p-3.5 rounded-2xl bg-white border border-gray-100 outline-none text-[11px] shadow-sm focus:border-[#FFFDF2] transition-all" placeholder="อีเมลที่ใช้งาน" />
                     <div className="flex gap-2">
                       <input name="firstPassword" type="text" defaultValue={editingTask?.firstPassword || ''} className="w-1/2 p-3.5 rounded-2xl bg-white border border-gray-100 outline-none text-[11px] shadow-sm focus:border-[#FFFDF2] transition-all" placeholder="พาสแรก" />
                       <input name="currentPassword" type="text" defaultValue={editingTask?.currentPassword || ''} className="w-1/2 p-3.5 rounded-2xl bg-white border border-gray-100 outline-none text-[11px] shadow-sm focus:border-[#FFFDF2] transition-all" placeholder="พาสปัจจุบัน" />
                     </div>
                     <input list="appTypesList" name="app" required defaultValue={editingTask?.app || ''} className="w-full p-3.5 rounded-2xl font-black text-[10px] outline-none border border-gray-100 shadow-sm" placeholder="แอปที่ต่ออายุ (เช่น Netflix)" />
                     <datalist id="appTypesList">{appTypes.map(type => <option key={type} value={type} />)}</datalist>
                     <textarea name="details" rows="2" defaultValue={editingTask?.details || ''} className="w-full p-3.5 rounded-2xl bg-white border border-gray-100 outline-none text-[11px] shadow-sm focus:border-[#FFFDF2] transition-all resize-none" placeholder="รายละเอียดแพ็กเกจ/อื่นๆ..."></textarea>
                     <div className="flex items-center justify-between bg-[#FFFDF2]/30 p-1.5 pl-4 rounded-2xl border border-[#FCEB9E]/50 transition-all hover:bg-[#FFFDF2]/80 hover:shadow-sm group mt-1">
                       <div className="flex items-center gap-1.5 text-[10px] uppercase tracking-wider font-black" style={{ color: COLORS.pinkDeep }}>
                         <IconCalendar size={12} className="group-hover:animate-bounce-slow transition-transform" /><span>ต่ออายุรอบถัดไป</span>
                       </div>
                       <input name="dueDate" type="date" required defaultValue={editingTask?.dueDate || ''} className="w-32 p-2.5 rounded-xl bg-white border border-[#FCEB9E] outline-none text-[10px] font-black text-[#ED6D5D] shadow-sm focus:border-[#ED6D5D] focus:ring-2 focus:ring-[#ED6D5D]/50 transition-all cursor-pointer active:scale-95 hover:border-[#ED6D5D]" />
                     </div>
                     <div className="flex items-center gap-2 mt-3">
                       <button type="submit" className="flex-1 py-3.5 rounded-2xl font-black text-xs text-white shadow-lg active:scale-95 transition-all disabled:opacity-50" style={{ backgroundColor: COLORS.pinkDeep }}>บันทึกรายการใหม่</button>
                       {editingTask && (
                         <button type="button" onClick={() => setTaskToDelete(editingTask.id)} className="w-12 h-[44px] flex items-center justify-center rounded-2xl bg-red-50 text-red-400 border border-red-100 hover:bg-red-100 active:scale-95 transition-all shadow-sm" title="ลบรายการ">
                           <IconTrash size={18} />
                         </button>
                       )}
                     </div>
                     <button type="button" onClick={() => { setShowModal(false); setEditingTask(null); }} className="w-full text-[9px] font-bold text-gray-300 mt-2 uppercase tracking-widest hover:text-gray-500 transition-colors">Close</button>
                   </div>
                </form>
              </div>
            )}

            {showAuthModal && (
              <div className="fixed inset-0 z-[110] flex items-center justify-center p-6 bg-black/10 backdrop-blur-[2px] animate-fadeIn">
                <form onSubmit={handleAdminLogin} className="bg-white/95 backdrop-blur-xl w-full max-w-xs rounded-[35px] p-6 shadow-2xl border border-white animate-slideUp text-center">
                   <h3 className="text-sm font-black mb-4 text-gray-800">เข้าสู่ระบบ Admin</h3>
                   <input type="password" required value={password} onChange={(e) => setPassword(e.target.value)} className="w-full p-3.5 rounded-2xl bg-white border outline-none text-[11px] shadow-sm text-center" placeholder="ใส่รหัสผ่าน" />
                   <label className="flex items-center justify-center gap-2 cursor-pointer mt-3">
                     <input type="checkbox" checked={rememberDevice} onChange={(e) => setRememberDevice(e.target.checked)} className="w-3 h-3 rounded accent-[#ED6D5D]" />
                     <span className="text-[9px] font-bold text-[#B39A94]">จดจำอุปกรณ์นี้ไว้ 30 วัน</span>
                   </label>
                   <button type="submit" className="w-full h-11 rounded-2xl font-black text-xs mt-3 text-white shadow-lg flex items-center justify-center active:scale-95 transition-all" style={{ backgroundColor: COLORS.pinkDeep }}>
                      {isSaving ? <IconLoader size={16} className="animate-spin-slow mx-auto" /> : 'Login'}
                   </button>
                   <button type="button" onClick={() => setShowAuthModal(false)} className="w-full text-[9px] font-bold text-gray-300 mt-2 uppercase tracking-widest hover:text-gray-500 transition-colors">Close</button>
                </form>
              </div>
            )}

            {taskToDelete && (
              <div className="fixed inset-0 z-[200] flex items-center justify-center p-6 bg-black/20 backdrop-blur-[2px] animate-fadeIn">
                <div className="bg-white/95 backdrop-blur-xl w-full max-w-[260px] rounded-[30px] p-6 shadow-2xl border border-white animate-slideUp text-center">
                  <div className="w-14 h-14 rounded-full bg-red-50 text-red-400 flex items-center justify-center mx-auto mb-3 shadow-sm border border-red-100"><IconTrash size={26} /></div>
                  <h3 className="text-[14px] font-black mb-1 text-gray-800">ยืนยันการลบ?</h3>
                  <p className="text-[10px] font-bold text-gray-500 mb-5">คุณต้องการลบรายการนี้ใช่หรือไม่<br/>(ไม่สามารถกู้คืนได้)</p>
                  <div className="flex gap-2">
                    <button onClick={() => setTaskToDelete(null)} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-gray-500 bg-gray-100 hover:bg-gray-200 active:scale-95 transition-all">ยกเลิก</button>
                    <button onClick={executeDeleteTask} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-white bg-red-400 hover:bg-red-500 active:scale-95 transition-all">ลบข้อมูล</button>
                  </div>
                </div>
              </div>
            )}

            {showRenewModal && (
              <div className="fixed inset-0 z-[200] flex items-center justify-center p-6 bg-black/20 backdrop-blur-[2px] animate-fadeIn">
                <div className="bg-white/95 backdrop-blur-xl w-[90%] max-w-[280px] rounded-[30px] p-6 shadow-2xl border border-white animate-slideUp text-center box-border">
                  <div className="w-14 h-14 rounded-full bg-[#FFFDF2] text-[#ED6D5D] flex items-center justify-center mx-auto mb-3 shadow-sm border border-[#ED6D5D]">
                    <IconCheck size={26} />
                  </div>
                  <h3 className="text-[14px] font-black mb-1 text-[#7A5B53]">ต่ออายุรายการ ✨</h3>
                  <p className="text-[10px] font-bold text-[#B39A94] mb-4">กำหนดวันชำระรอบถัดไป</p>
                  <div className="w-full flex items-center overflow-hidden bg-white rounded-2xl border-2 border-[#FCEB9E] mb-5 shadow-inner focus-within:border-[#ED6D5D] transition-all box-border">
                    <input type="date" value={newDueDate} onChange={e => setNewDueDate(e.target.value)} className="w-full bg-transparent text-center p-3 outline-none text-[#7A5B53] text-[13px] font-bold cursor-pointer font-sans appearance-none min-w-0 box-border" style={{ maxWidth: '100%', WebkitAppearance: 'none' }} />
                  </div>
                  <div className="flex gap-2">
                    <button onClick={() => setShowRenewModal(false)} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-gray-500 bg-gray-100 hover:bg-gray-200 active:scale-95 transition-all">ยกเลิก</button>
                    <button onClick={handleRenewSubmit} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-white bg-[#ED6D5D] hover:bg-[#A4CC63] active:scale-95 transition-all shadow-md">
                        {isSaving ? <IconLoader size={14} className="animate-spin-slow mx-auto" /> : 'บันทึกวัน'}
                    </button>
                  </div>
                </div>
              </div>
            )}

            {showImageModal && (
              <div className="fixed inset-0 z-[200] flex items-center justify-center p-6 bg-black/20 backdrop-blur-[2px] animate-fadeIn">
                <div className="bg-white/95 backdrop-blur-xl w-[90%] max-w-[280px] rounded-[30px] p-6 shadow-2xl border border-white animate-slideUp text-center box-border">
                  <h3 className="text-[14px] font-black mb-1 text-[#7A5B53]">เปลี่ยนรูปโปรไฟล์ 🐰</h3>
                  <p className="text-[10px] font-bold text-[#B39A94] mb-4">วางลิงก์รูปภาพ หรือ Google Drive</p>
                  <div className="w-full flex items-center overflow-hidden bg-white rounded-2xl border-2 border-[#FCEB9E] mb-5 shadow-inner focus-within:border-[#ED6D5D] transition-all box-border">
                    <input type="text" value={tempImageUrl} onChange={e => setTempImageUrl(e.target.value)} className="w-full bg-transparent text-center p-3 outline-none text-[#7A5B53] text-[11px] font-bold font-sans appearance-none min-w-0 box-border" placeholder="https://..." />
                  </div>
                  <div className="flex gap-2">
                    <button onClick={() => {setShowImageModal(false); setTempImageUrl('');}} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-gray-500 bg-gray-100 hover:bg-gray-200 active:scale-95 transition-all">ยกเลิก</button>
                    <button onClick={async () => {
                        setIsSaving(true);
                        let finalUrl = tempImageUrl;
                        if (finalUrl.includes("drive.google.com/file/d/")) {
                            const match = finalUrl.match(/\/d\/(.+?)\//);
                            if (match && match[1]) finalUrl = `https://lh3.googleusercontent.com/d/${match[1]}`;
                        }
                        setProfileImage(finalUrl);
                        await postAPI({ action: 'saveProfileImage', imageUrl: finalUrl });
                        setIsSaving(false);
                        setShowImageModal(false);
                        setTempImageUrl('');
                    }} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-white bg-[#ED6D5D] hover:bg-[#A4CC63] active:scale-95 transition-all shadow-md">
                        {isSaving ? <IconLoader size={14} className="animate-spin-slow mx-auto" /> : 'บันทึกรูป'}
                    </button>
                  </div>
                </div>
              </div>
            )}

            {showBannerModal && (
              <div className="fixed inset-0 z-[200] flex items-center justify-center p-6 bg-black/20 backdrop-blur-[2px] animate-fadeIn">
                <div className="bg-white/95 backdrop-blur-xl w-[90%] max-w-[280px] rounded-[30px] p-6 shadow-2xl border border-white animate-slideUp text-center box-border">
                  <h3 className="text-[14px] font-black mb-1 text-[#7A5B53]">เปลี่ยนรูปแบนเนอร์ 🖼️</h3>
                  <p className="text-[10px] font-bold text-[#B39A94] mb-4">วางลิงก์รูปภาพ หรือ Google Drive</p>
                  <div className="w-full flex items-center overflow-hidden bg-white rounded-2xl border-2 border-[#FCEB9E] mb-5 shadow-inner focus-within:border-[#ED6D5D] transition-all box-border">
                    <input type="text" value={tempImageUrl} onChange={e => setTempImageUrl(e.target.value)} className="w-full bg-transparent text-center p-3 outline-none text-[#7A5B53] text-[11px] font-bold font-sans appearance-none min-w-0 box-border" placeholder="https://..." />
                  </div>
                  <div className="flex gap-2">
                    <button onClick={() => {setShowBannerModal(false); setTempImageUrl('');}} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-gray-500 bg-gray-100 hover:bg-gray-200 active:scale-95 transition-all">ยกเลิก</button>
                    <button onClick={async () => {
                        setIsSaving(true);
                        let finalUrl = tempImageUrl;
                        if (finalUrl.includes("drive.google.com/file/d/")) {
                            const match = finalUrl.match(/\/d\/(.+?)\//);
                            if (match && match[1]) finalUrl = `https://lh3.googleusercontent.com/d/${match[1]}`;
                        }
                        setBannerImage(finalUrl);
                        await postAPI({ action: 'saveBannerImage', imageUrl: finalUrl });
                        setIsSaving(false);
                        setShowBannerModal(false);
                        setTempImageUrl('');
                    }} className="flex-1 py-3 rounded-2xl font-black text-[10px] text-white bg-[#ED6D5D] hover:bg-[#A4CC63] active:scale-95 transition-all shadow-md">
                        {isSaving ? <IconLoader size={14} className="animate-spin-slow mx-auto" /> : 'บันทึกรูป'}
                    </button>
                  </div>
                </div>
              </div>
            )}

          </div>

          <style>{`
            @keyframes float { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(25px, -15px); } }
            @keyframes float-reverse { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-25px, 15px); } }
            @keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }
            @keyframes float-icon { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
            @keyframes bounce-slow { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
            @keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
            @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
            @keyframes text-wave { 0%, 20%, 100% { transform: translateY(0px); } 10% { transform: translateY(-3px); } }
            @keyframes spin-slow { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

            .animate-text-wave { animation: text-wave 4s ease-in-out infinite; }
            .animate-breathe { animation: breathe 4s ease-in-out infinite; transform-origin: center; }
            .animate-float { animation: float 15s ease-in-out infinite; }
            .animate-float-reverse { animation: float-reverse 18s ease-in-out infinite; }
            .animate-float-icon { animation: float-icon 3s ease-in-out infinite; }
            .animate-bounce-slow { animation: bounce-slow 4s ease-in-out infinite; }
            .animate-slideUp { animation: slideUp 0.3s ease-out; }
            .animate-fadeIn { animation: fadeIn 0.4s ease-out; }
            .animate-spin-slow { animation: spin-slow 4s linear infinite; }

            .scrollbar-hide::-webkit-scrollbar { display: none; }
            .scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; }
          `}</style>
        </div>
      );
    }

    createRoot(document.getElementById('root')).render(<App />);