/* ============================================================
   MUIY — Monitoring screen (rebuilt)
   Scan-first Tests view + date-centric Visits view.
   · collapsed Smart Insights  · search + simplified filters
   · simplified cards + 3 layout directions (Triage/Cards/Status)
   Detail sheet lives in monitoring-detail.jsx; Visits + scanner
   in monitoring-visits.jsx.
   ============================================================ */

/* ---- shared status helpers (used across monitoring files) ---- */
const monStatusChip = (st) => {
  const m = MON.STATUS_META[st.status] || MON.STATUS_META.OPTIONAL;
  return (
    <span className="chip-status" style={{ background: m.wash, color: m.color, flex: 'none' }}>
      <span style={{ width: 7, height: 7, borderRadius: 999, background: m.color }} />{m.label}
    </span>
  );
};
const monDueText = (st) => {
  if (st.status === 'OPTIONAL') return 'Optional';
  if (st.never) return 'None yet';
  if (st.daysUntil < 0) return `${Math.abs(st.daysUntil)}d overdue`;
  if (st.daysUntil === 0) return 'Due today';
  if (st.daysUntil <= 60) return `Due in ${st.daysUntil}d`;
  return `Due ${TC.fmtDate(st.nextDue, { day: 'numeric', month: 'short' })}`;
};

/* ---- scroll a card comfortably into view, only when it isn't already ---- */
function monSmoothScrollTo(sc, to, dur) {
  const start = sc.scrollTop;
  const delta = to - start;
  if (Math.abs(delta) < 2) return;
  const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  if (reduce || dur <= 0) { sc.scrollTop = to; return; }
  const t0 = performance.now();
  const ease = (p) => (p < 0.5 ? 2 * p * p : 1 - Math.pow(-2 * p + 2, 2) / 2); // easeInOutQuad
  sc._monScroll = (sc._monScroll || 0) + 1;
  const token = sc._monScroll;
  const step = (now) => {
    if (sc._monScroll !== token) return; // superseded by a newer scroll
    const p = Math.min(1, (now - t0) / dur);
    sc.scrollTop = start + delta * ease(p);
    if (p < 1) requestAnimationFrame(step);
  };
  requestAnimationFrame(step);
}

function monScrollIntoView(el) {
  if (!el) return;
  const sc = el.closest('.tc-scroll');
  if (!sc) return;
  const scRect = sc.getBoundingClientRect();
  const elRect = el.getBoundingClientRect();
  // the phone mock is CSS-scaled: getBoundingClientRect returns scaled screen
  // pixels, but scrollTop is in unscaled content pixels — convert between them.
  const scale = sc.offsetHeight ? scRect.height / sc.offsetHeight : 1;
  const topPad = 56;       // comfortable offset below the top edge (screen px)
  const bottomPad = 104;   // keep clear of the floating bottom nav (screen px)
  const above = elRect.top < scRect.top + topPad;
  const below = elRect.bottom > scRect.bottom - bottomPad;
  if (!above && !below) return; // already fully, comfortably visible
  // expand-and-focus: bring the card's TOP to a comfortable position so the
  // header + revealed detail flow downward predictably (clamped by the scroller).
  const deltaScreen = elRect.top - scRect.top - topPad;
  monSmoothScrollTo(sc, sc.scrollTop + deltaScreen / (scale || 1), 460);
}

/* ---- inline expand panel (CSS grid-rows accordion) ---- */
function MonExpandPanel({ open, children }) {
  return (
    <div className={'mon-acc' + (open ? ' open' : '')} aria-hidden={!open}>
      <div>{open ? children : null}</div>
    </div>
  );
}

/* ---- insight card ---- */
function MonInsightCard({ ins, onOpen }) {
  const m = MON.SEV_META[ins.sev] || MON.SEV_META.soft;
  // calibrated "should I worry" cue, shared with the detail view (not AI)
  const w = window.RESULTMEANING ? RESULTMEANING.severityWorry(ins.sev) : null;
  return (
    <button className="card" onClick={onOpen}
      style={{ display: 'block', width: '100%', textAlign: 'left', cursor: 'pointer', fontFamily: 'inherit', padding: 0, overflow: 'hidden', border: `1.5px solid ${m.color}`, borderLeft: `5px solid ${m.color}`, marginBottom: 12 }}>
      <div style={{ padding: '13px 15px' }}>
        <div className="row" style={{ gap: 11, alignItems: 'flex-start' }}>
          <div className="leaf" style={{ width: 34, height: 34, flex: 'none', background: m.wash, color: m.color, borderRadius: 11 }}><Icon name={m.icon} size={17} color={m.color} /></div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontWeight: 800, fontSize: 14.5, color: m.color, letterSpacing: '-.01em' }}>{ins.title}</div>
            <div className="body" style={{ fontSize: 12.8, color: 'var(--ink)', lineHeight: 1.5, marginTop: 3 }}>{ins.body}</div>
            {w && ins.kind !== 'overdue' &&
            <div className="row" style={{ gap: 6, marginTop: 9 }}>
              <span style={{ width: 8, height: 8, borderRadius: 999, background: w.dot, flex: 'none' }} />
              <span style={{ fontWeight: 800, fontSize: 11.5, color: w.color }}>{w.label}</span>
              <span className="row" style={{ gap: 2, marginLeft: 'auto', color: 'var(--ink-3)', fontWeight: 700, fontSize: 11 }}>What this means<Icon name="chevR" size={12} color="var(--ink-3)" /></span>
            </div>
            }
          </div>
          {(!w || ins.kind === 'overdue') && <Icon name="chevR" size={16} color="var(--ink-3)" style={{ flex: 'none', marginTop: 8 }} />}
        </div>
      </div>
    </button>
  );
}

/* ---- triage insights into meaningful tiers, not one big count ---- */
function monBucketInsights(insights) {
  const attention = [], review = [], routine = [];
  insights.forEach((i) => {
    if (i.sev === 'danger' || i.sev === 'warn') attention.push(i);
    else if (i.kind === 'overdue') routine.push(i);
    else review.push(i);
  });
  return { attention, review, routine };
}
const MON_TIERS = {
  attention: { label: 'Need attention', short: 'attention', color: 'var(--danger)', wash: 'var(--danger-wash)' },
  review:    { label: 'Worth reviewing', short: 'reviewing', color: 'var(--warning)', wash: 'var(--warning-wash)' },
  routine:   { label: 'Routine catch-ups', short: 'catch-ups', color: 'var(--ink-3)', wash: 'var(--surface-2)' },
};
function monTestName(tests, id) { const t = tests.find((x) => x.id === id); return t ? t.name : 'this test'; }

/* synthesize one plain-language status line from the buckets */
function monSummaryLine(b) {
  const a = b.attention.length, r = b.review.length, q = b.routine.length;
  if (a) return `${a} result${a === 1 ? '' : 's'} ${a === 1 ? 'needs' : 'need'} a look with your care team`;
  if (r) return `${r} value${r === 1 ? ' is' : 's are'} worth reviewing — nothing urgent`;
  if (q) return `You're on top of your results — ${q} routine test${q === 1 ? ' is' : 's are'} due for a refresh`;
  return "Everything's on track — no action needed";
}

