// ShowDoc landing — app.jsx
const { useEffect, useMemo, useState } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": ["#0a0a0b", "#e8e4dc", "#daa550"],
  "displayFont": "Instrument Serif",
  "monoFont": "JetBrains Mono",
  "density": "regular",
  "headlineVariant": "coach",
  "showWaveform": true,
  "subtleGrain": true
}/*EDITMODE-END*/;

// --- copy variants -----------------------------------------------------------
const HEADLINES = {
  coach: { lead: "Every great host", em: "reviews tape.", sub: "ShowDoc is a private coach for founder-led podcasts. Send us an episode. We send back a teardown of the moments you crushed, the gold you walked past, and the sharper follow-ups that would have unlocked the room." },
  game: { lead: "Game tape", em: "for interviewers.", sub: "We review your podcast the way a sales coach reviews a closing call — line by line, with timestamped notes on missed gold, clip opportunities, and the exact follow-ups your next episode is missing." },
  craft: { lead: "Get sharper", em: "every episode.", sub: "A weekly coaching teardown for founder-led podcasts. Better follow-ups, deeper guests, more usable clips — built around the specific patterns of how you actually interview." },
  rep: { lead: "Treat the next episode", em: "like the next rep.", sub: "ShowDoc is a teardown studio for ambitious interviewers. Drop in any episode and we'll show you the breakthroughs, the missed gold, and the one drill to practice before you record again." }
};

const PRICING_TIERS = [
  {
    id: 'single-teardown',
    name: 'Single Teardown',
    price: '$500',
    unit: '/ episode',
    tag: 'For hosts kicking the tires. One episode, one private report.',
    features: [
      'One private microsite teardown',
      '5 missed-gold moments, timestamped',
      '10 sharper follow-ups',
      'Full clip map with suggested titles',
      '30-min Loom walkthrough'
    ],
    cta: 'Reserve a slot',
    captureCta: 'Reserve Single Teardown'
  },
  {
    id: 'show-coach-monthly',
    name: 'Show Coach · Monthly',
    price: '$2,000',
    unit: '/ month',
    tag: 'For founder-led shows that record weekly and care about getting better.',
    features: [
      '4 episode teardowns per month',
      'Pre-record guest prep briefs',
      'Monthly host fingerprint update',
      'Private Slack channel with your coach',
      'Quarterly "best of" highlight reel'
    ],
    cta: 'Apply for a slot',
    captureCta: 'Apply for Show Coach',
    featured: true
  },
  {
    id: 'network-team',
    name: 'Network · Team',
    price: '$7,500',
    unit: '+ / month',
    tag: 'For media companies, networks, and exec comms teams running multiple hosts.',
    features: [
      'Up to 5 hosts on a shared rubric',
      'Editorial dashboard across the slate',
      'Cross-show pattern reports',
      'Custom drill library for your bench',
      'Quarterly on-site session'
    ],
    cta: 'Talk to a coach',
    captureCta: 'Talk to a coach'
  }
];

// --- reusable bits -----------------------------------------------------------
const BAR_COUNT = 64;
const rng = (i, seed = 3) => {
  const x = Math.sin(i * 12.9898 + seed * 78.233) * 43758.5453;
  return x - Math.floor(x);
};
// pre-compute deterministic bar heights once
const BAR_HEIGHTS = Array.from({ length: BAR_COUNT }, (_, i) => 14 + rng(i) * 86);

const EPISODE_SECONDS = 47 * 60 + 30;
const HERO_LOOP_SECONDS = 18;
const parseTimecode = (timecode) => {
  const [minutes, seconds] = timecode.split(':').map(Number);
  return minutes * 60 + seconds;
};
const formatTimecode = (seconds) => {
  const rounded = Math.round(seconds);
  return `${String(Math.floor(rounded / 60)).padStart(2, '0')}:${String(rounded % 60).padStart(2, '0')}`;
};

