// =========================================================
// DEVELOPMENT WORKSPACE V2 — Phase 15
// -----------------------------------------------------------------
// Depth cap: Project → Development → System Detail.
// Three peer views: Overview / Systems / Delivery.
//
// Reads exclusively from pdata.dev.{systems, releases, qa,
// architectureNote, techDecisions} plus canonical features/stages.
// Systems remain the source of truth — Stage Backend/Frontend/
// Infra/QA missions filter via linkedDev() untouched.
// =========================================================

const DVD_STATE = {
  'ready':        { tone: 'green',  label: 'Ready'        },
  'in-progress':  { tone: 'blue',   label: 'In progress'  },
  'pending':      { tone: 'gray',   label: 'Pending'      },
  'blocked':      { tone: 'red',    label: 'Blocked'      },
  'partial':      { tone: 'yellow', label: 'Partial'      },
  'not-required': { tone: 'gray',   label: 'Not required' },
  'passed':       { tone: 'green',  label: 'Passed'       },
  'shipped':      { tone: 'green',  label: 'Shipped'      },
  'planned':      { tone: 'gray',   label: 'Planned'      },
};

const DVD_CAT = {
  frontend:    { label: 'Frontend',       icon: 'palette',   short: 'FE' },
  backend:     { label: 'Backend',        icon: 'terminal',  short: 'BE' },
  api:         { label: 'API',            icon: 'route',     short: 'API' },
  integration: { label: 'Integration',    icon: 'link',      short: 'INT' },
  infra:       { label: 'Infrastructure', icon: 'cloud',     short: 'INF' },
  data:        { label: 'Data',           icon: 'grid',      short: 'DAT' },
  auth:        { label: 'Auth',           icon: 'shield',    short: 'AUT' },
};

function dvdStateChip(state, size = 'sm') {
  const s = DVD_STATE[state];
  if (!s) return null;
  return <Label tone={s.tone} dot size={size}>{s.label}</Label>;
}

function dvdPortrait(name, pdata) {
  const k = (name || '').toLowerCase();
  return (pdata.people || {})[k]?.portrait || null;
}

function dvdSystemById(pdata, id) {
  return (pdata.dev?.systems || []).find(s => s.id === id);
}

// =========================================================
// ARCHITECTURE MAP — the flagship Development visual.
// One SVG. Three layered groups, restrained connectors,
// a single blue accent on the flagship "in progress" path.
// Clicking a node opens its System Detail.
// =========================================================

function DVDArchMap({ pdata, onOpen, flagshipId = 'sys-brief-service' }) {
  // Static positions — chosen for readability, not generated.
  // The layout is: Client (top) → Application (middle) → Data / Infra (bottom).
  const W = 960, H = 420;
  const nodes = {
    'sys-web':               { x: 480, y:  60, w: 200, h: 62, group: 'client', label: 'Web App',              sub: 'React · TypeScript' },
    'sys-app-api':           { x: 480, y: 180, w: 260, h: 68, group: 'app',    label: 'Application API',      sub: 'Node · Fastify' },
    'sys-brief-service':     { x: 130, y: 300, w: 200, h: 66, group: 'app',    label: 'Project Brief Service',sub: 'Backend' },
    'sys-decisions-service': { x: 360, y: 300, w: 200, h: 66, group: 'app',    label: 'Decisions Service',    sub: 'Backend' },
    'sys-research-service':  { x: 590, y: 300, w: 200, h: 66, group: 'app',    label: 'Research Service',     sub: 'Backend' },
    'sys-store':             { x: 820, y: 300, w: 130, h: 66, group: 'data',   label: 'Project Store',        sub: 'Postgres' },
    'sys-storage':           { x: 130, y: 380, w: 200, h: 34, group: 'data',   label: 'Document Storage',     sub: 'S3-compat' },
    'sys-ai':                { x: 360, y: 380, w: 200, h: 34, group: 'infra',  label: 'AI Provider',          sub: 'External' },
    'sys-auth':              { x: 590, y: 380, w: 200, h: 34, group: 'infra',  label: 'Authentication',       sub: 'Okta · SAML' },
    'sys-obs':               { x: 820, y: 380, w: 130, h: 34, group: 'infra',  label: 'Observability',        sub: 'OTel · Sentry' },
  };
  // Edges — only the ones that matter for the mental model.
  const edges = [
    { from: 'sys-web',                to: 'sys-app-api',           accent: true  },
    { from: 'sys-app-api',            to: 'sys-brief-service',     accent: true  },
    { from: 'sys-app-api',            to: 'sys-decisions-service' },
    { from: 'sys-app-api',            to: 'sys-research-service'  },
    { from: 'sys-app-api',            to: 'sys-store'             },
    { from: 'sys-brief-service',      to: 'sys-storage',           accent: true },
    { from: 'sys-brief-service',      to: 'sys-ai',                accent: true },
    { from: 'sys-brief-service',      to: 'sys-store',             accent: true },
    { from: 'sys-decisions-service',  to: 'sys-store'             },
    { from: 'sys-research-service',   to: 'sys-storage'           },
    { from: 'sys-research-service',   to: 'sys-store'             },
    { from: 'sys-web',                to: 'sys-auth',              accent: true, dashed: true },
    { from: 'sys-app-api',            to: 'sys-auth',              dashed: true },
    { from: 'sys-app-api',            to: 'sys-obs',               dashed: true },
  ];

  const stateColor = (id) => {
    const s = dvdSystemById(pdata, id);
    const st = s?.links?.state;
    if (st === 'blocked')     return '#FF381C';
    if (st === 'ready')       return '#00A656';
    if (st === 'in-progress') return '#2A85FF';
    return 'rgba(16,16,16,0.20)';
  };

  const edgePath = (from, to) => {
    const a = nodes[from], b = nodes[to];
    if (!a || !b) return '';
    const ax = a.x + a.w / 2;
    const ay = a.y + a.h;
    const bx = b.x + b.w / 2;
    const by = b.y;
    const midY = ay + (by - ay) / 2;
    return `M ${ax} ${ay} C ${ax} ${midY}, ${bx} ${midY}, ${bx} ${by}`;
  };

  return (
    <div className="dvd-arch-card">
      <div className="dvd-arch-head">
        <div>
          <div className="dv-eyebrow">Architecture</div>
          <h3 className="dvd-arch-title">System map</h3>
        </div>
        <div className="dvd-arch-legend">
          <span><i className="dvd-leg dvd-leg-blue" /> flagship path</span>
          <span><i className="dvd-leg dvd-leg-gray" /> depends on</span>
          <span><i className="dvd-leg dvd-leg-dash" /> lateral / observability</span>
        </div>
      </div>

      <div className="dvd-arch-svg-wrap">
        <svg viewBox={`0 0 ${W} ${H}`} width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
          {/* Layer bands */}
          <rect x="0"   y="30"  width={W} height="80"  rx="18" fill="rgba(16,16,16,0.02)" />
          <rect x="0"   y="150" width={W} height="118" rx="18" fill="rgba(16,16,16,0.02)" />
          <rect x="0"   y="290" width={W} height="130" rx="18" fill="rgba(16,16,16,0.02)" />
          <text x="14" y="46"  fill="var(--text-tertiary)" fontFamily="Inter" fontSize="10" fontWeight="700" letterSpacing="1.4">CLIENT</text>
          <text x="14" y="166" fill="var(--text-tertiary)" fontFamily="Inter" fontSize="10" fontWeight="700" letterSpacing="1.4">APPLICATION</text>
          <text x="14" y="306" fill="var(--text-tertiary)" fontFamily="Inter" fontSize="10" fontWeight="700" letterSpacing="1.4">DATA · INFRASTRUCTURE</text>

          {/* Edges */}
          {edges.map((e, i) => (
            <path
              key={i}
              d={edgePath(e.from, e.to)}
              fill="none"
              stroke={e.accent ? '#2A85FF' : 'rgba(16,16,16,0.18)'}
              strokeWidth={e.accent ? 1.4 : 1}
              strokeDasharray={e.dashed ? '4 4' : ''}
              opacity={e.accent ? 0.6 : 0.9}
            />
          ))}

          {/* Nodes */}
          {Object.entries(nodes).map(([id, n]) => {
            const sys = dvdSystemById(pdata, id);
            const isFlagship = id === flagshipId;
            const dotColor = stateColor(id);
            const compact = n.h <= 40;
            return (
              <g
                key={id}
                transform={`translate(${n.x} ${n.y})`}
                className="dvd-node"
                onClick={() => onOpen && onOpen(id)}
                style={{ cursor: sys ? 'pointer' : 'default' }}
              >
                <rect
                  x="0" y="0" width={n.w} height={n.h} rx="12"
                  fill="#FDFDFD"
                  stroke={isFlagship ? 'rgba(42,133,255,0.55)' : 'rgba(16,16,16,0.10)'}
                  strokeWidth={isFlagship ? 1.5 : 1}
                />
                {isFlagship && (
                  <rect x="0" y="0" width="3" height={n.h} rx="1.5" fill="#2A85FF" />
                )}
                <circle cx={n.w - 14} cy="14" r="4" fill={dotColor} />
                <text
                  x={compact ? 14 : 16}
                  y={compact ? (n.h/2 + 4) : 26}
                  fill="var(--text-primary)"
                  fontFamily="Inter" fontSize={compact ? 12 : 14}
                  fontWeight={compact ? 500 : 600}
                  letterSpacing="-0.015em"
                >{n.label}</text>
                {!compact && (
                  <text x="16" y="46" fill="var(--text-tertiary)"
                        fontFamily="Inter" fontSize="11" letterSpacing="-0.015em">{n.sub}</text>
                )}
              </g>
            );
          })}
        </svg>
      </div>
    </div>
  );
}