/* ---- Smart summary: synthesized status, not a list ---- */
function MonInsightsBar({ insights, expanded, onToggle, onOpenAll, openTest, tests }) {
  if (!insights.length) return null;
  const b = monBucketInsights(insights);
  const { attention, review, routine } = b;
  const signal = attention.concat(review);          // the only things that become cards
  const leadKey = attention.length ? 'attention' : review.length ? 'review' : 'routine';
  const lead = MON_TIERS[leadKey];
  const openFor = (ins) => { const t = tests.find((x) => x.id === ins.testId); if (t) openTest(t); };

  return (
    <div style={{ marginBottom: 14 }}>
      <button className="card" onClick={onToggle} style={{ display: 'block', width: '100%', textAlign: 'left', cursor: 'pointer', border: 'none', fontFamily: 'inherit', padding: '13px 14px' }}>
        <div className="row" style={{ gap: 11, alignItems: 'flex-start' }}>
          <div className="leaf" style={{ width: 36, height: 36, flex: 'none', background: lead.wash, color: lead.color, borderRadius: 11 }}><Icon name="clipboard" size={17} color={lead.color} /></div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="dmeta" style={{ fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--ink-3)', fontSize: 10 }}>Worth a look</div>
            <div style={{ fontWeight: 800, fontSize: 14.5, lineHeight: 1.32, color: lead.color, marginTop: 2, textWrap: 'pretty' }}>{monSummaryLine(b)}</div>
          </div>
          <Icon name="chevD" size={16} color="var(--ink-3)" style={{ flex: 'none', marginTop: 2, transition: '.18s', transform: expanded ? 'rotate(180deg)' : 'none' }} />
        </div>
        {!expanded && (signal.length > 0 || routine.length > 0) && (
          <div className="dmeta muted" style={{ marginTop: 8, paddingLeft: 47 }}>
            {signal.length > 0 && `${signal.length} to review`}
            {signal.length > 0 && routine.length > 0 && ' · '}
            {routine.length > 0 && `${routine.length} routine due`}
            {' · tap for detail'}
          </div>
        )}
      </button>

      {expanded && (
        <div style={{ marginTop: 10, display: 'flex', flexDirection: 'column', gap: 4 }}>
          {attention.length > 0 && (
            <React.Fragment>
              <div className="dmeta" style={{ fontWeight: 800, letterSpacing: '.03em', textTransform: 'uppercase', color: 'var(--ink-3)', fontSize: 10.5, margin: '4px 2px 2px' }}>Worth acting on</div>
              {attention.slice(0, 4).map((ins) => <MonInsightCard key={ins.id} ins={ins} onOpen={() => openFor(ins)} />)}
            </React.Fragment>
          )}
          {review.length > 0 && (
            <React.Fragment>
              <div className="dmeta" style={{ fontWeight: 800, letterSpacing: '.03em', textTransform: 'uppercase', color: 'var(--ink-3)', fontSize: 10.5, margin: '8px 2px 2px' }}>Worth reviewing</div>
              {review.slice(0, 3).map((ins) => <MonInsightCard key={ins.id} ins={ins} onOpen={() => openFor(ins)} />)}
            </React.Fragment>
          )}
          {routine.length > 0 && (
            <button className="card" onClick={onOpenAll} style={{ display: 'block', width: '100%', textAlign: 'left', cursor: 'pointer', fontFamily: 'inherit', border: 'none', padding: '12px 14px', marginTop: 4 }}>
              <div className="row" style={{ gap: 11 }}>
                <div className="leaf" style={{ width: 34, height: 34, flex: 'none', background: 'var(--surface-2)', color: 'var(--ink-3)', borderRadius: 11 }}><Icon name="calendar" size={16} color="var(--ink-3)" /></div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 800, fontSize: 13.5 }}>{routine.length} routine test{routine.length === 1 ? '' : 's'} due for a refresh</div>
                  <div className="dmeta muted">None out of range — just on a schedule</div>
                </div>
                <span className="row" style={{ gap: 3, color: 'var(--orange)', fontWeight: 800, fontSize: 12, flex: 'none' }}>Checklist<Icon name="chevR" size={14} color="var(--orange)" /></span>
              </div>
            </button>
          )}
        </div>
      )}
    </div>
  );
}

function MonAllInsightsSheet({ store, close, insights, tests, openTest }) {
  const { attention, review, routine } = monBucketInsights(insights);
  const openFor = (ins) => { const t = tests.find((x) => x.id === ins.testId); if (t) { close(); openTest(t); } };
  const section = (label, list) => list.length > 0 && (
    <React.Fragment>
      <div className="dmeta" style={{ fontWeight: 800, letterSpacing: '.03em', textTransform: 'uppercase', color: 'var(--ink-3)', fontSize: 10.5, margin: '10px 2px 4px' }}>{label} · {list.length}</div>
      {list.map((ins) => <MonInsightCard key={ins.id} ins={ins} onOpen={() => openFor(ins)} />)}
    </React.Fragment>
  );
  return (
    <MSheet title="Results worth a look" onClose={close}>
      <div style={{ display: 'flex', flexDirection: 'column' }}>
        {section('Need attention', attention)}
        {section('Worth reviewing', review)}
        {section('Routine catch-ups', routine)}
        {!insights.length && <div className="body" style={{ padding: '10px 0' }}>No insights right now — nice work.</div>}
      </div>
    </MSheet>
  );
}

/* ---- compact header: profile + coverage ring + timeline ---- */
function MonHeader({ profile, isDemo, cov, onTimeline, onEdit }) {
  const ag = MON.ageGroup(profile.age);
  const R = 22, C = 2 * Math.PI * R, dash = C * (cov.pct / 100);
  return (
    <div className="card" style={{ padding: 14, marginBottom: 14, border: isDemo ? '1.5px solid var(--sky-deep)' : undefined }}>
      <div className="between" style={{ gap: 12 }}>
        <div className="row" style={{ gap: 11, minWidth: 0 }}>
          <Avatar name={profile.label} size={42} />
          <div style={{ minWidth: 0 }}>
            <div className="row" style={{ gap: 7 }}>
              <span className="dname" style={{ fontSize: 15 }}>{isDemo ? profile.label.split(' · ')[0] : profile.label}</span>
              {isDemo && <span className="chip-status" style={{ background: 'var(--slate-wash)', color: 'var(--sky-deep)' }}>Demo</span>}
            </div>
            <div className="dmeta muted">{profile.age} yrs · {ag.label} · {profile.thalType}</div>
          </div>
        </div>
        <div style={{ position: 'relative', width: 52, height: 52, flex: 'none' }}>
          <svg width="52" height="52" viewBox="0 0 52 52" style={{ transform: 'rotate(-90deg)' }}>
            <circle cx="26" cy="26" r={R} fill="none" stroke="var(--hairline)" strokeWidth="5.5" />
            <circle cx="26" cy="26" r={R} fill="none" stroke="var(--success)" strokeWidth="5.5" strokeLinecap="round" strokeDasharray={`${dash} ${C}`} />
          </svg>
          <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center' }}><span className="num" style={{ fontWeight: 800, fontSize: 13 }}>{cov.pct}%</span></div>
        </div>
      </div>
      <div className="row" style={{ gap: 14, marginTop: 12, flexWrap: 'wrap' }}>
        <span className="row" style={{ gap: 5 }}><span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--success)' }} /><b style={{ fontSize: 12.5 }}>{cov.completed}</b><span className="body" style={{ fontSize: 11 }}>up to date</span></span>
        <span className="row" style={{ gap: 5 }}><span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--warning)' }} /><b style={{ fontSize: 12.5 }}>{cov.due}</b><span className="body" style={{ fontSize: 11 }}>due soon</span></span>
        <span className="row" style={{ gap: 5 }}><span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--danger)' }} /><b style={{ fontSize: 12.5 }}>{cov.overdue}</b><span className="body" style={{ fontSize: 11 }}>overdue</span></span>
        {cov.never > 0 && <span className="row" style={{ gap: 5 }}><span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--ink-3)' }} /><b style={{ fontSize: 12.5 }}>{cov.never}</b><span className="body" style={{ fontSize: 11 }}>not started</span></span>}
      </div>
      <div className="row" style={{ gap: 7, marginTop: 11 }}>
        <button className="chip" onClick={onTimeline} style={{ background: 'var(--slate-wash)', borderColor: 'transparent', color: 'var(--sky-deep)', fontWeight: 800, fontSize: 12, padding: '6px 12px' }}><Icon name="calendar" size={13} color="var(--sky-deep)" />General timeline</button>
        {!isDemo && <button className="chip" onClick={onEdit} style={{ background: 'var(--surface-2)', borderColor: 'var(--hairline-2)', color: 'var(--ink-2)', fontWeight: 700, fontSize: 12, padding: '6px 12px' }}><Icon name="edit" size={13} color="var(--ink-2)" />Edit profile</button>}
      </div>
    </div>
  );
}

