/* global React */
const { useState: useDashState, useEffect: useDashEffect, useRef: useDashRef } = React;

/* =========================================================
   Dashboard mock — used in hero + dashboard preview page
   ========================================================= */

/* IntersectionObserver hook — fires once when element first enters viewport */
function useDashInView(threshold = 0.18) {
  const ref = useDashRef(null);
  const [inView, setInView] = useDashState(false);
  useDashEffect(() => {
    if (!ref.current || inView) return;
    const io = new IntersectionObserver((entries) => {
      for (const e of entries) {
        if (e.isIntersecting) { setInView(true); io.disconnect(); break; }
      }
    }, { threshold });
    io.observe(ref.current);
    return () => io.disconnect();
  }, [inView, threshold]);
  return [ref, inView];
}

/* Sparkline path generator */
function sparkline(values, w, h, padding = 4) {
  const min = Math.min(...values);
  const max = Math.max(...values);
  const range = max - min || 1;
  const stepX = (w - padding * 2) / (values.length - 1);
  return values.map((v, i) => {
    const x = padding + i * stepX;
    const y = h - padding - ((v - min) / range) * (h - padding * 2);
    return `${i === 0 ? "M" : "L"} ${x.toFixed(1)} ${y.toFixed(1)}`;
  }).join(" ");
}

function MetricCard({ label, value, sub, trend, accent, sparkData, children }) {
  return (
    <div className="metric-card">
      <div className="metric-head">
        <span className="metric-label">{label}</span>
        {trend && (
          <span className={"metric-trend " + (trend.dir === "up" ? "up" : trend.dir === "down" ? "down" : "")}>
            {trend.dir === "up" ? "▲" : trend.dir === "down" ? "▼" : "•"} {trend.value}
          </span>
        )}
      </div>
      <div className="metric-value">{value}</div>
      {sub && <div className="metric-sub">{sub}</div>}
      {sparkData && (
        <svg className="metric-spark" viewBox="0 0 120 36" preserveAspectRatio="none">
          <path d={sparkline(sparkData, 120, 36)} pathLength="1" fill="none" stroke={accent || "var(--green-500)"} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      )}
      {children}
    </div>
  );
}

/* Reserve health ring */
function ReserveRing({ percent = 78, target = 30000, current = 23400 }) {
  const r = 54;
  const c = 2 * Math.PI * r;
  const dash = (percent / 100) * c;
  return (
    <div className="reserve-ring-card">
      <div className="reserve-ring-head">
        <div>
          <div className="metric-label">Reserve health</div>
          <div className="reserve-amount">${current.toLocaleString()}</div>
          <div className="metric-sub">of ${target.toLocaleString()} target</div>
        </div>
        <span className="tag" style={{background:"var(--green-100)", color:"var(--green-700)"}}>
          <span style={{width:6,height:6,borderRadius:"50%",background:"var(--green-500)"}}></span>
          On track
        </span>
      </div>
      <div className="reserve-ring-wrap">
        <svg viewBox="0 0 140 140" className="reserve-ring">
          <circle cx="70" cy="70" r={r} stroke="var(--gray-100)" strokeWidth="12" fill="none" />
          <circle
            className="reserve-ring-progress"
            cx="70" cy="70" r={r}
            stroke="url(#ringGrad)"
            strokeWidth="12"
            fill="none"
            pathLength="100"
            strokeDasharray={`${percent} 100`}
            strokeDashoffset="0"
            strokeLinecap="round"
            transform="rotate(-90 70 70)"
            style={{"--ring-pct": percent}}
          />
          <defs>
            <linearGradient id="ringGrad" x1="0" y1="0" x2="1" y2="1">
              <stop offset="0%" stopColor="#4caf63"/>
              <stop offset="100%" stopColor="#1c6529"/>
            </linearGradient>
          </defs>
          <text x="70" y="70" textAnchor="middle" dominantBaseline="central"
                style={{fontFamily:"var(--font-display)", fontWeight:700, fontSize:26, fill:"var(--charcoal-900)", letterSpacing:"-0.02em"}}>
            {percent}%
          </text>
          <text x="70" y="90" textAnchor="middle" dominantBaseline="central"
                style={{fontFamily:"var(--font-body)", fontSize:10, fill:"var(--charcoal-500)", letterSpacing:".06em", textTransform:"uppercase"}}>
            funded
          </text>
        </svg>
        <div className="reserve-legend">
          <div className="legend-row"><span className="dot operating"></span> Operating · 3 mo</div>
          <div className="legend-row"><span className="dot tax"></span> Tax · Q2 2026</div>
          <div className="legend-row"><span className="dot growth"></span> Growth fund</div>
          <div className="legend-row"><span className="dot owner"></span> Owner draw</div>
        </div>
      </div>
    </div>
  );
}

