// ─────────────────────────────────────────────────────────────
// NATIONAL VA LOANS — VIDEO SCENE LAYOUTS
// Every layout reads its text from the scene object in the video file.
// Text helpers:  "\n" = line break    *word* = highlight in accent green
// ─────────────────────────────────────────────────────────────
const NB = window.NVL_BRAND;
const NC = NB.colors;

const ease = (t, a, d = 0.6, fn = Easing.easeOutCubic) => fn(clamp((t - a) / d, 0, 1));
const fmtMoney = (n) => '$' + Math.round(n).toLocaleString('en-US');

const THEMES = {
  light: { bg: NC.paper, fg: NC.ink, head: NC.ink, eyebrow: NC.cta, muted: 'rgba(11,21,38,0.68)', fine: 'rgba(11,21,38,0.5)', rule: NC.divider, hi: NC.greenText },
  brand: { bg: NC.navy, fg: '#fff', head: '#fff', eyebrow: NC.sky, muted: 'rgba(255,255,255,0.78)', fine: 'rgba(255,255,255,0.55)', rule: 'rgba(255,255,255,0.15)', hi: NC.green },
  dark:  { bg: NC.navyDark, fg: '#fff', head: '#fff', eyebrow: NC.sky, muted: 'rgba(255,255,255,0.78)', fine: 'rgba(255,255,255,0.55)', rule: 'rgba(255,255,255,0.15)', hi: NC.green },
};

// "\n" → <br/>, *x* → highlighted span
function Rich({ text, hi }) {
  if (text == null) return null;
  return String(text).split('\n').map((line, li, arr) => (
    <React.Fragment key={li}>
      {line.split(/(\*[^*]+\*)/g).map((part, pi) =>
        part.startsWith('*') && part.endsWith('*') && part.length > 2
          ? <span key={pi} style={{ color: hi, fontWeight: 700 }}>{part.slice(1, -1)}</span>
          : <React.Fragment key={pi}>{part}</React.Fragment>
      )}
      {li < arr.length - 1 && <br />}
    </React.Fragment>
  ));
}

