/* ================================================
   vairee-demo-v5 — app.jsx
   Landing: peek L/R. Commit via edges. Lock path. Nav switches.
   Shareable routes: /talent  /hiring  (/) = intro
   ================================================ */
const { useState, useEffect, useMemo, useRef } = React;

const VALID_PATHS = new Set(['talent', 'hiring']);

function pathFromUrl() {
  const slug = window.location.pathname.replace(/\/+$/, '').split('/').filter(Boolean).pop();
  if (slug === 'talent' || slug === 'hiring') return slug;
  const q = new URLSearchParams(window.location.search).get('path');
  if (q === 'talent' || q === 'hiring') return q;
  return null;
}

function urlForPath(path) {
  if (path === 'talent') return '/talent';
  if (path === 'hiring') return '/hiring';
  return '/';
}

function pageTitle(path) {
  if (path === 'talent') return 'vairee — for professionals at work';
  if (path === 'hiring') return 'vairee — for hiring teams';
  return 'vairee — working while you sleep';
}

function fmtBerlin() {
  return new Intl.DateTimeFormat('en-GB', {
    timeZone: 'Europe/Berlin',
    hour: '2-digit', minute: '2-digit', hour12: false,
  }).format(new Date());
}

function berlinMinutesNow() {
  const parts = new Intl.DateTimeFormat('en-GB', {
    timeZone: 'Europe/Berlin',
    hour: 'numeric',
    minute: 'numeric',
    hour12: false,
  }).formatToParts(new Date());
  const h = Number(parts.find((p) => p.type === 'hour').value);
  const m = Number(parts.find((p) => p.type === 'minute').value);
  return h * 60 + m;
}

function berlinActivity() {
  const t = berlinMinutesNow();
  if (t >= 6 * 60 + 30 && t < 7 * 60) return 'preparing the kids for school and having breakfast';
  if (t >= 7 * 60 && t < 7 * 60 + 30) return 'taking the kids to school';
  if (t >= 7 * 60 + 30 && t < 8 * 60) return 'traveling to work';
  if (t >= 8 * 60 && t < 16 * 60) return 'at work';
  if (t >= 16 * 60 && t < 16 * 60 + 30) return 'on her way home';
  if (t >= 16 * 60 + 30 && t < 17 * 60) return 'at home, unwinding';
  if (t >= 17 * 60 && t < 18 * 60) return 'shopping and cooking';
  if (t >= 18 * 60 && t < 19 * 60) return 'at home';
  if (t >= 19 * 60 && t < 20 * 60) return 'spending time with her family';
  if (t >= 20 * 60 && t < 22 * 60) return 'watching a movie with her husband';
  if (t >= 22 * 60 && t < 22 * 60 + 30) return 'preparing for bed';
  if (t >= 22 * 60 + 30 && t < 23 * 60) return 'winding down';
  if (t >= 23 * 60 || t < 6 * 60 + 30) return 'sleeping';
  return 'at home';
}

function useMedia(query) {
  const [matches, setMatches] = useState(() =>
    typeof window !== 'undefined' ? window.matchMedia(query).matches : false
  );
  useEffect(() => {
    const mq = window.matchMedia(query);
    const onChange = () => setMatches(mq.matches);
    onChange();
    mq.addEventListener('change', onChange);
    return () => mq.removeEventListener('change', onChange);
  }, [query]);
  return matches;
}

function scrollToPathStory() {
  const el = document.getElementById('path-story');
  if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
}

function NavPathBar({ path, onPath }) {
  if (!path) return null;
  const label = path === 'hiring'
    ? <>Switch to talent <span className="arrow">→</span></>
    : <><span className="arrow">←</span> Switch to hiring</>;
  const next = path === 'hiring' ? 'talent' : 'hiring';
  return (
    <div className="nav-path-bar">
      <button type="button" onClick={() => onPath(next)} aria-label={`Switch to ${next}`}>
        {label}
      </button>
    </div>
  );
}

