function Divider() { return <div style={{ height: 1, background: 'var(--border-default)', margin: '4px 0' }} />; }

function UploadBox({ label, hint, value, onChange }) {
  const inputRef = React.useRef(null);
  function handleFile(e) {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => onChange && onChange(reader.result);
    reader.readAsDataURL(file);
  }
  return (
    <div onClick={() => onChange && inputRef.current && inputRef.current.click()} style={{ border: value ? '1px solid var(--border-default)' : '2px dashed var(--border-strong)', borderRadius: 'var(--radius-md)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 6, padding: value ? 0 : '10px 8px', color: 'var(--text-muted)', textAlign: 'center', height: '100%', minHeight: 76, cursor: onChange ? 'pointer' : 'default', overflow: 'hidden', position: 'relative' }}>
      {value ? (
        <img src={value} style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block', background: 'var(--bg-sunken)' }} />
      ) : (
        <React.Fragment>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M12 16V4M7 9l5-5 5 5" /><path d="M4 16v3a2 2 0 002 2h12a2 2 0 002-2v-3" /></svg>
          {label && <div style={{ fontSize: 'var(--text-xs)', fontWeight: 600, color: 'var(--text-secondary)' }}>{label}</div>}
          {hint && <div style={{ fontSize: 'var(--text-xs)' }}>{hint}</div>}
        </React.Fragment>
      )}
      {onChange && <input ref={inputRef} type="file" accept="image/*" onChange={handleFile} style={{ display: 'none' }} />}
    </div>
  );
}

function FormPanel({ title, toggle, children }) {
  return (
    <div style={{ background: 'var(--bg-sunken)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-lg)', padding: 18, display: 'flex', flexDirection: 'column', gap: 14 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ fontWeight: 700, fontSize: 'var(--text-sm)', color: 'var(--text-secondary)', textTransform: 'uppercase', letterSpacing: 'var(--tracking-wide)' }}>{title}</div>
        {toggle}
      </div>
      {children}
    </div>
  );
}

function WideUploadBox({ label, hint, value, onChange }) {
  const inputRef = React.useRef(null);
  function handleFile(e) {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => onChange && onChange(reader.result);
    reader.readAsDataURL(file);
  }
  return (
    <div onClick={() => inputRef.current && inputRef.current.click()} style={{ border: value ? '1px solid var(--border-default)' : '2px dashed var(--border-strong)', borderRadius: 'var(--radius-md)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 8, padding: value ? 0 : '28px 12px', color: 'var(--text-muted)', textAlign: 'center', width: '100%', cursor: 'pointer', overflow: 'hidden' }}>
      {value ? (
        <div style={{ position: 'relative', width: '100%', height: 140 }}>
          <img src={value} style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
          <span style={{ position: 'absolute', right: 8, bottom: 8, background: 'rgba(8,21,27,0.75)', color: 'white', fontSize: 'var(--text-xs)', padding: '4px 10px', borderRadius: 'var(--radius-pill)' }}>Change image</span>
        </div>
      ) : (
        <React.Fragment>
          <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M12 16V4M7 9l5-5 5 5" /><path d="M4 16v3a2 2 0 002 2h12a2 2 0 002-2v-3" /></svg>
          <div style={{ fontSize: 'var(--text-sm)', fontWeight: 600, color: 'var(--text-secondary)' }}>{label}</div>
          {hint && <div style={{ fontSize: 'var(--text-xs)' }}>{hint}</div>}
        </React.Fragment>
      )}
      <input ref={inputRef} type="file" accept="image/*" onChange={handleFile} style={{ display: 'none' }} />
    </div>
  );
}


function CategoryCombo({ value, onChange, options, onAddOption, placeholder, width }) {
  const [open, setOpen] = React.useState(false);
  const [query, setQuery] = React.useState('');
  const ref = useClickOutside(open, () => setOpen(false));
  React.useEffect(() => { if (open) setQuery(''); }, [open]);
  const selected = options.find((o) => o.value === value);
  const q = query.trim().toLowerCase();
  const filtered = q ? options.filter((o) => o.label.toLowerCase().includes(q)) : options;
  const exact = options.some((o) => o.label.toLowerCase() === q || o.value.toLowerCase() === q);
  function pick(v, label) { onChange(v); setOpen(false); }
  function addNew() {
    const label = query.trim();
    if (!label) return;
    const val = label.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
    onAddOption && onAddOption({ value: val, label });
    onChange(val);
    setOpen(false);
  }
  return (
    <div ref={ref} style={{ position: 'relative', width: width || 200 }}>
      <button type="button" onClick={() => setOpen((o) => !o)} style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, padding: '9px 14px', borderRadius: 'var(--radius-pill)', border: '1.5px solid ' + (open ? 'var(--ud-fill)' : 'var(--ud-border)'), background: open ? 'white' : 'var(--ud-tint)', color: 'var(--ud-text)', fontFamily: 'var(--font-body)', fontSize: 'var(--text-sm)', fontWeight: 600, cursor: 'pointer', transition: 'all .15s ease' }}>
        <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{selected ? selected.label : (placeholder || 'Select or type a category')}</span>
        <ChevronIcon open={open} />
      </button>
      {open && (
        <div style={{ position: 'absolute', top: 'calc(100% + 8px)', left: 0, minWidth: '100%', background: 'white', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-lg)', boxShadow: 'var(--shadow-lg)', zIndex: 60, overflow: 'hidden', animation: 'udPopIn 140ms var(--ease-standard) both' }}>
          <div style={{ padding: 8, borderBottom: '1px solid var(--border-default)' }}>
            <input autoFocus value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search or type new category…" style={{ width: '100%', boxSizing: 'border-box', padding: '8px 10px', borderRadius: 'var(--radius-md)', border: '1px solid var(--border-default)', fontFamily: 'var(--font-body)', fontSize: 'var(--text-sm)' }} />
          </div>
          <div style={{ maxHeight: 220, overflowY: 'auto' }}>
            {filtered.map((o) => (
              <div key={o.value} onClick={() => pick(o.value, o.label)} style={{ padding: '10px 16px', fontSize: 'var(--text-sm)', cursor: 'pointer', background: o.value === value ? 'var(--ud-tint)' : 'white', fontWeight: o.value === value ? 600 : 400 }} className="ud-row">{o.label}</div>
            ))}
            {filtered.length === 0 && <div style={{ padding: '10px 16px', fontSize: 'var(--text-sm)', color: 'var(--text-muted)' }}>No matches.</div>}
            {q && !exact && (
              <div onClick={addNew} style={{ padding: '10px 16px', fontSize: 'var(--text-sm)', cursor: 'pointer', color: 'var(--brand-primary)', fontWeight: 600, borderTop: '1px solid var(--border-default)' }}>+ Add "{query.trim()}"</div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

const REFUND_OPTIONS = [
  { value: 'none', label: 'No refunds' },
  { value: '7day', label: 'Refundable up to 7 days before' },
  { value: '24hr', label: 'Refundable up to 24 hours before' },
  { value: 'full', label: 'Fully refundable' },
  { value: 'transfer', label: 'Non-refundable, transferable' },
];

function CoachesEditor({ coaches, onChange }) {
  const { Input } = window.TheUpperDeckDesignSystem_4d3294;
  function set(i, k, v) { const c = coaches.slice(); c[i] = { ...c[i], [k]: v }; onChange(c); }
  function add() { onChange([...coaches, { name: '', bio: '', photo: null }]); }
  function remove(i) { onChange(coaches.filter((_, idx) => idx !== i)); }
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      {coaches.map((c, i) => (
        <div key={i} style={{ display: 'grid', gridTemplateColumns: '76px 1fr 24px', gap: 10, alignItems: 'start' }}>
          <div style={{ width: 76, height: 76 }}><UploadBox label="Photo" value={c.photo} onChange={(v) => set(i, 'photo', v)} /></div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <Input placeholder="Coach name" value={c.name} onChange={(v) => set(i, 'name', v)} />
            <Input placeholder="Short bio / description" value={c.bio} onChange={(v) => set(i, 'bio', v)} />
          </div>
          <button onClick={() => remove(i)} style={{ border: 'none', background: 'none', color: 'var(--text-muted)', cursor: 'pointer', fontSize: 'var(--text-lg)' }}>×</button>
        </div>
      ))}
      <button onClick={add} style={{ border: 'none', background: 'none', color: 'var(--text-link)', cursor: 'pointer', fontSize: 'var(--text-sm)', fontWeight: 600, textAlign: 'left', padding: 0 }}>+ Add coach</button>
    </div>
  );
}

function DatesEditor({ dates, onChange, mainVenue }) {
  const { Input, Checkbox } = window.TheUpperDeckDesignSystem_4d3294;
  function set(i, k, v) { const d = dates.slice(); d[i] = { ...d[i], [k]: v }; onChange(d); }
  function add() { onChange([...dates, { date: '', startTime: '', endTime: '', venue: '', sameAsMain: true }]); }
  function remove(i) { onChange(dates.filter((_, idx) => idx !== i)); }
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {dates.map((d, i) => (
        <div key={i} style={{ display: 'flex', flexDirection: 'column', gap: 10, paddingBottom: 14, borderBottom: i < dates.length - 1 ? '1px solid var(--border-default)' : 'none' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <CustomDatePicker value={d.date} onChange={(v) => set(i, 'date', v)} placeholder="Pick date" />
            <div style={{ flex: '1 1 140px' }}><Input placeholder="Starts e.g. 6:00 AM" value={d.startTime} onChange={(v) => set(i, 'startTime', v)} /></div>
            <div style={{ flex: '1 1 140px' }}><Input placeholder="Ends e.g. 9:00 AM" value={d.endTime} onChange={(v) => set(i, 'endTime', v)} /></div>
            <button onClick={() => remove(i)} style={{ border: 'none', background: 'none', color: 'var(--text-muted)', cursor: 'pointer', fontSize: 'var(--text-lg)' }}>×</button>
          </div>
          <Checkbox label="Same venue as main event" checked={d.sameAsMain} onChange={(v) => set(i, 'sameAsMain', v)} />
          {!d.sameAsMain && <Input placeholder="Venue for this date" value={d.venue} onChange={(v) => set(i, 'venue', v)} />}
          {d.sameAsMain && <div style={{ fontSize: 'var(--text-sm)', color: 'var(--text-muted)' }}>{mainVenue || 'Set the main event venue above'}</div>}
        </div>
      ))}
      <button onClick={add} style={{ border: 'none', background: 'none', color: 'var(--text-link)', cursor: 'pointer', fontSize: 'var(--text-sm)', fontWeight: 600, textAlign: 'left', padding: 0 }}>+ Add date</button>
    </div>
  );
}

function PricingTiersEditor({ tiers, onChange }) {
  const { Input, Switch } = window.TheUpperDeckDesignSystem_4d3294;
  const { CustomDatePicker } = window.UdUI;
  function set(i, k, v) { const t = tiers.slice(); t[i] = { ...t[i], [k]: v }; onChange(t); }
  function setEarlyBird(i, k, v) { const t = tiers.slice(); t[i] = { ...t[i], earlyBird: { ...(t[i].earlyBird || { enabled: false, pct: 10, start: '', end: '' }), [k]: v } }; onChange(t); }
  function setParticipants(i, v) { const t = tiers.slice(); t[i] = { ...t[i], groupSize: Math.max(1, Number(v) || 1) }; onChange(t); }
  function setFeaturesText(i, text) { const t = tiers.slice(); t[i] = { ...t[i], features: text.split('\n') }; onChange(t); }
  function add() { onChange([...tiers, { name: '', price: 0, description: '', features: [] }]); }
  function remove(i) { onChange(tiers.filter((_, idx) => idx !== i)); }
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      {tiers.map((t, i) => {
        const eb = t.earlyBird || { enabled: false, pct: 10, start: '', end: '' };
        return (
        <div key={i} style={{ display: 'flex', flexDirection: 'column', gap: 8, paddingBottom: 12, borderBottom: i < tiers.length - 1 ? '1px solid var(--border-default)' : 'none' }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 100px 24px', gap: 8, alignItems: 'center' }}>
            <Input placeholder="Tier name" value={t.name} onChange={(v) => set(i, 'name', v)} />
            <div style={{ position: 'relative' }}>
              <input type="number" value={t.price} onChange={(e) => set(i, 'price', Number(e.target.value) || 0)} style={{ width: '100%', boxSizing: 'border-box', padding: '11px 24px 11px 14px', fontSize: 'var(--text-base)', fontFamily: 'var(--font-body)', borderRadius: 'var(--radius-md)', border: '1px solid var(--border-default)' }} />
              <span style={{ position: 'absolute', right: 10, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-muted)', fontSize: 'var(--text-sm)' }}>₱</span>
            </div>
            <button onClick={() => remove(i)} style={{ border: 'none', background: 'none', color: 'var(--text-muted)', cursor: 'pointer', fontSize: 'var(--text-lg)' }}>×</button>
          </div>
          <Input placeholder="What's included in this tier" value={t.description || ''} onChange={(v) => set(i, 'description', v)} />
          <div>
            <div style={{ fontSize: 'var(--text-xs)', color: 'var(--text-muted)', marginBottom: 4 }}>Number of participants covered by this tier (1 for solo, e.g. 3 for "Team of 3")</div>
            <input type="number" min="1" value={t.groupSize || 1} onChange={(e) => setParticipants(i, e.target.value)} style={{ width: 90, boxSizing: 'border-box', padding: '9px 12px', fontSize: 'var(--text-sm)', fontFamily: 'var(--font-body)', borderRadius: 'var(--radius-md)', border: '1px solid var(--border-default)' }} />
          </div>
          {(t.groupSize || 1) > 1 && <div style={{ fontSize: 'var(--text-xs)', color: 'var(--text-muted)' }}>At checkout, the buyer will be asked to enter names for the other {(t.groupSize || 1) - 1} attendee(s) under this one order.</div>}
          <div>
            <div style={{ fontSize: 'var(--text-xs)', color: 'var(--text-muted)', marginBottom: 4 }}>Bullet points shown on this tier, one per line (e.g. "Full-day access", "Certificate included")</div>
            <textarea value={(t.features || []).join('\n')} onChange={(e) => setFeaturesText(i, e.target.value)} rows={3} placeholder={'Full-day access\nCertificate included\nLunch provided'} style={{ width: '100%', boxSizing: 'border-box', padding: '9px 12px', fontSize: 'var(--text-sm)', fontFamily: 'var(--font-body)', borderRadius: 'var(--radius-md)', border: '1px solid var(--border-default)', resize: 'vertical' }} />
          </div>
          <div style={{ background: 'var(--bg-sunken)', borderRadius: 'var(--radius-md)', padding: 10, display: 'flex', flexDirection: 'column', gap: 8 }}>
            <Switch label="Early bird discount" checked={eb.enabled} onChange={(c) => setEarlyBird(i, 'enabled', c)} />
            {eb.enabled && (
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'flex-end' }}>
                <div style={{ width: 90 }}>
                  <div style={{ position: 'relative' }}>
                    <input type="number" value={eb.pct} onChange={(e) => setEarlyBird(i, 'pct', Number(e.target.value) || 0)} style={{ width: '100%', boxSizing: 'border-box', padding: '9px 22px 9px 10px', fontSize: 'var(--text-sm)', fontFamily: 'var(--font-body)', borderRadius: 'var(--radius-md)', border: '1px solid var(--border-default)' }} />
                    <span style={{ position: 'absolute', right: 8, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-muted)', fontSize: 'var(--text-xs)' }}>%</span>
                  </div>
                </div>
                <CustomDatePicker value={eb.start} onChange={(v) => setEarlyBird(i, 'start', v)} placeholder="Start date" />
                <CustomDatePicker value={eb.end} onChange={(v) => setEarlyBird(i, 'end', v)} placeholder="End date" />
              </div>
            )}
          </div>
        </div>
        );
      })}
      <button onClick={add} style={{ border: 'none', background: 'none', color: 'var(--text-link)', cursor: 'pointer', fontSize: 'var(--text-sm)', fontWeight: 600, textAlign: 'left', padding: 0 }}>+ Add tier</button>
    </div>
  );
}

function ProgramEditor({ items, onChange }) {
  const { Input } = window.TheUpperDeckDesignSystem_4d3294;
  function set(i, k, v) { const p = items.slice(); p[i] = { ...p[i], [k]: v }; onChange(p); }
  function add() { onChange([...items, { time: '', description: '' }]); }
  function remove(i) { onChange(items.filter((_, idx) => idx !== i)); }
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      {items.map((p, i) => (
        <div key={i} style={{ display: 'grid', gridTemplateColumns: '120px 1fr 24px', gap: 8, alignItems: 'center' }}>
          <Input placeholder="e.g. 9:00 AM" value={p.time} onChange={(v) => set(i, 'time', v)} />
          <Input placeholder="e.g. Opening remarks" value={p.description} onChange={(v) => set(i, 'description', v)} />
          <button onClick={() => remove(i)} style={{ border: 'none', background: 'none', color: 'var(--text-muted)', cursor: 'pointer', fontSize: 'var(--text-lg)' }}>×</button>
        </div>
      ))}
      <button onClick={add} style={{ border: 'none', background: 'none', color: 'var(--text-link)', cursor: 'pointer', fontSize: 'var(--text-sm)', fontWeight: 600, textAlign: 'left', padding: 0 }}>+ Add program item</button>
    </div>
  );
}

function useClickOutside(open, onClose) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    function handler(e) { if (ref.current && !ref.current.contains(e.target)) onClose(); }
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [open]);
  return ref;
}

function ChevronIcon({ open }) {
  return <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ transition: 'transform .15s ease', transform: open ? 'rotate(180deg)' : 'rotate(0)' }}><path d="M6 9l6 6 6-6" /></svg>;
}

function CustomSelect({ value, onChange, options, placeholder, width }) {
  const [open, setOpen] = React.useState(false);
  const [hoverIdx, setHoverIdx] = React.useState(-1);
  const ref = useClickOutside(open, () => setOpen(false));
  const selected = options.find((o) => o.value === value);
  return (
    <div ref={ref} style={{ position: 'relative', width: width || 200 }}>
      <button onClick={() => setOpen((o) => !o)} style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, padding: '9px 14px', borderRadius: 'var(--radius-pill)', border: '1.5px solid ' + (open ? 'var(--ud-fill)' : 'var(--ud-border)'), background: open ? 'white' : 'var(--ud-tint)', color: value ? 'var(--ud-text)' : 'var(--ud-text)', fontFamily: 'var(--font-body)', fontSize: 'var(--text-sm)', fontWeight: 600, cursor: 'pointer', boxShadow: open ? '0 0 0 3px color-mix(in srgb, var(--navy-700) 20%, transparent)' : 'none', transition: 'all .15s ease' }}>
        <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{selected ? selected.label : placeholder}</span>
        <ChevronIcon open={open} />
      </button>
      {open && (
        <div style={{ position: 'absolute', top: 'calc(100% + 8px)', left: 0, minWidth: '100%', background: 'white', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-lg)', boxShadow: 'var(--shadow-lg)', zIndex: 60, overflow: 'hidden', animation: 'udPopIn 140ms var(--ease-standard) both', maxHeight: 280, overflowY: 'auto' }}>
          {value && <div onClick={() => { onChange(''); setOpen(false); }} style={{ padding: '10px 16px', fontSize: 'var(--text-sm)', color: 'var(--text-muted)', cursor: 'pointer', borderBottom: '1px solid var(--border-default)' }}>Clear · {placeholder}</div>}
          {options.map((o, i) => (
            <div key={o.value} onClick={() => { onChange(o.value); setOpen(false); }} onMouseEnter={() => setHoverIdx(i)} style={{ padding: '10px 16px', fontSize: 'var(--text-sm)', cursor: 'pointer', background: o.value === value ? 'var(--ud-tint)' : hoverIdx === i ? 'var(--bg-sunken)' : 'white', color: o.value === value ? 'var(--ud-text)' : 'var(--text-primary)', fontWeight: o.value === value ? 600 : 400 }}>{o.label}</div>
          ))}
        </div>
      )}
    </div>
  );
}

function buildMonthGrid(year, month) {
  const first = new Date(year, month, 1);
  const startDow = first.getDay();
  const daysInMonth = new Date(year, month + 1, 0).getDate();
  const cells = [];
  for (let i = 0; i < startDow; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(d);
  while (cells.length % 7 !== 0) cells.push(null);
  return cells;
}
const MONTH_SHORT = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

function CustomDatePicker({ value, onChange, placeholder }) {
  const [open, setOpen] = React.useState(false);
  const initial = value ? new Date(value) : new Date(2026, 0, 1);
  const [cursor, setCursor] = React.useState({ year: initial.getFullYear(), month: initial.getMonth() });
  const ref = useClickOutside(open, () => setOpen(false));
  const cells = buildMonthGrid(cursor.year, cursor.month);
  const selectedDate = value ? new Date(value) : null;
  function pick(day) {
    const iso = cursor.year + '-' + String(cursor.month + 1).padStart(2, '0') + '-' + String(day).padStart(2, '0');
    onChange(iso); setOpen(false);
  }
  function shift(delta) { setCursor((c) => { let m = c.month + delta, y = c.year; if (m < 0) { m = 11; y--; } if (m > 11) { m = 0; y++; } return { year: y, month: m }; }); }
  const label = value ? MONTH_SHORT[selectedDate.getMonth()] + ' ' + selectedDate.getDate() + ', ' + selectedDate.getFullYear() : placeholder;
  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button onClick={() => setOpen((o) => !o)} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '9px 14px', borderRadius: 'var(--radius-pill)', border: '1.5px solid ' + (open ? 'var(--ud-fill)' : 'var(--ud-border)'), background: open ? 'white' : 'var(--ud-tint)', color: value ? 'var(--ud-text)' : 'var(--ud-text)', fontFamily: 'var(--font-body)', fontSize: 'var(--text-sm)', fontWeight: 600, cursor: 'pointer', boxShadow: open ? '0 0 0 3px color-mix(in srgb, var(--navy-700) 20%, transparent)' : 'none', transition: 'all .15s ease' }}>
        <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8"><rect x="3" y="4" width="18" height="17" rx="2" /><path d="M3 9h18M8 2v4M16 2v4" /></svg>
        {label}
      </button>
      {open && (
        <div style={{ position: 'absolute', top: 'calc(100% + 8px)', left: 0, width: 260, background: 'white', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-lg)', boxShadow: 'var(--shadow-lg)', zIndex: 60, padding: 14, animation: 'udPopIn 140ms var(--ease-standard) both' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
            <button onClick={() => shift(-1)} style={{ border: 'none', background: 'var(--ud-tint)', color: 'var(--ud-text)', width: 26, height: 26, borderRadius: '50%', cursor: 'pointer', fontWeight: 700 }}>‹</button>
            <div style={{ fontWeight: 700, fontSize: 'var(--text-sm)' }}>{MONTH_SHORT[cursor.month]} {cursor.year}</div>
            <button onClick={() => shift(1)} style={{ border: 'none', background: 'var(--ud-tint)', color: 'var(--ud-text)', width: 26, height: 26, borderRadius: '50%', cursor: 'pointer', fontWeight: 700 }}>›</button>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7,1fr)', gap: 2, fontSize: 'var(--text-xs)', color: 'var(--text-muted)', marginBottom: 4 }}>
            {['S', 'M', 'T', 'W', 'T', 'F', 'S'].map((d, i) => <div key={i} style={{ textAlign: 'center', padding: '2px 0' }}>{d}</div>)}
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7,1fr)', gap: 2 }}>
            {cells.map((day, i) => {
              const isSel = selectedDate && day === selectedDate.getDate() && cursor.month === selectedDate.getMonth() && cursor.year === selectedDate.getFullYear();
              return (
                <button key={i} disabled={!day} onClick={() => day && pick(day)} style={{ border: 'none', background: isSel ? 'var(--ud-fill)' : 'transparent', color: !day ? 'transparent' : isSel ? 'white' : 'var(--text-primary)', borderRadius: '50%', width: 30, height: 30, fontSize: 'var(--text-xs)', cursor: day ? 'pointer' : 'default' }}
                  onMouseEnter={(e) => { if (day && !isSel) e.currentTarget.style.background = 'var(--ud-tint)'; }}
                  onMouseLeave={(e) => { if (day && !isSel) e.currentTarget.style.background = 'transparent'; }}>{day || ''}</button>
              );
            })}
          </div>
          {value && <div onClick={() => { onChange(''); setOpen(false); }} style={{ marginTop: 10, textAlign: 'center', fontSize: 'var(--text-xs)', color: 'var(--text-muted)', cursor: 'pointer', borderTop: '1px solid var(--border-default)', paddingTop: 8 }}>Clear date</div>}
          <div onClick={() => { const t = new Date(); setCursor({ year: t.getFullYear(), month: t.getMonth() }); const iso = t.getFullYear() + '-' + String(t.getMonth() + 1).padStart(2, '0') + '-' + String(t.getDate()).padStart(2, '0'); onChange(iso); setOpen(false); }} style={{ marginTop: value ? 4 : 10, textAlign: 'center', fontSize: 'var(--text-xs)', color: 'var(--ud-fill)', fontWeight: 600, cursor: 'pointer', borderTop: value ? 'none' : '1px solid var(--border-default)', paddingTop: value ? 0 : 8 }}>Set today</div>
        </div>
      )}
    </div>
  );
}

