// mockups.jsx — Interactive visuals for the Sarah marketing site
// Components: HeroMockup, DemoPlayer, DemoTranscript, WhiteLabelVisual

const { useState, useEffect, useRef, useMemo } = React;

/* ─────────────────────────────────────────────────────────────
   HERO MOCKUP
   Animated phone showing the call lifecycle:
     ringing  →  Sarah answers (live waveform)  →  SMS arrives on owner's phone
   Cycles continuously.
───────────────────────────────────────────────────────────── */

function HeroMockup() {
  // 0: ringing, 1: in-call (waveform), 2: SMS arriving
  const [stage, setStage] = useState(0);
  const [elapsed, setElapsed] = useState(0);

  useEffect(() => {
    let frame;
    const t0 = performance.now();
    const tick = (t) => {
      const dt = (t - t0) / 1000;
      setElapsed(dt);
      frame = requestAnimationFrame(tick);
    };
    frame = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(frame);
  }, []);

  useEffect(() => {
    // Stage 0 (ringing) 2.4s → Stage 1 (call) 5.5s → Stage 2 (sms) 4.5s → loop
    const seq = [2400, 5500, 4500];
    const id = setTimeout(() => setStage((s) => (s + 1) % 3), seq[stage]);
    return () => clearTimeout(id);
  }, [stage]);

  return (
    <div style={{
      position: 'relative',
      width: '100%',
      aspectRatio: '0.92 / 1',
    }}>
      {/* Subtle decorative dots */}
      <DotGrid />

      {/* Caller phone (left) */}
      <Phone
        style={{
          position: 'absolute',
          left: '2%',
          top: '6%',
          width: '54%',
          transform: `rotate(-4deg) translateY(${stage === 0 ? 0 : -4}px)`,
          transition: 'transform .9s cubic-bezier(.22,.61,.36,1)',
          zIndex: 2,
        }}
      >
        <CallerScreen stage={stage} elapsed={elapsed} />
      </Phone>

      {/* Owner phone (right) — receives SMS */}
      <Phone
        style={{
          position: 'absolute',
          right: '0%',
          bottom: '0%',
          width: '52%',
          transform: `rotate(5deg) translateY(${stage === 2 ? -6 : 0}px)`,
          transition: 'transform .9s cubic-bezier(.22,.61,.36,1)',
          zIndex: 3,
        }}
      >
        <OwnerScreen stage={stage} />
      </Phone>

      {/* Floating annotation */}
      <FloatingLabel
        text={
          stage === 0 ? 'Incoming · 11:47 PM'
          : stage === 1 ? 'Sarah · live'
          : 'SMS · sent to owner'
        }
        accent={stage === 1}
        style={{ position: 'absolute', left: '46%', top: '2%' }}
      />
    </div>
  );
}

function DotGrid() {
  return (
    <svg
      style={{ position: 'absolute', inset: 0, opacity: 0.5, pointerEvents: 'none' }}
      width="100%" height="100%" aria-hidden="true"
    >
      <defs>
        <pattern id="dotgrid" x="0" y="0" width="22" height="22" patternUnits="userSpaceOnUse">
          <circle cx="1.2" cy="1.2" r="1.2" fill="#0F0F0F" opacity="0.08" />
        </pattern>
      </defs>
      <rect width="100%" height="100%" fill="url(#dotgrid)" />
    </svg>
  );
}

function FloatingLabel({ text, accent, style }) {
  return (
    <div style={{
      ...style,
      display: 'inline-flex', alignItems: 'center', gap: 8,
      padding: '7px 12px 7px 10px',
      borderRadius: 999,
      background: 'var(--bg)',
      border: '1px solid var(--line)',
      boxShadow: '0 18px 40px -22px rgba(0,0,0,.25)',
      fontFamily: 'var(--mono)',
      fontSize: 11,
      letterSpacing: '0.08em',
      textTransform: 'uppercase',
      color: 'var(--ink-2)',
      whiteSpace: 'nowrap',
    }}>
      <span style={{
        width: 7, height: 7, borderRadius: 999,
        background: accent ? 'var(--accent)' : 'var(--ink)',
        boxShadow: accent ? '0 0 0 4px color-mix(in oklab, var(--accent) 22%, transparent)' : 'none',
        animation: accent ? 'pulse 1.6s ease-in-out infinite' : 'none',
      }} />
      {text}
    </div>
  );
}

