(function(){
/* FORGE — Aetherion Microsat · Hero ECO viewer.
   ScreenAetherionECO renders ECO-AET-0042 (solar-array hinge fastener
   A2-70 → A286 + Belleville stack) at /build/eco for the Space tenant.

   Spec source of truth: forge-web/demo/tenant-spec/space.md §6, §7.
   Babel-standalone in-browser pattern. NO ES imports / exports.
   Self-sufficient — fixtures-aetherion.jsx is owned by Agent #1; this
   screen carries its own ECO payload inline so it renders independent
   of fixture load order.

   Patterns mirrored:
     - sim-erp-eco.jsx ScreenECO  (3-pane layout, conversation, diff table)
     - pump/act3-screens.jsx      (registerSpaceRoute defensive guard)
     - pump/cross-cutting.jsx     (CSS variable + oklch fallbacks)

   Style: cool blues over deep navy. Mono codes, tnum mass values,
   ITAR / AS9100 lineage on every approval stage. No emoji. */

const { useState: uSEH, useMemo: uMEH, useEffect: uEEH } = React;

// ──────────────────────────────────────────────────────────────────────
// Tokens — rebound to the canonical light theme (tokens.css) so the
// ECO screen reads as a sibling of dashboard.jsx / act3-screens.jsx /
// auditor screens. Wave 12A · w12a-aet-eco-light. The cross-cutting
// CSS injection still defines a few `--space-*` vars (line/accent/slate/warn)
// with dark values — we route around them by binding directly to the
// global light tokens (--bg-0/--bg-1/--bg-2, --ink/--ink-3, --line) instead
// of relying on the `var(--space-*, fallback)` fallback (which doesn't fire
// when the outer var is defined).
// ──────────────────────────────────────────────────────────────────────
const SPACE_INK         = "var(--bg-0)";                // page bg → cream
const SPACE_INK_2       = "var(--bg-2)";                // elevated surface
const SPACE_ACCENT      = "#2D5BEA";                    // gold/blue accent that reads on cream
const SPACE_ACCENT_DIM  = "#9DB5F0";                    // soft blue tint
const SPACE_SLATE       = "var(--ink-3)";               // muted secondary text
const SPACE_LINE        = "var(--line)";                // hairline divider
const SPACE_MONO_COLOR  = "var(--ink)";                 // primary text (dark)
const SPACE_OK          = "var(--ok)";                  // pass tone (canonical)
const SPACE_WARN        = "var(--warn)";                // warn tone (canonical)
const SPACE_DANGER      = "var(--err)";                 // error tone (canonical)
const SPACE_PAPER       = "var(--bg-1)";                // card surface
const SPACE_FONT_MONO   = "var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace)";
const SPACE_FONT_UI     = "var(--font-ui, system-ui, -apple-system, sans-serif)";
const SPACE_FONT_SERIF  = "var(--font-serif, Georgia, 'Times New Roman', serif)";

// ──────────────────────────────────────────────────────────────────────
// ECO payload — exact §6 spec. Numbers are binding.
// ──────────────────────────────────────────────────────────────────────
const ECO_AET_0042 = {
  id:         "ECO-AET-0042",
  title:      "Solar-array hinge fastener — A2-70 → A286 + Belleville",
  target_pn:  "KESTREL-3.60.HG.03",
  rev_from:   "B",
  rev_to:     "C",
  opened:     "2026-04-24",
  owner:      "M. Sato",
  owner_role: "Mech Lead",
  severity:   "critical",
  state_init: "board-review",
  trigger: {
    test_id: "TVAC-AET-014",
    cycle:   "14 of 24",
    profile: "−40 °C → +85 °C, 90 min ramps",
    finding: "hinge HG-03 strain-gauge logged 50 µm pre-load loss",
    audit:   "post-run torque audit 0.42 Nm vs spec 0.55 ± 0.05 Nm",
  },
  root_cause: "M3 A2-70 + single Nord-Lock washer (PDR cost selection) "
            + "fatigues at the −40 °C end. PDR Belleville modeling covered a "
            + "25-cycle envelope; flight profile is 60 BOL + 200 operational.",
  change_summary:
    "Replace M3 A2-70 with M3 A286 stainless (DIN EN 2516). Replace "
  + "Nord-Lock with a Belleville stack of 4× DIN 2093 in series-parallel "
  + "(HHHL pattern). Vibra-Tite 213 at torque, 24 h cure, re-torque audit "
  + "at +1 day.",
  mass_per_hinge_g: 2.4,
  mass_total_g:     9.6,
  mass_margin_before_pct: 11.0,
  mass_margin_after_pct:  10.93,
  schedule_days_total:    11,
  schedule_breakdown: [
    { phase: "FAB-B re-issue",      days: 5 },
    { phase: "TVAC partial re-test", days: 4 },
    { phase: "CofC paperwork",       days: 2 },
  ],
  acc_target_was:   "2026-07-04",
  acc_target_new:   "2026-07-15",
  launch_holds:     true,
  retest: {
    id:      "TVAC-AET-014R",
    cycles:  24,
    profile: "−40 °C / +85 °C, 90 min ramps",
    audit:   "strain-gauge + torque audit at cycle 24",
    extras:  "shock-survival 2000g half-sine 0.5 ms",
  },
};

// 4-stage approval ladder. Stages 1-3 are signed per spec §6;
// stage 4 (Mission Director / FRR) is pending until the user clicks.
const APPROVAL_STAGES = [
  {
    key:        "engineering",
    role:       "Engineering",
    authority:  "Mech CCB",
    name:       "M. Sato + Mech CCB",
    date:       "2026-05-02",
    state:      "pass",
    as9100:     "8.3.4 · Design verification + validation",
    ecss:       "ECSS-E-ST-32-08 · Mechanical part stress",
    note:       "Originator M. Sato signed; CCB cleared root-cause + Belleville stack analysis.",
  },
  {
    key:        "manufacturing",
    role:       "Manufacturing",
    authority:  "FAB lead",
    name:       "K. Sato (Mfg)",
    date:       "2026-05-03",
    state:      "pass",
    as9100:     "8.5.1.3 · Production process verification (FAI per AS9102 rev B)",
    ecss:       "ECSS-Q-ST-70-08 · Manual soldering / high-rel build",
    note:       "FAB-B WO-AET-002 routing released; A286 fastener kit + 4× DIN 2093 staged.",
  },
  {
    key:        "quality",
    role:       "Quality",
    authority:  "Q&MA",
    name:       "R. Iyer (Q&MA)",
    date:       "2026-05-04",
    state:      "pass",
    as9100:     "8.7 · Nonconformity output control (NCR-AET-019 + waiver)",
    ecss:       "ECSS-Q-ST-70 · EEE parts derating + lot acceptance",
    note:       "Q&MA accepted retest plan; NCR-AET-019 closure pending pass of TVAC-AET-014R.",
  },
  {
    key:        "frr",
    role:       "FRR · Mission Director",
    authority:  "Mission Director",
    name:       "L. Okonkwo (MD)",
    date:       "2026-05-12 · target",
    state:      "pending",
    as9100:     "9.2 · Internal audit · flight readiness review",
    ecss:       "ECSS-E-ST-10-03 · Environmental qualification re-pass",
    note:       "Customer ack'd 2026-05-06 (Aperture Earth). CR-2026-014 issues at MD sign.",
  },
];

// Conversation thread — TVAC discovery → analysis → swap proposal →
// Belleville rationale → retest scheduled. Five entries.
const CONVERSATION_SEED = [
  {
    who:   "M. Sato",
    role:  "Mech Lead",
    ts:    "2026-04-22T14:18Z",
    body:  "TVAC-AET-014 cycle 14 flagged 50 µm pre-load loss on hinge HG-03. Pulled the run; post-run torque audit 0.42 Nm vs spec 0.55 Nm. Calling NCR-AET-019.",
  },
  {
    who:   "R. Iyer",
    role:  "Q&MA",
    ts:    "2026-04-23T09:02Z",
    body:  "Engineering analysis attached. A2-70 fastener loses pre-load at −40 °C end; PDR Belleville model only covered a 25-cycle envelope. Flight profile is 60 BOL + 200 operational. We need a material + stack revision before re-test.",
  },
  {
    who:   "M. Sato",
    role:  "Mech Lead",
    ts:    "2026-04-24T10:40Z",
    body:  "Proposing M3 A2-70 → M3 A286 (DIN EN 2516). A286 holds yield through cryo. Add a 4× DIN 2093 Belleville stack in HHHL series-parallel for live preload reserve. Mass impact +2.4 g per hinge × 4 = +9.6 g top-assy. Margin 11.0 % → 10.93 %.",
  },
  {
    who:   "K. Sato",
    role:  "Mfg",
    ts:    "2026-04-26T11:15Z",
    body:  "HHHL stack stiffness modeled at ~7.62 kN/mm vs single Nord-Lock ~1.92 kN/mm. Vibra-Tite 213 at torque, 24 h cure, re-torque audit +1 day. FAB-B re-issue is 5 days; full WO-AET-002 staged.",
  },
  {
    who:   "L. Okonkwo",
    role:  "Mission Director",
    ts:    "2026-05-06T16:50Z",
    body:  "Customer (Aperture Earth) ack'd via email. Re-test TVAC-AET-014R scheduled — 24 cycles −40 / +85 °C with strain-gauge + torque audit at cycle 24, plus shock-survival 2000g 0.5 ms half-sine. ACC slips 2026-07-04 → 2026-07-15. LAUNCH 2026-09-10 holds. CR-2026-014 issues at MD sign.",
  },
];

// Before / after diff. Values are precise per §6 + advisor reconciliation.
const BEFORE_AFTER = [
  {
    field:  "Fastener spec",
    before: "M3 A2-70 (austenitic, cost-selected at PDR)",
    after:  "M3 A286 (DIN EN 2516, precipitation-hardened)",
    delta:  "material upgrade · A2-70 → A286",
    tone:   "ok",
  },
  {
    field:  "Preload (Nm)",
    before: "0.42 Nm measured · 0.55 ± 0.05 Nm spec",
    after:  "0.55 ± 0.05 Nm spec held · re-torque audit at +1 d",
    delta:  "in spec, audited",
    tone:   "ok",
  },
  {
    field:  "Stack stiffness",
    before: "1× Nord-Lock washer · ~1.92 kN/mm",
    after:  "4× DIN 2093 Belleville HHHL · ~7.62 kN/mm",
    delta:  "+5.70 kN/mm · ×3.97",
    tone:   "ok",
  },
  {
    field:  "Lock washer geometry",
    before: "single Nord-Lock pair, no live preload reserve",
    after:  "Belleville stack 4× DIN 2093, HHHL series-parallel",
    delta:  "live preload reserve added",
    tone:   "ok",
  },
  {
    field:  "Mass / hinge",
    before: "baseline (4 hinges)",
    after:  "+2.4 g per hinge · +9.6 g top-assy",
    delta:  "+9.6 g",
    tone:   "warn",
  },
  {
    field:  "Mass margin",
    before: "11.0 % (1.54 kg / 14.00 kg cap)",
    after:  "10.93 % (1.530 kg / 14.00 kg cap)",
    delta:  "−0.07 pp · within margin",
    tone:   "warn",
  },
  {
    field:  "Schedule · ACC",
    before: "2026-07-04 target",
    after:  "2026-07-15 target",
    delta:  "+11 d slip · LAUNCH 2026-09-10 holds",
    tone:   "warn",
  },
];

// Severity → tone. Light-theme remap: foregrounds that used to be SPACE_INK
// (dark navy contrast text on a bright pill bg) now point at SPACE_MONO_COLOR
// which resolves to var(--ink) — still a dark contrast color, just sourced
// from the canonical light-theme token instead of the old page-bg constant.
function spaceSevTone(sev) {
  if (sev === "critical") return { fg: "#fff",          bg: SPACE_DANGER,    label: "critical" };
  if (sev === "warn")     return { fg: SPACE_MONO_COLOR, bg: SPACE_WARN,     label: "warn" };
  if (sev === "ok")       return { fg: SPACE_MONO_COLOR, bg: SPACE_OK,       label: "ok" };
  if (sev === "rejected") return { fg: "#fff",          bg: SPACE_DANGER,    label: "rejected" };
  if (sev === "approved") return { fg: SPACE_MONO_COLOR, bg: SPACE_OK,       label: "approved" };
  if (sev === "revisions-requested")
                          return { fg: SPACE_MONO_COLOR, bg: SPACE_WARN,     label: "revisions-requested" };
  if (sev === "pending")  return { fg: SPACE_MONO_COLOR, bg: SPACE_INK_2,    label: "pending" };
  if (sev === "pass")     return { fg: SPACE_MONO_COLOR, bg: SPACE_OK,       label: "pass" };
  return                       { fg: SPACE_MONO_COLOR, bg: SPACE_INK_2,      label: sev || "info" };
}

// ──────────────────────────────────────────────────────────────────────
// Atoms — local, scoped to this screen so we don't leak names. Cool
// blues, mono codes, tnum digits, no emoji.
// ──────────────────────────────────────────────────────────────────────
function SPill(props) {
  const t = spaceSevTone(props.tone);
  return React.createElement("span", {
    style: {
      display: "inline-flex",
      alignItems: "center",
      gap: 4,
      height: 18,
      padding: "0 8px",
      borderRadius: 3,
      fontFamily: SPACE_FONT_MONO,
      fontSize: 12,
      letterSpacing: "0.06em",
      textTransform: "uppercase",
      color: t.fg,
      background: t.bg,
      whiteSpace: "nowrap",
    },
  }, props.children || t.label);
}

function SLabel(props) {
  return React.createElement("div", {
    style: {
      fontFamily: SPACE_FONT_MONO,
      fontSize: 12,
      letterSpacing: "0.10em",
      textTransform: "uppercase",
      color: SPACE_SLATE,
      marginBottom: 4,
    },
  }, props.children);
}

function SButton(props) {
  const variant = props.variant || "primary";
  const palette = variant === "primary"
    ? { bg: SPACE_ACCENT, fg: "#fff", border: SPACE_ACCENT }
    : variant === "danger"
      ? { bg: "transparent", fg: SPACE_DANGER, border: SPACE_DANGER }
      : variant === "warn"
        ? { bg: "transparent", fg: SPACE_WARN, border: SPACE_WARN }
        : { bg: "transparent", fg: SPACE_MONO_COLOR, border: SPACE_LINE };
  return React.createElement("button", {
    onClick: props.onClick,
    disabled: !!props.disabled,
    title: props.title || undefined,
    style: {
      display: "inline-flex",
      alignItems: "center",
      gap: 6,
      height: 30,
      padding: "0 14px",
      fontFamily: SPACE_FONT_MONO,
      fontSize: 12,
      letterSpacing: "0.05em",
      textTransform: "uppercase",
      color: props.disabled ? SPACE_SLATE : palette.fg,
      background: props.disabled ? "transparent" : palette.bg,
      border: "1px solid " + (props.disabled ? SPACE_LINE : palette.border),
      borderRadius: 4,
      cursor: props.disabled ? "not-allowed" : "pointer",
      opacity: props.disabled ? 0.55 : 1,
      transition: "background .15s ease, border-color .15s ease",
    },
  }, props.children);
}

function SPanel(props) {
  return React.createElement("section", {
    style: Object.assign({
      background: SPACE_PAPER,
      border: "1px solid " + SPACE_LINE,
      borderRadius: 6,
      overflow: "hidden",
      display: "flex",
      flexDirection: "column",
      minHeight: 0,
    }, props.style || {}),
  },
    React.createElement("header", {
      style: {
        display: "flex",
        alignItems: "center",
        justifyContent: "space-between",
        padding: "10px 14px",
        borderBottom: "1px solid " + SPACE_LINE,
        background: SPACE_INK_2,
      },
    },
      React.createElement("div", {
        style: {
          fontFamily: SPACE_FONT_MONO,
          fontSize: 12,
          letterSpacing: "0.10em",
          textTransform: "uppercase",
          color: SPACE_MONO_COLOR,
        },
      }, props.title),
      props.right || null
    ),
    React.createElement("div", {
      style: { flex: 1, minHeight: 0, overflowY: "auto" },
    }, props.children)
  );
}

function MonoNum(props) {
  return React.createElement("span", {
    className: "mono tnum",
    style: {
      fontFamily: SPACE_FONT_MONO,
      fontVariantNumeric: "tabular-nums",
      color: props.color || SPACE_MONO_COLOR,
      fontSize: props.size || 13,
    },
  }, props.children);
}

// ──────────────────────────────────────────────────────────────────────
// Sub-components
// ──────────────────────────────────────────────────────────────────────

function HeroHeader(props) {
  const eco = ECO_AET_0042;
  const stateTone = props.ecoState === "released" ? "approved"
    : props.ecoState === "flight-readiness-approved" ? "approved"
    : props.ecoState === "mission-director-approved" ? "approved"
    : props.ecoState === "design-approved" ? "approved"
    : props.ecoState === "approved" ? "approved"
    : props.ecoState === "rejected" ? "rejected"
    : props.ecoState === "revisions-requested" ? "revisions-requested"
    : "warn";
  const buttons = Array.isArray(props.buttons) ? props.buttons : [];
  return React.createElement("div", {
    style: {
      padding: "16px 20px",
      borderBottom: "1px solid " + SPACE_LINE,
      background: "linear-gradient(180deg, " + SPACE_INK_2 + " 0%, " + SPACE_INK + " 100%)",
      display: "flex",
      alignItems: "flex-start",
      justifyContent: "space-between",
      gap: 24,
    },
  },
    React.createElement("div", { style: { flex: 1, minWidth: 0 } },
      React.createElement("div", {
        style: {
          display: "flex",
          alignItems: "center",
          gap: 10,
          marginBottom: 8,
        },
      },
        React.createElement(MonoNum, { color: SPACE_ACCENT, size: 12 }, eco.id),
        React.createElement(SPill, { tone: "critical" }, "critical"),
        React.createElement(SPill, { tone: "pending" }, "ITAR · controlled"),
        React.createElement(SPill, { tone: "pending" }, "AS9100 rev D"),
        React.createElement(SPill, { tone: stateTone }, props.ecoState)
      ),
      React.createElement("h1", {
        style: {
          fontFamily: SPACE_FONT_SERIF,
          fontSize: 22,
          fontWeight: 500,
          color: SPACE_MONO_COLOR,
          margin: 0,
          lineHeight: 1.25,
        },
      }, eco.title),
      React.createElement("div", {
        style: {
          marginTop: 8,
          display: "flex",
          flexWrap: "wrap",
          gap: 18,
          fontFamily: SPACE_FONT_MONO,
          fontSize: 12,
          color: SPACE_SLATE,
        },
      },
        React.createElement("span", null,
          "target ",
          React.createElement(MonoNum, { color: SPACE_ACCENT },
            eco.target_pn + " · rev " + eco.rev_from + " → " + eco.rev_to)
        ),
        React.createElement("span", null,
          "owner ",
          React.createElement("span", { style: { color: SPACE_MONO_COLOR } },
            eco.owner + " · " + eco.owner_role)
        ),
        React.createElement("span", null,
          "opened ",
          React.createElement(MonoNum, null, eco.opened)
        )
      )
    ),
    React.createElement("div", {
      style: { display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 8 },
    },
      React.createElement("div", { style: { display: "flex", gap: 8, flexWrap: "wrap", justifyContent: "flex-end" } },
        buttons.map(function(b) {
          return React.createElement(SButton, {
            key: b.key,
            variant: b.variant || "primary",
            disabled: !!b.disabled,
            onClick: b.onClick,
            title: b.title || null,
          }, b.label);
        })
      ),
      React.createElement("div", {
        style: {
          fontFamily: SPACE_FONT_MONO,
          fontSize: 12,
          color: SPACE_SLATE,
          letterSpacing: "0.04em",
        },
      }, "9-gate ladder · approve-design → mission → flight-readiness → release")
    )
  );
}

function TriggerCard() {
  const t = ECO_AET_0042.trigger;
  return React.createElement(SPanel, { title: "trigger · TVAC chatter" },
    React.createElement("div", { style: { padding: 14, lineHeight: 1.55, color: SPACE_MONO_COLOR } },
      React.createElement("div", { style: { display: "flex", flexWrap: "wrap", gap: 16, marginBottom: 12 } },
        React.createElement("div", null,
          React.createElement(SLabel, null, "test"),
          React.createElement(MonoNum, { color: SPACE_ACCENT }, t.test_id)
        ),
        React.createElement("div", null,
          React.createElement(SLabel, null, "cycle"),
          React.createElement(MonoNum, null, t.cycle)
        ),
        React.createElement("div", null,
          React.createElement(SLabel, null, "profile"),
          React.createElement("span", { style: { fontFamily: SPACE_FONT_MONO, fontSize: 12, color: SPACE_MONO_COLOR } }, t.profile)
        )
      ),
      React.createElement("div", { style: { fontFamily: SPACE_FONT_UI, fontSize: 13, color: SPACE_MONO_COLOR } },
        t.finding, ". ", t.audit, "."
      ),
      React.createElement("div", {
        style: {
          marginTop: 12,
          padding: 10,
          background: SPACE_INK_2,
          border: "1px solid " + SPACE_LINE,
          borderLeft: "3px solid " + SPACE_DANGER,
          borderRadius: 3,
          fontFamily: SPACE_FONT_UI,
          fontSize: 12,
          color: SPACE_MONO_COLOR,
          lineHeight: 1.55,
        },
      },
        React.createElement("strong", { style: { color: SPACE_DANGER, marginRight: 6 } }, "root cause."),
        ECO_AET_0042.root_cause
      ),
      React.createElement("div", {
        style: {
          marginTop: 10,
          padding: 10,
          background: SPACE_INK_2,
          border: "1px solid " + SPACE_LINE,
          borderLeft: "3px solid " + SPACE_ACCENT,
          borderRadius: 3,
          fontFamily: SPACE_FONT_UI,
          fontSize: 12,
          color: SPACE_MONO_COLOR,
          lineHeight: 1.55,
        },
      },
        React.createElement("strong", { style: { color: SPACE_ACCENT, marginRight: 6 } }, "change."),
        ECO_AET_0042.change_summary
      )
    )
  );
}

function ImpactStrip() {
  const eco = ECO_AET_0042;
  const cards = [
    {
      label: "Mass impact",
      value: "+9.6 g",
      sub:   "+2.4 g × 4 hinges · top-assy",
      tone:  "warn",
    },
    {
      label: "Mass margin",
      value: "10.93 %",
      sub:   "11.0 % → 10.93 % · within margin",
      tone:  "warn",
    },
    {
      label: "Schedule slip",
      value: "+11 d",
      sub:   "FAB-B 5d · TVAC 4d · CofC 2d",
      tone:  "warn",
    },
    {
      label: "ACC target",
      value: eco.acc_target_new,
      sub:   "was " + eco.acc_target_was,
      tone:  "info",
    },
    {
      label: "LAUNCH",
      value: "2026-09-10",
      sub:   "Falcon 9 Transporter-15 · holds",
      tone:  "ok",
    },
    {
      label: "Retest",
      value: eco.retest.id,
      sub:   "24 cycles · shock 2000g 0.5 ms",
      tone:  "info",
    },
  ];
  return React.createElement("div", {
    style: {
      display: "grid",
      gridTemplateColumns: "repeat(6, minmax(0, 1fr))",
      gap: 10,
      padding: "14px 20px",
      borderBottom: "1px solid " + SPACE_LINE,
      background: SPACE_INK,
    },
  },
    cards.map(function(c) {
      const valueColor = c.tone === "warn" ? SPACE_WARN
        : c.tone === "ok" ? SPACE_OK
        : c.tone === "danger" ? SPACE_DANGER
        : SPACE_ACCENT;
      return React.createElement("div", {
        key: c.label,
        style: {
          padding: 10,
          border: "1px solid " + SPACE_LINE,
          borderRadius: 4,
          background: SPACE_PAPER,
        },
      },
        React.createElement(SLabel, null, c.label),
        React.createElement("div", {
          style: {
            fontFamily: SPACE_FONT_MONO,
            fontVariantNumeric: "tabular-nums",
            fontSize: 18,
            color: valueColor,
            marginBottom: 4,
          },
        }, c.value),
        React.createElement("div", {
          style: { fontFamily: SPACE_FONT_MONO, fontSize: 12, color: SPACE_SLATE, lineHeight: 1.4 },
        }, c.sub)
      );
    })
  );
}

function ApprovalLadder(props) {
  return React.createElement(SPanel, {
    title: "approval ladder · 4 stages · ITAR / AS9100 / ECSS lineage",
  },
    React.createElement("div", { style: { padding: "14px 16px" } },
      React.createElement("div", {
        style: {
          display: "grid",
          gridTemplateColumns: "repeat(4, minmax(0, 1fr))",
          gap: 0,
        },
      },
        props.stages.map(function(s, i) {
          const isPass = s.state === "pass";
          const isPending = s.state === "pending";
          const isReject = s.state === "rejected";
          const topBar = isPass ? SPACE_OK
            : isPending ? SPACE_ACCENT
            : isReject  ? SPACE_DANGER
            : SPACE_LINE;
          return React.createElement("div", {
            key: s.key,
            style: {
              padding: 12,
              borderTop: "3px solid " + topBar,
              borderRight: i < props.stages.length - 1 ? "1px solid " + SPACE_LINE : "0",
              borderBottom: "1px solid " + SPACE_LINE,
              borderLeft: i === 0 ? "1px solid " + SPACE_LINE : "0",
              background: isPending ? "rgba(79,143,255,0.06)" : "transparent",
              display: "flex",
              flexDirection: "column",
              gap: 8,
              minHeight: 220,
            },
          },
            React.createElement("div", {
              style: { display: "flex", justifyContent: "space-between", alignItems: "center" },
            },
              React.createElement("div", null,
                React.createElement(SLabel, null, "Stage " + (i + 1)),
                React.createElement("div", {
                  style: {
                    fontFamily: SPACE_FONT_SERIF,
                    fontSize: 16,
                    color: SPACE_MONO_COLOR,
                    lineHeight: 1.2,
                  },
                }, s.role)
              ),
              React.createElement(SPill, {
                tone: isPass ? "pass" : isReject ? "rejected" : "pending",
              })
            ),
            React.createElement("div", {
              style: {
                fontFamily: SPACE_FONT_MONO,
                fontSize: 12,
                color: SPACE_ACCENT,
              },
            }, s.authority + " · " + s.name),
            React.createElement("div", {
              style: { fontFamily: SPACE_FONT_MONO, fontSize: 12, color: SPACE_SLATE },
            }, s.date),
            React.createElement("div", {
              style: {
                fontFamily: SPACE_FONT_UI,
                fontSize: 12,
                color: SPACE_MONO_COLOR,
                lineHeight: 1.45,
              },
            }, s.note),
            React.createElement("div", {
              style: {
                marginTop: "auto",
                paddingTop: 8,
                borderTop: "1px dashed " + SPACE_LINE,
                fontFamily: SPACE_FONT_MONO,
                fontSize: 12,
                color: SPACE_SLATE,
                lineHeight: 1.6,
              },
            },
              React.createElement("div", null,
                React.createElement("span", { style: { color: SPACE_MONO_COLOR } }, "ITAR  "),
                "controlled · US-persons only"
              ),
              React.createElement("div", null,
                React.createElement("span", { style: { color: SPACE_MONO_COLOR } }, "AS9100 "),
                s.as9100
              ),
              React.createElement("div", null,
                React.createElement("span", { style: { color: SPACE_MONO_COLOR } }, "ECSS  "),
                s.ecss
              )
            )
          );
        })
      ),
      React.createElement("div", {
        style: {
          marginTop: 12,
          padding: "10px 12px",
          background: SPACE_INK_2,
          border: "1px dashed " + SPACE_LINE,
          borderRadius: 3,
          fontFamily: SPACE_FONT_MONO,
          fontSize: 12,
          color: SPACE_SLATE,
          lineHeight: 1.55,
        },
      },
        React.createElement("span", { style: { color: SPACE_MONO_COLOR } }, "lineage. "),
        "ITAR data plane is aetherion-itar (US-persons only, no MCP egress). ",
        "Originator M. Sato signed 2026-04-30. Mech CCB cleared 2026-05-02. Q&MA cleared 2026-05-04. ",
        "Mission Director sign-off target 2026-05-12 — gates the FRR and emits CR-2026-014 to Aperture Earth."
      )
    )
  );
}

function BeforeAfterTable() {
  return React.createElement(SPanel, {
    title: "before / after · fastener spec · preload · stiffness · geometry",
  },
    React.createElement("div", { style: { padding: 0 } },
      React.createElement("table", {
        style: {
          width: "100%",
          borderCollapse: "collapse",
          fontFamily: SPACE_FONT_MONO,
          fontSize: 12,
          color: SPACE_MONO_COLOR,
        },
      },
        React.createElement("thead", null,
          React.createElement("tr", {
            style: {
              background: SPACE_INK_2,
              fontFamily: SPACE_FONT_MONO,
              fontSize: 12,
              letterSpacing: "0.10em",
              textTransform: "uppercase",
              color: SPACE_SLATE,
            },
          },
            React.createElement("th", { style: thStyle() }, "field"),
            React.createElement("th", { style: thStyle() }, "before · rev B"),
            React.createElement("th", { style: thStyle() }, "after · rev C"),
            React.createElement("th", { style: thStyle() }, "Δ")
          )
        ),
        React.createElement("tbody", null,
          BEFORE_AFTER.map(function(row, i) {
            const deltaColor = row.tone === "warn" ? SPACE_WARN
              : row.tone === "ok"   ? SPACE_OK
              : row.tone === "danger" ? SPACE_DANGER
              : SPACE_ACCENT;
            return React.createElement("tr", {
              key: row.field,
              style: {
                borderTop: "1px solid " + SPACE_LINE,
                background: i % 2 ? "transparent" : "rgba(79,143,255,0.02)",
              },
            },
              React.createElement("td", { style: tdStyle({ color: SPACE_ACCENT }) }, row.field),
              React.createElement("td", { style: tdStyle() }, row.before),
              React.createElement("td", { style: tdStyle({ color: SPACE_OK }) }, row.after),
              React.createElement("td", { style: tdStyle({ color: deltaColor }) }, row.delta)
            );
          })
        )
      )
    )
  );
}

function thStyle() {
  return {
    textAlign: "left",
    padding: "10px 14px",
    borderBottom: "1px solid " + SPACE_LINE,
    fontWeight: 500,
  };
}

function tdStyle(extra) {
  return Object.assign({
    padding: "10px 14px",
    verticalAlign: "top",
    lineHeight: 1.5,
  }, extra || {});
}

function ConversationThread(props) {
  const messages = props.messages;
  return React.createElement(SPanel, {
    title: "conversation · TVAC chatter → fastener swap → retest",
    style: { height: "100%" },
  },
    React.createElement("div", {
      style: { padding: 14, display: "flex", flexDirection: "column", gap: 14 },
    },
      messages.map(function(m, i) {
        const initials = m.who.split(" ").map(function(x) { return x[0]; }).join("");
        const tone = m.system ? "info" : null;
        return React.createElement("div", {
          key: i,
          style: {
            display: "flex",
            gap: 10,
            paddingBottom: 12,
            borderBottom: i < messages.length - 1 ? "1px dashed " + SPACE_LINE : "0",
          },
        },
          React.createElement("div", {
            style: {
              width: 28,
              height: 28,
              borderRadius: 28,
              background: m.system ? SPACE_ACCENT_DIM : SPACE_INK_2,
              border: "1px solid " + SPACE_LINE,
              color: SPACE_MONO_COLOR,
              fontFamily: SPACE_FONT_MONO,
              fontSize: 12,
              display: "grid",
              placeItems: "center",
              flexShrink: 0,
            },
          }, initials),
          React.createElement("div", { style: { flex: 1, minWidth: 0 } },
            React.createElement("div", {
              style: {
                display: "flex",
                alignItems: "center",
                gap: 8,
                marginBottom: 4,
                flexWrap: "wrap",
              },
            },
              React.createElement("span", {
                style: { fontFamily: SPACE_FONT_UI, fontSize: 12, color: SPACE_MONO_COLOR, fontWeight: 500 },
              }, m.who),
              React.createElement("span", {
                style: { fontFamily: SPACE_FONT_MONO, fontSize: 12, color: SPACE_SLATE },
              }, "· " + m.role),
              tone ? React.createElement(SPill, { tone: tone }, "system") : null,
              React.createElement("span", {
                style: { fontFamily: SPACE_FONT_MONO, fontSize: 12, color: SPACE_SLATE, marginLeft: "auto" },
              }, m.ts)
            ),
            React.createElement("div", {
              style: {
                fontFamily: SPACE_FONT_UI,
                fontSize: 12,
                color: SPACE_MONO_COLOR,
                lineHeight: 1.55,
              },
            }, m.body)
          )
        );
      }),
      React.createElement("div", {
        style: {
          marginTop: 4,
          border: "1px solid " + SPACE_LINE,
          borderRadius: 4,
          padding: 10,
          background: SPACE_INK_2,
        },
      },
        React.createElement("textarea", {
          placeholder: "Reply on ITAR-controlled thread…",
          rows: 2,
          style: {
            width: "100%",
            background: "transparent",
            border: 0,
            outline: "none",
            color: SPACE_MONO_COLOR,
            fontFamily: SPACE_FONT_UI,
            fontSize: 12,
            resize: "none",
          },
        }),
        React.createElement("div", {
          style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 4 },
        },
          React.createElement("span", {
            style: { fontFamily: SPACE_FONT_MONO, fontSize: 12, color: SPACE_SLATE },
          }, "ITAR · controlled · receipt signed ed25519"),
          React.createElement(SButton, { variant: "primary" }, "Send")
        )
      )
    )
  );
}

// ──────────────────────────────────────────────────────────────────────
// AetherionEcoListBar — Wave 3C item 22. Compact list of all ECOs from
// tenant.eco, selectable. Default selection = first board-review ECO,
// falling back to ECO_AET_0042 (the hero).
// ──────────────────────────────────────────────────────────────────────
function AetherionEcoListBar(props) {
  const ecos = Array.isArray(props.ecos) ? props.ecos : [];
  return React.createElement("div", {
    style: {
      display: "flex", overflowX: "auto", gap: 0,
      padding: "8px 14px",
      borderBottom: "1px solid " + SPACE_LINE,
      background: SPACE_INK_2,
    },
  }, ecos.map(function(e) {
    const isSel = e.id === props.selectedId;
    // Aetherion fixture uses `state`. Be defensive.
    const eState = e.state || e.status || "—";
    const isCritical = e.severity === "critical";
    const tone = eState === "approved" || eState === "released" ? "pass"
      : eState === "rejected" ? "rejected"
      : "pending";
    return React.createElement("div", {
      key: e.id,
      role: "button",
      tabIndex: 0,
      onClick: function() { props.onSelect(e.id); },
      onKeyDown: function(ev) {
        if (ev.key === "Enter" || ev.key === " ") { ev.preventDefault(); props.onSelect(e.id); }
      },
      style: {
        padding: "8px 14px",
        cursor: "pointer",
        borderRight: "1px solid " + SPACE_LINE,
        background: isSel ? SPACE_INK : "transparent",
        borderTop: "2px solid " + (isSel ? SPACE_ACCENT : "transparent"),
        minWidth: 220,
      },
    },
      React.createElement("div", {
        style: { display: "flex", gap: 6, alignItems: "center", marginBottom: 4 },
      },
        React.createElement(MonoNum, { color: isSel ? SPACE_ACCENT : SPACE_SLATE, size: 12 }, e.id),
        isCritical ? React.createElement(SPill, { tone: "critical" }, "crit") : null,
        React.createElement(SPill, { tone: tone }, eState)
      ),
      React.createElement("div", {
        style: {
          fontFamily: SPACE_FONT_UI, fontSize: 12,
          color: isSel ? SPACE_MONO_COLOR : SPACE_SLATE,
          overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
        },
      }, e.title || "")
    );
  }));
}

// Compact detail panel for non-hero ECOs (item 22 advisor option (a)).
// Rich fixture fields (trigger, retest, before_after) only exist on the
// hero ECO; minor entries get a flat metadata view.
function AetherionEcoMinimalPanel(props) {
  const e = props.eco || {};
  // Read server-canonical cost first; fall back nowhere for these minor ECOs.
  let costStr = "—";
  if (e.cost_delta_amount_minor != null && e.cost_delta_currency) {
    const i18n = (typeof window !== "undefined") ? window.forgeI18n : null;
    if (i18n && typeof i18n.formatMoneyMinor === "function") {
      costStr = i18n.formatMoneyMinor(e.cost_delta_amount_minor, e.cost_delta_currency);
    } else {
      costStr = String(e.cost_delta_amount_minor) + " " + e.cost_delta_currency + " (minor)";
    }
  } else if (typeof e.mass_impact_g === "number") {
    costStr = "mass " + (e.mass_impact_g > 0 ? "+" : "") + e.mass_impact_g + " g";
  }
  return React.createElement("div", {
    style: { padding: 24, display: "flex", flexDirection: "column", gap: 16 },
  },
    React.createElement("div", { style: { display: "flex", gap: 10, alignItems: "center" } },
      React.createElement(MonoNum, { color: SPACE_ACCENT, size: 12 }, e.id || "—"),
      e.severity ? React.createElement(SPill, { tone: e.severity === "critical" ? "critical" : "pending" }, e.severity) : null,
      React.createElement(SPill, { tone: (e.state || e.status) === "approved" ? "pass" : "pending" }, e.state || e.status || "—")
    ),
    React.createElement("h2", {
      style: { fontFamily: SPACE_FONT_SERIF, fontSize: 18, color: SPACE_MONO_COLOR, margin: 0 },
    }, e.title || ""),
    React.createElement("div", {
      style: { display: "grid", gridTemplateColumns: "repeat(3, minmax(0, 1fr))", gap: 12, marginTop: 4 },
    },
      [
        ["Target", (e.target_pn || "—") + (e.target_rev ? " · " + e.target_rev : "")],
        ["Originator", e.originator || "—"],
        ["Opened", (function() { var raw = e.date_raised || e.opened; if (!raw || raw === "—") return "—"; var i18n = (typeof window !== "undefined") ? window.forgeI18n : null; if (i18n && i18n.formatDate && /^\d{4}-\d{2}-\d{2}$/.test(raw)) return i18n.formatDate(raw) || raw; return raw; })()],
        ["Schedule Δ", typeof e.schedule_impact_days === "number" ? (e.schedule_impact_days + " d") : "—"],
        ["Mass / cost Δ", costStr],
        ["ITAR", e.itar ? "controlled" : "unrestricted"],
      ].map(function(kv) {
        return React.createElement("div", {
          key: kv[0],
          style: { padding: 10, border: "1px solid " + SPACE_LINE, borderRadius: 4, background: SPACE_PAPER },
        },
          React.createElement(SLabel, null, kv[0]),
          React.createElement("div", { style: { fontFamily: SPACE_FONT_MONO, fontSize: 13, color: SPACE_MONO_COLOR, marginTop: 4 } }, kv[1])
        );
      })
    ),
    e.change ? React.createElement("div", { style: { marginTop: 4 } },
      React.createElement(SLabel, null, "Change summary"),
      React.createElement("div", {
        style: { marginTop: 4, fontFamily: SPACE_FONT_UI, fontSize: 13, color: SPACE_MONO_COLOR, lineHeight: 1.5 },
      }, e.change)
    ) : null,
    React.createElement("div", { style: { color: SPACE_SLATE, fontSize: 12, fontFamily: SPACE_FONT_MONO } },
      "Detail viewer · minimal mode. Select " + (window.ECO_AET_0042 ? window.ECO_AET_0042.id : "the hero ECO") + " for full trigger / retest / approval ladder."
    )
  );
}

// ──────────────────────────────────────────────────────────────────────
// ScreenAetherionECO — top-level export, registered to /build/eco.
// ──────────────────────────────────────────────────────────────────────
function ScreenAetherionECO() {
  // Wave 3C item 22 — pull the full ECO list from active tenant.
  const tenant = (typeof useActiveTenant === "function") ? useActiveTenant() : null;
  const tenantEcos = (tenant && Array.isArray(tenant.eco)) ? tenant.eco : [];
  // Default selection — first board-review ECO, else the hero, else first.
  const defaultId = (function() {
    const boardRev = tenantEcos.find(function(e) { return e.state === "board-review"; });
    if (boardRev) return boardRev.id;
    const hero = tenantEcos.find(function(e) { return e.id === ECO_AET_0042.id; });
    if (hero) return hero.id;
    return (tenantEcos[0] && tenantEcos[0].id) || ECO_AET_0042.id;
  })();
  const [selectedId, setSelectedId] = uSEH(defaultId);

  const [stages, setStages] = uSEH(function() {
    return APPROVAL_STAGES.map(function(s) { return Object.assign({}, s); });
  });
  const [ecoState, setEcoState] = uSEH(ECO_AET_0042.state_init);
  const [messages, setMessages] = uSEH(CONVERSATION_SEED.slice());
  const [toast, setToast] = uSEH(null);
  // Re-render bump on tenant / user switch — buttons compute role gating
  // from window.__forgeCurrentUser, which lives outside React state.
  // Without this, switching to Mission Director leaves all gate buttons
  // disabled until something else triggers a re-render.
  const [actorBump, setActorBump] = uSEH(0);
  uEEH(function() {
    if (typeof window === "undefined") return undefined;
    const bump = function() { setActorBump(function(b) { return b + 1; }); };
    window.addEventListener("forge:tenant-change", bump);
    window.addEventListener("forge:user-switched", bump);
    return function() {
      window.removeEventListener("forge:tenant-change", bump);
      window.removeEventListener("forge:user-switched", bump);
    };
  }, []);

  uEEH(function() {
    if (!toast) return undefined;
    const t = setTimeout(function() { setToast(null); }, 3200);
    return function() { clearTimeout(t); };
  }, [toast]);

  function pushSystemMessage(body) {
    const stamp = (new Date()).toISOString().slice(0, 19) + "Z";
    setMessages(function(prev) {
      return prev.concat([{
        who:    "Forge",
        role:   "system",
        ts:     stamp,
        body:   body,
        system: true,
      }]);
    });
  }

  // Wave 7B item 24 — wire approve/reject to server-side FSM transitions.
  // Wave 8B — expand from single APPROVE to full 9-gate ladder. Aetherion verbs:
  //   submit → board-review
  //   approve-design → design-approved              (Design Lead | Mech CCB | Q&MA)
  //   approve-mission → mission-director-approved   (Mission Director)
  //   approve-flight-readiness → flight-readiness-approved (Flight Readiness Lead)
  //   release → released                            (any · server ITAR-gated)
  //   reject → rejected
  //   approve (generic) → picks next pending chain role
  // No `request-changes` verb exists server-side, so that button stays a
  // local-state-only annotation (see onRequestChanges note).
  //
  // Returns a Promise that resolves with the server response, or rejects so
  // the caller can surface errors via toast. Optimistic local-state updates
  // run first; on success we sync ecoState from the server response so the
  // next button in the ladder appears. On failure we flip the toast to danger
  // but leave the optimistic state in place (SSE refetch via useTenantState
  // reconciles the truth when the server pushes the new row).
  function callTransition(verb, extra) {
    const fApi = (typeof window !== "undefined") ? window.forgeApi : null;
    const cur  = (typeof window !== "undefined" && window.__forgeCurrentUser) || { name: "Mission Director", role: "Mission Director" };
    if (!(fApi && fApi.eco && typeof fApi.eco.transition === "function")) {
      return Promise.reject(new Error("forgeApi.eco.transition unavailable"));
    }
    const body = Object.assign({ actor: cur.name, role: cur.role }, extra || {});
    return fApi.eco.transition(selectedId, verb, body);
  }

  // Wave 8B — generic verb dispatcher used by every approve-* / release button.
  // Pushes a system message, sets a toast, fires the verb, then on success
  // syncs ecoState to the server's canonical status so the *next* gate's
  // button appears in the ladder. On terminal-approval verbs we also flip
  // the FRR stage row to "pass" optimistically.
  function fireVerb(verb, systemMsg, toastText) {
    pushSystemMessage(systemMsg);
    setToast({ tone: "ok", text: toastText });
    if (verb === "approve-mission" || verb === "approve-flight-readiness" || verb === "release") {
      setStages(function(prev) {
        return prev.map(function(s) {
          if (s.key === "frr") {
            return Object.assign({}, s, {
              state: "pass",
              date:  s.date.replace(" · target", " · signed"),
            });
          }
          return s;
        });
      });
    }
    callTransition(verb).then(function(result) {
      if (result && result.eco && result.eco.status) {
        setEcoState(result.eco.status);
        setToast({ tone: "ok", text: verb + " ok · server state · " + result.eco.status });
      }
    }).catch(function(err) {
      const msg = (err && err.message) || String(err);
      console.error("[aetherion-eco] " + verb + " failed", err);
      setToast({ tone: "danger", text: verb + " failed · " + msg });
    });
  }

  function onApproveDesign() {
    fireVerb("approve-design",
      "Design Lead approved ECO-AET-0042. Belleville stack analysis cleared; "
    + "FAB-B routing released. Mission Director sign-off pending.",
      "design approved · ladder advances");
  }

  function onApproveMission() {
    fireVerb("approve-mission",
      "Mission Director approved ECO-AET-0042. CR-2026-014 issued to Aperture Earth. "
    + "FAB-B WO-AET-002 cleared. Retest TVAC-AET-014R queued. "
    + "Flight Readiness Review pending.",
      "mission approved · CR-2026-014 issued");
  }

  function onApproveFlightReadiness() {
    fireVerb("approve-flight-readiness",
      "Flight Readiness Lead approved ECO-AET-0042. TVAC-AET-014R retest pass "
    + "logged; shock-survival 2000g 0.5 ms confirmed. Ready for release.",
      "flight readiness approved · release pending");
  }

  function onRelease() {
    fireVerb("release",
      "ECO-AET-0042 released. CR-2026-014 closed. Drawing pack rev C live "
    + "in PLM; FAB-B WO-AET-002 cleared for production. ITAR §126.18 guard "
    + "validated (actor is US Person).",
      "released · drawing rev C live");
  }

  function onReject() {
    setStages(function(prev) {
      return prev.map(function(s) {
        if (s.key === "frr") return Object.assign({}, s, { state: "rejected" });
        return s;
      });
    });
    setEcoState("rejected");
    pushSystemMessage(
      "ECO-AET-0042 rejected. Retest plan must address pre-load loss "
    + "across full 60 BOL + 200 operational envelope. NCR-AET-019 stays "
    + "open. WAIVER-AET-005 review required."
    );
    setToast({ tone: "danger", text: "rejected · NCR-AET-019 stays open" });
    callTransition("reject").then(function(result) {
      if (result && result.eco && result.eco.status) {
        setEcoState(result.eco.status);
        setToast({ tone: "danger", text: "rejected · server state · " + result.eco.status });
      }
    }).catch(function(err) {
      const msg = (err && err.message) || String(err);
      console.error("[aetherion-eco] reject failed", err);
      setToast({ tone: "danger", text: "reject failed · " + msg });
    });
  }

  function onRequestChanges() {
    // No `request-changes` verb in the Aetherion FSM (verbs: approve-*,
    // approve, reject, submit, release). This action stays local-state-only
    // until a verb is added; SSE refetch will not touch it.
    setStages(function(prev) {
      return prev.map(function(s) {
        if (s.key === "frr") return Object.assign({}, s, {
          state: "pending",
          note:  "Revisions requested: extend retest to full 200-cycle "
               + "operational envelope, add radiation TID delta, attach "
               + "Belleville stiffness cert from supplier.",
        });
        return s;
      });
    });
    setEcoState("revisions-requested");
    pushSystemMessage(
      "FRR / Mission Director requested changes. Engineering: extend "
    + "TVAC-AET-014R to 200-cycle operational envelope; attach Belleville "
    + "stiffness cert from supplier; add radiation TID delta on A286 stack."
    );
    setToast({ tone: "warn", text: "revisions requested · 3 deltas added · (UI-only, no FSM verb)" });
  }

  // Wave 8B — derive the button stack from current ecoState + actor role.
  // Visibility rules (see server/state-machines/aetherion.js for canonical FSM):
  //   approve-design       → board-review                              · Design Lead | Mech CCB | Q&MA
  //   approve-mission      → board-review | design-approved            · Mission Director
  //   approve-flight-readiness → mission-director-approved             · Flight Readiness Lead
  //   release              → flight-readiness-approved | approved      · any (server ITAR-gated)
  //   reject               → any non-terminal state                    · any
  //   request changes      → any non-terminal state                    · any (UI-only, no FSM verb)
  // "No eligible verb for current actor" UX: we render the relevant approve
  // buttons as DISABLED with a `title=` tooltip explaining the gate, rather
  // than hiding them. Demo discoverability > visual minimalism here — the
  // reviewer should see what role unlocks each gate. Reject + Request changes
  // stay enabled across non-terminal states.
  function actorRoleMatches(actorRole, allowed) {
    if (!actorRole) return false;
    const r = String(actorRole).toLowerCase();
    return allowed.some(function(a) { return r.indexOf(a.toLowerCase()) >= 0; });
  }

  const buttons = uMEH(function() {
    const cur = (typeof window !== "undefined" && window.__forgeCurrentUser) || null;
    const actorRole = (cur && cur.role) || "Mission Director";
    const state = ecoState;
    const isTerminal = state === "released" || state === "rejected";
    const out = [];

    // approve-design — board-review · Design Lead / Mech CCB / Q&MA
    // Demo consolidation: the seeded Aetherion roster has the Mech Lead
    // acting as Design Lead during the pilot (see scripts/seed-permissions.mjs);
    // surface "mech lead" so the button enables for that persona.
    {
      const stateOk = state === "board-review";
      const roleOk = actorRoleMatches(actorRole, ["design lead", "mech ccb", "q&ma", "mech lead"]);
      const enabled = stateOk && roleOk;
      const tip = !stateOk ? "requires status board-review"
        : !roleOk ? "requires Design Lead / Mech CCB / Q&MA"
        : null;
      out.push({
        key: "approve-design",
        label: "Approve design",
        variant: "primary",
        disabled: !enabled,
        title: tip,
        onClick: enabled ? onApproveDesign : function() {},
      });
    }

    // approve-mission — board-review | design-approved · Mission Director
    {
      const stateOk = state === "board-review" || state === "design-approved";
      const roleOk = actorRoleMatches(actorRole, ["mission director"]);
      const enabled = stateOk && roleOk;
      const tip = !stateOk ? "requires board-review or design-approved"
        : !roleOk ? "requires Mission Director"
        : null;
      out.push({
        key: "approve-mission",
        label: "Approve mission",
        variant: "primary",
        disabled: !enabled,
        title: tip,
        onClick: enabled ? onApproveMission : function() {},
      });
    }

    // approve-flight-readiness — mission-director-approved · Flight Readiness Lead
    // Demo consolidation: same as approve-design — Mech Lead (acting) covers
    // this hat in the pilot roster, so accept that role here too.
    {
      const stateOk = state === "mission-director-approved";
      const roleOk = actorRoleMatches(actorRole, ["flight readiness", "mech lead"]);
      const enabled = stateOk && roleOk;
      const tip = !stateOk ? "requires status mission-director-approved"
        : !roleOk ? "requires Flight Readiness Lead"
        : null;
      out.push({
        key: "approve-flight-readiness",
        label: "Approve flight readiness",
        variant: "primary",
        disabled: !enabled,
        title: tip,
        onClick: enabled ? onApproveFlightReadiness : function() {},
      });
    }

    // release — flight-readiness-approved | approved · any (server ITAR-gated)
    {
      const stateOk = state === "flight-readiness-approved" || state === "approved";
      const enabled = stateOk;
      const tip = !stateOk ? "requires flight-readiness-approved" : null;
      out.push({
        key: "release",
        label: "Release",
        variant: "primary",
        disabled: !enabled,
        title: tip,
        onClick: enabled ? onRelease : function() {},
      });
    }

    // reject — any non-terminal · always available
    out.push({
      key: "reject",
      label: "Reject",
      variant: "danger",
      disabled: isTerminal,
      title: isTerminal ? "already terminal" : null,
      onClick: isTerminal ? function() {} : onReject,
    });

    // request changes — any non-terminal · UI-only (no FSM verb)
    out.push({
      key: "request-changes",
      label: "Request changes",
      variant: "warn",
      disabled: isTerminal,
      title: isTerminal ? "already terminal" : "UI-only (no FSM verb)",
      onClick: isTerminal ? function() {} : onRequestChanges,
    });

    return out;
  }, [ecoState, selectedId, actorBump]);

  const isHeroSelected = selectedId === ECO_AET_0042.id;
  const selectedEco = tenantEcos.find(function(e) { return e.id === selectedId; }) || null;

  return React.createElement("div", {
    "data-tenant": "aetherion",
    style: {
      display: "flex",
      flexDirection: "column",
      minHeight: 0,
      height: "100%",
      background: SPACE_INK,
      color: SPACE_MONO_COLOR,
      fontFamily: SPACE_FONT_UI,
    },
  },
    // Wave 3C item 22 — list bar at top.
    tenantEcos.length > 0 ? React.createElement(AetherionEcoListBar, {
      ecos: tenantEcos,
      selectedId: selectedId,
      onSelect: setSelectedId,
    }) : null,
    isHeroSelected
      ? React.createElement(React.Fragment, null,
          React.createElement(HeroHeader, {
            ecoState: ecoState,
            buttons: buttons,
          }),
          React.createElement(ImpactStrip),
          React.createElement("div", {
            style: {
              display: "grid",
              gridTemplateColumns: "minmax(0, 1.6fr) minmax(0, 1fr)",
              gap: 14,
              padding: 14,
              flex: 1,
              minHeight: 0,
            },
          },
            React.createElement("div", {
              style: { display: "flex", flexDirection: "column", gap: 14, minHeight: 0 },
            },
              React.createElement(TriggerCard),
              React.createElement(ApprovalLadder, { stages: stages }),
              React.createElement(BeforeAfterTable)
            ),
            React.createElement(ConversationThread, { messages: messages })
          )
        )
      : React.createElement("div", {
          style: { flex: 1, minHeight: 0, overflowY: "auto" },
        }, React.createElement(AetherionEcoMinimalPanel, { eco: selectedEco })),
    toast ? React.createElement("div", {
      style: {
        position: "fixed",
        bottom: 18,
        left: "50%",
        transform: "translateX(-50%)",
        zIndex: 1200,
        padding: "10px 18px",
        borderRadius: 4,
        fontFamily: SPACE_FONT_MONO,
        fontSize: 12,
        letterSpacing: "0.04em",
        color: toast.tone === "danger" ? "#fff" : SPACE_MONO_COLOR,
        background: toast.tone === "danger" ? SPACE_DANGER
          : toast.tone === "warn" ? SPACE_WARN
          : SPACE_OK,
        boxShadow: "0 18px 40px -10px rgba(0,0,0,0.55)",
      },
    }, toast.text) : null
  );
}

// ──────────────────────────────────────────────────────────────────────
// Route registration · defensive (Agent #12 lands the registry).
// Export the screen on window for renderIfExists("ScreenAetherionECO").
// ──────────────────────────────────────────────────────────────────────
if (typeof window !== "undefined") {
  window.ScreenAetherionECO = ScreenAetherionECO;
  window.ECO_AET_0042       = ECO_AET_0042;
  window.AETHERION_APPROVAL_STAGES = APPROVAL_STAGES;
}

if (typeof registerSpaceRoute === "function") {
  registerSpaceRoute({
    path:     "/build/eco",
    mode:     "build",
    title:    "ECO-AET-0042 · Hinge fastener",
    renderer: function() { return React.createElement(ScreenAetherionECO); },
  });
}
})();
