/* global React */
const { useState: useVidState, useRef: useVidRef } = React;

// ─────────────────────────────────────────────────────────────
// VIDEO REVIEW — AI-scored self-tape / performance feedback
// Client extracts sample frames from the uploaded video (no
// video file leaves the browser) and posts them to /api/video-review
// along with the brief/context. Claude returns extensive feedback
// on screen presence, physicality, expression, choices and
// self-tape technique. Second page always offers a human follow-up
// call via Google Meet with one of our agents.
// ─────────────────────────────────────────────────────────────

const VIDEO_API = '/api/video-review';
const VIDEO_MAX_SECONDS = 240; // 4 minutes
const VIDEO_FRAME_COUNT = 8;
const VIDEO_DIRECT_FORMSPREE = 'https://formspree.io/f/xqpzrnoz'; // receives full details + the video file

// Sends the performer's details and the actual video file straight to
// Formspree (multipart), independent of the AI analysis pipeline.
function sendVideoToFormspree({ file, name, email, phone, represented, seekingRep, brief, duration }) {
  if (!VIDEO_DIRECT_FORMSPREE || VIDEO_DIRECT_FORMSPREE.includes('YOUR_FORM_ID')) return Promise.resolve();
  const fd = new FormData();
  fd.append('_subject', `Video Review submission · ${name}`);
  fd.append('_replyto', email);
  fd.append('Name', name);
  fd.append('Email', email);
  fd.append('Phone', phone);
  fd.append('Currently represented', represented === 'yes' ? 'Yes' : 'No');
  fd.append('Seeking representation / wants contact', seekingRep ? 'Yes' : 'No');
  fd.append('Brief / context', brief || '(none provided)');
  fd.append('Video length', duration ? `${Math.round(duration)}s` : '');
  if (file) fd.append('video', file, file.name);
  return fetch(VIDEO_DIRECT_FORMSPREE, { method: 'POST', headers: { Accept: 'application/json' }, body: fd })
    .catch((err) => console.error('Formspree video submit failed:', err));
}

const VIDEO_CATEGORIES = [
  { key: 'screenPresence',   label: 'Screen presence & confidence', max: 20 },
  { key: 'physicality',      label: 'Physicality & movement',       max: 15 },
  { key: 'expression',       label: 'Facial expression & emotional truth', max: 20 },
  { key: 'choices',          label: 'Character & performance choices', max: 20 },
  { key: 'energyPacing',     label: 'Energy, pacing & variation',    max: 15 },
  { key: 'technical',        label: 'Self-tape technical quality',   max: 10 },
];

const VIDEO_SAMPLE = {
  totalScore: 68,
  categories: {
    screenPresence: { score: 14, comment: 'Holds the frame with reasonable confidence. A touch of tension in the shoulders reads through the lens.' },
    physicality:    { score: 10, comment: 'Gesture choices support the text but repeat; vary scale and timing for a fuller physical vocabulary.' },
    expression:     { score: 14, comment: 'Strong eye engagement in close moments. Some transitions between beats feel telegraphed rather than lived.' },
    choices:        { score: 13, comment: 'Clear point of view on the character. Push further into specificity of relationship and stakes.' },
    energyPacing:   { score: 10, comment: 'Energy is consistent but under-varied across the piece; find contrast between beats.' },
    technical:      { score: 7,  comment: 'Framing and eyeline are solid. Lighting is slightly flat and background is mildly distracting.' },
  },
  summary: 'A committed, technically competent tape that shows a clear read of the character. The performance would benefit from more contrast between beats and a more considered visual setup to match the strength of the acting choices.',
  strengths: [
    'Clear, specific point of view on the character from the first line.',
    'Strong eye engagement and stillness in close, intimate moments.',
    'Confident use of the frame — comfortable on camera.',
  ],
  growthAreas: [
    'Beats transition too evenly; more contrast in pace and energy would land the arc.',
    'Gesture vocabulary repeats; vary scale and timing of physical choices.',
    'Lighting is flat and the background pulls focus from the performance.',
  ],
  recommendations: [
    'Re-shoot with a single soft key light and a plain, low-contrast background.',
    'Mark the beats on the page and choose a distinct physical or vocal shift for each.',
    'Run the piece with a wider emotional range in rehearsal, then dial back to the strongest choice.',
    'Slate cleanly at the top with name, role and reel length before the performance begins.',
  ],
};

