// VA application page

const applyStyles = {
  // ===== Hero =====
  hero: { position: 'relative', padding: '64px 32px 56px', overflow: 'hidden' },
  heroBg: {
    position: 'absolute', inset: 0, pointerEvents: 'none',
    background: 'radial-gradient(60% 50% at 80% 20%, rgba(29,78,137,0.06) 0%, transparent 60%), radial-gradient(40% 40% at 5% 90%, rgba(232,220,196,0.32) 0%, transparent 70%)',
  },
  heroInner: { maxWidth: 1280, margin: '0 auto', position: 'relative', display: 'grid', gridTemplateColumns: '1.1fr 0.9fr', gap: 72, alignItems: 'center' },
  eyebrow: { display: 'inline-flex', alignItems: 'center', gap: 8, fontSize: 13, color: 'var(--blue)', fontWeight: 500, padding: '6px 12px', borderRadius: 999, background: 'var(--blue-soft)', border: '1px solid rgba(29,78,137,0.12)', marginBottom: 24 },
  eyebrowDot: { width: 6, height: 6, borderRadius: 3, background: 'var(--blue)' },
  h1: { fontSize: 68, lineHeight: 0.99, letterSpacing: '-0.035em', fontWeight: 400, color: 'var(--ink)', marginBottom: 24 },
  italic: { color: 'var(--blue)' },
  heroSub: { fontSize: 18, lineHeight: 1.55, color: 'var(--ink-muted)', maxWidth: 540, marginBottom: 28 },
  heroJump: { display: 'inline-flex', alignItems: 'center', gap: 8, padding: '14px 22px', borderRadius: 12, background: 'var(--ink)', color: '#fff', fontSize: 15, fontWeight: 500, transition: 'background .2s' },

  // ===== Hero image (right side of hero) =====
  heroImageWrap: {
    position: 'relative',
    aspectRatio: '1 / 1',
    width: '100%',
  },
  heroImage: { width: '100%', height: '100%', objectFit: 'contain', display: 'block' },

  // ===== "Who we hire" band =====
  whoBand: { padding: '48px 32px', background: 'var(--paper-deep)', borderTop: '1px solid var(--line-soft)', borderBottom: '1px solid var(--line-soft)' },
  whoInner: { maxWidth: 1280, margin: '0 auto' },
  whoLabel: { fontFamily: "'Outfit', system-ui, sans-serif", fontVariantNumeric: 'tabular-nums', fontSize: 12, color: 'var(--blue)', letterSpacing: '0.08em', textTransform: 'uppercase', marginBottom: 18 },
  whoGrid: { display: 'grid', gridTemplateColumns: '1.4fr 1fr 1fr', gap: 56, alignItems: 'start' },
  whoH: { fontFamily: "'Outfit', system-ui, sans-serif", fontSize: 38, lineHeight: 1.1, letterSpacing: '-0.02em', color: 'var(--ink)' },
  whoCol: {},
  whoColTitle: { fontSize: 13, color: 'var(--ink)', fontWeight: 600, marginBottom: 10, display: 'flex', alignItems: 'center', gap: 8 },
  whoColDot: (color) => ({ width: 8, height: 8, borderRadius: 4, background: color }),
  whoList: { listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 10, fontSize: 14, color: 'var(--ink-soft)' },
  whoLi: { display: 'flex', alignItems: 'flex-start', gap: 10, lineHeight: 1.45 },
  whoIconYes: { flex: 'none', width: 18, height: 18, borderRadius: 9, background: 'rgba(47,107,62,0.12)', color: 'var(--green-ok)', display: 'grid', placeItems: 'center', marginTop: 2 },
  whoIconNo: { flex: 'none', width: 18, height: 18, borderRadius: 9, background: 'rgba(180,58,46,0.12)', color: '#B43A2E', display: 'grid', placeItems: 'center', marginTop: 2 },

  // ===== Form section =====
  formWrap: { padding: '88px 32px 64px' },
  formInner: { maxWidth: 920, margin: '0 auto' },
  formIntro: { textAlign: 'center', marginBottom: 56 },
  formH2: { fontFamily: "'Outfit', system-ui, sans-serif", fontSize: 56, lineHeight: 1.04, letterSpacing: '-0.025em', fontWeight: 600, marginBottom: 14 },
  formSub: { fontSize: 17, color: 'var(--ink-muted)', maxWidth: 560, margin: '0 auto', lineHeight: 1.55 },
  card: { background: '#fff', border: '1px solid var(--line)', borderRadius: 20, boxShadow: 'var(--shadow-md)', overflow: 'hidden' },
  step: { padding: '36px 40px', borderBottom: '1px solid var(--line-soft)' },
  stepLast: { padding: '36px 40px' },
  stepHead: { display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 6 },
  stepNum: { fontFamily: "'Outfit', system-ui, sans-serif", fontVariantNumeric: 'tabular-nums', fontSize: 12, color: 'var(--blue)', letterSpacing: '0.08em' },
  stepTitle: { fontSize: 22, fontWeight: 600, letterSpacing: '-0.015em', color: 'var(--ink)' },
  stepHelp: { fontSize: 14, color: 'var(--ink-muted)', marginBottom: 24, marginTop: 6 },

  fieldGrid2: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 18 },
  fieldGrid3: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 18 },
  field: { display: 'flex', flexDirection: 'column', gap: 6 },
  label: { fontSize: 13, fontWeight: 500, color: 'var(--ink-soft)' },
  required: { color: 'var(--blue)', marginLeft: 4 },
  hint: { fontSize: 12, color: 'var(--ink-muted)', marginTop: -2 },
  chipRow: { display: 'flex', flexWrap: 'wrap', gap: 8 },

  // bottom submit bar
  submitBar: { padding: '28px 40px', background: 'var(--paper-deep)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 24, borderTop: '1px solid var(--line-soft)' },
  submitNote: { fontSize: 13, color: 'var(--ink-muted)', maxWidth: 460, lineHeight: 1.5 },
  submitBtn: { background: 'var(--ink)', color: '#fff', padding: '14px 26px', borderRadius: 12, fontSize: 15, fontWeight: 500, display: 'inline-flex', alignItems: 'center', gap: 8, transition: 'background .2s, transform .1s' },
  submitBtnDis: { opacity: 0.5, cursor: 'not-allowed' },

  // video step
  videoCard: { background: 'var(--paper-deep)', border: '1px solid var(--line-soft)', borderRadius: 14, padding: '22px 24px', marginTop: 4 },
  videoCardHead: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 },
  videoCardKicker: { display: 'inline-flex', alignItems: 'center', gap: 8, fontFamily: "'Outfit', system-ui, sans-serif", fontSize: 12, color: 'var(--blue)', letterSpacing: '0.08em', textTransform: 'uppercase' },
  videoCardKickerDot: { width: 6, height: 6, borderRadius: 3, background: 'var(--blue)' },
  videoPrompts: { margin: 0, padding: '0 0 0 20px', display: 'flex', flexDirection: 'column', gap: 10, fontSize: 14.5, color: 'var(--ink-soft)', lineHeight: 1.55 },
  videoHowTo: { marginTop: 20, padding: '16px 18px', background: '#fff', border: '1px solid var(--line)', borderRadius: 12 },
  videoHowToTitle: { fontSize: 12, fontWeight: 600, color: 'var(--ink)', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 10 },
  videoSteps: { margin: 0, padding: '0 0 0 20px', display: 'flex', flexDirection: 'column', gap: 6, fontSize: 13.5, color: 'var(--ink-soft)', lineHeight: 1.55 },
  videoLink: { color: 'var(--blue)', fontWeight: 500, textDecoration: 'underline' },
  videoFallbackBtn: { marginTop: 18, background: 'transparent', border: 0, padding: 0, color: 'var(--blue)', fontSize: 13, fontWeight: 500, cursor: 'pointer', textDecoration: 'underline', textUnderlineOffset: 3 },

  // video upload
  videoDrop: {
    position: 'relative',
    display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
    gap: 10,
    padding: '36px 24px',
    background: '#fff',
    border: '1.5px dashed var(--line)',
    borderRadius: 14,
    textAlign: 'center',
    transition: 'border-color .15s, background .15s',
    cursor: 'pointer',
  },
  videoDropActive: { borderColor: 'var(--blue)', background: 'var(--blue-soft)' },
  videoDropIcon: {
    width: 44, height: 44, borderRadius: 22,
    background: 'var(--blue-soft)', color: 'var(--blue)',
    display: 'grid', placeItems: 'center',
    marginBottom: 4,
  },
  videoDropTitle: { fontSize: 15, fontWeight: 600, color: 'var(--ink)' },
  videoDropHint: { fontSize: 13, color: 'var(--ink-muted)' },
  videoDropMeta: { fontSize: 12, color: 'var(--ink-muted)', marginTop: 4 },
  videoDropFile: { position: 'absolute', inset: 0, width: '100%', height: '100%', opacity: 0, cursor: 'pointer' },

  // video preview card
  videoPreviewCard: {
    display: 'grid',
    gridTemplateColumns: '220px 1fr',
    gap: 18,
    padding: 16,
    background: '#fff',
    border: '1px solid var(--line)',
    borderRadius: 14,
    boxShadow: 'var(--shadow-sm)',
  },
  videoPreviewMedia: {
    width: '100%',
    aspectRatio: '16 / 10',
    background: '#000',
    borderRadius: 10,
    objectFit: 'cover',
    display: 'block',
  },
  videoPreviewBody: { display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minWidth: 0 },
  videoPreviewHead: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 },
  videoPreviewCheck: {
    width: 20, height: 20, borderRadius: 10,
    background: 'rgba(47,107,62,0.12)', color: 'var(--green-ok)',
    display: 'grid', placeItems: 'center',
  },
  videoPreviewTitleRow: { fontSize: 14, fontWeight: 600, color: 'var(--ink)' },
  videoPreviewName: {
    fontSize: 13, color: 'var(--ink-soft)',
    overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
    marginTop: 2,
  },
  videoPreviewMeta: {
    fontSize: 12, color: 'var(--ink-muted)',
    marginTop: 6,
    fontFamily: "'Outfit', system-ui, sans-serif", fontVariantNumeric: 'tabular-nums',
    display: 'flex', alignItems: 'center', gap: 10,
  },
  videoPreviewMetaDot: { width: 3, height: 3, borderRadius: 1.5, background: 'var(--ink-muted)', display: 'inline-block' },
  videoPreviewActions: { display: 'flex', gap: 14, marginTop: 12, flexWrap: 'wrap' },
  videoPreviewLink: {
    fontSize: 13, color: 'var(--blue)', fontWeight: 500,
    textDecoration: 'underline', textUnderlineOffset: 3, cursor: 'pointer',
    background: 'transparent', border: 0, padding: 0,
  },
  videoPreviewWarn: {
    marginTop: 12,
    fontSize: 12.5,
    padding: '8px 12px',
    borderRadius: 8,
    background: 'rgba(242,107,92,0.08)',
    border: '1px solid rgba(242,107,92,0.25)',
    color: 'var(--coral-ink)',
    display: 'flex', alignItems: 'flex-start', gap: 8,
  },

  // success
  successCard: { background: '#fff', border: '1px solid var(--line)', borderRadius: 20, padding: '64px 48px', textAlign: 'center', boxShadow: 'var(--shadow-lg)' },
  successIcon: { width: 64, height: 64, borderRadius: 32, background: 'rgba(47,107,62,0.1)', color: 'var(--green-ok)', display: 'grid', placeItems: 'center', margin: '0 auto 24px' },
  successH: { fontFamily: "'Outfit', system-ui, sans-serif", fontSize: 44, letterSpacing: '-0.02em', marginBottom: 14 },
  successP: { fontSize: 16, color: 'var(--ink-muted)', maxWidth: 520, margin: '0 auto 28px', lineHeight: 1.55 },
  successList: { textAlign: 'left', maxWidth: 480, margin: '0 auto', display: 'flex', flexDirection: 'column', gap: 14, padding: 24, background: 'var(--paper-deep)', borderRadius: 14, border: '1px solid var(--line-soft)' },
};