/* Runway forecast chart — INTERACTIVE: scrub the chart to inspect any month */
function RunwayChart() {
  const W = 560, H = 200, P = 28;
  // Underlying 12-month dataset: past + forecast (in $K of reserves)
  const fullData = [
    {month:"Oct", val:18, kind:"past"},
    {month:"Nov", val:22, kind:"past"},
    {month:"Dec", val:19, kind:"past"},
    {month:"Jan", val:26, kind:"past"},
    {month:"Feb", val:31, kind:"past"},
    {month:"Mar", val:34, kind:"past"},
    {month:"Apr", val:34, kind:"fcast"},
    {month:"May", val:38, kind:"fcast"},
    {month:"Jun", val:36, kind:"fcast"},
    {month:"Jul", val:42, kind:"fcast"},
    {month:"Aug", val:47, kind:"fcast"},
    {month:"Sep", val:52, kind:"fcast"},
  ];

  const [range, setRange] = useDashState("12mo");
  const [scrubIdx, setScrubIdx] = useDashState(null); // null = no hover, show default
  const svgRef = useDashRef(null);

  // Slice based on selected range
  const sliceFor = (r) => {
    if (r === "6mo")  return [3, 9];   // Jan–Jun (3 past + 3 fcast around NOW)
    if (r === "YTD")  return [3, 12];  // Jan–Sep
    return [0, 12];                     // 12mo: full
  };
  const [start, end] = sliceFor(range);
  const data = fullData.slice(start, end);

  // NOW boundary in absolute terms is index 5 (last "past")
  const nowIdxInView = Math.max(0, Math.min(data.length - 1, 5 - start));

  const min = 0, max = 60;
  const x = (i) => P + (i * (W - P*2)) / (data.length - 1);
  const y = (v) => H - P - ((v - min) / (max - min)) * (H - P*2);

  const past = data.slice(0, nowIdxInView + 1);
  const fcast = data.slice(nowIdxInView);

  const pastPath = past.map((d,i) => `${i===0?"M":"L"} ${x(i)} ${y(d.val)}`).join(" ");
  const forecastPath = fcast.map((d,i) => `${i===0?"M":"L"} ${x(nowIdxInView+i)} ${y(d.val)}`).join(" ");
  const fillPath = pastPath + ` L ${x(nowIdxInView)} ${H-P} L ${x(0)} ${H-P} Z`;

  // Burn rate ≈ $4K/mo → runway months = reserve / 4
  const burn = 4;
  const currentVal = data[nowIdxInView].val;
  const currentRunway = (currentVal / burn).toFixed(1);

  // What the header shows: scrub overrides default
  const headerVal = scrubIdx !== null
    ? (data[scrubIdx].val / burn).toFixed(1)
    : currentRunway;
  const headerSub = scrubIdx !== null
    ? `at ${data[scrubIdx].month} · $${data[scrubIdx].val}K reserves`
    : "at current burn";

  // Pointer handlers — convert client X to nearest data index
  const handlePointer = (e) => {
    if (!svgRef.current) return;
    const rect = svgRef.current.getBoundingClientRect();
    const localX = ((e.clientX - rect.left) / rect.width) * W;
    const t = (localX - P) / (W - P*2);
    const idx = Math.max(0, Math.min(data.length - 1, Math.round(t * (data.length - 1))));
    setScrubIdx(idx);
  };
  const handleLeave = () => setScrubIdx(null);

  const scrubX = scrubIdx !== null ? x(scrubIdx) : null;
  const scrubY = scrubIdx !== null ? y(data[scrubIdx].val) : null;

  return (
    <div className="runway-card">
      <div className="runway-head">
        <div>
          <div className="metric-label">Runway forecast</div>
          <div style={{display:"flex", alignItems:"baseline", gap:10}}>
            <div className="runway-value" key={headerVal}>{headerVal} months</div>
            <span className="metric-sub" key={headerSub}>{headerSub}</span>
          </div>
        </div>
        <div className="runway-tabs">
          {["12mo","6mo","YTD"].map(r => (
            <button key={r}
                    className={"runway-tab" + (range === r ? " active" : "")}
                    onClick={() => { setRange(r); setScrubIdx(null); }}>
              {r === "12mo" ? "12 mo" : r === "6mo" ? "6 mo" : "YTD"}
            </button>
          ))}
        </div>
      </div>
      <svg ref={svgRef} viewBox={`0 0 ${W} ${H}`} className="runway-svg runway-svg-interactive"
           onPointerMove={handlePointer}
           onPointerDown={handlePointer}
           onPointerLeave={handleLeave}>
        <defs>
          <linearGradient id="runwayFill" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="#2e9143" stopOpacity="0.20"/>
            <stop offset="100%" stopColor="#2e9143" stopOpacity="0"/>
          </linearGradient>
        </defs>
        {/* Gridlines */}
        {[0,1,2,3].map(i => (
          <line key={i} x1={P} x2={W-P} y1={P + i*((H-P*2)/3)} y2={P + i*((H-P*2)/3)}
                stroke="var(--gray-100)" strokeWidth="1" />
        ))}
        {/* "Now" line — present only if NOW is in current range */}
        {nowIdxInView >= 0 && nowIdxInView < data.length && (
          <g>
            <line x1={x(nowIdxInView)} x2={x(nowIdxInView)} y1={P-6} y2={H-P}
                  stroke="var(--gray-300)" strokeDasharray="3 3" />
            <text x={x(nowIdxInView)} y={P-10} textAnchor="middle" fontSize="9"
                  fill="var(--charcoal-500)" fontFamily="var(--font-display)" letterSpacing="0.1em">NOW</text>
          </g>
        )}
        {/* Fill */}
        <path className="runway-fill" d={fillPath} fill="url(#runwayFill)" />
        {/* Past line */}
        <path className="runway-past" d={pastPath} pathLength="1" fill="none" stroke="var(--green-600)" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"/>
        {/* Forecast line */}
        <path className="runway-fcast" d={forecastPath} pathLength="1" fill="none" stroke="var(--green-500)" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" strokeDasharray="4 4"/>
        {/* NOW dot */}
        <circle className="runway-dot" cx={x(nowIdxInView)} cy={y(data[nowIdxInView].val)} r="5" fill="#fff" stroke="var(--green-600)" strokeWidth="2.5"/>

        {/* Scrub indicator */}
        {scrubIdx !== null && (
          <g className="runway-scrub" pointerEvents="none">
            <line x1={scrubX} x2={scrubX} y1={P-6} y2={H-P}
                  stroke="var(--green-600)" strokeWidth="1.2" strokeDasharray="2 3"/>
            <circle cx={scrubX} cy={scrubY} r="6" fill="var(--green-600)" stroke="#fff" strokeWidth="2"/>
            {/* Floating value chip */}
            <g transform={`translate(${scrubX}, ${scrubY - 16})`}>
              <rect x="-32" y="-22" width="64" height="20" rx="4"
                    fill="var(--charcoal-900)" />
              <text x="0" y="-8" textAnchor="middle" fontSize="10" fontWeight="600"
                    fill="#fff" fontFamily="var(--font-display)" letterSpacing="0.02em">
                {data[scrubIdx].month} · ${data[scrubIdx].val}K
              </text>
            </g>
          </g>
        )}

        {/* Invisible hit zones for crisper hover */}
        {data.map((d, i) => (
          <rect key={i}
                x={x(i) - (W-P*2)/(data.length-1)/2}
                y={P}
                width={(W-P*2)/(data.length-1)}
                height={H-P*2}
                fill="transparent"
                onPointerEnter={() => setScrubIdx(i)} />
        ))}

        {/* X labels */}
        {data.map((d, i) => (
          <text key={i} x={x(i)} y={H-8} textAnchor="middle" fontSize="10"
                fill={scrubIdx === i ? "var(--green-700)" : "var(--charcoal-500)"}
                fontFamily="var(--font-body)"
                fontWeight={scrubIdx === i ? 700 : 400}>
            {d.month}
          </text>
        ))}
      </svg>
      <div className="runway-hint">
        <span className="runway-hint-icon">↔</span>
        Hover the chart to scrub through months · click the tabs to change range
      </div>
    </div>
  );
}