/* ---- simplified test card (Cards layout) ---- */
function MonTestCard({ test, profile, logs, store, expanded, startAdd, registerCard, onOpen, onAdd }) {
  const [info, setInfo] = React.useState(false);
  const cat = MON.catMeta(test.category);
  const st = MON.statusOf(test, profile, logs);
  const last = st.last;
  const flag = last && test.normal_range ? MON.valueFlag(test, last.value, profile) : null;
  const abn = flag && flag.dir !== 'normal';
  return (
    <div className={'card mon-card' + (expanded ? ' expanded' : '')} ref={(el) => registerCard && registerCard(test.id, el)} style={{ padding: 13, marginBottom: 12 }}>
      <div onClick={onOpen} style={{ cursor: 'pointer' }}>
        <div className="row" style={{ gap: 10, alignItems: 'center' }}>
          <div className="leaf" style={{ width: 34, height: 34, flex: 'none', background: cat.wash, color: cat.color, borderRadius: 11 }}><Icon name={cat.icon} size={16} color={cat.color} fill={cat.icon === 'sparkle' || cat.icon === 'drop' ? cat.color : 'none'} /></div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="dname" style={{ fontSize: 14, lineHeight: 1.2 }}>{test.name}</div>
            <div className="dmeta muted" style={{ marginTop: 2 }}>
              {last
                ? <span><b style={{ color: abn ? flag.color : 'var(--ink-2)', fontWeight: 800 }}>{last.value}{test.unit ? ' ' + test.unit : ''}</b> · {TC.fmtDate(last.date, { day: 'numeric', month: 'short', year: 'numeric' })}</span>
                : 'No result yet'}
            </div>
          </div>
          {monStatusChip(st)}
          <Icon name="chevD" size={16} color="var(--ink-3)" style={{ flex: 'none', transition: 'transform .2s', transform: expanded ? 'rotate(180deg)' : 'none' }} />
        </div>
      </div>
      {!expanded && (
        <div className="row" style={{ gap: 8, marginTop: 10, justifyContent: 'space-between' }}>
          <button className="chip" onClick={() => setInfo((v) => !v)} style={{ background: info ? 'var(--slate-wash)' : 'var(--surface-2)', borderColor: 'var(--hairline-2)', color: info ? 'var(--sky-deep)' : 'var(--ink-2)', fontWeight: 700, fontSize: 11.5, padding: '5px 10px' }}><Icon name="info" size={13} color={info ? 'var(--sky-deep)' : 'var(--ink-3)'} />What is this?</button>
          <button className="chip" onClick={onAdd} style={{ background: 'var(--orange-wash)', borderColor: 'transparent', color: 'var(--orange)', fontWeight: 800, fontSize: 11.5, padding: '5px 11px' }}><Icon name="plus" size={13} color="var(--orange)" sw={2.4} />Add result</button>
        </div>
      )}
      {!expanded && info && <div className="card-flat" style={{ padding: '10px 12px', marginTop: 9 }}><span className="body" style={{ fontSize: 12.3, lineHeight: 1.5 }}>{MON.plainOf(test)}</span></div>}
      <MonExpandPanel open={expanded}>
        <div style={{ paddingTop: 4 }}><MonTestDetailBody hideHeader store={store} test={test} profile={profile} startAdd={startAdd} /></div>
      </MonExpandPanel>
    </div>
  );
}

/* ---- dense single-line row (Triage + Status layouts) ---- */
function MonTestRow({ test, profile, logs, store, expanded, startAdd, registerCard, onOpen, onAdd }) {
  const cat = MON.catMeta(test.category);
  const st = MON.statusOf(test, profile, logs);
  const last = st.last;
  const flag = last && test.normal_range ? MON.valueFlag(test, last.value, profile) : null;
  const abn = flag && flag.dir !== 'normal';
  const dot = (MON.STATUS_META[st.status] || MON.STATUS_META.OPTIONAL).color;
  return (
    <div className={'mon-rowwrap' + (expanded ? ' expanded' : '')} ref={(el) => registerCard && registerCard(test.id, el)}>
      <div className="drow" style={{ padding: '11px 0', cursor: 'pointer', gap: 10 }} onClick={onOpen}>
        <div className="leaf" style={{ width: 32, height: 32, flex: 'none', background: cat.wash, color: cat.color, borderRadius: 10 }}><Icon name={cat.icon} size={15} color={cat.color} fill={cat.icon === 'sparkle' || cat.icon === 'drop' ? cat.color : 'none'} /></div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="dname" style={{ fontSize: 13.8 }}>{test.name}</div>
          <div className="dmeta muted">{last ? monDueText(st) : MON.freqLabel(st.freq)}</div>
        </div>
        <div style={{ textAlign: 'right', flex: 'none', minWidth: 52 }}>
          {last ? (
            <React.Fragment>
              <div className="row" style={{ gap: 4, alignItems: 'baseline', justifyContent: 'flex-end' }}>
                <span className="num" style={{ fontSize: 14.5, fontWeight: 800, color: abn ? flag.color : 'var(--ink)' }}>{last.value}</span>
                {test.unit && <span className="body" style={{ fontSize: 10 }}>{test.unit}</span>}
              </div>
              <div className="dmeta muted">{TC.fmtDate(last.date, { day: 'numeric', month: 'short' })}</div>
            </React.Fragment>
          ) : (
            <button className="chip" onClick={(e) => { e.stopPropagation(); onAdd(); }} style={{ background: 'var(--orange-wash)', borderColor: 'transparent', color: 'var(--orange)', fontWeight: 800, fontSize: 11, padding: '4px 9px' }}>+ Add</button>
          )}
        </div>
        <span style={{ width: 9, height: 9, borderRadius: 999, flex: 'none', background: dot }} />
        <Icon name="chevD" size={15} color="var(--ink-3)" style={{ flex: 'none', transition: 'transform .2s', transform: expanded ? 'rotate(180deg)' : 'none' }} />
      </div>
      <MonExpandPanel open={expanded}>
        <div style={{ padding: '2px 0 12px' }}><MonTestDetailBody hideHeader store={store} test={test} profile={profile} startAdd={startAdd} /></div>
      </MonExpandPanel>
    </div>
  );
}

