// EzClaim — payment, secure details, submission, status screens.

const { fmtUSD: pFmtUSD, fmtDate: pFmtDate, fmtTime: pFmtTime, shortId, lookup: pLookup, homesteadStatus: pHomesteadStatus } = window.EZ_MOCK;

// ─────────────────────────────────────────────────────────────────────────────
// Stripe handoff (loading)
// ─────────────────────────────────────────────────────────────────────────────
function CheckoutScreen({ nav, session, setSession }) {
  const [stage, setStage] = useState(session?.payment_status === "failed" ? "failed" : "loading");
  // simulate Stripe redirect → return
  useEffect(() => {
    if (stage !== "loading") return;
    const t = setTimeout(() => setStage("stripe"), 800);
    return () => clearTimeout(t);
  }, [stage]);

  function fakePay() {
    setStage("processing");
    setTimeout(() => {
      setSession({ ...session, payment_status: "paid", payment: {
        receipt_id: shortId("ch"),
        paid_at: new Date().toISOString(),
        amount: 19.99,
        last4: "4242",
      }});
      nav("/secure-details");
    }, 1400);
  }
  function fakeFail() {
    setSession({ ...session, payment_status: "failed" });
    setStage("failed");
  }

  if (stage === "loading") {
    return (
      <div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: 18, paddingTop: 32 }}>
        <div className="lockbox">
          <div className="ico"><I.Lock size={22}/></div>
          <div style={{ flex: 1 }}>
            <div className="t">Connecting to Stripe…</div>
            <div className="s">Redirecting you to secure checkout. This usually takes a second.</div>
          </div>
        </div>
        <div className="lbar"><i/></div>
        <p className="subtle text-center">Don't close this tab.</p>
      </div>
    );
  }

  if (stage === "failed") {
    return (
      <div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: 18 }}>
        <Callout kind="err" icon={<I.Alert size={18}/>} title="Payment didn't go through">
          Your bank declined the charge. No money was taken. Try a different card, or come back later — your filing answers are saved.
        </Callout>
        <div className="cta-bar">
          <Button kind="primary" block onClick={() => { setStage("stripe"); setSession({ ...session, payment_status: "pending" }); }}>Try again</Button>
          <Button kind="secondary" block onClick={() => nav("/review")}>Back to review</Button>
        </div>
        <p className="subtle text-center" style={{ fontSize: 12 }}>Common reasons: insufficient funds, expired card, or your bank flagged the merchant. Stripe never sends us the decline reason.</p>
      </div>
    );
  }

  if (stage === "processing") {
    return (
      <div className="fade-in" style={{ paddingTop: 32, display: "flex", flexDirection: "column", gap: 16, alignItems: "center" }}>
        <div style={{ width: 56, height: 56, borderRadius: 16, background: "var(--brand-50)", color: "var(--brand-700)", display: "grid", placeItems: "center" }}>
          <span className="spin" style={{ width: 22, height: 22 }}/>
        </div>
        <div className="h-section">Processing payment…</div>
        <p className="subtle text-center" style={{ maxWidth: "30ch" }}>Your card is being charged $19.99. We'll move you to secure filing in a moment.</p>
      </div>
    );
  }

  // Stripe-style mock checkout (the real one is hosted by Stripe; this is a UI handoff representation)
  return (
    <div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: 18 }}>
      <Button kind="ghost" size="sm" icon={<I.ArrowLeft size={14}/>} onClick={() => nav("/review")}>Back to review</Button>

      <div className="card lg">
        <div className="row between" style={{ alignItems: "flex-start" }}>
          <div>
            <div className="eyebrow" style={{ color: "var(--ink-500)" }}>EzClaim, Inc. · Stripe</div>
            <div className="h-section" style={{ marginTop: 4 }}>Homestead filing service</div>
          </div>
          <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: "-0.01em" }}>$19.99</div>
        </div>
        <div className="card-divider"/>

        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <Field label="Email">
            <Input aria-label="Email" type="email" leftIcon={<I.Mail size={16}/>} defaultValue={session?.filing?.email || ""}/>
          </Field>
          <Field label="Card information">
            <Input aria-label="Card information" leftIcon={<I.Card size={16}/>} placeholder="1234 1234 1234 1234"/>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginTop: 8 }}>
              <Input aria-label="Expiration date" placeholder="MM / YY"/>
              <Input aria-label="CVC" placeholder="CVC"/>
            </div>
          </Field>
          <Field label="Name on card">
            <Input aria-label="Name on card" defaultValue={session?.filing?.full_name || ""}/>
          </Field>
          <Field label="ZIP">
            <Input aria-label="ZIP" placeholder="21218"/>
          </Field>
        </div>
        <div className="card-divider"/>
        <Button kind="primary" block size="lg" onClick={fakePay} iconRight={<I.Lock size={16}/>}>
          Pay $19.99
        </Button>
        <p className="subtle text-center" style={{ marginTop: 12, fontSize: 12 }}>
          By paying, you authorize EzClaim to charge $19.99 and proceed with your Homestead filing. <br/>
          Powered by <strong>Stripe</strong> · <button className="btn-link" style={{ fontSize: 12 }} onClick={fakeFail}>Simulate a declined card</button>
        </p>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Secure details — collected AFTER payment
