// FFC Weekly Sales Briefing — Supabase app shell + fixed reporting calendar.
const { useState: ffcUseStateApp, useEffect: ffcUseEffectApp } = React;

const FFC_REPORTING_YEAR = 2026;
const FFC_WEEK1_END = '2026-01-03'; // Saturday week-ending calendar requested by FFC.

const parseISODate = (iso) => {
  const parts = String(iso || FFC_WEEK1_END).split('-').map(Number);
  return new Date(Date.UTC(parts[0], parts[1] - 1, parts[2]));
};
const isoDate = (d) => d.toISOString().slice(0, 10);
const addDays = (iso, days) => {
  const d = parseISODate(iso);
  d.setUTCDate(d.getUTCDate() + days);
  return isoDate(d);
};
const clampWeek = (w) => Math.max(1, Math.min(53, Number(w) || 1));
const periodEndingForWeek = (weekNumber) => addDays(FFC_WEEK1_END, (clampWeek(weekNumber) - 1) * 7);
const weekNumberForPeriod = (periodEnding) => {
  const days = Math.round((parseISODate(periodEnding) - parseISODate(FFC_WEEK1_END)) / 86400000);
  return clampWeek(Math.floor(days / 7) + 1);
};
const businessDaysYtd = (periodEnding) => {
  let d = parseISODate(FFC_REPORTING_YEAR + '-01-01');
  const end = parseISODate(periodEnding);
  let count = 0;
  while (d <= end) {
    const day = d.getUTCDay();
    if (day !== 0 && day !== 6) count += 1;
    d.setUTCDate(d.getUTCDate() + 1);
  }
  return count;
};

const businessDaysMtd = (periodEnding) => {
  const end = parseISODate(periodEnding || FFC_WEEK1_END);
  let d = new Date(Date.UTC(end.getUTCFullYear(), end.getUTCMonth(), 1));
  let count = 0;
  while (d <= end) {
    const day = d.getUTCDay();
    if (day !== 0 && day !== 6) count += 1;
    d.setUTCDate(d.getUTCDate() + 1);
  }
  return count;
};

