/* global React */
/* ============================================================
   Diagnostic pages
   - AuditLandingPage   /audit
   - AuditFlowPage      /audit/flow
   - AuditResultsPage   /audit/results
   ============================================================ */

const { useState: aState, useEffect: aEffect, useRef: aRef, useMemo: aMemo } = React;

/* ============================================================
   Persistence — answers stored in sessionStorage
   ============================================================ */
const STORE_KEY = 'tdp.audit.v1';
function loadAudit() {
  try {
    const raw = sessionStorage.getItem(STORE_KEY);
    return raw ? JSON.parse(raw) : { answers: {}, contact: null, completedAt: null };
  } catch { return { answers: {}, contact: null, completedAt: null }; }
}
function saveAudit(state) {
  try { sessionStorage.setItem(STORE_KEY, JSON.stringify(state)); } catch {}
}

/* ============================================================
   AUDIT LANDING — the threshold page
   ============================================================ */
function AuditLandingPage() {
  return (
    <div className="page-fade">
      <section style={{
        position: 'relative',
        overflow: 'hidden',
        minHeight: '100vh',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        paddingTop: 140,
        paddingBottom: 80,
      }}>
        <Beam intensity={0.55} from="-4%" width="85%" angle={-9} sweep />

        {/* atmospheric backdrop slot */}
        <ImageSlot tone="cool" showLabel={false}
          src="assets/images/audit-boardroom.jpg"
          style={{
            position: 'absolute', inset: 0,
            opacity: 0.18, aspectRatio: 'auto',
            height: '100%', borderRadius: 0,
          }} />
        <div style={{
          position: 'absolute', inset: 0,
          background: 'radial-gradient(80% 60% at 30% 50%, rgba(10,25,57,0.6) 0%, rgba(10,25,57,0.95) 100%)',
          pointerEvents: 'none',
        }} />

        <div className="container" style={{ position: 'relative', zIndex: 2 }}>
          <div style={{
            display: 'grid',
            gridTemplateColumns: '1.4fr 1fr',
            gap: 96,
            alignItems: 'center',
          }} data-asym="">
            <Reveal>
              <Eyebrow>Executive Authority Signal Audit</Eyebrow>
              <div className="thread-gold" style={{ marginTop: 26, marginBottom: 36 }} />
              <h1 style={{
                fontSize: 'clamp(40px, 5.4vw, 88px)',
                fontWeight: 600,
                lineHeight: 0.98,
                letterSpacing: '-0.035em',
                color: '#fff',
                margin: '0 0 36px',
                textWrap: 'balance',
                maxWidth: '15ch',
              }}>
                A short, deliberate reading of where authority leaks.
              </h1>
              <p style={{
                fontSize: 19,
                color: 'var(--c-steel-100)',
                lineHeight: 1.55,
                fontWeight: 300,
                margin: '0 0 24px',
                maxWidth: '52ch',
              }}>
                Ten questions. Roughly seven minutes. The audit asks how you respond under pressure that has consequence.
              </p>
              <p style={{
                fontSize: 15,
                color: 'var(--c-steel-300)',
                lineHeight: 1.7,
                fontWeight: 300,
                margin: '0 0 48px',
                maxWidth: '52ch',
              }}>
                There is no score. The result is a private reading. One dominant signature of how your authority leaks under load, one secondary, and a short observation on each. The full distribution of all four signatures appears as supporting context, never as a ranking.
              </p>

              <div style={{ display: 'flex', gap: 22, alignItems: 'center', flexWrap: 'wrap', marginBottom: 64 }}>
                <Button variant="primary" href="/audit/flow" size="lg">Begin the audit</Button>
                <Button variant="text" href="/conversation" noIcon>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
                    Or write directly to Daniel
                    <i data-lucide="arrow-right" style={{ width: 12, height: 12 }}></i>
                  </span>
                </Button>
              </div>

              <div style={{
                display: 'flex',
                gap: 48,
                paddingTop: 28,
                borderTop: '1px solid var(--line)',
                flexWrap: 'wrap',
              }}>
                <Spec k="10" l="Questions" />
                <Spec k="≈7" l="Minutes" />
                <Spec k="Private" l="Held in confidence" />
              </div>
            </Reveal>

            <Reveal delay={140}>
              <BlueprintPanel />
            </Reveal>
          </div>
        </div>
      </section>

      <section style={{ background: 'var(--c-nightfall)', padding: 'calc(100px * var(--tdp-density)) 0' }}>
        <div className="container">
          <div style={{
            display: 'grid',
            gridTemplateColumns: '1fr 1.4fr',
            gap: 96,
            alignItems: 'start',
          }} data-asym="">
            <Reveal>
              <Eyebrow>Not what this is</Eyebrow>
              <ul style={{ marginTop: 28, listStyle: 'none', padding: 0, display: 'flex', flexDirection: 'column', gap: 14, color: 'var(--c-steel-300)', fontSize: 15, fontWeight: 300, lineHeight: 1.55 }}>
                <NegItem>Not a personality test.</NegItem>
                <NegItem>Not therapy or journaling.</NegItem>
                <NegItem>Not a leadership self-assessment.</NegItem>
                <NegItem>Not optimised for a score.</NegItem>
              </ul>
            </Reveal>

            <Reveal delay={120}>
              <Eyebrow>What this is</Eyebrow>
              <h2 style={{
                fontSize: 'clamp(28px, 3.2vw, 44px)',
                fontWeight: 500,
                letterSpacing: '-0.025em',
                color: '#fff',
                lineHeight: 1.12,
                margin: '20px 0 24px',
                textWrap: 'balance',
                maxWidth: '26ch',
              }}>
                A structured, psychologically intelligent reading of authority under consequence.
              </h2>
              <p style={{
                fontSize: 16,
                color: 'var(--c-steel-300)',
                lineHeight: 1.7,
                fontWeight: 300,
                maxWidth: '54ch',
                margin: 0,
              }}>
                Each question presents a moment senior leaders actually live in. A board pushing back. A decision being revisited. A room that does not give. There is no right answer. The audit reads the pattern across your answers, not any one of them.
              </p>
            </Reveal>
          </div>
        </div>
      </section>
    </div>
  );
}

