/* FORGE — Acts 5–6 pump screens (S31, S32, S33, S34, S35, S37, S38).
   Babel-standalone, no imports/exports. Single registry tail.
   Mode color cues: line:// green, auditor:// ink-gray, forge:// blue. */

const { useState: uSA56, useEffect: uEA56, useMemo: uMA56 } = React;

/* ─────────────────────────────────────────────────────────────────────────
   Shared paper-deck atoms used across all 7 screens
   ───────────────────────────────────────────────────────────────────────── */

const A56_PAPER = {
  bg:        "oklch(0.985 0.004 85)",
  bg2:       "oklch(0.965 0.005 85)",
  bg3:       "oklch(0.93 0.005 85)",
  ink:       "oklch(0.16 0.01 85)",
  ink2:      "oklch(0.30 0.01 85)",
  ink3:      "oklch(0.46 0.01 85)",
  ink4:      "oklch(0.60 0.01 85)",
  line:      "oklch(0.84 0.006 85)",
  lineSoft:  "oklch(0.90 0.005 85)",
  green:     "oklch(0.62 0.16 145)",
  greenSoft: "oklch(0.94 0.06 145)",
  blue:      "oklch(0.52 0.13 250)",
  blueSoft:  "oklch(0.94 0.05 250)",
  red:       "oklch(0.55 0.18 28)",
  redSoft:   "oklch(0.94 0.07 28)",
  amber:     "oklch(0.70 0.13 75)",
  amberSoft: "oklch(0.95 0.07 75)",
  inkBg:     "oklch(0.96 0.003 85)",
};

const A56_FONT_UI    = "var(--font-ui)";
const A56_FONT_MONO  = "var(--font-mono)";
const A56_FONT_SERIF = "var(--font-serif)";

/* Locale-aware money/date — degrades gracefully when forgeI18n not yet loaded.
   minor = integer paise/cents (1 lakh INR = 10_000_000 paise). */
function _a56_money(minor, currency, fallback) {
  const i18n = (typeof window !== "undefined") ? window.forgeI18n : null;
  if (i18n && typeof i18n.formatMoneyMinor === "function") {
    const out = i18n.formatMoneyMinor(minor, currency || "INR");
    if (out) return out;
  }
  return fallback;
}
function _a56_date(iso, fallback) {
  const i18n = (typeof window !== "undefined") ? window.forgeI18n : null;
  if (i18n && typeof i18n.formatDate === "function") {
    const out = i18n.formatDate(iso);
    if (out) return out;
  }
  return fallback || iso;
}

/* Extracted styles (react-doctor: no-inline-exhaustive-style). */
function _a56PillStyle(palette) {
  return {
    display: "inline-flex", alignItems: "center", gap: 6, height: 20,
    padding: "0 8px", borderRadius: 999,
    fontFamily: A56_FONT_MONO, fontSize: 12,
    letterSpacing: "0.06em", textTransform: "uppercase",
    border: "1px solid " + palette.br, color: palette.fg, background: palette.bg,
  };
}
function _a56BtnStyle(s, h, small) {
  return {
    display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 6,
    height: small ? 26 : 32, padding: small ? "0 10px" : "0 14px",
    borderRadius: 6, cursor: "pointer",
    border: "1px solid " + s.br,
    background: h ? "color-mix(in oklch, " + s.bg + " 88%, white)" : s.bg,
    color: s.fg, fontFamily: A56_FONT_UI, fontSize: small ? 11 : 12, fontWeight: 600,
    letterSpacing: "-0.005em", whiteSpace: "nowrap", userSelect: "none",
    transition: "transform .12s ease, background .12s ease",
    transform: h ? "translateY(-1px)" : "translateY(0)",
  };
}
const _A56_TOOLBAR_STYLE = {
  display: "flex", alignItems: "center", justifyContent: "space-between",
  padding: "10px 16px", background: A56_PAPER.bg2,
  border: "1px solid " + A56_PAPER.line, borderRadius: 8, gap: 12,
};
const _A56_KEY_FP_STYLE = {
  marginTop: 14, padding: 10,
  background: A56_PAPER.bg, border: "1px dashed " + A56_PAPER.line,
  borderRadius: 4, fontFamily: A56_FONT_MONO, fontSize: 12,
  color: A56_PAPER.ink3,
};
const _A56_RAW_JSON_STYLE = {
  margin: "10px 0 0", padding: 10, background: A56_PAPER.bg2,
  border: "1px solid " + A56_PAPER.lineSoft, borderRadius: 4,
  fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2,
  whiteSpace: "pre-wrap", wordBreak: "break-all",
};
function _a56TraceDotStyle(tone) {
  return {
    width: 14, height: 14, borderRadius: 7,
    background: A56_PAPER.bg2, border: "2px solid " + tone, flexShrink: 0,
    marginTop: 2,
  };
}
function _a56TypeChipStyle(active, c) {
  return {
    height: 22, padding: "0 8px", borderRadius: 999,
    fontFamily: A56_FONT_MONO, fontSize: 12,
    letterSpacing: "0.06em", textTransform: "uppercase",
    border: "1px solid " + (active ? c : A56_PAPER.line),
    background: active ? "color-mix(in oklch, " + c + " 14%, transparent)" : A56_PAPER.bg,
    color: active ? A56_PAPER.ink : A56_PAPER.ink3, cursor: "pointer",
  };
}
const _A56_DAY_HEADER_STYLE = {
  position: "sticky", top: 0, zIndex: 10,
  background: A56_PAPER.inkBg,
  borderBottom: "1px solid " + A56_PAPER.ink,
  padding: "8px 0",
  marginBottom: 10,
  display: "flex", alignItems: "baseline", gap: 12,
};
function _a56TypeBadgeStyle(tcolor) {
  return {
    display: "inline-flex", alignItems: "center", height: 20, padding: "0 8px",
    borderRadius: 4, fontFamily: A56_FONT_MONO, fontSize: 12,
    letterSpacing: "0.06em", textTransform: "uppercase",
    color: A56_PAPER.ink2, border: "1px solid " + tcolor,
    background: "color-mix(in oklch, " + tcolor + " 8%, transparent)",
  };
}
function _a56ModeBadgeStyle(mcolor) {
  return {
    display: "inline-flex", alignItems: "center", height: 20, padding: "0 8px",
    borderRadius: 4, fontFamily: A56_FONT_MONO, fontSize: 12,
    letterSpacing: "0.04em",
    color: A56_PAPER.ink2, border: "1px solid " + mcolor,
    background: "color-mix(in oklch, " + mcolor + " 8%, transparent)",
  };
}
const _A56_VIEW_RAW_BTN_STYLE = {
  border: "1px solid " + A56_PAPER.line, background: "transparent",
  padding: "2px 8px", borderRadius: 3, cursor: "pointer",
  fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3,
  letterSpacing: "0.04em",
};
function _a56CartDrawerStyle() {
  return {
    position: "fixed", right: 24, bottom: 24, width: 360,
    background: A56_PAPER.bg2, border: "1px solid " + A56_PAPER.ink,
    borderRadius: 8, boxShadow: "0 12px 32px rgba(0,0,0,0.10)",
    padding: 16, zIndex: A56_Z.drawer,
  };
}
const _A56_QTY_BTN_STYLE = {
  width: 24, height: 24, borderRadius: 4,
  border: "1px solid " + A56_PAPER.line, background: A56_PAPER.bg2,
  cursor: "pointer", fontFamily: A56_FONT_MONO, color: A56_PAPER.ink2,
};
const _A56_GREEN_BANNER_STYLE = {
  marginBottom: 16, padding: "14px 16px",
  background: A56_PAPER.greenSoft, border: "1px solid " + A56_PAPER.green,
  borderRadius: 8, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16,
};
function _a56FieldPhotoStyle(has) {
  return {
    aspectRatio: "4/3", background: has ? A56_PAPER.bg3 : A56_PAPER.bg,
    border: "1px solid " + A56_PAPER.lineSoft, borderRadius: 4,
    display: "flex", alignItems: "center", justifyContent: "center",
    fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3,
  };
}
const _A56_BANG_DOT_STYLE = {
  width: 28, height: 28, borderRadius: 14,
  background: A56_PAPER.red, color: "#fff",
  display: "inline-flex", alignItems: "center", justifyContent: "center",
  fontWeight: 700,
};
const _A56_RED_BANNER_STYLE = {
  marginBottom: 16, padding: "12px 16px",
  background: A56_PAPER.redSoft, border: "1px solid " + A56_PAPER.red, borderRadius: 8,
  display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12,
};
const _A56_CHECK_TICK_STYLE = {
  display: "inline-block", width: 14, height: 14, borderRadius: 3,
  background: A56_PAPER.green, color: "#fff", fontSize: 12,
  textAlign: "center", lineHeight: "14px", fontWeight: 700,
};
const _A56_FOOTER_STRIP_STYLE = {
  marginTop: 28, paddingTop: 16,
  borderTop: "1px solid " + A56_PAPER.line,
  fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3,
  display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12,
};
const _A56_MODEL_BOX_STYLE = {
  display: "inline-block", padding: "6px 12px",
  border: "1px solid " + A56_PAPER.ink, borderRadius: 4,
  fontFamily: A56_FONT_MONO, fontSize: 12,
  letterSpacing: "0.10em", textTransform: "uppercase",
};
function _a56FlashStyle(palette) {
  return {
    position: "fixed", top: 64, right: 24, zIndex: A56_Z.toast,
    padding: "10px 14px", borderRadius: 8,
    border: "1px solid " + palette.br, background: palette.bg, color: palette.fg,
    fontFamily: A56_FONT_UI, fontSize: 13, boxShadow: "0 6px 18px rgba(0,0,0,0.08)",
    display: "flex", alignItems: "center", gap: 10,
  };
}

function A56Pill({ tone, children }) {
  const palette = {
    ok:    { bg: A56_PAPER.greenSoft, fg: A56_PAPER.ink2, br: A56_PAPER.green },
    warn:  { bg: A56_PAPER.amberSoft, fg: A56_PAPER.ink2, br: A56_PAPER.amber },
    err:   { bg: A56_PAPER.redSoft,   fg: A56_PAPER.ink2, br: A56_PAPER.red   },
    info:  { bg: A56_PAPER.blueSoft,  fg: A56_PAPER.ink2, br: A56_PAPER.blue  },
    "":    { bg: A56_PAPER.bg2,       fg: A56_PAPER.ink2,  br: A56_PAPER.line  },
  }[tone || ""] || { bg: A56_PAPER.bg2, fg: A56_PAPER.ink2, br: A56_PAPER.line };
  return (
    <span style={_a56PillStyle(palette)}>{children}</span>
  );
}

function A56Btn({ variant, onClick, children, small }) {
  const [h, setH] = uSA56(false);
  const v = variant || "ghost";
  const map = {
    primary: { bg: A56_PAPER.ink,  fg: A56_PAPER.bg,  br: A56_PAPER.ink  },
    blue:    { bg: A56_PAPER.blue, fg: "#fff",        br: A56_PAPER.blue },
    green:   { bg: A56_PAPER.green,fg: A56_PAPER.ink, br: A56_PAPER.green},
    danger:  { bg: A56_PAPER.red,  fg: "#fff",        br: A56_PAPER.red  },
    ghost:   { bg: "transparent",  fg: A56_PAPER.ink, br: A56_PAPER.line },
    soft:    { bg: A56_PAPER.bg3,  fg: A56_PAPER.ink, br: A56_PAPER.line },
  };
  const s = map[v] || map.ghost;
  return (
    <button
      onMouseEnter={function(){ setH(true); }}
      onMouseLeave={function(){ setH(false); }}
      onClick={onClick}
      style={_a56BtnStyle(s, h, small)}>
      {children}
    </button>
  );
}

function A56Card({ children, style, pad }) {
  return (
    <div style={Object.assign({
      background: A56_PAPER.bg2, border: "1px solid " + A56_PAPER.line,
      borderRadius: 8, padding: pad || 16,
    }, style || {})}>{children}</div>
  );
}

function A56SectionTitle({ children, kicker }) {
  return (
    <div style={{ marginBottom: 12 }}>
      {kicker && (
        <div style={{
          fontFamily: A56_FONT_MONO, fontSize: 12,
          letterSpacing: "0.10em", textTransform: "uppercase",
          color: A56_PAPER.ink3, marginBottom: 4,
        }}>{kicker}</div>
      )}
      <div style={{
        fontFamily: A56_FONT_SERIF, fontSize: 22,
        color: A56_PAPER.ink, letterSpacing: "-0.01em",
      }}>{children}</div>
    </div>
  );
}

function A56Toolbar({ left, right }) {
  return (
    <div style={_A56_TOOLBAR_STYLE}>
      <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>{left}</div>
      <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>{right}</div>
    </div>
  );
}

// Local z-index scale (deliberate, ≤50)
const A56_Z = { drawer: 20, toast: 30 };

function A56Flash({ kind, msg, onClose }) {
  if (!msg) return null;
  const palette = kind === "ok" ? { bg: A56_PAPER.greenSoft, fg: A56_PAPER.ink2, br: A56_PAPER.green }
    : kind === "warn" ? { bg: A56_PAPER.amberSoft, fg: A56_PAPER.ink2, br: A56_PAPER.amber }
    : kind === "err" ? { bg: A56_PAPER.redSoft, fg: A56_PAPER.ink2, br: A56_PAPER.red }
    : { bg: A56_PAPER.blueSoft, fg: A56_PAPER.ink2, br: A56_PAPER.blue };
  return (
    <div style={_a56FlashStyle(palette)}>
      <span>{msg}</span>
      <button onClick={onClose} style={{
        border: 0, background: "transparent", color: palette.fg,
        cursor: "pointer", fontSize: 16, lineHeight: 1,
      }}>×</button>
    </div>
  );
}

function A56UseFlash() {
  const [flash, setFlash] = uSA56(null);
  uEA56(function() {
    if (!flash) return;
    const id = setTimeout(function(){ setFlash(null); }, 3200);
    return function() { clearTimeout(id); };
  }, [flash]);
  return [flash, setFlash];
}


/* ═══════════════════════════════════════════════════════════════════════
   ECO state-machine plumbing — stubs for week-1 pump-data integration.
   These define:
     • window.forgeApi.eco.{submit, transition, release} — in-place mutators
     • window.forgeApi.fcp.health()                       — stub probe
     • window.useTenantState()                            — re-render hook
     • window.__forgeCurrentUser                          — active actor
     • window.SwitchUserPill                              — 5-person picker
   Real auth + a real API replace these at integration.
   ═══════════════════════════════════════════════════════════════════════ */