function TScene({ theme, label, children }) {
  const { localTime, duration } = useSprite();
  const o = Math.min(ease(localTime, 0, 0.5), 1 - ease(localTime, duration - 0.45, 0.45, Easing.easeInCubic));
  return <div data-screen-label={label} style={{ position: 'absolute', inset: 0, background: theme.bg, opacity: o, overflow: 'hidden' }}>{children}</div>;
}
function TRise({ t, at, dist = 30, dur = 0.7, style, children }) {
  const p = ease(t, at, dur);
  return <div style={{ opacity: p, transform: `translateY(${(1 - p) * dist}px)`, ...style }}>{children}</div>;
}
const TEyebrow = ({ theme, children }) => children ? <div style={{ fontSize: 26, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase', color: theme.eyebrow }}>{children}</div> : null;
function TFine({ theme, center, children }) {
  if (!children) return null;
  return <div style={{ position: 'absolute', left: 120, right: 120, bottom: 250, fontSize: 22, lineHeight: 1.4, color: theme.fine, textWrap: 'pretty', textAlign: center ? 'center' : 'left' }}>{children}</div>;
}
function THeader({ t, theme, s, size = 72, top = 100, width = 1680 }) {
  return (
    <div style={{ position: 'absolute', left: 120, top, width }}>
      <TRise t={t} at={0.2}><TEyebrow theme={theme}>{s.eyebrow}</TEyebrow></TRise>
      <div style={{ height: 20 }} />
      <TRise t={t} at={0.4}><div style={{ fontSize: size, fontWeight: 800, color: theme.head, letterSpacing: '-0.03em', lineHeight: 1.05, textWrap: 'balance' }}><Rich text={s.title} hi={theme.hi} /></div></TRise>
    </div>
  );
}
const stagger = (s, key, i, start, gap) => (s[key] && s[key][i] != null ? s[key][i] : start + i * gap);

// ── TITLE ── { eyebrow, title, subtitle, image, imagePosition }
function LayoutTitle({ s }) {
  const { localTime: t } = useSprite();
  const theme = THEMES[s.theme || 'dark'];
  const zoom = 1.12 - 0.08 * ease(t, 0, 6, Easing.easeOutSine);
  return (
    <TScene theme={theme} label={s.label}>
      {s.image && <img src={s.image} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: s.imagePosition || '50% 60%', transform: `scale(${zoom})`, opacity: 0.5 }} />}
      {s.image && <div style={{ position: 'absolute', inset: 0, background: `linear-gradient(90deg, ${theme.bg} 30%, ${theme.bg}8C 100%)` }} />}
      <div style={{ position: 'absolute', left: 140, top: 300, width: 1400 }}>
        <TRise t={t} at={0.3}><TEyebrow theme={theme}>{s.eyebrow ?? NB.name}</TEyebrow></TRise>
        <div style={{ height: 28 }} />
        <TRise t={t} at={0.6} dist={50}><div style={{ fontSize: s.titleSize || 140, fontWeight: 800, color: theme.head, lineHeight: 0.98, letterSpacing: '-0.035em' }}><Rich text={s.title} hi={theme.hi} /></div></TRise>
        <div style={{ height: 40 }} />
        <div style={{ height: 8, width: 160 * ease(t, 1.2, 0.8, Easing.easeOutExpo), background: NC.red, borderRadius: 4 }} />
        <div style={{ height: 40 }} />
        <TRise t={t} at={1.6}><div style={{ fontSize: 48, color: theme.muted, fontWeight: 500, letterSpacing: '-0.01em' }}><Rich text={s.subtitle} hi={theme.hi} /></div></TRise>
      </div>
    </TScene>
  );
}