function Phone({ children, style }) {
  return (
    <div style={{
      ...style,
      borderRadius: 38,
      background: '#0F0F0F',
      padding: 7,
      boxShadow: '0 40px 80px -30px rgba(0,0,0,.35), 0 0 0 1px rgba(255,255,255,.04) inset',
    }}>
      <div style={{
        borderRadius: 32,
        overflow: 'hidden',
        background: '#0F0F0F',
        aspectRatio: '0.49 / 1',
        position: 'relative',
        color: 'white',
      }}>
        {children}
      </div>
    </div>
  );
}

function CallerScreen({ stage, elapsed }) {
  // Stage 0: ringing UI; Stage 1: in-call with Sarah; Stage 2: call ended
  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: stage === 0
        ? 'linear-gradient(180deg, #1f1f1f 0%, #0a0a0a 100%)'
        : stage === 1
        ? 'linear-gradient(180deg, #0c0c0c 0%, #0a0a0a 100%)'
        : 'linear-gradient(180deg, #141414 0%, #0a0a0a 100%)',
      transition: 'background .6s ease',
      color: 'white',
      display: 'flex', flexDirection: 'column',
      padding: '14px 18px 20px',
      fontFamily: 'var(--sans)',
      fontSize: 12,
    }}>
      {/* Status bar */}
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        fontSize: 11, color: 'rgba(255,255,255,.85)', letterSpacing: '-0.01em',
        padding: '0 6px',
      }}>
        <span style={{ fontWeight: 600 }}>11:47</span>
        <span style={{ display: 'inline-flex', gap: 4, alignItems: 'center', opacity: 0.85 }}>
          <SignalIcon /><WifiIcon /><BatteryIcon />
        </span>
      </div>

      {/* Body */}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center',
                    justifyContent: 'center', gap: 14, textAlign: 'center', padding: '8% 4%' }}>
        {stage === 0 && (
          <>
            <div style={{ fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase',
                          color: 'rgba(255,255,255,.55)' }}>Incoming call</div>
            <div style={{
              width: 84, height: 84, borderRadius: 999,
              background: 'linear-gradient(180deg, #1c1c1c, #0a0a0a)',
              border: '1px solid rgba(255,255,255,.08)',
              display: 'grid', placeItems: 'center',
              margin: '4px 0 2px',
              position: 'relative',
            }}>
              <div style={{ position: 'absolute', inset: -6, borderRadius: 999,
                            border: '1px solid rgba(255,255,255,.06)',
                            animation: 'ring-pulse 1.6s ease-out infinite' }} />
              <div style={{ position: 'absolute', inset: -14, borderRadius: 999,
                            border: '1px solid rgba(255,255,255,.04)',
                            animation: 'ring-pulse 1.6s ease-out infinite .35s' }} />
              <div style={{
                fontSize: 22, fontFamily: 'var(--serif)', fontStyle: 'italic',
              }}>S</div>
            </div>
            <div style={{ fontSize: 17, fontWeight: 500, letterSpacing: '-0.01em' }}>Sarah</div>
            <div style={{ fontSize: 11, color: 'rgba(255,255,255,.55)' }}>Anchor Plumbing · Receptionist</div>
          </>
        )}

        {stage === 1 && (
          <>
            <div style={{ fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase',
                          color: 'rgba(255,255,255,.55)' }}>
              <span style={{
                display: 'inline-block', width: 6, height: 6, borderRadius: 999,
                background: '#2bd17e', marginRight: 7, verticalAlign: 'middle',
                boxShadow: '0 0 0 4px rgba(43,209,126,.18)',
              }} />
              Connected · 00:{String(Math.min(Math.floor(elapsed * 60) % 60, 59)).padStart(2,'0')}
            </div>
            <div style={{ fontSize: 17, fontWeight: 500, letterSpacing: '-0.01em' }}>Sarah</div>
            <Waveform elapsed={elapsed} />
            <div style={{ fontSize: 11, color: 'rgba(255,255,255,.55)', maxWidth: '90%',
                          fontStyle: 'italic', fontFamily: 'var(--serif)', fontSize: 14, lineHeight: 1.3 }}>
              &ldquo;Of course. I can have someone out by 8&nbsp;AM. What&rsquo;s the address?&rdquo;
            </div>
          </>
        )}

        {stage === 2 && (
          <>
            <div style={{ fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase',
                          color: 'rgba(255,255,255,.55)' }}>Call ended · 02:14</div>
            <CheckBadge />
            <div style={{ fontSize: 17, fontWeight: 500, letterSpacing: '-0.01em' }}>Booked for tomorrow</div>
            <div style={{ fontSize: 11, color: 'rgba(255,255,255,.55)' }}>Anchor Plumbing · 8:00 AM</div>
          </>
        )}
      </div>

      {/* Bottom actions / hint */}
      <div style={{ display: 'flex', justifyContent: 'center', gap: 22, padding: '4px 0 0' }}>
        {stage === 0 && (
          <>
            <RoundBtn color="#c4452d" icon={<DeclineIcon />} />
            <RoundBtn color="#2bd17e" icon={<AcceptIcon />} pulse />
          </>
        )}
        {stage === 1 && (
          <>
            <RoundBtn color="rgba(255,255,255,.08)" icon={<MuteIcon />} />
            <RoundBtn color="rgba(255,255,255,.08)" icon={<KeypadIcon />} />
            <RoundBtn color="#c4452d" icon={<DeclineIcon />} />
          </>
        )}
        {stage === 2 && (
          <div style={{ fontSize: 11, color: 'rgba(255,255,255,.45)', letterSpacing: '0.06em' }}>
            Summary sent →
          </div>
        )}
      </div>
    </div>
  );
}