// ============= Reusable form atoms =============
function Field({ label, required, hint, children, span = 1 }) {
  return (
    <div style={{ ...applyStyles.field, gridColumn: `span ${span}` }}>
      <label style={applyStyles.label}>
        {label}{required && <span style={applyStyles.required}>*</span>}
      </label>
      {children}
      {hint && <span style={applyStyles.hint}>{hint}</span>}
    </div>
  );
}

function Chip({ active, onClick, children }) {
  return (
    <button type="button" className={`bm-chip-input${active ? ' active' : ''}`} onClick={onClick}>
      <span className="check">
        {active && <svg width="8" height="8" viewBox="0 0 10 10" fill="none"><path d="M2 5.2 4.2 7.4 8 3.2" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/></svg>}
      </span>
      {children}
    </button>
  );
}

function ChipGroup({ options, value, onChange, multi = true }) {
  const arr = Array.isArray(value) ? value : [];
  const toggle = (opt) => {
    if (multi) {
      if (arr.includes(opt)) onChange(arr.filter(x => x !== opt));
      else onChange([...arr, opt]);
    } else {
      onChange(opt);
    }
  };
  return (
    <div style={applyStyles.chipRow}>
      {options.map(o => {
        const active = multi ? arr.includes(o) : value === o;
        return <Chip key={o} active={active} onClick={() => toggle(o)}>{o}</Chip>;
      })}
    </div>
  );
}

