// Scene 3: the dashboard reveal.
// Appears around 4.2s as the chips are still settling, builds in panels:
//   - Big KPI: Months of cash, ticking up to 9.2
//   - Runway line chart: animates a clean ascending curve
//   - Fund-balance bar: restricted vs unrestricted fills in
//   - Cash position counter: counts up to a tidy figure
// Holds through the headline scene (gently breathing) and then dissolves
// before the loop restarts.
//
// Transition feel is tweak-driven (see useHeroTweaks): panels rise with a long
// silk ease, lifting out of a soft blur + sub-pixel scale so the dashboard
// "resolves into focus" like an expensive product reveal instead of popping in.

const NAVY    = '#0e1f3a';
const NAVY_2  = '#1c2f4f';
const CREAM   = '#f5f0e6';
const CREAM_2 = '#ede6d6';
const ACCENT  = '#9b6a3f'; // warm copper (default; overridden by tweak)
const ACCENT_2 = '#c89a6e';
const MUTED   = '#5a6478';
const RULE    = '#d8d0bf';

// ── Tweak-aware reveal helpers ──────────────────────────────────────────────
// Every panel enters through the same vocabulary so the whole board feels like
// one calm, coordinated move: opacity + lift + a clearing blur + a sub-pixel
// scale, all on the chosen easing, all stretched by the transition-length tweak.
function _ease(t) {
  const n = (t && t.ease) || 'silk';
  return n === 'glide' ? Easing.easeInOutCubic
       : n === 'crisp' ? Easing.easeOutQuart
       : Easing.easeOutExpo; // 'silk'
}
function _dur(base, t) { return base * ((t && t.transScale) || 1); }

function revealOp(time, start, base, t) {
  const d = _dur(base, t);
  if (time < start) return 0;
  return _ease(t)(clamp((time - start) / d, 0, 1));
}
function revealLift(time, start, base, t) {
  const L = (t && t.lift != null) ? t.lift : 22;
  const d = _dur(base, t);
  if (time < start) return L;
  return (1 - _ease(t)(clamp((time - start) / d, 0, 1))) * L;
}
function revealBlur(time, start, base, t) {
  const B = (t && t.focusBlur != null) ? t.focusBlur : 10;
  const d = _dur(base, t);
  if (time < start) return B;
  return (1 - _ease(t)(clamp((time - start) / d, 0, 1))) * B;
}
function revealScale(time, start, base, t) {
  const d = _dur(base, t);
  const p = time < start ? 0 : _ease(t)(clamp((time - start) / d, 0, 1));
  return 0.985 + 0.015 * p;
}
// Compose the four into a ready-to-spread style object.
function revealStyle(time, start, base, t) {
  const blur = revealBlur(time, start, base, t);
  return {
    opacity: revealOp(time, start, base, t),
    transform: `translateY(${revealLift(time, start, base, t).toFixed(2)}px) scale(${revealScale(time, start, base, t).toFixed(4)})`,
    filter: blur > 0.04 ? `blur(${blur.toFixed(2)}px)` : 'none',
  };
}