function SearchInput({ value, onChange, placeholder, width }) {
  const [focused, setFocused] = React.useState(false);
  return (
    <div style={{ position: 'relative', width: width || '100%' }}>
      <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" style={{ position: 'absolute', left: 13, top: '50%', transform: 'translateY(-50%)', color: focused ? 'var(--ud-fill)' : 'var(--ud-text)', pointerEvents: 'none' }}><circle cx="11" cy="11" r="8" /><path d="M21 21l-4.35-4.35" /></svg>
      <input value={value} placeholder={placeholder} onChange={(e) => onChange(e.target.value)} onFocus={() => setFocused(true)} onBlur={() => setFocused(false)}
        style={{ width: '100%', boxSizing: 'border-box', padding: '9px 14px 9px 36px', borderRadius: 'var(--radius-pill)', border: '1.5px solid ' + (focused ? 'var(--ud-fill)' : 'var(--ud-border)'), background: focused ? 'white' : 'var(--ud-tint)', fontFamily: 'var(--font-body)', fontSize: 'var(--text-sm)', color: 'var(--text-primary)', boxShadow: focused ? '0 0 0 3px color-mix(in srgb, var(--navy-700) 20%, transparent)' : 'none', transition: 'all .15s ease' }} />
    </div>
  );
}

function Btn({ children, onClick, variant, size, disabled, icon, style }) {
  const [hover, setHover] = React.useState(false);
  const sizes = { sm: { padding: '6px 12px', fontSize: 'var(--text-xs)' }, md: { padding: '9px 18px', fontSize: 'var(--text-sm)' } };
  const s = sizes[size || 'md'];
  const palettes = {
    filled: { base: 'var(--ud-tint)', text: 'var(--ud-text)', hoverBg: 'var(--ud-fill-hover)', hoverText: 'white', border: 'none' },
    danger: { base: 'var(--status-error)', text: 'white', hoverBg: '#a01e2e', hoverText: 'white', border: 'none' },
    secondary: { base: 'white', text: 'var(--text-primary)', hoverBg: 'var(--bg-sunken)', hoverText: 'var(--text-primary)', border: '1.5px solid var(--border-strong)' },
    ghost: { base: 'transparent', text: 'var(--text-secondary)', hoverBg: 'var(--bg-sunken)', hoverText: 'var(--text-primary)', border: 'none' },
  };
  const p = palettes[variant || 'filled'];
  return (
    <button disabled={disabled} onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{ display: 'inline-flex', alignItems: 'center', gap: 6, border: p.border, borderRadius: 'var(--radius-md)', cursor: disabled ? 'default' : 'pointer', fontFamily: 'var(--font-body)', fontWeight: 600, opacity: disabled ? 0.5 : 1, background: hover && !disabled ? p.hoverBg : p.base, color: hover && !disabled ? p.hoverText : p.text, transform: hover && !disabled ? 'translateY(-1px)' : 'none', boxShadow: hover && !disabled ? 'var(--shadow-sm)' : 'none', transition: 'all .15s ease', ...s, ...style }}>
      {icon}{children}
    </button>
  );
}