/* AI recommendation card — INTERACTIVE: Apply plan and Show reasoning toggles */
function AICard() {
  const [applied, setApplied] = useDashState(false);
  const [showReasoning, setShowReasoning] = useDashState(false);
  return (
    <div className={"ai-card" + (applied ? " ai-applied" : "")}>
      <div className="ai-head">
        <span className="ai-badge">
          <Icon.spark style={{color:"var(--green-500)"}}/> AI guidance
        </span>
        <span className="metric-sub" style={{fontSize:11}}>
          {applied ? "Plan applied" : "Updated 2m ago"}
        </span>
      </div>
      {!applied ? (
        <div className="ai-message">
          Two of your three largest invoices land late this cycle. Pause the Q2 marketing increase by <strong>$1,800</strong> until June reserves clear <strong>$26K</strong>.
        </div>
      ) : (
        <div className="ai-message ai-message-success">
          <span className="ai-check">✓</span> Marketing budget paused at <strong>$1,800</strong>. ReservWise will re-evaluate when June reserves clear $26K.
        </div>
      )}
      {showReasoning && !applied && (
        <div className="ai-reasoning">
          <div className="ai-reasoning-title">Why this move</div>
          <ul className="ai-reasoning-list">
            <li><span className="ai-rb">Late-pay risk:</span> Acme + Globex historically pay 8–12 days past due</li>
            <li><span className="ai-rb">Buffer impact:</span> Pausing the increase preserves <strong>$1,800/mo</strong> until cash clears</li>
            <li><span className="ai-rb">Trigger:</span> When operating reserve hits $26K, marketing auto-resumes at planned pace</li>
          </ul>
        </div>
      )}
      <div className="ai-actions">
        {!applied ? (
          <>
            <button className="btn btn-primary btn-sm" onClick={() => setApplied(true)}>Apply plan</button>
            <button className="btn btn-secondary btn-sm" onClick={() => setShowReasoning(s => !s)}>
              {showReasoning ? "Hide reasoning" : "Show reasoning"}
            </button>
          </>
        ) : (
          <button className="btn btn-secondary btn-sm" onClick={() => { setApplied(false); setShowReasoning(false); }}>
            ← Undo
          </button>
        )}
      </div>
    </div>
  );
}