// Months-of-cash KPI: ticks 0 → 9.2 between 4.6 and 6.4
function MonthsKpi({ time }) {
  const t = useHeroTweaks();
  const acc = (t && t.accent) || ACCENT;
  const start = 3.2;
  const end   = 5.6;
  const tt = clamp((time - start) / (end - start), 0, 1);
  const eased = Easing.easeOutCubic(tt);
  const v = (eased * 9.2).toFixed(1);

  return (
    <div style={{
      position: 'absolute',
      left: 760, top: 140,
      width: 540, height: 260,
      background: CREAM,
      border: `1px solid ${RULE}`,
      borderRadius: 6,
      padding: '32px 36px',
      boxShadow: '0 8px 24px rgba(14,31,58,0.06)',
      willChange: 'transform, opacity, filter',
      ...revealStyle(time, 3.0, 0.8, t),
    }}>
      <div style={{
        fontFamily: 'Inter, system-ui, sans-serif',
        fontSize: 13, fontWeight: 600,
        letterSpacing: '0.14em', textTransform: 'uppercase',
        color: MUTED,
      }}>
        Months of cash
      </div>
      <div style={{
        fontFamily: 'Source Serif 4, "Source Serif Pro", Georgia, serif',
        fontSize: 152,
        fontWeight: 400,
        color: NAVY,
        lineHeight: 1,
        letterSpacing: '-0.03em',
        marginTop: 12,
        fontVariantNumeric: 'tabular-nums',
        display: 'flex', alignItems: 'baseline', gap: 10,
      }}>
        {v}
        <span style={{
          fontFamily: 'Inter, system-ui, sans-serif',
          fontSize: 22, fontWeight: 500,
          color: acc,
          letterSpacing: '0.04em',
        }}>
          ↑ healthy
        </span>
      </div>
      <div style={{
        marginTop: 14,
        fontFamily: 'Inter, system-ui, sans-serif',
        fontSize: 14, color: MUTED,
        letterSpacing: '-0.005em',
      }}>
        Up from 3.1 months at engagement.
      </div>
    </div>
  );
}

// Runway line chart: a clean ascending line that draws in.
// Uses SVG path with stroke-dasharray reveal.
function RunwayChart({ time }) {
  const t = useHeroTweaks();
  const acc = (t && t.accent) || ACCENT;

  // Reveal animation 5.2 → 6.8
  const drawT = clamp((time - 3.7) / 2.0, 0, 1);
  const drawn = Easing.easeInOutCubic(drawT);

  // 12 monthly data points, ascending with a small dip mid-year (storytelling)
  const data = [3.1, 3.6, 4.0, 4.2, 4.0, 4.6, 5.4, 6.1, 6.8, 7.5, 8.4, 9.2];
  const w = 460, h = 150;
  const padX = 8, padY = 12;
  const innerW = w - padX * 2;
  const innerH = h - padY * 2;
  const maxV = 10, minV = 0;
  const pts = data.map((v, i) => {
    const x = padX + (i / (data.length - 1)) * innerW;
    const y = padY + (1 - (v - minV) / (maxV - minV)) * innerH;
    return [x, y];
  });
  const d = pts.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(' ');

  // Approximate path length for stroke reveal
  const pathLen = 700;

  return (
    <div style={{
      position: 'absolute',
      left: 760, top: 420,
      width: 540, height: 220,
      background: CREAM,
      border: `1px solid ${RULE}`,
      borderRadius: 6,
      padding: '20px 24px',
      boxShadow: '0 8px 24px rgba(14,31,58,0.06)',
      willChange: 'transform, opacity, filter',
      ...revealStyle(time, 3.4, 0.8, t),
    }}>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
        marginBottom: 6,
      }}>
        <div style={{
          fontFamily: 'Inter, system-ui, sans-serif',
          fontSize: 13, fontWeight: 600,
          letterSpacing: '0.14em', textTransform: 'uppercase',
          color: MUTED,
        }}>
          Runway · 12 mo
        </div>
        <div style={{
          fontFamily: 'JetBrains Mono, ui-monospace, monospace',
          fontSize: 12, color: MUTED,
          letterSpacing: '0.04em',
        }}>
          FY24 → FY26
        </div>
      </div>
      <svg width={w} height={h} style={{ display: 'block', overflow: 'visible' }}>
        {/* Baseline grid */}
        {[0, 0.25, 0.5, 0.75, 1].map((g, i) => (
          <line key={i}
            x1={padX} x2={w - padX}
            y1={padY + g * innerH} y2={padY + g * innerH}
            stroke={RULE} strokeWidth={1}
          />
        ))}
        {/* Path with reveal */}
        <path
          d={d}
          fill="none"
          stroke={NAVY}
          strokeWidth={2.5}
          strokeLinejoin="round"
          strokeLinecap="round"
          style={{
            strokeDasharray: pathLen,
            strokeDashoffset: pathLen * (1 - drawn),
          }}
        />
        {/* Endpoint dot */}
        {drawn > 0.96 && (
          <circle
            cx={pts[pts.length - 1][0]} cy={pts[pts.length - 1][1]}
            r={5} fill={acc}
            opacity={(drawn - 0.96) / 0.04}
          />
        )}
      </svg>
    </div>
  );
}