function fmtDateISO(iso) {
  if (!iso) return '';
  const d = new Date(iso);
  return MONTH_SHORT[d.getMonth()] + ' ' + d.getDate() + ', ' + d.getFullYear();
}

window.UdUI = { CustomSelect, CategoryCombo, CustomDatePicker, SearchInput, Btn, useClickOutside, ChevronIcon, Divider, UploadBox, WideUploadBox, FormPanel, REFUND_OPTIONS, CoachesEditor, DatesEditor, PricingTiersEditor, ProgramEditor, fmtDateISO, ColumnPicker, useColumnPrefs };

function useColumnPrefs(key, defaultCols) {
  const storageKey = 'ud-cols-' + key;
  const [cols, setCols] = React.useState(() => {
    try { const saved = JSON.parse(localStorage.getItem(storageKey)); return saved && saved.length ? saved : defaultCols; } catch (e) { return defaultCols; }
  });
  function update(next) { setCols(next); try { localStorage.setItem(storageKey, JSON.stringify(next)); } catch (e) {} }
  return [cols, update];
}

function ColumnPicker({ columns, visible, onChange }) {
  const [open, setOpen] = React.useState(false);
  const ref = useClickOutside(open, () => setOpen(false));
  function toggle(key) { onChange(visible.includes(key) ? visible.filter((k) => k !== key) : [...visible, key]); }
  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button onClick={() => setOpen((o) => !o)} style={{ padding: '8px 14px', borderRadius: 'var(--radius-md)', border: '1px solid var(--border-default)', background: 'white', cursor: 'pointer', fontSize: 'var(--text-sm)', fontFamily: 'var(--font-body)', fontWeight: 600 }}>Adjust table</button>
      {open && (
        <div style={{ position: 'absolute', top: '110%', right: 0, background: 'white', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', boxShadow: 'var(--shadow-md)', padding: 10, zIndex: 500, width: 200 }}>
          {columns.map((c) => (
            <label key={c.key} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 4px', fontSize: 'var(--text-sm)', cursor: c.locked ? 'default' : 'pointer', opacity: c.locked ? 0.5 : 1 }}>
              <input type="checkbox" checked={visible.includes(c.key)} disabled={c.locked} onChange={() => toggle(c.key)} />
              {c.label}
            </label>
          ))}
        </div>
      )}
    </div>
  );
}