// =========================================================
// OVERVIEW
// =========================================================

function DVDOverview({ pdata, onNavigate, onOpenSystem }) {
  const dev = pdata.dev || {};
  const systems = dev.systems || [];
  const currentStage = pdata.stages.find(s => s.n === pdata.currentStage);

  // Engineering-readiness — derived from systems tied to the current stage
  // plus required qa items with the current stage's active missions.
  const stageSystems = systems.filter(s => s.links?.stage === pdata.currentStage);
  const stageRequired = stageSystems.filter(s => s.links?.required);
  const stageRequiredReady = stageRequired.filter(s => s.links?.state === 'ready').length;
  const readinessPct = stageRequired.length
    ? Math.round((stageRequiredReady / stageRequired.length) * 100)
    : 100;

  // Active missions inside the current stage that have engineering scope.
  const engMissions = ['frontend', 'backend', 'infra', 'qa'];
  const activeEngMissions = engMissions
    .map(k => currentStage?.missions?.find(m => m.key === k))
    .filter(Boolean);

  const nextRequired = stageRequired.find(s => s.links?.state !== 'ready');

  // Per-category readiness for the 5-cell strip.
  const catBucket = (key) => {
    const inCat = systems.filter(s => {
      if (key === 'apis')     return s.category === 'api';
      if (key === 'infra')    return s.category === 'infra' || s.category === 'data' || s.category === 'auth';
      if (key === 'qa')       return false;
      return s.category === key;
    });
    return inCat;
  };
  const cell = (key, label) => {
    if (key === 'qa') {
      const total   = (dev.qa || []).length;
      const passed  = (dev.qa || []).filter(q => q.state === 'passed').length;
      const blocked = (dev.qa || []).filter(q => q.state === 'blocked').length;
      const tone    = blocked ? 'red' : (passed === total ? 'green' : 'blue');
      return { key, label, ready: passed, total, tone, sub: blocked ? `${blocked} blocked` : `${passed}/${total} passed` };
    }
    const arr = catBucket(key);
    const ready = arr.filter(s => s.links?.state === 'ready').length;
    const blocked = arr.filter(s => s.links?.state === 'blocked').length;
    const tone = blocked ? 'red' : (ready === arr.length && arr.length ? 'green' : 'blue');
    return { key, label, ready, total: arr.length, tone, sub: blocked ? `${blocked} blocked` : `${ready}/${arr.length} ready` };
  };

  const cells = [
    cell('frontend', 'Frontend'),
    cell('backend',  'Backend'),
    cell('apis',     'APIs'),
    cell('infra',    'Infra'),
    cell('qa',       'QA / Security'),
  ];

  // Features (this stage) that have zero linked dev systems.
  const stageFeatures = (pdata.features || []).filter(f => f.stageN === pdata.currentStage);
  const featuresWaiting = stageFeatures.filter(f =>
    !systems.some(s => s.links?.feature === f.id)
  );

  // Active engineering work — systems currently in-progress.
  const activeWork = systems.filter(s => s.links?.state === 'in-progress').slice(0, 5);

  return (
    <div className="dvd-overview">

      <MGWorkspaceBanner
        kind="development"
        eyebrow="Development · MY GENI"
        title="A calm map of the system"
        sub="Every service, environment, and technical decision — grounded in the feature it serves."
      />

      {/* --- Current-stage context strip -------------------------- */}
      <div className="dv-context">
        <div className="dv-context-left">
          <div className="dv-eyebrow">Current stage</div>
          <div className="dv-context-stage">
            <span className="dv-stage-code mono">S{String(pdata.currentStage).padStart(2,'0')}</span>
            <span className="dv-stage-name">{currentStage?.name}</span>
          </div>
          <div className="dv-context-mission">
            <span>Engineering readiness ·</span>
            <b>{stageRequiredReady} of {stageRequired.length}</b>
            <span>required items ready</span>
          </div>
          {activeEngMissions.length > 0 && (
            <div className="dvd-active-missions">
              <span className="dv-eyebrow" style={{ marginRight: 8 }}>Active missions</span>
              {activeEngMissions.map(m => {
                const meta = window.MYGENI_MISSIONS[m.key];
                return (
                  <a key={m.key} href={`#/projects/${pdata.id}/plan`} className="dvd-mission-chip">
                    <Icon name={meta.icon} size={11} strokeWidth={1.75} />
                    <span>{meta.label}</span>
                  </a>
                );
              })}
            </div>
          )}
          {nextRequired && (
            <div className="dv-context-next">
              <span className="dv-eyebrow" style={{ marginRight: 8 }}>Next required</span>
              <a
                href={`#/projects/${pdata.id}/development/system/${nextRequired.id}`}
                className="dv-context-next-link"
                onClick={(e) => { e.preventDefault(); onOpenSystem(nextRequired.id); }}
              >
                {nextRequired.name} <Icon name="chevronRight" size={12} strokeWidth={2} />
              </a>
            </div>
          )}
        </div>

        <div className="dv-context-right">
          <div className="dv-readiness">
            <Ring percent={readinessPct} color="var(--primary-01)" size={72} />
            <div className="dv-readiness-meta">
              <div className="dv-eyebrow">Engineering readiness</div>
              <div className="dv-readiness-val">
                <span className="mono">{readinessPct}%</span>
                <Label tone={readinessPct === 100 ? 'green' : (readinessPct >= 60 ? 'blue' : 'yellow')} dot size="sm">
                  {readinessPct === 100 ? 'Ready' : (readinessPct >= 60 ? 'On track' : 'Needs work')}
                </Label>
              </div>
              <div className="dv-readiness-sub">for Stage {String(pdata.currentStage).padStart(2,'0')} · {currentStage?.name}</div>
            </div>
          </div>
          <a href={`#/projects/${pdata.id}/plan`} className="btn btn-dark btn-sm">
            <Icon name="stages" size={14} strokeWidth={1.75} />
            <span>View Stage</span>
          </a>
        </div>
      </div>

      {/* --- 5-cell readiness strip ------------------------------- */}
      <div className="dvd-readiness-strip">
        {cells.map(c => (
          <div className={`dvd-rs dvd-rs-${c.tone}`} key={c.key}>
            <div className="dvd-rs-head">
              <span className="dvd-rs-label">{c.label}</span>
              <span className="dvd-rs-frac mono">{c.ready}/{c.total}</span>
            </div>
            <div className="dvd-rs-bar">
              <div
                className={`dvd-rs-fill dvd-rs-fill-${c.tone}`}
                style={{ width: `${c.total ? (c.ready / c.total * 100) : 0}%` }}
              />
            </div>
            <div className="dvd-rs-sub">{c.sub}</div>
          </div>
        ))}
      </div>

      {/* --- Architecture map (flagship) -------------------------- */}
      <DVDArchMap pdata={pdata} onOpen={onOpenSystem} />

      {/* --- Two-col: active work + technical decisions ---------- */}
      <div className="dv-two-col">
        <div>
          <div className="ov-section-head" style={{ paddingBottom: 10 }}>
            <h3>Active engineering work</h3>
            <a className="link" onClick={() => onNavigate('systems')}>All systems →</a>
          </div>
          {activeWork.length ? (
            <div className="dvd-work-list">
              {activeWork.map(s => (
                <a key={s.id}
                   href={`#/projects/${pdata.id}/development/system/${s.id}`}
                   className="dvd-work-row"
                   onClick={(e) => { e.preventDefault(); onOpenSystem(s.id); }}>
                  <div className={`dvd-cat-glyph dvd-cat-${s.category}`}>
                    <Icon name={DVD_CAT[s.category]?.icon || 'grid'} size={14} strokeWidth={1.75} />
                  </div>
                  <div className="dvd-work-body">
                    <div className="dvd-work-title">{s.name}</div>
                    <div className="dvd-work-sub truncate">{s.purpose}</div>
                  </div>
                  <div className="dvd-work-owner">
                    <Avatar name={s.ownedBy} size="xs" portrait={dvdPortrait(s.ownedBy, pdata)} />
                    <span className="truncate">{s.ownedBy}</span>
                  </div>
                  {dvdStateChip(s.links?.state)}
                </a>
              ))}
            </div>
          ) : (
            <div className="dv-empty">No engineering work in flight right now.</div>
          )}
        </div>

        <div>
          <div className="ov-section-head" style={{ paddingBottom: 10 }}>
            <h3>Features waiting on development</h3>
          </div>
          {featuresWaiting.length ? (
            <div className="dv-missing">
              {featuresWaiting.map(f => (
                <a key={f.id} href={`#/projects/${pdata.id}/features/${f.id}`} className="dv-missing-row">
                  <div className="dv-missing-icon"><Icon name="features" size={14} strokeWidth={1.75} /></div>
                  <div className="dv-missing-body">
                    <div className="dv-missing-title truncate">{f.title}</div>
                    <div className="dv-missing-sub">{f.priority} · {f.owner} · Stage {String(f.stageN).padStart(2,'0')}</div>
                  </div>
                  <Label tone="yellow" size="sm">No system</Label>
                </a>
              ))}
            </div>
          ) : (
            <div className="dv-empty">Every current-stage feature has a system in flight.</div>
          )}
        </div>
      </div>

      {/* --- Technical decisions (canonical link) ---------------- */}
      {(dev.techDecisions || []).length > 0 && (
        <div style={{ marginTop: 4 }}>
          <div className="ov-section-head" style={{ paddingBottom: 10 }}>
            <h3>Technical decisions</h3>
            <a className="link" href="#/decisions">Open Decisions →</a>
          </div>
          <div className="dvd-decisions">
            {dev.techDecisions.map((td, i) => (
              <a key={i} href="#/decisions" className="dvd-decision">
                <div className="dvd-decision-body">
                  <div className="dvd-decision-title">{td.title}</div>
                  <div className="dvd-decision-why">{td.why}</div>
                </div>
                <div className="dvd-decision-meta">
                  <Avatar name={td.by} size="xs" portrait={dvdPortrait(td.by, pdata)} />
                  <span>{td.by}</span>
                  <span className="dot-sep">·</span>
                  <span className="mono">{td.when}</span>
                </div>
              </a>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// =========================================================
// SYSTEMS — catalog with filters
// =========================================================

function DVDSystems({ pdata, onOpenSystem }) {
  const systems = pdata.dev?.systems || [];
  const [cat,   setCat]   = React.useState('all');
  const [stage, setStage] = React.useState('all');
  const [feat,  setFeat]  = React.useState('all');
  const [owner, setOwner] = React.useState('all');
  const [state, setState] = React.useState('all');

  const stagesInUse = Array.from(new Set(systems.map(s => s.links?.stage).filter(Boolean))).sort();
  const featsInUse  = Array.from(new Set(systems.map(s => s.links?.feature).filter(Boolean)));
  const owners      = Array.from(new Set(systems.map(s => s.ownedBy).filter(Boolean)));
  const states      = Array.from(new Set(systems.map(s => s.links?.state).filter(Boolean)));

  const filtered = systems.filter(s => {
    if (cat   !== 'all' && s.category         !== cat)          return false;
    if (stage !== 'all' && String(s.links?.stage) !== stage)    return false;
    if (feat  !== 'all' && s.links?.feature   !== feat)         return false;
    if (owner !== 'all' && s.ownedBy          !== owner)        return false;
    if (state !== 'all' && s.links?.state     !== state)        return false;
    return true;
  });

  const clearAll = () => { setCat('all'); setStage('all'); setFeat('all'); setOwner('all'); setState('all'); };
  const any = cat !== 'all' || stage !== 'all' || feat !== 'all' || owner !== 'all' || state !== 'all';

  const cats = [
    { k: 'all',         label: 'All',            n: systems.length },
    { k: 'frontend',    label: 'Frontend',       n: systems.filter(s => s.category === 'frontend').length },
    { k: 'backend',     label: 'Backend',        n: systems.filter(s => s.category === 'backend').length },
    { k: 'api',         label: 'API',            n: systems.filter(s => s.category === 'api').length },
    { k: 'integration', label: 'Integration',    n: systems.filter(s => s.category === 'integration').length },
    { k: 'infra',       label: 'Infrastructure', n: systems.filter(s => ['infra','data','auth'].includes(s.category)).length },
  ];

  return (
    <div className="dvd-systems">
      <div className="dv-filters">
        <div className="dv-filter-chips">
          {cats.map(c => (
            <button key={c.k}
                    className={`dv-chip${cat === c.k ? ' active' : ''}`}
                    onClick={() => setCat(c.k === 'infra' ? 'infra' : c.k)}>
              {c.label} <span className="dv-chip-n">{c.n}</span>
            </button>
          ))}
        </div>
        <div className="dv-filter-selects">
          <select value={stage} onChange={(e) => setStage(e.target.value)} className="dv-select">
            <option value="all">All stages</option>
            {stagesInUse.map(s => <option key={s} value={String(s)}>Stage {String(s).padStart(2,'0')}</option>)}
          </select>
          <select value={feat} onChange={(e) => setFeat(e.target.value)} className="dv-select">
            <option value="all">All features</option>
            {featsInUse.map(fid => {
              const f = pdata.features.find(x => x.id === fid);
              return <option key={fid} value={fid}>{f?.title || fid}</option>;
            })}
          </select>
          <select value={owner} onChange={(e) => setOwner(e.target.value)} className="dv-select">
            <option value="all">All owners</option>
            {owners.map(o => <option key={o} value={o}>{o}</option>)}
          </select>
          <select value={state} onChange={(e) => setState(e.target.value)} className="dv-select">
            <option value="all">Any status</option>
            {states.map(s => <option key={s} value={s}>{DVD_STATE[s]?.label || s}</option>)}
          </select>
          {any && <button className="dv-clear" onClick={clearAll}>Clear</button>}
        </div>
      </div>

      {filtered.length ? (
        <div className="dvd-sys-list">
          {filtered.map(s => (
            <a key={s.id}
               href={`#/projects/${pdata.id}/development/system/${s.id}`}
               className="dvd-sys-row"
               onClick={(e) => { e.preventDefault(); onOpenSystem(s.id); }}>
              <div className={`dvd-cat-glyph dvd-cat-${s.category}`}>
                <Icon name={DVD_CAT[s.category]?.icon || 'grid'} size={16} strokeWidth={1.75} />
              </div>
              <div className="dvd-sys-main">
                <div className="dvd-sys-head-row">
                  <div className="dvd-sys-name">{s.name}</div>
                  <span className="dvd-cat-badge mono">{DVD_CAT[s.category]?.short}</span>
                  {dvdStateChip(s.links?.state)}
                </div>
                <div className="dvd-sys-purpose">{s.purpose}</div>
                <div className="dvd-sys-meta">
                  <span className="dvd-sys-tech">
                    {s.tech.slice(0, 3).map((t,i) => (
                      <React.Fragment key={t}>
                        {i > 0 && <span className="dot-sep">·</span>}
                        <span className="mono">{t}</span>
                      </React.Fragment>
                    ))}
                    {s.tech.length > 3 && <span className="dvd-sys-more">+{s.tech.length - 3}</span>}
                  </span>
                  {s.dependsOn?.length > 0 && (
                    <span className="dvd-sys-deps">
                      <Icon name="link" size={11} strokeWidth={1.75} />
                      <span>depends on {s.dependsOn.length}</span>
                    </span>
                  )}
                </div>
                {s.links && <RelatedTo links={s.links} pdata={pdata} compact asSpan />}
              </div>
              <div className="dvd-sys-owner">
                <Avatar name={s.ownedBy} size="sm" portrait={dvdPortrait(s.ownedBy, pdata)} />
                <div className="dvd-sys-owner-meta">
                  <div className="dvd-sys-owner-name">{s.ownedBy}</div>
                  <div className="dvd-sys-owner-when">Updated {s.updated}</div>
                </div>
              </div>
              <Icon name="chevronRight" size={14} strokeWidth={2} style={{ color: 'var(--text-tertiary)', flex: 'none' }} />
            </a>
          ))}
        </div>
      ) : (
        <div className="dv-empty dv-empty-large">
          Nothing matches those filters. <button className="link" onClick={clearAll}>Clear all</button>.
        </div>
      )}
    </div>
  );
}

// =========================================================
// SYSTEM DETAIL — Project Brief Service (canonical)
// =========================================================

function DVDSystemDetail({ pdata, systemId }) {
  const sys = dvdSystemById(pdata, systemId);
  if (!sys) {
    return (
      <div className="dvd-detail">
        <a href={`#/projects/${pdata.id}/development/systems`} className="dv-back">
          <Icon name="chevronL" size={12} strokeWidth={2} /> <span>Back to Systems</span>
        </a>
        <div className="dv-empty dv-empty-large" style={{ marginTop: 20 }}>System not found.</div>
      </div>
    );
  }

  const stage   = sys.links?.stage   ? pdata.stages.find(s => s.n === sys.links.stage) : null;
  const feature = sys.links?.feature ? pdata.features.find(f => f.id === sys.links.feature) : null;
  const missionMeta = sys.links?.mission ? window.MYGENI_MISSIONS[sys.links.mission] : null;

  const dependsOn = (sys.dependsOn || []).map(id => dvdSystemById(pdata, id)).filter(Boolean);
  const usedBy    = (sys.usedBy    || []).map(id => dvdSystemById(pdata, id)).filter(Boolean);

  // Related canonical design + research surfaces (Phase 12 links)
  const relatedDesign = (pdata.design?.screens || []).filter(d => d.links?.feature === sys.links?.feature).slice(0, 3);
  const relatedResearch = (pdata.research || []).filter(r => r.links?.feature === sys.links?.feature).slice(0, 3);
  const relatedDocs = (pdata.documents || []).filter(d => (sys.docs || []).includes(d.id));

  const catMeta = DVD_CAT[sys.category];

  return (
    <div className="dvd-detail">
      <a href={`#/projects/${pdata.id}/development/systems`} className="dv-back">
        <Icon name="chevronL" size={12} strokeWidth={2} /> <span>Back to Systems</span>
      </a>

      {/* --- Compact header --------------------------------------- */}
      <div className="dvd-detail-head">
        <div className="dvd-detail-head-l">
          <div className="dvd-detail-eyebrow">
            <Icon name={catMeta?.icon || 'terminal'} size={12} strokeWidth={1.75} />
            <span>Development · {catMeta?.label}</span>
            <span className="dot-sep">·</span>
            <span className="mono">SYS-{sys.id.replace('sys-','').toUpperCase()}</span>
          </div>
          <h1 className="dvd-detail-title">{sys.name}</h1>
          <p className="dvd-detail-purpose">{sys.purpose}</p>
          <div className="dvd-detail-meta">
            {dvdStateChip(sys.links?.state)}
            <span className="dvd-detail-meta-item">
              <Icon name="clock" size={12} strokeWidth={1.75} />
              <span>Updated {sys.updated}</span>
            </span>
            {stage && (
              <a href={`#/projects/${pdata.id}/plan`} className="dvd-detail-meta-item link">
                <Icon name="stages" size={12} strokeWidth={1.75} />
                <span>Stage {String(stage.n).padStart(2,'0')} · {stage.name}</span>
              </a>
            )}
            {missionMeta && (
              <a href={`#/projects/${pdata.id}/plan`} className="dvd-detail-meta-item link">
                <Icon name={missionMeta.icon} size={12} strokeWidth={1.75} />
                <span>{missionMeta.label} mission</span>
              </a>
            )}
            {feature && (
              <a href={`#/projects/${pdata.id}/features/${feature.id}`} className="dvd-detail-meta-item link">
                <Icon name="features" size={12} strokeWidth={1.75} />
                <span>{feature.title}</span>
              </a>
            )}
          </div>
        </div>

        <div className="dvd-detail-head-r">
          <div className="dvd-detail-owner-block">
            <div className="dv-eyebrow">Owner</div>
            <div className="dvd-detail-owner-row">
              <Avatar name={sys.ownedBy} size="sm" portrait={dvdPortrait(sys.ownedBy, pdata)} />
              <span>{sys.ownedBy}</span>
            </div>
          </div>
          <div className="dvd-tech-chips">
            {sys.tech.map(t => <span className="dvd-tech-chip mono" key={t}>{t}</span>)}
          </div>
        </div>
      </div>

      {/* --- Body split ------------------------------------------- */}
      <div className="dvd-detail-grid">

        {/* Left column */}
        <div className="dvd-detail-main">

          {/* Why + Responsibility */}
          <div className="dvd-card">
            <div className="dvd-card-head">
              <h3>Why it exists</h3>
            </div>
            <p className="dvd-prose">{sys.why}</p>

            <div className="dvd-resp">
              <div className="dvd-resp-col dvd-resp-does">
                <div className="dv-eyebrow">Responsible for</div>
                <ul className="dvd-resp-list">
                  {sys.responsibility.does.map((r, i) => (
                    <li key={i}><span className="dvd-resp-check"><Icon name="check" size={10} strokeWidth={2.5}/></span>{r}</li>
                  ))}
                </ul>
              </div>
              <div className="dvd-resp-col dvd-resp-not">
                <div className="dv-eyebrow">Not responsible for</div>
                <ul className="dvd-resp-list">
                  {sys.responsibility.notDoes.map((r, i) => (
                    <li key={i}><span className="dvd-resp-x">–</span>{r}</li>
                  ))}
                </ul>
              </div>
            </div>
          </div>

          {/* Dependencies visual */}
          <div className="dvd-card">
            <div className="dvd-card-head">
              <h3>Dependencies</h3>
              <span className="dvd-count-line mono">{dependsOn.length} up · {usedBy.length} down</span>
            </div>
            <DVDDepsDiagram center={sys} up={dependsOn} down={usedBy} pdata={pdata} />
          </div>

          {/* API endpoints */}
          {sys.apis?.length > 0 && (
            <div className="dvd-card">
              <div className="dvd-card-head">
                <h3>Interfaces</h3>
                <span className="dvd-count-line">{sys.apis.length} endpoints</span>
              </div>
              <table className="dvd-api-table">
                <thead>
                  <tr>
                    <th>Method</th>
                    <th>Path</th>
                    <th>Purpose</th>
                    <th>Status</th>
                  </tr>
                </thead>
                <tbody>
                  {sys.apis.map((a, i) => (
                    <tr key={i}>
                      <td><span className={`dvd-http dvd-http-${a.method.toLowerCase()}`}>{a.method}</span></td>
                      <td className="mono">{a.path}</td>
                      <td>{a.purpose}</td>
                      <td>{dvdStateChip(a.state)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>

              {sys.apiExample && (
                <div className="dvd-api-example">
                  <div className="dvd-api-ex-head">
                    <span className="dv-eyebrow">Example</span>
                    <span className="mono dvd-api-ex-line">
                      <span className={`dvd-http dvd-http-${sys.apiExample.request.method.toLowerCase()}`}>{sys.apiExample.request.method}</span>
                      {sys.apiExample.request.path}
                    </span>
                  </div>
                  <div className="dvd-api-ex-body">
                    <div>
                      <div className="dvd-api-ex-label">request</div>
                      <pre className="dvd-code">{JSON.stringify(sys.apiExample.request.body, null, 2)}</pre>
                    </div>
                    <div>
                      <div className="dvd-api-ex-label">response · 201</div>
                      <pre className="dvd-code">{JSON.stringify(sys.apiExample.response, null, 2)}</pre>
                    </div>
                  </div>
                </div>
              )}
            </div>
          )}

          {/* Related canonical items */}
          {(relatedDesign.length + relatedResearch.length + relatedDocs.length) > 0 && (
            <div className="dvd-card">
              <div className="dvd-card-head">
                <h3>Connected canonical work</h3>
              </div>
              <div className="dvd-linked-grid">
                {relatedDesign.length > 0 && (
                  <div>
                    <div className="dv-eyebrow" style={{ marginBottom: 8 }}>Design</div>
                    {relatedDesign.map(d => (
                      <a key={d.id} href={`#/projects/${pdata.id}/design/item/${d.id}`} className="dvd-linked-row">
                        <Icon name="palette" size={13} strokeWidth={1.75} />
                        <span className="truncate">{d.title}</span>
                        {dvdStateChip(d.links?.state)}
                      </a>
                    ))}
                  </div>
                )}
                {relatedResearch.length > 0 && (
                  <div>
                    <div className="dv-eyebrow" style={{ marginBottom: 8 }}>Research</div>
                    {relatedResearch.map(r => (
                      <a key={r.id} href={`#/projects/${pdata.id}/research/study/${r.id}`} className="dvd-linked-row">
                        <Icon name="flask" size={13} strokeWidth={1.75} />
                        <span className="truncate">{r.title}</span>
                      </a>
                    ))}
                  </div>
                )}
                {relatedDocs.length > 0 && (
                  <div>
                    <div className="dv-eyebrow" style={{ marginBottom: 8 }}>Documents</div>
                    {relatedDocs.map(d => (
                      <a key={d.id} href={`#/projects/${pdata.id}/documents`} className="dvd-linked-row">
                        <Icon name="files" size={13} strokeWidth={1.75} />
                        <span className="truncate">{d.title}</span>
                      </a>
                    ))}
                  </div>
                )}
              </div>
            </div>
          )}
        </div>

        {/* Right rail */}
        <div className="dvd-detail-rail">
          {/* Environments */}
          <div className="dvd-rail-card">
            <div className="dvd-card-head"><h4>Environments</h4></div>
            <div className="dvd-env-list">
              {['local','dev','staging','prod'].map(k => {
                const st = sys.deployments?.[k];
                if (!st) return null;
                return (
                  <div key={k} className="dvd-env-row">
                    <span className="dvd-env-name">{k === 'prod' ? 'Production' : k === 'dev' ? 'Development' : k.charAt(0).toUpperCase()+k.slice(1)}</span>
                    {dvdStateChip(st)}
                  </div>
                );
              })}
            </div>
          </div>

          {/* Security */}
          {sys.security?.length > 0 && (
            <div className="dvd-rail-card">
              <div className="dvd-card-head"><h4>Security & QA</h4></div>
              <div className="dvd-check-list">
                {sys.security.map((c, i) => (
                  <div key={i} className={`dvd-check-row dvd-check-${c.state}`}>
                    <span className={`dvd-check-glyph dvd-check-glyph-${c.state}`}>
                      {c.state === 'passed'  && <Icon name="check" size={10} strokeWidth={2.5} />}
                      {c.state === 'blocked' && <Icon name="alert" size={10} strokeWidth={2.5} />}
                    </span>
                    <span className="dvd-check-title">{c.check}</span>
                  </div>
                ))}
              </div>
            </div>
          )}

          {/* Risks */}
          {sys.risks?.length > 0 && (
            <div className="dvd-rail-card">
              <div className="dvd-card-head"><h4>Open risks</h4></div>
              <div className="dvd-risk-list">
                {sys.risks.map((r, i) => (
                  <div key={i} className={`dvd-risk-row dvd-risk-${r.level}`}>
                    <span className="dvd-risk-dot" />
                    <span>{r.note}</span>
                  </div>
                ))}
              </div>
            </div>
          )}

          {/* Decisions */}
          {sys.decisions?.length > 0 && (
            <div className="dvd-rail-card">
              <div className="dvd-card-head"><h4>Decisions</h4></div>
              <div className="dvd-decision-links">
                {sys.decisions.map((title, i) => (
                  <a key={i} href="#/decisions" className="dvd-decision-link">
                    <Icon name="decisions" size={13} strokeWidth={1.75} />
                    <span className="truncate">{title}</span>
                  </a>
                ))}
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// -----------------------------------------------------------------
// Compact upstream / downstream dependency diagram.
// One level each side — never a deep graph.
// -----------------------------------------------------------------

function DVDDepsDiagram({ center, up, down, pdata }) {
  const rowH = 40, gap = 12, colW = 220;
  const rows = Math.max(up.length, down.length, 1);
  const H = rows * (rowH + gap) + 20;
  const cy = H / 2;

  const nodeAt = (label, sub, x, y, isCenter = false, tone = 'gray') => (
    <g transform={`translate(${x} ${y - rowH/2})`}>
      <rect
        x="0" y="0" width={colW} height={rowH} rx="10"
        fill="#FDFDFD"
        stroke={isCenter ? 'rgba(42,133,255,0.55)' : 'rgba(16,16,16,0.10)'}
        strokeWidth={isCenter ? 1.5 : 1}
      />
      {isCenter && <rect x="0" y="0" width="3" height={rowH} rx="1.5" fill="#2A85FF" />}
      <text x="14" y={rowH/2 + 4} fill="var(--text-primary)"
            fontFamily="Inter" fontSize="13" fontWeight="600" letterSpacing="-0.015em">{label}</text>
      <text x={colW - 14} y={rowH/2 + 4} textAnchor="end" fill="var(--text-tertiary)"
            fontFamily="Inter" fontSize="11" letterSpacing="-0.015em">{sub}</text>
    </g>
  );

  const total = 3 * colW + 2 * 60;
  const leftX = 0, midX = colW + 60, rightX = 2 * colW + 120;

  return (
    <div className="dvd-deps">
      <svg viewBox={`0 0 ${total} ${H}`} width="100%" height={H} preserveAspectRatio="xMidYMid meet">
        <text x={leftX + 14}  y="14" fill="var(--text-tertiary)" fontFamily="Inter" fontSize="10" fontWeight="700" letterSpacing="1.4">DEPENDS ON</text>
        <text x={midX + 14}   y="14" fill="var(--text-tertiary)" fontFamily="Inter" fontSize="10" fontWeight="700" letterSpacing="1.4">THIS SERVICE</text>
        <text x={rightX + 14} y="14" fill="var(--text-tertiary)" fontFamily="Inter" fontSize="10" fontWeight="700" letterSpacing="1.4">USED BY</text>

        {/* Connectors upstream */}
        {up.map((n, i) => {
          const y = cy + (i - (up.length - 1)/2) * (rowH + gap);
          return (
            <path key={'u'+i}
                  d={`M ${leftX + colW} ${y} C ${leftX + colW + 30} ${y}, ${midX - 30} ${cy}, ${midX} ${cy}`}
                  fill="none" stroke="rgba(16,16,16,0.20)" strokeWidth="1" />
          );
        })}
        {up.map((n, i) => {
          const y = cy + (i - (up.length - 1)/2) * (rowH + gap);
          return <g key={'un'+i}>{nodeAt(n.name, DVD_CAT[n.category]?.short || '', leftX, y)}</g>;
        })}

        {/* Center */}
        {nodeAt(center.name, DVD_CAT[center.category]?.short || '', midX, cy, true)}

        {/* Connectors downstream */}
        {down.map((n, i) => {
          const y = cy + (i - (down.length - 1)/2) * (rowH + gap);
          return (
            <path key={'d'+i}
                  d={`M ${midX + colW} ${cy} C ${midX + colW + 30} ${cy}, ${rightX - 30} ${y}, ${rightX} ${y}`}
                  fill="none" stroke="rgba(42,133,255,0.35)" strokeWidth="1" />
          );
        })}
        {down.map((n, i) => {
          const y = cy + (i - (down.length - 1)/2) * (rowH + gap);
          return <g key={'dn'+i}>{nodeAt(n.name, DVD_CAT[n.category]?.short || '', rightX, y)}</g>;
        })}
      </svg>
    </div>
  );
}

// =========================================================
// DELIVERY — environments + release readiness + QA
// =========================================================

function DVDDelivery({ pdata }) {
  const dev = pdata.dev || {};
  const systems = dev.systems || [];

  // Environments summary — aggregate per environment across systems.
  const envKeys = ['local','dev','staging','prod'];
  const envSummary = envKeys.map(k => {
    const counts = { ready: 0, 'in-progress': 0, pending: 0, blocked: 0, partial: 0, 'not-required': 0 };
    systems.forEach(s => {
      const st = s.deployments?.[k];
      if (st) counts[st] = (counts[st] || 0) + 1;
    });
    let tone = 'gray', label = 'Pending';
    if (counts.blocked)                           { tone = 'red';    label = 'Blocked'; }
    else if (counts['in-progress'] || counts.partial) { tone = 'blue'; label = 'In progress'; }
    else if (counts.ready === systems.length)     { tone = 'green';  label = 'Ready'; }
    else if (counts.ready > 0)                    { tone = 'blue';   label = 'Mostly ready'; }
    return { key: k, counts, tone, label };
  });

  const envNames = {
    local: 'Local', dev: 'Development', staging: 'Staging', prod: 'Production',
  };
  const envUrls = {
    local: 'localhost',
    dev: 'dev.mygeni.app',
    staging: 'staging.mygeni.app',
    prod: 'app.mygeni.app',
  };

  // Resolve release-readiness items.
  const resolveItemState = (it) => {
    if (it.state) return it.state;
    if (it.from?.startsWith('sys-')) return dvdSystemById(pdata, it.from)?.links?.state || 'pending';
    if (it.from?.startsWith('qa-'))  return (dev.qa || []).find(q => q.id === it.from)?.state || 'pending';
    return 'pending';
  };

  return (
    <div className="dvd-delivery">
      {/* Environments row */}
      <div>
        <div className="ov-section-head" style={{ paddingBottom: 10 }}>
          <h3>Environments</h3>
          <span className="dvd-count-line">Where the product can run</span>
        </div>
        <div className="dvd-env-grid">
          {envSummary.map(e => (
            <div key={e.key} className={`dvd-env-tile dvd-env-tone-${e.tone}`}>
              <div className="dvd-env-tile-head">
                <span className="dvd-env-name">{envNames[e.key]}</span>
                {dvdStateChip(e.label.toLowerCase().replace(' ','-') === 'mostly-ready' ? 'in-progress' : e.label.toLowerCase().replace(' ','-'))}
              </div>
              <div className="dvd-env-url mono">{envUrls[e.key]}</div>
              <div className="dvd-env-counts">
                <span><b className="mono">{e.counts.ready}</b> ready</span>
                {e.counts['in-progress'] > 0 && <span><b className="mono">{e.counts['in-progress']}</b> in progress</span>}
                {e.counts.blocked > 0 && <span className="dvd-env-blocked"><b className="mono">{e.counts.blocked}</b> blocked</span>}
                {e.counts.pending > 0 && <span><b className="mono">{e.counts.pending}</b> pending</span>}
              </div>
            </div>
          ))}
        </div>
      </div>

      {/* Release readiness */}
      <div>
        <div className="ov-section-head" style={{ paddingBottom: 10, marginTop: 8 }}>
          <h3>Release readiness</h3>
        </div>
        <div className="dvd-release-grid">
          {(dev.releases || []).map(r => {
            const items = r.items.map(it => ({ ...it, resolved: resolveItemState(it) }));
            const ready = items.filter(i => ['ready','passed','shipped'].includes(i.resolved)).length;
            const total = items.length;
            const pct   = total ? Math.round(ready / total * 100) : 100;
            const blocked = items.some(i => i.resolved === 'blocked');
            return (
              <div className={`dvd-release dvd-release-${r.state}`} key={r.id}>
                <div className="dvd-release-head">
                  <div>
                    <div className="dvd-release-name">{r.name}</div>
                    <div className="dvd-release-when">{r.when}</div>
                  </div>
                  {dvdStateChip(r.state)}
                </div>
                <p className="dvd-release-note">{r.note}</p>
                <div className="dvd-release-bar">
                  <div className={`dvd-release-fill ${blocked ? 'dvd-release-fill-blocked' : ''}`} style={{ width: `${pct}%` }} />
                </div>
                <div className="dvd-release-stat mono">{ready}/{total} required · {pct}%</div>
                <ul className="dvd-release-items">
                  {items.map((it, i) => {
                    const s = it.resolved;
                    const done = ['ready','passed','shipped'].includes(s);
                    return (
                      <li key={i} className={`dvd-release-item dvd-release-item-${s}`}>
                        <span className={`dvd-release-check ${done ? 'is-done' : ''} ${s === 'blocked' ? 'is-blocked' : ''}`}>
                          {done && <Icon name="check" size={10} strokeWidth={2.5} />}
                          {s === 'blocked' && <Icon name="alert" size={10} strokeWidth={2.5} />}
                        </span>
                        <span className="dvd-release-item-title">{it.title}</span>
                        {dvdStateChip(s)}
                      </li>
                    );
                  })}
                </ul>
              </div>
            );
          })}
        </div>
      </div>

      {/* QA & Security */}
      {(dev.qa || []).length > 0 && (
        <div>
          <div className="ov-section-head" style={{ paddingBottom: 10, marginTop: 8 }}>
            <h3>QA &amp; Security</h3>
            <span className="dvd-count-line">Cross-cutting checks</span>
          </div>
          <div className="dvd-qa-list">
            {dev.qa.map(q => (
              <div key={q.id} className={`dvd-qa-row dvd-qa-${q.state}`}>
                <span className={`dvd-check-glyph dvd-check-glyph-${q.state}`}>
                  {q.state === 'passed'  && <Icon name="check" size={10} strokeWidth={2.5} />}
                  {q.state === 'blocked' && <Icon name="alert" size={10} strokeWidth={2.5} />}
                </span>
                <div className="dvd-qa-body">
                  <div className="dvd-qa-title">{q.title}</div>
                  {q.note && <div className="dvd-qa-note">{q.note}</div>}
                </div>
                {dvdStateChip(q.state)}
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// =========================================================
// ROUTER SHELL
// -----------------------------------------------------------------
// Sub-route shape:
//   /development                  → Overview
//   /development/systems          → Systems
//   /development/delivery         → Delivery
//   /development/system/:id       → System Detail
// =========================================================

function DevelopmentWorkspaceV2({ pdata, subId, sub2 }) {
  const isDetail = subId === 'system';
  const view = isDetail
    ? 'system'
    : (subId === 'systems' ? 'systems' : (subId === 'delivery' ? 'delivery' : 'overview'));

  const setView = (v) => {
    location.hash = v === 'overview'
      ? `#/projects/${pdata.id}/development`
      : `#/projects/${pdata.id}/development/${v}`;
  };
  const openSystem = (id) => {
    location.hash = `#/projects/${pdata.id}/development/system/${id}`;
  };

  return (
    <div className="dvd-root" data-screen-label={`Development · ${view}`}>
      {!isDetail && (
        <div className="dv-nav-row">
          <div className="dv-seg" role="tablist" aria-label="Development views">
            {[
              { k: 'overview', label: 'Overview' },
              { k: 'systems',  label: 'Systems'  },
              { k: 'delivery', label: 'Delivery' },
            ].map(t => (
              <button key={t.k} role="tab" aria-selected={view === t.k}
                      className={`dv-seg-btn${view === t.k ? ' active' : ''}`}
                      onClick={() => setView(t.k)}>
                {t.label}
              </button>
            ))}
          </div>
          <div className="dv-nav-actions">
            <span className="dv-direction">{pdata.dev?.architectureNote?.split('.')[0]}.</span>
          </div>
        </div>
      )}

      {view === 'overview' && <DVDOverview  pdata={pdata} onNavigate={setView} onOpenSystem={openSystem} />}
      {view === 'systems'  && <DVDSystems   pdata={pdata} onOpenSystem={openSystem} />}
      {view === 'delivery' && <DVDDelivery  pdata={pdata} />}
      {view === 'system'   && <DVDSystemDetail pdata={pdata} systemId={sub2} />}
    </div>
  );
}

Object.assign(window, {
  DevelopmentWorkspaceV2,
  DVDArchMap, DVDDepsDiagram,
});