// timeline: each moment's waveform position is derived from its timestamp
const MOMENTS = [
  {
    id: 'm1',
    ts: '22:14',
    eyebrow: 'Missed gold · emotional reveal',
    title: '"That was the hardest six months of my life."',
    note: <>Guest opened an emotional door. <strong>You moved to revenue numbers 9 seconds later.</strong></>,
    fix: "What made it hard in a way outsiders wouldn't understand?"
  },
  {
    id: 'm2',
    ts: '31:08',
    eyebrow: 'Vague claim · numbers slipped',
    title: '"We grew about 10x in that period."',
    note: <>A superlative slipped past unchallenged. <strong>4 of 6 numerical claims this episode went unverified.</strong></>,
    fix: '10x from what baseline, across how many quarters?'
  },
  {
    id: 'm3',
    ts: '44:05',
    eyebrow: 'Clip candidate · 89%',
    title: '"My co-founder showed up with a single line on a napkin."',
    note: <>Strongest narrative beat of the episode. <strong>Suggested clip: "The Napkin That Saved the Company."</strong></>,
    fix: 'Pause. Let the napkin breathe before you ask what was on it.'
  }
].map((moment) => {
  const episodeSeconds = parseTimecode(moment.ts);
  return {
    ...moment,
    episodeSeconds,
    pos: episodeSeconds / EPISODE_SECONDS,
    loopSeconds: (episodeSeconds / EPISODE_SECONDS) * HERO_LOOP_SECONDS
  };
});

const INTRO_MOMENT = {
  id: 'intro',
  eyebrow: 'Audio scan · listening for leverage',
  title: 'Scrubbing the tape for the moments worth replaying.',
  note: <>The waveform is moving through the episode. <strong>Coaching notes appear exactly when it reaches a marked cue.</strong></>,
  fix: 'Watch the waveform, title, note, and transport time move together.'
};

const Wave = ({ progress, activeIdx }) => {
  // bars light up as waveform progress sweeps through; bars near the active moment glow amber
  const momentPositions = MOMENTS.map(m => m.pos);
  return (
    <div className="wave" data-comment-anchor="hero-wave" data-progress={progress.toFixed(4)}>
      {BAR_HEIGHTS.map((h, i) => {
        const barPos = (i + 0.5) / BAR_COUNT;
        const played = barPos <= progress;
        // is this bar near an active moment marker?
        const nearMoment = momentPositions.some((p, mi) => mi === activeIdx && Math.abs(barPos - p) < 0.04);
        const cls = `bar${played ? ' played' : ''}${nearMoment ? ' moment' : ''}`;
        return <span key={i} className={cls} style={{ height: `${h}%` }} />;
      })}
      {/* moment markers along the wave */}
      {MOMENTS.map((m, i) => (
        <div
          key={m.id}
          className={`marker${i === activeIdx ? ' active' : ''}${progress >= m.pos ? ' passed' : ''}`}
          style={{ left: `${m.pos * 100}%` }}
        />
      ))}
    </div>
  );
};

const Transport = ({ progress, playing, onToggle }) => {
  const cur = progress * EPISODE_SECONDS;
  return (
    <div className="transport">
      <button className="play-btn" onClick={onToggle} aria-label={playing ? 'Pause' : 'Play'}>
        {playing ? (
          <svg width="10" height="12" viewBox="0 0 10 12"><rect x="0" y="0" width="3" height="12" fill="currentColor"/><rect x="7" y="0" width="3" height="12" fill="currentColor"/></svg>
        ) : (
          <svg width="10" height="12" viewBox="0 0 10 12"><polygon points="0,0 10,6 0,12" fill="currentColor"/></svg>
        )}
      </button>
      <span className="tc" data-current-timecode={formatTimecode(cur)}>{formatTimecode(cur)}</span>
      <span className="tc-sep">/</span>
      <span className="tc tc-dim">{formatTimecode(EPISODE_SECONDS)}</span>
      <span className="rec-dot" />
      <span className="rec-label">LIVE TEARDOWN</span>
    </div>
  );
};

