/* global React */
// Careers screen — hiring ethos, open roles (loaded from /roles markdown), application form.
const DSc = window.MaddyieLabsDesignSystem_80a5eb;
const { NavBar: NavBarC, Footer: FooterC, Button: ButtonC, Card: CardC, SectionIntro: SectionIntroC, Badge: BadgeC, Input: InputC, Select: SelectC, Checkbox: CheckboxC } = DSc;

const CWc = '1120px';

// Backend integration:
//  - GET  {API_BASE}/api/roles  -> JSON list of parsed roles (server reads roles/*.md)
//  - POST {API_BASE}/api/apply  -> multipart form (name,email,role,link,cv,agree,+honeypot)
// When no backend is present (static preview, single-file export, plain file://)
// both calls fall back: roles are read directly from roles/*.md, and the
// application opens the visitor's email client (mailto) as before.
const API_BASE = (typeof window !== 'undefined' && window.__API_BASE) || '';
// Fallback inbox used only when the backend is unreachable.
const APPLICATION_EMAIL = 'maddison@maddyie.com';

// Cloudflare Turnstile (CAPTCHA) site key. Defaults to Cloudflare's public TEST
// key (always passes) when window.__TURNSTILE_SITE_KEY isn't set.
const TURNSTILE_SITE_KEY = (typeof window !== 'undefined' && window.__TURNSTILE_SITE_KEY) || '1x00000000000000000000AA';