function guessVideoMime(name) {
  const ext = (name || '').toLowerCase().split('.').pop();
  if (ext === 'mov') return 'video/quicktime';
  if (ext === 'webm') return 'video/webm';
  return 'video/mp4';
}

// Extract N evenly-spaced frames from a video File as base64 JPEG strings.
// The original video never leaves the browser — only these still frames do.
function extractFrames(file, count) {
  return new Promise((resolve, reject) => {
    const url = URL.createObjectURL(file);
    const video = document.createElement('video');
    video.preload = 'metadata';
    video.muted = true;
    video.playsInline = true;
    video.src = url;

    const frames = [];
    let duration = 0;

    video.onloadedmetadata = () => {
      duration = video.duration || 0;
      if (duration > VIDEO_MAX_SECONDS + 1) {
        URL.revokeObjectURL(url);
        reject({ code: 'TOO_LONG', duration });
        return;
      }
      captureNext(0);
    };

    const times = Array.from({ length: count }, (_, i) => (duration * (i + 0.5)) / count);

    function captureNext(i) {
      if (i >= count || !duration) {
        URL.revokeObjectURL(url);
        resolve({ frames, duration });
        return;
      }
      video.currentTime = Math.min(times[i], Math.max(0, duration - 0.05));
    }

    video.onseeked = () => {
      const canvas = document.createElement('canvas');
      const scale = Math.min(1, 640 / (video.videoWidth || 640));
      canvas.width = Math.round((video.videoWidth || 640) * scale);
      canvas.height = Math.round((video.videoHeight || 360) * scale);
      const ctx = canvas.getContext('2d');
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      const dataUrl = canvas.toDataURL('image/jpeg', 0.72);
      frames.push(dataUrl.split(',')[1]);
      captureNext(frames.length);
    };

    video.onerror = () => { URL.revokeObjectURL(url); reject({ code: 'READ_ERROR' }); };
  });
}

function fmtDuration(sec) {
  const m = Math.floor(sec / 60), s = Math.round(sec % 60);
  return `${m}:${String(s).padStart(2, '0')}`;
}

// ── Simple two-option toggle (represented / not) ────────────────
const TogglePair = ({ label, hint, value, onChange, options }) => (
  <div>
    <FieldLabel hint={hint}>{label}</FieldLabel>
    <div style={{ display: 'flex', gap: 12 }}>
      {options.map((o) => {
        const active = value === o.key;
        return (
          <button key={o.key} type="button" onClick={() => onChange(o.key)}
            style={{
              flex: 1, height: 48, border: '1px solid var(--ink)', cursor: 'pointer',
              background: active ? 'var(--ink)' : 'transparent', color: active ? 'var(--paper)' : 'var(--ink)',
              fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 700, letterSpacing: '0.04em',
              transition: 'background 160ms var(--ease-stage), color 160ms var(--ease-stage)',
            }}>
            {o.label}
          </button>
        );
      })}
    </div>
  </div>
);

// ── Score ring (reuses the resume tool's visual language) ───────
const VideoScoreRing = ({ score }) => {
  const r = 84, c = 2 * Math.PI * r;
  const pct = Math.max(0, Math.min(100, score)) / 100;
  return (
    <div style={{ position: 'relative', width: 200, height: 200, flexShrink: 0 }}>
      <svg viewBox="0 0 200 200" style={{ width: '100%', height: '100%', transform: 'rotate(-90deg)' }}>
        <circle cx="100" cy="100" r={r} fill="none" stroke="var(--hairline-ink)" strokeWidth="2" />
        <circle cx="100" cy="100" r={r} fill="none" stroke="var(--spotlight)" strokeWidth="2"
          strokeDasharray={c} strokeDashoffset={c * (1 - pct)}
          style={{ transition: 'stroke-dashoffset 1.2s var(--ease-stage)' }} />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
        <span style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 64, letterSpacing: '-0.03em', lineHeight: 1, color: 'var(--paper)' }}>{score}</span>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-on-ink-2)', letterSpacing: '0.08em' }}>/ 100</span>
      </div>
    </div>
  );
};

