/* ============================================================================
   MOWDEW LIVE DEMO — per-tab screens, cloned from the App.html prototypes
   Each is the REAL app screen's layout (same headers, cards, components),
   re-wired to the shared demo `world` where the sync storyline needs it.
   Static tabs (Pro Done/Notes/Settings, Owner Customers) render the actual
   app components directly from the phone shells.
   ========================================================================= */

/* ───────────────────────── OWNER · MONEY ───────────────────────────── */
function OwnerMoneyTab({ world, act, nav }) {
  const inv = world.invoice; // null | 'sent' | 'paid'
  const ready = world.visit === 'done';
  const railLbl = (RAIL[world.paidVia] || RAIL.zelle).label;
  return (
    <Screen padBottom={24} footer={<TabBar role="owner" active="o_money" go={nav} onFab={() => {}} />}>
      <TopBar title="Money" big subtitle="Who's paid, who owes" />

      {/* summary — paid vs owed */}
      <div style={{ padding: '0 18px' }}>
        <div style={{ display: 'flex', gap: 10 }}>
          <div className="card" style={{ flex: 1, padding: 13 }}>
            <div style={{ fontSize: 11.5, color: 'var(--ink-500)', fontWeight: 600 }}>Collected · May</div>
            <Amount cents={184000 + (inv === 'paid' ? 26000 : 0)} size={20} tone="paid" />
          </div>
          <div className="card" style={{ flex: 1, padding: 13 }}>
            <div style={{ fontSize: 11.5, color: 'var(--ink-500)', fontWeight: 600 }}>Outstanding</div>
            <Amount cents={inv === 'sent' ? 26000 : 0} size={20} tone={inv === 'sent' ? 'due' : 'plain'} />
          </div>
        </div>
      </div>

      <div style={{ padding: '14px 18px 0' }}>
        <SectionHead tone="aqua" icon="invoice" style={{ marginBottom: 10 }} meta={<span style={{ whiteSpace: 'nowrap' }}>May 2026</span>}>Billing · Emma</SectionHead>

        {inv === 'sent' && (
          <div className="card" style={{ padding: 14 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 11 }}>
              <PaperAvatar who="home" size={40} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 700, fontSize: 14, whiteSpace: 'nowrap' }}>INV-0007 · Emma Walsh</div>
                <div style={{ fontSize: 11.5, color: 'var(--ink-500)', whiteSpace: 'nowrap' }}>Emailed with the PDF · 4 verified visits</div>
              </div>
              <DmMark tone="yellow" pulse>DUE MAY 26</DmMark>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, marginTop: 12, background: 'var(--paper)', border: '1px solid var(--ink-100)', borderRadius: 12, padding: '10px 13px' }}>
              <span style={{ fontSize: 12, color: 'var(--ink-500)' }}>Amount due</span>
              <Amount cents={26000} size={18} />
            </div>
            {world.nudged ? (
              <div style={{ display: 'flex', alignItems: 'center', gap: 9, marginTop: 12, background: 'var(--green-50)', borderRadius: 12, padding: '11px 13px', fontSize: 12.5, fontWeight: 600, color: 'var(--green-800)' }}>
                <Icon name="check-circle" size={16} style={{ flexShrink: 0 }} />Reminder sent — Emma was notified.
              </div>
            ) : (
              <button onClick={act.nudge} className="btn btn-primary btn-block" style={{ minHeight: 44, marginTop: 12 }}><Icon name="nudge" size={17} />Send respectful nudge</button>
            )}
            <div style={{ fontSize: 11.5, color: 'var(--ink-500)', marginTop: 10, lineHeight: 1.5 }}>Your Zelle, Venmo &amp; PayPal print on the PDF — Mowdew never touches the money.</div>
          </div>
        )}

        {inv === 'paid' && (
          <div className="card" style={{ padding: 14, borderColor: 'var(--green-100)' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 11 }}>
              <PaperAvatar who="home" size={40} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 700, fontSize: 14, whiteSpace: 'nowrap' }}>INV-0007 · Emma Walsh</div>
                <div style={{ fontSize: 11.5, color: 'var(--ink-500)', whiteSpace: 'nowrap' }}>Paid the same day it was sent</div>
              </div>
              <DmMark tone="green">{`PAID · ${railLbl.toUpperCase()}`}</DmMark>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 9, marginTop: 12, background: 'var(--green-50)', borderRadius: 12, padding: '11px 13px', fontSize: 12.5, fontWeight: 600, color: 'var(--green-800)', lineHeight: 1.5 }}>
              <Icon name="check-circle" size={16} style={{ flexShrink: 0 }} />
              All squared up — $260.00 went straight to your {railLbl}. Mowdew never touched it.
            </div>
          </div>
        )}
      </div>

      <div style={{ padding: '14px 18px 0' }}>
        <div className="card" style={{ padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 11 }}>
          <span style={{ width: 36, height: 36, borderRadius: 11, background: 'var(--aqua-50)', display: 'grid', placeItems: 'center', color: 'var(--aqua-700)', flexShrink: 0 }}><Icon name="dollar" size={18} /></span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 13 }}>May so far · Emma</div>
            <div style={{ fontSize: 11.5, color: 'var(--ink-500)' }}>{world.visit === 'done' ? '4 verified visits' : '3 verified visits'}{inv === 'paid' ? ' · collected' : ''}</div>
          </div>
          <Amount cents={world.visit === 'done' ? 26000 : 19500} size={16} />
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 11.5, color: 'var(--ink-500)', padding: '10px 2px 0' }}>
          <Icon name="eye-off" size={13} style={{ flexShrink: 0 }} />
          Marco never sees this tab — Pros are money-blind by design.
        </div>
      </div>
    </Screen>
  );
}