// ─────────────────────────────────────────────────────────────────────────────
function SecureDetailsScreen({ nav, session, setSession }) {
  const [secure, setSecure] = useState(session.secure || { ssn: "", consent: false, signature: "" });
  const f = session?.filing || {};
  const has = f.has_coowners;
  const sigRef = useRef(null);
  const [drew, setDrew] = useState(false);

  function setS(patch) { setSecure(prev => ({ ...prev, ...patch })); }

  // Tiny signature pad
  useEffect(() => {
    const c = sigRef.current; if (!c) return;
    const ctx = c.getContext("2d");
    ctx.lineWidth = 1.8; ctx.lineCap = "round"; ctx.strokeStyle = "#0B1F33";
    let drawing = false; let last = null;
    function pt(e) {
      const r = c.getBoundingClientRect();
      const x = (e.touches ? e.touches[0].clientX : e.clientX) - r.left;
      const y = (e.touches ? e.touches[0].clientY : e.clientY) - r.top;
      return [x * (c.width / r.width), y * (c.height / r.height)];
    }
    function down(e) { e.preventDefault(); drawing = true; last = pt(e); setDrew(true); }
    function move(e) {
      if (!drawing) return; e.preventDefault();
      const p = pt(e);
      ctx.beginPath(); ctx.moveTo(last[0], last[1]); ctx.lineTo(p[0], p[1]); ctx.stroke();
      last = p;
    }
    function up() { drawing = false; last = null; }
    c.addEventListener("mousedown", down); c.addEventListener("mousemove", move); window.addEventListener("mouseup", up);
    c.addEventListener("touchstart", down); c.addEventListener("touchmove", move); window.addEventListener("touchend", up);
    return () => {
      c.removeEventListener("mousedown", down); c.removeEventListener("mousemove", move); window.removeEventListener("mouseup", up);
      c.removeEventListener("touchstart", down); c.removeEventListener("touchmove", move); window.removeEventListener("touchend", up);
    };
  }, []);
  function clearSig() {
    const c = sigRef.current; if (!c) return;
    c.getContext("2d").clearRect(0,0,c.width,c.height);
    setDrew(false);
  }

  function submit() {
    if (!secure.ssn || !secure.consent || !drew) return;
    setSession({ ...session, secure: { ssn: maskSsn(secure.ssn), consent: true, signed_at: new Date().toISOString() } });
    nav("/submitting");
  }

  return (
    <div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: 18 }}>
      <div className="row gap-3" style={{ alignItems: "center" }}>
        <Tag kind="good"><I.Check size={11}/> Paid · $19.99</Tag>
        <span className="muted" style={{ fontSize: 12 }}>Receipt: <strong className="tabnum" style={{ color: "var(--ink-700)" }}>{session?.payment?.receipt_id}</strong></span>
      </div>
      <div>
        <h2 className="h-page">Final filing details</h2>
        <p className="subtle" style={{ marginTop: 6 }}>SDAT requires SSN and a signature on the form. We collect them only at this step, use them to generate the packet, and delete them after fax delivery.</p>
      </div>

      <Callout kind="" icon={<I.Lock size={16}/>} title="What we do with this data">
        Your SSN and signature are stored encrypted in volatile memory only long enough to render the PDF, fax it, and confirm delivery. They are <strong style={{ color: "var(--ink-900)" }}>not persisted to disk</strong> and not retained after the fax is delivered. The status link we email you contains only non-sensitive metadata.
      </Callout>

      <div className="card lg">
        <h3 className="h-section">Your Social Security Number</h3>
        <Field label="SSN" help="Required by SDAT to match you to property records.">
          <Input aria-label="SSN" value={secure.ssn} onChange={(e) => setS({ ssn: formatSsn(e.target.value) })} placeholder="___-__-____" inputMode="numeric" maxLength={11}/>
        </Field>
        {has ? (
          <>
            <div className="card-divider"/>
            <h3 className="h-section">Co-owner's SSN</h3>
            <p className="subtle" style={{ marginBottom: 8 }}>{f.coowner_name} — also required on the SDAT application.</p>
            <Field label="Co-owner SSN">
              <Input aria-label="Co-owner SSN" value={secure.coowner_ssn || ""} onChange={(e) => setS({ coowner_ssn: formatSsn(e.target.value) })} placeholder="___-__-____" inputMode="numeric" maxLength={11}/>
            </Field>
          </>
        ) : null}
      </div>

      <div className="card lg">
        <h3 className="h-section">Signature</h3>
        <p className="subtle" style={{ marginBottom: 12 }}>Sign with your finger or mouse. This becomes the signature on your SDAT application.</p>
        <div style={{ border: "1px dashed var(--line-2)", borderRadius: "var(--radius)", background: "var(--surface-2)", position: "relative", height: 160, overflow: "hidden" }}>
          <canvas ref={sigRef} width="900" height="240" style={{ width: "100%", height: "100%", display: "block", touchAction: "none" }}/>
          {!drew ? <span style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", color: "var(--ink-400)", fontSize: 13, pointerEvents: "none" }}>Sign here</span> : null}
        </div>
        <div className="row between mt-2">
          <span className="muted" style={{ fontSize: 12 }}>{f.full_name || "Your name"}</span>
          <Button kind="link" size="sm" onClick={clearSig}>Clear</Button>
        </div>
      </div>

      <Checkbox
        checked={!!secure.consent}
        onChange={(v) => setS({ consent: v })}
        label="I authorize EzClaim to prepare and submit my Homestead Tax Credit application to SDAT."
        sub="I confirm the information I've provided is true to the best of my knowledge. I understand approval is determined by SDAT, not EzClaim."
      />

      <div className="cta-bar sticky">
        <Button kind="secondary" onClick={() => nav("/review")} icon={<I.ArrowLeft size={14}/>}>Back</Button>
        <Button kind="primary" onClick={submit} iconRight={<I.ArrowRight size={14}/>} disabled={!secure.ssn || !secure.consent || !drew}>
          Submit my filing
        </Button>
      </div>
    </div>
  );
}