function Waveform({ elapsed }) {
  // 22 bars; vary heights with multiple sine components to feel like speech
  const bars = 22;
  const data = useMemo(() => Array.from({ length: bars }, (_, i) => ({
    a: 0.5 + Math.random() * 0.4,
    phase: Math.random() * Math.PI * 2,
    freq: 1.5 + Math.random() * 2.2,
  })), []);
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 4,
      height: 60, padding: '0 8px',
      width: '100%', justifyContent: 'center',
    }}>
      {data.map((d, i) => {
        const v = 0.18 + 0.82 * Math.abs(Math.sin(elapsed * d.freq + d.phase + i * 0.35)) * d.a;
        return (
          <div key={i} style={{
            width: 4, borderRadius: 2,
            height: `${Math.max(8, v * 56)}px`,
            background: 'linear-gradient(180deg, #fff, rgba(255,255,255,.6))',
            opacity: 0.4 + v * 0.6,
            transition: 'height .08s linear',
          }} />
        );
      })}
    </div>
  );
}

function RoundBtn({ color, icon, pulse }) {
  return (
    <div style={{
      width: 44, height: 44, borderRadius: 999, background: color,
      display: 'grid', placeItems: 'center',
      color: 'white',
      boxShadow: pulse ? '0 0 0 6px color-mix(in oklab, #2bd17e 22%, transparent)' : 'none',
      animation: pulse ? 'pulse-green 1.6s ease-in-out infinite' : 'none',
    }}>{icon}</div>
  );
}

function CheckBadge() {
  return (
    <div style={{
      width: 56, height: 56, borderRadius: 999,
      background: 'rgba(43,209,126,.14)',
      display: 'grid', placeItems: 'center',
      color: '#2bd17e',
      border: '1px solid rgba(43,209,126,.25)',
    }}>
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
           strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
        <polyline points="4,12.5 10,18 20,7"/>
      </svg>
    </div>
  );
}

/* Owner phone — SMS arriving */
function OwnerScreen({ stage }) {
  const show = stage === 2;
  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: 'linear-gradient(180deg, #F7F5F0 0%, #efebe2 100%)',
      color: '#0F0F0F',
      display: 'flex', flexDirection: 'column',
      padding: '14px 14px 18px',
      fontFamily: 'var(--sans)',
    }}>
      {/* Status bar */}
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        fontSize: 11, color: '#0F0F0F', padding: '0 6px',
      }}>
        <span style={{ fontWeight: 600 }}>11:49</span>
        <span style={{ display: 'inline-flex', gap: 4, alignItems: 'center', opacity: 0.7, color: '#0F0F0F' }}>
          <SignalIcon dark /><WifiIcon dark /><BatteryIcon dark />
        </span>
      </div>

      {/* SMS card */}
      <div style={{
        marginTop: 'auto', marginBottom: 'auto',
        transform: show ? 'translateY(0) scale(1)' : 'translateY(14px) scale(.96)',
        opacity: show ? 1 : 0.35,
        transition: 'transform .7s cubic-bezier(.22,.61,.36,1), opacity .7s ease',
      }}>
        <div style={{
          background: 'white',
          borderRadius: 14,
          padding: '12px 14px',
          boxShadow: '0 18px 30px -18px rgba(0,0,0,.25)',
          border: '1px solid rgba(0,0,0,.05)',
        }}>
          <div style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            marginBottom: 6,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
              <div style={{
                width: 16, height: 16, borderRadius: 4, background: '#0F0F0F',
                color: '#F7F5F0', display: 'grid', placeItems: 'center',
                fontSize: 9, fontWeight: 600,
              }}>6</div>
              <div style={{ fontSize: 11, fontWeight: 600 }}>Sarah · Anchor Plumbing</div>
            </div>
            <div style={{ fontSize: 9, color: 'rgba(0,0,0,.45)' }}>now</div>
          </div>
          <div style={{ fontSize: 11.5, lineHeight: 1.45, color: '#0F0F0F' }}>
            <strong style={{ fontWeight: 600 }}>New lead · Emergency</strong><br/>
            Jordan Reyes · (415) 555&#8209;0117<br/>
            Burst pipe under kitchen sink. Water shut off.<br/>
            <span style={{ color: '#1F8A5B' }}>✓ Booked: Tue 8:00 AM</span>
          </div>
          <div style={{
            marginTop: 8, paddingTop: 8, borderTop: '1px solid rgba(0,0,0,.06)',
            display: 'flex', gap: 6,
          }}>
            <Chip>Call back</Chip>
            <Chip>View transcript</Chip>
          </div>
        </div>
        {/* Second smaller toast for layered feel */}
        <div style={{
          marginTop: 8,
          background: 'rgba(255,255,255,.65)',
          borderRadius: 12, padding: '8px 12px',
          fontSize: 10.5, color: 'rgba(0,0,0,.6)',
          border: '1px solid rgba(0,0,0,.05)',
          display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        }}>
          <span>Calendar · Tue 8:00 AM</span>
          <span style={{ color: '#1F8A5B' }}>Confirmed</span>
        </div>
      </div>
    </div>
  );
}

