// Close-the-Books Checklist — interactive monthly close walkthrough
const { useState: useStateClose, useMemo: useMemoClose, useEffect: useEffectClose } = React;

/* --- Steps ------------------------------------------------------------- */
/* Each step is a phase of the close. Each has a small set of concrete tasks
   the owner can tick off. Ordered roughly the way a real close runs. */
const CLOSE_STEPS = [
  {
    id: 'cutoff',
    phase: 'Week 1',
    day: 'Day 1–2',
    title: 'Set a clean cutoff.',
    eyebrow: 'Prep',
    icon: 'flag',
    why: 'Nothing else works if the period isn\'t closed to new activity. Tell the team the books are locked to last month — invoices, bills, and journal entries dated after the cutoff go into the new period.',
    tasks: [
      { id: 'c1', t: 'Pick a close target (day 5, 10, 15 — commit to one)', d: 'Consistent cadence beats a heroic month.' },
      { id: 'c2', t: 'Freeze the prior period in the books', d: 'Most GL systems let you soft-close or lock a period to new entries.' },
      { id: 'c3', t: 'Send the "last call" email', d: 'Expense reports, mileage logs, and receipts due by day 3.' },
    ],
    tip: 'A monthly close without a cutoff is just a long backlog.',
  },
  {
    id: 'categorize',
    phase: 'Week 1',
    day: 'Day 2–4',
    title: 'Categorize everything.',
    eyebrow: 'Transactions',
    icon: 'tag',
    why: 'Every bank, credit card, and payment-processor line needs a real account — not Ask My Accountant, not Uncategorized Expense. This is the single biggest reason closes stall.',
    tasks: [
      { id: 't1', t: 'Clear Uncategorized Income / Expense to zero', d: 'Every transaction mapped to a real GL account.' },
      { id: 't2', t: 'Split personal + business charges', d: 'Owner coffees and Amazon orders don\'t belong in COGS.' },
      { id: 't3', t: 'Code transfers as transfers (not revenue)', d: 'Moving money between your own accounts is not a sale.' },
      { id: 't4', t: 'Attach receipts for anything over $75', d: 'IRS threshold. Your future self in an audit will thank you.' },
    ],
    tip: 'If you can\'t remember what a charge was, ask this month — not next year.',
  },
  {
    id: 'reconcile',
    phase: 'Week 1',
    day: 'Day 3–5',
    title: 'Reconcile every account.',
    eyebrow: 'Bank & cards',
    icon: 'check',
    why: 'Match every bank, credit card, loan, and merchant account to the statement — to the penny. An unreconciled account means your financials are fiction.',
    tasks: [
      { id: 'r1', t: 'Reconcile all operating & savings accounts', d: 'Ending balance in books = ending balance on statement.' },
      { id: 'r2', t: 'Reconcile every credit card', d: 'Personal card reimbursements get booked separately.' },
      { id: 'r3', t: 'Reconcile Stripe, PayPal, Shopify Payments', d: 'Gross sales, fees, refunds, and payouts — three separate lines.' },
      { id: 'r4', t: 'Investigate any stale uncleared items', d: 'Checks outstanding > 60 days usually need a void or reissue.' },
    ],
    tip: 'A rec with a $0.03 variance is not reconciled. Find the three cents.',
  },
  {
    id: 'accruals',
    phase: 'Week 2',
    day: 'Day 5–7',
    title: 'Book the accruals & prepaids.',
    eyebrow: 'Adjustments',
    icon: 'adjust',
    why: 'Accrual basis means matching revenue and expense to the month they belong in — not when cash moved. Prepaids get expensed over time; accrued expenses get recognized before the bill arrives.',
    tasks: [
      { id: 'a1', t: 'Amortize prepaid insurance, software, rent', d: 'Annual SaaS paid in January → 1/12th to expense each month.' },
      { id: 'a2', t: 'Accrue unpaid payroll & PTO earned', d: 'If the pay period crosses month-end, accrue the piece in this month.' },
      { id: 'a3', t: 'Accrue vendor bills not yet received', d: 'Utilities, legal, contractors — book the estimate, true up when the invoice lands.' },
      { id: 'a4', t: 'Defer revenue billed but not yet earned', d: 'Annual plans, retainers, deposits — sit on the balance sheet until delivered.' },
    ],
    tip: 'Prepaids and accruals are what separate bookkeeping from accounting.',
  },
  {
    id: 'loans',
    phase: 'Week 2',
    day: 'Day 6–8',
    title: 'Split interest from principal.',
    eyebrow: 'Debt',
    icon: 'debt',
    why: 'Every loan payment has two parts: principal (a balance-sheet transfer) and interest (a P&L expense). Booking the whole payment as expense overstates your costs and understates your liabilities.',
    tasks: [
      { id: 'l1', t: 'Pull the amortization schedule for each loan', d: 'SBA, term loans, equipment financing — all of them.' },
      { id: 'l2', t: 'Record this month\'s principal to the liability', d: 'Reduces the loan balance on the balance sheet.' },
      { id: 'l3', t: 'Record this month\'s interest to expense', d: 'Hits the P&L. Tax-deductible.' },
      { id: 'l4', t: 'Reconcile the loan balance to the lender portal', d: 'Your books should match the bank\'s balance at month-end.' },
    ],
    tip: 'If you only make one adjustment this month, make it this one.',
  },
  {
    id: 'inventory',
    phase: 'Week 2',
    day: 'Day 7–9',
    title: 'Roll inventory & COGS.',
    eyebrow: 'If applicable',
    icon: 'box',
    why: 'Physical product businesses: your COGS isn\'t what you spent on inventory — it\'s what you sold. Miss this and your margins are wrong by a lot.',
    tasks: [
      { id: 'i1', t: 'Count or cycle-count ending inventory', d: 'Full count quarterly; spot checks monthly.' },
      { id: 'i2', t: 'Post COGS journal: beginning + purchases − ending', d: 'Moves the cost of what shipped from inventory to COGS.' },
      { id: 'i3', t: 'Write off shrinkage, damage, obsolete SKUs', d: 'Inventory that doesn\'t exist shouldn\'t sit on the balance sheet.' },
      { id: 'i4', t: 'Reconcile fulfillment platform counts', d: 'Shopify, Amazon FBA, 3PL — counts should tie to the GL.' },
    ],
    tip: 'Service businesses: skip this step. Everyone else: do not skip this step.',
    optional: true,
  },
  {
    id: 'payroll',
    phase: 'Week 2',
    day: 'Day 7–10',
    title: 'Tie out payroll & contractors.',
    eyebrow: 'People',
    icon: 'people',
    why: 'Gross wages, employer taxes, benefits, and contractor spend all need to match the payroll provider\'s reports to the penny. 1099 vs W-2 classification mistakes compound fast.',
    tasks: [
      { id: 'p1', t: 'Tie payroll reports to GL wage + tax accounts', d: 'Gusto / Rippling / ADP totals = GL totals.' },
      { id: 'p2', t: 'Book employer-side taxes & benefits', d: 'FICA, SUTA, FUTA, 401(k) match, health contributions.' },
      { id: 'p3', t: 'Track contractor spend against $600 threshold', d: 'Anyone over $600 YTD gets a 1099 at year-end.' },
      { id: 'p4', t: 'Classify owner payments correctly', d: 'W-2 wages, owner draw, distribution, reimbursement — all different.' },
    ],
    tip: 'Payroll errors don\'t age well. Catch them this month, not at year-end.',
  },
  {
    id: 'fixed',
    phase: 'Week 2',
    day: 'Day 8–10',
    title: 'Depreciate & amortize.',
    eyebrow: 'Fixed assets',
    icon: 'asset',
    why: 'Big equipment purchases, vehicles, leasehold improvements, and capitalized software don\'t expense all at once — they spread over their useful life. Book the monthly depreciation entry.',
    tasks: [
      { id: 'f1', t: 'Post monthly depreciation journal entry', d: '1/60th of useful life for 5-year assets, etc.' },
      { id: 'f2', t: 'Add new assets to the fixed asset register', d: 'Anything over your capitalization threshold (usually $2,500).' },
      { id: 'f3', t: 'Amortize intangibles (capitalized software, goodwill)', d: 'Same concept, different column on the balance sheet.' },
    ],
    tip: 'Your accountant wants the fixed asset register clean before tax season, not during it.',
    optional: true,
  },
  {
    id: 'review',
    phase: 'Week 3',
    day: 'Day 10–12',
    title: 'Sanity-check the financials.',
    eyebrow: 'Review',
    icon: 'scan',
    why: 'Pull the P&L and balance sheet and actually look at them. Anything that changed more than 20% month-over-month deserves an explanation — or it\'s an error.',
    tasks: [
      { id: 's1', t: 'P&L comparative vs prior month & prior year', d: 'Every line. Explain anything with a >20% swing.' },
      { id: 's2', t: 'Balance sheet: check for negatives where none belong', d: 'Negative cash, negative AR, negative inventory = data problem.' },
      { id: 's3', t: 'Gross margin % sanity check', d: 'If GM jumped 10 points, either COGS is off or revenue is.' },
      { id: 's4', t: 'Trial balance nets to zero', d: 'Debits = credits. Non-negotiable.' },
    ],
    tip: 'If the numbers look too good, they\'re wrong. If they look too bad, they\'re also wrong.',
  },
  {
    id: 'lock',
    phase: 'Week 3',
    day: 'Day 12–15',
    title: 'Lock the books & report out.',
    eyebrow: 'Done',
    icon: 'lock',
    why: 'Close the period in the accounting software so nothing can be back-dated. Publish the financial package with commentary — this is what turns bookkeeping into a decision-making tool.',
    tasks: [
      { id: 'd1', t: 'Lock the period in the GL', d: 'No more edits to last month, ever. Corrections go as current-period entries.' },
      { id: 'd2', t: 'Publish P&L, balance sheet, cash flow', d: 'PDF + source file. Archive in a dated folder.' },
      { id: 'd3', t: 'Write a short monthly commentary', d: 'Three bullets: what happened, what surprised you, what to watch next month.' },
      { id: 'd4', t: 'Back up the data file', d: 'Cloud + one offline copy. A lost data file is a lost year.' },
    ],
    tip: 'A closed book is a locked book. Locked means locked.',
  },
];