// ── Results (page two) ───────────────────────────────────────────
const VideoResults = ({ data, contact, onReset, onRequestCall, callRequested, callSending }) => {
  const cats = data.categories || {};
  const total = data.totalScore != null
    ? data.totalScore
    : VIDEO_CATEGORIES.reduce((s, c) => s + (cats[c.key]?.score || 0), 0);
  const [wantsCall, setWantsCall] = useVidState(false);

  const List = ({ items }) => (
    <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 12 }}>
      {(items || []).map((t, i) => (
        <li key={i} style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
          <span style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 14, color: 'var(--mid)', transform: 'skewX(-12deg)', marginTop: 2 }}>/</span>
          <span style={{ fontSize: 16, lineHeight: 1.55, color: 'var(--ink)' }}>{t}</span>
        </li>
      ))}
    </ul>
  );

  return (
    <div style={{ marginTop: 64 }}>
      {/* AI disclosure banner — always visible, above the score */}
      <div style={{ border: '1px solid var(--ink)', padding: '22px 26px', marginBottom: 40, display: 'flex', gap: 18, alignItems: 'flex-start' }}>
        <span style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 22, color: 'var(--mid)', transform: 'skewX(-12deg)', flexShrink: 0 }}>/</span>
        <p style={{ fontSize: 14.5, lineHeight: 1.6, color: 'var(--ink)', margin: 0, maxWidth: '80ch' }}>
          <strong>This feedback is generated by AI</strong>, not a human agent. It analyses your performance frame-by-frame for screen presence, physicality, expression, choices and self-tape technique. It is a fast, useful first read — not a replacement for a trained eye. Tick the box below and one of our agents will follow up personally over a Google Meet call with real, human feedback.
        </p>
      </div>

      {/* Score card — ink */}
      <div style={{ background: 'var(--ink)', color: 'var(--paper)', padding: '56px 48px', display: 'flex', alignItems: 'center', gap: 56, flexWrap: 'wrap' }}>
        <VideoScoreRing score={total} />
        <div style={{ flex: 1, minWidth: 260 }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-on-ink-2)', letterSpacing: '0.08em', textTransform: 'uppercase', marginBottom: 12 }}>
            AI-generated · performance score
          </div>
          {contact.name && (
            <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(32px, 4vw, 56px)', letterSpacing: '-0.025em', lineHeight: 1, marginBottom: 8 }}>
              {contact.name}
            </div>
          )}
          {contact.email && (
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--fg-on-ink-2)', letterSpacing: '0.04em' }}>
              {contact.email}
            </div>
          )}
        </div>
      </div>

      {/* Category breakdown */}
      <div style={{ padding: '56px 0' }}>
        <Eyebrow style={{ color: 'var(--mid)' }}>Category breakdown</Eyebrow>
        <div style={{ marginTop: 32, borderTop: '1px solid var(--hairline)' }}>
          {VIDEO_CATEGORIES.map((c) => {
            const cat = cats[c.key] || { score: 0, comment: '' };
            const pct = Math.round((cat.score / c.max) * 100);
            return (
              <div key={c.key} style={{ padding: '24px 0', borderBottom: '1px solid var(--hairline)' }}>
                <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 16, marginBottom: 14 }}>
                  <span style={{ fontFamily: 'var(--font-sans)', fontSize: 18, fontWeight: 700, letterSpacing: '-0.01em' }}>{c.label}</span>
                  <span style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 22, letterSpacing: '-0.02em' }}>
                    {cat.score}<span style={{ color: 'var(--mid-soft)', fontSize: 15 }}>/{c.max}</span>
                  </span>
                </div>
                <div style={{ height: 4, background: 'var(--hairline)', position: 'relative', marginBottom: cat.comment ? 14 : 0 }}>
                  <div style={{ position: 'absolute', inset: 0, width: `${pct}%`, background: 'var(--ink)', transition: 'width 1s var(--ease-stage)' }} />
                </div>
                {cat.comment && (
                  <p style={{ fontSize: 15, lineHeight: 1.55, color: 'var(--mid)', margin: 0, maxWidth: '70ch' }}>{cat.comment}</p>
                )}
              </div>
            );
          })}
        </div>
      </div>

      {/* Overall read */}
      {data.summary && (
        <div style={{ padding: '0 0 56px' }}>
          <Eyebrow style={{ color: 'var(--mid)' }}>Overall read</Eyebrow>
          <p style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(24px, 3vw, 36px)', letterSpacing: '-0.02em', lineHeight: 1.15, color: 'var(--ink)', margin: '24px 0 0', textWrap: 'balance', maxWidth: '46ch' }}>
            {data.summary}
          </p>
        </div>
      )}

      {/* Strengths / growth / recommendations */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 0, border: '1px solid var(--hairline)' }}>
        {[
          { h: 'Strengths', items: data.strengths },
          { h: 'Areas for growth', items: data.growthAreas },
          { h: 'Recommended next steps', items: data.recommendations },
        ].map((col, i) => (
          <div key={col.h} style={{ padding: '36px 32px', borderLeft: i === 0 ? '0' : '1px solid var(--hairline)' }}>
            <h4 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 22, letterSpacing: '-0.01em', lineHeight: 1.1, margin: '0 0 24px' }}>{col.h}</h4>
            <List items={col.items} />
          </div>
        ))}
      </div>

      {/* Human follow-up call request */}
      <div style={{ marginTop: 56, border: '1px solid var(--ink)', padding: '40px 36px' }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--mid)', letterSpacing: '0.08em', textTransform: 'uppercase', marginBottom: 14 }}>
          Want real, human feedback?
        </div>
        <p style={{ fontSize: 16, lineHeight: 1.6, color: 'var(--ink)', margin: '0 0 24px', maxWidth: '72ch' }}>
          Every submission is eligible for a follow-up call with one of our agents over Google Meet — a genuine, human review of your tape, your choices and where to take it next. Tick the box below and we'll be in touch to arrange a time.
        </p>
        {callRequested ? (
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--mid)' }}>
            ✓ Request received — we'll email you to arrange a Google Meet call.
          </span>
        ) : (
          <React.Fragment>
            <ConsentCheckbox
              value={wantsCall} onChange={setWantsCall}
              label={<span>Yes — <strong>request a human feedback call</strong> with one of our agents via Google Meet.</span>}
            />
            <div style={{ marginTop: 24 }}>
              <button type="button" disabled={!wantsCall || callSending} onClick={() => onRequestCall()}
                className="cs-btn" style={{ opacity: (!wantsCall || callSending) ? 0.4 : 1, pointerEvents: (!wantsCall || callSending) ? 'none' : 'auto' }}>
                {callSending ? 'Sending…' : 'Request call'} <span style={{ marginLeft: 8 }}>→</span>
              </button>
            </div>
          </React.Fragment>
        )}
      </div>

      <div style={{ marginTop: 40, display: 'flex', gap: 16, alignItems: 'center', flexWrap: 'wrap' }}>
        <Button onClick={(e) => { e.preventDefault(); onReset(); }}>Review another video</Button>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--mid)', letterSpacing: '0.02em', maxWidth: '52ch' }}>
          This is a free, automated first read — not a guarantee of representation. This is a completely free tool, open to every performer.
        </span>
      </div>
    </div>
  );
};