// ── FLOW ── { eyebrow, title, boxes:[{label, title, style:'muted'|'brand'|'accent'}], boxTimes?, note }
function LayoutFlow({ s }) {
  const { localTime: t } = useSprite();
  const theme = THEMES[s.theme || 'light'];
  const n = s.boxes.length;
  const w = (1680 - 120 * (n - 1)) / n;
  const styles = { muted: [NC.card, NC.ink], brand: [NC.navy, '#fff'], accent: [NC.green, NC.navyDark] };
  return (
    <TScene theme={theme} label={s.label}>
      <THeader t={t} theme={theme} s={s} size={72} top={100} width={1500} />
      <div style={{ position: 'absolute', left: 120, top: 390, display: 'flex', alignItems: 'center' }}>
        {s.boxes.map((b, i) => {
          const at = stagger(s, 'boxTimes', i, 1.2, 1.1);
          const p = ease(t, at, 0.7, Easing.easeOutBack);
          const [bg, fg] = styles[b.style || (i === n - 1 ? 'accent' : i === 0 ? 'muted' : 'brand')];
          const ap = ease(t, at - 0.4, 0.5);
          const arrowC = i === n - 1 ? NC.green : NC.navy;
          return (
            <React.Fragment key={i}>
              {i > 0 && (
                <div style={{ width: 120, display: 'flex', justifyContent: 'center' }}>
                  <div style={{ position: 'relative', width: 80 * ap, height: 6, background: arrowC, borderRadius: 3 }}>
                    <div style={{ position: 'absolute', right: -4, top: -9, borderLeft: `18px solid ${arrowC}`, borderTop: '12px solid transparent', borderBottom: '12px solid transparent', opacity: ap }} />
                  </div>
                </div>
              )}
              <div style={{ width: w, height: 280, borderRadius: 24, background: bg, color: fg, padding: 40, boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', opacity: clamp(p, 0, 1), transform: `scale(${0.85 + 0.15 * p})`, boxShadow: '0 24px 60px rgba(0,25,66,0.18)' }}>
                <div style={{ fontSize: 26, fontWeight: 600, opacity: 0.75, letterSpacing: '0.04em', textTransform: 'uppercase' }}>{b.label}</div>
                <div style={{ fontSize: n > 3 ? 48 : 58, fontWeight: 800, letterSpacing: '-0.025em', lineHeight: 1.02 }}>{b.title}</div>
              </div>
            </React.Fragment>
          );
        })}
      </div>
      <TFine theme={theme}>{s.note}</TFine>
    </TScene>
  );
}

// ── STATEMENT ── { eyebrow, title, pills:[], footer, theme }
function LayoutStatement({ s }) {
  const { localTime: t } = useSprite();
  const theme = THEMES[s.theme || 'brand'];
  return (
    <TScene theme={theme} label={s.label}>
      <div style={{ position: 'absolute', left: 120, top: s.pills ? 150 : 260, width: 1680 }}>
        <TRise t={t} at={0.2}><TEyebrow theme={theme}>{s.eyebrow}</TEyebrow></TRise>
        <div style={{ height: 24 }} />
        <TRise t={t} at={0.4}><div style={{ fontSize: s.titleSize || 92, fontWeight: 800, color: theme.head, letterSpacing: '-0.03em', lineHeight: 1.02 }}><Rich text={s.title} hi={theme.hi} /></div></TRise>
        {s.pills && <>
          <div style={{ height: 48 }} />
          <div style={{ display: 'flex', gap: 28, flexWrap: 'wrap' }}>
            {s.pills.map((l, i) => {
              const p = ease(t, 1.3 + i * 0.25, 0.6, Easing.easeOutBack);
              return <div key={l} style={{ padding: '26px 44px', borderRadius: 999, border: `3px solid ${theme === THEMES.light ? NC.card : 'rgba(255,255,255,0.35)'}`, color: theme.fg, fontSize: 40, fontWeight: 600, opacity: clamp(p, 0, 1), transform: `translateY(${(1 - p) * 30}px)` }}>{l}</div>;
            })}
          </div>
        </>}
        {s.footer && <>
          <div style={{ height: 36 }} />
          <TRise t={t} at={s.pills ? 1.3 + s.pills.length * 0.25 + 0.3 : 1.4}><div style={{ fontSize: 40, color: theme.muted, fontWeight: 500 }}><Rich text={s.footer} hi={theme.hi} /></div></TRise>
        </>}
      </div>
      <TFine theme={theme}>{s.note}</TFine>
    </TScene>
  );
}

// ── BREAKDOWN ── { eyebrow, title, totalLabel, totalRight, total, items:[{label, value, at?}],
//                 result:{label, value?, at?}, summary, note }
function LayoutBreakdown({ s }) {
  const { localTime: t } = useSprite();
  const theme = THEMES.light;
  const W = 1680;
  const used = s.items.reduce((a, b) => a + b.value, 0);
  const result = { ...s.result, value: s.result.value ?? (s.total - used) };
  const segs = [
    ...s.items.map((it, i) => ({ ...it, c: NC.chart[i % NC.chart.length], at: it.at ?? 2 + i * 1.6 })),
    { ...result, c: NC.green, at: result.at ?? 2 + s.items.length * 1.6, isResult: true },
  ];
  const barP = ease(t, 1.0, 1.0, Easing.easeOutExpo);
  const resP = ease(t, segs[segs.length - 1].at, 1.8);
  let x = 0;
  const cols = segs.map((sg) => (sg.isResult ? '1.25fr' : '1fr')).join(' ');
  return (
    <TScene theme={theme} label={s.label}>
      <THeader t={t} theme={theme} s={s} />
      <div style={{ position: 'absolute', left: 120, top: 360, width: W }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 30, fontWeight: 600, color: NC.ink, marginBottom: 18, opacity: barP }}>
          <span>{s.totalLabel}</span><span style={{ fontVariantNumeric: 'tabular-nums' }}>{s.totalRight ?? fmtMoney(s.total)}</span>
        </div>
        <div style={{ position: 'relative', height: 120, borderRadius: 16, background: NC.navy, width: W * barP, overflow: 'hidden' }}>
          {segs.map((sg, i) => {
            const w = (sg.value / s.total) * W; const left = x; x += w;
            const p = ease(t, sg.at, 0.8);
            return <div key={i} style={{ position: 'absolute', left, top: 0, bottom: 0, width: Math.max(0, w * p), background: sg.c, borderRight: p > 0.02 ? '3px solid #fff' : 'none' }} />;
          })}
        </div>
      </div>
      <div style={{ position: 'absolute', left: 120, top: 580, width: W, display: 'grid', gridTemplateColumns: cols, gap: 32 }}>
        {segs.map((sg, i) => {
          const p = ease(t, sg.at, 0.6);
          return (
            <div key={i} style={{ opacity: p, transform: `translateY(${(1 - p) * 20}px)`, borderTop: `6px solid ${sg.c}`, paddingTop: 22 }}>
              <div style={{ fontSize: 28, fontWeight: 600, color: theme.muted }}>{sg.isResult ? '' : '− '}{sg.label}</div>
              <div style={{ fontSize: sg.isResult ? 84 : 56, fontWeight: 800, color: sg.isResult ? NC.greenText : NC.ink, letterSpacing: '-0.03em', fontVariantNumeric: 'tabular-nums', marginTop: 6 }}>
                {fmtMoney(sg.isResult ? sg.value * resP : sg.value)}
              </div>
            </div>
          );
        })}
      </div>
      {s.summary && <TRise t={t} at={segs[segs.length - 1].at + 2.2} style={{ position: 'absolute', left: 120, top: 830 }}>
        <div style={{ fontSize: 34, color: NC.ink, fontWeight: 500 }}><Rich text={s.summary} hi={theme.hi} /></div>
      </TRise>}
      <TFine theme={theme}>{s.note}</TFine>
    </TScene>
  );
}

// ── LIST + PHOTO ── { eyebrow, title, items:[], image, imagePosition }
function LayoutListPhoto({ s }) {
  const { localTime: t } = useSprite();
  const theme = THEMES[s.theme || 'dark'];
  const zoom = 1.04 + 0.08 * ease(t, 0, 7, Easing.linear);
  return (
    <TScene theme={theme} label={s.label}>
      {s.image && <div style={{ position: 'absolute', right: 0, top: 0, bottom: 0, width: 820, overflow: 'hidden' }}>
        <img src={s.image} style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: s.imagePosition || '50% 55%', transform: `scale(${zoom})` }} />
        <div style={{ position: 'absolute', inset: 0, background: `linear-gradient(90deg, ${theme.bg} 0%, ${theme.bg}00 40%)` }} />
      </div>}
      <div style={{ position: 'absolute', left: 120, top: 170, width: 1000 }}>
        <TRise t={t} at={0.2}><TEyebrow theme={theme}>{s.eyebrow}</TEyebrow></TRise>
        <div style={{ height: 24 }} />
        <TRise t={t} at={0.4}><div style={{ fontSize: 84, fontWeight: 800, color: theme.head, letterSpacing: '-0.03em', lineHeight: 1.04 }}><Rich text={s.title} hi={theme.hi} /></div></TRise>
        <div style={{ height: 70 }} />
        {s.items.map((u, i) => {
          const p = ease(t, stagger(s, 'itemTimes', i, 1.2, 0.4), 0.6);
          return (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 28, padding: '22px 0', borderTop: `1px solid ${theme.rule}`, opacity: p, transform: `translateX(${(1 - p) * -40}px)` }}>
              <div style={{ fontSize: 28, fontWeight: 700, color: NC.green, width: 50, fontVariantNumeric: 'tabular-nums' }}>{String(i + 1).padStart(2, '0')}</div>
              <div style={{ fontSize: 46, fontWeight: 600, color: theme.fg, letterSpacing: '-0.01em' }}>{u}</div>
            </div>
          );
        })}
      </div>
    </TScene>
  );
}