// ============= Video upload =============
const MAX_VIDEO_MB = 500; // soft cap; warn above this
const ACCEPTED_VIDEO = 'video/mp4,video/quicktime,video/webm,video/x-matroska,video/*';

function formatBytes(bytes) {
  if (!bytes && bytes !== 0) return '';
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
}

// ============= Loom Record SDK =============
// Replaces the old VideoUpload (file-upload) component. Records video in
// browser → uploads to Loom → returns 3 fields (sharedUrl, embedUrl, id)
// that we store in form state and push to Notion's Video / Video Embed URL
// / Video ID columns. Avoids the file-upload-size problem entirely.
//
// Loom Public App ID is hard-coded here (it's public — embedded in HTML, no
// security implication). The SDK script is loaded in apply.html.
const LOOM_PUBLIC_APP_ID = '2cb43f7f-4b0c-4150-91d1-b3decc5a932c';

function LoomRecorder({ video, onChange }) {
  const buttonRef = React.useRef(null);
  // status: 'idle' | 'loading' | 'ready' | 'error'
  const [status, setStatus] = React.useState('idle');
  const [errorMsg, setErrorMsg] = React.useState('');

  // Initialize Loom SDK and wire up the recorder button on mount.
  // Loom's SDK is ESM-only — apply.html loads it via <script type="module">
  // and exposes window.LoomSDK = { setup, isSupported }. We poll briefly
  // for that global to appear (the module script is async).
  React.useEffect(() => {
    if (video && video.videoUrl) {
      // Already have a recording — no need to init the SDK while showing
      // the success state. Will re-init on remount when the user re-records.
      return;
    }
    let cancelled = false;
    setStatus('loading');

    const initSDK = async () => {
      const sdk = await waitForGlobal(['LoomSDK'], 8000);
      if (cancelled) return;
      if (!sdk || typeof sdk.setup !== 'function' || typeof sdk.isSupported !== 'function') {
        setStatus('error');
        setErrorMsg("Couldn't load the Loom recorder. Please try again on a desktop browser (Chrome, Safari, Firefox, or Edge) with third-party cookies enabled.");
        return;
      }
      try {
        // Step 1 — check the browser can record (MediaRecorder API + third-party cookies).
        const { supported, error } = await sdk.isSupported();
        if (cancelled) return;
        if (!supported) {
          console.warn('[bluemoso] Loom isSupported returned false:', error);
          setStatus('error');
          setErrorMsg("Your browser can't record video. Please try on a desktop with Chrome, Safari, Firefox, or Edge — and make sure third-party cookies are enabled.");
          return;
        }

        // Step 2 — initialize the SDK with the public app ID.
        const { configureButton } = await sdk.setup({
          publicAppId: LOOM_PUBLIC_APP_ID,
        });
        if (cancelled) return;
        if (!buttonRef.current) return;

        // Step 3 — attach to our button. configureButton returns an SDK
        // button that emits events (NodeJS-style EventEmitter).
        const sdkButton = configureButton({ element: buttonRef.current });
        sdkButton.on('insert-click', (loomVideo) => {
          if (cancelled) return;
          onChange({
            videoUrl:      loomVideo.sharedUrl || '',
            videoEmbedUrl: loomVideo.embedUrl || '',
            videoId:       loomVideo.id || '',
          });
        });
        setStatus('ready');
      } catch (e) {
        if (cancelled) return;
        console.error('[bluemoso] Loom SDK init failed:', e);
        setStatus('error');
        setErrorMsg("The Loom recorder failed to start. Try refreshing the page, or apply from a different desktop browser.");
      }
    };
    initSDK();
    return () => { cancelled = true; };
  }, [video && video.videoUrl]);

  // Already recorded — show success state.
  if (video && video.videoUrl) {
    return (
      <div style={applyStyles.videoPreviewCard} className="bm-video-preview">
        <div style={{ ...applyStyles.videoPreviewBody, padding: '20px 22px' }}>
          <div>
            <div style={applyStyles.videoPreviewHead}>
              <span style={applyStyles.videoPreviewCheck} aria-hidden="true">
                <svg width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="M5 12l4 4 10-10" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"/></svg>
              </span>
              <span style={applyStyles.videoPreviewTitleRow}>Recording uploaded to Loom</span>
            </div>
            <div style={applyStyles.videoPreviewMeta}>
              <a href={video.videoUrl} target="_blank" rel="noreferrer" style={{ color: 'var(--blue)', textDecoration: 'none', fontWeight: 500 }}>
                View on Loom
              </a>
            </div>
          </div>
          <div style={applyStyles.videoPreviewActions}>
            <button
              type="button"
              style={applyStyles.videoPreviewLink}
              onClick={() => onChange({ videoUrl: '', videoEmbedUrl: '', videoId: '' })}
            >
              Re-record
            </button>
          </div>
        </div>
      </div>
    );
  }

  // Recording UI — Loom button + status feedback.
  return (
    <div style={applyStyles.videoDrop}>
      <span style={applyStyles.videoDropIcon} aria-hidden="true">
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
          <path d="M23 7l-7 5 7 5V7z" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
          <rect x="1" y="5" width="15" height="14" rx="2" stroke="currentColor" strokeWidth="1.8"/>
        </svg>
      </span>
      <div style={applyStyles.videoDropTitle}>Record a short intro video</div>
      <div style={applyStyles.videoDropHint}>60–90 seconds · Records in your browser via Loom</div>
      <button
        ref={buttonRef}
        type="button"
        disabled={status !== 'ready'}
        style={{
          marginTop: 16,
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          padding: '12px 20px',
          background: status === 'ready' ? 'var(--ink)' : 'var(--ink-muted)',
          color: '#fff',
          border: 'none', borderRadius: 10,
          fontSize: 14, fontWeight: 500,
          cursor: status === 'ready' ? 'pointer' : 'wait',
          transition: 'background .2s',
        }}
      >
        {status === 'loading' && 'Loading Loom…'}
        {status === 'ready' && 'Record with Loom'}
        {status === 'error' && 'Recorder unavailable'}
        {status === 'idle' && 'Loading Loom…'}
      </button>
      {status === 'error' && errorMsg && (
        <div style={{ marginTop: 12, fontSize: 12, color: 'var(--coral-ink)', lineHeight: 1.5 }}>
          {errorMsg}
        </div>
      )}
    </div>
  );
}