/* Bucket card — INTERACTIVE: click a row to focus / view detail */
function Buckets() {
  const buckets = [
    { name: "Operating",  value: 12400, target: 15000, color: "var(--green-600)",
      detail: "3 months runway covered. Auto-tops with first 50% of every deposit." },
    { name: "Tax · Q2",   value: 4800,  target: 6200,  color: "#3a4068",
      detail: "79% of Q2 estimate. Auto-fills 28% of every deposit until target met." },
    { name: "Owner draw", value: 3200,  target: 4000,  color: "#4caf63",
      detail: "Next draw May 1. Topped from owner-pay percentage on each deposit." },
    { name: "Growth",     value: 3000,  target: 5000,  color: "#a5d6a7",
      detail: "Long-game reserve. Funds only after operating + tax targets are met." },
  ];
  const [activeIdx, setActiveIdx] = useDashState(null);
  return (
    <div className="buckets-card">
      <div className="metric-head">
        <span className="metric-label">Reserve buckets</span>
        <span className="metric-sub" style={{fontSize:11}}>
          {activeIdx !== null ? "← click a bucket to deselect" : "4 active · click any"}
        </span>
      </div>
      <div className={"bucket-list" + (activeIdx !== null ? " has-active" : "")}>
        {buckets.map((b, i) => {
          const pct = Math.round((b.value / b.target) * 100);
          const isActive = activeIdx === i;
          return (
            <div key={b.name}
                 className={"bucket-row" + (isActive ? " active" : "")}
                 onClick={() => setActiveIdx(isActive ? null : i)}
                 role="button"
                 tabIndex={0}>
              <div className="bucket-name">
                <span className="bucket-dot" style={{background:b.color}}></span>
                {b.name}
              </div>
              <div className="bucket-bar">
                <div className="bucket-fill" style={{"--bucket-pct": pct+"%", background:b.color}}></div>
              </div>
              <div className="bucket-amount">${(b.value/1000).toFixed(1)}K</div>
            </div>
          );
        })}
      </div>
      {activeIdx !== null && (
        <div className="bucket-detail" key={activeIdx}>
          <div className="bucket-detail-head">
            <span className="bucket-dot" style={{background:buckets[activeIdx].color}}></span>
            <strong>{buckets[activeIdx].name}</strong>
            <span className="bucket-detail-pct">
              ${buckets[activeIdx].value.toLocaleString()} of ${buckets[activeIdx].target.toLocaleString()}
              · {Math.round((buckets[activeIdx].value/buckets[activeIdx].target)*100)}%
            </span>
          </div>
          <div className="bucket-detail-text">{buckets[activeIdx].detail}</div>
        </div>
      )}
    </div>
  );
}

