// components.jsx — Shared UI primitives: Button, Card, Input, Pill, Toast, Modal, etc.

function Button({ dark, variant = 'primary', size = 'md', children, icon, fullWidth, onClick, disabled, style = {} }) {
  const p = palette(dark);
  const sizes = {
    sm: { h: 32, px: 14, fs: 12 },
    md: { h: 40, px: 18, fs: 13 },
    lg: { h: 48, px: 24, fs: 14 },
  };
  const s = sizes[size];
  const variants = {
    primary: { bg: p.ink, color: p.paper, border: 'none' },
    gold:    { bg: p.gold, color: '#fff', border: 'none' },
    secondary: { bg: 'transparent', color: p.ink, border: `0.5px solid ${p.line}` },
    ghost: { bg: 'transparent', color: p.inkSoft, border: 'none' },
    danger: { bg: 'transparent', color: p.danger, border: `0.5px solid ${p.danger}` },
  };
  const v = variants[variant];
  return (
    <button onClick={onClick} disabled={disabled} style={{
      height: s.h, minHeight: 44 / 1.1, padding: `0 ${s.px}px`, fontSize: s.fs,
      background: v.bg, color: v.color, border: v.border, borderRadius: 999,
      fontFamily: TOKENS.font.sans, fontWeight: 500, letterSpacing: 0.1,
      cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? 0.5 : 1,
      width: fullWidth ? '100%' : undefined, display: 'inline-flex',
      alignItems: 'center', justifyContent: 'center', gap: 8,
      transition: 'all 0.18s ease', ...style,
    }}>
      {children}
      {icon}
    </button>
  );
}

function Card({ dark, children, style = {}, padding = 28, hoverable = false, onClick }) {
  const p = palette(dark);
  return (
    <div onClick={onClick} style={{
      background: p.paper, border: `0.5px solid ${p.line}`, borderRadius: TOKENS.radius.md,
      padding, transition: 'all 0.2s ease', cursor: onClick ? 'pointer' : 'default',
      ...style,
    }}>{children}</div>
  );
}

function Pill({ dark, children, tone = 'neutral', style = {} }) {
  const p = palette(dark);
  const tones = {
    neutral: { bg: p.paperSoft, color: p.inkSoft, bd: p.line },
    gold:    { bg: 'rgba(183, 146, 90, 0.10)', color: p.goldDeep, bd: 'rgba(183, 146, 90, 0.25)' },
    success: { bg: 'rgba(78, 91, 79, 0.10)', color: p.success, bd: 'rgba(78, 91, 79, 0.25)' },
    danger:  { bg: 'rgba(164, 66, 44, 0.08)', color: p.danger, bd: 'rgba(164, 66, 44, 0.25)' },
  };
  const t = tones[tone];
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '4px 10px', borderRadius: 999, background: t.bg, color: t.color,
      border: `0.5px solid ${t.bd}`, fontFamily: TOKENS.font.sans, fontSize: 11,
      fontWeight: 500, letterSpacing: 0.1, ...style,
    }}>{children}</span>
  );
}

function Input({ dark, label, value, placeholder, error, hint, type = 'text', onChange, suffix, required }) {
  const p = palette(dark);
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {label && (
        <span style={{ fontFamily: TOKENS.font.sans, fontSize: 11, color: p.inkSoft, letterSpacing: 0.2 }}>
          {label}{required && <span style={{ color: p.danger, marginLeft: 3 }}>*</span>}
        </span>
      )}
      <div style={{
        display: 'flex', alignItems: 'center', height: 44,
        border: `0.5px solid ${error ? p.danger : p.line}`,
        borderRadius: TOKENS.radius.sm, background: p.paper,
        padding: '0 14px',
      }}>
        <input
          type={type} value={value || ''} placeholder={placeholder}
          onChange={(e) => onChange && onChange(e.target.value)}
          style={{
            flex: 1, border: 'none', outline: 'none', background: 'transparent',
            fontFamily: TOKENS.font.sans, fontSize: 13, color: p.ink,
            height: '100%',
          }}
        />
        {suffix && <span style={{ fontFamily: TOKENS.font.sans, fontSize: 12, color: p.inkMuted }}>{suffix}</span>}
      </div>
      {error && <span style={{ fontFamily: TOKENS.font.sans, fontSize: 11, color: p.danger }}>{error}</span>}
      {hint && !error && <span style={{ fontFamily: TOKENS.font.sans, fontSize: 11, color: p.inkMuted }}>{hint}</span>}
    </label>
  );
}