// Poll briefly for one of `names` to appear on window. Resolves with the
// first found global (or null after timeout). Used because the Loom SDK
// script is loaded async — by the time the user reaches the apply form's
// video section, the script has usually loaded, but we don't want to crash
// if it hasn't yet.
function waitForGlobal(names, timeoutMs) {
  return new Promise((resolve) => {
    const start = Date.now();
    const tick = () => {
      for (const name of names) {
        if (window[name]) return resolve(window[name]);
      }
      if (Date.now() - start > timeoutMs) return resolve(null);
      setTimeout(tick, 80);
    };
    tick();
  });
}

// VideoUpload (file-upload variant) — preserved below for reference / quick
// rollback, but no longer used in the form. The application now records
// video through Loom (see LoomRecorder above).
function VideoUpload({ file, onChange }) {
  const [dragOver, setDragOver] = React.useState(false);
  const [previewUrl, setPreviewUrl] = React.useState('');

  React.useEffect(() => {
    if (!file) { setPreviewUrl(''); return; }
    const url = URL.createObjectURL(file);
    setPreviewUrl(url);
    return () => URL.revokeObjectURL(url);
  }, [file]);

  const accept = (f) => {
    if (!f) return;
    if (!f.type.startsWith('video/')) return; // ignore non-video drops
    onChange(f);
  };

  const onFileInput = (e) => {
    const f = e.target.files && e.target.files[0];
    accept(f);
  };

  const onDrop = (e) => {
    e.preventDefault();
    setDragOver(false);
    const f = e.dataTransfer.files && e.dataTransfer.files[0];
    accept(f);
  };

  if (file) {
    const tooLarge = file.size > MAX_VIDEO_MB * 1024 * 1024;
    return (
      <div>
        <div style={applyStyles.videoPreviewCard} className="bm-video-preview">
          <video
            src={previewUrl}
            style={applyStyles.videoPreviewMedia}
            controls
            playsInline
            preload="metadata"
          />
          <div style={applyStyles.videoPreviewBody}>
            <div>
              <div style={applyStyles.videoPreviewHead}>
                <span style={applyStyles.videoPreviewCheck} aria-hidden="true">
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="M5 12l4 4 10-10" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"/></svg>
                </span>
                <span style={applyStyles.videoPreviewTitleRow}>Video ready</span>
              </div>
              <div style={applyStyles.videoPreviewName} title={file.name}>{file.name}</div>
              <div style={applyStyles.videoPreviewMeta}>
                <span>{formatBytes(file.size)}</span>
                <span style={applyStyles.videoPreviewMetaDot}></span>
                <span>{file.type || 'video'}</span>
              </div>
            </div>
            <div style={applyStyles.videoPreviewActions}>
              <label style={applyStyles.videoPreviewLink}>
                Replace
                <input
                  type="file"
                  accept={ACCEPTED_VIDEO}
                  onChange={onFileInput}
                  style={{ position: 'absolute', width: 1, height: 1, opacity: 0, pointerEvents: 'none' }}
                />
              </label>
              <button type="button" style={applyStyles.videoPreviewLink} onClick={() => onChange(null)}>Remove</button>
            </div>
          </div>
        </div>
        {tooLarge && (
          <div style={applyStyles.videoPreviewWarn}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true" style={{ flex: 'none', marginTop: 1 }}>
              <path d="M12 8v5M12 16.5v.5M4.93 19h14.14a2 2 0 0 0 1.73-3L13.73 4.5a2 2 0 0 0-3.46 0L3.2 16a2 2 0 0 0 1.73 3z" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
            <span>This file is over {MAX_VIDEO_MB} MB. Upload should still work, but if it stalls, try trimming the clip or recording at a lower resolution.</span>
          </div>
        )}
      </div>
    );
  }

  return (
    <label
      style={{ ...applyStyles.videoDrop, ...(dragOver ? applyStyles.videoDropActive : {}) }}
      onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
      onDragLeave={() => setDragOver(false)}
      onDrop={onDrop}
    >
      <span style={applyStyles.videoDropIcon} aria-hidden="true">
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
          <path d="M12 16V4M12 4l-5 5M12 4l5 5" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
          <path d="M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"/>
        </svg>
      </span>
      <div style={applyStyles.videoDropTitle}>Drag a video here, or click to upload</div>
      <div style={applyStyles.videoDropHint}>MP4, MOV, WebM &middot; up to {MAX_VIDEO_MB} MB</div>
      <input
        type="file"
        accept={ACCEPTED_VIDEO}
        onChange={onFileInput}
        style={applyStyles.videoDropFile}
        aria-label="Upload a video"
      />
    </label>
  );
}