/* one-shot bootstrap — idempotent, runs once at load */
(function eco_bootstrap() {
  if (typeof window === "undefined") return;

  // Default current actor — derive from the active tenant's people roster so
  // a fresh Aetherion / Mittelstand session doesn't leak Tritan's Ishaan R.
  // as the global default. If the active tenant isn't resolvable yet (very
  // early boot), retry on the first forge:tenant-change event and once after
  // a short timeout in case load order races (active-tenant.jsx should load
  // before this file per index.html, but the listener is belt-and-suspenders).
  function _resolveDefaultActor() {
    if (window.__forgeCurrentUser) return; // already set (user action or earlier resolve)
    var tenant = (typeof window.getActiveTenant === "function") ? window.getActiveTenant() : null;
    var people = (tenant && Array.isArray(tenant.people)) ? tenant.people : [];
    if (people.length === 0) return;
    var def = people.find(function(p) { return /compliance|quality|design|lead/i.test(p.role); }) || people[0];
    window.__forgeCurrentUser = { id: def.id, name: def.name, role: def.role };
  }
  _resolveDefaultActor();
  if (!window.__forgeCurrentUser) {
    // active-tenant.jsx may not have loaded yet — listen for the next tenant
    // change event, and also retry shortly in case the load order races.
    window.addEventListener("forge:tenant-change", _resolveDefaultActor);
    setTimeout(_resolveDefaultActor, 100);
  }

  // Fire forge:tenant-change so all useActiveTenant subscribers re-render.
  function bump() {
    try {
      window.dispatchEvent(new CustomEvent("forge:tenant-change", { detail: { reason: "eco-mutation" } }));
    } catch (e) { /* ignore */ }
  }

  // useTenantState — read-through to PUMP_TENANT with bump-on-change re-render.
  if (typeof window.useTenantState !== "function") {
    window.useTenantState = function useTenantState() {
      const [, setBump] = React.useState(0);
      React.useEffect(function() {
        function onChange() { setBump(function(b) { return b + 1; }); }
        window.addEventListener("forge:tenant-change", onChange);
        return function() { window.removeEventListener("forge:tenant-change", onChange); };
      }, []);
      return window.PUMP_TENANT;
    };
  }

  // forgeApi stubs — in-place mutate PUMP_TENANT and emit ledger events.
  window.forgeApi = window.forgeApi || {};
  if (!window.forgeApi.eco) {
    window.forgeApi.eco = {
      submit: function(eco) {
        var state = window.PUMP_TENANT;
        if (!state || !Array.isArray(state.eco)) return Promise.reject(new Error("no tenant"));
        // ensure structural fields
        eco.status = eco.status || "draft";
        eco.transitions = eco.transitions || [{ from: null, to: eco.status, actor: eco.originator || "—", ts: new Date().toISOString() }];
        eco.approval_chain = eco.approval_chain || [];
        state.eco.push(eco);
        state.ledger.push({
          event_id: "E-" + ("0000" + (state.ledger.length + 1)).slice(-4),
          ts: new Date().toISOString().replace(/\.\d{3}Z$/, "Z"),
          type: "eco_raised",
          mode: "build",
          actor: eco.originator || "—",
          summary: eco.id + " raised · " + eco.title,
          ref: eco.id,
        });
        bump();
        return Promise.resolve(eco);
      },
      transition: function(id, verb, body) {
        var state = window.PUMP_TENANT;
        if (!state || !Array.isArray(state.eco)) return Promise.reject(new Error("no tenant"));
        var eco = state.eco.find(function(e) { return e.id === id; });
        if (!eco) return Promise.reject(new Error("eco not found: " + id));
        var actor = (body && body.actor) || (window.__forgeCurrentUser && window.__forgeCurrentUser.name) || "—";
        var nowIso = new Date().toISOString();
        var nowDay = nowIso.slice(0, 10);
        var prev = eco.status;

        // chain entry sign-off (for "approve" / "reject" verbs)
        if (verb === "approve" || verb === "reject") {
          var role = body && body.role;
          var chain = eco.approval_chain || [];
          // sign the first chain entry whose name matches actor (or role if provided), or first pending
          var idx = -1;
          for (var i = 0; i < chain.length; i++) {
            if (chain[i].status !== "pending") continue;
            if ((role && chain[i].role === role) || chain[i].name === actor) { idx = i; break; }
          }
          if (idx < 0) {
            // fallback: first pending
            idx = chain.findIndex(function(c) { return c.status === "pending"; });
          }
          if (idx >= 0) {
            chain[idx] = Object.assign({}, chain[idx], {
              status: verb === "approve" ? "approved" : "rejected",
              at: nowDay,
              name: chain[idx].name || actor,
            });
          }
          var anyRejected = chain.some(function(c) { return c.status === "rejected"; });
          var allApproved = chain.length > 0 && chain.every(function(c) { return c.status === "approved"; });
          var next = anyRejected ? "rejected" : allApproved ? "approved" : "in-review";
          if (next !== prev) {
            eco.status = next;
            eco.transitions = (eco.transitions || []).concat([{ from: prev, to: next, actor: actor, ts: nowIso }]);
          }
        } else if (verb === "submit-for-review") {
          if (eco.status === "draft") {
            eco.status = "in-review";
            eco.transitions = (eco.transitions || []).concat([{ from: "draft", to: "in-review", actor: actor, ts: nowIso }]);
          }
        } else if (verb === "withdraw") {
          if (eco.status !== "released" && eco.status !== "applied") {
            eco.status = "draft";
            eco.transitions = (eco.transitions || []).concat([{ from: prev, to: "draft", actor: actor, ts: nowIso }]);
          }
        }

        state.ledger.push({
          event_id: "E-" + ("0000" + (state.ledger.length + 1)).slice(-4),
          ts: nowIso.replace(/\.\d{3}Z$/, "Z"),
          type: verb === "approve" ? (eco.status === "approved" ? "eco_approved" : "eco_signed")
              : verb === "reject"  ? "eco_rejected"
              : verb === "submit-for-review" ? "eco_in_review"
              : verb === "withdraw" ? "eco_withdrawn"
              : "eco_event",
          mode: "build",
          actor: actor,
          summary: id + " · " + verb + (body && body.role ? " (" + body.role + ")" : ""),
          ref: id,
        });

        bump();
        return Promise.resolve(eco);
      },
      release: function(id, envelope) {
        var state = window.PUMP_TENANT;
        if (!state || !Array.isArray(state.eco)) return Promise.reject(new Error("no tenant"));
        var eco = state.eco.find(function(e) { return e.id === id; });
        if (!eco) return Promise.reject(new Error("eco not found: " + id));
        if (eco.status !== "approved") return Promise.reject(new Error("eco not approved: " + eco.status));

        var actor = (envelope && envelope.actor) || (window.__forgeCurrentUser && window.__forgeCurrentUser.name) || "—";
        var nowIso = new Date().toISOString();
        var prev = eco.status;
        eco.status = "released";
        eco.transitions = (eco.transitions || []).concat([{ from: prev, to: "released", actor: actor, ts: nowIso }]);

        // Build provenance receipt (the auditor artefact)
        eco.provenance = {
          submitter_id: eco.originator || "—",
          ts_submitted: eco.date_raised || (eco.transitions[0] && eco.transitions[0].ts) || nowIso,
          approval_chain: (eco.approval_chain || []).slice(),
          fcp_envelope_id: (envelope && envelope.fcp_envelope_id) || ("FCP-" + id + "-" + nowIso.slice(0, 10).replace(/-/g, "")),
          cost_delta_inr: eco.cost_delta_inr,
          parts_affected: (eco.parts_affected || []).slice(),
          overrides: (envelope && envelope.overrides) || [],
          released_by: actor,
          released_ts: nowIso,
        };

        state.ledger.push({
          event_id: "E-" + ("0000" + (state.ledger.length + 1)).slice(-4),
          ts: nowIso.replace(/\.\d{3}Z$/, "Z"),
          type: "eco_released",
          mode: "build",
          actor: actor,
          summary: id + " released to ERP · envelope " + eco.provenance.fcp_envelope_id,
          ref: id,
        });

        bump();
        return Promise.resolve(eco);
      },
    };
  }
  if (!window.forgeApi.fcp) {
    window.forgeApi.fcp = { health: function() { return Promise.resolve(true); } };
  }
})();

/* SwitchUserPill — temporary 5-person actor picker. Sets window.__forgeCurrentUser.
   Sized for the top-strip; renders inline. Use from any screen with React.createElement. */
function SwitchUserPill() {
  // Rerender on tenant change so we pick up actor changes triggered elsewhere.
  const [, setBump] = uSA56(0);
  uEA56(function() {
    function onChange() { setBump(function(b) { return b + 1; }); }
    window.addEventListener("forge:tenant-change", onChange);
    return function() { window.removeEventListener("forge:tenant-change", onChange); };
  }, []);

  const tenant = useActiveTenant();
  const peopleSrc = (tenant && Array.isArray(tenant.people)) ? tenant.people : [];
  // Only the 5 actors in the hero flow (Ishaan submits, Devansh + Meera approve, Priya releases, Karan as cost-eng).
  const heroIds = ["P-08", "P-07", "P-06", "P-02", "P-05"];
  const heroes = peopleSrc.filter(function(p) { return heroIds.indexOf(p.id) >= 0; });
  // Stable order: submitter first
  heroes.sort(function(a, b) { return heroIds.indexOf(a.id) - heroIds.indexOf(b.id); });

  // Current actor — fall back to a tenant-derived default rather than a
  // hardcoded Tritan persona. Mirrors the boot-time resolver above.
  let cur = window.__forgeCurrentUser;
  if (!cur) {
    const def = peopleSrc.find(function(p) { return /compliance|quality|design|lead/i.test(p.role); }) || peopleSrc[0];
    cur = def ? { id: def.id, name: def.name, role: def.role } : { id: null, name: "—", role: "—" };
  }

  async function pick(p) {
    // Step 1: update the in-memory actor so api.js#ensureAuth derives the right slug.
    window.__forgeCurrentUser = { id: p.id, name: p.name, role: p.role };
    // Step 2: invalidate auth + config caches. The tenant-change listener in
    // api.js (line ~525) clears __ensuredEmail and __configCache, so the next
    // ensureAuth() will re-derive email/password from the new persona and
    // call forgeApi.login() to swap the server session cookie.
    window.dispatchEvent(new CustomEvent("forge:tenant-change", { detail: { reason: "user-switch", actor: p.name } }));
    // Step 3: eagerly re-authenticate so the server session cookie
    // (forge_session_<tenant>) reflects the new persona BEFORE the user
    // clicks any permission-gated button. Without this, a permission-gated
    // action could fire before the lazy ensureAuth() runs and 403.
    try {
      if (window.forgeApi && typeof window.forgeApi.ensureAuth === "function") {
        await window.forgeApi.ensureAuth();
      }
    } catch (e) {
      console.warn("SwitchUserPill: re-auth failed for " + p.name + ":", e && e.message);
    }
    // Step 4: notify downstream listeners that the actor changed (separate
    // from tenant changes — same tenant, different actor).
    window.dispatchEvent(new CustomEvent("forge:user-switched", { detail: { user: p } }));
  }

  const wrap = {
    display: "inline-flex", alignItems: "center", gap: 6, padding: "4px 8px",
    background: A56_PAPER.bg2, border: "1px dashed " + A56_PAPER.line, borderRadius: 6,
    fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3,
  };
  function chip(p) {
    const active = cur && cur.id === p.id;
    return {
      padding: "2px 8px", borderRadius: 999, cursor: "pointer",
      border: "1px solid " + (active ? A56_PAPER.ink : A56_PAPER.line),
      background: active ? A56_PAPER.ink : "transparent",
      color: active ? A56_PAPER.bg : A56_PAPER.ink2,
      fontFamily: A56_FONT_UI, fontSize: 12, letterSpacing: "-0.005em", fontWeight: 500,
    };
  }
  return (
    <div style={wrap} title="Temporary actor switch — pump-data will replace this with real auth.">
      <span style={{ letterSpacing: "0.08em", textTransform: "uppercase" }}>acting as</span>
      {heroes.map(function(p) {
        return (
          <button key={p.id} type="button" style={chip(p)} onClick={function(){ pick(p); }}>
            {p.name.split(" ")[0]}
          </button>
        );
      })}
    </div>
  );
}


/* ═══════════════════════════════════════════════════════════════════════
   S31 — Performance test report  (/traveler/report, mode `traveler`)
   ═══════════════════════════════════════════════════════════════════════ */