// Fund-balance bar: restricted/unrestricted split fills horizontally.
function FundBalanceBar({ time }) {
  const t = useHeroTweaks();
  const acc = (t && t.accent) || ACCENT;

  // Fill in 5.6 → 6.6
  const fillT = clamp((time - 3.9) / 1.4, 0, 1);
  const fill = Easing.easeOutCubic(fillT);

  const restrictedPct = 0.42;
  const unrestrictedPct = 0.58;
  const totalW = 480;

  return (
    <div style={{
      position: 'absolute',
      left: 200, top: 420,
      width: 540, height: 220,
      background: CREAM,
      border: `1px solid ${RULE}`,
      borderRadius: 6,
      padding: '20px 24px',
      boxShadow: '0 8px 24px rgba(14,31,58,0.06)',
      willChange: 'transform, opacity, filter',
      ...revealStyle(time, 3.7, 0.8, t),
    }}>
      <div style={{
        fontFamily: 'Inter, system-ui, sans-serif',
        fontSize: 13, fontWeight: 600,
        letterSpacing: '0.14em', textTransform: 'uppercase',
        color: MUTED,
      }}>
        Net assets · by class
      </div>
      <div style={{
        marginTop: 16,
        fontFamily: 'Source Serif 4, "Source Serif Pro", Georgia, serif',
        fontSize: 40,
        fontWeight: 400,
        color: NAVY,
        lineHeight: 1,
        letterSpacing: '-0.02em',
        fontVariantNumeric: 'tabular-nums',
      }}>
        $1,084,392
      </div>
      {/* The bar */}
      <div style={{
        marginTop: 22,
        width: totalW, height: 14,
        background: CREAM_2,
        borderRadius: 2,
        position: 'relative',
        overflow: 'hidden',
      }}>
        <div style={{
          position: 'absolute', left: 0, top: 0, bottom: 0,
          width: totalW * unrestrictedPct * fill,
          background: NAVY,
        }}/>
        <div style={{
          position: 'absolute',
          left: totalW * unrestrictedPct, top: 0, bottom: 0,
          width: totalW * restrictedPct * fill,
          background: acc,
        }}/>
      </div>
      {/* Legend */}
      <div style={{
        marginTop: 14,
        display: 'flex', gap: 24,
        fontFamily: 'Inter, system-ui, sans-serif',
        fontSize: 13, color: MUTED,
        opacity: fill,
      }}>
        <LegendDot color={NAVY} label="Unrestricted" pct="58%" />
        <LegendDot color={acc} label="Restricted" pct="42%" />
      </div>
    </div>
  );
}

function LegendDot({ color, label, pct }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
      <div style={{
        width: 10, height: 10, borderRadius: 5,
        background: color,
      }}/>
      <div>{label}</div>
      <div style={{
        fontFamily: 'JetBrains Mono, ui-monospace, monospace',
        fontVariantNumeric: 'tabular-nums',
        color: NAVY, fontWeight: 500,
      }}>{pct}</div>
    </div>
  );
}