function Spec({ k, l }) {
  return (
    <div>
      <div style={{
        fontSize: 28,
        color: '#fff',
        fontWeight: 500,
        letterSpacing: '-0.025em',
        lineHeight: 1,
        fontVariantNumeric: 'tabular-nums',
      }}>{k}</div>
      <div style={{
        fontSize: 10,
        letterSpacing: '0.24em',
        textTransform: 'uppercase',
        color: 'var(--c-slate-ocean)',
        fontWeight: 500,
        marginTop: 8,
      }}>{l}</div>
    </div>
  );
}

function NegItem({ children }) {
  return (
    <li style={{ display: 'flex', alignItems: 'baseline', gap: 14 }}>
      <span style={{
        width: 18, height: 1, background: 'var(--c-slate-ocean)',
        flexShrink: 0, marginTop: 12,
      }} />
      <span>{children}</span>
    </li>
  );
}

/* The visual blueprint panel — gives the landing some atmospheric weight
   without showing the questions */
function BlueprintPanel() {
  return (
    <div style={{
      position: 'relative',
      padding: '48px 40px',
      border: '1px solid var(--line)',
      background: 'rgba(10,25,57,0.4)',
      backdropFilter: 'blur(14px)',
      WebkitBackdropFilter: 'blur(14px)',
    }}>
      <div style={{ position: 'absolute', top: 0, left: 0, width: 56, height: 2, background: 'var(--accent)' }} />
      <Eyebrow style={{ marginBottom: 28 }}>The territory</Eyebrow>

      <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 0 }}>
        {[
          { idx: '01', area: 'Scrutiny response', d: 'How the body answers before the mouth.' },
          { idx: '02', area: 'Over-explanation',  d: 'Where the case stops helping.' },
          { idx: '03', area: 'Pressure pattern',  d: 'The shape of the room when it does not give.' },
          { idx: '04', area: 'Decision trust',    d: 'What happens when your decision is revisited.' },
          { idx: '05', area: 'Composure cost',    d: 'What gets paid privately when nothing slips publicly.' },
        ].map((it) => (
          <li key={it.idx} style={{
            display: 'grid',
            gridTemplateColumns: '40px 1fr',
            padding: '16px 0',
            borderBottom: '1px solid var(--line)',
            alignItems: 'baseline',
            gap: 16,
          }}>
            <Idx>{it.idx}</Idx>
            <div>
              <div style={{ fontSize: 15, fontWeight: 500, color: '#fff', letterSpacing: '-0.008em', marginBottom: 4 }}>
                {it.area}
              </div>
              <div style={{ fontSize: 13, color: 'var(--c-steel-300)', fontWeight: 300, lineHeight: 1.55 }}>
                {it.d}
              </div>
            </div>
          </li>
        ))}
      </ul>
      <div style={{
        marginTop: 20,
        fontSize: 11,
        letterSpacing: '0.2em',
        textTransform: 'uppercase',
        color: 'var(--c-slate-ocean)',
        fontWeight: 500,
      }}>
        and five more
      </div>
    </div>
  );
}

/* ============================================================
   AUDIT FLOW — one question per screen
   ============================================================ */