/* ---- layout A · Triage (status-grouped, answers the 3 questions) ---- */
function MonTriageList({ tests, profile, logs, store, expandedId, startAddId, registerCard, openTest, addTest }) {
  const [showOk, setShowOk] = React.useState(false);
  const byStatus = { OVERDUE: [], DUESOON: [], COMPLETED: [], OPTIONAL: [] };
  tests.forEach((t) => { const s = MON.statusOf(t, profile, logs).status; (byStatus[s] || byStatus.OPTIONAL).push(t); });
  const rowProps = (t) => ({ test: t, profile, logs, store, expanded: expandedId === t.id, startAdd: startAddId === t.id, registerCard, onOpen: () => openTest(t), onAdd: () => addTest(t) });
  const Section = ({ title, items, color }) => items.length ? (
    <div style={{ marginBottom: 18 }}>
      <div className="between" style={{ marginBottom: 8 }}><span className="sec-title" style={{ color }}><span style={{ width: 9, height: 9, borderRadius: 999, background: color }} />{title}</span><span className="dmeta muted">{items.length}</span></div>
      <div className="card" style={{ padding: '2px 14px' }}>{items.map((t) => <MonTestRow key={t.id} {...rowProps(t)} />)}</div>
    </div>
  ) : null;
  const okItems = [...byStatus.COMPLETED, ...byStatus.OPTIONAL];
  // auto-reveal the "Up to date" section if the expanded test lives inside it
  const okHasExpanded = expandedId && okItems.some((t) => t.id === expandedId);
  React.useEffect(() => { if (okHasExpanded) setShowOk(true); }, [okHasExpanded]);
  const okOpen = showOk || okHasExpanded;
  return (
    <div>
      <Section title="Overdue" items={byStatus.OVERDUE} color="var(--danger)" />
      <Section title="Due soon" items={byStatus.DUESOON} color="var(--warning)" />
      {okItems.length > 0 && (
        <div style={{ marginBottom: 18 }}>
          <button className="between" onClick={() => setShowOk((v) => !v)} style={{ width: '100%', border: 'none', background: 'none', cursor: 'pointer', fontFamily: 'inherit', marginBottom: 8, padding: 0 }}>
            <span className="sec-title" style={{ color: 'var(--success)' }}><span style={{ width: 9, height: 9, borderRadius: 999, background: 'var(--success)' }} />Up to date</span>
            <span className="row" style={{ gap: 6 }}><span className="dmeta muted">{okItems.length}</span><Icon name="chevD" size={15} color="var(--ink-3)" style={{ transform: okOpen ? 'rotate(180deg)' : 'none' }} /></span>
          </button>
          {okOpen && <div className="card" style={{ padding: '2px 14px' }}>{okItems.map((t) => <MonTestRow key={t.id} {...rowProps(t)} />)}</div>}
        </div>
      )}
    </div>
  );
}

/* ---- layout B · Category cards ---- */
function MonCardsList({ tests, profile, logs, store, expandedId, startAddId, registerCard, openTest, addTest }) {
  const groups = MON.FILTER_GROUPS.map((g) => ({ g, items: tests.filter((t) => g.cats.indexOf(t.category) !== -1) })).filter((x) => x.items.length);
  return (
    <div>
      {groups.map(({ g, items }) => (
        <div key={g.key} style={{ marginBottom: 18 }}>
          <div className="between" style={{ marginBottom: 9 }}>
            <span className="sec-title" style={{ color: g.color }}><span style={{ width: 9, height: 9, borderRadius: 3, background: g.color }} />{g.label}</span>
            <span className="dmeta muted">{items.length}</span>
          </div>
          {items.map((t) => <MonTestCard key={t.id} test={t} profile={profile} logs={logs} store={store} expanded={expandedId === t.id} startAdd={startAddId === t.id} registerCard={registerCard} onOpen={() => openTest(t)} onAdd={() => addTest(t)} />)}
        </div>
      ))}
    </div>
  );
}

/* ---- layout C · Status (flat, urgency-sorted rows) ---- */
function MonStatusList({ tests, profile, logs, store, expandedId, startAddId, registerCard, openTest, addTest }) {
  const rank = { OVERDUE: 0, DUESOON: 1, COMPLETED: 2, OPTIONAL: 3 };
  const sorted = [...tests].sort((a, b) => (rank[MON.statusOf(a, profile, logs).status] ?? 9) - (rank[MON.statusOf(b, profile, logs).status] ?? 9));
  return <div className="card" style={{ padding: '2px 14px' }}>{sorted.map((t) => <MonTestRow key={t.id} test={t} profile={profile} logs={logs} store={store} expanded={expandedId === t.id} startAdd={startAddId === t.id} registerCard={registerCard} onOpen={() => openTest(t)} onAdd={() => addTest(t)} />)}</div>;
}