const businessDaysInMonth = (year, monthNumber) => {
  const last = new Date(Date.UTC(year, monthNumber, 0));
  let d = new Date(Date.UTC(year, monthNumber - 1, 1));
  let count = 0;
  while (d <= last) {
    const day = d.getUTCDay();
    if (day !== 0 && day !== 6) count += 1;
    d.setUTCDate(d.getUTCDate() + 1);
  }
  return count;
};
const MONTH_KEYS = ['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'];
const MONTH_LABELS = ['January','February','March','April','May','June','July','August','September','October','November','December'];
const defaultMonthlyForecasts = (annual = 19843000) => {
  const base = Math.floor((Number(annual) || 0) / 12);
  const remainder = Math.round((Number(annual) || 0) - (base * 12));
  return MONTH_KEYS.reduce((obj, key, idx) => { obj[key] = base + (idx === 11 ? remainder : 0); return obj; }, {});
};
const normalizeMonthlyForecasts = (value, fallbackAnnual = 19843000) => {
  let src = value;
  if (typeof src === 'string') { try { src = JSON.parse(src); } catch (_err) { src = null; } }
  const fallback = defaultMonthlyForecasts(fallbackAnnual);
  return MONTH_KEYS.reduce((obj, key) => { obj[key] = Number(src?.[key] ?? fallback[key]) || 0; return obj; }, {});
};
const annualFromMonthlyForecasts = (monthlyForecasts) => MONTH_KEYS.reduce((sum, key) => sum + (Number(monthlyForecasts?.[key]) || 0), 0);
const forecastForMonth = (monthlyForecasts, monthNumber) => Number(monthlyForecasts?.[MONTH_KEYS[Math.max(0, Math.min(11, (Number(monthNumber) || 1) - 1))]]) || 0;
const proratedMonthForecast = (monthlyForecasts, periodEnding) => {
  const end = parseISODate(periodEnding || FFC_WEEK1_END);
  const year = end.getUTCFullYear();
  const monthNumber = end.getUTCMonth() + 1;
  const elapsed = businessDaysMtd(periodEnding);
  const total = businessDaysInMonth(year, monthNumber);
  return Math.round(forecastForMonth(monthlyForecasts, monthNumber) * (elapsed / Math.max(1, total)));
};
const ytdForecastThrough = (monthlyForecasts, periodEnding) => {
  const end = parseISODate(periodEnding || FFC_WEEK1_END);
  const monthNumber = end.getUTCMonth() + 1;
  let total = 0;
  for (let m = 1; m < monthNumber; m += 1) total += forecastForMonth(monthlyForecasts, m);
  total += proratedMonthForecast(monthlyForecasts, periodEnding);
  return Math.round(total);
};
const monthKey = (periodEnding) => {
  const d = parseISODate(periodEnding || FFC_WEEK1_END);
  return d.getUTCFullYear() + '-' + String(d.getUTCMonth() + 1).padStart(2, '0');
};
const periodMeta = (periodEnding) => {
  const ending = periodEnding || FFC_WEEK1_END;
  const start = addDays(ending, -6);
  const ed = parseISODate(ending);
  const sd = parseISODate(start);
  const weekNumber = weekNumberForPeriod(ending);
  const fmt = (d, opts) => d.toLocaleDateString('en-US', { timeZone: 'UTC', ...opts });
  const sameMonth = sd.getUTCMonth() === ed.getUTCMonth();
  const weekLabel = sameMonth
    ? 'Week of ' + fmt(sd, { month: 'long' }) + ' ' + sd.getUTCDate() + '–' + ed.getUTCDate()
    : 'Week of ' + fmt(sd, { month: 'short', day: 'numeric' }) + '–' + fmt(ed, { month: 'short', day: 'numeric' });
  return {
    report_year: FFC_REPORTING_YEAR,
    week_number: weekNumber,
    period_start: start,
    period_ending: ending,
    month_number: ed.getUTCMonth() + 1,
    quarter_number: Math.floor(ed.getUTCMonth() / 3) + 1,
    business_days_ytd: businessDaysYtd(ending),
    week_label: weekLabel,
  };
};
const calcPair = (actual, fc) => {
  const a = Number(actual) || 0;
  const f = Number(fc) || 0;
  const diff = a - f;
  return { actual: a, fc: f, diff, percent: f ? Number(((diff / f) * 100).toFixed(2)) : 0 };
};
const defaultDivisionRows = () => ([
  { name: 'OEM', actual: 0, fc: 0, hidden: false },
  { name: 'Distribution', actual: 0, fc: 0, hidden: false },
  { name: 'GA', actual: 0, fc: 0, hidden: false },
  { name: 'Repair', actual: 0, fc: 0, hidden: false },
  { name: 'Military', actual: 0, fc: 0, hidden: false },
  { name: 'Heli', actual: 0, fc: 0, hidden: false },
]);
const normalizeReport = (row) => {
  const meta = periodMeta(row?.period_ending || FFC_WEEK1_END);
  return {
    ...row,
    ...meta,
    week_label: row?.week_label || meta.week_label,
    monthly_forecasts: normalizeMonthlyForecasts(row?.monthly_forecasts, row?.annual_fc || 19843000),
    division_rows: Array.isArray(row?.division_rows) ? row.division_rows.map((r) => ({ name: r.name || 'Division', actual: Number(r.actual) || 0, fc: Number(r.fc) || 0, hidden: Boolean(r.hidden) })) : defaultDivisionRows(),
  };
};

const blankReport = (seed) => {
  const meta = periodMeta(seed?.period_ending || FFC_WEEK1_END);
  const annual = Number(seed?.annual_fc) || 19843000;
  return normalizeReport({
    id: null,
    ...meta,
    weekly_actual: 0, weekly_fc: 0, weekly_diff: 0, weekly_percent: 0,
    daily_avg_actual: 0, daily_avg_fc: Math.round(annual / 252), daily_avg_diff: 0, daily_avg_percent: 0,
    mtd_actual: 0, mtd_fc: 0, mtd_diff: 0, mtd_percent: 0,
    ytd_actual: 0, ytd_fc: 0, ytd_diff: 0, ytd_percent: 0,
    monthly_forecasts: normalizeMonthlyForecasts(seed?.monthly_forecasts, annual),
    annual_fc: annual, monthly_fc: Math.round(annual / 12),
    weekly_wins: '', customer_service: '', quotes_over_60: '', projects_in_design: '',
    rma_warranty_returns: '', new_sales_opportunities: '', focus_for_week: '',
    follow_up_next_week: '', open_discussion: '',
    division_rows: seed?.division_rows || defaultDivisionRows(),
  });
};