function AuditFlowPage() {
  const router = useRouter();
  const tw = useTw();
  const pacing = pacingMs(tw.diagnosticPacing || 'measured');

  const [state, setState] = aState(() => loadAudit());

  // Name-gate — required before Q1 so the audit can address them
  // personally and so Daniel has a first name attached to any
  // submitted reading.
  const firstName = (state.contact && state.contact.firstName) || '';
  const [showNameGate, setShowNameGate] = aState(() => !firstName);
  const [pendingName, setPendingName] = aState('');

  // If audit is already complete, route to results so the user doesn't
  // land on Q10 again on revisit.
  aEffect(() => {
    if (state.completedAt && Object.keys(state.answers).length === AUDIT_QUESTIONS.length) {
      router.go('/audit/results');
    }
    // intentionally only run on mount
    // eslint-disable-next-line
  }, []);

  const submitName = (e) => {
    e.preventDefault();
    const name = pendingName.trim();
    if (!name) return;
    const next = {
      ...state,
      contact: { ...(state.contact || {}), firstName: name },
    };
    setState(next);
    saveAudit(next);
    setShowNameGate(false);
  };

  const [step, setStep] = aState(() => {
    const a = loadAudit();
    // resume at first unanswered question
    const answered = Object.keys(a.answers).length;
    return Math.min(answered, AUDIT_QUESTIONS.length - 1);
  });
  const [transitioning, setTransitioning] = aState(false);
  const [direction, setDirection] = aState(1);

  // persist state on every change
  aEffect(() => { saveAudit(state); }, [state]);

  const total = AUDIT_QUESTIONS.length;
  const q = AUDIT_QUESTIONS[step];

  if (showNameGate) {
    return (
      <div className="page-fade">
        <section style={{
          position: 'relative',
          minHeight: '100vh',
          overflow: 'hidden',
          display: 'flex',
          alignItems: 'center',
          paddingTop: 140,
          paddingBottom: 80,
        }}>
          <Beam intensity={0.45} from="-4%" width="70%" angle={-9} sweep />
          <div className="container" style={{ position: 'relative', zIndex: 2 }}>
            <div style={{
              display: 'grid',
              gridTemplateColumns: '1.2fr 1fr',
              gap: 96,
              alignItems: 'center',
            }} data-asym="">
              <Reveal>
                <Eyebrow>Before we begin</Eyebrow>
                <div className="thread-gold" style={{ marginTop: 22, marginBottom: 32 }} />
                <h1 style={{
                  fontSize: 'clamp(36px, 4.6vw, 68px)',
                  fontWeight: 600,
                  lineHeight: 1.02,
                  letterSpacing: '-0.032em',
                  color: '#fff',
                  margin: '0 0 28px',
                  textWrap: 'balance',
                  maxWidth: '18ch',
                }}>
                  What should I call you?
                </h1>
                <p style={{
                  fontSize: 17,
                  color: 'var(--c-steel-300)',
                  lineHeight: 1.65,
                  fontWeight: 300,
                  maxWidth: '46ch',
                  margin: '0 0 20px',
                }}>
                  Your first name is enough. The audit reads better when it speaks to you, not at you.
                </p>
                <p style={{
                  fontSize: 13,
                  color: 'var(--c-slate-ocean)',
                  letterSpacing: '0.04em',
                  lineHeight: 1.6,
                  fontWeight: 300,
                  maxWidth: '46ch',
                  margin: 0,
                }}>
                  Held in confidence. No newsletter. Nothing shared.
                </p>
              </Reveal>

              <Reveal delay={140}>
                <form onSubmit={submitName} style={{
                  border: '1px solid var(--line)',
                  padding: '44px 40px 40px',
                  background: 'rgba(255,255,255,0.012)',
                  display: 'flex', flexDirection: 'column', gap: 32,
                }}>
                  <FormField label="First name" required>
                    <input className="input" autoFocus required value={pendingName}
                           onChange={(e) => setPendingName(e.target.value)}
                           placeholder="Daniel" />
                  </FormField>
                  <div style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    paddingTop: 8,
                    gap: 18,
                  }}>
                    <span style={{
                      fontSize: 11,
                      letterSpacing: '0.22em',
                      textTransform: 'uppercase',
                      color: 'var(--c-slate-ocean)',
                      fontWeight: 500,
                    }}>
                      ≈ 7 minutes · 10 questions
                    </span>
                    <Button variant="primary" type="submit">Begin the audit</Button>
                  </div>
                </form>
              </Reveal>
            </div>
          </div>
        </section>
      </div>
    );
  }

  const selected = state.answers[q.id] || null;

  const answer = (sig) => {
    if (transitioning) return;
    const next = { ...state, answers: { ...state.answers, [q.id]: sig } };
    setState(next);

    setTimeout(() => {
      setTransitioning(true);
      setDirection(1);
      setTimeout(() => {
        if (step < total - 1) {
          setStep(step + 1);
        } else {
          // Done — go to results
          const done = { ...next, completedAt: Date.now() };
          saveAudit(done);
          router.go('/audit/results');
          return;
        }
        setTransitioning(false);
      }, pacing.transition);
    }, pacing.beforeAdvance);
  };

  const goBack = () => {
    if (step === 0 || transitioning) return;
    setDirection(-1);
    setTransitioning(true);
    setTimeout(() => {
      setStep(step - 1);
      setTransitioning(false);
    }, pacing.transition * 0.7);
  };

  return (
    <div className="page-fade">
      <section style={{
        position: 'relative',
        minHeight: '100vh',
        overflow: 'hidden',
        display: 'flex',
        flexDirection: 'column',
        paddingTop: 110,
        paddingBottom: 80,
      }}>
        <Beam intensity={0.35} from={`${(step / total) * 70 - 10}%`} width="60%" angle={-9} drift soft />

        {/* progress header */}
        <div className="container" style={{ position: 'relative', zIndex: 2 }}>
          <ProgressRail step={step} total={total} />
          <span
            aria-live="polite"
            aria-atomic="true"
            style={{
              position: 'absolute',
              left: '-9999px',
              width: 1, height: 1,
              overflow: 'hidden',
            }}>
            Question {step + 1} of {total}. {q.eyebrow}. {q.prompt}
          </span>
        </div>

        {/* question */}
        <div className="container" style={{
          position: 'relative',
          zIndex: 2,
          flex: 1,
          display: 'flex',
          alignItems: 'center',
          paddingTop: 40,
          paddingBottom: 40,
        }}>
          <QuestionCard
            key={q.id}
            q={q}
            selected={selected}
            onSelect={answer}
            transitioning={transitioning}
            direction={direction}
            step={step}
            total={total}
          />
        </div>

        {/* footer bar */}
        <div className="container" style={{ position: 'relative', zIndex: 2 }}>
          <div style={{
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'space-between',
            paddingTop: 24,
            borderTop: '1px solid var(--line)',
            gap: 16,
            flexWrap: 'wrap',
          }}>
            <div style={{ display: 'flex', gap: 24, alignItems: 'center' }}>
              {step > 0 && (
                <button onClick={goBack}
                  style={{
                    color: 'var(--c-steel-300)',
                    fontSize: 11,
                    letterSpacing: '0.22em',
                    textTransform: 'uppercase',
                    fontWeight: 500,
                    background: 'transparent', border: 0, cursor: 'pointer',
                    display: 'inline-flex', alignItems: 'center', gap: 8,
                    padding: '8px 0',
                  }}>
                  <i data-lucide="arrow-left" style={{ width: 14, height: 14 }} />
                  Previous
                </button>
              )}
            </div>
            <div style={{ fontSize: 11, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--c-slate-ocean)', fontWeight: 500 }}>
              Held in confidence
            </div>
            <button onClick={() => { sessionStorage.removeItem(STORE_KEY); router.go('/audit'); }}
              style={{ color: 'var(--c-slate-ocean)', fontSize: 11, letterSpacing: '0.22em', textTransform: 'uppercase', fontWeight: 500, background: 'transparent', border: 0, cursor: 'pointer', padding: '8px 0' }}>
              Restart
            </button>
          </div>
        </div>
      </section>
    </div>
  );
}