/* ---- Tests view: search + filters + layout switch ---- */
function MonTestsView({ store, profile, logs, layout, expandedId, startAddId, focusReq, onExpand, registerCard }) {
  const [query, setQuery] = React.useState('');
  const [filter, setFilter] = React.useState('all');
  const tests = MON.applicableTests(profile);
  const cov = MON.coverage(profile, logs);

  // expand-and-focus: open the card, then bring it comfortably into view + flash
  const openTest = (t, startAdd) => {
    if (!t) return;
    if (expandedId === t.id && !startAdd) { onExpand(null); return; } // toggle closed
    onExpand(t.id, !!startAdd);
  };
  const addTest = (t) => openTest(t, true);

  // when expandedId / focusReq changes, scroll the registered card into view
  React.useEffect(() => {
    if (!expandedId) return;
    const el = registerCard.get(expandedId);
    if (!el) return;
    // flash immediately so the selection is obvious
    const raf = requestAnimationFrame(() => {
      el.classList.remove('mon-flash');
      void el.offsetWidth; // restart the animation
      el.classList.add('mon-flash');
    });
    // scroll once the accordion has opened, so we target the full expanded height
    const t1 = setTimeout(() => monScrollIntoView(el), 300);
    const t2 = setTimeout(() => el.classList.remove('mon-flash'), 2500);
    return () => { cancelAnimationFrame(raf); clearTimeout(t1); clearTimeout(t2); };
  }, [expandedId, focusReq]);

  const matchFilter = (t) => {
    if (filter === 'all') return true;
    const s = MON.statusOf(t, profile, logs).status;
    if (filter === 'due') return s === 'DUESOON' || s === 'OVERDUE';
    if (filter === 'overdue') return s === 'OVERDUE';
    if (filter === 'completed') return s === 'COMPLETED';
    const grp = MON.groupMeta(filter);
    return grp ? grp.cats.indexOf(t.category) !== -1 : true;
  };
  const shown = tests.filter((t) => MON.searchTest(t, query) && matchFilter(t));

  const FILTERS = [
    { k: 'all', label: 'All', n: tests.length },
    { k: 'overdue', label: 'Overdue', n: cov.overdue },
    { k: 'due', label: 'Due', n: cov.due + cov.overdue },
    { k: 'completed', label: 'Completed', n: cov.completed },
  ];
  const groupsPresent = MON.FILTER_GROUPS.filter((g) => tests.some((t) => g.cats.indexOf(t.category) !== -1));
  const listProps = { tests: shown, profile, logs, store, expandedId, startAddId, registerCard, openTest, addTest };

  return (
    <div>
      <div className="card-flat row" style={{ gap: 9, padding: '10px 13px', marginBottom: 14 }}>
        <Icon name="search" size={17} color="var(--ink-3)" />
        <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search tests, categories…" style={{ flex: 1, minWidth: 0, border: 'none', background: 'none', outline: 'none', fontFamily: 'inherit', fontSize: 14, color: 'var(--ink)' }} />
        {query && <button className="icon-btn" style={{ width: 26, height: 26, flex: 'none', background: 'var(--surface-2)' }} onClick={() => setQuery('')} aria-label="Clear"><Icon name="x" size={13} /></button>}
      </div>

      <div className="row" style={{ gap: 8, marginBottom: 14, overflowX: 'auto', scrollbarWidth: 'none', paddingBottom: 2 }}>
        {FILTERS.map((ff) => (
          <button key={ff.k} className={'chip' + (filter === ff.k ? ' on' : '')} onClick={() => setFilter(ff.k)} style={{ flex: 'none', whiteSpace: 'nowrap' }}>
            {ff.label}{ff.n != null && <span style={{ opacity: .65, fontWeight: 800 }}>{ff.n}</span>}
          </button>
        ))}
        <span style={{ width: 1, background: 'var(--hairline-2)', flex: 'none', margin: '4px 2px' }} />
        {groupsPresent.map((g) => (
          <button key={g.key} className={'chip' + (filter === g.key ? ' on' : '')} onClick={() => setFilter(g.key)} style={{ flex: 'none', whiteSpace: 'nowrap' }}>{g.label}</button>
        ))}
      </div>

      {shown.length === 0
        ? <div className="card"><div className="body" style={{ padding: '8px 0' }}>No tests match this search or filter.</div></div>
        : layout === 'Status' ? <MonStatusList {...listProps} />
        : <MonTriageList {...listProps} />}
    </div>
  );
}

/* ---- monitoring-profile editor (writes to patient.monitoring) ---- */
function MonProfileSheet({ store, close }) {
  const mp = (store.patient.monitoring) || {};
  const age = MON.ageFromDob(store.patient.dob, mp.age);
  const [f, setF] = React.useState({
    sex: mp.sex || 'male',
    thalType: mp.thalType || 'TDT',
    puberty: mp.puberty != null ? mp.puberty : age >= 11,
    splenectomy: !!mp.splenectomy,
  });
  const set = (k, v) => setF((s) => ({ ...s, [k]: v }));
  const save = () => {
    store.mutate((d) => { d.patient.monitoring = Object.assign({}, d.patient.monitoring, f); });
    store.showToast('Monitoring profile updated', '🌱'); close();
  };
  const Row = ({ label, sub, children }) => (
    <div className="between" style={{ padding: '13px 0', borderTop: '1px solid var(--hairline)', gap: 12 }}>
      <div style={{ minWidth: 0 }}><div style={{ fontWeight: 800, fontSize: 14 }}>{label}</div>{sub && <div className="body" style={{ fontSize: 12 }}>{sub}</div>}</div>
      {children}
    </div>
  );
  return (
    <MSheet title="My monitoring profile" sub="These attributes personalise which tests apply to you and how often." onClose={close}>
      <div className="field" style={{ marginTop: 6 }}><label className="field-label">Thalassaemia type</label>
        <Segmented value={f.thalType} onChange={(v) => set('thalType', v)} options={[{ value: 'TDT', label: 'TDT' }, { value: 'NTDT', label: 'NTDT' }]} />
        <div className="body" style={{ fontSize: 11.5, marginTop: 6 }}>{f.thalType === 'TDT' ? 'Transfusion-dependent — more frequent iron & blood monitoring.' : 'Non-transfusion-dependent — less frequent, different imaging schedule.'}</div>
      </div>
      <div className="field"><label className="field-label">Sex</label>
        <Segmented value={f.sex} onChange={(v) => set('sex', v)} options={[{ value: 'male', label: 'Male' }, { value: 'female', label: 'Female' }]} />
      </div>
      <div className="card-flat" style={{ padding: '2px 14px', marginTop: 4 }}>
        <Row label="Reached puberty" sub="Unlocks gonadal / hormone tests"><Switch on={f.puberty} onChange={(v) => set('puberty', v)} /></Row>
        <Row label="Splenectomized" sub="Adds platelet & PHT monitoring"><Switch on={f.splenectomy} onChange={(v) => set('splenectomy', v)} /></Row>
      </div>
      <div className="card-flat row" style={{ padding: '11px 14px', marginTop: 12, gap: 10 }}>
        <Icon name="info" size={15} color="var(--sky-deep)" style={{ flex: 'none' }} />
        <span className="body" style={{ fontSize: 12 }}>Age ({age} yrs · {MON.ageGroup(age).label}) is taken from your date of birth in your profile.</span>
      </div>
      <div className="row" style={{ gap: 10, marginTop: 16 }}>
        <button className="btn btn-ghost" style={{ flex: 1 }} onClick={close}>Cancel</button>
        <button className="btn btn-primary" style={{ flex: 1.4 }} onClick={save}>Save</button>
      </div>
    </MSheet>
  );
}

/* ---- demo profile switcher ---- */
function MonSwitchSheet({ store, close, current, onPick }) {
  return (
    <MSheet title="View as…" sub="Switch profile to see how the engine adapts the schedule. (Demo only — does not change your data.)" onClose={close}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 9 }}>
        <button className="qa-item" onClick={() => { onPick(null); close(); }}>
          <div className="qa-ic" style={{ background: 'var(--orange-wash)', color: 'var(--orange)' }}><Icon name="user" size={20} color="var(--orange)" /></div>
          <div style={{ flex: 1, textAlign: 'left' }}><div style={{ fontWeight: 800, fontSize: 14.5 }}>My profile</div><div className="body" style={{ fontSize: 12 }}>{store.patient.name}</div></div>
          {!current && <Icon name="check" size={18} color="var(--orange)" sw={2.6} />}
        </button>
        {MON.DEMO_PROFILES.map((p) => {
          const on = current && current.key === p.key;
          return (
            <button key={p.key} className="qa-item" onClick={() => { onPick(p); close(); }}>
              <div className="qa-ic" style={{ background: 'var(--slate-wash)', color: 'var(--sky-deep)' }}><Icon name="user" size={20} color="var(--sky-deep)" /></div>
              <div style={{ flex: 1, textAlign: 'left' }}><div style={{ fontWeight: 800, fontSize: 14.5 }}>{p.label}</div><div className="body" style={{ fontSize: 12 }}>{MON.ageGroup(p.age).label} · {p.thalType}{p.splenectomy ? ' · splenectomized' : ''}</div></div>
              {on && <Icon name="check" size={18} color="var(--sky-deep)" sw={2.6} />}
            </button>
          );
        })}
      </div>
    </MSheet>
  );
}

