house-lights 1.9.0 → 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,6 +47,7 @@ body { margin: 0; }
47
47
  .pb-node.manager { background: var(--active); color: var(--on-active); border-color: var(--active); }
48
48
  .pb-node.ghost { border-style: dashed; color: var(--muted); cursor: default; }
49
49
  .pb-node[aria-pressed="true"] { border-color: var(--focus); box-shadow: 0 0 0 1px var(--focus); }
50
+ .pb-also { color: var(--type); font-size: 11px; white-space: nowrap; }
50
51
  .pb-type { margin: 8px 0 2px; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--type); }
51
52
  .pb-tag { font-size: 11px; padding: 1px 8px; border-radius: 999px; border: 1px solid currentColor; white-space: nowrap; }
52
53
  .pb-tag.ok { color: var(--has); } .pb-tag.pdi, .pb-tag.noOwner { color: var(--off); } .pb-tag.hiring, .pb-tag.neverPublished, .pb-tag.noEval { color: var(--amber); }
@@ -82,29 +83,45 @@ body { margin: 0; }
82
83
  .pb-pdi small { display: block; color: var(--muted); font-size: 12px; }
83
84
  .pb-empty { margin: 0; color: var(--muted); font-size: 13px; }
84
85
  .cl-foot { margin: 8px 0 0; font-size: 12px; color: var(--muted); text-align: center; }
86
+ /* the two views of a résumé: as a résumé (the paper one) and as a sheet */
87
+ .pb-views { display: flex; gap: 6px; justify-content: flex-end; }
88
+ .pb-views button { padding: 3px 10px; border-radius: 999px; border: 1px solid var(--line); background: var(--card); font-size: 12px; }
89
+ .pb-views button[aria-pressed="true"] { background: var(--active); color: var(--on-active); border-color: var(--active); }
90
+ .pb-cv { --paper: #fffdf8; --chip-bg: #f1ece1; background: var(--paper); border-radius: 16px; padding: 22px 22px 18px; box-shadow: 0 1px 0 var(--line); }
91
+ @media (prefers-color-scheme: dark) { .cl:not(.light) .pb-cv { --paper: var(--card); --chip-bg: var(--soft); } }
92
+ .pb-cv .pb-head { align-items: center; gap: 14px; }
93
+ .pb-cv .pb-who { flex: 1; min-width: 0; }
94
+ .pb-av { width: 64px; height: 64px; border-radius: 50%; background: var(--chip-bg); color: var(--ink); display: grid; place-items: center; flex: none; }
95
+ .pb-cv h2, .pb-cv .pb-perf b { font-family: Georgia, "Times New Roman", serif; }
96
+ .pb-cv .pb-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); font-size: 12.5px; }
97
+ .pb-cv .pb-chip { background: var(--chip-bg); border-color: transparent; border-radius: 8px; }
98
+ .pb-cv .pb-perf div { background: var(--chip-bg); }
99
+ .pb-cv .pb-seal { font-family: Georgia, "Times New Roman", serif; transform: rotate(-4deg); }
100
+ @media (max-width: 520px) { .pb-cv .pb-facts { grid-template-columns: 1fr; } .pb-av { width: 48px; height: 48px; } }
85
101
  </style>
86
102
  </head>
87
103
  <body>
88
104
  <div class="cl" id="app"></div>
89
105
  <script type="application/json" id="cast">{{CAST}}</script>