// ── COMPARE ── { eyebrow, title, left:{title, items, at?}, right:{title, items, at?} }
function LayoutCompare({ s }) {
  const { localTime: t } = useSprite();
  const theme = THEMES.light;
  const col = (c, color, mark, defAt) => {
    const at = c.at ?? defAt;
    return (
      <div style={{ flex: 1 }}>
        <TRise t={t} at={at}><div style={{ fontSize: 34, fontWeight: 700, color, letterSpacing: '0.08em', textTransform: 'uppercase', paddingBottom: 22, borderBottom: `4px solid ${color}` }}>{c.title}</div></TRise>
        {c.items.map((it, i) => {
          const p = ease(t, at + 0.4 + i * 0.3, 0.55);
          return (
            <div key={i} style={{ display: 'flex', gap: 22, alignItems: 'baseline', padding: '24px 0', borderBottom: `1px solid ${NC.divider}`, opacity: p, transform: `translateY(${(1 - p) * 16}px)` }}>
              <span style={{ fontSize: 36, fontWeight: 800, color, width: 28 }}>{mark}</span>
              <span style={{ fontSize: 38, fontWeight: 500, color: NC.ink, lineHeight: 1.25 }}>{it}</span>
            </div>
          );
        })}
      </div>
    );
  };
  return (
    <TScene theme={theme} label={s.label}>
      <THeader t={t} theme={theme} s={s} />
      <div style={{ position: 'absolute', left: 120, right: 120, top: 330, display: 'flex', gap: 100 }}>
        {col(s.left, NC.greenText, s.left.mark || '+', 0.9)}
        {col(s.right, NC.red, s.right.mark || '–', 3.2)}
      </div>
      <TFine theme={theme}>{s.note}</TFine>
    </TScene>
  );
}