function ScreenTestReport() {
  const tenant = useActiveTenant();
  const [flash, setFlash] = A56UseFlash();
  const dispatchTimerRef = React.useRef(null);
  uEA56(function() {
    return function() {
      if (dispatchTimerRef.current) { clearTimeout(dispatchTimerRef.current); dispatchTimerRef.current = null; }
    };
  }, []);

  // Allow URL hash override: #/traveler/report/TPX-H-0008
  const hashParts = (typeof window !== "undefined") ? window.location.hash.split("/").filter(Boolean) : [];
  const overrideSerial = hashParts.length > 2 ? hashParts[2] : null;
  const serialDefault = overrideSerial || "TPX-H-0008";

  const traveler = (tenant && tenant.travelers || []).find(function(t){ return t.serial === serialDefault; })
    || { serial: serialDefault, wo: "WO-44219", dimensions: {}, photos: [] };

  const today = "2026-04-29";
  const opTimestamp = "2026-04-29 14:32 IST";
  const qaTimestamp = "2026-04-29 14:48 IST";

  // Q-H curve points (synthetic, normalized to spec for M-27418 1.0 HP)
  const qhPoints = [
    { q: 0,    h: 42.0 },
    { q: 200,  h: 38.5 },
    { q: 400,  h: 35.0 },
    { q: 600,  h: 31.2 },
    { q: 800,  h: 26.8 },
    { q: 1000, h: 21.4 },
    { q: 1200, h: 14.8 },
  ];

  const testRows = [
    { code: "IR",      name: "Insulation Resistance @500V DC",   target: "≥ 100 MΩ",    measured: "168 MΩ",   pass: true  },
    { code: "HV",      name: "High-Voltage withstand @1500V AC", target: "no breakdown", measured: "no breakdown · 1 min", pass: true  },
    { code: "NL",      name: "No-load current draw @230V AC",    target: "≤ 4.2 A",     measured: "3.84 A",   pass: true  },
    { code: "HYDRO",   name: "Hydrostatic seal @14 bar",         target: "no leak · 5 min", measured: "no leak", pass: true  },
    { code: "QH",      name: "Q-H point at duty (600 LPM)",       target: "≥ 30.0 m",    measured: "31.2 m",   pass: true  },
  ];

  const root = {
    background: A56_PAPER.bg, color: A56_PAPER.ink, minHeight: "100vh",
    fontFamily: A56_FONT_UI, fontSize: 13, padding: "20px 28px",
  };

  return (
    <div style={root}>
      <A56Flash kind={flash && flash.kind} msg={flash && flash.msg} onClose={function(){ setFlash(null); }} />

      {/* Toolbar */}
      <A56Toolbar
        left={
          <>
            <A56Pill tone="info">traveler://report</A56Pill>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
              {traveler.serial} · {traveler.wo}
            </span>
          </>
        }
        right={
          <>
            <A56Btn variant="ghost" small onClick={function(){ setFlash({ kind: "ok", msg: "Print dialog opened" }); window.print && window.print(); }}>Print</A56Btn>
            <A56Btn variant="ghost" small onClick={function(){ setFlash({ kind: "info", msg: "Email to customer queued — v2" }); }}>Email to customer</A56Btn>
            <A56Btn variant="primary" small onClick={function(){ setFlash({ kind: "ok", msg: "Appended to dispatch packet · DN-2026-0118" }); if (typeof navigate === "function") { if (dispatchTimerRef.current) clearTimeout(dispatchTimerRef.current); dispatchTimerRef.current = setTimeout(function(){ dispatchTimerRef.current = null; navigate("/line/dispatch"); }, 800); } }}>Append to dispatch packet</A56Btn>
          </>
        }
      />

      {/* Letterhead */}
      <div style={{
        marginTop: 20, background: A56_PAPER.bg2,
        border: "1px solid " + A56_PAPER.line, borderRadius: 8,
        padding: "28px 32px",
      }}>
        <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 24, paddingBottom: 18, borderBottom: "2px solid " + A56_PAPER.ink }}>
          <div>
            <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 28, letterSpacing: "-0.015em" }}>Tritan Pumps Pvt Ltd</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 4, letterSpacing: "0.04em" }}>
              VADODARA · GUJARAT · INDIA · CIN U29130GJ2014PTC079XXX
            </div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>
              ISO 9001:2015 · ISO 14001:2015 · IS 8034 licensed
            </div>
          </div>
          <div style={{ textAlign: "right" }}>
            <div style={_A56_MODEL_BOX_STYLE}>Model · M-27418</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 8 }}>Performance Test Report · Rev B</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>Doc · TR-{traveler.serial}-2026</div>
          </div>
        </div>

        {/* Identity grid */}
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 20, marginTop: 20 }}>
          <div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Serial No</div>
            <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 32, color: A56_PAPER.ink, letterSpacing: "-0.015em", marginTop: 2 }}>{traveler.serial}</div>
          </div>
          <div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Customer</div>
            <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 18, color: A56_PAPER.ink, marginTop: 2 }}>Helios AgriFlow Pvt Ltd</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>PO · PO-HEL-9981 · Lot 1 of 5</div>
          </div>
          <div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Test Date</div>
            <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 18, color: A56_PAPER.ink, marginTop: 2 }}>{today}</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>Test bay 02 · ambient 28.4 °C</div>
          </div>
        </div>

        {/* Nameplate */}
        <div style={{ marginTop: 22 }}>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 8 }}>Nameplate</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12, fontFamily: A56_FONT_MONO, fontSize: 12 }}>
            <div><div style={{ color: A56_PAPER.ink3 }}>HP rating</div><div style={{ color: A56_PAPER.ink, fontSize: 13 }}>1.0 HP / 0.75 kW</div></div>
            <div><div style={{ color: A56_PAPER.ink3 }}>Stages</div><div style={{ color: A56_PAPER.ink, fontSize: 13 }}>3-stage submersible</div></div>
            <div><div style={{ color: A56_PAPER.ink3 }}>Voltage</div><div style={{ color: A56_PAPER.ink, fontSize: 13 }}>230 V · 50 Hz · 1-φ</div></div>
            <div><div style={{ color: A56_PAPER.ink3 }}>Bore</div><div style={{ color: A56_PAPER.ink, fontSize: 13 }}>4 inch · 100 mm OD</div></div>
            <div><div style={{ color: A56_PAPER.ink3 }}>Duty Q</div><div style={{ color: A56_PAPER.ink, fontSize: 13 }}>600 LPM</div></div>
            <div><div style={{ color: A56_PAPER.ink3 }}>Duty H</div><div style={{ color: A56_PAPER.ink, fontSize: 13 }}>30 m</div></div>
            <div><div style={{ color: A56_PAPER.ink3 }}>BEE Star</div><div style={{ color: A56_PAPER.ink, fontWeight: 600, fontSize: 13 }}>3-star Schedule 7</div></div>
            <div><div style={{ color: A56_PAPER.ink3 }}>Standard</div><div style={{ color: A56_PAPER.ink, fontSize: 13 }}>IS:8034 / IS:9079</div></div>
          </div>
        </div>

        {/* Test results table */}
        <div style={{ marginTop: 26 }}>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 8 }}>Test results</div>
          <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: A56_FONT_MONO, fontSize: 12 }}>
            <thead>
              <tr style={{ borderBottom: "2px solid " + A56_PAPER.ink, textAlign: "left", color: A56_PAPER.ink3 }}>
                <th style={{ padding: "8px 4px", width: 60 }}>Code</th>
                <th style={{ padding: "8px 4px" }}>Test</th>
                <th style={{ padding: "8px 4px" }}>Target</th>
                <th style={{ padding: "8px 4px" }}>Measured</th>
                <th style={{ padding: "8px 4px", width: 80, textAlign: "right" }}>Result</th>
              </tr>
            </thead>
            <tbody>
              {testRows.map(function(r, i) {
                return (
                  <tr key={r.code} style={{ borderBottom: "1px solid " + A56_PAPER.lineSoft }}>
                    <td style={{ padding: "10px 4px", color: A56_PAPER.ink3 }}>{r.code}</td>
                    <td style={{ padding: "10px 4px", color: A56_PAPER.ink, fontFamily: A56_FONT_UI }}>{r.name}</td>
                    <td style={{ padding: "10px 4px", color: A56_PAPER.ink2 }}>{r.target}</td>
                    <td style={{ padding: "10px 4px", color: A56_PAPER.ink, fontWeight: 600 }}>{r.measured}</td>
                    <td style={{ padding: "10px 4px", textAlign: "right" }}>
                      <A56Pill tone={r.pass ? "ok" : "err"}>{r.pass ? "PASS" : "FAIL"}</A56Pill>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>

        {/* Q-H curve */}
        <div style={{ marginTop: 26 }}>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 8 }}>Q-H curve</div>
          <div style={{ background: A56_PAPER.bg, border: "1px solid " + A56_PAPER.lineSoft, borderRadius: 6, padding: 16 }}>
            <svg viewBox="0 0 480 220" width="100%" height="220" style={{ display: "block" }}>
              {/* axes */}
              <line x1="48" y1="20" x2="48" y2="180" stroke={A56_PAPER.ink2} strokeWidth="1" />
              <line x1="48" y1="180" x2="460" y2="180" stroke={A56_PAPER.ink2} strokeWidth="1" />
              {/* gridlines */}
              {[0,1,2,3,4].map(function(i){
                const y = 180 - i * 36;
                return <line key={"hg"+i} x1="48" y1={y} x2="460" y2={y} stroke={A56_PAPER.lineSoft} strokeWidth="0.5" />;
              })}
              {[0,1,2,3,4,5,6].map(function(i){
                const x = 48 + i * 64;
                return <line key={"vg"+i} x1={x} y1="20" x2={x} y2="180" stroke={A56_PAPER.lineSoft} strokeWidth="0.5" />;
              })}
              {/* curve */}
              <polyline
                fill="none" stroke={A56_PAPER.blue} strokeWidth="2"
                points={qhPoints.map(function(p){
                  const x = 48 + (p.q / 1200) * (412);
                  const y = 180 - (p.h / 45) * 160;
                  return x + "," + y;
                }).join(" ")}
              />
              {/* duty point marker */}
              <circle cx={48 + (600/1200)*412} cy={180 - (31.2/45)*160} r="4" fill={A56_PAPER.green} />
              <text x={48 + (600/1200)*412 + 8} y={180 - (31.2/45)*160 - 6} fontFamily={A56_FONT_MONO} fontSize="10" fill={A56_PAPER.ink2}>duty · 31.2 m @ 600 LPM</text>
              {/* labels */}
              <text x="8"  y="184" fontFamily={A56_FONT_MONO} fontSize="9" fill={A56_PAPER.ink3}>0</text>
              <text x="8"  y="148" fontFamily={A56_FONT_MONO} fontSize="9" fill={A56_PAPER.ink3}>10</text>
              <text x="8"  y="112" fontFamily={A56_FONT_MONO} fontSize="9" fill={A56_PAPER.ink3}>20</text>
              <text x="8"  y="76"  fontFamily={A56_FONT_MONO} fontSize="9" fill={A56_PAPER.ink3}>30</text>
              <text x="8"  y="40"  fontFamily={A56_FONT_MONO} fontSize="9" fill={A56_PAPER.ink3}>40</text>
              <text x="20" y="14"  fontFamily={A56_FONT_MONO} fontSize="9" fill={A56_PAPER.ink3}>H (m)</text>
              <text x="240" y="206" fontFamily={A56_FONT_MONO} fontSize="9" fill={A56_PAPER.ink3} textAnchor="middle">Q (LPM)</text>
              {[0,200,400,600,800,1000,1200].map(function(q,i){
                const x = 48 + i * 64;
                return <text key={"qx"+i} x={x} y="194" fontFamily={A56_FONT_MONO} fontSize="9" fill={A56_PAPER.ink3} textAnchor="middle">{q}</text>;
              })}
            </svg>
          </div>
        </div>

        {/* Signatures */}
        <div style={{ marginTop: 26, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 28 }}>
          <div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 6 }}>Operator</div>
            <div style={{ borderBottom: "1px solid " + A56_PAPER.ink, paddingBottom: 4, fontFamily: A56_FONT_SERIF, fontSize: 18, fontStyle: "italic" }}>Neha G.</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 6 }}>{opTimestamp} · sig: 0x9d2c4a…</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>P-04 · Motor Assy / Test Operator</div>
          </div>
          <div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 6 }}>QA Sign-off</div>
            <div style={{ borderBottom: "1px solid " + A56_PAPER.ink, paddingBottom: 4, fontFamily: A56_FONT_SERIF, fontSize: 18, fontStyle: "italic" }}>Priya I.</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 6 }}>{qaTimestamp} · sig: 0x4e8f7b…</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>P-02 · Storage / QA Audit Lead</div>
          </div>
        </div>

        {/* Footer compliance strip */}
        <div style={_A56_FOOTER_STRIP_STYLE}>
          <div>Tested per IS:8034. BEE Schedule 7, 3-star efficiency band confirmed.</div>
          <div style={{ color: A56_PAPER.ink3 }}>Page 1 of 1 · TR-{traveler.serial}</div>
        </div>
      </div>
    </div>
  );
}


/* ═══════════════════════════════════════════════════════════════════════
   S32 — Compliance / certification gate (/build/compliance, mode `build`)
   ═══════════════════════════════════════════════════════════════════════ */