90
- <script>(()=>{var j={en:{title:"The cast\u2019s HR",sub:"The same cast, as people: staff board, org chart, post, r\xE9sum\xE9 and development plan. Everything comes from the files, the telemetry and the team\u2019s spreadsheets.",privacy:"This file holds the client\u2019s data: keep it in the client\u2019s environment.",staff:{cast:"on the staff",hiring:"being hired",noOwner:"with no owner",neverPublished:"never published",noEval:"with no evaluation",pdi:"with a development plan",ok:"in good standing"},tag:{hiring:"being hired",noOwner:"no owner",neverPublished:"never published",noEval:"no evaluation",pdi:"plan",ok:"in good standing"},missing:{inventory:"the admin center\u2019s inventory (owner, environment, published)",team:"the team\u2019s spreadsheet (team, goal)",telemetry:"the export of Application Insights (performance)"},more:"More with",org:"Org chart",client:"Customer",clientSub:"who is served",manager:"manager",ghost:"called, not in the folder",noType:"no type",post:"The post",postNote:"The post is the accepted pattern of the role and type, and the profile\u2019s rules. A newcomer is \xABhired\xBB when they meet it.",proposal:"proposal \u2014 no decision yet",manager_:"Manager",team:"Team",owner:"Owner",created:"Hired",published:"Last published",schema:"Badge",env:"Unit",nobody:"nobody calls it",summary:"Summary",tools:"Tools and access",conduct:"Languages and conduct",goal:"Goal",noGoal:"no goal declared",perf:e=>`Performance \xB7 ${e} days`,starts:"topic starts",errors:"errors logged",notFired:"did not fire",measured:"goal measured",noLine:"no line in the telemetry",noPerf:"The performance comes with the export of Application Insights (--telemetry).",certs:"Certifications",certsNone:"No evaluation in the folder of --evals.",passed:(e,t)=>`${e} of ${t} passed`,access:"Access only it has in its type",pdi:"Development plan",nothing:"Nothing to develop.",sources:"Sources",seal:{ok:"IN GOOD STANDING",pdi:"PLAN"},orchestrator:"Orchestrator",specialist:"Specialist",map:"\u2190 Map",foot:"cast-list \xB7 no model: what is here is what the files and tables say."},pt:{title:"RH do elenco",sub:"O mesmo elenco, visto como pessoas: quadro de pessoal, organograma, vaga, curr\xEDculo e plano de desenvolvimento. Tudo sai dos arquivos, da telemetria e das planilhas do time.",privacy:"Este arquivo tem dados do cliente: deixe-o no ambiente dele.",staff:{cast:"no quadro",hiring:"em admiss\xE3o",noOwner:"sem respons\xE1vel",neverPublished:"nunca publicado",noEval:"sem avalia\xE7\xE3o",pdi:"em PDI",ok:"em dia"},tag:{hiring:"em admiss\xE3o",noOwner:"sem respons\xE1vel",neverPublished:"nunca publicado",noEval:"sem avalia\xE7\xE3o",pdi:"PDI",ok:"em dia"},missing:{inventory:"o invent\xE1rio do admin center (respons\xE1vel, ambiente, publica\xE7\xE3o)",team:"a planilha do time (equipe, meta)",telemetry:"a exporta\xE7\xE3o do Application Insights (desempenho)"},more:"Mais com",org:"Organograma",client:"Cliente",clientSub:"quem \xE9 atendido",manager:"gestor",ghost:"chamado, fora da pasta",noType:"sem tipo",post:"A vaga",postNote:"A vaga \xE9 o padr\xE3o aceito do papel e do tipo, mais as regras do perfil. Quem chega \xE9 \xABcontratado\xBB quando cumpre a vaga.",proposal:"proposta \u2014 sem decis\xE3o ainda",manager_:"Gestor",team:"Equipe",owner:"Respons\xE1vel",created:"Admiss\xE3o",published:"\xDAltima publica\xE7\xE3o",schema:"Matr\xEDcula",env:"Lota\xE7\xE3o",nobody:"ningu\xE9m chama",summary:"Resumo",tools:"Ferramentas e acessos",conduct:"Idiomas e conduta",goal:"Meta",noGoal:"sem meta declarada",perf:e=>`Desempenho \xB7 ${e} dias`,starts:"in\xEDcios de t\xF3pico",errors:"erros registrados",notFired:"n\xE3o disparou",measured:"meta medida",noLine:"nenhuma linha na telemetria",noPerf:"O desempenho aparece com a exporta\xE7\xE3o do Application Insights (--telemetry).",certs:"Certifica\xE7\xF5es",certsNone:"Nenhuma avalia\xE7\xE3o na pasta do --evals.",passed:(e,t)=>`${e} de ${t} aprovados`,access:"Acessos que s\xF3 ele tem no tipo",pdi:"Plano de desenvolvimento",nothing:"Nada a desenvolver.",sources:"Fontes",seal:{ok:"EM DIA",pdi:"PDI"},orchestrator:"Orquestrador",specialist:"Especialista",map:"\u2190 Mapa",foot:"cast-list \xB7 sem modelo: o que est\xE1 aqui \xE9 o que os arquivos e as planilhas dizem."}},u=JSON.parse(document.getElementById("cast").textContent),{playbill:i,lang:c}=u,a=j[c];document.documentElement.lang=c==="pt"?"pt-BR":"en";document.title=`${a.title} \xB7 ${i.name??u.id}`;var s=e=>String(e??"").replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t]),$=document.getElementById("app"),k=e=>[...i.org.orchestrators,...i.org.types.flatMap(t=>t.people)].find(t=>t.id===e)?.situation??[],N=decodeURIComponent(location.hash.slice(1)),h=(i.resumes.find(e=>e.id===N)??i.resumes.find(e=>e.seal==="pdi"&&e.role==="specialist")??i.resumes[0])?.id,v=i.posts[0]?.scope,O={cast:"",hiring:"warn",noOwner:"bad",neverPublished:"warn",noEval:"warn",pdi:"bad",ok:"good"};function I(){let e=i.staff.map(n=>`<div class="pb-count ${O[n.key]}"><b>${n.people.length}</b><span>${s(a.staff[n.key])}${n.key!=="cast"&&n.people.length?` \u2014 ${s(n.people.map(o=>o.name).join(", "))}`:""}</span></div>`).join(""),t=i.missing.length?`<p class="pb-missing">${s(a.more)}: ${i.missing.map(n=>s(a.missing[n])).join(" \xB7 ")}</p>`:"";return`<section class="pb-staff" aria-label="${s(a.title)}">${e}</section>${t}`}var f=e=>e.filter(t=>t!=="ok"||e.length===1).map(t=>`<span class="pb-tag ${t}">${s(a.tag[t])}</span>`).join(" "),P=(e,t,n="")=>`<button class="pb-node ${n}" data-who="${s(e)}" aria-pressed="${e===h}"><span>${s(t)}</span>${f(k(e))}</button>`;function T(){let e=i.org.orchestrators.map(o=>`<button class="pb-node manager" data-who="${s(o.id)}" aria-pressed="${o.id===h}"><span>${s(o.name)}<br><small>${s(a.manager)}</small></span>${f(o.situation)}</button>`).join(""),t=i.org.types.map(o=>`<p class="pb-type">${s(o.name||a.noType)}</p>${o.people.map(r=>P(r.id,r.name)).join("")}`).join(""),n=i.org.ghosts.map(o=>`<div class="pb-node ghost"><span>${s(o.name)}</span><span class="pb-tag hiring">${s(a.ghost)}</span></div>`).join("");return`<section class="cl-card"><h2>${s(a.org)}</h2><div class="pb-org"><div class="pb-node ghost" style="justify-content:center"><span>${s(a.client)} \xB7 <small>${s(a.clientSub)}</small></span></div>${e}${t}${n}</div></section>`}function E(){let e=i.posts.find(o=>o.scope===v)??i.posts[0];if(!e)return"";let t=i.posts.map(o=>`<button data-post="${s(o.scope)}" aria-pressed="${o.scope===e.scope}">${s(o.name[c])}</button>`).join(""),n=e.requirements.map(o=>`<li class="${o.proposal?"proposal":""}">${s(o[c])}${o.proposal?` <span class="pb-src">(${s(a.proposal)})</span>`:""}</li>`).join("");return`<section class="cl-card"><h2>${s(a.post)}</h2><div class="pb-posts">${t}</div><ul class="pb-req">${n}</ul><p class="pb-note">${s(a.postNote)}</p></section>`}var m=e=>e?`${s(e.value)} <span class="pb-src">(${s(e.source)})</span>`:"\u2014",d=(e,t)=>`<div><dt>${s(e)}</dt><dd>${t}</dd></div>`,l=(e,t)=>`<div class="pb-section"><h3>${s(e)}</h3>${t}</div>`,b=(e,t=!1)=>e.length?`<div class="pb-chips">${e.map(n=>`<span class="pb-chip${t?" pb-quote":""}">${s(n[c])}</span>`).join("")}</div>`:'<p class="pb-empty">\u2014</p>';function R(e){let t=e.role==="orchestrator"?a.orchestrator:a.specialist,n=[e.title??"",`${t}${e.types.length?` \xB7 ${e.types.join(" \xB7 ")}`:""}`].filter(Boolean),o=[d(a.manager_,e.manager?s(e.manager):e.role==="orchestrator"?"\u2014":s(a.nobody)),d(a.team,m(e.team)),d(a.owner,m(e.owner)),d(a.created,m(e.created)),d(a.published,m(e.published)),d(a.schema,s(e.schemaName??"\u2014")),d(a.env,m(e.environment))].join(""),r=e.performance,w=r?r.silent?`<p class="pb-empty">${s(a.noLine)}</p>`:`<div class="pb-perf"><div><b>${r.starts}</b><span>${s(a.starts)}</span></div><div class="${r.notFired.length?"bad":""}"><b>${r.errors}</b><span>${s(a.errors)}${r.notFired.length?` \u2014 ${s(r.notFired.join(", "))} ${s(a.notFired)}`:""}</span></div><div><b>\u2014</b><span>${s(a.measured)}</span></div></div>`:`<p class="pb-empty">${s(a.noPerf)}</p>`,q=e.pdi.length?`<ol class="pb-pdi">${e.pdi.map(p=>`<li class="${p.group}"><span>${s(p[c])}<small>${s(p.why[c])}</small></span></li>`).join("")}</ol>`:`<p class="pb-empty">${s(a.nothing)}</p>`;return`<article class="cl-card pb-resume" aria-live="polite">
91
- <div class="pb-head"><div><h2>${s(e.name)}</h2>${e.title?`<p class="pb-quote">${s(e.title)}</p>`:""}<p>${s(n[n.length-1])}</p></div><span class="pb-seal ${e.seal}">${s(a.seal[e.seal])}</span></div>
92
- <dl class="pb-facts">${o}</dl>
93
- ${e.summary.length?l(a.summary,`<ul class="pb-quote">${e.summary.map(p=>`<li>${s(p)}</li>`).join("")}</ul>`):""}
94
- ${l(a.tools,b(e.tools))}
95
- ${l(a.conduct,b(e.conduct,!0))}
96
- ${l(a.goal,e.goal?`<p>${m(e.goal)}</p>`:`<p class="pb-empty">${s(a.noGoal)}</p>`)}
97
- ${l(r?a.perf(r.days):a.perf(0).replace(/ · .*/,""),w)}
98
- ${e.certifications?l(a.certs,e.certifications.length?`<ul>${e.certifications.map(p=>`<li><b>${s(a.passed(p.passed,p.total))}</b>${p.date?` \xB7 ${s(p.date)}`:""} <span class="pb-src">(${s(p.methods.map(g=>`${g.name} ${g.passed}/${g.total}`).join(" \xB7 "))} \u2014 ${s(p.file)})</span></li>`).join("")}</ul>`:`<p class="pb-empty">${s(a.certsNone)}</p>`):""}
99
- ${e.access.length?l(a.access,`<ul>${e.access.map(p=>`<li>${s(p[c])}</li>`).join("")}</ul>`):""}
100
- ${l(a.pdi,q)}
106
+ <script>(()=>{var C={en:{title:"The cast\u2019s HR",sub:"The same cast, as people: staff board, org chart, post, r\xE9sum\xE9 and development plan. Everything comes from the files, the telemetry and the team\u2019s spreadsheets.",privacy:"This file holds the client\u2019s data: keep it in the client\u2019s environment.",staff:{cast:"on the staff",hiring:"being hired",noOwner:"with no owner",neverPublished:"never published",noEval:"with no evaluation",pdi:"with a development plan",ok:"in good standing"},tag:{hiring:"being hired",noOwner:"no owner",neverPublished:"never published",noEval:"no evaluation",pdi:"plan",ok:"in good standing"},missing:{inventory:"the admin center\u2019s inventory (owner, environment, published)",team:"the team\u2019s spreadsheet (team, goal)",telemetry:"the export of Application Insights (performance)"},more:"More with",org:"Org chart",also:e=>`also ${e.join(", ")}`,client:"Customer",clientSub:"who is served",manager:"manager",ghost:"called, not in the folder",noType:"no type",post:"The post",postNote:"The post is the accepted pattern of the role and type, and the profile\u2019s rules. A newcomer is \xABhired\xBB when they meet it.",proposal:"proposal \u2014 no decision yet",manager_:"Manager",team:"Team",owner:"Owner",created:"Hired",published:"Last published",schema:"Badge",env:"Unit",nobody:"nobody calls it",summary:"Summary",tools:"Tools and access",conduct:"Languages and conduct",goal:"Goal",noGoal:"no goal declared",perf:e=>`Performance \xB7 ${e} days`,starts:"topic starts",errors:"errors logged",notFired:"did not fire",measured:"goal measured",noLine:"no line in the telemetry",noPerf:"The performance comes with the export of Application Insights (--telemetry).",certs:"Certifications",certsNone:"No evaluation in the folder of --evals.",passed:(e,t)=>`${e} of ${t} passed`,access:"Access only it has in its type",views:"How to see it",cv:"R\xE9sum\xE9",sheet:"Sheet",pdi:"Development plan",nothing:"Nothing to develop.",sources:"Sources",seal:{ok:"IN GOOD STANDING",pdi:"PLAN"},orchestrator:"Orchestrator",specialist:"Specialist",map:"\u2190 Map",foot:"cast-list \xB7 no model: what is here is what the files and tables say."},pt:{title:"RH do elenco",sub:"O mesmo elenco, visto como pessoas: quadro de pessoal, organograma, vaga, curr\xEDculo e plano de desenvolvimento. Tudo sai dos arquivos, da telemetria e das planilhas do time.",privacy:"Este arquivo tem dados do cliente: deixe-o no ambiente dele.",staff:{cast:"no quadro",hiring:"em admiss\xE3o",noOwner:"sem respons\xE1vel",neverPublished:"nunca publicado",noEval:"sem avalia\xE7\xE3o",pdi:"em PDI",ok:"em dia"},tag:{hiring:"em admiss\xE3o",noOwner:"sem respons\xE1vel",neverPublished:"nunca publicado",noEval:"sem avalia\xE7\xE3o",pdi:"PDI",ok:"em dia"},missing:{inventory:"o invent\xE1rio do admin center (respons\xE1vel, ambiente, publica\xE7\xE3o)",team:"a planilha do time (equipe, meta)",telemetry:"a exporta\xE7\xE3o do Application Insights (desempenho)"},more:"Mais com",org:"Organograma",also:e=>`tamb\xE9m ${e.join(", ")}`,client:"Cliente",clientSub:"quem \xE9 atendido",manager:"gestor",ghost:"chamado, fora da pasta",noType:"sem tipo",post:"A vaga",postNote:"A vaga \xE9 o padr\xE3o aceito do papel e do tipo, mais as regras do perfil. Quem chega \xE9 \xABcontratado\xBB quando cumpre a vaga.",proposal:"proposta \u2014 sem decis\xE3o ainda",manager_:"Gestor",team:"Equipe",owner:"Respons\xE1vel",created:"Admiss\xE3o",published:"\xDAltima publica\xE7\xE3o",schema:"Matr\xEDcula",env:"Lota\xE7\xE3o",nobody:"ningu\xE9m chama",summary:"Resumo",tools:"Ferramentas e acessos",conduct:"Idiomas e conduta",goal:"Meta",noGoal:"sem meta declarada",perf:e=>`Desempenho \xB7 ${e} dias`,starts:"in\xEDcios de t\xF3pico",errors:"erros registrados",notFired:"n\xE3o disparou",measured:"meta medida",noLine:"nenhuma linha na telemetria",noPerf:"O desempenho aparece com a exporta\xE7\xE3o do Application Insights (--telemetry).",certs:"Certifica\xE7\xF5es",certsNone:"Nenhuma avalia\xE7\xE3o na pasta do --evals.",passed:(e,t)=>`${e} de ${t} aprovados`,access:"Acessos que s\xF3 ele tem no tipo",views:"Como ver",cv:"Curr\xEDculo",sheet:"Ficha",pdi:"Plano de desenvolvimento",nothing:"Nada a desenvolver.",sources:"Fontes",seal:{ok:"EM DIA",pdi:"PDI"},orchestrator:"Orquestrador",specialist:"Especialista",map:"\u2190 Mapa",foot:"cast-list \xB7 sem modelo: o que est\xE1 aqui \xE9 o que os arquivos e as planilhas dizem."}},h=JSON.parse(document.getElementById("cast").textContent),{playbill:i,lang:d}=h,a=C[d];document.documentElement.lang=d==="pt"?"pt-BR":"en";document.title=`${a.title} \xB7 ${i.name??h.id}`;var s=e=>String(e??"").replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t]),b=document.getElementById("app"),y=[...i.org.orchestrators,...i.org.types.flatMap(e=>e.people)].map(e=>e.name),w=y.length>1?y.reduce((e,t)=>{let o=0;for(;o<e.length&&e[o]===t[o];)o++;return e.slice(0,o)}):"",v=/[-–·:]\s*$/.test(w)?w:"",u=e=>v&&e.startsWith(v)?e.slice(v.length):e,E=e=>[...i.org.orchestrators,...i.org.types.flatMap(t=>t.people)].find(t=>t.id===e)?.situation??[],S=decodeURIComponent(location.hash.slice(1)),g=(i.resumes.find(e=>e.id===S)??i.resumes.find(e=>e.seal==="pdi"&&e.role==="specialist")??i.resumes[0])?.id,q=i.posts[0]?.scope,f="cv",M={cast:"",hiring:"warn",noOwner:"bad",neverPublished:"warn",noEval:"warn",pdi:"bad",ok:"good"};function L(){let e=i.staff.map(o=>`<div class="pb-count ${M[o.key]}"><b>${o.people.length}</b><span>${s(a.staff[o.key])}${o.key!=="cast"&&o.people.length?` \u2014 ${s(o.people.map(n=>u(n.name)).join(", "))}`:""}</span></div>`).join(""),t=i.missing.length?`<p class="pb-missing">${s(a.more)}: ${i.missing.map(o=>s(a.missing[o])).join(" \xB7 ")}</p>`:"";return`<section class="pb-staff" aria-label="${s(a.title)}">${e}</section>${t}`}var I=e=>e.filter(t=>t!=="ok"||e.length===1).map(t=>`<span class="pb-tag ${t}">${s(a.tag[t])}</span>`).join(" "),D=(e,t,o)=>`<button class="pb-node" data-who="${s(e)}" aria-pressed="${e===g}"><span>${s(u(t))}${o?.length?` <small class="pb-also">${s(a.also(o))}</small>`:""}</span>${I(E(e))}</button>`;function F(){let e=i.org.orchestrators.map(n=>`<button class="pb-node manager" data-who="${s(n.id)}" aria-pressed="${n.id===g}"><span>${s(u(n.name))}<br><small>${s(a.manager)}</small></span>${I(n.situation)}</button>`).join(""),t=i.org.types.map(n=>`<p class="pb-type">${s(n.name||a.noType)}</p>${n.people.map(r=>D(r.id,r.name,r.alsoIn)).join("")}`).join(""),o=i.org.ghosts.map(n=>`<div class="pb-node ghost"><span>${s(u(n.name))}</span><span class="pb-tag hiring">${s(a.ghost)}</span></div>`).join("");return`<section class="cl-card"><h2>${s(a.org)}</h2><div class="pb-org"><div class="pb-node ghost" style="justify-content:center"><span>${s(a.client)} \xB7 <small>${s(a.clientSub)}</small></span></div>${e}${t}${o}</div></section>`}function x(){let e=i.posts.find(n=>n.scope===q)??i.posts[0];if(!e)return"";let t=i.posts.map(n=>`<button data-post="${s(n.scope)}" aria-pressed="${n.scope===e.scope}">${s(n.name[d])}</button>`).join(""),o=e.requirements.map(n=>`<li class="${n.proposal?"proposal":""}">${s(n[d])}${n.proposal?` <span class="pb-src">(${s(a.proposal)})</span>`:""}</li>`).join("");return`<section class="cl-card"><h2>${s(a.post)}</h2><div class="pb-posts">${t}</div><ul class="pb-req">${o}</ul><p class="pb-note">${s(a.postNote)}</p></section>`}var j=e=>e?`${s(e.value)} <span class="pb-src">(${s(e.source)})</span>`:"\u2014",m=(e,t)=>`<div><dt>${s(e)}</dt><dd>${t}</dd></div>`,G=e=>e?s(e.value):"\u2014",B='<svg viewBox="0 0 40 40" width="34" height="34" aria-hidden="true"><rect x="9" y="13" width="22" height="17" rx="5" fill="none" stroke="currentColor" stroke-width="2.2"/><line x1="20" y1="13" x2="20" y2="8" stroke="currentColor" stroke-width="2.2"/><circle cx="20" cy="7" r="2" fill="currentColor"/><circle cx="16" cy="21" r="2" fill="currentColor"/><circle cx="24" cy="21" r="2" fill="currentColor"/><path d="M16 26 q4 2.5 8 0" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',c=(e,t)=>`<div class="pb-section"><h3>${s(e)}</h3>${t}</div>`,k=(e,t=!1)=>e.length?`<div class="pb-chips">${e.map(o=>`<span class="pb-chip${t?" pb-quote":""}">${s(o[d])}</span>`).join("")}</div>`:'<p class="pb-empty">\u2014</p>';function H(e){let t=e.role==="orchestrator"?a.orchestrator:a.specialist,o=[e.title??"",`${t}${e.types.length?` \xB7 ${e.types.join(" \xB7 ")}`:""}`].filter(Boolean),n=f==="cv",r=n?G:j,O=[m(a.manager_,e.manager?s(e.manager):e.role==="orchestrator"?"\u2014":s(a.nobody)),m(a.team,r(e.team)),m(a.owner,r(e.owner)),m(a.created,r(e.created)),m(a.published,r(e.published)),m(a.schema,s(e.schemaName??"\u2014")),m(a.env,r(e.environment))].join(""),p=e.performance,R=p?p.silent?`<p class="pb-empty">${s(a.noLine)}</p>`:`<div class="pb-perf"><div><b>${p.starts}</b><span>${s(a.starts)}</span></div><div class="${p.notFired.length?"bad":""}"><b>${p.errors}</b><span>${s(a.errors)}${p.notFired.length?` \u2014 ${s(p.notFired.join(", "))} ${s(a.notFired)}`:""}</span></div><div><b>\u2014</b><span>${s(a.measured)}</span></div></div>`:`<p class="pb-empty">${s(a.noPerf)}</p>`,T=e.pdi.length?`<ol class="pb-pdi">${e.pdi.map(l=>`<li class="${l.group}"><span>${s(l[d])}<small>${s(l.why[d])}</small></span></li>`).join("")}</ol>`:`<p class="pb-empty">${s(a.nothing)}</p>`,A=n?`<div class="pb-head"><span class="pb-av">${B}</span><div class="pb-who"><h2>${s(e.name)}</h2>${e.title?`<p class="pb-quote">${s(e.title)}</p>`:""}<p>${s(o[o.length-1])}</p></div><span class="pb-seal ${e.seal}">${s(a.seal[e.seal])}</span></div>`:`<div class="pb-head"><div><h2>${s(e.name)}</h2>${e.title?`<p class="pb-quote">${s(e.title)}</p>`:""}<p>${s(o[o.length-1])}</p></div><span class="pb-seal ${e.seal}">${s(a.seal[e.seal])}</span></div>`,P=`<div class="pb-views" role="group" aria-label="${s(a.views)}">${["cv","sheet"].map(l=>`<button data-view="${l}" aria-pressed="${l===f}">${s(a[l])}</button>`).join("")}</div>`;return`<article class="cl-card pb-resume${n?" pb-cv":""}" aria-live="polite">
107
+ ${P}
108
+ ${A}
109
+ <dl class="pb-facts">${O}</dl>
110
+ ${e.summary.length?c(a.summary,`<ul class="pb-quote">${e.summary.map(l=>`<li>${s(l)}</li>`).join("")}</ul>`):""}
111
+ ${c(a.tools,k(e.tools))}
112
+ ${c(a.conduct,k(e.conduct,!0))}
113
+ ${c(a.goal,e.goal?`<p>${j(e.goal)}</p>`:`<p class="pb-empty">${s(a.noGoal)}</p>`)}
114
+ ${c(p?a.perf(p.days):a.perf(0).replace(/ · .*/,""),R)}
115
+ ${e.certifications?c(a.certs,e.certifications.length?`<ul>${e.certifications.map(l=>`<li><b>${s(a.passed(l.passed,l.total))}</b>${l.date?` \xB7 ${s(l.date)}`:""} <span class="pb-src">(${s(l.methods.map($=>`${$.name} ${$.passed}/${$.total}`).join(" \xB7 "))} \u2014 ${s(l.file)})</span></li>`).join("")}</ul>`:`<p class="pb-empty">${s(a.certsNone)}</p>`):""}
116
+ ${e.access.length?c(a.access,`<ul>${e.access.map(l=>`<li>${s(l[d])}</li>`).join("")}</ul>`):""}
117
+ ${c(a.pdi,T)}
101
118
  <p class="pb-note">${s(a.sources)}: ${s(e.sources.join(", "))}</p>
102
- </article>`}function y(){let e=i.resumes.find(t=>t.id===h)??i.resumes[0];$.innerHTML=`<div class="cl-wrap">
103
- <header>${u.map?`<p class="cl-sub"><a href="${s(u.map)}">${s(a.map)}</a></p>`:""}<h1 class="cl-title">${s(a.title)} \xB7 ${s(i.name??u.id)}</h1><p class="cl-sub">${s(a.sub)}</p><p class="cl-private">${s(a.privacy)}</p></header>
104
- ${I()}
105
- <div class="pb-body"><div class="pb-side">${T()}${E()}</div>${e?R(e):""}</div>
119
+ </article>`}function N(){let e=i.resumes.find(t=>t.id===g)??i.resumes[0];b.innerHTML=`<div class="cl-wrap">
120
+ <header>${h.map?`<p class="cl-sub"><a href="${s(h.map)}">${s(a.map)}</a></p>`:""}<h1 class="cl-title">${s(a.title)} \xB7 ${s(i.name??h.id)}</h1><p class="cl-sub">${s(a.sub)}</p><p class="cl-private">${s(a.privacy)}</p></header>
121
+ ${L()}
122
+ <div class="pb-body"><div class="pb-side">${F()}${x()}</div>${e?H(e):""}</div>
106
123
  <p class="cl-foot">${s(a.foot)}</p>
107
- </div>`}$.addEventListener("click",e=>{let t=e.target.closest("button");if(t){if(t.dataset.who)h=t.dataset.who;else if(t.dataset.post)v=t.dataset.post;else return;y(),t.dataset.who&&$.querySelector(".pb-resume")?.scrollIntoView({block:"nearest"})}});y();})();
124
+ </div>`}b.addEventListener("click",e=>{let t=e.target.closest("button");if(t){if(t.dataset.who)g=t.dataset.who;else if(t.dataset.post)q=t.dataset.post;else if(t.dataset.view)f=t.dataset.view;else return;N(),t.dataset.who&&b.querySelector(".pb-resume")?.scrollIntoView({block:"nearest"})}});N();})();
108
125
  </script>