// ── STEPS ── { eyebrow, title, steps:[[heading, detail]], stepTimes?, note, theme }
function LayoutSteps({ s }) {
  const { localTime: t } = useSprite();
  const theme = THEMES[s.theme || 'brand'];
  const n = s.steps.length;
  const times = s.steps.map((_, i) => stagger(s, 'stepTimes', i, 1.6, 1.8));
  const lineP = ease(t, times[0], Math.max(0.1, times[n - 1] - times[0]), Easing.linear);
  const colW = (1680 - 36 * (n - 1)) / n;
  const trackW = 1680 - colW + 0; // dot 1 center → dot n left edge-ish
  return (
    <TScene theme={theme} label={s.label}>
      <THeader t={t} theme={theme} s={s} size={80} top={120} />
      <div style={{ position: 'absolute', left: 120, right: 120, top: 400 }}>
        <div style={{ position: 'absolute', left: 36, width: trackW, top: 34, height: 4, background: theme.rule }} />
        <div style={{ position: 'absolute', left: 36, width: trackW * lineP, top: 34, height: 4, background: NC.green }} />
        <div style={{ display: 'grid', gridTemplateColumns: `repeat(${n}, 1fr)`, gap: 36 }}>
          {s.steps.map(([h, d], i) => {
            const p = ease(t, times[i], 0.6, Easing.easeOutBack);
            const on = t >= times[i];
            return (
              <div key={i} style={{ position: 'relative' }}>
                <div style={{ width: 72, height: 72, borderRadius: 36, background: on ? NC.green : theme.bg, border: `4px solid ${on ? NC.green : theme.rule}`, color: on ? NC.navyDark : theme.fg, fontSize: 32, fontWeight: 800, display: 'flex', alignItems: 'center', justifyContent: 'center', transform: `scale(${0.7 + 0.3 * clamp(p, 0, 1.2)})`, boxSizing: 'border-box' }}>{i + 1}</div>
                <div style={{ opacity: clamp(p, 0, 1), transform: `translateY(${(1 - clamp(p, 0, 1)) * 20}px)` }}>
                  <div style={{ fontSize: 38, fontWeight: 700, color: theme.head, marginTop: 36, letterSpacing: '-0.015em', lineHeight: 1.1 }}>{h}</div>
                  <div style={{ fontSize: 28, color: theme.muted, marginTop: 14, lineHeight: 1.35 }}>{d}</div>
                </div>
              </div>
            );
          })}
        </div>
      </div>
      <TFine theme={theme}>{s.note}</TFine>
    </TScene>
  );
}

