/* Listen, About, Pricing, FAQ, Final CTA, Footer — production wired */

// Pretty labels for each chunk on the homepage demo player. Keys match
// chunk.segment_type returned by /api/news/yesterday-detail.
const SEGMENT_LABELS = {
  us_news: { emoji: '🇺🇸', label: 'U.S. News' },
  world_news: { emoji: '🌍', label: 'World' },
  politics: { emoji: '🏛', label: 'Politics' },
  tech: { emoji: '💻', label: 'Tech' },
  business: { emoji: '💼', label: 'Business' },
  science: { emoji: '🔬', label: 'Science' },
  climate: { emoji: '🌿', label: 'Climate' },
  sports: { emoji: '⚽', label: 'Sports' },
  entertainment: { emoji: '🎬', label: 'Entertainment' },
  local_news: { emoji: '📍', label: 'Local' },
  good_news: { emoji: '☀', label: 'Good News' },
  freaky: { emoji: '👁', label: 'Freaky & Fun' },
};

function MLListen() {
  const t = window.mlTokens;
  const isMobile = window.useMobile();
  const audioRef = React.useRef(null);
  const sectionRef = React.useRef(null);
  const [playing, setPlaying] = React.useState(false);
  const [chunks, setChunks] = React.useState([]);          // Ordered playlist from /api/news/yesterday-detail
  const [chunkIdx, setChunkIdx] = React.useState(0);       // Which chunk is currently loaded into the audio element
  const [chunkTime, setChunkTime] = React.useState(0);     // currentTime of the loaded chunk (seconds)
  const [audioError, setAudioError] = React.useState(false);
  const [metro, setMetro] = React.useState(null);          // { id, label, source } | null

  // Gates whether we hit /api/news/yesterday-detail and start prefetching
  // chunk MP3s. We DON'T want to do either of these on initial page load —
  // the homepage gets crawled by bots and viewed by users who never scroll
  // to the player, and prefetching ~5MB of audio for everyone tanks our
  // SEO scores and burns Bunny.net egress.
  //
  // Flips true on whichever happens first:
  //   1. The LISTEN section enters the viewport (with 600px rootMargin)
  //   2. 15 seconds elapse since page load
  //   3. The user clicks the play button
  //
  // Crawlers that don't scroll and leave within 15s never trigger any
  // playlist fetch or audio prefetch. Real users get prefetch warm-up
  // well before they scroll-and-click.
  const [shouldLoad, setShouldLoad] = React.useState(false);
  React.useEffect(() => {
    if (shouldLoad) return;
    let cancelled = false;
    const trigger = () => { if (!cancelled) setShouldLoad(true); };

    // 15s safety timer — if the user is reading slowly above the fold
    // we still warm the player up before they scroll to it.
    const timerId = setTimeout(trigger, 15000);

    // IntersectionObserver — fire as soon as the player section is within
    // ~600px of the viewport. Modern browsers all support this; old ones
    // fall back to the timer.
    let observer = null;
    if (typeof IntersectionObserver !== 'undefined' && sectionRef.current) {
      observer = new IntersectionObserver((entries) => {
        for (const entry of entries) {
          if (entry.isIntersecting) {
            trigger();
            observer.disconnect();
            break;
          }
        }
      }, { rootMargin: '600px 0px' });
      observer.observe(sectionRef.current);
    }

    return () => {
      cancelled = true;
      clearTimeout(timerId);
      if (observer) observer.disconnect();
    };
  }, [shouldLoad]);

  // Prior day's date for display
  const priorDay = React.useMemo(() => {
    const d = new Date();
    d.setDate(d.getDate() - 1);
    return d.toLocaleDateString('en-US', {weekday:'long', month:'long', day:'numeric'}).toUpperCase();
  }, []);

  // Cumulative offsets per chunk (seconds before chunk[i] starts) — used
  // for the unified progress bar that spans the whole briefing.
  const offsets = React.useMemo(() => {
    const arr = [];
    let running = 0;
    for (const c of chunks) {
      arr.push(running);
      running += Number(c.duration_seconds) || 0;
    }
    return arr;
  }, [chunks]);

  const totalDuration = React.useMemo(() => {
    return chunks.reduce((sum, c) => sum + (Number(c.duration_seconds) || 0), 0);
  }, [chunks]);

  // Cumulative current playback time across all chunks.
  const cumulativeTime = (offsets[chunkIdx] || 0) + chunkTime;

  // Fetch homepage demo playlist (sample_intro + segments + local).
  // Gated on shouldLoad so this never fires for bots / quick bouncers.
  React.useEffect(() => {
    if (!shouldLoad) return;
    let cancelled = false;
    fetch('/api/news/yesterday-detail')
      .then(r => r.json())
      .then(d => {
        if (cancelled) return;
        const list = (d?.chunks || []).filter(c => c && c.url);
        if (list.length === 0) {
          setAudioError(true);
          return;
        }
        setChunks(list);
        setMetro(d?.metro || null);
      })
      .catch(() => { if (!cancelled) setAudioError(true); });
    return () => { cancelled = true; };
  }, [shouldLoad]);

  // Pre-warm every chunk into the browser's HTTP cache so the gap between
  // chunks during playback is near-zero. Uses hidden, muted <audio> elements
  // with preload=auto. Same pattern the /today page uses.
  //
  // Indirectly gated on shouldLoad: chunks only populates after the
  // playlist fetch fires, which itself only fires after shouldLoad. So a
  // crawler / above-the-fold bouncer never downloads any audio.
  const prefetchersRef = React.useRef([]);
  React.useEffect(() => {
    prefetchersRef.current.forEach(p => { try { p.remove(); } catch (e) {} });
    prefetchersRef.current = [];
    for (const c of chunks) {
      try {
        const p = document.createElement('audio');
        p.preload = 'auto';
        p.muted = true;
        p.style.display = 'none';
        p.src = c.url;
        document.body.appendChild(p);
        prefetchersRef.current.push(p);
      } catch (e) { /* best-effort */ }
    }
    return () => {
      prefetchersRef.current.forEach(p => { try { p.remove(); } catch (e) {} });
      prefetchersRef.current = [];
    };
  }, [chunks]);

  // Wire up HTML audio element events. Also handles auto-advance: when a
  // chunk ends and there's another in the playlist, swap src and continue
  // playing for a continuous-briefing experience.
  React.useEffect(() => {
    const audio = audioRef.current;
    if (!audio || chunks.length === 0) return;
    const onTime = () => setChunkTime(audio.currentTime || 0);
    const onEnded = () => {
      const nextIdx = chunkIdx + 1;
      if (nextIdx < chunks.length) {
        setChunkIdx(nextIdx);
        // Effect below will load + play the next chunk
      } else {
        setPlaying(false);
        setChunkIdx(0);
        setChunkTime(0);
      }
    };
    audio.addEventListener('timeupdate', onTime);
    audio.addEventListener('ended', onEnded);
    return () => {
      audio.removeEventListener('timeupdate', onTime);
      audio.removeEventListener('ended', onEnded);
    };
  }, [chunkIdx, chunks]);

  // When chunkIdx changes, swap the audio src and (if playing) keep playing.
  React.useEffect(() => {
    const audio = audioRef.current;
    if (!audio || !chunks[chunkIdx]) return;
    audio.src = chunks[chunkIdx].url;
    setChunkTime(0);
    if (playing) {
      audio.play().catch(() => setAudioError(true));
    }
  }, [chunkIdx, chunks]);

  const togglePlay = () => {
    // If the user beat the IntersectionObserver / 15s timer to the play
    // button, kick off the playlist fetch + prefetch right now so the
    // chunks start downloading.
    if (!shouldLoad) setShouldLoad(true);

    const audio = audioRef.current;
    if (!audio || chunks.length === 0) return;
    if (playing) {
      audio.pause();
      setPlaying(false);
    } else {
      // First play: ensure src is loaded
      if (!audio.src && chunks[chunkIdx]) audio.src = chunks[chunkIdx].url;
      audio.play().catch(() => setAudioError(true));
      setPlaying(true);
    }
  };

  const fmtTime = (s) => {
    if (!s || isNaN(s)) return '0:00';
    const m = Math.floor(s/60);
    const sec = Math.floor(s%60);
    return `${m}:${sec.toString().padStart(2,'0')}`;
  };

  // Decorative waveform bars — purely visual; the bar acts as the progress
  // indicator and the seek surface for the unified timeline.
  const bars = React.useMemo(()=>{
    const arr=[];
    for (let i=0;i<80;i++) arr.push(0.3 + 0.7 * Math.abs(Math.sin(i*0.5)+Math.cos(i*1.1)*0.6));
    return arr;
  },[]);

  // Seek into the unified timeline. Maps an x-fraction across the whole
  // bar to (chunkIdx, chunkTime) and swaps src + seeks accordingly.
  const handleBarClick = (e) => {
    if (totalDuration <= 0 || chunks.length === 0) return;
    const rect = e.currentTarget.getBoundingClientRect();
    const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
    const targetSeconds = x * totalDuration;

    // Find which chunk that lands in
    let targetIdx = 0;
    let into = targetSeconds;
    for (let i = 0; i < chunks.length; i++) {
      const dur = Number(chunks[i].duration_seconds) || 0;
      if (into <= dur || i === chunks.length - 1) {
        targetIdx = i;
        break;
      }
      into -= dur;
    }
    const audio = audioRef.current;
    if (!audio) return;
    if (targetIdx !== chunkIdx) {
      setChunkIdx(targetIdx);
      // After src swap, the loadedmetadata event will fire and we can seek.
      const onLoaded = () => {
        try { audio.currentTime = into; } catch (e) {}
        setChunkTime(into);
        audio.removeEventListener('loadedmetadata', onLoaded);
        if (playing) audio.play().catch(() => {});
      };
      audio.addEventListener('loadedmetadata', onLoaded);
    } else {
      try { audio.currentTime = into; } catch (e) {}
      setChunkTime(into);
    }
  };

  // Jump to a specific chunk (chip click). Always starts at 0s within
  // that chunk and resumes playback.
  const jumpToChunk = (idx) => {
    if (idx < 0 || idx >= chunks.length) return;
    const audio = audioRef.current;
    setChunkIdx(idx);
    setChunkTime(0);
    if (audio) {
      // Small delay to let the src swap effect run, then play
      setTimeout(() => audio.play().catch(() => setAudioError(true)), 0);
      setPlaying(true);
    }
  };

  // Currently-playing chunk descriptor for the header copy.
  const currentChunk = chunks[chunkIdx] || null;
  const currentLabel = (() => {
    if (!currentChunk) return null;
    if (currentChunk.kind === 'local') {
      return { emoji: '📍', label: currentChunk.metro_name ? `Local · ${currentChunk.metro_name}` : 'Local' };
    }
    if (currentChunk.segment_type && SEGMENT_LABELS[currentChunk.segment_type]) {
      return SEGMENT_LABELS[currentChunk.segment_type];
    }
    return { emoji: '▶', label: currentChunk.label || 'Briefing' };
  })();

  // The chip row hides the sample_intro chunk — visitors don't need to
  // jump to "Hi, I'm Harold". Keeps original playlist indices intact via
  // data-idx so jumpToChunk lands on the right chunk regardless.
  const visibleChips = chunks
    .map((c, i) => ({ chunk: c, idx: i }))
    .filter(({ chunk }) => chunk.kind !== 'sample_intro');

  // Media Session API for lock-screen controls
  React.useEffect(() => {
    if (!('mediaSession' in navigator)) return;
    if (!currentChunk) return;
    navigator.mediaSession.metadata = new MediaMetadata({
      title: (currentLabel?.label || 'Briefing') + ' — Harold',
      artist: 'Harold',
      album: 'The Harold',
    });
    navigator.mediaSession.setActionHandler('play', () => {
      audioRef.current?.play();
      setPlaying(true);
    });
    navigator.mediaSession.setActionHandler('pause', () => {
      audioRef.current?.pause();
      setPlaying(false);
    });
  }, [chunkIdx, chunks]);

  const progressFraction = totalDuration > 0 ? (cumulativeTime / totalDuration) : 0;

  return (
    <section ref={sectionRef} id="listen" style={{position:'relative', zIndex: 2, padding: isMobile ? '48px 0' : '72px 0', maxWidth: 1100, margin:'0 auto'}}>
      <div style={{marginBottom: isMobile ? 24 : 36, textAlign:'center'}}>
        <window.MLKicker>☀ LISTEN</window.MLKicker>
        <window.MLH2>Tap play to hear Harold.</window.MLH2>
        <p style={{marginTop: 18, fontSize: 16, color: t.ink60, maxWidth: 540, margin:'18px auto 0'}}>
          Yesterday's briefing.<br/>
          Matter-of-fact news, designed to inform, not trigger.
        </p>
      </div>

      <audio ref={audioRef} preload="auto"/>

      <div style={{
        background: t.paper, borderRadius: 28, padding: isMobile ? '24px 20px' : '36px 40px',
        border:'1px solid rgba(42,24,16,0.08)', boxShadow: t.card,
      }}>
        <div style={{display:'flex', alignItems:'center', gap: isMobile ? 16 : 24, paddingBottom: 20, flexWrap: isMobile ? 'wrap' : 'nowrap'}}>
          <button onClick={togglePlay} style={{
            width: isMobile ? 64 : 84, height: isMobile ? 64 : 84, borderRadius: 999, border:'none',
            background:'linear-gradient(135deg, #FF7A4D, #FF5A2D)',
            boxShadow:'0 12px 30px rgba(255,90,45,0.4), inset 0 1px 0 rgba(255,255,255,0.25)',
            cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center',
            flexShrink: 0, minWidth: isMobile ? 64 : 84,
          }}>
            {playing ? (
              <svg width={isMobile ? 24 : 32} height={isMobile ? 24 : 32} viewBox="0 0 24 24" fill="white"><rect x="6" y="5" width="4" height="14" rx="1"/><rect x="14" y="5" width="4" height="14" rx="1"/></svg>
            ):(
              <svg width={isMobile ? 24 : 32} height={isMobile ? 24 : 32} viewBox="0 0 24 24" fill="white"><path d="M7 5v14l12-7z"/></svg>
            )}
          </button>
          <div style={{flex: 1, minWidth: 0}}>
            <div style={{fontFamily: t.mono, fontSize: 11, letterSpacing:'0.2em', color: '#B85C2E', fontWeight: 600}}>
              {priorDay} · {currentLabel ? (currentLabel.emoji + ' ' + currentLabel.label.toUpperCase()) : 'DAILY BRIEFING'}
            </div>
            <div style={{fontSize: isMobile ? 18 : 26, fontWeight: 700, letterSpacing:'-0.02em', color: t.ink, marginTop: 4}}>
              Your Morning Briefing with Harold
            </div>
            <div style={{fontSize: 14, color: t.ink60, marginTop: 4}}>
              {totalDuration > 0 ? fmtTime(cumulativeTime) + ' / ' + fmtTime(totalDuration) + ' · ' : ''}narrated by Harold
            </div>
          </div>
        </div>

        <div
          onClick={handleBarClick}
          style={{display:'flex', alignItems:'center', gap: 2, height: isMobile ? 56 : 72, padding:'8px 0', cursor: chunks.length > 0 ? 'pointer' : 'default'}}>
          {bars.map((v,i)=>{
            const played = i/bars.length <= progressFraction;
            return <span key={i} style={{flex:1, minWidth: 2, borderRadius: 1,
              height: `${v*100}%`, background: played ? t.coral : t.peach}}/>;
          })}
        </div>

        {audioError && (
          <div style={{marginBottom: 12, fontSize: 13, color: t.ink60, textAlign:'center'}}>
            Yesterday's audio is being prepared — check back shortly.
          </div>
        )}

        {/* Segment skip controls */}
        <div style={{marginTop: 16, paddingTop: 16, borderTop:'1px dashed rgba(42,24,16,0.15)'}}>
          <div style={{fontSize: 11, fontFamily: t.mono, letterSpacing:'0.15em', color: t.ink40, marginBottom: 10, fontWeight: 600}}>
            SKIP TO SEGMENT
          </div>
          <div style={{display:'flex', gap: 8, flexWrap:'wrap'}}>
            {visibleChips.length > 0 ? (
              visibleChips.map(({ chunk, idx }) => {
                const info = chunk.kind === 'local'
                  ? { emoji: '📍', label: chunk.metro_name ? `Local · ${chunk.metro_name}` : 'Local' }
                  : (SEGMENT_LABELS[chunk.segment_type] || { emoji: '▶', label: chunk.label || chunk.segment_type || 'Chunk' });
                const isActive = idx === chunkIdx;
                return (
                  <button
                    key={idx}
                    onClick={() => jumpToChunk(idx)}
                    style={{
                      fontSize: 12, padding:'6px 12px', borderRadius: 999,
                      background: isActive ? t.coral : '#FFF3E6',
                      color: isActive ? t.cream : t.ink60,
                      fontWeight: isActive ? 600 : 500,
                      border: 'none', cursor: 'pointer', whiteSpace:'nowrap',
                      fontFamily:'inherit', minHeight: 32,
                      transition: 'all 0.15s',
                    }}>
                    {info.emoji} {info.label}
                    {chunk.duration_seconds ? ` · ${fmtTime(chunk.duration_seconds)}` : ''}
                  </button>
                );
              })
            ) : (
              /* Static fallback when no chunk data yet */
              ['🌍 World', '💼 Business', '⚽ Sports', '🔬 Tech & Science'].map(c=>(
                <span key={c} style={{fontSize: 12, padding:'6px 12px', borderRadius: 999,
                  background:'#FFF3E6', color: t.ink60, fontWeight: 500, whiteSpace:'nowrap'}}>{c}</span>
              ))
            )}
          </div>

          {/* Geo disclosure: when the local chunk is in the playlist, surface
              which metro we picked and explain why. Keeps visitors from
              wondering "why is Harold telling me about San Diego?" */}
          {metro && (
            <div style={{marginTop: 12, fontSize: 11, color: t.ink40, fontFamily: t.mono, letterSpacing:'0.05em'}}>
              {metro.source === 'ip'
                ? `Local segment: ${metro.label} — based on your IP address.`
                : `Local segment: ${metro.label} (example).`}
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

function MLAbout() {
  const t = window.mlTokens;
  const isMobile = window.useMobile();
  return (
    <section id="about" style={{position:'relative', zIndex: 2, padding: isMobile ? '56px 0 40px' : '96px 0 72px',
      maxWidth: 1200, margin:'0 auto'}}>
      {/* TOP: wide image + headline beside it */}
      <div style={{
        display:'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: isMobile ? 24 : 48,
        alignItems:'center',
      }}>
        <div style={{
          borderRadius: 28, overflow:'hidden',
          background:'linear-gradient(160deg, #FFE0B5 0%, #FF9E5C 100%)',
          padding: 8, boxShadow: t.card,
          position:'relative',
        }}>
          <div style={{
            borderRadius: 22, overflow:'hidden', position:'relative',
            aspectRatio: '16/9',
          }}>
            <img src="/assets/harold-studio.png" alt="Harold in the Harold newsroom"
              style={{width:'110%', height:'110%', objectFit:'cover', objectPosition:'center bottom', display:'block', position:'absolute', left:'-5%', bottom: 0}}/>
          </div>
        </div>

        <div style={{textAlign: isMobile ? 'left' : 'right'}}>
          <window.MLKicker>☀ MEET HAROLD</window.MLKicker>
          <h2 style={{
            fontFamily:'"DM Sans", sans-serif',
            fontSize: isMobile ? 36 : 52, lineHeight: 1.05, letterSpacing:'-0.035em',
            fontWeight: 700, margin: 0, color:'#2A1810',
          }}>
            The world is a zoo.<br/>
            <span style={{color: t.coral}}>Harold is your anchor.</span>
          </h2>
        </div>
      </div>

      {/* BOTTOM: paragraph full width, then stats full-width across bottom */}
      <div style={{marginTop: isMobile ? 28 : 44}}>
        <div style={{
          display:'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: isMobile ? 20 : 48,
        }}>
          <p style={{margin: 0, fontSize: isMobile ? 16 : 18, lineHeight: 1.65, color: t.ink80}}>
            Harold was built because the news is <em>exhausting.</em> Every headline
            designed to outrage. Every feed packed with ads. Every post demands a
            reaction. Harold just reports <em>what's happening now.</em><br/>
            We trust you to form your own opinions.
          </p>
          <p style={{margin: 0, fontSize: isMobile ? 16 : 18, lineHeight: 1.65, color: t.ink80}}>
            Like an owl, he's awake while you sleep. He reads news around the world,
            weighs the sources, strips the spin, and generates a custom, short
            <em> audio</em> briefing, and sends it via SMS. Listen whenever —
            no trigger-warning needed, every brief ends on some good news.
          </p>
        </div>

        <div style={{
          marginTop: 48, paddingTop: 36,
          borderTop:'1px solid rgba(42,24,16,0.12)',
          display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap: isMobile ? 12 : 20,
        }}>
          {[
            {n:'400+', l:'sources read every day'},
            {n:'5 min', l:'average briefing length'},
            {n:'0', l:'ads. forever.'},
          ].map((s,i)=>(
            <div key={i} style={{
              textAlign:'center',
              borderLeft: i===0 ? 'none' : '1px solid rgba(42,24,16,0.12)',
            }}>
              <div style={{fontFamily: t.sans, fontSize: isMobile ? 40 : 56, fontWeight: 700, color: t.coral, lineHeight: 1, letterSpacing:'-0.03em'}}>{s.n}</div>
              <div style={{fontSize: isMobile ? 12 : 14, color: t.ink60, marginTop: 10, lineHeight: 1.4}}>{s.l}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function MLPricing() {
  const t = window.mlTokens;
  const isMobile = window.useMobile();
  const [plan, setPlan] = React.useState('premium');
  // Homepage shows both monthly and annual pricing side-by-side without a toggle
  // so visitors can see both at a glance. The plan-selection step in the signup
  // wizard has the actual monthly/annual toggle for checkout.
  const priceBasic = '$3.50';
  const pricePrem = '$5';
  const per = '/mo';
  // Annual = monthly × 12 × 0.75 (25% off). Effective per-month is the
  // annual divided by 12, surfaced so users can see the discounted
  // per-month equivalent next to the headline monthly price.
  const annualBasic = '$31.50';        // 3.50 × 12 × 0.75
  const annualBasicPerMo = '$2.63';    // 31.50 / 12
  const annualPrem = '$45';            // 5 × 12 × 0.75
  const annualPremPerMo = '$3.75';     // 45 / 12

  const basicFeatures = ['US & World headlines','Morning briefing every day','One Good Story to close','7-day free trial — $0 today'];
  const premFeatures = ['Everything in The Harold Basic','Greeted by name each morning','Personalized segments & greeting','Your cities, teams & topics','Local weather & events','All segments — change anytime','7-day free trial — $0 today'];

  const goToSignup = () => {
    const el = document.getElementById('signup');
    if (el) el.scrollIntoView({behavior:'smooth'});
  };

  return (
    <section id="pricing" style={{position:'relative', zIndex: 2, padding: isMobile ? '48px 0' : '72px 0',
      maxWidth: 1100, margin:'0 auto'}}>
      <div style={{textAlign:'center', marginBottom: isMobile ? 28 : 40}}>
        <window.MLKicker>☀ PRICING</window.MLKicker>
        <window.MLH2>Two plans.</window.MLH2>
        <p style={{marginTop: 18, fontSize: 16, color: t.ink60, maxWidth: 560, margin:'18px auto 0'}}>
          7-day free trial — $0 charged today. Cancel anytime by texting STOP.
        </p>
      </div>

      <div style={{display:'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1.15fr', gap: isMobile ? 16 : 20}}>
        <div onClick={()=>setPlan('basic')} style={{
          background:'#fff', borderRadius: 24, padding: isMobile ? 24 : 36, cursor:'pointer',
          border: plan==='basic' ? `2px solid ${t.coral}` : '2px solid transparent',
          boxShadow: t.card,
        }}>
          <div style={{marginBottom: 14}}>
            <span style={{fontSize: 24, fontWeight: 700, letterSpacing:'-0.02em', color: t.ink}}>The Harold Basic</span>
            <div style={{fontSize: 13, color: t.ink40, marginTop: 4}}>For the casually informed</div>
          </div>
          <div style={{display:'flex', alignItems:'baseline', gap: 6, marginBottom: 6}}>
            <span style={{fontSize: isMobile ? 44 : 56, fontWeight: 700, letterSpacing:'-0.04em', lineHeight: 1, color: t.ink}}>{priceBasic}</span>
            <span style={{fontSize: 32, color: t.ink40, fontWeight: 500, letterSpacing:'-0.02em'}}>{per}</span>
          </div>
          <div style={{
            display:'inline-flex', alignItems:'center', gap: 8,
            padding:'6px 10px', borderRadius: 8,
            background:'rgba(255,90,45,0.06)',
            marginBottom: 14,
          }}>
            <span style={{
              fontFamily: t.mono, fontSize: 10, letterSpacing:'0.12em',
              fontWeight: 800, color: t.coral,
            }}>SAVE 25%</span>
            <span style={{fontSize: 12, color: t.ink60}}>
              with annual — <strong style={{color: t.ink}}>{annualBasic}/yr</strong> ({annualBasicPerMo}/mo)
            </span>
          </div>
          <p style={{fontSize: 14, lineHeight: 1.5, color: t.ink60, marginBottom: 22}}>
            One generic briefing each morning. ~2-3 min.
          </p>
          <ul style={{listStyle:'none', padding: 0, margin:'0 0 22px', display:'flex', flexDirection:'column', gap: 10}}>
            {basicFeatures.map(f=>(
              <li key={f} style={{display:'flex', alignItems:'center', gap: 10, fontSize: 14, color: t.ink80}}>
                <span style={{width: 20, height: 20, borderRadius: 999, background: t.coral, color:'#fff',
                  display:'flex', alignItems:'center', justifyContent:'center', flexShrink: 0}}>
                  <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round"><path d="M20 6L9 17l-5-5"/></svg>
                </span>
                <span>{f}</span>
              </li>
            ))}
            {['No personalization','No local news or weather','No local sports or events'].map(f=>(
              <li key={f} style={{display:'flex', alignItems:'center', gap: 10, fontSize: 14, color: t.ink40}}>
                <span style={{width: 20, height: 20, borderRadius: 999,
                  border:'1.5px solid rgba(42,24,16,0.2)',
                  display:'flex', alignItems:'center', justifyContent:'center', flexShrink: 0,
                  color: t.ink40,
                }}>
                  <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>
                </span>
                <span style={{textDecoration:'line-through'}}>{f}</span>
              </li>
            ))}
          </ul>
          <button onClick={(e)=>{e.stopPropagation(); goToSignup();}} style={{width:'100%', padding: 14, borderRadius: 12,
            border: `1.5px solid ${t.ink}`, background:'transparent',
            fontSize: 15, fontWeight: 600, color: t.ink, cursor:'pointer',
            fontFamily:'inherit', minHeight: 44}}>Start with The Harold Basic</button>
        </div>

        <div onClick={()=>setPlan('premium')} style={{
          background:'linear-gradient(160deg, #2A1810 0%, #4A2B1A 100%)',
          borderRadius: 24, padding: isMobile ? 24 : 36, cursor:'pointer',
          border: plan==='premium' ? `2px solid ${t.coral}` : '2px solid transparent',
          boxShadow: t.card,
          position:'relative',
        }}>
          <span style={{position:'absolute', top: -14, left: 32,
            padding:'6px 14px', borderRadius: 999,
            background: t.coral, color: t.cream,
            fontSize: 11, fontWeight: 700, letterSpacing:'0.05em',
          }}>Most popular</span>

          <div style={{marginBottom: 14}}>
            <span style={{fontSize: 24, fontWeight: 700, letterSpacing:'-0.02em', color: t.cream}}>The Harold Premium</span>
            <div style={{fontSize: 13, color:'rgba(255,243,230,0.6)', marginTop: 4}}>Made just for you</div>
          </div>
          <div style={{display:'flex', alignItems:'baseline', gap: 6, marginBottom: 6}}>
            <span style={{fontSize: isMobile ? 44 : 56, fontWeight: 700, letterSpacing:'-0.04em', lineHeight: 1, color: t.cream}}>{pricePrem}</span>
            <span style={{fontSize: 32, color:'rgba(255,243,230,0.65)', fontWeight: 500, letterSpacing:'-0.02em'}}>{per}</span>
          </div>
          <div style={{
            display:'inline-flex', alignItems:'center', gap: 8,
            padding:'6px 10px', borderRadius: 8,
            background:'rgba(255,228,176,0.12)',
            marginBottom: 14,
          }}>
            <span style={{
              fontFamily: t.mono, fontSize: 10, letterSpacing:'0.12em',
              fontWeight: 800, color: t.amber,
            }}>SAVE 25%</span>
            <span style={{fontSize: 12, color:'rgba(255,243,230,0.7)'}}>
              with annual — <strong style={{color: t.cream}}>{annualPrem}/yr</strong> ({annualPremPerMo}/mo)
            </span>
          </div>
          <p style={{fontSize: 14, lineHeight: 1.5, color:'rgba(255,243,230,0.8)', marginBottom: 22}}>
            Your morning briefing, made just for you — your cities, your teams, your topics, your greeting.
          </p>
          <ul style={{listStyle:'none', padding: 0, margin:'0 0 22px', display:'flex', flexDirection:'column', gap: 10}}>
            {premFeatures.map(f=>(
              <li key={f} style={{display:'flex', alignItems:'center', gap: 10, fontSize: 14, color:'rgba(255,243,230,0.9)'}}>
                <span style={{width: 20, height: 20, borderRadius: 999, background:'rgba(255,243,230,0.15)', color: t.amber,
                  display:'flex', alignItems:'center', justifyContent:'center', flexShrink: 0}}>
                  <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round"><path d="M20 6L9 17l-5-5"/></svg>
                </span>
                <span>{f}</span>
              </li>
            ))}
          </ul>
          <button onClick={(e)=>{e.stopPropagation(); goToSignup();}} style={{width:'100%', padding: 14, borderRadius: 12, border:'none',
            background: t.coral, color: t.cream, cursor:'pointer',
            fontSize: 15, fontWeight: 700, fontFamily:'inherit',
            boxShadow:'0 6px 20px rgba(255,90,45,0.35)', minHeight: 44}}>Get Harold — start free trial →</button>
        </div>
      </div>

      {/* Pricing justification */}
      <div style={{
        marginTop: isMobile ? 32 : 48,
        padding: isMobile ? '28px 24px' : '36px 48px',
        background:'rgba(42,24,16,0.04)',
        borderRadius: 20,
        border:'1px solid rgba(42,24,16,0.08)',
        maxWidth: 760, marginLeft:'auto', marginRight:'auto',
      }}>
        <p style={{fontSize: isMobile ? 15 : 16, lineHeight: 1.7, color: t.ink80, textAlign:'center', margin: 0}}>
          Most news is free because <strong>you're the product</strong>. Harold charges because we refuse to take money from anyone except you. No ads. No sponsors. No tracking. Your subscription covers the cost of AI research, voice generation, and daily SMS delivery — and that's it.
        </p>
        <div style={{marginTop: 20, display:'flex', justifyContent:'center', gap: isMobile ? 16 : 32, flexWrap:'wrap'}}>
          {['No ads. Ever.','No sponsors. Ever.','No tracking. Ever.'].map((badge, i) => (
            <div key={i} style={{
              display:'inline-flex', alignItems:'center', gap: 6,
              fontSize: 12, fontWeight: 700, color: t.coral,
              fontFamily: t.mono, letterSpacing:'0.04em',
            }}>
              <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round"><path d="M20 6L9 17l-5-5"/></svg>
              {badge}
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function MLFaq() {
  const t = window.mlTokens;
  const isMobile = window.useMobile();
  const faqs = [
    {q: 'How does the personalization work?', a: 'When you sign up, you pick your segments, your home city, favorite teams, and topics you care about. Harold writes and generates your briefing around those preferences. You can change them anytime by replying to the text.'},
    {q: 'How do I cancel?', a: 'Text the word STOP to Harold. That\'s it. You keep whatever days you\'ve already paid for.'},
    {q: 'Do you sell my phone number?', a: 'No. Your number is used for delivering Harold and for your Stripe billing receipt.'},
    {q: 'What sources does Harold read?', a: 'Over 400, across the political spectrum and the globe. Wire services (AP, Reuters), national papers, local papers, international outlets, tech blogs, and niche newsletters. Harold will add and remove sources as their quality shifts, but he\'s really just looking for the facts, without the bias.'},
    {q: 'Is this just AI-generated slop?', a: 'Harold uses AI to read, summarize, and narrate — but every briefing is checked for source diversity, factuality, and tone before it ships. No hallucinated stories. If we get something wrong, we correct it in the next briefing and tell you.'},
    {q: 'Will there ever be ads?', a: 'No. For realsies. Text STOP to cancel if we do. F* that.'},
  ];
  const [open, setOpen] = React.useState(0);

  return (
    <section id="faq" style={{position:'relative', zIndex: 2, padding: isMobile ? '48px 0' : '72px 0', maxWidth: 820, margin:'0 auto'}}>
      <div style={{textAlign:'center', marginBottom: isMobile ? 24 : 40}}>
        <window.MLKicker>☀ QUESTIONS</window.MLKicker>
        <window.MLH2>Stuff people ask.</window.MLH2>
      </div>
      <div style={{display:'flex', flexDirection:'column', gap: 10}}>
        {faqs.map((f, i) => {
          const isOpen = open === i;
          return (
            <div key={i} onClick={()=>setOpen(isOpen ? -1 : i)} style={{
              background: t.paper, borderRadius: 16,
              border: `1px solid ${isOpen ? 'rgba(255,90,45,0.35)' : 'rgba(42,24,16,0.08)'}`,
              padding: isMobile ? '16px 18px' : '20px 24px', cursor:'pointer',
              boxShadow: isOpen ? '0 8px 24px rgba(42,24,16,0.06)' : 'none',
              minHeight: 44,
            }}>
              <div style={{display:'flex', alignItems:'center', justifyContent:'space-between', gap: 16}}>
                <h3 style={{margin: 0, fontSize: isMobile ? 15 : 17, fontWeight: 700, color: t.ink, letterSpacing:'-0.01em'}}>{f.q}</h3>
                <span style={{width: 28, height: 28, borderRadius: 999,
                  background: isOpen ? t.coral : '#FFF3E6',
                  color: isOpen ? t.cream : t.ink, fontSize: 16, fontWeight: 700,
                  display:'flex', alignItems:'center', justifyContent:'center',
                  flexShrink: 0, transition:'all 0.15s',
                  minWidth: 28,
                }}>{isOpen ? '−' : '+'}</span>
              </div>
              {isOpen && <p style={{margin:'12px 0 0', fontSize: isMobile ? 14 : 15, lineHeight: 1.6, color: t.ink60, maxWidth: 640}}>{f.a}</p>}
            </div>
          );
        })}
      </div>
    </section>
  );
}

function MLFinalCta() {
  const t = window.mlTokens;
  const isMobile = window.useMobile();
  const scrollToSignup = () => {
    const el = document.getElementById('signup');
    if (el) el.scrollIntoView({behavior:'smooth'});
  };
  return (
    <section style={{position:'relative', zIndex: 2, padding: isMobile ? '24px 0 48px' : '40px 0 72px', maxWidth: 1100, margin:'0 auto'}}>
      <div style={{
        background:'linear-gradient(160deg, #FF7A4D 0%, #FF5A2D 100%)',
        borderRadius: 32, padding: isMobile ? '48px 24px' : '72px 56px', textAlign:'center',
        position:'relative', overflow:'hidden',
        boxShadow:'0 30px 60px rgba(255,90,45,0.3)',
      }}>
        <div style={{
          position:'absolute', top:-120, right:-80,
          width: 320, height: 320, borderRadius: 999,
          background:'radial-gradient(circle, rgba(255,228,176,0.4), transparent 70%)',
        }}/>
        <window.MLKicker color="rgba(255,243,230,0.85)">☀ READY WHEN YOU ARE</window.MLKicker>
        <h2 style={{
          fontFamily: t.sans, fontSize: isMobile ? 40 : 64, lineHeight: 0.98,
          letterSpacing:'-0.035em', fontWeight: 700, color: t.cream, margin: 0,
        }}>
          Your first briefing<br/>
          <span style={{fontStyle:'italic', fontWeight: 400}}>arrives tomorrow at 6:30am.</span>
        </h2>
        <p style={{marginTop: 22, fontSize: 17, color:'rgba(255,243,230,0.9)', maxWidth: 540, margin:'22px auto 0'}}>
          Seven days free. Cancel with one text. That's the whole pitch.
        </p>
        <button onClick={scrollToSignup} style={{
          marginTop: 32, background: t.ink, color: t.cream,
          border:'none', padding:'18px 36px', borderRadius: 14,
          fontSize: 16, fontWeight: 700, cursor:'pointer',
          fontFamily: t.sans, display:'inline-flex', alignItems:'center', gap: 12,
          boxShadow:'0 12px 30px rgba(42,24,16,0.3)',
          minHeight: 44,
        }}>
          Get Harold
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
        </button>
      </div>
    </section>
  );
}

/* Contact Modal */
function MLContactModal({ onClose }) {
  const t = window.mlTokens;
  const [name, setName] = React.useState('');
  const [email, setEmail] = React.useState('');
  const [message, setMessage] = React.useState('');
  const [status, setStatus] = React.useState('idle'); // idle | sending | sent | error

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!name.trim() || !email.trim() || !message.trim()) return;
    setStatus('sending');
    try {
      const res = await fetch('/api/contact', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: name.trim(), email: email.trim(), message: message.trim() }),
      });
      if (!res.ok) throw new Error('failed');
      setStatus('sent');
    } catch {
      setStatus('error');
    }
  };

  return (
    <div style={{
      position:'fixed', inset: 0, zIndex: 9999,
      background:'rgba(42,24,16,0.7)', backdropFilter:'blur(4px)',
      display:'flex', alignItems:'center', justifyContent:'center',
      padding: 16,
    }} onClick={onClose}>
      <div style={{
        background:'#FFF3E6', borderRadius: 24, padding: 32,
        maxWidth: 480, width:'100%', position:'relative',
        boxShadow:'0 24px 64px rgba(42,24,16,0.3)',
      }} onClick={e => e.stopPropagation()}>
        <button onClick={onClose} style={{
          position:'absolute', top: 16, right: 16,
          background:'transparent', border:'none', cursor:'pointer',
          fontSize: 20, color:'#2A1810', opacity: 0.5, lineHeight: 1,
          padding: 4,
        }}>✕</button>

        {status === 'sent' ? (
          <div style={{textAlign:'center', padding:'24px 0'}}>
            <div style={{fontSize: 48, marginBottom: 16}}>☀</div>
            <h3 style={{fontFamily:'"DM Sans", sans-serif', fontSize: 22, fontWeight: 700, color:'#2A1810', margin:'0 0 10px'}}>Got it, thanks.</h3>
            <p style={{fontSize: 15, color:'rgba(42,24,16,0.6)', margin: 0}}>We'll get back to you if needed.</p>
            <button onClick={onClose} style={{
              marginTop: 24, background:'#FF5A2D', color:'#FFF3E6',
              border:'none', padding:'12px 28px', borderRadius: 12,
              fontSize: 15, fontWeight: 600, cursor:'pointer', fontFamily:'inherit',
            }}>Close</button>
          </div>
        ) : (
          <>
            <h3 style={{fontFamily:'"DM Sans", sans-serif', fontSize: 22, fontWeight: 700, color:'#2A1810', margin:'0 0 6px'}}>Get in touch</h3>
            <p style={{fontSize: 14, color:'rgba(42,24,16,0.5)', margin:'0 0 24px'}}>Questions, feedback, or press inquiries.</p>
            <form onSubmit={handleSubmit} style={{display:'flex', flexDirection:'column', gap: 14}}>
              <input
                value={name} onChange={e=>setName(e.target.value)}
                placeholder="Your name" required
                style={{
                  padding:'12px 14px', borderRadius: 10, border:'1.5px solid rgba(42,24,16,0.15)',
                  fontSize: 15, fontFamily:'inherit', background:'#fff', color:'#2A1810',
                  outline:'none',
                }}
              />
              <input
                type="email" value={email} onChange={e=>setEmail(e.target.value)}
                placeholder="Email address" required
                style={{
                  padding:'12px 14px', borderRadius: 10, border:'1.5px solid rgba(42,24,16,0.15)',
                  fontSize: 15, fontFamily:'inherit', background:'#fff', color:'#2A1810',
                  outline:'none',
                }}
              />
              <textarea
                value={message} onChange={e=>setMessage(e.target.value)}
                placeholder="Your message" required rows={4}
                style={{
                  padding:'12px 14px', borderRadius: 10, border:'1.5px solid rgba(42,24,16,0.15)',
                  fontSize: 15, fontFamily:'inherit', background:'#fff', color:'#2A1810',
                  outline:'none', resize:'vertical', minHeight: 100,
                }}
              />
              {status === 'error' && (
                <p style={{fontSize: 13, color:'#E11D2E', margin: 0}}>Something went wrong. Try again.</p>
              )}
              <button type="submit" disabled={status==='sending'} style={{
                padding:'14px', borderRadius: 12, border:'none',
                background:'#FF5A2D', color:'#FFF3E6',
                fontSize: 15, fontWeight: 700, cursor:'pointer',
                fontFamily:'inherit', minHeight: 44,
                opacity: status==='sending' ? 0.7 : 1,
              }}>
                {status === 'sending' ? 'Sending…' : 'Send message →'}
              </button>
            </form>
          </>
        )}
      </div>
    </div>
  );
}

function MLFooter() {
  const t = window.mlTokens;
  const isMobile = window.useMobile();
  const [showContact, setShowContact] = React.useState(false);

  return (
    <>
      {showContact && <MLContactModal onClose={() => setShowContact(false)} />}
      <footer style={{position:'relative', zIndex: 2, padding:'40px 0 32px',
        borderTop:'1px solid rgba(42,24,16,0.1)',
        display:'flex', justifyContent:'space-between', alignItems: isMobile ? 'flex-start' : 'center',
        gap: 20, flexWrap:'wrap', flexDirection: isMobile ? 'column' : 'row'}}>
        <div style={{display:'flex', flexDirection:'column', gap: 8}}>
          <window.MLLogo small/>
        </div>
        <div style={{display:'flex', gap: 16, fontSize: 13, color: t.ink40, flexWrap:'wrap', alignItems:'center'}}>
          <a href="/privacy" style={{color: t.ink40, textDecoration:'none'}}>Privacy</a>
          <a href="/terms" style={{color: t.ink40, textDecoration:'none'}}>Terms</a>
          <button
            onClick={() => setShowContact(true)}
            style={{
              background:'transparent', border:'none', cursor:'pointer',
              color: t.ink40, fontSize: 13, fontFamily:'inherit', padding: 0,
            }}>
            Contact
          </button>
          <span>© 2026 The Harold</span>
        </div>
      </footer>
    </>
  );
}

window.MLListen = MLListen;
window.MLAbout = MLAbout;
window.MLPricing = MLPricing;
window.MLFaq = MLFaq;
window.MLFinalCta = MLFinalCta;
window.MLFooter = MLFooter;