// ============= Hero =============
function ApplyHero() {
  return (
    <section style={applyStyles.hero}>
      <div style={applyStyles.heroBg} />
      <div style={applyStyles.heroInner} className="bm-hero-grid">
        <div>
          <div style={applyStyles.eyebrow}>
            <span style={applyStyles.eyebrowDot}></span>
            Now accepting applications
          </div>
          <h1 className="serif bm-hero-title" style={applyStyles.h1}>
            The team behind<br/>
            <span style={applyStyles.italic}>your career.</span>
          </h1>
          <p style={applyStyles.heroSub}>
            BlueMoso matches high-performing virtual assistants with founders, executives, and agencies who actually value the work. Remote, fairly paid, and matched to clients who fit how you work, not the other way around.
          </p>
          <a href="#application" style={applyStyles.heroJump}
             onMouseEnter={e => e.currentTarget.style.background = 'var(--blue)'}
             onMouseLeave={e => e.currentTarget.style.background = 'var(--ink)'}>
            Start your application <Icon name="arrow" size={16} />
          </a>
        </div>

        <div style={applyStyles.heroImageWrap}>
          <img
            src="apply/hero-va.png"
            alt="A BlueMoso virtual assistant working on a video call with her team."
            style={applyStyles.heroImage}
            loading="eager"
            decoding="async"
          />
        </div>
      </div>
    </section>
  );
}