function ScreenCompliance() {
  const tenant = useActiveTenant();
  const compliance = (tenant && tenant.compliance) || { schedules: [], star_rating_decision_tree: [] };
  const [eta, setEta] = uSA56(38);
  const [flash, setFlash] = A56UseFlash();

  // Synthetic certification artifact roster
  const artifacts = [
    { name: "IS:8034 — Submersible Pumpsets", kind: "BIS standard mark license",     issued: "2024-07-12", expires: "2027-07-11", status: "current",     ref: "BIS-CM/L-8034-04982" },
    { name: "IS:9079 — Single-phase Induction Motors", kind: "BIS standard mark license", issued: "2024-08-05", expires: "2027-08-04", status: "current", ref: "BIS-CM/L-9079-02114" },
    { name: "BEE Schedule 7 — Agricultural Pumpsets", kind: "Energy efficiency certificate", issued: "2025-04-22", expires: "2026-04-21", status: "in-renewal", ref: "BEE-S7-M27418-2025" },
    { name: "ISI License — Plant",                 kind: "Manufacturing license",     issued: "2014-11-30", expires: "2026-11-29", status: "current",     ref: "ISI-L-VAD-77119" },
    { name: "Type-test report · M-27418",          kind: "CPRI accredited test report",issued: "2025-09-18", expires: "2027-09-17", status: "current",    ref: "CPRI-TT-M27418-25" },
    { name: "ISO 9001:2015",                       kind: "Quality management system", issued: "2024-02-10", expires: "2027-02-09", status: "current",     ref: "ISO-QMS-9001-VAD" },
    { name: "ISO 14001:2015",                      kind: "Environment management",    issued: "2024-02-10", expires: "2027-02-09", status: "current",     ref: "ISO-EMS-14001-VAD" },
    { name: "BEE Schedule 6 (3-φ)",                kind: "Not applicable",            issued: "—",          expires: "—",          status: "not-applicable", ref: "—" },
  ];

  // Lookup star band given HP class and η
  function lookupBand(hp, e) {
    const tree = compliance.star_rating_decision_tree || [];
    let best = null;
    for (let i = 0; i < tree.length; i++) {
      const row = tree[i];
      if (row.hp_class === hp && e >= row.efficiency_pct_min) {
        if (!best || row.efficiency_pct_min > best.efficiency_pct_min) best = row;
      }
    }
    return best ? best.star_band : "below 3-star";
  }
  const liveBand = lookupBand("1.0-2.0", eta);
  const bandColor = liveBand === "5-star" ? A56_PAPER.green
    : liveBand === "4-star" ? A56_PAPER.green
    : liveBand === "3-star" ? A56_PAPER.amber
    : A56_PAPER.red;

  const stMap = { current: "ok", "in-renewal": "warn", expired: "err", "not-applicable": "" };

  const root = {
    background: A56_PAPER.bg, color: A56_PAPER.ink, minHeight: "100vh",
    fontFamily: A56_FONT_UI, fontSize: 13, padding: "20px 28px",
  };

  return (
    <div style={root}>
      <A56Flash kind={flash && flash.kind} msg={flash && flash.msg} onClose={function(){ setFlash(null); }} />
      <A56SectionTitle kicker="build://compliance">Compliance & certification gate</A56SectionTitle>

      {/* Schedules table */}
      <A56Card style={{ marginBottom: 18 }}>
        <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 10 }}>Applicable schedules</div>
        <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: A56_FONT_MONO, fontSize: 12 }}>
          <thead>
            <tr style={{ borderBottom: "1px solid " + A56_PAPER.ink, color: A56_PAPER.ink3, textAlign: "left" }}>
              <th style={{ padding: "8px 4px" }}>Schedule</th>
              <th style={{ padding: "8px 4px", width: 110 }}>Applicable</th>
              <th style={{ padding: "8px 4px", width: 160 }}>Current rating / Status</th>
              <th style={{ padding: "8px 4px" }}>Reason</th>
            </tr>
          </thead>
          <tbody>
            {compliance.schedules && compliance.schedules.map(function(s) {
              return (
                <tr key={s.name} style={{ borderBottom: "1px solid " + A56_PAPER.lineSoft }}>
                  <td style={{ padding: "10px 4px", color: A56_PAPER.ink, fontFamily: A56_FONT_UI, fontWeight: 500 }}>{s.name}</td>
                  <td style={{ padding: "10px 4px" }}>{s.applicable ? <A56Pill tone="ok">applicable</A56Pill> : <A56Pill tone="">n/a</A56Pill>}</td>
                  <td style={{ padding: "10px 4px", color: A56_PAPER.ink2 }}>
                    {s.current_rating ? <A56Pill tone="info">{s.current_rating}</A56Pill> : (s.status ? <A56Pill tone="ok">{s.status}</A56Pill> : "—")}
                  </td>
                  <td style={{ padding: "10px 4px", color: A56_PAPER.ink3 }}>{s.reason || "—"}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </A56Card>

      {/* BEE decision tree visual */}
      <A56Card style={{ marginBottom: 18 }}>
        <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 12 }}>BEE Schedule 7 · star-rating decision tree</div>
        <div style={{ background: A56_PAPER.bg, border: "1px solid " + A56_PAPER.lineSoft, borderRadius: 6, padding: 16 }}>
          <svg viewBox="0 0 920 300" width="100%" height="300" style={{ display: "block" }}>
            {/* Root node */}
            <rect x="20" y="120" width="140" height="56" rx="6" fill={A56_PAPER.bg2} stroke={A56_PAPER.ink2} strokeWidth="1" />
            <text x="90" y="142" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink} textAnchor="middle">Pumpset HP class</text>
            <text x="90" y="160" fontFamily={A56_FONT_MONO} fontSize="9"  fill={A56_PAPER.ink3} textAnchor="middle">M-27418 → 1.0 HP</text>

            {/* HP branches */}
            {["0.5–1.0","1.0–2.0","2.0–5.0"].map(function(hp, hi) {
              const y = 50 + hi * 100;
              const isPath = hp === "1.0–2.0";
              return (
                <g key={hi}>
                  <line x1="160" y1="148" x2="220" y2={y + 28} stroke={isPath ? A56_PAPER.green : A56_PAPER.line} strokeWidth={isPath ? 2 : 1} />
                  <rect x="220" y={y} width="120" height="56" rx="6"
                        fill={isPath ? A56_PAPER.greenSoft : A56_PAPER.bg2}
                        stroke={isPath ? A56_PAPER.green : A56_PAPER.ink2} strokeWidth="1" />
                  <text x="280" y={y + 22} fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink} textAnchor="middle">HP {hp}</text>
                  <text x="280" y={y + 40} fontFamily={A56_FONT_MONO} fontSize="9" fill={A56_PAPER.ink3} textAnchor="middle">{isPath ? "← active path" : "—"}</text>
                </g>
              );
            })}

            {/* Star bands for HP 1.0-2.0 (the active path) */}
            {[
              { label: "η ≥ 40%", band: "3-star", y: 30,  active: true,  threshold: 40 },
              { label: "η ≥ 44%", band: "4-star", y: 130, active: false, threshold: 44 },
              { label: "η ≥ 48%", band: "5-star", y: 230, active: false, threshold: 48 },
            ].map(function(b, bi) {
              return (
                <g key={bi}>
                  <line x1="340" y1={150 + 28} x2="450" y2={b.y + 28} stroke={b.active ? A56_PAPER.green : A56_PAPER.line} strokeWidth={b.active ? 2 : 1} />
                  <rect x="450" y={b.y} width="160" height="56" rx="6"
                        fill={b.active ? A56_PAPER.greenSoft : A56_PAPER.bg2}
                        stroke={b.active ? A56_PAPER.green : A56_PAPER.ink2} strokeWidth="1" />
                  <text x="530" y={b.y + 22} fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink} textAnchor="middle">{b.label}</text>
                  <text x="530" y={b.y + 40} fontFamily={A56_FONT_MONO} fontSize="11" fill={b.active ? A56_PAPER.ink : A56_PAPER.ink3} textAnchor="middle">{b.band}{b.active ? " · highlighted" : ""}</text>

                  {b.active && (
                    <g>
                      <line x1="610" y1={b.y + 28} x2="720" y2="148" stroke={A56_PAPER.green} strokeWidth="2" />
                      <rect x="720" y="120" width="180" height="56" rx="6" fill={A56_PAPER.greenSoft} stroke={A56_PAPER.green} strokeWidth="1.5" />
                      <text x="810" y="142" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink} textAnchor="middle">M-27418 · 38% η</text>
                      <text x="810" y="160" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink} textAnchor="middle">3-star · BEE Sched 7 ✓</text>
                    </g>
                  )}
                </g>
              );
            })}
          </svg>
        </div>
      </A56Card>

      {/* Two columns: Artifacts + Drift simulator */}
      <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 18 }}>
        {/* Artifacts list */}
        <A56Card>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 10 }}>Certification artifacts</div>
          <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: A56_FONT_MONO, fontSize: 12 }}>
            <thead>
              <tr style={{ borderBottom: "1px solid " + A56_PAPER.ink, color: A56_PAPER.ink3, textAlign: "left" }}>
                <th style={{ padding: "8px 4px" }}>Artifact</th>
                <th style={{ padding: "8px 4px", width: 130 }}>Issued</th>
                <th style={{ padding: "8px 4px", width: 130 }}>Expires</th>
                <th style={{ padding: "8px 4px", width: 110 }}>Status</th>
                <th style={{ padding: "8px 4px", width: 80, textAlign: "right" }}>Action</th>
              </tr>
            </thead>
            <tbody>
              {artifacts.map(function(a) {
                const renewable = a.status === "in-renewal" || a.status === "expired";
                return (
                  <tr key={a.ref}
                      onClick={function(){ setFlash({ kind: "ok", msg: a.name + " · opening ledger · ref " + a.ref }); window.location.hash = "#/auditor/ledger"; }}
                      style={{ borderBottom: "1px solid " + A56_PAPER.lineSoft, cursor: "pointer" }}>
                    <td style={{ padding: "10px 4px" }}>
                      <div style={{ color: A56_PAPER.ink, fontFamily: A56_FONT_UI, fontSize: 12 }}>{a.name}</div>
                      <div style={{ color: A56_PAPER.ink3, fontSize: 12 }}>{a.kind} · {a.ref}</div>
                    </td>
                    <td style={{ padding: "10px 4px", color: A56_PAPER.ink2 }}>{a.issued}</td>
                    <td style={{ padding: "10px 4px", color: A56_PAPER.ink2 }}>{a.expires}</td>
                    <td style={{ padding: "10px 4px" }}>
                      <A56Pill tone={stMap[a.status] || ""}>{a.status}</A56Pill>
                    </td>
                    <td style={{ padding: "10px 4px", textAlign: "right" }} onClick={function(e){ e.stopPropagation(); }}>
                      {renewable ? (
                        <A56Btn variant="ghost" small onClick={function(){
                          var _q = function (err) { return err && (err.status === 404 || err.status === 400); };
                          if (window.forgeApi && typeof window.forgeApi.mutate === "function") {
                            window.forgeApi.mutate("compliance_renewals", { op: "add", path: "/-", value: { artifact_ref: a.ref, name: a.name, requested_at: Date.now() } })
                              .then(function(){ setFlash({ kind: "ok", msg: a.name + " renewal initiated · " + a.ref }); })
                              .catch(function(err){ setFlash({ kind: _q(err) ? "ok" : "err", msg: _q(err) ? a.name + " renewal queued · " + a.ref : "Renew failed · " + (err && err.message || "unknown") }); });
                          } else {
                            setFlash({ kind: "ok", msg: a.name + " renewal queued · " + a.ref });
                          }
                        }}>Renew</A56Btn>
                      ) : <span style={{ color: A56_PAPER.ink3, fontSize: 12 }}>-</span>}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </A56Card>

        {/* Drift simulator */}
        <A56Card>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 10 }}>Star-rating drift simulator</div>
          <div style={{ fontFamily: A56_FONT_UI, fontSize: 12, color: A56_PAPER.ink3, marginBottom: 14 }}>
            For HP class 1.0–2.0. Slide η to see which star band a build qualifies for.
          </div>
          <div style={{ marginBottom: 12 }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 6 }}>
              <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Efficiency · η</span>
              <span style={{ fontFamily: A56_FONT_SERIF, fontSize: 28, color: A56_PAPER.ink, letterSpacing: "-0.01em" }}>{eta}%</span>
            </div>
            <input id="pump-a56-f1" name="pump-a56-f1"
              type="range" min="32" max="52" step="1" value={eta}
              onChange={function(e){ setEta(parseInt(e.target.value, 10)); }}
              style={{ width: "100%" }}
            />
            <div style={{ display: "flex", justifyContent: "space-between", fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
              <span>32%</span><span>40%</span><span>44%</span><span>48%</span><span>52%</span>
            </div>
          </div>
          <div style={{
            padding: 14, borderRadius: 6,
            background: liveBand === "below 3-star" ? A56_PAPER.redSoft
              : liveBand === "3-star" ? A56_PAPER.amberSoft
              : A56_PAPER.greenSoft,
            border: "1px solid " + bandColor,
          }}>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Qualifies for</div>
            <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 30, color: A56_PAPER.ink, letterSpacing: "-0.01em", marginTop: 4 }}>
              {liveBand}
            </div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 6 }}>
              Current M-27418 build measures 38% → 3-star.
            </div>
          </div>
          <div style={{ marginTop: 16, fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
            BEE Schedule 7 thresholds (HP 1.0–2.0): 3-star ≥ 40% · 4-star ≥ 44% · 5-star ≥ 48%.
          </div>
        </A56Card>
      </div>

      <div style={{ marginTop: 20, fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
        Sources: BEE notification S.O.5311(E) · IS:8034:2018 · IS:9079:2018 · CPRI type-test on file.
      </div>
    </div>
  );
}


/* ═══════════════════════════════════════════════════════════════════════
   S33 — Pack & ship + private-label artwork (/line/dispatch, mode `line`)
   ═══════════════════════════════════════════════════════════════════════ */

function ScreenDispatch() {
  const [flash, setFlash] = A56UseFlash();
  const [carrier, setCarrier] = uSA56("Synthetic Express Logistics");
  const [carton, setCarton] = uSA56(0); // 0 = 3D box, 1 = front face

  uEA56(function() {
    function onTenant() { setCarrier("Synthetic Express Logistics"); setCarton(0); }
    window.addEventListener("forge:tenant-change", onTenant);
    return function() { window.removeEventListener("forge:tenant-change", onTenant); };
  }, []);

  const checklist = [
    { item: "Units packed",            done: 100, of: 100, kind: "ok" },
    { item: "Serials assigned",         done: 100, of: 100, kind: "ok",  detail: "TPX-H-0001 → TPX-H-0100" },
    { item: "Test reports bundled",     done: 100, of: 100, kind: "ok",  detail: "1 PDF per unit · stapled to carton" },
    { item: "Brand artwork applied",    done: 100, of: 100, kind: "ok",  detail: "NRV body silk-screen + carton stickers" },
    { item: "Foam end-caps inserted",   done: 100, of: 100, kind: "ok"   },
    { item: "Master cartons sealed",    done: 100, of: 100, kind: "ok"   },
    { item: "Pallet · stretch-wrap",    done:   4, of:   4, kind: "ok",  detail: "25 cartons / pallet · 4 pallets" },
    { item: "Outer barcode label",      done: 100, of: 100, kind: "ok"   },
    { item: "Warranty cards inserted",  done: 100, of: 100, kind: "ok"   },
  ];

  const docs = [
    { id: "INV-2026-0118", name: "Invoice draft (commercial)",    state: "draft",     amount: _a56_money("65000000", "INR", "₹6,50,000") },
    { id: "DN-2026-0118",  name: "Delivery note · 100 of 500",    state: "draft",     amount: "—" },
    { id: "EW-2026-0118",  name: "E-way bill placeholder",        state: "pending",   amount: "—" },
    { id: "PCK-2026-0118", name: "Packing list",                  state: "ready",     amount: "100 units" },
    { id: "QC-2026-0118",  name: "QC release certificate",        state: "ready",     amount: "100 units" },
  ];

  const root = {
    background: A56_PAPER.bg, color: A56_PAPER.ink, minHeight: "100vh",
    fontFamily: A56_FONT_UI, fontSize: 13, padding: "20px 28px",
  };

  return (
    <div style={root}>
      <A56Flash kind={flash && flash.kind} msg={flash && flash.msg} onClose={function(){ setFlash(null); }} />

      <A56SectionTitle kicker="line://dispatch">Pack & ship · WO-44219 · Helios pilot lot 100/500</A56SectionTitle>

      {/* Toolbar */}
      <A56Toolbar
        left={
          <>
            <A56Pill tone="ok">100/100 packed</A56Pill>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
              Lot ETA Helios receiving · 2026-05-22
            </span>
          </>
        }
        right={
          <>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>Carrier</span>
            <select id="dispatch-carrier" name="dispatch-carrier" aria-label="Carrier" value={carrier} onChange={function(e){ setCarrier(e.target.value); }} style={{
              height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12,
              border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg2,
            }}>
              <option>Synthetic Express Logistics</option>
              <option>Aurora Roadways</option>
              <option>Pinnacle Freight Lines</option>
              <option>Customer pickup (Helios fleet)</option>
            </select>
            <A56Btn variant="ghost" small onClick={function(){ setFlash({ kind: "ok", msg: "Print dialog opened · 100 outer labels" }); if (typeof window.print === "function") window.print(); }}>Print labels</A56Btn>
            <A56Btn variant="ghost" small onClick={function(){
              var _q = function (err) { return err && (err.status === 404 || err.status === 400); };
              if (window.forgeApi && typeof window.forgeApi.mutate === "function") {
                window.forgeApi.mutate("dispatch_packets", { op: "add", path: "/-", value: { kind: "dn-2026", count: 100, generated_at: Date.now() } })
                  .then(function(){ setFlash({ kind: "ok", msg: "Dispatch packet generated · 100 reports + invoice + DN" }); })
                  .catch(function(err){ setFlash({ kind: _q(err) ? "ok" : "err", msg: _q(err) ? "Dispatch packet queued · 100 reports + invoice + DN" : "Generate failed · " + (err && err.message || "unknown") }); });
              } else {
                setFlash({ kind: "ok", msg: "Dispatch packet queued · 100 reports + invoice + DN" });
              }
            }}>Generate dispatch packet</A56Btn>
            <A56Btn variant="green" small onClick={function(){
              var _q = function (err) { return err && (err.status === 404 || err.status === 400); };
              if (window.forgeApi && typeof window.forgeApi.mutate === "function") {
                window.forgeApi.mutate("logistics_handoffs", { op: "add", path: "/-", value: { carrier: carrier, eta: "2026-05-22", handed_off_at: Date.now() } })
                  .then(function(){ setFlash({ kind: "ok", msg: "Lot handed over to " + carrier + " · ETA 2026-05-22" }); })
                  .catch(function(err){ setFlash({ kind: _q(err) ? "ok" : "err", msg: _q(err) ? "Handoff queued · " + carrier + " · ETA 2026-05-22" : "Handoff failed · " + (err && err.message || "unknown") }); });
              } else {
                setFlash({ kind: "ok", msg: "Handoff queued · " + carrier + " · ETA 2026-05-22" });
              }
            }}>Hand over to logistics</A56Btn>
          </>
        }
      />

      {/* 3-column layout */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1.2fr 1fr", gap: 18, marginTop: 18 }}>
        {/* LEFT — checklist */}
        <A56Card>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 12 }}>Dispatch checklist</div>
          {checklist.map(function(c, i) {
            const pct = c.of ? c.done / c.of : 0;
            return (
              <div key={c.item} style={{ paddingBottom: 12, borderBottom: i < checklist.length - 1 ? "1px solid " + A56_PAPER.lineSoft : "none", marginBottom: i < checklist.length - 1 ? 12 : 0 }}>
                <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 }}>
                  <div style={{ fontFamily: A56_FONT_UI, fontSize: 12, color: A56_PAPER.ink, display: "flex", alignItems: "center", gap: 8 }}>
                    <span style={_A56_CHECK_TICK_STYLE}>✓</span>
                    {c.item}
                  </div>
                  <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, fontVariantNumeric: "tabular-nums" }}>
                    {c.done}/{c.of}
                  </div>
                </div>
                <div style={{ height: 4, background: A56_PAPER.bg3, borderRadius: 4, marginTop: 6, overflow: "hidden" }}>
                  <div style={{ width: (pct * 100) + "%", height: "100%", background: A56_PAPER.green }} />
                </div>
                {c.detail && <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 4 }}>{c.detail}</div>}
              </div>
            );
          })}
        </A56Card>

        {/* CENTER — artwork preview */}
        <A56Card>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 12 }}>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Carton artwork preview</div>
            <div style={{ display: "flex", gap: 6 }}>
              <A56Btn variant={carton === 0 ? "primary" : "ghost"} small onClick={function(){ setCarton(0); }}>3D</A56Btn>
              <A56Btn variant={carton === 1 ? "primary" : "ghost"} small onClick={function(){ setCarton(1); }}>Face</A56Btn>
            </div>
          </div>
          <div style={{ background: A56_PAPER.bg, border: "1px solid " + A56_PAPER.lineSoft, borderRadius: 6, padding: 16, minHeight: 360 }}>
            {carton === 0 ? (
              <svg viewBox="0 0 360 320" width="100%" height="320" style={{ display: "block" }}>
                {/* 3D box */}
                {/* top */}
                <polygon points="40,80 240,80 290,40 90,40" fill="#e9e1d2" stroke={A56_PAPER.ink2} strokeWidth="1" />
                {/* right */}
                <polygon points="240,80 290,40 290,260 240,300" fill="#d8cdb7" stroke={A56_PAPER.ink2} strokeWidth="1" />
                {/* front */}
                <rect x="40" y="80" width="200" height="220" fill="#f3ecd9" stroke={A56_PAPER.ink2} strokeWidth="1" />
                {/* tape on top */}
                <line x1="60" y1="80" x2="220" y2="80" stroke={A56_PAPER.ink} strokeWidth="0.5" />
                {/* Helios logo on front */}
                <text x="140" y="138" fontFamily={A56_FONT_SERIF} fontSize="22" fill={A56_PAPER.ink} textAnchor="middle" letterSpacing="-0.01em">Helios</text>
                <text x="140" y="160" fontFamily={A56_FONT_SERIF} fontSize="14" fill={A56_PAPER.ink2} textAnchor="middle" fontStyle="italic">AgriFlow</text>
                <line x1="80" y1="170" x2="200" y2="170" stroke={A56_PAPER.ink2} strokeWidth="0.5" />
                <text x="140" y="186" fontFamily={A56_FONT_MONO} fontSize="9"  fill={A56_PAPER.ink3} textAnchor="middle">SUBMERSIBLE PUMPSET</text>
                <text x="140" y="200" fontFamily={A56_FONT_MONO} fontSize="9"  fill={A56_PAPER.ink3} textAnchor="middle">1.0 HP · 4 INCH · 3-STAGE</text>

                <text x="55"  y="232" fontFamily={A56_FONT_MONO} fontSize="8" fill={A56_PAPER.ink3}>Model</text>
                <text x="55"  y="244" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink}>M-27418</text>

                <text x="55"  y="262" fontFamily={A56_FONT_MONO} fontSize="8" fill={A56_PAPER.ink3}>MRP (incl. all taxes)</text>
                <text x="55"  y="274" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink}>₹ 13,499</text>

                <text x="160" y="232" fontFamily={A56_FONT_MONO} fontSize="8" fill={A56_PAPER.ink3}>Serial range (lot 1)</text>
                <text x="160" y="244" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink}>TPX-H-0001 to 0100</text>
                <text x="160" y="262" fontFamily={A56_FONT_MONO} fontSize="8" fill={A56_PAPER.ink3}>BEE rating</text>
                <text x="160" y="274" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.green}>★★★ 3-star</text>

                {/* barcode-ish */}
                <g transform="translate(60,290)">
                  {["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y"].map(function(slot, idx){
                    const widths = [2,1,3,1,2,4,1,3,2,1,3,2,1,4,2,1,3,1,2,3,1,2,3,1,4];
                    return <rect key={slot} x={idx * 4} y="0" width={widths[idx] * 0.7} height="14" fill={A56_PAPER.ink} />;
                  })}
                </g>
              </svg>
            ) : (
              <svg viewBox="0 0 360 320" width="100%" height="320" style={{ display: "block" }}>
                <rect x="20" y="20" width="320" height="280" fill="#f3ecd9" stroke={A56_PAPER.ink2} strokeWidth="1.5" rx="4" />
                <text x="180" y="80" fontFamily={A56_FONT_SERIF} fontSize="42" fill={A56_PAPER.ink} textAnchor="middle" letterSpacing="-0.015em">Helios</text>
                <text x="180" y="118" fontFamily={A56_FONT_SERIF} fontSize="22" fill={A56_PAPER.ink2} textAnchor="middle" fontStyle="italic">AgriFlow</text>
                <line x1="60" y1="138" x2="300" y2="138" stroke={A56_PAPER.ink2} strokeWidth="0.6" />
                <text x="180" y="160" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink3} textAnchor="middle">SUBMERSIBLE PUMPSET</text>
                <text x="180" y="180" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink3} textAnchor="middle">1.0 HP · 4 INCH · 3-STAGE</text>
                <text x="180" y="220" fontFamily={A56_FONT_MONO} fontSize="14" fill={A56_PAPER.ink} textAnchor="middle">M-27418</text>
                <text x="180" y="244" fontFamily={A56_FONT_MONO} fontSize="11" fill={A56_PAPER.ink2} textAnchor="middle">MRP ₹ 13,499 · BEE ★★★</text>
                <text x="180" y="276" fontFamily={A56_FONT_MONO} fontSize="9"  fill={A56_PAPER.ink4} textAnchor="middle">Marketed by Helios AgriFlow Pvt Ltd · Manufactured by Tritan Pumps</text>
              </svg>
            )}
          </div>
          <div style={{ marginTop: 12, fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
            Wordmark set in Instrument Serif. Approved by Helios brand lead on 2026-04-08 (artwork rev 2).
          </div>
        </A56Card>

        {/* RIGHT — shipping docs */}
        <A56Card>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 12 }}>Shipping documents</div>
          {docs.map(function(d, i) {
            const tone = d.state === "ready" ? "ok" : d.state === "draft" ? "warn" : "";
            return (
              <div key={d.id} style={{
                paddingBottom: 12,
                borderBottom: i < docs.length - 1 ? "1px solid " + A56_PAPER.lineSoft : "none",
                marginBottom: i < docs.length - 1 ? 12 : 0,
              }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                  <span style={{ fontFamily: A56_FONT_UI, fontSize: 12, color: A56_PAPER.ink }}>{d.name}</span>
                  <A56Pill tone={tone}>{d.state}</A56Pill>
                </div>
                <div style={{ display: "flex", justifyContent: "space-between", marginTop: 4 }}>
                  <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>{d.id}</span>
                  <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>{d.amount}</span>
                </div>
              </div>
            );
          })}

          <div style={{ marginTop: 16, paddingTop: 12, borderTop: "1px solid " + A56_PAPER.line }}>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 6 }}>Carrier · ETA</div>
            <div style={{ fontFamily: A56_FONT_UI, fontSize: 13, color: A56_PAPER.ink }}>{carrier}</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 4 }}>Vadodara → Ahmedabad · 4 pallets · 920 kg</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2, marginTop: 4 }}>Pickup 2026-05-20 · ETA 2026-05-22 18:00 IST</div>
          </div>
        </A56Card>
      </div>
    </div>
  );
}