function Chip({ children }) {
  return (
    <span style={{
      fontSize: 9.5, padding: '4px 8px', borderRadius: 999,
      background: 'rgba(0,0,0,.05)', color: '#0F0F0F', fontWeight: 500,
    }}>{children}</span>
  );
}

/* Tiny icons */
function SignalIcon({ dark }) {
  const c = dark ? '#0F0F0F' : 'white';
  return (
    <svg width="14" height="9" viewBox="0 0 16 10" fill="none">
      <rect x="0" y="7" width="2" height="3" rx=".5" fill={c}/>
      <rect x="3" y="5" width="2" height="5" rx=".5" fill={c}/>
      <rect x="6" y="3" width="2" height="7" rx=".5" fill={c}/>
      <rect x="9" y="1" width="2" height="9" rx=".5" fill={c}/>
    </svg>
  );
}
function WifiIcon({ dark }) {
  const c = dark ? '#0F0F0F' : 'white';
  return (
    <svg width="13" height="9" viewBox="0 0 15 10" fill="none" stroke={c} strokeWidth="1.4" strokeLinecap="round">
      <path d="M1 3.5C3 1.5 6 .5 7.5 .5S12 1.5 14 3.5"/>
      <path d="M3 6c1.3-1.3 3-2 4.5-2S10.7 4.7 12 6"/>
      <circle cx="7.5" cy="8.5" r=".9" fill={c} stroke="none"/>
    </svg>
  );
}
function BatteryIcon({ dark }) {
  const c = dark ? '#0F0F0F' : 'white';
  return (
    <svg width="20" height="10" viewBox="0 0 22 10" fill="none">
      <rect x="0.5" y="0.5" width="18" height="9" rx="2.2" stroke={c} strokeOpacity=".6"/>
      <rect x="2" y="2" width="13" height="6" rx="1" fill={c}/>
      <rect x="19.5" y="3" width="1.5" height="4" rx=".5" fill={c} fillOpacity=".6"/>
    </svg>
  );
}
function AcceptIcon()  { return <svg width="18" height="18" viewBox="0 0 24 24" fill="white"><path d="M20.01 15.38c-1.23 0-2.42-.2-3.53-.56-.35-.12-.74-.03-1.01.24l-1.57 1.97c-2.83-1.35-5.48-3.9-6.89-6.83l1.95-1.66c.27-.28.35-.67.24-1.02-.37-1.11-.56-2.3-.56-3.53 0-.54-.45-.99-.99-.99H4.19C3.65 3 3 3.24 3 3.99 3 13.28 10.73 21 20.01 21c.71 0 .99-.63.99-1.18v-3.45c0-.54-.45-.99-.99-.99z"/></svg>; }
function DeclineIcon() { return <svg width="18" height="18" viewBox="0 0 24 24" fill="white" style={{transform:'rotate(135deg)'}}><path d="M20.01 15.38c-1.23 0-2.42-.2-3.53-.56-.35-.12-.74-.03-1.01.24l-1.57 1.97c-2.83-1.35-5.48-3.9-6.89-6.83l1.95-1.66c.27-.28.35-.67.24-1.02-.37-1.11-.56-2.3-.56-3.53 0-.54-.45-.99-.99-.99H4.19C3.65 3 3 3.24 3 3.99 3 13.28 10.73 21 20.01 21c.71 0 .99-.63.99-1.18v-3.45c0-.54-.45-.99-.99-.99z"/></svg>; }
function MuteIcon()    { return <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="1.8" strokeLinecap="round"><path d="M3 3l18 18"/><path d="M12 4v10M9 9v3a3 3 0 0 0 5.5 1.5"/><path d="M6 11v1a6 6 0 0 0 9.5 4.9"/></svg>; }
function KeypadIcon()  { return <svg width="16" height="16" viewBox="0 0 24 24" fill="white"><circle cx="6" cy="6" r="1.5"/><circle cx="12" cy="6" r="1.5"/><circle cx="18" cy="6" r="1.5"/><circle cx="6" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="18" cy="12" r="1.5"/><circle cx="6" cy="18" r="1.5"/><circle cx="12" cy="18" r="1.5"/><circle cx="18" cy="18" r="1.5"/></svg>; }


