// Workflow Inventory — the 2x2 matrix is the moment of the deliverable.

const { useState: useStateW, useMemo: useMemoW, useEffect: useEffectW, useRef: useRefW } = React;

function WorkflowsView() {
  const all = window.WORKFLOWS;
  const depts = useMemoW(() => ['All', ...Array.from(new Set(all.map(w => w.dept)))], [all]);
  const [dept, setDept] = useStateW('All');
  const [sopFilter, setSopFilter] = useStateW('All'); // 'All' | 'Has SOP' | 'No SOP'
  const [hover, setHover] = useStateW(null);
  const [active, setActive] = useStateW(null);
  const [sopOpen, setSopOpen] = useStateW(null);
  const [mounted, setMounted] = useStateW(false);
  const [tab, setTab] = useStateW('inventory'); // 'inventory' | 'matrix' | 'list'
  const [listSort, setListSort] = useStateW({ k: 'hours', dir: 'desc' });

  useEffectW(() => {
    const t = setTimeout(() => setMounted(true), 80);
    return () => clearTimeout(t);
  }, []);

  // attach computed readiness to every workflow
  const enriched = useMemoW(() => all.map(w => ({ ...w, readiness: window.computeReadiness(w) })), [all]);

  const filtered = useMemoW(() =>
    enriched.filter(w => {
      if (dept !== 'All' && w.dept !== dept) return false;
      if (sopFilter === 'Has SOP') return !!(window.SOPS && window.SOPS[w.id]);
      if (sopFilter === 'No SOP') return !(window.SOPS && window.SOPS[w.id]);
      return true;
    }),
  [enriched, dept, sopFilter]);

  const totalHours = useMemoW(() => filtered.reduce((s, w) => s + w.hours, 0), [filtered]);

  // dot sizing — radius from hours: sqrt scale
  const maxH = Math.max(...all.map(w => w.hours));
  const radiusFor = (h) => 10 + Math.sqrt(h / maxH) * 28;

  const colorFor = (band) => ({
    'Ready to build':    '#1a8f59',
    'Near-ready':        '#b07a18',
    'Discovery needed':  '#a73a3a',
  })[band] || '#5e6068';

  // matrix layout — in % within plot area
  // x: ease (10 - effort), normalize 0..1 with 0 -> "harder" and 1 -> "easier"
  //    so high-value + easy → top-right
  const pos = (w) => ({
    x: ((10 - w.effort) / 10) * 100,
    y: (1 - (w.value / 10)) * 100,
  });

  // sorted list
  const listed = useMemoW(() => {
    const r = [...filtered];
    r.sort((a, b) => {
      let av, bv;
      if (listSort.k === 'readinessC') { av = a.readiness.composite; bv = b.readiness.composite; }
      else { av = a[listSort.k]; bv = b[listSort.k]; }
      if (typeof av === 'string') return listSort.dir === 'asc' ? av.localeCompare(bv) : bv.localeCompare(av);
      return listSort.dir === 'asc' ? av - bv : bv - av;
    });
    return r;
  }, [filtered, listSort]);

  const toggleSort = (k) => setListSort(s => s.k === k ? { k, dir: s.dir === 'asc' ? 'desc' : 'asc' } : { k, dir: 'desc' });

  return (
    <div className="view workflows-view">
      <div className="page-head">
        <div>
          <div className="kicker">Section III · Centerpiece</div>
          <h1 className="page-title">Workflow Inventory</h1>
          <p className="page-lede">Sixteen recurring workflows mapped and scored on value, ease of deployment, and build readiness. Build readiness combines how complete the current-state process documentation is with how prepared the dependent data systems are. In the matrix view, dot color and size encode readiness band and annual hours recoverable.</p>
        </div>
        <div className="wf-summary">
          <div className="wfs-item">
            <div className="wfs-n serif-num">{filtered.length}</div>
            <div className="wfs-l">Workflows mapped</div>
          </div>
          <div className="wfs-item">
            <div className="wfs-n serif-num">{totalHours.toLocaleString()}</div>
            <div className="wfs-l">Annual hours mapped</div>
            <div className="wfs-note">All 16 workflows. Executive Summary shows {window.READINESS.hoursRecoverable.toLocaleString()} hrs (P0–P2 roadmap only).</div>
          </div>
        </div>
      </div>

      <div className="wf-controls">
        <div className="seg">
          <button className={tab === 'inventory' ? 'is-active' : ''} onClick={() => setTab('inventory')}><IconLayers size={13}/>Inventory</button>
          <button className={tab === 'matrix' ? 'is-active' : ''} onClick={() => setTab('matrix')}><IconMatrix size={13}/>Matrix</button>
          <button className={tab === 'list' ? 'is-active' : ''} onClick={() => setTab('list')}><IconTable size={13}/>List</button>
        </div>
        <div className="filter-group">
          <span className="filter-label">Department</span>
          {depts.map(d => (
            <button key={d} className={"chip-btn" + (dept === d ? ' is-active' : '')} onClick={() => setDept(d)}>{d}</button>
          ))}
        </div>
        <div className="filter-group">
          <span className="filter-label">SOP</span>
          {['All', 'Has SOP', 'No SOP'].map(f => (
            <button key={f} className={"chip-btn" + (sopFilter === f ? ' is-active' : '')} onClick={() => setSopFilter(f)}>{f}</button>
          ))}
        </div>
        <div className="legend">
          <span className="legend-label">Build readiness</span>
          <span><span className="legend-dot" style={{background:'#1a8f59'}}></span>Ready to build</span>
          <span><span className="legend-dot" style={{background:'#b07a18'}}></span>Near-ready</span>
          <span><span className="legend-dot" style={{background:'#a73a3a'}}></span>Discovery needed</span>
        </div>
      </div>

      {tab === 'inventory' && (
        <InventoryBoard workflows={filtered} onOpen={setActive}/>
      )}

      {tab === 'matrix' && (
        <div className="matrix-frame">
          <div className="matrix-axis-y">Value to the business →</div>
          <div className="matrix-area">
            <div className="quadrant-label q-tr">Quick Wins</div>
            <div className="quadrant-label q-tl">Strategic Bets</div>
            <div className="quadrant-label q-br">Tidy-ups</div>
            <div className="quadrant-label q-bl">Deprioritize</div>

            <div className="matrix-grid"></div>

            {filtered.map((w, i) => {
              const p = pos(w);
              const r = radiusFor(w.hours);
              const isHover = hover === w.id;
              const isActive = active && active.id === w.id;
              return (
                <button
                  key={w.id}
                  className={"wf-dot" + (isHover ? ' is-hover' : '') + (isActive ? ' is-active' : '') + (mounted ? ' is-in' : '')}
                  style={{
                    left: p.x + '%',
                    top: p.y + '%',
                    width: r*2 + 'px',
                    height: r*2 + 'px',
                    background: colorFor(w.readiness.band),
                    transitionDelay: (i * 45) + 'ms',
                  }}
                  onMouseEnter={() => setHover(w.id)}
                  onMouseLeave={() => setHover(null)}
                  onClick={() => setActive(w)}
                  aria-label={w.name}
                >
                  {isHover && (
                    <div className="wf-tip">
                      <div className="wf-tip-name">{w.name}</div>
                      <div className="wf-tip-meta">{w.dept} · {w.hours.toLocaleString()} hrs/yr · Readiness {w.readiness.composite}</div>
                    </div>
                  )}
                </button>
              );
            })}
          </div>
          <div className="matrix-axis-x">Ease to deploy →</div>
        </div>
      )}

      {tab === 'list' && (
        <div className="table-wrap">
          <table className="data-table wf-list">
            <thead>
              <tr>
                {[
                  { k: 'name', label: 'Workflow' },
                  { k: 'dept', label: 'Department' },
                  { k: 'value', label: 'Value' },
                  { k: 'effort', label: 'Effort' },
                  { k: 'hours', label: 'Hours / yr' },
                  { k: 'readinessC', label: 'Build readiness' },
                ].map(({ k, label }) => (
                  <th key={k} onClick={() => toggleSort(k)} style={{cursor:'pointer'}}>
                    <span className="th-inner">
                      {label}
                      {listSort.k === k && (listSort.dir === 'asc' ? <IconChevronUp size={11}/> : <IconChevronDown size={11}/>)}
                    </span>
                  </th>
                ))}
                <th>Status</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {listed.map(w => (
                <tr key={w.id} onClick={() => setActive(w)}>
                  <td className="cell-strong">{w.name}</td>
                  <td className="cell-soft">{w.dept}</td>
                  <td>
                    <div className="bar-cell"><div className="bar-cell-fill" style={{width: w.value*10 + '%', background:'var(--blue)'}}></div><span>{w.value.toFixed(1)}</span></div>
                  </td>
                  <td>
                    <div className="bar-cell"><div className="bar-cell-fill" style={{width: w.effort*10 + '%', background:'#cdcfd5'}}></div><span>{w.effort.toFixed(1)}</span></div>
                  </td>
                  <td className="cell-num serif-num">{w.hours.toLocaleString()}</td>
                  <td><ReadinessCell r={w.readiness}/></td>
                  <td><StatusChip status={w.status}/></td>
                  <td className="cell-arrow"><IconArrowRight size={13}/></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {active && (
        <>
          <div className="side-backdrop" onClick={() => setActive(null)}></div>
          <aside className="side-panel side-panel--wide">
            <div className="side-head">
              <div>
                <div className="kicker">{active.dept}</div>
                <h3 className="side-title">{active.name}</h3>
              </div>
              <button className="icon-btn" onClick={() => setActive(null)}><IconX size={16}/></button>
            </div>

            <ReadinessBlock w={active}/>

            {(() => {
              const hasSop = window.SOPS && window.SOPS[active.id];
              return (
                <div className="side-section">
                  <button className={'side-cta' + (hasSop ? '' : ' side-cta--ghost')} onClick={() => setSopOpen(active)}>
                    {hasSop ? 'Open full SOP' : 'View process documentation'}<IconArrowRight size={14}/>
                  </button>
                  <div className="sop-hint">
                    {hasSop
                      ? 'Step-by-step procedure · ' + window.SOPS[active.id].code + ' · v' + window.SOPS[active.id].version
                      : 'Not yet documented — see what exists and what\'s missing.'}
                  </div>
                </div>
              );
            })()}

            <div className="wf-detail-stats">
              <div className="wfds">
                <div className="wfds-l">Annual hours saved</div>
                <div className="wfds-v serif-num">{active.hours.toLocaleString()}</div>
              </div>
              <div className="wfds">
                <div className="wfds-l">Value · Effort</div>
                <div className="wfds-v serif-num">{active.value.toFixed(1)}<span style={{color:'var(--ink-3)', fontSize:'0.5em', margin:'0 6px'}}>/</span>{active.effort.toFixed(1)}</div>
              </div>
              <div className="wfds">
                <div className="wfds-l">Classification</div>
                <div className="wfds-v"><StatusChip status={active.status}/></div>
              </div>
              <div className="wfds">
                <div className="wfds-l">Frequency</div>
                <div className="wfds-v" style={{fontSize:14, color:'var(--ink-0)'}}>{active.frequency}</div>
              </div>
              <div className="wfds">
                <div className="wfds-l">Department</div>
                <div className="wfds-v" style={{fontSize:14, color:'var(--ink-0)'}}>{active.dept}</div>
              </div>
            </div>

            {active.trigger && (
              <div className="side-section">
                <div className="kicker">Trigger</div>
                <p className="side-body">{active.trigger}</p>
              </div>
            )}
            <div className="side-section">
              <div className="kicker">Current state</div>
              <p className="side-body">{active.current}</p>
            </div>
            <div className="side-section">
              <div className="kicker">Proposed AI approach</div>
              <p className="side-body">{active.proposed}</p>
            </div>
            <div className="side-section">
              <div className="kicker">Expected impact</div>
              <p className="side-body">{active.impact}</p>
            </div>
          </aside>
        </>
      )}
      {sopOpen && (
        <SopReader w={sopOpen} onClose={() => setSopOpen(null)}/>
      )}
    </div>
  );
}

// --- Rubric breakdown -------------------------------------------------------

function RubricBreakdown({ rubric, compact }) {
  const def = window.PROCESS_RUBRIC_DEF;
  if (!rubric || !def) return null;
  return (
    <div className={"rubric-breakdown" + (compact ? ' rubric-breakdown--compact' : '')}>
      {def.map(d => {
        const entry = rubric.find(r => r.id === d.id);
        if (!entry) return null;
        const score = entry.score || 0;
        return (
          <div key={d.id} className="rubric-row">
            <div className="rubric-row-label">{d.label}</div>
            <div className="rubric-row-right">
              <div className="rubric-dots">
                {[1, 2, 3].map(i => (
                  <span key={i} className={"rubric-dot" + (i <= score ? ' is-filled' : '')}/>
                ))}
              </div>
              {!compact && <span className="rubric-tier">{d.tiers[score]}</span>}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// --- Readiness components ---------------------------------------------------

function ReadinessCell({ r }) {
  const color = r.composite >= 80 ? '#1a8f59' : r.composite >= 60 ? '#b07a18' : '#a73a3a';
  return (
    <div className="readiness-cell">
      <div className="rc-num serif-num" style={{color}}>{r.composite}</div>
      <div className="rc-track"><div className="rc-fill" style={{width: r.composite + '%', background: color}}></div></div>
    </div>
  );
}

function TierMini({ tier }) {
  const c = tier === 'Ready Now' ? '#1a8f59' : tier === 'Needs Prep' ? '#b07a18' : '#7a7d85';
  return <span className="tier-mini" style={{color: c, borderColor: c}}>{tier}</span>;
}

function ReadinessBlock({ w }) {
  const r = w.readiness;
  const color = r.composite >= 80 ? '#1a8f59' : r.composite >= 60 ? '#b07a18' : '#a73a3a';
  const size = 88, stroke = 6;
  const rad = (size - stroke) / 2;
  const c = 2 * Math.PI * rad;
  const off = c - (r.composite / 100) * c;
  return (
    <div className="readiness-block">
      <div className="rb-head">
        <div className="rb-ring">
          <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
            <circle cx={size/2} cy={size/2} r={rad} stroke="rgba(10,10,10,0.07)" strokeWidth={stroke} fill="none"/>
            <circle cx={size/2} cy={size/2} r={rad} stroke={color} strokeWidth={stroke} fill="none"
              strokeDasharray={c} strokeDashoffset={off} strokeLinecap="round"
              transform={`rotate(-90 ${size/2} ${size/2})`}
              style={{transition:'stroke-dashoffset 700ms cubic-bezier(.2,.7,.2,1)'}}/>
          </svg>
          <div className="rb-ring-num">
            <span className="serif-num" style={{fontSize:28, color:'var(--ink-0)', lineHeight:1}}>{r.composite}</span>
            <span style={{fontSize:10, color:'var(--ink-3)'}}>/100</span>
          </div>
        </div>
        <div className="rb-meta">
          <div className="kicker">Build Readiness</div>
          <div className="rb-band" style={{color}}>{r.band}</div>
          <div className="rb-desc">A combined score across process documentation (35%), data-system readiness (35%), and output definition clarity (30%).</div>
        </div>
      </div>

      <div className="rb-breakdown">
        <div className="rb-bd-item">
          <div className="rb-bd-head">
            <span className="kicker">Process documentation</span>
            <span className="rb-bd-val serif-num">{r.processDoc}</span>
          </div>
          <div className="rb-track"><div className="rb-fill" style={{width: r.processDoc + '%'}}></div></div>
          {r.rubric
            ? <RubricBreakdown rubric={r.rubric}/>
            : <div className="rb-note">{w.processNote}</div>
          }
        </div>
        <div className="rb-bd-item">
          <div className="rb-bd-head">
            <span className="kicker">Data systems</span>
            <span className="rb-bd-val serif-num">{r.dataScore}</span>
          </div>
          <div className="rb-track"><div className="rb-fill" style={{width: r.dataScore + '%'}}></div></div>
          <div className="rb-note">Weighted average across {r.deps.length} required system{r.deps.length === 1 ? '' : 's'}.</div>
        </div>
        <div className="rb-bd-item">
          <div className="rb-bd-head">
            <span className="kicker">Output definition</span>
            <span className="rb-bd-val serif-num">{r.outputAmbiguity}</span>
          </div>
          <div className="rb-track"><div className="rb-fill" style={{width: r.outputAmbiguity + '%'}}></div></div>
          <div className="rb-note">{w.outputAmbiguityNote}</div>
        </div>
      </div>

      <div className="rb-systems">
        <div className="kicker" style={{marginBottom:8}}>Required systems</div>
        <ul className="rb-sys-list">
          {r.deps.map(d => (
            <li key={d.name}>
              <span className="rb-sys-name">{d.name}</span>
              <TierMini tier={d.tier}/>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

// --- Inventory board --------------------------------------------------------
// Org-chart style breakdown: each column is a department, each card a workflow.
// Goal: visualize every inventoried process and make them all 'agent ready'.

function InventoryBoard({ workflows, onOpen }) {
  // derive dept order from actual workflows (preserving first-seen order)
  const deptOrder = Array.from(new Set(workflows.map(w => w.dept)));
  const byDept = {};
  deptOrder.forEach(d => { byDept[d] = []; });
  workflows.forEach(w => { byDept[w.dept].push(w); });

  // overall stats
  const total = workflows.length;
  const ready = workflows.filter(w => w.readiness.band === 'Ready to build').length;
  const near = workflows.filter(w => w.readiness.band === 'Near-ready').length;
  const disc = workflows.filter(w => w.readiness.band === 'Discovery needed').length;
  const overallPct = total ? Math.round((ready / total) * 100) : 0;

  // horizontal scroll state
  const scrollRef = useRefW(null);
  const [scrollInfo, setScrollInfo] = useStateW({ left: 0, scrollWidth: 1, clientWidth: 1 });

  // data flow connections
  const gridRef    = useRefW(null);
  const [showFlows, setShowFlows] = useStateW(false);
  const [flowPos,   setFlowPos]   = useStateW({});
  const [flowSize,  setFlowSize]  = useStateW({ w: 0, h: 0 });
  const [hovNode,   setHovNode]   = useStateW(null);

  useEffectW(() => {
    const el = scrollRef.current;
    if (!el) return;
    const update = () => setScrollInfo({ left: el.scrollLeft, scrollWidth: el.scrollWidth, clientWidth: el.clientWidth });
    update();
    el.addEventListener('scroll', update, { passive: true });
    const ro = new ResizeObserver(update);
    ro.observe(el);
    return () => { el.removeEventListener('scroll', update); ro.disconnect(); };
  }, []);

  // Measure card positions when showFlows turns on
  useEffectW(() => {
    if (!showFlows || !gridRef.current) return;
    const grid = gridRef.current;
    const t = setTimeout(() => {
      const base = grid.getBoundingClientRect();
      const pos = {};
      grid.querySelectorAll('[data-wfid]').forEach(el => {
        const r = el.getBoundingClientRect();
        pos[el.getAttribute('data-wfid')] = {
          cx: r.left - base.left + r.width / 2,
          cy: r.top - base.top + r.height / 2,
        };
      });
      setFlowPos(pos);
      setFlowSize({ w: grid.scrollWidth, h: grid.scrollHeight });
    }, 60);
    return () => clearTimeout(t);
  }, [showFlows, workflows]);

  // Edges: pairs of workflows that share at least one data source
  const flowEdges = useMemoW(() => {
    if (!showFlows || !Object.keys(flowPos).length) return [];
    const bySystem = {};
    workflows.forEach(w => {
      (w.dependsOn || []).forEach(sys => {
        if (!bySystem[sys]) bySystem[sys] = [];
        bySystem[sys].push(w.id);
      });
    });
    const edgeMap = {};
    Object.entries(bySystem).forEach(([sys, wfIds]) => {
      for (let i = 0; i < wfIds.length; i++) {
        for (let j = i + 1; j < wfIds.length; j++) {
          if (!flowPos[wfIds[i]] || !flowPos[wfIds[j]]) continue;
          const key = [wfIds[i], wfIds[j]].sort().join('|||');
          if (!edgeMap[key]) edgeMap[key] = { a: wfIds[i], b: wfIds[j], systems: [] };
          if (!edgeMap[key].systems.includes(sys)) edgeMap[key].systems.push(sys);
        }
      }
    });
    return Object.values(edgeMap);
  }, [showFlows, flowPos, workflows]);

  const flowPath = (a, b) => {
    const pa = flowPos[a], pb = flowPos[b];
    if (!pa || !pb) return null;
    const mx = (pa.cx + pb.cx) / 2;
    return `M${pa.cx},${pa.cy} C${mx},${pa.cy} ${mx},${pb.cy} ${pb.cx},${pb.cy}`;
  };

  const maxScroll = Math.max(0, scrollInfo.scrollWidth - scrollInfo.clientWidth);
  const canLeft = scrollInfo.left > 2;
  const canRight = scrollInfo.left < maxScroll - 2;
  const thumbWPct = scrollInfo.scrollWidth > 0 ? Math.max(10, (scrollInfo.clientWidth / scrollInfo.scrollWidth) * 100) : 100;
  const thumbLeftPct = maxScroll > 0 ? (scrollInfo.left / maxScroll) * (100 - thumbWPct) : 0;
  const scrollBy = (dir) => { if (scrollRef.current) scrollRef.current.scrollBy({ left: dir * 250, behavior: 'smooth' }); };

  return (
    <div className="inv-board">
      <div className="inv-objective">
        <div className="inv-objective-left">
          <div className="kicker">The objective</div>
          <h3 className="inv-objective-h">Turn every column <em>green</em>.</h3>
          <p className="inv-objective-p">This is the inventory of every workflow we mapped, organized by department. The job of the engagement is to take each card from <span className="inv-band-inline inv-band-inline--disc">discovery</span> through <span className="inv-band-inline inv-band-inline--near">near-ready</span> to <span className="inv-band-inline inv-band-inline--ready">agent-ready</span> — process defined, data systems prepared, ready to build.</p>
          <button className={'ds-flow-btn' + (showFlows ? ' is-active' : '')}
            onClick={() => { setShowFlows(f => !f); if (showFlows) setHovNode(null); }}>
            <span className="ds-flow-btn-dot"></span>
            {showFlows ? 'Hide data flows' : 'Show data flows'}
          </button>
        </div>
        <div className="inv-objective-right">
          <div className="inv-prog">
            <div className="inv-prog-track">
              <div className="inv-prog-fill" style={{width: overallPct + '%'}}></div>
            </div>
            <div className="inv-prog-meta">
              <span className="serif-num" style={{fontSize:32, color:'var(--ink-0)', lineHeight:1}}>{ready}<span style={{color:'var(--ink-3)', fontSize:18}}>/{total}</span></span>
              <span className="inv-prog-l">workflows agent-ready</span>
            </div>
          </div>
          <div className="inv-tally">
            <span><span className="legend-dot" style={{background:'#1a8f59'}}></span>{ready} ready</span>
            <span><span className="legend-dot" style={{background:'#b07a18'}}></span>{near} near</span>
            <span><span className="legend-dot" style={{background:'#a73a3a'}}></span>{disc} discovery</span>
          </div>
        </div>
      </div>

      <div className="inv-grid-wrap">
        <div className="inv-grid-scroll" ref={scrollRef}>
          <div className="inv-grid" ref={gridRef} style={{position: 'relative'}}
            onMouseOver={showFlows ? (e => { const c = e.target.closest('[data-wfid]'); setHovNode(c ? c.getAttribute('data-wfid') : null); }) : undefined}
            onMouseLeave={showFlows ? (() => setHovNode(null)) : undefined}
          >
            {deptOrder.map(deptName => (
              <InventoryColumn key={deptName} dept={deptName} items={byDept[deptName]} onOpen={onOpen}/>
            ))}

            {showFlows && flowSize.w > 0 && (
              <svg style={{position:'absolute',top:0,left:0,pointerEvents:'none',width:flowSize.w,height:flowSize.h,overflow:'visible'}}>
                {flowEdges.map(e => {
                  const key = [e.a, e.b].sort().join('|||');
                  const d = flowPath(e.a, e.b);
                  if (!d) return null;
                  const isConn = hovNode && (e.a === hovNode || e.b === hovNode);
                  const dim    = hovNode && !isConn;
                  return (
                    <path key={key} d={d} fill="none"
                      stroke={isConn ? '#2e5dff' : 'rgba(10,10,10,0.22)'}
                      strokeWidth={isConn ? 2 : 1.5}
                      strokeDasharray={isConn ? 'none' : '5 4'}
                      opacity={dim ? 0.06 : isConn ? 1 : 0.45}
                      style={{transition:'opacity 120ms,stroke 120ms'}}
                    />
                  );
                })}
              </svg>
            )}
          </div>
        </div>

        {maxScroll > 4 && (
          <div className="inv-scroll-nav">
            <button className="inv-scroll-btn" onClick={() => scrollBy(-1)} disabled={!canLeft} aria-label="Scroll left">&#8249;</button>
            <div className="inv-scroll-track">
              <div className="inv-scroll-thumb" style={{left: thumbLeftPct + '%', width: thumbWPct + '%'}}></div>
            </div>
            <button className="inv-scroll-btn" onClick={() => scrollBy(1)} disabled={!canRight} aria-label="Scroll right">&#8250;</button>
          </div>
        )}
      </div>
    </div>
  );
}

function InventoryColumn({ dept, items, onOpen }) {
  const ready = items.filter(w => w.readiness.band === 'Ready to build').length;
  const pct = items.length ? Math.round((ready / items.length) * 100) : 0;
  const totalHours = items.reduce((s, w) => s + w.hours, 0);

  return (
    <div className="inv-col">
      <div className="inv-col-head">
        <div className="inv-col-title">{dept}</div>
        <div className="inv-col-meta">
          <span>{items.length} {items.length === 1 ? 'workflow' : 'workflows'}</span>
          <span className="dot-sep">·</span>
          <span>{totalHours.toLocaleString()} hrs/yr</span>
        </div>
        <div className="inv-col-bar">
          <div className="inv-col-bar-fill" style={{width: pct + '%'}}></div>
        </div>
        <div className="inv-col-pct">{ready} of {items.length} agent-ready</div>
      </div>
      <div className="inv-col-body">
        {items.map((w, i) => (
          <InventoryCard key={w.id} w={w} onOpen={onOpen} delay={i * 40}/>
        ))}
      </div>
    </div>
  );
}

function InventoryCard({ w, onOpen, delay }) {
  const band = w.readiness.band;
  const bandKey = band === 'Ready to build' ? 'ready' : band === 'Near-ready' ? 'near' : 'disc';
  return (
    <button
      className={"inv-card inv-card--" + bandKey}
      data-wfid={w.id}
      style={{animationDelay: delay + 'ms'}}
      onClick={() => onOpen(w)}
    >
      <div className="inv-card-top">
        <div className="inv-card-name">{w.name}</div>
        <span className="inv-card-score serif-num">{w.readiness.composite}</span>
      </div>
      <div className="inv-card-meta">
        <span className="inv-card-hrs">{w.hours.toLocaleString()} hrs/yr</span>
        <span className="dot-sep">·</span>
        <span className="inv-card-status">{w.status}</span>
      </div>
      <div className="inv-card-bars">
        <div className={"inv-card-bar" + (w.readiness.rubric ? ' inv-card-bar--scored' : '')}>
          <span className="inv-card-bar-l">Process</span>
          <div className="inv-card-bar-t"><div className="inv-card-bar-f" style={{width: w.readiness.processDoc + '%'}}></div></div>
          {w.readiness.rubric && (
            <div className="inv-card-rubric-tip">
              <div className="inv-card-rubric-tip-head">Process scoring</div>
              <RubricBreakdown rubric={w.readiness.rubric} compact/>
            </div>
          )}
        </div>
        <div className="inv-card-bar">
          <span className="inv-card-bar-l">Data</span>
          <div className="inv-card-bar-t"><div className="inv-card-bar-f" style={{width: w.readiness.dataScore + '%'}}></div></div>
        </div>
        <div className="inv-card-bar">
          <span className="inv-card-bar-l">Output</span>
          <div className="inv-card-bar-t"><div className="inv-card-bar-f" style={{width: w.readiness.outputAmbiguity + '%'}}></div></div>
        </div>
      </div>
    </button>
  );
}

window.WorkflowsView = WorkflowsView;

// --- SOP reader -------------------------------------------------------------

const SoftwareLogo = window.SoftwareLogo || (() => null);

const SOP_STATUS = {
  'Current':        { c: '#1a8f59', bg: 'rgba(26,143,89,0.10)' },
  'Draft':          { c: '#a06d10', bg: 'rgba(160,109,16,0.10)' },
  'In review':      { c: '#2e5dff', bg: 'rgba(46,93,255,0.10)' },
  'Not documented': { c: '#a73a3a', bg: 'rgba(167,58,58,0.10)' },
};

const RACI_COLOR = {
  'Accountable': '#2e5dff',
  'Responsible': '#1a8f59',
  'Consulted':   '#a06d10',
  'Informed':    '#6b6e76',
};

function SopStatusPill({ status }) {
  const s = SOP_STATUS[status] || SOP_STATUS['Current'];
  return <span className="sop-status" style={{ color: s.c, background: s.bg }}><span className="sop-status-dot" style={{ background: s.c }}></span>{status}</span>;
}

function SopReader({ w, onClose }) {
  const sop = window.SOPS ? window.SOPS[w.id] : null;
  const scrollRef = useRefW(null);
  const [activeSec, setActiveSec] = useStateW('overview');

  useEffectW(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  const sections = sop
    ? [['overview', 'Document control'], ['purpose', 'A · Purpose'], ['scope', 'B · Scope'], ['trigger', 'C · Trigger'], ['roles', 'D · Roles'], ['io', 'E · Inputs & outputs'], ['systems', 'F · Systems used'], ['procedure', 'G · Procedure'], ['exceptions', 'H · Exceptions'], ['quality', 'I · Quality checks'], ['revisions', 'Revision history']]
    : [['overview', 'Overview'], ['current', 'Current process'], ['gaps', 'Documentation gaps'], ['next', 'What it needs']];

  const onScroll = () => {
    const cont = scrollRef.current;
    if (!cont) return;
    const cRect = cont.getBoundingClientRect();
    const secs = cont.querySelectorAll('[data-sop-sec]');
    let cur = sections[0][0];
    secs.forEach(s => { if (s.getBoundingClientRect().top - cRect.top <= 130) cur = s.getAttribute('data-sop-sec'); });
    setActiveSec(cur);
  };

  const jump = (id) => {
    const cont = scrollRef.current;
    const el = cont && cont.querySelector('[data-sop-sec="' + id + '"]');
    if (!cont || !el) return;
    cont.scrollTop = cont.scrollTop + (el.getBoundingClientRect().top - cont.getBoundingClientRect().top) - 16;
    setActiveSec(id);
  };

  const r = w.readiness;
  const procColor = r.processDoc >= 70 ? '#1a8f59' : r.processDoc >= 50 ? '#b07a18' : '#a73a3a';

  return ReactDOM.createPortal((
    <div className="sop-overlay-root">
      <div className="sop-backdrop" onClick={onClose}></div>
      <div className="sop-overlay" role="dialog" aria-label={w.name + ' SOP'}>
        <div className="sop-bar">
          <button className="cat-back" onClick={onClose}><IconChevronLeft size={15}/>Back to inventory</button>
          <div className="sop-bar-mid">
            {sop && <span className="sop-code">{sop.code}</span>}
            <span className="sop-bar-title">{w.name}</span>
          </div>
          <div className="sop-bar-right">
            <button className="ghost-btn" onClick={() => window.print()}><IconDownload size={13}/>Print</button>
            <button className="icon-btn" onClick={onClose}><IconX size={18}/></button>
          </div>
        </div>

        <div className="sop-scroll" ref={scrollRef} onScroll={onScroll}>
          <div className="sop-layout">
            <aside className="sop-toc">
              <div className="sop-toc-label">On this page</div>
              {sections.map(([id, label]) => (
                <button key={id} className={'sop-toc-link' + (activeSec === id ? ' is-active' : '')} onClick={() => jump(id)}>{label}</button>
              ))}
              <div className="sop-toc-foot">
                <div className="sop-toc-foot-l">Process documentation</div>
                <div className="sop-toc-score" style={{ color: procColor }}>{r.processDoc}<span>/100</span></div>
                <div className="sop-toc-track"><div className="sop-toc-fill" style={{ width: r.processDoc + '%', background: procColor }}></div></div>
                {r.rubric && <RubricBreakdown rubric={r.rubric} compact/>}
              </div>
            </aside>

            <article className="sop-doc">
              {sop ? <SopFull w={w} sop={sop}/> : <SopGap w={w}/>}
            </article>
          </div>
        </div>
      </div>
    </div>
  ), document.body);
}

function SopFull({ w, sop }) {
  const s = SOP_STATUS[sop.status] || SOP_STATUS['Current'];
  const revisions = sop.revisions || [[sop.version, sop.lastReviewed, sop.owner.split('·')[0].trim(), 'Current controlled version']];
  let letter = 0;
  const L = () => String.fromCharCode(65 + (letter++));
  return (
    <>
      <header className="sopc-control" data-sop-sec="overview">
        <div className="sopc-control-bar">
          <div className="sopc-control-title">{sop.title}</div>
          <div className="sopc-control-tags">
            <span className="sop-code sop-code--lg">{sop.code}</span>
            <span className="sopc-control-status" style={{ color: s.c }}><span className="sop-status-dot" style={{ background: s.c }}></span>{sop.status}</span>
          </div>
        </div>
        <div className="sopc-control-grid">
          <div className="sopc-cc"><span>Process owner</span><b>{sop.owner}</b></div>
          <div className="sopc-cc"><span>Approver</span><b>{sop.approver}</b></div>
          <div className="sopc-cc"><span>Version</span><b>{sop.version}</b></div>
          <div className="sopc-cc"><span>Effective</span><b>{sop.lastReviewed}</b></div>
          <div className="sopc-cc"><span>Frequency</span><b>{sop.frequency}</b></div>
          <div className="sopc-cc"><span>Department</span><b>{w.dept}</b></div>
        </div>
      </header>

      <section className="sopc-sec" data-sop-sec="purpose">
        <h2 className="sopc-h"><em>{L()}</em>Purpose</h2>
        <p className="sopc-p">{sop.purpose}</p>
      </section>

      <section className="sopc-sec" data-sop-sec="scope">
        <h2 className="sopc-h"><em>{L()}</em>Scope</h2>
        <p className="sopc-p">{sop.scope}</p>
      </section>

      <section className="sopc-sec" data-sop-sec="trigger">
        <h2 className="sopc-h"><em>{L()}</em>Trigger</h2>
        <p className="sopc-p">{sop.trigger}</p>
      </section>

      <section className="sopc-sec" data-sop-sec="roles">
        <h2 className="sopc-h"><em>{L()}</em>Roles &amp; responsibilities</h2>
        <div className="sop-roles">
          {sop.roles.map(role => (
            <div key={role.role} className="sop-role">
              <div className="sop-role-l">
                <div className="sop-role-name">{role.role}</div>
                <div className="sop-role-who">{role.who}</div>
              </div>
              <div className="sop-role-resp">{role.responsibility}</div>
              <span className="sop-raci" style={{ color: RACI_COLOR[role.tag] || '#6b6e76', borderColor: (RACI_COLOR[role.tag] || '#6b6e76') + '40' }}>{role.tag}</span>
            </div>
          ))}
        </div>
      </section>

      <section className="sopc-sec" data-sop-sec="io">
        <h2 className="sopc-h"><em>{L()}</em>Inputs &amp; outputs</h2>
        <div className="sop-io">
          <div className="sop-io-col">
            <div className="sop-io-label sop-io-label--in">Inputs</div>
            <ul className="sop-io-list">{sop.inputs.map(x => <li key={x}>{x}</li>)}</ul>
          </div>
          <div className="sop-io-arrow"><IconArrowRight size={18}/></div>
          <div className="sop-io-col">
            <div className="sop-io-label sop-io-label--out">Outputs</div>
            <ul className="sop-io-list">{sop.outputs.map(x => <li key={x}>{x}</li>)}</ul>
          </div>
        </div>
      </section>

      <section className="sopc-sec" data-sop-sec="systems">
        <h2 className="sopc-h"><em>{L()}</em>Systems used</h2>
        <div className="sop-systems">
          {sop.systems.map(name => {
            const d = (window.DATA_SOURCES || []).find(x => x.name === name);
            return (
              <div key={name} className="sop-sys">
                <SoftwareLogo name={name} size={18}/>
                <span className="sop-sys-name">{name}</span>
                {d && <TierMini tier={d.tier}/>}
              </div>
            );
          })}
        </div>
      </section>

      <section className="sopc-sec" data-sop-sec="procedure">
        <h2 className="sopc-h"><em>{L()}</em>Procedure</h2>
        <div className="sopc-steps">
          {sop.steps.map((st, i) => (
            <div key={i} className="sopc-step">
              <div className="sopc-step-n">{i + 1}</div>
              <div className="sopc-step-body">
                <div className="sopc-step-title">{st.title}</div>
                <p className="sopc-step-detail">{st.detail}</p>
                <div className="sopc-step-meta">
                  <span><span className="sopc-step-meta-l">Who</span>{st.role}</span>
                  {st.system && st.system !== '—' && <span><span className="sopc-step-meta-l">System</span>{st.system}</span>}
                </div>
              </div>
            </div>
          ))}
        </div>
      </section>

      <section className="sopc-sec" data-sop-sec="exceptions">
        <h2 className="sopc-h"><em>{L()}</em>Exceptions &amp; edge cases</h2>
        <div className="sop-exceptions">
          {sop.exceptions.map((e, i) => (
            <div key={i} className="sop-exc">
              <div className="sop-exc-when"><span>If</span>{e.when}</div>
              <div className="sop-exc-then"><span>Then</span>{e.then}</div>
            </div>
          ))}
        </div>
      </section>

      <section className="sopc-sec" data-sop-sec="quality">
        <h2 className="sopc-h"><em>{L()}</em>Quality checks</h2>
        <ul className="sop-quality">
          {sop.quality.map(q => (
            <li key={q}><span className="sop-check"><IconCheck size={12}/></span>{q}</li>
          ))}
        </ul>
      </section>

      <section className="sopc-sec" data-sop-sec="revisions">
        <h2 className="sopc-h sopc-h--minor">Revision history</h2>
        <table className="sopc-revtable">
          <thead><tr><th>Version</th><th>Date</th><th>By</th><th>Change</th></tr></thead>
          <tbody>{revisions.map((rv, i) => <tr key={i}><td>{rv[0]}</td><td>{rv[1]}</td><td>{rv[2]}</td><td>{rv[3]}</td></tr>)}</tbody>
        </table>
      </section>
    </>
  );
}

function SopGap({ w }) {
  const r = w.readiness;
  return (
    <>
      <header className="sop-title-block" data-sop-sec="overview">
        <div className="sop-eyebrow">
          <span className="kicker">Standard Operating Procedure</span>
          <SopStatusPill status="Not documented"/>
        </div>
        <h1 className="sop-h1">{w.name}</h1>
        <div className="sop-id-row">
          <span className="sop-dept">{w.dept}</span>
          <span className="dot-sep">·</span>
          <span className="sop-ver">{w.frequency}</span>
        </div>
        <div className="sop-gap-callout">
          <div className="sop-gap-callout-h">No published SOP yet</div>
          <p>This workflow runs largely on tribal knowledge — it hasn't been written up as a repeatable procedure. That gap is the main reason its process-documentation score sits at <b>{r.processDoc}/100</b>, and it's the first thing to close before the workflow can be automated reliably.</p>
        </div>
      </header>

      <section className="sop-section" data-sop-sec="current">
        <h2 className="sop-h2">Current process</h2>
        <p className="sop-p">{w.current}</p>
        {w.trigger && <div className="sop-trigger"><span className="sop-trigger-l">Triggered when</span>{w.trigger}</div>}
        <div className="sop-systems" style={{ marginTop: 16 }}>
          {(w.dependsOn || []).map(name => {
            const d = (window.DATA_SOURCES || []).find(x => x.name === name);
            return (
              <div key={name} className="sop-sys">
                <SoftwareLogo name={name} size={18}/>
                <span className="sop-sys-name">{name}</span>
                {d && <TierMini tier={d.tier}/>}
              </div>
            );
          })}
        </div>
      </section>

      <section className="sop-section" data-sop-sec="gaps">
        <h2 className="sop-h2">Documentation gaps</h2>
        <div className="sop-gap-list">
          <div className="sop-gap-row">
            <div className="sop-gap-row-h"><span className="sop-gap-score" style={{ color: r.processDoc >= 60 ? '#b07a18' : '#a73a3a' }}>{r.processDoc}</span>Process documentation</div>
            <p>{w.processNote}</p>
          </div>
          <div className="sop-gap-row">
            <div className="sop-gap-row-h"><span className="sop-gap-score" style={{ color: r.outputAmbiguity >= 60 ? '#b07a18' : '#a73a3a' }}>{r.outputAmbiguity}</span>Output definition</div>
            <p>{w.outputAmbiguityNote}</p>
          </div>
        </div>
      </section>

      <section className="sop-section" data-sop-sec="next">
        <h2 className="sop-h2">What it needs</h2>
        <p className="sop-p"><b className="sop-lead">Proposed approach.</b> {w.proposed}</p>
        <p className="sop-p"><b className="sop-lead">Expected impact.</b> {w.impact}</p>
        <div className="sop-foot-note">
          Documenting this process — mapping the steps, the people, and the systems involved — is the concrete first deliverable that moves {w.name} from discovery toward agent-ready.
        </div>
      </section>
    </>
  );
}

Object.assign(window, { SopReader });