function Select({ dark, label, value, options, onChange, required }) {
  const p = palette(dark);
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {label && (
        <span style={{ fontFamily: TOKENS.font.sans, fontSize: 11, color: p.inkSoft, letterSpacing: 0.2 }}>
          {label}{required && <span style={{ color: p.danger, marginLeft: 3 }}>*</span>}
        </span>
      )}
      <div style={{
        height: 44, border: `0.5px solid ${p.line}`, borderRadius: TOKENS.radius.sm,
        background: p.paper, padding: '0 14px', display: 'flex', alignItems: 'center',
        justifyContent: 'space-between', cursor: 'pointer',
      }}>
        <span style={{ fontFamily: TOKENS.font.sans, fontSize: 13, color: value ? p.ink : p.inkMuted }}>
          {value || (options[0] && options[0].placeholder) || 'Select…'}
        </span>
        <svg width="10" height="6" viewBox="0 0 10 6"><path d="M0 0h10L5 6z" fill={p.inkMuted} /></svg>
      </div>
    </label>
  );
}

function Divider({ dark, label, style = {} }) {
  const p = palette(dark);
  if (!label) return <div style={{ height: 0.5, background: p.line, ...style }} />;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12, ...style }}>
      <div style={{ flex: 1, height: 0.5, background: p.line }} />
      <Mono dark={dark}>{label}</Mono>
      <div style={{ flex: 1, height: 0.5, background: p.line }} />
    </div>
  );
}

function Toast({ dark, tone = 'success', title, body, action, style = {} }) {
  const p = palette(dark);
  const tones = {
    success: { dot: p.success, label: 'Confirmed' },
    info:    { dot: p.gold,    label: 'Info' },
    warn:    { dot: p.danger,  label: 'Action needed' },
  };
  const t = tones[tone];
  return (
    <div style={{
      background: p.paper, border: `0.5px solid ${p.line}`, borderRadius: TOKENS.radius.md,
      padding: '14px 18px', display: 'flex', alignItems: 'flex-start', gap: 14,
      boxShadow: dark ? '0 8px 24px rgba(0,0,0,0.4)' : '0 8px 24px rgba(0,0,0,0.06)',
      minWidth: 320, ...style,
    }}>
      <div style={{ width: 7, height: 7, borderRadius: 4, background: t.dot, marginTop: 7 }} />
      <div style={{ flex: 1 }}>
        <div style={{ fontFamily: TOKENS.font.sans, fontSize: 12, fontWeight: 600, color: p.ink, marginBottom: 3 }}>{title}</div>
        {body && <div style={{ fontFamily: TOKENS.font.sans, fontSize: 12, color: p.inkMuted, lineHeight: 1.5 }}>{body}</div>}
      </div>
      {action && <span style={{ fontFamily: TOKENS.font.sans, fontSize: 12, color: p.gold, fontWeight: 500, cursor: 'pointer' }}>{action}</span>}
    </div>
  );
}

function Modal({ dark, title, sub, children, onClose, footer, width = 480 }) {
  const p = palette(dark);
  return (
    <div style={{
      position: 'absolute', inset: 0, background: 'rgba(15, 13, 8, 0.4)',
      backdropFilter: 'blur(4px)', display: 'flex', alignItems: 'center', justifyContent: 'center',
      zIndex: 50,
    }}>
      <div style={{
        width, maxWidth: 'calc(100% - 80px)', background: p.paper,
        border: `0.5px solid ${p.line}`, borderRadius: TOKENS.radius.lg,
        boxShadow: '0 24px 80px rgba(0,0,0,0.18)',
        display: 'flex', flexDirection: 'column',
      }}>
        <div style={{ padding: '24px 28px 16px', borderBottom: `0.5px solid ${p.lineSoft}` }}>
          <div style={{ fontFamily: TOKENS.font.sans, fontSize: 15, fontWeight: 600, color: p.ink }}>{title}</div>
          {sub && <div style={{ fontFamily: TOKENS.font.sans, fontSize: 12, color: p.inkMuted, marginTop: 4 }}>{sub}</div>}
        </div>
        <div style={{ padding: '20px 28px', flex: 1 }}>{children}</div>
        {footer && (
          <div style={{ padding: '16px 28px', borderTop: `0.5px solid ${p.lineSoft}`, display: 'flex', gap: 10, justifyContent: 'flex-end' }}>
            {footer}
          </div>
        )}
      </div>
    </div>
  );
}

function EmptyState({ dark, title, body, action }) {
  const p = palette(dark);
  return (
    <div style={{
      padding: '48px 32px', textAlign: 'center',
      border: `0.5px dashed ${p.line}`, borderRadius: TOKENS.radius.md,
      background: p.paperSoft,
    }}>
      <div style={{ width: 28, height: 28, margin: '0 auto 14px', border: `0.5px solid ${p.line}`, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ width: 6, height: 6, borderRadius: 3, background: p.inkMuted }} />
      </div>
      <div style={{ fontFamily: TOKENS.font.sans, fontSize: 13, fontWeight: 500, color: p.ink, marginBottom: 6 }}>{title}</div>
      {body && <div style={{ fontFamily: TOKENS.font.sans, fontSize: 12, color: p.inkMuted, maxWidth: 280, margin: '0 auto', lineHeight: 1.5 }}>{body}</div>}
      {action && <div style={{ marginTop: 18 }}>{action}</div>}
    </div>
  );
}