109
126
  </body>
110
127
  </html>
@@ -57,9 +57,9 @@ body { margin: 0; }
57
57
  .pl-checks li { padding: 3px 0; border-bottom: 1px dashed var(--line); }
58
58
  .pl-checks .ok::before { content: "✓ "; color: var(--ok); } .pl-checks .off::before { content: "✕ "; color: var(--bad); } .pl-checks .decide::before { content: "? "; color: var(--amber); }
59
59
  .pl-checks .off { color: var(--bad); } .pl-checks .decide { color: var(--amber); }
60
- .pl-narr { position: absolute; left: 14px; right: 14px; bottom: 12px; background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 10px 14px; font-size: 15px; box-shadow: 0 8px 30px rgba(0,0,0,.25); }
61
- .pl-narr[hidden] { display: none; }
62
- .pl-narr.warn { border-color: var(--bad); }
60
+ .pl-narr { margin: 0; background: var(--card); border-top: 1px solid var(--line); padding: 10px 14px; font-size: 15px; min-height: 64px; }
61
+ .pl-narr.idle { display: flex; align-items: center; }
62
+ .pl-narr.warn { border-top: 2px solid var(--bad); }
63
63
  .pl-narr .pl-step { color: var(--warm); font-weight: 650; margin-right: 6px; }