/* ═══════════════════════════════════════════════════════════════════════
   S34 — Customer acceptance ledger (/forge/acceptance, mode `forge`)
   ═══════════════════════════════════════════════════════════════════════ */

function ScreenCustomerAcceptance() {
  const [flash, setFlash] = A56UseFlash();
  const [acceptedExtra, setAcceptedExtra] = uSA56(0);

  uEA56(function() {
    function onTenant() { setAcceptedExtra(0); }
    window.addEventListener("forge:tenant-change", onTenant);
    return function() { window.removeEventListener("forge:tenant-change", onTenant); };
  }, []);

  const tranches = [
    { id: "T1", units: "1–100",   qty: 100, dispatch: "2026-05-20", eta: "2026-05-22", accepted: 50 + acceptedExtra, in_transit: 50 - acceptedExtra, payment: "LC at sight · doc pending", state: "in-flight" },
    { id: "T2", units: "101–200", qty: 100, dispatch: "2026-05-30", eta: "2026-06-01", accepted: 0,  in_transit: 0,  payment: "—", state: "in-production" },
    { id: "T3", units: "201–300", qty: 100, dispatch: "2026-06-08", eta: "2026-06-10", accepted: 0,  in_transit: 0,  payment: "—", state: "in-production" },
    { id: "T4", units: "301–400", qty: 100, dispatch: "2026-06-16", eta: "2026-06-18", accepted: 0,  in_transit: 0,  payment: "—", state: "queued" },
    { id: "T5", units: "401–500", qty: 100, dispatch: "2026-06-22", eta: "2026-06-24", accepted: 0,  in_transit: 0,  payment: "—", state: "queued" },
  ];

  const totalAccepted = tranches.reduce(function(s, t){ return s + t.accepted; }, 0);
  const totalDispatched = 100;
  const totalInTransit = tranches.reduce(function(s, t){ return s + t.in_transit; }, 0);
  const stillProduction = 500 - totalDispatched;

  const root = {
    background: A56_PAPER.bg, color: A56_PAPER.ink, minHeight: "100vh",
    fontFamily: A56_FONT_UI, fontSize: 13, padding: "20px 28px",
  };

  function bar(qty, accepted, transit) {
    const a = (accepted / qty) * 100;
    const t = (transit / qty) * 100;
    return (
      <div style={{ display: "flex", height: 8, background: A56_PAPER.bg3, borderRadius: 4, overflow: "hidden" }}>
        <div style={{ width: a + "%", background: A56_PAPER.green }} />
        <div style={{ width: t + "%", background: A56_PAPER.amber }} />
      </div>
    );
  }

  return (
    <div style={root}>
      <A56Flash kind={flash && flash.kind} msg={flash && flash.msg} onClose={function(){ setFlash(null); }} />
      <A56SectionTitle kicker="forge://acceptance">Customer acceptance · WO-44219 · Helios AgriFlow</A56SectionTitle>

      {/* Closeout PO summary */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12, marginBottom: 18 }}>
        <A56Card pad={14}>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Quoted value</div>
          <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 26, color: A56_PAPER.ink, fontVariantNumeric: "tabular-nums", marginTop: 4 }}>{_a56_money("650000000", "INR", "₹ 65,00,000")}</div>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>500 units · QT-2026-0042</div>
        </A56Card>
        <A56Card pad={14} style={{ borderColor: A56_PAPER.green }}>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Accepted (tranche 1)</div>
          <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 26, color: A56_PAPER.ink, fontVariantNumeric: "tabular-nums", marginTop: 4 }}>{_a56_money(String((6500 + acceptedExtra * 13) * 100), "INR", "₹ " + (6500 + acceptedExtra * 13).toLocaleString())}</div>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>{50 + acceptedExtra}/100 units · 13,000 ₹/u landed</div>
        </A56Card>
        <A56Card pad={14}>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Returns (open)</div>
          <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 26, color: A56_PAPER.ink, marginTop: 4 }}>0</div>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>This program · TPX-H pool</div>
        </A56Card>
        <A56Card pad={14}>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Disputes</div>
          <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 26, color: A56_PAPER.ink, marginTop: 4 }}>0</div>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>No invoice held · LC clean</div>
        </A56Card>
      </div>

      {/* Status pills row */}
      <div style={{ display: "flex", gap: 18, marginBottom: 18, flexWrap: "wrap" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <span style={{ width: 12, height: 12, background: A56_PAPER.green, borderRadius: 2 }} />
          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2 }}>Accepted · {totalAccepted}</span>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <span style={{ width: 12, height: 12, background: A56_PAPER.amber, borderRadius: 2 }} />
          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2 }}>In transit · {totalInTransit}</span>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <span style={{ width: 12, height: 12, background: A56_PAPER.bg3, border: "1px solid " + A56_PAPER.line, borderRadius: 2 }} />
          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2 }}>Still in production · {stillProduction}</span>
        </div>
      </div>

      {/* Per-tranche detail */}
      <A56Card>
        <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 12 }}>Per-tranche detail · 5 tranches</div>
        <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: A56_FONT_MONO, fontSize: 12 }}>
          <thead>
            <tr style={{ borderBottom: "1px solid " + A56_PAPER.ink, color: A56_PAPER.ink3, textAlign: "left" }}>
              <th style={{ padding: "8px 4px", width: 50 }}>Tr</th>
              <th style={{ padding: "8px 4px", width: 100 }}>Units</th>
              <th style={{ padding: "8px 4px", width: 120 }}>Dispatch</th>
              <th style={{ padding: "8px 4px", width: 110 }}>ETA</th>
              <th style={{ padding: "8px 4px" }}>Acceptance</th>
              <th style={{ padding: "8px 4px", width: 200 }}>Payment</th>
              <th style={{ padding: "8px 4px", width: 110 }}>State</th>
              <th style={{ padding: "8px 4px", width: 180, textAlign: "right" }}>Action</th>
            </tr>
          </thead>
          <tbody>
            {tranches.map(function(t, i) {
              return (
                <tr key={t.id} style={{ borderBottom: "1px solid " + A56_PAPER.lineSoft }}>
                  <td style={{ padding: "12px 4px", color: A56_PAPER.ink, fontWeight: 600 }}>{t.id}</td>
                  <td style={{ padding: "12px 4px", color: A56_PAPER.ink2 }}>{t.units}</td>
                  <td style={{ padding: "12px 4px", color: A56_PAPER.ink2 }}>{t.dispatch}</td>
                  <td style={{ padding: "12px 4px", color: A56_PAPER.ink2 }}>{t.eta}</td>
                  <td style={{ padding: "12px 4px" }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                      <div style={{ flex: 1, minWidth: 80 }}>{bar(t.qty, t.accepted, t.in_transit)}</div>
                      <span style={{ color: A56_PAPER.ink, width: 60, textAlign: "right", fontVariantNumeric: "tabular-nums" }}>
                        {t.accepted}/{t.qty}
                      </span>
                    </div>
                  </td>
                  <td style={{ padding: "12px 4px", color: A56_PAPER.ink3 }}>{t.payment}</td>
                  <td style={{ padding: "12px 4px" }}>
                    <A56Pill tone={t.state === "in-flight" ? "warn" : t.state === "in-production" ? "info" : ""}>{t.state}</A56Pill>
                  </td>
                  <td style={{ padding: "12px 4px", textAlign: "right" }}>
                    {t.state === "in-flight" ? (
                      <A56Btn variant="green" small onClick={function(){
                        setAcceptedExtra(function(x){ return Math.min(50, x + 25); });
                        var _q = function (err) { return err && (err.status === 404 || err.status === 400); };
                        if (window.forgeApi && typeof window.forgeApi.mutate === "function") {
                          window.forgeApi.mutate("tranches", { op: "replace", path: "/" + encodeURIComponent(t.id) + "/accepted", value: t.accepted + 25 })
                            .then(function(){ setFlash({ kind: "ok", msg: "Tranche " + t.id + " · 25 more units accepted · ACC-" + t.id }); })
                            .catch(function(err){ setFlash({ kind: _q(err) ? "ok" : "err", msg: _q(err) ? "Tranche " + t.id + " · 25 units acceptance queued · ACC-" + t.id : "Acceptance failed · " + (err && err.message || "unknown") }); });
                        } else {
                          setFlash({ kind: "ok", msg: "Tranche " + t.id + " · 25 units acceptance queued · ACC-" + t.id });
                        }
                      }}>Mark tranche acceptance</A56Btn>
                    ) : (
                      <span style={{ color: A56_PAPER.ink3 }}>-</span>
                    )}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>

        {/* Acceptance signature block */}
        <div style={{ marginTop: 24, padding: 16, background: A56_PAPER.bg, border: "1px solid " + A56_PAPER.lineSoft, borderRadius: 6 }}>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 12 }}>Acceptance signature · tranche 1</div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 24 }}>
            <div>
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>Helios: Quality Lead</div>
              <div style={{ borderBottom: "1px dashed " + A56_PAPER.ink2, height: 28, marginTop: 8 }} />
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 6 }}>Pending · placeholder</div>
            </div>
            <div>
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>Helios: Procurement Lead</div>
              <div style={{ borderBottom: "1px dashed " + A56_PAPER.ink2, height: 28, marginTop: 8 }} />
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 6 }}>Pending · placeholder</div>
            </div>
            <div>
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>Tritan: Sales Engineering Lead</div>
              <div style={{ borderBottom: "1px solid " + A56_PAPER.ink, height: 28, marginTop: 8, display: "flex", alignItems: "flex-end", paddingBottom: 2 }}>
                <span style={{ fontFamily: A56_FONT_SERIF, fontSize: 16, fontStyle: "italic" }}>Karan V.</span>
              </div>
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 6 }}>2026-05-20 09:30 IST</div>
            </div>
          </div>
        </div>
      </A56Card>

      <div style={{ marginTop: 14, fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
        Helios pre-acceptance walkthrough scheduled · ACC-HEL-2026-Q2 · 2026-05-15 (per ledger E-0030).
      </div>
    </div>
  );
}


/* ═══════════════════════════════════════════════════════════════════════
   S35 — Field issue inbox + NRV failure case (/forge/field-issues)
   ═══════════════════════════════════════════════════════════════════════ */

