// Polycode marketing — animated hero mock of the macOS app.
// Lightweight: no Stage. A single React component drives a looping timeline
// in requestAnimationFrame, replays the fan-out → consensus story used in the
// 30s teaser, but condensed to ~14s and tuned to fit a 1180×680 frame.

const HERO_DUR = 14.0;       // seconds, then loop
const HERO_W = 1180, HERO_H = 680;
const HERO_SIDEBAR_W = 188;
const HERO_INSP_W = 280;

const HERO_PROV = [
  { p: 'anthropic',  full: 'Claude Sonnet 4.6',   col: '#C96442', primary: true,  ms: 1240 },
  { p: 'openai',     full: 'GPT-5',               col: '#4C8C7A', primary: false, ms:  980 },
  { p: 'gemini',     full: 'Gemini 2.5 Pro',      col: '#4F7AC9', primary: false, ms: 1420 },
  { p: 'foundation', full: 'Apple Intelligence',  col: '#6B7280', primary: false, ms:  410 },
];

const ec = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
const eo = (t) => 1 - Math.pow(1 - t, 3);
const cl = (v, lo, hi) => Math.max(lo, Math.min(hi, v));

function useLoopTime(duration) {
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    let raf, t0 = performance.now();
    const tick = (now) => {
      const dt = (now - t0) / 1000;
      setT(dt % duration);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [duration]);
  return t;
}

