// ============================
// LELUSA — UI Kit & Shared Components
// ui-kit.jsx
// ============================

const LELUSA_BRAND_ASSETS = {
  horizontalColor: '/uploads/brand/lelusa-logo-horizontal-color.png',
  horizontalWhite: '/uploads/brand/lelusa-logo-horizontal-white.png',
  compactColor: '/uploads/brand/lelusa-logo-compact-color.png',
  emblemFloral: '/uploads/brand/lelusa-emblem-floral.png',
  monogram: '/uploads/brand/lelusa-monogram-ld.png',
};

// ─── Pastel accents (fixed, theme-independent) ──────────────────
// Single source of truth: the --blue/--babyblue/--rose/--sage tokens in index.html.
// accentForCategory rotates the 4 families deterministically over CATEGORIES so
// each category always maps to the same pastel (even spread: 2 categories per pastel).
(function () {
  const css = (name, fallback) => {
    try {
      const v = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
      return v || fallback;
    } catch (e) { return fallback; }
  };
  const ACCENTS = [
    { name: 'blue',     base: css('--blue', '#7FA0BC'),     light: css('--blue-light', '#E6EEF4'),     dark: css('--blue-dark', '#3E6378') },
    { name: 'babyblue', base: css('--babyblue', '#A9C4D4'), light: css('--babyblue-light', '#EAF2F6'), dark: css('--babyblue-dark', '#4A6B7C') },
    { name: 'rose',     base: css('--rose', '#E0A6BC'),     light: css('--rose-light', '#F6E9EF'),     dark: css('--rose-dark', '#9E5E74') },
    { name: 'sage',     base: css('--sage', '#A8BAB8'),     light: css('--sage-light', '#E8F0EE'),     dark: css('--sage-dark', '#7E9896') },
  ];
  function accentForCategory(categoryId) {
    const list = (typeof CATEGORIES !== 'undefined' && Array.isArray(CATEGORIES)) ? CATEGORIES : [];
    const idx = list.findIndex(c => c.id === categoryId);
    const i = idx >= 0 ? idx : 0;
    return ACCENTS[i % ACCENTS.length];
  }
  window.LelusaAccent = { ACCENTS, accentForCategory };
})();

// ─── App Context ────────────────────────────────────────────────
window.AppContext = React.createContext({
  navigate: () => {},
  currentPage: 'home',
  pageData: {},
});

const LELUSA_CONTACT = {
  phoneLabel: '(55) 1234-5678',
  phoneHref: 'tel:+525512345678',
  email: 'hola@lelusa.mx',
  whatsapp: 'https://wa.me/525512345678',
  location: 'Ciudad de México',
};

// ─── Icons ──────────────────────────────────────────────────────
const ICONS = {
  menu:       [["M3 12h18"],["M3 6h18"],["M3 18h18"]],
  x:          [["M18 6L6 18"],["M6 6l12 12"]],
  chevRight:  "M9 18l6-6-6-6",
  chevLeft:   "M15 18l-6-6 6-6",
  chevDown:   "M6 9l6 6 6-6",
  search:     "M21 21l-4.35-4.35M16.65 16.65A7.5 7.5 0 1 0 6.5 6.5",
  star:       "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",
  check:      "M20 6L9 17l-5-5",
  plus:       [["M12 5v14"],["M5 12h14"]],
  minus:      "M5 12h14",
  calendar:   [["M8 2v4"],["M16 2v4"],["M3 10h18"],["M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z"]],
  user:       [["M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"],["M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z"]],
  settings:   [["M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"],["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"]],
  package:    [["M16.5 9.4l-9-5.19"],["M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"],["M3.27 6.96L12 12.01l8.73-5.05"],["M12 22.08V12"]],
  fileText:   [["M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"],["M14 2v6h6"],["M16 13H8"],["M16 17H8"],["M10 9H8"]],
  barChart:   [["M18 20V10"],["M12 20V4"],["M6 20v-6"]],
  trendingUp: [["M23 6l-9.5 9.5-5-5L1 18"],["M17 6h6v6"]],
  trendingDown: [["M23 18l-9.5-9.5-5 5L1 6"],["M17 18h6v-6"]],
  bell:       [["M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9"],["M13.73 21a2 2 0 0 1-3.46 0"]],
  phone:      "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z",
  mail:       [["M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"],["M22 6l-10 7L2 6"]],
  mapPin:     [["M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"],["M12 13a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"]],
  clock:      [["M12 22c5.52 0 10-4.48 10-10S17.52 2 12 2 2 6.48 2 12s4.48 10 10 10z"],["M12 6v6l4 2"]],
  heart:      "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z",
  arrowLeft:  [["M19 12H5"],["M12 19l-7-7 7-7"]],
  arrowRight: [["M5 12h14"],["M12 5l7 7-7 7"]],
  grid:       [["M3 3h7v7H3z"],["M14 3h7v7h-7z"],["M14 14h7v7h-7z"],["M3 14h7v7H3z"]],
  list:       [["M8 6h13"],["M8 12h13"],["M8 18h13"],["M3 6h.01"],["M3 12h.01"],["M3 18h.01"]],
  eye:        [["M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"],["M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z"]],
  edit:       [["M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"],["M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"]],
  trash:      [["M3 6h18"],["M8 6V4h8v2"],["M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"]],
  home:       [["M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"],["M9 22V12h6v10"]],
  sparkles:   [["M12 3v1"],["M12 20v1"],["M4.22 4.22l.7.7"],["M19.07 19.07l.71.71"],["M3 12h1"],["M20 12h1"],["M4.22 19.78l.7-.7"],["M19.07 4.93l.71-.71"],["M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z"]],
  whatsapp:   "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347z",
  clients:    [["M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"],["M23 21v-2a4 4 0 0 0-3-3.87"],["M16 3.13a4 4 0 0 1 0 7.75"],["M9 7a4 4 0 1 0 0-8 4 4 0 0 0 0 8z"]],
  world:      [["M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z"],["M2 12h20"],["M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"]],
};

function Icon({ name, size = 20, color = 'currentColor', strokeWidth = 1.5, className = '', style = {} }) {
  const raw = ICONS[name];
  if (!raw) return null;
  const paths = Array.isArray(raw[0]) ? raw : (typeof raw === 'string' ? [[raw]] : raw);
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke={color} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round"
      className={className} style={style}>
      {paths.map((p, i) => {
        const d = Array.isArray(p) ? p[0] : p;
        return <path key={i} d={d} />;
      })}
    </svg>
  );
}

// ─── Button ─────────────────────────────────────────────────────
function Btn({ children, variant = 'primary', size = 'md', onClick, className = '', disabled = false, type = 'button', style = {} }) {
  const base = {
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '8px',
    fontFamily: "'DM Sans', sans-serif", fontWeight: 600, borderRadius: '999px',
    cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? 0.6 : 1,
    transition: 'all 0.2s ease', border: 'none', whiteSpace: 'nowrap',
    letterSpacing: '0.01em',
  };
  const variants = {
    primary:   { background: 'var(--primary)', color: '#fff',         padding: size === 'sm' ? '8px 18px' : size === 'lg' ? '15px 32px' : '12px 24px', fontSize: size === 'sm' ? '13px' : size === 'lg' ? '15px' : '14px' },
    secondary: { background: 'var(--sage)',    color: 'var(--text)',   padding: size === 'sm' ? '8px 18px' : size === 'lg' ? '15px 32px' : '12px 24px', fontSize: size === 'sm' ? '13px' : size === 'lg' ? '15px' : '14px' },
    ghost:     { background: 'transparent',   color: 'var(--primary)', padding: size === 'sm' ? '7px 17px' : size === 'lg' ? '14px 31px' : '11px 23px', fontSize: size === 'sm' ? '13px' : size === 'lg' ? '15px' : '14px', border: '1.5px solid var(--border)' },
    dark:      { background: 'var(--text)',    color: '#FAF0E8',       padding: size === 'sm' ? '8px 18px' : size === 'lg' ? '15px 32px' : '12px 24px', fontSize: size === 'sm' ? '13px' : size === 'lg' ? '15px' : '14px' },
    danger:    { background: '#E07070',        color: '#fff',          padding: '8px 18px', fontSize: '13px' },
  };
  const [hovered, setHovered] = React.useState(false);
  const hoverStyle = hovered && !disabled ? {
    transform: 'translateY(-1px)',
    boxShadow: '0 6px 20px rgba(196,137,154,0.3)',
    filter: 'brightness(1.05)',
  } : {};
  return (
    <button type={type} onClick={onClick} disabled={disabled}
      style={{ ...base, ...variants[variant], ...hoverStyle, ...style }}
      onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}
      className={className}>
      {children}
    </button>
  );
}