/* Live activity feed — fills the empty top-right cell with rotating income events */
function LiveActivity() {
  const events = [
    { src: "Acme Co.",      label: "Retainer",  amt: 5400, color: "var(--green-600)",
      split: [{k:"Tax",pct:28,c:"#e8b53b"},{k:"Ops",pct:24,c:"#3a8dde"},{k:"Owner",pct:28,c:"#2e9143"},{k:"Growth",pct:12,c:"#8c5cd6"},{k:"Wealth",pct:8,c:"#1c6529"}] },
    { src: "Globex",        label: "Milestone", amt: 8200, color: "#3a8dde",
      split: [{k:"Tax",pct:30,c:"#e8b53b"},{k:"Ops",pct:18,c:"#3a8dde"},{k:"Owner",pct:22,c:"#2e9143"},{k:"Growth",pct:16,c:"#8c5cd6"},{k:"Wealth",pct:14,c:"#1c6529"}] },
    { src: "Initech",       label: "Bonus",     amt: 1200, color: "#8c5cd6",
      split: [{k:"Tax",pct:28,c:"#e8b53b"},{k:"Ops",pct:18,c:"#3a8dde"},{k:"Owner",pct:22,c:"#2e9143"},{k:"Growth",pct:16,c:"#8c5cd6"},{k:"Wealth",pct:16,c:"#1c6529"}] },
    { src: "Northwind",     label: "Partial",   amt: 2100, color: "#e8b53b",
      split: [{k:"Tax",pct:28,c:"#e8b53b"},{k:"Ops",pct:40,c:"#3a8dde"},{k:"Owner",pct:22,c:"#2e9143"},{k:"Growth",pct:6,c:"#8c5cd6"},{k:"Wealth",pct:4,c:"#1c6529"}] },
  ];
  const [pulseIdx, setPulseIdx] = useDashState(0);
  const [expandedIdx, setExpandedIdx] = useDashState(0);
  // Auto-cycle which item glows as "newest"
  useDashEffect(() => {
    const id = setInterval(() => setPulseIdx(i => (i + 1) % events.length), 3500);
    return () => clearInterval(id);
  }, []);
  const timeFor = (i) => {
    const labels = ["Just now", "12m ago", "2h ago", "Yesterday"];
    // Rotate the time labels in sync with pulseIdx so the "newest" stays at the top label
    const pos = (i - pulseIdx + events.length) % events.length;
    return labels[pos] || "Earlier";
  };
  return (
    <div className="activity-card">
      <div className="metric-head">
        <span className="metric-label">Live activity</span>
        <span className="activity-live">
          <span className="activity-live-dot"></span> LIVE
        </span>
      </div>
      <div className="activity-list">
        {events.map((e, i) => {
          const isPulse = pulseIdx === i;
          const isExpanded = expandedIdx === i;
          return (
            <div key={e.src}
                 className={"activity-item" + (isPulse ? " is-new" : "") + (isExpanded ? " is-expanded" : "")}
                 onClick={() => setExpandedIdx(isExpanded ? -1 : i)}>
              <div className="activity-item-row">
                <span className="activity-bullet" style={{background: e.color}}></span>
                <div className="activity-item-text">
                  <div className="activity-item-src">
                    {e.src} <span className="activity-item-tag">· {e.label}</span>
                  </div>
                  <div className="activity-item-time">{timeFor(i)}</div>
                </div>
                <div className="activity-item-amt">+${e.amt.toLocaleString()}</div>
              </div>
              {/* Auto-split mini breakdown — only shown when expanded */}
              {isExpanded && (
                <div className="activity-split">
                  <div className="activity-split-bar">
                    {e.split.map((s, j) => (
                      <div key={j} className="activity-split-seg"
                           style={{width: s.pct+"%", background: s.c}}
                           title={`${s.k} · ${s.pct}%`}/>
                    ))}
                  </div>
                  <div className="activity-split-legend">
                    {e.split.map((s, j) => (
                      <span key={j} className="activity-split-chip">
                        <span className="activity-split-dot" style={{background:s.c}}></span>
                        {s.k} {s.pct}%
                      </span>
                    ))}
                  </div>
                </div>
              )}
            </div>
          );
        })}
      </div>
      <div className="activity-foot">
        <span className="activity-foot-icon">↓</span>
        Auto-split applied to every deposit
      </div>
    </div>
  );
}

