/* enterprisex.jsx — Mira Enterprise (rebuild) UI shell + screens.
 * Entity+lens architecture (§3). Mounts on #/mx (old #/enterprise kept gated).
 * Premium editorial terminal (§27). Uses window.MX (enterprisex-core.jsx).
 */
(function () {
  'use strict';
  var React = window.React, ReactDOM = window.ReactDOM;
  var h = React.createElement;
  var MX = window.MX;
  function devOnly() { try { if (typeof window.isEnterprisePreviewEnabled === 'function') return window.isEnterprisePreviewEnabled(); } catch (e) {} return /localhost|127\.0\.0\.1|\.local|vercel\.app/.test(location.hostname); }

  // ── Design system (§39) — warm editorial, injected once ─────────────────────
  var CSS = `
  #mx-root{--mx-page:#EDEAE2;--mx-surface:#FCFBF7;--mx-surface2:#F5F2EA;--mx-ink:#1A1712;--mx-body:#3A342B;--mx-muted:#6B6252;--mx-faint:#9A9184;--mx-border:#E3DBCB;--mx-line:#ECE6DA;--mx-accent:#B5701E;--mx-accent-t:#F4E9D8;--mx-strong:#2F6B34;--mx-warn:#8A5A16;--mx-crit:#9A3B2C;--mx-unknown:#6B6252;--mx-radius:12px;--mx-serif:Georgia,'Times New Roman',serif;--mx-sans:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;font-family:var(--mx-sans);color:var(--mx-body);background:var(--mx-page);position:fixed;inset:0;z-index:4000;display:flex;overflow:hidden}
  #mx-root *{box-sizing:border-box}
  .mx-nav{width:216px;flex:0 0 216px;background:var(--mx-surface);border-right:1px solid var(--mx-border);display:flex;flex-direction:column;padding:20px 12px;gap:4px}
  .mx-wordmark{font-family:var(--mx-serif);font-size:20px;font-weight:700;color:var(--mx-ink);letter-spacing:.01em;padding:4px 10px 6px}
  .mx-wordmark small{display:block;font-family:var(--mx-sans);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--mx-faint);font-weight:600;margin-top:2px}
  .mx-navitem{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:9px;color:var(--mx-body);font-size:14px;font-weight:500;cursor:pointer;border:0;background:none;text-align:left;width:100%}
  .mx-navitem:hover{background:var(--mx-surface2)}
  .mx-navitem.on{background:var(--mx-accent-t);color:var(--mx-ink);font-weight:600}
  .mx-navspacer{flex:1}
  .mx-main{flex:1;overflow-y:auto;overflow-x:hidden}
  .mx-wrap{max-width:1040px;margin:0 auto;padding:28px 36px 80px}
  .mx-ctxhead{position:sticky;top:0;z-index:5;background:linear-gradient(var(--mx-page),var(--mx-page) 70%,rgba(237,234,226,0));padding:24px 36px 10px;max-width:1112px;margin:0 auto}
  .mx-eyebrow{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--mx-accent);font-weight:700}
  .mx-h1{font-family:var(--mx-serif);font-size:30px;line-height:1.1;color:var(--mx-ink);margin:3px 0 2px;font-weight:700}
  .mx-sub{font-size:13px;color:var(--mx-muted)}
  .mx-tabs{display:flex;gap:2px;border-bottom:1px solid var(--mx-border);margin:14px 0 0}
  .mx-tab{padding:9px 14px;font-size:13.5px;font-weight:600;color:var(--mx-muted);border:0;background:none;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}
  .mx-tab.on{color:var(--mx-ink);border-bottom-color:var(--mx-accent)}
  .mx-tab:hover{color:var(--mx-ink)}
  .mx-row{display:flex;gap:14px;align-items:flex-start}
  .mx-card{background:var(--mx-surface);border:1px solid var(--mx-border);border-radius:var(--mx-radius);padding:16px 18px}
  .mx-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;background:var(--mx-surface2);border:1px solid var(--mx-border);font-size:12px;color:var(--mx-body);font-weight:500}
  .mx-chip button{border:0;background:none;color:var(--mx-faint);cursor:pointer;font-size:13px;line-height:1;padding:0}
  .mx-search{width:100%;padding:16px 18px;font-size:17px;border:1px solid var(--mx-border);border-radius:14px;background:var(--mx-surface);color:var(--mx-ink);font-family:var(--mx-serif)}
  .mx-search:focus{outline:2px solid var(--mx-accent);border-color:var(--mx-accent)}
  .mx-input{padding:9px 12px;font-size:14px;border:1px solid var(--mx-border);border-radius:8px;background:var(--mx-surface)}
  .mx-btn{display:inline-flex;align-items:center;gap:7px;padding:9px 15px;font-size:13.5px;font-weight:600;border-radius:9px;border:1px solid var(--mx-border);background:var(--mx-surface);color:var(--mx-ink);cursor:pointer}
  .mx-btn:hover{background:var(--mx-surface2)}
  .mx-btn--primary{background:var(--mx-accent);border-color:var(--mx-accent);color:#fff}
  .mx-btn--primary:hover{background:#a5651a}
  .mx-btn--sm{padding:6px 11px;font-size:12.5px}
  .mx-listrow{display:grid;grid-template-columns:1fr auto;gap:6px 16px;padding:14px 16px;border:1px solid var(--mx-border);border-radius:10px;background:var(--mx-surface);cursor:pointer;margin-bottom:8px}
  .mx-listrow:hover{border-color:var(--mx-accent);background:var(--mx-surface2)}
  .mx-lr-title{font-weight:600;color:var(--mx-ink);font-size:14.5px;line-height:1.3}
  .mx-lr-meta{font-size:12.5px;color:var(--mx-muted);margin-top:3px}
  .mx-lr-reason{font-size:12.5px;color:var(--mx-body);margin-top:6px}
  .mx-lr-concern{font-size:12.5px;color:var(--mx-warn);margin-top:2px}
  .mx-badge{display:inline-block;padding:3px 9px;border-radius:6px;font-size:11.5px;font-weight:700;white-space:nowrap}
  .mx-b-strong{background:#E2F0E1;color:var(--mx-strong)}
  .mx-b-review{background:#F5EAD3;color:var(--mx-warn)}
  .mx-b-monitor{background:var(--mx-surface2);color:var(--mx-muted)}
  .mx-b-nel{background:#F6E4DF;color:var(--mx-crit)}
  .mx-b-info{background:#EBE5F3;color:#5A3F8A}
  .mx-group-h{display:flex;align-items:center;gap:10px;margin:22px 0 10px;cursor:pointer}
  .mx-group-h h3{font-family:var(--mx-serif);font-size:17px;color:var(--mx-ink);margin:0}
  .mx-count{font-size:12px;color:var(--mx-faint);font-weight:600}
  .mx-section-h{font-family:var(--mx-serif);font-size:16px;color:var(--mx-ink);margin:22px 0 8px;border-bottom:1px solid var(--mx-line);padding-bottom:6px}
  .mx-kv{display:grid;grid-template-columns:180px 1fr;gap:6px 16px;font-size:13.5px}
  .mx-kv dt{color:var(--mx-muted)}
  .mx-kv dd{color:var(--mx-ink);margin:0;font-weight:500}
  .mx-dim{display:flex;justify-content:space-between;gap:12px;padding:8px 0;border-bottom:1px solid var(--mx-line);font-size:13.5px}
  .mx-dim b{font-weight:600}
  .mx-v-strong{color:var(--mx-strong);font-weight:700}
  .mx-v-weak{color:var(--mx-warn);font-weight:600}
  .mx-v-ineligible{color:var(--mx-crit);font-weight:700}
  .mx-v-unclear{color:var(--mx-faint);font-weight:600}
  .mx-v-possible{color:var(--mx-muted);font-weight:600}
  .mx-cov{background:var(--mx-surface2);border:1px solid var(--mx-border);border-radius:10px;padding:14px 16px;font-size:13px}
  .mx-cov b{color:var(--mx-ink)}
  .mx-empty{text-align:center;padding:48px 20px;color:var(--mx-muted)}
  .mx-empty h3{font-family:var(--mx-serif);color:var(--mx-ink);font-size:18px;margin:0 0 6px}
  .mx-drawer{position:fixed;top:0;right:0;bottom:0;width:min(420px,92vw);background:var(--mx-surface);border-left:1px solid var(--mx-border);box-shadow:-8px 0 30px rgba(26,23,18,.12);z-index:4100;padding:22px 24px;overflow-y:auto}
  .mx-source-link{color:var(--mx-accent);cursor:pointer;text-decoration:underline;font-size:12px}
  .mx-muted{color:var(--mx-muted)} .mx-faint{color:var(--mx-faint)}
  .mx-tile{background:var(--mx-surface);border:1px solid var(--mx-border);border-radius:12px;padding:16px 18px;display:flex;flex-direction:column;gap:8px}
  .mx-grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
  @media(max-width:820px){#mx-root{flex-direction:column}.mx-nav{width:100%;flex-direction:row;overflow-x:auto;padding:10px;border-right:0;border-bottom:1px solid var(--mx-border)}.mx-navspacer{display:none}.mx-wrap,.mx-ctxhead{padding-left:16px;padding-right:16px}.mx-grid2{grid-template-columns:1fr}.mx-kv{grid-template-columns:1fr}.mx-h1{font-size:24px}}
  `;
  function injectCSS() { if (document.getElementById('mx-css')) return; var s = document.createElement('style'); s.id = 'mx-css'; s.textContent = CSS; document.head.appendChild(s); }

  // ── small helpers ───────────────────────────────────────────────────────────
  function go(hash) { location.hash = hash; }
  function daysTo(iso) { if (!iso) return null; return Math.round((new Date(iso) - Date.now()) / 86400000); }
  function catBadge(cat) { var m = { 'Strong candidate': 'mx-b-strong', 'Worth reviewing': 'mx-b-review', 'Monitoring': 'mx-b-monitor', 'Not eligible': 'mx-b-nel', 'Insufficient information': 'mx-b-info', 'Probably not suitable': 'mx-b-monitor' }; return h('span', { className: 'mx-badge ' + (m[cat] || 'mx-b-monitor') }, cat); }
  function vClass(v) { return 'mx-v-' + v; }

  // ── Sources drawer (§20) ────────────────────────────────────────────────────
  function SourcesDrawer(p) {
    var o = p.opp;
    return h('div', { className: 'mx-drawer', role: 'dialog', 'aria-label': 'Sources' },
      h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 } },
        h('div', { className: 'mx-eyebrow' }, 'Sources & evidence'),
        h('button', { className: 'mx-btn mx-btn--sm', onClick: p.onClose }, 'Close')),
      h('div', { className: 'mx-section-h', style: { marginTop: 0 } }, 'Evidence for this opportunity'),
      h('dl', { className: 'mx-kv' },
        h('dt', null, 'Claim'), h('dd', null, o.title),
        h('dt', null, 'Source organisation'), h('dd', null, o.sourceName || o.funder || 'Unknown'),
        h('dt', null, 'Source URL'), h('dd', null, o.url ? h('a', { className: 'mx-source-link', href: o.url, target: '_blank', rel: 'noopener' }, o.url) : 'Not published'),
        h('dt', null, 'Supporting passage'), h('dd', null, o.evidence || h('span', { className: 'mx-faint' }, 'No passage stored')),
        h('dt', null, 'Direct or inferred'), h('dd', null, o.evidence ? 'Direct (from source listing)' : 'Inferred'),
        h('dt', null, 'Confidence'), h('dd', null, o.confidence != null ? o.confidence + '%' : (o.trust === 'high' ? 'Verified source' : 'Unclear')),
        h('dt', null, 'Trust'), h('dd', null, o.trust || 'unclear'),
        h('dt', null, 'Last checked'), h('dd', null, o.posted ? String(o.posted).slice(0, 10) : 'Unknown')),
      h('p', { className: 'mx-faint', style: { fontSize: 12, marginTop: 16 } }, 'Unknown fields remain unknown — Mira does not infer values it cannot verify.'));
  }

  // ── Ask Mira panel (§25) — context-aware, evidence-only, labelled ───────────
  function AskMira(p) {
    var st = React.useState([])[0], setSt = React.useState([])[1];
    var qs = ['Which of these should we review first?', 'Why is this only worth reviewing?', 'What weakens our strongest match?'];
    function answer(q) {
      var opps = p.opps || []; var org = MX.org();
      var scored = opps.map(function (o) { return { o: o, m: MX.match(o, org) }; });
      var strong = scored.filter(function (x) { return x.m.overall === 'Strong candidate'; });
      var a;
      if (/review first|matters most/i.test(q)) {
        var top = (strong[0] || scored.sort(function (a, b) { return MX.ORDER.indexOf(a.m.overall) - MX.ORDER.indexOf(b.m.overall); })[0]);
        a = top ? { fact: top.o.title + ' — ' + top.m.overall + '.', interpretation: 'It has the strongest combination of eligible geography, applicant type and sector among visible records.', recommendation: 'Open it and confirm ' + (top.m.missing[0] || 'the full guidelines') + '.', uncertainty: top.m.missing.length ? 'Missing: ' + top.m.missing.join(', ') + '.' : 'No major gaps flagged.' } : null;
      } else if (/weakens|weaken/i.test(q)) {
        var s = strong[0] || scored[0];
        a = s ? { fact: (s.o.title) + '.', interpretation: 'Concerns: ' + (s.m.concerns.join('; ') || 'none flagged') + '.', recommendation: 'Address the concern before committing effort.', uncertainty: s.m.missing.length ? 'Unverified: ' + s.m.missing.join(', ') + '.' : '' } : null;
      } else {
        a = { fact: strong.length + ' strong / ' + scored.filter(function (x) { return x.m.overall === 'Worth reviewing'; }).length + ' worth-reviewing among ' + scored.length + ' visible.', interpretation: 'Classification uses hard eligibility first, then sector, size and deadline fit.', recommendation: 'Start with strong candidates; monitor the rest.', uncertainty: 'Amounts unpublished for many records — see coverage.' };
      }
      setSt(st.concat([{ q: q, a: a }]));
    }
    return h('div', { className: 'mx-card', style: { marginTop: 20 } },
      h('div', { className: 'mx-eyebrow', style: { marginBottom: 8 } }, 'Ask Mira · this view'),
      st.map(function (m, i) {
        return h('div', { key: i, style: { marginBottom: 12, fontSize: 13.5 } },
          h('div', { style: { fontWeight: 600, color: 'var(--mx-ink)', marginBottom: 4 } }, m.q),
          m.a ? h('div', null,
            h('div', null, h('b', null, 'Fact: '), m.a.fact),
            h('div', { className: 'mx-muted' }, h('b', null, 'Interpretation: '), m.a.interpretation),
            h('div', { style: { color: 'var(--mx-accent)' } }, h('b', null, 'Recommendation: '), m.a.recommendation),
            m.a.uncertainty ? h('div', { className: 'mx-faint' }, h('b', null, 'Uncertainty: '), m.a.uncertainty) : null) : h('div', { className: 'mx-faint' }, 'No visible evidence to answer that yet.'));
      }),
      h('div', { style: { display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 4 } },
        qs.map(function (q, i) { return h('button', { key: i, className: 'mx-btn mx-btn--sm', onClick: function () { answer(q); } }, q); })));
  }

  // ── Coverage panel (§19) ────────────────────────────────────────────────────
  function Coverage(p) {
    var c = MX.coverage(p.opps);
    return h('div', { className: 'mx-cov' },
      h('div', { className: 'mx-eyebrow', style: { marginBottom: 6 } }, 'Coverage'),
      h('div', null, h('b', null, c.records), ' opportunities · ', h('b', null, c.sources), ' source', c.sources === 1 ? '' : 's'),
      h('div', { className: 'mx-muted', style: { marginTop: 3 } }, 'Award amounts available for ', h('b', null, c.amountPct + '%'), ' · eligibility details for ', h('b', null, c.eligPct + '%')),
      c.amountPct < 60 ? h('div', { className: 'mx-faint', style: { marginTop: 3 } }, 'Amount coverage limited — many records show “Amount not published”.') : null);
  }

  // ── Opportunity list row (§31) ──────────────────────────────────────────────
  function OppRow(p) {
    var o = p.opp, m = p.match;
    var d = daysTo(o.deadline);
    return h('div', { className: 'mx-listrow', onClick: function () { go('#/mx/opportunity/' + o.id); } },
      h('div', null,
        h('div', { className: 'mx-lr-title' }, o.title),
        h('div', { className: 'mx-lr-meta' }, o.funder, ' · ', o.type, ' · ', (o.countries[0] || o.regions[0] || 'Global'), ' · ', o.analyticalGBP != null ? MX.money.fmtGBP(o.analyticalGBP) : (o.amountType === 'total_programme_budget' ? MX.money.fmtGBP(MX.money.toGBP(o.totalBudget, o.currency)) + ' programme envelope' : 'Amount not published'), d != null ? ' · closes in ' + d + 'd' : ' · no deadline'),
        m.reasons[0] ? h('div', { className: 'mx-lr-reason' }, '✓ ' + m.reasons[0]) : null,
        m.concerns[0] ? h('div', { className: 'mx-lr-concern' }, '△ ' + m.concerns[0]) : null),
      h('div', { style: { textAlign: 'right', display: 'flex', flexDirection: 'column', gap: 6, alignItems: 'flex-end' } },
        catBadge(m.overall),
        h('span', { className: 'mx-faint', style: { fontSize: 11 } }, o.trust === 'high' ? 'Verified' : 'Unclear')));
  }

  // ── Grouped results (§31) ───────────────────────────────────────────────────
  function GroupedResults(p) {
    var org = MX.org();
    var scored = p.opps.map(function (o) { return { o: o, m: MX.match(o, org) }; });
    var groups = {}; MX.ORDER.forEach(function (g) { groups[g] = []; });
    scored.forEach(function (s) { (groups[s.m.overall] = groups[s.m.overall] || []).push(s); });
    var collapsedInit = {}; MX.ORDER.forEach(function (g, i) { collapsedInit[g] = i >= 2; });
    var col = React.useState(collapsedInit); var collapsed = col[0], setCol = col[1];
    if (!scored.length) return h('div', { className: 'mx-empty' }, h('h3', null, 'No opportunities match'), h('p', null, 'No records meet these filters. Try widening the amount or deadline range.'));
    return h('div', null, MX.ORDER.map(function (g) {
      var items = groups[g] || []; if (!items.length) return null;
      var isCol = collapsed[g];
      return h('div', { key: g },
        h('div', { className: 'mx-group-h', onClick: function () { var n = Object.assign({}, collapsed); n[g] = !n[g]; setCol(n); } },
          h('h3', null, g), h('span', { className: 'mx-count' }, items.length), h('span', { className: 'mx-faint', style: { fontSize: 12 } }, isCol ? '▸ show' : '▾ hide')),
        isCol ? null : items.map(function (s, i) { return h(OppRow, { key: s.o.id + i, opp: s.o, match: s.m }); }));
    }),
      g0(groups) === 0 ? h('div', { className: 'mx-empty' }, h('h3', null, 'No strong candidates'), h('p', null, 'No opportunities currently meet the strong-candidate threshold. Worth-reviewing and monitoring items are below.')) : null);
  }
  function g0(groups) { return (groups['Strong candidate'] || []).length; }

  // ── Screens ─────────────────────────────────────────────────────────────────
  function ContextHeader(p) {
    return h('div', { className: 'mx-ctxhead' },
      h('div', { className: 'mx-eyebrow' }, p.eyebrow),
      h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 12, flexWrap: 'wrap' } },
        h('div', null, h('div', { className: 'mx-h1' }, p.title), p.sub ? h('div', { className: 'mx-sub' }, p.sub) : null),
        h('div', { style: { display: 'flex', gap: 8 } }, p.actions || null)),
      p.tabs ? h('div', { className: 'mx-tabs' }, p.tabs.map(function (t) {
        return h('button', { key: t.id, className: 'mx-tab' + (t.on ? ' on' : ''), onClick: t.onClick }, t.label);
      })) : null);
  }

  function SearchScreen(p) {
    var qs = React.useState(p.initialQ || ''); var q = qs[0], setQ = qs[1];
    var rs = React.useState(null); var res = rs[0], setRes = rs[1];
    var recent = MX.store ? (function () { try { return JSON.parse(localStorage.getItem('mx.recent') || '[]'); } catch (e) { return []; } })() : [];
    function run(query) {
      var parsed = MX.parse(query, p.opps);
      try { var r = JSON.parse(localStorage.getItem('mx.recent') || '[]'); r = [query].concat(r.filter(function (x) { return x !== query; })).slice(0, 6); localStorage.setItem('mx.recent', JSON.stringify(r)); } catch (e) {}
      // route to entity view when identified
      if (parsed.entity && parsed.entity.type === 'country') { go('#/mx/country/' + encodeURIComponent(parsed.entity.id) + '/' + parsed.lens); return; }
      if (parsed.entity && parsed.entity.type === 'funder') { go('#/mx/funder/' + encodeURIComponent(parsed.entity.id) + '/' + (parsed.lens === 'funding' || parsed.lens === 'risk' || parsed.lens === 'sources' ? parsed.lens : 'funding')); return; }
      setRes(parsed);
    }
    var suggested = ['What funding is open in Kenya?', 'Climate grants below £100,000 in Southeast Asia', 'Show tenders closing in the next 30 days', 'What has changed at the Gates Foundation?'];
    var filtered = res ? MX.applyFilters(p.opps, res.filters) : [];
    return h('div', null,
      h('div', { className: 'mx-wrap' },
        h('div', { className: 'mx-eyebrow', style: { marginBottom: 10 } }, 'Search'),
        h('form', { onSubmit: function (e) { e.preventDefault(); run(q); } },
          h('input', { className: 'mx-search', placeholder: 'Ask anything — “health grants under £500k in Pakistan”', value: q, onChange: function (e) { setQ(e.target.value); }, autoFocus: true })),
        res ? h('div', { style: { marginTop: 14 } },
          h('div', { style: { display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' } },
            h('span', { className: 'mx-faint', style: { fontSize: 12 } }, 'Interpreted as:'),
            res.entity ? h('span', { className: 'mx-chip' }, res.entity.type + ': ' + res.entity.id) : null,
            h('span', { className: 'mx-chip' }, 'Lens: ' + res.lens),
            res.filters.sector ? h('span', { className: 'mx-chip' }, 'Theme: ' + res.filters.sector) : null,
            res.filters.amountMax ? h('span', { className: 'mx-chip' }, '≤ ' + MX.money.fmtGBP(res.filters.amountMax)) : null,
            res.filters.amountMin ? h('span', { className: 'mx-chip' }, '≥ ' + MX.money.fmtGBP(res.filters.amountMin)) : null,
            res.filters.deadlineDays ? h('span', { className: 'mx-chip' }, 'Closing ≤ ' + res.filters.deadlineDays + 'd') : null),
          h('div', { className: 'mx-faint', style: { fontSize: 12, marginTop: 6 } }, 'Personalised for ' + MX.org().name + (MX.org()._demo ? ' (demo profile)' : '') + '. Not what you meant? Refine your query.'),
          h('div', { style: { marginTop: 16 } }, h(Coverage, { opps: filtered })),
          h(GroupedResults, { opps: filtered }),
          h(AskMira, { opps: filtered })
        ) : h('div', { style: { marginTop: 22 } },
          h('div', { className: 'mx-section-h', style: { marginTop: 0 } }, 'Suggested searches'),
          suggested.map(function (s, i) { return h('div', { key: i, className: 'mx-listrow', onClick: function () { setQ(s); run(s); }, style: { gridTemplateColumns: '1fr' } }, h('div', { className: 'mx-lr-title', style: { fontWeight: 500, fontFamily: 'var(--mx-serif)' } }, s)); }),
          recent.length ? h('div', null, h('div', { className: 'mx-section-h' }, 'Recent'), recent.map(function (s, i) { return h('span', { key: i, className: 'mx-chip', style: { marginRight: 6, cursor: 'pointer' }, onClick: function () { setQ(s); run(s); } }, s); })) : null)));
  }

  function CountryScreen(p) {
    var name = p.id, lens = p.lens || 'funding';
    var opps = p.opps.filter(function (o) { return o.countries.indexOf(name) !== -1 || (o.regions.indexOf('Global') !== -1); });
    var direct = p.opps.filter(function (o) { return o.countries.indexOf(name) !== -1; });
    var tabs = ['funding', 'risk', 'sources'].map(function (l) { return { id: l, label: l.charAt(0).toUpperCase() + l.slice(1), on: l === lens, onClick: function () { go('#/mx/country/' + encodeURIComponent(name) + '/' + l); } }; });
    var pinned = MX.store.pins().some(function (x) { return x.key === 'country:' + name + ':' + lens; });
    var actions = [
      h('button', { key: 'pin', className: 'mx-btn mx-btn--sm', onClick: function () { if (pinned) MX.store.unpin('country:' + name + ':' + lens); else MX.store.pin({ key: 'country:' + name + ':' + lens, entity: 'Country', name: name, lens: lens }); p.refresh(); } }, pinned ? '✓ Pinned' : '+ Pin to Today'),
      h('button', { key: 'alert', className: 'mx-btn mx-btn--sm', onClick: function () { MX.store.addAlert({ scope: 'country:' + name, lens: lens, level: 'daily' }); p.toast('Alert created: ' + name + ' · ' + lens); } }, '+ Alert')];
    var body;
    if (lens === 'funding') {
      body = h('div', null,
        h('div', { style: { marginBottom: 14 } }, h(Coverage, { opps: direct.length ? direct : opps })),
        direct.length ? h(GroupedResults, { opps: direct }) : h('div', { className: 'mx-empty' }, h('h3', null, 'Mira has limited verified coverage for ' + name), h('p', null, 'No opportunities are currently attributed directly to ' + name + '. Global opportunities you may be eligible for are shown under Search.')),
        h(AskMira, { opps: direct.length ? direct : opps }));
    } else if (lens === 'risk') {
      body = h('div', { className: 'mx-empty' }, h('h3', null, 'No developments require immediate action'), h('p', null, 'Risk signals are generated only when an external development plausibly affects your programmes in ' + name + '. Nothing currently meets that bar.'));
    } else {
      var cov = MX.coverage(direct.length ? direct : opps);
      body = h('div', { className: 'mx-card' },
        h('div', { className: 'mx-section-h', style: { marginTop: 0 } }, 'Active sources for ' + name),
        h('dl', { className: 'mx-kv' },
          h('dt', null, 'Opportunities attributed'), h('dd', null, direct.length),
          h('dt', null, 'Distinct sources'), h('dd', null, cov.sources),
          h('dt', null, 'Amount coverage'), h('dd', null, cov.amountPct + '%'),
          h('dt', null, 'Eligibility coverage'), h('dd', null, cov.eligPct + '%'),
          h('dt', null, 'Local-language sources'), h('dd', null, h('span', { className: 'mx-faint' }, 'None yet — coverage limited')),
          h('dt', null, 'Last checked'), h('dd', null, new Date().toISOString().slice(0, 10))));
    }
    return h('div', null,
      h(ContextHeader, { eyebrow: 'Country', title: name, sub: (direct.length) + ' opportunities attributed · personalised for ' + MX.org().name, actions: actions, tabs: tabs }),
      h('div', { className: 'mx-wrap', style: { paddingTop: 8 } }, body));
  }

  function FunderScreen(p) {
    var name = p.id, lens = p.lens || 'funding';
    var prof = MX.funderProfile(name, p.opps);
    var org = MX.org();
    var tabs = ['funding', 'risk', 'sources'].map(function (l) { return { id: l, label: l.charAt(0).toUpperCase() + l.slice(1), on: l === lens, onClick: function () { go('#/mx/funder/' + encodeURIComponent(name) + '/' + l); } }; });
    var pinned = MX.store.pins().some(function (x) { return x.key === 'funder:' + name + ':' + lens; });
    var actions = [
      h('button', { key: 'pin', className: 'mx-btn mx-btn--sm', onClick: function () { if (pinned) MX.store.unpin('funder:' + name + ':' + lens); else MX.store.pin({ key: 'funder:' + name + ':' + lens, entity: 'Funder', name: name, lens: lens }); p.refresh(); } }, pinned ? '✓ Pinned' : '+ Pin to Today'),
      h('button', { key: 'alert', className: 'mx-btn mx-btn--sm', onClick: function () { MX.store.addAlert({ scope: 'funder:' + name, lens: lens, level: 'daily' }); p.toast('Alert created: ' + name + ' · ' + lens); } }, '+ Alert')];
    // Header facts (real only)
    var rel = (org.priorDonors || []).indexOf(name) !== -1 ? 'Prior donor' : 'No recorded relationship';
    var header = h('div', { className: 'mx-card', style: { marginBottom: 14 } },
      h('dl', { className: 'mx-kv' },
        h('dt', null, 'Funder type'), h('dd', null, prof.type || h('span', { className: 'mx-faint' }, 'Not published')),
        h('dt', null, 'Countries supported'), h('dd', null, prof.countries.length ? prof.countries.slice(0, 8).join(', ') + (prof.countries.length > 8 ? '…' : '') : h('span', { className: 'mx-faint' }, 'Not published')),
        h('dt', null, 'Sectors'), h('dd', null, prof.sectors.length ? prof.sectors.join(', ') : h('span', { className: 'mx-faint' }, 'Not published')),
        h('dt', null, 'Typical verified award range'), h('dd', null, prof.awardRange ? MX.money.fmtGBP(prof.awardRange.min) + ' – ' + MX.money.fmtGBP(prof.awardRange.max) + ' (from ' + prof.awardRange.n + ' priced calls)' : h('span', { className: 'mx-faint' }, 'No per-award amounts published')),
        prof.programmeBudgets.length ? h('dt', null, 'Programme budgets') : null,
        prof.programmeBudgets.length ? (function () { var b = prof.programmeBudgets.slice().sort(function (x, y) { return x - y; }); var med = b[Math.floor(b.length / 2)]; return h('dd', null, b.length + ' programme envelopes · ' + MX.money.fmtGBP(b[0]) + ' – ' + MX.money.fmtGBP(b[b.length - 1]) + ' · median ' + MX.money.fmtGBP(med), h('span', { className: 'mx-faint' }, ' (envelopes — not per-award grants)')); })() : null,
        h('dt', null, 'Active opportunities'), h('dd', null, prof.active + ' (' + prof.open + ' open' + (prof.forecast ? ', ' + prof.forecast + ' forecast' : '') + ')'),
        h('dt', null, 'Organisation relationship'), h('dd', null, rel),
        h('dt', null, 'Last verified'), h('dd', null, new Date().toISOString().slice(0, 10))));
    var body;
    if (lens === 'funding') body = h('div', null, h('div', { style: { marginBottom: 14 } }, h(Coverage, { opps: prof.opps })), h(GroupedResults, { opps: prof.opps }), h(AskMira, { opps: prof.opps }));
    else if (lens === 'risk') body = h('div', { className: 'mx-empty' }, h('h3', null, 'No material funder changes detected'), h('p', null, 'Mira flags funder risk only on evidence of budget cuts, country withdrawal, programme suspension, strategy or eligibility changes. None are currently evidenced for ' + name + '.'));
    else { var cov = MX.coverage(prof.opps); body = h('div', { className: 'mx-card' }, h('div', { className: 'mx-section-h', style: { marginTop: 0 } }, 'Sources & evidence for ' + name), h('dl', { className: 'mx-kv' }, h('dt', null, 'Official sources'), h('dd', null, cov.sources || 'Derived from opportunity listings'), h('dt', null, 'Fields supported'), h('dd', null, 'Award amounts (' + cov.amountPct + '%), eligibility (' + cov.eligPct + '%)'), h('dt', null, 'Local-language availability'), h('dd', null, h('span', { className: 'mx-faint' }, 'None yet — coverage limited')), h('dt', null, 'Known coverage gaps'), h('dd', null, cov.amountPct < 60 ? 'Per-award amounts missing for most calls' : 'None flagged'), h('dt', null, 'Last verified'), h('dd', null, new Date().toISOString().slice(0, 10)))); }
    return h('div', null,
      h(ContextHeader, { eyebrow: 'Funder', title: name, sub: prof.active + ' opportunities · personalised for ' + org.name, actions: actions, tabs: tabs }),
      h('div', { className: 'mx-wrap', style: { paddingTop: 8 } }, header, body));
  }

  function OpportunityScreen(p) {
    var o = p.opps.filter(function (x) { return x.id === p.id; })[0];
    var drawer = React.useState(false); var showDrawer = drawer[0], setDrawer = drawer[1];
    var saved = React.useState(MX.store.isSaved(p.id)); var isSaved = saved[0], setSaved = saved[1];
    if (!o) return h('div', { className: 'mx-wrap' }, h('div', { className: 'mx-empty' }, h('h3', null, 'Opportunity not found'), h('button', { className: 'mx-btn', onClick: function () { go('#/mx/search'); } }, 'Back to search')));
    var org = MX.org(); var m = MX.match(o, org); var d = daysTo(o.deadline);
    var actions = [
      h('button', { key: 's', className: 'mx-btn mx-btn--sm', onClick: function () { if (isSaved) { MX.store.unsave(o.id); setSaved(false); } else { MX.store.save(o); setSaved(true); p.toast('Saved'); } } }, isSaved ? '✓ Saved' : 'Save'),
      h('button', { key: 'a', className: 'mx-btn mx-btn--primary mx-btn--sm', onClick: function () { var app = MX.store.createApp(o); p.toast('Application created'); go('#/mx/applications'); } }, 'Start application')];
    function money() {
      return h('dl', { className: 'mx-kv' },
        h('dt', null, 'Minimum award'), h('dd', null, o.amountMin != null ? MX.money.fmtGBP(MX.money.toGBP(o.amountMin, o.currency)) : 'Amount not published'),
        h('dt', null, 'Maximum award'), h('dd', null, o.amountMax != null ? MX.money.fmtGBP(MX.money.toGBP(o.amountMax, o.currency)) : 'Amount not published'),
        h('dt', null, 'Total programme budget'), h('dd', null, o.totalBudget != null ? MX.money.fmtGBP(MX.money.toGBP(o.totalBudget, o.currency)) + ' (envelope — not per award)' : 'Amount not published'),
        h('dt', null, 'Original currency'), h('dd', null, o.currency || 'Unknown'),
        h('dt', null, 'Analytical GBP'), h('dd', null, o.analyticalGBP != null ? MX.money.fmtGBP(o.analyticalGBP) + ' (as of ' + MX.money.GBP_AS_OF + ')' : 'Not derivable'),
        h('dt', null, 'Amount type'), h('dd', null, o.amountType.replace(/_/g, ' ')));
    }
    function dims() {
      var order = ['eligibility', 'geography', 'sector', 'applicantType', 'fundingSize', 'deadline', 'evidence'];
      return order.map(function (k) { var dd = m.dims[k]; if (!dd) return null; return h('div', { key: k, className: 'mx-dim' }, h('b', null, k.replace(/([A-Z])/g, ' $1').replace(/^./, function (c) { return c.toUpperCase(); })), h('span', { className: vClass(dd.verdict) }, dd.verdict + (dd.note ? ' — ' + dd.note : ''))); });
    }
    return h('div', null,
      h(ContextHeader, { eyebrow: o.funder, title: o.title, sub: o.type + ' · ' + o.status.replace(/_/g, ' ') + (d != null ? ' · closes in ' + d + ' days' : ' · no published deadline'), actions: actions }),
      h('div', { className: 'mx-wrap', style: { paddingTop: 8 } },
        h('div', { style: { marginBottom: 8 } }, catBadge(m.overall), o.trust === 'high' ? h('span', { className: 'mx-badge mx-b-monitor', style: { marginLeft: 6 } }, 'Verified source') : null),
        h('div', { className: 'mx-section-h' }, 'Summary'),
        h('p', { style: { fontSize: 14 } }, o.summary || h('span', { className: 'mx-faint' }, 'No summary published by the source.')),
        h('div', { className: 'mx-section-h' }, 'Funding'), money(),
        h('div', { className: 'mx-section-h' }, 'Eligibility'),
        h('dl', { className: 'mx-kv' },
          h('dt', null, 'Eligible countries'), h('dd', null, o.countries.length ? o.countries.join(', ') : h('span', { className: 'mx-faint' }, 'Not published')),
          h('dt', null, 'Eligible applicant types'), h('dd', null, o.eligible.length ? o.eligible.join(', ') : h('span', { className: 'mx-faint' }, 'Not published')),
          h('dt', null, 'Eligibility notes'), h('dd', null, o.eligibilityText || h('span', { className: 'mx-faint' }, 'Not published'))),
        h('div', { className: 'mx-section-h' }, 'Match analysis'),
        h('div', null, dims()),
        h('div', { style: { marginTop: 10, fontWeight: 700, fontSize: 14 } }, 'Overall: ', catBadge(m.overall), m.hardFail ? h('span', { className: 'mx-muted', style: { fontWeight: 400, marginLeft: 8 } }, 'Hard eligibility failure overrides other strengths.') : null),
        m.reasons.length ? h('div', null, h('div', { className: 'mx-section-h' }, 'Why it matches'), h('ul', null, m.reasons.map(function (r, i) { return h('li', { key: i, style: { fontSize: 13.5, color: 'var(--mx-strong)' } }, r); }))) : null,
        m.concerns.length ? h('div', null, h('div', { className: 'mx-section-h' }, 'What weakens the match'), h('ul', null, m.concerns.map(function (r, i) { return h('li', { key: i, style: { fontSize: 13.5, color: 'var(--mx-warn)' } }, r); }))) : null,
        m.missing.length ? h('div', null, h('div', { className: 'mx-section-h' }, 'Missing information'), h('ul', null, m.missing.map(function (r, i) { return h('li', { key: i, style: { fontSize: 13.5 }, className: 'mx-faint' }, r + ' — Mira cannot verify this'); }))) : null,
        h('div', { className: 'mx-section-h' }, 'Recommended action'),
        h('p', { style: { fontSize: 14, fontWeight: 600, color: 'var(--mx-ink)' } }, MX.goNoGo(o, org).recommendation),
        h('div', { className: 'mx-section-h' }, 'Sources'),
        h('button', { className: 'mx-btn mx-btn--sm', onClick: function () { setDrawer(true); } }, 'View evidence for every field'),
        o.url ? h('span', { style: { marginLeft: 10 } }, h('a', { className: 'mx-source-link', href: o.url, target: '_blank', rel: 'noopener' }, 'Official listing ↗')) : null),
      showDrawer ? h(SourcesDrawer, { opp: o, onClose: function () { setDrawer(false); } }) : null);
  }

  function ApplicationsScreen(p) {
    var apps = MX.store.apps();
    var tk = React.useState(0); var setTick = tk[1];
    if (!apps.length) return h('div', null, h(ContextHeader, { eyebrow: 'Applications', title: 'Applications', sub: 'Your funding pipeline' }),
      h('div', { className: 'mx-wrap' }, h('div', { className: 'mx-empty' }, h('h3', null, 'No applications yet'), h('p', null, 'Save an opportunity or start an application to build your pipeline.'), h('button', { className: 'mx-btn mx-btn--primary', style: { marginTop: 10 }, onClick: function () { go('#/mx/search'); } }, 'Find opportunities'))));
    var byStage = {}; MX.APP_STAGES.forEach(function (s) { byStage[s] = []; });
    apps.forEach(function (a) { (byStage[a.stage] = byStage[a.stage] || []).push(a); });
    return h('div', null, h(ContextHeader, { eyebrow: 'Applications', title: 'Pipeline', sub: apps.length + ' in progress' }),
      h('div', { className: 'mx-wrap' }, MX.APP_STAGES.map(function (stage) {
        var items = byStage[stage] || []; if (!items.length) return null;
        return h('div', { key: stage }, h('div', { className: 'mx-group-h' }, h('h3', null, stage), h('span', { className: 'mx-count' }, items.length)),
          items.map(function (a) {
            var d = daysTo(a.deadline);
            return h('div', { key: a.id, className: 'mx-card', style: { marginBottom: 10 } },
              h('div', { style: { fontWeight: 600, color: 'var(--mx-ink)' } }, a.title),
              h('div', { className: 'mx-lr-meta' }, a.funder, d != null ? ' · deadline in ' + d + ' days' : ' · no deadline', a.owner ? ' · owner ' + a.owner : ''),
              h('div', { style: { display: 'flex', gap: 6, marginTop: 10, flexWrap: 'wrap', alignItems: 'center' } },
                h('button', { className: 'mx-btn mx-btn--primary mx-btn--sm', onClick: function () { go('#/mx/applications/' + a.id); } }, 'Open workspace'),
                h('span', { className: 'mx-faint', style: { fontSize: 12 } }, 'Move to:'),
                MX.APP_STAGES.filter(function (s) { return s !== a.stage; }).slice(0, 4).map(function (s) {
                  return h('button', { key: s, className: 'mx-btn mx-btn--sm', onClick: function () { MX.store.updateApp(a.id, { stage: s, updatedAt: Date.now() }); setTick(Date.now()); } }, s);
                })));
          }));
      })));
  }

  function ApplicationWorkspace(p) {
    var apps = MX.store.apps(); var app = apps.filter(function (x) { return x.id === p.id; })[0];
    var tk = React.useState(0); var setTick = tk[1];
    var noteSt = React.useState(''); var note = noteSt[0], setNote = noteSt[1];
    var taskSt = React.useState(''); var task = taskSt[0], setTask = taskSt[1];
    var reasonSt = React.useState((app && app.decisionReason) || ''); var reason = reasonSt[0], setReason = reasonSt[1];
    if (!app) return h('div', { className: 'mx-wrap' }, h('div', { className: 'mx-empty' }, h('h3', null, 'Application not found'), h('button', { className: 'mx-btn', onClick: function () { go('#/mx/applications'); } }, 'Back to pipeline')));
    var opp = p.opps.filter(function (x) { return x.id === app.oppId; })[0];
    var org = MX.org();
    var gng = opp ? MX.goNoGo(opp, org) : null;
    var d = daysTo(app.deadline);
    function upd(patch) { MX.store.updateApp(app.id, Object.assign({ updatedAt: Date.now() }, patch)); setTick(Date.now()); }
    var actions = [
      opp ? h('button', { key: 'src', className: 'mx-btn mx-btn--sm', onClick: function () { go('#/mx/opportunity/' + opp.id); } }, 'Return to opportunity') : null,
      h('button', { key: 'arch', className: 'mx-btn mx-btn--sm', onClick: function () { upd({ stage: 'Withdrawn', archived: true }); p.toast('Application archived'); go('#/mx/applications'); } }, 'Archive')];
    return h('div', null,
      h(ContextHeader, { eyebrow: app.funder, title: app.title, sub: 'Stage: ' + app.stage + (d != null ? ' · deadline in ' + d + ' days' : ' · no deadline') + (app.updatedAt ? ' · updated ' + new Date(app.updatedAt).toLocaleDateString('en-GB') : ''), actions: actions }),
      h('div', { className: 'mx-wrap', style: { paddingTop: 8 } },
        // Stage
        h('div', { className: 'mx-section-h', style: { marginTop: 0 } }, 'Stage'),
        h('div', { style: { display: 'flex', gap: 6, flexWrap: 'wrap' } }, MX.APP_STAGES.map(function (s) { return h('button', { key: s, className: 'mx-btn mx-btn--sm' + (s === app.stage ? ' mx-btn--primary' : ''), onClick: function () { upd({ stage: s }); } }, s); })),
        // Owner
        h('div', { className: 'mx-section-h' }, 'Owner & team'),
        h('div', { style: { display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' } },
          h('input', { className: 'mx-input', placeholder: 'Assign owner (name/email)', defaultValue: app.owner || '', onBlur: function (e) { upd({ owner: e.target.value.trim() }); } }),
          h('span', { className: 'mx-faint', style: { fontSize: 12 } }, app.owner ? 'Owner: ' + app.owner : 'No owner assigned')),
        // Go/no-go
        h('div', { className: 'mx-section-h' }, 'Go / no-go decision'),
        gng ? h('div', { className: 'mx-card' },
          h('div', { style: { fontSize: 13.5 } }, h('b', null, 'Mira recommendation: '), gng.recommendation),
          h('div', { className: 'mx-faint', style: { fontSize: 12, margin: '4px 0 8px' } }, gng.note),
          gng.keyRisks.length ? h('div', { className: 'mx-lr-concern', style: { fontSize: 12.5 } }, 'Key risks: ' + gng.keyRisks.join('; ')) : null,
          gng.missing.length ? h('div', { className: 'mx-faint', style: { fontSize: 12.5 } }, 'Missing: ' + gng.missing.join(', ')) : null,
          h('textarea', { className: 'mx-input', style: { width: '100%', marginTop: 10, minHeight: 60 }, placeholder: 'Decision reasoning…', value: reason, onChange: function (e) { setReason(e.target.value); } }),
          h('div', { style: { display: 'flex', gap: 6, marginTop: 8 } },
            h('button', { className: 'mx-btn mx-btn--primary mx-btn--sm', onClick: function () { upd({ decision: 'Go', decisionReason: reason, stage: 'Preparing', decisionAt: Date.now() }); p.toast('Decision recorded: Go'); } }, 'Record: Go'),
            h('button', { className: 'mx-btn mx-btn--sm', onClick: function () { upd({ decision: 'No-go', decisionReason: reason, stage: 'Withdrawn', decisionAt: Date.now() }); p.toast('Decision recorded: No-go'); } }, 'Record: No-go')),
          app.decision ? h('div', { style: { marginTop: 8, fontSize: 13, fontWeight: 600, color: app.decision === 'Go' ? 'var(--mx-strong)' : 'var(--mx-crit)' } }, 'Recorded: ' + app.decision + (app.decisionReason ? ' — ' + app.decisionReason : '')) : null) : h('p', { className: 'mx-faint' }, 'Source opportunity no longer in the dataset — decision brief unavailable.'),
        // Tasks
        h('div', { className: 'mx-section-h' }, 'Tasks'),
        (app.tasks || []).map(function (t, i) { return h('label', { key: i, style: { display: 'flex', gap: 8, alignItems: 'center', padding: '4px 0', fontSize: 13.5, textDecoration: t.done ? 'line-through' : 'none', color: t.done ? 'var(--mx-faint)' : 'var(--mx-body)' } }, h('input', { type: 'checkbox', checked: !!t.done, onChange: function () { var tasks = (app.tasks || []).slice(); tasks[i] = Object.assign({}, t, { done: !t.done }); upd({ tasks: tasks }); } }), t.text); }),
        h('form', { onSubmit: function (e) { e.preventDefault(); if (!task.trim()) return; upd({ tasks: (app.tasks || []).concat([{ text: task.trim(), done: false }]) }); setTask(''); }, style: { display: 'flex', gap: 6, marginTop: 6 } },
          h('input', { className: 'mx-input', style: { flex: 1 }, placeholder: 'Add a task…', value: task, onChange: function (e) { setTask(e.target.value); } }), h('button', { className: 'mx-btn mx-btn--sm' }, 'Add')),
        // Notes
        h('div', { className: 'mx-section-h' }, 'Notes'),
        (app.notes || []).map(function (n, i) { return h('div', { key: i, className: 'mx-card', style: { marginBottom: 6, fontSize: 13 } }, h('div', { className: 'mx-faint', style: { fontSize: 11 } }, new Date(n.at).toLocaleString('en-GB')), n.text); }),
        h('form', { onSubmit: function (e) { e.preventDefault(); if (!note.trim()) return; upd({ notes: (app.notes || []).concat([{ text: note.trim(), at: Date.now() }]) }); setNote(''); }, style: { display: 'flex', gap: 6, marginTop: 6 } },
          h('input', { className: 'mx-input', style: { flex: 1 }, placeholder: 'Add a note…', value: note, onChange: function (e) { setNote(e.target.value); } }), h('button', { className: 'mx-btn mx-btn--sm' }, 'Add')),
        // Missing info + docs + drafting
        h('div', { className: 'mx-section-h' }, 'Missing information'),
        h('ul', null, (gng && gng.missing.length ? gng.missing : ['None flagged']).map(function (m, i) { return h('li', { key: i, className: 'mx-faint', style: { fontSize: 13 } }, m); })),
        h('div', { className: 'mx-section-h' }, 'Evidence-backed drafting'),
        h('p', { className: 'mx-faint', style: { fontSize: 13 } }, 'Coming later — drafting will only be enabled once the organisation evidence system is reliable (never fabricated).')));
  }

  function TodayScreen(p) {
    var pins = MX.store.pins();
    var apps = MX.store.apps();
    return h('div', null,
      h(ContextHeader, { eyebrow: new Date().toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long' }), title: 'Today', sub: pins.length ? 'Changes across your pinned views' : 'Compose your intelligence board' }),
      h('div', { className: 'mx-wrap' },
        pins.length ? h('div', null,
          h('div', { className: 'mx-cov', style: { marginBottom: 16 } }, h('b', null, 'Executive summary. '), pins.length + ' pinned view' + (pins.length === 1 ? '' : 's') + ', ' + apps.length + ' application' + (apps.length === 1 ? '' : 's') + ' in your pipeline. No developments require action today.'),
          h('div', { className: 'mx-grid2' }, pins.map(function (pin, i) {
            return h('div', { key: i, className: 'mx-tile' },
              h('div', { className: 'mx-eyebrow' }, pin.entity + ' · ' + pin.lens),
              h('div', { style: { fontFamily: 'var(--mx-serif)', fontSize: 18, color: 'var(--mx-ink)' } }, pin.name),
              h('div', { className: 'mx-faint', style: { fontSize: 12.5 } }, 'No meaningful changes since you pinned this'),
              h('div', { style: { display: 'flex', gap: 6, marginTop: 6 } },
                h('button', { className: 'mx-btn mx-btn--sm', onClick: function () { go('#/mx/country/' + encodeURIComponent(pin.name) + '/' + pin.lens); } }, 'Open'),
                h('button', { className: 'mx-btn mx-btn--sm', onClick: function () { MX.store.unpin(pin.key); p.refresh(); } }, 'Unpin')));
          }))) : h('div', { className: 'mx-empty' },
          h('h3', null, 'Your board is empty'),
          h('p', null, 'Pin an entity-lens view — for example a country’s funding — and Today will show only what changed.'),
          h('div', { style: { display: 'flex', gap: 8, justifyContent: 'center', marginTop: 12, flexWrap: 'wrap' } },
            h('button', { className: 'mx-btn mx-btn--primary', onClick: function () { go('#/mx/country/Pakistan/funding'); } }, 'Pakistan · Funding'),
            h('button', { className: 'mx-btn', onClick: function () { go('#/mx/country/Kenya/funding'); } }, 'Kenya · Funding'),
            h('button', { className: 'mx-btn', onClick: function () { go('#/mx/search'); } }, 'Search')))));
  }

  function SettingsScreen(p) {
    var org = MX.org();
    return h('div', null, h(ContextHeader, { eyebrow: 'Settings', title: 'Settings', sub: 'Organisation, team and billing' }),
      h('div', { className: 'mx-wrap' },
        h('div', { className: 'mx-card', style: { marginBottom: 14 } },
          h('div', { className: 'mx-section-h', style: { marginTop: 0 } }, 'Organisation'),
          h('dl', { className: 'mx-kv' },
            h('dt', null, 'Name'), h('dd', null, org.name, org._demo ? h('span', { className: 'mx-faint' }, ' (demo profile — not confirmed)') : null),
            h('dt', null, 'Type'), h('dd', null, (org.types || []).join(', ')),
            h('dt', null, 'Operating countries'), h('dd', null, (org.countries || []).join(', ')),
            h('dt', null, 'Sectors'), h('dd', null, (org.sectors || []).join(', ')),
            h('dt', null, 'Preferred funding range'), h('dd', null, MX.money.fmtGBP(org.preferredMinGBP) + ' – ' + MX.money.fmtGBP(org.preferredMaxGBP)))),
        h('div', { className: 'mx-card' }, h('div', { className: 'mx-section-h', style: { marginTop: 0 } }, 'Team & Billing'), h('p', { className: 'mx-muted', style: { fontSize: 13 } }, 'Team and billing management move here from the old top-level nav (§4). Wiring to the enterprise_* tables is a later phase.'))));
  }

  // ── Shell + router ──────────────────────────────────────────────────────────
  function Root() {
    var st = React.useState(location.hash); var hash = st[0], setHash = st[1];
    var od = React.useState(null); var opps = od[0], setOpps = od[1];
    var tk = React.useState(0); var setTick = tk[1];
    var toastSt = React.useState(null); var toast = toastSt[0], setToast = toastSt[1];
    React.useEffect(function () { function on() { setHash(location.hash); } window.addEventListener('hashchange', on); return function () { window.removeEventListener('hashchange', on); }; }, []);
    React.useEffect(function () { MX.loadOpportunities().then(setOpps); }, []);
    function fireToast(msg) { setToast(msg); setTimeout(function () { setToast(null); }, 2200); }
    function refresh() { setTick(Date.now()); }
    if (opps == null) return h('div', { id: 'mx-root' }, h('div', { style: { margin: 'auto', color: 'var(--mx-muted)' } }, 'Loading real funding data…'));
    var parts = hash.replace(/^#\/mx\/?/, '').split('/');
    var screen = parts[0] || 'today';
    var props = { opps: opps, refresh: refresh, toast: fireToast };
    var content;
    if (screen === 'search') content = h(SearchScreen, props);
    else if (screen === 'country') content = h(CountryScreen, Object.assign({}, props, { id: decodeURIComponent(parts[1] || ''), lens: parts[2] || 'funding' }));
    else if (screen === 'funder') content = h(FunderScreen, Object.assign({}, props, { id: decodeURIComponent(parts[1] || ''), lens: parts[2] || 'funding' }));
    else if (screen === 'opportunity') content = h(OpportunityScreen, Object.assign({}, props, { id: parts[1] }));
    else if (screen === 'applications') content = parts[1] ? h(ApplicationWorkspace, Object.assign({}, props, { id: parts[1] })) : h(ApplicationsScreen, props);
    else if (screen === 'settings') content = h(SettingsScreen, props);
    else content = h(TodayScreen, props);
    var nav = [['today', 'Today', '#/mx'], ['search', 'Search', '#/mx/search'], ['applications', 'Applications', '#/mx/applications'], ['settings', 'Settings', '#/mx/settings']];
    return h('div', { id: 'mx-root' },
      h('nav', { className: 'mx-nav' },
        h('div', { className: 'mx-wordmark' }, 'Globally', h('small', null, 'Mira Enterprise')),
        nav.map(function (n) { return h('button', { key: n[0], className: 'mx-navitem' + (screen === n[0] || (screen === 'today' && n[0] === 'today') ? ' on' : ''), onClick: function () { go(n[2]); } }, n[1]); }),
        h('div', { className: 'mx-navspacer' }),
        h('div', { className: 'mx-faint', style: { fontSize: 11, padding: '0 10px' } }, 'Rebuild preview · #/mx')),
      h('main', { className: 'mx-main', key: hash }, content),
      toast ? h('div', { style: { position: 'fixed', bottom: 22, left: '50%', transform: 'translateX(-50%)', background: 'var(--mx-ink)', color: '#fff', padding: '10px 18px', borderRadius: 10, fontSize: 13, zIndex: 4200 } }, toast) : null);
  }

  // ── mount (dev-only, on #/mx) ───────────────────────────────────────────────
  var rootEl = null, reactRoot = null;
  function ensureMount() {
    // Retired: the separate #/mx prototype shell now redirects into the real
    // integrated Enterprise product. One Mira Enterprise, one shell.
    if (/^#\/mx/.test(location.hash)) { if (rootEl) rootEl.style.display = 'none'; location.replace(location.pathname + location.search + '#/enterprise/today'); return; }
    if (rootEl) rootEl.style.display = 'none';
  }
  window.addEventListener('hashchange', ensureMount);
  if (document.readyState !== 'loading') ensureMount(); else document.addEventListener('DOMContentLoaded', ensureMount);
})();