// Cash position: top-left card with counter ticking up.
function CashPosition({ time }) {
  const t = useHeroTweaks();

  const start = 3.4;
  const end = 5.8;
  const tt = clamp((time - start) / (end - start), 0, 1);
  const eased = Easing.easeOutCubic(tt);
  const target = 487420;
  const v = Math.round(eased * target);
  const formatted = v.toLocaleString('en-US');

  return (
    <div style={{
      position: 'absolute',
      left: 200, top: 140,
      width: 540, height: 260,
      background: NAVY,
      borderRadius: 6,
      padding: '32px 36px',
      boxShadow: '0 12px 32px rgba(14,31,58,0.18)',
      color: CREAM,
      willChange: 'transform, opacity, filter',
      ...revealStyle(time, 3.2, 0.8, t),
    }}>
      <div style={{
        fontFamily: 'Inter, system-ui, sans-serif',
        fontSize: 13, fontWeight: 600,
        letterSpacing: '0.14em', textTransform: 'uppercase',
        color: 'rgba(245,240,230,0.7)',
      }}>
        Cash position
      </div>
      <div style={{
        fontFamily: 'Source Serif 4, "Source Serif Pro", Georgia, serif',
        fontSize: 96,
        fontWeight: 400,
        lineHeight: 1,
        letterSpacing: '-0.03em',
        marginTop: 14,
        fontVariantNumeric: 'tabular-nums',
        color: CREAM,
      }}>
        ${formatted}
      </div>
      <div style={{
        marginTop: 20,
        display: 'flex', gap: 24,
        fontFamily: 'Inter, system-ui, sans-serif',
        fontSize: 14,
        color: 'rgba(245,240,230,0.7)',
      }}>
        <div>
          <div style={{ color: ACCENT_2, fontWeight: 500 }}>+ $214,180</div>
          <div style={{ fontSize: 12, marginTop: 2 }}>vs. Jan 2025</div>
        </div>
        <div style={{ width: 1, background: 'rgba(245,240,230,0.15)' }}/>
        <div>
          <div style={{ color: CREAM, fontWeight: 500 }}>Reconciled</div>
          <div style={{ fontSize: 12, marginTop: 2 }}>through Mar 31, 2026</div>
        </div>
      </div>
    </div>
  );
}

// A small "NFP CFO · Q1 Report" header above the dashboard area
function DashHeader({ time }) {
  const t = useHeroTweaks();
  return (
    <div style={{
      position: 'absolute',
      left: 200, top: 78,
      display: 'flex', alignItems: 'baseline', gap: 18,
      willChange: 'transform, opacity, filter',
      ...revealStyle(time, 3.0, 0.75, t),
    }}>
      <div style={{
        fontFamily: 'Inter, system-ui, sans-serif',
        fontSize: 13, fontWeight: 600,
        color: NAVY,
        letterSpacing: '0.18em', textTransform: 'uppercase',
      }}>
        Board Packet · Q1 FY26
      </div>
      <div style={{
        fontFamily: 'JetBrains Mono, ui-monospace, monospace',
        fontSize: 12, color: MUTED,
        letterSpacing: '0.04em',
      }}>
        Prepared by The Not-For-Profit CFO
      </div>
    </div>
  );
}

function DashboardScene() {
  const time = useTime();
  const t = useHeroTweaks();

  // Dashboard exits before the headline takes over — longer, softer handoff:
  // it eases up, scales down a hair, and melts into a blur so the headline can
  // rise through it (a real crossfade, not a hard cut).
  const exitStart = 8.2;
  const exitEnd   = 9.1;
  let groupOp = 1;
  let groupLift = 0;
  let groupScale = 1;
  let groupBlur = 0;
  if (time >= exitStart) {
    const tt = clamp((time - exitStart) / (exitEnd - exitStart), 0, 1);
    const eased = _ease(t)(tt);
    groupOp = 1 - eased;
    groupLift = -eased * 26;
    groupScale = 1 - eased * 0.03;
    groupBlur = eased * (((t && t.focusBlur != null) ? t.focusBlur : 10) * 0.8);
  }

  // Subtle "breathing" while held
  const holdStart = 5.9;
  const breath = time > holdStart && time < exitStart
    ? Math.sin((time - holdStart) * 1.4) * 1.2
    : 0;

  if (time < 2.9) return null;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      opacity: groupOp,
      transform: `translateY(${(groupLift + breath).toFixed(2)}px) scale(${groupScale.toFixed(4)})`,
      transformOrigin: 'center',
      filter: groupBlur > 0.04 ? `blur(${groupBlur.toFixed(2)}px)` : 'none',
      willChange: 'transform, opacity, filter',
    }}>
      <DashHeader time={time} />
      <CashPosition time={time} />
      <MonthsKpi time={time} />
      <FundBalanceBar time={time} />
      <RunwayChart time={time} />
    </div>
  );
}

Object.assign(window, { DashboardScene });