// ─── Badge ───────────────────────────────────────────────────────
function Badge({ children, color = 'primary', accent = null }) {
  const colors = {
    primary:   { bg: 'var(--accent-light)', color: 'var(--primary-dark)' },
    sage:      { bg: '#E0EAE9',             color: '#6A8B8A'             },
    warm:      { bg: '#F0E8DC',             color: '#8B6A4A'             },
    dark:      { bg: 'var(--text)',         color: '#FAF0E8'             },
  };
  const c = accent ? { bg: accent.light, color: accent.dark } : (colors[color] || colors.primary);
  return (
    <span style={{
      display: 'inline-block', padding: '3px 12px', borderRadius: '999px',
      fontSize: '11px', fontWeight: 600, letterSpacing: '0.05em', textTransform: 'uppercase',
      fontFamily: "'DM Sans', sans-serif", background: c.bg, color: c.color,
    }}>{children}</span>
  );
}

function StatusBadge({ status }) {
  // Color map keyed by raw status value; the visible label is localized via LelusaStatusLabel.
  const colors = {
    pendiente:  { bg: '#FFF3DC', color: '#C8881A' },
    revision:   { bg: '#DCE8FF', color: '#3A62C8' },
    aprobada:   { bg: '#DCF5E6', color: '#2A8A50' },
    rechazada:  { bg: '#FFE0E0', color: '#C83A3A' },
    completada: { bg: '#E8E0F5', color: '#6A4AC8' },
    confirmado: { bg: '#DCF5E6', color: '#2A8A50' },
    reservado:  { bg: '#DCE8FF', color: '#3A62C8' },
    agendado:   { bg: '#FFF3DC', color: '#C8881A' },
    completado: { bg: '#E8E0F5', color: '#6A4AC8' },
  };
  const c = colors[status] || { bg: '#EEE', color: '#666' };
  const label = window.LelusaStatusLabel ? window.LelusaStatusLabel(status) : status;
  return (
    <span style={{
      display: 'inline-block', padding: '4px 12px', borderRadius: '999px',
      fontSize: '12px', fontWeight: 600, background: c.bg, color: c.color,
      fontFamily: "'DM Sans', sans-serif",
    }}>{label}</span>
  );
}