const getLeadEndpoint = () => {
  const config = window.SHOWDOC_LEAD_CONFIG || {};
  const formspreeEndpoint = String(config.formspreeEndpoint || '').trim();
  if (formspreeEndpoint) {
    return { url: formspreeEndpoint, provider: 'formspree' };
  }
  return {
    url: String(config.localEndpoint || '/api/leads').trim() || '/api/leads',
    provider: 'local'
  };
};

const LeadForm = ({ cta, source, className = '', selectedPlan = null }) => {
  const [email, setEmail] = useState('');
  const [status, setStatus] = useState('idle');
  const [message, setMessage] = useState('');

  const submitLead = async (event) => {
    event.preventDefault();
    const normalized = email.trim().toLowerCase();
    if (!normalized) {
      setStatus('error');
      setMessage('Enter your email to request a teardown.');
      return;
    }

    setStatus('submitting');
    setMessage('');

    try {
      const plan = selectedPlan ? {
        id: selectedPlan.id,
        name: selectedPlan.name,
        price: `${selectedPlan.price}${selectedPlan.unit}`
      } : null;
      const { url, provider } = getLeadEndpoint();
      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          email: normalized,
          source,
          plan,
          plan_id: plan?.id || '',
          plan_name: plan?.name || '',
          plan_price: plan?.price || '',
          _subject: plan ? `ShowDoc lead: ${plan.name}` : 'ShowDoc lead',
          capture_provider: provider,
          page: window.location.href
        })
      });
      const result = await response.json().catch(() => ({}));
      if (!response.ok || result.ok === false) {
        throw new Error(result.error || 'Unable to capture that email.');
      }
      setEmail('');
      setStatus('success');
      setMessage("You're on the list. We'll follow up with the teardown details.");
    } catch (error) {
      setStatus('error');
      setMessage(error.message || 'Unable to capture that email right now.');
    }
  };

  return (
    <div className="lead-form-wrap" data-lead-source={source}>
      <form className={`hero-form ${className}`.trim()} onSubmit={submitLead} data-status={status}>
        <input
          type="email"
          name="email"
          placeholder="founder@yourshow.com"
          value={email}
          autoComplete="email"
          required
          data-lead-email-input
          onChange={(event) => setEmail(event.target.value)}
        />
        <button type="submit" disabled={status === 'submitting'}>
          {status === 'submitting' ? 'Sending...' : cta}
        </button>
      </form>
      <div className={`form-status ${status}`} aria-live="polite">
        {message}
      </div>
    </div>
  );
};