/* ───────────────────────── HOME · VISIT FEED (app HomeFeed clone) ──── */
function HomeFeedTab({ world, act, nav, openRequest, openReq, toast }) {
  const v = world.visit;
  const rq = world.resched;
  return (
    <Screen padBottom={26} footer={<TabBar role="homeowner" active="h_feed" go={nav} onFab={openRequest} />}>
      {/* header — same as the app's feed */}
      <div style={{ padding: '8px 18px 6px', display: 'flex', alignItems: 'center', gap: 12 }}>
        <Logo size={34} />
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 12.5, color: 'var(--ink-500)', fontWeight: 600 }}>88 Crestline Ave</div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 21, letterSpacing: '-0.02em' }}>Your visits</div>
        </div>
        <PaperAvatar who="home" size={42} />
        <DemoBell persona="home" world={world} act={act} />
      </div>

      {/* provider strip — with the request actions, same as the app */}
      <div style={{ padding: '8px 18px 0' }}>
        <div className="card" style={{ padding: 13, background: 'var(--green-50)', borderColor: 'var(--green-100)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
            <PaperAvatar who="owner" size={42} ring />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontWeight: 700, fontSize: 15 }}>Diego Marta</div>
              <div style={{ fontSize: 12.5, color: 'var(--green-800)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>Marta Lawn &amp; Pool · Weekly pool</div>
            </div>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11.5, fontWeight: 700, color: 'var(--green-700)' }}><Icon name="star" size={14} />4.9</span>
          </div>
          <div style={{ display: 'flex', gap: 8, marginTop: 11 }}>
            <button onClick={openRequest} style={{ flex: 1, minHeight: 42, border: 'none', background: 'var(--green-700)', color: '#fff', borderRadius: 12, fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 13.5, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, cursor: 'pointer', boxShadow: 'var(--shadow-green)' }}>
              <Icon name="calendar-check" size={17} />Reschedule
            </button>
            <button onClick={() => toast && toast('Messages live in the full prototype', 'blue')} style={{ flex: 1, minHeight: 42, border: '1px solid var(--green-100)', background: '#fff', color: 'var(--green-800)', borderRadius: 12, fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 13.5, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, cursor: 'pointer' }}>
              <Icon name="message" size={17} />Message
            </button>
          </div>
        </div>
      </div>

      {/* approve-before-work — request lifecycle */}
      <HomeRequestCard world={world} act={act} openReq={openReq} />

      {/* reviews — fires once the month is paid (peak trust) */}
      <HomeReviewCard world={world} act={act} />

      {/* respectful nudge — lands as a banner, not just a toast */}
      {world.nudged && world.invoice === 'sent' && (
        <div style={{ padding: '10px 18px 0' }}>
          <div onClick={() => nav('h_inbox')} style={{ display: 'flex', alignItems: 'center', gap: 11, background: 'var(--yellow-50)', border: '1px solid var(--yellow-100)', borderRadius: 'var(--radius-lg)', padding: '12px 14px', cursor: 'pointer', boxShadow: 'var(--shadow-sm)' }}>
            <span style={{ width: 38, height: 38, borderRadius: 11, background: 'var(--yellow-500)', display: 'grid', placeItems: 'center', color: 'var(--ink-900)', flexShrink: 0 }}><Icon name="nudge" size={19} /></span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontWeight: 700, fontSize: 13.5 }}>A friendly reminder from Diego</div>
              <div style={{ fontSize: 12, color: 'var(--ink-600,#6E6B60)', marginTop: 1 }}>INV-0007 · $260.00 · due May 26 — pay in one tap</div>
            </div>
            <Icon name="chevron-right" size={17} style={{ color: 'var(--yellow-700)', flexShrink: 0 }} />
          </div>
        </div>
      )}

      {/* message from Diego — the field-note follow-up */}
      {(world.note === 'asked' || world.note === 'replied' || world.note === 'closed') && (
        <div style={{ padding: '10px 18px 0' }}>
          <div className="card" style={{ padding: 14 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 9, marginBottom: 10 }}>
              <PaperAvatar who="owner" size={34} />
              <div style={{ flex: 1, minWidth: 0, fontWeight: 700, fontSize: 13.5 }}>Marta Lawn &amp; Pool</div>
              {world.note === 'asked' && <DmMark tone="blue" pulse>NEW MESSAGE</DmMark>}
              {world.note === 'replied' && <DmMark tone="yellow" pulse>SENT</DmMark>}
              {world.note === 'closed' && <DmMark tone="green">DONE</DmMark>}
            </div>
            <div style={{ display: 'grid', gap: 8 }}>
              <div style={{ justifySelf: 'start', maxWidth: '88%', background: 'var(--paper)', border: '1px solid var(--ink-100)', color: 'var(--ink-900)', borderRadius: '14px 14px 14px 4px', padding: '9px 12px', fontSize: 12.5, lineHeight: 1.45 }}>Marco says you'd like a monthly filter deep-clean — I can add it for $20/visit. Want it?</div>
              {(world.note === 'replied' || world.note === 'closed') && (
                <div style={{ justifySelf: 'end', maxWidth: '85%', background: 'var(--green-700)', color: '#fff', borderRadius: '14px 14px 4px 14px', padding: '9px 12px', fontSize: 12.5, lineHeight: 1.45 }}>{world.noteYes ? 'Yes please — add it.' : 'Not right now, thanks.'}</div>
              )}
            </div>
            {world.note === 'asked' && (
              <div style={{ display: 'flex', gap: 8, marginTop: 11 }}>
                <button onClick={() => act.homeReply(true)} className="btn btn-primary" style={{ flex: 1.3, minHeight: 42 }}><Icon name="check" size={16} />Yes, add it</button>
                <button onClick={() => act.homeReply(false)} className="btn btn-secondary" style={{ flex: 1, minHeight: 42 }}>Not now</button>
              </div>
            )}
            {world.note === 'closed' && world.noteYes && (
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 11, background: 'var(--green-50)', borderRadius: 11, padding: '9px 12px', fontSize: 12, fontWeight: 600, color: 'var(--green-800)' }}>
                <Icon name="check-circle" size={15} style={{ flexShrink: 0 }} />Added to your weekly service — starts next visit.
              </div>
            )}
          </div>
        </div>
      )}

      {/* live negotiation — appears once a request exists */}
      {rq && (
        <div style={{ padding: '10px 18px 0' }}>
          <div className="card" style={{ padding: 14 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 9, marginBottom: 10 }}>
              <PaperAvatar who="owner" size={34} />
              <div style={{ flex: 1, minWidth: 0, fontWeight: 700, fontSize: 13.5, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>Marta Lawn &amp; Pool</div>
              {(() => { const [t, l, p] = rqMark(rq.state, 'home'); return <DmMark tone={t} pulse={p}>{l}</DmMark>; })()}
            </div>
            <TimeChange compact from="Mon, May 18 · 10 AM" to={rq.state === 'declined' ? rq.to : (rq.proposedTo || rq.to)} toLabel={rq.state === 'approved' ? 'CONFIRMED' : rq.proposedTo ? 'DIEGO SUGGESTED' : 'REQUESTED'} toTone={rq.state === 'declined' ? 'alert' : 'green'} />
            <div style={{ margin: '11px 0 0' }}>
              <NegotiationThread thread={rq.thread} compact names={{ owner: 'Diego', homeowner: 'You' }} />
            </div>
            <div style={{ marginTop: 11 }}>
              {rq.state === 'pending' && <ReschedStatusBar state="waiting" text="Sent to Diego — you'll hear right here." />}
              {rq.state === 'proposed' && (
                <div style={{ display: 'grid', gap: 8 }}>
                  <button onClick={act.homeAccept} className="btn btn-primary btn-block" style={{ minHeight: 44 }}><Icon name="check" size={17} />Accept {rq.proposedTo}</button>
                  <button onClick={act.homeDeclineProposal} className="btn btn-secondary btn-block" style={{ minHeight: 40, color: 'var(--alert-700)' }}>Keep my original time</button>
                </div>
              )}
              {rq.state === 'approved' && <ReschedStatusBar state="approved" text={`Confirmed — your pool visit moved to ${rq.final}.`} />}
              {rq.state === 'declined' && <ReschedStatusBar state="declined" text={`Diego kept your original time (Mon, May 18). "${rq.declineNote}"`} />}
            </div>
          </div>
        </div>
      )}

      {/* tagline + timeline — same as the app */}
      <div style={{ padding: '12px 18px 2px' }}>
        <SectionHead tone="blue" icon="shield" meta="4 this month">Every visit, on the record</SectionHead>
        <div style={{ fontSize: 11.5, color: 'var(--ink-500)', marginTop: 6, lineHeight: 1.5 }}>GPS check-in proves when Marco arrived and left — no honor system.</div>
      </div>
      <div style={{ padding: '8px 18px 0', position: 'relative' }}>
        <div style={{ position: 'absolute', left: 36, top: 14, bottom: 10, width: 2, background: 'var(--ink-100)' }} />
        <div style={{ display: 'grid', gap: 16 }}>
          {/* today's visit — live, world-wired */}
          <div style={{ display: 'flex', gap: 12, position: 'relative' }}>
            <div style={{ flexShrink: 0, zIndex: 1 }}>
              <span style={{ width: 36, height: 36, borderRadius: '50%', background: v === 'done' ? 'var(--green-500)' : v === 'scheduled' ? 'var(--yellow-500)' : 'var(--blue-500)', display: 'grid', placeItems: 'center', color: v === 'scheduled' ? 'var(--ink-900)' : '#fff', border: '3px solid var(--paper)', boxShadow: 'var(--shadow-sm)' }}>
                <Icon name={v === 'done' ? 'check' : v === 'scheduled' ? 'clock' : 'pin'} size={17} strokeWidth={2.6} />
              </span>
            </div>
            <div className="card" style={{ flex: 1, padding: 13, borderColor: v === 'onsite' || v === 'driving' ? 'var(--blue-200,#8FD2F6)' : 'var(--ink-100)', boxShadow: v === 'onsite' || v === 'driving' ? '0 0 0 3px var(--blue-50), var(--shadow-sm)' : 'var(--shadow-sm)' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 9, marginBottom: 10 }}>
                <PaperAvatar who="pro" size={30} />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 700, fontSize: 14, lineHeight: 1.2 }}>Pool service</div>
                  <div style={{ fontSize: 11.5, color: 'var(--ink-500)' }}>Today · May 12</div>
                </div>
                {v === 'scheduled' && <DmMark tone="yellow">TODAY · 10 AM</DmMark>}
                {v === 'driving' && <DmMark tone="blue" pulse>ON THE WAY</DmMark>}
                {v === 'onsite' && <DmMark tone="blue" pulse>ON-SITE</DmMark>}
                {v === 'done' && <DmMark tone="green">DONE</DmMark>}
              </div>
              {(v === 'onsite' || v === 'done') && (
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 7 }}>
                  <PhotoTile scene="pool-before" label="BEFORE" height={84} />
                  {v === 'done'
                    ? <PhotoTile scene="pool-clean" label="AFTER" height={84} />
                    : <PhotoTile scene="empty" label="AFTER" height={84} icon="camera">In progress</PhotoTile>}
                </div>
              )}
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 11, fontSize: 12, color: 'var(--ink-500)' }}>
                {v === 'scheduled' && <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}><Icon name="clock" size={13} />You'll see Marco the moment he's en route</span>}
                {v === 'driving' && <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, color: 'var(--blue-700)', fontWeight: 700 }}><Icon name="navigation" size={13} />Marco is about 6 min out</span>}
                {(v === 'onsite' || v === 'done') && <>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}><Icon name="clock" size={13} />{world.checkInAt}{world.checkOutAt ? `–${world.checkOutAt}` : ''}</span>
                  <span style={{ fontWeight: 700, color: v === 'onsite' ? 'var(--blue-700)' : 'var(--ink-700)' }}>{dmClock(world.sec)}</span>
                </>}
                {(v === 'onsite' || v === 'done') && <span style={{ marginLeft: 'auto' }}><Mono tone="blue" icon="shield">AUTO CHECK-IN</Mono></span>}
              </div>
              {v === 'done' && <button onClick={() => nav('h_recap', { id: 'v2' })} className="btn btn-secondary btn-block" style={{ minHeight: 40, marginTop: 11 }}><Icon name="camera" size={16} />See the full recap</button>}
            </div>
          </div>
          {/* past visits — the full 4-week record behind INV-0007 */}
          {FEED.slice(1).map((fv, i) => <FeedCard key={fv.id} v={fv} go={() => nav('h_recap', { id: fv.id })} alt={i % 2 === 0} />)}
        </div>
      </div>
    </Screen>
  );
}