// ── Screen ────────────────────────────────────────────────────
const VideoReviewScreen = ({ navigate }) => {
  const [file, setFile] = useVidState(null);
  const [name, setName] = useVidState('');
  const [email, setEmail] = useVidState('');
  const [phone, setPhone] = useVidState('');
  const [represented, setRepresented] = useVidState(null);
  const [seekingRep, setSeekingRep] = useVidState(false);
  const [brief, setBrief] = useVidState('');
  const [consent, setConsent] = useVidState(false);
  const [status, setStatus] = useVidState('idle'); // idle | reading | analysing | done
  const [result, setResult] = useVidState(null);
  const [error, setError] = useVidState(null);
  const [callRequested, setCallRequested] = useVidState(false);
  const [callSending, setCallSending] = useVidState(false);

  const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());
  const ready = !!file && !!name.trim() && emailValid && !!phone.trim() && represented !== null && consent;

  const reset = () => {
    setFile(null); setName(''); setEmail(''); setPhone(''); setRepresented(null);
    setSeekingRep(false); setBrief(''); setConsent(false);
    setStatus('idle'); setResult(null); setError(null); setCallRequested(false);
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const submit = async (e) => {
    e.preventDefault();
    setError(null);
    if (!name.trim())    return setError('Please enter your name to continue.');
    if (!emailValid)     return setError('Please enter a valid email address to continue.');
    if (!phone.trim())   return setError('Please enter a phone number to continue.');
    if (represented === null) return setError('Please tell us whether you are currently represented.');
    if (!file)           return setError('Please upload your video to continue.');
    if (!consent)        return setError('Please tick the consent box to continue.');

    setStatus('reading');
    try {
      const { frames, duration } = await extractFrames(file.file || file, VIDEO_FRAME_COUNT);
      sendVideoToFormspree({
        file: file.file || file, name: name.trim(), email: email.trim(), phone: phone.trim(),
        represented, seekingRep, brief: brief.trim(), duration,
      });
      setStatus('analysing');
      const res = await fetch(VIDEO_API, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          frames,
          durationSeconds: Math.round(duration),
          brief: brief.trim(),
          name: name.trim(), email: email.trim(), phone: phone.trim(),
          represented: represented === 'yes',
          seekingRepresentation: seekingRep,
          filename: file.name,
        }),
      });
      if (!res.ok) throw new Error('Server responded with ' + res.status);
      const data = await res.json();
      setResult(data);
      setStatus('done');
      window.scrollTo({ top: 0, behavior: 'smooth' });
    } catch (err) {
      console.error(err);
      setStatus('idle');
      if (err && err.code === 'TOO_LONG') {
        setError(`Your video is ${fmtDuration(err.duration)} long. Please upload a video under 4 minutes.`);
      } else {
        setError('We could not reach the review engine. This tool activates once the site is deployed with the review service connected. In the meantime, use “See a sample review” below to preview your results.');
      }
    }
  };

  const showSample = () => {
    setResult(VIDEO_SAMPLE);
    setStatus('done');
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const requestCall = async () => {
    setCallSending(true);
    try {
      await fetch(VIDEO_API, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ type: 'call-request', name, email, phone, represented: represented === 'yes', seekingRepresentation: seekingRep }),
      });
    } catch (err) { /* best effort */ }
    setCallSending(false);
    setCallRequested(true);
  };

  if (status === 'done' && result) {
    return (
      <main data-screen-label="Video Review · Results" style={{ maxWidth: 1100, margin: '0 auto', padding: '56px 48px 0' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 16 }}>
          <Eyebrow style={{ color: 'var(--mid)' }}>Video Review <Slash /> Results</Eyebrow>
          <div style={{ flex: 1, height: 1, background: 'var(--hairline)' }} />
        </div>
        <VideoResults data={result} contact={{ name, email }} onReset={reset}
          onRequestCall={requestCall} callRequested={callRequested} callSending={callSending} />
      </main>
    );
  }

  return (
    <main data-screen-label="Video Review">
      {/* Hero */}
      <section style={{ maxWidth: 1600, margin: '0 auto', padding: '56px 48px 96px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 48 }}>
          <Eyebrow style={{ color: 'var(--mid)' }}>Free tool <Slash /> Open to everyone</Eyebrow>
          <div style={{ flex: 1, height: 1, background: 'var(--hairline)' }} />
          <span className="cs-mono" style={{ color: 'var(--mid)' }}>AI-generated · human follow-up available</span>
        </div>

        <h1 style={{
          fontFamily: 'var(--font-display)', fontWeight: 900,
          fontSize: 'clamp(48px, 8vw, 132px)', letterSpacing: '-0.035em', lineHeight: 0.9,
          margin: 0, color: 'var(--ink)', textWrap: 'balance',
        }}>
          A free read on<br/>your performance.
        </h1>

        <div style={{ marginTop: 56, display: 'grid', gridTemplateColumns: '1.2fr 1fr', gap: 64, alignItems: 'flex-end' }}>
          <p style={{ fontSize: 21, lineHeight: 1.5, color: 'var(--ink)', margin: 0, maxWidth: '54ch' }}>
            Upload a self-tape or audition video and our AI reviews your screen presence, physicality, expression and performance choices — completely free, open to every performer. Every submission can request a genuine, human follow-up call with one of our agents.
          </p>
          <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
            <Button href="#video" onClick={(e) => { e.preventDefault(); document.getElementById('video-upload')?.scrollIntoView({ behavior: 'smooth' }); }}>Upload video · free</Button>
          </div>
        </div>

        <div style={{ marginTop: 40 }}>
          <div style={{ border: '1px solid var(--ink)', padding: '22px 26px', display: 'flex', flexDirection: 'column', gap: 8 }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--mid)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>
              Transparency
            </div>
            <p style={{ fontSize: 14.5, lineHeight: 1.6, color: 'var(--ink)', margin: 0, maxWidth: '80ch' }}>
              This tool's initial feedback is <strong>generated entirely by AI</strong> — it is not written by a human agent. It is a fast, useful first read, not a guarantee or a formal assessment. Every performer can request a genuine human feedback call with one of our agents on the results page, at no cost.
            </p>
          </div>
        </div>
      </section>

      <Hairline />

      {/* How it works */}
      <section style={{ maxWidth: 1600, margin: '0 auto', padding: '120px 48px' }}>
        <SectionHeader eyebrow="The process" />
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 0, border: '1px solid var(--hairline)' }}>
          {[
            { n: '01', t: 'Upload', d: 'Upload a self-tape or performance video under four minutes, with a little context on the brief or scene.' },
            { n: '02', t: 'Analyse', d: 'Our AI reviews your performance for screen presence, physicality, expression, choices and technical quality.' },
            { n: '03', t: 'Request feedback', d: 'Read your extensive AI-generated report, then request a real human feedback call with one of our agents.' },
          ].map((s, i) => (
            <div key={s.n} style={{ padding: '48px 36px', borderLeft: i === 0 ? '0' : '1px solid var(--hairline)', display: 'flex', flexDirection: 'column', gap: 18 }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--mid)', letterSpacing: '0.08em' }}>{s.n} / 03</div>
              <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 36, letterSpacing: '-0.02em', lineHeight: 1, margin: 0 }}>{s.t}</h3>
              <p style={{ fontSize: 15, lineHeight: 1.6, color: 'var(--ink)', margin: 0 }}>{s.d}</p>
            </div>
          ))}
        </div>
      </section>

      {/* What we review — dark band */}
      <section style={{ background: 'var(--ink)', color: 'var(--paper)' }}>
        <div style={{ maxWidth: 1600, margin: '0 auto', padding: '120px 48px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 80, alignItems: 'flex-start' }}>
          <div>
            <Eyebrow style={{ color: 'var(--spotlight)' }}>What we review</Eyebrow>
            <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(40px, 5.5vw, 88px)', letterSpacing: '-0.03em', lineHeight: 0.95, margin: '24px 0 24px', color: 'var(--paper)', textWrap: 'balance' }}>
              Six categories.<br/>One hundred points.
            </h2>
            <p style={{ fontSize: 17, lineHeight: 1.6, color: 'var(--fg-on-ink-2)', margin: 0, maxWidth: '44ch' }}>
              Assessed frame by frame against the standards expected by Australian agents, casting directors and producers. Every score is backed by evidence and a clear path forward.
            </p>
          </div>
          <ul style={{ margin: 0, padding: 0, listStyle: 'none', borderTop: '1px solid var(--hairline-ink)' }}>
            {VIDEO_CATEGORIES.map((c) => (
              <li key={c.key} style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 16, padding: '22px 0', borderBottom: '1px solid var(--hairline-ink)' }}>
                <span style={{ fontFamily: 'var(--font-sans)', fontSize: 18, fontWeight: 700, letterSpacing: '-0.01em', color: 'var(--paper)' }}>{c.label}</span>
                <span style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 28, letterSpacing: '-0.02em', color: 'var(--spotlight)' }}>{c.max}</span>
              </li>
            ))}
          </ul>
        </div>
      </section>

      {/* Upload */}
      <section id="video-upload" style={{ maxWidth: 1100, margin: '0 auto', padding: '120px 48px' }}>
        <div style={{ marginBottom: 40 }}>
          <Eyebrow style={{ color: 'var(--mid)' }}>Upload your video</Eyebrow>
          <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(40px, 6vw, 88px)', letterSpacing: '-0.03em', lineHeight: 0.95, margin: '20px 0 0', textWrap: 'balance' }}>
            Ready when you are.
          </h2>
        </div>

        <div style={{ border: '1px solid var(--ink)', padding: '28px 32px', marginBottom: 48, display: 'flex', flexDirection: 'column', gap: 14 }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--mid)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>
            How to read this feedback
          </div>
          <p style={{ fontSize: 16, lineHeight: 1.6, color: 'var(--ink)', margin: 0, maxWidth: '74ch' }}>
            This initial report is generated entirely by AI, not a human agent. It is a fast, practical first pass on your on-screen performance — not a formal assessment or a guarantee of representation.
          </p>
          <p style={{ fontSize: 16, lineHeight: 1.6, color: 'var(--ink)', margin: 0, maxWidth: '74ch' }}>
            On your results page you can request a genuine human feedback call with one of our agents over Google Meet, at no cost. You do not need to be signed with CentreStage to use this tool.
          </p>
        </div>

        {(status === 'reading' || status === 'analysing') ? (
          <div style={{ border: '1px solid var(--hairline)', padding: '80px 48px', textAlign: 'center' }}>
            <div style={{ display: 'inline-block', width: 40, height: 40, border: '2px solid var(--hairline)', borderTopColor: 'var(--ink)', borderRadius: '50%', animation: 'cs-slash-spin 0.9s linear infinite' }} />
            <p style={{ fontSize: 17, lineHeight: 1.55, color: 'var(--ink)', margin: '28px auto 0', maxWidth: '40ch' }}>
              {status === 'reading' ? 'Reading your video…' : 'Analysing your performance against industry standards. This usually takes about a minute.'}
            </p>
          </div>
        ) : (
          <form onSubmit={submit} noValidate style={{ display: 'flex', flexDirection: 'column', gap: 32 }}>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 28 }}>
              <TextField label="Your name" name="videoName" required placeholder="First and last name" autoComplete="name" value={name} onChange={setName} />
              <TextField label="Your email" name="videoEmail" type="email" required placeholder="you@example.com" autoComplete="email" value={email} onChange={setEmail} />
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 28 }}>
              <TextField label="Phone number" name="videoPhone" type="tel" required placeholder="04XX XXX XXX" autoComplete="tel" value={phone} onChange={setPhone} />
              <TogglePair label="Are you currently represented?" required value={represented}
                onChange={setRepresented}
                options={[{ key: 'yes', label: 'Yes, represented' }, { key: 'no', label: 'No, not represented' }]} />
            </div>

            <ConsentCheckbox
              value={seekingRep} onChange={setSeekingRep}
              label={<span>I am <strong>looking for representation</strong> and would like CentreStage Agency to contact me about it.</span>}
            />

            <div>
              <FieldLabel hint="optional, but helps us give more accurate feedback">Tell us about the brief or character</FieldLabel>
              <textarea
                value={brief} onChange={(e) => setBrief(e.target.value)}
                placeholder="e.g. This is a self-tape for a drama pilot. My character is a defence lawyer in her 30s confronting a client who has just lied to her. The scene is emotionally guarded until the final line."
                rows={5}
                style={{
                  width: '100%', padding: '16px 0', background: 'transparent', border: 0, borderBottom: '1px solid var(--ink)',
                  fontFamily: 'var(--font-sans)', fontSize: 16, lineHeight: 1.5, color: 'var(--ink)', resize: 'vertical', outline: 'none',
                }}
              />
            </div>

            <FileUpload
              label="Your video" name="video" required accept="video/mp4,video/quicktime,video/webm"
              hint="MP4, MOV or WEBM · under 4 minutes"
              value={file} onChange={setFile}
            />

            <div style={{ paddingTop: 8, borderTop: '1px solid var(--hairline)' }}>
              <ConsentCheckbox
                value={consent} onChange={setConsent}
                label={(
                  <span>
                    I consent to my video being analysed by AI for the purpose of providing feedback, and to CentreStage Agency contacting me about my results.{' '}
                    <span style={{ color: 'var(--mid)' }}>Only still frames sampled from your video are analysed — the original file is not stored.</span>
                  </span>
                )}
              />
            </div>

            {error && (
              <div style={{ border: '1px solid var(--ink)', padding: '18px 20px', fontSize: 14, lineHeight: 1.55, color: 'var(--ink)' }}>
                {error}
              </div>
            )}

            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 24, flexWrap: 'wrap' }}>
              <button type="button" onClick={showSample}
                style={{ background: 'transparent', border: 0, padding: 0, cursor: 'pointer', fontFamily: 'var(--font-sans)', fontSize: 12, fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--mid)', textDecoration: 'underline', textUnderlineOffset: 4 }}>
                See a sample review →
              </button>
              <button type="submit" className="cs-btn"
                style={{ opacity: ready ? 1 : 0.4, pointerEvents: ready ? 'auto' : 'none' }}>
                Get my feedback <span style={{ marginLeft: 8 }}>→</span>
              </button>
            </div>
          </form>
        )}
      </section>
    </main>
  );
};

Object.assign(window, { VideoReviewScreen });