function formatSsn(s) {
  const d = s.replace(/\D/g, "").slice(0, 9);
  if (d.length <= 3) return d;
  if (d.length <= 5) return d.slice(0,3) + "-" + d.slice(3);
  return d.slice(0,3) + "-" + d.slice(3,5) + "-" + d.slice(5);
}
function maskSsn(s) { return "•••-••-" + s.slice(-4); }

// ─────────────────────────────────────────────────────────────────────────────
// Submitting — animated progress
// ─────────────────────────────────────────────────────────────────────────────
function SubmittingScreen({ nav, session, setSession }) {
  const STEPS = [
    { k: "build",   t: "Building your filing packet",   d: 1200 },
    { k: "fax",     t: "Faxing to SDAT (410-225-9344)", d: 1600 },
    { k: "deliver", t: "Confirming delivery",            d: 1300 },
    { k: "scrub",   t: "Deleting your sensitive data",   d: 900  },
  ];
  const [i, setI] = useState(0);
  const [done, setDone] = useState(false);
  const [failed, setFailed] = useState(false);

  useEffect(() => {
    if (done || failed) return;
    if (i >= STEPS.length) { setDone(true); return; }
    const t = setTimeout(() => setI(i + 1), STEPS[i].d);
    return () => clearTimeout(t);
  }, [i, done, failed]);

  useEffect(() => {
    if (!done) return;
    const filingId = session.filing_id || shortId("hf");
    const payload = {
      ...session,
      filing_id: filingId,
      submitted_at: new Date().toISOString(),
      // simulated server-side timeline. caller can flip "fax_failed" via demo.
      events: [
        { k: "payment", t: "Payment received", at: session.payment?.paid_at },
        { k: "build",   t: "Filing packet generated", at: new Date(Date.now() - 1200*3).toISOString() },
        { k: "fax",     t: "Fax submitted to SDAT (410-225-9344)", at: new Date(Date.now() - 1200*2).toISOString() },
        { k: "deliver", t: "Fax delivered · 6 pages · 1m 42s", at: new Date(Date.now() - 1200).toISOString() },
        { k: "scrub",   t: "Sensitive data deleted from EzClaim", at: new Date().toISOString() },
      ],
      sdat_status: "Awaiting SDAT processing",
    };
    setSession(payload);
    const t = setTimeout(() => nav("/submitted"), 700);
    return () => clearTimeout(t);
  }, [done]);

  return (
    <div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: 18, paddingTop: 24 }}>
      <div className="text-center">
        <h2 className="h-page">Submitting your filing</h2>
        <p className="subtle" style={{ marginTop: 6 }}>Stay on this page. This takes about 5 seconds.</p>
      </div>
      <div className="card lg">
        {STEPS.map((s, idx) => (
          <div key={s.k} className="row gap-3" style={{ padding: "10px 0", alignItems: "center" }}>
            <span style={{
              width: 28, height: 28, borderRadius: "50%",
              background: idx < i ? "var(--good-600)" : idx === i ? "var(--brand-600)" : "var(--bg-2)",
              color: "#fff", display: "grid", placeItems: "center",
              transition: "background .2s",
            }}>
              {idx < i ? <I.Check size={14}/> : idx === i ? <span className="spin" style={{ borderColor: "#fff", borderBottomColor: "transparent" }}/> : <span style={{ width: 8, height: 8, borderRadius: 50, background: "var(--ink-300)" }}/>}
            </span>
            <span style={{ fontWeight: idx === i ? 600 : 500, color: idx <= i ? "var(--ink-900)" : "var(--ink-500)" }}>{s.t}</span>
          </div>
        ))}
      </div>
      <p className="subtle text-center" style={{ fontSize: 12 }}>
        SDAT's confirmation can take 4–8 weeks. We'll keep checking and email you any updates.
      </p>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Submitted (magic-link confirmation)