// ─── Admin Modal + Form Helpers ─────────────────────────────────
function AdminModal({ open, title, subtitle, children, footer, onClose, width = '860px' }) {
  React.useEffect(() => {
    if (!open) return undefined;
    const onKey = (event) => {
      if (event.key === 'Escape') onClose?.();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  if (!open) return null;

  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 260, background: 'rgba(58,42,32,0.42)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '22px', backdropFilter: 'blur(5px)' }} onClick={onClose}>
      <div style={{ width: '100%', maxWidth: width, maxHeight: '88vh', background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '20px', boxShadow: '0 28px 80px rgba(58,42,32,0.24)', display: 'flex', flexDirection: 'column', overflow: 'hidden' }} onClick={event => event.stopPropagation()}>
        <div style={{ padding: '20px 24px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', gap: '18px', alignItems: 'flex-start' }}>
          <div>
            <h2 style={{ margin: 0, fontFamily: "'Cormorant Garamond', serif", fontSize: '26px', fontWeight: 700, color: 'var(--text)', lineHeight: 1.15 }}>{title}</h2>
            {subtitle && <p style={{ margin: '6px 0 0', fontSize: '13px', color: 'var(--muted)', lineHeight: 1.5 }}>{subtitle}</p>}
          </div>
          <button onClick={onClose} aria-label="Cerrar" style={{ width: '34px', height: '34px', borderRadius: '10px', border: '1px solid var(--border)', background: 'var(--bg-soft)', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <Icon name="x" size={16} color="var(--muted)" />
          </button>
        </div>
        <div style={{ padding: '22px 24px', overflowY: 'auto' }}>
          {children}
        </div>
        {footer && (
          <div style={{ padding: '16px 24px', borderTop: '1px solid var(--border)', background: 'var(--bg-soft)', display: 'flex', justifyContent: 'flex-end', gap: '10px', flexWrap: 'wrap' }}>
            {footer}
          </div>
        )}
      </div>
    </div>
  );
}

function AdminFormSection({ title, subtitle, children, columns = 2 }) {
  return (
    <section style={{ marginBottom: '18px' }}>
      <div style={{ marginBottom: '12px' }}>
        <h3 style={{ margin: 0, fontSize: '13px', fontWeight: 800, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{title}</h3>
        {subtitle && <p style={{ margin: '4px 0 0', fontSize: '12px', color: 'var(--muted)', lineHeight: 1.45 }}>{subtitle}</p>}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`, gap: '12px' }} className="form-row">
        {children}
      </div>
    </section>
  );
}

function AdminField({ label, hint, error, children, full = false }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: '6px', gridColumn: full ? '1 / -1' : 'auto' }}>
      <span style={{ fontSize: '12px', fontWeight: 700, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{label}</span>
      {children}
      {hint && !error && <span style={{ fontSize: '11px', color: 'var(--muted)', lineHeight: 1.4 }}>{hint}</span>}
      {error && <span style={{ fontSize: '11px', color: '#C83A3A', lineHeight: 1.4 }}>{error}</span>}
    </label>
  );
}

const ADMIN_INPUT_STYLE = {
  width: '100%',
  padding: '10px 12px',
  border: '1px solid var(--border)',
  borderRadius: '10px',
  background: 'var(--bg-soft)',
  color: 'var(--text)',
  fontFamily: "'DM Sans', sans-serif",
  fontSize: '13px',
  boxSizing: 'border-box',
  outline: 'none',
};

function AdminFileField({ label, value, onChange, accept = 'image/*', hint = 'Arrastra una imagen, selecciona un archivo local o pega una URL/ruta existente.', full = false }) {
  const fileInputRef = React.useRef(null);
  const [fileName, setFileName] = React.useState('');
  const [dragging, setDragging] = React.useState(false);
  const [uploading, setUploading] = React.useState(false);
  const [uploadError, setUploadError] = React.useState('');
  const isImage = value && (String(value).startsWith('data:image') || /\.(png|jpe?g|webp|gif|svg)$/i.test(String(value)));

  const readFile = async (file) => {
    if (!file) return;
    if (accept.includes('image') && !file.type.startsWith('image/')) return;
    setFileName(file.name);
    setUploadError('');
    setUploading(true);
    try {
      if (window.LelusaStore?.isRemoteConfigured?.() && window.LelusaStore?.uploadMediaFiles) {
        const urls = await window.LelusaStore.uploadMediaFiles([file], 'crud');
        if (urls[0]) {
          onChange(urls[0]);
          return;
        }
      }
      const reader = new FileReader();
      reader.onload = () => onChange(reader.result || '');
      reader.readAsDataURL(file);
    } catch (error) {
      setUploadError(error.message || 'No se pudo subir. Se usara vista local.');
      const reader = new FileReader();
      reader.onload = () => onChange(reader.result || '');
      reader.readAsDataURL(file);
    } finally {
      setUploading(false);
    }
  };

  const handleFile = (event) => {
    readFile(event.target.files?.[0]);
  };

  const handleDrop = (event) => {
    event.preventDefault();
    setDragging(false);
    readFile(event.dataTransfer.files?.[0]);
  };

  return (
    <AdminField label={label} hint={hint} full={full}>
      <div
        onDragOver={(event) => { event.preventDefault(); setDragging(true); }}
        onDragLeave={() => setDragging(false)}
        onDrop={handleDrop}
        onClick={() => fileInputRef.current?.click()}
        style={{
          border: `1.5px dashed ${dragging ? 'var(--primary)' : 'var(--border)'}`,
          borderRadius: '14px',
          background: dragging ? 'var(--accent-light)' : 'var(--bg-soft)',
          padding: '12px',
          cursor: 'pointer',
          transition: 'border-color 0.15s, background 0.15s',
        }}
      >
        <div style={{ display: 'grid', gridTemplateColumns: isImage ? '96px 1fr auto' : '1fr auto', gap: '12px', alignItems: 'center' }} className="form-row">
          {isImage && (
            <img src={value} alt="" style={{ width: '96px', height: '72px', objectFit: 'cover', borderRadius: '10px', border: '1px solid var(--border)', background: 'var(--card)' }} />
          )}
          <div style={{ minWidth: 0 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' }}>
              <span style={{ width: 30, height: 30, borderRadius: 10, background: 'var(--card)', display: 'grid', placeItems: 'center', border: '1px solid var(--border)' }}>
                <Icon name="plus" size={14} color="var(--primary)" />
              </span>
              <div>
                <div style={{ fontSize: '12px', fontWeight: 800, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>Soltar imagen o buscar archivo</div>
                <div style={{ fontSize: '11px', color: uploadError ? '#C83A3A' : 'var(--muted)', marginTop: '2px' }}>{uploading ? 'Subiendo a Supabase...' : uploadError || fileName || (isImage ? 'Vista previa cargada' : 'PNG, JPG, WEBP, GIF o SVG')}</div>
              </div>
            </div>
            <input
              value={value || ''}
              onClick={event => event.stopPropagation()}
              onChange={event => onChange(event.target.value)}
              placeholder="/uploads/imagen.png o https://..."
              style={{ ...ADMIN_INPUT_STYLE, background: 'var(--card)' }}
            />
          </div>
          <input ref={fileInputRef} type="file" accept={accept} onChange={handleFile} style={{ display: 'none' }} />
          <Btn type="button" variant="ghost" size="sm" disabled={uploading} onClick={(event) => { event.stopPropagation(); fileInputRef.current?.click(); }}>
            {uploading ? 'Subiendo' : 'Archivo'}
          </Btn>
        </div>
      </div>
    </AdminField>
  );
}

function AdminImageGalleryField({ label, images = [], primary = '', onChange, hint = 'Agrega varias imagenes y marca una como principal.', full = false }) {
  const fileInputRef = React.useRef(null);
  const [dragging, setDragging] = React.useState(false);
  const [newUrl, setNewUrl] = React.useState('');
  const [uploading, setUploading] = React.useState(false);
  const [uploadError, setUploadError] = React.useState('');
  const imageList = Array.from(new Set([primary, ...(images || [])].filter(Boolean)));
  const primaryImage = primary || imageList[0] || '';

  const emit = (nextImages, nextPrimary = primaryImage) => {
    const clean = Array.from(new Set(nextImages.filter(Boolean)));
    const main = clean.includes(nextPrimary) ? nextPrimary : (clean[0] || '');
    onChange?.({ image: main, images: main ? [main, ...clean.filter(item => item !== main)] : clean });
  };

  const readAsDataUrls = (files) => Promise.all(files.map(file => new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result || '');
    reader.readAsDataURL(file);
  })));

  const readFiles = async (fileList) => {
    const files = Array.from(fileList || []).filter(file => file.type.startsWith('image/'));
    if (!files.length) return;
    setUploading(true);
    setUploadError('');
    try {
      let results = [];
      if (window.LelusaStore?.isRemoteConfigured?.() && window.LelusaStore?.uploadMediaFiles) {
        results = await window.LelusaStore.uploadMediaFiles(files, 'crud-gallery');
      }
      if (!results.length) {
        results = await readAsDataUrls(files);
      }
      emit([...imageList, ...results.filter(Boolean)], primaryImage || results[0]);
    } catch (error) {
      setUploadError(error.message || 'No se pudo subir a Supabase. Se usara vista local.');
      const results = await readAsDataUrls(files);
      emit([...imageList, ...results.filter(Boolean)], primaryImage || results[0]);
    } finally {
      setUploading(false);
    }
  };

  const addManualImage = () => {
    const trimmed = newUrl.trim();
    if (!trimmed) return;
    emit([...imageList, trimmed], primaryImage || trimmed);
    setNewUrl('');
  };
  const updateImage = (index, value) => {
    const next = imageList.map((item, itemIndex) => itemIndex === index ? value : item);
    emit(next, imageList[index] === primaryImage ? value : primaryImage);
  };
  const removeImage = (index) => {
    const removed = imageList[index];
    const next = imageList.filter((_, itemIndex) => itemIndex !== index);
    emit(next, removed === primaryImage ? next[0] : primaryImage);
  };

  return (
    <AdminField label={label} hint={hint} full={full}>
      <div
        onDragOver={(event) => { event.preventDefault(); setDragging(true); }}
        onDragLeave={() => setDragging(false)}
        onDrop={(event) => { event.preventDefault(); setDragging(false); readFiles(event.dataTransfer.files); }}
        style={{
          border: `1.5px dashed ${dragging ? 'var(--primary)' : 'var(--border)'}`,
          borderRadius: 14,
          background: dragging ? 'var(--accent-light)' : 'var(--bg-soft)',
          padding: 12,
          display: 'grid',
          gap: 12,
        }}
      >
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
          <div>
            <div style={{ fontSize: 12, fontWeight: 800, color: 'var(--text)' }}>Galeria visual</div>
            <div style={{ fontSize: 11, color: uploadError ? '#C83A3A' : 'var(--muted)', marginTop: 2 }}>
              {uploading ? 'Subiendo imagenes a Supabase...' : uploadError || (imageList.length ? `${imageList.length} imagen(es)` : 'Arrastra imagenes o agrega una ruta')}
            </div>
          </div>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            <input ref={fileInputRef} type="file" accept="image/*" multiple onChange={event => readFiles(event.target.files)} style={{ display: 'none' }} />
            <Btn type="button" variant="ghost" size="sm" disabled={uploading} onClick={() => fileInputRef.current?.click()}>{uploading ? 'Subiendo' : 'Archivos'}</Btn>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: 8 }} className="form-row">
          <input value={newUrl} onChange={event => setNewUrl(event.target.value)} onKeyDown={event => { if (event.key === 'Enter') { event.preventDefault(); addManualImage(); } }} placeholder="/uploads/imagen.png o https://..." style={{ ...ADMIN_INPUT_STYLE, background: 'var(--card)' }} />
          <Btn type="button" variant="ghost" size="sm" disabled={uploading} onClick={addManualImage}>Agregar ruta</Btn>
        </div>

        {imageList.length === 0 ? (
          <button type="button" onClick={() => fileInputRef.current?.click()} style={{ border: '1px solid var(--border)', borderRadius: 12, background: 'var(--card)', minHeight: 94, cursor: 'pointer', display: 'grid', placeItems: 'center', color: 'var(--muted)', fontSize: 12, fontWeight: 700 }}>
            Soltar imagenes o seleccionar archivos
          </button>
        ) : (
          <div style={{ display: 'grid', gap: 10 }}>
            {imageList.map((item, index) => {
              const isPrimary = item === primaryImage;
              const isImage = item && (String(item).startsWith('data:image') || /\.(png|jpe?g|webp|gif|svg)$/i.test(String(item)));
              return (
                <div key={`${item || 'empty'}-${index}`} style={{ display: 'grid', gridTemplateColumns: '82px 1fr auto', gap: 10, alignItems: 'center', background: 'var(--card)', border: `1px solid ${isPrimary ? 'var(--primary)' : 'var(--border)'}`, borderRadius: 12, padding: 8 }} className="form-row">
                  <div style={{ width: 82, height: 62, borderRadius: 9, overflow: 'hidden', background: 'var(--bg-soft)', border: '1px solid var(--border)', display: 'grid', placeItems: 'center' }}>
                    {isImage ? <img src={item} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} /> : <Icon name="grid" size={20} color="var(--muted)" />}
                  </div>
                  <input value={item} onChange={event => updateImage(index, event.target.value)} placeholder="/uploads/imagen.png o https://..." style={{ ...ADMIN_INPUT_STYLE, background: 'var(--bg-soft)' }} />
                  <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
                    <button type="button" onClick={() => emit(imageList, item)} disabled={isPrimary}
                      style={{ border: '1px solid var(--border)', background: isPrimary ? 'var(--primary)' : 'var(--bg-soft)', color: isPrimary ? '#fff' : 'var(--primary)', borderRadius: 999, padding: '7px 10px', cursor: isPrimary ? 'default' : 'pointer', fontSize: 11, fontWeight: 800 }}>
                      Principal
                    </button>
                    <button type="button" onClick={() => removeImage(index)} style={{ border: 'none', background: '#FFE0E0', color: '#C83A3A', borderRadius: 999, padding: '7px 10px', cursor: 'pointer', fontSize: 11, fontWeight: 800 }}>
                      Quitar
                    </button>
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </div>
    </AdminField>
  );
}

// ─── Decoration Placeholder ─────────────────────────────────────
function DecoPlaceholder({ category = 'default', style = {}, className = '' }) {
  const { t } = window.ReactI18next.useTranslation();
  const palettes = {
    'baby-shower':  { bg: '#F5EBF0', ball1: '#D4A8B8', ball2: '#A8BAB8', stripe: '#D4A8B820' },
    'boda':         { bg: '#F0EDE6', ball1: '#C8A87A', ball2: '#A8BAB8', stripe: '#C8A87A20' },
    'cumpleanos':   { bg: '#EDF2F0', ball1: '#A8BAB8', ball2: '#C4899A', stripe: '#A8BAB820' },
    'gender-reveal':{ bg: '#EEE8F5', ball1: '#C4899A', ball2: '#A8C4C0', stripe: '#C4899A20' },
    'bautizo':      { bg: '#F0EDE6', ball1: '#A8BAB8', ball2: '#C8A87A', stripe: '#A8BAB820' },
    'quinceañera':  { bg: '#F5EBF0', ball1: '#C8A87A', ball2: '#C4899A', stripe: '#C8A87A20' },
    'pedida':       { bg: '#F5EBF0', ball1: '#C4899A', ball2: '#D4A8B8', stripe: '#C4899A20' },
    'default':      { bg: '#F0EBE8', ball1: '#C4899A', ball2: '#A8BAB8', stripe: '#C4899A20' },
  };
  const p = palettes[category] || palettes['default'];
  const uid = `deco-${category}-${Math.random().toString(36).substr(2,5)}`;
  return (
    <svg viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"
      style={{ width: '100%', height: '100%', display: 'block', ...style }}
      className={className} preserveAspectRatio="xMidYMid slice">
      <defs>
        <pattern id={uid} x="0" y="0" width="28" height="28" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
          <rect width="28" height="28" fill={p.bg} />
          <rect width="4" height="28" fill={p.stripe} />
        </pattern>
      </defs>
      <rect width="400" height="300" fill={`url(#${uid})`} />
      {/* Soft backdrop circle */}
      <ellipse cx="200" cy="148" rx="95" ry="115" fill={p.ball1} opacity="0.18" />
      {/* Balloon arch */}
      {[
        [148,175,21,p.ball1,0.75],[153,143,19,p.ball2,0.70],[164,113,17,p.ball1,0.70],
        [183,90,18,p.ball2,0.75],[200,82,20,p.ball1,0.80],[217,90,18,p.ball2,0.75],
        [236,113,17,p.ball1,0.70],[247,143,19,p.ball2,0.70],[252,175,21,p.ball1,0.75],
      ].map(([cx,cy,r,fill,op],i) => (
        <circle key={i} cx={cx} cy={cy} r={r} fill={fill} opacity={op} />
      ))}
      {/* Table */}
      <rect x="100" y="218" width="200" height="14" rx="5" fill={p.ball1} opacity="0.5" />
      <rect x="128" y="232" width="6" height="36" rx="3" fill={p.ball1} opacity="0.3" />
      <rect x="266" y="232" width="6" height="36" rx="3" fill={p.ball1} opacity="0.3" />
      {/* Center flower */}
      {[0,60,120,180,240,300].map((deg,i) => {
        const rad = deg * Math.PI / 180;
        return <circle key={i} cx={200+Math.cos(rad)*13} cy={148+Math.sin(rad)*13} r={10} fill={p.ball2} opacity="0.55" />;
      })}
      <circle cx="200" cy="148" r="9" fill={p.ball1} opacity="0.85" />
      {/* Label */}
      <text x="200" y="280" textAnchor="middle" fill={p.ball1} opacity="0.6"
        fontSize="12" fontFamily="'DM Sans', sans-serif" fontWeight="500">
        {(typeof CATEGORY_LABELS !== 'undefined' ? CATEGORY_LABELS[category] : category) || t('card_fallback_category')}
      </text>
    </svg>
  );
}

// ─── Hero Illustration ───────────────────────────────────────────
function HeroIllustration() {
  return (
    <svg viewBox="0 0 520 620" xmlns="http://www.w3.org/2000/svg" style={{ width: '100%', height: '100%' }}>
      {/* Soft background circles */}
      <circle cx="260" cy="310" r="230" fill="var(--accent-light)" opacity="0.5" />
      <circle cx="260" cy="310" r="180" fill="var(--accent-light)" opacity="0.3" />
      {/* Backdrop arch */}
      <rect x="135" y="105" width="250" height="380" rx="125" fill="var(--primary)" opacity="0.10" />
      <rect x="148" y="118" width="224" height="354" rx="112" fill="none" stroke="var(--primary)" strokeWidth="1.5" opacity="0.3" />
      {/* Balloon arch — left */}
      {[[155,378,23],[145,336,20],[142,292,18],[150,250,20],[165,212,22],[187,181,20],[213,160,18]].map(([cx,cy,r],i) => (
        <circle key={'l'+i} cx={cx} cy={cy} r={r}
          fill={i%2===0 ? 'var(--primary)' : 'var(--sage)'} opacity={0.65+i*0.02} />
      ))}
      {/* Balloon arch — right */}
      {[[365,378,23],[375,336,20],[378,292,18],[370,250,20],[355,212,22],[333,181,20],[307,160,18]].map(([cx,cy,r],i) => (
        <circle key={'r'+i} cx={cx} cy={cy} r={r}
          fill={i%2===0 ? 'var(--sage)' : 'var(--primary)'} opacity={0.65+i*0.02} />
      ))}
      {/* Top of arch */}
      <circle cx="260" cy="148" r="26" fill="var(--primary)" opacity="0.8" />
      {/* Table */}
      <rect x="108" y="455" width="304" height="20" rx="6" fill="var(--accent)" opacity="0.7" />
      <rect x="148" y="475" width="8" height="64" rx="4" fill="var(--accent)" opacity="0.4" />
      <rect x="364" y="475" width="8" height="64" rx="4" fill="var(--accent)" opacity="0.4" />
      {/* Flower centerpiece */}
      {[0,60,120,180,240,300].map((deg,i) => {
        const rad = deg * Math.PI/180;
        return <circle key={'f'+i} cx={260+Math.cos(rad)*20} cy={310+Math.sin(rad)*20} r={16} fill="var(--primary-light)" opacity="0.8" />;
      })}
      <circle cx="260" cy="310" r="14" fill="var(--primary)" opacity="0.75" />
      {/* Floating small balloons */}
      <circle cx="448" cy="110" r="18" fill="var(--primary)" opacity="0.35" />
      <line x1="448" y1="128" x2="446" y2="168" stroke="var(--primary)" strokeWidth="1" opacity="0.3" />
      <circle cx="68" cy="170" r="15" fill="var(--sage)" opacity="0.4" />
      <line x1="68" y1="185" x2="70" y2="218" stroke="var(--sage)" strokeWidth="1" opacity="0.3" />
      <circle cx="468" cy="320" r="12" fill="var(--accent)" opacity="0.4" />
      <line x1="468" y1="332" x2="466" y2="358" stroke="var(--accent)" strokeWidth="1" opacity="0.3" />
      {/* Confetti dots */}
      {[[80,270,5],[440,400,4],[60,420,4],[490,200,3],[420,470,5],[75,500,3]].map(([x,y,r],i) => (
        <circle key={'c'+i} cx={x} cy={y} r={r} fill={i%3===0?'var(--primary)':i%3===1?'var(--sage)':'var(--accent)'} opacity="0.35" />
      ))}
    </svg>
  );
}

// ─── DecoCard ────────────────────────────────────────────────────
function DecoCard({ deco }) {
  const { navigate } = React.useContext(window.AppContext);
  const [hovered, setHovered] = React.useState(false);
  const [pressed, setPressed] = React.useState(false);
  const imageCount = (deco.images || []).length || (deco.image ? 1 : 0);
  const categoryLabel = window.LelusaStore?.getCatalogCategories?.(window.LelusaStore.read?.().catalogCategories, 'design')
    .find(item => item.slug === deco.category)?.name || CATEGORY_LABELS[deco.category] || deco.category;
  return (
    <div
      onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}
      onTouchStart={() => setPressed(true)}
      onTouchEnd={() => setPressed(false)}
      onTouchCancel={() => setPressed(false)}
      style={{
        background: 'var(--card)', borderRadius: '24px', border: '1px solid var(--border)',
        overflow: 'hidden', display: 'flex', flexDirection: 'column',
        transition: 'transform 0.18s ease, box-shadow 0.25s ease',
        transform: pressed ? 'scale(0.97)' : (hovered ? 'translateY(-5px)' : 'translateY(0)'),
        boxShadow: hovered ? '0 20px 50px rgba(58,42,32,0.14)' : '0 4px 24px rgba(58,42,32,0.07)',
        cursor: 'pointer',
      }}
      onClick={() => { window.LelusaGestures.haptic(8); navigate('deco-detail', { decoId: deco.id }, 'forward'); }}>
      {/* Image */}
      <div style={{ height: '220px', position: 'relative', overflow: 'hidden' }}>
        {deco.image ? (
          <img src={deco.image} alt={deco.name} style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
        ) : (
          <DecoPlaceholder category={deco.category} />
        )}
        <div style={{ position: 'absolute', top: '12px', left: '12px' }}>
          <Badge>{categoryLabel}</Badge>
        </div>
        {deco.featured && (
          <div style={{ position: 'absolute', top: '12px', right: '12px' }}>
            <Badge color="warm">Destacado</Badge>
          </div>
        )}
        {imageCount > 1 && (
          <div style={{ position: 'absolute', right: 12, bottom: 12, background: 'rgba(58,42,32,0.72)', color: '#fff', borderRadius: 999, padding: '5px 9px', fontSize: 11, fontWeight: 800, display: 'flex', alignItems: 'center', gap: 5 }}>
            <Icon name="grid" size={12} color="#fff" />
            {imageCount}
          </div>
        )}
      </div>
      {/* Content */}
      <div style={{ padding: '18px 20px 20px', flex: 1, display: 'flex', flexDirection: 'column', gap: '10px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
          <h3 style={{ margin: 0, fontSize: '17px', fontFamily: "'Cormorant Garamond', serif", fontWeight: 600, color: 'var(--text)', lineHeight: 1.3 }}>{deco.name}</h3>
          <div style={{ display: 'flex', alignItems: 'center', gap: '3px', flexShrink: 0, marginLeft: '8px' }}>
            <Icon name="star" size={13} color="#C8A87A" style={{ fill: '#C8A87A' }} />
            <span style={{ fontSize: '13px', fontWeight: 600, color: '#8B7068' }}>{deco.rating}</span>
          </div>
        </div>
        <p style={{ margin: 0, fontSize: '13px', color: 'var(--muted)', lineHeight: 1.5, display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{deco.description}</p>
        <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
          {(deco.tags || []).slice(0,2).map(t => (
            <span key={t} style={{ fontSize: '11px', color: 'var(--muted)', background: 'var(--bg-soft)', borderRadius: '999px', padding: '3px 10px', fontFamily: "'DM Sans', sans-serif" }}>#{t}</span>
          ))}
        </div>
        <div style={{ marginTop: 'auto', paddingTop: '6px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <span style={{ fontSize: '12px', color: 'var(--muted)' }}>Desde </span>
            <span style={{ fontSize: '20px', fontWeight: 700, color: 'var(--primary)', fontFamily: "'Cormorant Garamond', serif" }}>${deco.price.toLocaleString()}</span>
          </div>
          <Btn size="sm" onClick={(e) => { e.stopPropagation(); navigate('customizer', { decoId: deco.id }); }}>
            Personalizar
          </Btn>
        </div>
      </div>
    </div>
  );
}

// ─── NavBar ──────────────────────────────────────────────────────
function NavLink({ label, active, onClick }) {
  const [hover, setHover] = React.useState(false);
  return (
    <button onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{ position: 'relative', background: 'none', border: 'none', cursor: 'pointer', fontSize: '14px', fontFamily: "'DM Sans', sans-serif", fontWeight: active ? 600 : 400, color: active || hover ? 'var(--primary)' : 'var(--muted)', transition: 'color 0.2s', padding: '4px 0' }}>
      {label}
      <span style={{ position: 'absolute', left: 0, bottom: 0, height: '1.5px', background: 'var(--primary)', width: active || hover ? '100%' : '0%', transition: 'width 0.25s ease' }} />
    </button>
  );
}

// ─── Language Switcher ──────────────────────────────────────────
function LanguageSwitcher({ variant = 'ghost' }) {
  const { i18n } = window.ReactI18next.useTranslation();
  const current = i18n.language;
  const toggle = () => i18n.changeLanguage(current === 'es' ? 'en' : 'es');

  return (
    <button onClick={toggle} style={{
      background: 'none', border: variant === 'ghost' ? '1px solid var(--border)' : 'none',
      borderRadius: '8px', padding: '6px 10px', cursor: 'pointer',
      display: 'flex', alignItems: 'center', gap: '6px',
      color: variant === 'ghost' ? 'var(--muted)' : 'rgba(255,255,255,0.6)',
      fontFamily: "'DM Sans', sans-serif", fontSize: '12px', fontWeight: 700,
      textTransform: 'uppercase', transition: 'all 0.2s'
    }}>
      <Icon name="world" size={14} color={variant === 'ghost' ? 'var(--muted)' : 'rgba(255,255,255,0.6)'} />
      {current === 'es' ? 'ES' : 'EN'}
    </button>
  );
}

function NavBar() {
  const { navigate, currentPage } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const systemSettings = window.LelusaStore?.useSystemSettings?.() || {};
  const brand = systemSettings.brand || LELUSA_CONTACT;
  const desktopLogo = brand.logo || LELUSA_BRAND_ASSETS.horizontalColor;
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [scrolled, setScrolled] = React.useState(false);
  React.useEffect(() => {
    const fn = () => setScrolled(window.scrollY > 20);
    window.addEventListener('scroll', fn);
    return () => window.removeEventListener('scroll', fn);
  }, []);
  const scrollHomeSection = (section) => {
    if (currentPage !== 'home') {
      navigate('home', section ? { section } : {});
      return;
    }
    if (!section) {
      window.scrollTo({ top: 0, behavior: 'smooth' });
      return;
    }
    document.querySelector(`[data-section="${section}"]`)?.scrollIntoView({ behavior: 'smooth', block: 'start' });
  };
  const links = [
    { id: 'home',    label: t('nav_home'),    action: () => scrollHomeSection() },
    { id: 'catalog', label: t('nav_catalog'), action: () => navigate('catalog') },
    { id: 'about',   label: t('nav_about'),   action: () => scrollHomeSection('nosotras') },
    { id: 'contact', label: t('nav_contact'), action: () => scrollHomeSection('contacto') },
  ];
  return (
    <nav style={{
      position: 'sticky', top: 0, zIndex: 100,
      background: scrolled ? 'rgba(250,240,232,0.96)' : 'rgba(250,240,232,0.85)',
      backdropFilter: 'blur(12px)', borderBottom: `1px solid ${scrolled ? 'var(--border)' : 'transparent'}`,
      transition: 'all 0.3s ease',
    }}>
      <div style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 24px', height: '68px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        {/* Logo */}
        <div style={{ cursor: 'pointer', display: 'flex', alignItems: 'center' }} onClick={() => navigate('home')}>
          <img className="lel-nav-logo-desktop" src={desktopLogo} alt="Lelusa Delights & Decor logo" style={{ display: 'block', width: '136px', height: 'auto', maxHeight: '56px', objectFit: 'contain' }} />
          <img className="lel-nav-logo-mobile" src={LELUSA_BRAND_ASSETS.compactColor} alt="Lelusa Delights & Decor logo" style={{ display: 'none', width: '58px', height: 'auto', maxHeight: '48px', objectFit: 'contain' }} />
        </div>
        {/* Desktop links */}
        <div style={{ display: 'flex', alignItems: 'center', gap: '20px' }} className="nav-desktop">
          {links.map(l => (
            <NavLink key={l.id} label={l.label} active={(l.id === 'home' && currentPage === 'home') || (l.id === 'catalog' && currentPage === 'catalog')} onClick={l.action} />
          ))}
          <div style={{ display: 'flex', alignItems: 'center', gap: '12px', marginLeft: '12px' }}>
            <LanguageSwitcher />
            <Btn size="sm" onClick={() => navigate('catalog')}>{t('hero_btn_catalog')}</Btn>
          </div>
        </div>
        {/* Mobile: language + hamburger */}
        <div className="nav-mobile" style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
          <LanguageSwitcher />
          <button onClick={() => setMenuOpen(!menuOpen)}
            style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text)', padding: '4px' }}>
            <Icon name={menuOpen ? 'x' : 'menu'} size={22} />
          </button>
        </div>
      </div>
      {/* Mobile menu */}
      {menuOpen && (
        <div className="nav-mobile" style={{ borderTop: '1px solid var(--border)', background: 'var(--bg)', padding: '16px 24px', display: 'flex', flexDirection: 'column', gap: '4px' }}>
          {links.map(l => (
            <button key={l.id} onClick={() => { l.action(); setMenuOpen(false); }}
              style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: '15px', fontFamily: "'DM Sans', sans-serif", fontWeight: 500, color: 'var(--text)', padding: '10px 0', textAlign: 'left', borderBottom: '1px solid var(--border)' }}>
              {l.label}
            </button>
          ))}
          <div style={{ marginTop: '12px' }}>
            <Btn onClick={() => { navigate('catalog'); setMenuOpen(false); }} style={{ width: '100%' }}>{t('hero_btn_catalog')}</Btn>
          </div>
        </div>
      )}
    </nav>
  );
}

// ─── Footer ──────────────────────────────────────────────────────
function Footer() {
  const { navigate } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const systemSettings = window.LelusaStore?.useSystemSettings?.() || {};
  const brand = { ...LELUSA_CONTACT, ...(systemSettings.brand || {}) };
  const landing = systemSettings.landing || {};
  const services = [
    ['cat_baby_shower', 'baby-shower'],
    ['cat_boda', 'boda'],
    ['cat_cumpleanos', 'cumpleanos'],
    ['cat_quinceanera', 'quinceañera'],
    ['cat_bautizo', 'bautizo'],
  ];
  const contactRows = [
    ['phone', brand.phoneLabel, brand.phoneHref],
    ['mail', brand.email, `mailto:${brand.email}`],
    ['mapPin', brand.location, null],
  ];
  const goCatalog = (category) => navigate('catalog', category ? { category } : {});
  return (
    <footer data-section="contacto" className="lel-footer" style={{ background: 'linear-gradient(180deg, #2B1B14 0%, var(--text) 55%, #24140F 100%)', color: 'var(--bg)', padding: '74px 24px 36px', position: 'relative', overflow: 'hidden' }}>
      <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', opacity: 0.7, background: 'radial-gradient(520px 260px at 8% 8%, rgba(196,137,154,0.18), transparent 62%), radial-gradient(520px 260px at 92% 0%, rgba(200,168,122,0.16), transparent 60%)' }} />
      <img src={LELUSA_BRAND_ASSETS.emblemFloral} alt="" aria-hidden="true" loading="lazy" style={{ position: 'absolute', right: '-80px', top: '-120px', width: '360px', height: 'auto', opacity: 0.08, pointerEvents: 'none', filter: 'saturate(0.86)' }} />
      <div className="lel-footer-inner" style={{ maxWidth: '1200px', margin: '0 auto', position: 'relative', zIndex: 1, display: 'grid', gap: '32px' }}>
        <div style={{ height: '1px', background: 'linear-gradient(to right, transparent, rgba(250,240,232,0.26), transparent)' }} />
        <div className="lel-footer-main" style={{ display: 'grid', gridTemplateColumns: 'minmax(280px, 1.15fr) minmax(220px, 0.8fr) minmax(260px, 0.9fr)', gap: '18px', alignItems: 'stretch' }}>
          <div className="lel-footer-brand-card" style={{ border: '1px solid rgba(250,240,232,0.14)', borderRadius: '8px', padding: '28px', background: 'rgba(255,248,244,0.055)', boxShadow: '0 18px 46px rgba(0,0,0,0.14)' }}>
            <div className="lel-footer-brand-row" style={{ display: 'flex', alignItems: 'flex-start', gap: '14px', marginBottom: '18px' }}>
              <img className="lel-footer-logo" src={LELUSA_BRAND_ASSETS.horizontalWhite} alt="Lelusa Delights & Decor logo" loading="lazy" style={{ width: '160px', height: 'auto', maxHeight: '82px', objectFit: 'contain', opacity: 0.96, flexShrink: 0, filter: 'drop-shadow(0 10px 24px rgba(0,0,0,0.22))' }} />
            </div>
            <p className="lel-footer-desc" style={{ margin: '0 0 22px', fontSize: '14px', color: 'rgba(250,240,232,0.74)', lineHeight: 1.8, maxWidth: '380px' }}>{landing.ctaDescription || t('footer_desc')}</p>
            <div className="lel-footer-cta-row" style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
              <Btn size="sm" onClick={() => goCatalog()}>{t('hero_btn_catalog')}</Btn>
              <Btn size="sm" variant="ghost" style={{ borderColor: 'rgba(250,240,232,0.26)', color: 'var(--bg)' }} onClick={() => { window.location.href = brand.phoneHref || 'tel:+525512345678'; }}>
                <Icon name="phone" size={14} color="var(--bg)" />
                {t('cta_btn_call')}
              </Btn>
            </div>
          </div>
          <div className="lel-footer-panel" style={{ border: '1px solid rgba(250,240,232,0.12)', borderRadius: '8px', padding: '26px', background: 'rgba(255,248,244,0.035)' }}>
            <h4 style={{ margin: '0 0 16px', fontSize: '11px', letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 800 }}>{t('footer_services')}</h4>
            <div className="lel-footer-service-grid" style={{ display: 'grid', gridTemplateColumns: '1fr', gap: '8px' }}>
              {services.map(([key, category]) => (
                <button key={key} type="button" onClick={() => goCatalog(category)} style={{ minHeight: '42px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '10px', width: '100%', border: '1px solid rgba(250,240,232,0.12)', borderRadius: '999px', background: 'rgba(255,248,244,0.055)', color: 'rgba(250,240,232,0.82)', padding: '9px 12px 9px 14px', cursor: 'pointer', fontFamily: "'DM Sans', sans-serif", fontSize: '13px', fontWeight: 700, textAlign: 'left' }}>
                  <span>{t(key)}</span>
                  <Icon name="arrowRight" size={13} color="rgba(250,240,232,0.54)" />
                </button>
              ))}
            </div>
          </div>
          <div className="lel-footer-panel" style={{ border: '1px solid rgba(250,240,232,0.12)', borderRadius: '8px', padding: '26px', background: 'rgba(255,248,244,0.035)' }}>
            <h4 style={{ margin: '0 0 16px', fontSize: '11px', letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 800 }}>{t('footer_contact')}</h4>
            <div style={{ display: 'grid', gap: '10px' }}>
              {contactRows.map(([icon, text, href]) => (
                <div key={text} className="lel-footer-contact-row" onClick={() => { if (href) window.location.href = href; }} style={{ minHeight: '44px', display: 'grid', gridTemplateColumns: '34px minmax(0, 1fr)', alignItems: 'center', gap: '10px', border: '1px solid rgba(250,240,232,0.10)', borderRadius: '12px', background: 'rgba(255,248,244,0.045)', padding: '8px 10px', cursor: href ? 'pointer' : 'default' }}>
                  <span style={{ width: '34px', height: '34px', borderRadius: '50%', background: 'rgba(250,240,232,0.09)', display: 'grid', placeItems: 'center' }}>
                    <Icon name={icon} size={15} color="var(--accent)" />
                  </span>
                  <span style={{ minWidth: 0, fontSize: '13px', color: 'rgba(250,240,232,0.78)', lineHeight: 1.35, overflowWrap: 'anywhere' }}>{text}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
        <div className="lel-footer-bottom" style={{ borderTop: '1px solid rgba(255,255,255,0.1)', paddingTop: '20px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '14px' }}>
          <span style={{ fontSize: '12px', color: 'rgba(250,240,232,0.55)', lineHeight: 1.5 }}>{t('footer_rights')}</span>
          <div style={{ display: 'flex', gap: '8px', justifyContent: 'center', flexWrap: 'wrap' }}>
            {services.slice(0, 3).map(([key, category]) => (
              <button key={key} type="button" onClick={() => goCatalog(category)} style={{ border: 'none', background: 'transparent', color: 'rgba(250,240,232,0.48)', cursor: 'pointer', fontFamily: "'DM Sans', sans-serif", fontSize: '12px', padding: '4px 6px' }}>
                {t(key)}
              </button>
            ))}
          </div>
        </div>
      </div>
    </footer>
  );
}

// ─── Admin Sidebar ───────────────────────────────────────────────
function AdminSidebar({ collapsed = false }) {
  const { navigate, currentPage, adminUser } = React.useContext(window.AppContext);
  const { t } = window.ReactI18next.useTranslation();
  const systemSettings = window.LelusaStore?.useSystemSettings?.() || {};
  const brand = systemSettings.brand || {};
  const adminConfig = systemSettings.admin || {};
  const items = [
    { icon: 'barChart',  label: t('admin_dashboard'), page: 'admin-dashboard' },
    { icon: 'fileText',  label: t('admin_quotes'),    page: 'admin-quotes'    },
    { icon: 'grid',      label: t('admin_designs'),   page: 'admin-designs'   },
    { icon: 'sparkles',  label: t('admin_desserts'),  page: 'admin-desserts', hidden: adminConfig.showDesserts === false },
    { icon: 'calendar',  label: t('admin_calendar'),  page: 'admin-calendar'  },
    { icon: 'mail',      label: t('admin_email'),     page: 'admin-email', hidden: adminConfig.showEmail === false },
    { icon: 'trendingUp', label: t('admin_finance'),   page: 'admin-finance', hidden: adminConfig.showFinance === false },
    { icon: 'package',   label: t('admin_inventory'), page: 'admin-inventory', hidden: adminConfig.showInventory === false },
    { icon: 'grid',      label: t('admin_postera'),   page: 'admin-postera', hidden: adminConfig.showPostera === false },
    { icon: 'clients',   label: t('admin_team'),      page: 'admin-team'      },
    { icon: 'settings',  label: t('admin_settings'),  page: 'admin-settings'  },
  ];
  return (
    <div style={{
      width: collapsed ? '64px' : '220px', minHeight: '100vh', background: 'var(--text)',
      display: 'flex', flexDirection: 'column', transition: 'width 0.3s ease', flexShrink: 0,
    }}>
      {/* Logo */}
      <div style={{ padding: collapsed ? '20px 0' : '24px 20px', display: 'flex', alignItems: 'center', gap: '10px', justifyContent: collapsed ? 'center' : 'flex-start', borderBottom: '1px solid rgba(255,255,255,0.08)' }}>
        <img src={LELUSA_BRAND_ASSETS.compactColor} alt="Lelusa Delights & Decor logo" style={{ height: '36px', width: '36px', objectFit: 'contain', opacity: 0.95, flexShrink: 0 }} />
        {!collapsed && <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: '16px', fontWeight: 700, color: 'var(--bg)' }}>{brand.businessName || 'Lelusa'}</div>}
      </div>
      {/* Nav items */}
      <div style={{ flex: 1, padding: '16px 0' }}>
        {items.filter(item => !item.hidden && window.LelusaAccess?.canAccessPage?.(adminUser, item.page) !== false).map(item => {
          const active = currentPage === item.page;
          return (
            <button key={item.label} onClick={() => navigate(item.page)}
              style={{
                width: '100%', display: 'flex', alignItems: 'center', gap: '12px',
                padding: collapsed ? '12px 0' : '11px 20px', justifyContent: collapsed ? 'center' : 'flex-start',
                background: active ? 'rgba(250,240,232,0.12)' : 'transparent',
                border: 'none', cursor: 'pointer', transition: 'background 0.15s',
                color: active ? 'var(--bg)' : 'rgba(250,240,232,0.55)',
                borderLeft: active ? '3px solid var(--accent)' : '3px solid transparent',
                fontFamily: "'DM Sans', sans-serif", fontSize: '13.5px', fontWeight: active ? 600 : 400,
              }}>
              <Icon name={item.icon} size={18} color={active ? 'var(--bg)' : 'rgba(250,240,232,0.55)'} />
              {!collapsed && item.label}
            </button>
          );
        })}
      </div>
      {/* Back to site */}
      <div style={{ padding: collapsed ? '16px 0' : '16px 20px', borderTop: '1px solid rgba(255,255,255,0.08)', display: 'flex', flexDirection: 'column', gap: '12px' }}>
        <div style={{ display: 'flex', justifyContent: collapsed ? 'center' : 'flex-start' }}>
          <LanguageSwitcher variant="dark" />
        </div>
        <button onClick={() => navigate('home')}
          style={{ display: 'flex', alignItems: 'center', gap: '8px', background: 'none', border: 'none', cursor: 'pointer', color: 'rgba(250,240,232,0.5)', fontSize: '13px', fontFamily: "'DM Sans', sans-serif", padding: 0 }}>
          <Icon name="arrowLeft" size={15} color="rgba(250,240,232,0.5)" />
          {!collapsed && t('view_site')}
        </button>
      </div>
    </div>
  );
}

// ─── TagInput ────────────────────────────────────────────────────
function TagInput({ label, value = [], onChange, placeholder, full = false, hint }) {
  const { t } = window.ReactI18next.useTranslation();
  const ph = placeholder != null ? placeholder : t('tag_add_placeholder');
  const [input, setInput] = React.useState('');
  const inputRef = React.useRef(null);
  const add = (raw) => {
    const trimmed = raw.trim();
    if (!trimmed || value.includes(trimmed)) return;
    onChange([...value, trimmed]);
  };
  const handleKey = (e) => {
    if (e.key === 'Enter' || e.key === ',') {
      e.preventDefault();
      add(input);
      setInput('');
    } else if (e.key === 'Backspace' && input === '' && value.length > 0) {
      onChange(value.slice(0, -1));
    }
  };
  const handleBlur = () => {
    if (input.trim()) { add(input); setInput(''); }
  };
  const remove = (item) => onChange(value.filter(v => v !== item));
  return (
    <AdminField label={label} hint={hint} full={full}>
      <div onClick={() => inputRef.current?.focus()} style={{ display: 'flex', flexWrap: 'wrap', gap: 6, alignItems: 'center', minHeight: 42, padding: '6px 10px', border: '1px solid var(--border)', borderRadius: 10, background: 'var(--bg-soft)', cursor: 'text', boxSizing: 'border-box', width: '100%' }}>
        {value.map(item => (
          <span key={item} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, background: 'var(--primary-light)', color: 'var(--primary-dark)', fontSize: 12, fontWeight: 600, borderRadius: 999, padding: '3px 8px 3px 10px', fontFamily: "'DM Sans', sans-serif", whiteSpace: 'nowrap' }}>
            {item}
            <button type="button" onClick={(e) => { e.stopPropagation(); remove(item); }} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--primary-dark)', lineHeight: 1, padding: '0 2px', fontSize: 14, display: 'flex', alignItems: 'center', opacity: 0.7 }} aria-label={t('tag_remove', { item })}>×</button>
          </span>
        ))}
        <input ref={inputRef} value={input} onChange={e => setInput(e.target.value)} onKeyDown={handleKey} onBlur={handleBlur} placeholder={value.length === 0 ? ph : ''} style={{ border: 'none', outline: 'none', background: 'transparent', fontSize: 13, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif", minWidth: 80, flex: 1, padding: '2px 0' }} />
      </div>
    </AdminField>
  );
}

function AdminCategoryManager({ title = 'Categorias', subtitle = '', type = 'design', categories = [], usedValues = [] }) {
  const [open, setOpen] = React.useState(false);
  const [formOpen, setFormOpen] = React.useState(false);
  const [form, setForm] = React.useState({ name: '', slug: '', description: '' });
  const [editing, setEditing] = React.useState(null);
  const [message, setMessage] = React.useState('');
  const [search, setSearch] = React.useState('');
  const [statusFilter, setStatusFilter] = React.useState('all');
  const allCategories = window.LelusaStore.getCatalogCategories(categories, type, true);
  const used = new Set((usedValues || []).filter(Boolean));
  const activeCount = allCategories.filter(item => item.active !== false).length;
  const inactiveCount = allCategories.length - activeCount;
  const usedCount = allCategories.filter(item => used.has(item.slug)).length;
  const filteredCategories = allCategories.filter((category) => {
    const q = search.trim().toLowerCase();
    const haystack = `${category.name} ${category.slug} ${category.description}`.toLowerCase();
    const matchesSearch = !q || haystack.includes(q);
    const matchesStatus = statusFilter === 'all'
      || (statusFilter === 'active' && category.active !== false)
      || (statusFilter === 'paused' && category.active === false)
      || (statusFilter === 'used' && used.has(category.slug));
    return matchesSearch && matchesStatus;
  });
  const slugifyCategory = (value) => String(value || '')
    .trim()
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '');

  const reset = () => {
    setEditing(null);
    setForm({ name: '', slug: '', description: '' });
    setMessage('');
  };
  const openNew = () => {
    reset();
    setFormOpen(true);
  };
  const startEdit = (category) => {
    setEditing(category);
    setForm({ name: category.name || '', slug: category.slug || '', description: category.description || '' });
    setMessage('');
    setFormOpen(true);
  };
  const save = () => {
    const name = form.name.trim();
    const slug = (form.slug.trim() || slugifyCategory(name));
    if (!name || !slug) {
      setMessage('Escribe nombre y clave de categoria.');
      return;
    }
    const duplicate = allCategories.some(item => item.slug === slug && String(item.id) !== String(editing?.id));
    if (duplicate) {
      setMessage('Ya existe una categoria con esa clave.');
      return;
    }
    const payload = { type, name, slug, description: form.description.trim(), active: editing?.active !== false };
    if (editing) window.LelusaStore.updateCatalogCategory(editing.id, payload);
    else window.LelusaStore.addCatalogCategory(payload);
    reset();
    setFormOpen(false);
  };

  return (
    <>
      <div style={{ border: '1px solid var(--border)', borderRadius: 16, background: 'var(--card)', marginBottom: 16, padding: 14, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontSize: 13, fontWeight: 900, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{title}</div>
          {subtitle && <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 3 }}>{subtitle}</div>}
        </div>
        <Btn type="button" variant="ghost" size="sm" onClick={() => setOpen(true)}>
          <Icon name="settings" size={14} color="var(--primary)" />
          Gestionar ({allCategories.filter(item => item.active !== false).length})
        </Btn>
      </div>
      <AdminModal
        open={open}
        title={title}
        subtitle={subtitle || 'Administra categorias visibles en los formularios y filtros.'}
        width="920px"
        onClose={() => { setOpen(false); setFormOpen(false); reset(); }}
      >
        <div style={{ display: 'grid', gap: 16 }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 10 }} className="form-row">
            {[
              ['Activas', activeCount, '#2A8A50'],
              ['Pausadas', inactiveCount, '#C8881A'],
              ['En uso', usedCount, 'var(--primary)'],
            ].map(([label, value, color]) => (
              <div key={label} style={{ border: '1px solid var(--border)', borderRadius: 14, background: 'var(--bg-soft)', padding: 12 }}>
                <div style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 900, textTransform: 'uppercase', letterSpacing: '0.07em' }}>{label}</div>
                <div style={{ marginTop: 4, fontSize: 24, color, fontWeight: 900, fontFamily: "'DM Sans', sans-serif" }}>{value}</div>
              </div>
            ))}
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 170px auto', gap: 10, alignItems: 'center' }} className="form-row">
            <div style={{ position: 'relative' }}>
              <Icon name="search" size={15} color="var(--muted)" style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none' }} />
              <input value={search} onChange={event => setSearch(event.target.value)} placeholder="Buscar por nombre, clave o descripcion..." style={{ ...ADMIN_INPUT_STYLE, paddingLeft: 36 }} />
            </div>
            <select value={statusFilter} onChange={event => setStatusFilter(event.target.value)} style={ADMIN_INPUT_STYLE}>
              <option value="all">Todas</option>
              <option value="active">Activas</option>
              <option value="paused">Pausadas</option>
              <option value="used">En uso</option>
            </select>
            <Btn type="button" size="sm" onClick={openNew}>
              <Icon name="plus" size={14} color="#fff" />
              Nueva
            </Btn>
          </div>
          <div style={{ display: 'grid', gap: 10 }}>
            {filteredCategories.length === 0 ? (
              <div style={{ border: '1px dashed var(--border)', borderRadius: 16, padding: 28, textAlign: 'center', color: 'var(--muted)', fontSize: 13 }}>
                <Icon name="search" size={24} color="var(--muted)" />
                <div style={{ marginTop: 10, fontWeight: 900, color: 'var(--text)' }}>Sin resultados</div>
                <div style={{ marginTop: 4 }}>Ajusta la busqueda o crea una categoria nueva.</div>
              </div>
            ) : filteredCategories.map(category => {
              const inUse = used.has(category.slug);
              return (
                <div key={category.id} style={{ border: '1px solid var(--border)', borderRadius: 16, padding: 14, background: category.active === false ? 'var(--bg-soft)' : 'var(--card)', display: 'grid', gridTemplateColumns: '42px 1fr auto', gap: 12, alignItems: 'center' }} className="form-row">
                  <div style={{ width: 42, height: 42, borderRadius: 14, background: category.active === false ? '#FFF3DC' : 'var(--accent-light)', display: 'grid', placeItems: 'center', border: '1px solid var(--border)' }}>
                    <Icon name={type === 'dessert' ? 'sparkles' : 'grid'} size={18} color={category.active === false ? '#C8881A' : 'var(--primary)'} />
                  </div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                    <span style={{ fontSize: 14, fontWeight: 900, color: 'var(--text)' }}>{category.name}</span>
                    <Badge color={category.active === false ? 'warm' : 'sage'}>{category.active === false ? 'Pausada' : 'Activa'}</Badge>
                    {inUse && <span style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 800 }}>en uso</span>}
                  </div>
                    <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 4, lineHeight: 1.45 }}>{category.slug}{category.description ? ` · ${category.description}` : ''}</div>
                  </div>
                  <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
                  <Btn type="button" size="sm" variant="ghost" onClick={() => startEdit(category)}>Editar</Btn>
                  <Btn type="button" size="sm" variant="ghost" onClick={() => window.LelusaStore.updateCatalogCategory(category.id, { active: category.active === false })}>
                    {category.active === false ? 'Activar' : 'Pausar'}
                  </Btn>
                    <Btn type="button" size="sm" variant="danger" disabled={inUse} onClick={() => window.LelusaStore.deleteCatalogCategory(category.id)}>Eliminar</Btn>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </AdminModal>
      <AdminModal
        open={formOpen}
        title={editing ? 'Editar categoria' : 'Nueva categoria'}
        subtitle={editing ? 'Actualiza el nombre, clave o descripcion de esta categoria.' : 'Crea una categoria para usarla en formularios y filtros.'}
        width="620px"
        onClose={() => { setFormOpen(false); reset(); }}
        footer={
          <>
            <Btn type="button" variant="ghost" onClick={() => { setFormOpen(false); reset(); }}>Cancelar</Btn>
            <Btn type="button" onClick={save}>{editing ? 'Guardar cambios' : 'Crear categoria'}</Btn>
          </>
        }
      >
        <div style={{ display: 'grid', gap: 14 }}>
          {message && <div style={{ padding: '10px 12px', borderRadius: 12, background: '#FFE0E0', color: '#A33A3A', fontSize: 12, fontWeight: 800 }}>{message}</div>}
          <div style={{ border: '1px solid var(--border)', borderRadius: 16, background: 'var(--bg-soft)', padding: 14, display: 'grid', gridTemplateColumns: '46px 1fr', gap: 12, alignItems: 'center' }}>
            <div style={{ width: 46, height: 46, borderRadius: 16, background: 'var(--accent-light)', display: 'grid', placeItems: 'center' }}>
              <Icon name={type === 'dessert' ? 'sparkles' : 'grid'} size={20} color="var(--primary)" />
            </div>
            <div>
              <div style={{ fontSize: 13, fontWeight: 900, color: 'var(--text)' }}>{form.name || 'Nombre de categoria'}</div>
              <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 3 }}>{form.slug || 'clave-categoria'}</div>
            </div>
          </div>
          <AdminField label="Nombre visible" hint="Es el texto que veran el administrador y las clientas.">
            <input value={form.name} onChange={event => setForm(current => ({ ...current, name: event.target.value, slug: editing ? current.slug : slugifyCategory(event.target.value) }))} placeholder="Ej: Baby Shower Premium" style={ADMIN_INPUT_STYLE} />
          </AdminField>
          <AdminField label="Clave interna" hint="Debe ser unica. Cambiarla puede afectar elementos que ya usan esta categoria.">
            <input value={form.slug} onChange={event => setForm(current => ({ ...current, slug: slugifyCategory(event.target.value) }))} placeholder="baby-shower-premium" style={ADMIN_INPUT_STYLE} />
          </AdminField>
          <AdminField label="Descripcion" hint="Sirve como contexto en el formulario y para organizar el catalogo.">
            <textarea value={form.description} onChange={event => setForm(current => ({ ...current, description: event.target.value }))} rows={4} placeholder="Describe cuando se usa esta categoria..." style={ADMIN_INPUT_STYLE} />
          </AdminField>
        </div>
      </AdminModal>
    </>
  );
}

// ─── Expose all ──────────────────────────────────────────────────
Object.assign(window, {
  Icon, Btn, Badge, StatusBadge,
  AdminModal, AdminFormSection, AdminField, AdminFileField, AdminImageGalleryField, AdminCategoryManager, TagInput, ADMIN_INPUT_STYLE,
  DecoPlaceholder, HeroIllustration, DecoCard,
  NavBar, Footer, AdminSidebar,
  LanguageSwitcher,
});