function ProgressRail({ step, total }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 24, flexWrap: 'wrap' }}>
      <Eyebrow>The Audit</Eyebrow>
      <div style={{ display: 'flex', gap: 4, flex: 1, minWidth: 240, maxWidth: 520 }}>
        {Array.from({ length: total }).map((_, i) => (
          <div key={i} style={{
            flex: 1, height: 2,
            background: i < step
              ? 'var(--accent)'
              : i === step
                ? 'var(--c-steel-300)'
                : 'var(--line)',
            transition: 'background 480ms var(--ease-out)',
          }} />
        ))}
      </div>
      <span style={{
        fontSize: 11,
        letterSpacing: '0.22em',
        textTransform: 'uppercase',
        color: 'var(--c-slate-ocean)',
        fontWeight: 500,
        fontVariantNumeric: 'tabular-nums',
      }}>
        {String(step + 1).padStart(2, '0')} / {String(total).padStart(2, '0')}
      </span>
    </div>
  );
}

function QuestionCard({ q, selected, onSelect, transitioning, direction, step, total }) {
  const tw = useTw();
  const pacing = pacingMs(tw.diagnosticPacing || 'measured');

  return (
    <div style={{
      width: '100%',
      maxWidth: 1120,
      margin: '0 auto',
      opacity: transitioning ? 0 : 1,
      transform: transitioning ? `translateY(${direction > 0 ? -12 : 12}px)` : 'translateY(0)',
      transition: `opacity ${pacing.transition * 0.7}ms var(--ease-out), transform ${pacing.transition * 0.7}ms var(--ease-out)`,
    }}>
      <div style={{
        display: 'grid',
        gridTemplateColumns: '1fr 1.8fr',
        gap: 80,
        alignItems: 'start',
      }} data-asym="">
        <div style={{ position: 'sticky', top: 120 }}>
          <Idx>{String(step + 1).padStart(2, '0')} / {String(total).padStart(2, '0')}</Idx>
          <div className="thread-gold" style={{ marginTop: 16, marginBottom: 22 }} />
          <Eyebrow style={{ marginBottom: 18 }}>{q.eyebrow}</Eyebrow>
          <p style={{
            fontSize: 12,
            letterSpacing: '0.08em',
            color: 'var(--c-slate-ocean)',
            margin: 0,
            fontWeight: 400,
            maxWidth: '24ch',
            lineHeight: 1.5,
          }}>
            Choose the response closest to the truth, not closest to the answer you would prefer.
          </p>
        </div>

        <div>
          <h2 style={{
            fontSize: 'clamp(28px, 3.3vw, 48px)',
            fontWeight: 500,
            lineHeight: 1.16,
            letterSpacing: '-0.022em',
            color: '#fff',
            margin: '0 0 56px',
            textWrap: 'balance',
            maxWidth: '32ch',
          }}>
            {q.prompt}
          </h2>

          <div style={{ display: 'flex', flexDirection: 'column' }}>
            {q.options.map((opt, i) => (
              <OptionRow key={i}
                idx={String.fromCharCode(65 + i)}
                label={opt.label}
                selected={selected === opt.sig}
                onClick={() => onSelect(opt.sig)}
                hint={selected === opt.sig}
              />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function OptionRow({ idx, label, selected, onClick }) {
  const [hover, setHover] = aState(false);
  return (
    <button
      onClick={onClick}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        textAlign: 'left',
        display: 'grid',
        gridTemplateColumns: '40px 1fr 32px',
        gap: 22,
        alignItems: 'center',
        padding: '26px 4px 26px 4px',
        background: 'transparent',
        border: 0,
        borderBottom: '1px solid var(--line)',
        borderTop: idx === 'A' ? '1px solid var(--line)' : 'none',
        cursor: 'pointer',
        color: 'inherit',
        position: 'relative',
        transition: 'background 240ms var(--ease-out)',
      }}>
      <div style={{
        position: 'absolute', left: 0, top: 0, bottom: 0,
        width: selected ? '100%' : hover ? '60%' : 0,
        background: selected
          ? 'linear-gradient(90deg, rgba(212,169,66,0.12) 0%, rgba(212,169,66,0) 100%)'
          : 'linear-gradient(90deg, rgba(255,255,255,0.03) 0%, rgba(255,255,255,0) 100%)',
        transition: 'width 480ms var(--ease-out)',
        pointerEvents: 'none',
      }} />

      <span style={{
        position: 'relative',
        fontSize: 11,
        letterSpacing: '0.22em',
        color: selected ? 'var(--accent)' : 'var(--c-slate-ocean)',
        fontWeight: 500,
        transition: 'color 240ms',
      }}>{idx}</span>

      <span style={{
        position: 'relative',
        fontSize: 'clamp(16px, 1.3vw, 19px)',
        color: selected ? '#fff' : hover ? 'var(--c-steel-100)' : 'var(--c-steel-300)',
        fontWeight: selected ? 400 : 300,
        lineHeight: 1.5,
        letterSpacing: '-0.005em',
        textWrap: 'balance',
        transition: 'color 240ms',
      }}>{label}</span>

      <span style={{
        position: 'relative',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'flex-end',
        color: selected ? 'var(--accent)' : hover ? 'var(--c-steel-300)' : 'transparent',
        transition: 'color 240ms',
      }}>
        <i data-lucide={selected ? 'check' : 'arrow-right'} style={{ width: 16, height: 16 }} />
      </span>
    </button>
  );
}

/* ============================================================
   AUDIT RESULTS
   ============================================================ */
function AuditResultsPage() {
  const router = useRouter();
  const [state, setState] = aState(() => loadAudit());
  const [email, setEmail] = aState('');
  const [lastName, setLastName] = aState('');
  const [unlocking, setUnlocking] = aState(false);
  const [unlockError, setUnlockError] = aState(null);
  const loadedAt = aMemo(() => Date.now(), []);

  const firstName = (state.contact && state.contact.firstName) || '';
  const unlocked = !!(state.contact && state.contact.email);

  const answered = Object.keys(state.answers).length;
  const result = aMemo(() => answered === AUDIT_QUESTIONS.length ? scoreAudit(state.answers) : null, [state.answers]);

  const unlockReading = (e) => {
    e.preventDefault();
    if (!email.trim() || !lastName.trim() || !result) return;

    setUnlocking(true);
    setUnlockError(null);

    fetch('/api/audit-lead.php', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        firstName,
        lastName: lastName.trim(),
        email: email.trim(),
        primary: result.primary,
        secondary: result.secondary,
        total: result.total,
        primaryCount: result.counts ? result.counts[result.primary] : null,
        website: '',
        ts: loadedAt,
      }),
    })
      .then((res) => res.json())
      .then((data) => {
        setUnlocking(false);
        // Unlock locally regardless of email-send outcome — the reading
        // is already computed client-side and shouldn't be blocked by
        // a transient email issue. Log server errors silently.
        const next = {
          ...state,
          contact: {
            ...(state.contact || {}),
            lastName: lastName.trim(),
            email: email.trim(),
            capturedAt: Date.now(),
          },
        };
        setState(next);
        saveAudit(next);
        if (!data || !data.ok) {
          setUnlockError('Your reading is unlocked below. We had trouble emailing a copy — you can also save this page.');
        }
      })
      .catch(() => {
        setUnlocking(false);
        const next = {
          ...state,
          contact: {
            ...(state.contact || {}),
            lastName: lastName.trim(),
            email: email.trim(),
            capturedAt: Date.now(),
          },
        };
        setState(next);
        saveAudit(next);
        setUnlockError('Your reading is unlocked below. We had trouble emailing a copy — you can also save this page.');
      });
  };

  // Animate reveal
  const [revealStage, setRevealStage] = aState(0);
  aEffect(() => {
    if (!result) return;
    const t1 = setTimeout(() => setRevealStage(1), 200);
    const t2 = setTimeout(() => setRevealStage(2), 800);
    const t3 = setTimeout(() => setRevealStage(3), 1600);
    return () => { clearTimeout(t1); clearTimeout(t2); clearTimeout(t3); };
  }, [result]);

  if (!result) {
    return (
      <div className="page-fade">
        <section style={{ minHeight: '92vh', display: 'flex', alignItems: 'center', paddingTop: 160 }}>
          <div className="container-narrow" style={{ textAlign: 'center' }}>
            <Eyebrow style={{ display: 'inline-block' }}>The audit</Eyebrow>
            <h1 style={{ fontSize: 'clamp(32px, 4vw, 56px)', fontWeight: 500, color: '#fff', margin: '24px 0 32px', letterSpacing: '-0.028em' }}>
              The audit has not been completed.
            </h1>
            <p style={{ fontSize: 17, color: 'var(--c-steel-300)', lineHeight: 1.6, fontWeight: 300, maxWidth: '48ch', margin: '0 auto 40px' }}>
              The reading is generated only after all ten responses. Begin the audit, or resume where you left off.
            </p>
            <Button variant="primary" href="/audit/flow">{answered > 0 ? 'Resume the audit' : 'Begin the audit'}</Button>
          </div>
        </section>
      </div>
    );
  }

  const primary = SIGNATURES[result.primary];
  const secondary = result.secondary ? SIGNATURES[result.secondary] : null;

  if (!unlocked) {
    return (
      <div className="page-fade">
        <section style={{
          position: 'relative',
          minHeight: '100vh',
          overflow: 'hidden',
          display: 'flex',
          alignItems: 'center',
          paddingTop: 140,
          paddingBottom: 80,
        }}>
          <Beam intensity={0.55} from="-4%" width="80%" angle={-9} sweep />
          <ImageSlot tone="cool" showLabel={false}
            src="assets/images/audit-reflection.jpg"
            style={{ position: 'absolute', inset: 0, opacity: 0.18, aspectRatio: 'auto', height: '100%', borderRadius: 0 }} />
          <div style={{
            position: 'absolute', inset: 0,
            background: 'radial-gradient(80% 60% at 30% 50%, rgba(10,25,57,0.6) 0%, rgba(10,25,57,0.95) 100%)',
            pointerEvents: 'none',
          }} />

          <div className="container" style={{ position: 'relative', zIndex: 2 }}>
            <div style={{
              display: 'grid',
              gridTemplateColumns: '1.2fr 1fr',
              gap: 96,
              alignItems: 'center',
            }} data-asym="">
              <Reveal>
                <Eyebrow>The reading is ready</Eyebrow>
                <div className="thread-gold" style={{ marginTop: 22, marginBottom: 32 }} />
                <h1 style={{
                  fontSize: 'clamp(36px, 4.8vw, 72px)',
                  fontWeight: 600,
                  lineHeight: 1.0,
                  letterSpacing: '-0.034em',
                  color: '#fff',
                  margin: '0 0 28px',
                  textWrap: 'balance',
                  maxWidth: '18ch',
                }}>
                  {firstName ? `${firstName}, your reading is ready.` : 'Your reading is ready.'}
                </h1>
                <p style={{
                  fontSize: 18,
                  color: 'var(--c-steel-100)',
                  lineHeight: 1.6,
                  fontWeight: 300,
                  maxWidth: '46ch',
                  margin: '0 0 22px',
                }}>
                  Your full name and email open the reading on this page — and send a copy to your inbox, so it stays with you.
                </p>
                <p style={{
                  fontSize: 14,
                  color: 'var(--c-slate-ocean)',
                  lineHeight: 1.65,
                  fontWeight: 300,
                  maxWidth: '46ch',
                  margin: 0,
                }}>
                  Held in confidence. No newsletter. The reading is for you.
                </p>
              </Reveal>

              <Reveal delay={140}>
                <form onSubmit={unlockReading} style={{
                  border: '1px solid var(--line)',
                  padding: '40px 36px 36px',
                  background: 'rgba(255,255,255,0.012)',
                  display: 'flex', flexDirection: 'column', gap: 28,
                }}>
                  <FormField label="Last name" required>
                    <input className="input" autoFocus required value={lastName}
                           onChange={(e) => setLastName(e.target.value)} />
                  </FormField>
                  <FormField label="Email" required>
                    <input className="input" type="email" required value={email}
                           onChange={(e) => setEmail(e.target.value)} />
                  </FormField>
                  <div style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    paddingTop: 8,
                    gap: 18,
                  }}>
                    <span style={{
                      fontSize: 11,
                      letterSpacing: '0.22em',
                      textTransform: 'uppercase',
                      color: 'var(--c-slate-ocean)',
                      fontWeight: 500,
                    }}>
                      Reveal · send
                    </span>
                    <Button variant="primary" type="submit" disabled={unlocking}>
                      {unlocking ? 'Unlocking…' : 'Reveal the reading'}
                    </Button>
                  </div>
                  {unlockError && (
                    <p style={{ fontSize: 13, color: 'var(--c-rose-400, #f87171)', margin: 0 }}>{unlockError}</p>
                  )}
                </form>
              </Reveal>
            </div>
          </div>
        </section>
      </div>
    );
  }

  return (
    <div className="page-fade">
      {/* Hero — the signature */}
      <section style={{
        position: 'relative',
        overflow: 'hidden',
        paddingTop: 140,
        paddingBottom: 100,
      }}>
        <Beam intensity={0.55} from="-4%" width="80%" angle={-9} sweep />

        <div className="container" style={{ position: 'relative', zIndex: 2 }}>
          <div style={{
            opacity: revealStage >= 1 ? 1 : 0,
            transform: revealStage >= 1 ? 'translateY(0)' : 'translateY(12px)',
            transition: 'all 800ms var(--ease-out)',
          }}>
            <Eyebrow>The reading</Eyebrow>
            <div className="thread-gold" style={{ marginTop: 22, marginBottom: 36 }} />
          </div>

          <div style={{
            opacity: revealStage >= 2 ? 1 : 0,
            transform: revealStage >= 2 ? 'translateY(0)' : 'translateY(16px)',
            transition: 'all 1100ms var(--ease-out)',
          }}>
            <h1 style={{
              fontSize: 'clamp(40px, 6vw, 96px)',
              fontWeight: 600,
              lineHeight: 0.98,
              letterSpacing: '-0.038em',
              color: '#fff',
              margin: '0 0 32px',
              textWrap: 'balance',
              maxWidth: '18ch',
            }}>
              {primary.name}
            </h1>
            <p style={{
              fontSize: 'clamp(20px, 1.8vw, 28px)',
              color: 'var(--c-glow-200)',
              fontWeight: 300,
              fontStyle: 'italic',
              lineHeight: 1.35,
              letterSpacing: '-0.012em',
              maxWidth: '32ch',
              margin: '0 0 56px',
              textWrap: 'balance',
            }}>
              {primary.short}
            </p>
          </div>

          {/* Distribution bars */}
          <div style={{
            opacity: revealStage >= 3 ? 1 : 0,
            transform: revealStage >= 3 ? 'translateY(0)' : 'translateY(20px)',
            transition: 'all 1100ms var(--ease-out)',
          }}>
            <SignatureBars counts={result.counts} primary={result.primary} secondary={result.secondary} />
          </div>
        </div>
      </section>

      {/* Imagery Moment — Reflection */}
      <section style={{
        position: 'relative',
        overflow: 'hidden',
        padding: 'calc(100px * var(--tdp-density)) 0',
        background: 'linear-gradient(180deg, var(--c-nightfall) 0%, rgba(19,23,30,0.8) 100%)',
      }}>
        <Beam intensity={0.2} from="70%" width="60%" angle={-12} drift soft sweep />
        <div className="container" style={{ position: 'relative', zIndex: 2 }}>
          <div style={{
            opacity: revealStage >= 2 ? 1 : 0,
            transform: revealStage >= 2 ? 'translateY(0)' : 'translateY(20px)',
            transition: 'all 1200ms var(--ease-out)',
          }}>
            <div style={{
              display: 'grid',
              gridTemplateColumns: '1.2fr 1fr',
              gap: 80,
              alignItems: 'center',
            }} data-asym="">
              <div>
                <p style={{
                  fontSize: 'clamp(18px, 1.6vw, 24px)',
                  color: 'var(--c-steel-100)',
                  lineHeight: 1.65,
                  fontWeight: 300,
                  margin: '0 0 24px',
                  maxWidth: '45ch',
                }}>
                  The reading reflects a pattern. Not a fixed identity. A habit of authority under pressure.
                </p>
                <p style={{
                  fontSize: 16,
                  color: 'var(--c-steel-300)',
                  lineHeight: 1.65,
                  fontWeight: 300,
                  margin: 0,
                  maxWidth: '45ch',
                }}>
                  The next step is a discovery conversation to explore what shifts are possible.
                </p>
              </div>
              <div>
                <ImageSlot label="introspective · moment of clarity" tone="cool" src="assets/images/audit-reflection.jpg" />
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* Reading */}
      <section style={{ background: 'var(--c-nightfall)', padding: 'calc(120px * var(--tdp-density)) 0' }}>
        <div className="container">
          <div style={{
            display: 'grid',
            gridTemplateColumns: '1fr 1.6fr',
            gap: 96,
            alignItems: 'start',
          }} data-asym="">
            <div style={{ position: 'sticky', top: 120 }}>
              <Eyebrow>Reading</Eyebrow>
              <h2 style={{
                fontSize: 'clamp(28px, 2.6vw, 40px)',
                fontWeight: 500,
                letterSpacing: '-0.024em',
                color: '#fff',
                lineHeight: 1.1,
                margin: '20px 0 0',
                textWrap: 'balance',
                maxWidth: '14ch',
              }}>
                What the pattern says.
              </h2>
            </div>
            <div>
              <ol style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 0 }}>
                {primary.reading.map((line, i) => (
                  <li key={i} style={{
                    padding: '32px 0',
                    borderBottom: i < primary.reading.length - 1 ? '1px solid var(--line)' : 'none',
                    display: 'grid',
                    gridTemplateColumns: '40px 1fr',
                    gap: 20,
                    alignItems: 'baseline',
                  }}>
                    <Idx>{String(i + 1).padStart(2, '0')}</Idx>
                    <p style={{
                      fontSize: 'clamp(17px, 1.4vw, 21px)',
                      color: 'var(--c-steel-100)',
                      lineHeight: 1.6,
                      fontWeight: 300,
                      margin: 0,
                      textWrap: 'pretty',
                    }}>{line}</p>
                  </li>
                ))}
              </ol>

              <div style={{
                marginTop: 56,
                padding: '32px 36px',
                border: '1px solid var(--line)',
                background: 'rgba(212,169,66,0.04)',
              }}>
                <div style={{ display: 'grid', gridTemplateColumns: '120px 1fr', gap: 24, marginBottom: 20, alignItems: 'baseline' }}>
                  <Eyebrow>Pattern</Eyebrow>
                  <div style={{ fontSize: 17, color: '#fff', fontWeight: 400, letterSpacing: '-0.01em' }}>{primary.pattern}</div>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: '120px 1fr', gap: 24, marginBottom: 20, alignItems: 'baseline' }}>
                  <Eyebrow>Cost</Eyebrow>
                  <div style={{ fontSize: 17, color: '#fff', fontWeight: 400, lineHeight: 1.5, letterSpacing: '-0.005em' }}>{primary.cost}</div>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: '120px 1fr', gap: 24, alignItems: 'baseline' }}>
                  <Eyebrow>Work</Eyebrow>
                  <div style={{ fontSize: 17, color: 'var(--c-glow-200)', fontStyle: 'italic', fontWeight: 300, lineHeight: 1.5, letterSpacing: '-0.005em' }}>{primary.work}</div>
                </div>
              </div>

              {/* Secondary */}
              {secondary && (
                <div style={{ marginTop: 80 }}>
                  <Eyebrow>Secondary signature</Eyebrow>
                  <h3 style={{
                    fontSize: 'clamp(22px, 1.9vw, 30px)',
                    fontWeight: 500,
                    color: '#fff',
                    letterSpacing: '-0.018em',
                    margin: '14px 0 16px',
                    textWrap: 'balance',
                  }}>
                    {secondary.name}
                  </h3>
                  <p style={{
                    fontSize: 16,
                    color: 'var(--c-steel-300)',
                    lineHeight: 1.65,
                    fontWeight: 300,
                    margin: 0,
                    maxWidth: '54ch',
                  }}>
                    {secondary.short} It does not run the room as your primary signature does. It surfaces in moments of greater consequence.
                  </p>
                </div>
              )}
            </div>
          </div>
        </div>
      </section>

      {/* Conversion */}
      <section style={{ position: 'relative', overflow: 'hidden', padding: 'calc(140px * var(--tdp-density)) 0 calc(140px * var(--tdp-density))' }}>
        <Beam intensity={0.35} from="-10%" width="90%" angle={-7} drift soft sweep />

        <div className="container" style={{ position: 'relative', zIndex: 2 }}>
          <div style={{
            display: 'grid',
            gridTemplateColumns: '1.1fr 1fr',
            gap: 96,
            alignItems: 'center',
          }} data-asym="">
            <div>
              <Eyebrow>The next step</Eyebrow>
              <h2 style={{
                fontSize: 'clamp(34px, 4vw, 64px)',
                fontWeight: 500,
                lineHeight: 1.04,
                letterSpacing: '-0.028em',
                color: '#fff',
                margin: '20px 0 28px',
                textWrap: 'balance',
                maxWidth: '20ch',
              }}>
                A reading is useful. A conversation is structural.
              </h2>
              <p style={{
                fontSize: 17,
                color: 'var(--c-steel-300)',
                lineHeight: 1.65,
                fontWeight: 300,
                maxWidth: '50ch',
                margin: '0 0 36px',
              }}>
                If the reading recognises something, that is the indication that the underlying structure is correctable. A short, private conversation is the next deliberate step.
              </p>
              <Button variant="primary" href="/conversation" size="lg">Request the conversation</Button>
              <div style={{ marginTop: 20 }}>
                <Button variant="text" onClick={() => { sessionStorage.removeItem(STORE_KEY); router.go('/audit'); }}>Retake the audit</Button>
              </div>
            </div>

            <div style={{ border: '1px solid var(--line)', padding: '40px 36px', background: 'rgba(212,169,66,0.04)' }}>
              <Eyebrow>A copy is in your inbox</Eyebrow>
              <p style={{ fontSize: 17, color: '#fff', fontWeight: 300, lineHeight: 1.55, margin: '20px 0 18px', maxWidth: '40ch' }}>
                The reading you are looking at has been sent to {(state.contact && state.contact.email) || 'your email'}. It will keep, and it will not be sent to anyone else.
              </p>
              <p style={{ fontSize: 14, color: 'var(--c-steel-300)', fontWeight: 300, lineHeight: 1.6, margin: 0, maxWidth: '40ch' }}>
                When you are ready, the next step is a private conversation. No timeline pressure.
              </p>
            </div>
          </div>
        </div>
      </section>
    </div>
  );
}