// ── CTA ── { eyebrow, title, subtitle, disclaimer }  (logo, phone, URL, compliance come from brand.js)
function LayoutCTA({ s }) {
  const { localTime: t } = useSprite();
  const theme = THEMES.light;
  const pulse = 1 + 0.025 * Math.sin(Math.max(0, t - 2) * 4);
  const lp = ease(t, 0.2, 0.9);
  return (
    <TScene theme={theme} label={s.label}>
      <div style={{ position: 'absolute', left: 120, right: 120, top: 0, bottom: 280, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 110 }}>
        <img src={NB.logo} alt={NB.name} style={{ width: 560, height: 'auto', flexShrink: 0, opacity: lp, transform: `scale(${0.94 + 0.06 * lp})` }} />
        <div style={{ width: 2, height: 520 * ease(t, 0.6, 0.8, Easing.easeOutExpo), background: NC.card, flexShrink: 0 }} />
        <div style={{ width: 920, flexShrink: 0 }}>
          <TRise t={t} at={0.5}><TEyebrow theme={theme}>{s.eyebrow}</TEyebrow></TRise>
          <div style={{ height: 26 }} />
          <TRise t={t} at={0.7} dist={40}><div style={{ fontSize: s.titleSize || 84, fontWeight: 800, color: NC.navy, letterSpacing: '-0.035em', lineHeight: 1.02 }}><Rich text={s.title} hi={theme.hi} /></div></TRise>
          <div style={{ height: 30 }} />
          <TRise t={t} at={1.1}><div style={{ fontSize: 36, color: theme.muted, fontWeight: 500, lineHeight: 1.35, textWrap: 'pretty' }}><Rich text={s.subtitle} hi={theme.hi} /></div></TRise>
          <div style={{ height: 56 }} />
          <TRise t={t} at={1.7}>
            <div style={{ display: 'inline-flex', alignItems: 'baseline', gap: 18, padding: '30px 60px', borderRadius: 18, background: NC.cta, color: '#fff', transform: `scale(${pulse})`, transformOrigin: 'left center', boxShadow: '0 18px 36px -8px rgba(20,136,252,.55)', whiteSpace: 'nowrap' }}>
              <span style={{ fontSize: 40, fontWeight: 600, opacity: 0.92 }}>{NB.phoneLabel}</span>
              <span style={{ fontSize: 48, fontWeight: 800, letterSpacing: '-0.01em', fontVariantNumeric: 'tabular-nums' }}>{NB.phone}</span>
            </div>
          </TRise>
          <div style={{ height: 32 }} />
          <TRise t={t} at={2.1}><div style={{ fontSize: 32, fontWeight: 700, color: NC.navy, letterSpacing: '0.01em' }}>{NB.url}</div></TRise>
        </div>
      </div>
      <TFine theme={theme} center>{[s.disclaimer, NB.compliance].filter(Boolean).join(' ')}</TFine>
    </TScene>
  );
}

const NVL_LAYOUTS = {
  title: LayoutTitle, flow: LayoutFlow, statement: LayoutStatement, breakdown: LayoutBreakdown,
  listPhoto: LayoutListPhoto, compare: LayoutCompare, steps: LayoutSteps, cta: LayoutCTA,
};
Object.assign(window, { NVL_LAYOUTS });