function ScreenFieldIssues() {
  const tenant = useActiveTenant();
  const heliosReturns = (tenant && tenant.field_returns) || [];

  const sites = ["Ahmedabad", "Anand", "Vapi", "Surat", "Vadodara"];

  // Augment each Helios return with a synthetic site assignment
  const heliosCases = heliosReturns.map(function(r, i) {
    return {
      id: r.rma,
      kind: "nrv",
      serial: r.serial,
      reported: r.date_returned,
      customer: r.customer,
      site: sites[i % sites.length],
      failure: r.failure,
      root_cause: r.root_cause,
      linked_eco: r.linked_eco,
      photos: 3 + (i % 2),
      severity: "high",
      note: "5 units returned — pumps stop after 3 weeks of irrigation. Customer calling daily.",
    };
  });

  // 7 synthetic placeholder cases from other customers
  const otherCases = [
    { id: "RMA-2026-009", kind: "bearing", serial: "TPX-A-0011", reported: "2026-03-22", customer: "Solaris Cooperative Society", site: "Pune",      failure: "Bearing noise after 600 hr",       root_cause: "lubricant degradation",          linked_eco: null,        photos: 2, severity: "med",  note: "Service report: knock under load, replaced top bearing." },
    { id: "RMA-2026-013", kind: "leak",    serial: "TPX-B-0044", reported: "2026-03-29", customer: "Verdant Crops Coop",      site: "Nashik",    failure: "Stage seal leak",                  root_cause: "O-ring 86×3 swelling",           linked_eco: null,        photos: 4, severity: "med",  note: "Two units leaking at coupling — replaced O-rings batch." },
    { id: "RMA-2026-015", kind: "trip",    serial: "TPX-C-0007", reported: "2026-03-30", customer: "Riverstone Estates",      site: "Belagavi", failure: "Capacitor electrical trip",        root_cause: "capacitor 25µF marginal",        linked_eco: null,        photos: 1, severity: "low",  note: "Tripped MCB on start. Replaced run capacitor." },
    { id: "RMA-2026-019", kind: "noise",   serial: "TPX-A-0054", reported: "2026-04-03", customer: "Solaris Cooperative Society", site: "Pune",   failure: "Bearing noise + heat",             root_cause: "TBD",                            linked_eco: null,        photos: 0, severity: "med",  note: "Technician en route." },
    { id: "RMA-2026-022", kind: "leak",    serial: "TPX-B-0061", reported: "2026-04-07", customer: "Sunrise Horticulture",     site: "Mysuru",   failure: "Cable joint kit leak",             root_cause: "field rework defect",            linked_eco: null,        photos: 2, severity: "low",  note: "Customer admits in-field cable splice." },
    { id: "RMA-2026-025", kind: "trip",    serial: "TPX-C-0031", reported: "2026-04-09", customer: "Northstar Agro Estate",    site: "Indore",   failure: "Phase imbalance trip",             root_cause: "supply 178V at site",            linked_eco: null,        photos: 1, severity: "low",  note: "Site grid issue, not pump." },
    { id: "RMA-2026-028", kind: "bearing", serial: "TPX-A-0072", reported: "2026-04-13", customer: "Verdant Crops Coop",      site: "Nashik",    failure: "Bearing seizure",                  root_cause: "TBD · sand ingress suspected",   linked_eco: null,        photos: 3, severity: "high", note: "Strainer torn, sand-laden borewell." },
  ];

  const allCases = heliosCases.concat(otherCases);
  const [activeId, setActiveId] = uSA56(allCases.length > 0 ? allCases[0].id : null);
  const active = allCases.find(function(c){ return c.id === activeId; }) || allCases[0];
  const [flash, setFlash] = A56UseFlash();

  uEA56(function() {
    function onTenant() { setActiveId(allCases.length > 0 ? allCases[0].id : null); }
    window.addEventListener("forge:tenant-change", onTenant);
    return function() { window.removeEventListener("forge:tenant-change", onTenant); };
  }, []);

  const root = {
    background: A56_PAPER.bg, color: A56_PAPER.ink, minHeight: "100vh",
    fontFamily: A56_FONT_UI, fontSize: 13, padding: "20px 28px",
  };

  function kindIcon(k) {
    return k === "nrv" ? "✕" : k === "bearing" ? "◎" : k === "leak" ? "≈" : k === "trip" ? "⚡" : "·";
  }

  return (
    <div style={root}>
      <A56Flash kind={flash && flash.kind} msg={flash && flash.msg} onClose={function(){ setFlash(null); }} />
      <A56SectionTitle kicker="forge://field-issues">Field issue inbox</A56SectionTitle>

      {/* Red-flag banner */}
      <div style={_A56_RED_BANNER_STYLE}>
        <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <span style={_A56_BANG_DOT_STYLE}>!</span>
          <div>
            <div style={{ fontFamily: A56_FONT_UI, fontSize: 13, color: A56_PAPER.ink, fontWeight: 700 }}>5 returns in 30 days from Helios AgriFlow · NRV cracking pattern flagged</div>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2, marginTop: 2 }}>
              ECO-0051 raised by Ishaan R. on {_a56_date("2026-04-15", "2026-04-15")} · pending Plant Director · cost delta +{_a56_money("19000", "INR", "₹190")}/unit · part 20.07 → 20.07b
            </div>
          </div>
        </div>
        <A56Btn variant="primary" small onClick={function(){ typeof navigate === "function" && navigate("/build/eco"); }}>View ECO-0051 →</A56Btn>
      </div>

      {/* 2-column layout */}
      <div style={{ display: "grid", gridTemplateColumns: "320px 1fr", gap: 16 }}>
        {/* Inbox */}
        <A56Card pad={0}>
          <div style={{ padding: "10px 14px", borderBottom: "1px solid " + A56_PAPER.line, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Inbox · {allCases.length} cases</span>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.red }}>{heliosCases.length} flagged</span>
          </div>
          <div style={{ maxHeight: 620, overflowY: "auto" }}>
            {allCases.map(function(c, i) {
              const isActive = c.id === active.id;
              const isHelios = c.customer === "Helios AgriFlow Pvt Ltd";
              return (
                <div key={c.id} role="button" tabIndex={0} onClick={function(){ setActiveId(c.id); }} onKeyDown={function(e){ if(e.key === "Enter" || e.key === " "){ e.preventDefault(); setActiveId(c.id); } }} style={{
                  padding: "10px 14px", borderBottom: "1px solid " + A56_PAPER.lineSoft,
                  background: isActive ? A56_PAPER.blueSoft : "transparent",
                  borderLeft: isHelios ? "3px solid " + A56_PAPER.red : "3px solid transparent",
                  cursor: "pointer",
                }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                    <span style={{ fontFamily: A56_FONT_MONO, fontSize: 13, color: isHelios ? A56_PAPER.red : A56_PAPER.ink2, width: 14 }}>{kindIcon(c.kind)}</span>
                    <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink, fontWeight: isActive ? 700 : 400 }}>{c.serial}</span>
                    <span style={{ marginLeft: "auto", fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>{c.reported}</span>
                  </div>
                  <div style={{ fontFamily: A56_FONT_UI, fontSize: 12, color: A56_PAPER.ink, marginTop: 4, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                    {c.failure}
                  </div>
                  <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>
                    {c.customer} · {c.site}
                  </div>
                </div>
              );
            })}
          </div>
        </A56Card>

        {/* Detail panel */}
        <A56Card>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 14 }}>
            <div>
              <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                <span style={{ fontFamily: A56_FONT_SERIF, fontSize: 24, color: A56_PAPER.ink, letterSpacing: "-0.01em" }}>{active.serial}</span>
                <A56Pill tone={active.severity === "high" ? "err" : active.severity === "med" ? "warn" : ""}>{active.severity}</A56Pill>
                {active.linked_eco && <A56Pill tone="info">{active.linked_eco}</A56Pill>}
              </div>
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 4 }}>
                {active.id} · reported {active.reported} · {active.customer} · {active.site}
              </div>
            </div>
            {active.linked_eco && (
              <A56Btn variant="blue" small onClick={function(){ typeof navigate === "function" && navigate("/build/eco"); }}>Open {active.linked_eco}</A56Btn>
            )}
          </div>

          {/* Failure summary */}
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
            <div>
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 6 }}>Fail mode</div>
              <div style={{ fontFamily: A56_FONT_UI, fontSize: 13, color: A56_PAPER.ink }}>{active.failure}</div>
            </div>
            <div>
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 6 }}>Root cause</div>
              <div style={{ fontFamily: A56_FONT_UI, fontSize: 13, color: A56_PAPER.ink2 }}>{active.root_cause}</div>
            </div>
          </div>

          {/* Photos placeholder */}
          <div style={{ marginTop: 16 }}>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 6 }}>Field photos · {active.photos}</div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 8 }}>
              {["p1","p2","p3","p4"].map(function(slot, i) {
                const has = i < active.photos;
                return (
                  <div key={slot} style={_a56FieldPhotoStyle(has)}>
                    {has ? ("photo " + (i + 1)) : "—"}
                  </div>
                );
              })}
            </div>
          </div>

          {/* Customer note */}
          <div style={{ marginTop: 16, padding: 14, background: A56_PAPER.bg, border: "1px solid " + A56_PAPER.lineSoft, borderRadius: 6 }}>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 6 }}>Customer note</div>
            <div style={{ fontFamily: A56_FONT_SERIF, fontStyle: "italic", fontSize: 14, color: A56_PAPER.ink2, lineHeight: 1.5 }}>
              "{active.note}"
            </div>
          </div>

          {/* Site engineer report */}
          <div style={{ marginTop: 14, padding: 14, background: A56_PAPER.bg, border: "1px solid " + A56_PAPER.lineSoft, borderRadius: 6 }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Site engineer report</div>
              <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>filed by Ishaan R. · sig: 0x7c34ee…</div>
            </div>
            <div style={{ fontFamily: A56_FONT_UI, fontSize: 12, color: A56_PAPER.ink2, marginTop: 8, lineHeight: 1.6 }}>
              {active.kind === "nrv" ? (
                <>
                  Visited {active.site} · pump dismantled in customer yard. NRV body shows hairline crack at flange root,
                  consistent with fatigue at 20–25 Hz pressure cycling against C.I. body. Spring intact,
                  seat dimensionally OK. Replacement done with 20.07b (S.G.-400) under warranty.
                  Pattern recognition: 5th identical fail mode from same customer in 30 days. Root cause is a
                  material limit, not workmanship. ECO-0051 raised; pending Plant Director sign-off.
                </>
              ) : (
                <>
                  Site assessment performed. Failure consistent with described root cause.
                  Replacement parts dispatched under warranty terms ({active.kind === "trip" ? "no charge" : "no charge"}).
                  No systemic pattern across customer fleet; case isolated.
                </>
              )}
            </div>
          </div>

          {/* Action row */}
          <div style={{ marginTop: 16, display: "flex", gap: 8, flexWrap: "wrap" }}>
            <A56Btn variant="ghost" small onClick={function(){ setFlash({ kind: "info", msg: "Site engineer notification queued — v2 · " + active.customer }); }}>Contact site engineer</A56Btn>
            <A56Btn variant="ghost" small onClick={function(){ setFlash({ kind: "info", msg: "Replacement " + active.serial + " queued — v2 · " + active.id }); }}>Issue replacement</A56Btn>
            {active.linked_eco && <A56Btn variant="primary" small onClick={function(){ typeof navigate === "function" && navigate("/build/eco"); }}>Open ECO-0051</A56Btn>}
            <A56Btn variant="ghost" small onClick={function(){
              var _q = function (err) { return err && (err.status === 404 || err.status === 400); };
              if (window.forgeApi && typeof window.forgeApi.mutate === "function") {
                window.forgeApi.mutate("warranty_cases", { op: "replace", path: "/" + encodeURIComponent(active.id) + "/status", value: "resolved" })
                  .then(function(){ setFlash({ kind: "ok", msg: active.id + " marked resolved · ledger event appended" }); })
                  .catch(function(err){ setFlash({ kind: _q(err) ? "ok" : "err", msg: _q(err) ? active.id + " resolution queued · ledger event appended" : "Resolve failed · " + (err && err.message || "unknown") }); });
              } else {
                setFlash({ kind: "ok", msg: active.id + " resolution queued · ledger event appended" });
              }
            }}>Mark resolved</A56Btn>
          </div>
        </A56Card>
      </div>

      <div style={{ marginTop: 14, fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
        Inbox covers last 60 days. Synthetic site mapping: NRV cluster spans Ahmedabad, Anand, Vapi, Surat, Vadodara, all Helios fleet sites.
      </div>
    </div>
  );
}


/* ═══════════════════════════════════════════════════════════════════════
   S37 — Aftermarket / spares catalog (/forge/aftermarket, mode `forge`)
   ═══════════════════════════════════════════════════════════════════════ */

function ScreenAftermarket() {
  const tenant = useActiveTenant();
  const aftermarket = (tenant && tenant.aftermarket) || [];
  const [flash, setFlash] = A56UseFlash();
  const [cart, setCart] = uSA56({});
  const [filterParent, setFilterParent] = uSA56("all");
  const [filterSide, setFilterSide] = uSA56("all");

  uEA56(function() {
    function onTenant() { setCart({}); setFilterParent("all"); setFilterSide("all"); }
    window.addEventListener("forge:tenant-change", onTenant);
    return function() { window.removeEventListener("forge:tenant-change", onTenant); };
  }, []);

  // Enrich aftermarket entries with derived fields (memoized — stock is deterministic per SKU).
  const enriched = uMA56(function() {
    function stockFor(sku) {
      let h = 0;
      for (let i = 0; i < sku.length; i++) h = (h * 31 + sku.charCodeAt(i)) >>> 0;
      return 100 + (h % 200);
    }
    return aftermarket.map(function(s) {
      const isMotor = /Bushing|Bearing|Stator|Cable|Capacitor|Winding|Rotor|Frame|Insulation|Wedge|Gland/i.test(s.name);
      const parent = isMotor ? "Motor sub-assembly" : "Pump sub-assembly";
      const side = isMotor ? "motor" : "pump";
      return Object.assign({}, s, {
        parent: parent,
        side: side,
        moq: 10,
        lead_days: /NRV/.test(s.name) ? 38 : 14,
        stock: stockFor(s.sku || s.name || ""),
      });
    });
  }, [aftermarket]);

  const filtered = enriched.filter(function(s) {
    if (filterSide !== "all" && s.side !== filterSide) return false;
    if (filterParent !== "all" && s.parent !== filterParent) return false;
    return true;
  });

  function addToCart(sku, delta) {
    setCart(function(c) {
      const next = Object.assign({}, c);
      const cur = next[sku] || 0;
      const v = Math.max(0, cur + delta);
      if (v === 0) delete next[sku]; else next[sku] = v;
      return next;
    });
  }

  const cartItems = Object.keys(cart).map(function(sku) {
    const meta = enriched.find(function(s){ return s.sku === sku; });
    return { sku: sku, qty: cart[sku], meta: meta };
  });
  const cartTotal = cartItems.reduce(function(t, i){ return t + (i.meta ? i.meta.mrp_inr : 0) * i.qty; }, 0);

  const root = {
    background: A56_PAPER.bg, color: A56_PAPER.ink, minHeight: "100vh",
    fontFamily: A56_FONT_UI, fontSize: 13, padding: "20px 28px",
    paddingBottom: 200,
  };

  return (
    <div style={root}>
      <A56Flash kind={flash && flash.kind} msg={flash && flash.msg} onClose={function(){ setFlash(null); }} />
      <A56SectionTitle kicker="forge://aftermarket">Aftermarket & spares catalog</A56SectionTitle>

      {/* Helios recommendation banner */}
      <div style={_A56_GREEN_BANNER_STYLE}>
        <div>
          <div style={{ fontFamily: A56_FONT_UI, fontSize: 13, color: A56_PAPER.ink, fontWeight: 700 }}>
            Recommended for Helios fleet (post-ECO-0051 NRV redesign)
          </div>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2, marginTop: 4 }}>
            Order 50× SP-NRV-86HS (NRV 1.5" 86mm HS S.G.-400) replacements · ₹ 31,000 list · covers all fielded TPX-A units
          </div>
        </div>
        <A56Btn variant="green" onClick={function(){
          setCart(function(c){ return Object.assign({}, c, { "SP-NRV-86HS": 50 }); });
          var _q = function (err) { return err && (err.status === 404 || err.status === 400); };
          if (window.forgeApi && typeof window.forgeApi.mutate === "function") {
            window.forgeApi.mutate("spare_orders", { op: "add", path: "/-", value: { id: "WO-44223", kind: "fleet-refresh", sku: "SP-NRV-86HS", qty: 50, drafted_at: Date.now() } })
              .then(function(){ setFlash({ kind: "ok", msg: "Helios fleet refresh PO drafted · WO-44223 · spare_order_drafted appended" }); })
              .catch(function(err){ setFlash({ kind: _q(err) ? "ok" : "err", msg: _q(err) ? "Helios fleet refresh PO queued · WO-44223" : "Draft failed · " + (err && err.message || "unknown") }); });
          } else {
            setFlash({ kind: "ok", msg: "Helios fleet refresh PO queued · WO-44223" });
          }
        }}>Generate Helios fleet refresh PO</A56Btn>
      </div>

      {/* Filters */}
      <A56Toolbar
        left={
          <>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.06em", textTransform: "uppercase" }}>Filter</span>
            <select id="aftermarket-parent-filter" name="aftermarket-parent-filter" aria-label="Filter by parent assembly" value={filterParent} onChange={function(e){ setFilterParent(e.target.value); }}
                    style={{ height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12, border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg2 }}>
              <option value="all">All parents</option>
              <option value="Motor sub-assembly">Motor sub-assembly</option>
              <option value="Pump sub-assembly">Pump sub-assembly</option>
            </select>
            <select id="aftermarket-side-filter" name="aftermarket-side-filter" aria-label="Filter by side" value={filterSide} onChange={function(e){ setFilterSide(e.target.value); }}
                    style={{ height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12, border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg2 }}>
              <option value="all">All sides</option>
              <option value="motor">Motor side</option>
              <option value="pump">Pump side</option>
            </select>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>{filtered.length} of {enriched.length} SKUs</span>
          </>
        }
        right={
          <>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>Cart</span>
            <A56Pill tone={cartItems.length ? "info" : ""}>{cartItems.length} SKU{cartItems.length === 1 ? "" : "s"}</A56Pill>
            <A56Pill tone=""><span style={{ fontVariantNumeric: "tabular-nums" }}>₹ {cartTotal.toLocaleString()}</span></A56Pill>
          </>
        }
      />

      {/* Card grid */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14, marginTop: 18 }}>
        {filtered.map(function(s) {
          const inCart = cart[s.sku] || 0;
          const isHelios = s.sku === "SP-NRV-86HS";
          return (
            <div key={s.sku} style={{
              background: A56_PAPER.bg2,
              border: "1px solid " + (isHelios ? A56_PAPER.green : A56_PAPER.line),
              borderRadius: 8, overflow: "hidden",
              display: "flex", flexDirection: "column",
            }}>
              {/* image placeholder */}
              <div style={{
                height: 100, background: A56_PAPER.bg3,
                borderBottom: "1px solid " + A56_PAPER.lineSoft,
                display: "flex", alignItems: "center", justifyContent: "center",
                position: "relative",
              }}>
                <svg viewBox="0 0 100 60" width="80" height="48">
                  {/* synthetic part silhouette */}
                  {s.side === "motor" ? (
                    <g stroke={A56_PAPER.ink3} strokeWidth="1" fill="none">
                      <rect x="20" y="14" width="60" height="32" rx="3" />
                      <line x1="22" y1="22" x2="78" y2="22" />
                      <line x1="22" y1="38" x2="78" y2="38" />
                      <circle cx="34" cy="30" r="3" fill={A56_PAPER.ink3} />
                      <circle cx="66" cy="30" r="3" fill={A56_PAPER.ink3} />
                    </g>
                  ) : (
                    <g stroke={A56_PAPER.ink3} strokeWidth="1" fill="none">
                      <circle cx="50" cy="30" r="20" />
                      <circle cx="50" cy="30" r="6" fill={A56_PAPER.ink3} />
                      <line x1="50" y1="10" x2="50" y2="50" />
                      <line x1="30" y1="30" x2="70" y2="30" />
                    </g>
                  )}
                </svg>
                {isHelios && (
                  <div style={{ position: "absolute", top: 6, right: 6 }}>
                    <A56Pill tone="ok">post-ECO upgrade</A56Pill>
                  </div>
                )}
              </div>

              <div style={{ padding: 12, flex: 1, display: "flex", flexDirection: "column" }}>
                <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.04em" }}>{s.sku}</div>
                <div style={{ fontFamily: A56_FONT_UI, fontSize: 13, color: A56_PAPER.ink, marginTop: 4, lineHeight: 1.35, minHeight: 36 }}>
                  {s.name}
                </div>
                <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 6 }}>
                  {s.parent}
                </div>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginTop: 10 }}>
                  <span style={{ fontFamily: A56_FONT_SERIF, fontSize: 18, color: A56_PAPER.ink, letterSpacing: "-0.01em", fontVariantNumeric: "tabular-nums" }}>₹ {s.mrp_inr}</span>
                  <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>MRP / unit</span>
                </div>
                <div style={{ display: "flex", justifyContent: "space-between", fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 4 }}>
                  <span>MOQ {s.moq}</span>
                  <span>LT {s.lead_days}d</span>
                  <span>stock {s.stock}</span>
                </div>

                <div style={{ marginTop: 12, display: "flex", alignItems: "center", gap: 6 }}>
                  <button onClick={function(){ addToCart(s.sku, -1); }} style={_A56_QTY_BTN_STYLE}>−</button>
                  <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink, minWidth: 32, textAlign: "center" }}>{inCart}</span>
                  <button onClick={function(){ addToCart(s.sku, 1); }} style={_A56_QTY_BTN_STYLE}>+</button>
                  <A56Btn variant={inCart > 0 ? "primary" : "ghost"} small onClick={function(){ addToCart(s.sku, 10); }}>+10</A56Btn>
                </div>
              </div>
            </div>
          );
        })}
      </div>

      {/* Cart drawer */}
      {cartItems.length > 0 && (
        <div style={_a56CartDrawerStyle()}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 10 }}>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.08em", textTransform: "uppercase" }}>Spare order draft</span>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>{cartItems.length} SKU{cartItems.length === 1 ? "" : "s"}</span>
          </div>
          <div style={{ maxHeight: 180, overflowY: "auto" }}>
            {cartItems.map(function(it) {
              return (
                <div key={it.sku} style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", padding: "6px 0", borderBottom: "1px solid " + A56_PAPER.lineSoft, fontFamily: A56_FONT_MONO, fontSize: 12 }}>
                  <span style={{ color: A56_PAPER.ink, lineHeight: 1.4, flex: 1, paddingRight: 8 }}>{it.meta && it.meta.name}</span>
                  <span style={{ color: A56_PAPER.ink2, whiteSpace: "nowrap", flexShrink: 0, fontVariantNumeric: "tabular-nums" }}>{it.qty}× ₹{it.meta && it.meta.mrp_inr}</span>
                </div>
              );
            })}
          </div>
          <div style={{ display: "flex", justifyContent: "space-between", marginTop: 10, paddingTop: 10, borderTop: "1px solid " + A56_PAPER.line, fontFamily: A56_FONT_MONO, fontSize: 12 }}>
            <span style={{ color: A56_PAPER.ink3 }}>Order total</span>
            <span style={{ color: A56_PAPER.ink, fontWeight: 600, fontVariantNumeric: "tabular-nums" }}>₹ {cartTotal.toLocaleString()}</span>
          </div>
          <div style={{ display: "flex", gap: 8, marginTop: 12 }}>
            <A56Btn variant="ghost" small onClick={function(){ setCart({}); }}>Clear</A56Btn>
            <A56Btn variant="primary" small onClick={function(){
              var _q = function (err) { return err && (err.status === 404 || err.status === 400); };
              var skuCount = cartItems.length, total = cartTotal;
              if (window.forgeApi && typeof window.forgeApi.mutate === "function") {
                window.forgeApi.mutate("spare_orders", { op: "add", path: "/-", value: { kind: "manual-cart", skus: skuCount, total_minor: total, drafted_at: Date.now() } })
                  .then(function(){ setFlash({ kind: "ok", msg: "Spare order · " + skuCount + " SKU draft saved · ₹" + total.toLocaleString() }); })
                  .catch(function(err){ setFlash({ kind: _q(err) ? "ok" : "err", msg: _q(err) ? "Spare order · " + skuCount + " SKU queued · ₹" + total.toLocaleString() : "Save failed · " + (err && err.message || "unknown") }); });
              } else {
                setFlash({ kind: "ok", msg: "Spare order · " + skuCount + " SKU queued · ₹" + total.toLocaleString() });
              }
              setCart({});
            }}>Add to spare order</A56Btn>
          </div>
        </div>
      )}
    </div>
  );
}