function SignatureBars({ counts, primary, secondary }) {
  const labels = { E: 'Explanation', C: 'Composure', D: 'Deflection', R: 'Recovery' };
  const total = Object.values(counts).reduce((a, b) => a + b, 0) || 1;
  const max = Math.max(...Object.values(counts), 1);
  const order = Object.entries(counts).sort((a, b) => b[1] - a[1]);
  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: 'repeat(4, 1fr)',
      gap: 24,
      maxWidth: 760,
      paddingTop: 28,
      borderTop: '1px solid var(--line)',
    }} data-asym="">
      {order.map(([sig, n]) => {
        const isPrimary = sig === primary;
        const isSecondary = sig === secondary;
        return (
          <div key={sig}>
            <div style={{
              fontSize: 10,
              letterSpacing: '0.24em',
              textTransform: 'uppercase',
              color: isPrimary ? 'var(--accent)' : 'var(--c-slate-ocean)',
              fontWeight: 500,
              marginBottom: 10,
            }}>
              {isPrimary ? 'Primary · ' : isSecondary ? 'Secondary · ' : ''}{labels[sig]}
            </div>
            <div style={{
              height: 3,
              background: 'var(--line)',
              position: 'relative',
              marginBottom: 10,
            }}>
              <div style={{
                position: 'absolute', left: 0, top: 0, bottom: 0,
                width: `${(n / max) * 100}%`,
                background: isPrimary
                  ? 'var(--accent)'
                  : isSecondary
                    ? 'var(--c-glow-deep)'
                    : 'var(--c-slate-ocean)',
                transition: 'width 1200ms var(--ease-out)',
              }} />
            </div>
            <div style={{
              fontSize: 22,
              fontWeight: 500,
              color: isPrimary ? '#fff' : 'var(--c-steel-300)',
              letterSpacing: '-0.02em',
              fontVariantNumeric: 'tabular-nums',
            }}>
              {n}<span style={{ fontSize: 12, color: 'var(--c-slate-ocean)', letterSpacing: '0.04em', fontWeight: 400 }}> / {total}</span>
            </div>
          </div>
        );
      })}
    </div>
  );
}

Object.assign(window, { AuditLandingPage, AuditFlowPage, AuditResultsPage });