const HeroCard = ({ showWaveform }) => {
  const [progress, setProgress] = useState(0);
  const [playing, setPlaying] = useState(true);

  // animate waveform progress
  useEffect(() => {
    if (!playing) return;
    let raf;
    let last = performance.now();
    const tick = (now) => {
      const dt = (now - last) / 1000;
      last = now;
      setProgress(p => {
        const next = p + dt / HERO_LOOP_SECONDS;
        return next >= 1 ? 0 : next;
      });
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [playing]);

  // which moment is "now playing" — the latest moment whose cue is at or behind waveform progress
  const activeIdx = useMemo(() => {
    let idx = -1;
    for (let i = 0; i < MOMENTS.length; i++) {
      if (progress >= MOMENTS[i].pos) idx = i;
    }
    return idx;
  }, [progress]);

  const active = activeIdx >= 0 ? MOMENTS[activeIdx] : INTRO_MOMENT;

  useEffect(() => {
    window.__showdocSetHeroProgress = (nextProgress) => {
      const clamped = Math.min(1, Math.max(0, Number(nextProgress) || 0));
      setPlaying(false);
      setProgress(clamped);
    };
    return () => {
      delete window.__showdocSetHeroProgress;
    };
  }, []);

  useEffect(() => {
    window.__showdocHeroDebug = {
      progress: Number(progress.toFixed(4)),
      episodeSeconds: Number((progress * EPISODE_SECONDS).toFixed(2)),
      loopSeconds: Number((progress * HERO_LOOP_SECONDS).toFixed(2)),
      currentTimecode: formatTimecode(progress * EPISODE_SECONDS),
      activeMomentId: active.id,
      activeMomentIndex: activeIdx,
      cues: MOMENTS.map((moment) => ({
        id: moment.id,
        timecode: moment.ts,
        progress: Number(moment.pos.toFixed(4)),
        episodeSeconds: moment.episodeSeconds,
        loopSeconds: Number(moment.loopSeconds.toFixed(2))
      }))
    };
  }, [active.id, activeIdx, progress]);

  return (
    <div
      className="hero-card"
      data-comment-anchor="hero-card"
      data-active-moment={active.id}
      data-progress={progress.toFixed(4)}
    >
      <div className="card-hd">
        <div className="lights"><span/><span/><span/></div>
        <span>SHOWDOC · TEARDOWN.PRIVATE</span>
        <span>EP 247</span>
      </div>
      <div className="card-body">
        <div className="card-eyebrow" key={active.id + '-eb'} data-active-moment={active.id}>
          {active.eyebrow}
        </div>
        <h3 className="card-title morph" key={active.id + '-t'} data-active-moment={active.id}>
          {active.title}
        </h3>
        {showWaveform && <Wave progress={progress} activeIdx={activeIdx} />}
        <Transport progress={progress} playing={playing} onToggle={() => setPlaying(p => !p)} />

        {/* coaching note panel — animates between moments */}
        <div className="note-stage">
          {activeIdx < 0 && (
            <div className="note-card is-active" data-moment-id={INTRO_MOMENT.id}>
              <div className="timestamp-row">
                <span className="ts">00:00</span>
                <div className="ts-text">
                  {INTRO_MOMENT.note}
                  <div className="followup">
                    <span className="followup-label">Timing QA</span>
                    {INTRO_MOMENT.fix}
                  </div>
                </div>
              </div>
            </div>
          )}
          {MOMENTS.map((m, i) => (
            <div
              key={m.id}
              className={`note-card${i === activeIdx ? ' is-active' : ''}${i < activeIdx ? ' is-past' : ''}`}
              data-moment-id={m.id}
              data-cue-progress={m.pos.toFixed(4)}
            >
              <div className="timestamp-row">
                <span className="ts">{m.ts}</span>
                <div className="ts-text">
                  {m.note}
                  <div className="followup">
                    <span className="followup-label">Stronger follow-up</span>
                    {m.fix}
                  </div>
                </div>
              </div>
            </div>
          ))}
        </div>

        <div className="moment-pips">
          {MOMENTS.map((m, i) => (
            <span key={m.id} className={`pip${i === activeIdx ? ' active' : ''}${i < activeIdx ? ' done' : ''}`}>
              <span className="pip-dot" />
              <span className="pip-ts">{m.ts}</span>
            </span>
          ))}
        </div>
      </div>
    </div>
  );
};

// --- main page ---------------------------------------------------------------
function App(){
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [selectedPlan, setSelectedPlan] = useState(null);

  // apply CSS variable tweaks
  useEffect(() => {
    const root = document.documentElement;
    root.style.setProperty('--ink', t.palette[0]);
    root.style.setProperty('--bone', t.palette[1]);
    root.style.setProperty('--amber', t.palette[2]);
    // recompute companion colors
    root.style.setProperty('--signal', t.palette[2]);
    root.style.setProperty('--serif', `'${t.displayFont}', 'Times New Roman', serif`);
    root.style.setProperty('--mono', `'${t.monoFont}', ui-monospace, Menlo, monospace`);
    document.body.dataset.density = t.density;
    document.body.style.setProperty('--grain-opacity', t.subtleGrain ? '0.05' : '0');
  }, [t]);

  const copy = HEADLINES[t.headlineVariant] || HEADLINES.coach;
  const selectPlan = (plan) => {
    setSelectedPlan(plan);
    window.location.hash = 'waitlist';
    requestAnimationFrame(() => {
      document.getElementById('waitlist')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
      window.setTimeout(() => {
        document.querySelector('#waitlist [data-lead-email-input]')?.focus();
      }, 350);
    });
  };

  return (
    <>
      <nav className="nav" data-screen-label="Nav">
        <div className="nav-inner">
          <div className="brand">
            <div className="brand-mark" />
            <div className="brand-name">ShowDoc <em>· tape room</em></div>
          </div>
          <div className="nav-links">
            <a href="#how">How it works</a>
            <a href="#teardown">Sample teardown</a>
            <a href="#pricing">Pricing</a>
            <a href="#waitlist">Waitlist</a>
          </div>
          <a className="nav-cta" href="#waitlist">Join the waitlist</a>
        </div>
      </nav>

      <section className="hero" data-screen-label="01 Hero">
        <div className="hero-inner">
          <div>
            <div className="eyebrow">
              <span className="dot" />
              <span>NOW INTERVIEWING · FOUNDER-LED SHOWS</span>
            </div>
            <h1 className="headline">
              {copy.lead}<br/><em>{copy.em}</em>
            </h1>
            <p className="sub">{copy.sub}</p>
            <LeadForm cta="Request a teardown" source="hero" />
            <div className="hero-meta">10 FOUNDING SLOTS · 48-HR TURNAROUND · NDA BY DEFAULT</div>
          </div>
          <HeroCard showWaveform={t.showWaveform} />
        </div>
      </section>

      <section className="bay" id="how" data-screen-label="02 How it works">
        <div className="bay-inner">
          <div className="section-eyebrow">The Process</div>
          <h2 className="section-title">
            Three steps. No dashboard. <em>Just the report.</em>
          </h2>
          <p className="section-lede">
            ShowDoc is built around the loop a great sales org runs every Monday morning:
            tape, teardown, and a single skill to drill before the next call. We rebuilt it
            for the host's chair.
          </p>

          <div className="hiw">
            <div className="hiw-cell">
              <div className="hiw-num">01 · INTAKE</div>
              <h3 className="hiw-h">Send one episode.</h3>
              <p className="hiw-p">
                Drop in a YouTube, Spotify, Apple, or RSS link. We'll pull the audio,
                generate a clean transcript, and route it to a coach who knows your beat.
              </p>
              <div className="hiw-icon">·· LINK · TRANSCRIPT · ROUTED</div>
            </div>
            <div className="hiw-cell">
              <div className="hiw-num">02 · TEARDOWN</div>
              <h3 className="hiw-h">A coach reviews the tape.</h3>
              <p className="hiw-p">
                Within 48 hours you get a private microsite: five missed-gold moments,
                ten sharper follow-ups, a clip map, and your host fingerprint — the
                patterns you fall into when the room gets interesting.
              </p>
              <div className="hiw-icon">·· 5 MISSES · 10 FOLLOW-UPS · 1 FINGERPRINT</div>
            </div>
            <div className="hiw-cell">
              <div className="hiw-num">03 · DRILL</div>
              <h3 className="hiw-h">One skill to practice.</h3>
              <p className="hiw-p">
                Every teardown ends with a single rep to drill before your next record:
                the question type you're under-using, the pause you keep collapsing,
                the superlative you keep letting slide.
              </p>
              <div className="hiw-icon">·· READY FOR EP 248</div>
            </div>
          </div>
        </div>
      </section>

      <section className="bay" id="teardown" data-screen-label="03 Sample teardown">
        <div className="bay-inner">
          <div className="section-eyebrow">Inside The Report</div>
          <h2 className="section-title">
            The teardown <em>your interviews</em> deserve.
          </h2>
          <p className="section-lede">
            Every report opens with a five-axis scorecard, then walks moment by moment
            through the episode. Below is a teaser from a real founder-podcast review.
          </p>

          <div className="teardown">
            <div className="teardown-side">
              <div className="scorecard" data-comment-anchor="scorecard">
                <div className="scorecard-h">
                  <span>EP 247 · SCORECARD</span>
                  <span>v1.2</span>
                </div>
                <div className="score-row">
                  <span className="score-label">Guest depth</span>
                  <span className="score-val">7.4 / 10</span>
                  <div className="score-bar" style={{'--w': '74%'}} />
                </div>
                <div className="score-row">
                  <span className="score-label">Follow-up quality</span>
                  <span className="score-val">5.8 / 10</span>
                  <div className="score-bar" style={{'--w': '58%'}} />
                </div>
                <div className="score-row">
                  <span className="score-label">Novelty density</span>
                  <span className="score-val">8.1 / 10</span>
                  <div className="score-bar" style={{'--w': '81%'}} />
                </div>
                <div className="score-row">
                  <span className="score-label">Energy spikes</span>
                  <span className="score-val">6.6 / 10</span>
                  <div className="score-bar" style={{'--w': '66%'}} />
                </div>
                <div className="score-row">
                  <span className="score-label">Clip potential</span>
                  <span className="score-val">8.9 / 10</span>
                  <div className="score-bar" style={{'--w': '89%'}} />
                </div>
              </div>
            </div>

            <div className="teardown-main">
              <div className="td-tabs">
                <span className="td-tab active">Missed gold</span>
                <span className="td-tab">Follow-ups</span>
                <span className="td-tab">Clip map</span>
                <span className="td-tab">Fingerprint</span>
              </div>
              <div className="td-body">
                <div className="td-moment">
                  <div className="td-meta">
                    <span className="ts">22:14</span>
                    <span className="tag">Emotional reveal</span>
                  </div>
                  <p className="td-quote">That was the hardest six months of my life.</p>
                  <p className="td-note">
                    Guest dropped an emotional door. You walked past it to a revenue
                    question in <strong>9 seconds</strong> — your fastest pivot of the
                    episode. The room was warm; the next minute could have been the clip.
                  </p>
                  <div className="td-fix">
                    <div className="td-fix-label">Try next time</div>
                    <p className="td-fix-text">
                      What made it hard in a way outsiders wouldn't understand?
                    </p>
                  </div>
                </div>

                <div className="td-moment">
                  <div className="td-meta">
                    <span className="ts">31:08</span>
                    <span className="tag">Vague claim</span>
                  </div>
                  <p className="td-quote">We grew about 10x in that period.</p>
                  <p className="td-note">
                    A superlative slipped past unchallenged. Across this episode, you let
                    <strong> 4 of 6 numerical claims</strong> through without a follow-up.
                    The drill: when a guest gives a multiplier, ask for the denominator.
                  </p>
                  <div className="td-fix">
                    <div className="td-fix-label">Try next time</div>
                    <p className="td-fix-text">
                      10x from what baseline, across how many quarters, and what was breaking?
                    </p>
                  </div>
                </div>

                <div className="td-moment">
                  <div className="td-meta">
                    <span className="ts">44:05</span>
                    <span className="tag">Clip candidate · 89%</span>
                  </div>
                  <p className="td-quote">
                    The day I almost shut it down, my co-founder showed up with a single line on a napkin.
                  </p>
                  <p className="td-note">
                    Strongest narrative beat of the episode. Suggested title: <strong>"The
                    Napkin That Saved the Company."</strong> Best fit for YouTube Shorts and
                    LinkedIn — the visual hook of a written object travels.
                  </p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>

      <section className="bay" id="pricing" data-screen-label="04 Pricing">
        <div className="bay-inner">
          <div className="section-eyebrow">Founding Customer Pricing</div>
          <h2 className="section-title">
            Three rooms. <em>Pick your bench.</em>
          </h2>
          <p className="section-lede">
            We're capping ShowDoc at ten founding shows for the first quarter. That's how
            many teardowns one head coach can deliver without it turning into software too
            soon. After the cap, prices step up.
          </p>

          <div className="tiers">
            {PRICING_TIERS.map((tier) => (
              <div
                key={tier.id}
                className={`tier${tier.featured ? ' featured' : ''}${selectedPlan?.id === tier.id ? ' selected' : ''}`}
              >
                <div className="tier-name">{tier.name}</div>
                <h3 className="tier-price">{tier.price}<span className="unit">{tier.unit}</span></h3>
                <p className="tier-tag">{tier.tag}</p>
                <ul className="tier-list">
                  {tier.features.map((feature) => <li key={feature}>{feature}</li>)}
                </ul>
                <button
                  type="button"
                  className="tier-cta"
                  aria-pressed={selectedPlan?.id === tier.id}
                  onClick={() => selectPlan(tier)}
                >
                  {tier.cta}
                </button>
              </div>
            ))}
          </div>
        </div>
      </section>

      <section className="finale" id="waitlist" data-screen-label="05 Waitlist CTA">
        <div className="finale-inner">
          <div className="section-eyebrow" style={{justifyContent:'center'}}>The Bench</div>
          <h2>
            Ten founding hosts.<br/><em>Be one of them.</em>
          </h2>
          <p>
            We're picking ten founder-led shows for the first quarter. If you're hosting
            an interview podcast and you read every note in your guest's brief twice,
            you'll fit the room.
          </p>
          {selectedPlan && (
            <div className="selected-plan" aria-live="polite">
              <span>Selected</span>
              {selectedPlan.name} · {selectedPlan.price}{selectedPlan.unit}
            </div>
          )}
          <LeadForm
            cta={selectedPlan ? selectedPlan.captureCta : 'Join the waitlist'}
            source={selectedPlan ? 'pricing' : 'waitlist'}
            selectedPlan={selectedPlan}
            className="finale-form"
          />
          <div className="hero-meta" style={{marginTop: 16}}>NO PITCH DECK · NO DASHBOARD · JUST TAPE</div>
        </div>
      </section>

      <footer>
        <div className="footer-inner">
          <span>SHOWDOC · TAPE ROOM · 2026</span>
          <span>BUILT FOR HOSTS WHO REVIEW TAPE</span>
        </div>
      </footer>

      <TweaksPanel>
        <TweakSection label="Copy" />
        <TweakRadio
          label="Headline angle"
          value={t.headlineVariant}
          options={['coach', 'game', 'craft', 'rep']}
          onChange={(v) => setTweak('headlineVariant', v)}
        />

        <TweakSection label="Palette" />
        <TweakColor
          label="Theme"
          value={t.palette}
          options={[
            ["#0a0a0b", "#e8e4dc", "#daa550"], // ink + bone + amber (default)
            ["#0b0d10", "#e6e8ec", "#9bb5ff"], // ink + cool + ice blue
            ["#0a0a0b", "#e8e4dc", "#d96d52"], // ink + bone + ember red
            ["#0d0b0a", "#ece6dc", "#9fb89a"], // ink + bone + sage
            ["#070708", "#f0ece4", "#c8a8ff"]  // ink + bone + mauve
          ]}
          onChange={(v) => setTweak('palette', v)}
        />

        <TweakSection label="Type" />
        <TweakSelect
          label="Display"
          value={t.displayFont}
          options={['Instrument Serif', 'Space Grotesk', 'JetBrains Mono']}
          onChange={(v) => setTweak('displayFont', v)}
        />
        <TweakSelect
          label="Mono"
          value={t.monoFont}
          options={['JetBrains Mono', 'Space Grotesk']}
          onChange={(v) => setTweak('monoFont', v)}
        />

        <TweakSection label="Layout" />
        <TweakRadio
          label="Density"
          value={t.density}
          options={['compact', 'regular', 'comfy']}
          onChange={(v) => setTweak('density', v)}
        />
        <TweakToggle
          label="Hero waveform"
          value={t.showWaveform}
          onChange={(v) => setTweak('showWaveform', v)}
        />
        <TweakToggle
          label="Film grain"
          value={t.subtleGrain}
          onChange={(v) => setTweak('subtleGrain', v)}
        />
      </TweaksPanel>
    </>
  );
}

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