const deriveReportFinancials = (report, reports = []) => {
  const base = normalizeReport(report || blankReport());
  const divisionRows = (base.division_rows || []).map((row) => ({
    name: row.name || 'Division',
    actual: Number(row.actual) || 0,
    fc: Number(row.fc) || 0,
    hidden: Boolean(row.hidden),
  }));
  const activeRows = divisionRows.filter((row) => !row.hidden);
  const weekly = calcPair(
    activeRows.reduce((sum, row) => sum + (Number(row.actual) || 0), 0),
    activeRows.reduce((sum, row) => sum + (Number(row.fc) || 0), 0),
  );
  const monthlyForecasts = normalizeMonthlyForecasts(base.monthly_forecasts, base.annual_fc || 19843000);
  const annual = annualFromMonthlyForecasts(monthlyForecasts);
  const monthly = forecastForMonth(monthlyForecasts, base.month_number || 1);
  const dailyFc = Math.round(annual / 252);
  const currentPeriod = String(base.period_ending);
  const all = [
    { ...base, weekly_actual: weekly.actual, weekly_fc: weekly.fc, period_ending: currentPeriod },
    ...(reports || []).filter((r) => String(r.period_ending) !== currentPeriod).map((r) => normalizeReport(r)),
  ].filter((r) => r.period_ending);
  const currentDate = parseISODate(currentPeriod);
  const currentYear = currentDate.getUTCFullYear();
  const currentMonthKey = monthKey(currentPeriod);
  const throughCurrent = all.filter((r) => parseISODate(r.period_ending) <= currentDate);
  const monthRows = throughCurrent.filter((r) => monthKey(r.period_ending) === currentMonthKey);
  const yearRows = throughCurrent.filter((r) => parseISODate(r.period_ending).getUTCFullYear() === currentYear);
  const sumField = (rows, key) => rows.reduce((sum, r) => sum + (Number(r[key]) || 0), 0);
  const mtd = calcPair(sumField(monthRows, 'weekly_actual'), proratedMonthForecast(monthlyForecasts, currentPeriod));
  const ytdActual = sumField(yearRows, 'weekly_actual');
  const ytdFc = ytdForecastThrough(monthlyForecasts, currentPeriod);
  const ytd = calcPair(ytdActual, ytdFc);
  const daily = calcPair(Math.round(mtd.actual / Math.max(1, businessDaysMtd(currentPeriod))), dailyFc);
  return {
    ...base,
    monthly_forecasts: monthlyForecasts,
    division_rows: divisionRows,
    weekly_actual: weekly.actual, weekly_fc: weekly.fc, weekly_diff: weekly.diff, weekly_percent: weekly.percent,
    daily_avg_actual: daily.actual, daily_avg_fc: daily.fc, daily_avg_diff: daily.diff, daily_avg_percent: daily.percent,
    mtd_actual: mtd.actual, mtd_fc: mtd.fc, mtd_diff: mtd.diff, mtd_percent: mtd.percent,
    ytd_actual: ytd.actual, ytd_fc: ytd.fc, ytd_diff: ytd.diff, ytd_percent: ytd.percent,
    annual_fc: annual, monthly_fc: monthly,
  };
};

Object.assign(window, { FFCCalendar: { FFC_REPORTING_YEAR, FFC_WEEK1_END, MONTH_KEYS, MONTH_LABELS, periodMeta, periodEndingForWeek, weekNumberForPeriod, businessDaysYtd, businessDaysMtd, businessDaysInMonth, calcPair, deriveReportFinancials, blankReport, normalizeReport, normalizeMonthlyForecasts, annualFromMonthlyForecasts, forecastForMonth } });

