// ============================
// LELUSA — Admin Pages
// admin-pages.jsx
// ============================

function AdminNotificationBell() {
  const { navigate } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const [open, setOpen] = React.useState(false);
  const isMobile = window.LelusaGestures.useIsMobile();
  const notificationState = window.LelusaNotifications?.useNotifications?.() || { items: [], prefs: {}, permission: 'unsupported', supported: false };
  const items = notificationState.items || [];
  const unread = items.filter(item => !item.readAt);

  React.useEffect(() => {
    window.LelusaNotifications?.syncFromBusinessData?.(window.LelusaStore.read());
  }, []);

  React.useEffect(() => {
    const interval = setInterval(() => {
      window.LelusaStore.refreshFromRemote?.().then((data) => {
        window.LelusaNotifications?.syncFromBusinessData?.(data || window.LelusaStore.read());
      });
    }, 60000);
    return () => clearInterval(interval);
  }, []);

  React.useEffect(() => {
    if (!open) return undefined;
    const onClick = (event) => {
      if (!event.target.closest('[data-admin-notifications]')) setOpen(false);
    };
    setTimeout(() => document.addEventListener('mousedown', onClick), 0);
    return () => document.removeEventListener('mousedown', onClick);
  }, [open]);

  const openNotification = (notification) => {
    window.LelusaNotifications.markRead(notification.id);
    setOpen(false);
    navigate(notification.page || 'admin-dashboard', notification.data || {});
  };

  const realtimeLabel = {
    connected: t('admin_notif_rt_connected'),
    connecting: t('admin_notif_rt_connecting'),
    reconnecting: t('admin_notif_rt_reconnecting'),
    closed: t('admin_notif_rt_closed'),
    unsupported: t('admin_notif_rt_unsupported'),
    error: t('admin_notif_rt_error'),
    idle: t('admin_notif_rt_idle'),
  }[notificationState.realtimeStatus || 'idle'];

  const panelStyle = isMobile
    ? {
      position: 'fixed',
      left: 10,
      right: 10,
      bottom: 'calc(92px + env(safe-area-inset-bottom))',
      maxHeight: 'min(74vh, 660px)',
      overflow: 'hidden',
      borderRadius: '22px',
      border: '1px solid var(--border)',
      background: 'var(--card)',
      boxShadow: '0 -18px 60px rgba(58,42,32,0.24)',
      zIndex: 900,
      display: 'flex',
      flexDirection: 'column',
    }
    : {
      position: 'absolute',
      top: '44px',
      right: 0,
      width: 'min(390px, calc(100vw - 28px))',
      maxHeight: 'min(620px, calc(100vh - 86px))',
      overflow: 'hidden',
      borderRadius: '18px',
      border: '1px solid var(--border)',
      background: 'var(--card)',
      boxShadow: '0 24px 70px rgba(58,42,32,0.22)',
      zIndex: 500,
      display: 'flex',
      flexDirection: 'column',
    };

  return (
    <div data-admin-notifications style={{ position: 'relative' }}>
      <button onClick={() => setOpen(current => !current)} title={t('admin_notif_btn')}
        style={{ width: '36px', height: '36px', borderRadius: '50%', border: '1px solid var(--border)', background: 'var(--bg-soft)', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative' }}>
        <Icon name="bell" size={17} color={unread.length ? 'var(--primary)' : 'var(--muted)'} />
        {unread.length > 0 && (
          <span style={{ position: 'absolute', top: '-4px', right: '-4px', minWidth: '18px', height: '18px', padding: '0 5px', borderRadius: '999px', background: '#C83A3A', color: '#fff', fontSize: '10px', fontWeight: 800, display: 'flex', alignItems: 'center', justifyContent: 'center', border: '2px solid var(--card)' }}>
            {unread.length > 9 ? '9+' : unread.length}
          </span>
        )}
      </button>

      {open && isMobile && <div onClick={() => setOpen(false)} style={{ position: 'fixed', inset: 0, background: 'rgba(58,42,32,0.18)', zIndex: 890 }} />}
      {open && (
        <div style={panelStyle}>
          <div style={{ padding: '16px 18px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', gap: '12px', alignItems: 'flex-start' }}>
            <div>
              <div style={{ fontSize: '14px', fontWeight: 800, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{t('admin_notif_title')}</div>
              <div style={{ fontSize: '12px', color: 'var(--muted)', marginTop: '3px' }}>{t('admin_notif_unread_count', { count: unread.length, status: realtimeLabel })}</div>
            </div>
            <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
              <button onClick={() => window.LelusaNotifications.markAllRead()} style={{ border: 'none', background: 'transparent', color: 'var(--primary)', cursor: 'pointer', fontSize: '12px', fontWeight: 800, whiteSpace: 'nowrap' }}>
                {t('admin_notif_mark_read')}
              </button>
              {isMobile && (
                <button onClick={() => setOpen(false)} title={t('admin_notif_close')} style={{ width: 30, height: 30, border: '1px solid var(--border)', borderRadius: 10, background: 'var(--bg-soft)', display: 'grid', placeItems: 'center' }}>
                  <Icon name="x" size={14} color="var(--muted)" />
                </button>
              )}
            </div>
          </div>

          <div style={{ overflowY: 'auto', flex: 1, WebkitOverflowScrolling: 'touch' }}>
            {items.length === 0 ? (
              <div style={{ padding: '34px 20px', textAlign: 'center', color: 'var(--muted)', fontSize: '13px' }}>
                {t('admin_notif_empty')}
              </div>
            ) : items.map((notification) => (
              <button key={notification.id} onClick={() => openNotification(notification)}
                style={{ width: '100%', border: 'none', borderBottom: '1px solid var(--border)', background: notification.readAt ? 'var(--card)' : 'var(--accent-light)', padding: '13px 16px', cursor: 'pointer', textAlign: 'left', display: 'grid', gridTemplateColumns: '28px 1fr', gap: '10px' }}>
                <div style={{ width: '28px', height: '28px', borderRadius: '10px', background: notification.priority === 'alta' ? '#C83A3A18' : 'var(--bg-soft)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <Icon name={notification.type === 'evento' ? 'calendar' : notification.type === 'cotizacion' ? 'fileText' : 'bell'} size={14} color={notification.priority === 'alta' ? '#C83A3A' : 'var(--primary)'} />
                </div>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontSize: '12.5px', fontWeight: 800, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif", lineHeight: 1.25 }}>{notification.title}</div>
                  <div style={{ fontSize: '11.5px', color: 'var(--muted)', marginTop: '4px', lineHeight: 1.45 }}>{notification.body}</div>
                  <div style={{ fontSize: '10.5px', color: 'var(--light)', marginTop: '6px' }}>{new Date(notification.createdAt).toLocaleString(i18next.language === 'es' ? 'es-MX' : 'en-US', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' })}</div>
                </div>
              </button>
            ))}
          </div>

          {items.some(item => item.readAt) && (
            <button onClick={() => window.LelusaNotifications.clearRead()} style={{ width: '100%', border: 'none', borderTop: '1px solid var(--border)', background: 'var(--bg-soft)', padding: '10px', color: 'var(--muted)', cursor: 'pointer', fontSize: '12px', fontWeight: 800 }}>
              {t('admin_notif_clear_read')}
            </button>
          )}
        </div>
      )}
    </div>
  );
}

// ─── Admin Layout wrapper ────────────────────────────────────────
function AdminLayout({ children, title, subtitle }) {
  const { logoutAdmin } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const [collapsed, setCollapsed] = React.useState(false);
  const isMobile = window.LelusaGestures.useIsMobile();
  return (
    <div style={{ display: 'flex', minHeight: '100vh', background: 'var(--bg-soft)' }}>
      {!isMobile && <AdminSidebar collapsed={collapsed} />}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }} className={isMobile ? 'lel-has-bottomnav' : ''}>
        {/* Top bar */}
        <div style={{ height: '64px', background: 'var(--card)', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: isMobile ? '0 16px' : '0 28px', flexShrink: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
            {!isMobile && (
              <button type="button" onClick={() => setCollapsed(c => !c)} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--muted)', padding: '4px' }}>
                <Icon name="menu" size={20} />
              </button>
            )}
            <div>
              <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: isMobile ? '18px' : '20px', fontWeight: 600, color: 'var(--text)', lineHeight: 1.1 }}>{title}</div>
              {subtitle && <div style={{ fontSize: '12px', color: 'var(--muted)' }}>{subtitle}</div>}
            </div>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: isMobile ? '8px' : '12px' }}>
            {!isMobile && <div style={{ fontSize: '12px', color: 'var(--muted)', fontFamily: "'DM Sans', sans-serif" }}>{t('admin_layout_today', { date: new Date().toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { weekday: 'long', day: 'numeric', month: 'long' }) })}</div>}
            <AdminNotificationBell />
            {!isMobile && (
              <button type="button" onClick={logoutAdmin} title={t('admin_layout_logout')}
                style={{ background: 'var(--bg-soft)', border: '1px solid var(--border)', borderRadius: '10px', padding: '7px 10px', cursor: 'pointer', color: 'var(--muted)', fontFamily: "'DM Sans', sans-serif", fontSize: '12px', fontWeight: 700 }}>
                {t('admin_layout_logout_short')}
              </button>
            )}
            <div style={{ width: '36px', height: '36px', borderRadius: '50%', background: 'var(--accent-light)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Icon name="user" size={16} color="var(--primary)" />
            </div>
          </div>
        </div>
        {/* Page content */}
        <div style={{ flex: 1, overflowY: 'auto', padding: isMobile ? '16px 14px calc(128px + env(safe-area-inset-bottom))' : '28px' }}>
          {children}
        </div>
      </div>
    </div>
  );
}

// ─── Stat Card ───────────────────────────────────────────────────
function StatCard({ icon, label, value, sub, color = 'var(--primary)', actionLabel, onClick }) {
  return (
    <div className="lel-stat-card" style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '18px', padding: '20px', display: 'flex', flexDirection: 'column', gap: '14px', minHeight: '142px', boxShadow: '0 10px 30px rgba(58,42,32,0.05)' }}>
      <div className="lel-stat-card-main" style={{ display: 'flex', alignItems: 'flex-start', gap: '14px' }}>
      <div className="lel-stat-card-icon" style={{ width: '46px', height: '46px', borderRadius: '14px', background: `${color}18`, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
        <Icon name={icon} size={22} color={color} />
      </div>
      <div style={{ minWidth: 0 }}>
        <div className="lel-stat-card-label" style={{ fontSize: '12px', color: 'var(--muted)', fontFamily: "'DM Sans', sans-serif", marginBottom: '4px', letterSpacing: '0.04em' }}>{label}</div>
        <div className="lel-stat-card-value" style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: '32px', fontWeight: 700, color: 'var(--text)', lineHeight: 1 }}>{value}</div>
        {sub && <div className="lel-stat-card-sub" style={{ fontSize: '12px', color: 'var(--muted)', marginTop: '4px' }}>{sub}</div>}
      </div>
      </div>
      {actionLabel && (
        <button className="lel-stat-card-action" onClick={onClick} style={{ marginTop: 'auto', border: 'none', background: 'transparent', color, padding: 0, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: '6px', fontSize: '12px', fontWeight: 700, fontFamily: "'DM Sans', sans-serif" }}>
          {actionLabel}
          <Icon name="arrowRight" size={13} color={color} />
        </button>
      )}
    </div>
  );
}

function AdminPanelCard({ title, action, onAction, children }) {
  return (
    <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '18px', overflow: 'hidden', boxShadow: '0 10px 30px rgba(58,42,32,0.05)' }}>
      <div style={{ padding: '16px 18px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '12px' }}>
        <h3 style={{ margin: 0, fontSize: '14px', fontWeight: 800, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{title}</h3>
        {action && <button onClick={onAction} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: '12px', color: 'var(--primary)', fontFamily: "'DM Sans', sans-serif", fontWeight: 700 }}>{action}</button>}
      </div>
      {children}
    </div>
  );
}

// ─── Dashboard Page ──────────────────────────────────────────────
function DashboardPage() {
  const { navigate } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const { assets, designs, desserts, teamMembers, quotes, events, isRemoteConfigured, loading } = window.LelusaStore.useBusinessData();
  const systemSettings = window.LelusaStore.useSystemSettings();
  const isMobile = window.LelusaGestures.useIsMobile();
  const today = new Date().toISOString().slice(0, 10);
  const currentMonth = today.slice(0, 7);
  const currentMonthLabel = new Date(`${currentMonth}-01T12:00:00`).toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { month: 'long', year: 'numeric' });
  const thisMonth = events.filter(e => e.date?.startsWith(currentMonth));
  const pending = quotes.filter(q => q.status === 'pendiente');
  const approved = quotes.filter(q => q.status === 'aprobada');
  const lowStock = assets.filter(asset => Number(asset.quantity) <= 3);
  const dessertEvents = events.filter(event => event.department === 'postres' || event.type === 'postres');
  const dessertTeam = (teamMembers || []).filter(member => member.active !== false && member.department === 'postres');
  const publishedDesigns = designs.filter(design => (design.status || 'published') === 'published');
  const revenue = approved.reduce((sum, q) => sum + q.total, 0);
  const upcoming = events.filter(e => e.date >= today).slice(0, 5);
  const recentQuotes = quotes.slice(0, 5);
  const quickActions = [
    { id: 'design', icon: 'grid', label: t('admin_new_design'), desc: t('admin_dash_qa_design_desc'), page: 'admin-designs', data: { action: 'new' }, color: 'var(--primary)' },
    { id: 'dessert', icon: 'sparkles', label: t('admin_new_dessert'), desc: t('admin_dash_qa_dessert_desc'), page: 'admin-desserts', data: { action: 'new' }, color: '#C8881A' },
    { id: 'quotes', icon: 'fileText', label: t('admin_dash_qa_review_quotes'), desc: t('admin_dash_qa_review_quotes_desc', { count: pending.length }), page: 'admin-quotes', color: '#C8881A' },
    { id: 'calendar', icon: 'calendar', label: t('admin_dash_qa_view_calendar'), desc: t('admin_dash_qa_view_calendar_desc', { count: thisMonth.length }), page: 'admin-calendar', color: '#3A62C8' },
  ];

  return (
    <AdminLayout title={t('admin_dashboard')} subtitle={`${systemSettings.admin?.dashboardSubtitle || (isRemoteConfigured ? t('admin_dash_subtitle_remote') : t('admin_dash_subtitle_local'))}${loading ? ` · ${t('admin_dash_syncing')}` : ''}`}>
      {/* Stats */}
      <div className="lel-stat-grid" style={{ display: 'grid', gridTemplateColumns: isMobile ? 'repeat(2, minmax(0, 1fr))' : 'repeat(auto-fill, minmax(210px, 1fr))', gap: isMobile ? '10px' : '16px', marginBottom: isMobile ? '18px' : '22px' }}>
        <StatCard icon="calendar"  label={t('admin_stat_events_month')} value={thisMonth.length} sub={currentMonthLabel} color="var(--primary)" actionLabel={t('admin_dash_open_calendar')} onClick={() => navigate('admin-calendar')} />
        <StatCard icon="fileText"  label={t('admin_stat_pending_quotes')} value={pending.length} sub={t('admin_dash_requests_sub', { count: quotes.length })} color="#C8881A" actionLabel={t('admin_dash_review')} onClick={() => navigate('admin-quotes')} />
        <StatCard icon="grid" label={t('admin_stat_published_designs')} value={publishedDesigns.length} sub={t('admin_dash_decorations_sub', { count: designs.length })} color="#2A8A50" actionLabel={t('admin_dash_manage')} onClick={() => navigate('admin-designs')} />
        <StatCard icon="sparkles" label={t('admin_stat_active_desserts')} value={(desserts || []).filter(item => item.status !== 'paused').length} sub={t('admin_dash_events_sub', { count: dessertEvents.length })} color="var(--sage-dark)" actionLabel={t('admin_dash_view_desserts')} onClick={() => navigate('admin-desserts')} />
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1.25fr 0.75fr', gap: '20px', alignItems: 'stretch', marginBottom: '22px' }} className="dash-grid">
        <div style={{ background: 'var(--text)', color: 'var(--bg)', borderRadius: '18px', padding: isMobile ? '20px' : '24px', display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr auto', gap: isMobile ? '14px' : '18px', alignItems: 'center', overflow: 'hidden' }}>
          <div>
            <Badge color="dark">{isRemoteConfigured ? t('admin_dash_supabase_active') : t('admin_dash_local_mode')}</Badge>
            <h2 style={{ margin: '12px 0 8px', fontFamily: "'Cormorant Garamond', serif", fontSize: isMobile ? '28px' : '30px', fontWeight: 700, lineHeight: 1.1 }}>{t('admin_dash_title')}</h2>
            <p style={{ margin: 0, color: 'rgba(250,240,232,0.68)', fontSize: '13px', lineHeight: 1.6, maxWidth: '620px' }}>
              {t('admin_dash_desc')}
            </p>
          </div>
          <div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap', justifyContent: isMobile ? 'stretch' : 'flex-end' }}>
            <Btn variant="secondary" onClick={() => navigate('admin-designs', { action: 'new' })} style={isMobile ? { flex: '1 1 0', minWidth: 0, justifyContent: 'center', paddingLeft: '10px', paddingRight: '10px' } : undefined}>{t('admin_new_design')}</Btn>
            <Btn variant="ghost" style={{ borderColor: 'rgba(250,240,232,0.25)', color: 'var(--bg)', ...(isMobile ? { flex: '1 1 0', minWidth: 0, justifyContent: 'center', paddingLeft: '10px', paddingRight: '10px' } : {}) }} onClick={() => navigate('admin-desserts', { action: 'new' })}>{t('admin_new_dessert')}</Btn>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px' }}>
          {quickActions.map(action => (
            <button key={action.id} onClick={() => navigate(action.page, action.data || {})} style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '16px', padding: '16px', cursor: 'pointer', textAlign: 'left', display: 'flex', flexDirection: 'column', gap: '10px', minHeight: '118px' }}>
              <div style={{ width: '34px', height: '34px', borderRadius: '11px', background: `${action.color}18`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <Icon name={action.icon} size={17} color={action.color} />
              </div>
              <div>
                <div style={{ fontSize: '13px', fontWeight: 800, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{action.label}</div>
                <div style={{ fontSize: '11px', color: 'var(--muted)', marginTop: '3px' }}>{action.desc}</div>
              </div>
            </button>
          ))}
        </div>
      </div>

      {/* Main grid */}
      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: '20px', alignItems: 'flex-start' }} className="dash-grid">
        {/* Recent quotes */}
        <AdminPanelCard title={t('admin_recent_quotes')} action={t('admin_view_all')} onAction={() => navigate('admin-quotes')}>
          <div>
            {recentQuotes.map((q, i) => (
              <div key={q.id} style={{ padding: '14px 22px', borderBottom: i < recentQuotes.length - 1 ? '1px solid var(--border)' : 'none', display: 'flex', alignItems: 'center', gap: '14px' }}>
                <div style={{ width: '38px', height: '38px', borderRadius: '50%', background: 'var(--accent-light)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: "'Cormorant Garamond', serif", fontSize: '15px', fontWeight: 700, color: 'var(--primary)', flexShrink: 0 }}>
                  {q.clientName.split(' ').map(n => n[0]).join('').slice(0,2)}
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: '14px', fontWeight: 600, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif", whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{q.clientName}</div>
                  <div style={{ fontSize: '12px', color: 'var(--muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{q.designName}</div>
                </div>
                <div style={{ textAlign: 'right', flexShrink: 0 }}>
                  <div style={{ fontSize: '14px', fontWeight: 700, color: 'var(--text)', fontFamily: "'Cormorant Garamond', serif" }}>${q.total.toLocaleString()}</div>
                  <StatusBadge status={q.status} />
                </div>
              </div>
            ))}
          </div>
        </AdminPanelCard>
        {/* Upcoming events */}
        <AdminPanelCard title={t('admin_upcoming_events')} action={t('admin_calendar_short')} onAction={() => navigate('admin-calendar')}>
          <div>
            {upcoming.map((ev, i) => (
              <div key={ev.id} style={{ padding: '13px 22px', borderBottom: i < upcoming.length - 1 ? '1px solid var(--border)' : 'none', display: 'flex', gap: '14px', alignItems: 'center' }}>
                <div style={{ width: '40px', height: '40px', borderRadius: '12px', background: `${ev.color}20`, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', flexShrink: 0, border: `1.5px solid ${ev.color}40` }}>
                  <div style={{ fontSize: '14px', fontWeight: 700, color: ev.color, lineHeight: 1, fontFamily: "'Cormorant Garamond', serif" }}>{ev.date.split('-')[2]}</div>
                  <div style={{ fontSize: '9px', color: ev.color, textTransform: 'uppercase', letterSpacing: '0.05em', fontFamily: "'DM Sans', sans-serif", opacity: 0.8 }}>
                    {new Date(ev.date + 'T12:00:00').toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { month: 'short' })}
                  </div>
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: '13.5px', fontWeight: 600, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif", whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{ev.name}</div>
                  <div style={{ fontSize: '12px', color: 'var(--muted)' }}>{ev.client} · {ev.time}h</div>
                </div>
                <StatusBadge status={ev.status} />
              </div>
            ))}
          </div>
        </AdminPanelCard>
      </div>
    </AdminLayout>
  );
}

// ─── Quotes Admin Page ───────────────────────────────────────────
function addHoursToTime(time = '10:00', duration = 2) {
  const [h, m] = String(time || '10:00').split(':').map(Number);
  const date = new Date(2000, 0, 1, Number.isFinite(h) ? h : 10, Number.isFinite(m) ? m : 0);
  date.setMinutes(date.getMinutes() + (Number(duration || 2) * 60));
  return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
}

function toGoogleCalendarStamp(date, time = '10:00') {
  return `${String(date || '').replace(/-/g, '')}T${String(time || '10:00').replace(':', '').padEnd(4, '0')}00`;
}

function getGoogleCalendarUrl(event, quote) {
  if (!event?.date) return '#';
  const start = toGoogleCalendarStamp(event.date, event.time);
  const end = toGoogleCalendarStamp(event.date, addHoursToTime(event.time, event.duration));
  const details = [
    quote?.id ? `Cotizacion: ${quote.id}` : null,
    event.client ? `Cliente: ${event.client}` : null,
    event.contact ? `Contacto: ${event.contact}` : null,
    eventServiceLabel(event) ? `Areas: ${eventServiceLabel(event)}` : null,
    event.designName ? `Decoracion: ${event.designName}` : null,
    event.notes || event.details || null,
  ].filter(Boolean).join('\n\n');
  const params = new URLSearchParams({
    action: 'TEMPLATE',
    text: event.name || quote?.designName || 'Evento Lelusa',
    dates: `${start}/${end}`,
    details,
    location: event.eventPlace || '',
  });
  return `https://calendar.google.com/calendar/render?${params.toString()}`;
}

function openGoogleCalendarEvent(event, quote) {
  const url = getGoogleCalendarUrl(event, quote);
  if (url !== '#') window.open(url, '_blank', 'noopener,noreferrer');
}

function ApprovalCalendarModal({ open, event, quote, onClose, onViewEvent }) {
  const { t } = window.ReactI18next.useTranslation();
  if (!open || !event) return null;

  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 420, background: 'rgba(58,42,32,0.42)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '20px', backdropFilter: 'blur(4px)' }} onClick={onClose}>
      <div style={{ width: '100%', maxWidth: 480, background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '20px', boxShadow: '0 28px 80px rgba(58,42,32,0.22)', padding: '22px' }} onClick={e => e.stopPropagation()}>
        <div style={{ width: 48, height: 48, borderRadius: '16px', background: 'var(--accent-light)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 14 }}>
          <Icon name="calendar" size={22} color="var(--primary)" />
        </div>
        <h3 style={{ margin: '0 0 8px', fontFamily: "'Cormorant Garamond', serif", fontSize: 26, color: 'var(--text)' }}>{t('admin_event_approved_modal_title')}</h3>
        <p style={{ margin: '0 0 18px', color: 'var(--muted)', lineHeight: 1.6, fontSize: 14 }}>{t('admin_event_approved_modal_desc')}</p>
        <div style={{ background: 'var(--bg-soft)', border: '1px solid var(--border)', borderRadius: '14px', padding: '12px 14px', marginBottom: 18 }}>
          <div style={{ fontWeight: 800, color: 'var(--text)', fontSize: 14 }}>{event.name}</div>
          <div style={{ color: 'var(--muted)', fontSize: 12, marginTop: 4 }}>{event.date} · {event.time || '10:00'} · {event.eventPlace || t('admin_event_place_pending')}</div>
        </div>
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
          <Btn variant="ghost" onClick={onClose}>{t('admin_event_close')}</Btn>
          <Btn variant="ghost" onClick={() => onViewEvent?.(event)}>{t('admin_event_open_detail')}</Btn>
          <Btn onClick={() => openGoogleCalendarEvent(event, quote)}>
            <Icon name="calendar" size={15} color="#fff" /> {t('admin_event_add_google')}
          </Btn>
        </div>
      </div>
    </div>
  );
}

function getAdminQuoteSelections(quote, designs) {
  const design = (designs || []).find(item => String(item.id) === String(quote.designId));
  const optionLabels = quote.selectedOptionLabels || (design?.options || []).map(option => {
    const selectedId = quote.selectedOptions?.[option.id];
    const choice = (option.choices || []).find(item => String(item.id) === String(selectedId));
    return choice ? `${option.name}: ${choice.label}` : null;
  }).filter(Boolean);
  const extraLabels = quote.selectedExtraLabels || (design?.extras || []).filter(extra =>
    (quote.selectedExtras || []).some(id => String(id) === String(extra.id))
  ).map(extra => `${extra.name} (+$${Number(extra.price || 0).toLocaleString()})`);
  return { optionLabels, extraLabels };
}

function QuotesPage() {
  const { navigate } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const { quotes, designs, events } = window.LelusaStore.useBusinessData();
  const [filterStatus, setFilterStatus] = React.useState('all');
  const [search, setSearch] = React.useState('');
  const [selected, setSelected] = React.useState(null);
  const [approvedModal, setApprovedModal] = React.useState(null);

  const isMobile = window.LelusaGestures.useIsMobile();
  const STATUS_META = {
    pendiente:  { color: '#C8881A' },
    revision:   { color: '#3A62C8' },
    aprobada:   { color: '#2A8A50' },
    rechazada:  { color: '#C83A3A' },
    completada: { color: '#6A4AC8' },
    cancelada:  { color: '#8B7068' },
  };

  const statusOptions = [
    { id: 'all', label: t('admin_quotes_filter_all') },
    { id: 'pendiente', label: t('admin_quotes_filter_pending') },
    { id: 'revision', label: t('admin_quotes_filter_review') },
    { id: 'aprobada', label: t('admin_quotes_filter_approved') },
    { id: 'rechazada', label: t('admin_quotes_filter_rejected') },
    { id: 'completada', label: t('admin_quotes_filter_completed') },
  ];

  const filtered = quotes.filter(q => {
    const matchStatus = filterStatus === 'all' || q.status === filterStatus;
    const matchSearch = !search || q.clientName.toLowerCase().includes(search.toLowerCase()) || q.designName.toLowerCase().includes(search.toLowerCase()) || q.id.toLowerCase().includes(search.toLowerCase());
    return matchStatus && matchSearch;
  });

  const counts = statusOptions.reduce((acc, s) => {
    acc[s.id] = s.id === 'all' ? quotes.length : quotes.filter(q => q.status === s.id).length;
    return acc;
  }, {});

  const setQuoteStatus = (quote, status) => {
    const updated = window.LelusaStore.updateQuoteStatus(quote.id, status);
    if (updated) setSelected(updated);
  };

  const approveAndSchedule = (quote) => {
    const result = window.LelusaStore.convertQuoteToEvent(quote.id);
    if (result?.quote) setSelected(result.quote);
    if (result?.event) setApprovedModal({ event: result.event, quote: result.quote || quote });
  };

  const resendEventConfirmation = async (quote) => {
    const event = (events || []).find(item => String(item.quoteId) === String(quote.id) && item.department !== 'postres');
    if (!event) {
      alert(t('admin_quotes_resend_no_event'));
      return;
    }
    const res = await window.LelusaEmailEvents?.onEventApproved?.(event, quote, { force: true });
    alert(res?.ok ? t('admin_quotes_resend_success') : t('admin_quotes_resend_error'));
  };

  const addDessertsToQuote = (quote) => {
    const updated = window.LelusaStore.updateQuote(quote.id, {
      dessertRequest: quote.dessertRequest || {
        notes: t('admin_quotes_dessert_note_default'),
        items: [],
      },
    });
    if (updated) setSelected(updated);
  };

  return (
    <AdminLayout title={t('admin_quotes')} subtitle={t('admin_quotes_subtitle', { count: quotes.length })}>
      {/* Stats row */}
      <div style={{ display: 'grid', gridTemplateColumns: isMobile ? 'repeat(2, minmax(0, 1fr))' : 'repeat(auto-fill, minmax(150px, 1fr))', gap: isMobile ? '10px' : '14px', marginBottom: isMobile ? '18px' : '24px' }}>
        {[
          { id: 'pendiente', label: t('admin_quotes_stat_pending'), count: counts.pendiente || 0, color: '#C8881A' },
          { id: 'revision', label: t('admin_quotes_stat_review'), count: counts.revision || 0, color: '#3A62C8' },
          { id: 'aprobada', label: t('admin_quotes_stat_approved'),  count: counts.aprobada || 0, color: '#2A8A50' },
          { id: 'completada', label: t('admin_quotes_stat_completed'),count: counts.completada || 0, color: '#6A4AC8' },
        ].map(s => (
          <div key={s.id} className="lel-quote-stat-card" style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '16px', padding: '16px 18px' }}>
            <div className="lel-quote-stat-value" style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: '28px', fontWeight: 700, color: s.color }}>{s.count}</div>
            <div className="lel-quote-stat-label" style={{ fontSize: '12px', color: 'var(--muted)' }}>{s.label}</div>
          </div>
        ))}
      </div>
      {/* Filters + search */}
      <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '20px', overflow: 'hidden' }}>
        <div style={{ padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
          <div style={{ position: 'relative', flex: 1, minWidth: '200px' }}>
            <Icon name="search" size={15} color="var(--muted)" style={{ position: 'absolute', left: '12px', top: '50%', transform: 'translateY(-50%)' }} />
            <input value={search} onChange={e => setSearch(e.target.value)} placeholder={t('admin_quotes_search_ph')}
              style={{ width: '100%', padding: '9px 12px 9px 36px', background: 'var(--bg-soft)', border: '1px solid var(--border)', borderRadius: '10px', fontFamily: "'DM Sans', sans-serif", fontSize: '13px', color: 'var(--text)', outline: 'none', boxSizing: 'border-box' }} />
          </div>
          <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
            {statusOptions.map(s => (
              <button key={s.id} onClick={() => setFilterStatus(s.id)}
                style={{ padding: '7px 14px', borderRadius: '999px', border: `1.5px solid ${filterStatus === s.id ? 'var(--primary)' : 'var(--border)'}`, background: filterStatus === s.id ? 'var(--accent-light)' : 'transparent', color: filterStatus === s.id ? 'var(--primary)' : 'var(--muted)', fontFamily: "'DM Sans', sans-serif", fontSize: '12px', fontWeight: filterStatus === s.id ? 600 : 400, cursor: 'pointer', transition: 'all 0.15s' }}>
                {s.label} {counts[s.id] > 0 && <span style={{ fontWeight: 700 }}>({counts[s.id]})</span>}
              </button>
            ))}
          </div>
        </div>
        {/* Mobile: compact list */}
        {isMobile && (
          <div>
            {filtered.length === 0 ? (
              <div style={{ padding: '40px', textAlign: 'center', color: 'var(--muted)', fontSize: '14px' }}>{t('admin_quotes_none')}</div>
            ) : filtered.map(q => {
              const meta = STATUS_META[q.status] || { color: 'var(--muted)' };
              return (
                <AdminListRow key={q.id} icon="fileText" title={q.clientName}
                  subtitle={`${q.eventType} · ${new Date(q.eventDate + 'T12:00:00').toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { day: 'numeric', month: 'short' })}`}
                  value={`$${q.total.toLocaleString()}`} badge={window.LelusaStatusLabel(q.status)} badgeColor={meta.color}
                  onClick={() => setSelected(q)} />
              );
            })}
          </div>
        )}
        {/* Desktop: table */}
        <div style={{ overflowX: 'auto', display: isMobile ? 'none' : 'block' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontFamily: "'DM Sans', sans-serif" }}>
            <thead>
              <tr style={{ borderBottom: '1px solid var(--border)' }}>
                {[
                  { id: 'id', label: t('admin_quotes_col_id') },
                  { id: 'client', label: t('admin_quotes_col_client') },
                  { id: 'design', label: t('admin_quotes_col_design') },
                  { id: 'event', label: t('admin_quotes_col_event') },
                  { id: 'eventDate', label: t('admin_quotes_col_event_date') },
                  { id: 'total', label: t('admin_quotes_col_total') },
                  { id: 'status', label: t('admin_quotes_col_status') },
                  { id: 'actions', label: t('admin_quotes_col_actions') },
                ].map(h => (
                  <th key={h.id} style={{ padding: '12px 16px', fontSize: '11px', color: 'var(--muted)', fontWeight: 600, letterSpacing: '0.07em', textTransform: 'uppercase', textAlign: 'left', whiteSpace: 'nowrap' }}>{h.label}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {filtered.length === 0 ? (
                <tr><td colSpan={8} style={{ padding: '48px', textAlign: 'center', color: 'var(--muted)', fontSize: '14px' }}>{t('admin_quotes_none')}</td></tr>
              ) : filtered.map((q, i) => (
                <tr key={q.id} style={{ borderBottom: i < filtered.length - 1 ? '1px solid var(--border)' : 'none', transition: 'background 0.1s' }}
                  onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-soft)'}
                  onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                  <td style={{ padding: '14px 16px', fontSize: '12px', color: 'var(--muted)', fontWeight: 500, whiteSpace: 'nowrap' }}>{q.id}</td>
                  <td style={{ padding: '14px 16px' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
                      <div style={{ width: '32px', height: '32px', borderRadius: '50%', background: 'var(--accent-light)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: "'Cormorant Garamond', serif", fontSize: '13px', fontWeight: 700, color: 'var(--primary)', flexShrink: 0 }}>
                        {q.clientName.split(' ').map(n => n[0]).join('').slice(0,2)}
                      </div>
                      <div>
                        <div style={{ fontSize: '13.5px', fontWeight: 600, color: 'var(--text)', whiteSpace: 'nowrap' }}>{q.clientName}</div>
                        <div style={{ fontSize: '11px', color: 'var(--muted)' }}>{t('admin_quotes_guests', { count: q.guests })}</div>
                      </div>
                    </div>
                  </td>
                  <td style={{ padding: '14px 16px', fontSize: '13px', color: 'var(--text)', whiteSpace: 'nowrap', maxWidth: '160px', overflow: 'hidden', textOverflow: 'ellipsis' }}>{q.designName}</td>
                  <td style={{ padding: '14px 16px', fontSize: '13px', color: 'var(--muted)', whiteSpace: 'nowrap' }}>{q.eventType}</td>
                  <td style={{ padding: '14px 16px', fontSize: '13px', color: 'var(--muted)', whiteSpace: 'nowrap' }}>
                    {new Date(q.eventDate + 'T12:00:00').toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { day: 'numeric', month: 'short', year: 'numeric' })}
                  </td>
                  <td style={{ padding: '14px 16px', whiteSpace: 'nowrap' }}>
                    <span style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: '18px', fontWeight: 700, color: 'var(--text)' }}>${q.total.toLocaleString()}</span>
                  </td>
                  <td style={{ padding: '14px 16px' }}><StatusBadge status={q.status} /></td>
                  <td style={{ padding: '14px 16px' }}>
                    <div style={{ display: 'flex', gap: '6px' }}>
                      <button onClick={() => setSelected(q)}
                        style={{ background: 'var(--bg-soft)', border: '1px solid var(--border)', borderRadius: '8px', padding: '6px 10px', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '4px', fontSize: '12px', color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>
                        <Icon name="eye" size={13} color="var(--muted)" /> {t('admin_quotes_view')}
                      </button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
      {/* Detail Modal */}
      {selected && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(58,42,32,0.4)', zIndex: 200, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '20px', backdropFilter: 'blur(4px)' }} onClick={() => setSelected(null)}>
          <div style={{ background: 'var(--card)', borderRadius: '24px', padding: '28px', maxWidth: '520px', width: '100%', maxHeight: '80vh', overflowY: 'auto', boxShadow: '0 24px 60px rgba(58,42,32,0.2)' }} onClick={e => e.stopPropagation()}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: '20px' }}>
              <div>
                <div style={{ fontSize: '12px', color: 'var(--muted)', marginBottom: '4px' }}>{selected.id}</div>
                <h2 style={{ margin: 0, fontFamily: "'Cormorant Garamond', serif", fontSize: '26px', fontWeight: 600, color: 'var(--text)' }}>{selected.clientName}</h2>
              </div>
              <button onClick={() => setSelected(null)} style={{ background: 'var(--bg-soft)', border: '1px solid var(--border)', borderRadius: '999px', padding: '8px', cursor: 'pointer' }}>
                <Icon name="x" size={16} color="var(--muted)" />
              </button>
            </div>
            <StatusBadge status={selected.status} />
            <div style={{ marginTop: '20px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px' }}>
              {[
                { id: 'design', label: t('admin_quotes_field_design'), value: selected.designName },
                { id: 'eventType', label: t('admin_quotes_field_event_type'), value: selected.eventType },
                { id: 'eventDate', label: t('admin_quotes_field_event_date'), value: new Date(selected.eventDate + 'T12:00:00').toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { day: 'numeric', month: 'long', year: 'numeric' }) },
                { id: 'eventTime', label: t('admin_quotes_field_event_time'), value: selected.eventTime || t('admin_quotes_to_confirm') },
                { id: 'guests', label: t('admin_quotes_field_guests'), value: selected.guests },
                { id: 'phone', label: t('admin_quotes_field_phone'), value: selected.phone },
                { id: 'email', label: t('admin_quotes_field_email'), value: selected.email },
                { id: 'contactPref', label: t('admin_quotes_field_contact_pref'), value: selected.contactPreference || t('admin_quotes_not_indicated') },
                { id: 'place', label: t('admin_quotes_field_place'), value: selected.eventPlace },
                { id: 'setup', label: t('admin_quotes_field_setup'), value: selected.setupWindow || t('admin_quotes_to_confirm') },
                { id: 'sent', label: t('admin_quotes_field_sent'), value: selected.createdAt },
              ].map(({ id, label, value }) => (
                <div key={id} style={{ background: 'var(--bg-soft)', borderRadius: '12px', padding: '12px 14px' }}>
                  <div style={{ fontSize: '11px', color: 'var(--muted)', letterSpacing: '0.05em', textTransform: 'uppercase', marginBottom: '4px' }}>{label}</div>
                  <div style={{ fontSize: '14px', color: 'var(--text)', fontWeight: 500 }}>{value}</div>
                </div>
              ))}
            </div>
            {(() => {
              const details = selected.decorationDetails || {};
              const selectionData = getAdminQuoteSelections(selected, designs);
              const detailItems = [
                { id: 'focus', label: t('admin_quotes_detail_focus'), value: details.focus },
                { id: 'theme', label: t('admin_quotes_detail_theme'), value: details.theme },
                { id: 'colors', label: t('admin_quotes_detail_colors'), value: details.colors },
                { id: 'mustHave', label: t('admin_quotes_detail_musthave'), value: details.mustHave },
                { id: 'budget', label: t('admin_quotes_detail_budget'), value: details.budgetRange },
                { id: 'custom', label: t('admin_quotes_detail_custom'), value: details.customBrief },
              ].filter(item => item.value);
              if (!selectionData.optionLabels.length && !selectionData.extraLabels.length && !detailItems.length) return null;
              return (
                <div style={{ marginTop: '14px', background: 'var(--bg-soft)', borderRadius: '14px', padding: '14px' }}>
                  <strong style={{ display: 'block', marginBottom: '10px', color: 'var(--text)', fontSize: '13px' }}>{t('admin_quotes_selected_decoration')}</strong>
                  {selectionData.optionLabels.length > 0 && (
                    <div style={{ marginBottom: '10px' }}>
                      <div style={{ fontSize: '11px', color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '5px' }}>{t('admin_quotes_options')}</div>
                      {selectionData.optionLabels.map(label => <div key={label} style={{ fontSize: '13px', color: 'var(--text)', lineHeight: 1.5 }}>{label}</div>)}
                    </div>
                  )}
                  {selectionData.extraLabels.length > 0 && (
                    <div style={{ marginBottom: '10px' }}>
                      <div style={{ fontSize: '11px', color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '5px' }}>{t('admin_quotes_extras')}</div>
                      <div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px' }}>
                        {selectionData.extraLabels.map(label => <span key={label} style={{ fontSize: '12px', color: 'var(--primary)', background: 'var(--accent-light)', borderRadius: '999px', padding: '4px 9px' }}>{label}</span>)}
                      </div>
                    </div>
                  )}
                  {detailItems.length > 0 && detailItems.map(({ id, label, value }) => (
                    <div key={id} style={{ display: 'flex', justifyContent: 'space-between', gap: '12px', borderTop: '1px solid var(--border)', paddingTop: '8px', marginTop: '8px', fontSize: '13px' }}>
                      <span style={{ color: 'var(--muted)' }}>{label}</span>
                      <span style={{ color: 'var(--text)', fontWeight: 600, textAlign: 'right' }}>{value}</span>
                    </div>
                  ))}
                  {Array.isArray(details.inspirationImages) && details.inspirationImages.length > 0 && (
                    <div style={{ borderTop: '1px solid var(--border)', paddingTop: '10px', marginTop: '10px' }}>
                      <div style={{ fontSize: '11px', color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '8px' }}>{t('admin_quotes_inspirations')}</div>
                      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(74px, 1fr))', gap: '8px' }}>
                        {details.inspirationImages.map((image, index) => (
                          <img key={`${image.name || 'inspiracion'}-${index}`} src={image.dataUrl} alt={image.name || t('admin_quotes_inspiration_alt')} style={{ width: '100%', aspectRatio: '1', objectFit: 'cover', borderRadius: '10px', border: '1px solid var(--border)', background: 'var(--card)' }} />
                        ))}
                      </div>
                    </div>
                  )}
                </div>
              );
            })()}
            {selected.notes && (
              <div style={{ marginTop: '14px', background: 'var(--accent-light)', borderRadius: '12px', padding: '14px', fontSize: '13px', color: 'var(--muted)' }}>
                <strong style={{ display: 'block', marginBottom: '4px', color: 'var(--text)' }}>{t('admin_quotes_notes')}</strong>
                <div style={{ whiteSpace: 'pre-wrap', lineHeight: 1.55 }}>{selected.notes}</div>
              </div>
            )}
            <div style={{ marginTop: '14px', background: selected.dessertRequest ? 'rgba(200,136,26,0.12)' : 'var(--bg-soft)', border: '1px solid var(--border)', borderRadius: '14px', padding: '14px' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', gap: '12px', alignItems: 'center' }}>
                <div>
                  <strong style={{ display: 'block', color: 'var(--text)', fontSize: '13px' }}>{t('admin_quotes_dessert_service')}</strong>
                  <span style={{ fontSize: '12px', color: 'var(--muted)', lineHeight: 1.45 }}>
                    {selected.dessertRequest ? (selected.dessertRequest.notes || t('admin_quotes_dessert_requested')) : t('admin_quotes_dessert_mark')}
                  </span>
                </div>
                {selected.dessertRequest ? (
                  <Badge color="warm">{t('admin_quotes_dessert_included')}</Badge>
                ) : (
                  <Btn size="sm" variant="ghost" onClick={() => addDessertsToQuote(selected)}>
                    <Icon name="sparkles" size={14} /> {t('admin_quotes_add')}
                  </Btn>
                )}
              </div>
            </div>
            <div style={{ marginTop: '20px', borderTop: '1px solid var(--border)', paddingTop: '16px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <div>
                <div style={{ fontSize: '12px', color: 'var(--muted)' }}>{t('admin_quotes_total_quoted')}</div>
                <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: '32px', fontWeight: 700, color: 'var(--primary)' }}>${selected.total.toLocaleString()}</div>
              </div>
              <div style={{ display: 'flex', gap: '8px' }}>
                {selected.status === 'pendiente' && (
                  <>
                    <Btn size="sm" variant="ghost" style={{ borderColor: '#E07070', color: '#E07070' }} onClick={() => setQuoteStatus(selected, 'rechazada')}>{t('admin_quotes_reject')}</Btn>
                    <Btn size="sm" onClick={() => approveAndSchedule(selected)}>{t('admin_quotes_approve_schedule')}</Btn>
                  </>
                )}
                {selected.status === 'revision' && (
                  <Btn size="sm" onClick={() => setQuoteStatus(selected, 'pendiente')}>{t('admin_quotes_mark_pending')}</Btn>
                )}
                {selected.status === 'aprobada' && (
                  <>
                    <Btn size="sm" variant="ghost" onClick={() => resendEventConfirmation(selected)}>{t('admin_quotes_resend_confirmation')}</Btn>
                    {events.find(item => String(item.quoteId) === String(selected.id) && item.department !== 'postres') && (
                      <Btn size="sm" variant="ghost" onClick={() => openGoogleCalendarEvent(events.find(item => String(item.quoteId) === String(selected.id) && item.department !== 'postres'), selected)}>{t('admin_event_add_google')}</Btn>
                    )}
                    <Btn size="sm" variant="ghost" onClick={() => navigate('admin-calendar')}>{t('admin_quotes_view_calendar')}</Btn>
                  </>
                )}
              </div>
            </div>
          </div>
        </div>
      )}
      <ApprovalCalendarModal
        open={Boolean(approvedModal)}
        event={approvedModal?.event}
        quote={approvedModal?.quote}
        onClose={() => setApprovedModal(null)}
        onViewEvent={(event) => {
          setApprovedModal(null);
          navigate('admin-event-detail', { eventId: event.id });
        }}
      />
    </AdminLayout>
  );
}

// ─── Designs Admin Page ─────────────────────────────────────────
function DesignsPage() {
  const { pageData, navigate } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const { designs, assets, catalogCategories } = window.LelusaStore.useBusinessData();
  const designCategories = window.LelusaStore.getCatalogCategories(catalogCategories, 'design');
  const emptyForm = {
    name: '',
    category: CATEGORIES[0].id,
    price: '',
    description: '',
    image: '',
    images: [],
    status: 'draft',
    featured: false,
    includes: [],
    tags: [],
    assetIds: [],
    materials: [],
    options: [],
    extras: [],
    sceneAssets: [],
  };
  const [formOpen, setFormOpen] = React.useState(false);
  const [editingId, setEditingId] = React.useState(null);
  const [form, setForm] = React.useState(emptyForm);
  const [error, setError] = React.useState('');
  const isMobile = window.LelusaGestures.useIsMobile();
  const [mobileActions, setMobileActions] = React.useState(null);

  React.useEffect(() => {
    if (pageData.action !== 'new') return;
    resetForm();
    setFormOpen(true);
  }, [pageData.action]);

  const published = designs.filter(design => (design.status || 'published') === 'published');
  const drafts = designs.filter(design => (design.status || 'published') !== 'published');
  const selectedCategory = designCategories.find(item => item.slug === form.category) || designCategories[0] || CATEGORIES[0];
  const categoryLabelBySlug = Object.fromEntries(designCategories.map(item => [item.slug, item.name]));
  const designTotal = Number(form.price || 0) + form.extras.reduce((sum, extra) => sum + Number(extra.price || 0), 0);
  const designMarginHint = form.materials.reduce((sum, material) => {
    const asset = assets.find(item => String(item.id) === String(material.assetId));
    return sum + (Number(asset?.internalCost || 0) * Math.max(1, Number(material.quantity || 1)));
  }, 0);

  const inputStyle = ADMIN_INPUT_STYLE;

  const set = (key, value) => setForm(current => ({ ...current, [key]: value }));
  const getDesignMaterials = (source) => {
    const materials = Array.isArray(source.materials) && source.materials.length
      ? source.materials
      : (source.assetIds || []).map((assetId, index) => ({ assetId, quantity: 1, required: true, sortOrder: index }));
    return materials
      .filter(item => item && item.assetId !== undefined && item.assetId !== null && item.assetId !== '')
      .map((item, index) => ({
        assetId: item.assetId,
        quantity: String(item.quantity || 1),
        role: item.role || '',
        variant: item.variant || '',
        notes: item.notes || '',
        required: item.required !== false,
        sortOrder: item.sortOrder ?? index,
      }));
  };

  const buildPayload = () => {
    const options = form.options
      .filter(option => option.name.trim())
      .map(option => ({
        id: option.id.trim() || option.name.toLowerCase().replace(/\s+/g, '_'),
        name: option.name.trim(),
        type: option.type,
        choices: (option.choices || [])
          .filter(choice => choice.label.trim())
          .map(choice => ({
            id: choice.id.trim() || choice.label.toLowerCase().replace(/\s+/g, '_'),
            label: choice.label.trim(),
            color: option.type === 'color' ? choice.color : '',
            price: Number(choice.price) || 0,
          })),
      }));
    const extras = form.extras
      .filter(extra => extra.name.trim())
      .map(extra => ({
        id: extra.id.trim() || extra.name.toLowerCase().replace(/\s+/g, '_'),
        name: extra.name.trim(),
        price: Number(extra.price) || 0,
      }));
    const materials = form.materials
      .filter(material => material.assetId)
      .map((material, index) => ({
        assetId: material.assetId,
        quantity: Math.max(1, Number(material.quantity || 1)),
        role: material.role.trim(),
        variant: material.variant.trim(),
        notes: material.notes.trim(),
        required: material.required !== false,
        sortOrder: index,
      }));
    return {
      name: form.name.trim(),
      category: form.category,
      price: Number(form.price) || 0,
      description: form.description.trim(),
      image: form.image.trim(),
      images: Array.from(new Set([form.image.trim(), ...(form.images || [])].filter(Boolean))),
      status: form.status,
      featured: Boolean(form.featured),
      includes: form.includes,
      tags: form.tags,
      assetIds: materials.map(material => material.assetId),
      materials,
      options,
      extras,
      scene_assets: form.sceneAssets,
    };
  };

  const resetForm = () => {
    setEditingId(null);
    setError('');
    setForm({ ...emptyForm, category: designCategories[0]?.slug || CATEGORIES[0].id });
  };

  const editDesign = (design) => {
    setEditingId(design.id);
    setForm({
      name: design.name || '',
      category: design.category || designCategories[0]?.slug || CATEGORIES[0].id,
      price: design.price || '',
      description: design.description || '',
      image: design.image || '',
      images: Array.from(new Set([design.image, ...(design.images || [])].filter(Boolean))),
      status: design.status || 'draft',
      featured: Boolean(design.featured),
      includes: design.includes || [],
      tags: design.tags || [],
      assetIds: design.assetIds || [],
      materials: getDesignMaterials(design),
      options: (design.options || []).map(option => ({
        ...option,
        choices: (option.choices || []).map(choice => ({ ...choice, price: String(choice.price || 0) })),
      })),
      extras: (design.extras || []).map(extra => ({ ...extra, price: String(extra.price || 0) })),
      sceneAssets: design.scene_assets || [],
    });
    setFormOpen(true);
    setError('');
  };

  const submit = (event) => {
    event.preventDefault();
    setError('');
    if (!form.name.trim()) {
      setError(t('admin_designs_name_required'));
      return;
    }
    try {
      const payload = buildPayload();
      if (editingId) window.LelusaStore.updateDesign(editingId, payload);
      else window.LelusaStore.addDesign(payload);
      resetForm();
      setFormOpen(false);
    } catch (submitError) {
      setError(submitError.message || String(submitError));
    }
  };

  const addMaterial = (assetId = '') => {
    const nextAssetId = assetId || (assets.find(asset => !form.materials.some(material => String(material.assetId) === String(asset.id)))?.id || '');
    if (!nextAssetId) return;
    if (form.materials.some(material => String(material.assetId) === String(nextAssetId))) return;
    set('materials', [
      ...form.materials,
      { assetId: nextAssetId, quantity: '1', role: '', variant: '', notes: '', required: true, sortOrder: form.materials.length },
    ]);
  };

  const updateMaterial = (index, key, value) => {
    set('materials', form.materials.map((material, i) => i === index ? { ...material, [key]: value } : material));
  };

  const removeMaterial = (index) => {
    set('materials', form.materials.filter((_, i) => i !== index));
  };

  const addOption = () => {
    set('options', [
      ...form.options,
      { id: `opcion_${form.options.length + 1}`, name: '', type: 'radio', choices: [{ id: 'incluido', label: 'Incluido', color: '#D4A8A8', price: '0' }] },
    ]);
  };
  const addPresetOption = (name, type, choices) => {
    const id = name.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '');
    if (form.options.some(option => option.id === id || option.name.toLowerCase() === name.toLowerCase())) return;
    set('options', [
      ...form.options,
      { id, name, type, choices },
    ]);
  };

  const updateOption = (index, key, value) => {
    set('options', form.options.map((option, i) => i === index ? { ...option, [key]: value } : option));
  };

  const removeOption = (index) => {
    set('options', form.options.filter((_, i) => i !== index));
  };

  const addChoice = (optionIndex) => {
    set('options', form.options.map((option, i) => i === optionIndex
      ? { ...option, choices: [...(option.choices || []), { id: '', label: '', color: '#D4A8A8', price: '0' }] }
      : option));
  };

  const updateChoice = (optionIndex, choiceIndex, key, value) => {
    set('options', form.options.map((option, i) => i === optionIndex
      ? {
          ...option,
          choices: (option.choices || []).map((choice, ci) => ci === choiceIndex ? { ...choice, [key]: value } : choice),
        }
      : option));
  };

  const removeChoice = (optionIndex, choiceIndex) => {
    set('options', form.options.map((option, i) => i === optionIndex
      ? { ...option, choices: (option.choices || []).filter((_, ci) => ci !== choiceIndex) }
      : option));
  };

  const addExtra = () => {
    set('extras', [...form.extras, { id: `extra_${form.extras.length + 1}`, name: '', price: '0' }]);
  };
  const addPresetExtra = (name, price) => {
    const id = name.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '');
    if (form.extras.some(extra => extra.id === id || extra.name.toLowerCase() === name.toLowerCase())) return;
    set('extras', [...form.extras, { id, name, price: String(price) }]);
  };

  const updateExtra = (index, key, value) => {
    set('extras', form.extras.map((extra, i) => i === index ? { ...extra, [key]: value } : extra));
  };

  const removeExtra = (index) => {
    set('extras', form.extras.filter((_, i) => i !== index));
  };

  return (
    <AdminLayout title={t('admin_designs')} subtitle={t('admin_designs_subtitle', { total: designs.length, published: published.length })}>
      <div className="lel-stat-grid" style={{ display: 'grid', gridTemplateColumns: isMobile ? 'repeat(2, minmax(0, 1fr))' : 'repeat(auto-fill, minmax(180px, 1fr))', gap: isMobile ? '10px' : '14px', marginBottom: isMobile ? '18px' : '22px' }}>
        <StatCard icon="grid" label={t('admin_designs_stat_total')} value={designs.length} sub={t('admin_designs_stat_total_sub')} color="var(--primary)" />
        <StatCard icon="eye" label={t('admin_designs_stat_published')} value={published.length} sub={t('admin_designs_stat_published_sub')} color="#2A8A50" />
        <StatCard icon="edit" label={t('admin_designs_stat_drafts')} value={drafts.length} sub={t('admin_designs_stat_drafts_sub')} color="#C8881A" />
      </div>

      <AdminCategoryManager
        title="Categorias de decoracion"
        subtitle="Estas categorias alimentan el catalogo publico y el formulario de decoraciones."
        type="design"
        categories={catalogCategories}
        usedValues={designs.map(item => item.category)}
      />

      <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '20px', overflow: 'hidden' }}>
        <div style={{ padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', gap: '12px', alignItems: 'center', flexWrap: 'wrap' }}>
          <div>
            <h3 style={{ margin: 0, fontSize: '15px', fontWeight: 600, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{t('admin_designs_packages_title')}</h3>
            <p style={{ margin: '4px 0 0', fontSize: '12px', color: 'var(--muted)' }}>{t('admin_designs_packages_desc')}</p>
          </div>
          <Btn onClick={() => { resetForm(); setFormOpen(true); }}>
            <Icon name="plus" size={15} color="#fff" />
            {t('admin_designs_new')}
          </Btn>
        </div>

        <AdminModal
          open={formOpen}
          title={editingId ? t('admin_designs_edit_title') : t('admin_designs_new_title')}
          subtitle={t('admin_designs_modal_subtitle')}
          onClose={() => { resetForm(); setFormOpen(false); }}
          footer={
            <>
              <Btn type="button" variant="ghost" onClick={() => { resetForm(); setFormOpen(false); }}>{t('admin_designs_cancel')}</Btn>
              <Btn type="submit" onClick={submit}>{editingId ? t('admin_designs_save_changes') : t('admin_designs_create')}</Btn>
            </>
          }
        >
          <form onSubmit={submit}>
            {error && <div style={{ background: '#FFE0E0', color: '#A33A3A', borderRadius: '10px', padding: '10px 12px', fontSize: '13px', marginBottom: '16px' }}>{error}</div>}
            <AdminFormSection title={t('admin_designs_section_info')} subtitle={t('admin_designs_section_info_sub')}>
              <AdminField label={t('admin_designs_field_name')}>
                <input required value={form.name} onChange={e => set('name', e.target.value)} placeholder="Baby Shower Boho" style={inputStyle} />
              </AdminField>
              <AdminField label={t('admin_designs_field_category')}>
                <select value={form.category} onChange={e => set('category', e.target.value)} style={inputStyle}>
                  {designCategories.map(item => <option key={item.slug} value={item.slug}>{item.name}</option>)}
                </select>
              </AdminField>
              <AdminField label={t('admin_designs_field_base_price')}>
                <input type="number" min="0" value={form.price} onChange={e => set('price', e.target.value)} placeholder="450" style={inputStyle} />
              </AdminField>
              <AdminImageGalleryField
                label={`${t('admin_designs_field_image')} / galeria`}
                primary={form.image}
                images={form.images}
                onChange={({ image, images }) => setForm(current => ({ ...current, image, images }))}
                hint="La primera imagen marcada como principal se usara en catalogo, cotizaciones y tarjetas."
                full
              />
              <div style={{ gridColumn: '1 / -1', display: 'grid', gridTemplateColumns: isMobile ? '1fr' : 'minmax(220px, 0.85fr) 1fr', gap: 12 }}>
                <div style={{ border: '1px solid var(--border)', borderRadius: 16, overflow: 'hidden', background: 'var(--bg-soft)' }}>
                  <div style={{ aspectRatio: '16/10', background: 'var(--card)', display: 'grid', placeItems: 'center' }}>
                    {form.image ? <img src={form.image} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} /> : <DecoPlaceholder category={form.category} />}
                  </div>
                  <div style={{ padding: 12 }}>
                    <div style={{ fontSize: 14, fontWeight: 800, color: 'var(--text)' }}>{form.name || 'Nuevo paquete'}</div>
                    <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 3 }}>{selectedCategory.name} · {form.status === 'published' ? t('admin_designs_status_published') : t('admin_designs_status_draft')}</div>
                    <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 10 }}>
                      <Badge color="sage">{form.materials.length} materiales</Badge>
                      <Badge color="primary">{form.options.length} opciones</Badge>
                      <Badge color="warm">{form.extras.length} extras</Badge>
                    </div>
                  </div>
                </div>
                <div style={{ border: '1px solid var(--border)', borderRadius: 16, padding: 14, background: 'var(--bg-soft)', display: 'flex', flexDirection: 'column', gap: 12 }}>
                  <div>
                    <div style={{ fontSize: 12, fontWeight: 800, color: 'var(--text)', textTransform: 'uppercase', letterSpacing: '0.07em' }}>Contexto del paquete</div>
                    <p style={{ margin: '5px 0 0', fontSize: 12, color: 'var(--muted)', lineHeight: 1.45 }}>{selectedCategory.description}</p>
                  </div>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 8 }}>
                    <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: 12, padding: 10 }}>
                      <div style={{ fontSize: 10, color: 'var(--muted)', fontWeight: 800 }}>BASE</div>
                      <div style={{ fontSize: 16, color: 'var(--text)', fontWeight: 800 }}>${Number(form.price || 0).toLocaleString()}</div>
                    </div>
                    <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: 12, padding: 10 }}>
                      <div style={{ fontSize: 10, color: 'var(--muted)', fontWeight: 800 }}>CON EXTRAS</div>
                      <div style={{ fontSize: 16, color: 'var(--text)', fontWeight: 800 }}>${designTotal.toLocaleString()}</div>
                    </div>
                    <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: 12, padding: 10 }}>
                      <div style={{ fontSize: 10, color: 'var(--muted)', fontWeight: 800 }}>COSTO MAT.</div>
                      <div style={{ fontSize: 16, color: designMarginHint > Number(form.price || 0) ? '#C83A3A' : 'var(--text)', fontWeight: 800 }}>${designMarginHint.toLocaleString()}</div>
                    </div>
                  </div>
                  <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                    {['boho', 'elegante', 'pastel', 'premium'].map(tag => (
                      <button key={tag} type="button" onClick={() => { if (!form.tags.includes(tag)) set('tags', [...form.tags, tag]); }}
                        style={{ border: 'none', background: form.tags.includes(tag) ? 'var(--accent-light)' : 'var(--card)', color: form.tags.includes(tag) ? 'var(--primary)' : 'var(--muted)', borderRadius: 999, padding: '6px 10px', cursor: 'pointer', fontSize: 11, fontWeight: 800 }}>
                        #{tag}
                      </button>
                    ))}
                  </div>
                </div>
              </div>
              {editingId && (
                <div style={{ marginTop: 24, marginBottom: 8 }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text)', marginBottom: 6 }}>{t('admin_designs_animated_scene')}</div>
                  <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 8 }}>{t('admin_designs_animated_scene_desc')}</div>
                  <Btn size="sm" variant="ghost" onClick={(e) => { e.stopPropagation(); setFormOpen(false); navigate('admin-scene-editor', { designId: editingId }); }}>
                    {t('admin_designs_edit_animation')}
                  </Btn>
                </div>
              )}
              <AdminField label={t('admin_designs_field_description')} full>
                <textarea value={form.description} onChange={e => set('description', e.target.value)} placeholder={t('admin_designs_description_ph')} rows={3} style={{ ...inputStyle, resize: 'vertical' }} />
              </AdminField>
            </AdminFormSection>

            <AdminFormSection title={t('admin_designs_section_publish')} columns={3}>
              <AdminField label={t('admin_designs_field_status')}>
                <select value={form.status} onChange={e => set('status', e.target.value)} style={inputStyle}>
                  <option value="draft">{t('admin_designs_status_draft')}</option>
                  <option value="published">{t('admin_designs_status_published')}</option>
                  <option value="archived">{t('admin_designs_status_archived')}</option>
                </select>
              </AdminField>
              <AdminField label={t('admin_designs_field_featured')}>
                <label style={{ minHeight: '39px', display: 'flex', alignItems: 'center', gap: '8px', fontSize: '13px', color: 'var(--text)' }}>
                  <input type="checkbox" checked={form.featured} onChange={e => set('featured', e.target.checked)} style={{ accentColor: 'var(--primary)' }} />
                  {t('admin_designs_show_favorites')}
                </label>
              </AdminField>
              <TagInput
                label={t('admin_designs_field_tags')}
                value={form.tags}
                onChange={v => set('tags', v)}
                placeholder={t('admin_designs_tags_ph')}
              />
              <TagInput
                label={t('admin_designs_field_includes')}
                value={form.includes}
                onChange={v => set('includes', v)}
                placeholder={t('admin_designs_includes_ph')}
                hint={t('admin_designs_includes_hint')}
                full
              />
            </AdminFormSection>

            <AdminFormSection title={t('admin_designs_section_materials')} subtitle={t('admin_designs_section_materials_sub')} columns={1}>
              <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
                {form.materials.length === 0 && (
                  <div style={{ border: '1px dashed var(--border)', borderRadius: '12px', padding: '18px', textAlign: 'center', color: 'var(--muted)', fontSize: '13px', background: 'var(--bg-soft)' }}>
                    {t('admin_designs_materials_empty')}
                  </div>
                )}
                {form.materials.map((material, index) => {
                  const selectedAsset = assets.find(asset => String(asset.id) === String(material.assetId));
                  return (
                    <div key={index} style={{ border: '1px solid var(--border)', borderRadius: '14px', padding: '12px', background: 'var(--bg-soft)' }}>
                      <div style={{ display: 'grid', gridTemplateColumns: '1.5fr 90px 1fr 1fr auto', gap: '8px', alignItems: 'end' }} className="form-row">
                        <AdminField label={t('admin_designs_field_asset')}>
                          <select value={material.assetId} onChange={e => updateMaterial(index, 'assetId', e.target.value)} style={inputStyle}>
                            {assets.map(asset => <option key={asset.id} value={asset.id}>{asset.name}</option>)}
                          </select>
                        </AdminField>
                        <AdminField label={t('admin_designs_field_quantity')}>
                          <input type="number" min="1" value={material.quantity} onChange={e => updateMaterial(index, 'quantity', e.target.value)} style={inputStyle} />
                        </AdminField>
                        <AdminField label={t('admin_designs_field_role')}>
                          <input value={material.role} onChange={e => updateMaterial(index, 'role', e.target.value)} placeholder={t('admin_designs_role_ph')} style={inputStyle} />
                        </AdminField>
                        <AdminField label={t('admin_designs_field_variant')}>
                          <input value={material.variant} onChange={e => updateMaterial(index, 'variant', e.target.value)} placeholder={t('admin_designs_variant_ph')} style={inputStyle} />
                        </AdminField>
                        <Btn type="button" variant="danger" size="sm" onClick={() => removeMaterial(index)}>{t('admin_designs_remove')}</Btn>
                      </div>
                      <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: '10px', alignItems: 'center', marginTop: '10px' }} className="form-row">
                        <input value={material.notes} onChange={e => updateMaterial(index, 'notes', e.target.value)} placeholder={t('admin_designs_notes_ph')} style={inputStyle} />
                        <label style={{ display: 'flex', alignItems: 'center', gap: '7px', color: 'var(--text)', fontSize: '12px', whiteSpace: 'nowrap' }}>
                          <input type="checkbox" checked={material.required !== false} onChange={e => updateMaterial(index, 'required', e.target.checked)} style={{ accentColor: 'var(--primary)' }} />
                          {t('admin_designs_required')}
                        </label>
                      </div>
                      {selectedAsset && (
                        <div style={{ marginTop: '8px', display: 'flex', flexWrap: 'wrap', gap: '6px', fontSize: '11px', color: 'var(--muted)' }}>
                          <span>{selectedAsset.category}</span>
                          <span>·</span>
                          <span>{t('admin_designs_in_stock', { count: selectedAsset.quantity })}</span>
                          {selectedAsset.color && <><span>·</span><span>{selectedAsset.color}</span></>}
                          {selectedAsset.size && <><span>·</span><span>{selectedAsset.size}</span></>}
                        </div>
                      )}
                    </div>
                  );
                })}
                <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
                  <Btn type="button" variant="ghost" onClick={() => addMaterial()} style={{ alignSelf: 'flex-start' }}>
                    <Icon name="plus" size={14} color="var(--primary)" />
                    {t('admin_designs_add_material')}
                  </Btn>
                  {assets.length === 0 && <span style={{ fontSize: '12px', color: 'var(--muted)', alignSelf: 'center' }}>{t('admin_designs_register_assets_first')}</span>}
                </div>
              </div>
            </AdminFormSection>

            <AdminFormSection title={t('admin_designs_section_options')} subtitle={t('admin_designs_section_options_sub')} columns={1}>
              <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
                <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                  <button type="button" onClick={() => addPresetOption('Paleta de color', 'color', [
                    { id: 'rosa', label: 'Rosa', color: '#E0A6BC', price: 0 },
                    { id: 'azul', label: 'Azul', color: '#A9C4D4', price: 0 },
                    { id: 'sage', label: 'Sage', color: '#A8BAB8', price: 0 },
                  ])} style={{ border: '1px solid var(--border)', background: 'var(--bg-soft)', color: 'var(--text)', borderRadius: 999, padding: '7px 11px', cursor: 'pointer', fontSize: 12, fontWeight: 800 }}>+ Paleta de color</button>
                  <button type="button" onClick={() => addPresetOption('Tamaño del montaje', 'radio', [
                    { id: 'compacto', label: 'Compacto', color: '', price: 0 },
                    { id: 'premium', label: 'Premium', color: '', price: 750 },
                    { id: 'full', label: 'Full setup', color: '', price: 1500 },
                  ])} style={{ border: '1px solid var(--border)', background: 'var(--bg-soft)', color: 'var(--text)', borderRadius: 999, padding: '7px 11px', cursor: 'pointer', fontSize: 12, fontWeight: 800 }}>+ Tamaño</button>
                  <button type="button" onClick={() => addPresetOption('Personalización', 'radio', [
                    { id: 'sin_texto', label: 'Sin texto', color: '', price: 0 },
                    { id: 'nombre', label: 'Nombre', color: '', price: 250 },
                    { id: 'nombre_frase', label: 'Nombre + frase', color: '', price: 450 },
                  ])} style={{ border: '1px solid var(--border)', background: 'var(--bg-soft)', color: 'var(--text)', borderRadius: 999, padding: '7px 11px', cursor: 'pointer', fontSize: 12, fontWeight: 800 }}>+ Personalización</button>
                </div>
                {form.options.map((option, optionIndex) => (
                  <div key={optionIndex} style={{ border: '1px solid var(--border)', borderRadius: '14px', padding: '14px', background: 'var(--bg-soft)' }}>
                    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 140px auto', gap: '10px', alignItems: 'end' }} className="form-row">
                      <AdminField label={t('admin_designs_field_id')}>
                        <input value={option.id} onChange={e => updateOption(optionIndex, 'id', e.target.value)} placeholder="balloon_color" style={inputStyle} />
                      </AdminField>
                      <AdminField label={t('admin_designs_field_option_name')}>
                        <input value={option.name} onChange={e => updateOption(optionIndex, 'name', e.target.value)} placeholder={t('admin_designs_option_name_ph')} style={inputStyle} />
                      </AdminField>
                      <AdminField label={t('admin_designs_field_type')}>
                        <select value={option.type} onChange={e => updateOption(optionIndex, 'type', e.target.value)} style={inputStyle}>
                          <option value="radio">{t('admin_designs_type_list')}</option>
                          <option value="color">{t('admin_designs_type_color')}</option>
                        </select>
                      </AdminField>
                      <Btn type="button" variant="danger" size="sm" onClick={() => removeOption(optionIndex)}>{t('admin_designs_remove')}</Btn>
                    </div>
                    <div style={{ marginTop: '12px', display: 'flex', flexDirection: 'column', gap: '8px' }}>
                      {(option.choices || []).map((choice, choiceIndex) => (
                        <div key={choiceIndex} style={{ display: 'grid', gridTemplateColumns: option.type === 'color' ? '1fr 1.4fr 90px 100px auto' : '1fr 1.4fr 100px auto', gap: '8px', alignItems: 'center' }} className="form-row">
                          <input value={choice.id} onChange={e => updateChoice(optionIndex, choiceIndex, 'id', e.target.value)} placeholder="id" style={inputStyle} />
                          <input value={choice.label} onChange={e => updateChoice(optionIndex, choiceIndex, 'label', e.target.value)} placeholder={t('admin_designs_choice_label_ph')} style={inputStyle} />
                          {option.type === 'color' && <input type="color" value={choice.color || '#D4A8A8'} onChange={e => updateChoice(optionIndex, choiceIndex, 'color', e.target.value)} style={{ ...inputStyle, padding: '4px', height: '39px' }} />}
                          <input type="number" value={choice.price} onChange={e => updateChoice(optionIndex, choiceIndex, 'price', e.target.value)} placeholder="+$" style={inputStyle} />
                          <button type="button" onClick={() => removeChoice(optionIndex, choiceIndex)} style={{ border: 'none', background: 'transparent', cursor: 'pointer', color: '#C83A3A', fontSize: '12px', fontWeight: 700 }}>{t('admin_designs_remove')}</button>
                        </div>
                      ))}
                      <Btn type="button" variant="ghost" size="sm" onClick={() => addChoice(optionIndex)} style={{ alignSelf: 'flex-start' }}>{t('admin_designs_add_choice')}</Btn>
                    </div>
                  </div>
                ))}
                <Btn type="button" variant="ghost" onClick={addOption} style={{ alignSelf: 'flex-start' }}>
                  <Icon name="plus" size={14} color="var(--primary)" />
                  {t('admin_designs_add_option')}
                </Btn>
              </div>
            </AdminFormSection>

            <AdminFormSection title={t('admin_designs_section_extras')} subtitle={t('admin_designs_section_extras_sub')} columns={1}>
              <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
                <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                  {[
                    ['Letras luminosas', 850],
                    ['Mesa de dulces', 1200],
                    ['Flores premium', 950],
                    ['Montaje express', 500],
                  ].map(([name, price]) => (
                    <button key={name} type="button" onClick={() => addPresetExtra(name, price)}
                      style={{ border: '1px solid var(--border)', background: 'var(--bg-soft)', color: 'var(--text)', borderRadius: 999, padding: '7px 11px', cursor: 'pointer', fontSize: 12, fontWeight: 800 }}>
                      + {name} ${Number(price).toLocaleString()}
                    </button>
                  ))}
                </div>
                {form.extras.map((extra, index) => (
                  <div key={index} style={{ display: 'grid', gridTemplateColumns: '1fr 1.7fr 120px auto', gap: '8px', alignItems: 'center' }} className="form-row">
                    <input value={extra.id} onChange={e => updateExtra(index, 'id', e.target.value)} placeholder="id" style={inputStyle} />
                    <input value={extra.name} onChange={e => updateExtra(index, 'name', e.target.value)} placeholder={t('admin_designs_extra_name_ph')} style={inputStyle} />
                    <input type="number" value={extra.price} onChange={e => updateExtra(index, 'price', e.target.value)} placeholder={t('admin_designs_extra_price_ph')} style={inputStyle} />
                    <button type="button" onClick={() => removeExtra(index)} style={{ border: 'none', background: 'transparent', cursor: 'pointer', color: '#C83A3A', fontSize: '12px', fontWeight: 700 }}>{t('admin_designs_remove')}</button>
                  </div>
                ))}
                <Btn type="button" variant="ghost" onClick={addExtra} style={{ alignSelf: 'flex-start' }}>
                  <Icon name="plus" size={14} color="var(--primary)" />
                  {t('admin_designs_add_extra')}
                </Btn>
              </div>
            </AdminFormSection>
          </form>
        </AdminModal>

        {isMobile && (
          <div className="lel-admin-list">
            {designs.length === 0 ? (
              <div style={{ padding: '40px', textAlign: 'center', color: 'var(--muted)', fontSize: '14px' }}>{t('admin_designs_empty')}</div>
            ) : designs.map(design => {
              const published = (design.status || 'published') === 'published';
              return (
                <AdminListRow key={design.id} icon="grid" title={design.name}
                  subtitle={categoryLabelBySlug[design.category] || CATEGORY_LABELS[design.category] || design.category}
                  value={`$${Number(design.price || 0).toLocaleString()}`}
                  badge={published ? t('admin_designs_status_published') : t('admin_designs_status_draft')} badgeColor={published ? '#2A8A50' : '#8B7068'}
                  onClick={() => setMobileActions(design)} />
              );
            })}
          </div>
        )}
        <div style={{ overflowX: 'auto', display: isMobile ? 'none' : 'block' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontFamily: "'DM Sans', sans-serif" }}>
            <thead>
              <tr style={{ borderBottom: '1px solid var(--border)' }}>
                {[
                  { id: 'design', label: t('admin_designs_col_design') },
                  { id: 'category', label: t('admin_designs_col_category') },
                  { id: 'price', label: t('admin_designs_col_price') },
                  { id: 'options', label: t('admin_designs_col_options') },
                  { id: 'extras', label: t('admin_designs_col_extras') },
                  { id: 'status', label: t('admin_designs_col_status') },
                  { id: 'actions', label: t('admin_designs_col_actions') },
                ].map(header => (
                  <th key={header.id} style={{ padding: '12px 16px', fontSize: '11px', color: 'var(--muted)', fontWeight: 600, letterSpacing: '0.07em', textTransform: 'uppercase', textAlign: 'left' }}>{header.label}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {designs.map((design, index) => (
                <tr key={design.id} style={{ borderBottom: index < designs.length - 1 ? '1px solid var(--border)' : 'none' }}>
                  <td style={{ padding: '14px 16px' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
                      <div style={{ width: '44px', height: '36px', borderRadius: '8px', overflow: 'hidden', background: 'var(--bg-soft)', flexShrink: 0 }}>
                        {design.image ? <img src={design.image} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} /> : <DecoPlaceholder category={design.category} />}
                      </div>
                      <div>
                        <div style={{ fontSize: '13.5px', fontWeight: 600, color: 'var(--text)' }}>{design.name}</div>
                        <div style={{ fontSize: '11px', color: 'var(--muted)' }}>{t('admin_designs_materials_count', { materials: (design.materials || design.assetIds || []).length, includes: (design.includes || []).length })} · {(design.images || []).length || (design.image ? 1 : 0)} fotos</div>
                      </div>
                    </div>
                  </td>
                  <td style={{ padding: '14px 16px', fontSize: '13px', color: 'var(--muted)' }}>{categoryLabelBySlug[design.category] || CATEGORY_LABELS[design.category] || design.category}</td>
                  <td style={{ padding: '14px 16px', fontSize: '13px', color: 'var(--text)', fontWeight: 700 }}>${Number(design.price || 0).toLocaleString()}</td>
                  <td style={{ padding: '14px 16px', fontSize: '13px', color: 'var(--muted)' }}>{(design.options || []).length}</td>
                  <td style={{ padding: '14px 16px', fontSize: '13px', color: 'var(--muted)' }}>{(design.extras || []).length}</td>
                  <td style={{ padding: '14px 16px' }}>
                    <Badge color={(design.status || 'published') === 'published' ? 'sage' : 'warm'}>{(design.status || 'published') === 'published' ? t('admin_designs_status_published') : t('admin_designs_status_draft')}</Badge>
                  </td>
                  <td style={{ padding: '14px 16px' }}>
                    <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
                      <Btn size="sm" variant="ghost" onClick={() => editDesign(design)}>{t('admin_designs_edit')}</Btn>
                      <Btn size="sm" variant="ghost" onClick={() => navigate('admin-scene-editor', { designId: design.id })} title={t('admin_designs_scene_editor')}>✨</Btn>
                      <Btn size="sm" variant="ghost" onClick={() => window.LelusaStore.updateDesignStatus(design.id, (design.status || 'published') === 'published' ? 'draft' : 'published')}>
                        {(design.status || 'published') === 'published' ? t('admin_designs_unpublish') : t('admin_designs_publish')}
                      </Btn>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
        {mobileActions && (
          <BottomSheet open={!!mobileActions} onClose={() => setMobileActions(null)} title={mobileActions.name}>
            <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', paddingBottom: '8px' }}>
              <Btn onClick={() => { const id = mobileActions.id; setMobileActions(null); navigate('admin-scene-editor', { designId: id }); }}>{t('admin_designs_open_scene_editor')}</Btn>
              <Btn variant="ghost" onClick={() => { const d = mobileActions; setMobileActions(null); editDesign(d); }}>{t('admin_designs_edit_data')}</Btn>
              <Btn variant="ghost" onClick={() => { const d = mobileActions; setMobileActions(null); window.LelusaStore.updateDesignStatus(d.id, (d.status || 'published') === 'published' ? 'draft' : 'published'); }}>
                {(mobileActions.status || 'published') === 'published' ? t('admin_designs_to_draft') : t('admin_designs_publish')}
              </Btn>
            </div>
          </BottomSheet>
        )}
    </AdminLayout>
  );
}

// ─── Calendar Page ───────────────────────────────────────────────
// ─── Calendar constants ─────────────────────────────────────────
const CAL_STATUS_COLORS = {
  reservado:        '#3A62C8',
  confirmado:       '#2A8A50',
  'en preparacion': '#C8881A',
  'en montaje':     '#9A4AC8',
  completado:       '#6A4AC8',
  cancelado:        '#C83A3A',
  nota:             '#9A8070',
};

const CAL_STATUS_ICONS = {
  reservado:        'calendar',
  confirmado:       'check',
  'en preparacion': 'settings',
  'en montaje':     'tool',
  completado:       'star',
  cancelado:        'x',
  nota:             'edit',
};

const CAL_STATUS_I18N = {
  reservado:        'admin_cal_status_reservado',
  confirmado:       'admin_cal_status_confirmado',
  'en preparacion': 'admin_cal_status_en_preparacion',
  'en montaje':     'admin_cal_status_en_montaje',
  completado:       'admin_cal_status_completado',
  cancelado:        'admin_cal_status_cancelado',
  nota:             'admin_cal_status_nota',
};

// Translated label for a calendar status value (does not change the stored value).
function calStatusLabel(status) {
  const key = CAL_STATUS_I18N[status];
  return key ? window.i18next.t(key) : status;
}

const CAL_EVENT_TYPES = ['boda', 'xv', 'graduacion', 'cumpleanos', 'corporativo', 'postres', 'nota', 'otro'];
const CAL_TYPE_I18N = { boda: 'admin_cal_type_boda', xv: 'admin_cal_type_xv', graduacion: 'admin_cal_type_graduacion', cumpleanos: 'admin_cal_type_cumpleanos', corporativo: 'admin_cal_type_corporativo', postres: 'admin_cal_type_postres', nota: 'admin_cal_type_nota', otro: 'admin_cal_type_otro' };

// Translated label for a calendar event type value (does not change the stored value).
function calTypeLabel(type) {
  const key = CAL_TYPE_I18N[type];
  return key ? window.i18next.t(key) : type;
}

function eventServiceDepartments(event = {}) {
  return Array.isArray(event.serviceDepartments) && event.serviceDepartments.length
    ? event.serviceDepartments
    : [event.department || (event.type === 'postres' ? 'postres' : 'decoracion')];
}

function eventServiceLabel(event = {}) {
  return eventServiceDepartments(event).map(dept => (window.DEPARTMENT_LABELS || {})[dept] || dept).join(' + ');
}

// Single-letter weekday initials (Sun..Sat order), localized.
function CAL_DAY_INITIALS() {
  const t = window.i18next.t;
  return [t('admin_cal_init_sun'), t('admin_cal_init_mon'), t('admin_cal_init_tue'), t('admin_cal_init_wed'), t('admin_cal_init_thu'), t('admin_cal_init_fri'), t('admin_cal_init_sat')];
}

function getEventColor(event) {
  return CAL_STATUS_COLORS[event.status] || event.color || '#C4899A';
}

function CalendarToolbar({ view, onViewChange, viewDate, onNavigate, onToday, isMobile }) {
  const { t } = window.ReactI18next.useTranslation();
  const dateLocale = i18next.language === 'es' ? 'es-MX' : 'en-US';
  const views = [
    { key: 'month', label: t('admin_cal_view_month') },
    { key: 'week', label: t('admin_cal_view_week') },
    { key: 'day', label: t('admin_cal_view_day') },
    { key: 'year', label: t('admin_cal_view_year') },
  ];

  const getTitle = () => {
    if (view === 'month' || view === 'year') {
      return viewDate.toLocaleDateString(dateLocale, { month: 'long', year: 'numeric' });
    }
    if (view === 'week') {
      const monday = new Date(viewDate);
      const day = monday.getDay();
      const diff = (day === 0 ? -6 : 1 - day);
      monday.setDate(monday.getDate() + diff);
      const sunday = new Date(monday);
      sunday.setDate(monday.getDate() + 6);
      const fmt = d => d.toLocaleDateString(dateLocale, { day: 'numeric', month: 'short' });
      return `${fmt(monday)} – ${fmt(sunday)}`;
    }
    return viewDate.toLocaleDateString(dateLocale, { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });
  };

  const navigate = (dir) => {
    const d = new Date(viewDate);
    if (view === 'month' || view === 'year') d.setMonth(d.getMonth() + dir);
    else if (view === 'week') d.setDate(d.getDate() + dir * 7);
    else d.setDate(d.getDate() + dir);
    onNavigate(d);
  };

  const btnBase = { background: 'none', border: '1px solid var(--border)', borderRadius: '10px', padding: '7px 11px', cursor: 'pointer', display: 'flex', alignItems: 'center', color: 'var(--muted)' };

  return (
    <div style={{ padding: isMobile ? '10px 14px' : '12px 16px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: isMobile ? 'stretch' : 'center', justifyContent: 'space-between', gap: isMobile ? '10px' : '12px', flexWrap: 'wrap', background: 'var(--card)' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: '8px', minWidth: 0, width: isMobile ? '100%' : 'auto' }}>
        <button style={btnBase} onClick={() => navigate(-1)}>
          <Icon name="chevLeft" size={15} color="var(--muted)" />
        </button>
        <h2 style={{ margin: 0, fontFamily: "'Cormorant Garamond', serif", fontSize: isMobile ? '16px' : '20px', fontWeight: 600, color: 'var(--text)', textTransform: 'capitalize', minWidth: 0, flex: isMobile ? 1 : '0 0 auto', textAlign: 'center', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          {getTitle()}
        </h2>
        <button style={btnBase} onClick={() => navigate(1)}>
          <Icon name="chevRight" size={15} color="var(--muted)" />
        </button>
        <button onClick={onToday} style={{ background: 'var(--accent-light)', border: 'none', borderRadius: '8px', padding: '6px 12px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, color: 'var(--primary)', fontFamily: "'DM Sans', sans-serif" }}>
          {t('admin_cal_today')}
        </button>
      </div>
      <div style={{ display: 'flex', background: 'var(--bg-soft)', borderRadius: '10px', padding: '3px', gap: '2px', width: isMobile ? '100%' : 'auto' }}>
        {views.map(v => (
          <button key={v.key} onClick={() => onViewChange(v.key)} style={{ flex: isMobile ? 1 : '0 0 auto', padding: '5px 12px', borderRadius: '8px', border: 'none', fontSize: '12px', fontWeight: 700, cursor: 'pointer', fontFamily: "'DM Sans', sans-serif", background: view === v.key ? 'var(--primary)' : 'transparent', color: view === v.key ? '#fff' : 'var(--muted)', transition: 'all 0.15s' }}>
            {v.label}
          </button>
        ))}
      </div>
    </div>
  );
}

function CalendarSidebar({ viewDate, onNavigate, filters, onToggleFilter, events, onSelectEvent, onNewEvent, collapsed, onToggleCollapse, isMobile }) {
  const { t } = window.ReactI18next.useTranslation();
  const dateLocale = i18next.language === 'es' ? 'es-MX' : 'en-US';
  const year = viewDate.getFullYear();
  const month = viewDate.getMonth();
  const daysInMonth = new Date(year, month + 1, 0).getDate();
  const firstDayOfWeek = new Date(year, month, 1).getDay();
  const totalCells = Math.ceil((firstDayOfWeek + daysInMonth) / 7) * 7;
  const cells = Array.from({ length: totalCells }, (_, i) => {
    const day = i - firstDayOfWeek + 1;
    return day >= 1 && day <= daysInMonth ? day : null;
  });
  const today = new Date();
  const isToday = (d) => d === today.getDate() && month === today.getMonth() && year === today.getFullYear();

  const getEventsForDay = (day) => {
    const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
    return events.filter(e => e.date === dateStr);
  };

  const upcoming = events
    .filter(e => e.date >= today.toISOString().slice(0, 10))
    .sort((a, b) => a.date.localeCompare(b.date))
    .slice(0, 5);

  const sidebarStyle = {
    width: collapsed ? '52px' : '220px',
    flexShrink: 0,
    background: 'var(--card)',
    borderRight: '1px solid var(--border)',
    display: 'flex',
    flexDirection: 'column',
    overflow: 'hidden',
    transition: 'width 0.2s ease',
  };

  const labelStyle = { fontSize: '10px', fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: '8px', fontFamily: "'DM Sans', sans-serif" };

  if (isMobile) return null;

  return (
    <div style={sidebarStyle}>
      {/* Collapse toggle */}
      <div style={{ padding: '12px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: collapsed ? 'center' : 'flex-end' }}>
        <button onClick={onToggleCollapse} title={collapsed ? t('admin_cal_expand') : t('admin_cal_collapse')} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--muted)', padding: '4px', borderRadius: '8px' }}>
          <Icon name="menu" size={18} color="var(--muted)" />
        </button>
      </div>

      {collapsed ? (
        /* Icon-only mode */
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '12px', padding: '12px 0' }}>
          <button onClick={onNewEvent} title={t('admin_cal_new_event')} style={{ background: 'var(--primary)', border: 'none', borderRadius: '10px', width: '36px', height: '36px', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="plus" size={18} color="#fff" />
          </button>
          {Object.entries(CAL_STATUS_COLORS).map(([status, color]) => (
            <button key={status} onClick={() => onToggleFilter(status)} title={calStatusLabel(status)}
              style={{ background: filters.size === 0 || filters.has(status) ? `${color}22` : 'transparent', border: `1px solid ${filters.size === 0 || filters.has(status) ? color : 'var(--border)'}`, borderRadius: '8px', width: '32px', height: '32px', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Icon name={CAL_STATUS_ICONS[status]} size={14} color={filters.size === 0 || filters.has(status) ? color : 'var(--muted)'} />
            </button>
          ))}
        </div>
      ) : (
        /* Full sidebar */
        <div style={{ flex: 1, overflowY: 'auto', padding: '14px', display: 'flex', flexDirection: 'column', gap: '18px' }}>
          {/* Mini calendar */}
          <div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px' }}>
              <button onClick={() => { const d = new Date(year, month - 1, 1); onNavigate(d); }} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '2px 6px', borderRadius: '6px', color: 'var(--muted)' }}>
                <Icon name="chevLeft" size={13} color="var(--muted)" />
              </button>
              <span style={{ fontSize: '12px', fontWeight: 700, color: 'var(--text)', textTransform: 'capitalize', fontFamily: "'DM Sans', sans-serif" }}>
                {viewDate.toLocaleDateString(dateLocale, { month: 'short', year: 'numeric' })}
              </span>
              <button onClick={() => { const d = new Date(year, month + 1, 1); onNavigate(d); }} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '2px 6px', borderRadius: '6px', color: 'var(--muted)' }}>
                <Icon name="chevRight" size={13} color="var(--muted)" />
              </button>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '1px', textAlign: 'center' }}>
              {CAL_DAY_INITIALS().map((d, i) => (
                <div key={i} style={{ fontSize: '9px', fontWeight: 700, color: 'var(--muted)', padding: '2px 0' }}>{d}</div>
              ))}
              {cells.map((day, idx) => {
                const dayEvents = day ? getEventsForDay(day) : [];
                const firstColor = dayEvents.length ? getEventColor(dayEvents[0]) : null;
                return (
                  <div key={idx} onClick={() => { if (day) { const d = new Date(year, month, day); onNavigate(d); } }}
                    style={{ fontSize: '10px', padding: '3px 1px', borderRadius: '50%', cursor: day ? 'pointer' : 'default', background: day && isToday(day) ? 'var(--primary)' : 'transparent', color: day && isToday(day) ? '#fff' : day ? 'var(--text)' : 'transparent', fontWeight: day && isToday(day) ? 700 : 400, position: 'relative', textAlign: 'center' }}>
                    {day || ''}
                    {firstColor && day && !isToday(day) && (
                      <div style={{ position: 'absolute', bottom: '1px', left: '50%', transform: 'translateX(-50%)', width: '4px', height: '4px', borderRadius: '50%', background: firstColor }} />
                    )}
                  </div>
                );
              })}
            </div>
          </div>

          {/* Filters */}
          <div>
            <div style={labelStyle}>{t('admin_cal_filter_status')}</div>
            {Object.entries(CAL_STATUS_COLORS).map(([status, color]) => {
              const active = filters.size === 0 || filters.has(status);
              return (
                <div key={status} onClick={() => onToggleFilter(status)}
                  style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '5px 6px', borderRadius: '8px', cursor: 'pointer', marginBottom: '2px', background: active ? `${color}15` : 'transparent' }}>
                  <div style={{ width: '10px', height: '10px', borderRadius: '3px', background: active ? color : 'var(--border)', flexShrink: 0 }} />
                  <span style={{ fontSize: '11px', color: active ? 'var(--text)' : 'var(--muted)', fontFamily: "'DM Sans', sans-serif" }}>{calStatusLabel(status)}</span>
                </div>
              );
            })}
          </div>

          {/* Upcoming events */}
          <div>
            <div style={labelStyle}>{t('admin_cal_upcoming')}</div>
            {upcoming.length === 0 ? (
              <div style={{ fontSize: '11px', color: 'var(--muted)' }}>{t('admin_cal_no_upcoming')}</div>
            ) : upcoming.map(ev => {
              const color = getEventColor(ev);
              return (
                <div key={ev.id} onClick={() => onSelectEvent(ev)}
                  style={{ padding: '7px 8px', borderRadius: '8px', background: 'var(--bg-soft)', border: '1px solid var(--border)', marginBottom: '4px', cursor: 'pointer' }}>
                  <div style={{ fontSize: '11px', fontWeight: 700, color: 'var(--text)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{ev.name}</div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: '4px', marginTop: '2px' }}>
                    <div style={{ width: '6px', height: '6px', borderRadius: '50%', background: color, flexShrink: 0 }} />
                    <span style={{ fontSize: '10px', color: 'var(--muted)' }}>{ev.date.slice(5)} · {calStatusLabel(ev.status)}</span>
                  </div>
                </div>
              );
            })}
          </div>

          {/* New event button */}
          <button onClick={onNewEvent} style={{ marginTop: 'auto', background: 'var(--primary)', color: '#fff', border: 'none', borderRadius: '12px', padding: '10px', fontSize: '13px', fontWeight: 700, cursor: 'pointer', fontFamily: "'DM Sans', sans-serif", display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '6px' }}>
            <Icon name="plus" size={15} color="#fff" />
            {t('admin_cal_new_event')}
          </button>
        </div>
      )}
    </div>
  );
}

function MonthView({ viewDate, events, filters, onSelectEvent, onDayClick }) {
  const { t } = window.ReactI18next.useTranslation();
  const year = viewDate.getFullYear();
  const month = viewDate.getMonth();
  const daysInMonth = new Date(year, month + 1, 0).getDate();
  const firstDayOfWeek = new Date(year, month, 1).getDay();
  const totalCells = Math.ceil((firstDayOfWeek + daysInMonth) / 7) * 7;
  const today = new Date();
  const isToday = (d) => d === today.getDate() && month === today.getMonth() && year === today.getFullYear();

  const filteredEvents = filters.size === 0 ? events : events.filter(e => filters.has(e.status));

  const getEventsForDay = (day) => {
    const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
    return filteredEvents.filter(e => e.date === dateStr);
  };

  const cells = Array.from({ length: totalCells }, (_, i) => {
    const day = i - firstDayOfWeek + 1;
    return day >= 1 && day <= daysInMonth ? day : null;
  });

  const dayLabels = [t('admin_cal_day_dom'), t('admin_cal_day_lun'), t('admin_cal_day_mar'), t('admin_cal_day_mie'), t('admin_cal_day_jue'), t('admin_cal_day_vie'), t('admin_cal_day_sab')];

  return (
    <div className="lel-calendar-month" style={{ flex: 1, overflowY: 'auto' }}>
      {/* Day labels header */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', borderBottom: '1px solid var(--border)', background: 'var(--bg-soft)' }}>
        {dayLabels.map(d => (
          <div key={d} style={{ padding: '8px 2px', textAlign: 'center', fontSize: '11px', fontWeight: 700, color: 'var(--muted)', letterSpacing: '0.05em', textTransform: 'uppercase', fontFamily: "'DM Sans', sans-serif" }}>{d}</div>
        ))}
      </div>
      {/* Grid */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)' }}>
        {cells.map((day, idx) => {
          const dayEvents = day ? getEventsForDay(day) : [];
          const isT = day && isToday(day);
          const dateStr = day ? `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}` : null;

          return (
            <div key={`${year}-${month}-${day || 'empty-' + idx}`}
              style={{ minHeight: '90px', padding: '6px', borderRight: '1px solid var(--border)', borderBottom: '1px solid var(--border)', background: isT ? '#fdf5f8' : 'transparent', cursor: day ? 'pointer' : 'default' }}
              onClick={() => { if (day) onDayClick(dateStr); }}>
              {day && (
                <>
                  <div style={{ fontSize: '13px', fontWeight: isT ? 700 : 400, marginBottom: '4px', width: '24px', height: '24px', borderRadius: '50%', background: isT ? 'var(--primary)' : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', color: isT ? '#fff' : 'var(--text)' }}>
                    {day}
                  </div>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: '2px' }}>
                    {dayEvents.slice(0, 3).map(ev => {
                      const color = getEventColor(ev);
                      const serviceDepartments = eventServiceDepartments(ev);
                      return (
                        <div key={ev.id}
                          onClick={e => { e.stopPropagation(); onSelectEvent(ev); }}
                          style={{ borderRadius: '4px', padding: '2px 5px', fontSize: '10px', fontWeight: 600, background: `${color}22`, borderLeft: `2px solid ${color}`, color, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', fontFamily: "'DM Sans', sans-serif", cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '3px' }}>
                          <Icon name={CAL_STATUS_ICONS[ev.status] || 'calendar'} size={9} color={color} />
                          {serviceDepartments.length > 1 && <span title={eventServiceLabel(ev)} style={{ color: '#A56A14', fontWeight: 900 }}>+</span>}
                          {ev.type === 'nota' ? '📝 ' : ''}{ev.name}
                        </div>
                      );
                    })}
                    {dayEvents.length > 3 && (
                      <div style={{ fontSize: '10px', color: 'var(--muted)', paddingLeft: '4px', fontFamily: "'DM Sans', sans-serif" }}>{t('admin_cal_more', { count: dayEvents.length - 3 })}</div>
                    )}
                  </div>
                </>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function WeekView({ viewDate, events, filters, onSelectEvent, onSlotClick }) {
  const HOUR_START = 6;
  const HOUR_END = 22;
  const HOUR_HEIGHT = 56;
  const today = new Date();
  const todayStr = today.toISOString().slice(0, 10);

  const getWeekDays = () => {
    const d = new Date(viewDate);
    const day = d.getDay();
    const diff = day === 0 ? -6 : 1 - day;
    d.setDate(d.getDate() + diff);
    return Array.from({ length: 7 }, (_, i) => {
      const dd = new Date(d);
      dd.setDate(d.getDate() + i);
      return dd;
    });
  };

  const weekDays = getWeekDays();
  const filteredEvents = filters.size === 0 ? events : events.filter(e => filters.has(e.status));
  const hours = Array.from({ length: HOUR_END - HOUR_START }, (_, i) => HOUR_START + i);

  const getEventsForDate = (dateStr) => filteredEvents.filter(e => e.date === dateStr && e.type !== 'nota');

  const getEventTop = (time) => {
    const [h, m] = (time || '08:00').split(':').map(Number);
    return (h - HOUR_START + m / 60) * HOUR_HEIGHT;
  };

  const getEventHeight = (duration) => Math.max((Number(duration) || 1) * HOUR_HEIGHT, 24);

  const isCurrentWeek = weekDays.some(d => d.toISOString().slice(0, 10) === todayStr);
  const currentTimeTop = isCurrentWeek ? getEventTop(`${today.getHours()}:${today.getMinutes()}`) : null;

  return (
    <div style={{ flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column' }}>
      {/* Day headers */}
      <div style={{ display: 'grid', gridTemplateColumns: '48px repeat(7, 1fr)', borderBottom: '1px solid var(--border)', background: 'var(--bg-soft)', flexShrink: 0 }}>
        <div />
        {weekDays.map(d => {
          const ds = d.toISOString().slice(0, 10);
          const isT = ds === todayStr;
          return (
            <div key={ds} style={{ padding: '8px 4px', textAlign: 'center', borderLeft: '1px solid var(--border)' }}>
              <div style={{ fontSize: '10px', fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>
                {d.toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { weekday: 'short' })}
              </div>
              <div style={{ fontSize: '18px', fontWeight: isT ? 700 : 400, fontFamily: "'Cormorant Garamond', serif", width: '32px', height: '32px', borderRadius: '50%', background: isT ? 'var(--primary)' : 'transparent', color: isT ? '#fff' : 'var(--text)', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '2px auto 0' }}>
                {d.getDate()}
              </div>
            </div>
          );
        })}
      </div>
      {/* Time grid */}
      <div style={{ display: 'grid', gridTemplateColumns: '48px repeat(7, 1fr)', flex: 1, position: 'relative' }}>
        {/* Hour labels */}
        <div style={{ gridColumn: '1', gridRow: '1', position: 'relative', height: `${(HOUR_END - HOUR_START) * HOUR_HEIGHT}px` }}>
          {hours.map(h => (
            <div key={h} style={{ position: 'absolute', top: `${(h - HOUR_START) * HOUR_HEIGHT}px`, width: '100%', fontSize: '10px', color: 'var(--muted)', textAlign: 'right', paddingRight: '6px', fontFamily: "'DM Sans', sans-serif", transform: 'translateY(-7px)' }}>
              {String(h).padStart(2, '0')}:00
            </div>
          ))}
        </div>
        {/* Day columns */}
        {weekDays.map((d, colIdx) => {
          const ds = d.toISOString().slice(0, 10);
          const dayEvs = getEventsForDate(ds);
          return (
            <div key={ds} style={{ gridColumn: `${colIdx + 2}`, gridRow: '1', borderLeft: '1px solid var(--border)', position: 'relative', height: `${(HOUR_END - HOUR_START) * HOUR_HEIGHT}px` }}>
              {/* Hour lines */}
              {hours.map(h => (
                <div key={h} style={{ position: 'absolute', top: `${(h - HOUR_START) * HOUR_HEIGHT}px`, left: 0, right: 0, borderTop: '1px solid var(--border)', opacity: 0.5 }} />
              ))}
              {/* Current time line */}
              {isCurrentWeek && ds === todayStr && currentTimeTop !== null && (
                <div style={{ position: 'absolute', top: `${currentTimeTop}px`, left: 0, right: 0, height: '2px', background: '#C83A3A', zIndex: 3 }}>
                  <div style={{ position: 'absolute', left: '-4px', top: '-4px', width: '10px', height: '10px', borderRadius: '50%', background: '#C83A3A' }} />
                </div>
              )}
              {/* Click to add */}
              <div style={{ position: 'absolute', inset: 0, zIndex: 1 }}
                onClick={(e) => { const rect = e.currentTarget.getBoundingClientRect(); const relY = e.clientY - rect.top; const h = Math.floor(HOUR_START + relY / HOUR_HEIGHT); onSlotClick(ds, `${String(Math.max(HOUR_START, Math.min(h, HOUR_END - 1))).padStart(2, '0')}:00`); }} />
              {/* Events */}
              {dayEvs.map((ev, evIdx) => {
                const color = getEventColor(ev);
                const serviceDepartments = eventServiceDepartments(ev);
                const top = getEventTop(ev.time);
                const height = getEventHeight(ev.duration);
                const overlap = dayEvs.filter(e2 => {
                  const t1 = getEventTop(e2.time);
                  return t1 < top + height && t1 + getEventHeight(e2.duration) > top && e2.id !== ev.id;
                });
                const width = overlap.length > 0 ? `${90 / (overlap.length + 1)}%` : '92%';
                const left = overlap.length > 0 ? `${(90 / (overlap.length + 1)) * evIdx}%` : '4%';
                return (
                  <div key={ev.id}
                    onClick={e => { e.stopPropagation(); onSelectEvent(ev); }}
                    style={{ position: 'absolute', top: `${top}px`, height: `${height}px`, left, width, background: `${color}22`, borderLeft: `3px solid ${color}`, borderRadius: '4px', padding: '2px 4px', overflow: 'hidden', cursor: 'pointer', zIndex: 2, boxSizing: 'border-box' }}>
                    <div style={{ fontSize: '10px', fontWeight: 700, color, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', fontFamily: "'DM Sans', sans-serif" }}>{ev.name}</div>
                    {height > 30 && <div style={{ fontSize: '9px', color: 'var(--muted)' }}>{ev.time} · {ev.duration}h{serviceDepartments.length > 1 ? ` · ${eventServiceLabel(ev)}` : ''}</div>}
                  </div>
                );
              })}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function DayView({ viewDate, events, filters, onSelectEvent, onSlotClick }) {
  const HOUR_START = 6;
  const HOUR_END = 22;
  const HOUR_HEIGHT = 56;
  const today = new Date();
  const todayStr = today.toISOString().slice(0, 10);
  const dateStr = viewDate.toISOString().slice(0, 10);
  const isToday = dateStr === todayStr;
  const filteredEvents = (filters.size === 0 ? events : events.filter(e => filters.has(e.status)))
    .filter(e => e.date === dateStr && e.type !== 'nota');
  const hours = Array.from({ length: HOUR_END - HOUR_START }, (_, i) => HOUR_START + i);

  const getEventTop = (time) => {
    const [h, m] = (time || '08:00').split(':').map(Number);
    return (h - HOUR_START + m / 60) * HOUR_HEIGHT;
  };
  const getEventHeight = (duration) => Math.max((Number(duration) || 1) * HOUR_HEIGHT, 24);
  const currentTimeTop = isToday ? getEventTop(`${today.getHours()}:${today.getMinutes()}`) : null;

  return (
    <div style={{ flex: 1, overflowY: 'auto' }}>
      {/* Header */}
      <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--border)', background: 'var(--bg-soft)' }}>
        <div style={{ fontSize: '11px', fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>
          {viewDate.toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { weekday: 'long' })}
        </div>
        <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: '28px', fontWeight: 600, color: isToday ? 'var(--primary)' : 'var(--text)' }}>
          {viewDate.toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { day: 'numeric', month: 'long', year: 'numeric' })}
        </div>
      </div>
      {/* Timeline */}
      <div style={{ display: 'grid', gridTemplateColumns: '48px 1fr', position: 'relative' }}>
        {/* Hours */}
        <div style={{ position: 'relative', height: `${(HOUR_END - HOUR_START) * HOUR_HEIGHT}px` }}>
          {hours.map(h => (
            <div key={h} style={{ position: 'absolute', top: `${(h - HOUR_START) * HOUR_HEIGHT}px`, width: '100%', fontSize: '10px', color: 'var(--muted)', textAlign: 'right', paddingRight: '6px', fontFamily: "'DM Sans', sans-serif", transform: 'translateY(-7px)' }}>
              {String(h).padStart(2, '0')}:00
            </div>
          ))}
        </div>
        {/* Events column */}
        <div style={{ borderLeft: '1px solid var(--border)', position: 'relative', height: `${(HOUR_END - HOUR_START) * HOUR_HEIGHT}px` }}>
          {hours.map(h => (
            <div key={h} style={{ position: 'absolute', top: `${(h - HOUR_START) * HOUR_HEIGHT}px`, left: 0, right: 0, borderTop: '1px solid var(--border)', opacity: 0.5 }} />
          ))}
          {isToday && currentTimeTop !== null && (
            <div style={{ position: 'absolute', top: `${currentTimeTop}px`, left: 0, right: 0, height: '2px', background: '#C83A3A', zIndex: 3 }}>
              <div style={{ position: 'absolute', left: '-4px', top: '-4px', width: '10px', height: '10px', borderRadius: '50%', background: '#C83A3A' }} />
            </div>
          )}
          <div style={{ position: 'absolute', inset: 0, zIndex: 1 }} onClick={(e) => { const rect = e.currentTarget.getBoundingClientRect(); const relY = e.clientY - rect.top; const h = Math.floor(HOUR_START + relY / HOUR_HEIGHT); onSlotClick(dateStr, `${String(Math.max(HOUR_START, Math.min(h, HOUR_END - 1))).padStart(2, '0')}:00`); }} />
          {filteredEvents.map((ev, evIdx) => {
            const color = getEventColor(ev);
            const serviceDepartments = eventServiceDepartments(ev);
            const top = getEventTop(ev.time);
            const height = getEventHeight(ev.duration);
            const overlap = filteredEvents.filter(e2 => {
              const t1 = getEventTop(e2.time);
              return t1 < top + height && t1 + getEventHeight(e2.duration) > top && e2.id !== ev.id;
            });
            const width = overlap.length > 0 ? `${90 / (overlap.length + 1)}%` : '94%';
            const left = overlap.length > 0 ? `${(90 / (overlap.length + 1)) * evIdx}%` : '3%';
            return (
              <div key={ev.id}
                onClick={e => { e.stopPropagation(); onSelectEvent(ev); }}
                style={{ position: 'absolute', top: `${top}px`, height: `${height}px`, left, width, background: `${color}22`, borderLeft: `3px solid ${color}`, borderRadius: '6px', padding: '4px 8px', overflow: 'hidden', cursor: 'pointer', zIndex: 2, boxSizing: 'border-box' }}>
                <div style={{ fontSize: '12px', fontWeight: 700, color, fontFamily: "'DM Sans', sans-serif" }}>{ev.name}</div>
                {height > 36 && <div style={{ fontSize: '11px', color: 'var(--muted)' }}>{ev.time} · {ev.duration}h · {ev.client}{serviceDepartments.length > 1 ? ` · ${eventServiceLabel(ev)}` : ''}</div>}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

function YearView({ viewDate, events, onMonthClick }) {
  const year = viewDate.getFullYear();
  const today = new Date();
  const months = Array.from({ length: 12 }, (_, i) => i);

  return (
    <div style={{ flex: 1, overflowY: 'auto', padding: '16px' }}>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '16px' }}>
        {months.map(month => {
          const daysInMonth = new Date(year, month + 1, 0).getDate();
          const firstDayOfWeek = new Date(year, month, 1).getDay();
          const totalCells = Math.ceil((firstDayOfWeek + daysInMonth) / 7) * 7;
          const cells = Array.from({ length: totalCells }, (_, i) => {
            const day = i - firstDayOfWeek + 1;
            return day >= 1 && day <= daysInMonth ? day : null;
          });
          const isActiveMonth = month === viewDate.getMonth();
          const isTodayMonth = month === today.getMonth() && year === today.getFullYear();

          const getEventsForDay = (day) => {
            const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
            return events.filter(e => e.date === dateStr);
          };

          return (
            <div key={month}
              onClick={() => onMonthClick(new Date(year, month, 1))}
              style={{ background: 'var(--card)', border: `1px solid ${isActiveMonth ? 'var(--primary)' : 'var(--border)'}`, borderRadius: '14px', padding: '12px', cursor: 'pointer', transition: 'box-shadow 0.1s' }}
              onMouseEnter={e => e.currentTarget.style.boxShadow = '0 4px 16px rgba(58,42,32,0.1)'}
              onMouseLeave={e => e.currentTarget.style.boxShadow = 'none'}>
              <div style={{ fontSize: '12px', fontWeight: 700, color: isActiveMonth ? 'var(--primary)' : 'var(--text)', marginBottom: '8px', textTransform: 'capitalize', fontFamily: "'DM Sans', sans-serif" }}>
                {new Date(year, month, 1).toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { month: 'long' })}
                {isTodayMonth && <span style={{ marginLeft: '6px', fontSize: '10px', color: 'var(--primary)', fontWeight: 700 }}>●</span>}
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '1px' }}>
                {CAL_DAY_INITIALS().map((d, i) => (
                  <div key={i} style={{ fontSize: '8px', color: 'var(--muted)', textAlign: 'center', fontWeight: 600 }}>{d}</div>
                ))}
                {cells.map((day, idx) => {
                  const dayEvs = day ? getEventsForDay(day) : [];
                  const firstColor = dayEvs.length ? getEventColor(dayEvs[0]) : null;
                  const isT = day === today.getDate() && isTodayMonth;
                  return (
                    <div key={`${month}-${day || 'e' + idx}`} style={{ textAlign: 'center', fontSize: '9px', color: isT ? '#fff' : day ? 'var(--text)' : 'transparent', background: isT ? 'var(--primary)' : 'transparent', borderRadius: '50%', width: '14px', height: '14px', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto', position: 'relative' }}>
                      {day || ''}
                      {firstColor && !isT && day && (
                        <div style={{ position: 'absolute', bottom: '0px', left: '50%', transform: 'translateX(-50%)', width: '3px', height: '3px', borderRadius: '50%', background: firstColor }} />
                      )}
                    </div>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function EventModal({ open, event, quotes, onSave, onDelete, onClose }) {
  const { t } = window.ReactI18next.useTranslation();
  const { teamMembers } = window.LelusaStore.useBusinessData();
  const isNew = !event || event === 'new';
  const initialForm = {
    name: '',
    client: '',
    type: 'otro',
    date: '',
    time: '10:00',
    duration: 2,
    eventPlace: '',
    status: 'reservado',
    customColor: '',
    contact: '',
    budget: '',
    quoteId: '',
    department: 'decoracion',
    serviceDepartments: ['decoracion'],
    assignedUserIds: [],
    notes: '',
  };

  const [form, setForm] = React.useState(initialForm);
  const [errors, setErrors] = React.useState({});
  const [confirmDelete, setConfirmDelete] = React.useState(false);

  React.useEffect(() => {
    if (!open) { setErrors({}); setConfirmDelete(false); return; }
    if (isNew) {
      const preDate = event && event.date ? event.date : '';
      const preType = event && event.type ? event.type : 'otro';
      const preStatus = event && event.status ? event.status : 'reservado';
      const preDepartment = preType === 'postres' ? 'postres' : 'decoracion';
      setForm({ ...initialForm, date: preDate, type: preType, department: preDepartment, serviceDepartments: [preDepartment], status: preStatus });
    } else {
      const serviceDepartments = Array.isArray(event.serviceDepartments) && event.serviceDepartments.length
        ? event.serviceDepartments
        : [event.department || (event.type === 'postres' ? 'postres' : 'decoracion')];
      setForm({
        name: event.name || '',
        client: event.client || '',
        type: event.type || 'otro',
        date: event.date || '',
        time: event.time || '10:00',
        duration: event.duration || 2,
        eventPlace: event.eventPlace || '',
        status: event.status || 'reservado',
        customColor: event.customColor || '',
        contact: event.contact || '',
        budget: event.budget != null ? String(event.budget) : '',
        quoteId: event.quoteId || '',
        department: event.department || (event.type === 'postres' ? 'postres' : 'decoracion'),
        serviceDepartments,
        assignedUserIds: event.assignedUserIds || [],
        notes: event.notes || '',
      });
    }
    setErrors({});
    setConfirmDelete(false);
  }, [open, event]);

  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  if (!open) return null;

  const set = (key, val) => setForm(f => ({ ...f, [key]: val }));
  const toggleServiceDepartment = (department) => setForm(f => {
    const current = Array.isArray(f.serviceDepartments) && f.serviceDepartments.length ? f.serviceDepartments : [f.department || 'decoracion'];
    const exists = current.includes(department);
    const next = exists ? current.filter(item => item !== department) : [...current, department];
    const serviceDepartments = next.length ? next : [department];
    const primary = serviceDepartments.includes(f.department) ? f.department : serviceDepartments[0];
    return { ...f, serviceDepartments, department: primary };
  });

  const validate = () => {
    const errs = {};
    if (!form.name.trim()) errs.name = t('admin_event_name_required');
    if (!form.date) errs.date = t('admin_event_date_required');
    return errs;
  };

  const handleSave = () => {
    const errs = validate();
    if (Object.keys(errs).length) { setErrors(errs); return; }
    const payload = {
      ...form,
      duration: Number(form.duration) || 1,
      budget: form.budget !== '' ? Number(form.budget) : null,
      quoteId: form.quoteId || null,
      department: form.department || 'decoracion',
      serviceDepartments: Array.isArray(form.serviceDepartments) && form.serviceDepartments.length ? form.serviceDepartments : [form.department || 'decoracion'],
      assignedUserIds: form.assignedUserIds || [],
    };
    if (!isNew) payload.id = event.id;
    onSave(payload);
  };

  const handleDelete = () => {
    if (!confirmDelete) { setConfirmDelete(true); return; }
    onDelete(event.id);
  };

  const isNota = form.type === 'nota';
  const isMobile = window.innerWidth < 768;
  const activeDepartments = Array.isArray(form.serviceDepartments) && form.serviceDepartments.length ? form.serviceDepartments : [form.department || 'decoracion'];
  const assignableMembers = (teamMembers || []).filter(member => member.active !== false && (activeDepartments.includes(member.department) || member.department === 'direccion'));

  const inputStyle = { width: '100%', padding: '10px 12px', border: '1px solid var(--border)', borderRadius: '10px', background: 'var(--bg-soft)', color: 'var(--text)', fontFamily: "'DM Sans', sans-serif", fontSize: '16px', outline: 'none', boxSizing: 'border-box' };
  const labelStyle = { display: 'block', fontSize: '12px', fontWeight: 700, color: 'var(--muted)', marginBottom: '5px', fontFamily: "'DM Sans', sans-serif" };
  const fieldStyle = { marginBottom: '14px' };
  const COLOR_SWATCHES = ['#C4899A','#3A62C8','#2A8A50','#C8881A','#9A4AC8','#C83A3A','#6A4AC8','#9A8070'];

  const statusColor = CAL_STATUS_COLORS[form.status] || '#C4899A';

  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 300, background: 'rgba(58,42,32,0.42)', display: 'flex', alignItems: isMobile ? 'flex-end' : 'center', justifyContent: 'center', padding: isMobile ? 0 : '22px', backdropFilter: 'blur(4px)' }} onClick={onClose}>
      <div style={{ width: '100%', maxWidth: isMobile ? '100%' : '560px', maxHeight: isMobile ? '95vh' : '88vh', background: 'var(--card)', border: '1px solid var(--border)', borderRadius: isMobile ? '20px 20px 0 0' : '20px', boxShadow: '0 28px 80px rgba(58,42,32,0.24)', display: 'flex', flexDirection: 'column', overflow: 'hidden' }} onClick={e => e.stopPropagation()}>
        {/* Header */}
        <div style={{ padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <h2 style={{ margin: 0, fontFamily: "'Cormorant Garamond', serif", fontSize: '22px', fontWeight: 600, color: 'var(--text)' }}>
            {isNew ? t('admin_event_new') : t('admin_event_edit')}
          </h2>
          <button onClick={onClose} style={{ background: 'var(--bg-soft)', border: '1px solid var(--border)', borderRadius: '10px', width: '32px', height: '32px', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="x" size={15} color="var(--muted)" />
          </button>
        </div>
        {/* Body */}
        <div style={{ padding: '20px 22px', overflowY: 'auto' }}>
          {/* Name */}
          <div style={fieldStyle}>
            <label style={labelStyle}>{t('admin_event_field_name')}</label>
            <input value={form.name} onChange={e => set('name', e.target.value)} placeholder={t('admin_event_name_ph')} style={{ ...inputStyle, borderColor: errors.name ? '#C83A3A' : 'var(--border)' }} />
            {errors.name && <div style={{ fontSize: '11px', color: '#C83A3A', marginTop: '3px' }}>{errors.name}</div>}
          </div>
          {/* Client + Type row */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginBottom: '14px' }}>
            <div>
              <label style={labelStyle}>{t('admin_event_field_client')}</label>
              <input value={form.client} onChange={e => set('client', e.target.value)} placeholder={t('admin_event_client_ph')} style={inputStyle} />
            </div>
            <div>
              <label style={labelStyle}>{t('admin_event_field_type')}</label>
              <select value={form.type} onChange={e => {
                const nextType = e.target.value;
                setForm(f => ({
                  ...f,
                  type: nextType,
                  department: nextType === 'postres' ? 'postres' : f.department,
                  serviceDepartments: nextType === 'postres' ? ['postres'] : (f.serviceDepartments || ['decoracion']),
                }));
              }} style={inputStyle}>
                {CAL_EVENT_TYPES.map(type => <option key={type} value={type}>{calTypeLabel(type)}</option>)}
              </select>
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginBottom: '14px' }} className="form-row">
            <div>
              <label style={labelStyle}>{t('admin_event_field_department')}</label>
              <select value={form.department} onChange={e => {
                const department = e.target.value;
                setForm(f => ({
                  ...f,
                  department,
                  serviceDepartments: Array.from(new Set([department, ...((f.serviceDepartments || []).filter(item => ['decoracion', 'postres'].includes(item)))])),
                }));
              }} style={inputStyle}>
                <option value="decoracion">{t('admin_cal_dept_decoracion')}</option>
                <option value="postres">{t('admin_cal_dept_postres')}</option>
                <option value="operaciones">{t('admin_cal_dept_operaciones')}</option>
                <option value="finanzas">{t('admin_cal_dept_finanzas')}</option>
                <option value="direccion">{t('admin_cal_dept_direccion')}</option>
              </select>
              {!isNota && (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 8 }}>
                  {['decoracion', 'postres'].map(department => {
                    const active = activeDepartments.includes(department);
                    return (
                      <button key={department} type="button" onClick={() => toggleServiceDepartment(department)}
                        style={{ border: `1px solid ${active ? 'var(--primary)' : 'var(--border)'}`, background: active ? 'var(--accent-light)' : 'var(--card)', color: active ? 'var(--primary)' : 'var(--muted)', borderRadius: 999, padding: '6px 9px', fontSize: 11, fontWeight: 800, cursor: 'pointer' }}>
                        {department === 'postres' ? t('admin_cal_dept_postres') : t('admin_cal_dept_decoracion')}
                      </button>
                    );
                  })}
                </div>
              )}
            </div>
            <div>
              <label style={labelStyle}>{t('admin_event_field_team')}</label>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px', minHeight: '42px', padding: '7px', border: '1px solid var(--border)', borderRadius: '10px', background: 'var(--bg-soft)' }}>
                {assignableMembers.length === 0 ? (
                  <span style={{ fontSize: '12px', color: 'var(--muted)', alignSelf: 'center' }}>{t('admin_event_no_active_team')}</span>
                ) : assignableMembers.map(member => {
                  const active = (form.assignedUserIds || []).includes(member.id);
                  return (
                    <button key={member.id} type="button" onClick={() => set('assignedUserIds', active ? form.assignedUserIds.filter(id => id !== member.id) : [...(form.assignedUserIds || []), member.id])}
                      style={{ border: `1px solid ${active ? 'var(--primary)' : 'var(--border)'}`, background: active ? 'var(--accent-light)' : 'var(--card)', color: active ? 'var(--primary)' : 'var(--muted)', borderRadius: '999px', padding: '6px 9px', fontSize: '11px', fontWeight: 700, cursor: 'pointer' }}>
                      {member.name}
                    </button>
                  );
                })}
              </div>
            </div>
          </div>
          {/* Date + Time + Duration */}
          <div style={{ display: 'grid', gridTemplateColumns: isNota ? '1fr' : '1fr 1fr 1fr', gap: '12px', marginBottom: '14px' }}>
            <div>
              <label style={labelStyle}>{t('admin_event_field_date')}</label>
              <input type="date" value={form.date} onChange={e => set('date', e.target.value)} style={{ ...inputStyle, borderColor: errors.date ? '#C83A3A' : 'var(--border)' }} />
              {errors.date && <div style={{ fontSize: '11px', color: '#C83A3A', marginTop: '3px' }}>{errors.date}</div>}
            </div>
            {!isNota && (
              <>
                <div>
                  <label style={labelStyle}>{t('admin_event_field_start_time')}</label>
                  <input type="time" value={form.time} onChange={e => set('time', e.target.value)} style={inputStyle} />
                </div>
                <div>
                  <label style={labelStyle}>{t('admin_event_field_duration')}</label>
                  <input type="number" value={form.duration} onChange={e => set('duration', e.target.value)} min="1" max="24" style={inputStyle} />
                </div>
              </>
            )}
          </div>
          {/* Place */}
          <div style={fieldStyle}>
            <label style={labelStyle}>{t('admin_event_field_place')}</label>
            <input value={form.eventPlace} onChange={e => set('eventPlace', e.target.value)} placeholder={t('admin_event_place_ph')} style={inputStyle} />
          </div>
          {/* Status + Color */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: '12px', marginBottom: '14px', alignItems: 'flex-start' }}>
            <div>
              <label style={labelStyle}>{t('admin_event_field_status')}</label>
              <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                <select value={form.status} onChange={e => set('status', e.target.value)} style={{ ...inputStyle, flex: 1 }}>
                  {Object.keys(CAL_STATUS_I18N).map(s => <option key={s} value={s}>{calStatusLabel(s)}</option>)}
                </select>
                <div style={{ width: '20px', height: '20px', borderRadius: '6px', background: statusColor, flexShrink: 0 }} />
              </div>
            </div>
            <div>
              <label style={labelStyle}>{t('admin_event_field_color')}</label>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: '5px', width: '80px' }}>
                {COLOR_SWATCHES.map(c => (
                  <div key={c} onClick={() => set('customColor', form.customColor === c ? '' : c)}
                    style={{ width: '22px', height: '22px', borderRadius: '6px', background: c, cursor: 'pointer', border: form.customColor === c ? '2px solid var(--text)' : '2px solid transparent', boxSizing: 'border-box' }} />
                ))}
              </div>
            </div>
          </div>
          {/* Contact + Budget */}
          {!isNota && (
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginBottom: '14px' }}>
              <div>
                <label style={labelStyle}>{t('admin_event_field_phone')}</label>
                <input type="tel" value={form.contact} onChange={e => set('contact', e.target.value)} placeholder={t('admin_event_phone_ph')} style={inputStyle} />
              </div>
              <div>
                <label style={labelStyle}>{t('admin_event_field_budget')}</label>
                <div style={{ position: 'relative' }}>
                  <span style={{ position: 'absolute', left: '12px', top: '50%', transform: 'translateY(-50%)', fontSize: '14px', color: 'var(--muted)' }}>$</span>
                  <input type="number" value={form.budget} onChange={e => set('budget', e.target.value)} placeholder="0" min="0" style={{ ...inputStyle, paddingLeft: '24px' }} />
                </div>
              </div>
            </div>
          )}
          {/* Linked quote */}
          {!isNota && quotes && quotes.length > 0 && (
            <div style={fieldStyle}>
              <label style={labelStyle}>{t('admin_event_field_linked_quote')}</label>
              <select value={form.quoteId} onChange={e => set('quoteId', e.target.value)} style={inputStyle}>
                <option value="">{t('admin_event_no_link')}</option>
                {quotes.map(q => <option key={q.id} value={q.id}>{q.id} · {q.clientName}</option>)}
              </select>
            </div>
          )}
          {/* Notes */}
          <div style={fieldStyle}>
            <label style={labelStyle}>{t('admin_event_field_notes')}</label>
            <textarea value={form.notes} onChange={e => set('notes', e.target.value)} rows={4} placeholder={t('admin_event_notes_ph')} style={{ ...inputStyle, resize: 'vertical' }} />
          </div>
        </div>
        {/* Footer */}
        <div style={{ padding: '14px 22px', borderTop: '1px solid var(--border)', display: 'flex', gap: '8px', justifyContent: 'flex-end', background: 'var(--card)', flexShrink: 0 }}>
          {!isNew && (
            <button onClick={handleDelete}
              style={{ marginRight: 'auto', background: confirmDelete ? '#C83A3A' : 'transparent', color: confirmDelete ? '#fff' : '#C83A3A', border: `1px solid #C83A3A`, borderRadius: '10px', padding: '9px 14px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, fontFamily: "'DM Sans', sans-serif", transition: 'all 0.15s' }}>
              {confirmDelete ? t('admin_event_confirm_delete') : t('admin_event_delete')}
            </button>
          )}
          <button onClick={onClose} style={{ background: 'var(--bg-soft)', border: '1px solid var(--border)', borderRadius: '10px', padding: '9px 16px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, color: 'var(--muted)', fontFamily: "'DM Sans', sans-serif" }}>
            {t('admin_event_cancel')}
          </button>
          <button onClick={handleSave} style={{ background: 'var(--primary)', border: 'none', borderRadius: '10px', padding: '9px 18px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, color: '#fff', fontFamily: "'DM Sans', sans-serif" }}>
            {isNew ? t('admin_event_save') : t('admin_event_save_changes')}
          </button>
        </div>
      </div>
    </div>
  );
}

function EventDetailPanel({ event, isMobile, onEdit, onClose, onStatusChange, onNavigateQuote, onOpenDetail, onAddGoogleCalendar }) {
  const { t } = window.ReactI18next.useTranslation();
  const { teamMembers } = window.LelusaStore.useBusinessData();
  const [statusOpen, setStatusOpen] = React.useState(false);
  const color = getEventColor(event);

  React.useEffect(() => {
    if (!event) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [event, onClose]);

  if (!event) return null;
  const serviceDepartments = Array.isArray(event.serviceDepartments) && event.serviceDepartments.length
    ? event.serviceDepartments
    : [event.department || (event.type === 'postres' ? 'postres' : 'decoracion')];

  const rows = [
    event.date ? ['calendar', new Date(event.date + 'T12:00:00').toLocaleDateString(i18next.language === 'es' ? 'es-MX' : 'en-US', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' })] : null,
    event.time && event.type !== 'nota' ? ['clock', t('admin_event_duration_label', { time: event.time, duration: event.duration })] : null,
    event.client ? ['user', event.client] : null,
    event.contact ? ['phone', event.contact] : null,
    event.eventPlace ? ['mapPin', event.eventPlace] : null,
    event.designName ? ['package', event.designName] : null,
    serviceDepartments.length ? ['clients', t('admin_event_department_label', { department: serviceDepartments.map(dept => (window.DEPARTMENT_LABELS || {})[dept] || dept).join(' + ') })] : null,
    event.budget != null ? ['star', t('admin_event_budget_label', { amount: Number(event.budget).toLocaleString() })] : null,
  ].filter(Boolean);
  const assignedNames = (teamMembers || [])
    .filter(member => (event.assignedUserIds || []).includes(member.id))
    .map(member => member.name);

  const panelContent = (
    <div style={{ padding: '20px' }}>
      {/* Color dot + name + close */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: '12px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '10px', flex: 1, minWidth: 0 }}>
          <div style={{ width: '12px', height: '12px', borderRadius: '50%', background: color, flexShrink: 0 }} />
          <h3 style={{ margin: 0, fontFamily: "'Cormorant Garamond', serif", fontSize: '20px', fontWeight: 600, color: 'var(--text)', lineHeight: 1.2 }}>{event.name}</h3>
        </div>
        <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '2px', flexShrink: 0 }}>
          <Icon name="x" size={16} color="var(--muted)" />
        </button>
      </div>

      {/* Status badge + change */}
      <div style={{ position: 'relative', marginBottom: '16px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
          <StatusBadge status={event.status} />
          <button onClick={() => setStatusOpen(o => !o)}
            style={{ background: 'none', border: '1px solid var(--border)', borderRadius: '8px', padding: '3px 8px', cursor: 'pointer', fontSize: '11px', fontWeight: 700, color: 'var(--muted)', fontFamily: "'DM Sans', sans-serif", display: 'flex', alignItems: 'center', gap: '4px' }}>
            {t('admin_event_change')} <Icon name="chevDown" size={11} color="var(--muted)" />
          </button>
        </div>
        {statusOpen && (
          <div style={{ position: 'absolute', top: '32px', left: 0, background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '12px', boxShadow: '0 8px 24px rgba(58,42,32,0.12)', zIndex: 10, minWidth: '180px', padding: '4px' }}>
            {Object.keys(CAL_STATUS_I18N).map((s) => (
              <div key={s} onClick={() => { onStatusChange(event.id, s); setStatusOpen(false); }}
                style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '8px 10px', borderRadius: '8px', cursor: 'pointer', background: event.status === s ? `${CAL_STATUS_COLORS[s]}18` : 'transparent' }}
                onMouseEnter={e => e.currentTarget.style.background = `${CAL_STATUS_COLORS[s]}18`}
                onMouseLeave={e => e.currentTarget.style.background = event.status === s ? `${CAL_STATUS_COLORS[s]}18` : 'transparent'}>
                <div style={{ width: '8px', height: '8px', borderRadius: '50%', background: CAL_STATUS_COLORS[s], flexShrink: 0 }} />
                <span style={{ fontSize: '12px', color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{calStatusLabel(s)}</span>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Info rows */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', marginBottom: '16px' }}>
        {rows.map(([iconName, text]) => (
          <div key={text} style={{ display: 'flex', alignItems: 'flex-start', gap: '8px' }}>
            <Icon name={iconName} size={13} color="var(--muted)" />
            <span style={{ fontSize: '12px', color: 'var(--muted)', lineHeight: 1.5, fontFamily: "'DM Sans', sans-serif" }}>{text}</span>
          </div>
        ))}
      </div>

      {(serviceDepartments.length > 0 || assignedNames.length > 0) && (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px', marginBottom: '16px' }}>
          {serviceDepartments.map(dept => (
            <span key={dept} style={{ border: '1px solid var(--border)', background: dept === 'postres' ? 'rgba(200,136,26,0.12)' : 'var(--accent-light)', borderRadius: '999px', padding: '5px 8px', fontSize: '11px', color: dept === 'postres' ? '#A56A14' : 'var(--primary)', fontWeight: 800 }}>
              {(window.DEPARTMENT_LABELS || {})[dept] || dept}
            </span>
          ))}
          {assignedNames.map(name => (
            <span key={name} style={{ border: '1px solid var(--border)', background: 'var(--bg-soft)', borderRadius: '999px', padding: '5px 8px', fontSize: '11px', color: 'var(--muted)', fontWeight: 700 }}>
              {name}
            </span>
          ))}
        </div>
      )}

      {/* Notes */}
      {(event.notes || event.details) && (
        <div style={{ background: 'var(--bg-soft)', borderRadius: '10px', padding: '10px 12px', fontSize: '12px', color: 'var(--muted)', lineHeight: 1.6, whiteSpace: 'pre-wrap', marginBottom: '16px', fontFamily: "'DM Sans', sans-serif" }}>
          {event.notes || event.details}
        </div>
      )}

      {/* Actions */}
      <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
        <button onClick={() => onEdit(event)} style={{ flex: 1, background: 'var(--primary)', color: '#fff', border: 'none', borderRadius: '10px', padding: '9px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, fontFamily: "'DM Sans', sans-serif" }}>
          {t('admin_event_edit_btn')}
        </button>
        <button onClick={() => onOpenDetail?.(event)} style={{ background: 'var(--card)', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: '10px', padding: '9px 12px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, fontFamily: "'DM Sans', sans-serif" }}>
          {t('admin_event_open_detail')}
        </button>
        {event.type !== 'nota' && (
          <button onClick={() => onAddGoogleCalendar?.(event)} style={{ background: 'var(--accent-light)', color: 'var(--primary)', border: 'none', borderRadius: '10px', padding: '9px 12px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, fontFamily: "'DM Sans', sans-serif" }}>
            {t('admin_event_add_google')}
          </button>
        )}
        {event.quoteId && (
          <button onClick={() => onNavigateQuote(event.quoteId)} style={{ background: 'var(--accent-light)', color: 'var(--primary)', border: 'none', borderRadius: '10px', padding: '9px 12px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, fontFamily: "'DM Sans', sans-serif" }}>
            {t('admin_event_view_quote')}
          </button>
        )}
      </div>
    </div>
  );

  if (isMobile) {
    return (
      <div style={{ position: 'fixed', inset: 0, zIndex: 300, background: 'rgba(58,42,32,0.42)', display: 'flex', alignItems: 'flex-end', backdropFilter: 'blur(4px)' }} onClick={onClose}>
        <div style={{ width: '100%', maxHeight: '80vh', background: 'var(--card)', borderRadius: '20px 20px 0 0', overflowY: 'auto', border: '1px solid var(--border)' }} onClick={e => e.stopPropagation()}>
          {panelContent}
        </div>
      </div>
    );
  }

  return (
    <div style={{ background: 'var(--card)', border: `2px solid ${color}40`, borderRadius: '16px', overflow: 'visible', flexShrink: 0 }}>
      {panelContent}
    </div>
  );
}

function DetailMetric({ label, value, sub, icon = 'calendar', color = 'var(--primary)' }) {
  return (
    <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '14px', padding: '14px', minWidth: 0 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, color: 'var(--muted)', fontSize: 12, fontWeight: 800, marginBottom: 8 }}>
        <Icon name={icon} size={14} color={color} /> {label}
      </div>
      <div style={{ color: 'var(--text)', fontSize: 20, fontWeight: 900, lineHeight: 1.15 }}>{value || '-'}</div>
      {sub && <div style={{ color: 'var(--muted)', fontSize: 12, marginTop: 4 }}>{sub}</div>}
    </div>
  );
}

function DetailSection({ title, children, action }) {
  return (
    <section style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '16px', padding: '18px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, marginBottom: 14 }}>
        <h3 style={{ margin: 0, fontSize: 15, fontWeight: 900, color: 'var(--text)' }}>{title}</h3>
        {action}
      </div>
      {children}
    </section>
  );
}

function EmptyState({ message }) {
  return (
    <div style={{ border: '1px dashed var(--border)', borderRadius: '14px', padding: '16px', color: 'var(--muted)', fontSize: 13, lineHeight: 1.5, background: 'var(--bg-soft)' }}>
      {message}
    </div>
  );
}

function EventDetailPage() {
  const { pageData, navigate } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const { events, quotes, designs, assets, desserts, expenses, teamMembers } = window.LelusaStore.useBusinessData();
  const event = (events || []).find(item => String(item.id) === String(pageData.eventId));

  if (!event) {
    return (
      <AdminLayout title={t('admin_event_detail_title')} subtitle={t('admin_event_detail_missing')}>
        <Btn variant="ghost" onClick={() => navigate('admin-calendar')}>{t('admin_event_back_calendar')}</Btn>
      </AdminLayout>
    );
  }

  const quote = (quotes || []).find(item => String(item.id) === String(event.quoteId));
  const design = quote ? (designs || []).find(item => String(item.id) === String(quote.designId)) : null;
  const assigned = (teamMembers || []).filter(member => (event.assignedUserIds || []).includes(member.id));
  const serviceDepartments = Array.isArray(event.serviceDepartments) && event.serviceDepartments.length
    ? event.serviceDepartments
    : [event.department || (event.type === 'postres' ? 'postres' : 'decoracion')];
  const relatedEvents = event.quoteId
    ? (events || []).filter(item => String(item.quoteId) === String(event.quoteId) && String(item.id) !== String(event.id))
    : [];
  const linkedExpenses = (expenses || []).filter(item => String(item.eventId) === String(event.id) || (quote && String(item.quoteId) === String(quote.id)));
  const expenseTotal = linkedExpenses.reduce((sum, item) => sum + Number(item.amount || 0), 0);
  const income = Number(quote?.total ?? event.budget ?? 0);
  const margin = income ? Math.round(((income - expenseTotal) / income) * 100) : null;
  const designMaterials = [
    ...((design?.materials || []).map(item => ({ assetId: item.assetId, quantity: item.quantity || 1 }))),
    ...((design?.assetIds || []).map(assetId => ({ assetId, quantity: 1 }))),
  ];
  const uniqueMaterials = Array.from(new Map(designMaterials.map(item => [String(item.assetId), item])).values())
    .map(item => ({ ...item, asset: (assets || []).find(asset => String(asset.id) === String(item.assetId)) }))
    .filter(item => item.asset);
  const dessertNotes = quote?.dessertRequest?.notes || '';
  const dessertList = event.dessertItems?.length ? event.dessertItems : (quote?.dessertRequest?.items || []);
  const optionLabels = quote?.selectedOptionLabels || [];
  const extraLabels = quote?.selectedExtraLabels || [];

  const row = (label, value) => value ? (
    <div style={{ display: 'flex', justifyContent: 'space-between', gap: 16, padding: '9px 0', borderBottom: '1px solid var(--border)', fontSize: 13 }}>
      <span style={{ color: 'var(--muted)' }}>{label}</span>
      <span style={{ color: 'var(--text)', fontWeight: 800, textAlign: 'right' }}>{value}</span>
    </div>
  ) : null;

  return (
    <AdminLayout title={event.name} subtitle={t('admin_event_detail_subtitle', { id: event.id })}>
      <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap', marginBottom: 18 }}>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          <Btn variant="ghost" onClick={() => navigate('admin-calendar')}>{t('admin_event_back_calendar')}</Btn>
          {quote && <Btn variant="ghost" onClick={() => navigate('admin-quotes', { highlightId: quote.id })}>{t('admin_event_view_quote')}</Btn>}
        </div>
        <Btn onClick={() => openGoogleCalendarEvent(event, quote)}>
          <Icon name="calendar" size={15} color="#fff" /> {t('admin_event_add_google')}
        </Btn>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 12, marginBottom: 18 }}>
        <DetailMetric icon="calendar" label={t('admin_event_detail_date')} value={event.date} sub={event.time ? t('admin_event_duration_label', { time: event.time, duration: event.duration }) : null} />
        <DetailMetric icon="mapPin" label={t('admin_event_detail_place')} value={event.eventPlace || t('admin_event_place_pending')} />
        <DetailMetric icon="star" label={t('admin_event_detail_income')} value={`$${income.toLocaleString()}`} sub={margin != null ? t('admin_event_detail_margin', { margin }) : null} color="#2A8A50" />
        <DetailMetric icon="fileText" label={t('admin_event_detail_expenses')} value={`$${expenseTotal.toLocaleString()}`} sub={t('admin_event_detail_expense_count', { count: linkedExpenses.length })} color="#C8881A" />
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.35fr) minmax(280px, 0.65fr)', gap: 16 }} className="form-row">
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <DetailSection title={t('admin_event_detail_overview')}>
            {row(t('admin_event_field_client'), event.client)}
            {row(t('admin_quotes_field_phone'), event.contact)}
            {row(t('admin_quotes_field_design'), event.designName || design?.name)}
            {row(t('admin_event_field_department'), serviceDepartments.map(dept => (window.DEPARTMENT_LABELS || {})[dept] || dept).join(' + '))}
            {row(t('admin_event_field_status'), calStatusLabel(event.status))}
            <TagList title={t('admin_event_detail_service_areas')} items={serviceDepartments.map(dept => (window.DEPARTMENT_LABELS || {})[dept] || dept)} />
            {(event.notes || event.details) && (
              <div style={{ whiteSpace: 'pre-wrap', color: 'var(--muted)', lineHeight: 1.65, fontSize: 13, marginTop: 12 }}>{event.notes || event.details}</div>
            )}
          </DetailSection>

          <DetailSection title={t('admin_event_detail_specifications')}>
            {quote ? (
              <>
                {row(t('admin_quotes_field_event_type'), quote.eventType)}
                {row(t('admin_quotes_field_guests'), quote.guests ? t('admin_quotes_guests', { count: quote.guests }) : '')}
                {row(t('admin_quotes_field_setup'), quote.setupWindow)}
                {row(t('admin_quotes_detail_theme'), quote.decorationDetails?.theme)}
                {row(t('admin_quotes_detail_colors'), quote.decorationDetails?.colors)}
                {row(t('admin_quotes_detail_focus'), quote.decorationDetails?.focus)}
                {row(t('admin_quotes_detail_musthave'), quote.decorationDetails?.mustHave)}
                {row(t('admin_quotes_detail_budget'), quote.decorationDetails?.budgetRange)}
                {optionLabels.length > 0 && <TagList title={t('admin_quotes_options')} items={optionLabels} />}
                {extraLabels.length > 0 && <TagList title={t('admin_quotes_extras')} items={extraLabels} />}
              </>
            ) : (
              <EmptyState message={t('admin_event_detail_no_quote')} />
            )}
          </DetailSection>

          <DetailSection title={t('admin_event_detail_inventory')}>
            {uniqueMaterials.length ? (
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: 10 }}>
                {uniqueMaterials.map(({ asset, quantity }) => (
                  <div key={asset.id} style={{ border: '1px solid var(--border)', borderRadius: 12, padding: 10, display: 'flex', gap: 10, alignItems: 'center' }}>
                    {asset.image && <img src={asset.image} alt={asset.name} style={{ width: 42, height: 42, objectFit: 'cover', borderRadius: 8 }} />}
                    <div style={{ minWidth: 0 }}>
                      <div style={{ color: 'var(--text)', fontWeight: 900, fontSize: 13 }}>{asset.name}</div>
                      <div style={{ color: 'var(--muted)', fontSize: 11 }}>{asset.category} · x{quantity}</div>
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <EmptyState message={t('admin_event_detail_no_inventory')} />
            )}
          </DetailSection>
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <DetailSection title={t('admin_event_detail_team')}>
            {assigned.length ? assigned.map(member => (
              <div key={member.id} style={{ display: 'flex', justifyContent: 'space-between', gap: 10, padding: '8px 0', borderBottom: '1px solid var(--border)' }}>
                <span style={{ color: 'var(--text)', fontWeight: 800 }}>{member.name}</span>
                <span style={{ color: 'var(--muted)', fontSize: 12 }}>{member.department}</span>
              </div>
            )) : <EmptyState message={t('admin_event_detail_no_team')} />}
          </DetailSection>

          <DetailSection title={t('admin_event_detail_related_events')}>
            {relatedEvents.length ? relatedEvents.map(item => (
              <button key={item.id} onClick={() => navigate('admin-event-detail', { eventId: item.id })}
                style={{ width: '100%', textAlign: 'left', border: '1px solid var(--border)', background: 'var(--bg-soft)', borderRadius: 12, padding: 10, cursor: 'pointer', marginBottom: 8 }}>
                <div style={{ color: 'var(--text)', fontWeight: 900, fontSize: 13 }}>{item.name}</div>
                <div style={{ color: 'var(--muted)', fontSize: 11, marginTop: 3 }}>{item.date} · {item.time || '10:00'} · {(window.DEPARTMENT_LABELS || {})[item.department] || item.department}</div>
              </button>
            )) : <EmptyState message={t('admin_event_detail_no_related_events')} />}
          </DetailSection>

          <DetailSection title={t('admin_event_detail_desserts')}>
            {dessertNotes && <div style={{ color: 'var(--muted)', fontSize: 13, lineHeight: 1.6, marginBottom: 10 }}>{dessertNotes}</div>}
            {dessertList?.length ? <TagList items={dessertList.map(item => item.name || item.label || item.id || item)} /> : <EmptyState message={t('admin_event_detail_no_desserts')} />}
          </DetailSection>

          <DetailSection title={t('admin_event_detail_finance')}>
            {row(t('admin_quotes_total_quoted'), quote ? `$${Number(quote.total || 0).toLocaleString()}` : '')}
            {row(t('admin_event_field_budget'), event.budget != null ? `$${Number(event.budget || 0).toLocaleString()}` : '')}
            {row(t('admin_event_detail_expenses'), `$${expenseTotal.toLocaleString()}`)}
            {row(t('admin_event_detail_profit'), income ? `$${Math.max(0, income - expenseTotal).toLocaleString()}` : '')}
          </DetailSection>
        </div>
      </div>
    </AdminLayout>
  );
}

function TagList({ title, items = [] }) {
  if (!items.length) return null;
  return (
    <div style={{ marginTop: title ? 12 : 0 }}>
      {title && <div style={{ color: 'var(--muted)', fontSize: 11, fontWeight: 900, textTransform: 'uppercase', marginBottom: 8 }}>{title}</div>}
      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
        {items.map((item, index) => {
          const label = String(item || '').trim();
          if (!label) return null;
          return <span key={`${label}-${index}`} style={{ border: '1px solid var(--border)', background: 'var(--bg-soft)', borderRadius: '999px', padding: '5px 9px', fontSize: 11, color: 'var(--muted)', fontWeight: 800 }}>{label}</span>;
        })}
      </div>
    </div>
  );
}

function CalendarPage() {
  const { events, quotes, teamMembers } = window.LelusaStore.useBusinessData();
  const { navigate } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const [view, setView] = React.useState('month');
  const [viewDate, setViewDate] = React.useState(() => new Date());
  const [filters, setFilters] = React.useState(new Set());
  const [selectedEvent, setSelectedEvent] = React.useState(null);
  const [editingEvent, setEditingEvent] = React.useState(null);
  const [sidebarOpen, setSidebarOpen] = React.useState(true);
  const [isMobile, setIsMobile] = React.useState(window.innerWidth < 768);
  const [calSheetOpen, setCalSheetOpen] = React.useState(false);
  const [departmentFilter, setDepartmentFilter] = React.useState('all');
  const [userFilter, setUserFilter] = React.useState('all');

  React.useEffect(() => {
    const onResize = () => setIsMobile(window.innerWidth < 768);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);

  React.useEffect(() => {
    const onKey = (e) => {
      if (editingEvent || selectedEvent) return;
      if (e.key === 'ArrowLeft') {
        setViewDate(d => {
          const nd = new Date(d);
          if (view === 'week') nd.setDate(nd.getDate() - 7);
          else if (view === 'day') nd.setDate(nd.getDate() - 1);
          else nd.setMonth(nd.getMonth() - 1);
          return nd;
        });
      }
      if (e.key === 'ArrowRight') {
        setViewDate(d => {
          const nd = new Date(d);
          if (view === 'week') nd.setDate(nd.getDate() + 7);
          else if (view === 'day') nd.setDate(nd.getDate() + 1);
          else nd.setMonth(nd.getMonth() + 1);
          return nd;
        });
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [view, editingEvent, selectedEvent]);

  const handleNavigate = (date) => setViewDate(date);

  const handleToggleFilter = (status) => {
    setFilters(prev => {
      const next = new Set(prev);
      if (next.has(status)) next.delete(status);
      else next.add(status);
      return next;
    });
  };

  const handleSelectEvent = (ev) => setSelectedEvent(ev);

  const handleDayClick = (dateStr) => {
    setEditingEvent({ date: dateStr, type: 'nota', status: 'nota' });
  };

  const handleSlotClick = (dateStr, timeStr) => {
    setEditingEvent({ date: dateStr, time: timeStr, type: 'otro', status: 'reservado' });
  };

  const handleNewEvent = () => setEditingEvent('new');

  const handleSave = (formData) => {
    if (editingEvent === 'new' || !formData.id) {
      window.LelusaStore.addEvent(formData);
    } else {
      window.LelusaStore.updateEvent(formData.id, formData);
      if (selectedEvent && selectedEvent.id === formData.id) {
        setSelectedEvent(ev => ({ ...ev, ...formData }));
      }
    }
    setEditingEvent(null);
  };

  const handleDelete = (id) => {
    window.LelusaStore.deleteEvent(id);
    setEditingEvent(null);
    if (selectedEvent && selectedEvent.id === id) setSelectedEvent(null);
  };

  const handleStatusChange = (id, status) => {
    window.LelusaStore.updateEvent(id, { status });
    if (selectedEvent && selectedEvent.id === id) {
      setSelectedEvent(ev => ({ ...ev, status }));
    }
  };

  const handleMonthClick = (date) => {
    setViewDate(date);
    setView('month');
  };

  const eventsThisMonth = events.filter(e => {
    const d = new Date(e.date + 'T12:00:00');
    return d.getFullYear() === viewDate.getFullYear() && d.getMonth() === viewDate.getMonth();
  });

  const visibleEvents = events.filter(event => {
    const serviceDepartments = Array.isArray(event.serviceDepartments) && event.serviceDepartments.length ? event.serviceDepartments : [event.department || (event.type === 'postres' ? 'postres' : 'decoracion')];
    const matchesDepartment = departmentFilter === 'all' || serviceDepartments.includes(departmentFilter) || (departmentFilter === 'postres' && event.type === 'postres');
    const matchesUser = userFilter === 'all' || (event.assignedUserIds || []).includes(userFilter);
    return matchesDepartment && matchesUser;
  });

  const viewProps = { viewDate, events: visibleEvents, filters, onSelectEvent: handleSelectEvent };

  return (
    <AdminLayout
      title={t('admin_calendar')}
      subtitle={t(eventsThisMonth.length === 1 ? 'admin_cal_subtitle_one' : 'admin_cal_subtitle_other', { count: eventsThisMonth.length })}
    >
      <div style={{ display: 'flex', height: isMobile ? 'calc(100vh - 64px - 152px)' : 'calc(100vh - 64px - 56px)', margin: isMobile ? 0 : '-28px', overflow: 'hidden', borderRadius: isMobile ? '16px' : 0, border: isMobile ? '1px solid var(--border)' : 'none', background: 'var(--card)' }}>

        {/* Sidebar */}
        {!isMobile && (
          <CalendarSidebar
            viewDate={viewDate}
            onNavigate={handleNavigate}
            filters={filters}
            onToggleFilter={handleToggleFilter}
            events={events}
            onSelectEvent={handleSelectEvent}
            onNewEvent={handleNewEvent}
            collapsed={!sidebarOpen}
            onToggleCollapse={() => setSidebarOpen(o => !o)}
            isMobile={isMobile}
          />
        )}

        {/* Main area */}
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', background: 'var(--bg-soft)' }}>
          <CalendarToolbar
            view={view}
            onViewChange={setView}
            viewDate={viewDate}
            onNavigate={handleNavigate}
            onToday={() => setViewDate(new Date())}
            isMobile={isMobile}
          />

          {/* Mobile: mini info bar */}
          {isMobile && (
            <div style={{ padding: '8px 12px', background: 'var(--card)', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '8px' }}>
              <span style={{ fontSize: '12px', color: 'var(--muted)', fontFamily: "'DM Sans', sans-serif", minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                {t('admin_cal_subtitle_other', { count: eventsThisMonth.length })}
              </span>
              <div style={{ display: 'flex', gap: '8px', flexShrink: 0 }}>
                <button onClick={() => setCalSheetOpen(true)} style={{ background: 'var(--bg-soft)', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: '20px', padding: '6px 12px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, fontFamily: "'DM Sans', sans-serif", display: 'flex', alignItems: 'center', gap: '4px', touchAction: 'manipulation' }}>
                  <Icon name="list" size={13} color="var(--text)" /> {t('admin_cal_filters')}
                </button>
                <button onClick={handleNewEvent} style={{ background: 'var(--primary)', color: '#fff', border: 'none', borderRadius: '20px', padding: '6px 14px', cursor: 'pointer', fontSize: '12px', fontWeight: 700, fontFamily: "'DM Sans', sans-serif", display: 'flex', alignItems: 'center', gap: '4px', touchAction: 'manipulation' }}>
                  <Icon name="plus" size={13} color="#fff" /> {t('admin_cal_new')}
                </button>
              </div>
            </div>
          )}
          <div style={{ padding: isMobile ? '8px 12px' : '10px 16px', background: 'var(--card)', borderBottom: '1px solid var(--border)', display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
            <select value={departmentFilter} onChange={e => { setDepartmentFilter(e.target.value); setUserFilter('all'); }} style={{ ...ADMIN_INPUT_STYLE, width: isMobile ? '100%' : 190, padding: '8px 10px', fontSize: '12px' }}>
              <option value="all">{t('admin_cal_all_departments')}</option>
              <option value="decoracion">{t('admin_cal_dept_decoracion')}</option>
              <option value="postres">{t('admin_cal_dept_postres')}</option>
              <option value="operaciones">{t('admin_cal_dept_operaciones')}</option>
              <option value="finanzas">{t('admin_cal_dept_finanzas')}</option>
              <option value="direccion">{t('admin_cal_dept_direccion')}</option>
            </select>
            <select value={userFilter} onChange={e => setUserFilter(e.target.value)} style={{ ...ADMIN_INPUT_STYLE, width: isMobile ? '100%' : 210, padding: '8px 10px', fontSize: '12px' }}>
              <option value="all">{t('admin_cal_all_users')}</option>
              {(teamMembers || []).filter(member => member.active !== false && (departmentFilter === 'all' || member.department === departmentFilter || member.department === 'direccion')).map(member => (
                <option key={member.id} value={member.id}>{member.name}</option>
              ))}
            </select>
          </div>

          {/* View */}
          <div style={{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
            {view === 'month' && <MonthView {...viewProps} onDayClick={handleDayClick} />}
            {view === 'week' && <WeekView {...viewProps} onSlotClick={handleSlotClick} />}
            {view === 'day' && <DayView {...viewProps} onSlotClick={handleSlotClick} />}
            {view === 'year' && <YearView viewDate={viewDate} events={events} onMonthClick={handleMonthClick} />}
          </div>
        </div>

        {/* Desktop: EventDetailPanel in right column */}
        {!isMobile && selectedEvent && (
          <div style={{ width: '280px', flexShrink: 0, overflowY: 'auto', padding: '16px', background: 'var(--bg-soft)', borderLeft: '1px solid var(--border)' }}>
            <EventDetailPanel
              event={selectedEvent}
              isMobile={false}
              onEdit={(ev) => { setEditingEvent(ev); }}
              onClose={() => setSelectedEvent(null)}
              onStatusChange={handleStatusChange}
              onNavigateQuote={(qid) => navigate('admin-quotes', { highlightId: qid })}
              onOpenDetail={(ev) => navigate('admin-event-detail', { eventId: ev.id })}
              onAddGoogleCalendar={(ev) => openGoogleCalendarEvent(ev, quotes.find(q => String(q.id) === String(ev.quoteId)))}
            />
          </div>
        )}
      </div>

      {/* Mobile: detail as bottom sheet */}
      {isMobile && selectedEvent && (
        <EventDetailPanel
          event={selectedEvent}
          isMobile={true}
          onEdit={(ev) => { setEditingEvent(ev); setSelectedEvent(null); }}
          onClose={() => setSelectedEvent(null)}
          onStatusChange={handleStatusChange}
          onNavigateQuote={(qid) => navigate('admin-quotes', { highlightId: qid })}
          onOpenDetail={(ev) => navigate('admin-event-detail', { eventId: ev.id })}
          onAddGoogleCalendar={(ev) => openGoogleCalendarEvent(ev, quotes.find(q => String(q.id) === String(ev.quoteId)))}
        />
      )}

      {/* Mobile: filters + events list as a sheet */}
      {isMobile && (
        <BottomSheet open={calSheetOpen} onClose={() => setCalSheetOpen(false)} title={t('admin_cal_filters_events')}>
          <CalendarSidebar
            viewDate={viewDate}
            onNavigate={handleNavigate}
            filters={filters}
            onToggleFilter={handleToggleFilter}
            events={events}
            onSelectEvent={(ev) => { setCalSheetOpen(false); handleSelectEvent(ev); }}
            onNewEvent={() => { setCalSheetOpen(false); handleNewEvent(); }}
            collapsed={false}
            onToggleCollapse={() => {}}
            isMobile={true}
          />
        </BottomSheet>
      )}

      {/* EventModal */}
      <EventModal
        open={editingEvent !== null}
        event={editingEvent}
        quotes={quotes}
        onSave={handleSave}
        onDelete={handleDelete}
        onClose={() => setEditingEvent(null)}
      />

      {/* Mobile "Nuevo" now lives in the info bar (Task 10); the old floating FAB
          was removed because it sat under the admin bottom nav (z-index). */}
    </AdminLayout>
  );
}

// ─── Scene Editor Admin Page ─────────────────────────────────────
function AdminSceneEditorPage() {
  const { pageData, navigate } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const { designs, assets } = window.LelusaStore.useBusinessData();

  const designId = pageData.designId;
  const design = designs.find(d => d.id === designId);

  const [sceneAssets, setSceneAssets] = React.useState(design ? (design.scene_assets || []) : []);
  const [sceneBg, setSceneBg]         = React.useState(design ? (design.scene_bg || null) : null);
  const [saving, setSaving] = React.useState(false);
  const [saved, setSaved] = React.useState(false);

  React.useEffect(() => {
    if (design) {
      setSceneAssets(design.scene_assets || []);
      setSceneBg(design.scene_bg || null);
    }
  }, [design && design.id]);

  const handleSave = async () => {
    if (!designId) return;
    setSaving(true);
    setSaved(false);
    await window.LelusaStore.updateDesign(designId, { scene_assets: sceneAssets, scene_bg: sceneBg });
    setSaving(false);
    setSaved(true);
    setTimeout(() => setSaved(false), 2500);
  };

  if (!design) {
    return (
      <div style={{
        minHeight: '100vh', background: '#151010',
        display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
        gap: 16, fontFamily: "'DM Sans', sans-serif",
      }}>
        <div style={{ fontSize: 52 }}>🎈</div>
        <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: 24, color: '#E8D8CC' }}>
          {t('admin_scene_not_found')}
        </div>
        <button
          onClick={() => navigate('admin-designs')}
          style={{
            background: 'transparent', border: '1px solid #3D2C24', color: '#A07868',
            borderRadius: 8, padding: '8px 18px', fontSize: 13, cursor: 'pointer',
            fontFamily: "'DM Sans', sans-serif",
          }}
        >
          {t('admin_scene_back_designs')}
        </button>
      </div>
    );
  }

  return (
    <div style={{
      height: '100vh', display: 'flex', flexDirection: 'column',
      background: '#151010', fontFamily: "'DM Sans', sans-serif",
      overflow: 'hidden',
    }}>
      {/* ── Top bar ─────────────────────────────────────────────── */}
      <div style={{
        height: 52, flexShrink: 0,
        background: '#1E1818', borderBottom: '1px solid #3D2C24',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '0 18px',
      }}>
        {/* Left */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <button
            onClick={() => navigate('admin-designs')}
            style={{
              background: 'transparent', border: '1px solid #3D2C24',
              color: '#A07868', borderRadius: 7, padding: '5px 12px',
              fontSize: 12, cursor: 'pointer', fontFamily: "'DM Sans', sans-serif",
              display: 'flex', alignItems: 'center', gap: 5,
              transition: 'all 0.1s',
            }}
            onMouseEnter={e => { e.currentTarget.style.borderColor = '#6B5048'; e.currentTarget.style.color = '#C4899A'; }}
            onMouseLeave={e => { e.currentTarget.style.borderColor = '#3D2C24'; e.currentTarget.style.color = '#A07868'; }}
          >
            {t('admin_scene_back')}
          </button>
          <div style={{ width: 1, height: 20, background: '#3D2C24' }} />
          <div>
            <div style={{
              fontFamily: "'Cormorant Garamond', serif", fontSize: 17,
              fontWeight: 600, color: '#E8D8CC', lineHeight: 1.1,
            }}>
              {design.name}
            </div>
            <div style={{ fontSize: 10, color: '#6B5048', marginTop: 1 }}>
              {t('admin_scene_animation_editor')}
            </div>
          </div>
        </div>

        {/* Right */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          {saved && (
            <div style={{
              display: 'flex', alignItems: 'center', gap: 5,
              background: '#1A3020', border: '1px solid #2A5030',
              borderRadius: 20, padding: '4px 12px',
              fontSize: 11, color: '#6BBF80', fontWeight: 700,
              animation: 'fadeIn 0.2s ease',
            }}>
              <span>✓</span> {t('admin_scene_saved')}
            </div>
          )}
          <button
            onClick={handleSave}
            disabled={saving}
            style={{
              background: saving ? '#3D2C24' : '#C4899A',
              color: saving ? '#6B5048' : '#fff',
              border: 'none', borderRadius: 8,
              padding: '7px 18px', fontSize: 12, cursor: saving ? 'default' : 'pointer',
              fontWeight: 700, fontFamily: "'DM Sans', sans-serif",
              boxShadow: saving ? 'none' : '0 2px 8px #C4899A44',
              transition: 'all 0.15s',
            }}
          >
            {saving ? t('admin_scene_saving') : t('admin_scene_save')}
          </button>
        </div>
      </div>

      {/* ── Editor (fills remaining height) ─────────────────────── */}
      <div style={{ flex: 1, overflow: 'hidden', display: 'flex' }}>
        {window.SceneEditor
          ? React.createElement(window.SceneEditor, {
              design,
              assets,
              sceneAssets,
              onChange: setSceneAssets,
              sceneBg,
              onChangeBg: setSceneBg,
            })
          : (
            <div style={{
              flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: '#4A3028', fontSize: 13,
            }}>
              {t('admin_scene_loading')}
            </div>
          )
        }
      </div>
    </div>
  );
}

// ─── Export ──────────────────────────────────────────────────────
Object.assign(window, { AdminLayout, DashboardPage, QuotesPage, DesignsPage, CalendarPage, EventDetailPage, AdminSceneEditorPage });