function HeroAppMock() {
  const t = useLoopTime(HERO_DUR);
  // Timeline (s):
  // 0.0–2.4  question types
  // 2.4–3.0  send + user bubble lands
  // 3.0–7.0  fan-out: provider chips stream
  // 6.5–7.5  inspector slides in
  // 7.0–11.5 consensus answer types in
  // 11.5–13.5 hold
  // 13.5–14   gentle reset

  // Question
  const QUESTION = "What's the best way to handle a flaky test in CI?";
  const typeProg = cl((t - 0.2) / 2.0, 0, 1);
  const typedQ = QUESTION.slice(0, Math.floor(typeProg * QUESTION.length));
  const sent = t > 2.4;
  const userF = eo(cl((t - 2.4) / 0.5, 0, 1));

  // Pill row mounts at 3.0
  const pillsT0 = 3.0;

  // Inspector slide-in
  const inspF = eo(cl((t - 6.5) / 0.7, 0, 1));

  // Answer
  const ansT0 = 7.0, ansT1 = 11.5;
  const ANSWER = "Quarantine first, then triage. Move the failing test to a flaky lane that still runs but doesn't gate the merge — that stops the bleeding. Then write a deterministic repro: pin time, seed randomness, isolate races.";
  const aProg = cl((t - ansT0) / (ansT1 - ansT0), 0, 1);
  const ansChars = Math.floor(ec(aProg) * ANSWER.length);
  const ansShown = ANSWER.slice(0, ansChars);
  const ansFade = eo(cl((t - ansT0) / 0.4, 0, 1));

  return (
    <div className="win" style={{ aspectRatio: `${HERO_W} / ${HERO_H}`, height: 'auto' }}>
      <div className="win-titlebar">
        <div className="tlights"><span className="red"/><span className="yel"/><span className="grn"/></div>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginLeft:8, color:'var(--pc-content-tertiary)'}}>
          <Icon name="panel" size={14}/>
          <Icon name="plus" size={14}/>
        </div>
        <div className="win-title">
          <PolycodeIcon size={16}/>
          <span>New session</span>
          <span style={{color:'var(--pc-content-tertiary)', fontWeight:500}}>— polycode-apple</span>
        </div>
        <div className="win-titlebar-actions">
          <Icon name="shield" size={14}/>
          <Icon name="panelR" size={14}/>
        </div>
      </div>

      <div style={{
        flex:1, display:'flex', minHeight:0, position:'relative',
        background:'var(--pc-surface-canvas)',
      }}>
        <HeroSidebar/>

        {/* main column */}
        <div style={{ flex:1, minWidth:0, display:'flex', flexDirection:'column', position:'relative',
          marginRight: inspF * HERO_INSP_W,
          transition: 'margin-right 600ms cubic-bezier(0.4,0,0.2,1)' }}>
          <div style={{ flex:1, minWidth:0, padding:'18px 22px 6px', overflow:'hidden', position:'relative' }}>
            {/* user bubble */}
            {sent && (
              <div style={{
                display:'flex', justifyContent:'flex-end', marginBottom:14,
                opacity:userF, transform:`translateY(${(1-userF)*10}px)`,
              }}>
                <div style={{
                  maxWidth:'74%', padding:'9px 13px', borderRadius:10,
                  background:'var(--pc-user-bubble)',
                  boxShadow:'inset 0 0 0 0.5px rgba(28,25,21,0.10)',
                  fontSize:13.5, lineHeight:1.5, color:'var(--pc-content-primary)',
                }}>{QUESTION}</div>
              </div>
            )}

            {/* fan-out pill row */}
            {t >= pillsT0 - 0.1 && (() => {
              const f = eo(cl((t - pillsT0) / 0.5, 0, 1));
              return (
                <div style={{
                  display:'flex', alignItems:'flex-start', gap:10,
                  opacity:f, transform:`translateY(${(1-f)*8}px)`, marginBottom:12,
                }}>
                  <div style={{ paddingTop:2 }}><PolycodeIcon size={28}/></div>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{
                      display:'flex', alignItems:'center', gap:6, marginBottom:8,
                      fontFamily:FONT_MONO, fontSize:10.5, fontWeight:600,
                      letterSpacing:'0.10em', textTransform:'uppercase',
                      color:'var(--pc-content-tertiary)',
                    }}>
                      <Icon name="sparkles" size={11} color="var(--pc-accent-solid)"/>
                      Consensus of 4
                    </div>
                    <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
                      {HERO_PROV.map((x, i) => {
                        const tIn = pillsT0 + 0.4 + i * 0.18;
                        const o = eo(cl((t - tIn) / 0.4, 0, 1));
                        const dy = (1 - o) * 6;
                        const streamStart = tIn + 0.15;
                        const streamDur = (x.ms / 1000) * 1.4;
                        const prog = ec(cl((t - streamStart) / streamDur, 0, 1));
                        const settled = prog >= 1.0;
                        return (
                          <span key={x.p} className={"provider-chip " + (x.primary ? 'primary' : '')}
                            style={{
                              opacity:o, transform:`translateY(${dy}px)`,
                              height:26, padding:'0 9px 0 4px', fontSize:11.5, gap:6,
                            }}>
                            <ProviderTile provider={x.p} size={18}/>
                            <span style={{ fontWeight: x.primary ? 600 : 500 }}>{x.full}</span>
                            {x.primary && <Icon name="crown" size={9} color="var(--pc-accent-solid)" strokeWidth={2.2}/>}
                            <span className="ms">{(x.ms/1000).toFixed(2)}s</span>
                            <span style={{
                              width:36, height:3, borderRadius:2,
                              background:'rgba(28,25,21,0.08)', overflow:'hidden', position:'relative',
                            }}>
                              <span style={{
                                position:'absolute', inset:0, width:`${prog * 100}%`,
                                background: settled ? 'var(--pc-status-success)' : (x.primary ? 'var(--pc-accent-solid)' : x.col),
                                borderRadius:2,
                              }}/>
                            </span>
                            <span style={{
                              fontFamily:FONT_MONO, fontSize:10, fontWeight:600,
                              color: settled ? 'var(--pc-status-success)' : 'var(--pc-content-tertiary)',
                              minWidth:8, textAlign:'center',
                            }}>{settled ? '✓' : '·'}</span>
                          </span>
                        );
                      })}
                    </div>

                    {/* answer */}
                    {t >= ansT0 - 0.05 && (
                      <div style={{
                        marginTop:14, opacity:ansFade,
                        fontSize:14.5, lineHeight:1.55, color:'var(--pc-content-primary)',
                        textWrap:'pretty',
                      }}>
                        {ansShown}
                        {aProg > 0 && aProg < 1 && Math.floor(t*2) % 2 === 0 && (
                          <span style={{
                            display:'inline-block', width:7, height:15, background:'var(--pc-accent-solid)',
                            marginLeft:2, verticalAlign:'text-bottom',
                          }}/>
                        )}
                        {aProg >= 1 && (
                          <span style={{
                            display:'inline-flex', alignItems:'center', gap:5,
                            verticalAlign:'middle',
                            marginLeft:6,
                            padding:'1px 7px 1px 4px',
                            background:'var(--pc-surface-elevated)',
                            boxShadow:'inset 0 0 0 0.5px rgba(28,25,21,0.10)',
                            borderRadius:999,
                          }}>
                            <span style={{ display:'inline-flex' }}>
                              {['anthropic','openai','gemini','foundation'].map((p,i)=>(
                                <span key={p} style={{ marginLeft:i===0?0:-4, boxShadow:'0 0 0 1.5px var(--pc-surface-elevated)', borderRadius:999 }}>
                                  <ProviderTile provider={p} size={11}/>
                                </span>
                              ))}
                            </span>
                            <span style={{ fontSize:9.5, fontWeight:600, fontFamily:FONT_MONO, color:'var(--pc-status-success)', letterSpacing:'0.04em' }}>4/4 agree</span>
                          </span>
                        )}
                      </div>
                    )}
                  </div>
                </div>
              );
            })()}
          </div>

          {/* composer */}
          <HeroComposer typed={typedQ} sent={sent} t={t}/>
        </div>

        <HeroInspector f={inspF} t={t}/>
      </div>
    </div>
  );
}