/* ───────────────────────── HOME · POOL (app HomeChemistry clone) ───── */
function HomePoolTab({ world, nav, openRequest }) {
  const live = world.chem && world.chem !== 'scanning' ? world.chem : null;
  const log = live
    ? [{ id: 'k0', date: 'Today · May 12', ph: live.ph, cl: live.cl, alk: live.alk, live: true }, ...CHEM_LOG.slice(1)]
    : CHEM_LOG.slice(1);
  const latest = log[0];
  const phSeries = log.map(r => r.ph).reverse();
  return (
    <Screen padBottom={26} footer={<TabBar role="homeowner" active="h_chem" go={nav} onFab={openRequest} />}>
      <div style={{ padding: '8px 18px 6px', display: 'flex', alignItems: 'center', gap: 12 }}>
        <span style={{ width: 38, height: 38, borderRadius: 11, background: 'var(--aqua-500)', display: 'grid', placeItems: 'center', color: '#fff' }}><Icon name="droplet" size={21} /></span>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 12.5, color: 'var(--ink-500)', fontWeight: 600 }}>88 Crestline Ave</div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 21, letterSpacing: '-0.02em' }}>Pool chemistry</div>
        </div>
        <Dewy size={42} mood="happy" />
      </div>

      {/* latest reading hero — same as the app */}
      <div style={{ padding: '6px 18px 0' }}>
        <div className="card card-feature" style={{ padding: 18, borderColor: 'var(--aqua-100)' }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
            <SectionHead tone="aqua" icon="flask" rule={false}>Latest reading</SectionHead>
            {latest.live ? <DmMark tone="aqua" pulse>CAPTURED TODAY</DmMark> : <DmMark tone="ink">{latest.date.toUpperCase()}</DmMark>}
          </div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginTop: 8, flexWrap: 'wrap' }}>
            <div>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10.5, letterSpacing: '.1em', color: 'var(--ink-500)', whiteSpace: 'nowrap' }}>pH BALANCE</div>
              <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 40, letterSpacing: '-0.03em', color: 'var(--green-700)', lineHeight: 1 }}>{latest.ph.toFixed(1)}</div>
            </div>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, color: 'var(--green-700)', fontWeight: 700, fontSize: 13.5 }}><Icon name="check-circle" size={16} />Perfectly balanced</span>
          </div>
          <div style={{ marginTop: 8 }}><PhGauge value={latest.ph} /></div>
          <div style={{ borderTop: '1px solid var(--ink-100)', marginTop: 14 }}>
            <ChemReadout rkey="cl" value={latest.cl} sub={latest.live ? 'Marco topped it up on-site' : undefined} />
            <div style={{ borderTop: '1px solid var(--ink-100)' }} />
            <ChemReadout rkey="alk" value={latest.alk} />
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 12, padding: '10px 12px', background: 'var(--aqua-50)', borderRadius: 12 }}>
            <Icon name="camera" size={16} style={{ color: 'var(--aqua-700)', flexShrink: 0 }} />
            <span style={{ fontSize: 12, color: 'var(--ink-700)' }}>{latest.live ? 'Read from the test strip Marco photographed — moments ago.' : 'Captured from a photo of your test strip on each verified visit.'}</span>
          </div>
        </div>
      </div>

      {/* equipment — the REAL app screen, reachable (auto-synced with the app) */}
      <div style={{ padding: '16px 18px 0' }}>
        <div onClick={() => nav('h_equipment')} className="card" style={{ padding: 14, display: 'flex', alignItems: 'center', gap: 12, cursor: 'pointer' }}>
          <span style={{ width: 42, height: 42, borderRadius: 12, background: 'var(--aqua-50)', display: 'grid', placeItems: 'center', color: 'var(--aqua-700)', flexShrink: 0 }}><Icon name="flask" size={21} /></span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 14 }}>Your equipment</div>
            <div style={{ fontSize: 12, color: 'var(--ink-500)' }}>Pump, filter, heater &amp; more — age, warranty &amp; history</div>
          </div>
          <Icon name="chevron-right" size={18} style={{ color: 'var(--ink-300)', flexShrink: 0 }} />
        </div>
      </div>

      {/* pH trend — same as the app */}
      <div style={{ padding: '16px 18px 0' }}>
        <div className="card" style={{ padding: 16 }}>
          <SectionHead tone="green" icon="trend-up" style={{ marginBottom: 12 }} meta={<span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, color: 'var(--green-700)', fontWeight: 700, whiteSpace: 'nowrap' }}><Icon name="check-circle" size={14} />6 weeks in range</span>}>pH over time</SectionHead>
          <ChemTrend points={phSeries} labels={['Apr 7', '', 'Apr 21', '', latest.live ? 'May 5' : '', latest.live ? 'Now' : 'May 5']} ideal={[7.2, 7.6]} rangeMin={6.8} rangeMax={8.2} color="var(--aqua-500)" />
        </div>
      </div>

      {/* reading history — same as the app */}
      <div style={{ padding: '16px 18px 0' }}>
        <SectionHead tone="aqua" icon="ledger" style={{ marginBottom: 12 }}>Every reading, on the record</SectionHead>
        <div className="card" style={{ overflow: 'hidden' }}>
          {log.map((r, i) => (
            <div key={r.id} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 14px', borderTop: i ? '1px solid var(--ink-100)' : 'none' }}>
              <PhBadge value={r.ph} size={42} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 700, fontSize: 13.5 }}>{r.date}</div>
                <div style={{ fontSize: 11.5, color: 'var(--ink-500)', fontFamily: 'var(--font-mono)' }}>CL {r.cl.toFixed(1)} · ALK {r.alk}</div>
              </div>
              {r.live && <DmMark tone="aqua" pulse>NEW</DmMark>}
              <div style={{ textAlign: 'right' }}>
                <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 17, color: 'var(--green-700)' }}>{r.ph.toFixed(1)}</div>
                <div style={{ fontSize: 10, color: 'var(--ink-400,#A8A498)', fontFamily: 'var(--font-mono)' }}>pH</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </Screen>
  );
}