/* ─────────────────────────────────────────────────────────────
   DEMO PLAYER + TRANSCRIPT (dark section)
───────────────────────────────────────────────────────────── */

const TRANSCRIPT = [
  { t: 0,    speaker: 'sarah',  text: "Hi, thanks for calling DMV Plumbing and HVAC. This is Sarah. What's going on?" },
  { t: 4,    speaker: 'caller', text: "Hi. So I'm currently having a problem with my bathroom sink. It's been draining slowly for, like, a few days now — are you guys able to handle something like that?" },
  { t: 15,   speaker: 'sarah',  text: "Absolutely. We handle slow and clogged drains all the time. Can I get your name?" },
  { t: 20,   speaker: 'caller', text: "Yeah. My name is Taylor." },
  { t: 22,   speaker: 'sarah',  text: "Thanks, Taylor. What's the best phone number for you just in case we get disconnected?" },
  { t: 26,   speaker: 'caller', text: "This number that I'm currently calling you at." },
  { t: 32,   speaker: 'sarah',  text: "I'll use the number you're calling from. Now, what's the service address for where the sink is clogged?" },
  { t: 36,   speaker: 'caller', text: "It is Maple Drive, Bethesda, Maryland." },
  { t: 40,   speaker: 'sarah',  text: "Perfect. Got it. Just to double-check — there isn't any water coming out onto the floor or overflowing right now, right?" },
  { t: 46,   speaker: 'caller', text: "No, it's not an emergency. There's no water spilling out. It's just slowly getting worse. I'd like someone to come out this week, in the afternoon." },
  { t: 55,   speaker: 'sarah',  text: "Does any day this week work better for you, or do you have a specific afternoon in mind for the appointment?" },
  { t: 60,   speaker: 'caller', text: "This Thursday afternoon." },
  { t: 62,   speaker: 'sarah',  text: "All right. Let me check on that. We've got Thursday afternoon open. Would you prefer the tech to arrive closer to 1 PM or more like 4 PM?" },
  { t: 70,   speaker: 'caller', text: "Closer to 1 PM would be perfect." },
  { t: 72,   speaker: 'sarah',  text: "Great. You're set for Thursday afternoon, arrival around 1 PM. The tech will text you when they're about thirty minutes away. Sound good?" },
  { t: 80,   speaker: 'caller', text: "Yeah. Thank you so much." },
  { t: 82,   speaker: 'sarah',  text: "Perfect. You're all set, Taylor. Thanks for calling DMV Plumbing and HVAC. Have a good one." },
];

const DEMO_AUDIO_SRC = 'assets/audio/sarah-demo.mp3';

