// V5 — Pulse
// "Live operations HUD" — the business is moving and you can see it.
// Ticker of events, animated KPI rings, projects heatmap with crew dots pulsing,
// waveform AI composer, money-flow sparklines. Dark, neon-on-slate.

const v5 = {
  bg: '#080b12',
  panel: '#0e1320',
  panel2: '#141a2a',
  line: '#1a2134',
  line2: '#232c44',
  ink: '#e7ecf5',
  ink2: '#a7b2cc',
  ink3: '#6b7796',
  blue: '#6ea7ff',
  cyan: '#5ee9d6',
  lime: '#bef264',
  amber: '#fbbf24',
  pink: '#f472b6',
  red: '#f87171',
  sans: '"Inter Tight", -apple-system, sans-serif',
  mono: '"JetBrains Mono", ui-monospace, monospace',
  serif: '"Instrument Serif", Georgia, serif',
};

function V5Pulse() {
  return (
    <div style={{
      width: '100%', height: '100%', background: v5.bg, color: v5.ink,
      fontFamily: v5.sans, fontSize: 13, overflow: 'hidden',
      display: 'grid', gridTemplateRows: '48px 28px 1fr 30px',
      position: 'relative',
    }}>
      {/* ambient glow */}
      <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', background: `
        radial-gradient(600px 300px at 15% 10%, rgba(110,167,255,0.08), transparent 70%),
        radial-gradient(500px 260px at 85% 90%, rgba(94,233,214,0.06), transparent 70%)
      ` }} />

      <V5TopBar />
      <V5Ticker />
      <V5Main />
      <V5StatusBar />

      <style>{`
        @keyframes v5Blink { 50% { opacity: 0.35 } }
        @keyframes v5Pulse { 0%,100% { transform: scale(1); opacity: 1 } 50% { transform: scale(1.15); opacity: 0.6 } }
        @keyframes v5Ping { 0% { transform: scale(1); opacity: 0.8 } 100% { transform: scale(2.4); opacity: 0 } }
        @keyframes v5Ticker { 0% { transform: translateX(0) } 100% { transform: translateX(-50%) } }
        @keyframes v5Dash { to { stroke-dashoffset: -60 } }
        @keyframes v5Wave { 0%,100% { d: path("M0,15 Q10,8 20,15 T40,15 T60,15 T80,15 T100,15 T120,15") }
                           50%     { d: path("M0,15 Q10,22 20,15 T40,15 T60,15 T80,15 T100,15 T120,15") } }
        @keyframes v5Drift { 0% { transform: translateX(0) } 100% { transform: translateX(-20px) } }
        @keyframes v5Sweep { 0% { transform: translateX(-100%) } 100% { transform: translateX(200%) } }
        @keyframes v5CountUp { 0% { opacity: 0; transform: translateY(6px) } 100% { opacity: 1; transform: translateY(0) } }
        @keyframes v5Spark { 0%,100% { opacity: 0.4 } 50% { opacity: 1 } }
        @keyframes v5RingFill { 0% { stroke-dashoffset: var(--c) } 100% { stroke-dashoffset: var(--d) } }
      `}</style>
    </div>
  );
}

function V5TopBar() {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 16, padding: '0 18px',
      borderBottom: `1px solid ${v5.line}`, background: 'rgba(14,19,32,0.6)', backdropFilter: 'blur(8px)',
      position: 'relative', zIndex: 2,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        <div style={{
          width: 22, height: 22, background: v5.ink, color: v5.bg, borderRadius: 5,
          display: 'grid', placeItems: 'center', fontFamily: v5.mono, fontSize: 12, fontWeight: 700,
        }}>C</div>
        <div style={{ fontWeight: 600, letterSpacing: '-0.01em' }}>Contro</div>
        <span style={{ color: v5.ink3, fontFamily: v5.mono, fontSize: 11 }}>/ ridgeline-dev</span>
      </div>
      {['Pulse','Projects','Money','Schedule','Crew','Docs'].map((n, i) => (
        <div key={n} style={{
          padding: '4px 10px', borderRadius: 5, fontSize: 12,
          color: i === 0 ? v5.ink : v5.ink2, fontWeight: i === 0 ? 500 : 400,
          background: i === 0 ? v5.panel2 : 'transparent',
        }}>{n}</div>
      ))}
      <div style={{ flex: 1 }} />
      {/* live mic / waveform */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '4px 10px', background: v5.panel2, borderRadius: 6, border: `1px solid ${v5.line2}` }}>
        <div style={{ width: 6, height: 6, borderRadius: '50%', background: v5.red, animation: 'v5Pulse 1.4s ease-in-out infinite' }} />
        <span style={{ fontSize: 11, fontFamily: v5.mono, color: v5.ink2 }}>LIVE</span>
        <svg width="80" height="18" viewBox="0 0 80 18">
          {Array.from({ length: 20 }).map((_, i) => (
            <rect key={i} x={i * 4} y={9 - (Math.sin(i * 0.9) * 4 + 4)} width="2" height={(Math.sin(i * 0.9) * 4 + 5) * 2}
              fill={v5.cyan} opacity={0.4 + (i % 3) * 0.2}
              style={{ animation: `v5Spark ${0.8 + (i % 4) * 0.15}s ease-in-out infinite` }} />
          ))}
        </svg>
      </div>
      <div style={{ width: 26, height: 26, borderRadius: '50%', background: 'linear-gradient(135deg,#d4a373,#a68260)', display: 'grid', placeItems: 'center', fontSize: 11, fontWeight: 600, color: v5.bg }}>MR</div>
    </div>
  );
}

function V5Ticker() {
  const events = [
    ['09:14', 'INV-1142  ·  $184,220  approved', v5.lime],
    ['09:11', 'RFI-044  ·  opened on Harborview Blk B', v5.amber],
    ['09:08', 'Draw #7  ·  signed by Calloway Co', v5.cyan],
    ['09:04', 'Weather alert  ·  rain 14:00, Portsmouth', v5.blue],
    ['08:58', 'CO-017  ·  awaiting owner signature', v5.amber],
    ['08:51', 'PPE flag  ·  no vest · cam 3 / Block A', v5.red],
    ['08:47', 'Material delivery  ·  rebar #4 · on site', v5.lime],
    ['08:42', 'Timesheet  ·  Mondragon Framing submitted', v5.ink2],
  ];
  const line = (
    <div style={{ display: 'flex', gap: 48, whiteSpace: 'nowrap', padding: '0 24px' }}>
      {events.map((e, i) => (
        <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 11 }}>
          <span style={{ fontFamily: v5.mono, color: v5.ink3 }}>{e[0]}</span>
          <span style={{ width: 5, height: 5, borderRadius: '50%', background: e[2] }} />
          <span style={{ color: v5.ink2 }}>{e[1]}</span>
        </div>
      ))}
    </div>
  );
  return (
    <div style={{
      borderBottom: `1px solid ${v5.line}`, background: v5.panel, overflow: 'hidden',
      display: 'flex', alignItems: 'center', position: 'relative', zIndex: 2,
    }}>
      <div style={{ padding: '0 14px', fontSize: 10, letterSpacing: '0.1em', color: v5.ink3, background: v5.panel2, height: '100%', display: 'grid', placeItems: 'center', borderRight: `1px solid ${v5.line}`, fontFamily: v5.mono }}>
        LIVE  ·  APR 21
      </div>
      <div style={{ display: 'flex', animation: 'v5Ticker 60s linear infinite' }}>
        {line}{line}
      </div>
    </div>
  );
}

function V5Main() {
  return (
    <div style={{
      padding: 16, display: 'grid', gap: 14,
      gridTemplateColumns: '1.3fr 1fr 1fr',
      gridTemplateRows: 'auto auto 1fr',
      overflow: 'hidden', position: 'relative', zIndex: 1,
    }}>
      <V5Greeting />
      <V5KPIRings />
      <V5Waveform />

      <V5Heatmap />
      <V5MoneyFlow />
      <V5CrewDots />

      <V5ActivityStream />
      <V5AgentQueue />
      <V5Insight />
    </div>
  );
}

function V5Greeting() {
  const [n, setN] = React.useState(0);
  React.useEffect(() => { const t = setInterval(() => setN((v) => Math.min(v + 1, 100)), 30); return () => clearInterval(t); }, []);
  return (
    <V5Card glow>
      <div style={{ fontSize: 10, letterSpacing: '0.1em', color: v5.ink3, fontFamily: v5.mono }}>PULSE  ·  TUE APR 21</div>
      <div style={{ fontFamily: v5.serif, fontStyle: 'italic', fontSize: 28, letterSpacing: '-0.02em', marginTop: 6, lineHeight: 1.1 }}>
        Good morning, <span style={{ color: v5.cyan }}>Marcus</span>.
      </div>
      <div style={{ fontSize: 12, color: v5.ink2, marginTop: 8, lineHeight: 1.55 }}>
        Across <b style={{ color: v5.ink }}>12 active projects</b>, 41 of 44 crew checked in.
        Two items need you today — Draw #7 signature and a PPE flag on Block A.
      </div>
      <div style={{ display: 'flex', gap: 10, marginTop: 14 }}>
        {[
          ['ON PACE', '8', v5.lime],
          ['WATCH', '3', v5.amber],
          ['BLOCKED', '1', v5.red],
        ].map((k, i) => (
          <div key={i} style={{ flex: 1, padding: '8px 10px', background: v5.panel2, border: `1px solid ${v5.line2}`, borderRadius: 6, borderLeft: `3px solid ${k[2]}` }}>
            <div style={{ fontSize: 9, letterSpacing: '0.1em', color: v5.ink3, fontFamily: v5.mono }}>{k[0]}</div>
            <div style={{ fontSize: 22, fontWeight: 600, marginTop: 2, letterSpacing: '-0.02em' }}>{k[1]}</div>
          </div>
        ))}
      </div>
    </V5Card>
  );
}

function V5KPIRings() {
  const rings = [
    ['Revenue',  '$5.27M',  0.72, v5.cyan],
    ['Margin',   '18.4%',   0.61, v5.lime],
    ['On-time',  '94%',     0.94, v5.blue],
    ['Safety',   '0 incid.',0.88, v5.pink],
  ];
  return (
    <V5Card>
      <V5Title>KPI · YTD</V5Title>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginTop: 10, flex: 1 }}>
        {rings.map((r, i) => {
          const C_ = 2 * Math.PI * 22;
          return (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <svg width="58" height="58" viewBox="0 0 58 58">
                <circle cx="29" cy="29" r="22" fill="none" stroke={v5.line2} strokeWidth="4" />
                <circle cx="29" cy="29" r="22" fill="none" stroke={r[3]} strokeWidth="4" strokeLinecap="round"
                  strokeDasharray={C_} strokeDashoffset={C_ - (C_ * r[2])}
                  transform="rotate(-90 29 29)"
                  style={{ transition: 'stroke-dashoffset 1.4s ease-out', filter: `drop-shadow(0 0 4px ${r[3]}66)` }} />
              </svg>
              <div>
                <div style={{ fontSize: 10, letterSpacing: '0.06em', color: v5.ink3, fontFamily: v5.mono }}>{r[0].toUpperCase()}</div>
                <div style={{ fontSize: 17, fontWeight: 600, letterSpacing: '-0.02em' }}>{r[1]}</div>
              </div>
            </div>
          );
        })}
      </div>
    </V5Card>
  );
}

function V5Waveform() {
  return (
    <V5Card>
      <V5Title>Copilot · ask anything</V5Title>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 14 }}>
        <svg viewBox="0 0 260 60" style={{ width: '100%', height: 60 }}>
          {Array.from({ length: 60 }).map((_, i) => {
            const h = 8 + Math.abs(Math.sin(i * 0.4)) * 16 + Math.abs(Math.cos(i * 0.11)) * 10;
            return <rect key={i} x={i * 4 + 4} y={30 - h / 2} width="2" height={h}
              fill={i < 24 ? v5.cyan : v5.line2} rx="1"
              style={{ animation: i < 24 ? `v5Spark ${0.6 + (i % 5) * 0.12}s ease-in-out infinite` : 'none' }} />;
          })}
        </svg>
        <div style={{ padding: '8px 10px', background: v5.panel2, border: `1px solid ${v5.line2}`, borderRadius: 6, fontFamily: v5.mono, fontSize: 11, color: v5.ink2 }}>
          <span style={{ color: v5.cyan }}>▸</span> which subs are overbudget this week
          <span style={{ display: 'inline-block', width: 6, height: 12, background: v5.cyan, marginLeft: 2, verticalAlign: 'middle', animation: 'v5Blink 1s steps(2) infinite' }} />
        </div>
      </div>
    </V5Card>
  );
}

function V5Heatmap() {
  const projects = [
    ['Harborview Blk B', [3,4,4,5,5,4,5,5,4,5,5,5,4,5]],
    ['Pine Ridge L3',    [3,3,4,4,4,3,4,4,5,4,4,3,4,4]],
    ['East Bay Lofts',   [2,3,3,4,3,4,4,3,3,4,4,4,3,4]],
    ['Meridian Tower',   [4,4,5,5,5,5,4,5,5,5,5,4,5,5]],
    ['Foster & 9th',     [1,2,2,3,2,2,3,3,2,2,3,3,2,3]],
    ['Warehouse Fit-out',[3,3,3,4,4,3,3,4,4,4,3,4,4,4]],
  ];
  const color = (v) => ({ 1: '#1e2740', 2: '#243662', 3: '#2f5d9a', 4: '#4682d4', 5: '#6ea7ff' }[v]);
  return (
    <V5Card span={2}>
      <V5Title>Portfolio heat · 14-day activity</V5Title>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 4, marginTop: 10, position: 'relative' }}>
        {projects.map((p, i) => (
          <div key={i} style={{ display: 'grid', gridTemplateColumns: '140px 1fr auto', gap: 10, alignItems: 'center', fontSize: 11 }}>
            <span style={{ color: v5.ink2 }}>{p[0]}</span>
            <div style={{ display: 'flex', gap: 2 }}>
              {p[1].map((v, j) => (
                <div key={j} style={{
                  flex: 1, height: 14, background: color(v), borderRadius: 2,
                  opacity: 0.9, transition: 'opacity 200ms',
                }} />
              ))}
            </div>
            <span style={{ fontFamily: v5.mono, color: v5.ink3, fontSize: 10 }}>{Math.round(p[1].reduce((a,b)=>a+b,0)/p[1].length*20)}%</span>
          </div>
        ))}
        {/* sweep beam */}
        <div style={{ position: 'absolute', top: 0, bottom: 0, width: 40,
          background: 'linear-gradient(90deg, transparent, rgba(110,167,255,0.14), transparent)',
          left: 150, animation: 'v5Sweep 6s linear infinite', pointerEvents: 'none' }} />
      </div>
    </V5Card>
  );
}

function V5MoneyFlow() {
  return (
    <V5Card>
      <V5Title>Money · in ↔ out</V5Title>
      <div style={{ display: 'flex', gap: 12, marginTop: 10, flex: 1 }}>
        {[
          ['AR', '$1.84M', '+2 draws', v5.lime, 0.72],
          ['AP', '$1.12M', '11 bills', v5.amber, 0.48],
        ].map((k, i) => (
          <div key={i} style={{ flex: 1, padding: '10px 12px', background: v5.panel2, border: `1px solid ${v5.line2}`, borderRadius: 6 }}>
            <div style={{ fontSize: 10, letterSpacing: '0.1em', color: v5.ink3, fontFamily: v5.mono }}>{k[0]}</div>
            <div style={{ fontSize: 18, fontWeight: 600, letterSpacing: '-0.02em', marginTop: 2 }}>{k[1]}</div>
            <div style={{ fontSize: 10, color: v5.ink2, marginBottom: 8 }}>{k[2]}</div>
            <svg viewBox="0 0 120 28" style={{ width: '100%', height: 22 }}>
              <path d={`M 0 22 ${Array.from({length: 12}).map((_,j) => `L ${j*10+10} ${22 - Math.abs(Math.sin(j*0.7 + i))*18}`).join(' ')}`}
                fill="none" stroke={k[3]} strokeWidth="1.6" strokeLinecap="round" />
            </svg>
          </div>
        ))}
      </div>
    </V5Card>
  );
}

function V5CrewDots() {
  const dots = [
    [20, 30, v5.lime], [45, 25, v5.lime], [60, 50, v5.lime], [80, 30, v5.amber],
    [30, 60, v5.lime], [50, 70, v5.lime], [70, 75, v5.lime], [85, 60, v5.lime],
    [25, 80, v5.red],  [15, 50, v5.amber], [40, 45, v5.lime], [65, 20, v5.lime],
  ];
  return (
    <V5Card>
      <V5Title>Crew · on site right now</V5Title>
      <div style={{ position: 'relative', flex: 1, background: v5.panel2, borderRadius: 6, marginTop: 10, overflow: 'hidden', border: `1px solid ${v5.line2}` }}>
        <svg viewBox="0 0 100 100" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}>
          <defs>
            <pattern id="v5grid" width="10" height="10" patternUnits="userSpaceOnUse">
              <path d="M 10 0 L 0 0 0 10" fill="none" stroke={v5.line} strokeWidth="0.3" />
            </pattern>
          </defs>
          <rect width="100" height="100" fill="url(#v5grid)" />
          {/* building outlines */}
          <rect x="10" y="15" width="38" height="40" fill="none" stroke={v5.ink3} strokeWidth="0.4" strokeDasharray="2 2" />
          <rect x="52" y="45" width="40" height="40" fill="none" stroke={v5.ink3} strokeWidth="0.4" strokeDasharray="2 2" />
          {dots.map((d, i) => (
            <g key={i}>
              <circle cx={d[0]} cy={d[1]} r="2" fill={d[2]} />
              <circle cx={d[0]} cy={d[1]} r="2" fill="none" stroke={d[2]} strokeWidth="0.6"
                style={{ animation: `v5Ping 2s ${i * 0.2}s ease-out infinite`, transformOrigin: `${d[0]}px ${d[1]}px` }} />
            </g>
          ))}
        </svg>
        <div style={{ position: 'absolute', bottom: 6, left: 8, fontFamily: v5.mono, fontSize: 9, color: v5.ink3 }}>41 / 44 CHECKED IN</div>
      </div>
    </V5Card>
  );
}

function V5ActivityStream() {
  const lines = [
    ['09:14', 'INVOICE', 'INV-1142 · $184,220', 'Brannigan Concrete', v5.lime],
    ['09:11', 'RFI',     'RFI-044 opened',       'Harborview Blk B',  v5.amber],
    ['09:08', 'DRAW',    'Draw #7 signed',       'Calloway Co',       v5.cyan],
    ['08:58', 'CO',      'CO-017 pending',       'Low-E glazing',     v5.amber],
    ['08:51', 'SAFETY',  'PPE flag · cam 3',     'Block A',           v5.red],
  ];
  return (
    <V5Card>
      <V5Title>Activity</V5Title>
      <div style={{ marginTop: 6, display: 'flex', flexDirection: 'column', gap: 1, flex: 1 }}>
        {lines.map((l, i) => (
          <div key={i} style={{
            display: 'grid', gridTemplateColumns: '40px 60px 1fr auto', gap: 8, padding: '6px 4px',
            fontSize: 11, borderBottom: `1px solid ${v5.line}`, alignItems: 'center',
          }}>
            <span style={{ fontFamily: v5.mono, color: v5.ink3, fontSize: 10 }}>{l[0]}</span>
            <span style={{ fontFamily: v5.mono, fontSize: 9, letterSpacing: '0.05em', color: l[4] }}>{l[1]}</span>
            <span>{l[2]}</span>
            <span style={{ color: v5.ink3, fontSize: 10 }}>{l[3]}</span>
          </div>
        ))}
      </div>
    </V5Card>
  );
}

function V5AgentQueue() {
  const agents = [
    ['Invoice parser',  'reading  inv-1143.pdf', 'running', v5.cyan],
    ['Schedule watcher','3 projects drifting',   'alert',   v5.amber],
    ['Draw prep',       'G703 ready for review',  'done',    v5.lime],
    ['Lien waiver bot', 'chasing 4 subs',         'running', v5.cyan],
  ];
  return (
    <V5Card>
      <V5Title>Agents · background</V5Title>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 8, flex: 1 }}>
        {agents.map((a, i) => (
          <div key={i} style={{ padding: '8px 10px', background: v5.panel2, border: `1px solid ${v5.line2}`, borderRadius: 6, display: 'flex', alignItems: 'center', gap: 10 }}>
            <div style={{ width: 6, height: 6, borderRadius: '50%', background: a[3],
              boxShadow: `0 0 8px ${a[3]}`,
              animation: a[2] === 'running' ? 'v5Pulse 1.4s ease-in-out infinite' : 'none' }} />
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 11, fontWeight: 500 }}>{a[0]}</div>
              <div style={{ fontSize: 10, color: v5.ink3, fontFamily: v5.mono }}>{a[1]}</div>
            </div>
            <span style={{ fontSize: 9, fontFamily: v5.mono, letterSpacing: '0.08em', color: a[3], textTransform: 'uppercase' }}>{a[2]}</span>
          </div>
        ))}
      </div>
    </V5Card>
  );
}

function V5Insight() {
  return (
    <V5Card glow>
      <V5Title accent>Insight · now</V5Title>
      <div style={{ marginTop: 8, fontSize: 12, lineHeight: 1.55, color: v5.ink }}>
        Brannigan Concrete is <b style={{ color: v5.cyan }}>8.2%</b> over their slab-B budget.
        Three other projects had the same spike last month. Likely cause: <b>rebar price jump</b>.
      </div>
      <div style={{ display: 'flex', gap: 6, marginTop: 12, flexWrap: 'wrap' }}>
        {['See drilldown','Draft CO','Notify PM','Dismiss'].map((a, i) => (
          <span key={a} style={{
            padding: '4px 9px', fontSize: 10, borderRadius: 4, fontFamily: v5.mono, letterSpacing: '0.03em',
            background: i === 0 ? v5.cyan : 'transparent', color: i === 0 ? v5.bg : v5.ink2,
            border: i === 0 ? 'none' : `1px solid ${v5.line2}`, fontWeight: i === 0 ? 600 : 400,
          }}>{a}</span>
        ))}
      </div>
    </V5Card>
  );
}

function V5StatusBar() {
  return (
    <div style={{
      borderTop: `1px solid ${v5.line}`, background: v5.panel, display: 'flex',
      alignItems: 'center', padding: '0 16px', fontFamily: v5.mono, fontSize: 10, color: v5.ink3,
      gap: 18, letterSpacing: '0.03em',
    }}>
      <span><span style={{ color: v5.lime }}>●</span> connected</span>
      <span>api: 42ms</span>
      <span>events: 1,284 today</span>
      <span style={{ flex: 1 }} />
      <span>shift Δ · open copilot</span>
      <span>⌘K · command</span>
      <span>esc · dismiss</span>
    </div>
  );
}

// ── primitives ──────────────────────────────────────────────
function V5Card({ children, glow, span }) {
  return (
    <div style={{
      background: v5.panel, border: `1px solid ${v5.line}`, borderRadius: 10,
      padding: 14, display: 'flex', flexDirection: 'column',
      boxShadow: glow ? '0 0 0 1px rgba(110,167,255,0.14), 0 8px 30px rgba(110,167,255,0.06)' : 'none',
      gridColumn: span ? `span ${span}` : undefined,
      minHeight: 0, overflow: 'hidden',
    }}>{children}</div>
  );
}
function V5Title({ children, accent }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
      <span style={{ fontSize: 10, letterSpacing: '0.12em', color: accent ? v5.cyan : v5.ink3, fontFamily: v5.mono, fontWeight: 500 }}>{String(children).toUpperCase()}</span>
      {accent && <span style={{ width: 5, height: 5, borderRadius: '50%', background: v5.cyan, animation: 'v5Pulse 1.4s ease-in-out infinite' }} />}
    </div>
  );
}

Object.assign(window, { V5Pulse });