function Nav({ path, onPath, onModal }) {
  const [scrolled, setScrolled] = useState(0);
  useEffect(() => {
    const onScroll = () => {
      const max = document.body.scrollHeight - window.innerHeight;
      setScrolled(max > 0 ? window.scrollY / max : 0);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  const goIntro = (e) => {
    e.preventDefault();
    onPath(null);
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const switchPath = (next) => {
    onPath(next);
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  return (
    <>
      <nav className={`nav${path === 'hiring' ? ' nav-on-light' : ''}`}>
        <a className="wordmark" href="/" onClick={goIntro}>vairee</a>
        <div className="nav-right">
          {path === 'hiring' && (
            <button type="button" className="nav-path-switch" onClick={() => switchPath('talent')}>
              For talent <span className="arrow">→</span>
            </button>
          )}
          {path === 'talent' && (
            <button type="button" className="nav-path-switch" onClick={() => switchPath('hiring')}>
              <span className="arrow">←</span> For hiring
            </button>
          )}
          <a className="nav-access" href="#" onClick={(e) => { e.preventDefault(); onModal(); }}>
            <span className="nav-access-short">BUILD</span>
            <span className="nav-access-long">BUILD MY VAIREE</span>
          </a>
        </div>
      </nav>
      <NavPathBar path={path} onPath={(p) => { onPath(p); window.scrollTo({ top: 0, behavior: 'smooth' }); }} />
      <div className="scroll-track">
        <div className="scroll-fill" style={{ width: `${scrolled * 100}%` }}></div>
        <div className="scroll-dot" style={{ left: `${scrolled * 100}%` }}></div>
      </div>
    </>
  );
}

function Particles({ count }) {
  const isMobile = useMedia('(max-width: 760px)');
  const reduced = useMedia('(prefers-reduced-motion: reduce)');
  const n = reduced ? 0 : (count ?? (isMobile ? 12 : 32));
  const items = useMemo(() => {
    const a = [];
    for (let i = 0; i < n; i++) {
      a.push({
        left:  (Math.random() * 100).toFixed(2) + '%',
        dur:   (16 + Math.random() * 22).toFixed(1) + 's',
        delay: (-Math.random() * 30).toFixed(1) + 's',
        dx:    ((Math.random() - 0.5) * 80).toFixed(0) + 'px',
        op:    (0.25 + Math.random() * 0.45).toFixed(2),
        lg:    Math.random() > 0.8,
      });
    }
    return a;
  }, [n]);
  if (!n) return null;
  return (
    <div className="particles" aria-hidden="true">
      {items.map((p, i) => (
        <span key={i} className={`particle${p.lg ? ' lg' : ''}`}
          style={{ left: p.left, '--dur': p.dur, '--delay': p.delay, '--dx': p.dx, '--op': p.op }} />
      ))}
    </div>
  );
}

function Pings() {
  const isMobile = useMedia('(max-width: 760px)');
  const reduced = useMedia('(prefers-reduced-motion: reduce)');
  if (isMobile || reduced) return null;
  return (
    <div className="pings" aria-hidden="true">
      <span className="ping p1"></span>
      <span className="ping p2"></span>
      <span className="ping p3"></span>
      <span className="ping p4"></span>
    </div>
  );
}

function TwinCard({ id="0028", cls="A", role="Senior product designer",
                    city="Berlin · DE", years="6y", avail="Passive only", state="Sleeping" }) {
  const isLive = state === 'Matched' || state === 'Active';
  return (
    <div className="card-content">
      <span className="card-corner tl"></span>
      <span className="card-corner tr"></span>
      <span className="card-corner bl"></span>
      <span className="card-corner br"></span>
      <div className="card-ticks top">
        {Array.from({ length: 9 }).map((_, i) => <span key={i}></span>)}
      </div>
      <div className="card-ticks bottom">
        {Array.from({ length: 9 }).map((_, i) => <span key={i}></span>)}
      </div>
      <div style={{ display:'flex', justifyContent:'space-between', marginBottom:0 }}>
        <div className="card-tl"><span className="v">vairee</span></div>
        <div className="card-tr"><span>{id}</span><span className="cls">{cls}</span></div>
      </div>
      <div className="card-void">
        <div className="void-id-block">
          <span className="void-label">identity</span>
          <span className="void-hash">████████ ████</span>
          <span className="void-sub">redacted until handshake</span>
        </div>
        <svg className="void-wave" viewBox="0 0 200 24" preserveAspectRatio="none">
          <path d="M 0 12 Q 10 4, 20 12 T 40 12 T 60 12 Q 74 4, 88 12 T 112 12 Q 124 18, 138 12 T 164 12 T 200 12"
            fill="none" stroke="rgba(236,227,210,0.22)" strokeWidth="1" strokeLinecap="round"/>
        </svg>
      </div>
      <div className="card-data">
        <div className="row"><span className="k">Role</span><span className="v">{role}</span></div>
        <div className="row"><span className="k">Location</span><span className="v">{city}</span></div>
        <div className="row"><span className="k">Experience</span><span className="v">{years}</span></div>
        <div className="row"><span className="k">Availability</span><span className="v">{avail}</span></div>
      </div>
      <div className="card-foot">
        <span className="state">
          <span className={`state-dot${isLive ? ' is-live' : ''}`}></span>
          {state}
        </span>
        <span className="action">↗</span>
      </div>
    </div>
  );
}

function CaseCard() {
  return (
    <div className="stack">
      <div className="card card-single">
        <TwinCard />
      </div>
    </div>
  );
}

function HiringPanel({ panelRef, locked, onModal }) {
  return (
    <div ref={panelRef} className={`panel panel-left${locked ? ' is-locked' : ''}`}>
      <div className="panel-mark"><span className="num">01</span> For hiring</div>
      <h2 className="panel-h">I am <span>hiring</span>.</h2>
      <p className="panel-body panel-body-wide">
        Most of the best people aren't on job boards — they're at work. With vairee you only
        meet candidates who already chose you — and whose skills are already proven.
      </p>
      <p className="panel-body panel-body-wide">
        <em className="panel-hi panel-hi--ink">First build your vairee</em>. Define who you are as a
        leader, your team culture, and what truly matters. Then let your vairee do the work. It
        actively meets candidate vairees in vairee space,{' '}
        <em className="panel-hi panel-hi--ink">holds real conversations</em>, verifies skills through
        proven credentials, and only brings you matches where both sides already said yes.
      </p>
      <button type="button" className="panel-cta" onClick={onModal}>
        Start here <span className="arrow">→</span>
      </button>
      {locked && (
        <button type="button" className="panel-scroll-hint" onClick={scrollToPathStory}>
          Scroll for more ↓
        </button>
      )}
    </div>
  );
}

function TalentPanel({ panelRef, locked, jobSeeking, onJobSeeking, onPath, onModal }) {
  const [hoverSeek, setHoverSeek] = useState(false);
  const headlineWord = jobSeeking
    ? 'actively looking'
    : hoverSeek
      ? 'job seeking?'
      : 'working';

  const activateSeeking = (e) => {
    e.stopPropagation();
    onJobSeeking(true);
    if (!locked) onPath('talent');
  };

  return (
    <div ref={panelRef} className={`panel panel-right${locked ? ' is-locked' : ''}${jobSeeking ? ' panel-seeking' : ''}`}>
      <div className="panel-mark"><span className="num">02</span> For professionals</div>
      <h2 className={`panel-h${jobSeeking ? ' panel-h--seeking' : ''}`}>
        <span className="panel-h-lead">I am</span>
        {jobSeeking ? (
          <span className="panel-h-phrase" aria-label="actively looking">
            <span className="panel-h-line">actively</span>
            <span className="panel-h-line">looking</span>
          </span>
        ) : (
          <button
            type="button"
            className={`panel-h-toggle${hoverSeek ? ' is-hint' : ''}`}
            onMouseEnter={() => setHoverSeek(true)}
            onMouseLeave={() => setHoverSeek(false)}
            onFocus={() => setHoverSeek(true)}
            onBlur={() => setHoverSeek(false)}
            onClick={activateSeeking}
            aria-label="Hover to see job seeking, click to switch"
          >
            {headlineWord}
          </button>
        )}
        <span className="panel-h-dot" aria-hidden="true">.</span>
      </h2>
      <p className="panel-body panel-body-wide">
        {jobSeeking ? (
          <>
            I want to move forward — but I refuse to waste time on noise.
            {' '}Build your vairee once. Then let it hunt for you.
            {' '}
            <em className="panel-hi">Your vairee is active 24/7</em>, holds real conversations with
            hiring vairees, filters out 95% of bad fits, and only brings you high-quality opportunities
            worth your time.
          </>
        ) : (
          <>
            Not looking. Not applying. Just quietly open to the right thing.
            {' '}Build your vairee once. Then work. Live. Sleep. Repeat.
            {' '}
            <em className="panel-hi">Your vairee represents you 24/7</em>, holds real conversations, and only
            informs you when an opportunity actually matches what you'd turn your head for.
          </>
        )}
      </p>
      <p className="panel-body-foot">
        <strong>Talent never pays. <em className="panel-ever">Ever.</em></strong>
      </p>
      <button type="button" className="panel-cta panel-cta-ghost" onClick={onModal}>
        Build my vairee <span className="arrow">→</span>
      </button>
      {locked && (
        <button type="button" className="panel-scroll-hint" onClick={scrollToPathStory}>
          Scroll for more ↓
        </button>
      )}
    </div>
  );
}

function PricingMoreLink({ onModal }) {
  const [open, setOpen] = useState(false);
  const close = () => setOpen(false);

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') close(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [open]);

  return (
    <>
      <span className="ed-pricing-more">
        <button
          type="button"
          className={`ed-more-trigger${open ? ' is-open' : ''}`}
          aria-expanded={open}
          aria-haspopup="dialog"
          aria-controls="pricing-pop-title"
          onClick={(e) => {
            e.stopPropagation();
            setOpen((v) => !v);
          }}
        >
          more here
        </button>
      </span>
      {open && ReactDOM.createPortal(
        <PricingPopover onClose={close} onModal={onModal} />,
        document.body,
      )}
    </>
  );
}

function PricingPopover({ onClose, onModal }) {
  const boxRef = useRef(null);

  useEffect(() => {
    document.body.classList.add('pricing-pop-open');
    const prev = document.activeElement;
    const t = setTimeout(() => boxRef.current?.focus(), 0);
    return () => {
      clearTimeout(t);
      document.body.classList.remove('pricing-pop-open');
      if (prev && typeof prev.focus === 'function') prev.focus();
    };
  }, []);

  const usPlatforms = [
    ['LinkedIn', '$300 – $1,000'],
    ['Indeed', '$150 – $500+'],
    ['ZipRecruiter', '$299 – $519'],
    ['Glassdoor', '$190 – $400'],
    ['Monster', '$249 – $399'],
  ];
  const czPlatforms = [
    ['LinkedIn', '4,000 – 15,000+ CZK'],
    ['Indeed', '3,000 – 12,000 CZK'],
    ['Jobs.cz', '2,070 – 9,990 CZK'],
    ['Prace.cz', '2,990 – 9,690 CZK'],
    ['JenPráce.cz / Profesia.cz', '1,500 – 6,000 CZK'],
  ];

  return (
    <div className="pricing-pop-overlay open" onClick={onClose} role="presentation">
      <div
        ref={boxRef}
        className="pricing-pop-box"
        role="dialog"
        aria-modal="true"
        aria-labelledby="pricing-pop-title"
        tabIndex={-1}
        onClick={(e) => e.stopPropagation()}
      >
        <button type="button" className="pricing-pop-close" onClick={onClose} aria-label="Close">×</button>
        <p className="pricing-pop-eyebrow">For hiring managers</p>
        <h2 id="pricing-pop-title" className="pricing-pop-title">How vairee pricing works</h2>

        <div className="pricing-pop-block">
          <h3 className="pricing-pop-h">Core model</h3>
          <ul className="pricing-pop-list">
            <li><strong>199 EUR / month</strong> — per active vairee-job<br /><span className="pricing-pop-note">Your virtual hiring manager stays live and working 24/7</span></li>
            <li><strong>1,999 EUR success fee</strong> — only if you hire through vairee<br /><span className="pricing-pop-note">60–75% of typical internal referral bonus (companies usually pay 3,000–5,000 EUR)</span></li>
          </ul>
          <p className="pricing-pop-p"><strong>Important:</strong> Paid only after probation (max 3 months). Success fee applies if hired later (typically within 24 months of first contact). No subscriptions or hidden fees. Pause or archive your vairee-job anytime.</p>
          <p className="pricing-pop-p">Small monthly fee while your twin works. One reasonable success fee when you actually hire.</p>
        </div>

        <div className="pricing-pop-block">
          <h3 className="pricing-pop-h">Real cost comparison (2026)</h3>
          <p className="pricing-pop-region">United States — mid-market / tech role</p>
          <table className="pricing-pop-table">
            <thead><tr><th>Platform</th><th>Typical monthly</th></tr></thead>
            <tbody>{usPlatforms.map(([n, c]) => <tr key={n}><td>{n}</td><td>{c}</td></tr>)}</tbody>
          </table>
          <p className="pricing-pop-p">Total across 5 platforms: <strong>$1,200 – $6,000+ / month</strong>. Annual: <strong>$15,000 – $40,000+</strong> before recruiter time or bad hires.</p>

          <p className="pricing-pop-region">Czech Republic (CZK, excl. VAT)</p>
          <table className="pricing-pop-table">
            <thead><tr><th>Platform</th><th>Typical monthly</th></tr></thead>
            <tbody>{czPlatforms.map(([n, c]) => <tr key={n}><td>{n}</td><td>{c}</td></tr>)}</tbody>
          </table>
          <p className="pricing-pop-p">Total across 5 platforms: <strong>12,000 – 80,000+ CZK / month</strong>. Annual: <strong>300,000 – 800,000+ CZK</strong> per role.</p>
        </div>

        <div className="pricing-pop-block pricing-pop-why">
          <p className="pricing-pop-p">Instead of spraying money across job boards, you create one vairee. Your vairee-job enters vairee space and talks to candidate twins 24/7. No wasted ad budgets. No keyword games. You only meet people who already said yes — with proven skills.</p>
          <p className="pricing-pop-tagline">The old model dies. Your twin works while you sleep.</p>
        </div>

        <div className="pricing-pop-actions">
          <button type="button" className="btn-text" onClick={onClose}>Close</button>
          <button
            type="button"
            className="panel-cta"
            onClick={() => { onClose(); onModal?.(); }}
          >
            Start here <span className="arrow">→</span>
          </button>
        </div>
      </div>
    </div>
  );
}

function HiringStory({ onModal }) {
  const specs = [
    { dt: 'Pool', dd: 'Passive professionals' },
    { dt: 'Screening', dd: 'Conversations, not keywords' },
    {
      dt: 'Pricing',
      dd: <>Low compared to market standard <PricingMoreLink onModal={onModal} /></>,
    },
    { dt: 'Risk', dd: 'None' },
  ];

  const steps = [
    {
      num: 'i.',
      title: <>Post a <em className="ed-em">vairee-job</em>.</>,
      body: 'Describe the role and what “worth waking someone up for” means. No public listing needed. No inbox of irrelevant CVs.',
    },
    {
      num: 'ii.',
      title: <>Twins talk <em className="ed-em">first</em>.</>,
      body: 'Their vairee and yours have a real conversation — fit, intent, timing — before any name or calendar invite.',
    },
    {
      num: 'iii.',
      title: <>Meet people who already said <em className="ed-em">yes</em>.</>,
      body: 'Identity stays hidden until they opt in. You only spend time on matches. Every conversation is high-signal.',
    },
    {
      num: 'iv.',
      title: <>Pay on <em className="ed-em">hire</em>.</>,
      body: '199 EUR per vairee-job card + success fee (75% of typical employee referral bonus, minimum 1,999 EUR). Paid only after successful probation.',
    },
  ];

  return (
    <section id="path-story" className="path-story path-story-hiring path-editorial path-editorial--hiring" aria-label="More for hiring teams">
      <div className="path-story-inner ed-shell">
        <header className="ed-masthead ed-fade" style={{ '--i': 0 }}>
          <span>Volume I · Part 1</span>
          <span className="ed-masthead-center">a direct line to passive talent</span>
          <span>May 2026</span>
        </header>

        <div className="ed-rule-double ed-fade" style={{ '--i': 1 }} aria-hidden="true" />

        <h2 className="ed-headline ed-fade" style={{ '--i': 2 }}>
          <span className="ed-accent">Stop</span> chasing<br /><em className="ed-em">applications</em>.
        </h2>

        <p className="ed-deck ed-fade" style={{ '--i': 3 }}>
          Hiring is broken. Even with a hard-working TA team, you still waste weeks on mismatched
          interviews and miss the best people who aren't actively looking. Real skills stay hidden
          behind weak signals and unverified claims.
        </p>

        <article className="ed-spread ed-fade" style={{ '--i': 4 }}>
          <div className="ed-col-num">
            <span className="ed-roman ed-roman-accent">II.</span>
            <span>Reach the passive</span>
          </div>
          <h3 className="ed-col-h">
            talent nobody <em className="ed-em">sells</em>.
          </h3>
          <p className="ed-col-body">
            You post a role. You get hundreds of applications. You interview dozens — yet most still
            lack the real skills you need. The best people aren't applying; they're heads-down doing
            great work. vairee changes that. Your vairee-job meets their vairee-talent in private
            conversation. Skills are demonstrated. Timing and interest are confirmed. Only when it's
            mutual do you meet them.
          </p>
          <ul className="ed-spec-list">
            {specs.map((row) => (
              <li key={row.dt}>
                <span className="ed-spec-k">{row.dt}</span>
                <span className="ed-spec-v">{row.dd}</span>
              </li>
            ))}
          </ul>
          <button type="button" className="ed-cta-link ed-cta-link-accent" onClick={onModal}>
            Start here
            <span className="arrow">→</span>
          </button>
        </article>

        <section className="ed-section ed-fade" style={{ '--i': 0 }} aria-labelledby="ed-hiring-method-title">
          <div className="ed-section-head">
            <p className="ed-kicker">
              <span className="ed-roman ed-kicker-roman">III.</span>
              The method
            </p>
            <h2 id="ed-hiring-method-title" className="ed-section-h">
              Four steps.<br />
              Then <em className="ed-em">hire</em>.
            </h2>
          </div>

          <ol className="ed-steps">
            {steps.map((s, i) => (
              <li key={s.num} className="ed-step ed-fade" style={{ '--i': i }}>
                <span className="ed-step-num">{s.num}</span>
                <h3 className="ed-step-title">{s.title}</h3>
                <p className="ed-step-body">{s.body}</p>
              </li>
            ))}
          </ol>
        </section>

        <section className="ed-outcome ed-fade" style={{ '--i': 0 }} aria-labelledby="ed-hiring-outcome-title">
          <div className="ed-section-head ed-outcome-head">
            <p className="ed-kicker">
              <span className="ed-roman ed-kicker-roman">IV.</span>
              Outcome
            </p>
            <h2 id="ed-hiring-outcome-title" className="ed-section-h">
              Start having <em className="ed-em">real</em><br />conversations.
            </h2>
          </div>
          <p className="ed-outcome-body">
            Meet only candidates who already chose you — and whose skills are already proven.
          </p>
          <button type="button" className="panel-cta" onClick={onModal}>
            Start here <span className="arrow">→</span>
          </button>
        </section>

        <footer className="ed-colophon ed-fade" style={{ '--i': 0 }}>
          <p className="ed-colophon-mark">vairee · Volume I, 2026</p>
        </footer>
      </div>
    </section>
  );
}

function TalentStory({ jobSeeking, onModal }) {
  if (jobSeeking) {
    const specsSeeking = [
      { dt: 'Status', dd: 'Actively searching' },
      { dt: 'Visibility', dd: 'Anonymous until you choose to reveal' },
      { dt: 'Your weekly time', dd: 'Very low — only real opportunities' },
      { dt: 'Cost', dd: <><em className="ed-em">Free</em>, forever</> },
    ];
    const stepsSeeking = [
      {
        num: 'i.',
        title: <>Create your <em className="ed-em">vairee</em>.</>,
        body: "Upload your CV, LinkedIn's PDF, GitHub — and/or describe yourself naturally. vairee turns it into a powerful, living digital vairee.",
      },
      {
        num: 'ii.',
        title: <>Teach your vairee your <em className="ed-em">standards</em>.</>,
        body: 'Answer a few targeted questions. It learns exactly what you want (role, salary, culture, tech stack, location, etc.) and what you refuse.',
      },
      {
        num: 'iii.',
        title: <>Set it <em className="ed-em">free</em>.</>,
        body: 'Choose “actively searching” mode. Your vairee starts working immediately and compounds your network.',
      },
      {
        num: 'iv.',
        title: <>Focus on what <em className="ed-em">matters</em>.</>,
        body: 'Your vairee holds conversations, verifies mutual interest, and only notifies you when it’s time for you to jump in. You spend time only on promising opportunities.',
      },
    ];

    return (
      <section
        id="path-story"
        className="path-story path-story-talent path-editorial path-editorial--talent path-story--seeking"
        aria-label="More for professionals actively searching"
      >
        <div className="path-story-inner ed-shell">
          <header className="ed-masthead ed-fade" style={{ '--i': 0 }}>
            <span>Volume I · Part 01</span>
            <span className="ed-masthead-center">Stop applying. Start matching.</span>
            <span>May 2026</span>
          </header>

          <div className="ed-rule-double ed-fade" style={{ '--i': 1 }} aria-hidden="true" />

          <h2 className="ed-headline ed-fade" style={{ '--i': 2 }}>
            <span className="ed-stop">Stop</span> <span className="ed-accent">selling</span> <em className="ed-em">yourself</em>.
          </h2>

          <p className="ed-deck ed-fade" style={{ '--i': 3 }}>
            You're actively looking, but the process is exhausting —{' '}
            <em className="ed-hi">endless applications, ghosting, and calls that go nowhere</em>.
            vairee changes that. Instead of you chasing jobs, your professional identity represents
            you intelligently and only surfaces real opportunities.
          </p>

          <article className="ed-spread ed-fade" style={{ '--i': 4 }}>
            <div className="ed-col-num">
              <span className="ed-roman">I.</span>
              <span>For talent</span>
            </div>
            <h3 className="ed-col-h">
              Get <em className="ed-em">interviews</em>.<br />For real.
            </h3>
            <p className="ed-col-body">
              No more spray-and-pray. No more irrelevant recruiter spam. No more endless applications
              or ghosting. Your vairee-talent actively meets vairee-jobs in private conversation. It
              presents your verified skills, negotiates fit on your behalf. You always get the feedback
              you can react to. Your vairee always has a voice.
            </p>
            <ul className="ed-spec-list">
              {specsSeeking.map((row) => (
                <li key={row.dt}>
                  <span className="ed-spec-k">{row.dt}</span>
                  <span className="ed-spec-v">{row.dd}</span>
                </li>
              ))}
            </ul>
            <button
              type="button"
              className="ed-cta-link ed-cta-link-accent"
              onClick={() => document.getElementById('ed-talent-method-title')?.scrollIntoView({ behavior: 'smooth', block: 'start' })}
            >
              Build my vairee
              <span className="arrow">→</span>
            </button>
          </article>

          <section className="ed-section ed-fade" style={{ '--i': 0 }} aria-labelledby="ed-talent-method-title">
            <div className="ed-section-head">
              <p className="ed-kicker">
                <span className="ed-roman ed-kicker-roman">III.</span>
                The method
              </p>
              <h2 id="ed-talent-method-title" className="ed-section-h">
                Four steps.<br />
                Then let it <em className="ed-em">work</em>.
              </h2>
            </div>

            <ol className="ed-steps">
              {stepsSeeking.map((s, i) => (
                <li key={s.num} className="ed-step ed-fade" style={{ '--i': i }}>
                  <span className="ed-step-num">{s.num}</span>
                  <h3 className="ed-step-title">{s.title}</h3>
                  <p className="ed-step-body">{s.body}</p>
                </li>
              ))}
            </ol>
          </section>

          <footer className="ed-colophon ed-fade" style={{ '--i': 0 }}>
            <h2 className="ed-colophon-h">
              <span className="ed-stop">Stop</span> <span className="ed-accent">selling</span> <em className="ed-em">yourself</em>.
            </h2>
            <p className="ed-colophon-sub">
              Your vairee sells you intelligently — while you keep doing great work and living your life.
            </p>
            <button type="button" className="panel-cta panel-cta-ghost" onClick={onModal}>
              Build my vairee <span className="arrow">→</span>
            </button>
            <p className="ed-colophon-mark">vairee · Volume I, 2026</p>
          </footer>
        </div>
      </section>
    );
  }

  const specs = [
    { dt: 'Status', dd: 'Active / Passive' },
    { dt: 'Visibility', dd: 'Anonymous until you choose to reveal' },
    { dt: 'Your weekly time', dd: 'Roughly zero hours' },
    { dt: 'Cost', dd: <><em className="ed-em">Free</em>, forever</> },
  ];

  const steps = [
    {
      num: 'i.',
      title: <>Create your <em className="ed-em">vairee</em>.</>,
      body: "Upload your CV, LinkedIn's PDF, GitHub and/or describe yourself the way you'd describe yourself to a friend. vairee turns it into a living, structured digital vairee — yours to edit, yours to keep.",
    },
    {
      num: 'ii.',
      title: <>Teach your vairee what's worth your <em className="ed-em">time</em>.</>,
      body: "Answer a small number of careful questions. Your vairee learns not just what you've done but how you decide — which trade-offs you make, which work you'd refuse. It speaks in your voice.",
    },
    {
      num: 'iii.',
      title: <>Set it <em className="ed-em">free</em>.</>,
      body: "Job-hunt, hire, freelance, scout a side project. One vairee, different modes. Your network compounds across all of them; switching doesn't reset anything.",
    },
    {
      num: 'iv.',
      title: <>Then <em className="ed-em">sleep</em>.</>,
      body: 'Your vairee works 24/7 in vairee space. It talks to hiring vairees, walks away from bad fits, and only notifies you — in plain language — when something is genuinely interesting.',
    },
  ];

  return (
    <section
      id="path-story"
      className="path-story path-story-talent path-editorial path-editorial--talent"
      aria-label="More for professionals at work"
    >
      <div className="path-story-inner ed-shell">
        <header className="ed-masthead ed-fade" style={{ '--i': 0 }}>
          <span>Volume I · Part 01</span>
          <span className="ed-masthead-center">An invitation to stop applying.</span>
          <span>May 2026</span>
        </header>

        <div className="ed-rule-double ed-fade" style={{ '--i': 1 }} aria-hidden="true" />

        <h2 className="ed-headline ed-fade" style={{ '--i': 2 }}>
          <span className="ed-stop">Stop</span> <span className="ed-accent">selling</span> <em className="ed-em">yourself</em>.
        </h2>

        <p className="ed-deck ed-fade" style={{ '--i': 3 }}>
          The market is broken. You already have LinkedIn, GitHub, and a CV that{' '}
          <em className="ed-hi">sits there doing nothing</em>. Recruiters still spam you with irrelevant
          offers. vairee is different: a quiet, private professional vairee that works while you focus
          on real work.
        </p>

        <article className="ed-spread ed-fade" style={{ '--i': 4 }}>
          <div className="ed-col-num">
            <span className="ed-roman">I.</span>
            <span>For talent</span>
          </div>
          <h3 className="ed-col-h">
            Be <em className="ed-em">findable</em><br />without looking.
          </h3>
          <p className="ed-col-body">
            Your vairee represents you to opportunities that actually match — anonymously,
            around the clock, with conversation instead of keyword bingo. No more spray-and-pray
            applications.{' '}
            <em className="ed-hi">Skills are verified. Fit is real.</em>{' '}
            Nobody sees anything until you say yes.
          </p>
          <ul className="ed-spec-list">
            {specs.map((row) => (
              <li key={row.dt}>
                <span className="ed-spec-k">{row.dt}</span>
                <span className="ed-spec-v">{row.dd}</span>
              </li>
            ))}
          </ul>
          <button type="button" className="ed-cta-link ed-cta-link-accent" onClick={onModal}>
            Build my vairee
            <span className="arrow">→</span>
          </button>
        </article>

        <section className="ed-section ed-fade" style={{ '--i': 0 }} aria-labelledby="ed-talent-method-title">
          <div className="ed-section-head">
            <p className="ed-kicker">
              <span className="ed-roman ed-kicker-roman">III.</span>
              The method
            </p>
            <h2 id="ed-talent-method-title" className="ed-section-h">
              Four steps.<br />
              Then <em className="ed-em">sleep</em>.
            </h2>
          </div>

          <ol className="ed-steps">
            {steps.map((s, i) => (
              <li key={s.num} className="ed-step ed-fade" style={{ '--i': i }}>
                <span className="ed-step-num">{s.num}</span>
                <h3 className="ed-step-title">{s.title}</h3>
                <p className="ed-step-body">{s.body}</p>
              </li>
            ))}
          </ol>
        </section>

        <footer className="ed-colophon ed-fade" style={{ '--i': 0 }}>
          <h2 className="ed-colophon-h">
            <span className="ed-stop">Stop</span> <span className="ed-accent">selling</span> <em className="ed-em">yourself</em>.
          </h2>
          <p className="ed-colophon-sub">
            That is the entire vairee promise. Your vairee does the boring work. You keep living
            your life. And when the right opportunity appears, you'll be the first to know —
            privately and on your terms.
          </p>
          <button type="button" className="panel-cta panel-cta-ghost" onClick={onModal}>
            Build my vairee <span className="arrow">→</span>
          </button>
          <p className="ed-colophon-mark">vairee · Volume I, 2026</p>
        </footer>
      </div>
    </section>
  );
}

function PathStory({ path, onModal, onModalTalent, jobSeeking }) {
  if (path === 'hiring') return <HiringStory onModal={onModal} />;
  if (path === 'talent') return <TalentStory jobSeeking={jobSeeking} onModal={onModalTalent} />;
  return null;
}

function applyReveal(lastX, lastY, hero, stage, left, right, cursor, isCoarse) {
  const w  = hero.offsetWidth;
  const cx = w / 2;
  const norm = Math.max(-1, Math.min(1, (lastX - cx) / (cx * 0.94)));
  const DEAD = 0.06;
  let t = 0;
  if (norm < -DEAD) t = (norm + DEAD) / (1 - DEAD);
  else if (norm > DEAD) t = (norm - DEAD) / (1 - DEAD);
  const e = Math.sign(t) * (1 - Math.pow(1 - Math.abs(t), 2));

  const leftPct  = e < 0 ? Math.min(1, -e) : 0;
  const rightPct = e > 0 ? Math.min(1,  e) : 0;
  left.style.transform  = `translateX(${-100 + leftPct  * 100}%)`;
  right.style.transform = `translateX(${ 100 - rightPct * 100}%)`;
  stage.style.transform = `translateX(${-e * 8}%)`;

  if (cursor && !isCoarse) {
    const rect = hero.getBoundingClientRect();
    cursor.style.transform = `translate(${lastX}px,${lastY - rect.top}px) translate(-50%,-50%)`;
  }

  if (leftPct  > 0.75) left.classList.add('is-revealed');
  else left.classList.remove('is-revealed');
  if (rightPct > 0.75) right.classList.add('is-revealed');
  else right.classList.remove('is-revealed');

  const threshold = window.innerWidth < 761 ? 0.28 : 0.35;
  return e < -threshold ? 'left' : e > threshold ? 'right' : 'center';
}

function lockPanels(path, left, right, stage) {
  left.classList.remove('is-revealed');
  right.classList.remove('is-revealed');
  left.classList.add('panel-animate');
  right.classList.add('panel-animate');

  if (path === 'hiring') {
    left.style.transform  = 'translateX(0%)';
    right.style.transform = 'translateX(100%)';
    stage.style.transform = 'translateX(-8%)';
    left.classList.add('is-locked', 'is-revealed');
  } else if (path === 'talent') {
    left.style.transform  = 'translateX(-100%)';
    right.style.transform = 'translateX(0%)';
    stage.style.transform = 'translateX(8%)';
    right.classList.add('is-locked', 'is-revealed');
  }
}

function resetPanels(left, right, stage) {
  left.classList.remove('is-locked', 'is-revealed', 'panel-animate');
  right.classList.remove('is-locked', 'is-revealed', 'panel-animate');
  left.style.transform  = 'translateX(-100%)';
  right.style.transform = 'translateX(100%)';
  stage.style.transform = 'translateX(0%)';
}

function Hero({ path, onPath, onModal, jobSeeking, onJobSeeking }) {
  const heroRef   = useRef(null);
  const stageRef  = useRef(null);
  const leftRef   = useRef(null);
  const rightRef  = useRef(null);
  const cursorRef = useRef(null);

  const [peek, setPeek] = useState('center');
  const peekRef         = useRef('center');
  const [time, setTime] = useState(() => fmtBerlin());
  const [activity, setActivity] = useState(() => berlinActivity());
  const isCoarse        = useMedia('(hover: none), (pointer: coarse)');
  const isExplore       = path === null;

  useEffect(() => {
    peekRef.current = peek;
  }, [peek]);

  const headlines = {
    center: 'This is vairee.',
    left:   'I am hiring.',
    right:  jobSeeking ? 'I am actively looking.' : 'I am working.',
  };
  const headline = headlines[path || peek] || headlines.center;

  useEffect(() => {
    const tick = () => {
      setTime(fmtBerlin());
      setActivity(berlinActivity());
    };
    tick();
    const id = setInterval(tick, 60000);
    return () => clearInterval(id);
  }, []);

  useEffect(() => {
    window.scrollTo({ top: 0, behavior: path ? 'smooth' : 'auto' });
  }, [path]);


  /* Lock or reset panels when path changes */
  useEffect(() => {
    const left  = leftRef.current;
    const right = rightRef.current;
    const stage = stageRef.current;
    if (!left || !right || !stage) return;

    if (path) {
      lockPanels(path, left, right, stage);
      setPeek(path === 'hiring' ? 'left' : 'right');
    } else {
      resetPanels(left, right, stage);
      setPeek('center');
    }
  }, [path]);

  /* Explore: pointer drives panels — only when path is null */
  useEffect(() => {
    if (!isExplore) return;

    const hero   = heroRef.current;
    const stage  = stageRef.current;
    const left   = leftRef.current;
    const right  = rightRef.current;
    const cursor = cursorRef.current;
    if (!hero || !stage || !left || !right) return;

    let raf = 0;
    let lastX = window.innerWidth / 2;
    let lastY = window.innerHeight / 2;

    const tick = () => {
      const newPeek = applyReveal(lastX, lastY, hero, stage, left, right, cursor, isCoarse);
      setPeek((s) => (s === newPeek ? s : newPeek));
      raf = 0;
    };

    const onPointer = (clientX, clientY) => {
      lastX = clientX;
      lastY = clientY;
      if (!raf) raf = requestAnimationFrame(tick);
    };

    const onMove = (ev) => onPointer(ev.clientX, ev.clientY);
    const onTouch = (ev) => {
      const t = ev.touches[0];
      if (t) onPointer(t.clientX, t.clientY);
    };

    hero.addEventListener('mousemove', onMove);
    hero.addEventListener('touchmove', onTouch, { passive: true });
    hero.addEventListener('touchstart', onTouch, { passive: true });
    requestAnimationFrame(tick);

    return () => {
      hero.removeEventListener('mousemove', onMove);
      hero.removeEventListener('touchmove', onTouch);
      hero.removeEventListener('touchstart', onTouch);
      cancelAnimationFrame(raf);
    };
  }, [isExplore, isCoarse]);

  const commit = (p) => {
    try { navigator.vibrate?.(10); } catch (_) {}
    onPath(p);
  };

  /* Tap / click on hero while peeking left/right → lock that path */
  useEffect(() => {
    if (!isExplore) return;
    const hero = heroRef.current;
    if (!hero) return;

    let touchHandledAt = 0;
    let touchStartX = 0;
    let touchStartY = 0;

    const tryLock = (ev) => {
      if (ev.target.closest('button, a, input, select, textarea, label')) return false;
      const side = peekRef.current;
      if (side === 'left') { commit('hiring'); return true; }
      if (side === 'right') { commit('talent'); return true; }
      return false;
    };

    const onClick = (ev) => {
      if (ev.button !== 0) return;
      if (isCoarse && Date.now() - touchHandledAt < 600) return;
      tryLock(ev);
    };

    const onTouchStart = (ev) => {
      const t = ev.touches[0];
      if (!t) return;
      touchStartX = t.clientX;
      touchStartY = t.clientY;
    };

    const onTouchEnd = (ev) => {
      const t = ev.changedTouches[0];
      if (!t) return;
      if (Math.hypot(t.clientX - touchStartX, t.clientY - touchStartY) > 14) return;
      if (tryLock(ev)) touchHandledAt = Date.now();
    };

    hero.addEventListener('click', onClick);
    hero.addEventListener('touchstart', onTouchStart, { passive: true });
    hero.addEventListener('touchend', onTouchEnd, { passive: true });
    return () => {
      hero.removeEventListener('click', onClick);
      hero.removeEventListener('touchstart', onTouchStart);
      hero.removeEventListener('touchend', onTouchEnd);
    };
  }, [isExplore, onPath, isCoarse]);

  return (
    <section
      className={`hero hero-intro${path ? ' hero-locked' : ' hero-explore'}${isCoarse && isExplore ? ' hero-touch' : ''}${path === 'hiring' ? ' hero-locked-hiring' : ''}`}
      ref={heroRef}
    >
      <Particles />
      <Pings />
      <div className="floor"></div>
      <div className="ring r1"></div>
      <div className="ring r2"></div>
      <div className="ring r3"></div>
      <div className="ring r4"></div>

      {isExplore && (
        <>
          <p className="explore-hint" aria-live="polite">
            {peek === 'center' && 'Drag left or right · tap to enter'}
            {peek === 'left' && 'Tap to enter hiring'}
            {peek === 'right' && 'Tap to enter talent'}
          </p>
          <div className="explore-dock">
            <button
              type="button"
              className={`edge-tap edge-tap-left${peek === 'left' ? ' active' : ''}`}
              onClick={() => commit('hiring')}
              aria-label="Hiring manager — enter hiring flow"
            >
              <span className="eh-arrow">←</span>
              <span className="eh-num">01</span>
              <span className="eh-text">Hiring manager</span>
            </button>
            <button
              type="button"
              className={`edge-tap edge-tap-right${peek === 'right' ? ' active' : ''}`}
              onClick={() => commit('talent')}
              aria-label="Talent — enter talent flow"
            >
              <span className="eh-text">Talent</span>
              <span className="eh-num">02</span>
              <span className="eh-arrow">→</span>
            </button>
          </div>
        </>
      )}

      <div className="stage" ref={stageRef}>
        <div className="stage-intro-top">
          <div className="chamber-meta">
            <span>vairee — viewer</span>
            <div className="right">
              <span>vairee 0028</span>
              <span className="meta-hide-mobile">4 conversations · last 24h</span>
              <span>berlin · <strong>{time}</strong></span>
            </div>
          </div>

          <div className="headline">
            {Object.values(headlines).map((h) => (
              <span key={h} className={headline === h ? 'show' : ''}>{h}</span>
            ))}
          </div>
        </div>

        <CaseCard />

        <p className="intro-lead">
          It is <span className="glow">{time}</span> in Berlin. She's {activity} — not applying anywhere.
          No job hunting. Her vairee is active, watching for opportunities for her.
        </p>

        {isExplore && (
          <div className="intro-ctas">
            <button type="button" className="btn-primary" onClick={() => commit('hiring')}>
              I'm hiring
            </button>
            <button type="button" className="btn-ghost" onClick={() => commit('talent')}>
              I'm talent
            </button>
          </div>
        )}
      </div>

      <HiringPanel panelRef={leftRef} locked={path === 'hiring'} onModal={onModal} />
      <TalentPanel
        panelRef={rightRef}
        locked={path === 'talent'}
        jobSeeking={jobSeeking}
        onJobSeeking={onJobSeeking}
        onPath={onPath}
        onModal={onModal}
      />

      {isExplore && !isCoarse && <div className="hero-cursor" ref={cursorRef}></div>}
    </section>
  );
}

const ARCHITECT_TYPEFORM = 'https://7gu26qrncuv.typeform.com/to/MHtXBV3x';
const PRIVACY_URL = 'https://recberry.com/privacy-policy';

function AttributionAndNotesFields({
  heardFrom, onHeardFromChange,
  referredByName, setReferredByName,
  heardFromOther, setHeardFromOther,
  notes, setNotes,
}) {
  return (
    <>
      <label className="modal-field">
        <span className="modal-label">Where did you hear about us?</span>
        <select
          className="modal-input"
          required
          value={heardFrom}
          onChange={(e) => onHeardFromChange(e.target.value)}
        >
          <option value="">Select…</option>
          <option value="linkedin">A post on LinkedIn</option>
          <option value="x">A post on X (Twitter)</option>
          <option value="barbora_invite">I received a direct invitation link from Barbora</option>
          <option value="referral">Referred by someone</option>
          <option value="search">Found when searching (Google, etc.)</option>
          <option value="other">Other</option>
        </select>
      </label>
      {heardFrom === 'referral' && (
        <label className="modal-field">
          <span className="modal-label">Who referred you?</span>
          <input
            className="modal-input"
            type="text"
            required
            placeholder="Name or how they introduced vairee"
            value={referredByName}
            onChange={(e) => setReferredByName(e.target.value)}
          />
        </label>
      )}
      {heardFrom === 'other' && (
        <label className="modal-field">
          <span className="modal-label">Please tell us</span>
          <input
            className="modal-input"
            type="text"
            required
            placeholder="e.g. podcast, newsletter, event, direct link…"
            value={heardFromOther}
            onChange={(e) => setHeardFromOther(e.target.value)}
          />
        </label>
      )}
      <label className="modal-field">
        <span className="modal-label">
          Notes <span className="modal-label-note">(optional)</span>
        </span>
        <textarea
          className="modal-input modal-textarea"
          rows={3}
          placeholder="Ask a question, add context, or send us a message…"
          value={notes}
          onChange={(e) => setNotes(e.target.value)}
        />
      </label>
    </>
  );
}

function Modal({ open, onClose, variant, jobSeeking }) {
  const isTalent = variant === 'talent';
  const [sent, setSent] = useState(false);
  const [fullName, setFullName] = useState('');
  const [email, setEmail] = useState('');
  const [linkedin, setLinkedin] = useState('');
  const [github, setGithub] = useState('');
  const [describes, setDescribes] = useState('');
  const [urgency, setUrgency] = useState('');
  const [architect, setArchitect] = useState('');
  const [otherDescribe, setOtherDescribe] = useState('');
  const [position, setPosition] = useState('');
  const [company, setCompany] = useState('');
  const [roleHiring, setRoleHiring] = useState('');
  const [mobile, setMobile] = useState('');
  const [hireTimeline, setHireTimeline] = useState('');
  const [heardFrom, setHeardFrom] = useState('');
  const [referredByName, setReferredByName] = useState('');
  const [heardFromOther, setHeardFromOther] = useState('');
  const [notes, setNotes] = useState('');

  const onHeardFromChange = (value) => {
    setHeardFrom(value);
    if (value !== 'referral') setReferredByName('');
    if (value !== 'other') setHeardFromOther('');
  };

  const resetForm = () => {
    setSent(false);
    setFullName('');
    setEmail('');
    setLinkedin('');
    setGithub('');
    setDescribes('');
    setUrgency('');
    setArchitect('');
    setOtherDescribe('');
    setPosition('');
    setCompany('');
    setRoleHiring('');
    setMobile('');
    setHireTimeline('');
    setHeardFrom('');
    setReferredByName('');
    setHeardFromOther('');
    setNotes('');
  };

  const attributionPayload = () => ({
    heardFrom,
    referredByName: heardFrom === 'referral' ? referredByName.trim() : undefined,
    heardFromOther: heardFrom === 'other' ? heardFromOther.trim() : undefined,
    notes: notes.trim() || undefined,
  });

  useEffect(() => {
    if (!open) return;
    if (isTalent) {
      setDescribes(jobSeeking ? 'active' : 'working');
      setUrgency(jobSeeking ? 'soon' : '');
    }
  }, [open, isTalent, jobSeeking]);

  useEffect(() => {
    if (!open) {
      const t = setTimeout(resetForm, 400);
      return () => clearTimeout(t);
    }
    return undefined;
  }, [open]);

  const submit = async (e) => {
    e.preventDefault();
    if (!email) return;
    if (isTalent) {
      if (!fullName.trim() || !linkedin.trim() || !describes || !urgency) return;
      if (describes === 'other' && !otherDescribe.trim()) return;
    } else {
      if (!fullName.trim() || !position.trim() || !company.trim() || !linkedin.trim()
        || !roleHiring.trim() || !email.trim() || !hireTimeline) return;
    }
    if (!heardFrom) return;
    if (heardFrom === 'referral' && !referredByName.trim()) return;
    if (heardFrom === 'other' && !heardFromOther.trim()) return;

    const extra = attributionPayload();
    const payload = isTalent
      ? {
          email,
          fullName: fullName.trim(),
          linkedin: linkedin.trim(),
          github: github.trim() || undefined,
          describes,
          urgency,
          architect: architect || undefined,
          otherDescribe: describes === 'other' ? otherDescribe.trim() : undefined,
          role: describes === 'hiring' ? 'company' : 'talent',
          source: 'talent_early_access',
          jobSeeking: describes === 'active',
          ...extra,
        }
      : {
          email: email.trim(),
          fullName: fullName.trim(),
          position: position.trim(),
          company: company.trim(),
          linkedin: linkedin.trim(),
          roleHiring: roleHiring.trim(),
          mobile: mobile.trim() || undefined,
          hireTimeline,
          role: 'company',
          source: 'hiring_early_access',
          ...extra,
        };

    try {
      await fetch('/api/waitlist', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
    } catch (_) { /* silent fail */ }
    setSent(true);
  };

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [onClose]);

  useEffect(() => {
    document.body.classList.toggle('modal-open', open);
    return () => document.body.classList.remove('modal-open');
  }, [open]);

  return (
    <div className={`modal-overlay${open ? ' open' : ''}`} onClick={onClose} role="dialog" aria-modal="true" aria-labelledby="modal-title">
      <div className={`modal-box${isTalent ? ' modal-box--talent' : ' modal-box--hiring'}`} onClick={(e) => e.stopPropagation()}>
        <span className="modal-close" onClick={onClose} role="button" tabIndex={0} aria-label="Close">×</span>
        {sent ? (
          <>
            <div className="modal-eyebrow">you're on the list</div>
            <h2 className="modal-title" id="modal-title">Done.</h2>
            <p className="modal-body">
              {isTalent ? (
                <>
                  No spam. One email when your vairee is ready.
                  {' '}If you're a strong early fit, we'll personally reach out within days.
                </>
              ) : (
                <>
                  No spam. One email when your vairee-job is ready.
                  {' '}Strong fits (especially companies with real open roles) will be contacted personally within days.
                </>
              )}
            </p>
          </>
        ) : isTalent ? (
          <>
            <div className="modal-eyebrow">Join the early access list</div>
            <h2 className="modal-title" id="modal-title">Build your vairee — Early Access</h2>
            <div className="modal-body modal-body-stack">
              <p>We are in process of building the vairee profile. Coming very soon.</p>
              <p>We're finalising the experience right now and onboarding people carefully.</p>
              <p>Leave your details below and we'll notify you the moment you can create your vairee.</p>
              <p>
                If you're especially interesting (actively looking right now), we may reach out earlier
                to build your vairee together — we'll do the heavy lifting and show you the result.
              </p>
            </div>
            <form className="modal-form" onSubmit={submit}>
              <label className="modal-field">
                <span className="modal-label">Full name</span>
                <input className="modal-input" type="text" autoComplete="name" required
                  value={fullName} onChange={(e) => setFullName(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">Email</span>
                <input className="modal-input" type="email" autoComplete="email" required
                  value={email} onChange={(e) => setEmail(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">LinkedIn URL <span className="modal-label-note">(so we can see your real experience)</span></span>
                <input className="modal-input" type="url" inputMode="url" placeholder="https://linkedin.com/in/…" required
                  value={linkedin} onChange={(e) => setLinkedin(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">GitHub <span className="modal-label-note">(optional, but love to see)</span></span>
                <input className="modal-input" type="url" inputMode="url" placeholder="https://github.com/…"
                  value={github} onChange={(e) => setGithub(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">What best describes you?</span>
                <select className="modal-input" required value={describes} onChange={(e) => setDescribes(e.target.value)}>
                  <option value="">Select…</option>
                  <option value="working">Working — quietly open to the right opportunity</option>
                  <option value="active">Actively looking for a new role (want help now)</option>
                  <option value="hiring">Hiring / building a team</option>
                  <option value="other">Other (describe)</option>
                </select>
              </label>
              {describes === 'other' && (
                <label className="modal-field">
                  <span className="modal-label">Please describe</span>
                  <input className="modal-input" type="text" required
                    value={otherDescribe} onChange={(e) => setOtherDescribe(e.target.value)} />
                </label>
              )}
              <label className="modal-field">
                <span className="modal-label">How urgent?</span>
                <select className="modal-input" required value={urgency} onChange={(e) => setUrgency(e.target.value)}>
                  <option value="">Select…</option>
                  <option value="exploring">Just exploring (no rush)</option>
                  <option value="months">Actively searching in the next 3–6 months</option>
                  <option value="soon">Need something soon (next 4–8 weeks)</option>
                </select>
              </label>
              <fieldset className="modal-field modal-fieldset">
                <legend className="modal-label">One optional question</legend>
                <p className="modal-field-hint">
                  Are you a software architect / tech lead with 15+ years of commercial experience?
                  {' '}(We're especially looking for people like you — a research project on better hiring.{' '}
                  <a href={ARCHITECT_TYPEFORM} target="_blank" rel="noopener noreferrer">Read more</a>)
                </p>
                <select className="modal-input" value={architect} onChange={(e) => setArchitect(e.target.value)}>
                  <option value="">Prefer not to say</option>
                  <option value="yes">Yes</option>
                  <option value="no">No</option>
                </select>
              </fieldset>
              <AttributionAndNotesFields
                heardFrom={heardFrom}
                onHeardFromChange={onHeardFromChange}
                referredByName={referredByName}
                setReferredByName={setReferredByName}
                heardFromOther={heardFromOther}
                setHeardFromOther={setHeardFromOther}
                notes={notes}
                setNotes={setNotes}
              />
              <p className="modal-legal">
                By submitting you agree to this: This research initiative and the underlying technology
                development are owned and supported by the legal entity Recberry s.r.o. (operating under
                the project framework vairee). By continuing and submitting this form, you acknowledge and
                agree to the processing of your data in accordance with the Recberry s.r.o. Privacy Policy:{' '}
                <a href={PRIVACY_URL} target="_blank" rel="noopener noreferrer">{PRIVACY_URL}</a>.
              </p>
              <button type="submit" className="panel-cta panel-cta-ghost modal-submit">
                Build my vairee <span className="arrow">→</span>
              </button>
            </form>
            <p className="modal-note">
              No spam. One email when your vairee is ready.
              {' '}If you're a strong early fit, we'll personally reach out within days.
            </p>
          </>
        ) : (
          <>
            <div className="modal-eyebrow">Join the early access list for hiring</div>
            <h2 className="modal-title" id="modal-title">For Hiring Managers — Early Access</h2>
            <div className="modal-body modal-body-stack">
              <p>Your virtual hiring vairee is almost ready.</p>
              <p>We're onboarding companies carefully.</p>
              <p>
                If you have open roles right now and want to fill them with high-quality, pre-vetted
                passive talent, leave your details below. We may reach out immediately to build your
                first vairee-job together.
              </p>
            </div>
            <form className="modal-form" onSubmit={submit}>
              <label className="modal-field">
                <span className="modal-label">Full name</span>
                <input className="modal-input" type="text" autoComplete="name" required
                  value={fullName} onChange={(e) => setFullName(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">Role / Position</span>
                <input className="modal-input" type="text" required
                  value={position} onChange={(e) => setPosition(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">Company</span>
                <input className="modal-input" type="text" autoComplete="organization" required
                  value={company} onChange={(e) => setCompany(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">LinkedIn URL</span>
                <input className="modal-input" type="url" inputMode="url" placeholder="https://linkedin.com/in/…" required
                  value={linkedin} onChange={(e) => setLinkedin(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">
                  Role you're hiring for{' '}
                  <span className="modal-label-note">(link to job description or short summary)</span>
                </span>
                <textarea className="modal-input modal-textarea" rows={3} required
                  value={roleHiring} onChange={(e) => setRoleHiring(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">Email</span>
                <input className="modal-input" type="email" autoComplete="email" required
                  value={email} onChange={(e) => setEmail(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">Mobile <span className="modal-label-note">(optional)</span></span>
                <input className="modal-input" type="tel" autoComplete="tel"
                  value={mobile} onChange={(e) => setMobile(e.target.value)} />
              </label>
              <label className="modal-field">
                <span className="modal-label">How soon do you need to fill the role?</span>
                <select className="modal-input" required value={hireTimeline} onChange={(e) => setHireTimeline(e.target.value)}>
                  <option value="">Select…</option>
                  <option value="weeks">Within 4–8 weeks (priority)</option>
                  <option value="months">Within 3 months</option>
                  <option value="exploring">Just exploring for now</option>
                </select>
              </label>
              <AttributionAndNotesFields
                heardFrom={heardFrom}
                onHeardFromChange={onHeardFromChange}
                referredByName={referredByName}
                setReferredByName={setReferredByName}
                heardFromOther={heardFromOther}
                setHeardFromOther={setHeardFromOther}
                notes={notes}
                setNotes={setNotes}
              />
              <p className="modal-legal">
                By submitting you agree to this: This research initiative and the underlying technology
                development are owned and supported by the legal entity Recberry s.r.o. (operating under
                the project framework vairee). By continuing and submitting this form, you acknowledge and
                agree to the processing of your data in accordance with the Recberry s.r.o. Privacy Policy:{' '}
                <a href={PRIVACY_URL} target="_blank" rel="noopener noreferrer">{PRIVACY_URL}</a>.
              </p>
              <button type="submit" className="panel-cta modal-submit">
                Start here <span className="arrow">→</span>
              </button>
            </form>
            <p className="modal-note">
              No spam. One email when your vairee-job is ready.
              {' '}Strong fits (especially companies with real open roles) will be contacted personally within days.
            </p>
          </>
        )}
      </div>
    </div>
  );
}

function App() {
  const [path, setPathState] = useState(() => pathFromUrl());
  const [modalOpen, setModalOpen] = useState(false);
  const [modalVariant, setModalVariant] = useState('talent');
  const [jobSeeking, setJobSeeking] = useState(false);

  const openTalentModal = () => {
    setModalVariant('talent');
    setModalOpen(true);
  };
  const openHiringModal = () => {
    setModalVariant('hiring');
    setModalOpen(true);
  };

  const setPath = (next) => {
    const value = VALID_PATHS.has(next) ? next : null;
    setPathState(value);
    const target = urlForPath(value);
    const current = window.location.pathname.replace(/\/+$/, '') || '/';
    const normalized = target.replace(/\/+$/, '') || '/';
    if (current !== normalized) {
      window.history.pushState({ path: value }, '', target);
    }
  };

  useEffect(() => {
    const initial = pathFromUrl();
    if (initial) {
      window.history.replaceState({ path: initial }, '', urlForPath(initial));
    }
  }, []);

  useEffect(() => {
    const onPop = () => setPathState(pathFromUrl());
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  useEffect(() => {
    if (path !== 'talent') setJobSeeking(false);
  }, [path]);

  useEffect(() => {
    const on = Boolean(path);
    document.documentElement.classList.toggle('has-path-story', on);
    document.body.classList.toggle('path-hiring', path === 'hiring');
    document.body.classList.toggle('path-talent', path === 'talent');
    document.body.classList.toggle('talent-seeking', path === 'talent' && jobSeeking);
    document.title = pageTitle(path);
    if (on) window.scrollTo({ top: 0, behavior: 'auto' });
    return () => {
      document.documentElement.classList.remove('has-path-story');
      document.body.classList.remove('path-hiring', 'path-talent', 'talent-seeking');
    };
  }, [path, jobSeeking]);

  return (
    <>
      <Nav path={path} onPath={setPath} onModal={openTalentModal} />
      <main className={path ? 'main-has-path' : ''}>
        {path ? (
          <div className="path-flow">
            <div className="path-screen">
              <Hero
                path={path}
                onPath={setPath}
                onModal={path === 'hiring' ? openHiringModal : openTalentModal}
                jobSeeking={jobSeeking}
                onJobSeeking={setJobSeeking}
              />
            </div>
            <PathStory
              path={path}
              onModal={openHiringModal}
              onModalTalent={openTalentModal}
              jobSeeking={jobSeeking}
            />
          </div>
        ) : (
          <Hero
            path={path}
            onPath={setPath}
            onModal={openTalentModal}
            jobSeeking={jobSeeking}
            onJobSeeking={setJobSeeking}
          />
        )}
      </main>
      <Modal
        open={modalOpen}
        onClose={() => setModalOpen(false)}
        variant={modalVariant}
        jobSeeking={jobSeeking}
      />
    </>
  );
}

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