=== GREP selectStage / guards / bridge ===
11:    selectedStageName: document.getElementById("selected-stage-name"),
12:    selectedStageDesc: document.getElementById("selected-stage-desc"),
13:    selectedStageTotal: document.getElementById("selected-stage-total"),
14:    selectedStageDonut: document.getElementById("selected-stage-donut"),
16:    selectedPipelineSteps: document.getElementById("selected-pipeline-steps"),
43:    selectedStage: null
144:          '<button type="button" class="tree-phase-row ' + (state.selectedStage === phaseId ? 'active' : '') + '" data-phase-id="' + phaseId + '">',
207:        state.selectedStage = phaseId;
209:        selectStage(phaseId);
222:        state.selectedStage = phaseId;
227:        selectStage(phaseId);
240:        state.selectedStage = phaseId;
245:        selectStage(phaseId);
473:    if (!els.selectedPipelineSteps) return;
480:      els.selectedPipelineSteps.innerHTML = '<li><span>No pipeline contract found</span><span class="step-state">missing</span></li>';
484:    els.selectedPipelineSteps.innerHTML = seq.map(function (step) {
500:  function hasRuntimeStageKey(stageKey) {
509:  function hasPipelineStageKey(stageKey) {
520:      return normStageKey(p.id || p.stage_key || "") === normStageKey(state.selectedStage);
533:    if (!els.selectedStageName) return;
534:    if (els.selectedStageName) els.selectedStageName.textContent = cat.title || ph.name || "Category";
535:    if (els.selectedStageDesc) els.selectedStageDesc.textContent = cat.sub || "Category view from canonical hub index.";
536:    if (els.selectedStageTotal) els.selectedStageTotal.innerHTML = ((cat.docs || []).length) + ' docs<br>in category';
537:    if (els.selectedStageDonut) els.selectedStageDonut.innerHTML = donutMarkup(0, "category");
538:    if (els.selectedPipelineSteps) {
540:      els.selectedPipelineSteps.innerHTML = docs.length ? docs.map(function (doc) {
547:    if (els.selectedStageName) els.selectedStageName.textContent = (cat.title || ph.name || "Category") + " / " + titleize(bucket);
548:    if (els.selectedStageDesc) els.selectedStageDesc.textContent = "Bucket detail from canonical category documents.";
553:    if (els.selectedStageTotal) els.selectedStageTotal.innerHTML = bucketDocs.length + ' docs<br>in bucket view';
554:    if (els.selectedStageDonut) els.selectedStageDonut.innerHTML = donutMarkup(0, titleize(bucket));
556:    if (els.selectedPipelineSteps) {
557:      els.selectedPipelineSteps.innerHTML = bucketDocs.length ? bucketDocs.map(function (doc) {
586:  function selectStage(stageKey) {
587:      state.selectedStage = normStageKey(stageKey);
590:        return normStageKey(item.stage_key) === state.selectedStage;
593:      const runtimeEligible = hasRuntimeStageKey(state.selectedStage);
594:      const pipelineEligible = hasPipelineStageKey(state.selectedStage);
595:      const rollup = runtimeEligible ? stageRollup(state.selectedStage) : null;
599:      if (els.heroTitle) els.heroTitle.textContent = navItem ? navItem.label : titleize(state.selectedStage);
606:      if (els.selectedStageName) {
607:        els.selectedStageName.textContent = navItem ? navItem.label : titleize(state.selectedStage);
609:      if (els.selectedStageDesc) {
610:        els.selectedStageDesc.textContent = runtimeEligible
612:          : "Canonical selection view. No sovereign runtime stage binding exists for this phase key.";
614:      if (els.selectedStageTotal) {
615:        els.selectedStageTotal.innerHTML = runtimeEligible && totalSteps
617:          : 'Canonical selection<br>without runtime bridge';
619:      if (els.selectedStageDonut) {
620:        els.selectedStageDonut.innerHTML = runtimeEligible
633:        renderSelectedPipeline(state.selectedStage, rollup);
634:      } else if (els.selectedPipelineSteps) {
635:        els.selectedPipelineSteps.innerHTML = '<li><span>Canonical selection has no runtime pipeline binding</span><span class="step-state">n/a</span></li>';
641:        btn.classList.toggle("active", btn.dataset.stageKey === state.selectedStage);

=== CONTEXTO 450..700 ===
   450	      els.pipelineRuntimeCount.textContent = items.length + " runtime rows";
   451	    }
   452	    if (!els.pipelineRuntimeBoard) return;
   453	    if (!items.length) {
   454	      els.pipelineRuntimeBoard.innerHTML = '<div class="pipeline-item"><h4>No runtime rows</h4><p>Status is MISSING.</p></div>';
   455	      return;
   456	    }
   457	    els.pipelineRuntimeBoard.innerHTML = items.slice(0, 24).map(function (item) {
   458	      const status = runtimeStatusOf(item);
   459	      return [
   460	        '<div class="pipeline-item">',
   461	        '<h4>' + titleize(item.deployment_stage || "runtime") + ' / ' + titleize(item.technology || item.subcategory || "item") + '</h4>',
   462	        '<p>Kind: ' + titleize(item.row_kind || "runtime_row") + '</p>',
   463	        '<div class="pipeline-kv">',
   464	        '<span class="pill ' + getBadgeClass(status) + '">' + status + '</span>',
   465	        '<span class="pill">' + valueOrDash(item.progress_pct, "%") + '</span>',
   466	        '</div>',
   467	        '</div>'
   468	      ].join("");
   469	    }).join("");
   470	  }
   471	
   472	  function renderSelectedPipeline(stageKey, rollup) {
   473	    if (!els.selectedPipelineSteps) return;
   474	    const pipelines = (state.pipelines && state.pipelines.pipelines) || {};
   475	    const contract = pipelines[stageKey] || {};
   476	    const seq = Array.isArray(contract.sequence) ? contract.sequence : [];
   477	    const stepStatuses = rollup && Array.isArray(rollup.step_statuses) ? rollup.step_statuses : [];
   478	
   479	    if (!seq.length) {
   480	      els.selectedPipelineSteps.innerHTML = '<li><span>No pipeline contract found</span><span class="step-state">missing</span></li>';
   481	      return;
   482	    }
   483	
   484	    els.selectedPipelineSteps.innerHTML = seq.map(function (step) {
   485	      const observed = stepStatuses.find(function (x) {
   486	        return normStageKey(x.step || x.name) === normStageKey(step);
   487	      });
   488	      const status = observed ? safeUpper(observed.status) : "MISSING";
   489	      return [
   490	        '<li>',
   491	        '<span>' + titleize(step) + '</span>',
   492	        '<span class="pill ' + getBadgeClass(status) + '">' + status + '</span>',
   493	        '</li>'
   494	      ].join("");
   495	    }).join("");
   496	  }
   497	
   498	
   499	  
   500	  function hasRuntimeStageKey(stageKey) {
   501	    const key = normStageKey(stageKey);
   502	    const items = ((state.runtimeStatus && state.runtimeStatus.runtime_snapshot) || []);
   503	    return items.some(function (row) {
   504	      return String(row && row.row_kind || "") === "stage_rollup"
   505	        && normStageKey(row && row.deployment_stage) === key;
   506	    });
   507	  }
   508	
   509	  function hasPipelineStageKey(stageKey) {
   510	    const key = normStageKey(stageKey);
   511	    const pipelines = (state.subcategoryPipelines && state.subcategoryPipelines.pipelines) || {};
   512	    return Object.keys(pipelines).some(function (k) {
   513	      return normStageKey(k) === key;
   514	    });
   515	  }
   516	
   517	function selectedPhaseObject() {
   518	    const phases = (state.hubIndex && Array.isArray(state.hubIndex.phases)) ? state.hubIndex.phases : [];
   519	    return phases.find(function (p) {
   520	      return normStageKey(p.id || p.stage_key || "") === normStageKey(state.selectedStage);
   521	    }) || null;
   522	  }
   523	
   524	  function selectedCategoryObject() {
   525	    if (!state.selectedCategory) return null;
   526	    const cats = (state.hubIndex && Array.isArray(state.hubIndex.categories)) ? state.hubIndex.categories : [];
   527	    return cats.find(function (c) {
   528	      return String(c.id || "") === String(state.selectedCategory);
   529	    }) || null;
   530	  }
   531	
   532	  function renderCenterCategory(ph, cat) {
   533	    if (!els.selectedStageName) return;
   534	    if (els.selectedStageName) els.selectedStageName.textContent = cat.title || ph.name || "Category";
   535	    if (els.selectedStageDesc) els.selectedStageDesc.textContent = cat.sub || "Category view from canonical hub index.";
   536	    if (els.selectedStageTotal) els.selectedStageTotal.innerHTML = ((cat.docs || []).length) + ' docs<br>in category';
   537	    if (els.selectedStageDonut) els.selectedStageDonut.innerHTML = donutMarkup(0, "category");
   538	    if (els.selectedPipelineSteps) {
   539	      const docs = Array.isArray(cat.docs) ? cat.docs : [];
   540	      els.selectedPipelineSteps.innerHTML = docs.length ? docs.map(function (doc) {
   541	        return '<li><span>' + (doc.title || doc.label || doc.id || "item") + '</span><span class="pill">' + (doc.type || "doc") + '</span></li>';
   542	      }).join("") : '<li><span>No documents registered</span><span class="pill missing">MISSING</span></li>';
   543	    }
   544	  }
   545	
   546	  function renderCenterBucket(ph, cat, bucket) {
   547	    if (els.selectedStageName) els.selectedStageName.textContent = (cat.title || ph.name || "Category") + " / " + titleize(bucket);
   548	    if (els.selectedStageDesc) els.selectedStageDesc.textContent = "Bucket detail from canonical category documents.";
   549	
   550	    const docs = Array.isArray(cat.docs) ? cat.docs : [];
   551	    const bucketDocs = bucket === "authority_docs" ? docs : [];
   552	
   553	    if (els.selectedStageTotal) els.selectedStageTotal.innerHTML = bucketDocs.length + ' docs<br>in bucket view';
   554	    if (els.selectedStageDonut) els.selectedStageDonut.innerHTML = donutMarkup(0, titleize(bucket));
   555	
   556	    if (els.selectedPipelineSteps) {
   557	      els.selectedPipelineSteps.innerHTML = bucketDocs.length ? bucketDocs.map(function (doc) {
   558	        return [
   559	          '<li>',
   560	            '<span>' + (doc.title || doc.label || doc.id || "item") + '</span>',
   561	            '<span class="pill">' + (doc.type || "doc") + '</span>',
   562	          '</li>'
   563	        ].join("");
   564	      }).join("") : '<li><span>No documents registered in this bucket.</span><span class="pill">MISSING</span></li>';
   565	    }
   566	  }
   567	
   568	  function renderCanonicalSelection() {
   569	    const ph = selectedPhaseObject();
   570	    const cat = selectedCategoryObject();
   571	
   572	    if (!ph) return;
   573	
   574	    if (cat && state.selectedBucket) {
   575	      renderCenterBucket(ph, cat, state.selectedBucket);
   576	      return;
   577	    }
   578	
   579	    if (cat) {
   580	      renderCenterCategory(ph, cat);
   581	      return;
   582	    }
   583	  }
   584	
   585	
   586	  function selectStage(stageKey) {
   587	      state.selectedStage = normStageKey(stageKey);
   588	      const items = ((state.contentIndex && state.contentIndex.content_index) || []);
   589	      const navItem = items.find(function (item) {
   590	        return normStageKey(item.stage_key) === state.selectedStage;
   591	      }) || null;
   592	
   593	      const runtimeEligible = hasRuntimeStageKey(state.selectedStage);
   594	      const pipelineEligible = hasPipelineStageKey(state.selectedStage);
   595	      const rollup = runtimeEligible ? stageRollup(state.selectedStage) : null;
   596	      const pct = rollup && typeof rollup.progress_pct === "number" ? Math.round(rollup.progress_pct) : 0;
   597	      const totalSteps = rollup && Array.isArray(rollup.step_statuses) ? rollup.step_statuses.length : 0;
   598	
   599	      if (els.heroTitle) els.heroTitle.textContent = navItem ? navItem.label : titleize(state.selectedStage);
   600	      if (els.heroSubtitle) {
   601	        els.heroSubtitle.textContent = "Runtime-backed stage view. Contract and runtime data are rendered from panel exports only.";
   602	      }
   603	      if (els.stageOrderBadge) {
   604	        els.stageOrderBadge.textContent = navItem ? ("ORDER " + navItem.deployment_order) : "—";
   605	      }
   606	      if (els.selectedStageName) {
   607	        els.selectedStageName.textContent = navItem ? navItem.label : titleize(state.selectedStage);
   608	      }
   609	      if (els.selectedStageDesc) {
   610	        els.selectedStageDesc.textContent = runtimeEligible
   611	          ? "Stage completion is read from runtime_status stage_rollup.progress_pct."
   612	          : "Canonical selection view. No sovereign runtime stage binding exists for this phase key.";
   613	      }
   614	      if (els.selectedStageTotal) {
   615	        els.selectedStageTotal.innerHTML = runtimeEligible && totalSteps
   616	          ? (totalSteps + ' required steps<br>in contract')
   617	          : 'Canonical selection<br>without runtime bridge';
   618	      }
   619	      if (els.selectedStageDonut) {
   620	        els.selectedStageDonut.innerHTML = runtimeEligible
   621	          ? donutMarkup(pct, "stage completion")
   622	          : donutMarkup(0, "canonical");
   623	      }
   624	      if (els.selectedRuntimeBadge) {
   625	        if (runtimeEligible && rollup) {
   626	          setBadge(els.selectedRuntimeBadge, runtimeStatusOf(rollup), runtimeStatusOf(rollup));
   627	        } else {
   628	          setBadge(els.selectedRuntimeBadge, "MISSING", "N/A");
   629	        }
   630	      }
   631	
   632	      if (runtimeEligible || pipelineEligible) {
   633	        renderSelectedPipeline(state.selectedStage, rollup);
   634	      } else if (els.selectedPipelineSteps) {
   635	        els.selectedPipelineSteps.innerHTML = '<li><span>Canonical selection has no runtime pipeline binding</span><span class="step-state">n/a</span></li>';
   636	      }
   637	
   638	      renderCanonicalSelection();
   639	
   640	      document.querySelectorAll(".stage-btn").forEach(function (btn) {
   641	        btn.classList.toggle("active", btn.dataset.stageKey === state.selectedStage);
   642	      });
   643	    }
   644	  }
   645	
   646	  boot();
   647	})();
   648	
   649	
   650	document.getElementById('btn-monitor')?.addEventListener('click', () => {
   651	  window.open('../monitor/', '_blank');
   652	});