/* ───────────────── HOME · INVOICES (app HomeInbox clone, world-wired) ─ */
function HomeInvoicesTab({ world, act, nav, openRequest }) {
  const state = world.invoice; // null | 'sent' | 'paid'
  const inv = INVOICES[0];
  const [rail, setRail] = React.useState(null);
  const [sheet, setSheet] = React.useState(false);
  const paid = state === 'paid';
  const paidRail = world.paidVia || 'zelle';
  const confirmPay = () => { setSheet(false); act.payInvoice(rail || 'zelle'); };
  return (
    <>
    <Screen padBottom={24} footer={<TabBar role="homeowner" active="h_inbox" go={nav} onFab={openRequest} />}>
      <TopBar title="Invoice inbox" subtitle={state ? `From ${inv.from}` : '88 Crestline Ave'} />

      {!state && (
        <div style={{ padding: '4px 18px 0' }}>
          <div className="card" style={{ padding: '22px 14px', textAlign: 'center' }}>
            <Dewy size={74} mood="zzz" />
            <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 15, marginTop: 6 }}>No open invoices.</div>
            <div style={{ fontSize: 12.5, color: 'var(--ink-500)', marginTop: 4, lineHeight: 1.5 }}>The moment Diego sends one, it lands here — same numbers as the PDF in your email.</div>
          </div>
        </div>
      )}

      {state && (
        <div style={{ padding: '4px 18px 0' }}>
          {world.nudged && !paid && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 9, background: 'var(--yellow-50)', border: '1px solid var(--yellow-100)', borderRadius: 'var(--radius-lg)', padding: '10px 13px', marginBottom: 10 }}>
              <Icon name="nudge" size={16} style={{ color: 'var(--yellow-700)', flexShrink: 0 }} />
              <span style={{ fontSize: 12.5, color: 'var(--ink-700)', lineHeight: 1.45 }}><b>Diego sent a friendly reminder</b> — this one's due May 26.</span>
            </div>
          )}
          <div className="card card-feature" style={{ padding: 0, overflow: 'hidden' }}>
            <div style={{ padding: '18px 18px 16px', background: paid ? 'var(--green-50)' : 'var(--yellow-50)', borderBottom: '1px solid var(--ink-100)' }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                  <PaperAvatar who="owner" size={38} />
                  <div>
                    <div style={{ fontWeight: 700, fontSize: 14.5 }}>{inv.biz}</div>
                    <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--ink-500)', letterSpacing: '.04em' }}>{inv.id} · DUE {inv.due.toUpperCase()}</div>
                  </div>
                </div>
                {paid ? <DmMark tone="green">PAID</DmMark> : <DmMark tone="yellow" pulse>{`DUE ${inv.due.toUpperCase()}`}</DmMark>}
              </div>
              <div style={{ marginTop: 14 }}>
                <div style={{ fontSize: 12.5, color: 'var(--ink-500)', fontWeight: 600 }}>{paid ? 'Paid in full' : 'Amount due'}</div>
                <Amount cents={inv.total} size={40} tone={paid ? 'paid' : 'plain'} />
              </div>
            </div>
            {/* lines — the same verified visits */}
            <div style={{ padding: '6px 16px 8px' }}>
              <div style={{ padding: '10px 0 8px', display: 'flex', alignItems: 'center', gap: 7 }}>
                <Icon name="shield" size={15} style={{ color: 'var(--blue-700)' }} />
                <span style={{ fontSize: 12, color: 'var(--ink-500)' }}>The same 4 verified visits from your feed</span>
              </div>
              {inv.lines.map((l, i) => (
                <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 11, padding: '11px 0', borderTop: '1px solid var(--ink-100)' }}>
                  <PhotoTile scene="pool-after" height={38} radius={10} style={{ width: 46, flexShrink: 0 }} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight: 700, fontSize: 14 }}>{l.label}</div>
                    <div style={{ fontSize: 11.5, color: 'var(--blue-700)', fontWeight: 600, display: 'flex', alignItems: 'center', gap: 4 }}><Icon name="shield" size={11} strokeWidth={2.4} />{l.date} · Verified</div>
                  </div>
                  <Amount cents={l.cents} size={14} />
                </div>
              ))}
            </div>
            {/* pay module — same three rails as the app */}
            {!paid ? (
              <div style={{ padding: '2px 16px 16px' }}>
                <div style={{ borderTop: '1px solid var(--ink-100)', paddingTop: 13, marginBottom: 12, display: 'flex', alignItems: 'center', gap: 7 }}>
                  <Icon name="wallet" size={16} style={{ color: 'var(--green-700)' }} />
                  <span style={{ fontSize: 13, color: 'var(--ink-900)', fontWeight: 700 }}>Pay Diego in one tap</span>
                </div>
                <div style={{ display: 'grid', gap: 10 }}>
                  {PROVIDER.rails.map(r => <RailPayButton key={r} rail={r} onClick={() => { setRail(r); setSheet(true); }} />)}
                </div>
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6, marginTop: 13, fontSize: 11.5, color: 'var(--ink-500)' }}><Icon name="shield" size={13} />Mowdew never touches your money.</div>
              </div>
            ) : (
              <div style={{ padding: '2px 16px 16px' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 11, background: 'var(--green-50)', border: '1px solid var(--green-100)', borderRadius: 14, padding: '13px 14px' }}>
                  <span style={{ width: 38, height: 38, borderRadius: 11, background: 'var(--green-700)', display: 'grid', placeItems: 'center', color: '#fff', flexShrink: 0 }}><Icon name="check" size={20} strokeWidth={2.6} /></span>
                  <div style={{ flex: 1 }}><div style={{ fontWeight: 700, fontSize: 14 }}>Paid via {RAIL[paidRail].label}</div><div style={{ fontSize: 12, color: 'var(--ink-500)' }}>Marked in your ledger — you won't pay this twice.</div></div>
                  <RailChip rail={paidRail} size={28} />
                </div>
              </div>
            )}
          </div>
          {!paid && (
            <div style={{ paddingTop: 14 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, background: 'var(--blue-50)', border: '1px solid var(--blue-100)', borderRadius: 'var(--radius-lg)', padding: '12px 14px' }}>
                <Icon name="ledger" size={20} style={{ color: 'var(--blue-700)', flexShrink: 0 }} />
                <div style={{ fontSize: 12.5, color: 'var(--ink-700)' }}>Pay once here and it's marked in your <b>ledger</b> — you'll never pay twice.</div>
              </div>
            </div>
          )}
        </div>
      )}
    </Screen>
    {/* slim confirm sheet — same as the app */}
    <Sheet open={sheet} onClose={() => setSheet(false)} title={`Pay with ${rail ? RAIL[rail].label : ''}`}>
      <div style={{ fontSize: 13.5, color: 'var(--ink-500)', marginBottom: 14, marginTop: -6 }}>Mowdew opens {rail ? RAIL[rail].label : 'the app'} with the amount and Diego prefilled — confirm there to finish.</div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '13px 15px', background: 'var(--paper)', borderRadius: 14, border: '1px solid var(--ink-100)', marginBottom: 14 }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 11 }}>
          <RailChip rail={rail || 'zelle'} size={38} />
          <span>
            <div style={{ fontWeight: 700, fontSize: 14.5 }}>{rail ? RAIL[rail].label : ''}</div>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--ink-500)' }}>{rail === 'venmo' ? PROVIDER.venmo : rail === 'paypal' ? 'pay.mowdew.co/diego' : PROVIDER.zelle}</div>
          </span>
        </span>
        <Amount cents={inv.total} size={20} />
      </div>
      <RailPayButton rail={rail || 'zelle'} height={56} size={21} onClick={confirmPay} />
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6, marginTop: 12, fontSize: 12, color: 'var(--ink-500)' }}><Icon name="shield" size={14} />Mowdew never touches your money.</div>
    </Sheet>
    </>
  );
}