function DemoPlayer() {
  const audioRef = useRef(null);
  const [playing, setPlaying] = useState(false);
  const [pos, setPos] = useState(0);
  const [duration, setDuration] = useState(0);
  const [waveform, setWaveform] = useState(null); // null = loading, [] = failed
  const [ready, setReady] = useState(false);

  // Decode the audio file once and extract peaks for the waveform.
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const res = await fetch(DEMO_AUDIO_SRC);
        const buf = await res.arrayBuffer();
        const AC = window.AudioContext || window.webkitAudioContext;
        const ctx = new AC();
        const audioBuf = await ctx.decodeAudioData(buf);
        if (cancelled) return;

        const bars = 64;
        const ch = audioBuf.getChannelData(0);
        const block = Math.floor(ch.length / bars);
        const peaks = new Array(bars);
        let max = 0;
        for (let i = 0; i < bars; i++) {
          let sum = 0;
          for (let j = 0; j < block; j++) {
            const v = ch[i * block + j] || 0;
            sum += v * v;
          }
          peaks[i] = Math.sqrt(sum / block); // RMS
          if (peaks[i] > max) max = peaks[i];
        }
        // Normalize & lift floor so very quiet sections still show a bar
        const normalized = peaks.map(v => Math.max(0.12, Math.min(1, (v / (max || 1)) * 1.1)));
        setWaveform(normalized);
        ctx.close && ctx.close();
      } catch (err) {
        // Fall back to synthetic waveform so the UI still works.
        console.warn('[Sarah demo] Could not decode audio:', err);
        const fallback = Array.from({ length: 64 }, (_, i) => {
          const v = 0.5
            + 0.32 * Math.sin(i * 0.55)
            + 0.22 * Math.sin(i * 1.31 + 1.7)
            + 0.18 * Math.sin(i * 2.07 + 0.4);
          return Math.max(0.18, Math.min(1, v));
        });
        if (!cancelled) setWaveform(fallback);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  // Hook up the <audio> element
  useEffect(() => {
    const a = audioRef.current;
    if (!a) return;
    const onTime = () => {
      setPos(a.currentTime);
      window.__demoPos = a.currentTime;
    };
    const onMeta = () => { setDuration(a.duration || 0); setReady(true); };
    const onEnd  = () => setPlaying(false);
    const onPlay = () => setPlaying(true);
    const onPause = () => setPlaying(false);
    a.addEventListener('timeupdate', onTime);
    a.addEventListener('loadedmetadata', onMeta);
    a.addEventListener('durationchange', onMeta);
    a.addEventListener('ended', onEnd);
    a.addEventListener('play', onPlay);
    a.addEventListener('pause', onPause);
    return () => {
      a.removeEventListener('timeupdate', onTime);
      a.removeEventListener('loadedmetadata', onMeta);
      a.removeEventListener('durationchange', onMeta);
      a.removeEventListener('ended', onEnd);
      a.removeEventListener('play', onPlay);
      a.removeEventListener('pause', onPause);
    };
  }, []);

  const toggle = () => {
    const a = audioRef.current;
    if (!a) return;
    if (a.ended) a.currentTime = 0;
    if (a.paused) a.play().catch(err => console.warn('[Sarah demo] play() failed:', err));
    else a.pause();
  };

  const fmt = (s) => {
    if (!isFinite(s) || s < 0) s = 0;
    return `${String(Math.floor(s/60)).padStart(2,'0')}:${String(Math.floor(s%60)).padStart(2,'0')}`;
  };

  const heights = waveform || Array.from({ length: 64 }, () => 0.4);
  const bars = heights.length;
  const progress = duration > 0 ? pos / duration : 0;

  const seek = (e) => {
    const a = audioRef.current;
    if (!a || !duration) return;
    const rect = e.currentTarget.getBoundingClientRect();
    const x = (e.clientX - rect.left) / rect.width;
    const p = Math.max(0, Math.min(1, x)) * duration;
    a.currentTime = p;
    setPos(p);
    window.__demoPos = p;
  };

  return (
    <div style={{
      background: 'rgba(247,245,240,0.04)',
      border: '1px solid rgba(247,245,240,0.08)',
      borderRadius: 24,
      padding: 28,
      display: 'flex', flexDirection: 'column', gap: 22,
      color: 'var(--bg)',
    }}>
      <audio ref={audioRef} src={DEMO_AUDIO_SRC} preload="metadata" style={{ display: 'none' }} />

      {/* Top row: caller + meta */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <div style={{
            width: 44, height: 44, borderRadius: 999,
            background: 'linear-gradient(180deg, #2a2a28, #0F0F0F)',
            border: '1px solid rgba(255,255,255,.08)',
            display: 'grid', placeItems: 'center',
            fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 22,
            color: 'var(--bg)',
          }}>S</div>
          <div style={{ display: 'flex', flexDirection: 'column' }}>
            <div style={{ fontSize: 15, fontWeight: 500 }}>Sarah · DMV Plumbing &amp; HVAC</div>
            <div style={{ fontSize: 12, color: 'rgba(247,245,240,.55)' }}>Inbound · Service request &amp; booking</div>
          </div>
        </div>
        <div style={{
          fontFamily: 'var(--mono)', fontSize: 11, color: 'rgba(247,245,240,.55)',
          letterSpacing: '0.08em', textTransform: 'uppercase',
        }}>
          {fmt(pos)} / {fmt(duration)}
        </div>
      </div>

      {/* Waveform */}
      <div
        onClick={seek}
        style={{
          height: 96, display: 'flex', alignItems: 'center', gap: 3,
          cursor: ready ? 'pointer' : 'default', userSelect: 'none', padding: '0 2px',
          position: 'relative',
          opacity: waveform ? 1 : 0.6,
          transition: 'opacity .4s ease',
          minWidth: 0, overflow: 'hidden',
        }}
      >
        {heights.map((h, i) => {
          const filled = (i / bars) <= progress;
          const playingHere = filled && Math.abs(i / bars - progress) < 0.04;
          const wobble = playing && playingHere ? Math.sin(performance.now() / 80 + i) * 0.18 : 0;
          return (
            <div key={i} style={{
              flex: '1 1 0',
              minWidth: 0,
              height: `${Math.max(8, (h + wobble) * 80)}px`,
              borderRadius: 2,
              background: filled
                ? 'linear-gradient(180deg, var(--bg), rgba(247,245,240,.65))'
                : 'rgba(247,245,240,0.2)',
              transition: filled ? 'none' : 'background .3s ease',
            }} />
          );
        })}
      </div>

      {/* Controls */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
        <button
          onClick={toggle}
          disabled={!ready}
          aria-label={playing ? 'Pause' : 'Play'}
          style={{
            width: 56, height: 56, borderRadius: 999,
            border: 'none', cursor: ready ? 'pointer' : 'wait',
            background: 'var(--bg)', color: 'var(--ink)',
            display: 'grid', placeItems: 'center',
            boxShadow: '0 12px 30px -12px rgba(0,0,0,.6)',
            transition: 'transform .2s ease',
            opacity: ready ? 1 : 0.55,
          }}
          onMouseDown={(e) => e.currentTarget.style.transform = 'scale(.96)'}
          onMouseUp={(e) => e.currentTarget.style.transform = 'scale(1)'}
          onMouseLeave={(e) => e.currentTarget.style.transform = 'scale(1)'}
        >
          {playing
            ? <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><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="18" height="18" viewBox="0 0 24 24" fill="currentColor" style={{transform:'translateX(1px)'}}><path d="M7 4.5v15l13-7.5-13-7.5z"/></svg>
          }
        </button>
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 4 }}>
          <div style={{ fontSize: 14, fontWeight: 500 }}>
            {!ready ? "Loading the call…" : playing ? "Playing the live call demo" : pos > 0 && pos >= duration - 0.1 ? "Replay the call" : "Press play to hear Sarah"}
          </div>
          <div style={{ fontSize: 12, color: 'rgba(247,245,240,.55)' }}>
            Real customer scenario · greeting to handoff
          </div>
        </div>
        <a href="https://calendly.com/kalif-6ssdesign/30min" target="_blank" rel="noopener" className="btn-link" style={{ color: 'var(--bg)', borderColor: 'rgba(247,245,240,.25)' }}>
          Book a demo <span className="arr">→</span>
        </a>
      </div>
    </div>
  );
}