// ─────────────────────────────────────────────────────────────────────────────
function SubmittedScreen({ nav, session }) {
  const link = `https://ezclaim.app/s/${session.filing_id?.toLowerCase()}-${(session.filing?.email || "you").split("@")[0].slice(0,6)}`;
  const [copied, setCopied] = useState(false);
  return (
    <div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: 20, alignItems: "center", paddingTop: 24, textAlign: "center" }}>
      <div style={{ width: 72, height: 72, borderRadius: 18, background: "var(--good-100)", color: "var(--good-700)", display: "grid", placeItems: "center" }}>
        <I.CheckCircle size={36}/>
      </div>
      <div>
        <h2 className="h-page">Your Homestead application is on its way to SDAT</h2>
        <p className="subtle" style={{ marginTop: 8, maxWidth: 48 + "ch" }}>
          Fax delivered at {pFmtTime(new Date())} today. We've emailed your status link to <strong style={{ color: "var(--ink-700)" }}>{session.filing?.email}</strong>.
        </p>
      </div>

      <div className="card" style={{ width: "100%", textAlign: "left" }}>
        <h3 className="h-section">Your status link</h3>
        <p className="subtle" style={{ marginBottom: 12 }}>Bookmark this. There's no account or password — opening the link is how you check progress.</p>
        <pre className="codeblock" onClick={(e) => { navigator.clipboard?.writeText(link); setCopied(true); setTimeout(()=>setCopied(false), 1400); }} style={{ cursor: "copy" }}>
{link}
        </pre>
        <div className="row mt-3">
          <Button kind="secondary" size="sm" icon={<I.Copy size={14}/>} onClick={() => { navigator.clipboard?.writeText(link); setCopied(true); setTimeout(()=>setCopied(false), 1400); }}>{copied ? "Copied!" : "Copy link"}</Button>
          <Button kind="primary" size="sm" iconRight={<I.ArrowRight size={14}/>} onClick={() => nav("/status")}>Open status page</Button>
        </div>
      </div>

      <Callout kind="info" icon={<I.Info size={18}/>}>
        <strong>Note:</strong> SDAT's public records can lag behind fax delivery by 2–6 weeks. We'll keep refreshing daily and update your status page as soon as anything changes.
      </Callout>

      <div className="rcpt" style={{ width: "100%", textAlign: "left" }}>
        <div className="row"><span className="k">Receipt</span><span className="v" style={{ marginLeft: "auto" }}>{session.payment?.receipt_id}</span></div>
        <div className="row"><span className="k">Amount</span><span className="v" style={{ marginLeft: "auto" }}>{pFmtUSD(19.99, { cents: true })}</span></div>
        <div className="row"><span className="k">Filing ID</span><span className="v" style={{ marginLeft: "auto" }}>{session.filing_id}</span></div>
      </div>

      <p className="subtle" style={{ fontSize: 12 }}>EzClaim is not a government agency. You can also file free directly with SDAT at <a href="https://sdathtc.dat.maryland.gov" target="_blank" rel="noreferrer">sdathtc.dat.maryland.gov</a>.</p>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Status page (magic-link target)
