// Forecast — weighted pipeline, target tracking by month/quarter/FY
function Forecast({ deals, stages, reps, months, allDeals, targets, currentUser, showroomScope, filters, showrooms }) {
  const [monthWindow, setMonthWindow] = React.useState(0); // 0 = current+next3, negative = scroll back
  const [forecastView, setForecastView] = React.useState('showroom');
  const active = deals.filter(d => d.stage !== 'sold' && d.stage !== 'lost');
  const won = deals.filter(d => d.stage === 'sold');

  // Determine which designer to scope targets to
  // Priority: filters.rep (if set) > sales_designer's own repId
  const focusRepId = (filters && filters.rep && filters.rep !== 'all')
    ? filters.rep
    : (currentUser.role === 'sales_designer' ? currentUser.repId : null);
  const focusRep = focusRepId ? reps.find(r => r.id === focusRepId) : null;

  // Weighted pipeline
  const weighted = active.reduce((s, d) => {
    const p = stages.find(x => x.id === d.stage)?.prob || 0;
    return s + d.value * p;
  }, 0);
  const totalActive = active.reduce((s, d) => s + d.value, 0);
  const committed = active.filter(d => d.stage === 'in_progress').reduce((s, d) => s + d.value, 0);
  const wonTotal = won.reduce((s, d) => s + d.value, 0);

  // FY26 progress (Jul 25 – Jun 26)
  const fyMonths = FY_MONTHS.map(m => m.key);
  const _now = new Date();
  const currentMonth = `${_now.getFullYear()}-${String(_now.getMonth() + 1).padStart(2, '0')}`;
  const currentQ = FY_MONTHS.find(m => m.key === currentMonth)?.q || 4;
  const monthsThisFY = FY_MONTHS.filter(m => m.key <= currentMonth).map(m => m.key);
  const monthsThisQ = FY_MONTHS.filter(m => m.q === currentQ).map(m => m.key);

  // Use the filtered deals (deals prop) for target achieved — respects rep + showroom + date filters
  // This way the cards react to every filter, not just the rep dropdown.
  const sourceDeals = deals;
  const fyProgress = computeTargetProgress(sourceDeals, targets || {}, focusRepId, fyMonths);
  const ytdProgress = computeTargetProgress(sourceDeals, targets || {}, focusRepId, monthsThisFY);
  const qProgress = computeTargetProgress(sourceDeals, targets || {}, focusRepId, monthsThisQ);
  const thisMonthProgress = computeTargetProgress(sourceDeals, targets || {}, focusRepId, [currentMonth]);

  // Monthly progress — window of current month + next 3 (default), scrollable to past months.
  // Build a continuous list of YYYY-MM keys spanning a few years so we can window into it.
  const allMonthKeys = [];
  for (let y = 2024; y <= 2027; y++) {
    for (let mo = 1; mo <= 12; mo++) {
      allMonthKeys.push(`${y}-${String(mo).padStart(2, '0')}`);
    }
  }
  const monthLabel = (key) => {
    const [y, mo] = key.split('-').map(Number);
    return new Date(y, mo - 1, 1).toLocaleDateString('en-AU', { month: 'short', year: '2-digit' });
  };
  const monthQuarter = (key) => {
    const mo = Number(key.split('-')[1]);
    // Australian FY quarters: Q1 Jul-Sep, Q2 Oct-Dec, Q3 Jan-Mar, Q4 Apr-Jun
    if (mo >= 7 && mo <= 9) return 1;
    if (mo >= 10 && mo <= 12) return 2;
    if (mo >= 1 && mo <= 3) return 3;
    return 4;
  };
  const curIdx = allMonthKeys.indexOf(currentMonth);
  const windowStart = curIdx + monthWindow; // monthWindow 0 = start at current month
  const windowKeys = allMonthKeys.slice(Math.max(0, windowStart), Math.max(0, windowStart) + 4);
  const monthlyRows = windowKeys.map(key => {
    const prog = computeTargetProgress(sourceDeals, targets || {}, focusRepId, [key]);
    return { key, label: monthLabel(key), q: monthQuarter(key), ...prog };
  });

  // Quarterly summary
  const quarters = [1, 2, 3, 4].map(qNum => {
    const qKeys = FY_MONTHS.filter(m => m.q === qNum).map(m => m.key);
    const prog = computeTargetProgress(sourceDeals, targets || {}, focusRepId, qKeys);
    return { q: qNum, label: `Q${qNum}`, ...prog };
  });

  const hasTargets = fyProgress.targetTotal > 0;

  // ── 3-month forecast by showroom + rep ──────────────────────────────────
  const getMonthKeys = (startKey, count) => {
    const keys = []; let [y, m] = startKey.split('-').map(Number);
    for (let i = 0; i < count; i++) {
      keys.push(`${y}-${String(m).padStart(2, '0')}`); m++; if (m > 12) { m = 1; y++; }
    }
    return keys;
  };
  const nextMonths = getMonthKeys(currentMonth, 3);
  const nextMonthLabels = nextMonths.map(k => {
    const [y, mo] = k.split('-').map(Number);
    return new Date(y, mo - 1, 1).toLocaleDateString('en-AU', { month: 'short', year: '2-digit' });
  });
  const getWeighted = (d) => (stages.find(s => s.id === d.stage)?.prob || 0) * d.value;
  const buildForecastRows = (groupKey, items) => {
    return items.map(item => {
      const itemDeals = active.filter(d => d[groupKey] === item.id);
      const monthValues = nextMonths.map(mk => {
        const mDeals = itemDeals.filter(d => d.forecastDepositMonth === mk);
        return { key: mk, value: mDeals.reduce((s, d) => s + d.value, 0), weighted: mDeals.reduce((s, d) => s + getWeighted(d), 0), count: mDeals.length };
      });
      const pipeline = itemDeals.reduce((s, d) => s + d.value, 0);
      const scheduledVal = monthValues.reduce((s, mv) => s + mv.value, 0);
      return { ...item, monthValues, pipeline, scheduledVal, unscheduled: pipeline - scheduledVal };
    }).filter(r => r.pipeline > 0).sort((a, b) => b.scheduledVal - a.scheduledVal);
  };
  const showroomRows = buildForecastRows('showroom', showrooms || []);
  const repRows = buildForecastRows('rep', reps);
  const forecastRows = forecastView === 'showroom' ? showroomRows : repRows;
  const forecastTotals = nextMonths.map(mk => forecastRows.reduce((s, r) => s + (r.monthValues.find(v => v.key === mk)?.value || 0), 0));
  const totalScheduled = forecastRows.reduce((s, r) => s + r.scheduledVal, 0);
  const totalUnscheduled = forecastRows.reduce((s, r) => s + r.unscheduled, 0);
  const totalPipeline = forecastRows.reduce((s, r) => s + r.pipeline, 0);

  return (
    <div>
      {!hasTargets && currentUser.role === 'sales_designer' && (
        <div className="card" style={{ marginBottom: 16, padding: '14px 18px', background: 'var(--warn-soft)', border: '1px solid oklch(0.85 0.08 70)' }}>
          <div style={{ fontSize: 13, fontWeight: 600, color: 'oklch(0.45 0.13 60)' }}>
            <Icon name="alert" size={13}/> No targets set yet
          </div>
          <div style={{ fontSize: 12, color: 'var(--ink-2)', marginTop: 4 }}>
            Your manager hasn't set monthly targets for you yet. Ask them to set them in Admin → Targets.
          </div>
        </div>
      )}

      {hasTargets && (
        <div>
          <div style={{ marginBottom: 6, fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 500 }}>
            {focusRep ? `${focusRep.name} · sold deals vs target` : 'Team · sold deals vs target'}
          </div>
          <div className="forecast-grid" style={{ marginBottom: 18 }}>
            <TargetCard label="This month" period="May 26" progress={thisMonthProgress}/>
            <TargetCard label={`This quarter (Q${currentQ})`} period={`Q${currentQ} FY26`} progress={qProgress} accent/>
            <TargetCard label="FY26 to date" period="Year to date" progress={ytdProgress}/>
            <TargetCard label="FY26 full year" period="Jul 25 – Jun 26" progress={fyProgress} muted/>
          </div>
        </div>
      )}

      <div className="forecast-grid">
        <div className="fc-card">
          <div className="fc-label">Committed</div>
          <div className="fc-value num">{fmt.money(committed, true)}</div>
          <div className="fc-foot">In Progress · 50% prob</div>
        </div>
        <div className="fc-card" style={{ borderColor: 'var(--accent)', background: 'var(--accent-soft)' }}>
          <div className="fc-label" style={{ color: 'var(--accent-ink)' }}>Weighted forecast</div>
          <div className="fc-value num" style={{ color: 'var(--accent-ink)' }}>{fmt.money(weighted, true)}</div>
          <div className="fc-foot" style={{ color: 'var(--accent-ink)' }}>Probability-weighted pipeline</div>
        </div>
        <div className="fc-card">
          <div className="fc-label">Best case</div>
          <div className="fc-value num">{fmt.money(totalActive, true)}</div>
          <div className="fc-foot">All active deals win</div>
        </div>
      </div>

      {/* 3-Month Revenue Forecast — by showroom & designer */}
      <div className="card" style={{ marginBottom: 18 }}>
        <div className="card-hd">
          <div>
            <div className="card-title">3-Month Revenue Forecast</div>
            <div className="card-sub">Active deals with deposit month set · {nextMonthLabels.join(' · ')}</div>
          </div>
          <div className="seg">
            <button className={forecastView === 'showroom' ? 'on' : ''} onClick={() => setForecastView('showroom')}>By Showroom</button>
            <button className={forecastView === 'rep' ? 'on' : ''} onClick={() => setForecastView('rep')}>By Designer</button>
          </div>
        </div>
        <div className="tbl-wrap">
          <table className="tbl">
            <thead>
              <tr>
                <th>{forecastView === 'showroom' ? 'Showroom' : 'Designer'}</th>
                {nextMonths.map((m, i) => (
                  <th key={m} className="num-col">{nextMonthLabels[i]}</th>
                ))}
                <th className="num-col">3-mo total</th>
                <th className="num-col">Unscheduled</th>
                <th className="num-col">Total pipeline</th>
              </tr>
            </thead>
            <tbody>
              {forecastRows.map(row => (
                <tr key={row.id}>
                  <td>
                    {forecastView === 'showroom' ? (
                      <span className="pill">
                        <span className={`ss-tab-dot ${row.id}`} style={{ background: `var(--ss-${row.id}, var(--accent))` }}></span>
                        <span style={{ fontWeight: 500 }}>{row.name}</span>
                      </span>
                    ) : (
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                        <Avatar name={row.name} sz="sm"/>
                        <span style={{ fontWeight: 500 }}>{row.name}</span>
                      </div>
                    )}
                  </td>
                  {row.monthValues.map(mv => (
                    <td key={mv.key} className="num-col">
                      {mv.value > 0 ? (
                        <div>
                          <span className="num" style={{ fontWeight: 500 }}>{fmt.money(mv.value, true)}</span>
                          <span style={{ fontSize: 10, color: 'var(--ink-4)', marginLeft: 3 }}>{mv.count}d</span>
                        </div>
                      ) : <span style={{ color: 'var(--ink-4)' }}>—</span>}
                    </td>
                  ))}
                  <td className="num-col">
                    <span className="num" style={{ fontWeight: 600, color: row.scheduledVal > 0 ? 'var(--accent)' : 'var(--ink-4)' }}>
                      {row.scheduledVal > 0 ? fmt.money(row.scheduledVal, true) : '—'}
                    </span>
                  </td>
                  <td className="num-col">
                    <span className="num" style={{ color: 'var(--ink-3)' }}>
                      {row.unscheduled > 0 ? fmt.money(row.unscheduled, true) : '—'}
                    </span>
                  </td>
                  <td className="num-col">
                    <span className="num" style={{ fontWeight: 500 }}>{fmt.money(row.pipeline, true)}</span>
                  </td>
                </tr>
              ))}
              {forecastRows.length === 0 && (
                <tr><td colSpan={5 + nextMonths.length} className="empty">No active deals in pipeline</td></tr>
              )}
            </tbody>
            <tfoot>
              <tr style={{ background: 'var(--surface-2)', fontWeight: 600 }}>
                <td>Total</td>
                {forecastTotals.map((t, i) => (
                  <td key={nextMonths[i]} className="num-col"><span className="num">{fmt.money(t, true)}</span></td>
                ))}
                <td className="num-col"><span className="num" style={{ color: 'var(--accent)' }}>{fmt.money(totalScheduled, true)}</span></td>
                <td className="num-col"><span className="num" style={{ color: 'var(--ink-3)' }}>{fmt.money(totalUnscheduled, true)}</span></td>
                <td className="num-col"><span className="num">{fmt.money(totalPipeline, true)}</span></td>
              </tr>
            </tfoot>
          </table>
        </div>
        <div style={{ padding: '8px 16px', borderTop: '1px solid var(--border)', fontSize: 11, color: 'var(--ink-3)', display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          <span><strong>3-mo total</strong> = deals with forecast deposit month in next 3 months</span>
          <span style={{ marginLeft: 'auto' }}><strong>Unscheduled</strong> = active deals without a forecast month — update deals to improve accuracy</span>
        </div>
      </div>

      {hasTargets && (
        <div className="card" style={{ marginBottom: 18 }}>
          <div className="card-hd">
            <div>
              <div className="card-title">Monthly progress vs target</div>
              <div className="card-sub">{focusRep ? focusRep.name : 'Team'} · sold deals only</div>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <button className="btn sm" onClick={() => setMonthWindow(w => w - 1)} title="Earlier months"><Icon name="chevron-left" size={12}/></button>
              <button className="btn sm" onClick={() => setMonthWindow(0)} disabled={monthWindow === 0} style={monthWindow === 0 ? { opacity: 0.5 } : null}>Current</button>
              <button className="btn sm" onClick={() => setMonthWindow(w => w + 1)} title="Later months"><Icon name="chevron-right" size={12}/></button>
            </div>
          </div>
          <div style={{ padding: '14px 18px' }}>
            {monthlyRows.map((m, idx) => {
              const pct = m.targetTotal > 0 ? m.achieved / m.targetTotal : 0;
              const over = pct >= 1;
              const isPast = m.key < currentMonth;
              const isCurrent = m.key === currentMonth;
              const isFuture = m.key > currentMonth;
              const barWidth = Math.min(pct, 1.3) * 100;
              return (
                <div key={m.key} style={{ marginBottom: 14 }}>
                  <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 6 }}>
                    <span style={{ fontSize: 12, fontWeight: isCurrent ? 600 : 500, color: isFuture ? 'var(--ink-3)' : 'var(--ink)' }}>
                      {m.label}
                      <span style={{ fontSize: 10, color: 'var(--ink-4)', marginLeft: 6, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Q{m.q}</span>
                      {isCurrent && <span className="pill" style={{ marginLeft: 6, background: 'var(--accent)', color: 'white', fontSize: 10 }}>Current</span>}
                    </span>
                    <span style={{ fontSize: 11.5, color: 'var(--ink-3)' }} className="num">
                      <span style={{ color: over ? 'var(--won)' : (isPast && pct < 0.8 ? 'var(--lost)' : 'var(--ink-2)'), fontWeight: 500 }}>{fmt.money(m.achieved, true)}</span>
                      {' '}of {fmt.money(m.targetTotal, true)}
                      {m.targetTotal > 0 && <span style={{ marginLeft: 8, fontWeight: 600, color: over ? 'var(--won)' : 'var(--ink-2)' }}>{fmt.pct(pct, 0)}</span>}
                    </span>
                  </div>
                  <div style={{ position: 'relative', height: 18, background: 'var(--surface-2)', borderRadius: 4, overflow: 'hidden' }}>
                    {m.targetTotal > 0 && (
                      <>
                        <div style={{
                          position: 'absolute', left: 0, top: 0, bottom: 0,
                          width: Math.min(barWidth, 100) + '%',
                          background: over ? 'var(--won)' : isPast && pct < 0.8 ? 'var(--lost)' : isCurrent ? 'var(--accent)' : 'var(--ink-2)',
                        }}/>
                        {over && (
                          <div style={{
                            position: 'absolute', left: '100%', top: 0, bottom: 0,
                            width: ((barWidth - 100) / 100 * 100) + '%',
                            background: 'oklch(0.4 0.12 155)',
                          }}/>
                        )}
                        <div style={{ position: 'absolute', left: '100%', top: -2, bottom: -2, width: 1.5, background: 'var(--ink)' }}/>
                      </>
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {hasTargets && (
        <div className="grid-2-eq" style={{ marginBottom: 18 }}>
          <div className="card">
            <div className="card-hd">
              <div>
                <div className="card-title">Quarterly performance</div>
                <div className="card-sub">FY26 by quarter</div>
              </div>
            </div>
            <div style={{ padding: 18 }}>
              {quarters.map(q => {
                const over = q.pct >= 1;
                const isCurrent = q.q === currentQ;
                const isPast = q.q < currentQ;
                const isFuture = q.q > currentQ;
                return (
                  <div key={q.q} style={{ marginBottom: 16, padding: 14, border: '1px solid var(--border)', borderRadius: 8, background: isCurrent ? 'var(--accent-soft)' : 'var(--surface)' }}>
                    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
                      <div>
                        <span style={{ fontSize: 14, fontWeight: 600 }}>{q.label}</span>
                        {isCurrent && <span className="pill" style={{ marginLeft: 8, background: 'var(--accent)', color: 'white', fontSize: 10 }}>Current</span>}
                        {isPast && over && <span className="pill" style={{ marginLeft: 8, background: 'var(--won-soft)', color: 'oklch(0.35 0.1 155)', fontSize: 10 }}>Achieved</span>}
                        {isPast && !over && <span className="pill" style={{ marginLeft: 8, background: 'var(--lost-soft)', color: 'oklch(0.4 0.12 28)', fontSize: 10 }}>Missed</span>}
                      </div>
                      <span style={{ fontSize: 18, fontWeight: 700, color: over ? 'var(--won)' : 'var(--ink)' }} className="num">{fmt.pct(q.pct, 0)}</span>
                    </div>
                    <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginBottom: 6 }} className="num">
                      <strong style={{ color: 'var(--ink)' }}>{fmt.money(q.achieved, true)}</strong> of {fmt.money(q.targetTotal, true)}
                    </div>
                    <div style={{ height: 6, background: 'var(--surface-3)', borderRadius: 3, overflow: 'hidden' }}>
                      <div style={{ width: Math.min(q.pct, 1) * 100 + '%', height: '100%', background: over ? 'var(--won)' : isPast ? 'var(--lost)' : 'var(--accent)' }}/>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>

          <div className="card">
            <div className="card-hd">
              <div>
                <div className="card-title">FY26 summary</div>
                <div className="card-sub">{focusRep ? focusRep.name : 'Team'} · year-end projection</div>
              </div>
            </div>
            <div style={{ padding: 18 }}>
              <div style={{ marginBottom: 18, padding: 14, background: 'var(--surface-2)', borderRadius: 8 }}>
                <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 500 }}>FY26 Annual Target</div>
                <div style={{ fontSize: 28, fontWeight: 700, letterSpacing: '-0.02em', marginTop: 4 }} className="num">{fmt.money(fyProgress.targetTotal, true)}</div>
              </div>
              <div style={{ marginBottom: 14 }}>
                <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginBottom: 4 }}>Sold year-to-date</div>
                <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                  <span style={{ fontSize: 22, fontWeight: 600 }} className="num">{fmt.money(ytdProgress.achieved, true)}</span>
                  <span className="num" style={{ color: ytdProgress.pct >= 0.9 ? 'var(--won)' : ytdProgress.pct >= 0.6 ? 'var(--ink-2)' : 'var(--lost)', fontWeight: 600 }}>{fmt.pct(ytdProgress.pct, 0)}</span>
                </div>
              </div>
              <div style={{ marginBottom: 14 }}>
                <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginBottom: 4 }}>Remaining to hit FY26 (sold $ needed)</div>
                <div style={{ fontSize: 18, fontWeight: 500 }} className="num">{fmt.money(Math.max(0, fyProgress.targetTotal - ytdProgress.achieved), true)}</div>
              </div>
              <div>
                <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginBottom: 4 }}>Projected year-end <span style={{ fontStyle: 'italic' }}>(sold + weighted pipeline)</span></div>
                <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                  <span style={{ fontSize: 20, fontWeight: 600, color: 'var(--accent)' }} className="num">{fmt.money(ytdProgress.achieved + weighted, true)}</span>
                  <span className="num" style={{ color: 'var(--ink-3)' }}>
                    {fyProgress.targetTotal > 0 ? fmt.pct((ytdProgress.achieved + weighted) / fyProgress.targetTotal, 0) + ' of target' : ''}
                  </span>
                </div>
                <div style={{ fontSize: 11, color: 'var(--ink-4)', marginTop: 4 }}>
                  Projection only · target only counts sold deals
                </div>
              </div>
            </div>
          </div>
        </div>
      )}

      <div className="card">
        <div className="card-hd">
          <div>
            <div className="card-title">Weighted pipeline by stage</div>
            <div className="card-sub">Value × stage probability</div>
          </div>
        </div>
        <div className="card-pad">
          {stages.filter(s => s.id !== 'sold' && s.id !== 'lost').map(s => {
            const ds = active.filter(d => d.stage === s.id);
            const raw = ds.reduce((sm, d) => sm + d.value, 0);
            const wtd = raw * s.prob;
            const max = Math.max(...stages.filter(x => x.id !== 'sold' && x.id !== 'lost').map(x => active.filter(d => d.stage === x.id).reduce((sm, d) => sm + d.value, 0)), 1);
            return (
              <div key={s.id} style={{ display: 'grid', gridTemplateColumns: '140px 1fr 90px 90px', gap: 12, alignItems: 'center', padding: '8px 0', fontSize: 12.5 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
                  <span style={{ width: 8, height: 8, borderRadius: 4, background: `var(--s-${s.id})` }}></span>
                  {s.label} <span style={{ color: 'var(--ink-3)', fontSize: 11 }}>· {fmt.pct(s.prob, 0)}</span>
                </div>
                <div style={{ position: 'relative', height: 18, background: 'var(--surface-2)', borderRadius: 3 }}>
                  <div style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: (raw / max * 100) + '%', background: 'var(--surface-3)', borderRadius: 3 }}/>
                  <div style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: (wtd / max * 100) + '%', background: `var(--s-${s.id})`, borderRadius: 3 }}/>
                </div>
                <div style={{ textAlign: 'right', color: 'var(--ink-3)' }}><span className="num">{fmt.money(raw, true)}</span></div>
                <div style={{ textAlign: 'right', fontWeight: 600 }}><span className="num">{fmt.money(wtd, true)}</span></div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

function TargetCard({ label, period, progress, accent, muted }) {
  const pct = progress.pct;
  const over = pct >= 1;
  const color = muted ? 'var(--ink-2)' : accent ? 'var(--accent)' : 'var(--ink)';
  const pctColor = over ? 'var(--won)' : pct >= 0.7 ? 'var(--ink)' : pct >= 0.4 ? 'oklch(0.55 0.13 60)' : 'var(--lost)';
  return (
    <div className="fc-card" style={accent ? { borderColor: 'var(--accent)', background: 'var(--accent-soft)' } : null}>
      <div className="fc-label" style={accent ? { color: 'var(--accent-ink)' } : null}>{label}</div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginTop: 4 }}>
        <span className="fc-value num" style={{ fontSize: 22, color: accent ? 'var(--accent-ink)' : color }}>{fmt.money(progress.achieved, true)}</span>
        <span style={{ fontSize: 14, fontWeight: 600, color: pctColor }} className="num">{progress.targetTotal > 0 ? fmt.pct(pct, 0) : '—'}</span>
      </div>
      <div style={{ marginTop: 8, height: 5, background: 'var(--surface-3)', borderRadius: 3, overflow: 'hidden' }}>
        {progress.targetTotal > 0 && (
          <div style={{ width: Math.min(pct, 1) * 100 + '%', height: '100%', background: pctColor, borderRadius: 3 }}/>
        )}
      </div>
      <div className="fc-foot" style={{ marginTop: 6 }}>
        of {fmt.money(progress.targetTotal, true)} · {period}
      </div>
    </div>
  );
}

window.Forecast = Forecast;