/* Compact dashboard for hero — most important cards */
function DashboardHero() {
  const [ref, inView] = useDashInView(0.18);
  const [activeNav, setActiveNav] = useDashState("Overview");
  const navItems = ["Overview","Reserves","Forecast","Owner draws","Tax buckets","AI guidance","Reports"];
  return (
    <div ref={ref} className={"dash-frame" + (inView ? " dash-animated" : "")}>
      <div className="dash-chrome">
        <div className="dash-dots">
          <span></span><span></span><span></span>
        </div>
        <div className="dash-url">
          <span className="dash-lock">⌃</span> app.reservwise.com / {activeNav.toLowerCase().replace(/ /g,"-")}
        </div>
        <div className="dash-user">
          <div className="dash-avatar">J</div>
        </div>
      </div>
      <div className="dash-body">
        <div className="dash-side">
          <div className="dash-side-brand">
            <LogoMark size={22}/>
            <div style={{fontFamily:"var(--font-display)",fontWeight:700,fontSize:14}}>
              <span style={{color:"var(--charcoal-900)"}}>Reserv</span><span style={{color:"var(--green-600)"}}>Wise</span>
            </div>
          </div>
          <div className="dash-nav-section">Workspace</div>
          {navItems.map((n) => (
            <div key={n}
                 className={"dash-nav-item " + (activeNav === n ? "active" : "")}
                 onClick={() => setActiveNav(n)}
                 role="button"
                 tabIndex={0}>
              <span className="dash-nav-dot"></span>{n}
            </div>
          ))}
        </div>
        <div className="dash-main">
          <div className="dash-topbar">
            <div>
              <div style={{fontSize:12, color:"var(--charcoal-500)", letterSpacing:".08em", textTransform:"uppercase", fontWeight:600}}>
                Welcome back, Jordan
              </div>
              <div className="h-card" style={{fontSize:24, marginTop:4}}>
                Cashflow overview · April 2026
              </div>
            </div>
            <div className="dash-pill">
              <span className="dot" style={{background:"var(--green-500)"}}></span>
              All systems calm
            </div>
          </div>

          <div className="dash-grid">
            <ReserveRing />
            <div className="dash-stack">
              <MetricCard
                label="Safe to spend"
                value="$4,820"
                sub="this week · after reserves"
                trend={{dir:"up", value:"+12%"}}
                sparkData={[3,4,4,5,4,6,5,7,6,8,7,9]}
              />
              <MetricCard
                label="Owner draw available"
                value="$3,200"
                sub="next draw · May 1"
                trend={{dir:"up", value:"+$420"}}
                sparkData={[2,2,3,2,3,4,3,4,5,4,5,5]}
              />
            </div>
            <LiveActivity />
            <RunwayChart />
            <AICard />
            <Buckets />
            <MetricCard
              label="Tax set aside · Q2"
              value="$4,800"
              sub="79% of estimated $6,080"
              trend={{dir:"up", value:"on pace"}}
            >
              <div className="bucket-bar" style={{marginTop:14}}>
                <div className="bucket-fill" style={{"--bucket-pct":"79%", background:"var(--charcoal-800)"}}></div>
              </div>
            </MetricCard>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { DashboardHero, MetricCard, ReserveRing, RunwayChart, AICard, Buckets, LiveActivity, sparkline });