// Parse a role markdown file in the format:
//   # RoleName
//   ## Tagline:
//   ...
//   ## location:
//   ...
//   ## Full Role description:
//   ...everything after this marker is the (rich markdown) full description...
//
// First-wins for name / tagline / location, so a long description that itself
// contains markdown headings (### / ####, even pasted ## blocks) is captured
// whole and rendered as markdown rather than truncated.
function parseRole(md) {
  const role = { name: '', tagline: '', location: '', description: '' };
  const lines = md.split('\n');

  // Locate the first and last "## Full Role description:" markers. A file may
  // contain a nested second role block (pasted whole); metadata is read from
  // the head (before the FIRST marker) and the rich body from the LAST marker,
  // which drops any duplicated Tagline/location scaffolding in between.
  const markerIdx = [];
  let descInline = '';
  for (let i = 0; i < lines.length; i++) {
    const m = lines[i].match(/^##\s+full\s+role\s+description\s*:?(.*)$/i);
    if (m) { markerIdx.push(i); if (markerIdx.length === 1) descInline = (m[1] || '').trim(); }
  }
  const firstMarker = markerIdx.length ? markerIdx[0] : -1;
  const lastMarker = markerIdx.length ? markerIdx[markerIdx.length - 1] : -1;

  // Metadata is parsed only from the lines BEFORE the first description marker.
  const head = firstMarker >= 0 ? lines.slice(0, firstMarker) : lines;
  let section = null;
  let buf = [];
  const flush = () => {
    const text = buf.join('\n').trim();
    if (section === 'tagline' && !role.tagline) role.tagline = text;
    else if (section === 'location' && !role.location) role.location = text;
    buf = [];
  };
  for (const line of head) {
    const h2 = line.match(/^##\s+(.*)$/);
    const h1 = line.match(/^#\s+(.*)$/);
    if (h2) {
      flush();
      const key = h2[1].toLowerCase();
      section = key.includes('tagline') ? 'tagline' : key.includes('location') ? 'location' : null;
    } else if (h1) {
      flush();
      section = null;
      if (!role.name) role.name = h1[1].trim();
    } else if (section) {
      buf.push(line);
    }
  }
  flush();

  // Everything after the last marker is the description. Only carry the
  // inline-on-marker text through when there is a single marker (no nested block).
  if (lastMarker >= 0) {
    const body = lines.slice(lastMarker + 1).join('\n');
    const inline = markerIdx.length === 1 ? descInline : '';
    role.description = (inline ? inline + '\n' : '') + body;
    role.description = role.description.replace(/\n{3,}/g, '\n\n').trim();
  }
  return role;
}

// Render an inline string with **bold** spans.
function renderInline(text, keyBase) {
  const parts = text.split(/(\*\*[^*]+\*\*)/g).filter(Boolean);
  return parts.map((p, i) => {
    const b = p.match(/^\*\*([^*]+)\*\*$/);
    return b
      ? <strong key={keyBase + '-' + i} style={{ fontWeight: 700, color: 'var(--ink-1)' }}>{b[1]}</strong>
      : <React.Fragment key={keyBase + '-' + i}>{p}</React.Fragment>;
  });
}

// Render a rich-markdown role description as styled React.
// Handles #/##/### / #### headings, **bold**, "* " / "- " bullet lists, paragraphs.
function MarkdownBody({ md }) {
  const lines = md.split('\n');
  const blocks = [];
  let i = 0;
  let key = 0;
  while (i < lines.length) {
    const line = lines[i];
    const trimmed = line.trim();
    if (!trimmed) { i++; continue; }

    const heading = trimmed.match(/^(#{1,6})\s+(.*)$/);
    if (heading) {
      const level = heading[1].length;
      const txt = heading[2].replace(/:$/, '');
      const styles = {
        1: { fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: '24px', letterSpacing: '-0.015em', color: 'var(--ink-1)', margin: blocks.length ? '30px 0 4px' : '0 0 4px', lineHeight: 1.2 },
        2: { fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: '19px', letterSpacing: '-0.01em', color: 'var(--ink-1)', margin: '24px 0 4px', lineHeight: 1.25 },
        3: { fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: '16.5px', letterSpacing: '-0.005em', color: 'var(--ink-1)', margin: '24px 0 6px', lineHeight: 1.3 },
      };
      const sub = { fontFamily: 'var(--font-mono)', fontWeight: 500, fontSize: '12px', letterSpacing: 'var(--tracking-eyebrow)', textTransform: 'uppercase', color: 'var(--accent)', margin: '18px 0 4px' };
      blocks.push(React.createElement(level <= 1 ? 'h3' : level === 2 ? 'h4' : 'h5', { key: key++, style: level >= 4 ? sub : styles[level] }, renderInline(txt, 'h' + key)));
      i++;
      continue;
    }

    if (/^[*-]\s+/.test(trimmed)) {
      const items = [];
      while (i < lines.length && /^[*-]\s+/.test(lines[i].trim())) {
        items.push(lines[i].trim().replace(/^[*-]\s+/, ''));
        i++;
      }
      blocks.push(
        <ul key={key++} style={{ margin: '10px 0 0', paddingLeft: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: '8px' }}>
          {items.map((it, j) => (
            <li key={j} style={{ display: 'flex', gap: '12px', fontFamily: 'var(--font-body)', fontSize: '15.5px', lineHeight: 1.55, color: 'var(--ink-2)' }}>
              <span aria-hidden="true" style={{ color: 'var(--accent)', fontWeight: 700, flex: 'none', lineHeight: 1.55 }}>—</span>
              <span style={{ textWrap: 'pretty' }}>{renderInline(it, 'li' + key + j)}</span>
            </li>
          ))}
        </ul>
      );
      continue;
    }

    // paragraph: gather consecutive non-blank, non-structural lines
    const para = [];
    while (i < lines.length) {
      const l = lines[i];
      const t = l.trim();
      if (!t || /^(#{1,6})\s+/.test(t) || /^[*-]\s+/.test(t)) break;
      para.push(t);
      i++;
    }
    blocks.push(
      <p key={key++} style={{ fontFamily: 'var(--font-body)', fontSize: '15.5px', lineHeight: 1.65, color: 'var(--ink-2)', margin: '12px 0 0', textWrap: 'pretty' }}>
        {renderInline(para.join(' '), 'p' + key)}
      </p>
    );
  }
  return <div>{blocks}</div>;
}

async function loadRoles() {
  // 1) Inlined sources (single-file export) win.
  if (window.__ROLE_SOURCES) {
    const texts = await Promise.all(window.__ROLE_SOURCES.map((u) => fetch(u).then((r) => r.text())));
    return texts.map(parseRole).filter((r) => r.name);
  }
  // 2) Try the backend API (server parses the markdown).
  try {
    const res = await fetch(API_BASE + '/api/roles', { headers: { Accept: 'application/json' } });
    if (res.ok) {
      const data = await res.json();
      const list = Array.isArray(data) ? data : data.roles;
      if (Array.isArray(list) && list.length) return list;
    }
  } catch (e) { /* no backend — fall through to static markdown */ }
  // 3) Static fallback: read the markdown files directly.
  const idx = await fetch('roles/index.json').then((r) => r.json());
  const texts = await Promise.all(idx.map((f) => fetch('roles/' + f).then((r) => r.text())));
  return texts.map(parseRole).filter((r) => r.name);
}

function RoleRow({ role, first, onApply }) {
  const [open, setOpen] = React.useState(false);
  return (
    <div style={{ padding: '24px 28px', borderTop: first ? 'none' : '1px solid var(--border-quiet)' }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: '24px' }}>
        <div style={{ maxWidth: '660px' }}>
          <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: '21px', letterSpacing: '-0.01em', margin: '0 0 6px', color: 'var(--ink-1)' }}>{role.name}</h3>
          <p style={{ fontFamily: 'var(--font-body)', fontSize: '15px', lineHeight: 1.5, color: 'var(--ink-2)', margin: '0 0 8px', textWrap: 'pretty' }}>{role.tagline}</p>
          <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: '12.5px', color: 'var(--ink-3)' }}>{role.location}</span>
            {role.description ? (
              <button type="button" onClick={() => setOpen((v) => !v)}
                style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer', fontFamily: 'var(--font-body)', fontSize: '14px', fontWeight: 600, color: 'var(--accent)' }}>
                {open ? 'Hide role ↑' : 'View full role ↓'}
              </button>
            ) : null}
          </div>
        </div>
        <ButtonC variant="secondary" size="sm" arrow onClick={() => onApply(role.name)}>Apply</ButtonC>
      </div>
      {open && role.description ? (
        <div style={{ marginTop: '20px', paddingTop: '22px', borderTop: '1px dashed var(--border-quiet)', maxWidth: '760px' }}>
          <MarkdownBody md={role.description} />
        </div>
      ) : null}
    </div>
  );
}

// Required file-upload field (CV), styled to match the design system.
function FileField({ label, accept, file, error, hint, onChange }) {
  const ref = React.useRef(null);
  const borderColor = error ? 'var(--maddyie-purple)' : file ? 'var(--accent)' : 'var(--border-quiet)';
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '7px', fontFamily: 'var(--font-body)' }}>
      <label style={{ fontSize: '14px', fontWeight: 600, color: 'var(--ink-1)' }}>{label}</label>
      <div
        onClick={() => ref.current && ref.current.click()}
        style={{
          display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px 10px 10px',
          borderRadius: 'var(--radius-sm)', border: `1px ${file ? 'solid' : 'dashed'} ${borderColor}`,
          background: 'var(--white)', cursor: 'pointer',
        }}
      >
        <span style={{ fontWeight: 600, fontSize: '13.5px', color: 'var(--white)', background: 'var(--accent)', borderRadius: 'var(--radius-full)', padding: '7px 16px', whiteSpace: 'nowrap' }}>Choose file</span>
        <span style={{ fontSize: '14px', color: file ? 'var(--ink-1)' : 'var(--ink-3)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
          {file ? file.name : 'PDF or Word document'}
        </span>
        <input ref={ref} type="file" accept={accept} required
          onChange={(e) => onChange(e.target.files && e.target.files[0])}
          style={{ display: 'none' }} />
      </div>
      {(error || hint) ? <span style={{ fontSize: '13px', color: error ? 'var(--purple-700)' : 'var(--ink-3)' }}>{error || hint}</span> : null}
    </div>
  );
}

function CareersScreen({ go }) {
  const [sent, setSent] = React.useState(false); // false | 'api' | 'mailto'
  const [role, setRole] = React.useState('');
  const [roles, setRoles] = React.useState(null); // null = loading
  const [form, setForm] = React.useState({ name: '', email: '', link: '', cv: null, agree: false, company: '' });
  const [errors, setErrors] = React.useState({});
  const [submitting, setSubmitting] = React.useState(false);
  const [serverError, setServerError] = React.useState('');
  const [captchaToken, setCaptchaToken] = React.useState('');
  const turnstileRef = React.useRef(null);
  const widgetId = React.useRef(null);
  const setField = (key) => (val) => setForm((f) => ({ ...f, [key]: val }));

  // Render the Cloudflare Turnstile widget once its script is ready and the form
  // is on screen. Re-runs when the form reappears after "Submit another".
  React.useEffect(() => {
    if (sent) return; // form not shown
    let poll;
    const render = () => {
      const el = turnstileRef.current;
      if (!window.turnstile || !el || el.dataset.rendered) return;
      el.dataset.rendered = '1';
      widgetId.current = window.turnstile.render(el, {
        sitekey: TURNSTILE_SITE_KEY,
        callback: (tok) => { setCaptchaToken(tok); setErrors((x) => ({ ...x, captcha: undefined })); },
        'expired-callback': () => setCaptchaToken(''),
        'error-callback': () => setCaptchaToken(''),
      });
    };
    if (window.turnstile) render();
    else poll = setInterval(() => { if (window.turnstile) { clearInterval(poll); render(); } }, 200);
    return () => { if (poll) clearInterval(poll); };
  }, [sent]);

  // Turnstile tokens are single-use; reset the widget after a failed submit.
  function resetCaptcha() {
    setCaptchaToken('');
    if (window.turnstile && widgetId.current !== null) {
      try { window.turnstile.reset(widgetId.current); } catch (e) { /* ignore */ }
    }
  }

  React.useEffect(() => {
    let cancelled = false;
    loadRoles()
      .then((r) => { if (!cancelled) { setRoles(r); if (r[0]) setRole(r[0].name); } })
      .catch(() => { if (!cancelled) setRoles([]); });
    return () => { cancelled = true; };
  }, []);

  function apply(roleName) {
    setRole(roleName);
    setErrors((e) => ({ ...e, role: undefined }));
    setSent(false);
    const f = document.getElementById('apply-form');
    if (f) { const y = f.getBoundingClientRect().top + window.scrollY - 100; window.scrollTo({ top: y, behavior: 'smooth' }); }
  }

  // Build the formatted plain-text body shared by API and mailto paths.
  function buildBody() {
    return [
      'New application via maddyielabs.com',
      '',
      'Name:   ' + form.name.trim(),
      'Email:  ' + form.email.trim(),
      'Role:   ' + role,
      'Work:   ' + form.link.trim(),
      'CV:     ' + (form.cv ? form.cv.name : '—'),
      '',
      'Confirmed they have read our hiring approach: yes',
      '',
      '— Sent from the Maddyie Labs careers page',
    ].join('\n');
  }

  function openMailto() {
    const subject = `Application — ${role} — ${form.name.trim()}`;
    const body = buildBody() + '\n\n(Please attach your CV file to this email before sending.)';
    window.location.href = `mailto:${APPLICATION_EMAIL}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
  }

  // Validate every field (all mandatory), then POST to the backend. If the
  // backend is unreachable (static hosting / file export), fall back to mailto.
  async function handleSubmit(e) {
    if (e && e.preventDefault) e.preventDefault();
    setServerError('');
    // Honeypot: a real user never fills this hidden field.
    if (form.company) { setSent('api'); return; }

    const errs = {};
    if (!form.name.trim()) errs.name = 'Please enter your name.';
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(form.email.trim())) errs.email = 'Please enter a valid email address.';
    if (!role) errs.role = 'Please choose a role.';
    if (!form.link.trim()) errs.link = 'Please share a link to something you have built.';
    if (!form.cv) errs.cv = 'Please attach your CV.';
    if (!form.agree) errs.agree = 'Please confirm you have read this.';
    if (!captchaToken) errs.captcha = 'Please complete the verification below.';
    setErrors(errs);
    if (Object.keys(errs).length) return;

    setSubmitting(true);
    try {
      const fd = new FormData();
      fd.append('name', form.name.trim());
      fd.append('email', form.email.trim());
      fd.append('role', role);
      fd.append('link', form.link.trim());
      fd.append('agree', 'yes');
      fd.append('company', form.company); // honeypot, server also checks
      fd.append('cv', form.cv, form.cv.name);
      fd.append('cf-turnstile-response', captchaToken);
      const res = await fetch(API_BASE + '/api/apply', { method: 'POST', body: fd });
      if (!res.ok) {
        let msg = 'Something went wrong sending your application.';
        try { const j = await res.json(); if (j && j.error) msg = j.error; } catch (e2) {}
        throw new Error(msg);
      }
      setSent('api');
    } catch (err) {
      // Turnstile tokens are single-use — reset so a retry gets a fresh one.
      resetCaptcha();
      // No backend reachable -> graceful mailto fallback. A genuine server
      // error (4xx with message) is surfaced instead of silently falling back.
      if (err && /\b(4\d\d|5\d\d)\b/.test(String(err.message)) === false && err.message && err.message !== 'Failed to fetch') {
        // server responded with an explicit error message
        if (err.message.indexOf('went wrong') === -1) { setServerError(err.message); setSubmitting(false); return; }
      }
      openMailto();
      setSent('mailto');
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <div>
      <div style={{ background: 'var(--white)', borderBottom: '1px solid var(--border-quiet)' }}>
        <NavBarC active="Careers" onNavigate={go} markSrc={window.__resources.markPurple} wordmarkSrc={window.__resources.wordBlack} />
      </div>

      {/* Header */}
      <section style={{ background: 'var(--white)', padding: '88px 40px 56px' }}>
        <div style={{ maxWidth: '820px', margin: '0 auto' }}>
          <BadgeC tone="purple" mono>Hiring</BadgeC>
          <h1 style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: '56px', lineHeight: 1.05, letterSpacing: 'var(--tracking-display)', margin: '20px 0 0', color: 'var(--ink-1)', textWrap: 'balance' }}>
            We hire for proof of ability, not just symbols of ability.
          </h1>
          <p style={{ fontFamily: 'var(--font-body)', fontSize: '20px', lineHeight: 1.55, color: 'var(--ink-2)', margin: '24px 0 0', textWrap: 'pretty' }}>
            A high bar is not the same as a narrow gate. We care about what people can build, how they think, how they learn, and whether they can be trusted with hard problems.
          </p>
        </div>
      </section>

      {/* Ethos points */}
      <section style={{ background: 'var(--soft-lilac)', padding: '72px 40px' }}>
        <div style={{ maxWidth: CWc, margin: '0 auto', display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px' }}>
          {[
            ['Demonstrated ability', 'What have you built? What have you learned? We care about the person behind the paper.'],
            ['Learning velocity', 'Some of the best people are self-taught. Curiosity and growth count for a great deal.'],
            ['Judgement & integrity', 'Can you act with ownership, communicate clearly, and persevere when things get hard?'],
          ].map(([t, d]) => (
            <CardC key={t} padding={26} style={{ background: 'var(--white)', border: '1px solid var(--border-quiet)' }}>
              <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: '20px', letterSpacing: '-0.01em', margin: '0 0 8px', color: 'var(--ink-1)' }}>{t}</h3>
              <p style={{ fontFamily: 'var(--font-body)', fontSize: '15px', lineHeight: 1.55, color: 'var(--ink-2)', margin: 0, textWrap: 'pretty' }}>{d}</p>
            </CardC>
          ))}
        </div>
      </section>

      {/* Open roles — loaded from roles/*.md */}
      <section style={{ background: 'var(--white)', padding: '88px 40px' }}>
        <div style={{ maxWidth: CWc, margin: '0 auto' }}>
          <SectionIntroC eyebrow="Open roles" size="2xl" title="Work close to the centre of the company." lead="We are small and founder-led, so every person matters and good ideas can come from anywhere." />
          <div style={{ marginTop: '40px', border: '1px solid var(--border-quiet)', borderRadius: 'var(--radius-md)', overflow: 'hidden' }}>
            {roles === null ? (
              <div style={{ padding: '28px', fontFamily: 'var(--font-mono)', fontSize: '13px', color: 'var(--ink-3)' }}>Loading roles…</div>
            ) : roles.length === 0 ? (
              <div style={{ padding: '28px', fontFamily: 'var(--font-body)', fontSize: '15px', color: 'var(--ink-3)' }}>No open roles right now — but we always read speculative applications.</div>
            ) : (
              roles.map((r, i) => <RoleRow key={r.name + '#' + i} role={r} first={i === 0} onApply={apply} />)
            )}
          </div>
        </div>
      </section>

      {/* Application form */}
      <section style={{ background: 'var(--warm-sand)', padding: '88px 40px' }}>
        <div style={{ maxWidth: '640px', margin: '0 auto' }}>
          <SectionIntroC eyebrow="Apply" size="2xl" align="center" maxWidth={560}
            title={sent ? 'Thank you. We read every application.' : 'Tell us what you have built.'}
            lead={sent === 'mailto'
              ? 'Your email client should have opened with your application ready to send — attach your CV and hit send. We reply to every message, usually within a week.'
              : sent === 'api'
                ? 'We have got your application and your CV. We reply to every message, usually within a week.'
                : 'No cover-letter theatre. Show us the work and how you think. Every field is required.'} />
          {sent ? (
            <div style={{ textAlign: 'center', marginTop: '32px' }}>
              <ButtonC variant="secondary" onClick={() => setSent(false)}>Submit another</ButtonC>
            </div>
          ) : (
            <form id="apply-form" tabIndex={-1} onSubmit={handleSubmit}
              style={{ marginTop: '36px', display: 'flex', flexDirection: 'column', gap: '20px', background: 'var(--white)', border: '1px solid var(--border-quiet)', borderRadius: 'var(--radius-lg)', padding: '32px' }}>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '18px' }}>
                <InputC label="Your name" placeholder="Maddison Frogley" required
                  value={form.name} onChange={(e) => setField('name')(e.target.value)}
                  error={!!errors.name} hint={errors.name} />
                <InputC label="Email" type="email" placeholder="you@example.com" required
                  value={form.email} onChange={(e) => setField('email')(e.target.value)}
                  error={!!errors.email} hint={errors.email} />
              </div>
              <SelectC label="Role" value={role} onChange={(e) => { setRole(e.target.value); setErrors((x) => ({ ...x, role: undefined })); }}
                hint={errors.role}>
                {(roles || []).map((r, i) => <option key={r.name + '#' + i}>{r.name}</option>)}
                <option>Something hard to explain at dinner</option>
              </SelectC>
              <InputC label="Link to something you've built" placeholder="github.com / a demo / a write-up" required
                value={form.link} onChange={(e) => setField('link')(e.target.value)}
                error={!!errors.link}
                hint={errors.link || 'A repo, a project, a thing you fixed. Evidence over credentials.'} />
              <FileField label="Your CV" accept=".pdf,.doc,.docx" file={form.cv}
                error={errors.cv}
                hint={!errors.cv ? 'PDF or Word, up to 5 MB. Sent securely with your application.' : undefined}
                onChange={(file) => setField('cv')(file)} />
              {/* Honeypot — hidden from people, catches bots. */}
              <input type="text" name="company" tabIndex={-1} autoComplete="off" aria-hidden="true"
                value={form.company} onChange={(e) => setField('company')(e.target.value)}
                style={{ position: 'absolute', left: '-9999px', width: '1px', height: '1px', opacity: 0 }} />
              <div>
                <CheckboxC label="I understand Maddyie Labs hires for demonstrated ability, not pedigree."
                  checked={form.agree} onChange={(v) => setField('agree')(v)} />
                {errors.agree ? <div style={{ fontSize: '13px', color: 'var(--purple-700)', marginTop: '6px' }}>{errors.agree}</div> : null}
              </div>
              <div>
                <div ref={turnstileRef} style={{ minHeight: '65px' }} />
                {errors.captcha ? <div style={{ fontSize: '13px', color: 'var(--purple-700)', marginTop: '6px' }}>{errors.captcha}</div> : null}
              </div>
              {serverError ? (
                <div style={{ fontFamily: 'var(--font-body)', fontSize: '14px', color: 'var(--purple-700)', background: 'var(--purple-100)', border: '1px solid var(--purple-200)', borderRadius: 'var(--radius-sm)', padding: '12px 14px' }}>{serverError}</div>
              ) : null}
              <ButtonC variant="primary" arrow disabled={submitting} onClick={handleSubmit} style={{ alignSelf: 'flex-start', marginTop: '4px' }}>
                {submitting ? 'Sending…' : 'Send application'}
              </ButtonC>
            </form>
          )}
        </div>
      </section>

      <FooterC onNavigate={go} markSrc={window.__resources.markWhite} wordmarkSrc={window.__resources.wordWhite} />
    </div>
  );
}

window.CareersScreen = CareersScreen;