function Stepper({ dark, steps, current }) {
  const p = palette(dark);
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 0 }}>
      {steps.map((s, i) => (
        <React.Fragment key={i}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <div style={{
              width: 24, height: 24, borderRadius: 12,
              border: `0.5px solid ${i <= current ? p.ink : p.line}`,
              background: i < current ? p.ink : 'transparent',
              color: i < current ? p.paper : p.ink,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontFamily: TOKENS.font.sans, fontSize: 11, fontWeight: 500,
            }}>
              {i < current ? '✓' : i + 1}
            </div>
            <span style={{
              fontFamily: TOKENS.font.sans, fontSize: 12,
              color: i === current ? p.ink : p.inkMuted,
              fontWeight: i === current ? 500 : 400,
            }}>{s}</span>
          </div>
          {i < steps.length - 1 && (
            <div style={{ flex: 1, height: 0.5, background: p.line, margin: '0 16px', minWidth: 24 }} />
          )}
        </React.Fragment>
      ))}
    </div>
  );
}

function PortalNav({ dark, items, active, onSelect, brand }) {
  const p = palette(dark);
  return (
    <div style={{
      width: 220, background: p.paperSoft, borderRight: `0.5px solid ${p.line}`,
      padding: '24px 14px', display: 'flex', flexDirection: 'column', gap: 4,
      flexShrink: 0,
    }}>
      <div style={{ padding: '0 12px 20px' }}>
        <Logotype dark={dark} size={13} serif={true} />
        {brand && <div style={{ fontFamily: TOKENS.font.mono, fontSize: 9, color: p.inkMuted, letterSpacing: 1, textTransform: 'uppercase', marginTop: 6 }}>{brand}</div>}
      </div>
      {items.map((it, i) => (
        <div key={i} onClick={() => onSelect && onSelect(it.id)} style={{
          padding: '9px 12px', borderRadius: TOKENS.radius.sm, cursor: 'pointer',
          background: active === it.id ? p.paper : 'transparent',
          border: `0.5px solid ${active === it.id ? p.line : 'transparent'}`,
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        }}>
          <span style={{ fontFamily: TOKENS.font.sans, fontSize: 12.5, color: active === it.id ? p.ink : p.inkSoft, fontWeight: active === it.id ? 500 : 400 }}>{it.label}</span>
          {it.badge && (
            <span style={{ fontFamily: TOKENS.font.mono, fontSize: 10, color: p.gold, background: 'rgba(183,146,90,0.10)', padding: '1px 6px', borderRadius: 3 }}>{it.badge}</span>
          )}
        </div>
      ))}
    </div>
  );
}

function ProgramCard({ dark, title, sub, price, tag, headingFont = 'sans' }) {
  const p = palette(dark);
  return (
    <div style={{ border: `0.5px solid ${p.line}`, borderRadius: TOKENS.radius.md, padding: 22, background: p.paper, position: 'relative' }}>
      {tag && <div style={{ position: 'absolute', top: -10, left: 18, background: p.gold, color: '#fff', fontFamily: TOKENS.font.sans, fontSize: 9, fontWeight: 600, letterSpacing: 0.4, padding: '3px 8px', borderRadius: 999 }}>{tag}</div>}
      <Mono dark={dark}>{sub}</Mono>
      <H as="div" dark={dark} font={headingFont} size={22} weight={500} style={{ marginTop: 10, marginBottom: 14 }}>{title}</H>
      <div style={{ fontFamily: TOKENS.font.sans, fontSize: 18, fontWeight: 600, color: p.ink, letterSpacing: -0.4 }}>{price}</div>
    </div>
  );
}

function FacultyCard({ dark, name, inst, mark, headingFont = 'sans' }) {
  const p = palette(dark);
  return (
    <div style={{ border: `0.5px solid ${p.line}`, borderRadius: TOKENS.radius.md, overflow: 'hidden', background: p.paper, display: 'flex', flexDirection: 'column' }}>
      <div style={{ aspectRatio: '4 / 3', background: `repeating-linear-gradient(135deg, ${dark ? 'rgba(242,237,226,0.06)' : 'rgba(29,29,31,0.045)'} 0 1px, transparent 1px 10px), ${p.paperSoft}`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <span style={{ fontFamily: TOKENS.font.serif, fontSize: 36, color: p.inkMuted, letterSpacing: 2 }}>{mark}</span>
      </div>
      <div style={{ padding: 18 }}>
        <H as="div" dark={dark} font={headingFont} size={16} weight={500}>{name}</H>
        <Mono dark={dark} style={{ marginTop: 6, display: 'inline-block' }}>{inst}</Mono>
      </div>
    </div>
  );
}

Object.assign(window, { Button, Card, Pill, Input, Select, Divider, Toast, Modal, EmptyState, Stepper, PortalNav, ProgramCard, FacultyCard });