/* --- Local storage ----------------------------------------------------- */
const STORE_KEY = 'revenu-close-checklist-v1';

function loadState() {
  try {
    const raw = localStorage.getItem(STORE_KEY);
    if (!raw) return { checked: {}, current: 0 };
    const p = JSON.parse(raw);
    return { checked: p.checked || {}, current: p.current || 0 };
  } catch {
    return { checked: {}, current: 0 };
  }
}
function saveState(s) {
  try { localStorage.setItem(STORE_KEY, JSON.stringify(s)); } catch {}
}

/* --- Icons ------------------------------------------------------------- */
function CIcon({ name, size = 16 }) {
  const p = { width: size, height: size, viewBox: '0 0 20 20', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (name) {
    case 'flag':   return (<svg {...p}><path d="M5 3v14M5 4h9l-2 3 2 3H5"/></svg>);
    case 'tag':    return (<svg {...p}><path d="M3 10V4h6l8 8-6 6-8-8Z"/><circle cx="7" cy="7" r="1" fill="currentColor"/></svg>);
    case 'check':  return (<svg {...p}><path d="M4 10l4 4 8-8"/></svg>);
    case 'adjust': return (<svg {...p}><path d="M3 8h14M3 12h14M7 5v6M13 9v6"/></svg>);
    case 'debt':   return (<svg {...p}><path d="M3 6h14v8H3z"/><path d="M3 9h14M6 12h2"/></svg>);
    case 'box':    return (<svg {...p}><path d="M3 6l7-3 7 3v8l-7 3-7-3V6Z"/><path d="M3 6l7 3 7-3M10 9v9"/></svg>);
    case 'people': return (<svg {...p}><circle cx="7" cy="7" r="3"/><path d="M2 17c0-2.8 2.2-5 5-5s5 2.2 5 5"/><circle cx="14" cy="8" r="2.5"/><path d="M12.5 12.6A4.5 4.5 0 0 1 18 17"/></svg>);
    case 'asset':  return (<svg {...p}><path d="M4 16V9l6-4 6 4v7"/><path d="M4 16h12M8 16v-4h4v4"/></svg>);
    case 'scan':   return (<svg {...p}><path d="M3 7V4h3M17 7V4h-3M3 13v3h3M17 13v3h-3"/><path d="M6 10h8"/></svg>);
    case 'lock':   return (<svg {...p}><rect x="4" y="9" width="12" height="8" rx="1.5"/><path d="M7 9V7a3 3 0 0 1 6 0v2"/></svg>);
    case 'checkbold': return (<svg {...p} strokeWidth="2.2"><path d="M4 10l4 4 8-8"/></svg>);
    case 'arrow':  return (<svg {...p}><path d="M4 10h12M12 6l4 4-4 4"/></svg>);
    case 'back':   return (<svg {...p}><path d="M16 10H4M8 6l-4 4 4 4"/></svg>);
    case 'reset':  return (<svg {...p}><path d="M4 10a6 6 0 1 0 2-4.5"/><path d="M3 3v4h4"/></svg>);
    case 'info':   return (<svg {...p}><circle cx="10" cy="10" r="7.5"/><path d="M10 9v5M10 6.5v0" strokeWidth="1.8"/></svg>);
    case 'spark':  return (<svg {...p}><path d="M10 3v4M10 13v4M3 10h4M13 10h4M5 5l2.5 2.5M12.5 12.5L15 15M5 15l2.5-2.5M12.5 7.5L15 5"/></svg>);
    default: return null;
  }
}

/* --- Main component ---------------------------------------------------- */
function CloseChecklist() {
  const initial = loadState();
  const [checked, setChecked]   = useStateClose(initial.checked);
  const [current, setCurrent]   = useStateClose(Math.min(initial.current, CLOSE_STEPS.length - 1));

  useEffectClose(() => { saveState({ checked, current }); }, [checked, current]);

  const allTasks = useMemoClose(() => CLOSE_STEPS.flatMap(s => s.tasks.map(t => ({ ...t, step: s.id }))), []);
  const totalTasks = allTasks.length;
  const doneTasks  = allTasks.filter(t => checked[t.id]).length;
  const pct = Math.round((doneTasks / totalTasks) * 100);

  const stepStatus = (s) => {
    const all = s.tasks.length;
    const done = s.tasks.filter(t => checked[t.id]).length;
    if (done === 0) return { state: 'todo', done, all };
    if (done === all) return { state: 'done', done, all };
    return { state: 'active', done, all };
  };
  const statuses = CLOSE_STEPS.map(stepStatus);

  const stepsComplete = statuses.filter(s => s.state === 'done').length;
  const allDone = stepsComplete === CLOSE_STEPS.length;

  const toggle = (id) => setChecked(c => ({ ...c, [id]: !c[id] }));
  const toggleStep = (s) => {
    const st = stepStatus(s);
    const all = st.state !== 'done';
    setChecked(c => {
      const next = { ...c };
      s.tasks.forEach(t => { next[t.id] = all; });
      return next;
    });
  };
  const reset = () => { setChecked({}); setCurrent(0); };
  const next = () => setCurrent(c => Math.min(c + 1, CLOSE_STEPS.length - 1));
  const back = () => setCurrent(c => Math.max(c - 1, 0));
  const go   = (i) => setCurrent(i);

  const step = CLOSE_STEPS[current];
  const st   = statuses[current];

  return (
    <>
      <section className="container">
        <div className="close-hero">
          <div className="eyebrow">Resources · Tools</div>
          <h1 className="display">
            {allDone
              ? <>The books are <em>closed.</em></>
              : <>Close the books, <em>the right way.</em></>}
          </h1>
          <p className="lede">
            {allDone
              ? 'Every step checked, every account reconciled. Publish your financial package, lock the period, and take the rest of the day off. Next month starts tomorrow.'
              : 'Ten phases, fifty-ish tasks, one locked period. Work through the steps at your own pace — your progress saves automatically, so you can come back tomorrow and pick up exactly where you left off.'}
          </p>

          <div className="close-hero-meta">
            <span className="close-factor"><span className="dot"/> {CLOSE_STEPS.length} phases</span>
            <span className="close-factor">{totalTasks} tasks</span>
            <span className="close-factor">Target: 10 business days</span>
            <span className="close-factor">Progress saves locally</span>
          </div>
        </div>
      </section>

      {/* Progress strip */}
      <section className="container">
        <div className={`close-progress-bar ${allDone ? 'is-done' : ''}`}>
          <div className="close-progress-main">
            <div className="close-progress-label">
              <div className="close-progress-count"><strong>{doneTasks}</strong> of {totalTasks} tasks complete</div>
              <div className="close-progress-sub">{stepsComplete} of {CLOSE_STEPS.length} phases closed</div>
            </div>
            <div className="close-progress-pct tabular">{pct}<span>%</span></div>
          </div>
          <div className="close-progress-track">
            <div className="close-progress-fill" style={{ width: `${pct}%` }}/>
          </div>
          <div className="close-progress-actions">
            <button className="close-reset" onClick={reset}>
              <CIcon name="reset" size={12}/> Start over
            </button>
          </div>
        </div>
      </section>

      {/* Main shell */}
      <section className="container" style={{ paddingBottom: 24 }}>
        <div className="close-shell">

          {/* Steps rail */}
          <aside className="close-rail">
            <div className="close-rail-head">
              <div className="close-rail-title">Monthly close</div>
              <div className="close-rail-sub">Day 1 → lock</div>
            </div>
            <ol className="close-rail-list">
              {CLOSE_STEPS.map((s, i) => {
                const st = statuses[i];
                const active = i === current;
                const cls = `close-rail-item ${active ? 'is-active' : ''} is-${st.state}`;
                return (
                  <li key={s.id}>
                    <button className={cls} onClick={() => go(i)}>
                      <span className="close-rail-node">
                        {st.state === 'done'
                          ? <CIcon name="checkbold" size={12}/>
                          : String(i + 1).padStart(2, '0')}
                      </span>
                      <span className="close-rail-body">
                        <span className="close-rail-phase">{s.phase} · {s.day}</span>
                        <span className="close-rail-name">{s.title.replace(/\.$/, '')}</span>
                        <span className="close-rail-count">{st.done}/{st.all} tasks</span>
                      </span>
                      {s.optional && <span className="close-rail-optional">optional</span>}
                    </button>
                  </li>
                );
              })}
            </ol>
          </aside>

          {/* Step detail */}
          <div className="close-main">
            {allDone && <DonePanel onReset={reset}/>}
            {!allDone && (
              <StepCard
                step={step}
                idx={current}
                total={CLOSE_STEPS.length}
                status={st}
                checked={checked}
                onToggle={toggle}
                onToggleAll={() => toggleStep(step)}
                onNext={next}
                onBack={back}
              />
            )}
          </div>
        </div>

        {/* Disclaimer */}
        <div className="close-disclaimer">
          <div className="close-disclaimer-icon"><CIcon name="info" size={16}/></div>
          <div className="close-disclaimer-body">
            <strong>This is a generalized close — yours may have more (or fewer) steps.</strong> Industries with inventory, multi-entity consolidations, foreign currency, revenue recognition rules (ASC 606), lease accounting (ASC 842), or sales tax across states have extra work we haven't broken out here. If your close takes more than two weeks — or you haven't closed a month in three — <a href="cfo.html">talk to a Revenu advisor</a> or <a href="bookkeeping.html">see our bookkeeping service</a>. We close books for a living.
          </div>
        </div>
      </section>

      {/* Reference strip — why this matters */}
      <section className="container">
        <div className="close-tips">
          <div className="close-tip">
            <div className="num">01 / Cadence</div>
            <h3>Closed on day 10 beats perfect on day 40.</h3>
            <p>A monthly close that lands the same week every month is worth more than one that tries to be exhaustive and slips. Pick a target day, publish it internally, and protect it.</p>
          </div>
          <div className="close-tip">
            <div className="num">02 / Accrual discipline</div>
            <h3>Cash is a lie. Accrual is the truth.</h3>
            <p>Matching revenue and expense to the month they belong in — with real prepaids, accruals, and deferred revenue — is what turns bookkeeping into financial statements a bank or investor can read.</p>
          </div>
          <div className="close-tip">
            <div className="num">03 / Lock it</div>
            <h3>A locked period is a finished period.</h3>
            <p>Once you publish the package, lock the GL. Any corrections after that go as current-period journal entries with a note. This is the single biggest upgrade from "doing the books" to "running a company."</p>
          </div>
        </div>
      </section>
    </>
  );
}

/* --- Step card --------------------------------------------------------- */
function StepCard({ step, idx, total, status, checked, onToggle, onToggleAll, onNext, onBack }) {
  const isFirst = idx === 0;
  const isLast  = idx === total - 1;
  const allChecked = status.state === 'done';

  return (
    <div className="close-step" key={step.id}>
      <div className="close-step-head">
        <div className="close-step-eyebrow">
          <span className="close-step-num">Phase {String(idx + 1).padStart(2, '0')} / {String(total).padStart(2, '0')}</span>
          <span className="close-step-chips">
            <span className="close-chip">{step.phase}</span>
            <span className="close-chip close-chip-quiet">{step.day}</span>
            {step.optional && <span className="close-chip close-chip-optional">Optional</span>}
          </span>
        </div>
        <div className="close-step-title-row">
          <div className="close-step-icon"><CIcon name={step.icon} size={22}/></div>
          <h2 className="close-step-title">{step.title}</h2>
        </div>
        <p className="close-step-why">{step.why}</p>
      </div>

      <div className="close-step-tasks">
        <div className="close-tasks-head">
          <div className="close-tasks-head-l">
            <div className="close-tasks-title">Checklist</div>
            <div className="close-tasks-count tabular">{status.done} / {status.all}</div>
          </div>
          <button className="close-toggle-all" onClick={onToggleAll}>
            {allChecked ? 'Uncheck all' : 'Check all'}
          </button>
        </div>

        <ul className="close-tasks">
          {step.tasks.map((t) => {
            const done = !!checked[t.id];
            return (
              <li key={t.id} className={`close-task ${done ? 'is-done' : ''}`}>
                <button className="close-task-btn" onClick={() => onToggle(t.id)} aria-pressed={done}>
                  <span className="close-task-box">
                    {done && <CIcon name="checkbold" size={11}/>}
                  </span>
                  <span className="close-task-body">
                    <span className="close-task-t">{t.t}</span>
                    <span className="close-task-d">{t.d}</span>
                  </span>
                </button>
              </li>
            );
          })}
        </ul>

        <div className="close-step-tip">
          <CIcon name="spark" size={14}/>
          <span>{step.tip}</span>
        </div>
      </div>

      <div className="close-step-nav">
        <button className="close-back" onClick={onBack} disabled={isFirst}>
          <CIcon name="back" size={12}/> Previous phase
        </button>
        <div className="close-step-dots">
          {Array.from({length: total}).map((_, i) => (
            <span key={i} className={`close-dot ${i === idx ? 'is-active' : ''}`}/>
          ))}
        </div>
        <button className={`close-next ${isLast ? 'is-final' : ''}`} onClick={onNext} disabled={isLast}>
          {isLast ? 'Final phase' : 'Next phase'} <CIcon name="arrow" size={12}/>
        </button>
      </div>
    </div>
  );
}

/* --- Done panel -------------------------------------------------------- */
function DonePanel({ onReset }) {
  return (
    <div className="close-done">
      <div className="close-done-badge">
        <CIcon name="lock" size={28}/>
      </div>
      <div className="close-done-eyebrow">Period closed</div>
      <h2 className="close-done-title">Nice close.</h2>
      <p className="close-done-sub">
        Books reconciled, accruals booked, loans split, financials reviewed, period locked. The hard part is building the muscle — the next close will be faster.
      </p>
      <div className="close-done-meta">
        <div className="close-done-stat">
          <div className="close-done-stat-v tabular">10</div>
          <div className="close-done-stat-l">Phases completed</div>
        </div>
        <div className="close-done-stat">
          <div className="close-done-stat-v tabular">100<span>%</span></div>
          <div className="close-done-stat-l">Tasks checked off</div>
        </div>
        <div className="close-done-stat">
          <div className="close-done-stat-v">Locked</div>
          <div className="close-done-stat-l">General ledger status</div>
        </div>
      </div>
      <div className="close-done-actions">
        <a href="cfo.html" className="btn btn-primary is-accent">Hand next month to Revenu <CIcon name="arrow" size={12}/></a>
        <a href="bookkeeping.html" className="btn btn-secondary">See bookkeeping service</a>
        <button className="close-done-reset" onClick={onReset}>
          <CIcon name="reset" size={12}/> Start a new month
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { CloseChecklist });