function HeroSidebar() {
  return (
    <div style={{
      width: HERO_SIDEBAR_W, flexShrink:0, height:'100%',
      background:'var(--pc-surface-sidebar)',
      borderRight:'0.5px solid var(--pc-border-subtle)',
      display:'flex', flexDirection:'column',
      padding:'10px 8px',
    }}>
      <div style={{
        display:'flex', alignItems:'center', gap:8,
        padding:'6px 8px', borderRadius:6,
        background:'var(--pc-surface-elevated)',
        boxShadow:'inset 0 0 0 0.5px var(--pc-border-subtle)',
        marginBottom:10,
      }}>
        <span style={{ width:16, height:16, borderRadius:4, background:'#C2723A',
          display:'inline-flex', alignItems:'center', justifyContent:'center' }}>
          <span style={{ width:6, height:6, borderRadius:1, background:'rgba(255,255,255,0.7)' }}/>
        </span>
        <span style={{ fontSize:11.5, fontWeight:600, letterSpacing:'-0.005em', flex:1, minWidth:0,
          whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>polycode-apple</span>
        <Icon name="chevronD" size={9} color="var(--pc-content-tertiary)"/>
      </div>
      <div style={{
        display:'flex', alignItems:'center', gap:6,
        padding:'5px 8px', borderRadius:5,
        background:'rgba(28,25,21,0.04)',
        fontSize:10.5, color:'var(--pc-content-tertiary)',
      }}>
        <span style={{ width:9, height:9, borderRadius:'50%', boxShadow:'inset 0 0 0 1.4px currentColor' }}/>
        <span style={{ flex:1 }}>Search</span>
        <span style={{ fontFamily:FONT_MONO, fontSize:9.5 }}>⌘F</span>
      </div>

      {[
        { name:'polycode-apple', dot:'#C2723A', items:[
          { t:'New session', s:'— in flight', sel:true },
          { t:'Flaky test triage', s:'Consensus · 6' },
          { t:'SwiftData migration', s:'Opus 4 · 8' },
        ]},
        { name:'consensus-engine', dot:'#3F6D8C', items:[
          { t:'Provider golden fixtures', s:'Gemini · 5' },
          { t:'MCP registry filter UX', s:'Consensus · 4' },
        ]},
      ].map((proj, pi) => (
        <div key={pi} style={{ marginTop:12 }}>
          <div style={{
            display:'flex', alignItems:'center', gap:6,
            padding:'4px 8px',
            fontFamily:FONT_MONO, fontSize:10, color:'var(--pc-content-secondary)',
          }}>
            <Icon name="chevronD" size={8} color="var(--pc-content-tertiary)"/>
            <span style={{ width:6, height:6, borderRadius:1.5, background:proj.dot, marginRight:2 }}/>
            <span style={{ fontWeight:600 }}>{proj.name}</span>
          </div>
          {proj.items.map((r, i) => (
            <div key={i} style={{
              margin:'1px 4px', padding:'5px 8px 5px 14px', borderRadius:5,
              background: r.sel ? 'rgba(197,90,31,0.10)' : 'transparent',
              boxShadow: r.sel ? 'inset 0 0 0 0.5px rgba(197,90,31,0.20)' : 'none',
            }}>
              <div style={{ fontSize:11, fontWeight: r.sel ? 600 : 500, color:'var(--pc-content-primary)',
                whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{r.t}</div>
              <div style={{ fontSize:10, color:'var(--pc-content-tertiary)', marginTop:1 }}>{r.s}</div>
            </div>
          ))}
        </div>
      ))}

      <div style={{ flex:1 }}/>
      <div style={{
        display:'flex', alignItems:'center', gap:6,
        padding:'8px 6px', borderTop:'0.5px solid var(--pc-border-subtle)',
        fontSize:10.5, color:'var(--pc-content-tertiary)',
      }}>
        <span style={{ width:6, height:6, borderRadius:'50%', background:'var(--pc-status-success)',
          boxShadow:'0 0 0 2.5px rgba(46,125,91,0.18)' }}/>
        MCP · 3 connected
      </div>
    </div>
  );
}

function HeroComposer({ typed, sent, t }) {
  // Pre-send: glowing focus. Post-send: muted.
  return (
    <div style={{ padding:'10px 22px 16px', position:'relative' }}>
      <div style={{
        background:'var(--pc-surface-elevated)',
        borderRadius:10,
        boxShadow: !sent && t > 0.4
          ? 'inset 0 0 0 0.75px var(--pc-accent-solid), 0 0 0 4px rgba(197,90,31,0.14), 0 1px 2px rgba(0,0,0,0.04)'
          : 'inset 0 0 0 0.5px var(--pc-border-standard), 0 1px 2px rgba(0,0,0,0.04)',
      }}>
        <div style={{
          padding:'10px 14px',
          fontSize:13.5, lineHeight:1.5,
          color: typed ? 'var(--pc-content-primary)' : 'var(--pc-content-tertiary)',
          minHeight:42,
        }}>
          {sent ? 'Reply to Polycode…' : (typed || 'Ask anything · drop files · @mention project files')}
          {!sent && typed && Math.floor(t*2) % 2 === 0 && (
            <span style={{
              display:'inline-block', width:7, height:15, background:'var(--pc-accent-solid)',
              marginLeft:2, verticalAlign:'text-bottom',
            }}/>
          )}
        </div>
        <div style={{
          display:'flex', alignItems:'center', gap:8,
          padding:'7px 9px', borderTop:'0.5px solid var(--pc-border-subtle)',
        }}>
          <span style={{
            display:'inline-flex', alignItems:'center', gap:6,
            padding:'3px 8px 3px 4px', borderRadius:14,
            background:'var(--pc-surface-sidebar)',
            boxShadow:'inset 0 0 0 0.5px var(--pc-border-subtle)',
            fontSize:10.5, color:'var(--pc-content-secondary)',
          }}>
            <span style={{ display:'flex' }}>
              {HERO_PROV.map((p, i) => (
                <span key={p.p} style={{ marginLeft: i === 0 ? 0 : -5, position:'relative', zIndex: 10-i }}>
                  <ProviderTile provider={p.p} size={14}/>
                </span>
              ))}
            </span>
            <span style={{ color:'var(--pc-content-primary)', fontWeight:500 }}>4 models</span>
            <span style={{ opacity:0.4 }}>·</span>
            <span>primary</span>
            <ProviderTile provider="anthropic" size={11}/>
            <span style={{ color:'var(--pc-content-primary)', fontWeight:500 }}>Claude</span>
          </span>
          <div style={{ flex:1 }}/>
          <span style={{ fontFamily:FONT_MONO, fontSize:10.5, color:'var(--pc-content-tertiary)' }}>
            ≈ {Math.max(8, (typed||'').length * 4)} tok · $0.001
          </span>
          <span style={{
            display:'inline-flex', alignItems:'center', gap:4,
            padding:'4px 10px', borderRadius:5,
            background: typed && !sent ? 'var(--pc-accent-gradient)' : 'var(--pc-surface-sidebar)',
            color: typed && !sent ? 'white' : 'var(--pc-content-tertiary)',
            fontSize:10.5, fontWeight:500,
            boxShadow: typed && !sent
              ? 'inset 0 1px 0 rgba(255,255,255,0.2), 0 1px 2px rgba(0,0,0,0.15)'
              : 'inset 0 0 0 0.5px var(--pc-border-subtle)',
          }}>
            <Icon name="send" size={10} color={typed && !sent ? 'white' : 'var(--pc-content-tertiary)'}/>
            Send
          </span>
        </div>
      </div>
    </div>
  );
}

function HeroInspector({ f, t }) {
  if (f < 0.01) return null;
  return (
    <div style={{
      position:'absolute', top:0, bottom:0, right:0, width: HERO_INSP_W,
      background:'#F5EFE3',
      borderLeft:'0.5px solid var(--pc-border-subtle)',
      transform:`translateX(${(1-f)*HERO_INSP_W}px)`, opacity:f,
      padding:'14px 14px',
      display:'flex', flexDirection:'column', gap:8,
    }}>
      <div style={{ display:'flex', alignItems:'center', gap:7 }}>
        <Icon name="inspector" size={12} color="var(--pc-content-secondary)"/>
        <span style={{ fontSize:11.5, fontWeight:600 }}>Provider trace</span>
        <div style={{ flex:1 }}/>
        <span style={{ fontFamily:FONT_MONO, fontSize:10, color:'var(--pc-content-tertiary)' }}>1.42s · 4/4</span>
      </div>
      {/* consensus card */}
      <div style={{
        padding:'9px 10px', borderRadius:8,
        background:'var(--pc-surface-elevated)',
        boxShadow:'inset 0 0 0 0.5px var(--pc-border-subtle)',
      }}>
        <div style={{ display:'flex', alignItems:'center', gap:7, marginBottom:7 }}>
          <PolycodeIcon size={18}/>
          <div style={{ fontSize:11, fontWeight:600 }}>Consensus reached</div>
          <div style={{ flex:1 }}/>
          <span style={{ fontFamily:FONT_MONO, fontSize:10, color:'var(--pc-content-tertiary)' }}>94%</span>
        </div>
        <div style={{ height:3, borderRadius:2, background:'rgba(28,25,21,0.06)', overflow:'hidden' }}>
          <div style={{
            width:`${94 * eo(cl((t - 7.4)/0.9, 0, 1))}%`, height:'100%',
            background:'var(--pc-accent-gradient)', borderRadius:2,
          }}/>
        </div>
      </div>
      {HERO_PROV.map((p, i) => {
        const rd = 6.7 + i * 0.10;
        const rf = eo(cl((t - rd)/0.4, 0, 1));
        const fill = cl(p.ms / 1500, 0, 1);
        return (
          <div key={p.p} style={{
            background:'var(--pc-surface-elevated)', borderRadius:8,
            boxShadow: p.primary ? 'inset 0 0 0 1.25px var(--pc-accent-solid)' : 'inset 0 0 0 0.5px var(--pc-border-subtle)',
            padding:'9px 10px',
            opacity:rf, transform:`translateX(${(1-rf)*8}px)`,
          }}>
            <div style={{ display:'flex', alignItems:'center', gap:8 }}>
              <ProviderTile provider={p.p} size={18}/>
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ fontSize:11, fontWeight:600, display:'flex', alignItems:'center', gap:4 }}>
                  {p.full}
                  {p.primary && <Icon name="crown" size={9} color="var(--pc-accent-solid)" strokeWidth={2.2}/>}
                </div>
                <div style={{ fontSize:10, color:'var(--pc-content-tertiary)', fontFamily:FONT_MONO, marginTop:1 }}>847 in · 412 out</div>
              </div>
              <span style={{
                padding:'1px 6px', borderRadius:3,
                background:'rgba(46,125,91,0.10)', color:'var(--pc-status-success)',
                fontSize:9.5, fontWeight:600, fontFamily:FONT_MONO,
              }}>✓ {p.ms}ms</span>
            </div>
            <div style={{ marginTop:7, height:2.5, borderRadius:2, background:'rgba(28,25,21,0.06)', overflow:'hidden' }}>
              <div style={{
                width:`${fill * 100 * rf}%`, height:'100%',
                background: p.primary ? 'var(--pc-accent-solid)' : p.col, borderRadius:2,
              }}/>
            </div>
          </div>
        );
      })}
    </div>
  );
}

Object.assign(window, { HeroAppMock });