function App() {
  const { Button } = window.FloatsFuelCellsDesignSystem_f57587;
  const [session, setSession] = ffcUseStateApp(null);
  const [authChecked, setAuthChecked] = ffcUseStateApp(false);
  const [tab, setTab] = ffcUseStateApp('presentation');
  const [reports, setReports] = ffcUseStateApp([]);
  const [current, setCurrent] = ffcUseStateApp(blankReport());
  const [loadingReports, setLoadingReports] = ffcUseStateApp(false);
  const [loadError, setLoadError] = ffcUseStateApp('');
  const [theme, setTheme] = ffcUseStateApp(() => {
    try { return localStorage.getItem('ffc_theme') || 'dark'; } catch (_err) { return 'dark'; }
  });
  const [showHelp, setShowHelp] = ffcUseStateApp(false);

  const supabase = window.FFCSupabase;
  const sortReports = (rows) => [...rows].map(normalizeReport).sort((a, b) => new Date(b.period_ending) - new Date(a.period_ending));

  const loadReports = async () => {
    if (!supabase) { setLoadError('Supabase is not configured or failed to load.'); return; }
    setLoadingReports(true);
    setLoadError('');
    const { data, error } = await supabase.from('sales_reports').select('*').order('period_ending', { ascending: false });
    setLoadingReports(false);
    if (error) { setLoadError(error.message || 'Could not load sales reports.'); return; }
    const rows = sortReports(data || []);
    setReports(rows);
    setCurrent(rows[0] || blankReport());
  };

  ffcUseEffectApp(() => {
    if (!supabase) { setAuthChecked(true); return; }
    supabase.auth.getSession().then(({ data }) => { setSession(data.session || null); setAuthChecked(true); });
    const { data: listener } = supabase.auth.onAuthStateChange((_event, nextSession) => {
      setSession(nextSession || null);
      if (!nextSession) { setReports([]); setCurrent(blankReport()); setTab('presentation'); }
    });
    return () => listener.subscription.unsubscribe();
  }, []);

  ffcUseEffectApp(() => { if (session) loadReports(); }, [session]);

  ffcUseEffectApp(() => {
    try { localStorage.setItem('ffc_theme', theme); } catch (_err) {}
    document.documentElement.setAttribute('data-theme', theme);
  }, [theme]);

  if (!authChecked) return <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center', color: 'var(--text-secondary)', fontFamily: 'var(--font-sans)' }}>Checking session…</div>;
  if (!session) return <LoginView onLogin={(nextSession) => setSession(nextSession)} />;

  const tabs = [
    { id: 'presentation', label: 'Presentation' },
    { id: 'edit', label: 'Edit Report' },
    { id: 'history', label: 'History' },
  ];

  const saveReport = async (updated) => {
    if (!supabase) throw new Error('Supabase is not configured.');
    const normalized = deriveReportFinancials(updated, reports);
    const payload = { ...normalized };
    delete payload.created_at; delete payload.updated_at; delete payload.id;
    delete payload.month_number; delete payload.quarter_number; delete payload.business_days_ytd;
    const { data, error } = await supabase.from('sales_reports').upsert(payload, { onConflict: 'period_ending' }).select().single();
    if (error) throw error;
    const saved = normalizeReport(data || normalized);
    setCurrent(saved);
    setReports((rs) => sortReports([saved, ...rs.filter((r) => r.id !== saved.id && r.period_ending !== saved.period_ending)]));
    return saved;
  };

  const logout = async () => { if (supabase) await supabase.auth.signOut(); setSession(null); setTab('presentation'); };

  const printPresentation = () => {
    // The printable report is intentionally the Presentation screen only.
    // If the user clicks Print from Edit or History, switch to Presentation first,
    // then let the browser use the PresentationView's print layout and dynamic title.
    setTab('presentation');
    window.requestAnimationFrame(() => {
      window.requestAnimationFrame(() => window.print());
    });
  };

  const toggleTheme = () => setTheme((value) => value === 'light' ? 'dark' : 'light');

  return (
    <div data-theme={theme} style={{ minHeight: '100vh', background: 'var(--grad-app)', backgroundColor: 'var(--surface-app)' }}>
      <header className="ffc-no-print ffc-app-header" style={{ position: 'sticky', top: 0, zIndex: 40, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, padding: '14px 32px', background: 'var(--surface-overlay)', backdropFilter: 'blur(14px)', WebkitBackdropFilter: 'blur(14px)', borderBottom: '1px solid var(--border-subtle)' }}>
        <div className="ffc-header-brand">
          <a className="ffc-brand-link" href="https://www.ffcfuelcells.com/" target="_blank" rel="noopener noreferrer" aria-label="Open Floats & Fuel Cells website">
            <FFCLogo size="sm" variant="markText" />
          </a>
          <button type="button" className="ffc-theme-toggle" onClick={toggleTheme} aria-label={theme === 'light' ? 'Switch to dark flight mode' : 'Switch to light flight mode'}>
            <span aria-hidden="true">{theme === 'light' ? '✈︎' : '◐'}</span>
            <span>{theme === 'light' ? 'Night Flight' : 'Light Cabin'}</span>
          </button>
        </div>
        <nav className="ffc-main-tabs" style={{ display: 'flex', gap: 4, background: 'var(--surface-inset)', padding: 4, borderRadius: 'var(--radius-md)', border: '1px solid var(--border-subtle)' }}>
          {tabs.map((t) => <button key={t.id} onClick={() => setTab(t.id)} style={{ border: 'none', cursor: 'pointer', padding: '8px 18px', borderRadius: 'var(--radius-sm)', fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.06em', textTransform: 'uppercase', background: tab === t.id ? 'var(--brand-primary)' : 'transparent', color: tab === t.id ? 'var(--text-on-brand)' : 'var(--text-secondary)', transition: 'background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard)' }}>{t.label}</button>)}
        </nav>
        <div className="ffc-header-actions" style={{ display: 'flex', gap: 14, alignItems: 'center' }}>
          <Button variant="secondary" size="sm" onClick={printPresentation}>Print</Button>
          <button
            type="button"
            className="ffc-attendant-help-button"
            onClick={() => setShowHelp(true)}
            aria-label="Open help guide"
            title="Help"
          >
            <span className="ffc-attendant-help-shell" aria-hidden="true">
              <span className="ffc-attendant-help-face">
                <svg viewBox="0 0 64 64" className="ffc-attendant-help-svg" aria-hidden="true" focusable="false">
                  <g fill="none" stroke="currentColor" strokeWidth="3.1" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M22 14h20l-3 8H25z" />
                    <path d="M18 55V46c0-4.2 3.2-7.8 7.8-8.9l5.3-1.2h1.8l5.3 1.2c4.6 1.1 7.8 4.7 7.8 8.9v9" />
                    <path d="M26 55V44l6 6 6-6v11" />
                    <path d="M25 37l7 7 7-7" />
                    <path d="M22.5 26.5c0-8.4 6.2-12.8 9.5-12.8s9.5 4.4 9.5 12.8v6.5c0 2.1-1.7 3.8-3.8 3.8H26.3c-2.1 0-3.8-1.7-3.8-3.8z" />
                    <path d="M23 23.5h7.5c1.7 0 3.4-.5 4.8-1.6l1.7-1.4" />
                    <path d="M32 18.2c1.9 2.3 5.1 5.2 9.2 5.6" />
                    <path d="M18 55h28" />
                    <path d="M41 44h4.5" />
                    <path d="M31 28.2v2.8" />
                  </g>
                </svg>
                <span className="ffc-attendant-help-gloss"></span>
              </span>
            </span>
          </button>
          <Button variant="ghost" size="sm" onClick={logout}>Logout</Button>
        </div>
      </header>

      {showHelp && (
        <div className="ffc-help-overlay ffc-no-print" role="dialog" aria-modal="true" aria-label="Floats and Fuel Cells Sales Briefing Help">
          <div className="ffc-help-modal">
            <div className="ffc-help-header">
              <div>
                <span className="ffc-help-kicker">Sales Meeting Guide</span>
                <h2>How to Use the FFC Sales Briefing Dashboard</h2>
              </div>
              <button type="button" className="ffc-help-close" onClick={() => setShowHelp(false)} aria-label="Close help">×</button>
            </div>
            <div className="ffc-help-body">
              <section>
                <h3>1. What this dashboard is for</h3>
                <p>Use this dashboard to prepare, save, present, and print sales briefing reports for weekly managers meetings. It shows weekly performance, forecast comparison, month-to-date progress, year-to-date progress, division or segment detail, charts, and executive briefing notes.</p>
              </section>

              <section>
                <h3>2. Normal weekly workflow</h3>
                <ol>
                  <li>Open the dashboard and sign in.</li>
                  <li>Go to <strong>Edit Report</strong>.</li>
                  <li>Select the correct reporting week.</li>
                  <li>Enter actual and forecast numbers by division or segment.</li>
                  <li>Update the executive briefing notes.</li>
                  <li>Click <strong>Save</strong>.</li>
                  <li>Go to <strong>Presentation</strong> and review the report before the meeting.</li>
                  <li>Use <strong>Print</strong> if you need a PDF or paper copy.</li>
                </ol>
              </section>

              <section>
                <h3>3. Presentation screen</h3>
                <p>Use <strong>Presentation</strong> during the meeting. Select <strong>Week</strong>, <strong>Month</strong>, <strong>Quarter</strong>, or <strong>Year</strong> at the top. The arrow buttons move backward or forward based on the selected view. If Week is selected, the arrows move one saved week at a time. If Quarter is selected, they move one saved quarter at a time.</p>
              </section>

              <section>
                <h3>4. Edit Report screen</h3>
                <p>This is where you enter the weekly numbers and meeting notes. The reporting calendar controls the week number, period start, period ending, month, quarter, and year. You do not need to calculate those dates manually.</p>
                <p>The weekly top-line numbers come from the active division or segment rows. Enter the actual and forecast sales for each active row, and the dashboard calculates weekly actual, weekly forecast, difference, and percentage.</p>
              </section>

              <section>
                <h3>5. Division and segment rows</h3>
                <p>Use the division/segment rows for categories like OEM, Distribution, GA, Repair, Military, or any other categories you want to track. You can rename rows, add rows, hide rows, and unhide rows later.</p>
                <p>Hidden rows are not deleted. They are simply removed from the visible report until you unhide them.</p>
              </section>

              <section>
                <h3>6. Monthly forecast setup</h3>
                <p>Enter forecast targets by month. The dashboard adds the monthly forecasts together to calculate the annual forecast. This is better than forcing every month to have the same forecast because some months may naturally be stronger or weaker.</p>
                <p>The weekly forecast comes from the division/segment rows. The monthly forecast setup is used for MTD, YTD, annual forecast context, and daily sales average forecast.</p>
              </section>

              <section>
                <h3>7. Executive briefing cards</h3>
                <p>The Executive Briefing cards are for meeting discussion notes: Weekly Wins, Customer Service, Quotes over 60%, Projects in Design, RMA/Warranty, New Sales Opportunities, Focus for the Week, Follow Up for Next Week, and Open Discussion.</p>
                <p>On the Presentation screen, click a card to open the note. Click the opened panel again to close it. Long notes can scroll inside the panel.</p>
              </section>

              <section>
                <h3>8. History</h3>
                <p>Use <strong>History</strong> to find older reports. Reports are grouped by year, then quarter, then week. Click a year to expand it, then click a quarter to see the weeks with saved data.</p>
              </section>

              <section>
                <h3>9. Printing or saving a PDF</h3>
                <p>Click <strong>Print</strong> to print or save the report as a PDF. The dashboard always prints the Presentation report, even if you are currently on Edit Report or History. The PDF name is based on the current view, such as Week 5, January, Q1, or 2026.</p>
              </section>

              <section>
                <h3>10. Light and dark mode</h3>
                <p>Use the airplane-themed toggle under the logo to switch between <strong>Night Flight</strong> and <strong>Light Cabin</strong>. This only changes the appearance of the dashboard; it does not change your saved data.</p>
              </section>

              <section>
                <h3>Quick pre-meeting checklist</h3>
                <ul>
                  <li>Correct week, month, quarter, or year is selected.</li>
                  <li>Division/segment actuals and forecasts are entered.</li>
                  <li>Monthly forecast setup is current.</li>
                  <li>Executive briefing notes are filled in.</li>
                  <li>The report has been saved.</li>
                  <li>The Presentation screen looks ready for the meeting.</li>
                </ul>
              </section>
            </div>
          </div>
        </div>
      )}
      {loadingReports && <div className="ffc-preflight-loading"><span className="ffc-preflight-icon">✈︎</span><span>Running pre-flight checks…</span><small>Loading briefing data</small></div>}
      {loadError && <div style={{ margin: 18, padding: 12, border: '1px solid var(--status-behind)', color: 'var(--status-behind)', fontFamily: 'var(--font-sans)' }}>{loadError}</div>}
      <main key={tab} className="ffc-fade">
        {tab === 'presentation' && <PresentationView report={current} reports={reports} onEdit={() => setTab('edit')} />}
        {tab === 'edit' && <EditReportView report={current} reports={reports} onSave={saveReport} onPreview={() => setTab('presentation')} />}
        {tab === 'history' && <HistoryView reports={reports} onOpenPresentation={(r) => { setCurrent(normalizeReport(r)); setTab('presentation'); }} onOpenEdit={(r) => { setCurrent(normalizeReport(r)); setTab('edit'); }} />}
      </main>
    </div>
  );
}

Object.assign(window, { App });