/* ============================================================
   REDESIGN · summary dashboard + collapsible sections +
   enriched cards + full-screen detail page.
   ============================================================ */

/* ---- the tiny trend indicator on a card ---- */
function MonTrendInline({ test, logs, sparklines }) {
  const tr = MON.trendOf(test, logs);
  const vals = MON.logsFor(test.id, logs).map(MON.numVal).filter((v) => v != null).reverse();
  if (!tr) return <span className="dmeta muted" style={{ fontSize: 11 }}>—</span>;
  const cat = MON.catMeta(test.category);
  const col = tr.dir === 'flat' ? 'var(--ink-3)' : (tr.dir === 'up' ? cat.color : 'var(--success)');
  return (
    <div className="row" style={{ gap: 6, alignItems: 'center' }}>
      {sparklines && vals.length >= 3 && <div style={{ width: 40, flex: 'none' }}><Sparkline values={vals} color={col} height={18} fill={false} strokeWidth={2} /></div>}
      <span className="mon-trend" style={{ color: col }}>
        <Icon name={tr.icon} size={13} color={col} />{Math.abs(Math.round(tr.pct))}%
      </span>
    </div>
  );
}

/* ---- enriched test card ---- */
function MonTestCard2({ test, profile, logs, store, onOpen, onAdd }) {
  const cat = MON.catMeta(test.category);
  const grp = MON.groupOfCat(test.category);
  const st = MON.statusOf(test, profile, logs);
  const last = st.last;
  const flag = last && (test.normal_range || test.therapy_relative) ? MON.valueFlag(test, last.value, profile) : null;
  const abn = flag && flag.dir !== 'normal';
  const numHist = MON.logsFor(test.id, logs).filter((l) => MON.numVal(l) != null).length;
  return (
    <div className={'mon-card2' + (abn ? ' abn' : '')} style={abn ? { '--c': flag.color } : undefined}>
      <div className="top" onClick={onOpen}>
        <div className="leaf" style={{ width: 36, height: 36, flex: 'none', background: cat.wash, color: cat.color, borderRadius: 11 }}><Icon name={cat.icon} size={17} color={cat.color} fill={cat.icon === 'sparkle' || cat.icon === 'drop' ? cat.color : 'none'} /></div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="nm">{test.name}</div>
          <div className="gp">{grp ? grp.label : cat.key}</div>
        </div>
        {monStatusChip(st)}
      </div>
      <div className="metrics">
        <div className="metric">
          <div className="k">Latest</div>
          <div className="v" style={{ color: abn ? flag.color : 'var(--ink)' }}>{last ? <React.Fragment>{last.value}{test.unit && <small> {test.unit}</small>}</React.Fragment> : '—'}</div>
          <div className="sub">{last ? TC.fmtDate(last.date, { day: 'numeric', month: 'short', year: 'numeric' }) : 'No result yet'}</div>
        </div>
        <div className="metric">
          <div className="k">Due</div>
          <div className="v" style={{ color: (MON.STATUS_META[st.status] || {}).color || 'var(--ink)' }}>{monDueText(st)}</div>
          <div className="sub">{MON.freqLabel(st.freq)}</div>
        </div>
        <div className="metric">
          <div className="k">Trend</div>
          <div style={{ marginTop: 1 }}>{numHist >= 2 ? <MonTrendInline test={test} logs={logs} sparklines={store.sparklines} /> : <span className="dmeta muted" style={{ fontSize: 11 }}>—</span>}</div>
          <div className="sub">{numHist >= 2 ? `${numHist} readings` : 'Need 2+ readings'}</div>
        </div>
      </div>
      <div className="acts">
        <button className="act add" onClick={onAdd}><Icon name="plus" size={14} color="var(--orange)" sw={2.6} />{last ? 'Quick add' : 'Add first result'}</button>
        <button className="act hist" onClick={onOpen}><Icon name="chart" size={14} color="var(--ink-2)" />View history</button>
      </div>
    </div>
  );
}

/* ---- summary dashboard ---- */
function MonDashboard({ cov, lastUpdated, onJump }) {
  const tiles = [
    { k: 'OVERDUE', n: cov.overdue, l: 'Overdue', color: 'var(--danger)', wash: 'var(--danger-wash)' },
    { k: 'DUESOON', n: cov.due, l: 'Due soon', color: 'var(--warning)', wash: 'var(--warning-wash)' },
    cov.never > 0
      ? { k: 'NEVER', n: cov.never, l: 'Not started', color: 'var(--ink-3)', wash: 'var(--neutral-wash)' }
      : { k: 'COMPLETED', n: cov.completed, l: 'Up to date', color: 'var(--success)', wash: 'var(--success-wash)' },
  ];
  return (
    <div>
      <div className="mon-dash">
        {tiles.map((t) => (
          <button key={t.k} className={'mon-stat' + (t.n === 0 ? ' is-zero' : '')} onClick={() => onJump(t.k)}>
            <span className="bar" style={{ background: t.color }} />
            <span className="n" style={{ color: t.n ? t.color : undefined }}>{t.n}</span>
            <span className="l">{t.l}</span>
          </button>
        ))}
      </div>
      <div className="mon-updated">
        <span className="dot" />
        <span className="dmeta muted">{lastUpdated ? `Last updated ${TC.fmtDate(lastUpdated)} · ${cov.total} tracked tests` : `${cov.total} tracked tests · no results yet`}</span>
      </div>
    </div>
  );
}

/* ---- collapsible status section ---- */
function MonSection({ title, color, count, open, onToggle, children, secRef }) {
  if (!count) return null;
  return (
    <div className="mon-sec" ref={secRef}>
      <button className={'mon-sec-head' + (open ? ' open' : '')} onClick={onToggle}>
        <span className="tt" style={{ color }}><span style={{ width: 9, height: 9, borderRadius: 999, background: color }} />{title}</span>
        <span className="pill" style={{ background: color + '1f', color }}>{count}</span>
        <Icon name="chevD" size={17} className="chev" />
      </button>
      <div className={'mon-acc2' + (open ? ' open' : '')}><div>{open ? children : null}</div></div>
    </div>
  );
}