/* ═══════════════════════════════════════════════════════════════════════
   S38 — Auditor mode / signed-event ledger (/auditor/ledger, mode `auditor`)
   THE SHOWCASE SCREEN.
   ═══════════════════════════════════════════════════════════════════════ */

function ScreenAuditorLedger() {
  const tenant = useActiveTenant();
  const ledger = (tenant && tenant.ledger) || [];
  const [flash, setFlash] = A56UseFlash();

  // Wave 3E — top-level tab ∈ {"events", "transitions"}. Defaults to "events"
  // so the existing experience is unchanged for casual viewers; auditors
  // who want the state-machine audit trail switch to "transitions".
  const [tab, setTab] = uSA56("events");

  const [filterTypes, setFilterTypes] = uSA56([]);
  const [filterMode, setFilterMode] = uSA56("all");
  const [filterActor, setFilterActor] = uSA56("all");
  const [dateFrom, setDateFrom] = uSA56("");
  const [dateTo, setDateTo] = uSA56("");
  const [expanded, setExpanded] = uSA56({});

  // Wave 3E — FSM transitions tab state. Lazy-loads on first switch.
  const [fsmRows, setFsmRows] = uSA56([]);
  const [fsmLoading, setFsmLoading] = uSA56(false);
  const [fsmErr, setFsmErr] = uSA56(null);
  const [fsmMachine, setFsmMachine] = uSA56("all");
  const [fsmEntity, setFsmEntity] = uSA56("");
  const [fsmLimit, setFsmLimit] = uSA56(50);

  function loadFsmRows() {
    if (!window.forgeApi || !window.forgeApi.fsmTransitions) return;
    setFsmLoading(true);
    setFsmErr(null);
    const filters = { limit: fsmLimit };
    if (fsmMachine && fsmMachine !== "all") filters.machine = fsmMachine;
    if (fsmEntity) filters.entity_id = fsmEntity;
    window.forgeApi.fsmTransitions(filters)
      .then(function(r){ setFsmRows((r && r.rows) || []); setFsmLoading(false); })
      .catch(function(e){ setFsmErr(e && e.message || String(e)); setFsmLoading(false); });
  }
  uEA56(function() {
    if (tab === "transitions") loadFsmRows();
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tab, fsmMachine, fsmEntity, fsmLimit]);

  uEA56(function() {
    function onTenant() {
      setFilterTypes([]); setFilterMode("all"); setFilterActor("all");
      setDateFrom(""); setDateTo(""); setExpanded({});
      setTab("events");
      setFsmRows([]); setFsmMachine("all"); setFsmEntity("");
    }
    window.addEventListener("forge:tenant-change", onTenant);
    return function() { window.removeEventListener("forge:tenant-change", onTenant); };
  }, []);

  // Signature hash placeholder generator (deterministic based on event_id)
  function hashFor(id) {
    let h = 0;
    for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) >>> 0;
    const hex = ("00000000" + h.toString(16)).slice(-8);
    return "0x" + hex.slice(0, 4) + hex.slice(4, 8);
  }

  // Mode chip color
  function modeColor(m) {
    return m === "forge"    ? A56_PAPER.blue
      :    m === "build"    ? A56_PAPER.amber
      :    m === "line"     ? A56_PAPER.green
      :    m === "traveler" ? A56_PAPER.green
      :    m === "auditor"  ? A56_PAPER.ink2
      :    A56_PAPER.ink3;
  }

  // Type chip color
  function typeColor(t) {
    if (/passed|complete|approved|certified|received/.test(t)) return A56_PAPER.green;
    if (/return|fail|blocked|escalat/.test(t)) return A56_PAPER.red;
    if (/eco|review/.test(t)) return A56_PAPER.amber;
    if (/dispatch|spare|customer/.test(t)) return A56_PAPER.blue;
    return A56_PAPER.ink3;
  }

  // Distinct values
  const allTypes = Array.from(new Set(ledger.map(function(e){ return e.type; }))).sort();
  const allModes = Array.from(new Set(ledger.map(function(e){ return e.mode; }))).sort();
  const allActors = Array.from(new Set(ledger.map(function(e){ return e.actor; }))).sort();

  // Apply filters
  const filtered = ledger.filter(function(e) {
    if (filterTypes.length > 0 && filterTypes.indexOf(e.type) < 0) return false;
    if (filterMode !== "all" && e.mode !== filterMode) return false;
    if (filterActor !== "all" && e.actor !== filterActor) return false;
    const ymd = e.ts.slice(0, 10);
    if (dateFrom && ymd < dateFrom) return false;
    if (dateTo && ymd > dateTo) return false;
    return true;
  });

  // Group by date
  const groups = {};
  filtered.forEach(function(e) {
    const ymd = e.ts.slice(0, 10);
    if (!groups[ymd]) groups[ymd] = [];
    groups[ymd].push(e);
  });
  const groupKeys = Object.keys(groups).sort();

  function toggleType(t) {
    setFilterTypes(function(arr) {
      const ix = arr.indexOf(t);
      if (ix >= 0) {
        const next = arr.slice(); next.splice(ix, 1); return next;
      }
      return arr.concat([t]);
    });
  }

  // Right rail summary derived from ledger
  const heliosSummary = [
    { label: "Quote sent · QT-2026-0042",      ts: "2026-02-18", state: "ok",  count: _a56_money("4650000000", "INR", "₹4.65 Cr") },
    { label: "Quality gates published",         ts: "2026-03-20", state: "ok",  count: "30 gates" },
    { label: "WO-44219 released",               ts: "2026-04-22", state: "ok",  count: "500 units" },
    { label: "Traveler signoffs (in-flight)",   ts: "ongoing",    state: "info", count: "10 of 500" },
    { label: "Field returns (NRV cracking)",    ts: "2026-04-02→14", state: "err", count: "5" },
    { label: "ECO-0051 raised",                 ts: "2026-04-15", state: "warn", count: "in-review" },
    { label: "Pilot dispatch · DN-2026-0118",   ts: "2026-04-29", state: "info", count: "20 unit draft" },
    { label: "Pre-acceptance walkthrough",      ts: "2026-05-15", state: "info", count: "scheduled" },
    { label: "Spare fleet-refresh PO",          ts: "pending",    state: "info", count: "50× SP-NRV-86HS" },
  ];

  // Subtle paper-grain background — auditor signature look
  const grainStyle = {
    background: A56_PAPER.inkBg,
    backgroundImage: "repeating-linear-gradient(0deg, rgba(0,0,0,0.012) 0px, rgba(0,0,0,0.012) 1px, transparent 1px, transparent 3px), repeating-linear-gradient(90deg, rgba(0,0,0,0.008) 0px, rgba(0,0,0,0.008) 1px, transparent 1px, transparent 3px)",
  };

  const root = Object.assign({
    color: A56_PAPER.ink, minHeight: "100vh",
    fontFamily: A56_FONT_UI, fontSize: 13, padding: "20px 28px",
    paddingBottom: 60,
  }, grainStyle);

  return (
    <div style={root}>
      <A56Flash kind={flash && flash.kind} msg={flash && flash.msg} onClose={function(){ setFlash(null); }} />

      {/* Distinctive auditor letterhead */}
      <div style={{
        display: "flex", justifyContent: "space-between", alignItems: "flex-start",
        paddingBottom: 14, marginBottom: 12,
        borderBottom: "2px solid " + A56_PAPER.ink,
      }}>
        <div>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.14em", textTransform: "uppercase" }}>auditor://ledger</div>
          <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 30, color: A56_PAPER.ink, letterSpacing: "-0.015em", marginTop: 4 }}>Signed event ledger · canonical record</div>
          <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 4 }}>
            Tritan Pumps Pvt Ltd · Vadodara · {ledger.length} events on file · read-only · cryptographic signatures truncated to 4-byte preview
          </div>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <A56Btn variant="ghost" small onClick={function(){ setFilterTypes([]); setFilterMode("all"); setFilterActor("all"); setDateFrom(""); setDateTo(""); }}>Reset</A56Btn>
          <A56Btn variant="ghost" small onClick={function(){
            window.location.href = window.forgeApi.exportAuditUrl("csv");
            setFlash({ kind: "info", msg: "Audit CSV download started · events flattened" });
          }}>Export CSV</A56Btn>
          <A56Btn variant="ghost" small onClick={function(){
            window.location.href = window.forgeApi.exportAuditUrl("json");
            setFlash({ kind: "info", msg: "Audit JSON download started · " + ledger.length + " events + transitions + FCP envelopes" });
          }}>Export JSON</A56Btn>
          {/* W15B — wires GET /api/:tenant/audit/export.pdf (pdfkit stream). */}
          <A56Btn variant="primary" small onClick={function(){
            window.location.href = window.forgeApi.exportAuditUrl("pdf");
            setFlash({ kind: "ok", msg: "Audit PDF download started · " + ledger.length + " events + transitions + FCP envelopes" });
          }}>Export PDF</A56Btn>
        </div>
      </div>

      {/* Wave 3E: signing-algorithm banner — honest about v1 HMAC + v2 plan */}
      <div style={{
        background: A56_PAPER.bg2,
        border: "1px solid " + A56_PAPER.line,
        borderLeft: "3px solid " + A56_PAPER.amber,
        borderRadius: 4,
        padding: "8px 12px",
        marginBottom: 14,
        fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2, lineHeight: 1.45,
      }}>
        <span style={{ color: A56_PAPER.ink, fontWeight: 600 }}>Signature algorithm</span> · v1 uses HMAC-SHA256.
        Production deploys upgrade per tenant: ed25519 (Aetherion), eIDAS QES (Mittelstand), DSC Class 3 (Tritan).
        PDF rendering requires print-to-PDF — use JSON for machine-readable audit.
      </div>

      {/* Wave 3E: tab bar — Events ↔ State transitions */}
      <div style={{ display: "flex", gap: 4, marginBottom: 14, borderBottom: "1px solid " + A56_PAPER.line }}>
        {[
          { id: "events",      label: "Events (ledger)" },
          { id: "transitions", label: "State transitions" },
        ].map(function(t){
          const active = tab === t.id;
          return (
            <button key={t.id} onClick={function(){ setTab(t.id); }} style={{
              padding: "8px 14px",
              background: active ? A56_PAPER.bg : "transparent",
              border: 0,
              borderBottom: active ? "2px solid " + A56_PAPER.ink : "2px solid transparent",
              fontFamily: A56_FONT_MONO, fontSize: 12, color: active ? A56_PAPER.ink : A56_PAPER.ink3,
              letterSpacing: "0.06em", textTransform: "uppercase", cursor: "pointer",
            }}>{t.label}</button>
          );
        })}
      </div>

      {tab === "transitions" && (
        <div>
          <div style={{
            background: A56_PAPER.bg2, border: "1px solid " + A56_PAPER.line, borderRadius: 8,
            padding: 14, marginBottom: 14,
            display: "flex", flexWrap: "wrap", alignItems: "center", gap: 12,
          }}>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.10em", textTransform: "uppercase" }}>Machine</span>
            <select id="fsm-machine" name="fsm-machine" aria-label="FSM machine" value={fsmMachine} onChange={function(e){ setFsmMachine(e.target.value); }}
                    style={{ height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12, border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg }}>
              {["all", "eco", "traveler", "wo"].map(function(m){ return <option key={m} value={m}>{m}</option>; })}
            </select>
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.10em", textTransform: "uppercase" }}>Entity</span>
            <input type="text" id="fsm-entity" name="fsm-entity" aria-label="FSM entity id" value={fsmEntity} onChange={function(e){ setFsmEntity(e.target.value); }} placeholder="ECO-0051"
                   style={{ height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12, border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg, width: 140 }} />
            <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.10em", textTransform: "uppercase" }}>Limit</span>
            <select id="fsm-limit" name="fsm-limit" aria-label="FSM event limit" value={fsmLimit} onChange={function(e){ setFsmLimit(parseInt(e.target.value, 10) || 50); }}
                    style={{ height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12, border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg }}>
              {[10, 50, 100, 200, 500].map(function(n){ return <option key={n} value={n}>{n}</option>; })}
            </select>
            <span style={{ marginLeft: "auto", fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2 }}>
              {fsmLoading ? "loading…" : (fsmRows.length + " row" + (fsmRows.length === 1 ? "" : "s"))}
            </span>
            <A56Btn variant="ghost" small onClick={loadFsmRows}>Refresh</A56Btn>
          </div>

          {fsmErr && (
            <A56Card style={{ borderColor: A56_PAPER.red, padding: 14, color: A56_PAPER.red, marginBottom: 14 }}>
              fsm-transitions error: {fsmErr}
            </A56Card>
          )}

          <A56Card style={{ padding: 0 }}>
            <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: A56_FONT_MONO, fontSize: 12 }}>
              <thead>
                <tr style={{ background: A56_PAPER.bg2 }}>
                  {["entity_id", "machine", "verb", "from → to", "actor", "role", "ts"].map(function(h){
                    return <th key={h} style={{ textAlign: "left", padding: "8px 12px", color: A56_PAPER.ink3, letterSpacing: "0.06em", textTransform: "uppercase", borderBottom: "1px solid " + A56_PAPER.line }}>{h}</th>;
                  })}
                </tr>
              </thead>
              <tbody>
                {fsmRows.length === 0 && !fsmLoading && (
                  <tr><td colSpan={7} style={{ padding: 24, textAlign: "center", color: A56_PAPER.ink3 }}>
                    No transitions recorded yet. (FSM v2 must be enabled for this tenant — set FORGE_FSM_V2=all.)
                  </td></tr>
                )}
                {fsmRows.map(function(r){
                  let iso = "";
                  try { iso = new Date(r.ts).toISOString().slice(0, 19) + "Z"; } catch(_e) { iso = String(r.ts); }
                  return (
                    <tr key={r.id} style={{ borderBottom: "1px solid " + A56_PAPER.lineSoft }}>
                      <td style={{ padding: "8px 12px", color: A56_PAPER.ink }}>{r.entity_id}</td>
                      <td style={{ padding: "8px 12px", color: A56_PAPER.ink3 }}>{r.machine}</td>
                      <td style={{ padding: "8px 12px", color: A56_PAPER.blue }}>{r.verb}</td>
                      <td style={{ padding: "8px 12px", color: A56_PAPER.ink2 }}>
                        <span style={{ color: A56_PAPER.ink3 }}>{r.from_state}</span>
                        <span style={{ color: A56_PAPER.ink3 }}> → </span>
                        <span style={{ color: A56_PAPER.ink }}>{r.to_state}</span>
                      </td>
                      <td style={{ padding: "8px 12px", color: A56_PAPER.ink2 }}>{r.actor_id || "—"}</td>
                      <td style={{ padding: "8px 12px", color: A56_PAPER.ink3 }}>{r.actor_role || "—"}</td>
                      <td style={{ padding: "8px 12px", color: A56_PAPER.ink3 }}>{iso}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </A56Card>
        </div>
      )}

      {tab === "events" && (<>

      {/* Filter bar */}
      <div style={{
        background: A56_PAPER.bg2, border: "1px solid " + A56_PAPER.line, borderRadius: 8,
        padding: 14, marginBottom: 18,
      }}>
        {/* Top row: mode + actor + date */}
        <div style={{ display: "flex", flexWrap: "wrap", alignItems: "center", gap: 12, marginBottom: 10 }}>
          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.10em", textTransform: "uppercase" }}>Mode</span>
          <select id="ledger-mode-filter" name="ledger-mode-filter" aria-label="Filter ledger by mode" value={filterMode} onChange={function(e){ setFilterMode(e.target.value); }}
                  style={{ height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12, border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg }}>
            <option value="all">all</option>
            {allModes.map(function(m){ return <option key={m} value={m}>{m}://</option>; })}
          </select>

          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.10em", textTransform: "uppercase" }}>Actor</span>
          <select id="ledger-actor-filter" name="ledger-actor-filter" aria-label="Filter ledger by actor" value={filterActor} onChange={function(e){ setFilterActor(e.target.value); }}
                  style={{ height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12, border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg }}>
            <option value="all">all</option>
            {allActors.map(function(a){ return <option key={a} value={a}>{a}</option>; })}
          </select>

          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.10em", textTransform: "uppercase" }}>From</span>
          <input type="date" id="ledger-date-from" name="ledger-date-from" aria-label="Ledger events from date" value={dateFrom} onChange={function(e){ setDateFrom(e.target.value); }}
                 style={{ height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12, border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg }} />
          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.10em", textTransform: "uppercase" }}>To</span>
          <input type="date" id="ledger-date-to" name="ledger-date-to" aria-label="Ledger events to date" value={dateTo} onChange={function(e){ setDateTo(e.target.value); }}
                 style={{ height: 26, padding: "0 8px", fontFamily: A56_FONT_MONO, fontSize: 12, border: "1px solid " + A56_PAPER.line, borderRadius: 4, background: A56_PAPER.bg }} />

          <span style={{ marginLeft: "auto", fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2 }}>
            {filtered.length} of {ledger.length} events
          </span>
        </div>

        {/* Type chips */}
        <div style={{ display: "flex", flexWrap: "wrap", alignItems: "center", gap: 6 }}>
          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.10em", textTransform: "uppercase", marginRight: 4 }}>Type</span>
          {allTypes.map(function(t) {
            const active = filterTypes.indexOf(t) >= 0;
            const c = typeColor(t);
            return (
              <button key={t} onClick={function(){ toggleType(t); }} style={_a56TypeChipStyle(active, c)}>
                {t}
              </button>
            );
          })}
        </div>
      </div>

      {/* Two-column: timeline + right rail */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 320px", gap: 20 }}>
        {/* Timeline */}
        <div>
          {groupKeys.length === 0 && (
            <A56Card style={{ textAlign: "center", color: A56_PAPER.ink3, padding: 40 }}>
              No events match current filters.
            </A56Card>
          )}
          {groupKeys.map(function(ymd) {
            const dayEvents = groups[ymd];
            return (
              <div key={ymd} style={{ marginBottom: 18 }}>
                {/* Sticky day header */}
                <div style={_A56_DAY_HEADER_STYLE}>
                  <span style={{ fontFamily: A56_FONT_SERIF, fontSize: 18, color: A56_PAPER.ink, letterSpacing: "-0.01em" }}>{ymd}</span>
                  <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.04em" }}>
                    {dayEvents.length} event{dayEvents.length === 1 ? "" : "s"}
                  </span>
                  <span style={{ flex: 1, height: 1, background: A56_PAPER.lineSoft }} />
                </div>

                {/* Event cards */}
                {dayEvents.map(function(ev) {
                  const open = expanded[ev.event_id];
                  const tcolor = typeColor(ev.type);
                  const mcolor = modeColor(ev.mode);
                  return (
                    <div key={ev.event_id} style={{
                      display: "grid",
                      gridTemplateColumns: "80px 1fr",
                      gap: 12,
                      marginBottom: 10,
                    }}>
                      {/* Time gutter */}
                      <div style={{ paddingTop: 8 }}>
                        <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2 }}>
                          {ev.ts.slice(11, 16)}Z
                        </div>
                        <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>
                          {ev.event_id}
                        </div>
                      </div>

                      {/* Event card */}
                      <div style={{
                        background: A56_PAPER.bg,
                        border: "1px solid " + A56_PAPER.line,
                        borderLeft: "3px solid " + tcolor,
                        borderRadius: 6,
                        padding: 12,
                      }}>
                        <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginBottom: 6 }}>
                          <span style={_a56TypeBadgeStyle(tcolor)}>{ev.type}</span>
                          <span style={_a56ModeBadgeStyle(mcolor)}>{ev.mode}://</span>
                          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink2 }}>
                            {ev.actor}
                          </span>
                          <span style={{ marginLeft: "auto", fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
                            sig: {hashFor(ev.event_id)}…
                          </span>
                        </div>

                        <div style={{ fontFamily: A56_FONT_UI, fontSize: 13, color: A56_PAPER.ink, lineHeight: 1.4 }}>
                          {ev.summary}
                        </div>

                        <div style={{ display: "flex", justifyContent: "space-between", marginTop: 8, alignItems: "center" }}>
                          <span style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3 }}>
                            ref · {ev.ref}
                          </span>
                          <button onClick={function(){
                            setExpanded(function(x){ const n = Object.assign({}, x); if (n[ev.event_id]) delete n[ev.event_id]; else n[ev.event_id] = true; return n; });
                          }} style={_A56_VIEW_RAW_BTN_STYLE}>
                            {open ? "hide" : "view"} raw json
                          </button>
                        </div>

                        {open && (
                          <pre style={_A56_RAW_JSON_STYLE}>{JSON.stringify({
                              event_id: ev.event_id,
                              ts: ev.ts,
                              type: ev.type,
                              mode: ev.mode,
                              actor: ev.actor,
                              summary: ev.summary,
                              ref: ev.ref,
                              signature: hashFor(ev.event_id) + "…(truncated)",
                              algo: "HMAC-SHA256",
                              signed_by: "tritan-canonical-key-2026",
                              prod_alg_target: "DSC Class 3 per Tritan deploy plan",
                            }, null, 2)}</pre>
                        )}
                      </div>
                    </div>
                  );
                })}
              </div>
            );
          })}
        </div>

        {/* Right rail */}
        <div>
          <div style={{
            position: "sticky", top: 12,
            background: A56_PAPER.bg2,
            border: "1px solid " + A56_PAPER.ink2, borderRadius: 8,
            padding: 16,
          }}>
            <div style={{ fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, letterSpacing: "0.10em", textTransform: "uppercase", marginBottom: 12 }}>Helios order timeline</div>
            <div style={{ fontFamily: A56_FONT_SERIF, fontSize: 16, color: A56_PAPER.ink, marginBottom: 12, letterSpacing: "-0.005em" }}>
              500 units · M-27418 · {_a56_money("650000000", "INR", "₹ 65 lakh")}
            </div>

            <div style={{ display: "flex", flexDirection: "column", gap: 8, position: "relative" }}>
              {/* trace line */}
              <div style={{ position: "absolute", left: 7, top: 6, bottom: 6, width: 1, background: A56_PAPER.line }} />
              {heliosSummary.map(function(s) {
                const tone = s.state === "ok" ? A56_PAPER.green : s.state === "err" ? A56_PAPER.red : s.state === "warn" ? A56_PAPER.amber : A56_PAPER.blue;
                return (
                  <div key={s.label} style={{ display: "flex", alignItems: "flex-start", gap: 10, position: "relative" }}>
                    <div style={_a56TraceDotStyle(tone)} />
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontFamily: A56_FONT_UI, fontSize: 12, color: A56_PAPER.ink, lineHeight: 1.3 }}>{s.label}</div>
                      <div style={{ display: "flex", justifyContent: "space-between", fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, marginTop: 2 }}>
                        <span>{/^\d{4}-\d{2}-\d{2}$/.test(s.ts) ? _a56_date(s.ts, s.ts) : s.ts}</span>
                        <span style={{ color: A56_PAPER.ink, fontVariantNumeric: "tabular-nums" }}>{s.count}</span>
                      </div>
                    </div>
                  </div>
                );
              })}
            </div>

            <div style={{ marginTop: 16, paddingTop: 12, borderTop: "1px solid " + A56_PAPER.lineSoft, fontFamily: A56_FONT_MONO, fontSize: 12, color: A56_PAPER.ink3, lineHeight: 1.5 }}>
              Every entry above expands to a chain of signed events in the timeline at left.
              Traveler signoffs (10 of 500) are collapsed to one row by design; drill into
              a specific WO via the line console.
            </div>

            <div style={_A56_KEY_FP_STYLE}>
              Signing key fingerprint<br />
              <span style={{ color: A56_PAPER.ink2 }}>tritan-canonical-key-2026 · HMAC-SHA256 · 30:b1:7c:9e:4a:…</span>
            </div>
          </div>
        </div>
      </div>
      </>)}
    </div>
  );
}