function DemoTranscript() {
  const [pos, setPos] = useState(0);
  // Listen to the player's position via a custom hook — we use a global event
  useEffect(() => {
    let frame;
    const tick = () => {
      const p = window.__demoPos || 0;
      setPos(p);
      frame = requestAnimationFrame(tick);
    };
    frame = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(frame);
  }, []);

  // Active line is the last one whose t <= pos
  const activeIdx = TRANSCRIPT.reduce((acc, l, i) => l.t <= pos ? i : acc, -1);

  return (
    <div style={{
      background: 'rgba(247,245,240,0.04)',
      border: '1px solid rgba(247,245,240,0.08)',
      borderRadius: 24,
      padding: 28,
      display: 'flex', flexDirection: 'column', gap: 14,
      maxHeight: 440, overflow: 'hidden',
    }}>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        paddingBottom: 12, borderBottom: '1px solid rgba(247,245,240,.08)',
      }}>
        <div style={{
          fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.1em',
          textTransform: 'uppercase', color: 'rgba(247,245,240,.55)',
        }}>Live Transcript</div>
        <div style={{ fontSize: 11, color: 'rgba(247,245,240,.55)' }}>auto-syncs with audio</div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14, overflowY: 'hidden' }}>
        {TRANSCRIPT.map((l, i) => {
          const isActive = i === activeIdx;
          const isPast = i < activeIdx;
          const isFuture = i > activeIdx && activeIdx >= 0;
          const sarah = l.speaker === 'sarah';
          return (
            <div key={i} style={{
              display: 'flex', flexDirection: 'column', gap: 4,
              opacity: isFuture ? 0.35 : isPast ? 0.55 : 1,
              transform: isActive ? 'translateX(0)' : 'translateX(-2px)',
              transition: 'opacity .4s ease, transform .4s ease',
            }}>
              <div style={{
                display: 'flex', gap: 8, alignItems: 'center',
                fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.1em',
                textTransform: 'uppercase',
                color: sarah ? 'var(--accent)' : 'rgba(247,245,240,.55)',
              }}>
                <span>{sarah ? 'Sarah' : 'Caller'}</span>
                <span style={{ color: 'rgba(247,245,240,.35)' }}>· {String(Math.floor(l.t)).padStart(2,'0')}s</span>
              </div>
              <div style={{
                fontSize: 15, lineHeight: 1.45,
                color: isActive ? 'var(--bg)' : 'rgba(247,245,240,.78)',
                fontWeight: isActive ? 500 : 400,
              }}>{l.text}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}


/* ─────────────────────────────────────────────────────────────
   WHITE-LABEL VISUAL
   Shows three "client brands" being served by one Sarah engine.
───────────────────────────────────────────────────────────── */

function WhiteLabelVisual() {
  const clients = [
    { name: "Northwind HVAC",   color: "#2F6BFF", initials: "N",  service: "Heating · Cooling" },
    { name: "Beacon Roofing",   color: "#B89B6A", initials: "B",  service: "Roofing · Restoration" },
    { name: "Cypress Plumbing", color: "#1F8A5B", initials: "C",  service: "Emergency · Service" },
  ];

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <div style={{
        fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.1em',
        textTransform: 'uppercase', color: 'var(--ink-3)',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
      }}>
        <span>Partner Console · 3 Active Lines</span>
        <span style={{ display:'inline-flex', alignItems:'center', gap: 6 }}>
          <span className="status-dot" style={{ width: 6, height: 6 }} />
          All on-call
        </span>
      </div>

      {clients.map((c, i) => (
        <ClientRow key={c.name} client={c} delay={i * 0.4} />
      ))}

      <div style={{
        marginTop: 6, paddingTop: 14, borderTop: '1px solid var(--line)',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        fontSize: 13, color: 'var(--ink-3)',
      }}>
        <span>One engine · your brand on every call</span>
        <span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-2)' }}>6SS · managed</span>
      </div>
    </div>
  );
}

function ClientRow({ client, delay }) {
  const [t, setT] = useState(0);
  useEffect(() => {
    let frame;
    const t0 = performance.now() / 1000 + delay;
    const tick = () => {
      setT(performance.now() / 1000 - t0);
      frame = requestAnimationFrame(tick);
    };
    frame = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(frame);
  }, [delay]);

  const bars = 16;
  const heights = useMemo(() => Array.from({ length: bars }, () => ({
    phase: Math.random() * Math.PI * 2,
    freq: 1.5 + Math.random() * 2.4,
    amp: 0.6 + Math.random() * 0.4,
  })), []);

  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 14,
      padding: '14px 4px',
      borderBottom: '1px solid var(--line)',
    }}>
      <div style={{
        width: 32, height: 32, borderRadius: 8,
        background: client.color, color: 'white',
        display: 'grid', placeItems: 'center',
        fontWeight: 600, fontSize: 13,
      }}>{client.initials}</div>
      <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 14, fontWeight: 500 }}>{client.name}</div>
        <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>{client.service}</div>
      </div>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 2,
        width: 80, height: 22,
      }}>
        {heights.map((h, i) => {
          const v = 0.2 + 0.8 * Math.abs(Math.sin(t * h.freq + h.phase + i * 0.4)) * h.amp;
          return (
            <div key={i} style={{
              flex: 1, height: `${Math.max(3, v * 18)}px`,
              borderRadius: 1,
              background: client.color,
              opacity: 0.35 + v * 0.5,
            }} />
          );
        })}
      </div>
      <div style={{
        fontFamily: 'var(--mono)', fontSize: 10, color: 'var(--ink-3)',
        letterSpacing: '0.06em', minWidth: 38, textAlign: 'right',
      }}>
        {String(Math.floor((t + 12) % 60)).padStart(2,'0')}s
      </div>
    </div>
  );
}

/* Expose to global scope so app.jsx can use them */
Object.assign(window, { HeroMockup, DemoPlayer, DemoTranscript, WhiteLabelVisual });

/* Ring-pulse keyframes injected from JS */
(function injectKeyframes() {
  if (document.getElementById('__sarah_kf')) return;
  const s = document.createElement('style');
  s.id = '__sarah_kf';
  s.textContent = `
    @keyframes ring-pulse {
      0% { transform: scale(1); opacity: 1; }
      100% { transform: scale(1.45); opacity: 0; }
    }
  `;
  document.head.appendChild(s);
})();