/* ---- the redesigned Tests view ---- */
function MonTestsRedesign({ store, profile, logs, openDetail, openReport }) {
  const [query, setQuery] = React.useState('');
  const tests = MON.applicableTests(profile);
  const cov = MON.coverage(profile, logs);
  let lastUpdated = null;
  logs.forEach((l) => { if (!lastUpdated || TC.parse(l.date) > TC.parse(lastUpdated)) lastUpdated = l.date; });

  const [open, setOpen] = React.useState({ OVERDUE: true, DUESOON: true, NEVER: false, COMPLETED: false, ALL: false });
  const refs = { OVERDUE: React.useRef(null), DUESOON: React.useRef(null), NEVER: React.useRef(null), COMPLETED: React.useRef(null) };
  const toggle = (k) => setOpen((s) => ({ ...s, [k]: !s[k] }));
  const jump = (k) => {
    setOpen((s) => ({ ...s, [k]: true }));
    setTimeout(() => { const el = refs[k] && refs[k].current; if (el) monScrollIntoView(el); }, 120);
  };

  const byStatus = { OVERDUE: [], DUESOON: [], COMPLETED: [], OPTIONAL: [], NEVER: [] };
  tests.forEach((t) => { const st = MON.statusOf(t, profile, logs); if (st.never) byStatus.NEVER.push(t); else (byStatus[st.status] || byStatus.OPTIONAL).push(t); });
  const upToDate = [...byStatus.COMPLETED, ...byStatus.OPTIONAL];

  const card = (t) => <MonTestCard2 key={t.id} test={t} profile={profile} logs={logs} store={store} onOpen={() => openDetail(t)} onAdd={() => openDetail(t, true)} />;

  // search → flat results across everything
  const searching = query.trim().length > 0;
  const found = searching ? tests.filter((t) => MON.searchTest(t, query)) : [];

  // "All tests" — every applicable test, urgency-sorted
  const rank = { OVERDUE: 0, DUESOON: 1, COMPLETED: 2, OPTIONAL: 3 };
  const allSorted = [...tests].sort((a, b) => (rank[MON.statusOf(a, profile, logs).status] ?? 9) - (rank[MON.statusOf(b, profile, logs).status] ?? 9));

  return (
    <div>
      <MonDashboard cov={cov} lastUpdated={lastUpdated} onJump={jump} />

      <button className="card" onClick={openReport} style={{ display: 'flex', width: '100%', alignItems: 'center', gap: 12, cursor: 'pointer', border: 'none', fontFamily: 'inherit', padding: '13px 15px', marginBottom: 14, textAlign: 'left' }}>
        <div className="leaf" style={{ width: 40, height: 40, flex: 'none', background: 'var(--sky-wash)', color: 'var(--sky-deep)', borderRadius: 12 }}><Icon name="clipboard" size={19} color="var(--sky-deep)" /></div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="dname" style={{ fontSize: 14.5 }}>Doctor report</div>
          <div className="dmeta muted">Build a clinical summary PDF to share</div>
        </div>
        <Icon name="chevR" size={17} color="var(--ink-3)" />
      </button>

      <div className="card-flat row" style={{ gap: 9, padding: '10px 13px', marginBottom: 14 }}>
        <Icon name="search" size={17} color="var(--ink-3)" />
        <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search tests, categories…" style={{ flex: 1, minWidth: 0, border: 'none', background: 'none', outline: 'none', fontFamily: 'inherit', fontSize: 14, color: 'var(--ink)' }} />
        {query && <button className="icon-btn" style={{ width: 26, height: 26, flex: 'none', background: 'var(--surface-2)' }} onClick={() => setQuery('')} aria-label="Clear"><Icon name="x" size={13} /></button>}
      </div>

      {searching ? (
        <div>
          <div className="between" style={{ marginBottom: 9 }}><span className="sec-title">Results</span><span className="dmeta muted">{found.length}</span></div>
          {found.length ? found.map(card) : <div className="card"><div className="body" style={{ padding: '8px 0' }}>No tests match “{query}”.</div></div>}
        </div>
      ) : (
        <React.Fragment>
          <MonSection title="Overdue" color="var(--danger)" count={byStatus.OVERDUE.length} open={open.OVERDUE} onToggle={() => toggle('OVERDUE')} secRef={refs.OVERDUE}>
            {byStatus.OVERDUE.map(card)}
          </MonSection>
          <MonSection title="Due soon" color="var(--warning)" count={byStatus.DUESOON.length} open={open.DUESOON} onToggle={() => toggle('DUESOON')} secRef={refs.DUESOON}>
            {byStatus.DUESOON.map(card)}
          </MonSection>
          <MonSection title="Not started yet" color="var(--ink-3)" count={byStatus.NEVER.length} open={open.NEVER} onToggle={() => toggle('NEVER')} secRef={refs.NEVER}>
            {byStatus.NEVER.map(card)}
          </MonSection>
          <MonSection title="Up to date" color="var(--success)" count={upToDate.length} open={open.COMPLETED} onToggle={() => toggle('COMPLETED')} secRef={refs.COMPLETED}>
            {upToDate.map(card)}
          </MonSection>

          {(byStatus.OVERDUE.length + byStatus.DUESOON.length + byStatus.NEVER.length + upToDate.length) === 0 && (
            <div className="card"><div className="body" style={{ padding: '8px 0' }}>No tests apply to this profile yet.</div></div>
          )}

          <div className="mon-sec" style={{ marginTop: 4 }}>
            <button className={'mon-sec-head' + (open.ALL ? ' open' : '')} onClick={() => toggle('ALL')}>
              <span className="tt" style={{ color: 'var(--ink-2)' }}><Icon name="grid" size={15} color="var(--ink-2)" />All tests</span>
              <span className="pill" style={{ background: 'var(--surface-2)', color: 'var(--ink-2)' }}>{tests.length}</span>
              <Icon name="chevD" size={17} className="chev" />
            </button>
            <div className={'mon-acc2' + (open.ALL ? ' open' : '')}><div>{open.ALL ? allSorted.map(card) : null}</div></div>
          </div>
        </React.Fragment>
      )}
    </div>
  );
}

/* ---- full-screen test detail page ---- */
function MonTestDetailPage({ store, test, profile, startAdd, onBack }) {
  const logs = store.data.testLogs || [];
  const st = MON.statusOf(test, profile, logs);
  // visits that contain a result for this test → "attached reports"
  const related = MON.logsFor(test.id, logs)
    .map((l) => ({ log: l, visit: (store.data.visits || []).find((v) => v.id === l.visitId) }))
    .filter((x) => x.visit);
  return (
    <div className="mon-page">
      <div className="mon-page-head">
        <button className="mon-back" onClick={onBack} aria-label="Back"><Icon name="chevL" size={20} color="var(--ink)" /></button>
        <div className="ttl">{test.name}</div>
        {monStatusChip(st)}
      </div>
      <div className="mon-page-body">
        <MonTestDetailBody store={store} test={test} profile={profile} startAdd={startAdd} />
        {related.length > 0 && (
          <div className="detail-sec" style={{ marginTop: 18 }}>
            <SLabel>Attached reports · {related.length}</SLabel>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {related.slice(0, 8).map(({ log, visit }) => {
                const vm = MON.visitTypeMeta(visit.type);
                return (
                  <div key={log.id} className="card-flat row" style={{ padding: '11px 13px', gap: 11 }}>
                    <div className="leaf" style={{ width: 34, height: 34, flex: 'none', background: vm.wash, color: vm.color, borderRadius: 10 }}><Icon name={log.method === 'scan' ? 'sparkle' : vm.icon} size={15} color={vm.color} fill={vm.icon === 'drop' ? vm.color : 'none'} /></div>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div className="dname" style={{ fontSize: 13.5 }}>{vm.label}{log.method === 'scan' ? ' · from report (OCR)' : ''}</div>
                      <div className="dmeta muted">{TC.fmtDate(visit.date)}{visit.provider ? ` · ${visit.provider}` : ''}</div>
                    </div>
                    <span className="num" style={{ fontWeight: 800, fontSize: 14 }}>{log.value}{test.unit ? <span className="body" style={{ fontSize: 10.5 }}> {test.unit}</span> : ''}</span>
                  </div>
                );
              })}
            </div>
            <div className="dmeta muted" style={{ marginTop: 8, lineHeight: 1.5 }}>Each result is linked to the lab session it came from. Original report files stay on your device.</div>
          </div>
        )}
      </div>
    </div>
  );
}