/* ──────────── HOME · LEDGER (app HomeLedger statement clone) ────────── */
function HomeLedgerTab({ world, nav, openRequest }) {
  const mayPaid = world.invoice === 'paid';
  const rows = LEDGER.map(r => r.id === 'l1'
    ? (mayPaid ? { ...r, status: 'paid', rail: world.paidVia || 'zelle', paidOn: 'May 12' } : r)
    : r);
  const paidYTD = rows.filter(r => r.status === 'paid').reduce((s, r) => s + r.cents, 0);
  const due = rows.filter(r => r.status === 'unpaid').reduce((s, r) => s + r.cents, 0);
  const billed = paidYTD + due;
  const paidCount = rows.filter(r => r.status === 'paid').length;
  return (
    <Screen padBottom={24} footer={<TabBar role="homeowner" active="h_ledger" go={nav} onFab={openRequest} />}>
      {/* statement header — same as the app */}
      <div style={{ padding: '8px 18px 8px', display: 'flex', alignItems: 'center', gap: 12 }}>
        <span style={{ width: 38, height: 38, borderRadius: 11, background: 'var(--ink-900)', display: 'grid', placeItems: 'center', color: '#fff', flexShrink: 0 }}><Icon name="ledger" size={20} /></span>
        <div style={{ flex: 1 }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '.14em', color: 'var(--ink-500)' }}>PAYMENT STATEMENT</div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 21, letterSpacing: '-0.02em' }}>Your ledger</div>
        </div>
        <span style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 14.5, background: '#fff', border: '1px solid var(--ink-200)', borderRadius: 11, padding: '7px 13px' }}>2026</span>
      </div>

      {/* statement summary band — same dark artifact */}
      <div style={{ padding: '0 18px' }}>
        <div style={{ background: 'var(--ink-900)', borderRadius: 'var(--radius-2xl)', padding: '16px 18px 15px', color: '#fff' }}>
          <div style={{ display: 'flex', gap: 16 }}>
            <div style={{ flex: 1 }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '.1em', color: 'rgba(255,255,255,.6)' }}>CLEARED · 2026</div>
              <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 26, letterSpacing: '-0.03em', marginTop: 3 }}>{fmtMoney(paidYTD)}</div>
              <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,.6)', marginTop: 1 }}>{paidCount} months cleared</div>
            </div>
            <div onClick={() => due && nav('h_inbox')} style={{ flex: 1, paddingLeft: 16, borderLeft: '1px solid rgba(255,255,255,.16)', cursor: due ? 'pointer' : 'default' }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '.1em', color: due ? '#FF9E7D' : 'rgba(255,255,255,.6)' }}>STILL DUE</div>
              <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 26, letterSpacing: '-0.03em', marginTop: 3, color: due ? '#FFB59A' : '#fff' }}>{fmtMoney(due)}</div>
              <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,.6)', marginTop: 1 }}>{rows.length - paidCount} invoice{rows.length - paidCount === 1 ? '' : 's'} open</div>
            </div>
          </div>
          <div style={{ marginTop: 13 }}>
            <div style={{ height: 6, borderRadius: 99, background: 'rgba(255,255,255,.16)', overflow: 'hidden' }}>
              <span style={{ display: 'block', height: '100%', width: `${Math.round((paidYTD / billed) * 100)}%`, background: 'var(--green-500)' }} />
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 7, fontFamily: 'var(--font-mono)', fontSize: 9.5, letterSpacing: '.04em', color: 'rgba(255,255,255,.55)' }}>
              <span>{Math.round((paidYTD / billed) * 100)}% CLEARED</span><span>BILLED {fmtMoney(billed)}</span>
            </div>
          </div>
        </div>
      </div>

      {/* ledger entries — same row anatomy as the app */}
      <div style={{ padding: '14px 18px 0', display: 'grid', gap: 9 }}>
        {rows.map(r => {
          const unpaid = r.status === 'unpaid';
          const [mo, yr] = r.month.split(' ');
          return (
            <div key={r.id} onClick={() => unpaid && nav('h_inbox')} className="card" style={{ padding: '12px 13px', cursor: unpaid ? 'pointer' : 'default', display: 'flex', alignItems: 'center', gap: 12 }}>
              <div style={{ width: 42, textAlign: 'center', flexShrink: 0 }}>
                <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 15, letterSpacing: '-0.02em', lineHeight: 1, color: 'var(--ink-900)' }}>{mo.slice(0, 3)}</div>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9.5, color: 'var(--ink-400,#A8A498)', marginTop: 2 }}>{yr}</div>
              </div>
              <span style={{ width: 1, alignSelf: 'stretch', background: 'var(--ink-100)' }} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontWeight: 700, fontSize: 14 }}>{r.visits} visits</span>
                  {unpaid ? <DmMark tone="alert">DUE</DmMark> : <DmMark tone="green">CLEARED</DmMark>}
                </div>
                <div style={{ fontSize: 12, color: 'var(--ink-500)', display: 'flex', alignItems: 'center', gap: 5, marginTop: 3 }}>
                  {unpaid
                    ? <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11 }}>{r.invoice}</span>
                    : <><RailChip rail={r.rail} size={15} /><span>Paid {r.paidOn} · {RAIL[r.rail].label}</span></>}
                </div>
              </div>
              <Amount cents={r.cents} size={15} tone={unpaid ? 'due' : 'plain'} />
            </div>
          );
        })}
        {world.invoice === null && (
          <div style={{ fontSize: 11.5, color: 'var(--ink-500)', padding: '4px 2px 0', lineHeight: 1.5 }}>May's invoice arrives here when Diego sends it — built from the same verified visits.</div>
        )}
      </div>
    </Screen>
  );
}

Object.assign(window, { OwnerMoneyTab, HomeFeedTab, HomePoolTab, HomeInvoicesTab, HomeLedgerTab });