// ─────────────────────────────────────────────────────────────────────────────
function StatusScreen({ nav, session, setSession, scenario = "happy" }) {
  const [refreshing, setRefreshing] = useState(false);
  const [lastRefresh, setLastRefresh] = useState(new Date());

  // If session is empty (cold open of status link), fabricate one
  useEffect(() => {
    if (!session.filing_id) {
      const now = Date.now();
      setSession({
        ...session,
        filing_id: shortId("hf"),
        filing: session.filing || { email: "you@example.com", full_name: "Renee A. Whitlock" },
        lookup: session.lookup?.matches?.length ? session.lookup : { state: "ok", matches: [PROPERTIES[0]] },
        payment: session.payment || { receipt_id: shortId("ch"), paid_at: new Date(now - 1000*60*60*4).toISOString(), amount: 19.99 },
        events: [
          { k: "payment", t: "Payment received", at: new Date(now - 1000*60*60*4).toISOString() },
          { k: "build",   t: "Filing packet generated", at: new Date(now - 1000*60*60*4 + 12000).toISOString() },
          { k: "fax",     t: "Fax submitted to SDAT (410-225-9344)", at: new Date(now - 1000*60*60*4 + 18000).toISOString() },
          { k: "deliver", t: "Fax delivered · 6 pages · 1m 42s", at: new Date(now - 1000*60*60*4 + 25000).toISOString() },
          { k: "scrub",   t: "Sensitive data deleted from EzClaim", at: new Date(now - 1000*60*60*4 + 28000).toISOString() },
        ],
        sdat_status: "Awaiting SDAT processing",
      });
    }
  }, []);

  const property = session?.lookup?.matches?.[0] || PROPERTIES[0];

  async function refreshFromRecords() {
    if (!property?.site_address) return;
    setRefreshing(true);
    try {
      const res = await pLookup(property.site_address);
      const fresh = res?.matches?.[0];
      if (fresh) {
        setSession({
          ...session,
          lookup: res,
          sdat_status: pHomesteadStatus(fresh).label,
        });
      }
    } catch (e) {
      // Keep the local status visible if the public-record refresh fails.
    } finally {
      setRefreshing(false);
      setLastRefresh(new Date());
    }
  }

  // Refresh-on-open
  useEffect(() => {
    if (!session.filing_id) return;
    refreshFromRecords();
  }, [session.filing_id]);

  const events = session.events || [];
  const sdat = session.sdat_status || "Awaiting SDAT processing";

  // Scenarios override
  let timeline = [
    { k: "payment", t: "Payment received", at: session.payment?.paid_at, state: "done" },
    { k: "build",   t: "Filing packet generated", at: events.find(e => e.k === "build")?.at, state: "done" },
    { k: "fax",     t: "Fax submitted to SDAT", at: events.find(e => e.k === "fax")?.at, state: "done", sub: "410-225-9344 · 6 pages" },
    { k: "deliver", t: "Fax delivered", at: events.find(e => e.k === "deliver")?.at, state: "done", sub: "1m 42s · session 88a3" },
    { k: "scrub",   t: "Sensitive data deleted", at: events.find(e => e.k === "scrub")?.at, state: "done", sub: "SSN + signed PDF purged from servers" },
    { k: "sdat",    t: "SDAT public status", at: null, state: "cur", sub: "Awaiting SDAT acknowledgement — typical 4–8 weeks" },
  ];

  if (scenario === "fax_failed") {
    timeline = [
      { k: "payment", t: "Payment received", at: session.payment?.paid_at, state: "done" },
      { k: "build",   t: "Filing packet generated", at: events.find(e => e.k === "build")?.at, state: "done" },
      { k: "fax",     t: "Fax submitted to SDAT", at: events.find(e => e.k === "fax")?.at, state: "err", sub: "Fax line busy · auto-retry queued" },
      { k: "retry",   t: "Retrying delivery", at: null, state: "cur", sub: "We retry every 30 minutes for 24 hours. No action needed." },
    ];
  } else if (scenario === "denied") {
    timeline.push({ k: "denied", t: "SDAT denied the application", at: new Date().toISOString(), state: "err", sub: "Reason: address not matched to deed. We'll refile at no charge." });
  } else if (scenario === "approved") {
    timeline[5] = { k: "sdat", t: "SDAT approved", at: new Date().toISOString(), state: "done", sub: "Approved · effective " + (new Date().getFullYear()+1) };
  }

  return (
    <div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: 18 }}>
      <div className="row between">
        <div className="row gap-2">
          <Tag kind="info"><I.Lock size={11}/> Secure link</Tag>
          <span className="muted" style={{ fontSize: 12 }}>No login required</span>
        </div>
        <Button kind="ghost" size="sm" icon={<I.Refresh size={14}/>} onClick={refreshFromRecords} disabled={refreshing}>
          {refreshing ? <>Refreshing…</> : <>Refresh now</>}
        </Button>
      </div>

      <div>
        <h2 className="h-page">Your Homestead filing</h2>
        <div className="row gap-2 mt-2 wrap" style={{ rowGap: 4 }}>
          <span className="muted" style={{ fontSize: 13, whiteSpace: "nowrap" }}>Filing ID</span>
          <span className="tabnum" style={{ fontSize: 13, fontWeight: 600, whiteSpace: "nowrap" }}>{session.filing_id}</span>
          <span className="muted" style={{ fontSize: 13 }}>·</span>
          <span className="muted" style={{ fontSize: 13, whiteSpace: "nowrap" }}>Last checked {pFmtTime(lastRefresh)}</span>
        </div>
      </div>

      <PropertyCard p={property} compact/>

      {scenario === "fax_failed" ? (
        <Callout kind="warn"><strong>SDAT's fax line was busy.</strong> We'll keep retrying every 30 minutes for up to 24 hours. You don't need to do anything.</Callout>
      ) : scenario === "denied" ? (
        <Callout kind="err"><strong>SDAT denied this application.</strong> We'll prepare a corrected refiling at no charge — check your email for next steps.</Callout>
      ) : scenario === "approved" ? (
        <Callout kind="good"><strong>You're approved.</strong> SDAT confirmed your Homestead Credit. It takes effect on the next assessment cycle.</Callout>
      ) : (
        <Callout kind="info"><strong>SDAT public records may lag</strong> behind fax delivery by 2–6 weeks. That's normal — we'll keep checking daily and update this page automatically.</Callout>
      )}

      <div className="card">
        <h3 className="h-section">Timeline</h3>
        <div className="tl">
          {timeline.map((row) => (
            <div key={row.k} className={"tl-row " + (row.state || "")}>
              <div className="tl-mark">
                {row.state === "done" ? <I.Check size={14}/> :
                 row.state === "err"  ? <I.X size={14}/> :
                 row.state === "cur"  ? <span className="spin" style={{ width: 12, height: 12, borderColor: "#fff", borderBottomColor: "transparent" }}/> :
                 <span style={{ width: 8, height: 8, borderRadius: 50, background: "currentColor" }}/>}
              </div>
              <div>
                <div className="tl-title">{row.t}</div>
                {row.sub ? <div className="tl-meta">{row.sub}</div> : null}
              </div>
              <div className="tl-time">{row.at ? pFmtTime(row.at) + " · " + pFmtDate(row.at) : "—"}</div>
            </div>
          ))}
        </div>
      </div>

      <div className="card">
        <h3 className="h-section">Receipt</h3>
        <div className="rcpt">
          <div className="row"><span className="k">Amount</span><span className="v" style={{ marginLeft: "auto" }}>{pFmtUSD(19.99, { cents: true })}</span></div>
          <div className="row"><span className="k">Paid</span><span className="v" style={{ marginLeft: "auto" }}>{pFmtDate(session.payment?.paid_at)}</span></div>
          <div className="row"><span className="k">Receipt ID</span><span className="v" style={{ marginLeft: "auto" }}>{session.payment?.receipt_id}</span></div>
          <div className="row"><span className="k">Payment method</span><span className="v" style={{ marginLeft: "auto" }}>•••• 4242</span></div>
        </div>
        <div className="row mt-3">
          <Button kind="link" size="sm" icon={<I.Print size={14}/>} onClick={() => window.print()}>Print</Button>
          <Button kind="link" size="sm" icon={<I.Mail size={14}/>}>Email receipt</Button>
        </div>
      </div>

      <p className="subtle text-center" style={{ fontSize: 12 }}>
        Questions? Email <a href="mailto:help@ezclaim.app">help@ezclaim.app</a>. EzClaim is not a government agency. The Homestead Tax Credit is administered by Maryland SDAT — you can also file directly at <a href="https://sdathtc.dat.maryland.gov" target="_blank" rel="noreferrer">sdathtc.dat.maryland.gov</a>.
      </p>
    </div>
  );
}

Object.assign(window, {
  CheckoutScreen, SecureDetailsScreen, SubmittingScreen, SubmittedScreen, StatusScreen,
});