/* ═══════════════════════════════════════════════════════════════════════
   Route registration
   ═══════════════════════════════════════════════════════════════════════ */

if (typeof registerPumpRoute === "function") {
  registerPumpRoute({ path: "/traveler/report",   mode: "traveler",title: "Test report",         renderer: function() { return React.createElement(ScreenTestReport); } });
  registerPumpRoute({ path: "/build/compliance",  mode: "build",   title: "Compliance",          renderer: function() { return React.createElement(ScreenCompliance); } });
  registerPumpRoute({ path: "/line/dispatch",     mode: "line",    title: "Pack & ship",         renderer: function() { return React.createElement(ScreenDispatch); } });
  registerPumpRoute({ path: "/forge/acceptance",  mode: "forge",   title: "Customer acceptance", renderer: function() { return React.createElement(ScreenCustomerAcceptance); } });
  registerPumpRoute({ path: "/forge/field-issues",mode: "forge",   title: "Field issues",        renderer: function() { return React.createElement(ScreenFieldIssues); } });
  registerPumpRoute({ path: "/forge/aftermarket", mode: "forge",   title: "Aftermarket",         renderer: function() { return React.createElement(ScreenAftermarket); } });
  registerPumpRoute({ path: "/auditor/ledger",    mode: "auditor", title: "Auditor ledger",      renderer: function() { return React.createElement(ScreenAuditorLedger); } });
}

/* expose components for direct lookup just in case */
if (typeof window !== "undefined") {
  window.ScreenTestReport          = ScreenTestReport;
  window.ScreenCompliance          = ScreenCompliance;
  window.ScreenDispatch            = ScreenDispatch;
  window.ScreenCustomerAcceptance  = ScreenCustomerAcceptance;
  window.ScreenFieldIssues         = ScreenFieldIssues;
  window.ScreenAftermarket         = ScreenAftermarket;
  window.ScreenAuditorLedger       = ScreenAuditorLedger;
  window.SwitchUserPill            = SwitchUserPill;
  // Re-export a few atom helpers so the new eco-compose / erp-release-queue files
  // (which load after this one) can build matching UI without re-defining palettes.
  window.A56Btn                    = A56Btn;
  window.A56Pill                   = A56Pill;
  window.A56Card                   = A56Card;
  window.A56Toolbar                = A56Toolbar;
  window.A56SectionTitle           = A56SectionTitle;
  window.A56UseFlash               = A56UseFlash;
  window.A56Flash                  = A56Flash;
  window.A56_PAPER                 = A56_PAPER;
  window.A56_FONT_UI               = A56_FONT_UI;
  window.A56_FONT_MONO             = A56_FONT_MONO;
  window.A56_FONT_SERIF            = A56_FONT_SERIF;
}
