(function(){
/* FORGE — Aetherion · Plan / Gantt screen.

   Wave-A1 · Space tenant · agent #15 deliverable.
   Route: /plan/gantt  →  ScreenAetherionGantt
   Spec : forge-web/demo/tenant-spec/space.md  §5 lifecycle, §6 ECO,
          §2 hero arc, §10 vertical color & typography.

   9-gate program ribbon: SRR · PDR · CDR · FAB · ASSY · I&T · TVAC · ACC · LAUNCH
   Critical path: TVAC retest after ECO-AET-0042 → 11-day slip on ACC,
   LAUNCH holds at 2026-09-10 (Falcon 9 Transporter-15).

   Babel-standalone, no ES imports. Globals attached via window. */

const { useState: uSAG } = React;

// Date math. Today is locked to 2026-05-09 per §5 — never new Date().
const AET_TODAY     = "2026-05-09";
const AET_T_MINUS_0 = "2026-09-10"; // Falcon 9 Transporter-15 manifest lock

function aetDay(iso) {
  const [y, m, d] = iso.split("-").map(Number);
  return Math.floor((Date.UTC(y, m - 1, d) - Date.UTC(2025, 0, 1)) / 86_400_000);
}
function aetDaysBetween(a, b) { return aetDay(b) - aetDay(a); }

// 9-gate phase ribbon. Dates from §2 hero arc + §5 lifecycle.
const AET_PHASES = [
  { id:"SRR",    full:"System Requirements Review", start:"2025-02-10", end:"2025-03-04", state:"passed",    note:"7 actions tracked · closed 2025-03-04",          actions:7  },
  { id:"PDR",    full:"Preliminary Design Review",  start:"2025-04-01", end:"2025-06-18", state:"passed",    note:"Propulsion trade · cold-gas R-236fa selected",   actions:12 },
  { id:"CDR",    full:"Critical Design Review",     start:"2025-08-01", end:"2025-10-22", state:"passed",    note:"Mass margin 11.4% at gate · all subs frozen",    actions:9  },
  { id:"FAB-A",  full:"Fabrication · phase A",      start:"2025-10-23", end:"2026-01-30", state:"passed",    note:"Structure + harness on the bench",               actions:0  },
  { id:"ASSY",   full:"Assembly · integration",     start:"2026-02-01", end:"2026-06-04", state:"in-flight", note:"FAB-B re-issue 2026-05-05 in flight (4 hinges)", actions:0  },
  { id:"I&T",    full:"Integration & Test",         start:"2026-05-12", end:"2026-06-22", state:"upcoming",  note:"Paused for ECO retest",                          actions:0  },
  { id:"TVAC",   full:"Thermal-vacuum cycling",     start:"2026-05-20", end:"2026-06-04", state:"retest",    note:"Re-test 24/24 cycles · partial pass 2026-05-28", actions:1  },
  { id:"ACC",    full:"Flight acceptance",          start:"2026-06-25", end:"2026-07-15", state:"upcoming",  note:"Slipped 2026-07-04 → 2026-07-15 (ECO-AET-0042)", actions:0  },
  { id:"LAUNCH", full:"Launch manifest lock",       start:"2026-09-10", end:"2026-09-10", state:"upcoming",  note:"Falcon 9 Transporter-15 · sun-sync LEO 525 km",  actions:0  },
];
const AET_AXIS_START = "2025-01-12"; // LOI signed
const AET_AXIS_END   = "2026-10-15"; // 5 weeks past launch

// ECO-AET-0042 — overlay band on ASSY phase. Spec: §6.
const AET_ECO_RIBBON = {
  id: "ECO-AET-0042",
  title: "Solar-array hinge fastener — A2-70 → A286 + Belleville stack",
  target: "KESTREL-3.60.HG.03 (rev B → C)",
  opened: "2026-04-24", start: "2026-04-24", end: "2026-06-04",
  owner: "M. Sato · Mech Lead", severity: "critical",
  schedule: "FAB-B 5d + TVAC partial 4d + CofC 2d = 11d slip on ACC",
  mass: "+9.6 g (4×2.4 g) → margin 11.0% → 10.93%",
  steps: [
    { d:"2026-04-22", t:"TVAC chatter · cycle 14/24 · 50 µm pre-load loss" },
    { d:"2026-04-24", t:"NCR-AET-019 logged · ECO-AET-0042 raised" },
    { d:"2026-05-02", t:"Mech CCB sign-off" },
    { d:"2026-05-04", t:"Q&MA sign-off" },
    { d:"2026-05-05", t:"FAB-B re-issue · 4 hinges re-built" },
    { d:"2026-05-12", t:"Mission Director sign-off (target)" },
    { d:"2026-05-28", t:"TVAC-AET-014R partial re-test · 24/24 cycles" },
    { d:"2026-07-15", t:"ACC slip absorbed · LAUNCH holds 2026-09-10" },
  ],
};

// Mass-margin trend (§2 + §6). 11.4% at CDR → 10.93% after ECO.
const AET_MASS_TREND = [
  { at:"2025-03-04", phase:"SRR",   pct:14.20 },
  { at:"2025-06-18", phase:"PDR",   pct:12.80 },
  { at:"2025-10-22", phase:"CDR",   pct:11.40 },
  { at:"2026-01-30", phase:"FAB-A", pct:11.10 },
  { at:"2026-04-22", phase:"ASSY",  pct:11.00 },
  { at:"2026-04-24", phase:"ECO",   pct:10.93 },
  { at:"2026-07-15", phase:"ACC",   pct:10.93 },
];
const AET_MASS_FLOOR = 10.0;

// Phase state → cool-blue palette (§10, no neon).
const AET_STATE = {
  "passed":    { stroke:"#2D5BEA", fillPct:26, label:"PASSED",    tone:"ok"     },
  "in-flight": { stroke:"#2D5BEA", fillPct:38, label:"IN-FLIGHT", tone:"accent" },
  "retest":    { stroke:"var(--warn)", fillPct:38, label:"RETEST",    tone:"warn"   },
  "upcoming":  { stroke:"var(--ink-3)", fillPct:18, label:"UPCOMING",  tone:""       },
};
function aetPhaseFill(s)   { const x = AET_STATE[s] || AET_STATE.upcoming; return `color-mix(in oklch, ${x.stroke} ${x.fillPct}%, transparent)`; }
function aetPhaseStroke(s) { return (AET_STATE[s] || AET_STATE.upcoming).stroke; }
function aetStateLabel(s)  { return (AET_STATE[s] || AET_STATE.upcoming).label; }
function aetStateTone(s)   { return (AET_STATE[s] || AET_STATE.upcoming).tone; }

// Hoisted root layout — extracted from inline JSX style for react-doctor.
const _ae_gantt_rootStyle = {
  padding: 14, display: "grid",
  gridTemplateColumns: "1fr 320px",
  gridTemplateRows: "auto 1fr auto",
  gap: 14, height: "100%", minHeight: 0,
  background: "var(--bg-0)",
};

// ── ScreenAetherionGantt — main composition ──
function ScreenAetherionGantt() {
  const [selPhase, setSelPhase] = uSAG("ASSY");
  const [showECO,  setShowECO]  = uSAG(true);

  const tMinus = aetDaysBetween(AET_TODAY, AET_T_MINUS_0);
  const tMinusLabel = "T-" + String(tMinus).padStart(3, "0");
  const phase = AET_PHASES.find(function(p) { return p.id === selPhase; }) || AET_PHASES[4];

  return (
    <div style={_ae_gantt_rootStyle}>

      {/* HEADER STRIP — T-countdown + mission card */}
      <Panel style={{ gridColumn:"1/-1" }} title="KESTREL-3 · Plan / Gantt">
        <div style={{ display:"grid", gridTemplateColumns:"auto 1fr auto auto auto", alignItems:"center", gap:14, padding:"10px 14px" }}>
          <div>
            <div className="label" style={{ fontSize: 12, color:"var(--ink-3)" }}>Days to launch</div>
            <div className="mono tnum" style={{ fontSize:36, color:"#2D5BEA", letterSpacing:"-0.01em" }}>{tMinusLabel}</div>
            <div className="mono" style={{ fontSize: 12, color:"var(--ink-3)" }}>L-0 · {AET_T_MINUS_0}</div>
          </div>
          <div style={{ borderLeft:"1px solid var(--line)", paddingLeft:14 }}>
            <div className="serif" style={{ fontSize:14, color:"var(--ink)" }}>
              Aetherion Microsat · 12U bus · sun-sync LEO 525 km · dawn-dusk
            </div>
            <div className="mono" style={{ fontSize: 12, color:"var(--ink-3)", marginTop:2 }}>
              Aperture Earth · {((window.forgeI18n && window.forgeI18n.formatMoneyMinor("420000000", "USD")) || "$4.2M") + " FFP"} · Falcon 9 Transporter-15 manifest lock
            </div>
          </div>
          <KVMini k="Mass margin"  v="10.93%" warn />
          <KVMini k="Power margin" v="8 W" />
          <KVMini k="Open NCRs"    v="2" warn />
        </div>
      </Panel>

      {/* MAIN GANTT */}
      <Panel title="9-gate program lifecycle · 2025-Q1 → 2026-Q4" right={
        <>
          <Btn size="sm" variant={showECO?"primary":"ghost"} onClick={function(){ setShowECO(function(s){ return !s; }); }}>
            ECO-AET-0042 ribbon
          </Btn>
          <Btn size="sm" icon="ArrowD" onClick={() => window.forgeToast && window.forgeToast("Gantt export queued — wired in v2")}>Export</Btn>
        </>
      }>
        <AetGanttChart
          phases={AET_PHASES}
          today={AET_TODAY}
          launch={AET_T_MINUS_0}
          axisStart={AET_AXIS_START}
          axisEnd={AET_AXIS_END}
          eco={showECO ? AET_ECO_RIBBON : null}
          selPhase={selPhase}
          onSelectPhase={setSelPhase}
        />
      </Panel>

      {/* RIGHT — phase detail + mass trend */}
      <div style={{ display:"flex", flexDirection:"column", gap:14, minHeight:0 }}>
        <AetPhaseDetail phase={phase} eco={AET_ECO_RIBBON} today={AET_TODAY} />
        <AetMassTrend series={AET_MASS_TREND} floor={AET_MASS_FLOOR} />
      </div>

      {/* BOTTOM — critical path strip */}
      <Panel style={{ gridColumn:"1/-1" }} title="Critical path · TVAC re-test → ACC slip → LAUNCH hold">
        <AetCriticalPath eco={AET_ECO_RIBBON} today={AET_TODAY} />
      </Panel>
    </div>
  );
}

function KVMini({ k, v, warn }) {
  return (
    <div style={{ borderLeft:"1px solid var(--line)", paddingLeft:14 }}>
      <div className="label" style={{ fontSize: 12, color:"var(--ink-3)" }}>{k}</div>
      <div className="mono tnum" style={{ fontSize:18, color: warn ? "var(--warn)" : "var(--ink)" }}>{v}</div>
    </div>
  );
}

// ── AetGanttChart — SVG nine bands + NOW + LAUNCH milestone + ECO ribbon ──
function AetGanttChart(props) {
  const { phases, today, launch, axisStart, axisEnd, eco, selPhase, onSelectPhase } = props;

  const W = 920, LEFT = 140, ROW_H = 36, HDR_H = 34;
  const TOTAL_W = LEFT + W;
  const TOTAL_H = HDR_H + phases.length * ROW_H + (eco ? ROW_H + 8 : 0) + 24;

  const a0 = aetDay(axisStart), a1 = aetDay(axisEnd), aSpan = a1 - a0;
  function dayToX(iso) { return LEFT + ((aetDay(iso) - a0) / aSpan) * W; }

  const quarters = [];
  for (let y = 2025; y <= 2026; y++) {
    for (let q = 0; q < 4; q++) {
      const iso = y + "-" + String(q * 3 + 1).padStart(2, "0") + "-01";
      if (aetDay(iso) >= a0 && aetDay(iso) <= a1) quarters.push({ iso, label: y + " Q" + (q + 1) });
    }
  }

  const todayX  = dayToX(today);
  const launchX = dayToX(launch);

  return (
    <div style={{ overflow:"auto", height:"100%" }}>
      <svg width={TOTAL_W + 16} height={TOTAL_H} style={{ display:"block", minWidth: TOTAL_W }}>
        {/* header band */}
        <rect x="0" y="0" width={TOTAL_W} height={HDR_H} fill="var(--bg-0)" />
        <line x1="0" y1={HDR_H} x2={TOTAL_W} y2={HDR_H} stroke="var(--line)" strokeWidth="1" />

        {/* quarter ticks */}
        {quarters.map(function(q, i) {
          const x = dayToX(q.iso);
          return (
            <g key={"q" + i}>
              <line x1={x} y1={HDR_H} x2={x} y2={TOTAL_H} stroke="var(--line)" strokeWidth="0.5" />
              <text x={x + 4} y={22} fontSize="10" fontFamily="var(--font-mono)" fill="var(--ink-3)">{q.label}</text>
            </g>
          );
        })}

        {/* TODAY */}
        <line x1={todayX} y1={HDR_H - 6} x2={todayX} y2={TOTAL_H - 12}
          stroke="#2D5BEA" strokeWidth="1.5" strokeDasharray="3,3" />
        <rect x={todayX - 24} y={HDR_H - 14} width="48" height="14" rx="2" fill="#2D5BEA" />
        <text x={todayX} y={HDR_H - 4} textAnchor="middle"
          fontSize="9" fontFamily="var(--font-mono)" fill="var(--bg-0)" fontWeight="600">TODAY</text>

        {/* LAUNCH milestone column */}
        <line x1={launchX} y1={HDR_H} x2={launchX} y2={TOTAL_H - 12}
          stroke="var(--ink)" strokeWidth="1" strokeDasharray="2,4" opacity="0.6" />

        {/* phase bands */}
        {phases.map(function(p, i) {
          const y    = HDR_H + i * ROW_H;
          const isMs = p.id === "LAUNCH";
          const x0   = dayToX(p.start);
          const w    = Math.max(dayToX(p.end) - x0, 6);
          const sel  = p.id === selPhase;

          return (
            <g key={p.id} onClick={function() { onSelectPhase(p.id); }} style={{ cursor:"pointer" }}>
              <rect x="0" y={y} width={TOTAL_W} height={ROW_H}
                fill={sel ? "color-mix(in oklch, #2D5BEA 8%, transparent)"
                          : (i % 2 === 0 ? "transparent" : "color-mix(in oklch, var(--line) 35%, transparent)")} />
              <text x="10" y={y + ROW_H / 2 + 4} fontSize="11"
                fontFamily="var(--font-mono)" fill={sel ? "var(--ink)" : "var(--ink-3)"} fontWeight={sel ? "600" : "400"}>
                {p.id}
              </text>
              <text x="58" y={y + ROW_H / 2 + 4} fontSize="9"
                fontFamily="var(--font-mono)" fill="var(--ink-3)">
                {p.start.slice(2).replace(/-/g, "·")}
              </text>

              {isMs ? (
                <g>
                  <polygon
                    points={`${x0},${y + ROW_H / 2} ${x0 + 10},${y + 6} ${x0 + 20},${y + ROW_H / 2} ${x0 + 10},${y + ROW_H - 6}`}
                    fill="var(--ink)" stroke="#2D5BEA" strokeWidth="1.5" />
                  <text x={x0 + 26} y={y + ROW_H / 2 + 4} fontSize="10"
                    fontFamily="var(--font-mono)" fill="var(--ink)" fontWeight="600">
                    LAUNCH · {p.start}
                  </text>
                </g>
              ) : (
                <g>
                  <rect x={x0} y={y + 8} width={w} height={ROW_H - 16}
                    rx="3"
                    fill={aetPhaseFill(p.state)}
                    stroke={aetPhaseStroke(p.state)}
                    strokeWidth={sel ? "2" : "1"} />
                  {p.state === "in-flight" && (
                    <rect x={x0} y={y + 8}
                      width={Math.max(0, Math.min(todayX - x0, w))}
                      height={ROW_H - 16} rx="3"
                      fill="color-mix(in oklch, #2D5BEA 18%, transparent)" />
                  )}
                  <text x={x0 + w + 8} y={y + ROW_H / 2 + 4} fontSize="9"
                    fontFamily="var(--font-mono)" fill={aetPhaseStroke(p.state)}>
                    {aetStateLabel(p.state)}
                  </text>
                </g>
              )}
            </g>
          );
        })}

        {/* ECO-AET-0042 overlay ribbon */}
        {eco && (() => {
          const ribbonY = HDR_H + phases.length * ROW_H + 4;
          const x0 = dayToX(eco.start);
          const w  = Math.max(dayToX(eco.end) - x0, 8);
          return (
            <g>
              <rect x="0" y={ribbonY} width={TOTAL_W} height={ROW_H - 6}
                fill="color-mix(in oklch, var(--warn) 6%, transparent)" />
              <text x="10" y={ribbonY + ROW_H / 2} fontSize="11"
                fontFamily="var(--font-mono)" fill="var(--warn)" fontWeight="600">{eco.id}</text>
              <text x="10" y={ribbonY + ROW_H / 2 + 12} fontSize="9"
                fontFamily="var(--font-mono)" fill="var(--ink-3)">11-day slip</text>
              <rect x={x0} y={ribbonY + 4} width={w} height={ROW_H - 14}
                rx="2"
                fill="color-mix(in oklch, var(--warn) 22%, transparent)"
                stroke="var(--warn)" strokeWidth="1" strokeDasharray="3,2" />
              {eco.steps.map(function(s, i) {
                const sx = dayToX(s.d);
                return (
                  <g key={"step" + i}>
                    <line x1={sx} y1={ribbonY + 4} x2={sx} y2={ribbonY + ROW_H - 10}
                      stroke="var(--warn)" strokeWidth="0.8" />
                    <circle cx={sx} cy={ribbonY + ROW_H / 2 - 3} r="2" fill="var(--warn)" />
                  </g>
                );
              })}
            </g>
          );
        })()}

        {/* legend */}
        <g transform={`translate(${LEFT}, ${TOTAL_H - 14})`}>
          {[
            ["#2D5BEA", "passed"],
            ["#2D5BEA", "in-flight", true],
            ["var(--warn)", "retest"],
            ["var(--ink-3)", "upcoming"],
          ].map(function(it, i) {
            return (
              <g key={it[1]} transform={`translate(${i * 110}, 0)`}>
                <rect x="0" y="0" width="14" height="9" rx="2"
                  fill={`color-mix(in oklch, ${it[0]} ${it[2] ? 38 : 22}%, transparent)`}
                  stroke={it[0]} strokeWidth="1" />
                <text x="20" y="8" fontSize="9" fontFamily="var(--font-mono)" fill="var(--ink-3)">{it[1]}</text>
              </g>
            );
          })}
        </g>
      </svg>
    </div>
  );
}

// ── AetPhaseDetail — right panel, click-to-select detail ──
function AetPhaseDetail(props) {
  const { phase, eco, today } = props;
  const dur = aetDaysBetween(phase.start, phase.end);
  const linkedToEco = (phase.id === "ASSY" || phase.id === "TVAC" || phase.id === "ACC");
  const stationMap = { ASSY:"s3", TVAC:"s4", "I&T":"s3", ACC:"s4", LAUNCH:"s4" };
  const station = stationMap[phase.id] || "s2";

  return (
    <Panel title={phase.id + " · " + phase.full}>
      <div style={{ padding:12 }}>
        <div style={{ display:"flex", alignItems:"center", gap:8, marginBottom:8 }}>
          <Pill tone={aetStateTone(phase.state)} dot={false}>{aetStateLabel(phase.state)}</Pill>
          {phase.actions > 0 && <Pill tone="" dot={false}>{phase.actions} actions</Pill>}
          {linkedToEco && <Pill tone="warn" dot={false}>{eco.id}</Pill>}
        </div>

        <KVRow k="Start"    v={(window.forgeI18n && window.forgeI18n.formatDate(phase.start)) || phase.start} />
        <KVRow k="End"      v={(window.forgeI18n && window.forgeI18n.formatDate(phase.end)) || phase.end} />
        <KVRow k="Duration" v={dur === 0 ? "milestone" : dur + " d"} />
        <KVRow k="Today"    v={(window.forgeI18n && window.forgeI18n.formatDate(today)) || today} />

        <div className="hr" />
        <div className="serif" style={{ fontSize:12, color:"var(--ink)", marginTop:4, lineHeight:1.4 }}>
          {phase.note}
        </div>

        {phase.id === "TVAC" && (
          <>
            <div className="hr" />
            <div className="label" style={{ fontSize: 12, color:"var(--ink-3)", marginBottom:4 }}>Re-test plan</div>
            <ul style={{ margin:0, paddingLeft:16, fontSize: 12, color:"var(--ink)", lineHeight:1.6 }}>
              <li>TVAC-AET-014R · 24 cycles −40 / +85 °C · 90 min ramps</li>
              <li>Strain-gauge + torque audit at cycle 24</li>
              <li>Shock-survival 2000g half-sine 0.5 ms</li>
            </ul>
          </>
        )}

        {phase.id === "LAUNCH" && (
          <>
            <div className="hr" />
            <KVRow k="Vehicle"  v="Falcon 9 · Transporter-15" />
            <KVRow k="Orbit"    v="Sun-sync LEO · 525 km" />
            <KVRow k="Crossing" v="Dawn-dusk" />
          </>
        )}

        <div className="hr" />
        <div className="label" style={{ fontSize: 12, color:"var(--ink-3)", marginBottom:4 }}>Linked</div>
        <div style={{ display:"flex", flexDirection:"column", gap:4 }}>
          <Pill tone="" dot={false}>{"traveler://aetherion/" + station}</Pill>
          <Pill tone="" dot={false}>{"ledger://aetherion/" + phase.id.toLowerCase().replace("&","and") + "_closed"}</Pill>
        </div>
      </div>
    </Panel>
  );
}

function KVRow({ k, v }) {
  return (
    <div style={{ display:"grid", gridTemplateColumns:"86px 1fr", gap:8, padding:"3px 0" }}>
      <span className="label" style={{ fontSize: 12, color:"var(--ink-3)" }}>{k}</span>
      <span className="mono tnum" style={{ fontSize: 12, color:"var(--ink)" }}>{v}</span>
    </div>
  );
}

// ── AetMassTrend — sparkline of mass-margin %, with policy floor ──
function AetMassTrend(props) {
  const { series, floor } = props;
  const W = 280, H = 96, PAD = 18;

  const min = Math.min(floor, ...series.map(function(p){ return p.pct; })) - 0.4;
  const max = Math.max(...series.map(function(p){ return p.pct; })) + 0.4;
  const rng = max - min;

  const xs = series.map(function(_, i) { return PAD + (i * (W - 2 * PAD)) / (series.length - 1); });
  const ys = series.map(function(p) { return PAD + ((max - p.pct) / rng) * (H - 2 * PAD); });
  const path = xs.map(function(x, i) { return (i ? "L" : "M") + x.toFixed(1) + " " + ys[i].toFixed(1); }).join(" ");

  const floorY = PAD + ((max - floor) / rng) * (H - 2 * PAD);
  const last   = series[series.length - 1];
  const ecoIx  = series.findIndex(function(s){ return s.phase === "ECO"; });

  return (
    <Panel title="Mass margin · trend (% of 14.000 kg cap)">
      <div style={{ padding:10 }}>
        <svg width={W} height={H} style={{ display:"block" }}>
          <line x1={PAD} y1={floorY} x2={W - PAD} y2={floorY}
            stroke="var(--warn)" strokeWidth="1" strokeDasharray="3,2" />
          <text x={W - PAD} y={floorY - 3} textAnchor="end"
            fontSize="9" fontFamily="var(--font-mono)" fill="var(--warn)">
            policy floor {floor.toFixed(1)}%
          </text>

          <path d={path} stroke="#2D5BEA" strokeWidth="1.6" fill="none" />
          <path d={path + " L" + xs[xs.length - 1].toFixed(1) + " " + (H - PAD).toFixed(1) + " L" + xs[0].toFixed(1) + " " + (H - PAD).toFixed(1) + " Z"}
            fill="color-mix(in oklch, #2D5BEA 14%, transparent)" />

          {series.map(function(p, i) {
            const isEco = p.phase === "ECO";
            return (
              <g key={p.phase}>
                <circle cx={xs[i]} cy={ys[i]} r={isEco ? 4 : 2.5}
                  fill={isEco ? "var(--warn)" : "#2D5BEA"} stroke="var(--bg-0)" strokeWidth="1" />
                <text x={xs[i]} y={H - 4} textAnchor="middle"
                  fontSize="8" fontFamily="var(--font-mono)" fill="var(--ink-3)">{p.phase}</text>
              </g>
            );
          })}

          <text x={xs[0]} y={ys[0] - 6} textAnchor="middle"
            fontSize="9" fontFamily="var(--font-mono)" fill="var(--ink)">{series[0].pct.toFixed(1)}%</text>
          {ecoIx >= 0 && (
            <text x={xs[ecoIx]} y={ys[ecoIx] - 8} textAnchor="middle"
              fontSize="9" fontFamily="var(--font-mono)" fill="var(--warn)">{series[ecoIx].pct.toFixed(2)}%</text>
          )}
          <text x={xs[xs.length - 1]} y={ys[xs.length - 1] - 6} textAnchor="end"
            fontSize="9" fontFamily="var(--font-mono)" fill="var(--ink)">{last.pct.toFixed(2)}%</text>
        </svg>
        <div className="mono" style={{ fontSize: 12, color:"var(--ink-3)", marginTop:4 }}>
          ECO-AET-0042 absorbed: 11.0% → 10.93% (+9.6 g top-assy)
        </div>
      </div>
    </Panel>
  );
}

// ── AetCriticalPath — bottom strip · linear ECO timeline ──
function AetCriticalPath(props) {
  const { eco, today } = props;
  const W = 1080, H = 92, PAD = 24;
  const t0 = aetDay(eco.steps[0].d);
  const span = aetDay(eco.steps[eco.steps.length - 1].d) - t0;
  function x(iso) { return PAD + ((aetDay(iso) - t0) / span) * (W - 2 * PAD); }

  return (
    <div style={{ padding:"8px 14px", overflow:"auto" }}>
      <svg width={W} height={H} style={{ display:"block" }}>
        <line x1={PAD} y1={H / 2} x2={W - PAD} y2={H / 2} stroke="var(--line)" strokeWidth="2" />

        {/* shaded slip region · ECO open → ACC slip-absorbed */}
        <rect x={x("2026-04-24")} y={H / 2 - 8}
          width={x("2026-07-15") - x("2026-04-24")} height="16"
          fill="color-mix(in oklch, var(--warn) 14%, transparent)"
          stroke="var(--warn)" strokeWidth="0.6" strokeDasharray="3,3" />

        <line x1={x(today)} y1={12} x2={x(today)} y2={H - 12}
          stroke="#2D5BEA" strokeWidth="1.5" strokeDasharray="3,3" />
        <text x={x(today)} y={10} textAnchor="middle"
          fontSize="9" fontFamily="var(--font-mono)" fill="#2D5BEA">TODAY {(window.forgeI18n && window.forgeI18n.formatDate(today)) || today}</text>

        {eco.steps.map(function(s, i) {
          const above = i % 2 === 0;
          const cx = x(s.d);
          const ty = above ? H / 2 - 22 : H / 2 + 30;
          return (
            <g key={s.d}>
              <line x1={cx} y1={above ? ty + 4 : H / 2 + 8} x2={cx} y2={above ? H / 2 - 8 : ty - 4}
                stroke="var(--ink-3)" strokeWidth="0.8" />
              <circle cx={cx} cy={H / 2} r="4"
                fill={s.d === today ? "#2D5BEA" : "var(--bg-0)"}
                stroke="#2D5BEA" strokeWidth="1.5" />
              <text x={cx} y={ty} textAnchor="middle"
                fontSize="9" fontFamily="var(--font-mono)" fill="var(--ink)">{s.d}</text>
              <text x={cx} y={ty + (above ? -10 : 10)} textAnchor="middle"
                fontSize="9" fontFamily="var(--font-ui)" fill="var(--ink-3)">
                {s.t.length > 38 ? s.t.slice(0, 36) + "…" : s.t}
              </text>
            </g>
          );
        })}
      </svg>

      <div style={{ display:"grid", gridTemplateColumns:"repeat(4, 1fr)", gap:14, marginTop:8 }}>
        <CritKV k="ECO"      v={eco.id} />
        <CritKV k="Owner"    v={eco.owner} />
        <CritKV k="Schedule" v={eco.schedule} />
        <CritKV k="Mass"     v={eco.mass} />
      </div>
    </div>
  );
}

function CritKV({ k, v }) {
  return (
    <div style={{ borderLeft:"2px solid #2D5BEA", paddingLeft:10 }}>
      <div className="label" style={{ fontSize: 12, color:"var(--ink-3)" }}>{k}</div>
      <div className="mono" style={{ fontSize: 12, color:"var(--ink)", marginTop:2 }}>{v}</div>
    </div>
  );
}

// ── Route registration. Agent #12 owns SPACE_ROUTES; queue if not loaded ──
(function registerAetherionGanttRoute() {
  if (typeof window === "undefined") return;
  const route = {
    path:     "/plan/gantt",
    mode:     "plan",
    title:    "Plan / Gantt — KESTREL-3",
    tenant:   "aetherion",
    renderer: function() { return React.createElement(ScreenAetherionGantt); },
  };
  if (typeof window.registerSpaceRoute === "function") {
    window.registerSpaceRoute(route);
  } else {
    window.__SPACE_ROUTE_QUEUE__ = window.__SPACE_ROUTE_QUEUE__ || [];
    window.__SPACE_ROUTE_QUEUE__.push(route);
  }
})();

if (typeof window !== "undefined") {
  window.ScreenAetherionGantt = ScreenAetherionGantt;
  window.AET_PHASES           = AET_PHASES;
  window.AET_ECO_RIBBON       = AET_ECO_RIBBON;
  window.AET_MASS_TREND       = AET_MASS_TREND;
}
})();