64
64
  .pl-narr q { display: block; margin-top: 4px; color: var(--muted); font-size: 13px; }
65
65
  .pl-narr .pl-keys { display: block; margin-top: 4px; color: var(--muted); font-size: 11px; }
@@ -98,17 +98,17 @@ body { margin: 0; }
98
98
  <body>
99
99
  <div class="cl" id="app"></div>
100
100
  <script type="application/json" id="cast">{{CAST}}</script>
101
- <script>(()=>{var F={en:{title:"Stage",sub:"The cast on stage: who talks to whom, the traffic each one gets, the patterns as lenses, and a follow spot that walks a call.",privacy:"This file holds the client\u2019s data: keep it in the client\u2019s environment.",client:"Customer",lenses:"Lenses \u2014 light a pattern",lensHint:"Pick a lens: who follows the pattern lights green, who is off blinks red.",scenes:"Follow spot \u2014 walk a call",actor:"Actor",actorHint:"Click someone on stage.",resume:"See the r\xE9sum\xE9 \u2192",map:"\u2190 Map",vol:(e,a)=>`${e.toLocaleString("en")} topic starts / ${a} days`,silent:"no telemetry",noTraffic:"The traffic shows with the export of Application Insights (--telemetry).",legend:["traffic (topic starts of who receives it)","off a pattern","to decide","not in the folder / unused"],structure:"Inner arrows (flows, systems) are structure, not measured traffic.",step:(e,a)=>`step ${e}/${a}`,keys:"\u2190 \u2192 to move \xB7 space plays all \xB7 Esc leaves",orchestrator:"Orchestrator",specialist:"Specialist",fingerprint:"Fingerprint of its instructions",foot:"cast-list \xB7 no model: what is here is what the files and tables say."},pt:{title:"Palco",sub:"O elenco no palco: quem fala com quem, o tr\xE1fego de cada um, os padr\xF5es como lentes, e um canh\xE3o que segue uma chamada.",privacy:"Este arquivo tem dados do cliente: deixe-o no ambiente dele.",client:"Cliente",lenses:"Lentes \u2014 acenda um padr\xE3o",lensHint:"Escolha uma lente: quem segue o padr\xE3o acende em verde, quem foge pisca em vermelho.",scenes:"Canh\xE3o seguidor \u2014 siga uma chamada",actor:"Ator",actorHint:"Clique em algu\xE9m no palco.",resume:"Ver curr\xEDculo \u2192",map:"\u2190 Mapa",vol:(e,a)=>`${e.toLocaleString("pt-BR")} in\xEDcios de t\xF3pico / ${a} dias`,silent:"sem telemetria",noTraffic:"O tr\xE1fego aparece com a exporta\xE7\xE3o do Application Insights (--telemetry).",legend:["tr\xE1fego (in\xEDcios de t\xF3pico de quem recebe)","fora do padr\xE3o","a decidir","fora da pasta / sem uso"],structure:"As setas internas (fluxos, sistemas) s\xE3o estrutura, n\xE3o tr\xE1fego medido.",step:(e,a)=>`passo ${e}/${a}`,keys:"\u2190 \u2192 avan\xE7am e voltam \xB7 espa\xE7o toca tudo \xB7 Esc sai",orchestrator:"Orquestrador",specialist:"Especialista",fingerprint:"Impress\xE3o digital das instru\xE7\xF5es",foot:"cast-list \xB7 sem modelo: o que est\xE1 aqui \xE9 o que os arquivos e as planilhas dizem."}},y=JSON.parse(document.getElementById("cast").textContent),{stage:o,lang:$}=y,l=F[$];document.documentElement.lang=$==="pt"?"pt-BR":"en";document.title=`${l.title} \xB7 ${o.name??y.id}`;var s=e=>String(e??"").replace(/[&<>"']/g,a=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[a]),v=document.getElementById("app"),N=matchMedia("(prefers-reduced-motion: reduce)").matches,m=168,S=48,b=e=>o.nodes.find(a=>a.id===e),L=e=>e.kind==="orchestrator"||e.kind==="specialist",k,p,f=0,T,q;function V(e){let a=b(e.from),i=b(e.to),r=i.x>=a.x,c=a.x+(r?m/2:-m/2),d=i.x+(r?-m/2:m/2),n=(c+d)/2;return{d:`M${c},${a.y} C${n},${a.y} ${n},${i.y} ${d},${i.y}`,mx:n,my:(a.y+i.y)/2,x2:d,y2:i.y}}var B=e=>e.kind==="client"?l.client:e.label,x=(e,a=24)=>e.length>a?`${e.slice(0,a-1)}\u2026`:e,C=o.nodes.filter(L),G=C.length>1?C.map(e=>e.label).reduce((e,a)=>{let i=0;for(;i<e.length&&e[i]===a[i];)i++;return e.slice(0,i)}):"",M=/[-–·:]\s*$/.test(G)?G:"",O=e=>L(e)&&M?e.label.slice(M.length):B(e);function P(){let e=o.lenses.find(t=>t.id===k),a=t=>{let u=["pl-node",t.kind,t.unused?"unused":""];return e&&u.push(e.bad.includes(t.id)?"l-bad":e.amber.includes(t.id)?"l-amber":e.ok.includes(t.id)?"l-ok":""),p&&p.steps[f]?.node===t.id&&p.steps[f].warn&&u.push("warn"),u.filter(Boolean).join(" ")},i=o.groups.map(t=>`<rect class="pl-band" x="${b(o.nodes.find(u=>u.kind==="specialist").id).x-m/2-18}" y="${t.y1}" width="${m+36}" height="${t.y2-t.y1}" rx="12"/><text class="pl-group" x="${b(o.nodes.find(u=>u.kind==="specialist").id).x-m/2-10}" y="${t.y1-6}">${s(t.label)}</text>`).join(""),r=o.edges.map((t,u)=>{let h=V(t),g=t.tone??"",I=t.kind==="traffic"&&b(t.to).kind!=="ghost",H=t.label?I?`<text class="pl-elabel ${g}" x="${h.x2-10}" y="${h.y2-9}" text-anchor="end">${s(x(t.label[$],56))}</text>`:`<text class="pl-elabel ${g}" x="${h.mx}" y="${h.my-6}" text-anchor="middle">${s(x(t.label[$],40))}</text>`:"";return`<path id="e${u}" class="pl-edge ${t.kind} ${g} ${t.dashed?"dashed":""}" d="${h.d}"/>${H}`}).join(""),c=o.nodes.map(t=>{let u=L(t)&&o.hasTelemetry?`<text class="pl-vol ${t.silent?"silent":""}" x="${m/2}" y="${S+14}" text-anchor="middle">${s(t.silent?l.silent:t.volume!==void 0?l.vol(t.volume,o.days??0):"")}</text>`:"",h=L(t)?` tabindex="0" role="button" aria-label="${s(t.label)}"`:"";return`<g class="${a(t)}" data-node="${s(t.id)}" transform="translate(${t.x-m/2},${t.y-S/2})"${h}>${u}<rect width="${m}" height="${S}" rx="${t.kind==="client"?S/2:10}"/><text x="${m/2}" y="21" text-anchor="middle">${s(x(O(t),22))}</text><text class="pl-sub" x="${m/2}" y="37" text-anchor="middle">${s(x(t.sub[$],30))}</text></g>`}).join(""),d=p?.steps[f],n=d?b(d.node):void 0;return`<svg class="pl-svg ${e?"lensing":""}" viewBox="0 0 ${o.width} ${o.height}" role="img" aria-label="${s(l.title)}">
101
+ <script>(()=>{var H={en:{title:"Stage",sub:"The cast on stage: who talks to whom, the traffic each one gets, the patterns as lenses, and a follow spot that walks a call.",privacy:"This file holds the client\u2019s data: keep it in the client\u2019s environment.",client:"Customer",lenses:"Lenses \u2014 light a pattern",lensHint:"Pick a lens: who follows the pattern lights green, who is off blinks red.",scenes:"Follow spot \u2014 walk a call",narrIdle:"Pick a call under \xABFollow spot\xBB to walk it step by step here.",actor:"Actor",actorHint:"Click someone on stage.",resume:"See the r\xE9sum\xE9 \u2192",map:"\u2190 Map",vol:(e,n)=>`${e.toLocaleString("en")} topic starts / ${n} days`,silent:"no telemetry",noTraffic:"The traffic shows with the export of Application Insights (--telemetry).",legend:["traffic (topic starts of who receives it)","off a pattern","to decide","not in the folder / unused"],structure:"Inner arrows (flows, systems) are structure, not measured traffic.",step:(e,n)=>`step ${e}/${n}`,keys:"\u2190 \u2192 to move \xB7 space plays all \xB7 Esc leaves",orchestrator:"Orchestrator",specialist:"Specialist",fingerprint:"Fingerprint of its instructions",foot:"cast-list \xB7 no model: what is here is what the files and tables say."},pt:{title:"Palco",sub:"O elenco no palco: quem fala com quem, o tr\xE1fego de cada um, os padr\xF5es como lentes, e um canh\xE3o que segue uma chamada.",privacy:"Este arquivo tem dados do cliente: deixe-o no ambiente dele.",client:"Cliente",lenses:"Lentes \u2014 acenda um padr\xE3o",lensHint:"Escolha uma lente: quem segue o padr\xE3o acende em verde, quem foge pisca em vermelho.",scenes:"Canh\xE3o seguidor \u2014 siga uma chamada",narrIdle:"Escolha uma chamada em \xABCanh\xE3o seguidor\xBB para segui-la passo a passo aqui.",actor:"Ator",actorHint:"Clique em algu\xE9m no palco.",resume:"Ver curr\xEDculo \u2192",map:"\u2190 Mapa",vol:(e,n)=>`${e.toLocaleString("pt-BR")} in\xEDcios de t\xF3pico / ${n} dias`,silent:"sem telemetria",noTraffic:"O tr\xE1fego aparece com a exporta\xE7\xE3o do Application Insights (--telemetry).",legend:["tr\xE1fego (in\xEDcios de t\xF3pico de quem recebe)","fora do padr\xE3o","a decidir","fora da pasta / sem uso"],structure:"As setas internas (fluxos, sistemas) s\xE3o estrutura, n\xE3o tr\xE1fego medido.",step:(e,n)=>`passo ${e}/${n}`,keys:"\u2190 \u2192 avan\xE7am e voltam \xB7 espa\xE7o toca tudo \xB7 Esc sai",orchestrator:"Orquestrador",specialist:"Especialista",fingerprint:"Impress\xE3o digital das instru\xE7\xF5es",foot:"cast-list \xB7 sem modelo: o que est\xE1 aqui \xE9 o que os arquivos e as planilhas dizem."}},y=JSON.parse(document.getElementById("cast").textContent),{stage:o,lang:h}=y,l=H[h];document.documentElement.lang=h==="pt"?"pt-BR":"en";document.title=`${l.title} \xB7 ${o.name??y.id}`;var s=e=>String(e??"").replace(/[&<>"']/g,n=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[n]),v=document.getElementById("app"),N=matchMedia("(prefers-reduced-motion: reduce)").matches,m=168,k=48,x=e=>o.nodes.find(n=>n.id===e),I=e=>e.kind==="orchestrator"||e.kind==="specialist",b,d,$=0,L,A;function V(e){let n=x(e.from),i=x(e.to),r=i.x>=n.x,c=n.x+(r?m/2:-m/2),p=i.x+(r?-m/2:m/2),a=(c+p)/2;return{d:`M${c},${n.y} C${a},${n.y} ${a},${i.y} ${p},${i.y}`,mx:a,my:(n.y+i.y)/2,x2:p,y2:i.y}}var B=e=>e.kind==="client"?l.client:e.labels?.[h]??e.label,w=(e,n=24)=>e.length>n?`${e.slice(0,n-1)}\u2026`:e,j=o.nodes.filter(I),G=j.length>1?j.map(e=>e.label).reduce((e,n)=>{let i=0;for(;i<e.length&&e[i]===n[i];)i++;return e.slice(0,i)}):"",C=/[-–·:]\s*$/.test(G)?G:"",O=e=>(I(e)||e.kind==="ghost")&&C&&e.label.startsWith(C)?e.label.slice(C.length):B(e);function P(){let e=o.lenses.find(t=>t.id===b),n=t=>{let u=["pl-node",t.kind,t.unused?"unused":""];return e&&u.push(e.bad.includes(t.id)?"l-bad":e.amber.includes(t.id)?"l-amber":e.ok.includes(t.id)?"l-ok":""),d&&d.steps[$]?.node===t.id&&d.steps[$].warn&&u.push("warn"),u.filter(Boolean).join(" ")},i=o.groups.map(t=>`<rect class="pl-band" x="${x(o.nodes.find(u=>u.kind==="specialist").id).x-m/2-18}" y="${t.y1}" width="${m+36}" height="${t.y2-t.y1}" rx="12"/><text class="pl-group" x="${x(o.nodes.find(u=>u.kind==="specialist").id).x-m/2-10}" y="${t.y1-6}">${s(t.label)}</text>`).join(""),r=o.edges.map((t,u)=>{let f=V(t),g=t.tone??"",M=t.kind==="traffic"&&x(t.to).kind!=="ghost",F=t.label?M?`<text class="pl-elabel ${g}" x="${f.x2-10}" y="${f.y2-9}" text-anchor="end">${s(w(t.label[h],56))}</text>`:`<text class="pl-elabel ${g}" x="${f.mx}" y="${f.my-6}" text-anchor="middle">${s(w(t.label[h],40))}</text>`:"";return`<path id="e${u}" class="pl-edge ${t.kind} ${g} ${t.dashed?"dashed":""}" d="${f.d}"/>${F}`}).join(""),c=o.nodes.map(t=>{let u=I(t)&&o.hasTelemetry?`<text class="pl-vol ${t.silent?"silent":""}" x="${m/2}" y="${k+14}" text-anchor="middle">${s(t.silent?l.silent:t.volume!==void 0?l.vol(t.volume,o.days??0):"")}</text>`:"",f=I(t)?` tabindex="0" role="button" aria-label="${s(t.label)}"`:"";return`<g class="${n(t)}" data-node="${s(t.id)}" transform="translate(${t.x-m/2},${t.y-k/2})"${f}>${u}<rect width="${m}" height="${k}" rx="${t.kind==="client"?k/2:10}"/><text x="${m/2}" y="21" text-anchor="middle">${s(w(O(t),t.kind==="ghost"?30:22))}</text><text class="pl-sub" x="${m/2}" y="37" text-anchor="middle">${s(w(t.sub[h],30))}</text></g>`}).join(""),p=d?.steps[$],a=p?x(p.node):void 0;return`<svg class="pl-svg ${e?"lensing":""}" viewBox="0 0 ${o.width} ${o.height}" role="img" aria-label="${s(l.title)}">
102
102
  <defs><radialGradient id="pl-spot" r="0.5"><stop offset="0" stop-color="#000"/><stop offset="0.6" stop-color="#000"/><stop offset="1" stop-color="#000" stop-opacity="0"/></radialGradient>
103
- <mask id="pl-mask"><rect width="${o.width}" height="${o.height}" fill="#fff"/>${n?`<circle cx="${n.x}" cy="${n.y}" r="150" fill="url(#pl-spot)"/>`:""}</mask></defs>
103
+ <mask id="pl-mask"><rect width="${o.width}" height="${o.height}" fill="#fff"/>${a?`<ellipse cx="${a.x}" cy="${a.y}" rx="${m/2+34}" ry="${k/2+30}" fill="url(#pl-spot)"/>`:""}</mask></defs>
104
104
  <g>${i}</g><g>${r}</g><g id="pl-parts"></g><g>${c}</g>
105
- <rect class="pl-dark" width="${o.width}" height="${o.height}" mask="url(#pl-mask)" opacity="${p?.72:0}"/>
106
- </svg>`}function D(){let e=o.lenses.find(n=>n.id===k),a=`<section class="pl-box"><h2>${s(l.lenses)}</h2><div class="pl-chips">${o.lenses.map(n=>`<button data-lens="${s(n.id)}" aria-pressed="${n.id===k}">${s(x(n.name[$],28))}</button>`).join("")}</div><p class="pl-cap">${e?s(e.caption[$]):`<span class="pl-note">${s(l.lensHint)}</span>`}</p></section>`,i=o.scenes.length?`<section class="pl-box"><h2>${s(l.scenes)}</h2><div class="pl-scenes">${o.scenes.map(n=>`<button data-scene="${s(n.id)}" aria-pressed="${n.id===p?.id}">\u25B6 ${s(n.title[$])}</button>`).join("")}</div></section>`:"",r=o.actors.find(n=>n.id===T),c=r?`<section class="pl-box pl-card" aria-live="polite"><h2>${s(l.actor)}</h2><p class="pl-name">${s(r.name)}</p><p class="pl-role">${s(r.role==="orchestrator"?l.orchestrator:l.specialist)}${r.types.length?` \xB7 ${s(r.types.join(" \xB7 "))}`:""}${o.hasTelemetry?` \xB7 ${s(r.silent?l.silent:r.volume!==void 0?l.vol(r.volume,o.days??0):"")}`:""}</p>
107
- ${r.fingerprint.length?`<p class="pl-note">${s(l.fingerprint)}</p><div class="pl-dna">${r.fingerprint.map(n=>`<span class="${n.kind}" style="flex:${n.size}" title="${s(n.label??"")}"></span>`).join("")}</div>`:""}
108
- <ul class="pl-checks">${r.checks.map(n=>`<li class="${n.state}">${s(n[$])}</li>`).join("")}${r.access.map(n=>`<li class="decide">${s(n[$])}</li>`).join("")}</ul>
109
- ${y.playbill?`<p class="pl-note" style="margin-top:8px"><a href="${s(y.playbill)}#${encodeURIComponent(r.id)}">${s(l.resume)}</a></p>`:""}</section>`:`<section class="pl-box pl-card"><h2>${s(l.actor)}</h2><p class="pl-note">${s(l.actorHint)}</p></section>`,d=`<section class="pl-box"><div class="pl-legend">${[["var(--beam)",l.legend[0]],["var(--bad)",l.legend[1]],["var(--amber)",l.legend[2]],["var(--ghost)",l.legend[3]]].map(([n,t])=>`<span><i class="pl-dot" style="background:${n}"></i>${s(t)}</span>`).join("")}</div><p class="pl-note" style="margin-top:8px">${s(o.hasTelemetry?l.structure:l.noTraffic)}</p></section>`;return a+i+c+d}function R(){let e=p?.steps[f];return!p||!e?'<div class="pl-narr" hidden></div>':`<div class="pl-narr ${e.warn?"warn":""}" role="status"><span class="pl-step">${s(l.step(f+1,p.steps.length))}</span>${s(e.text[$])}${e.quote?`<q class="pb-quote">${s(e.quote)}</q>`:""}<span class="pl-keys">${s(l.keys)}</span></div>`}function w(){v.innerHTML=`<header class="pl-head">${y.map?`<p><a href="${s(y.map)}">${s(l.map)}</a></p>`:""}<h1>${s(l.title)} \xB7 <span>${s(o.name??y.id)}</span></h1><p>${s(l.sub)}</p><p class="pl-private">${s(l.privacy)}</p></header>
105
+ <rect class="pl-dark" width="${o.width}" height="${o.height}" mask="url(#pl-mask)" opacity="${d?.72:0}"/>
106
+ </svg>`}function D(){let e=o.lenses.find(a=>a.id===b),n=`<section class="pl-box"><h2>${s(l.lenses)}</h2><div class="pl-chips">${o.lenses.map(a=>`<button data-lens="${s(a.id)}" aria-pressed="${a.id===b}">${s(w(a.name[h],28))}</button>`).join("")}</div><p class="pl-cap">${e?s(e.caption[h]):`<span class="pl-note">${s(l.lensHint)}</span>`}</p></section>`,i=o.scenes.length?`<section class="pl-box"><h2>${s(l.scenes)}</h2><div class="pl-scenes">${o.scenes.map(a=>`<button data-scene="${s(a.id)}" aria-pressed="${a.id===d?.id}">\u25B6 ${s(a.title[h])}</button>`).join("")}</div></section>`:"",r=o.actors.find(a=>a.id===L),c=r?`<section class="pl-box pl-card" aria-live="polite"><h2>${s(l.actor)}</h2><p class="pl-name">${s(r.name)}</p><p class="pl-role">${s(r.role==="orchestrator"?l.orchestrator:l.specialist)}${r.types.length?` \xB7 ${s(r.types.join(" \xB7 "))}`:""}${o.hasTelemetry?` \xB7 ${s(r.silent?l.silent:r.volume!==void 0?l.vol(r.volume,o.days??0):"")}`:""}</p>
107
+ ${r.fingerprint.length?`<p class="pl-note">${s(l.fingerprint)}</p><div class="pl-dna">${r.fingerprint.map(a=>`<span class="${a.kind}" style="flex:${a.size}" title="${s(a.label??"")}"></span>`).join("")}</div>`:""}
108
+ <ul class="pl-checks">${r.checks.map(a=>`<li class="${a.state}">${s(a[h])}</li>`).join("")}${r.access.map(a=>`<li class="decide">${s(a[h])}</li>`).join("")}</ul>
109
+ ${y.playbill?`<p class="pl-note" style="margin-top:8px"><a href="${s(y.playbill)}#${encodeURIComponent(r.id)}">${s(l.resume)}</a></p>`:""}</section>`:`<section class="pl-box pl-card"><h2>${s(l.actor)}</h2><p class="pl-note">${s(l.actorHint)}</p></section>`,p=`<section class="pl-box"><div class="pl-legend">${[["var(--beam)",l.legend[0]],["var(--bad)",l.legend[1]],["var(--amber)",l.legend[2]],["var(--ghost)",l.legend[3]]].map(([a,t])=>`<span><i class="pl-dot" style="background:${a}"></i>${s(t)}</span>`).join("")}</div><p class="pl-note" style="margin-top:8px">${s(o.hasTelemetry?l.structure:l.noTraffic)}</p></section>`;return n+i+c+p}function R(){let e=d?.steps[$];return!d||!e?`<div class="pl-narr idle"><span class="pl-note">${s(l.narrIdle)}</span></div>`:`<div class="pl-narr ${e.warn?"warn":""}" role="status"><span class="pl-step">${s(l.step($+1,d.steps.length))}</span>${s(e.text[h])}${e.quote?`<q class="pb-quote">${s(e.quote)}</q>`:""}<span class="pl-keys">${s(l.keys)}</span></div>`}function E(){v.innerHTML=`<header class="pl-head">${y.map?`<p><a href="${s(y.map)}">${s(l.map)}</a></p>`:""}<h1>${s(l.title)} \xB7 <span>${s(o.name??y.id)}</span></h1><p>${s(l.sub)}</p><p class="pl-private">${s(l.privacy)}</p></header>
110
110
  <div class="pl-wrap"><div class="pl-stage">${P()}${R()}</div><aside class="pl-panel">${D()}</aside></div>
111
- <p class="pl-foot">${s(l.foot)}</p>`,z()}var E;function z(){E&&cancelAnimationFrame(E);let e=v.querySelector("#pl-parts");if(!e||!o.hasTelemetry)return;let a=[];o.edges.forEach((c,d)=>{let n=v.querySelector(`#e${d}`);if(!n||c.dashed)return;let t=c.kind==="traffic"?c.volume?Math.max(1,Math.min(8,Math.round(Math.log10(c.volume+1)*2.2))):0:1,u=n.getTotalLength();for(let h=0;h<t;h++){let g=document.createElementNS("http://www.w3.org/2000/svg","circle");g.setAttribute("r",c.kind==="traffic"?"3":"2.2"),g.setAttribute("class",`pl-part ${c.kind}`),e.appendChild(g),a.push({el:g,path:n,len:u,phase:h/t,speed:c.kind==="traffic"?11e-5:6e-5})}});let i=c=>{for(let d of a){let n=d.path.getPointAtLength(((d.phase+c*d.speed)%1+1)%1*d.len);d.el.setAttribute("cx",n.x.toFixed(1)),d.el.setAttribute("cy",n.y.toFixed(1))}};if(N)return i(0);let r=c=>{i(c),E=requestAnimationFrame(r)};E=requestAnimationFrame(r)}function A(){q&&clearInterval(q),q=void 0}function j(e){p&&(f=Math.max(0,Math.min(p.steps.length-1,e)),w())}v.addEventListener("click",e=>{let a=e.target,i=a.closest("button"),r=a.closest("[data-node]");if(i?.dataset.lens)k=k===i.dataset.lens?void 0:i.dataset.lens;else if(i?.dataset.scene)A(),p=p?.id===i.dataset.scene?void 0:o.scenes.find(c=>c.id===i.dataset.scene),f=0;else if(r&&o.actors.some(c=>c.id===r.dataset.node))T=r.dataset.node;else return;w()});v.addEventListener("keydown",e=>{let a=e.target.closest?.("[data-node]");a&&(e.key==="Enter"||e.key===" ")&&o.actors.some(i=>i.id===a.dataset.node)&&(e.preventDefault(),T=a.dataset.node,w(),v.querySelector(`[data-node="${CSS.escape(T)}"]`)?.focus())});document.addEventListener("keydown",e=>{if(p)if(e.key==="ArrowRight")j(f+1);else if(e.key==="ArrowLeft")j(f-1);else if(e.key==="Escape")A(),p=void 0,w();else if(e.key===" "&&!e.target.closest?.("[data-node]"))e.preventDefault(),A(),q=window.setInterval(()=>p&&f<p.steps.length-1?j(f+1):A(),1800);else return});w();})();
111
+ <p class="pl-foot">${s(l.foot)}</p>`,z()}var q;function z(){q&&cancelAnimationFrame(q);let e=v.querySelector("#pl-parts");if(!e||!o.hasTelemetry)return;let n=[];o.edges.forEach((c,p)=>{let a=v.querySelector(`#e${p}`);if(!a||c.dashed)return;let t=c.kind==="traffic"?c.volume?Math.max(1,Math.min(8,Math.round(Math.log10(c.volume+1)*2.2))):0:1,u=a.getTotalLength();for(let f=0;f<t;f++){let g=document.createElementNS("http://www.w3.org/2000/svg","circle");g.setAttribute("r",c.kind==="traffic"?"3":"2.2"),g.setAttribute("class",`pl-part ${c.kind}`),e.appendChild(g),n.push({el:g,path:a,len:u,phase:f/t,speed:c.kind==="traffic"?11e-5:6e-5})}});let i=c=>{for(let p of n){let a=p.path.getPointAtLength(((p.phase+c*p.speed)%1+1)%1*p.len);p.el.setAttribute("cx",a.x.toFixed(1)),p.el.setAttribute("cy",a.y.toFixed(1))}};if(N)return i(0);let r=c=>{i(c),q=requestAnimationFrame(r)};q=requestAnimationFrame(r)}function S(){A&&clearInterval(A),A=void 0}function T(e){d&&($=Math.max(0,Math.min(d.steps.length-1,e)),E())}v.addEventListener("click",e=>{let n=e.target,i=n.closest("button"),r=n.closest("[data-node]");if(i?.dataset.lens)b=b===i.dataset.lens?void 0:i.dataset.lens,b&&(S(),d=void 0);else if(i?.dataset.scene)S(),d=d?.id===i.dataset.scene?void 0:o.scenes.find(c=>c.id===i.dataset.scene),$=0,d&&(b=void 0);else if(r&&o.actors.some(c=>c.id===r.dataset.node))L=r.dataset.node;else return;E()});v.addEventListener("keydown",e=>{let n=e.target.closest?.("[data-node]");n&&(e.key==="Enter"||e.key===" ")&&o.actors.some(i=>i.id===n.dataset.node)&&(e.preventDefault(),L=n.dataset.node,E(),v.querySelector(`[data-node="${CSS.escape(L)}"]`)?.focus())});document.addEventListener("keydown",e=>{if(d)if(e.key==="ArrowRight")T($+1);else if(e.key==="ArrowLeft")T($-1);else if(e.key==="Escape")S(),d=void 0,E();else if(e.key===" "&&!e.target.closest?.("[data-node]"))e.preventDefault(),S(),A=window.setInterval(()=>d&&$<d.steps.length-1?T($+1):S(),1800);else return});E();})();
112
112
  </script>
113
113
  </body>
114
114
  </html>