
// OwnerDashboard.jsx — Redesigned with sidebar layout matching landing mockup

// ── CLP formatters ────────────────────────────────────────────────────────────
const formatCLP = (n) => '$' + Math.round(n).toLocaleString('es-CL');
const formatCLPShort = (n) => {
  if (n === 0) return '$0';
  if (n >= 1000000) return '$' + (n / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
  if (n >= 1000)    return '$' + Math.round(n / 1000) + 'K';
  return '$' + n;
};
const WEEK_LABELS = ['Lun','Mar','Mié','Jue','Vie','Sáb','Dom'];

const NAV_ITEMS = [
  { id: 'dashboard', icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>, label: 'Dashboard' },
  { id: 'boxes', icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>, label: 'Mis boxes' },
  { id: 'reservas', icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>, label: 'Reservas' },
  { id: 'checkinout', icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>, label: 'Check-in/Out' },
  { id: 'pagos', icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="1" y="4" width="22" height="16" rx="2"/><line x1="1" y1="10" x2="23" y2="10"/></svg>, label: 'Pagos' },
  { id: 'ajustes', icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>, label: 'Ajustes' },
];

// ── RESERVAS MOCKUP DATA ────────────────────────────────────────────────────
const RESERVAS = [
  { id: 1, prof: 'Dr. Carlos Muñoz', box: 'Box Dental 1', fecha: 'Hoy, 10:00–11:00', monto: 9350, status: 'confirmed' },
  { id: 2, prof: 'Dra. Ana Torres', box: 'Box Dental 1', fecha: 'Hoy, 14:00–15:00', monto: 9350, status: 'confirmed' },
  { id: 3, prof: 'Dr. Pedro Soto', box: 'Box Kinesiología', fecha: 'Mañana, 09:00–10:00', monto: 6600, status: 'pending' },
  { id: 4, prof: 'Dra. María López', box: 'Box Dental 1', fecha: '4 May, 11:00–12:00', monto: 9350, status: 'confirmed' },
  { id: 5, prof: 'Nut. Jorge Vera', box: 'Box Kinesiología', fecha: '5 May, 15:00–16:00', monto: 6600, status: 'cancelled' },
];

// ── MAIN DASHBOARD ──────────────────────────────────────────────────────────
const OwnerDashboard = ({ onBack, onNavigate, initialNav = 'dashboard' }) => {
  const [activeNav, setActiveNav] = React.useState(initialNav);
  const [boxes, setBoxes] = React.useState([]);
  const isMobile = useWindowWidth() <= 768;
  const [bookings, setBookings] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [stripeConnected, setStripeConnected] = React.useState(false);
  const [connectingStripe, setConnectingStripe] = React.useState(false);
  const [liveEarnings, setLiveEarnings] = React.useState(0);
  const [pulse, setPulse] = React.useState(false);
  const [showAddBox, setShowAddBox] = React.useState(false);
  const [editingBox, setEditingBox] = React.useState(null);
  const [previewBox, setPreviewBox] = React.useState(null);
  const [lightbox, setLightbox] = React.useState(null); // { images:[], index:0 }
  const [deleteBoxId, setDeleteBoxId] = React.useState(null);
  const [deletingBox, setDeletingBox] = React.useState(false);
  const [ratingOwnerReserva, setRatingOwnerReserva] = React.useState(null);
  const [showRatingOwner, setShowRatingOwner] = React.useState(false);

  // Chart controls
  const [chartRange, setChartRange] = React.useState('30D');
  const [hoveredBar, setHoveredBar] = React.useState(null); // index

  // Default arrival instructions panel (Mis Boxes tab)
  const [arrivalPanelOpen, setArrivalPanelOpen] = React.useState(false);
  const [arrivalText, setArrivalText] = React.useState(user?.defaultArrivalInstructions || '');
  const [arrivalSaving, setArrivalSaving] = React.useState(false);
  const [arrivalSaved, setArrivalSaved] = React.useState(false);
  const [arrivalError, setArrivalError] = React.useState('');

  // Re-fetch only boxes (reuses current bookings state for enrichment)
  const fetchBoxes = React.useCallback(async () => {
    try {
      const boxesResponse = await fetchWithAuth('https://lokat.fly.dev/api/boxes', {});
      if (!boxesResponse.ok) return;
      const boxesData = await boxesResponse.json();
      const enrichedBoxes = boxesData.map(box => {
        const boxBookings = bookings.filter(b => b.box_id === box.id);
        const revenue = boxBookings.reduce((sum, b) => sum + (b.total_amount || 0), 0);
        return { ...box, price: box.price_per_slot, bookingsThisMonth: boxBookings.length, revenue };
      });
      enrichedBoxes.forEach(b => {
        console.log(`📍 [BOX refresh] "${b.name}" | arrival_instructions=${JSON.stringify(b.arrival_instructions)}`);
      });
      setBoxes(enrichedBoxes);
    } catch (err) {
      if (err.sessionExpired) return;
      console.error('❌ Error refreshing boxes:', err.message);
    }
  }, [bookings]);

  const handleSaveArrival = async () => {
    setArrivalSaving(true);
    setArrivalError('');
    setArrivalSaved(false);
    try {
      const res = await fetchWithAuth('https://lokat.fly.dev/api/users/profile', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ defaultArrivalInstructions: arrivalText.trim() || null }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Error al guardar');
      // Persist to localStorage so ProfileSettings also sees it
      const stored = localStorage.getItem('lokat_user');
      if (stored) {
        const parsed = JSON.parse(stored);
        localStorage.setItem('lokat_user', JSON.stringify({
          ...parsed,
          defaultArrivalInstructions: data.user?.defaultArrivalInstructions ?? null,
        }));
      }
      setArrivalSaved(true);
      setTimeout(() => setArrivalSaved(false), 3000);
      // Refresh boxes so the updated default instructions appear immediately
      await fetchBoxes();
    } catch (err) {
      if (err.sessionExpired) return;
      setArrivalError(err.message);
    } finally {
      setArrivalSaving(false);
    }
  };

  // Get logged-in user from localStorage
  const userJson = localStorage.getItem('lokat_user');
  const user = userJson ? JSON.parse(userJson) : null;
  const userInitials = user?.fullName
    ? user.fullName.split(' ').map(n => n[0]).join('').toUpperCase().substring(0, 2)
    : 'OW';

  // Authentication guard: Check on mount
  React.useEffect(() => {
    const token = localStorage.getItem('lokat_token');
    const userJson = localStorage.getItem('lokat_user');
    const parsedUser = userJson ? JSON.parse(userJson) : null;

    // Redirect if no token or role is not owner/admin
    if (!token || !parsedUser || (parsedUser.role !== 'owner' && parsedUser.role !== 'admin')) {
      console.log('🔐 Access denied. Redirecting to login.');
      onNavigate('auth', { defaultRole: 'owner' });
    }
  }, [onNavigate]);

  // Fetch boxes and bookings on mount
  React.useEffect(() => {
    const fetchData = async () => {
      try {
        setLoading(true);
        const token = localStorage.getItem('lokat_token');
        if (!token) {
          throw new Error('No token found');
        }

        // Debug: check lokat_user in localStorage
        const rawLokatUser = localStorage.getItem('lokat_user');
        console.log('🔍 Raw lokat_user from localStorage:', rawLokatUser);
        console.log('📋 Parsed user object:', user);

        console.log('📦 Fetching owner boxes...');
        const boxesResponse = await fetchWithAuth('https://lokat.fly.dev/api/boxes', {});
        if (!boxesResponse.ok) throw new Error('Failed to fetch boxes');
        const boxesData = await boxesResponse.json();
        console.log('✅ Boxes fetched:', boxesData);

        console.log('📅 Fetching owner bookings...');
        const bookingsResponse = await fetchWithAuth('https://lokat.fly.dev/api/bookings/owner/all', {});
        if (!bookingsResponse.ok) throw new Error('Failed to fetch bookings');
        const bookingsData = await bookingsResponse.json();
        console.log('✅ Bookings fetched:', bookingsData);

        // Calculate stats per box — spread the full API box so no fields are dropped
        const enrichedBoxes = boxesData.map(box => {
          const boxBookings = bookingsData.filter(b => b.box_id === box.id);
          const revenue = boxBookings.reduce((sum, b) => sum + (b.total_amount || 0), 0);
          return {
            ...box,                                  // all API fields pass through untouched
            price: box.price_per_slot,               // alias used by the UI
            bookingsThisMonth: boxBookings.length,
            revenue,
          };
        });

        // Debug: verify arrival_instructions resolved correctly per box
        enrichedBoxes.forEach(b => {
          console.log(`📍 [BOX] "${b.name}" | arrival_instructions=${JSON.stringify(b.arrival_instructions)}`);
        });

        setBoxes(enrichedBoxes);
        setBookings(bookingsData);
        setLiveEarnings(bookingsData.reduce((sum, b) => sum + (b.total_amount || 0), 0));
        setError(null);
      } catch (err) {
        if (err.sessionExpired) return;
        console.error('❌ Error fetching data:', err);
        setError(err.message);
        setBoxes([]);
        setBookings([]);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  React.useEffect(() => {
    const iv = setInterval(() => {
      if (Math.random() > 0.6) {
        setLiveEarnings(p => p + 6000);
        setPulse(true);
        setTimeout(() => setPulse(false), 1200);
      }
    }, 5000);
    return () => clearInterval(iv);
  }, []);

  const toggleBox = (id) => setBoxes(p => p.map(b => b.id === id ? { ...b, status: b.status === 'open' ? 'blocked' : 'open' } : b));

  // ── Chart data: aggregate bookings by selected time range ─────────────────
  const chartData = React.useMemo(() => {
    const now = new Date();
    const validBookings = bookings.filter(b => b.status !== 'cancelled' && b.date);

    if (chartRange === '7D' || chartRange === '30D') {
      const days = chartRange === '7D' ? 7 : 30;
      const result = [];
      for (let i = days - 1; i >= 0; i--) {
        const d = new Date(now);
        d.setDate(d.getDate() - i);
        const dateStr = d.toISOString().split('T')[0];
        const value = validBookings
          .filter(b => b.date === dateStr)
          .reduce((s, b) => s + (b.total_amount || 0), 0);
        // Show label only every N bars to avoid crowding
        const step = days === 7 ? 1 : 5;
        const showLabel = i === days - 1 || i === 0 || (days - 1 - i) % step === 0;
        result.push({
          value,
          label: showLabel ? d.toLocaleDateString('es-CL', { day: 'numeric', month: 'short' }) : '',
          fullLabel: d.toLocaleDateString('es-CL', { day: 'numeric', month: 'long', year: 'numeric' }),
        });
      }
      return result;
    }

    if (chartRange === '3M' || chartRange === '6M') {
      const months = chartRange === '3M' ? 3 : 6;
      const cutoff = new Date(now);
      cutoff.setMonth(cutoff.getMonth() - months);
      const result = [];
      // Start from Monday of the cutoff week
      const cur = new Date(cutoff);
      cur.setDate(cur.getDate() - ((cur.getDay() + 6) % 7)); // Monday
      let weekIdx = 0;
      while (cur <= now) {
        const weekStart = cur.toISOString().split('T')[0];
        const weekEnd = new Date(cur);
        weekEnd.setDate(weekEnd.getDate() + 6);
        const weekEndStr = weekEnd.toISOString().split('T')[0];
        const value = validBookings
          .filter(b => b.date >= weekStart && b.date <= weekEndStr)
          .reduce((s, b) => s + (b.total_amount || 0), 0);
        const totalWeeks = months === 3 ? 13 : 26;
        const step = months === 3 ? 2 : 4;
        const showLabel = weekIdx === 0 || weekIdx % step === 0;
        result.push({
          value,
          label: showLabel ? cur.toLocaleDateString('es-CL', { day: 'numeric', month: 'short' }) : '',
          fullLabel: `Semana del ${cur.toLocaleDateString('es-CL', { day: 'numeric', month: 'short' })}`,
        });
        cur.setDate(cur.getDate() + 7);
        weekIdx++;
      }
      return result;
    }

    if (chartRange === '1A') {
      const result = [];
      for (let i = 11; i >= 0; i--) {
        const d = new Date(now.getFullYear(), now.getMonth() - i, 1);
        const y = d.getFullYear(), m = d.getMonth();
        const value = validBookings
          .filter(b => { const bd = new Date(b.date); return bd.getFullYear() === y && bd.getMonth() === m; })
          .reduce((s, b) => s + (b.total_amount || 0), 0);
        result.push({
          value,
          label: d.toLocaleDateString('es-CL', { month: 'short' }),
          fullLabel: d.toLocaleDateString('es-CL', { month: 'long', year: 'numeric' }),
        });
      }
      return result;
    }
    return [];
  }, [bookings, chartRange]);

  const chartMax     = Math.max(...chartData.map(d => d.value), 1);
  const chartTotal   = chartData.reduce((s, d) => s + d.value, 0);
  // Y-axis: 3 evenly-spaced ticks (0, mid, max), rounded to nice numbers
  const chartYMid    = chartMax / 2;
  const chartYTicks  = [chartMax, chartYMid, 0];

  const handleArchiveBox = async () => {
    if (!deleteBoxId) return;
    setDeletingBox(true);
    try {
      const res = await fetchWithAuth(`https://lokat.fly.dev/api/boxes/${deleteBoxId}`, { method: 'DELETE' });
      if (!res.ok) {
        const d = await res.json();
        throw new Error(d.error || 'Error al eliminar el box');
      }
      setBoxes(p => p.filter(b => b.id !== deleteBoxId));
      setDeleteBoxId(null);
    } catch (err) {
      if (err.sessionExpired) return;
      alert(`Error: ${err.message}`);
    } finally {
      setDeletingBox(false);
    }
  };

  if (showAddBox) return (
    <AddBoxScreen
      onBack={() => { setShowAddBox(false); setEditingBox(null); }}
      editingBox={editingBox}
      onSaved={box => {
        if (editingBox) {
          setBoxes(p => p.map(b => b.id === box.id
            ? { ...b, name: box.name, description: box.description || null, price: box.price_per_slot, specialty: box.specialty, address: box.address, resolution_type: box.resolution_type, arrival_instructions: box.arrival_instructions || null, has_own_arrival_instructions: !!box.arrival_instructions, images: Array.isArray(box.images) ? box.images : [] }
            : b));
        } else {
          setBoxes(p => [...p, { ...box, price: box.price_per_slot, description: box.description || null, bookingsThisMonth: 0, revenue: 0, arrival_instructions: box.arrival_instructions || null, has_own_arrival_instructions: !!box.arrival_instructions, images: Array.isArray(box.images) ? box.images : [] }]);
        }
        setShowAddBox(false);
        setEditingBox(null);
      }}
    />
  );
  if (showRatingOwner) return (
    <RatingFlow
      userType="owner"
      reserva={ratingOwnerReserva}
      onBack={() => setShowRatingOwner(false)}
      onDone={() => { setShowRatingOwner(false); setActiveNav('checkinout'); }}
    />
  );
  if (activeNav === 'checkinout') return (
    <CheckInOut
      activeNav={activeNav}
      setActiveNav={setActiveNav}
      onBack={() => setActiveNav('dashboard')}
      onRateOwner={(r) => { setRatingOwnerReserva(r); setShowRatingOwner(true); }}
    />
  );

  return (
    <div style={owS.root}>
      {/* ── MOBILE BOTTOM TAB BAR ── */}
      {isMobile && (
        <nav style={{position:'fixed', bottom:0, left:0, right:0, height:60, background:'#0984e3', borderTop:'2px solid rgba(255,255,255,0.15)', display:'flex', zIndex:300, fontFamily:"'Helvetica Neue',Helvetica,Arial,sans-serif"}}>
          {NAV_ITEMS.map(item => (
            <button
              key={item.id}
              style={{flex:1, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', background:'none', border:'none', cursor:'pointer', padding:'4px 2px', color: activeNav === item.id ? '#fff' : 'rgba(255,255,255,0.55)', fontFamily:'inherit', gap:2}}
              onClick={() => setActiveNav(item.id)}
            >
              <span style={{display:'flex', alignItems:'center', justifyContent:'center', width:20, height:20, opacity: activeNav === item.id ? 1 : 0.7}}>{item.icon}</span>
              <span style={{fontSize:8, fontWeight: activeNav === item.id ? 700 : 500, letterSpacing:0.2, lineHeight:1}}>{item.label}</span>
            </button>
          ))}
        </nav>
      )}

      {/* ── LIGHTBOX ── */}
      {lightbox && (
        <Lightbox
          images={lightbox.images}
          index={lightbox.index}
          onClose={() => setLightbox(null)}
          onNext={() => setLightbox(p => ({ ...p, index: (p.index + 1) % p.images.length }))}
          onPrev={() => setLightbox(p => ({ ...p, index: (p.index - 1 + p.images.length) % p.images.length }))}
        />
      )}

      {/* ── PREVIEW MODAL ── */}
      {previewBox && (
        <div style={owS.modalOverlay} onClick={() => setPreviewBox(null)}>
          <div style={owS.modalBox} onClick={e => e.stopPropagation()}>
            <div style={owS.modalHeader}>
              <div style={owS.modalTitle}>Vista previa del box</div>
              <button style={owS.modalClose} onClick={() => setPreviewBox(null)}>✕</button>
            </div>
            {previewBox.images && previewBox.images.length > 0 ? (
              <div style={{display:'flex', gap:8, overflowX:'auto', marginBottom:20, paddingBottom:4}}>
                {previewBox.images.map((url, i) => (
                  <img
                    key={i} src={url} alt={`foto ${i+1}`}
                    style={{height:140, minWidth:200, objectFit:'cover', borderRadius:10, flexShrink:0, cursor:'pointer', transition:'opacity 0.15s'}}
                    onClick={() => setLightbox({ images: previewBox.images, index: i })}
                    title="Ver en pantalla completa"
                  />
                ))}
              </div>
            ) : (
              <div style={{height:100, background:'#f0f4f8', borderRadius:10, display:'flex', alignItems:'center', justifyContent:'center', marginBottom:20, color:'#adb5bd', fontSize:13}}>Sin fotos</div>
            )}
            <div style={{display:'flex', flexDirection:'column', gap:12}}>
              <div><span style={owS.previewLabel}>Nombre</span><div style={owS.previewValue}>{previewBox.name}</div></div>
              <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:12}}>
                <div><span style={owS.previewLabel}>Especialidad</span><div style={owS.previewValue}>{previewBox.specialty || '—'}</div></div>
                <div><span style={owS.previewLabel}>Precio por hora</span><div style={{...owS.previewValue, color:'#0984e3', fontWeight:700}}>${(previewBox.price || 0).toLocaleString()}</div></div>
              </div>
              <div><span style={owS.previewLabel}>Dirección</span><div style={owS.previewValue}>{previewBox.address || '—'}</div></div>
              {previewBox.resolution_type && (
                <div><span style={owS.previewLabel}>Resolución sanitaria</span><div style={owS.previewValue}>{previewBox.resolution_type}</div></div>
              )}
              {previewBox.arrival_instructions && (
                <div>
                  <div style={{display:'flex', alignItems:'center', gap:8, marginBottom:4}}>
                    <span style={owS.previewLabel}>📍 Indicaciones de llegada</span>
                    {!previewBox.has_own_arrival_instructions && (
                      <span style={{fontSize:11, background:'#e9ecef', color:'#636e72', borderRadius:20, padding:'2px 7px', fontWeight:500}}>instrucción por defecto</span>
                    )}
                  </div>
                  <div style={{whiteSpace:'pre-wrap', background:'#fff8e1', border:'1.5px solid #f39c12', borderRadius:8, padding:'10px 12px', fontSize:13, color:'#555', lineHeight:1.6}}>{previewBox.arrival_instructions}</div>
                </div>
              )}
              <div><span style={owS.previewLabel}>Estado</span>
                <div style={{display:'inline-block', background: previewBox.status==='open'?'#d4edda':'#f8d7da', color: previewBox.status==='open'?'#155724':'#721c24', borderRadius:20, padding:'3px 10px', fontSize:12, fontWeight:600, marginTop:4}}>
                  {previewBox.status==='open'?'● Abierto':'● Bloqueado'}
                </div>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ── DELETE CONFIRM MODAL ── */}
      {deleteBoxId && (
        <div style={owS.modalOverlay} onClick={() => !deletingBox && setDeleteBoxId(null)}>
          <div style={{...owS.modalBox, maxWidth:400}} onClick={e => e.stopPropagation()}>
            <div style={owS.modalHeader}>
              <div style={owS.modalTitle}>¿Eliminar este box?</div>
              <button style={owS.modalClose} onClick={() => !deletingBox && setDeleteBoxId(null)}>✕</button>
            </div>
            <div style={{fontSize:14, color:'#636e72', lineHeight:1.6, marginBottom:24}}>
              Esta acción archivará el box y dejará de aparecer para los profesionales. Las reservas existentes no se verán afectadas.
            </div>
            <div style={{display:'flex', gap:10}}>
              <button style={{...owS.saveSettingsBtn, background:'#e74c3c', flex:1, textAlign:'center', marginTop:0, opacity: deletingBox ? 0.6 : 1}} disabled={deletingBox} onClick={handleArchiveBox}>
                {deletingBox ? 'Eliminando...' : 'Sí, eliminar'}
              </button>
              <button style={{...owS.saveSettingsBtn, background:'#f0f4f8', color:'#636e72', flex:1, textAlign:'center', marginTop:0}} disabled={deletingBox} onClick={() => setDeleteBoxId(null)}>
                Cancelar
              </button>
            </div>
          </div>
        </div>
      )}

      {/* ── SIDEBAR ── */}
      <aside style={{...owS.sidebar, display: isMobile ? 'none' : 'flex'}}>
        {/* Logo */}
        <div style={owS.sidebarLogo} onClick={onBack}>
          <img src="uploads/lokat_color.png" alt="Lokat" style={{height:28, objectFit:'contain', filter:'brightness(0) invert(1)'}} />
        </div>

        {/* Nav items */}
        <nav style={owS.sidebarNav}>
          {NAV_ITEMS.map(item => (
            <button
              key={item.id}
              style={{...owS.navItem, ...(activeNav === item.id ? owS.navItemActive : {})}}
              onClick={() => setActiveNav(item.id)}
            >
              <span style={{...owS.navIcon, ...(activeNav === item.id ? {color:'#fff'} : {})}}>{item.icon}</span>
              <span>{item.label}</span>
            </button>
          ))}
        </nav>

        {/* Inicio + Cerrar sesión — right below nav items */}
        <div style={{padding:'12px 12px 0', display:'flex', flexDirection:'column', gap:8}}>
          <button style={owS.backBtn} onClick={onBack}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="m15 18-6-6 6-6"/></svg>
            Volver al inicio
          </button>
          <button style={{background:'none', border:'none', borderRadius:8, padding:'8px 12px', color:'rgba(255,255,255,0.4)', fontSize:12, cursor:'pointer', fontFamily:'inherit', display:'flex', alignItems:'center', gap:6, transition:'color 0.15s'}} onMouseEnter={e => e.currentTarget.style.color='rgba(255,255,255,0.75)'} onMouseLeave={e => e.currentTarget.style.color='rgba(255,255,255,0.4)'} onClick={() => { localStorage.removeItem('lokat_token'); localStorage.removeItem('lokat_user'); onBack(); }}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg>
            Cerrar sesión
          </button>
        </div>

        {/* Stripe status — pushed to bottom */}
        <div style={owS.sidebarBottom}>
          {!stripeConnected ? (
            <button style={owS.stripeConnectBtn} onClick={() => { setConnectingStripe(true); setTimeout(() => { setConnectingStripe(false); setStripeConnected(true); }, 2000); }}>
              {connectingStripe
                ? <span style={{display:'flex',alignItems:'center',gap:8}}><span style={owS.spinnerWhite}></span>Conectando...</span>
                : <span>💳 Conectar Stripe</span>
              }
            </button>
          ) : (
            <div style={owS.stripeOk}>
              <span style={owS.stripeOkDot}>✓</span> Stripe activo
            </div>
          )}
        </div>
      </aside>

      {/* ── MAIN CONTENT ── */}
      <main style={{...owS.main, paddingBottom: isMobile ? 68 : 0}}>
        {/* Top header */}
        <div style={{...owS.topHeader, padding: isMobile ? '16px 16px 0' : '24px 32px 0', marginBottom: isMobile ? 16 : 24, flexDirection: isMobile && activeNav !== 'dashboard' ? 'column' : 'row', alignItems: isMobile && activeNav !== 'dashboard' ? 'flex-start' : 'center', gap: isMobile && activeNav !== 'dashboard' ? 12 : undefined}}>
          {isMobile && activeNav !== 'dashboard' && (
            <button style={{background:'rgba(0,0,0,0.08)', border:'none', borderRadius:6, padding:'6px 10px', color:'#2D3436', fontSize:13, fontWeight:600, cursor:'pointer', fontFamily:'inherit', display:'flex', alignItems:'center', gap:6}} onClick={() => setActiveNav('dashboard')}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="m15 18-6-6 6-6"/></svg>
              Atrás
            </button>
          )}
          <div style={{flex: isMobile && activeNav !== 'dashboard' ? 1 : undefined}}>
            <h1 style={{...owS.pageTitle, fontSize: isMobile ? 18 : 24}}>
              {activeNav === 'dashboard' && 'Dashboard'}
              {activeNav === 'boxes' && 'Mis boxes'}
              {activeNav === 'reservas' && 'Reservas'}
              {activeNav === 'checkinout' && 'Check-in / Check-out'}
              {activeNav === 'pagos' && 'Pagos'}
              {activeNav === 'ajustes' && 'Ajustes'}
            </h1>
            <div style={owS.pageSubtitle}>{user?.fullName || 'Owner'} · Mayo 2026</div>
          </div>
          <div style={owS.headerRight}>
            <div style={owS.livePill}>
              <span style={owS.liveDot}></span>
              En vivo
            </div>
            <button
              style={{background:'none', border:'none', padding:8, cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', color:'#636e72', fontSize:18}}
              onClick={() => setActiveNav('ajustes')}
              title="Configuración"
            >
              ⚙️
            </button>
            <div style={owS.avatarCircle}>{userInitials}</div>
          </div>
        </div>

        {/* Loading state */}
        {loading && (
          <div style={{textAlign:'center', padding:'60px 40px', color:'#636e72'}}>
            <div style={{fontSize:16, fontWeight:600}}>Cargando datos...</div>
            <div style={{fontSize:13, marginTop:8}}>Conectando con el servidor</div>
          </div>
        )}

        {/* Error state */}
        {error && !loading && (
          <div style={{textAlign:'center', padding:'60px 40px', color:'#c0392b'}}>
            <div style={{fontSize:16, fontWeight:600, marginBottom:8}}>Error al cargar datos</div>
            <div style={{fontSize:13, marginBottom:24}}>{error}</div>
            <button style={{...owS.stripeBannerBtn, background:'#c0392b'}} onClick={() => window.location.reload()}>
              Intentar nuevamente
            </button>
          </div>
        )}

        {/* ── DASHBOARD TAB ── */}
        {activeNav === 'dashboard' && !loading && !error && (
          <div style={{...owS.content, padding: isMobile ? '0 16px 24px' : '0 32px 32px'}}>
            {/* Stripe banner */}
            {!stripeConnected && (
              <div style={owS.stripeBanner}>
                <span>💳 <strong>Conecta Stripe</strong> para empezar a recibir pagos automáticos</span>
                <button style={owS.stripeBannerBtn} onClick={() => { setConnectingStripe(true); setTimeout(() => { setConnectingStripe(false); setStripeConnected(true); }, 2000); }}>
                  Conectar ahora →
                </button>
              </div>
            )}

            {/* KPI row */}
            <div style={{...owS.kpiRow, gridTemplateColumns: isMobile ? 'repeat(2,1fr)' : 'repeat(4,1fr)'}}>
              {[
                { label: 'Ingresos Mayo', value: `$${(liveEarnings || 0).toLocaleString()}`, color: '#0984e3', pulse },
                { label: 'Reservas activas', value: boxes.reduce((a,b)=>a+b.bookingsThisMonth,0), delta: '+3 hoy', color: '#00b894' },
                { label: 'Boxes activos', value: `${boxes.filter(b=>b.status==='open').length}/${boxes.length}`, delta: 'en línea ahora', color: '#6c5ce7' },
              ].map(k => (
                <div key={k.label} style={{...owS.kpiCard, ...(k.pulse ? owS.kpiCardPulse : {})}}>
                  <div style={owS.kpiLabel}>{k.label}</div>
                  <div style={{...owS.kpiValue, color: k.color}}>{k.value}</div>
                  {k.delta && <div style={owS.kpiDelta}>{k.delta}</div>}
                </div>
              ))}
            </div>

            {/* Chart + boxes row */}
            <div style={{...owS.twoCol, gridTemplateColumns: isMobile ? '1fr' : '2fr 1fr'}}>
              {/* Earnings chart */}
              <div style={owS.chartCard}>
                {/* Header row */}
                <div style={{display:'flex', alignItems:'flex-start', justifyContent:'space-between', marginBottom:12, flexWrap:'wrap', gap:8}}>
                  <div>
                    <div style={owS.cardTitle}>Ingresos</div>
                    <div style={{fontSize:11, color:'#adb5bd', marginTop:2}}>Total período: <strong style={{color:'#2d3436'}}>{formatCLP(chartTotal)}</strong></div>
                  </div>
                  {/* Range selector */}
                  <div style={{display:'flex', gap:4}}>
                    {['7D','30D','3M','6M','1A'].map(r => (
                      <button
                        key={r}
                        onClick={() => { setChartRange(r); setHoveredBar(null); }}
                        style={{padding:'4px 8px', fontSize:11, fontWeight:700, borderRadius:6, border:'1px solid', cursor:'pointer', fontFamily:'inherit', transition:'all 0.15s',
                          background: chartRange === r ? '#0984e3' : '#f8f9fa',
                          color:      chartRange === r ? '#fff'     : '#636e72',
                          borderColor:chartRange === r ? '#0984e3'  : '#e9ecef'}}
                      >{r}</button>
                    ))}
                  </div>
                </div>

                {/* Chart body: Y-axis + bars */}
                <div style={{display:'flex', gap:6, alignItems:'stretch'}}>
                  {/* Y-axis labels */}
                  <div style={{display:'flex', flexDirection:'column', justifyContent:'space-between', alignItems:'flex-end', paddingBottom:18, flexShrink:0}}>
                    {chartYTicks.map((t, i) => (
                      <div key={i} style={{fontSize:9, color:'#adb5bd', whiteSpace:'nowrap'}}>{formatCLPShort(t)}</div>
                    ))}
                  </div>

                  {/* Bars */}
                  <div style={{flex:1, position:'relative'}}>
                    {/* Horizontal grid lines */}
                    <div style={{position:'absolute', inset:0, paddingBottom:18, pointerEvents:'none'}}>
                      {[0,50,100].map(pct => (
                        <div key={pct} style={{position:'absolute', left:0, right:0, bottom:`calc(18px + ${pct}% * (100% - 18px) / 100)`, borderTop:'1px dashed #f0f0f0'}} />
                      ))}
                    </div>

                    <div style={{...owS.chartArea, position:'relative', height:120}}>
                      {chartData.map((item, i) => (
                        <div
                          key={i}
                          style={owS.barWrap}
                          onMouseEnter={() => setHoveredBar(i)}
                          onMouseLeave={() => setHoveredBar(null)}
                        >
                          {/* Tooltip */}
                          {hoveredBar === i && (
                            <div style={{position:'absolute', bottom:'calc(100% + 4px)', left:'50%', transform:'translateX(-50%)', background:'#2d3436', color:'#fff', borderRadius:6, padding:'4px 8px', fontSize:11, fontWeight:600, whiteSpace:'nowrap', zIndex:10, pointerEvents:'none', boxShadow:'0 2px 8px rgba(0,0,0,0.2)'}}>
                              <div style={{fontSize:10, fontWeight:400, opacity:0.8, marginBottom:1}}>{item.fullLabel}</div>
                              {formatCLP(item.value)}
                            </div>
                          )}
                          <div style={{...owS.barFill,
                            height: `${(item.value / chartMax) * 100}%`,
                            background: hoveredBar === i ? '#0966c2' : i === chartData.length - 1 ? '#0984e3' : '#c8e6fd',
                          }}></div>
                          <div style={owS.barLabel}>{item.label}</div>
                        </div>
                      ))}
                    </div>
                  </div>
                </div>
              </div>

              {/* Recent bookings */}
              <div style={owS.recentCard}>
                <div style={owS.cardHeader}>
                  <div style={owS.cardTitle}>Reservas recientes</div>
                  <button style={owS.seeAllBtn} onClick={() => setActiveNav('reservas')}>Ver todas</button>
                </div>
                {bookings.slice(0,3).map(b => {
                  const boxName = b.boxes?.name || 'Box';
                  const fecha = new Date(b.date).toLocaleDateString('es-CL', { day: 'numeric', month: 'short' });
                  const hora = b.slot ? `${b.slot}:00–${b.slot + 1}:00` : 'Sin horario';
                  const profesionalInitials = 'P';
                  return (
                    <div key={b.id} style={owS.reservaRow}>
                      <div style={owS.reservaAvatar}>{profesionalInitials}</div>
                      <div style={owS.reservaInfo}>
                        <div style={owS.reservaName}>Profesional</div>
                        <div style={owS.reservaMeta}>{boxName} · {fecha}, {hora}</div>
                      </div>
                      <div style={{...owS.reservaStatus, ...(b.status==='confirmed'?owS.statusConfirmed:b.status==='pending'?owS.statusPending:owS.statusCancelled)}}>
                        {b.status==='confirmed'?'Confirmada':b.status==='pending'?'Pendiente':b.status==='completed'?'Completada':'Cancelada'}
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>

            {/* Box inventory */}
            <div style={owS.boxesCard}>
              <div style={owS.cardHeader}>
                <div style={owS.cardTitle}>Mis boxes</div>
                <button style={owS.addBoxBtn} onClick={() => setShowAddBox(true)}>+ Agregar box</button>
              </div>
              <div style={{...owS.boxGrid, gridTemplateColumns: isMobile ? '1fr' : 'repeat(3,1fr)'}}>
                {boxes.map(box => (
                  <div key={box.id} style={owS.boxCard}>
                    <div style={owS.boxImgArea}>
                      {box.images && box.images[0]
                        ? <img src={box.images[0]} alt={box.name} style={{width:'100%', height:'100%', objectFit:'cover'}} />
                        : <div style={owS.boxImgPlaceholder}><svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#adb5bd" strokeWidth="1.5"><rect x="2" y="3" width="20" height="14" rx="2"/></svg><span style={owS.boxImgLabel}>foto</span></div>
                      }
                      <div style={{...owS.boxStatusBadge, background: box.status==='open'?'#d4edda':'#f8d7da', color: box.status==='open'?'#155724':'#721c24'}}>
                        {box.status==='open'?'● Abierto':'● Bloqueado'}
                      </div>
                    </div>
                    <div style={owS.boxCardBody}>
                      <div style={owS.boxCardName}>{box.name}</div>
                      <div style={owS.boxCardStats}>
                        <span style={owS.boxCardPrice}>${(box.price || 0).toLocaleString()}/hr</span>
                        <span style={owS.boxCardRev}>${(box.revenue || 0).toLocaleString()} este mes</span>
                      </div>
                      <div style={owS.boxCardFooter}>
                        <span style={owS.boxCardBookings}>{box.bookingsThisMonth} reservas</span>
                        <div style={owS.toggleRow} onClick={() => toggleBox(box.id)}>
                          <div style={{...owS.toggleTrack, background: box.status==='open'?'#0984e3':'#dee2e6'}}>
                            <div style={{...owS.toggleThumb, left: box.status==='open'?22:2}}></div>
                          </div>
                        </div>
                      </div>
                      <div style={owS.boxActions}>
                        <button style={owS.boxActionBtn} onClick={() => setPreviewBox(box)}>Ver</button>
                        <button style={{...owS.boxActionBtn, ...owS.boxActionEdit}} onClick={() => { setEditingBox(box); setShowAddBox(true); }}>Editar</button>
                        <button style={{...owS.boxActionBtn, ...owS.boxActionDelete}} onClick={() => setDeleteBoxId(box.id)}>Eliminar</button>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        )}

        {/* ── BOXES TAB ── */}
        {activeNav === 'boxes' && !loading && !error && (
          <div style={{...owS.content, padding: isMobile ? '0 16px 24px' : '0 32px 32px'}}>
            <div style={owS.tabToolbar}>
              <div style={owS.tabToolbarInfo}>{boxes.length} boxes en total · {boxes.filter(b=>b.status==='open').length} activos</div>
              <button style={owS.addBoxBtn} onClick={() => setShowAddBox(true)}>+ Agregar box</button>
            </div>

            {/* ── Collapsible default arrival instructions panel ── */}
            <div style={{marginBottom:20, border:'1px solid #e9ecef', borderRadius:12, background:'#fff', overflow:'hidden'}}>
              <button
                onClick={() => setArrivalPanelOpen(p => !p)}
                style={{width:'100%', display:'flex', alignItems:'center', justifyContent:'space-between', padding:'13px 18px', background:'none', border:'none', cursor:'pointer', fontFamily:'inherit', textAlign:'left'}}
              >
                <div style={{display:'flex', alignItems:'center', gap:10}}>
                  <span style={{fontSize:16}}>📍</span>
                  <span style={{fontSize:14, fontWeight:600, color:'#2d3436'}}>Indicaciones generales de llegada</span>
                  {user?.defaultArrivalInstructions && !arrivalPanelOpen && (
                    <span style={{fontSize:11, background:'#d4edda', color:'#155724', borderRadius:20, padding:'2px 8px', fontWeight:600}}>Guardado</span>
                  )}
                </div>
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#636e72" strokeWidth="2.5"
                  style={{transform: arrivalPanelOpen ? 'rotate(180deg)' : 'rotate(0deg)', transition:'transform 0.2s', flexShrink:0}}>
                  <path d="m6 9 6 6 6-6"/>
                </svg>
              </button>

              {arrivalPanelOpen && (
                <div style={{padding:'0 18px 18px', borderTop:'1px solid #f0f4f8'}}>
                  <p style={{fontSize:12, color:'#636e72', margin:'12px 0 10px', lineHeight:1.5}}>
                    Estas instrucciones se aplican a todos tus boxes que no tengan indicaciones propias. Por ejemplo: cómo llegar al edificio, a quién preguntar, dónde hay estacionamiento.
                  </p>
                  <textarea
                    style={{width:'100%', padding:'11px 13px', border:'1px solid #dee2e6', borderRadius:8, fontSize:14, fontFamily:'inherit', lineHeight:1.55, resize:'vertical', height:100, boxSizing:'border-box', outline:'none'}}
                    placeholder="Ej: Ingresar por el portón lateral de Av. Principal 123. Preguntar por recepción en piso 2. Hay estacionamiento sin costo en la calle interior."
                    value={arrivalText}
                    onChange={e => { setArrivalText(e.target.value); setArrivalSaved(false); }}
                    maxLength={1000}
                  />
                  <div style={{display:'flex', alignItems:'center', justifyContent:'space-between', marginTop:8}}>
                    <span style={{fontSize:11, color:'#adb5bd'}}>{arrivalText.length}/1000</span>
                    <div style={{display:'flex', alignItems:'center', gap:10}}>
                      {arrivalSaved && <span style={{fontSize:13, color:'#27ae60', fontWeight:600}}>✓ Guardado</span>}
                      {arrivalError && <span style={{fontSize:12, color:'#e74c3c'}}>{arrivalError}</span>}
                      <button
                        onClick={handleSaveArrival}
                        disabled={arrivalSaving}
                        style={{background:'#0984e3', color:'#fff', border:'none', borderRadius:8, padding:'8px 20px', fontSize:13, fontWeight:600, cursor: arrivalSaving ? 'not-allowed' : 'pointer', fontFamily:'inherit', opacity: arrivalSaving ? 0.7 : 1}}
                      >
                        {arrivalSaving ? 'Guardando...' : 'Guardar'}
                      </button>
                    </div>
                  </div>
                </div>
              )}
            </div>

            <div style={owS.boxGrid}>
              {boxes.map(box => (
                <div key={box.id} style={owS.boxCard}>
                  <div style={owS.boxImgArea}>
                    {box.images && box.images[0]
                      ? <img src={box.images[0]} alt={box.name} style={{width:'100%', height:'100%', objectFit:'cover'}} />
                      : <div style={owS.boxImgPlaceholder}><svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#adb5bd" strokeWidth="1.5"><rect x="2" y="3" width="20" height="14" rx="2"/></svg><span style={owS.boxImgLabel}>foto</span></div>
                    }
                    <div style={{...owS.boxStatusBadge, background: box.status==='open'?'#d4edda':'#f8d7da', color: box.status==='open'?'#155724':'#721c24'}}>
                      {box.status==='open'?'● Abierto':'● Bloqueado'}
                    </div>
                  </div>
                  <div style={owS.boxCardBody}>
                    <div style={owS.boxCardName}>{box.name}</div>
                    <div style={owS.boxCardStats}>
                      <span style={owS.boxCardPrice}>${(box.price || 0).toLocaleString()}/hr</span>
                      <span style={owS.boxCardRev}>${(box.revenue || 0).toLocaleString()} este mes</span>
                    </div>
                    <div style={owS.boxCardFooter}>
                      <span style={owS.boxCardBookings}>{box.bookingsThisMonth} reservas</span>
                      <div style={owS.toggleRow} onClick={() => toggleBox(box.id)}>
                        <div style={{...owS.toggleTrack, background: box.status==='open'?'#0984e3':'#dee2e6'}}>
                          <div style={{...owS.toggleThumb, left: box.status==='open'?22:2}}></div>
                        </div>
                      </div>
                    </div>
                    <div style={owS.boxActions}>
                      <button style={owS.boxActionBtn} onClick={() => setPreviewBox(box)}>Ver</button>
                      <button style={{...owS.boxActionBtn, ...owS.boxActionEdit}} onClick={() => { setEditingBox(box); setShowAddBox(true); }}>Editar</button>
                      <button style={{...owS.boxActionBtn, ...owS.boxActionDelete}} onClick={() => setDeleteBoxId(box.id)}>Eliminar</button>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        {/* ── RESERVAS TAB ── */}
        {activeNav === 'reservas' && !loading && !error && (
          <div style={{...owS.content, padding: isMobile ? '0 16px 24px' : '0 32px 32px'}}>
            <div style={{...owS.tableCard, overflowX: 'auto'}}>
              <div style={owS.cardHeader}>
                <div style={owS.cardTitle}>Todas las reservas</div>
                <div style={owS.cardSubtitle}>{RESERVAS.length} reservas</div>
              </div>
              <table style={owS.table}>
                <thead>
                  <tr>
                    {['Profesional','Box','Fecha y hora','Monto','Estado'].map(h => (
                      <th key={h} style={owS.th}>{h}</th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  {RESERVAS.map(r => (
                    <tr key={r.id} style={owS.tr}>
                      <td style={owS.td}>
                        <div style={{display:'flex', alignItems:'center', gap:10}}>
                          <div style={owS.reservaAvatar}>{r.prof.split(' ').map(w=>w[0]).slice(0,2).join('')}</div>
                          <span style={{fontWeight:600}}>{r.prof}</span>
                        </div>
                      </td>
                      <td style={owS.td}><span style={{color:'#636e72'}}>{r.box}</span></td>
                      <td style={owS.td}><span style={{color:'#636e72'}}>{r.fecha}</span></td>
                      <td style={owS.td}><strong style={{color:'#0984e3'}}>${(r.monto || 0).toLocaleString()}</strong></td>
                      <td style={owS.td}>
                        <span style={{...owS.reservaStatus, ...(r.status==='confirmed'?owS.statusConfirmed:r.status==='pending'?owS.statusPending:owS.statusCancelled)}}>
                          {r.status==='confirmed'?'Confirmada':r.status==='pending'?'Pendiente':'Cancelada'}
                        </span>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        )}

        {/* ── PAGOS TAB ── */}
        {activeNav === 'pagos' && (
          <div style={owS.content}>
            <div style={owS.kpiRow}>
              {[
                {label:'Balance disponible', value:'$187.450', color:'#0984e3'},
                {label:'En tránsito', value:'$37.550', color:'#f39c12'},
                {label:'Total Mayo', value:`$${(liveEarnings || 0).toLocaleString()}`, color:'#00b894'},
              ].map(k => (
                <div key={k.label} style={owS.kpiCard}>
                  <div style={owS.kpiLabel}>{k.label}</div>
                  <div style={{...owS.kpiValue, color:k.color}}>{k.value}</div>
                </div>
              ))}
            </div>
            <div style={owS.tableCard}>
              <div style={owS.cardHeader}><div style={owS.cardTitle}>Historial de pagos</div></div>
              <div style={{overflowX:'auto', WebkitOverflowScrolling:'touch', marginLeft:-24, marginRight:-24, paddingLeft:24, paddingRight:24}}>
                <table style={{...owS.table, minWidth:480}}>
                  <thead><tr>{['Fecha','Descripción','Monto','Estado'].map(h=><th key={h} style={owS.th}>{h}</th>)}</tr></thead>
                  <tbody>
                    {[
                      {fecha:'2 May 2026', desc:'Pago por reservas semana 18', monto:87000, status:'paid'},
                      {fecha:'25 Abr 2026', desc:'Pago por reservas semana 17', monto:72000, status:'paid'},
                      {fecha:'18 Abr 2026', desc:'Pago por reservas semana 16', monto:66000, status:'paid'},
                    ].map((p,i) => (
                      <tr key={i} style={owS.tr}>
                        <td style={owS.td}>{p.fecha}</td>
                        <td style={owS.td}>{p.desc}</td>
                        <td style={owS.td}><strong style={{color:'#0984e3'}}>${(p.monto || 0).toLocaleString()}</strong></td>
                        <td style={owS.td}><span style={{...owS.reservaStatus, ...owS.statusConfirmed}}>Pagado</span></td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        )}

        {/* ── AJUSTES TAB ── */}
        {activeNav === 'ajustes' && (
          <ProfileSettings
            onBack={() => setActiveNav('dashboard')}
            userRole="owner"
          />
        )}
      </main>
    </div>
  );
};

// ── CHECK-IN / CHECK-OUT SCREEN ───────────────────────────────────────────────
const CheckInOut = ({ activeNav, setActiveNav, onBack, onRateOwner }) => {
  console.log('✅ CheckInOut component mounted');
  const isMobile = useWindowWidth() <= 768;

  const [bookings, setBookings] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);

  // State machine per booking: esperando | checkin_ok | checkout_ok
  const [states, setStates] = React.useState({});
  const [observaciones, setObservaciones] = React.useState({});
  const [processingId, setProcessingId] = React.useState(null);

  React.useEffect(() => {
    console.log('🔄 CheckInOut useEffect: Fetching today\'s bookings');
    
    const fetchTodayBookings = async () => {
      try {
        setLoading(true);
        const token = localStorage.getItem('lokat_token');
        if (!token) {
          throw new Error('No se encontró token de autenticación');
        }

        const today = new Date().toISOString().split('T')[0];
        console.log(`📡 Fetching bookings for today: ${today}`);

        const response = await fetchWithAuth(`https://lokat.fly.dev/api/bookings/owner/all?date=${today}`, {});

        console.log('📥 API Response status:', response.status);

        if (!response.ok) {
          const err = await response.json();
          console.error('❌ API error response:', err);
          throw new Error(err.error || `Error: ${response.status}`);
        }

        const data = await response.json();
        console.log('✅ Bookings fetched successfully:', data);
        console.log(`📊 Total bookings today: ${data.length}`);

        // Map API response to component format
        const mappedBookings = data.map(booking => ({
          id: booking.id,
          booking_code: booking.booking_code,
          profesional: booking.boxes?.specialty || 'Profesional',
          box: booking.boxes?.name || 'Box',
          fecha: new Date(booking.date),
          slot: booking.slot,
          status: booking.status,
          checkin_at: booking.checkin_at,
          checkout_at: booking.checkout_at,
        }));

        setBookings(mappedBookings);
        
        // Initialize states
        const initialStates = {};
        mappedBookings.forEach(b => {
          if (b.checkin_at && b.checkout_at) {
            initialStates[b.id] = 'checkout_ok';
          } else if (b.checkin_at) {
            initialStates[b.id] = 'checkin_ok';
          } else {
            initialStates[b.id] = 'esperando';
          }
        });
        setStates(initialStates);
        
        // Initialize observaciones
        const initialObservaciones = {};
        mappedBookings.forEach(b => {
          initialObservaciones[b.id] = '';
        });
        setObservaciones(initialObservaciones);

        setError(null);
      } catch (err) {
        if (err.sessionExpired) return;
        console.error('❌ Error fetching bookings:', err);
        setError(err.message);
        setBookings([]);
      } finally {
        setLoading(false);
      }
    };

    fetchTodayBookings();
  }, []);

  const advance = async (id) => {
    const booking = bookings.find(b => b.id === id);
    const currentState = states[id];
    
    try {
      setProcessingId(id);
      const token = localStorage.getItem('lokat_token');

      if (currentState === 'esperando') {
        // Check-in
        console.log(`✅ Checking in booking ${id}`);
        const response = await fetchWithAuth(`https://lokat.fly.dev/api/bookings/${id}`, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            status: 'confirmed',
            checkin_at: new Date().toISOString(),
          }),
        });

        if (!response.ok) {
          const err = await response.json();
          throw new Error(err.error || `Error: ${response.status}`);
        }

        console.log('✅ Check-in successful');
        setStates(p => ({ ...p, [id]: 'checkin_ok' }));
      } else if (currentState === 'checkin_ok') {
        // Check-out
        console.log(`✅ Checking out booking ${id}`);
        const response = await fetchWithAuth(`https://lokat.fly.dev/api/bookings/${id}`, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            status: 'completed',
            checkout_at: new Date().toISOString(),
          }),
        });

        if (!response.ok) {
          const err = await response.json();
          throw new Error(err.error || `Error: ${response.status}`);
        }

        console.log('✅ Check-out successful');
        setStates(p => ({ ...p, [id]: 'checkout_ok' }));
      }
    } catch (err) {
      if (err.sessionExpired) return;
      console.error('❌ Error updating booking:', err);
      alert(`Error: ${err.message}`);
    } finally {
      setProcessingId(null);
    }
  };

  const displayList = bookings.length > 0 ? bookings : [];

  return (
    <div style={owS.root}>
      <aside style={{...owS.sidebar, display: isMobile ? 'none' : 'flex'}}>
        <div style={owS.sidebarLogo} onClick={onBack}>
          <img src="uploads/lokat_color.png" alt="Lokat" style={{height:28, objectFit:'contain', filter:'brightness(0) invert(1)'}} />
        </div>
        <div style={{padding:'0 12px', marginTop:16}}>
          <button style={owS.backBtn} onClick={onBack}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="m15 18-6-6 6-6"/></svg>
            Volver al panel
          </button>
        </div>
      </aside>
      <main style={{...owS.main, paddingBottom: isMobile ? 68 : 0}}>
        <div style={{...owS.topHeader, padding: isMobile ? '16px 16px 0' : undefined, flexDirection: isMobile ? 'column' : 'row', alignItems: isMobile ? 'flex-start' : 'center', gap: isMobile ? 12 : undefined}}>
          {isMobile && (
            <button style={{background:'rgba(0,0,0,0.08)', border:'none', borderRadius:6, padding:'6px 10px', color:'#2D3436', fontSize:13, fontWeight:600, cursor:'pointer', fontFamily:'inherit', display:'flex', alignItems:'center', gap:6}} onClick={onBack}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="m15 18-6-6 6-6"/></svg>
              Atrás
            </button>
          )}
          <div style={{flex:1}}>
            <h1 style={{...owS.pageTitle, fontSize: isMobile ? 18 : 24}}>Check-in / Check-out</h1>
            <div style={owS.pageSubtitle}>Reservas de hoy · {displayList.length} profesionales</div>
          </div>
          <div style={owS.headerRight}>
            <div style={owS.livePill}><span style={owS.liveDot}></span>En vivo</div>
          </div>
        </div>

        <div style={{...owS.content, maxWidth: 740}}>
          {displayList.length === 0 ? (
            <div style={{textAlign:'center', padding:'60px 24px', color:'#adb5bd'}}>
              <div style={{fontSize:48, marginBottom:16}}>📅</div>
              <div style={{fontSize:16, fontWeight:600, color:'#636e72'}}>No hay reservas para hoy</div>
            </div>
          ) : displayList.map(r => {
            const st = states[r.id];
            return (
              <div key={r.id} style={{background:'#fff', borderRadius:16, border:'1px solid #e9ecef', boxShadow:'0 4px 16px rgba(0,0,0,0.07)', marginBottom:16, overflow:'hidden'}}>
                {/* Header */}
                <div style={{padding:'16px 20px 14px', borderBottom:'1px solid #f0f4f8', display:'flex', justifyContent:'space-between', alignItems:'center', gap:12}}>
                  <div style={{display:'flex', alignItems:'center', gap:12}}>
                    <div style={{width:40, height:40, borderRadius:'50%', background:'#e3f0fc', color:'#0984e3', display:'flex', alignItems:'center', justifyContent:'center', fontWeight:700, fontSize:13, flexShrink:0}}>
                      {r.booking_code.split('-')[1]?.slice(0,2).toUpperCase() || 'PR'}
                    </div>
                    <div>
                      <div style={{fontSize:15, fontWeight:700}}>{r.profesional}</div>
                      <div style={{fontSize:12, color:'#636e72'}}>{r.box} · {r.slot.toString().padStart(2,'0')}:00 – {(r.slot+1).toString().padStart(2,'0')}:00</div>
                      <div style={{fontSize:11, color:'#adb5bd', marginTop:2}}>{r.booking_code}</div>
                    </div>
                  </div>
                  {/* State badge */}
                  {st === 'esperando' && <span style={{background:'#fff3cd', color:'#856404', borderRadius:20, padding:'4px 12px', fontSize:11, fontWeight:700}}>Esperando</span>}
                  {st === 'checkin_ok' && <span style={{background:'#d4edda', color:'#155724', borderRadius:20, padding:'4px 12px', fontSize:11, fontWeight:700}}>Check-in ✓</span>}
                  {st === 'checkout_ok' && <span style={{background:'#e3f0fc', color:'#0984e3', borderRadius:20, padding:'4px 12px', fontSize:11, fontWeight:700}}>Completado ✓</span>}
                </div>

                {/* Body */}
                <div style={{padding:'14px 20px', display:'flex', flexDirection:'column', gap:10}}>
                  {/* Stepper */}
                  <div style={{display:'flex', alignItems:'center', gap:0, marginBottom:4}}>
                    {[{label:'Esperando'},{label:'Check-in'},{label:'Check-out'}].map((s, i) => {
                      const stIdx = st === 'esperando' ? 0 : st === 'checkin_ok' ? 1 : 2;
                      const done = i <= stIdx;
                      return (
                        <React.Fragment key={i}>
                          <div style={{display:'flex', flexDirection:'column', alignItems:'center', gap:4}}>
                            <div style={{width:28, height:28, borderRadius:'50%', background: done ? '#0984e3' : '#e9ecef', color: done ? '#fff' : '#adb5bd', display:'flex', alignItems:'center', justifyContent:'center', fontSize:12, fontWeight:700, transition:'all 0.3s'}}>{i+1}</div>
                            <div style={{fontSize:10, color: done ? '#0984e3' : '#adb5bd', fontWeight: done ? 600 : 400}}>{s.label}</div>
                          </div>
                          {i < 2 && <div style={{flex:1, height:2, background: i < stIdx ? '#0984e3' : '#e9ecef', marginBottom:16, transition:'background 0.3s'}}></div>}
                        </React.Fragment>
                      );
                    })}
                  </div>

                  {/* Actions */}
                  {st === 'esperando' && (
                    <button
                      style={{background:'#00b894', color:'#fff', border:'none', borderRadius:10, padding:'11px 20px', fontSize:14, fontWeight:700, cursor:'pointer', fontFamily:'inherit', opacity: processingId === r.id ? 0.6 : 1}}
                      onClick={() => advance(r.id)}
                      disabled={processingId === r.id}
                    >{processingId === r.id ? '⏳ Procesando...' : '✓ Confirmar llegada'}</button>
                  )}
                  {st === 'checkin_ok' && (
                    <button
                      style={{background:'#0984e3', color:'#fff', border:'none', borderRadius:10, padding:'11px 20px', fontSize:14, fontWeight:700, cursor:'pointer', fontFamily:'inherit', opacity: processingId === r.id ? 0.6 : 1}}
                      onClick={() => advance(r.id)}
                      disabled={processingId === r.id}
                    >{processingId === r.id ? '⏳ Procesando...' : '✓ Confirmar entrega del box'}</button>
                  )}
                  {st === 'checkout_ok' && (
                    <div style={{display:'flex', flexDirection:'column', gap:10}}>
                      <div>
                        <label style={{fontSize:13, fontWeight:600, display:'block', marginBottom:6}}>Estado del box</label>
                        <textarea
                          style={{width:'100%', border:'1.5px solid #dee2e6', borderRadius:10, padding:'10px 14px', fontSize:13, fontFamily:'inherit', resize:'vertical', outline:'none', boxSizing:'border-box', minHeight:72}}
                          placeholder="Ej: Box en perfecto estado, sin observaciones..."
                          value={observaciones[r.id]}
                          onChange={e => setObservaciones(p => ({...p, [r.id]: e.target.value}))}
                        />
                      </div>
                      <button
                        style={{background:'#6c5ce7', color:'#fff', border:'none', borderRadius:10, padding:'11px 20px', fontSize:14, fontWeight:700, cursor:'pointer', fontFamily:'inherit'}}
                        onClick={() => onRateOwner && onRateOwner(r)}
                      >Calificar médico ★</button>
                    </div>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      </main>

      {/* ── MOBILE BOTTOM TAB BAR ── */}
      {isMobile && (
        <nav style={{position:'fixed', bottom:0, left:0, right:0, height:60, background:'#0984e3', borderTop:'2px solid rgba(255,255,255,0.15)', display:'flex', zIndex:300, fontFamily:"'Helvetica Neue',Helvetica,Arial,sans-serif"}}>
          {NAV_ITEMS.map(item => (
            <button
              key={item.id}
              style={{flex:1, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', background:'none', border:'none', cursor:'pointer', padding:'4px 2px', color: activeNav === item.id ? '#fff' : 'rgba(255,255,255,0.55)', fontFamily:'inherit', gap:2}}
              onClick={() => setActiveNav(item.id)}
            >
              <span style={{display:'flex', alignItems:'center', justifyContent:'center', width:20, height:20, opacity: activeNav === item.id ? 1 : 0.7}}>{item.icon}</span>
              <span style={{fontSize:8, fontWeight: activeNav === item.id ? 700 : 500, letterSpacing:0.2, lineHeight:1}}>{item.label}</span>
            </button>
          ))}
        </nav>
      )}
    </div>
  );
};

// ── LIGHTBOX ──────────────────────────────────────────────────────────────────
const Lightbox = ({ images, index, onClose, onNext, onPrev }) => {
  React.useEffect(() => {
    const handle = (e) => {
      if (e.key === 'Escape')      onClose();
      if (e.key === 'ArrowRight')  onNext();
      if (e.key === 'ArrowLeft')   onPrev();
    };
    window.addEventListener('keydown', handle);
    return () => window.removeEventListener('keydown', handle);
  }, [index, images.length]);

  const hasMany = images.length > 1;

  return (
    <div
      style={{position:'fixed', inset:0, background:'rgba(0,0,0,0.92)', zIndex:3000, display:'flex', alignItems:'center', justifyContent:'center'}}
      onClick={onClose}
    >
      {/* Close button */}
      <button
        style={{position:'absolute', top:20, right:24, background:'rgba(255,255,255,0.14)', border:'none', borderRadius:'50%', width:42, height:42, color:'#fff', fontSize:20, cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', lineHeight:1}}
        onClick={onClose}
        title="Cerrar (Esc)"
      >✕</button>

      {/* Counter */}
      {hasMany && (
        <div style={{position:'absolute', top:24, left:'50%', transform:'translateX(-50%)', color:'rgba(255,255,255,0.65)', fontSize:13, fontWeight:600, letterSpacing:0.5, pointerEvents:'none'}}>
          {index + 1} / {images.length}
        </div>
      )}

      {/* Prev arrow */}
      {hasMany && (
        <button
          style={{position:'absolute', left:16, top:'50%', transform:'translateY(-50%)', background:'rgba(255,255,255,0.14)', border:'none', borderRadius:'50%', width:48, height:48, color:'#fff', fontSize:28, cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', lineHeight:1}}
          onClick={e => { e.stopPropagation(); onPrev(); }}
          title="Anterior (←)"
        >‹</button>
      )}

      {/* Image */}
      <img
        src={images[index]}
        alt={`foto ${index + 1}`}
        style={{maxWidth:'90vw', maxHeight:'85vh', objectFit:'contain', borderRadius:10, boxShadow:'0 12px 50px rgba(0,0,0,0.6)', userSelect:'none'}}
        onClick={e => e.stopPropagation()}
      />

      {/* Next arrow */}
      {hasMany && (
        <button
          style={{position:'absolute', right:16, top:'50%', transform:'translateY(-50%)', background:'rgba(255,255,255,0.14)', border:'none', borderRadius:'50%', width:48, height:48, color:'#fff', fontSize:28, cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', lineHeight:1}}
          onClick={e => { e.stopPropagation(); onNext(); }}
          title="Siguiente (→)"
        >›</button>
      )}
    </div>
  );
};

// ── ADD BOX SCREEN ────────────────────────────────────────────────────────────
const RESOLUTION_OPTIONS = [
  'Solo consulta',
  'Procedimientos invasivos',
  'Dental/Radiología',
  'Sin resolución sanitaria',
];

const AddBoxScreen = ({ onBack, onSaved, editingBox }) => {
  const isEditing = !!editingBox;
  const isMobile = useWindowWidth() <= 768;
  const [form, setForm] = React.useState({
    name:                 isEditing ? (editingBox.name || '') : '',
    description:          isEditing ? (editingBox.description || '') : '',
    price:                isEditing ? (editingBox.price || '') : '',
    specialty:            isEditing ? (editingBox.specialty || '') : '',
    address:              isEditing ? (editingBox.address || '') : '',
    equip:                [],
    resolution_type:      isEditing ? (editingBox.resolution_type || '') : '',
    arrival_instructions: isEditing ? (editingBox.arrival_instructions || '') : '',
  });
  const [saving, setSaving] = React.useState(false);
  const [saveError, setSaveError] = React.useState('');
  const [images, setImages] = React.useState(isEditing && Array.isArray(editingBox.images) ? editingBox.images : []);
  const [uploading, setUploading] = React.useState(false);
  const [uploadError, setUploadError] = React.useState('');
  const [lightbox, setLightbox] = React.useState(null); // { images:[], index:0 }
  const [customSpecialty, setCustomSpecialty] = React.useState(isEditing && !['Dental', 'Kinesiología', 'Psicología', 'Medicina General', 'Dermatología', 'Nutrición'].includes(editingBox.specialty) ? editingBox.specialty : '');
  const fileInputRef = React.useRef(null);
  const equipOptions = ['Camilla', 'PC Clínico', 'Lavamanos', 'Unidad Dental', 'Compresor', 'Climatización', 'Estetoscopio', 'Sillones'];
  const specialties = ['Dental', 'Kinesiología', 'Psicología', 'Medicina General', 'Dermatología', 'Nutrición'];
  const toggleEquip = (e) => setForm(p => ({ ...p, equip: p.equip.includes(e) ? p.equip.filter(x=>x!==e) : [...p.equip, e] }));
  const canSave = form.name && form.price && form.specialty && form.address && !saving;

  const handleFileSelect = async (e) => {
    const files = Array.from(e.target.files);
    if (!files.length) return;
    const remaining = 5 - images.length;
    if (remaining <= 0) return;
    const toUpload = files.slice(0, remaining);
    setUploading(true);
    setUploadError('');
    const newUrls = [];
    for (const file of toUpload) {
      try {
        const formData = new FormData();
        formData.append('image', file);
        const res = await fetchWithAuth('https://lokat.fly.dev/api/boxes/upload-image', {
          method: 'POST',
          body: formData,
        });
        const data = await res.json();
        if (!res.ok) throw new Error(data.error || 'Error al subir imagen');
        newUrls.push(data.url);
      } catch (err) {
        if (err.sessionExpired) return;
        setUploadError(`Error subiendo ${file.name}: ${err.message}`);
      }
    }
    setImages(p => [...p, ...newUrls]);
    setUploading(false);
    e.target.value = '';
  };

  const handleSave = async () => {
    setSaving(true);
    setSaveError('');
    try {
      const url    = isEditing ? `https://lokat.fly.dev/api/boxes/${editingBox.id}` : 'https://lokat.fly.dev/api/boxes';
      const method = isEditing ? 'PATCH' : 'POST';

      // ── Debug: verify box ID and request payload ────────────────────────────
      console.log('📦 [SAVE_BOX] Method:', method);
      console.log('📦 [SAVE_BOX] URL:', url);
      console.log('📦 [SAVE_BOX] editingBox.id:', editingBox?.id, '| type:', typeof editingBox?.id);
      if (isEditing && !editingBox?.id) {
        console.error('❌ [SAVE_BOX] editingBox.id is undefined — URL will be malformed!');
      }
      const requestBody = {
        name:                 form.name,
        description:          form.description.trim() || null,
        price:                parseInt(form.price),
        specialty:            form.specialty,
        address:              form.address,
        resolution_type:      form.resolution_type || null,
        arrival_instructions: form.arrival_instructions.trim() || null,
        images:               images,
      };
      console.log('📦 [SAVE_BOX] Request body:', JSON.stringify(requestBody, null, 2));
      // ────────────────────────────────────────────────────────────────────────

      const res = await fetchWithAuth(url, {
        method,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(requestBody),
      });

      console.log('📦 [SAVE_BOX] Response status:', res.status, res.statusText);

      const data = await res.json();
      console.log('📦 [SAVE_BOX] Response body:', JSON.stringify(data, null, 2));

      if (!res.ok) throw new Error(data.error || (isEditing ? 'Error al actualizar el box' : 'Error al crear el box'));
      onSaved(data.box);
    } catch (err) {
      if (err.sessionExpired) return;
      setSaveError(err.message);
      setSaving(false);
    }
  };

  return (
    <div style={owS.root}>
      {lightbox && (
        <Lightbox
          images={lightbox.images}
          index={lightbox.index}
          onClose={() => setLightbox(null)}
          onNext={() => setLightbox(p => ({ ...p, index: (p.index + 1) % p.images.length }))}
          onPrev={() => setLightbox(p => ({ ...p, index: (p.index - 1 + p.images.length) % p.images.length }))}
        />
      )}
      <aside style={{...owS.sidebar, display: isMobile ? 'none' : 'flex'}}>
        <div style={owS.sidebarLogo}><img src="uploads/lokat_color.png" alt="Lokat" style={{height:28, objectFit:'contain', filter:'brightness(0) invert(1)'}} /></div>
        <div style={{padding:'0 12px', marginTop:16}}>
          <button style={owS.backBtn} onClick={onBack}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="m15 18-6-6 6-6"/></svg>
            Volver al panel
          </button>
        </div>
      </aside>
      <main style={owS.main}>
        <div style={{...owS.topHeader, padding: isMobile ? '16px 16px 0' : undefined}}>
          <h1 style={owS.pageTitle}>{isEditing ? 'Editar box' : 'Agregar nuevo box'}</h1>
        </div>
        <div style={{...owS.content, maxWidth:600}}>
          <div style={owS.tableCard}>
            {/* PHOTO UPLOAD ZONE */}
            <div style={owS.formGroup}>
              <label style={owS.label}>
                Fotos del box <span style={{color:'#adb5bd', fontWeight:400}}>(hasta 5 imágenes)</span>
              </label>
              <input
                ref={fileInputRef}
                type="file"
                accept="image/*"
                multiple
                style={{display:'none'}}
                onChange={handleFileSelect}
              />
              {images.length > 0 && (
                <div style={{display:'flex', flexWrap:'wrap', gap:8, marginBottom:10}}>
                  {images.map((url, idx) => (
                    <div key={url} style={{position:'relative', width:96, height:72}}>
                      <img
                        src={url} alt={`foto ${idx+1}`}
                        style={{width:96, height:72, objectFit:'cover', borderRadius:8, border:'1px solid #dee2e6', cursor:'pointer', display:'block'}}
                        onClick={() => setLightbox({ images, index: idx })}
                        title="Ver en pantalla completa"
                      />
                      <button
                        onClick={() => setImages(p => p.filter((_, i) => i !== idx))}
                        style={{position:'absolute', top:-6, right:-6, width:20, height:20, background:'#e74c3c', color:'#fff', border:'none', borderRadius:'50%', fontSize:12, lineHeight:'20px', textAlign:'center', cursor:'pointer', padding:0}}
                      >×</button>
                    </div>
                  ))}
                  {images.length < 5 && !uploading && (
                    <div
                      onClick={() => fileInputRef.current && fileInputRef.current.click()}
                      style={{width:96, height:72, border:'2px dashed #dee2e6', borderRadius:8, display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer', color:'#adb5bd', fontSize:24}}
                    >+</div>
                  )}
                </div>
              )}
              {images.length === 0 && (
                <div style={owS.photoZone} onClick={() => !uploading && fileInputRef.current && fileInputRef.current.click()}>
                  {uploading ? (
                    <>
                      <div style={{width:24, height:24, border:'3px solid #dee2e6', borderTop:'3px solid #0984e3', borderRadius:'50%', animation:'spin 0.8s linear infinite'}}></div>
                      <div style={{fontSize:13, color:'#636e72'}}>Subiendo imágenes...</div>
                    </>
                  ) : (
                    <>
                      <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#adb5bd" strokeWidth="1.5"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
                      <div style={{fontSize:14, color:'#636e72'}}>Haz clic para subir fotos</div>
                      <button style={owS.photoZoneBtn} onClick={e => { e.stopPropagation(); fileInputRef.current && fileInputRef.current.click(); }}>Seleccionar fotos</button>
                    </>
                  )}
                </div>
              )}
              {uploading && images.length > 0 && (
                <div style={{fontSize:12, color:'#636e72', marginBottom:6}}>⏳ Subiendo imagen...</div>
              )}
              {uploadError && <div style={{fontSize:12, color:'#e74c3c', marginTop:4}}>{uploadError}</div>}
            </div>
            <div style={owS.formGroup}><label style={owS.label}>Nombre del box</label><input style={owS.input} placeholder="Ej: Box Dental Premium" value={form.name} onChange={e=>setForm({...form,name:e.target.value})} /></div>
            <div style={owS.formGroup}>
              <label style={owS.label}>Descripción del box <span style={{color:'#adb5bd',fontWeight:400}}>(opcional)</span></label>
              <textarea
                style={{...owS.input, height:88, resize:'vertical', lineHeight:1.5}}
                placeholder="Ej: Box completamente equipado con camilla hidráulica, excelente iluminación y vista al parque. Ideal para consultas de kinesiología y rehabilitación."
                value={form.description}
                onChange={e => setForm({...form, description: e.target.value})}
                maxLength={500}
              />
              <div style={{fontSize:11, color: form.description.length > 450 ? '#e17055' : '#adb5bd', textAlign:'right', marginTop:2}}>{form.description.length}/500</div>
            </div>
            <div style={{display:'flex',gap:12}}>
              <div style={{...owS.formGroup,flex:1}}><label style={owS.label}>Precio por hora (CLP)</label><input style={owS.input} type="number" placeholder="8500" value={form.price} onChange={e=>setForm({...form,price:e.target.value})} /></div>
              <div style={{...owS.formGroup,flex:1}}>
                <label style={owS.label}>Especialidad</label>
                <select
                  style={owS.input}
                  value={specialties.includes(form.specialty) ? form.specialty : 'otro'}
                  onChange={e=>{
                    if(e.target.value==='otro'){
                      setCustomSpecialty('');
                      setForm({...form,specialty:''});
                    } else {
                      setCustomSpecialty('');
                      setForm({...form,specialty:e.target.value});
                    }
                  }}
                >
                  <option value="">Seleccionar</option>
                  {specialties.map(s=><option key={s} value={s}>{s}</option>)}
                  <option value="otro">Otro</option>
                </select>
              </div>
            </div>
            {(!specialties.includes(form.specialty) && form.specialty !== '') || (specialties.includes(form.specialty) === false && customSpecialty !== '') ? (
              <div style={owS.formGroup}>
                <label style={owS.label}>Especifica tu especialidad</label>
                <input
                  style={owS.input}
                  type="text"
                  placeholder="Ej: Oftalmología, Fonoaudiología, etc."
                  value={customSpecialty || form.specialty}
                  onChange={e=>{
                    setCustomSpecialty(e.target.value);
                    setForm({...form,specialty:e.target.value});
                  }}
                />
              </div>
            ) : null}
            <div style={owS.formGroup}><label style={owS.label}>Dirección</label><input style={owS.input} placeholder="Av. Apoquindo 4501, Las Condes" value={form.address} onChange={e=>setForm({...form,address:e.target.value})} /></div>
            <div style={owS.formGroup}>
              <label style={owS.label}>Tipo de resolución sanitaria <span style={{color:'#adb5bd',fontWeight:400}}>(opcional)</span></label>
              <select style={owS.input} value={form.resolution_type} onChange={e=>setForm({...form,resolution_type:e.target.value})}>
                <option value="">Sin especificar</option>
                {RESOLUTION_OPTIONS.map(o=><option key={o} value={o}>{o}</option>)}
              </select>
            </div>
            <div style={owS.formGroup}>
              <label style={owS.label}>Indicaciones de llegada <span style={{color:'#adb5bd',fontWeight:400}}>(opcional)</span></label>
              {/* Read-only preview of resolved instructions when editing */}
              {isEditing && editingBox.arrival_instructions && !editingBox.has_own_arrival_instructions && (
                <div style={{background:'#fff8e1', border:'1.5px solid #f39c12', borderRadius:8, padding:'10px 12px', marginBottom:10, fontSize:13, color:'#555', lineHeight:1.6}}>
                  <div style={{display:'flex', alignItems:'center', gap:6, marginBottom:4}}>
                    <span style={{fontSize:13}}>📍</span>
                    <span style={{fontWeight:600, color:'#856404', fontSize:12}}>Aplicando instrucción por defecto del perfil</span>
                  </div>
                  <div style={{whiteSpace:'pre-wrap', color:'#636e72'}}>{editingBox.arrival_instructions}</div>
                  <div style={{fontSize:11, color:'#856404', marginTop:6}}>Escribe abajo para agregar instrucciones específicas para este box.</div>
                </div>
              )}
              <textarea
                style={{...owS.input, height:100, resize:'vertical', lineHeight:1.5}}
                placeholder="Ej: Tocar el timbre del 3er piso, preguntar por Claudia en recepción. El box es el último a la derecha. Hay estacionamiento en Av. Las Condes 123."
                value={form.arrival_instructions}
                onChange={e=>setForm({...form,arrival_instructions:e.target.value})}
                maxLength={1000}
              />
              <div style={{fontSize:11,color:'#adb5bd',textAlign:'right',marginTop:2}}>{form.arrival_instructions.length}/1000</div>
            </div>
            <div style={owS.formGroup}>
              <label style={owS.label}>Equipamiento</label>
              <div style={{display:'flex',flexWrap:'wrap',gap:8}}>
                {equipOptions.map(e=>(
                  <button key={e} style={{...owS.equipOption,...(form.equip.includes(e)?owS.equipOptionActive:{})}} onClick={()=>toggleEquip(e)}>{e}</button>
                ))}
              </div>
            </div>
            {saveError && <div style={{color:'#e74c3c',fontSize:13,marginBottom:8}}>{saveError}</div>}
            <button style={{...owS.saveSettingsBtn,opacity:canSave?1:0.5}} disabled={!canSave} onClick={handleSave}>
              {saving ? (isEditing ? 'Guardando...' : 'Publicando...') : (isEditing ? 'Guardar cambios →' : 'Publicar box →')}
            </button>
          </div>
        </div>
      </main>
    </div>
  );
};

// ── STYLES ────────────────────────────────────────────────────────────────────
const owS = {
  root: { display:'flex', minHeight:'100vh', background:'#F8F9FA', fontFamily:"'Helvetica Neue',Helvetica,Arial,sans-serif", color:'#2D3436' },
  // Sidebar
  sidebar: { width:220, background:'#1a1d23', display:'flex', flexDirection:'column', position:'sticky', top:0, height:'100vh', flexShrink:0 },
  sidebarLogo: { display:'flex', alignItems:'center', gap:10, padding:'24px 20px 20px', cursor:'pointer' },
  sidebarLogoMark: { width:32, height:32, background:'rgba(255,255,255,0.12)', borderRadius:9, display:'flex', alignItems:'center', justifyContent:'center', color:'#fff', fontWeight:600, fontSize:16 },
  sidebarLogoText: { fontSize:18, fontWeight:600, color:'#fff', letterSpacing:'-0.5px' },
  sidebarNav: { display:'flex', flexDirection:'column', gap:2, padding:'0 12px' },
  navItem: { display:'flex', alignItems:'center', gap:10, padding:'10px 12px', borderRadius:8, color:'rgba(255,255,255,0.55)', fontSize:14, fontWeight:500, cursor:'pointer', background:'none', border:'none', fontFamily:'inherit', textAlign:'left', transition:'all 0.15s' },
  navItemActive: { background:'rgba(255,255,255,0.08)', color:'#fff', fontWeight:600 },
  navIcon: { color:'rgba(255,255,255,0.75)', display:'flex', alignItems:'center', flexShrink:0 },
  sidebarBottom: { padding:'16px 12px 24px', display:'flex', flexDirection:'column', gap:8 },
  stripeConnectBtn: { background:'rgba(255,255,255,0.08)', border:'1px solid rgba(255,255,255,0.15)', borderRadius:8, padding:'10px 14px', color:'rgba(255,255,255,0.8)', fontSize:13, fontWeight:600, cursor:'pointer', fontFamily:'inherit', textAlign:'left' },
  spinnerWhite: { width:14, height:14, border:'2px solid rgba(255,255,255,0.3)', borderTop:'2px solid #fff', borderRadius:'50%', animation:'spin 0.8s linear infinite', display:'inline-block' },
  stripeOk: { background:'rgba(255,255,255,0.08)', borderRadius:8, padding:'10px 14px', color:'rgba(255,255,255,0.8)', fontSize:13, fontWeight:600, display:'flex', alignItems:'center', gap:8 },
  stripeOkDot: { width:20, height:20, background:'#2ecc71', borderRadius:'50%', display:'inline-flex', alignItems:'center', justifyContent:'center', fontSize:11, fontWeight:600, color:'#fff' },
  backBtn: { background:'rgba(255,255,255,0.06)', border:'none', borderRadius:8, padding:'8px 12px', color:'rgba(255,255,255,0.6)', fontSize:12, cursor:'pointer', fontFamily:'inherit', display:'flex', alignItems:'center', gap:6 },
  // Main
  main: { flex:1, display:'flex', flexDirection:'column', minWidth:0, overflow:'auto' },
  topHeader: { display:'flex', justifyContent:'space-between', alignItems:'center', padding:'20px 32px', marginBottom:24, borderBottom:'1px solid #f0f0f0', background:'#fff' },
  pageTitle: { fontSize:22, fontWeight:600, letterSpacing:'-0.3px', margin:0, marginBottom:2 },
  pageSubtitle: { fontSize:13, color:'#adb5bd' },
  headerRight: { display:'flex', alignItems:'center', gap:8 },
  livePill: { display:'flex', alignItems:'center', gap:6, background:'#e8f8f1', borderRadius:20, padding:'6px 12px', fontSize:12, fontWeight:600, color:'#00b894' },
  liveDot: { width:7, height:7, borderRadius:'50%', background:'#2ecc71', animation:'pulse 1.5s infinite' },
  avatarCircle: { width:36, height:36, borderRadius:'50%', background:'#1a1d23', color:'#fff', display:'flex', alignItems:'center', justifyContent:'center', fontWeight:600, fontSize:13 },
  content: { padding:'0 32px 32px' },
  // Stripe banner
  stripeBanner: { background:'#fff8e1', border:'1.5px solid #ffc107', borderRadius:12, padding:'14px 18px', display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:24, fontSize:14 },
  stripeBannerBtn: { background:'#635bff', color:'#fff', border:'none', borderRadius:8, padding:'8px 16px', fontSize:13, fontWeight:600, cursor:'pointer', fontFamily:'inherit', whiteSpace:'nowrap' },
  // KPIs
  kpiRow: { display:'grid', gridTemplateColumns:'repeat(4,1fr)', gap:16, marginBottom:24 },
  kpiCard: { background:'#fff', borderRadius:12, padding:'18px 20px', border:'1px solid #ebebeb', boxShadow:'0 2px 12px rgba(0,0,0,0.06)', transition:'box-shadow 0.3s' },
  kpiCardPulse: { boxShadow:'0 0 0 3px rgba(9,132,227,0.12)' },
  kpiLabel: { fontSize:12, color:'#adb5bd', marginBottom:6, fontWeight:500 },
  kpiValue: { fontSize:26, fontWeight:600, letterSpacing:'-0.5px', marginBottom:4 },
  kpiDelta: { fontSize:12, color:'#636e72' },
  // Two col layout
  twoCol: { display:'grid', gridTemplateColumns:'2fr 1fr', gap:16, marginBottom:24 },
  chartCard: { background:'#fff', borderRadius:12, padding:20, border:'1px solid #ebebeb', boxShadow:'0 2px 12px rgba(0,0,0,0.06)' },
  chartArea: { display:'flex', alignItems:'flex-end', gap:2, height:120 },
  barWrap: { flex:1, display:'flex', flexDirection:'column', alignItems:'center', height:'100%', gap:2, position:'relative', cursor:'default' },
  barFill: { width:'100%', borderRadius:'3px 3px 0 0', minHeight:3, transition:'height 0.3s' },
  barLabel: { fontSize:9, color:'#adb5bd', whiteSpace:'nowrap' },
  recentCard: { background:'#fff', borderRadius:12, padding:20, border:'1px solid #ebebeb', boxShadow:'0 2px 12px rgba(0,0,0,0.06)', display:'flex', flexDirection:'column', gap:12 },
  cardHeader: { display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:12 },
  cardTitle: { fontSize:15, fontWeight:600 },
  cardSubtitle: { fontSize:12, color:'#adb5bd' },
  seeAllBtn: { background:'none', border:'none', color:'#0984e3', fontSize:12, fontWeight:600, cursor:'pointer', fontFamily:'inherit' },
  reservaRow: { display:'flex', alignItems:'center', gap:10, paddingBottom:10, borderBottom:'1px solid #f0f4f8' },
  reservaAvatar: { width:34, height:34, borderRadius:'50%', background:'#e3f0fc', color:'#0984e3', display:'flex', alignItems:'center', justifyContent:'center', fontSize:11, fontWeight:700, flexShrink:0 },
  reservaInfo: { flex:1, minWidth:0 },
  reservaName: { fontSize:13, fontWeight:600, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' },
  reservaMeta: { fontSize:11, color:'#adb5bd' },
  reservaStatus: { borderRadius:20, padding:'3px 10px', fontSize:11, fontWeight:600, flexShrink:0 },
  statusConfirmed: { background:'#d4edda', color:'#155724' },
  statusPending: { background:'#fff3cd', color:'#856404' },
  statusCancelled: { background:'#f8d7da', color:'#721c24' },
  // Boxes
  boxesCard: { background:'#fff', borderRadius:12, padding:20, border:'1px solid #ebebeb', boxShadow:'0 2px 12px rgba(0,0,0,0.06)' },
  boxGrid: { display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:16, marginTop:4 },
  boxCard: { background:'#F8F9FA', borderRadius:12, overflow:'hidden', border:'1px solid #e9ecef' },
  boxImgArea: { height:80, background:'#e9ecef', display:'flex', alignItems:'center', justifyContent:'center', position:'relative' },
  boxImgPlaceholder: { display:'flex', flexDirection:'column', alignItems:'center', gap:4, opacity:0.5 },
  boxImgLabel: { fontSize:9, color:'#adb5bd', fontFamily:'monospace', textTransform:'uppercase', letterSpacing:1 },
  boxStatusBadge: { position:'absolute', top:6, right:6, borderRadius:20, padding:'3px 8px', fontSize:10, fontWeight:600 },
  boxCardBody: { padding:'12px 14px' },
  boxCardName: { fontSize:14, fontWeight:700, marginBottom:6 },
  boxCardStats: { display:'flex', flexDirection:'column', gap:2, marginBottom:10 },
  boxCardPrice: { fontSize:14, fontWeight:700, color:'#0984e3' },
  boxCardRev: { fontSize:11, color:'#636e72' },
  boxCardFooter: { display:'flex', justifyContent:'space-between', alignItems:'center' },
  boxCardBookings: { fontSize:11, color:'#adb5bd' },
  toggleRow: { cursor:'pointer' },
  toggleTrack: { width:40, height:22, borderRadius:11, position:'relative', transition:'background 0.2s', flexShrink:0 },
  toggleThumb: { position:'absolute', top:3, width:16, height:16, borderRadius:'50%', background:'#fff', boxShadow:'0 1px 3px rgba(0,0,0,0.2)', transition:'left 0.2s' },
  // Toolbar
  tabToolbar: { display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:16 },
  tabToolbarInfo: { fontSize:13, color:'#636e72' },
  addBoxBtn: { background:'#0984e3', color:'#fff', border:'none', borderRadius:8, padding:'8px 16px', fontSize:13, fontWeight:600, cursor:'pointer', fontFamily:'inherit' },
  // Table
  tableCard: { background:'#fff', borderRadius:12, padding:24, border:'1px solid #ebebeb', boxShadow:'0 2px 12px rgba(0,0,0,0.06)' },
  table: { width:'100%', borderCollapse:'collapse' },
  th: { padding:'10px 14px', fontSize:11, fontWeight:700, color:'#adb5bd', textTransform:'uppercase', letterSpacing:0.5, textAlign:'left', borderBottom:'1px solid #e9ecef' },
  tr: { borderBottom:'1px solid #f0f4f8' },
  td: { padding:'12px 14px', fontSize:14, verticalAlign:'middle' },
  // Add box form
  photoZone: { border:'2px dashed #dee2e6', borderRadius:12, padding:24, textAlign:'center', marginBottom:20, display:'flex', flexDirection:'column', alignItems:'center', gap:8 },
  photoZoneBtn: { background:'#e3f0fc', color:'#0984e3', border:'none', borderRadius:8, padding:'8px 16px', fontSize:13, fontWeight:600, cursor:'pointer', fontFamily:'inherit' },
  formGroup: { marginBottom:16 },
  label: { display:'block', fontSize:13, fontWeight:600, marginBottom:6 },
  input: { width:'100%', border:'1.5px solid #dee2e6', borderRadius:10, padding:'11px 14px', fontSize:15, color:'#2D3436', fontFamily:'inherit', background:'#fff', boxSizing:'border-box', outline:'none' },
  equipOption: { background:'#f0f4f8', border:'1.5px solid #dee2e6', borderRadius:8, padding:'7px 13px', fontSize:13, cursor:'pointer', fontFamily:'inherit', color:'#636e72' },
  equipOptionActive: { background:'#e3f0fc', borderColor:'#0984e3', color:'#0984e3', fontWeight:600 },
  saveSettingsBtn: { background:'#0984e3', color:'#fff', border:'none', borderRadius:10, padding:'12px 24px', fontSize:14, fontWeight:600, cursor:'pointer', fontFamily:'inherit', marginTop:8 },
  // Box action buttons
  boxActions: { display:'flex', gap:6, marginTop:10, paddingTop:10, borderTop:'1px solid #e9ecef' },
  boxActionBtn: { flex:1, background:'#f0f4f8', border:'none', borderRadius:7, padding:'6px 0', fontSize:12, fontWeight:600, cursor:'pointer', fontFamily:'inherit', color:'#636e72' },
  boxActionEdit: { background:'#e3f0fc', color:'#0984e3' },
  boxActionDelete: { background:'#fdecea', color:'#e74c3c' },
  // Modals
  modalOverlay: { position:'fixed', inset:0, background:'rgba(0,0,0,0.45)', zIndex:1000, display:'flex', alignItems:'center', justifyContent:'center', padding:20 },
  modalBox: { background:'#fff', borderRadius:12, padding:28, width:'100%', maxWidth:520, boxShadow:'0 20px 60px rgba(0,0,0,0.18)', maxHeight:'90vh', overflowY:'auto' },
  modalHeader: { display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:20 },
  modalTitle: { fontSize:18, fontWeight:600, letterSpacing:'-0.3px' },
  modalClose: { background:'none', border:'none', fontSize:18, cursor:'pointer', color:'#adb5bd', lineHeight:1, padding:4 },
  previewLabel: { fontSize:11, color:'#adb5bd', fontWeight:600, textTransform:'uppercase', letterSpacing:0.5, display:'block', marginBottom:3 },
  previewValue: { fontSize:14, color:'#2D3436', fontWeight:500 },
};

window.OwnerDashboard = OwnerDashboard;