/* ============================================================
   MAIN SCREEN
   ============================================================ */
function MonitoringScreen({ store }) {
  const [override, setOverride] = React.useState(null);
  const [viewMode, setViewMode] = React.useState('tests'); // tests | visits
  const [sheet, setSheet] = React.useState(null);
  const [insOpen, setInsOpen] = React.useState(false);
  // full-screen overlays: dedicated test detail page + doctor report
  const [detail, setDetail] = React.useState(null);   // { test, startAdd } | null
  const [report, setReport] = React.useState(null);    // computed report model | null
  // general timeline (TIF schedule) — controlled open state + scroll target
  const TT_OPEN_KEY = 'tc.mon.timetable.open';
  const [ttOpen, setTtOpen] = React.useState(() => { try { return localStorage.getItem(TT_OPEN_KEY) === '1'; } catch (e) { return false; } });
  const ttRef = React.useRef(null);
  const toggleTimeline = (force) => setTtOpen((v) => { const n = (force == null) ? !v : force; try { localStorage.setItem(TT_OPEN_KEY, n ? '1' : '0'); } catch (e) {} return n; });
  const openTimeline = () => { setViewMode('tests'); toggleTimeline(true); setTimeout(() => { if (ttRef.current) monScrollIntoView(ttRef.current); }, 160); };
  // inline expand-and-focus state
  const [expandedId, setExpandedId] = React.useState(null);
  const [startAddId, setStartAddId] = React.useState(null);
  const [focusReq, setFocusReq] = React.useState(0);
  const cardEls = React.useRef(new Map());
  const registerCard = React.useRef({
    get: (id) => cardEls.current.get(id),
    set: (id, el) => { if (el) cardEls.current.set(id, el); else cardEls.current.delete(id); },
  }).current;
  // make registerCard callable as registerCard(id, el) and also expose .get
  const regFn = React.useRef(null);
  if (!regFn.current) { regFn.current = (id, el) => registerCard.set(id, el); regFn.current.get = registerCard.get; }

  const logs = store.data.testLogs || [];
  const profile = override || MON.profileOf(store.patient);
  MON.setActiveProfile(profile);
  const isDemo = !!override;
  const tests = MON.applicableTests(profile);
  const cov = MON.coverage(profile, logs);
  const insights = MON.insights(profile, logs);
  const layout = store.monLayout || 'Triage';

  // expand a test inline (and request a scroll-into-view + flash)
  const expandTest = (id, startAdd) => {
    setViewMode('tests');
    setExpandedId(id);
    setStartAddId(startAdd ? id : null);
    setFocusReq((n) => n + 1);
  };
  // open the dedicated full-screen detail page (replaces inline expand)
  const openDetail = (t, startAdd) => { if (t) { setViewMode('tests'); setDetail({ test: t, startAdd: !!startAdd }); } };
  const openTest = (t, startAdd) => openDetail(t, startAdd);
  const addTest = (t) => openDetail(t, true);
  const genReport = (opts) => { setSheet(null); try { setReport(TCReport.build(store.data, opts)); } catch (e) {} };
  const onExpand = (id, startAdd) => { // from MonTestsView toggles
    if (id == null) { setExpandedId(null); setStartAddId(null); return; }
    expandTest(id, startAdd);
  };
  const openVisit = (v) => setSheet({ type: 'visit', visit: v });
  const openScan = () => setSheet({ type: 'scan' });

  // honour a focus request from the Home screen (e.g. “open the ferritin test”)
  React.useEffect(() => {
    if (!store.healthFocus) return;
    const t = tests.find((x) => x.id === store.healthFocus);
    if (t) openDetail(t);
    store.setHealthFocus(null);
  }, [store.healthFocus]);

  return (
    <div>
      <div className="seg tri" style={{ marginBottom: 14 }}>
        <button className={viewMode === 'tests' ? 'on' : ''} onClick={() => setViewMode('tests')}>Tests</button>
        <button className={viewMode === 'visits' ? 'on' : ''} onClick={() => setViewMode('visits')}>Visits</button>
        <button className={viewMode === 'reports' ? 'on' : ''} onClick={() => setViewMode('reports')}>Lab Reports</button>
      </div>

      {viewMode === 'tests' ? (
        <React.Fragment>
          <MonTestsRedesign store={store} profile={profile} logs={logs} openDetail={openDetail} openReport={() => setSheet({ type: 'report' })} />
          <div ref={ttRef}><MonTimetable profile={profile} logs={logs} open={ttOpen} onToggle={() => toggleTimeline()} /></div>
          <div className="dmeta muted" style={{ textAlign: 'center', padding: '4px 20px 8px', lineHeight: 1.5 }}>
            Schedules follow TIF monitoring recommendations, personalised to this profile. Always confirm with your care team.
          </div>
        </React.Fragment>
      ) : viewMode === 'visits' ? (
        <MonVisitsView store={store} openVisit={openVisit} openScan={openScan} />
      ) : (
        <LabReportsView store={store} openVisit={openVisit} openScan={openScan} />
      )}

      {sheet && sheet.type === 'test' && <MonTestSheet store={store} close={() => setSheet(null)} test={sheet.test} profile={profile} startAdd={sheet.startAdd} />}
      {sheet && sheet.type === 'visit' && <MonVisitSheet store={store} close={() => setSheet(null)} visit={sheet.visit} openTest={(t) => { setSheet(null); openTest(t); }} />}
      {sheet && sheet.type === 'profile' && <MonProfileSheet store={store} close={() => setSheet(null)} />}
      {sheet && sheet.type === 'scan' && <LabImportSheet store={store} close={() => setSheet(null)} profile={profile} />}
      {sheet && sheet.type === 'allInsights' && <MonAllInsightsSheet store={store} close={() => setSheet(null)} insights={insights} tests={tests} openTest={(t) => { setSheet(null); openTest(t); }} />}
      {sheet && sheet.type === 'report' && <MonReportConfigSheet store={store} close={() => setSheet(null)} onGenerate={genReport} />}

      {detail && <MonTestDetailPage store={store} test={detail.test} profile={profile} startAdd={detail.startAdd} onBack={() => setDetail(null)} />}
      {report && <MonReportOverlay store={store} model={report} onClose={() => setReport(null)} />}
    </div>
  );
}

Object.assign(window, { monStatusChip, monDueText, MonInsightCard, MonInsightsBar, MonAllInsightsSheet, MonHeader, MonTestCard, MonTestRow, MonTriageList, MonCardsList, MonStatusList, MonTestsView, MonProfileSheet, MonSwitchSheet, MonitoringScreen });