// ============= Who we hire band =============
function WhoBand() {
  return (
    <section style={applyStyles.whoBand}>
      <div style={applyStyles.whoInner}>
        <div className="mono" style={applyStyles.whoLabel}>Who we hire</div>
        <div style={applyStyles.whoGrid} className="bm-who-grid">
          <h2 className="serif" style={applyStyles.whoH}>
            We're selective on purpose.<br/>
            <span style={{ color: 'var(--blue)' }}>Roughly 1% of applicants make our roster.</span>
          </h2>
          <div style={applyStyles.whoCol}>
            <div style={applyStyles.whoColTitle}>
              You'll thrive here if
            </div>
            <ul style={applyStyles.whoList}>
              {[
                "You're in it for the long haul",
                'You demonstrate loyalty',
                "You're a team player",
                "You're coachable",
                "You're a quick learner",
                'You thrive in ambiguity',
                'You can commit to a regular schedule',
                'You have great time management',
              ].map(t => (
                <li key={t} style={applyStyles.whoLi}>
                  <span style={applyStyles.whoIconYes} aria-hidden="true">
                    <svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 5.2 4.2 7.4 8 3.2" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/></svg>
                  </span>
                  <span>{t}</span>
                </li>
              ))}
            </ul>
          </div>
          <div style={applyStyles.whoCol}>
            <div style={applyStyles.whoColTitle}>
              Probably not a fit if
            </div>
            <ul style={applyStyles.whoList}>
              {[
                "You're bouncing between jobs",
                "You don't demonstrate loyalty",
                "You're not a team player",
                "You're not coachable",
                'You need a lot of hand-holding',
                'You freeze without clear instructions',
                "You can't commit to a regular schedule",
                "You don't have great time management",
              ].map(t => (
                <li key={t} style={applyStyles.whoLi}>
                  <span style={applyStyles.whoIconNo} aria-hidden="true">
                    <svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2.5 2.5 7.5 7.5 M7.5 2.5 2.5 7.5" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"/></svg>
                  </span>
                  <span>{t}</span>
                </li>
              ))}
            </ul>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============= Application form =============
const HOURS = ['Up to 10 hrs/week', '10–20 hrs/week', '20–30 hrs/week', 'Full-time (30–40 hrs/week)', 'Open to anything'];
const ENGLISH_LEVELS = ['Native', 'Fluent (C2)', 'Advanced (C1)', 'Upper-intermediate (B2)', 'Intermediate (B1)'];

function ApplicationForm() {
  const [data, setData] = React.useState({
    firstName: '', lastName: '', email: '', phone: '', country: '', city: '',
    english: '', otherLanguages: '',
    linkedin: '', portfolio: '', portfolioFile: null, resume: '', resumeFile: null,
    hours: '', startDate: '', rate: '',
    // Video is recorded via Loom Record SDK. videoFile (File object) is
    // retained for forwards-compat with any code that reads from state, but
    // is no longer populated by the UI. The three Loom fields below are the
    // canonical source of truth and map 1:1 to the Notion VA Applicants
    // DB's Video / Video Embed URL / Video ID properties.
    // The text fallback (useTextFallback / why) was removed — applicants
    // MUST submit a video. Loom Record SDK is desktop-only, so applicants
    // on mobile are intentionally filtered out.
    videoFile: null, videoUrl: '', videoEmbedUrl: '', videoId: '',
    referrer: '',
    consent: false,
  });
  const [submitted, setSubmitted] = React.useState(false);
  const [submitting, setSubmitting] = React.useState(false);

  const set = (k, v) => setData(d => ({ ...d, [k]: v }));

  // Video is required — no text fallback. Applicant must complete a Loom recording.
  const videoOk = !!data.videoUrl;
  const requiredOk = data.firstName && data.lastName && data.email && data.country &&
    data.english &&
    data.hours && videoOk && data.consent;

  const submit = async (e) => {
    e.preventDefault();
    if (!requiredOk || submitting) return;
    setSubmitting(true);

    // Always stash locally as a safety net — recoverable if the network call fails.
    try {
      localStorage.setItem('bluemoso_va_application_last', JSON.stringify({ ...data, submittedAt: new Date().toISOString() }));
    } catch (e) { /* no-op */ }

    // Submit to the Worker via lib/bluemoso.js. The lib transparently mints
    // a Turnstile token into the inline #cf-turnstile-apply mount, strips
    // File objects from the payload (we don't upload files yet — Phase 2),
    // and POSTs to /capture-applicant. Worker pushes to Notion + emails
    // hr@bluemoso.com.
    try {
      if (window.bluemoso && window.bluemoso.api && window.bluemoso.api.submitApplicant) {
        await window.bluemoso.api.submitApplicant({
          ...data,
          submittedAt: new Date().toISOString(),
          turnstileMount: '#cf-turnstile-apply',
        });
      } else {
        console.warn('window.bluemoso.api.submitApplicant not available — application saved to localStorage only.');
      }
    } catch (err) {
      console.error('Application submit failed:', err);
      // Don't block the success UI — data is in localStorage. Surface a console error instead.
    }

    setSubmitting(false);
    setSubmitted(true);
    window.scrollTo({ top: document.getElementById('application').offsetTop - 80, behavior: 'smooth' });
  };

  if (submitted) {
    return (
      <section id="application" style={applyStyles.formWrap}>
        <div style={applyStyles.formInner}>
          <div style={applyStyles.successCard}>
            <div style={applyStyles.successIcon}>
              <svg width="28" height="28" viewBox="0 0 24 24" fill="none"><path d="M5 12l4 4 10-10" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </div>
            <h2 style={applyStyles.successH}>Application received.</h2>
            <p style={applyStyles.successP}>
              Thanks, {data.firstName || 'there'}. We've got your application and someone on our team will personally review it.
            </p>
            <div style={applyStyles.successList}>
              {[
                { n: '01', t: 'Review', d: 'We read every application within 5–7 business days.' },
                { n: '02', t: 'Skills assessment', d: 'If it\'s a fit, we\'ll send a short paid skills exercise.' },
                { n: '03', t: 'Interview', d: '30-minute video interview with a member of our team.' },
                { n: '04', t: 'Roster + first match', d: 'If accepted, we\'ll start matching you with clients right away.' },
              ].map(s => (
                <div key={s.n} style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
                  <div className="mono" style={{ fontSize: 12, color: 'var(--blue)', fontWeight: 500, paddingTop: 2 }}>{s.n}</div>
                  <div>
                    <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 2 }}>{s.t}</div>
                    <div style={{ fontSize: 13, color: 'var(--ink-muted)', lineHeight: 1.5 }}>{s.d}</div>
                  </div>
                </div>
              ))}
            </div>
            <div style={{ marginTop: 28, fontSize: 13, color: 'var(--ink-muted)' }}>
              Questions? Email <a href="mailto:apply@bluemoso.com" style={{ color: 'var(--blue)', fontWeight: 500 }}>apply@bluemoso.com</a>
            </div>
          </div>
        </div>
      </section>
    );
  }

  return (
    <section id="application" style={applyStyles.formWrap}>
      <div style={applyStyles.formInner}>
        <div style={applyStyles.formIntro}>
          <h2 style={applyStyles.formH2}>The application.</h2>
          <p style={applyStyles.formSub}>
            About 8 minutes. Take your time, your answers are how we match you with the right client.
          </p>
        </div>

        <form className="card" style={applyStyles.card} onSubmit={submit}>
          {/* ===== 01 About you ===== */}
          <div style={applyStyles.step}>
            <div style={applyStyles.stepHead}>
              <span className="mono" style={applyStyles.stepNum}>01</span>
              <span style={applyStyles.stepTitle}>About you</span>
            </div>
            <p style={applyStyles.stepHelp}>The basics. We won't share any of this without your permission.</p>
            <div style={applyStyles.fieldGrid2} className="bm-form-grid-2">
              <Field label="First name" required>
                <input className="bm-input" value={data.firstName} onChange={e => set('firstName', e.target.value)} placeholder="Maya" />
              </Field>
              <Field label="Last name" required>
                <input className="bm-input" value={data.lastName} onChange={e => set('lastName', e.target.value)} placeholder="Reyes" />
              </Field>
              <Field label="Email" required>
                <input type="email" className="bm-input" value={data.email} onChange={e => set('email', e.target.value)} placeholder="you@example.com" />
              </Field>
              <Field label="Phone / WhatsApp" hint="Include country code">
                <input className="bm-input" value={data.phone} onChange={e => set('phone', e.target.value)} placeholder="+63 917 ..." />
              </Field>
              <Field label="Country" required>
                <input className="bm-input" value={data.country} onChange={e => set('country', e.target.value)} placeholder="Philippines" />
              </Field>
              <Field label="City" hint="Optional">
                <input className="bm-input" value={data.city} onChange={e => set('city', e.target.value)} placeholder="Cebu" />
              </Field>
              <Field label="English level" required>
                <select className="bm-select" value={data.english} onChange={e => set('english', e.target.value)}>
                  <option value="">Select your level…</option>
                  {ENGLISH_LEVELS.map(l => <option key={l} value={l}>{l}</option>)}
                </select>
              </Field>
              <Field label="Other languages" hint="Comma-separated, e.g. Spanish, Tagalog">
                <input className="bm-input" value={data.otherLanguages} onChange={e => set('otherLanguages', e.target.value)} placeholder="Spanish (fluent), Tagalog (native)" />
              </Field>
            </div>
          </div>

          {/* ===== 02 Experience ===== */}
          <div style={applyStyles.step}>
            <div style={applyStyles.stepHead}>
              <span className="mono" style={applyStyles.stepNum}>02</span>
              <span style={applyStyles.stepTitle}>Your experience</span>
            </div>
            <p style={applyStyles.stepHelp}>What you've done as a VA, executive assistant, or in equivalent professional roles.</p>
            <div style={applyStyles.fieldGrid2} className="bm-form-grid-2">
              <Field label="LinkedIn URL" span={2}>
                <input className="bm-input" value={data.linkedin} onChange={e => set('linkedin', e.target.value)} placeholder="https://linkedin.com/in/..." />
              </Field>
              <Field label="Portfolio / website" hint="Paste a link or upload a file. Optional." span={2}>
                <div className="bm-resume-row">
                  <input className="bm-input bm-resume-link" value={data.portfolio} onChange={e => set('portfolio', e.target.value)} placeholder="https://..." />
                  <label className="bm-file-button">
                    <input
                      type="file"
                      accept=".pdf,.doc,.docx,.ppt,.pptx,.key,.zip,.png,.jpg,.jpeg,.webp,.gif,application/pdf,image/*"
                      onChange={e => set('portfolioFile', e.target.files && e.target.files[0] ? e.target.files[0] : null)}
                      style={{ position: 'absolute', width: 1, height: 1, opacity: 0, pointerEvents: 'none' }}
                    />
                    <Icon name="arrow" size={14} />
                    <span>{data.portfolioFile ? 'Replace file' : 'Upload file'}</span>
                  </label>
                </div>
                {data.portfolioFile ? (
                  <div className="bm-file-chip">
                    <span className="bm-file-chip-name">{data.portfolioFile.name}</span>
                    <span className="bm-file-chip-size">{(data.portfolioFile.size / 1024).toFixed(0)} KB</span>
                    <button type="button" className="bm-file-chip-x" onClick={() => set('portfolioFile', null)} aria-label="Remove file">×</button>
                  </div>
                ) : null}
              </Field>
              <Field label="Resume / CV" hint="Paste a link (Google Drive, Dropbox, Notion) or upload a file" span={2}>
                <div className="bm-resume-row">
                  <input className="bm-input bm-resume-link" value={data.resume} onChange={e => set('resume', e.target.value)} placeholder="https://..." />
                  <label className="bm-file-button">
                    <input
                      type="file"
                      accept=".pdf,.doc,.docx,.rtf,.txt,.pages,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                      onChange={e => set('resumeFile', e.target.files && e.target.files[0] ? e.target.files[0] : null)}
                      style={{ position: 'absolute', width: 1, height: 1, opacity: 0, pointerEvents: 'none' }}
                    />
                    <Icon name="arrow" size={14} />
                    <span>{data.resumeFile ? 'Replace file' : 'Upload file'}</span>
                  </label>
                </div>
                {data.resumeFile ? (
                  <div className="bm-file-chip">
                    <span className="bm-file-chip-name">{data.resumeFile.name}</span>
                    <span className="bm-file-chip-size">{(data.resumeFile.size / 1024).toFixed(0)} KB</span>
                    <button type="button" className="bm-file-chip-x" onClick={() => set('resumeFile', null)} aria-label="Remove file">×</button>
                  </div>
                ) : null}
              </Field>
            </div>
          </div>

          {/* ===== 03 Availability ===== */}
          <div style={applyStyles.step}>
            <div style={applyStyles.stepHead}>
              <span className="mono" style={applyStyles.stepNum}>03</span>
              <span style={applyStyles.stepTitle}>Availability & rate</span>
            </div>
            <p style={applyStyles.stepHelp}>Helps us match you to the right kind of client.</p>
            <div style={applyStyles.fieldGrid2} className="bm-form-grid-2">
              <Field label="Hours per week available" required>
                <select className="bm-select" value={data.hours} onChange={e => set('hours', e.target.value)}>
                  <option value="">Select…</option>
                  {HOURS.map(h => <option key={h} value={h}>{h}</option>)}
                </select>
              </Field>
              <Field label="Earliest start date" hint="If accepted">
                <input className="bm-input" value={data.startDate} onChange={e => set('startDate', e.target.value)} placeholder="Within 2 weeks" />
              </Field>
              <Field label="Target hourly rate (USD)" hint="Optional, but helps us match faster" span={2}>
                <input className="bm-input" value={data.rate} onChange={e => set('rate', e.target.value)} placeholder="$4–10/hr" />
              </Field>
            </div>
          </div>

          {/* ===== 04 Video intro ===== */}
          <div style={applyStyles.stepLast}>
            <div style={applyStyles.stepHead}>
              <span className="mono" style={applyStyles.stepNum}>04</span>
              <span style={applyStyles.stepTitle}>A short video about you</span>
            </div>
            <p style={applyStyles.stepHelp}>This is the part we actually pay attention to. We'd rather hear you than read you, so record a quick video (60–90 seconds) covering the prompts below — right here in your browser, via Loom.</p>

            <div style={applyStyles.videoCard}>
              <div style={applyStyles.videoCardHead}>
                <div style={applyStyles.videoCardKicker}>
                  <span style={applyStyles.videoCardKickerDot}></span>
                  In your video, please cover
                </div>
              </div>
              <ol style={applyStyles.videoPrompts}>
                <li><strong>Why BlueMoso?</strong> What pulled you to apply here specifically.</li>
                <li><strong>What should a client know about working with you?</strong> Your strengths, how you communicate, what you're best at.</li>
                <li><strong>What's your work style?</strong> How you stay organized, how you handle ambiguity, and the kind of role you'd thrive in.</li>
              </ol>

              <div style={applyStyles.videoHowTo}>
                <div style={applyStyles.videoHowToTitle}>How to record</div>
                <ol style={applyStyles.videoSteps}>
                  <li>Click <em>Record with Loom</em> below — it opens a recorder right in your browser.</li>
                  <li>Allow camera and microphone access when prompted.</li>
                  <li>Hit record, speak naturally and answer the three prompts above. 60–90 seconds is plenty.</li>
                  <li>When you're done, click insert and the recording will be linked to your application.</li>
                </ol>
              </div>
            </div>

            <div style={{ height: 20 }} />
            <LoomRecorder
              video={{ videoUrl: data.videoUrl, videoEmbedUrl: data.videoEmbedUrl, videoId: data.videoId }}
              onChange={(v) => setData(d => ({
                ...d,
                videoUrl: v.videoUrl || '',
                videoEmbedUrl: v.videoEmbedUrl || '',
                videoId: v.videoId || '',
              }))}
            />
            <div style={{ height: 20 }} />
            <Field label="How did you hear about us?" hint="Optional">
              <input className="bm-input" value={data.referrer} onChange={e => set('referrer', e.target.value)} placeholder="LinkedIn, a friend, Google search…" />
            </Field>
            <div style={{ height: 20 }} />
            <label style={{ display: 'flex', alignItems: 'flex-start', gap: 12, cursor: 'pointer', fontSize: 13, color: 'var(--ink-soft)', lineHeight: 1.55 }}>
              <input type="checkbox" checked={data.consent} onChange={e => set('consent', e.target.checked)} style={{ marginTop: 3, accentColor: 'var(--blue)', width: 16, height: 16, cursor: 'pointer' }} />
              <span>
                I agree to the <a href="applicant-terms.html" style={{ color: 'var(--blue)', textDecoration: 'underline' }}>applicant terms</a> and <a href="applicant-privacy.html" style={{ color: 'var(--blue)', textDecoration: 'underline' }}>applicant privacy notice</a>, and I understand BlueMoso may contact me about this application and future opportunities.
              </span>
            </label>
          </div>

          {/* Inline Turnstile mount. Collapses to 0×0 when no challenge needed;
              grows in-flow above the submit bar when Cloudflare wants to
              verify the user. Matches the placement pattern used by the
              playbook + booking widget. */}
          <div id="cf-turnstile-apply" style={{
            display: 'flex', justifyContent: 'center',
            padding: '0 32px',
          }}></div>

          <div style={applyStyles.submitBar} className="bm-submit-bar">
            <div style={applyStyles.submitNote}>
              We review every application by hand. Expect a personal reply within 5–7 business days.
            </div>
            <button type="submit"
                    style={{ ...applyStyles.submitBtn, ...(requiredOk && !submitting ? {} : applyStyles.submitBtnDis) }}
                    disabled={!requiredOk || submitting}
                    onMouseEnter={e => { if (requiredOk && !submitting) e.currentTarget.style.background = 'var(--blue)'; }}
                    onMouseLeave={e => { if (requiredOk && !submitting) e.currentTarget.style.background = 'var(--ink)'; }}>
              {submitting ? 'Sending…' : 'Submit application'}
              {!submitting && <Icon name="arrow" size={16} />}
            </button>
          </div>
        </form>
      </div>
    </section>
  );
}

// ============= Page shell =============
function ApplyApp() {
  React.useEffect(() => {
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) e.target.classList.add('in'); });
    }, { threshold: 0.12 });
    document.querySelectorAll('.reveal').forEach(el => io.observe(el));
    return () => io.disconnect();
  }, []);

  return (
    <div>
      <Nav baseHref="index.html" />
      <main>
        <ApplyHero />
        <WhoBand />
        <ApplicationForm />
      </main>
      {/* baseHref="index.html" with no localHashes — apply page has none
          of the homepage section anchors (#matching, #packages, #cta,
          #story, #faq), so every footer hash link must route back to the
          homepage. */}
      <Footer baseHref="index.html" />
      <style>{`
        @media (max-width: 980px) {
          .bm-hero-grid { grid-template-columns: 1fr !important; gap: 40px !important; }
          .bm-who-grid { grid-template-columns: 1fr !important; gap: 32px !important; }
        }
        @media (max-width: 640px) {
          .bm-form-grid-2 { grid-template-columns: 1fr !important; }
          .bm-submit-bar { flex-direction: column !important; align-items: stretch !important; }
          .bm-submit-bar button { width: 100%; justify-content: center; }
          .bm-video-preview { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<ApplyApp />);
