---
title: "AI Infra 面试学习手册：推理加速、SGLang 与 vLLM"
description: "围绕推理系统梳理架构、缓存、调度、并行与量化；包含 SGLang 和 vLLM 各 30 分钟学习路线、项目追问、训练优化基础与交互图示。"
pubDate: 2026-10-15
tags: ["AI Infra","推理加速","SGLang","vLLM","面试准备"]
category: "AI Infra"
lang: "zh"
math: false
---
<div class="cortex-interview-page">
    <iframe title="寒武纪 AI Infra 面试学习手册" allow="fullscreen" style="position:fixed;inset:0;width:100%;height:100dvh;border:0;z-index:2147483000;background:#f4f6fa" srcdoc="&lt;!doctype html&gt;&#10;&lt;html lang=&quot;zh-CN&quot;&gt;&lt;head&gt;&lt;meta charset=&quot;utf-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;&lt;title&gt;寒武纪 AI Infra 面试准备 · 陈城&lt;/title&gt;&#10;&lt;style&gt;&#10;:root{--bg:#f4f6fa;--paper:#fff;--ink:#18263a;--muted:#53647a;--line:#dbe3ee;--blue:#195ecb;--tint:#eaf1ff;--amber:#fff4dd;--green:#e7f6ef}*{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:20px}body{margin:0;background:var(--bg);color:var(--ink);font:16px/1.85 &quot;Microsoft YaHei&quot;,&quot;Segoe UI&quot;,sans-serif}a{color:var(--blue);text-underline-offset:3px}button,input{font:inherit}button{cursor:pointer;border:1px solid var(--line);background:white;border-radius:8px;padding:7px 13px;color:var(--ink)}button:hover{background:var(--tint)}aside{position:fixed;width:245px;height:100vh;padding:27px 20px;background:#14263d;color:#d7e3f4;overflow:auto}aside .brand{font-weight:750;font-size:20px;color:white;line-height:1.5;margin-bottom:20px}aside a{display:block;color:#d7e3f4;text-decoration:none;padding:7px 10px;border-radius:6px;font-size:14px}aside a:hover{background:#264366}aside small{display:block;color:#9fb4cf;margin:16px 10px}main{margin-left:245px;max-width:1390px;padding:36px 46px 90px}header{background:linear-gradient(120deg,#15365c,#245e8c);border-radius:18px;color:white;padding:36px;margin-bottom:24px}header p{color:#e3edf9;margin:12px 0 0}h1{font-size:34px;line-height:1.45;margin:6px 0 16px}h2{font-size:26px;line-height:1.55;margin:0 0 18px}h3{font-size:20px;line-height:1.55;margin:28px 0 12px}h4{font-size:17px;margin:20px 0 8px}p{margin:10px 0}section{background:var(--paper);border:1px solid var(--line);border-radius:15px;padding:30px;margin:24px 0}small,.muted{color:var(--muted)}.eyebrow{font-size:13px;letter-spacing:2px;color:#bbd7f5}.tag{display:inline-block;background:var(--tint);color:#174a96;border-radius:30px;font-size:13px;padding:3px 12px;margin:3px 5px 3px 0}.callout{border-left:4px solid var(--blue);background:var(--tint);padding:14px 18px;margin:18px 0;border-radius:0 8px 8px 0}.warn{background:var(--amber);border-color:#c88815}.success{background:var(--green);border-color:#15875c}.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.card{border:1px solid var(--line);border-radius:11px;padding:18px;min-width:0}.card h3{margin-top:0}.tablewrap{overflow-x:auto}table{border-collapse:collapse;width:100%;margin:15px 0;font-size:14px}th,td{border:1px solid var(--line);padding:11px 12px;vertical-align:top;text-align:left}th{background:#edf2f9;font-weight:700}tr:nth-child(even) td{background:#fafbfd}code{font-family:Consolas,monospace;font-size:.92em;background:#edf2f8;padding:2px 5px;border-radius:4px;overflow-wrap:anywhere}pre{background:#13253b;color:#e2eaf4;padding:18px;border-radius:9px;white-space:pre-wrap;overflow-wrap:anywhere;font:14px/1.75 Consolas,monospace}pre code{background:none;padding:0;color:inherit}li{margin:7px 0}ul,ol{padding-left:24px}.formula{font:17px/1.9 Consolas,&quot;Microsoft YaHei&quot;,monospace;background:#f2f5fa;border:1px solid var(--line);padding:15px 20px;border-radius:8px;overflow-wrap:anywhere}details{border:1px solid var(--line);border-radius:9px;margin:12px 0;padding:13px 16px}summary{font-weight:700;cursor:pointer}details[open] summary{margin-bottom:12px;color:var(--blue)}.checkpoint label{display:block;padding:7px 0}.checkpoint input{width:17px;height:17px;margin-right:8px;accent-color:var(--blue)}.timer{display:flex;gap:10px;align-items:center;flex-wrap:wrap;border:1px solid var(--line);padding:14px;border-radius:10px}.clock{font:600 27px Consolas,monospace;min-width:95px}.flow{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:18px;background:#f3f6fb;border-radius:10px}.flow b{border:1px solid #c9d7e9;background:white;border-radius:8px;padding:9px 13px;font-size:14px}.flow span{color:#6786ad}.source{font-size:13px;color:var(--muted);margin-top:12px}.sources li{font-size:14px;overflow-wrap:anywhere}.key{font-weight:700;color:#145ea7}.question{font-size:18px}.search{width:100%;padding:12px;border:1px solid var(--line);border-radius:8px;margin:12px 0}.toplink{float:right;font-size:13px;font-weight:400}.progress{height:7px;background:#dfe7f2;border-radius:8px;margin:14px 0}.progress div{height:100%;background:#23865d;border-radius:8px;width:0}.printbtn{margin-top:16px}.links a{display:inline-block;border:1px solid #a6bee0;padding:10px 16px;border-radius:8px;background:white;margin:5px}.badge{font-size:12px;color:#855c10;background:#fff0cb;border-radius:5px;padding:3px 7px}footer{font-size:13px;color:var(--muted)}@media(max-width:1000px){aside{position:static;width:auto;height:auto;padding:18px}aside nav{display:flex;flex-wrap:wrap}aside .brand{margin:0}aside small{display:none}main{margin-left:0;padding:18px}.grid{grid-template-columns:1fr}h1{font-size:28px}section,header{padding:22px}}@media print{aside,.timer,.printbtn,.search,.toplink{display:none}main{margin:0;padding:0;max-width:none}body{background:white;font-size:11pt}section{border:none;border-radius:0;padding:0;break-before:page}header{background:white;color:black;padding:0}header p{color:#444}details{break-inside:avoid}h2,h3{break-after:avoid}a{color:#16456b}pre{color:black;background:#f1f1f1}.card{break-inside:avoid}}&#10;&#10;    .online-diagram{width:100%;height:850px;border:1px solid var(--line);border-radius:10px;background:white}&#10;    .online-map svg{display:block;width:100%;height:auto}&#10;    .diagram-fullscreen{margin:8px 0 14px}&#10;    @media(max-width:1000px){.online-diagram{height:700px}.online-map{overflow-x:auto}.online-map svg{min-width:960px}}&#10;    @media print{.online-diagram{height:680px}}&#10;    &lt;/style&gt;&lt;/head&gt;&lt;body&gt;&#10;&lt;aside&gt;&lt;div class=&quot;brand&quot;&gt;寒武纪 · AI Infra&lt;br&gt;&lt;span style=&quot;font-size:13px;font-weight:400&quot;&gt;2026.10.16 面试准备&lt;/span&gt;&lt;/div&gt;&lt;nav&gt;&lt;a href=&quot;/&quot; target=&quot;_top&quot;&gt;← Cortex CC 首页&lt;/a&gt;&lt;a href=&quot;#start&quot;&gt;00 · 怎么学&lt;/a&gt;&lt;a href=&quot;#map&quot;&gt;01 · 系统全景与两张图&lt;/a&gt;&lt;a href=&quot;#architecture-online&quot;&gt;↳ 推理架构图&lt;/a&gt;&lt;a href=&quot;#mindmap-online&quot;&gt;↳ 知识思维导图&lt;/a&gt;&lt;a href=&quot;#core&quot;&gt;02 · 推理加速核心知识&lt;/a&gt;&lt;a href=&quot;#parallel&quot;&gt;03 · 并行与通信&lt;/a&gt;&lt;a href=&quot;#sglang&quot;&gt;04 · SGLang 30 分钟&lt;/a&gt;&lt;a href=&quot;#vllm&quot;&gt;05 · vLLM 30 分钟&lt;/a&gt;&lt;a href=&quot;#resume&quot;&gt;06 · 简历逐条补课&lt;/a&gt;&lt;a href=&quot;#training&quot;&gt;07 · 训练与 MLU 适配&lt;/a&gt;&lt;a href=&quot;#design&quot;&gt;08 · 系统设计与压测&lt;/a&gt;&lt;a href=&quot;#quiz&quot;&gt;09 · 自测与口述卡&lt;/a&gt;&lt;a href=&quot;#sources&quot;&gt;10 · 来源与事实边界&lt;/a&gt;&lt;/nav&gt;&lt;small&gt;在线学习材料&lt;br&gt;按推理部署方向简历定制&lt;br&gt;学习勾选只保存在此浏览器&lt;/small&gt;&lt;/aside&gt;&#10;&lt;main&gt;&lt;header&gt;&lt;div class=&quot;eyebrow&quot;&gt;INTERVIEW FIELD GUIDE / AI INFRA&lt;/div&gt;&lt;h1&gt;把推理加速讲成一套系统&lt;/h1&gt;&lt;p&gt;从请求、调度、KV Cache、算子到芯片；从指标、瓶颈、改动到验证。&lt;/p&gt;&lt;p&gt;陈城 · 推理部署方向简历 · 2026 年 10 月 14 日编制&lt;/p&gt;&lt;/header&gt;&#10;&#10;&lt;section id=&quot;start&quot;&gt;&lt;h2&gt;00 · 先抓住这场面试的主线&lt;/h2&gt;&#10;&lt;p&gt;&lt;b&gt;本地已核实：&lt;/b&gt;岗位是“大模型训练优化工程师-27届”，线上专业面试，&lt;b&gt;10 月 16 日周五 11:00&lt;/b&gt;，邮件给定约 1 小时、双机位。投递记录注明实际使用“大模型推理部署方向 PDF”。准备以你的推理优化项目为主，同时补齐训练系统基础。未找到完整 JD 正文，不把推测写成招聘要求。&lt;/p&gt;&#10;&lt;div class=&quot;callout&quot;&gt;&lt;b&gt;回答所有优化题的固定顺序：&lt;/b&gt;业务负载与目标 → 测量瓶颈 → 解释机制 → 选择改动 → 对照验证 → 代价与适用边界。&lt;br&gt;每个术语都要能回答：它减少了什么工作？节约了什么资源？又增加了什么成本？&lt;/div&gt;&#10;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;顺序&lt;/th&gt;&lt;th&gt;时间&lt;/th&gt;&lt;th&gt;学习内容&lt;/th&gt;&lt;th&gt;必须交出的口述结果&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;40 分钟&lt;/td&gt;&lt;td&gt;架构图、核心知识、并行通信&lt;/td&gt;&lt;td&gt;画出一次请求链路；解释三个不同层面的“Attention 优化”&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;30 分钟&lt;/td&gt;&lt;td&gt;SGLang 专节&lt;/td&gt;&lt;td&gt;讲清 Scheduler、RadixCache、ModelRunner 的分工&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;30 分钟&lt;/td&gt;&lt;td&gt;vLLM 专节&lt;/td&gt;&lt;td&gt;讲清 V1 EngineCore、调度预算、分页 KV 与前缀复用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;60 分钟&lt;/td&gt;&lt;td&gt;简历逐条补课&lt;/td&gt;&lt;td&gt;死锁修复 3 分钟；量化权衡 2 分钟；指标口径 1 分钟&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;25 分钟&lt;/td&gt;&lt;td&gt;训练基础与寒武纪适配&lt;/td&gt;&lt;td&gt;训练显存拆解；ZeRO/FSDP；从 CUDA 迁移到 MLU 的步骤&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;25 分钟&lt;/td&gt;&lt;td&gt;系统设计与抽题口述&lt;/td&gt;&lt;td&gt;不用笔记回答 8 个 P0 问题&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;p&gt;总计 &lt;b&gt;3 小时 30 分钟&lt;/b&gt;，可分两次学。两段框架课严格各 30 分钟，以阅读和推演为主；环境安装、下载模型、完整压测不计入，也不假装能在 30 分钟内完成。周五只用 20 分钟回忆口述卡，10:50 前按原邮件准备双机位。&lt;/p&gt;&#10;&lt;p&gt;&lt;span class=&quot;tag&quot;&gt;P0 必须能解释并举项目例子&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;P1 能分析取舍&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;P2 有余力再读源码细节&lt;/span&gt;&lt;/p&gt;&#10;&lt;div class=&quot;checkpoint&quot;&gt;&lt;label&gt;&lt;input type=&quot;checkbox&quot; data-check=&quot;map&quot;&gt;能画请求链路并指出五类瓶颈&lt;/label&gt;&lt;label&gt;&lt;input type=&quot;checkbox&quot; data-check=&quot;sg&quot;&gt;完成 SGLang 30 分钟并通过自测&lt;/label&gt;&lt;label&gt;&lt;input type=&quot;checkbox&quot; data-check=&quot;vl&quot;&gt;完成 vLLM 30 分钟并通过自测&lt;/label&gt;&lt;label&gt;&lt;input type=&quot;checkbox&quot; data-check=&quot;resume&quot;&gt;能解释简历中每个数字的口径和证据边界&lt;/label&gt;&lt;label&gt;&lt;input type=&quot;checkbox&quot; data-check=&quot;train&quot;&gt;能解释训练显存与通信，以及 MLU 迁移方案&lt;/label&gt;&lt;label&gt;&lt;input type=&quot;checkbox&quot; data-check=&quot;mock&quot;&gt;完成一次 25 分钟无笔记口述&lt;/label&gt;&lt;/div&gt;&lt;div class=&quot;progress&quot;&gt;&lt;div id=&quot;progressbar&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;small id=&quot;progresslabel&quot;&gt;0 / 6 项已勾选&lt;/small&gt;&lt;br&gt;&lt;button class=&quot;printbtn&quot; onclick=&quot;printAll()&quot;&gt;展开答案并打印 / 保存 PDF&lt;/button&gt;&#10;&lt;/section&gt;&#10;&#10;&lt;section id=&quot;map&quot;&gt;&lt;h2&gt;01 · AI Infra 的系统全景&lt;/h2&gt;&lt;p&gt;&lt;b&gt;AI Infra 的目标：&lt;/b&gt;让模型在数据、训练、评估、发布、在线服务这一生命周期中，可靠地使用计算、存储和网络资源，并在质量与延迟约束下控制成本。推理引擎是其中一层。&lt;/p&gt;&#10;&lt;div class=&quot;links&quot;&gt;&lt;a href=&quot;#architecture-online&quot;&gt;打开可缩放的推理服务架构图 ↗&lt;/a&gt;&lt;a href=&quot;#mindmap-online&quot;&gt;打开可点击的系统知识思维导图 ↗&lt;/a&gt;&lt;/div&gt;&#10;&lt;div class=&quot;flow&quot;&gt;&lt;b&gt;数据与版本&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;训练 / 后训练&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;评估与模型制品&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;部署与推理引擎&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;监控、回归与迭代&lt;/b&gt;&lt;/div&gt;&#10;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;层次&lt;/th&gt;&lt;th&gt;你要会问的问题&lt;/th&gt;&lt;th&gt;关键知识&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;负载与服务目标&lt;/td&gt;&lt;td&gt;谁在请求？长短输入输出、并发、突发、共享前缀是什么？&lt;/td&gt;&lt;td&gt;SLO、TTFT、ITL、吞吐、Goodput、成本/有效输出 token&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;模型与数据&lt;/td&gt;&lt;td&gt;模型结构如何决定计算量和 KV 规模？质量下降能接受多少？&lt;/td&gt;&lt;td&gt;Transformer、GQA、MoE、量化、蒸馏、数据版本与评估集&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;训练系统&lt;/td&gt;&lt;td&gt;模型状态还是激活占显存？通信能否与计算重叠？&lt;/td&gt;&lt;td&gt;DDP、TP/PP、ZeRO/FSDP、混合精度、检查点、数据加载&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;推理运行时 &lt;b&gt;P0&lt;/b&gt;&lt;/td&gt;&lt;td&gt;谁决定每一步执行哪些 token？如何管理缓存和请求生命周期？&lt;/td&gt;&lt;td&gt;连续批处理、分块预填充、分页、前缀缓存、抢占、取消与回收&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;算子与硬件 &lt;b&gt;P0&lt;/b&gt;&lt;/td&gt;&lt;td&gt;瓶颈是计算、访存、通信还是 CPU launch？&lt;/td&gt;&lt;td&gt;GEMM、Attention、融合、图执行、设备编程、显存带宽、拓扑&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;平台与可靠性&lt;/td&gt;&lt;td&gt;服务变慢、OOM 或节点失效时怎么定位和恢复？&lt;/td&gt;&lt;td&gt;容器、资源调度、观测、负载均衡、灰度、回滚、超时、背压&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;p&gt;&lt;b&gt;一次请求：&lt;/b&gt;HTTP → 鉴权/限流/路由 → tokenize（VLM 还需图像预处理和编码）→ 等待队列 → 缓存命中与 KV 分配 → prefill → 采样第一个 token → 多轮 decode → detokenize/流式返回 → 完成或取消 → 释放引用、回收可用块。前缀缓存可能保留可复用块，但不应保留失效的“正在使用”引用。&lt;/p&gt;&#10;&lt;p class=&quot;source&quot;&gt;图示是用于面试解释的概念架构，不是寒武纪内部架构。框架进程分工参考 &lt;a href=&quot;https://docs.vllm.ai/en/latest/design/arch_overview/&quot;&gt;vLLM 架构文档&lt;/a&gt; 与 &lt;a href=&quot;https://github.com/sgl-project/sglang/tree/main/python/sglang/srt&quot;&gt;SGLang 官方源码&lt;/a&gt;。&lt;/p&gt;&lt;/section&gt;&#10;&#10;&#10;    &lt;section id=&quot;architecture-online&quot;&gt;&lt;h2&gt;推理服务架构图&lt;/h2&gt;&lt;p&gt;可缩放、搜索和导出。全屏后阅读更方便；退出全屏返回手册。&lt;/p&gt;&lt;button class=&quot;diagram-fullscreen&quot; onclick=&quot;document.querySelector(&#x27;#architecture-frame&#x27;).requestFullscreen()&quot;&gt;全屏查看架构图&lt;/button&gt;&lt;iframe id=&quot;architecture-frame&quot; class=&quot;online-diagram&quot; title=&quot;AI 推理服务架构图&quot; loading=&quot;lazy&quot; allow=&quot;fullscreen&quot; srcdoc=&quot;&amp;lt;!DOCTYPE html&amp;gt;&#10;&amp;lt;html lang=&amp;quot;zh-CN&amp;quot; data-theme=&amp;quot;dark&amp;quot; data-preset=&amp;quot;classic&amp;quot;&amp;gt;&#10;&amp;lt;head&amp;gt;&#10;  &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&#10;  &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&amp;gt;&#10;  &amp;lt;meta name=&amp;quot;generator&amp;quot; content=&amp;quot;archify 2.17.0-dev.1&amp;quot;&amp;gt;&#10;  &amp;lt;title&amp;gt;AI 推理服务：从请求到芯片&amp;lt;/title&amp;gt;&#10;  &amp;lt;script&amp;gt;&#10;    // Resolve the theme before first paint so light-preference users don&amp;#x27;t&#10;    // see a dark flash. The toolbar script below re-applies with UI state.&#10;    (function () {&#10;      try {&#10;        var theme = null;&#10;        try {&#10;          var param = new URLSearchParams(window.location.search).get(&amp;#x27;theme&amp;#x27;);&#10;          if (param === &amp;#x27;light&amp;#x27; || param === &amp;#x27;dark&amp;#x27;) theme = param;&#10;          if (new URLSearchParams(window.location.search).get(&amp;#x27;embed&amp;#x27;) === &amp;#x27;1&amp;#x27;) {&#10;            document.documentElement.setAttribute(&amp;#x27;data-embed&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          }&#10;          if (new URLSearchParams(window.location.search).get(&amp;#x27;present&amp;#x27;) === &amp;#x27;1&amp;#x27;) {&#10;            document.documentElement.setAttribute(&amp;#x27;data-present&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          }&#10;        } catch (_) {}&#10;        if (!theme) {&#10;          try { theme = localStorage.getItem(&amp;#x27;archify-theme&amp;#x27;); } catch (_) {}&#10;        }&#10;        if (theme !== &amp;#x27;light&amp;#x27; &amp;amp;&amp;amp; theme !== &amp;#x27;dark&amp;#x27;) {&#10;          theme = window.matchMedia(&amp;#x27;(prefers-color-scheme: light)&amp;#x27;).matches ? &amp;#x27;light&amp;#x27; : &amp;#x27;dark&amp;#x27;;&#10;        }&#10;        document.documentElement.setAttribute(&amp;#x27;data-theme&amp;#x27;, theme);&#10;      } catch (_) {}&#10;    })();&#10;  &amp;lt;/script&amp;gt;&#10;  &amp;lt;style id=&amp;quot;archify-fonts&amp;quot;&amp;gt;&#10;/*&#10;JetBrains Mono variable WOFF2 subsets from Google Fonts service revision v24.&#10;These fixed bytes are shared by the viewer and its SVG/raster exports.&#10;No local() source: an installed copy must not override the bundled font.&#10;Uncovered characters (including CJK) still use the system fallback stack.&#10;Upstream: https://github.com/JetBrains/JetBrainsMono&#10;&#10;cyrillic-ext    1664 bytes  sha256 9343de2ca5d9549f792e7962375af8efb0f320c7643bfd36c884b5a30e5c396f&#10;cyrillic        8892 bytes  sha256 4995a9a43ac659ec32fcd8b463755cd6a07b31a6e6b3894a6a153b661cf490e2&#10;greek           6800 bytes  sha256 49c3da6c9a2b279b0f1f860f5cfb1f5dc38d88a5c7be9c9b1837bbc4e3db6111&#10;vietnamese      5872 bytes  sha256 d44eb1936043a56038eb02dd70b243f379bef65783f94ec12f277550720411f1&#10;latin-ext      11596 bytes  sha256 9c38cb2d0d2d93c1ee6e21fa78db76f13ea7e15e15cc64214c7ca89b6aaa35c4&#10;latin          31340 bytes  sha256 2c32b9b3ee358c119e210f6f5195f9bd34894d78a785ff2e95d60e718e400af4&#10;&#10;Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)&#10;&#10;This Font Software is licensed under the SIL Open Font License, Version 1.1.&#10;This license is copied below, and is also available with a FAQ at:&#10;https://openfontlicense.org&#10;&#10;&#10;-----------------------------------------------------------&#10;SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007&#10;-----------------------------------------------------------&#10;&#10;PREAMBLE&#10;The goals of the Open Font License (OFL) are to stimulate worldwide&#10;development of collaborative font projects, to support the font creation&#10;efforts of academic and linguistic communities, and to provide a free and&#10;open framework in which fonts may be shared and improved in partnership&#10;with others.&#10;&#10;The OFL allows the licensed fonts to be used, studied, modified and&#10;redistributed freely as long as they are not sold by themselves. The&#10;fonts, including any derivative works, can be bundled, embedded,&#10;redistributed and/or sold with any software provided that any reserved&#10;names are not used by derivative works. The fonts and derivatives,&#10;however, cannot be released under any other type of license. The&#10;requirement for fonts to remain under this license does not apply&#10;to any document created using the fonts or their derivatives.&#10;&#10;DEFINITIONS&#10;&amp;quot;Font Software&amp;quot; refers to the set of files released by the Copyright&#10;Holder(s) under this license and clearly marked as such. This may&#10;include source files, build scripts and documentation.&#10;&#10;&amp;quot;Reserved Font Name&amp;quot; refers to any names specified as such after the&#10;copyright statement(s).&#10;&#10;&amp;quot;Original Version&amp;quot; refers to the collection of Font Software components as&#10;distributed by the Copyright Holder(s).&#10;&#10;&amp;quot;Modified Version&amp;quot; refers to any derivative made by adding to, deleting,&#10;or substituting -- in part or in whole -- any of the components of the&#10;Original Version, by changing formats or by porting the Font Software to a&#10;new environment.&#10;&#10;&amp;quot;Author&amp;quot; refers to any designer, engineer, programmer, technical&#10;writer or other person who contributed to the Font Software.&#10;&#10;PERMISSION &amp;amp; CONDITIONS&#10;Permission is hereby granted, free of charge, to any person obtaining&#10;a copy of the Font Software, to use, study, copy, merge, embed, modify,&#10;redistribute, and sell modified and unmodified copies of the Font&#10;Software, subject to the following conditions:&#10;&#10;1) Neither the Font Software nor any of its individual components,&#10;in Original or Modified Versions, may be sold by itself.&#10;&#10;2) Original or Modified Versions of the Font Software may be bundled,&#10;redistributed and/or sold with any software, provided that each copy&#10;contains the above copyright notice and this license. These can be&#10;included either as stand-alone text files, human-readable headers or&#10;in the appropriate machine-readable metadata fields within text or&#10;binary files as long as those fields can be easily viewed by the user.&#10;&#10;3) No Modified Version of the Font Software may use the Reserved Font&#10;Name(s) unless explicit written permission is granted by the corresponding&#10;Copyright Holder. This restriction only applies to the primary font name as&#10;presented to the users.&#10;&#10;4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font&#10;Software shall not be used to promote, endorse or advertise any&#10;Modified Version, except to acknowledge the contribution(s) of the&#10;Copyright Holder(s) and the Author(s) or with their explicit written&#10;permission.&#10;&#10;5) The Font Software, modified or unmodified, in part or in whole,&#10;must be distributed entirely under this license, and must not be&#10;distributed under any other license. The requirement for fonts to&#10;remain under this license does not apply to any document created&#10;using the Font Software.&#10;&#10;TERMINATION&#10;This license becomes null and void if any of the above conditions are&#10;not met.&#10;&#10;DISCLAIMER&#10;THE FONT SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND,&#10;EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF&#10;MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT&#10;OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE&#10;COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,&#10;INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL&#10;DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING&#10;FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM&#10;OTHER DEALINGS IN THE FONT SOFTWARE.&#10;*/&#10;    /* cyrillic-ext */&#10;    @font-face { font-family: &amp;#x27;JetBrains Mono&amp;#x27;; font-style: normal; font-weight: 400 800; font-display: swap;&#10;      src: url(data:font/woff2;base64,d09GMgABAAAAAAaAABIAAAAADMwAAAYdAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhwoBmA/U1RBVIEgJx4AdC9MEQgKhGSEAAsgADCDOgE2AiQDOgQgBYdGB4EUGw8LIxEmZHIexT8PYyJTH6s540K0vrtCWaIRpUzRCqKVgSh/33L3iSgiBkN7EeGRTTw85UW9X5WkwZF7tJBx0g3Cac+S8lfO/UPNN4h5WrZiW1TT4nbixDB3vt1UJciEG0hoUc5XuE5OKAqYvtaSRANO3rv/tVb/oBJpOuAlQEikTDqxv3uuFVOLvC6aVeM2NBS8cplGyFpZ1RkosWs55KTlc8eza3siAl1ACKUQAiHQNt10sd4GuaWgrYCaBYG2BSwg+XhrehjdJgND8D69SDvFvJJ0SaoENkV7xx5CYy2QaJlypoYnsMkAPC/FV/nf/18l/xv+I3HLBzdAWiC9jZFSCE0J41WYJ514oKBNBfgC5g2oGAkHKYX4m64rCymGIJCRooirSE8jQTTyiPQ9eWRhKi992skqVhXL+JV4UY6QEupjD/kvCxDK5z0YGrfsUuYfjQABEjLGywLjFfYCxhrKkp6RtW15IVJxX/GqZtFR9xYv+VOTr9mDrLim6l1byfqVJkoNXD8wlMSObPvNzPMA8Z3LC1Fgye9EyU1t3ajeKV/0ouFvFf28Uc0aAFTMxI2vwyuYB/LI0nGFPCarIoFtH26NnJutwaDVGtvSGVcYdspesU+v3O/QbmfPzu7tHdrb7drZ4XZNXOZIT22Xzs43p62V1+jtlPa+RKF29nemThriq+VTHyptQ6/tohdnqz1JbrycqAhyXp5FwA7W7VX2SKwGSG1E8pK76a3obHdqBHfonTUF3dXlucvtvs1Ut/Riq65Z+8UuZplnbnU/fatmyRfuLTahevtXfMialNlPz9X/YX3InZN1V/ntv2xl9fH+Gb86qqYJLNra50g5J2upIRzN0xyo0D3qQtfKj1t9XaT8rESJ6ybu9LkNJawTt6qkiGNea49QPzW14hy0e31NVBe27G5oFYUxg8LWJGts5vWrF0paN+m3r3OTKE3cKtUl/f/Q7mGP2k5J586AC0sfsZ/fJqmhuexCb91FDp6iZVMw9iWPzIoCKsOr9vYZLLghRbwLVBcQqPRmiqA+W6WAF7VYHpYhLZAfRTC38fLpba1zkz3/fkJgOQOwAphoujlWtLr9iCy7Y75/D3hxLRCa5o4YDnxx12XKnZdW8xwffa+T/9X0zlV0njyBweD9owcOHTh2n2FAHud8JQFzrt7/+PFb/z9+gWrZar9mPtORGfJlWLMw08XUJbNw2BcFN+w8BazvOcvp4+Mp5iNjx1grXfjjDbHQaFsg8w865aWZ4azb//nbiNW3z4b6lWXDvMxevjRbMMxufnvrnJ7/1lsG0vtsanX9+SbPe/OT9sQyyFJH9kETE422CTL/oF3y9OVK9Wbrjx9/R6z//fyuo5Ut5m+n812WtPPX1f3j+dVpxvMf596UQ+OTJw8cE9QsU6n8/++JyywnhmlHJyTGRcv8uMT4qDEJzQr540cu0xiSTHmWWpVIKad0lsb3l+Z/vrOp/vwBvcnwHyCQVlAf85sVNRjFf9NWy18C3rm8vQl45/bFz16aW+emiPwoKgkEn2Z12skn6P/wOYSJ9u20WvUMBf5uUN0zHgEAfC7Aq05gYJ5slpyeTTp6nK8bR9HC08mZwDA9FZj043fMVosnsbBYXIGlqXEcVhaJTRL7VojxmYJuNLHQj9+x1PUvVpp+xYaxPsaO5dyLXcs4DXuWsAX2rWQiDnS1/+ZQG9sgpGgyWdrQJIS4smFtkrWgCcm0ykPIEFb5AOvr0ua5EZIREk3sruRYNoeLhRBqJ+XBNpRfUAk5TouzilHr9FBRXohPoA3witRyrWIt+TU8FlcLIbk2rQIdS0gi0JFa8AXZUrrcE7Z9rvxyWEuqjyJknC1jCctY2tKFyllm49ySS1ct2WTYJedoTXV87+YpCLluLW8kODW7FLCMbEcD7sTpLVtpQfkiGDeJbW3tb20lWvzntJB3tx1I6Gdpx+lWty9CKmivAQbdPJ+PZMptjYUi3PMA87wcyWqRo4gyqmjI0YxWtKNTrb1PC+7AWu1HCIOXWzsNhawfzSf908vHlAfuLZXShddLrR2c1t3GkN63vQ3/MIvgz1kYfbtt2aVWaAAAAAA=) format(&amp;#x27;woff2&amp;#x27;);&#10;      unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; }&#10;    /* cyrillic */&#10;    @font-face { font-family: &amp;#x27;JetBrains Mono&amp;#x27;; font-style: normal; font-weight: 400 800; font-display: swap;&#10;      src: url(data:font/woff2;base64,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) format(&amp;#x27;woff2&amp;#x27;);&#10;      unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }&#10;    /* greek */&#10;    @font-face { font-family: &amp;#x27;JetBrains Mono&amp;#x27;; font-style: normal; font-weight: 400 800; font-display: swap;&#10;      src: url(data:font/woff2;base64,d09GMgABAAAAABqQABIAAAAANggAABopAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGnwbHhyBWgZgP1NUQVSBICceAIFiL0wRCAqrfKMTC4FmADCgXAE2AiQDg0QEIAWHRgeHQRt7L1UHctg4AONHDw/J/98StCEx8OvQuaoS6nSKOb1TAFiw0Fg4OrHmUFx9lE0RHuCAwNZTYLzu0qIYrA2BIRRRhOaLtZ08a/sp9zYCdQA8KAuMM8JgShJLBIph0a9CVKNU5Kz3C6kz9f9u+04Z3maEJLM+PW3a+3+XBRaLKxEnQkSEEoEu1rSppBKruKauuYp7ciJWOcmUo7nhJS8iHiFtjmq7+WH3ih3OVZkJbJviPSALIQK9R2ufHSCVMDwf3t6dTUbxJMCBZZzEHGDq/dW5+BuhCCwAyNGp7Qbfqz4neKAyTZqkGLqcOXD2yAf6S9CXBKjiYHe7/6RBBJEETaIBSYQfAEpOU/IgUnwldDH6e5eQmMaEF7GNOjhvxlN4rPb8O1d9ZTAkFFEhK06K6oYYy9vXX9FcKceGqruiyWE2JCclRgHFyIg66EQRUWcsdUzg/vg/XWk7f2d14NAqqA3ePkfv6RIuurMrd3UqjTRrwUg5rbL7vDodg9Y+ExzrQgidzOugHCAuSqIOqEyXok1RVKmsstSQWe1WWYkPCB2v22Tun9a18LCMh7GGEmM6XPw5a4EAkANqUzghYDwPnpH3EcgHC+HV1Hy4cD5SFB8jho+XzGulG7k3nqCAJyjlCap5At3xCRr0RWDiCSxAMgAPn2dCCl+VdZCABQC7HQBgbrxidHmvu3FUC5SwCxOQ6poAHfAe0QaloTJaGWDAQSf/xZSacW2eDz4yws0e48wXgakYTRmcfIB1YrQBABIopChcNDhxSYyuFQkBLWkYEOfEiH46rVhq7LKIALoAY4AKU0Ks0VTuMAWkyBeci7es/AJwGQrmlb3Lc4DphegAkC3/VwBV054AAUQglOdSAC6bC0HHfoaMIgB+IKiaqDY3RJ1c0XzIqYqUOACyBkixZFk1PQ80AyJmAtBvcq01mxzEpcY2TadE5E01uYqNGl6eWHUBxFlRdDkvwCoOnHc8Qp8o0oKnMPAZENNn8ZCLEXD3WCjk78+zFVcIZUY7xQUucpnb3GeXd3zkq7MDCKNg1uaWuNwd7vcj72Y7IyjK5bt5eUemqvc7oHdv9ub2zrGJ+RcLgrzKRZMfGCxcf1St2sUbIIFGomQp6mmlMjGzqGVUx6CvBoI0BIADCsKO8eFBy0im8g6CgLBNApERkSpqo5xwIekkCiIGu0Q56bBHNWIdBnyzeRuIlgVic0C60JQ8zYDaSR0me6BaVZsihtnzAjUTzCIy0mZ0ndVjc+2+CFPkLJwWCwGKnhBJc01RbKponrUcQ3xFlmEkUmepVC5RCl8nJ6VCKvFQ8XXRScE1AZ5XKFh2x1GxLKp8Iqci3JRuLs5eDvEBbkZWBaVXjMtxAz2UKlepR6xbn9xJzrIlIYHBxrcMDc4lHRT5NKzzVrbmJ/zI5Ml2clsFATKRG6KH58X8xmxb/ETWNKnEi1mJc0GHjAI59LSCo5OiguksFii5rWQpm/XVwm8ie9xZem6I/Q1gp2pK/I1abEITR5Ss19NLEoO76Wx09wvmZNKVNVXSw/OGpmMb8QOAYU9pD5sV4kxzv6ml4HFn6ro29zZQiJisz9xWJR51jr3UvNNN+d6mPmq+y1f8W0GXFeSQJAKZ8Uj0r8nP1NIjgGwjm28qPTfU/iavBDGTrMspK+0JYjONRSmPSRxEF0rKO7LGjw2tUT3knQ3TlKH6Y5XFdvJaBwFGNrdlSWMmBj1xE5tpM6nOcx/j9qJIhkuDeV1spps0ot+0oPB8rgMJIsqOQKV3N0zzQ3V2d+6HwBAdFrHnTO9PaPgz84cgK35rIKzTrwqvJk6i3nopC/XZBflAofAzhJVgLJnfCQ1jbvzldHZqrr3BZ/4KBvv21tV9cmGF8b4UIGg19Piga95n0h9qnnje+IdOFjoM/Pp8IfclGMivV/xKw0GoVWZMeujlo497y7bCxwlNQ0SsMvqH511Qr11f3UjTLZ5RoKxnfn5SvqQppumAUNAVWIdYQtc/2tsG3/nF5shtVeBjHOe4ejr8wC668QvNTa7106oNf0Tq+S2dl4wXjNIYguaICF1TQVF8gjrTrrYNme6SvKgeBo/sbqDWybhnp0d9QUN4beOFQ7jmIRlavgwsle5NI0W0+0WPUaWQ55EIF914AeoD+zzGEdRfgp0FgjTcdkKXBuulJjfQyKjucsrxdrXWqUfpOtAHWz1Mj6CIeIe3cT9spO5Tq6xQS73Js8KyNdNJjl/68DBgmK+eqolt7QYb+rqJfVUuwHxE2LCpSgETT029ZWyhZ+dbloQAVP+PSg8AzYXu8ee7TXGPfXqJyFOc1n5hj/UzZ8oH/h/WPY9Wt61qx5alc0tKY5bVxYTqEMdtP6Idr5ukppispDLqwcJumSGOo0jeA5p6dlYqPgrvs3RAhf4dvULqV6nCfXO6r3Ro1p+fslo/J3Ng1j8Xab2rU/vfab04YfB1fZoroLJnTMXXR2bHk/+Wlfw0pscojR7UKh3FD9Xu6vm7e+awQeIOUXvCMAg94z5r8xhYSnUhlxi26U/b3AeUC70EK6T51mjMoxkWcxuT1UhcmqUxbwVagpjhDC4aoKxqGdHA3POzPiDB+4zynfp118+Onnx2RnEKYTMJz8b/83/0P+lvzwdLn7TfHDxk6+vTFguZxUd1vBpws/HJ2MEHP9fiVmQXHTX5B9gdP77tLos6/dTd/aPTp0dZwsrjUC+kgnrlyqpctQKixPm2aMKj5+QnuWeT1Uhcem5ekrcCLUJKyTm5RQOUmZaxEyBSamvf2vUsD6u6IBId3+N0d2wFv59aZN637SqfeDLzrDHt9rkcWnr2VWpOgtez8S1h3g82Vj8PE9nxmKN+lZfg2Qls1kwcZBukX+VoHCuuvVvVs9+Hll6M+inirm384uLzET9F3c9Vg0a19bF1y1eDT4vO+Tdf+cZWx8QfvgnfXRsnGNz49hPjfw/UnaDD/Rr9w3prW2gNL+LI2LL9ABNUZRfj4qiZqz+tP3UQt7NUf7ACtHo0A02rfKqLS/Z3/N7k8UscTCkBup/TJjq1zrLnbaGf1H1DnChUx7seMd3Zog79Qp2byjh/ZULTu4k6JpvKLdTYMdwK3bOW8GhKmoXNFIS5iGdJ9pe8dDMYdqzGN7g7lGwkW57tBO6IxtdDJq219vlX22y9il5MqRPHb7AWWxvGT8TF9KK8iAx8QXYhFSVFIxfkfs6A6djd7ETHixHiL09UFITqW14psqYQ5/oJevxxbmKmYcqyTlGgsFzEBif/r9VSKoMP9fGroeY9vT3XTgkESGi5d/Conq3+3x+H8TpH020J0tRTxmm+/qoxKjv9gxfVODK/yVF5zVpJ09ZJ0hrbCMzXXg2PeDW4IBBYoL0aEf5qUAEo4uLsTfU0JtQYyK78kBAOaNWFMFbqFS+39T02QjP76D6eC/+O3V3YF88vXdQXDYcfGWK7orUMFJwIcqbBdN7ZtadcYJUrhb2HnAqKy9jUWeG14ZPLi6RBRbKZgmxmTfIppgE+MKutDRMW0rxpVLtrWoutmRATXiQG8e7EeUiSoqLckykXxColWf7D8ulR1QpsiS9ZtMQIS8/qg04Naph7oh6alz5lD/bjuuuRq6/52c/v66tHr4b5WI/QBBUqiIjC1dZqb0OfE/ojsTiQTGgaw+8GfVhS6NLxZ2U34Mb+leuTq6O8rVpiWkcorYhCOovalXYyRxQlR5ItXp9ua/fBzcCdrRT8YuDml8IrXc24nM8vyy6YWgOWYx45MduNEGpHoha5OifSLkRFrZTGEyf2m7R19PtoYNLoH5CdbQDDg2Usye1EGfGDXA1anCaKkDF8Vk6+Cv3O1/BX79gEDLfWyLW5z3Qjx2sTjtXYZl4oGWNimm2pTFm8igteNzC9pDpraHfqn+ivFeQohyqAHjveb1jPdaoOooby/nCdU888aFE33bmT/S+DGejBSHtkCJBrDGoGfL/084zSQAoZfjXdO3GvNNOoFwbR3WpVS7c/578oHibz85OF3SstRUQlr7F1V5pr7xZuwcyUnOIsLquYzjvmodnc78LGloWouhE3Kz/2aIj2jSsN/vTFyMrLEpw+fYmoob4XGvZArX4QFnoPO7fUpMyYnoJ905XD0gI7AwP2B7hkIvJIsjNq/TzfQF+/IF/fIL8m/H/1WsHzTXi7UVHw7FtZpy+01FCTVxJmD1+mCivJk0Y8m6V/g75I026x5myBwyZVP51hRp+xiF+EqkEAcBixdFULucIEs9gFi7AD5rAYS7AU81iGXbEcK7AKu7lKOAWPATHaEtGQFOX+pMZh1N0YzYnxzclwxFRIXBy7FQT4HIZPK6N8Du4GdsaO4CSvZpSAvRLno1ZN1x2K27HTAq1rj2E0WF1HS68SRzI7MZO55kkB2SRESTn0RxQaD+HQzy8mHn77+HymOc3Y8kuqDoAGqJo5aaZpTyzgBC3gDk0ggXqLgVST/1FzFfm9OmaIh0qQgwAfjmvMO0C/ibVA/oOCGrQ1gfTjBFfT5LVT8j1BDEU4lsWr6ltsScw9yP/wu9WFnb+ZGLImADSMUsr70YjU0NgYTNUuCaLr8w8MjYWQd/2gyVKdSgppUjOOI05qzYKSHtWc1JqFRQRpcwRKRpd/cffNqbRZvpuwZGr3q+Pvt/frdOKx65HHZi0m9/x+rBQEAJny/0HsA/TuKrjxEaSCoNk4C3AAV/A9AZGTSJJDqju6i7u5+3qi3/Qd9CKlEupLg2kEjaN9sTGQcUxhFivpZAu7OM1FrnOXx/xJnRkvJpAJZ+KYFCaLKbRcnSNc5TVfj5jNYBtn4uyY03Nxnszv85ZHiOJEpdux6/b6dm+Cd4xwHBc0uJ4zc/25IVwLN4qbwE3j5nJd3CnuAvc5y7l/xSqx2xCfIUH7jz1mSOKQCnEfcbO4XTxDvEC8QtyV63pagAPEowB+bT1GrBUjvWzOdIhD6raZTFEAgrz97+crP9+QRDhA5/BidhXd9DwiFgoUELSDuIgMcGveIt9Ls4McxbIheGS7Wbyk7p4vc10j6QqubI7cQbU/OEh43Q/H7dIyKgq3czCgauO/XWp/9xWb9efGAeBr+RLbpDZjabJPgEK2xW+KRjAEfC4DMpMZoovw5BdXiO3PBhPIg26zedEQlhUICqAoz2FwshwtSQGHB8tuXf/jeYPS/39rNeR3HyTy2tPmbBisuZHb6M/7c4vzc2bzaGFh5vWfKNBbGpBlom2Wx5fYw2ouWXTqltnT1zttLTPZ/347tHM3HC71pf36qspa1R3iYXQGc5DG+3SThNGYXqtFsC8bczSbRrOWTk6mphjNUT9jSDUlMxUkNOQqPB4AVEPyMsKvrXkT5q54vrW21jJ+s6JIAMO2Nt5ZIb/LQoKtST8aCQvd6t5qQ6mPA5GqpI/YPEYOuv4xymOLe8O8EA4dFxVWgjiePHriaPK4QEAQH2YynzKZ96yA36FPlquj7R2CsC+fYCx7DJXS+6WBaOx66cxlFi4ECLbY/NxLr/CiC9Pg08nMuiJOrqbRqCEXJJAJOojxJm2QJB4bsXuXQ2r3us6MVpw7rWeny+Qks+uoGQypHY+ZlAcN9CJgyQtAvOCDQkJklF/UxB5rgexNmtEcosEnsjUi4qEnq8ZhNOxg9y3Ni4Y7cxGdzHnlJQh5XcYq3+gcHkvDNJjWI6KOfKazUaENPS3FiK7XykVWVfQMigZD+PHDQRRttVzoXMvjQlLVnncLPNaIID8Y9pZ1frg3BE5qNh5bWcnqu0GIHzQOH+o7enY3JKZ2lKpGo5533DlOcjUEVcFgnR6gS/98Fqon8s+E1tVmvzDIXAeTyc+f8Z3ESW9+Onv6liSQRAIRbt9HcYZRFJDit4nKNC1H+uTdAWv5yEOXW1yUb70S6d2vZ3npz9+V1mOfHG6O7O8/aTZ9EvgqfIH5OwS8E0W3yr3Ie6XZ0+ipw/8F8f//T4e0k6dOWU1XFU4GKF2vlopUU6SxehMudFw2H8FQVNSMlctAs8SQS3W3pKZuyXF9gk63O6OAXmAJAAKn9fNHBlSvstkScESiUUG0VLW1iwbTmNOn2wc6OGibGjBOaX9iXy3BduM0vomzG7gGYNmhbFJqXgMva0iQT3p4QYkgbKoKtmZ5NV8re+Tju6gk47i7KPBlzP3sSQ5X2uKaJkMvlHJHnz/u0HTW5zdtWvf/F0zXXewX22c1Y5d1x8Bu40oac5JKMa5G+WCWl03JpURyBxtDBwNao+chTgQyGGGFsH32prAplLSw6/BN83zqHXgjq6jeHI3cNdt6mKYZQNc6n4QQcc1bCBH6WnahRdbFO+952BVlk7WSrrOcZTn4FOM40fLHz5w9dRwDp86ePvZKoSdN3iQYZkmgBwdSoPRjBNghy9k1SVLyjeSaI8VHcdcvOdIp58oud450CSYEI9AayNDhQLCHQM7jiSFr02iQKTzr5aydLrNt37m6LFcyp44hG7KbemfiARxS1yhEHRfR6uisjZmdxQJ2a6QQ57E/tie0ZLsaTVPXUJOrbQOK9PRhGO7rirKsP7HhUnlOVQt56e0Pb974zijZzMTwRhCRfR+BExvr64v4gSqK0TAeOJSmpwXFrFo2RYjtS5i1BnyaDJasggMjgVChwDBH760cS5GCJKE+R3wZMSONtgHT0KK6/s4UciaFU3Nt2E0Yexsk2Qu5wm1LJRKcI38SJTmGEjheKtGAWK+vZyjnJGXkuyPxoEtazbp3D75/XxYHJ45gMk+tl+XVFJkjpPbo3AI+ICowUfz307nLv565nkGqlVAUDoIXyhxiUqhtFS0AeBBuFg0X4pMmwIcEwFw7RThMcfEuXHcIz4KjhUJlq5JHZMkYAgxbXi63KWakUGu3t07m6TtbtHdifKLZKH63/xbEaGAckVFymFX9+CBsGpRE+fSOpCadPk9Pfeaew2BZouFWhYdYiJHUxRDK408vVjY20TSJYYJ0bsqAz+DDcDK5gFtWPDCeCLFcgSYInKJGmYdnKWT4DfAHaGWr6HZ7Mnz/tEkHNQDHOjHBpVSQ6P1bwcBlJ6py8UrHea40ffezaOB5Pi4NGhsdM+r/f3brb0TG0bRHszaZef7ukzjK9sSGMYe4Mob7Vh/FNbYTSPLXHcinjzLIXTgaReIoKG6Qv6tGwx3e/O/b229+2b/rCO/kJoF9qyRT8bf8n+SXq9gQa00rmjJqjHwTxupItaKoGSz+/r0gCqcinkToRMEp8ChQxtWIQcC1qpFv53Hh/1YkSTG/FrmvGUxgfFSAAtzewij8VZpDZJPv96k5wkZB/+up/6Cqh85RoiEWrim8fWKikoNO2A6A8bItfNE21jZzZiiKhgjBR4c6StO2ufktUy9LRGLLlQBcDnurg2XwqzWTR3PZSjcOMC0+96v0g79YXoZpVXHzhto8T2RDxnx2zGyVInMz3DjNA8PGdXgnsfjQMeuVi1NyxOFUgLHiHu9/oj01/KCqolIk8F/QtH5Vo6yPDnFbZ4mjIzhi2af3n5bWgwaUl+Y7R7wO8T+wgtNqiXsT3csmGnPDwLE8pGkEIV75qM90NhXBfzlres3syYois6wsV4yuHOoYv2R5BPB1eI7Ovp9S73WSo11OZIEGryR3A6qnFdARClLBWr52wA/cLcjvhypjWu1HGSDyEkNtwPkQORejENEqthGLIPrzKm4WsU6NsI17JMDBB2JFmw6p6hiKUq0OCLGwLt4k+ZaPEGRuDqFIkmLz1AGwHu254R/70ldlbjsg+h0AANZmv1lvPv3VTMPZVdkrKfRkAA4UAECAbx5yqHGi6kPoxYQg72trY4RcVwMWu8mEZjDblVDb2ARaCIdgu35kC23QAlZICTfi2i1VaLLrm8NGN2GNK1vXHra65LSQYoeboEH8mW9xAV3WTFVIsx2YbUFBpl3sxi5sto1qDGXQQj7Ugye2anDKWaNDq2OKukK4vhl0thkTumGXvX/EdYcxSuySAJjcxt0AnhuLxHuOL7WvjgDoEI9BEjbMz4yCAnD2ExgQVgrgPA2oigQ+zYoUSvJOZJBZZ0UW0bVEFMGrRokcIqv8cCVSyuVoBJATCWNxqRJFkKNX5CDBG1EMJ1+JMiQ5LMqhMUlUIFa1qEQqN0MFjv93OoAHcDM9PeE1UfDAaJooSwC+5IJeZNPbcb+T6tSzaPl0iKfTaeEtkuChVqfBCrZGFm7hAYKoZo5Bh5OBi36uCjlImRz1SO1FYsJjast3pfEQgzpGNnMrV96c3vikjKNiCIuxzxh2szEIE+DUG7P5GBtaGuPILGNaSIxtmLxjw87D7CcEUimzvvaMvQrJFKh7a1EbtzkWYfimFpr8hyr45Oui+xmCPB3eWBTeU+o5OrU93h2NEvITau+GBRDsuKMALQvvoAkNj4q2dvy3Ke6yaDMys/Qwoi8pK6qmG6ZlO67H6xOACsKEhEXgCCQKjcHiRMXw4nr16Tdg0JBhI0aNGTdh0pSEpJQjjjqWDVKdcNIpp51x1jnnmSw2h8vjC0xMzczjqILfNVWWYchvbWNrlyXqHBydnBV3qZnh3f0d16+pTEpINJPFu2uS/MS8Qb8i0iS/+nIJ6sO2VW86iWlDK7vsmdZjJ9d7Dru33D7feGRCPjiD86zYfOUR6rZCC42WGp2Rr74P/2ntaI14mx90h8NW4T18/HC+ErzOJ2xnfb1Hu/LzJJ6C/g40HY9xqtYYAmrJlEsKybqgNeHDCbrq5rthkzAXbafuP620/ZELm2jHHQUmhQtPhImM0Z9ZKPBkmvhDglUC8R0/KNYW8jX00uiLnKg5WNisEz8mklcAFKeBQUTuLiXKiySyC2PPZ8UaekxY87W9XgiaVew0K9qvrECVdCYFgs+TcAnl0F4oSOHb75vWbuJ7krbIHBWfF6H29siCNkklk/eLT5Ur/3XvXTqIvrf733vVumw7TrFoj1RDrZ1tGQAAAAA=) format(&amp;#x27;woff2&amp;#x27;);&#10;      unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }&#10;    /* vietnamese */&#10;    @font-face { font-family: &amp;#x27;JetBrains Mono&amp;#x27;; font-style: normal; font-weight: 400 800; font-display: swap;&#10;      src: url(data:font/woff2;base64,d09GMgABAAAAABbwABIAAAAAP8wAABaJAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGoEYG4YcHIIWBmA/U1RBVIEgJx4AgwQvTBEICrBAp3ILgjgAMKEmATYCJAOEKAQgBYdGB4xOGw05JeOYFbBxAJizfwap/v9LAidj5+rgVi2AmnKs4xCdVNzZFtedQQYTHrvu9fJjcffSRGkQNsblzkX3scG0IVTkKwtieRAjQYIYSTEMHWyen+61Gx9Jw60vaxE6DsqpIySZ9eH5bf657z2M9+hFIWIMA5WBjUx4aGPSw8RGG91QWchkJcv4GeEvf3Tx8P1+7dy/5kDURCg2nSEy5E24JCqZUkjFJBE1S7W0jXlX6ayeGY3CSEgkB4GRCRdj/t/jhxD23f9+V/97pRgxZLFewVpgBoEIUPGH787svV+Szt0o4q0YhCDIhSzmNsrTVAyxi1iFhaS8ob3ndnUNSK+n8wPYtvFX7IFjYJvXAM9YQnjiuRrX0ynt3jl65pMQAQ7OC3XgBYde/n82zXb+zn6z7rxBuQvte3II+rEOy3Obl6JMddV6tLsjuJHpQDJKDtmH8hFLJpIdItIFraACWKWiLq8HhgqwaVKm6NKmS7o0fV66gCo45XaAf8bky97UPvDRbT1uNyGEEE2WiYYZOdvv9Ws9LxA0uYdFt6BIEYTl1sTaOglaIo2WLV8rZNCMqjUrm+bg0jx6tD6j2rjJXU6bRpsV0raLaHssbE0AqzUh5tEm8M13j4IgYGYGAmCl0qNm7uocEO/eT41CjAHgcsX/0EUQByCQjNCnoTgke8R4qKw9Qv3ZaS/A3hxQyF+n4CDwFTpd1SnKJ+yg0pdpL3Re4HPaT+r7AQgcOTcAMzoswH0EHZoALAAgJwEdWao9gEYiWaOjpGY5LISldLUur9WqibBUfpccUGES5qNaivCQpqBSupquo+lUR/OphdbSeupt3U0MaG/AA7bs9uJEHaASzGDIqvREWkiIqaWO1qpZ1UGQqjkgq5bCnDoULKHsPNYGlSeG+7XdibM6QK08joxDbNMAKAAtxoC6KiDGjzUGQFFg0YhUxBUAAhCgAcRxhBwBMCiUnSJwMq9IxKEMij3W5kXm7bXPgiyWgxzruMSAY2oieChflCBiTRfm3m+3w5wwJvNwOAKgTvUEsA7XT+ajD3NAQbyHPaqgEUAZtXYawENEo9/kn/9FKO4jWbcgZ39/ATXmUgAVAZJfLbA8o+tLRR2/DkwRAF+wyyWS6xvgYJZFQahYp0IaGBvA0gw5HFDnyaOkRKsgP3ywAv5itJrqBm1TvEB+Ccgtdi2hajJv6gGS5oEJrvMQAJBaNr4B64/MMKs5115LI4PGxPguU6kwGKLPnneRh4MQGRn4uZibSmiGjqdTrv9U8RKAMgomUtIZ4CJuLGj54qAXPUc/Rxq8BjxE/52dh7rLaAe8/4RAurUUlFSSpQIwmM//fgCakVSNBC75Rql10BowbY5YFYlq8Sw45YQqiFRilWFsFMMkllkcnkCpVZqs1mwNGzmr5eqt0GClRsvUUXBaxyFVm/XaJfJI4pWsRYpWKpuk6ZShS6ZuGj3S+WTrk6PfBn56Q3INyzNCZ1CRCYXGFQswmEQAUhRiOQZ76JDDHJ7azwVB8t4ipEYEQMXr6iTmcNmXNEgs7dcoaYIgCUgAwDkAyFSAVmCOA8FnwDwG9GAAgEalh7JLt8T2R0QRExJEJwKC1+50k4oaH2I+nDGDQto+KL8D2GCepuPiGSErFMpPQq88XP004XDVCbP2gF2NXIhXTeQV6rwZJlasGMmiUsxUW8hO1k1sa9l23ZaRnoVVUoX3xEm3ii0nEDFdx4KeTyE018G1sS7W0cK5LpGVx6FqIYJHwEX/a6DmsMi6uKgSOiws+yYMIRpCpeUIJ2CJCCzDwbcgr1/P0jeMdHWVC1i9Tf4Q4aJMCIe5zbYSvb7LCBFwzMhTcvQEN3EsLUd7uU1nwopTcV3L6aGc6fWGleNI+LILULBJFgXFEnZVsfcSmjbmTlNNwpsimdZFrOwaNaYSAl4GT2ZImgANiZdaidwiWrZbM8IRjmaJiLJZBKESAra//557ExvTHOV5T4J7xR6lcrKHXvZ/GKe7fRYOwkB3bifiICLk99yHFjoJDy7aMFdZp8RQaxfn7HBzjiaNk3U5hhaEcHONi67Ui2WoXHPNt0gCWEpeKF99dTvN5+jvGD/Hfq7WsKQ/rDObKF/bn1Di1UMuzhlyc45QspKh8Q1BaEyozO3z5m7j8yfkcnMO3+uyRJhfdoqET0od0enl5o2mEnocX/Q0iz035OYcner57NlLXIy9wgr2MzSOHS9z6ZgHI1QeHIkNeVy9PyTvaZSr+5HFgLvpvWu5F+645gp24bK0DbdffflsJt0XyoAJzQyZ5JX7g8a17R3Hshl7ly5batNllZj+1xiyoL//rZn73mrRPvxunYIX3VX4wf/nToUizOw/UIN1tfXxhqX7q/ryi3xlKWVFXeMGqroauy21NZYUvr2H3ehZusxm/Si9OZ222uC3nSg4YdvdpoYm3tKu07fztRZ9m/ktyy5tvJXXty/HN5WUWkprS72mxGAyBu94ODTLL5cmS63WJs38hq0RZnpNfN/QuE/ulRsNFRuNJRXGWUzX4BhuOf1CCB6E+y/ZZtT/z99+qu2w5q5XVq366K4Dmrblk1iGv+nObk9dfbfbeU1h7hNFOj7d4o2rnLS7O0Z8jlmPX/KdsbWioNLcbNI3XJWt0+R8AjXe1jHS3tvRPmIvb6wpXb6cbH3Hu+T1y5ebGqvX1xdtrCj1lrauRcXGMrPXnEHcr9Z2KzTxfGduXrvppDmvbfTzy5m2mX2ufJ4v35j3y8obVz7VlGZZz5srPo7KV/AJAjhtj+68xsYs3m0LnbGWDl0hf9RiuN9iXdr4Y3xe+3J8YwnPm4+a25oSg8UYxCD6Ep8sEy/FKXdMu/tNZvrM+I6JcV+7t73UVF5YZC4vnZ2Pb3Icm54MyMrRw5dqE858HS/uNm6+tem1Z+meHfbOB0ymB5qCdp/4Lai6QrnJwAsW/jXcdFnTqy/OV5YSlE7D3dasVGf3JiQlKJMTEpKVY/e/nWZo9iY1x05bUpLtEW5GeiQQ7RmJ4tWyP+objWJLZCFqj0a7m+sb66HZUe1u5KvS/k/PkKRV8dw6JvYpHeemZCLIlbwyW5aOfPEPnwdB9Hyr2QoSUb4iWq5q4v3qz1JUgkloFtMdpTW36nasTn4sU0udqCyzPWzsZGZ7hPJH17dHeVWKtq2Je7S6jZGmqF54VRhOnZVv0p5OVsSlfGg0O+raqgyViX3Z2X2JlYbWqmgwEO4MhtcXDgSD4wpkEAo+FxVx74gKjbxGrRLtnU16UBipdi/PJxZmaqoSecMiE8EViZZpm0z8n8Tkl6ebMlWWgbhaqWwyxpnfA9GeYHQusC/qWIj2NtY31ePhsX1Qamv0qvfjit+fO8AKhRK9sTDHncJN7U+a2XgUV36cNUVy4hW0jMSvRgaCnSPBvKDZWmGsVDlVuqSmotI4P2Meslzhuq+U3GB3sLM9CMnH45/3x8WxNUbf2qdWiUKzv+cv+VACLUrLwyjh86KJ579yvUwkEcfysWphhurAI+fLxD+I3Of8Dcz5yECwbyQ4F9xFsu58gsGeQPBS+56uLRv/L8hJJRaDU9WsEG0J6ma6Nx7VVcdOJ2nOiE6OzNWvrbehuqm6vQI1FgKIERl2nLsB5BihKEnaLZYXrrLHu58Ae5I91fsuPnuaPYNn48i2aR1rjtw1McgOG+OUsCrrNmAmO40905+zZHZfYE+Qrk0KM459fZyg6F2pQ1XaRoBVskpVKasQKai6OjIAmyDgmH8XulW10sMsG7YNamtNwKUOW4Q2mDT/YQWZCyLh0AJHuCqYbAFbQEuSthXQHAWot0y+eziWtJ9hD7AHySGCg7C1wGcPs0cOwlHkwJzpUSur5NVaCQJsLda2g8zO0e1gN8ifacmWz2lKn2pXWj3cahSqW1YdAdaN7rbIArSjOjRgbYLA2Nn3eHLe9p7aK0FYOpAUGsZk4TR29sO2piASBsbmxwq7qBdcdgzHbh2mZPqZ83+/Txf2F+H2PTz49Tcj9Y6B/DMsaby2MeANEo86XKr/OD0s6IE47imDFjiC5ahhlpGLQ+jm+C3C9/5LDjj6+5xX4kkXBQ+AexzcojqI6AzqywaeEZCTfQ3BTGsBF3d5c7wp/nOJPK+LRdp7BxSshgVclDeTDXwpj0L5LpEDBhZw0YDyUgaY7ZlnAi9RLjrAiUYsNzSJZxtnuGq5wdYXx8kizlxpdKKTw0tjRg1Ma2FjmhYWahpfCQMW82BvRBFiQQ4y2FhRWYPCOc+EiEph8VFNizf2VNbg8bg1rbBSaDUhCsNJqgdS56gMi//rCUEABAEym3MAkLkAwEoKydLlyGNgVqmOjUe7HkP2Oe0Cl7nGTe5wn0c85Q3v+dTXEWMVCaSQgZZ8jAwTYJrtRFjgEq7iBl7iT/6nQZc++8ZTEmqF60yyTpseO+x1yAmDbnPefR7yhOd8Ut/f/bc0HU9L6BVd16RqW9jSVnS4gU53eyNd6OGe7FP9sb/339ba6WIYhmUyRzdFY5qKqRvb9M7wBGZmdjw+JW+cJ+fP2ZnO+IsSJC/NMq/G1b/GVnDXge6kz9DX6Pv0Z1qlY9EQTxMfEcfEreJp8QPxL9GXVqWrJI80IM1Lz18EAhkKWYCo+3/O/K+7dphV50tsQVSnrDabYBg7n7/zyTtf7DhEIAdza8sZtr0d/A0wQZxThLmz1cNpKzgrzWZiPX+UiufXE5uJpeddjqM7hDPGHTob+YZGbeU8tjjC8P/9POAwyWqTSBFGlHrsiPBiLgq/RusnqO1aJz7183Kbrpkx6Uk/w88n5YhMZJxYwn9pOGpNvJaKeROQkxtbJmUY1IqGoGUzjDg2pQrjPCwlQz5iCoWTT85sKlo/8Q/b4ixzslMfuDPm2F5P1VTIWUcrFwWt1zCobBM6rFQ0d4EDR0aK0XHDiVUXh/57KtmxkaTbopE5hYsjY9hIV8oicO5hM6qaYWJBkVMHhLvYgfw3f73R8I4bTwBThf2RtCynCENbvOmqnDx3Vdc2LN+QG5Yw1xFG6Jn3BP2Kx4hggtB6b29vufq704d8/iAnkVSq/ndD3VnLH1dkWFaUsPvXXzV3WFLCAHx65Op4jFMR+icDkLYuL/EO3Bg9wu00RNwV2u3fm7XaxsZgpFF3uVezor2lPvzgdM63bCKqfFJC4cAGthXTRTjttAzjze+1Zp2zzdN8G/xDFq5tKaBJz8WlN0FKwiTWznUyqFRWI6Th3EcRK6O2Y1MiMR7MS+vzgA+HbO1I7TzFmARCsPvv36DLBdG5XJFEPhWaBd/zrcXcM76DM+BGkS4UotTZBmO6SJXLg1bmeSC3MhMy+BUV+WAUmg1nc7H45chBCGMcphzLElmcdFJGDlo/21+1FciZk3KGe5tYvR6CHHXw4rbWhaFSAlQqHN8dVN31F61IDPkdkbxTR4MdkgpGUbF5Kv5NTIhIzlwyFgWCED6J+ZACRTv5vPDHm29yf/8KwmAwdDsRRUydempKBAS0ohAbSI1LetgTkbiUHbkB67ONHGw386PxYglb1sgc5RRhYouP3XNe3nn3rLbRi8HuiIE7px1zErvt8PNz5XLwb6oNlpGWRpyCGM7pdBSiS+DZhnfaaSYN3fR037dDmm7JUcfRVIQf7pVKQpJIJ3rt3pzO1X0SjZL918Sf/ecd9AI5IdMYkS8TSKOW23Ce8jat59KgX7/YbWXW9xeqU4agHCLmA5dEQBgjARcpdxOsZ4phCOo6LKqdAopkMZ8vyrKnnY8BE4LLJLkzxUn7fn/Xde0c8H0+Nwrjq2bFWnycyUiOhOVgdB7IS6Kk/1kT8vd8B56zZBWU0ayF02AEUc4Smoe8nO/F7IWyHHrFW8yHSAT81y4vTx7Bf9RuMrjKNzyymVKRgWCMCEJI/pYT8ncAgzF5tu9TOt0fzODmWxMUo6Hvm6ayHLuuYQiLRTbt2AZlLGZZVowxCtZRR1kOea+1axgrl5TMhAbDiVzDqevKWjIU02NvS25EVzdS68fe423eYVY6EZNRbo0kxq5rtyjB1PNMUxEIWi4Alcq57dFstkDYSaE5sTAESrWUZ6BRCuFkEi5KifmccxrLqspKz+68QiEpTxoSvzVgzDjvFLe1sT4CzXm6rnZ4z03zCgMnRYqrApOrbvh+4bCjGg4vFLaKLepzhGEKSSylySQItlhwSV+iboXZvx2T0vWIytxVkhgz0scUHnv8CeS4xqMz+iFHjk0HiUmQWh0d+P//0Wg4Ul+kLxRWVQeoDdRWCaVa0rzaIMnFCo7rNUE+A5/rgtNwdhLQCkY2w7Yrl6br7k7kI8Y4lTBGZHvDwYgrVKK8v9vrscnFp1/mx/YP+T5jQTelcG4Y8RUiUrQATI34O+fheLLAMA+JsUvZsdUF50qy7GloYWttaNjbtQrv0M3YQ+OSShSNJRWJUmnJK6msba5pZ3ry4HMmoqLSbQJOiKzGBUUuyzCkK0fPOixHjBH5gX6vzzolGnheu8UrAVf3O5/HFXJ/PcHkoDn6S+iLwHRqA1ZxzwHwGcIT56q/fdAwjmRCugAA//363LPDvf/35wGw5bE+Sf5J9gAxKABA4B/wYqhu2P+vqyMI8dAyk3niZaj0z8BOaI87/6TwTAzvuFImBQ/e34vzamJ4x1XI4ta8gG0+dYdFQfs73yub3rf1gZ3GMDkN3GPjtRPAOdkYzRgEEKBRs8xXizXy8QDuy1S9TigyRqeI4zedZox7dEZWHNQF1saUHiMzarcRK4jlOyCAMOIkI8ihCyD0jx6DOL/osZD7SOeQ5wZdCL2tugg5GnQxiqz0SUD2xykNC7AZM8JnVI0pPsP8utXqNcUiwMdv1KR6Y0aNkRfNVmHaFCFsMfZtEHq6zqSG6/VG54TfZiN0sF2ZfpsN8wloFEOcLLgX9es3YOrZiFzHTTLQlnm4W+AqPG5qoeWY9A3bS3NMQD+tRpXqlCXW0+LSK3BJ/S0qejnNkenoBMpVvTuV4FQqiY8pi5L08W77U65bZsy4GYHScLWBDc9hFccWejugOtwkMMwZ1KubXcvbXGJePE7rPb3ctf388fBmXUWgu7J9aVP0V5vxPhkoD1P7fy89gPif4Bwg1RE/ymS2GFab3eF0uT3e0gEQghEUw8sIklJDpdEZTBabw+XxBcImkVgilckVSlWbWqPV9ck3GE1mi9VmdzhdeKRqFmXKVahUpVpNb6hlVZdNvQaNmjSzsXNwcnHz2JSHV4tWbdp1EEIwUiuK4US0LUnRDMvxgijJiqrphmnZjuvx+vzCdpoXsctue+y1z4Ko/YP/Ar1bemPb7+eIwYTBYQUCEpVlGXQoUKFBWIPk/PJxnb9GUcMMJ4CARGUOq9CozuHMkirXfu1PK+0zPAAVEmT2ZOiWDNnO7vq4xFQTDBx0MgQlDMgOI7IjrgwJg5GCxpIwlJwb7ejxI8vN/nNue0WK4XAqN/9rYESJiBS5DfQoUaNFtNlqnOEkEJGq3GE1WtU7nD2czu2rgIgaKXKU6KeM2StapOgxIiKfUmbfqBHRoi8Vc+9SPPdH6ZG4XgADKdfPrK6XrVdPQdlqWeTEfwfvOcX58v26tSKS2CpRnCYuvDqr7q7X43xx5e1TWV1fX/DzLFvj8+/2XV67NlfMCWzISpK4GyrKa+niIpSVtxKLaLA5vfBlWaqs6Y4OC6xGCoRFFlidTBvinumYRq+w6laz1LxPCLfgVlMKAA==) format(&amp;#x27;woff2&amp;#x27;);&#10;      unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }&#10;    /* latin-ext */&#10;    @font-face { font-family: &amp;#x27;JetBrains Mono&amp;#x27;; font-style: normal; font-weight: 400 800; font-display: swap;&#10;      src: url(data:font/woff2;base64,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) format(&amp;#x27;woff2&amp;#x27;);&#10;      unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }&#10;    /* latin */&#10;    @font-face { font-family: &amp;#x27;JetBrains Mono&amp;#x27;; font-style: normal; font-weight: 400 800; font-display: swap;&#10;      src: url(data:font/woff2;base64,d09GMgABAAAAAHpsABIAAAABMqgAAHoCAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGoE4G4caHIGacgZgP1NUQVSBICceAIUiL0wRCAqB3DiBrC4LhhYAMIGcXgE2AiQDjBoEIAWHRgejDFtJFnGBsU2lnge5WVVyxx2bn8k4NuF2FGQmX4ZnRm0XabU42f//JyUdMjTEGqDSdar2O+SQccghITKCZESYriN72BqZaY6RUJB0uPlEx4STwvdgyWM3TuN0dmkHp1ih39djHtzlZcqjBEH+ukP3Wz2Jw710mcz4TFNrmNOowSgzl/nbXWIQYdApTKZOe7tkuslj1O5nl5Xxs02ucpl/GRe5jCSh2wdn5w+vLRqoQQaS6d12/ahE1x4WOtXW1XwVGLvMRqwTlb7w/3yd/a99zq1bSbrwIKT7UWk++xPjPwI01EzUCEbn5/nc7M+97xFCjCGFmCITMY0pRowMpimlfMpHmvIj5TNphjI0EylFDBH5lOIWaUSkacSIkV1gEFn2MtRPcUPcMhQ3xI1mKFKLqY2UobhhGkN4GZ50818CCAFBBURmCFmEBBISMhbJXcYlZJDjSCCcIWGEESCwBRWqiFoVa504Fiq1RXeljtVhqzhmFSsdnzpWrdphh/bDTzn1e29IoxGMbEt2HHAA24+4TCe87h5ueIw86QLdbnvdfCBK2rrg/sQFk+xItobn+R9r3fcHk9CHUCw0KhFCo4qeLhoivhvNQ9tsWj0Tx/68Ou1VoBykd00hBcoRbR+ngZaNZzf/87D9t9PG0BQo5KZBO7YkWwaZKLk0R2tlVQ08vAQB4tG2emAvYRWLTwgu6oV9y9c2CSF51opjTMS9cn8I9KQeiRD1rYt5dfo57Q8ZJMeWQbYsO5aTuBCCjzD9d/MN8y1DXX2axgMabwaCMuSg/ewIGGRTk20/oZ1EgCgaw2qh9rsFV+OziO75Z2b3vr8iigLNck+8o3XN1d2Ly7daI+KHolRhtbf/vVtf90JL1T3QOl75quSzQTbyhIYvDV/HvAcSSOlUbNSjXY/WKx8bzLPJSYXd+Ss9re+Qpqnx59x/f5Y46W3C5aT0AHuXgB2zUCjXoyRQO6tIEStiC/8v6rSgOLIFxqTkAfO758Bv3tArKLOBa+k/koGuxad8VfWVF/WjTr9nUJo6bdMPSDcMm+0eTOMN661AUHIhSW0nkuFZ0hP8valW6X9okGqS2i1AWgOOhXbPQDNnMLtBQpm95RnrUv+7+wPd/RsgGw2IagCUBIDSqglJNw1QBqBmrgjHAWh2SY7TOM/xvgHKgGMht8Mz1mWaM8Zk66LgwgsvDZxJLwjSS8KrC9LzP02tUuADuHlNDM6t0xZnJztjw41dn/epD7IPNnpIqZujLwLScL3O+nhND9dpxDOU5rzOWU0SXnphfvD8u9fZd6E5J4Et64nEqNaKT08YSfs6lkfIMV27w5jaDilxWIGV/O/UpJYdZ3SMiUhyr4CVEZ+/lH+25Dhda+tLNxy1m7Xs+BEw+/hYbPOJSQHgBXDC11X0eRFkXbIPIZUxRittfP+wLGv9Tvz/f2uNtwvt/Y2j9xfVV1UxRl5ERGxR+/1+vr/fV/VNQEq77JM2lGApCio6s4/33w7j8v/nePeFEYVUWyFpHez/P/b76mJm82mO7/N1nbeO8ZSQQ4SEpIhE7P6v1WZUEXtBXmHl48UIel8IAj8f8q+AWYYAnSgD0XKGYDvFNE4ZvVPO4kyU61RwOlVwp5rXuVWNM1uTc7sW504d8ot2IpwOpC0ZEKBMVI1zG6p36tAcRwHqPhcIYJgzg1ZPwB81cRkcINABDeHg3a8hJEDsirPYQcRxn7XWgwhIALoZ/9OwFYQAgQYJktYfCI/CrUC0cZhsbUQSsXoOAHYIdvHfeHyOtgMjZD+CobVEDBbLBaxgY3rl6rOq+IwoBZ5hVDn6FgQbgBWYxJ85iVh8naFxAP2ghytvA8bTRsdkY8RrpfHrAp3VGfWpB9C1x3MCgOAL+WUAQVoAlz2cxcwwB75BTGYArjIK4+6G5BTO1H4LZoL8X4QHeIi7mp1y1bZmo8KOloUxQut5gw4Ay5qQ83468KgSduX1ZwAGJWYf1nObUxzDrjsFWooJYVIZFqNmYAZhDAzK5DE442LKmHImM1MrAuCAgV2wZdkBqxNIAOiBBixu7xH24wSxvCrxb3ZxGMAeE2xj8kjB0pa25UqvQ/6LkzQbDn0emn/5mvL1aTnehjyfGLFzg50CyEuYmQKmNqgt3BACr4Ahwe0mTqCD0w79rK4VQMvl/kYgfRv7v794KyBYaSivA+kK07WSBWYb5OimjE4B4Lxv/+rFCx9YvCbKdDPESUBGRZeKLR2XgIiMgoqGnpGZFSqfQyGcW4kylXxq+TVq0aZDp/fMV8TgAJMSR5SpdFSdese1aNepW49v9TnljAHnXTZk2DUjRt12j9WEn/zsoV/YTZs155l5f3BZDNCyaoa0PVYJVXeDC+NyOKfr/fnz99//NHQQRiYWuVAYuwJOOBe3EmUaDGIuMCtND00jpmGT02SSezjneM4eYf6eAMb7xtvGTmOZcarhL4PKQEduIceRSsSiv6+/rT+vL9AbyT2ve6i7pEN0Qo5K+7X2U+2ANkbzn6ZVUwb/Dj+ER5K7EJ4FV0P/QM/FLevVUAcUDU1S/6Neop4DhyNU9bolFaYSqpjZR7O3ZK9QPlbeVnqV2D2p+EKxU1aoQiz/Sf61XCnnfknIzsoOwS1rSOZx6pDLQyqHYMn0lNtJSDIGYyxJTN1f1IvrOdX47WFlrZQVNIrZea6zssO1vbgnOvQd9Y31w9LuTD+1l7TntX3XdqFN3sZtvd3aO9LcGtLKx5/hdbaYEvHieYB7y13BbeVSudHcSRnVGQsfExnRGUTlpFenF3B+5zx8JzgWDlWpwCvJHi37+VYoSlXxo5goiotdRWTRneUYt+WleVHul3+z/iv2Z8aMm/4JS9JdK+Uf2uuOXYw4K8yh28xtk2osl4s2kVyypKmT3Ph5PB6nx3ZZUGH997/MaFPk3txaan8K1b3ulof5ISscmDwYdAfKQBeI/cf+GV/uyxde3wLvizfq6b365t/NuHkxfiBRr2tGrlAu/dR6itIdyfhLspfzRsvG6rkYFN2OSJF38zO83RzGfXae1feSmIRxeopWUiPlkj/lApJLQPxypNktcOv4X07NzX6q5dRQZ8yxOEpHiC/iBmrEkThEF1E1NSIZEgwaK6+VnWVSCuup5kVZ0Vr6lzzIl+Wqxee/vJmVUYV+Q9d3umPvd/v35m6mf3LBb9npSZXv9IXmi6WI9GHupIr0+ku7FY9HDc3i9ZaPJY1emBcgvwgm4h/6Dz3ppV7qekJKsIlEPPbc57vQccMVCoLkEIJa+xBhQeNgsGmvZTtxArid+wnXDkwwSVZFC4Y2bAiFsieCg0Dougp0PBCUoF0IDHKAYY5TquZqVbQ4DS/2K7Z3gJnD6q8voiJ9JYO+llEHVGzexgNh3AIewaM7pnwC8BsJOgqI4EELACwRLTjf9anyOG0eGIINVdj9F25ETagZtaBW1IZmeTlUII8TWwSEbTDUz6ojgAjaEgnst/nB4Qo5GDKgjbArF82C4DT2jEKEIz0OIkSUsxtGMJPHFQjQ/HGm2PPYRGXGxC9nqWyq0ezYHUuAQqKxXaauHhE91Cfbo31NDzd46LGhAcQeMiSRSFeyXr97HoBNlAlRyq8LEPFjOqaDJaSykKKbOu3XfQrgnlDi28l2cEf3/PmBgGD2rY67p8L1lrsA+WvmfBDQ/Zx41mFgVrTK/fBGiPuApM/UQX5ZJ5XehO5Q3wiiA9GdExpMeyC6GbLClRa9S09cMWOzz08Z3jZ7JZTFzx3s9ovCYW73fD9Ug8ytSYverCfPLbZxD+qUqWS/kEF70VUdFjjdXiWRBXa36AVy2gJr/uyjaSHfPImOEHWvc/p3Xdrc7Y6jRfNEI7sbnUNbXVGEkDbU/TNxGnD1rXpyFy9J93ONCnRm+0WBeidb98zpsDvRKZeFjrQ2fYSettAubuL4Y1TgkZntKiYgsdvRMXkJPkrpGGGGjd+OOGbmJh+0CR1m3yikregYDY0ct1VlSUOdFr1KT2skJObuH3/cRgtMqdms012B3Vy1U7PsJJT2OeU/u4rmtw9Zy4PldD/HRlPcE/1fIbthn/CHkp1NQvHbenJ2ADPXSnjXBKACvW8xd7Us+DJ3V2PiHWkxv6HHVHe2QCj+NDaCCQF89djZWYHdaadjoq6lr7d7xL5jz39w4c4fLAAB9lIwrHbpdHoe0X4QHM2w+a7Getg1n3aqPRV2P62B3WF7JHUmodgmPTk1wmlrrIdt81ZGKzp6MNSusDliKrc28xo5jitOV3M9LH2s1/xtNKM9BP3gk2U0S7vF8ZjPop2h14ca4pcpIesnPYeonXwUnsCq8RZ6zycxNKJlhyTQjhAu8e9ujXqTnBzfF2ep8RaSekVSj+ZsELA9FC186damD5TT+JM4a8234Pkx+zOl1KIxgct9TKdWGrGZEE+1LbjskF7efyRkduh5RGK85zCMGm+AFz46RA7/OkTbrAPDEi13QsFxOTnqhMup8Qa45TGfBHcG1FsBBwQutzbzbXKcRZyp5hugZIwI7i0C7CHqtz48SxC7YSaEeywA+mF9i+zcPlofnZ/+Z+LCS9yFMt+c9IekEghkfgGLFmBpapjvtgsAX+bPJKHA1jx/Ar8diSwpffophZEPKky/NITmYclsWBpg5yGdvrSUpqSVdJwbSxyopNapq+Ij7fRtDjNHFYe2R26OMkjb3bTod+hGmwUVOXXSlMy3ss0sJQx1ys1SfKnPukXPlpPrkwVy6WfwIKkVRCsr13eCZmBxP6LF183UJosbmwn1fNuGWMeWeqUScyymwqfV7U8XM3iGluCxD611PiZQHYvFIUbaOlp3bUXR2j/bUGtmAUksrcm6EenIiaFuur8b/vdInhK55Jgip735od8fGUtuLzQVi/pKcknjpact8aKGjse8x4ud+gPzngMiqdFXp3sBoJ7aMaIBVzeqS5zs8KpmdoG6pUYNC6LG9SIOuLqYG1tS1hz8PEtRnpSZMI/biAccrnHl1yTk+5yeZ6u0vOzE0WpSuPeOt/ByB3k8DdUmMKnGz3IdcfHW4553mFyzmBY6TaV9qjRdCpnehncrhGveOHXW+WTxcCBV+juTrDxsMOHmtLa6hi+zq4ck5KtQmQ+tqm4ZVc0WbI/G83hVbnqlxTzkbwWmnyU54rJsj63zcK6vkknIW7X+G55NlQx3mxGwNTLNcamRLT0NqMHdXrZEjVAr97tmwhZpG1zUiy0YCfkSr0vixtGAo/HMu8E5TGOSpmhgtMooaUQjxswUZkI6YzWmmkVqRUKejLrEqVxDmnAzwPphjQII8eWqk7idWkhWN9uVOrTyByYxkBSRNCPW7U28H/SisEoBmmkDyujWkxO9KrTKLNWeGi+4XB/D3MlK4rglAqp9FBGXW2QzIXIsx8V8CKWrgbYkWq/0HwcFwb94FHzRgeBvAi4H5qYAGyNU4moJ4LYtAC4wX51kAgh1L9P3Cs7OBWhAwgEwY9UgRkU3BaHn49zrQVJHnWipi7UUZ9NlEMb4v5zz78Utuiyd8u0gHjXKm1BWSeBbJQbvBoSxnUL0876UvmRrDhO83n7BayXMmJWYfbIuiWHcgwxU9e2ZZD2rQsDzfWimD2zSEErtB5z7FaGgpQ317CxnT6EnZ6lpwNWP6GZI9KDl+t3VWYCrY+WUB9oj9cAZfaDTTlJNR9y83cGlssWOqbXuEqiIG/baUslL9SJ1wG0BjW8N0iGK9OtVk824ZsLabzPYSbY0Niox2+tUdrSxGr2MXkNC2Orxqkr66BsunVjjvC2iN7lUhgk2x70plaxBm9VSy5VcVqYG8GKwBg/LuFiOGxiogisLBszLzA8mDLMWYqlfDONIyItJl3gY1pAmcq2MUQhLEruLa38BHm6fW5YYRoN+BJSczYlHr+VFoLAE8Ei8wK19R6PChRq7wcGBeZ7ZHDIrs5t5wu7mtci99arZqcCerEZkHkyOnBd2FiJVZ7puz+1RL6vAvcSn545P3y4F1I88zMJsUvF44hTANIn4jTBgs8aIdiZ3eeXpks5KHY0qx5eKGvlY7DLz9gQjeIVTFmb6aLk7Aqeckh2P/gIvghNLt0xTm93mTNeoGplGNTD3fVQdSGXIkEIDcuA4XQ0yo6CXchxLxEW5l0okA8+slpqruDIwNICP0zX4mAJkzqeBeaE02/PkiYR5PlM2E8an9jnGSZmjNysxj9d1abPYz+S56BgB37szlaNQmBE8xWH24tHvIjzBES4d4V5wcHiKVTcVM7xGyYt+eO1oDBvB7zgUYgxKmwR4mYzMJBQv1Z+PbtwCgumEZxEwgcXVkP6DA6/ACEZoRg50MwEK7W+AbPaEiRlQ1Hbj3iR3A+7wa8izGcAyirIRPMZaiShJmwSAhsuR768AMEtkJ6GAAt2IkPafAo15wZlSTH6F0ANj86vivgS86BGmg8AUU9yHgW78JsC9Ozf6wJGtHIENSw9sUdokoHOIzU1C6ex6mk2rHWOtUYGu1/unaip11n3/AHYKnUn8SFqbPl83/CCQcffA2FpdNHRyryrpAeaJoIrsA3TCLZVrK9tQc2ZpaQ17UjeUomgf187CH5+yfQAdpb2OCE1iVof2jL2Ptp3hSjxoqzkw+pvqAoh8TqHWsLga0o+YHKVWMkLjMtnMhDra/ht1CHvCxFwHUBFWImL8YU0DhFgbCQY/XzEz0Dff74QNFTMmEfoBkyYYix2DOcFwJYMD08hB9L8pxkLosFhiCL8MAO7GVzjEAHsHkcaUVMBeKMQ42hIj2Jm40tGulYMq1s/XElQWQqu3YrqFUR9soL2FUCiWnqmhyr1ncCphn6Ybw7T8LSwE/mSmJF7rzE3FCFrjbirWZZ0kbsFTomVJKH5OT9bSZt3l98Bnc7OH72cv4iiM4AaiCb5xNIhGcF3iro7HoxyAKQm8jodrPwYeOg1VgEQvNfBRUbEOehb2Ouy2MLnHXNU0xfMqna5IeC4mqER7BW6eh1WUnNnZqFykSANWkFxD2CHher3Io+8RjEGk2e/hTCIS1Vr0+bopokU3br+xnk1Tw8WxMw8F/QuBByfx3EGWrUBn0gO3WQscg5EZo5WIIR7WySr8NLK1Q9nJrLsK3ErnYX5LgZoxFLaT4cosm3QJXg9bzsosGXRRvMbxKT5nHiP6wsOEV0g8nwgBmCYxWbPA4QKLbl12UVSUtcHAJ97k0WtcqxIUNTw5MIMG4SZRGHybT+fEXW0mtBp7DoWaLQGmxFzEUxFPDaCXYp4bn4aZCjwoGI/KC7Rt6CxcImS3reisuMjE4wrtWbDRV8kiCvXMBvU8LHPJy2cuXW98rO4fYIVeSuk07HCQAnsaTL0l2eR4G+qEA2ha91G6KZ52rDMI4cm0wVgsroZ0ElZZqIsR6hcbbSZQu/0O9C57wsRML1EZ63pj1P3fviUQ/f/bD9ff4hMvA0f+FVEJFMEZhPBEtgtlaYR6MSQF4rb/BJlhDvQUQCYYrsQDcp2DUnuScuxokiB1vlHRN+inQiO334DskiY8bfxeoxtNMDxqfvCbKtwzrelS+sCSXZfyEyZzix7LBpPCg8I1RjIHfNvr4a5jUdyg+20HcI/o5iQUXK9Fl4eVLtopWVc0SlDaGlTdQsvHWKmM1IauGjjaaym1SlcUJmi+bYVmCuZuVmJWLl0aJj3gl9UUtBn/D29gZIcyKCXYA68goYZ5epk8NaPjFNWHLwOAJvOXwxoIqsE2QpkYrq/iYWCjdTs6JD+VCVMaHlbrsEuiIrKGPEMk3FOcooQSoQa0O4Lys8eggDmoKD0cyqfAKPK1HMgpDOC/l6e8fJsOTOT/VvaHTOSXrf+Y7ASEH5H+gcb5VXwX2KTjbxgA40uZ2qodgk/shMpMqoyCG8MKl+okW1qkTPdx4VkdrqVHcn16qF+DXUGQeEyGBaZaNAqQPi/mqGarifJHBDFhayCGhZg2r8Qs+nWJic7DWibXTXDXHEQ2FoW8kKpQj1Yi22RTtdQDibgUWwVCXwgZEjJ26NKERM/kvyI8CX8Fv3MUVnSMggc0QhWo4wLutOXA1UxcyWrXyBVPOnPnwyiDAk7wvJhKYcYD32VLgUXCMzoZVTypC1iTcU/XTS67+/y2frD9xjr3+1odozOMYax26IVkhomHSvMmlw6LCU885mrawzByURGbPa3AiS6JCvb1h5Gj8l+MqcH2RAS32QfsoUOVHlR3/Uc1HRLdGSZ8FNlDFXcvuwfUk5D5jDIfUDPAVUH+morxFrxfypk0oGLoiFJaNUIHRQvNhNJii8F1Uvby1f7PYaM1O/WYFnGiS2Jp0sBRBUz6byknH6BmAuezM1kEMkK1gjN9Gdt9vd0uvf9aKMCUK7sqOyA8N6jGGCGMun7V7ibetNaiGy6qal+M0FdQvFAM2K9Q5UnRuadmO+kDL68M4KdX6rWieN6O/fbbdez17KRnbsbTa7Hf4Xk37YcsDrzG7sdeIdyYZI9Sk/cxDRceQrIJMxry4JtkdLBLcW4PwMPhfs3bmKd1GXmD3VWPqmkfxGRABrsPu1ZBeUkou0o9GaXjanip3i1N7FI846m9qavuMwbsXuykW9RZfNWGWnjXdF+65szG03rpSf15ehW3gPJZlrYzciuLqyF9CT5dcgsjlC98zEzIe+0e5HXsCRNzXkyFWUPjM+cgq46SKyXS7TbXmnkMdnZtKpa0E6qJILacB2EO15cswBwwSkMgirkWv4Ke2567JngCoQcy6DtaxbX2GZ/YiTxqpx2oBoAqn7EpdCb711CRryPz1YKiweePko9J4t3YmjLYDSnfbWzFnLr/iMSnB71rneqRyAvZOR0H5aFiI8/22Qx9IaW7mZBZ7RfIZWxJ/1LrppNQkX3vQ4vOWPKB8PPe25b/jDIDpmetObtWyx0XyDrOklJ1Naf1dcbTkD6XUtlMyMQ2B6hukQUgIaNiXeKMplU0pz+MFkUBJXhGo2wUDwKdt9lAIqE22hpUQqCAK/fMgui6SS01RbQivWGsI+cBbPO01GRprSuwWRW+cHt2z68K7tWTqfrF0Id1UAhw/piKnJwywahCOYiQVthMM4GCzQSOFjLLTo/Sp40W70yw9dMF6pKQq1p1XyLDTUJ4MYSvyQUxsQFtBksF2cHDakhbhMmJTzup2ghlLJhEoudy2s34MhQiYUL+ytWHAbKAvkFc9Vrmxf/9W8tqAMrQL0cB2Q86GP36EFk+lNDB0q/BTAg6ezCK54eJPXhJyMWUnoeTsYA5ccqaFIrGcWYNkeZAJURm8U6ZA2dsM8Fn3IEq4zCrcysttFIpPz4r9qFbQUUEOI2VgIfdkPajb3spWIzQPulbbibkLrsXuZ09YWLOx6gwa8BxPsDH/ytFp5qTkRRTdIS+Ub4EsBtV3+ArvwA933W81APRX13yKRDq7O3sKw0LE187ak1hFWK6BCRPu1G4bl1f3TBMvMsActIjox3oYwpI7I6NbOrVUcluyxQ3Mpu5pBoeZOXeSLNNBQQ9d9tUzj2a0lifytN0u/bch7fVaFnduMiC3qDMICKJSNqMshFlopg7050lLk18CWR2bai2sEbljthXzOebR8IfHYYsmXhA2iJ1ffoNonCS3Rp2WJ201nu/AIAWvViuGtAGlFBMrRHaKMWsmWByuwEtMQuTorXvQnVJNIEG5hV3XdR5FWoUjw5q3mua1qHID7LO1x2/9m2whohtQ33prv4sR5+Yte4pntwIoUoCRFZL5+Fcf/CNIrB2pR0Nu7zlNwjS4C/VVLC0wlyyblmdTdRC2BmRQWuQ96LG9WLQasnrmgk47GpU56JnNiXm6iQ1HtTff0acYq9GF1u7DNWSN8CoUCH1IGeB3DFZaqhnK3P6/xSSGKGVi8w2M4Fo24Oq9EuEYqH13fH1GwEEilabfdNy47LhwwytVZJPBNk4yOgj1IVMhRDmKxbqlCzOTKj02k4EOo/Q65SY3UGFN+QSnMUn+W1c8GEW14Qj2tEyWbyPzIiGtFw1c9EbLrICbmJP2Bp3Oioia8hfT4X/B2dQgHgMKx6pEVqGFmVwkV0K5zJf9f4ECDVtRuskB+aQVUPg/PvfpPKgFbALHhktRs0akNjFG1bXr4uZZIoLFbeA4jjrco1oYXE1pIWoZZfYywgtkFqKmRDr7HxEI3vCxBx3UBFZA/5pVMGHwe9MgPRkS4zQCM1F9VGIwXYOIoeJK1ldJTmY/zSx8jw4w1VikkbSx+ZqSLNQzStJAyM0U6qpZkJisjOQ7GJPmJiTDCoia1hk07rmjyMDErFPgFpRmQthzrYioV8Ok0kIglPCiBI0CNMhDKqeHMbXFM6v6g3rJWB/7Khad1+oQD23XIRUH0xmuk5wOju9CpG7mqqbl+xo4Uyxp541ZxaT1pMO02QfxuLzuhH4hfxTy4feZ6sWfBgHma68/zYlxmhKlTbqaBNNUyUtScSF2CmV63a4SMiuUWZGesXt5t3iP/AwdkbXQJOQ8radrAHQxK2U7k0ParcTYfOM4OpK9lBhZbZHbZov2W6LwqeoHiMe3xS1L5RhlV4SGo9YFMS342G5l8RCLEAtLG1NKKbQDeZwFouA31ZZTDCcNKCxiKzOtAGN2Upc/G2Qy46G7MzkkZg1RoVZz2CT0xc/DR7t4SMfk4FnkHilalNNI6vE4Ax2BJTHM61hS0FqJq7kYTeB183+Vd6LyFPj393gId6FNAwJDu734mHPjubrEA/21Jz/0Mfjr4a8XaAhCNXBetwQ1ShWlxbzUj3OZGMu3dYU+H8qNCunVwkdKVNxMvWgQQiCgMkOgk5cQ5ddV6vqrpG+415qw4UEd1TnXAh3riMpz8EsuU5xjJJxF1ZnDmJ4FdIAeMq02foB2MBeEQWrroL7U41GiOORUT/YbEBi+4GnzPQX9vXUfafu0/gXsdg1qAYudk1VmXBvg1w4HW4Fd7sknRFdGbVrcjNXjasul/rcbTKsu6CicmGhH58JW1ruw9VYLsRTc5b/txcfb+gzGYgfsKFsnsmjIeVQJ5TMYjWkrOmqjyDFyITUspB+ZoJCbA3isBMTs4DKJxzeD87wyMbuB0aju1FQBWIWBhChNP1Fgfu0w0ZQzp48EjOF1PhGhb+B5P6/vSVGCm+P4S33r3XVVHW4bFZHfGCsQdRQBPG+aviFEVJFzg6e6gy2ZNx6ruxYhvcB0lLQSrwAO+/djVo7j60DQBAIgAFVPiw7BRypeoxahc+2Zh4AHre01/qsvA3g/2E6HxCu+fAuAJuERwHGCAKlBe3NJo01AfGEzOpWAgD+ZRE1wpRrtewg6RLrKUFrFxtABhO4TyNRac0eZrYcpQTf+yF64TaNR+tt157gtATNr9eT6AbjrNcB3IBMNns9Thg8tY+ouUzA2IQA5HzL+xWs0wPNHP+YF/RDkfNnMu+ZQILWo3x82oZt1H5wAkESPsQqfjQlnkKmUClMShZFTtFR9qVQU1alrKFGUqePTzSHAHL4Msn1X65gywHhBH1lFCWWkrg6AUWWflawnykATbRrgN57sB82wUaoGq8GoHdhbDUA+GhHqBH+J7wv6ART99fue902/hmPR/4ABLAcYI/7AHQlH6SuDVGXqBL8XvpRmT41XmYSYsB3jmlwlMthLUrUMjsSgF4euDw+gGCwhKX4wjFdjBkSJSFLRkHFli4DF08mETEJKbkd6jSHhI58AQpaOggjq1w2qEJFcDO5uFWq5lOjjl+zFq3adNgef+gPhqfKvfCHec5Eo8koF4XDHgdCQGtYaBeaighgdCB5KAgtgarshkXyHWRy0CGVaGBI6HjhjQ9M/E01TaQEseLEi+ANTDR0LAz/WU2ITyCLDEctNaVsMBWIhp5FDhOzAph8dgbFyniU8Cr1f5s1qdeg0SxV2qWpSAXywz7/1KnbN7oggD6IIDgCYbSVtzIa0RbHEeg2IYTz1DJsoBm2Z0PTSvuVD9tTa1X8sLdplbJW571VfcALWW3AqIKpjw0kowb8SpaHrflhPWtbvuJOqo80xEm7vJY/8KP9NHzhwAtwTkA/q+zBpW+WzJmX1AvfWlL4UdhiKJ25TqEnPOmQC77BVQhf9OihF81OBt/mD4MkhEV8USFd4W5bILxNi1Q4uGtxKpHEB0w3NSPhNHXSj3my8LMsoU6rxOZxBGywUnB3VyQGtAJi4BvJWpqcBW2FtPgGTckl4pqsmIi1/E3SE/bHj4bgY7QBsrWreZUdsGO3yZzELKWkkHRVxaqdqrcHmGRr6t0SXbGd6HJenui6zF1Z0YlT8bu9yiOnezdtYBLksTP3R0c5yUqiuqSSkhXTYpU3eraL6i1pVmFJQRm4NiywrCIbC53KjxlMHznn3V1EaDc2sPLoPRPh6i4c87dSfYVEL/I9JUptYVIfZSvlVt5rMWGvGtXkNejhReWxff9nv7sqLMNZRuMHwlHLG2ET8XSHjsBbLoBIWDYy5xN3yn1/prtE8BRSqgkSWVxjbs9DtU16x82OOgfM/PHshy1/sELGCWKpE1fwtQkb/ZKKZHHA4ueiMVujxntp+C4mfZQHESfDwCl+G3CCeE84MSqwsMPVEWkkGDMmtFPfrjONvjgur3707Rr/YRDTVhJxzzkLaJpLjcCPNH//j2+l3LeOVTGiIph7S8xoomDdJyGQOCCPK5/PFVQxnAFNtxH+f/5RQ81m75VQLKHCID8ulxGCW6x367CV3TqrnADL5yYZ51kHIz33Fmrx1cPrGSA8VRIJNLHtZ4NRN73ziH0KoCyqIY8UOWOyspnaycIgKkfnwEVFXHHAqAr7JBXQvQgBaMhl/YqQmCIEPQmBGxYV7pWn565c8kZ7m/tVsHgkBxLenCmo11YXg3P50NochbwQ9mnBlcjT3cnOMLDNVY6mXelMgqeLIX1mHCthj3bQBLcy5JPN4rijxRWCdI3NMnqAsdlbAoj2HEadiv0pdiHUuAoQpEoLp6rYNAECgaBD6NhERJoPv4T5q3gVFSD8YKq7ht7dOW650iKsLBZYnZM1mNIN7fqVnbayImsLqs5GRFWsIAqh52YxZmvttOhmYXWGIRRco/Xm2Ko2QmMHfMpjn3Z90iVTw2HgYniEE4W/kYAJy/5czhI3qQ5Qj+NLkdVdgBTZ1/0SS/uHbYBQXkZaqyqmvNsBjcyMd0FKGZMry/FbUAnzaKGPhaQKUviooBUEOkQsnBXUQpQWc08BqVwCGpZP+cg8vQAP82t8AIZREZZPAZlHJzWimHgBo9ga/GBJ6T/fArXDhl4DRdgbugPAo9TRJvfNJDfChysMkUnUhBNYSzTNIkqxlQ9vRZ5Ce2C4TW34xKtlH0logInKaWCiKd8BERL1UQlNyajHhHzmCDRVYlA/KRwoxiR2Ah/9kP6QVW0ArqaQGjMUnKgwVcXSuyM7hV3bTNSntMp8TrkWdzYU1XV7uF9zRQgroUp0JZosBZWxqVy9bshWPpW/7UARBEESdhUGgRHgcYuM+TNsW0soqqUNYUaKLDJkUdGWolC/OAqtxmzhlMiYFb5CmDEKZkokfzO7cRfONf9DTAJ70+3yjXjBzlmW14rRAisSLjg2YkRgDNgxuhzn7AT7KhCitF2Tdo1tB206dliOJ0NlIuR2GzZ8AlDli1C08zelQJ4qLjcPzy5V5dCh8X57AHmXO10VmXW9sKye2TUelpAXNiap2MLsAtvX7wW80b2XWMyufAmI5x8SUcvtBsUzwRzOHu9gkzTG2OgFuGl8aO7ykShRwJsHzHvfQt8nK0Kw93lMFjdJUmGnPFqVgytog4X2jwmi3Vwn00pwg3LDLnKq/No1Gu178h+rsPrAzCAinprJcI8aOSiKPLZFxwPiYqSlCrRz1iVGFR/wR+wUhvCYCDuF3X6z/aNuZb+PmhegaYxBFxk8UsgR8nJwtjYqRXsskSp5aeT1NLaobA+KUpSvLQNndTx584MRgp1oogjcvk7SJIpLjSW9V1WwsxW1sCbeOx8yKFAdbWa25gg9WitDbktr7DIikziHjtr4V/ZtBgZN7UQgENg4Dwon92NTaOyyfvB9j6In01j9MD3R/QuurTAoZ5pi7zS/OK1WDw5Dtj3j8ia1Mgtr5YpOBf6ayHsXVBcJK1aOshfWGQZxiuuxoRwqpH8mM5O4o9e8FNRVH0EY4iwdotn71WntrC3m3mpJXuCRpN++CeXhbFc3nmFngURLNu86iaq3FdrbL0EMUdSd8s4ozPruRCFdXyi1B7l+SGseJP8+7HKTdEjHEQJvKouBkRvGQmnv6twb1kArj8AUmxk7hkEQYhLxRIMt4nJKgFe6jl4gdgrzlLMJxLTb4KaLWpWzxW1q7lZ0uMsVR8E+1/lE88ShDVOdZ6EOH9XWVJK/QYTR4W7lwvW4eU7RHg8Lw6eCftwTyfX6tgtzIdRR69d98mp+5hdWMBWe7G/5dwoTJIAyxjp4ucvvkHnjccwnkSPhmAbaMEGoGxUq8qaQm+1JUh3L5GBZ8XghEuJXvXSTGup0kdNI24qLL2NytlTbMPxY53Q3E/ZpQPldlSyMmlgCtQ0tIWxyKkaTXNeOMtB7NMqc2P1uOn8h/TtT0sroBq+McVkmbTpFDQ/ZKDMiUKWlXQqNFbPpnMWfsNFU/Z3XENLRl2g5ZoPXacuFMlOeK0uQR6IELRKLxohTiCfsyEP8Ltm13wMiCadvPRFMmpKqnGTlpMWYNyzQr2g6tH4Ul9EcbVLarO/gYrq/z0WhRTrhNp3VxswMg5QzUiGT+tiuLlBf2ekuEt5h2nKD6w+4WUetSae5S/E0dRPAJMrNg8Pmx+3EVMfswlMKX2uO68fnsOGHParmLOSO0MmwPUcodtdCy8cXgLZXS/ndUoC817sf+C8pBr0NP4cGMX3/MGwn/n+ktHifcX/0agJ6Lz8ujHff7OtL4SQOksjHkXTHWoTx8/EcofDW80bERAXvI8XM2SrZdYPu07YFoP33IhvRjZad3cZkj1lzXNujSh8xqLVqVteGBX9fNdacqOcSOmXqPwjIOLTHYJCV4EjoETszGwWPcQYFqrGz87Fbm6IN9hjMitCTcBFMX18Euup0C9uEUWeZDNEa1Y6XL6QUNxacwYYzk/3DiE/8rcHVguYy+la8EZN5pjEZk1CJE9ZPt5sKteU3CILpX1/MfxbC1f7HRsV4ghkM9S+7EPNB0XDvfvs2Wrph36swZseHWm591hRy161t9gJi3phhyzMPDPQ+d4NPa9aOH3wTGTc3OMtfyC4Dl7evNjrIAS/0aH+m6OH1y+/f2+hhvlGKndg8SpaQb0UbgaGQ8ilZSlWFMgu6UxB3FEp15d2N4t21AjcYwWYwVOgCwQ4NSeReXOEvaml6POdyuIUjXNAxd8YQJWbCaUpaDTxtQlsYs77R1Z/Zz3SC8nUdtciFs6LT7o/Pst1nfJsu2s9WjC5vnbVvjBvxt3daObBntoSBxhaXn6qoSV7w5k3hdndqtbxhHU6TGk5aBWUeoehCXhak/F7kmWqK/bqnoVpj9vfHAzQQyqh9yAt0nnce53ySObbrKb37UaboRzxjge7Nzg5x9qnDemWH0j56KZM8+HCWnSls8s3b/v3GXJ+DyYoW9Fe1ecIepeUCmPBOcElcs7FSCj4kp3B2ilu+ZCGOfIYmS4My4yJ3aQBi+XwW8EBrUwHgNy8Van1Pf5ljHnyIsR3ucijq7WvWVPAIRfx82vBnx/qy0O5PulB9WJXma7oKI3VOCXJuzBPJkfAZOs/nKL1M4h+7Gcpyo2goT1j2It4jSBKVZOV9ZZrwEx0BpEIfg7Tal1+RUars7DjGUi2xAA9kNAIpVqC7MxPoFBo+UchYdeuEm+SLtJSoL7LNaU3fPkrJzev4+cghUXNmVlnpi3wJNVPdfJDsaKndXE7WOCxR1a/0I8kXaFAO0g3dQr7PmP9bTGcHvMx+m92aafTb9v2kfbb443rxmTBBD59Pns6463IW+Da1idhLVJaSY3LjLJ8rGgKhoWglJwmcURZBmXC3zWScAomirD2JRNXCuxusSf1qLZYLlI4a7YopTtwS2l8WfMLTlMZGOYuVpE7Pi/isP6+oBUDKNPncFxjqk8vPv7pai8fP19o8vb6zvYXh8GjTCXQLkPholXUvU/0CKcbFChMRs8o5LA2q7Voa0/YiC0RQdxCfwuD0QbEgIMOUt7P38/9+5DiFVLldVOUD96t8MZV7ePwLz5R07VaBgOjVO629+1LggdQKvIwHG7aPsvG4fzTKcrJliIM9McJCQ+M8/iNzswqjTx6Ir3Iuys+oU5HV7cinffLMYk97UKjYe58ZnLJe1Shbo5BpoNctlM7XYtQpx28AG+6oqnlZ2piNTxqNvEDCQ5zPnM7DPp06vuT4RrjHWe+Hd0VL/ZdqKhlTRsVAZ2ciKmMEMgWeEe/4lsXW+lZg7muzGV7tWq+2jI8OjBbz0xXqiUWeDgRn7s0+fW8m78sfBws4/LhkbIJyJCbqr6xxQF55rxc7+nArthUcxSZf/iD1kmj6vGYpKB697m0sLxKk5VhS0Skr7Rlch0KVNdOTqV2EdqqNGrnSaFJ35s6Sa7JFIjhb3g54JE0JX+iGTRphcQlfo/EIsophXAVpFAoNrDKrNBEvDBUOZbnzf3kDNy9JkJjd4dN8AqpbZlndkh9PhTPFIV90t3aNnjFUiqSlWppWWsZ1DGW2co0pR0OD/VNfDkgPc6z5m9zmvyi9owOY+T4rjxVgxoDn+wNYwR9KTK47DdAi7da12Mt9fJiLR3Hpcyn+Wgh9jgIftk68Dlv8zxqEB772tkpcixghSH+Ga48exEghlR1twDWKy+p2SMuG3GfnVA3m+TDQMoovMWHAMjrL/MtBciY0vtLwfNaok5Qe1EBqDa2RtNV5ZtUhpMrg5qAmPgngox0/NcYGGokofVPhaMePjTMC5tGMTYBD0rj5As6dgmI394mhmuENphwYVag0KpPKxxRy9Q9GBkhNeBBj18tuKKmN5VekTH0G3SFvVtDt/O3OpP2wgRaEkrDDjzdgG8YPYyQ0iLrxB5KN/TarOest+8oauEZ/0ZULxR4NLC6xP3y6VeldqxSIMVuFGBSrAD6K923UlPBFRcqZbXXlG4cCN8phSCLVqGUbwUdHag6tC/wiRFsmFJUUdI3IwwmtrlRIrWggrazc2PrFz/8qkJxsSIUYFUgYVVB2Mgxco/fh4/8XvVhtsvjgqA3qml5Rm/j9JVItIldo9dIlgEcyVvIkReG4xKTWqpFsSToXPl1GNsWgtTkKYYEnEy5pqQFOXAwpFXJIIsjgwVfLk40xNr9JKSny8sHEucPYc2x4KeCQKmsbSyPxSKVcn61U6JWReGRZTQN4eepe8dxX56Y5xeKpznNzXs087aV7cPzivQJxAhlVDExaM8tqVfHIBDtrari/JpFI1byF95qyGXR6FRb2wRLmOAv2bm4/X1XdeHc+UzWNOX/H3fLzpTfbqzqfzGd+OJ0x//BT0CTte4uVnDOPG6+/u/nBsunNMAVgsQM3Zuiw7bgxIx8D70iF5U6LtbzQsUeSdV7Kh1kaPARpyS/0+Evtc5y+KS+VLr0YgfLUgtxPMvgc7kMwSFIZzZBShRkRkyn9b1piSpJDbbQoU2UDlEDKWhJDZ3GYVv3kY1jJlLwkh9pmgRlxCymBlNu+GAuli+EzJkeSlUkpRwlLzUxLSrKSCcwkXZ5RHR3pw0fxfkJndLQKy9Hml/s9O9zl/karDNZCfRCslUkgvapPBekBj6Qp44vccJ9GVFzG13haKoiFOB2SShV6jWq9Sq9VSCEZDScWtlSAG6sJIo1P5299WIB5/e4dnnJ/vi4vRxUdTejsx0dxX2S0Os/IsErVHGHfJ+XxRxiwSboqibRCqxWWucXqpJv/1kbI/hyC8J1mtF1iKKv+fI0O9WVaGz8XfgAhsupKmd4GWWxwOhV6wFFFCVZrwCHBJVlCt7oPEhaDwjmjGCotED1+luqyhX968RBdK5qqYcCQXpUN6+GkIPDD1n6s3wPnmYw7sB3Jk5M8P2M/bwX9R7CD7AoWQiiPjFDa9FpHab271V3qd2htemXENF+R3IQ78uj0E2B8SKX6IM+boP8zGvJF0WEros8vrXA249UKFSSWQnrIDRzYuQV7sMDbJzBgP5LfrdJpsj97jEHBpe1NFcAziq+v2X6/6njQqWTf9j9r34D2TAMjVc/79QQWpaYWUA5iQMO0aSLvcoPYXL5W9RE7lctgC6VWaGf+Luo3iQkPqQPGXbSHiYlD1AHgYuIsyC8NaFOcYI3HEMNqm4flC9U18AbHHNimgGFoNeRjCrkGYFwQZBytnXms9kCUIVujz77eZFNqdNl9Rtcqlaqr+rKTFsERktZakPPWZHVoWWlrQeBtYRpLa75lpr6fvExlcrxN5thqNkpZaQunBoK1aUmWZCXzbTZEcY2G6/gEthqZsh0EM48oy4tiRl1+WZ1nhzp9JsqXavNVKdXxtwxSHOxjMgkcYTwjQcHgI/zRuu16EdlxBGVVXo4uv2S7p7QOaz/j5t+KalMh1fE2MJ2+6YlQkQW3FFbWFafgcbBKJ5dN8S+q+GApRp1ixl1wOlskp9OejuSEoeG5RsRUjLqZNk/ONrxoPI2Z9YhJnbc7J8wZjpqNlpKCMuCKUWW53AII8rCFmFLAtuZyPIWfKdmiYo8Q1mBSpR6Ry3VwdnouW6rSi+QTDwkMy2NAtSHXrNduxjZvxjf/gP2gVSv7MMAmeZoaS924W6XWSaSQTvVupbSlEbw6xnDNbupPzIQSV85qmpk0B3MLGah4EaNs6tQFDOWiAiVsC/4BkS6yzGSUy+cq1icnt5uz5wLBV/FHQ2vqBmsuSlIv1vgHfUfDvoyraTtSc8UofTFn1hFw+Ah653KAd15+yVm1+izanl8acQ/geNbsdGwVLputx0DreUnA8hlscrwoRaC/yBf9j31uVWCGOzW1i1/Bqoi/MD0mLjH1SHJYRthmHuCcFj7jobxnwq9hSVJWEqoEXCXgkM5eErwxlwk1FqXR0qnZxuBP8xQvEwiJCSBh+N5MJAAcO5/9zRrvwJy5S3ZiwOX66cXyLHd6tkYvh4wGNU6ApSXeLK2mxFF5DhU822Q9csKKAQpJU2b9LPBsnS5bpTXIhf5HTKsy40MHWVgP/tXpMG9bU4lQLS4uF4JN/aYPKPvKWJ+zXn+KD4A0UlHTTJIVN41L1CqtyqD6+AWSuuFLPHDNfCyN+PviBM8kUjtBWX25obSpEaSTkGq5zIdIyL6xo0zvNbOAAyelKQslvAoEkfkq5YgNstoRxGqHvhcEJwLfj67Dz15w/tctlh9OrqhQASPFFnoJd4inTct8IhY/zWRxtT0lGTa6wa0pmlXttWUjKhEnQz/g4dqYhiK1lJ83k6NWKyaTVG1wYqzShXvSdWwxogan6LMK56hKvUFWXSXX87e82jDn5GJmfkVsWgv1sGcX2EoQj68aAh+tLdzR4Vkew9xEo21iIkTYZoV0VgtMSzOY5rlHIZCwTGczQ3raRgZtKY3WQSNrXc5j0Gtba32ixmpQQTYzwL331N57QAG162ismCRB0mBSRumyxVL9dgqSLy92ZYXuWBfjFySsFcx6IY4evIPolY6oWsHY2la1SbATKBUcWIscRLsO6BefntpSpLz5FUbt2JN194dyvYynjLMmk61xrxNLIstQ1RbBXUkNFinRyng8vazjwy5L5pCYlxmpV5nMq6mMy2Bgu028oFsMOBsZ31Gp3zGYwzhwmLErFwGD9fmpspSNKZQ9lGjlprrgGSnmTBwSdyZmxv7H7P1rCmt+nAPCftHLOmo6nsPc7+OnxTc6OWmMcyPjwV9HuqIXQ3hf06WqSuInJKiTopNUCYn8JHDrypAAMiEKhQmBuxxdSKVQ6tHIeLhd1OxT3uzhOfMHDZUCiRuScQvtWQt8eKdVsEJu0szR7SKZy/lTqNUKRVqNLkGjEQk1WjBUbOCLrF8Joe+ZKX+GIoXJSZgmkOFNvxwveqh1hsfpmdF6CNO+WzaMOPOYrMShf26X/ALRD4utlzBaO+zPyAvOy/B/CfLpFxxwKe1CGVw/SUhL+z+LHyYyQ/ppfSYw+WOy9nl0I9j/+DPtYfsH1K1X1w2VGbct9s+McYwX27O6bENWQZcbGwfN7UVQRDEm6LIO2bK6iu3jDlfMIr9xW9nQuq1XwR2/ws7kmGikXXQ3XI/Ww266VTk5GbMiA83gxccnuQGQ3gIFqRFrxB1eSbzSFmD3w3EXUgftihHNIPXaHHoHVO+kcUwLgyv+fW/QzZM3o2Cd/9v8Zh/oTUEhSLYnOn5QKupEgaLcPGYGcrVRxEAHmTeMhL6V6giX17hxxBupF18Nv6q5+uvV37BfFQQXUq8vvfQd9GNRCLjqsBtVefnXa7+Bdalf1HdwKFC3P+wmXoqH3pz+rQLCpv66vtK+0HUgPQXNYju6QVUQMaXPoB4AHnlWFz+1UfOY+YTpO/OStjHFDQGUX13WAx0YX2rfhe7qxLWNC1XRlqHLhLN1oKFZcB5Fj4ZPPL9D5/Zgbtbqzhof64ClzQvj3/x8b/jymjqyWgiBTas3/ob+pnxFkmQfKALwtPx7HkJLuYSGB1HLk+Pr2L3L2TwdjQmlKx1KioOSUCfv7QSKUf7UW9AWXHquoX34PqDz7+tGUyenogcLfe5x29Q2H4ylXM3yc+WV2NENf/DpOwyfGTioGv8/SbhQtJ41uak7MUS0Ad8/4s1vohqL2VG78u+sBdq9iG0jykSzYDH9FIN+kj4kGKdonBEv0Cl0Knry2aOjZiDwNdiM7q7cHo7CjQdw1tvQQdKnorqcNcjmF/bOQXbndr5BUrzeiGxZSnmtYy7y8bK//nACvVfosjYFCz32Cj2OCla+Zq6VrWoDP6f2Kzr0CzPlDQmZlZaEqbiCrOhydrGat75qVUyCTcqaajHzAIXcmOurYzUC3ACCHg4shxumwdEJL/kU9sHHr67w95y7cvpxfAPf/JT+g0M2ENUqBp+sMKPmndvo7BzHaqKy2clCtOW6pqDDsjwm6ZOH8eNzQKxaQWZy9k/iTBpneq81EbrAnJpvjkiWxbTXDNaly4q+j9+Rk9MdR06aP95aC+JHA0mUcwzvS4ZbNXJPrTAnp1YkL9Nmc4vzJWu8+EEBbMjRwLkmPWIzqJWTaBea4C5SF+y8k6RKTOAnRVuhiwdP+Oh/nZVbJ5KTvlzhl/p6GnheJ1djTx6RVY5WOAiKYCN4xaKbBr5GQGZ6sWD824isoFg2VlZulAdsX6LH0WP/+msNujE86il+uYQTl48/Mm3srVm+w39zzaX93vQJtJxSF6W0aPbo5EH2WPhzXfmvzDNvEjq8aBCloNdfoTfQ7NUhDkE9+Rd70KISgNpLXut2gHp3VivPvIYlQftU0d79I7iojxXa1B0ae/9p0BDYOIg2ogJwfgsFhckEqd9/eQLZY17zomA8eJEZJJSbpWYwo1elVNG6901++F42FhQU15OT6/12+49Y/l+kZErs3w7Hy8JCfzFZPZ6ffwXDnvydnBzyxG4HasbOBCYzYSeD8SkHx8H5FET29hQH11QTHDh/f8Gkjy+7HRdaVpUfvFDZgwWXV4E8nBd6/p/OC24NsOrawpCe28EzMy/SHfqIIif8aBBHqEaOA3VYNczKg/O8GmCFV0elKuZKC+pwh04pUeoNatZH8EdemFhqnSFbkjEceJ20YL8lYPY2R7PiOKpz16VMWRbmSddo6Hsoyx7mEcAKifwfUbLq8pdRmkwO1UjvakYvZ6LVKFCEm8fM/1tnLy6xff9tv4kDzn2Ofn7O+WmAze/Tlov5A+oHy1eupDk8SlmLxwXlTPNK882bxmB21KzHPGDfiB5A97/yVwrskC0IEbsXfoytOh8gyMmfabb480kEQOOIwoDIGTJk5N/oGXMTEMdiEDEoimxM7w8/OH1lQTt65Raw5X+6yH5oUV4DoeXrNNntnmYCKDoyinuVUkillkFKL+4t8dV6eFCs1hZImOOdErobRPwfm4Zsb6DabFDD1/6fTJUO1sBamK5CM2ZrwDn+9fuFAqgwFYCJClNODt12/vhWH/Uvyhvfia3YXn1oYnpMCGCTiu5TotDJSgmvWp6e+F9VoDvi6EJ0C5x2HOru0NstfrncbzlgkCTSmNsyYV2upcOiy4Uzt6XejiXpg2QMqzFVjJe3VNu9Nc3FiDkwLa1U2MCrTWN18jp4neARCXMVWrtEYiPX9yzBQM9MN6BMsdyelmEW4UmzP0tO6LHHx+Wk7X2BvOduPN/aX64qyClx26gvCldfevgkpYv1Aowfee6oLrag1mqXA12Br0BXgMSNYidTquvyzP+OTZadTaVz42ZG6sLznXJZTp43OGHTeyJTdYGbbKuzkSBPXU8qOauXSeHeK4pEIvIc2XKjTRn8xauDWbl+vCwCu3N5CY02xMyJuHNpEZW5OwZw/JZmhbrW2GdU1zYrLNamJ9TUjK8s4vIdsj4Z317EUyoVBz6SHIUcyC7VqYQLhF6XSrUxD04A8QkgYYEa8SABFq7LJvnUhfeqN2RrNrxX1Pfi/CJ3s/hpZuZTsXj5WXH8D/HDD5sYNDeJvYJAgVf8fjWaUmFdlpRUY6VU5FZLfoyKFYbl32IlVWZRqlg38xPorKgfAedLLWaDYY1qdXkB4/l0grQoNicqjRXAYQeAgWChaNCgjfvd1czxLzvxziKeHwSR5TOkPfDTypQXxYuMUYkt8HPgmR8QPuovrDHnMmDY2oftd7qtcfqyB4O0r8ucRjS96Bm3q+voXHnYFCSCfTw1I3N2/yCczJ2GPtg4naH15RwmSQ+QPPnEQfR7FDjtWrxzF7qrHWjGaLn4hD4Egi5xU8atH/QEdz/aEs5KLaXyAO2eP2GFf2OEZ7rsmu6nZZxHz7eHhGEtkK50GP5PItLzYk1erK76dHixd83aStfpaXgQKPerMoHbKeifzB7ZnMld6K5+Ckycxtb339UsPgYcEu/ev5uPQGoI+SD/yO8HQEdgiinW8y+8hX+YZ2itIu+2EZzZl/ZfUzcp5Hedr+0+l/ZRLJe0WsXf7UBI8dwWVvvqRqa/+Q397Y3zc04oylLlxW5EU9DK+a8Rorwy4UiRh6/Qvf3C8A29RClFcSnj4+qIoIy9Iyn4rGsqCgP8MgBCGENuSUAj3Yu/u+afOxI4Ra1Z7KQA1EWRadI1FaBrn8iFxs1stOZusw9lQ6HhDQVon3MdWlA6zM9tovoWl6MMle1bZ6De2RfQ1xwI7hfS+Qe3obcqt8tQf3Dq2IHecSrRxpl/UHvz7RhsBbobNEjXVdmV7BD6lF3eeaK1zHX4s4+DHpUElzwKerbHWTrmLf0Cf1G842M8ZzxPrfEt7lctaUey+ZORnWC3HSobEExFGXVh/Hf09+HxdTkBU4Ti8zEUjTwqRySaN7Z2BoPKxinNRedkzRGeeA4kYzSIyU0BZncJQlsKiqm5TROh1m7tBxfHb8KXxlHJ3/aCEnAJdoMCFFysyd4xPO57zHjMotyfHSguGeDPFWaNMGtFzonnYBxNQVein6N4o1lR/i6sCtDnVte4X8rRfq9Dzu68ZO2Zcz4oWk7H+tyO1XmxJlxbVNV4epqrcu0abzFot69NpSqZ9HJqmqx01J6eovCuWVuhOD29ymZ4pasasPozOPeKozmOgQE7+/Q0f9ccfA4I+PZ82RCHxP/K2e+bBWEzvj73qSu6NPjjnJi8GpPv3rvO/Ml48L6p63p0Ts+rRZWPt0i5iGaL1eBCqdxZMOl1s4Z4b2i/OEf+ULs07kOrL45nfTHxnYVWEqgBYc0Pxm3uDVHjXlPYBFsrGj0tc51+0jGNXXWnMTjkji4r/bmlP8918RwQwG1CaHDka5/+/ENAmVsnrmV4uzEbXcfEI8Wf4YaxdU3M8X1ktt8AUC6MjoXPVbuR6O6rLgzluCYbZPf7FvueMJ6YAbod0P7nnB3KXGAM1uXf+sC5k72w0joo29bG399b3WbcG1s3FtocC79oin7EdZ68Rvtyqa+M37JK0qsFV7FFlTsa3YxyG9Lk+MKYtm+39o2Jw5aN3SJzrB1av/OVXfb1zsWauZmg517Frx9SrIW5fNIURYp6SkkZPY+mtqg5KOf34OQJv/PaIzjvM8RO7hEhINL6xIB33D83Ka4X+0FmMoFfQ1JEyyjqgv6P1Sy9nl4+XTD7/NznslfXY5bbrIDn0kMVAgF/hg+z65X6zH5ijds12V825sH+Ar1PHVzKv06FXHmU8Cqkn8Lk6hsod8rJx/EBzf9ehZwB5d+ndS5T1CUkV1CUDmU6E9LTuOzlyzh18ZRCclAkepOip4M28XbqWATGdHEOr5DrlObkpGcxnhWMDIp3JeJAhOKrZ5g5OZwCQYE2x82BN2kTuL3rBqeonz1sY55Yfz1SRFlxTIZMPCIGdvckK7nBIGc5WAm9MdEp91dJTEsiR2NBGYMZSD57e3ropF+ZyntdAPcjOdcDp6i/MqIy7+6KnHFGFHuQWVTWoV7MuBIqsHvMva+FJ3bfYq/F8xsvFNs3hR9EH80aW7M/JubqrrljtFdJPzqzsdq0JCkliUxNSqKSY/W7wgCcJSl57MJSUrCmeYC1sLnX6+8F3y709ZbWh5OdtXBZb35vb3me1WYFHI8YVmVlwSrxKteeABITCQkJhOY4AGhaSrZvbp0WDiLJMDljGgt1Rbz+myCA3q1myAwIH/Kt8GgKCvuYj2mUoBbAuU158is33twsEHeEz/hg5Bp2ZwfDR3Z6YPCbnTaNPMcwFtpgQ+rEmDYl1QDPVxtwWhRdDq724CleGqM/tSo1TZ2iXPv2qv2amWGUt4GaGEI7FeIkIABE5QcVvfTQ88ueul57bL32AlPATOmVL+n1JaenrnOPIziDvg9Emj1n9JxRTaFTTW3Wk9qT2pPak9ozs2dmz8yemdVSYBQztKuKXlu9em7plfm4V5YXs40x9tIG9doKPbd0ZtqYvF4a3y7tOoJIFYEp+OJ2Zj4LOJHt42oXKz3dbW4fiNDmHgPMtmp/sza/D0To6a9uw+1vq3ekUKKrgPDmqh4EANo+ZBFaNugwS2mUTbjqUo/SBeo7a4JUO7pfNndD/SSs1rpvS6dR8gyw7aNChX0Qrs4I8Hyzo70epRu6VgzmE6jAhPoc7MfSSYmv6P5THTY/g0j7dYWALaUYrCWQrawFEicPSJxUPUmZRExOSRkttU0EP8GzfTIk8PyhefBDKsyR+Kruw6Sz7M3KNb2Ij1bytMv8Fv9kwrjt09D6dgd44UhvREPge8k1at8vnbUCGxnHBY96TZFg9BrSwB81M9vDGFw9PZVAX7E0cK0zUUOny3/x4fBEmQHfmkjz25Iyd+cwe8dp4oNz4Jm/Y9ONsyHYLFiHB3oHcBRZvJWodg+wC3eFCvtjZUBhiDoJT4yW2cpkMduYbOZzRsfsYfKZL5m9TAHa961esfv6tXt+h+2Ljn+Cpv0cQBhCXw489m8rRGQB+lN9ILukAQJPAZqwAk8JswGbRBzNTLgOl/P7VSyDVSjSwdv6aP0I+WFgqqQ3XZZS/zJgQogQeaqqxg1IR8tXATYv2OCaBi4ShLppk+HjqgWYoOADuwGbnnKEgImlbk+14DA8tSBd+oe+uHxQxuTBNQ3lJHRKUi0sBSJc/mMC0T60pxmHmufQ66hC0FtREgG6omb4qJZgO6xnzw0dd29ozJ3nMxEh1H/Zasc9mvrWnogHWzofgiWwxuV6nE91j77YJnpdYE8h0EzvTZx5ONN9cQ0/40YdyEi3ZVJHIOlO2fYYsfbDO1kJ8ukM6hv7TIqjZB0ybsKsSWnJOzPiv5tRagkn8OJ84jJMj178wyOqlKrKUnNHeVVcRaLaJk9t6gGqVlSp0ppPpHZrS9G6zMNVFBtAuWv5bj+AS0AQqyRDymYktPCG0JmjgK6yVPedBKfK1yr21+D2BxyHdni42FBJQwMug+XFpBGf/IEavkX2jJu1r00E6mrw0fd+mFONELTETzH2AdthN/xs7i8UDrjtDtv4M67hCOS+fw2F/85xdBnAtI7+W5NBElGxcAnJQYos0O5nrsSiVJSBspAMqZEVtaAFKtNRHVOLunRZ3+onTZAEJ2AYG7AV5+Mi3G0H7JTdshc+gxASFUQTsdSPeJX/w5u8z+/7vyyC5JA0Mpe0kzhZQlaSdWQzeTacZ59MKmmMb7bPxSlNbdojTh91GJALF8pRgyZ0YB4WYxP24UsYnErzdC7lhIjQwlbO4Rk+UUbZKlSvzuhb6XJ0qheerA6wxA5Xu96t7vEBX3GyYm365m3Z9u7h/WIHR493uddw7bfnrpyfXFZk9WjSlN7sztUEef5Avum1v3nv/bfirXsH3oUXlJVXRbXNKVa8Za1uczu7uMu7utu6v8d7rrWK1Rt9aXvn+7ovxzenDMuL5awcLkfKF+UfgYIy1IIGo1FoAjIhFBUiN9qPrqPbyIomkQ25STJOcRPuxOtwAz6Lh/AitThznBPOCwbV5tVG3A/cRnej+4N735113eU0wkhJWslwMv7u+6qabCfjdGlMJF1AceqjDXQBbad9dJhO0FnGZpI1sKmsa/Uf7LPMIQixSbyBL+dn+BAf4Vb+gE8LkTghV8m10i8Xyn5pkVelVT5RsDRDpWqCKlLb1HdqVM3pZXqUnqLtul4v0b36hv5Vu+o4L/RSb5i3zCvxWr0PvAqvwzvnjXg/eXPeyybF3+5f8R/6znZa0BnsC84Hzi42nBgWhQ3hgrA2PBFeCR+Gj0NnH5HCiZZFh2NBPCReES+I/52sSJYl55KJxJa4HIn+mhHGmLpZZDym1fSYY6bFdJlvzUlzzlw2V8xN86v53bz0YHuaTex4a7EltsG22bm22x6wh22FrbW1YwBAgA5WUQDYT95uL3/zRRA+hqYroSdARZ7p/BUEtD4u/PbZb1/xeTwg/h71fYFCdgQ+IJIjzCTod1qpZT6e8bgujU3qPpxdeiR81gLTP2rYKD660MiQRvGr+NgqIQxJY2PEXyU09l1KjWxx2wr0bRrSFXE4b+xIDFtikqZ2L8aKXdz4f9EghmI64xrZOgihIcI+k7UnFWYrmowTunp9LQCd/sQK+5K7KhsodTM8LgXJA6JkfKCtZjiRIVBBXrBAk6Dqss02hDZksNhGoQst53R4XrScTRh1ksiLauVTm6GxRrb8TGMOoWZVKmOP2Y2CZKW9mycqyQ6oQWjm8Aqas8MYq4e27usplYbRkrdy1oupz1P7NNxV2P+3oOQbgHRKbXoXeZaorBniRgQ/VUneS+18Pwr2xXuzK08kj/zDnK0TrJvepN3O2C8W/gbV6P05k1gilCvIxPG3mlRq98kHj1ZFW5zhX5NrW0srS1tzsJbi9ZrfErqIZD2cvf978M4zfpBI9z0gG+HstwX3XTbLMe2Q40gWS9YLtdpue4WXgMRFPGsI16St8vNf5zrw3WFcmDfYogmQFK+gD+rRUo0S5vbo3cvu45McocimsDjmbxQklrrvV9vhWDz50jDSt6+D/naYRgniVSTCTXL4PXtxzob4W61WOfiHJBLmQdGB2VNsr4243dpKecFnfpfF03dKGut7xAt/vvTk0x1/6P0DgFZ9OhQTWYUK8Pyg2wN/LaKY/otw1KDAPnE59FyhH3fg8KIwKPA/D2Jnz70YAu3QixPhIC/h2pVNDyg5vbwkEITVCEFkJEoRHcmSS/s+UmZXmQadSOxwzzDjU7CLcdOccDw9IW/yD+e2HglC1If8dMeMJdGUMFoTCXyi/JdvH0XiX/ftxVga3d/477+2n9lhiXgQx0fcMStofQJGPdol8kENiQM6e45D0vZUzHu8qbQ7lPCHYKHlkmG+8HEE/1tn94nU0xaKpsJqLgEL49Usmwqjv7sdiPaWoBgC50ASzgvjsmFJxBzpwFsPWSt1UYSkphsaXYIgMY+vSWZ/EpMHYegv5274UOmMeZO30qruYa4Yf8wDTa68FktKfgefWB6YDZVMcqyUWhySmE4MR0tkxeOG+WdLi0ZNJAG9OYEGWs7EvUwqtTzYWUm2lBt1aPnGk7tAPCoepmv0pgmLfFU2g4itMaofF6QdZ9qafHH4SQarE5RPCkbrg5pw69WqYCI6Yar0SgePBg+mGLoHqgiB5nCJ3AaC4iVL3M0y3qjNy3fNuerowWi1G+y67FxmfejYGBmtW+cAERbNSXp57Jy3Dyps3joV8/CF0QybGV3oJe+H4ObwvS9bUqvwm86C9NjHPd58mJMMFqX6/WaIfu1r64DTc7K0TNXj3cHZQXeUAM67v1EpF8vlk2YgWDTtQProVAHhrvowQ+l5NPT8uTFFK99BJxpqu2geESI8aPbJX+vfCZUPfgreenmFEsPNhVGYPIjaQ6nm/E+chQOb+/oib4KNjb0wChadlQa8crwYzs45Il23mNfrAvEyW0jos13zdAjtC1TKNSZqxtK/KaPC2K1q/3UkeJ28bQywmQ7pPCTnBcwvrGdBFtyydqaq2KGCjm71ouMcEzNHAeJweNNKMlwLQSYJ45yRdmCqIAxj5AClRHtemqXDONAnMkK+hySMs1yVVyKDRB9go2lXE3teYxjelLdDP0RsnDszg91uN9AbS4EmoggvgEpxQFl5hhMB0od9MTs8lV0oTFZ6ugnRw0sb1wS5RuyDJbIs2KO8CV2xfB5YdQ0yGkzFVIj9IvE2hdTBVh9qKXPIaMbvcG2z/XnfM8dPPFwarUiy9ASmfDoi/4NdmeR5CFVFnl92Am6TZHi8R922DzePAZjIhZepDIsmBXUhD/lHHhwhsX0VNhtHcHIG0bLAtQTNw6UnDo2g/6ezogZBVVml4rYlHBZuLQqC1lsqZqBUUDHQUmUsqMf14dpaMR3X5SHcvewRQ1GPDRkq5kK2sZgN6cCHgzvxTCRGErg1TIh6AzrY5RYU2lH81lvayEdJHZVJm03mEts2adTg7YjKAXJ61rotlDAWYyGsNVVdEvQzsJcTGk04VclTS07y2f9CLMwd8w6p59wbL33mDdQZh+7w/zuQPSsISVjGnJekGbcqv8IbnxWCl9eAoVO+A6/p2gnRlBUnAXysMpxUedzQkuS+pp09CQ622OTXIKajPs16g4RPXYd5Urrd3IDBexwMV82ZSFWvcwx8hSgC0HQCvlfUMkz0K+f2vO3Rr8CjIGJd1KU2BStNSUHXeU+cfXrqrnBST5wCAy/tM+iyC2Ct8VyZJz6c7xs/g8gRW9N7nKE3vglSzcftWDIKtYnCW4m/Ohn1vWZffHIARWt7byhpnaiqoasgbBRrOjIRBtpz+ZZFaOwyLKwvxBs+aIzNZE4vOUhJqiZVFyE9jExJqMPamxxel9eOfc9OkFipcQ8+GKCVWrMgOVmlF+DZbrcDetOAZl26L1ZOpRD4M2cYO7R8e7+3Uo/LdK/heLzSsvA+j1mTaFuwDqVD8qBaFCFDrKuDClig5sYTWCTjQkoJUNmBEKNpjgtpLHDhY2ZpyK6VDbrdWoXS0hhgt8/nM0yY2UfYnZos+kgq1Kq93DCZGfvbZ1Gcd3bw4crd12XJFhvGo2ylm/0wFHAo3GAKZPVCOhPTPpG0jTxMs8z0r62Aj/R9p/p5lVKVuga/o3drUYh4NHfmJkV3NIprDz/ihJMhG1WI/ZJxzItVUeyFgQKPeL7DKkLLjpF4BZClGPI2d9RYZpg3O8kgbYeiauKr+qIVtwk/rEbCcYIOJqvggDGq7aysaFg4vX4En1ofypdttpEBLDd8Rm4b4aSdq0fD5ra7JJlBZVW4i7CQtOpKs/xQ6UZVjCmTeqZCx+3KtAIKZdVooSLOQotC5esIuHiuOjeN0iXyIK5iie9JdFHpBepl5ucTj2SnGX5oPRnFhC2DAJjrs1seZUmOQ6+chadH8GTVXS5LnK9Q2nVWC7WN0HS7dngKEDq1HOXu22EBKVyH9lR0ymL2FcNfz/Xt10SB/VNC2y6Agz203KeCutoF9eHtIWB5fXEJ57KkLeZ6bzU0ia9cyz6nkhKiVWFaXSRpwOJNuTNNzsi6Ef7Ota1xdPaEfO1CTpaqv3Dp3Fy8O1onZtC4KN4zaeDBG6NlP8ZmzRrw/4F65/9T3Xyz8UFJsd8TwCLKRDAh7BkVKRQI5UpEfNjRN9hztlKEIHP+7edo+83ftRmkNdtIlkOvnuIMlVKoxL2LuSu0XU9p9nkzo4oOYt0G49OOkgao+F5uFYJTQycqnVMljmxATws9ClR8mggvK0/dzls9qVifvDOweYaEMJS7gHmVSPEfCElTkUacQ3YisoRQ3UidiZkVMhaUheaRccKySxEbdT6zndAMKU9fbE4QcTLte5KoOJrjSpmcD4aG+3B6m+tWYIZMNSd4QeAWYwTeXsgW85MTpc8W+sW+mZwjjrDRX5iIbO53+mGcu//D0zEIA4B3TbMTzTtqSEM62N6p7io0Ah4MbU3AV1WVU/JABEd8/whSpzuCqzNdOp8tg/EM3q+7dspuaT6YNnNZQQsFo4L+8dorjTNsIBUU11T6NEnq5C4Jcvi/19iHNcZ82ryyzQWPIwOBuf6II6SxiXHAekRO7Lr8IGE103xgPzbYgTe7JBcA+P18fl5zKLWCHXXJ9gPm+y7OvSUT84jSuON2s/zOX82cmKX4+gljEDy+DDMzyYHf6QCBkC/kFGL3QxqnlqrafHezhCyCLcuyxvvp9TnBKnLTTcJA9EppG8A6yw6TFJg3K2zrae3b/flL+0dHDLzxAUCeQacnJRa3hp6vELmoGVphnRK4FHh64Jadb7iuBwlBNXw3O6+5QVOVx1PMkZ7HFB0suIr8oPGaFyvCuWQQem9Zy541MGoFH7y1Ey54EwwVqwQN7jmKVCumJ0I4dzIxpsqyRVXcjpyuWFZJZT+s81B7jrBgVsFMelwVvj+iRKrE4cLntEj2tQEkAG+bJsPWF1JGuVhF6mlHc6+UJrtL5jInKEFK19ckBeOp+LYqrUZ5oXbPt9WIfMF5ogS4cXzP94Ou2/ArJYW9mYkTwrlbcxUdVnrZig7TsWMRhyKgj+S90fhlvlWGTaYjBZ2nfbJyY93Ez1QgPS2OgO2qZTtKzrWFKM6tc9F6WVVXuWSbkSvSs4qaRSmUmRMud8USIVjURGvODkFYn0pxCjxiGaJqlq0YjrOnB4Iu4BCecVusV9gle1uGSJu0fU4KEJNUKI7PzEfNFbmHm5JUI8wSwRDuBRlpjb2WcNN4cmlajeCtaFKFSrRpEWRJimqWOne+APo+nDngQoA/JchNl6LFcPRziiYaLyYR5hEkHYCgzuySLIa3EjSaruCKwanMzENxDEZ0oO7IjE9FCRnj6vqlsQ96UGAVtWSoMF8yVCocLRvEQYOOXIh+Kvg4td8mYq8VXuiyS1kmOqHgSKkMpqm1v/iYgLX5/oYsLzu2MHXdMpV8UWlzbK0y2FlPLFcRkk3QpSMFWqdCdV5VllzoGZruwTC1qOKGys0VMSec6navvejTls9VeWvZtKPDpae75BVNu2TCT7CnIXM+rmW3EfQ69ph3uY2HLizcOHpwH4p8kHSRPsiNHVmzgPAmDuK11v5Yy3Oyl0E5nLlDJzIck6HyOCZs9nIl79EjuGTQfEwSZlxvolycdeJJdB15bYMOpmwiXlg6mn9wpLivpkJI0Np5DoOzHulbh5PRYb2tRmTUosHGow5xyVpqSkHzP1OBYJSFTfpkfE/NKjDhNmoz+njM2gIJljofjzZObeXtTMtBVXMB1fOMiVoYJ/leqOcYlzUa6PvJILVJ01xUV0e/NfXnp7eXTTYvzsbrYekIXlPqnl1LHnKgjnSEQL2EIemfi8xy0h04wQu63UoQSOMZp3irMoop+N2aXLmdXJaJ5TO/kLdt8JoHhelg0z6CkCSp21BWV4JUy4S+YrNwQIWkFqwmOPyUtYDdrl+6zLFTUU/O0nPoSaq8BbXEkfjapbrqvFbsv/9AoW0kkgBJw3s7hMhDGk9kyCxsbs6AKQX+myKhyCbMESHBwhR2KMJqqolAa15G6naUlS8kWF4P8mZEVSu3z6M6JTucIfQ4SBTkIimBqN9exN/YZnnPElXcfMOUpLy0t6zbZV1EtH5c8mxBvHaKomt84qGVPbShBoQlS339rjagRwPiIL7wKvSzq6SuzMvNsac/lsG5t3hnna7mgQh2IkYMYbqjFwz3SmKSsg6HcSjREDF/0wKd4dO93xspZW58LCRRWAD7+fzno8fpR+Brzg+XD8v8TpWNeyJ4PPoofOj4B+dRed8Q2B2wagRLR8tP/X9mzkumhTGbdPaHj29mmK0bQWcD8Oq3/Dl+w2IxR79rXAnzKQ8M7N33HzIwMvnhO7qRnDS/wkSqgKmdPyiYMcIBduTi0Y8FCaw8xuKFPkFTr+3e/fHut28HyMeDPQtJDz+Ge8xLSojvAbJkkITjzeNEoCn7yServXs3QAf3dv3y6esT42KRtDkY9nrt2jWr371baaxb/9l/v/13Pmvo1MlTn+39OvOr+d8uuHDSL78Dz7wSKzIItKw99Wn/3YPnU5zlrNA6GrDd2U1cAU+5hdW/R/3Ojr97d9wDiv8Atwb7u8VvZF8hBVnW+kgQOk4+eoawrDkaqDEnFnyW6pc4P9Ax7mpIDEqJimFhkVDU2nrs2rqiKhEepKgHj2pkcVC7oBiCixPnMrgJXmy1RIKRjajDh4VgqY6LhjIfV3PCkId735n2xat9fOHVeWcx7ntQTXbUO36co/RpeA6f/ninrpp7tdr6oDTvHZaL1nGtZRlQZSu/hDlmSNv8PvD00x8XPjKPZ8D/Oz143wc7GSK+KZ9OaIMCX1tlTmn1Bvv6SPGAUruDaou6R48rZ+1i6ThuTamiP5lqqGQOLEpGKS9lrsMLLNzhWwkNvagBwhInt92hc1FwLGKehzv3CAOEpb94Pdll7JSGpMHUamHSSi7evjBZKtKAp25BFjjE2Cv1k2omnv/9JT7JurmxT1Ld17FmebebddxBfMx4fMDgrSLDR3vLrQTV+QTpIifd//gTqiZaceBnIER/4D0z3hAZHBasjo/vuLLVks8GLVUtIe1GfJ4JM6cvpjrDi7HBhAOecYqfuDQzzCUTkShLAjYjVr9GKfi0Cfudtx4GDRzse2zoOGrs4IUUi9fl5Vvm1RoJPIku+7OudvvGBN4fZFbkg7hWvfwKGk1fxckWE9B2RrD5RjlE68Ues8na2+y5CkLJfhU9Prlo1896VtiIqQyb5use2hh3cEVK5zDUYO17drtie9XEeflBViCzcbD4gU2wV1JMIlge5elp+7QsywSqJqypsTMzvaJoaJUoxA7p6tHlsgJbe9tAaxluZeUx0TbxmUASeiVg17u0INfx2qdU0/6rKLj/2EJeoe23R8ZfKLx6YSyAnRqdOQO1CLKZRSgqszPD207PVaozWjokqpvIPVC0SoD9Cdl/MZ28JcjLiApT0XYUM7dagtJSLemqTK896RXWk5bLOfvkzwve6q8NbrkYKtWF4QqLy6M4vp6qQ01VPy5leOhTd7Rnc1p1rJFocqq9mSC4lYE4vgCXI1wvzIX6jAylVnrd3q5K4oIcJjzLdUnuyQNhxQ9FOzExHoMgomB6cAKiHKB9wppypQwUMkJhWnGXSnet8AGNKIBCECUI1lcnHcs4w7QW5b1zcNrz7spqGQynloIXPZxx/3zeUj/dXjuDW+B6OjxcufPrK8f1MgfjyomIJlxxVJozSJzm1jyvL7dmpw+UHjaGtn95saxWw6LahNjhtbLOpJniUF3g8ymfIpb8lMVUVne9UlU/voVlA4QHOKnx9Ky2m3IYV68ec0nyPGsCQrO0rz6Foy59IK7sQfTRkr1AtsOtjxEEJPH+VkLz51n23tO/FCNA0nkPrtPLeSs/VSRDrpbSe7zR80sn9m1EezHwPqIrIHaiMQ9v0pfrc96Ydif53HYDlhKn5NH7cDiU4bxB7N3ZPpXWxhdMr48lAI2VL631EHFOi2DVTuZEISEIbuHDdCNKygS8WowxEnBqDiX0vGHVkquSSqtHjMFrUUsVoJnlF4ocEC5YRX+hAZKEZdiae3LcrySSY3IQbmaSVMS0Xt9JOoRIJqkIqh3u6N4Pfx8Ly0ENDSWIUqnVfm/htqZY/H7YxM7OVuOZrPM2zR5supKalbdfbnd1jWSzqQCQbhy10UKQSDQ8NBHUGIK1Cl1VYvCXEREVqESuaTiH6xVfMTGhUtkv/DSOj0AwzycLCOtHQuFPGia/UFtD2jlFqV0UInxk2ixyftKFtRIB102yIdp2Y1FcXrkSJ9xiG6+1/D6Fp7tlhEqFEoXgMptOl5S2i0g3Td+7ht4UdC9cEHohuM8+rJ146/YjapmAqshtSIWueIlYzV/9y+Hhhria7axnW6t9LLSiFfAL6yW8NPHlWj84GDX+i3Se7FlHK73pFwesQEy4nS/yLUeagKG6pjhapwuEWO5Aog9N/Swcx4pFn711wQpGN7eyC7CyQeiLn8ptoVMtWdNzmTAVHINDdV32A61KEDXakLXIgKPnJpQ4y6767SJIct0pTu0p3YJbWefcQlZoHt3nR112ycIH4XmS8xIFXWsgg6vvJVGgrLVo0PE2YaESJE9RpKFfEpdKLSdIPuMgM+r0vuBiZN3carRbKz1xA/3W09YFjO/xTr3D1ngGWw7xCXOOGEMZpeej+poLqTzFuasjzBuVsK6YmJFgLC907keYIRInYeDO6SsjK2lfcZQV2dHunGrXX9/lPBdGtJvlk13m13xZWjY9EO98FpQpJ3ANVerTcAr6Pzgr3AeN0CdAlJ8BdGjKK045Ghw56vths4hrCkWqoimrhxnUisGNsSpnwqTq9sGLj1EyAhE8wQU2d8ygJ9pGKphp5nJMF3N254CD2wEMt7wydbMAHux2DqDCuuEAbdLySQkVVO81b+/mYWz7UXQ6uCR2WIzFm92ne1cboDOIQ35bSSYr0rrFo4/j8XrL/K2p2p3OslzUhtS6kBNv8AhL/J0E8jR8Afb2Ss8XWHWe7sa0FFYsDeNsFdPimpygwbq2FuwKiyhv/fCM3ZEvl6KHYBga5HKNPp1veZtqFNS4Bncmi5LQo4yx6wWeamqvjKs9D7cf+1VTk3kEXcbchUSvImRIu1l2x5vuZOCsQ63KD+KZqgTyonEQadAT346K7LucMmJ93RTzvqkNTfMDJiONbRSaDIPtDBQal5/BCAkKhGWsMqbUDJP9IN6Ghhwre0AsCvdbrWY4GEclyrRfTGdyQ2VAlaLAKPCWBXJuTKGJoAnnCOgvKuAqlaacq5oWzPTP5EuVVpmoit5WcxWeRaV1njJkGMK+SHXBHbAZ2B3+/49/d9zqx9OXXUP8r71ChOrvYUAJo7kINA3PxCjsUto3CXThMlpQ7/fu+eBdrVPoL/Xwk5/a3EDbru/0SNtJD9drG17fOnMDT842V9vSPYMl646rhKCmOIxnu6OR5FVp3ECjC/IovG6gnpxbUP9i2GtLS2rLXLjGyTvhqHaOTdY8yERlYq739r/9XI+/iDpge3IY53JxyP5WR2V26VXPkfgsXQZ3NavjqwtQ69hjtUa3mxNBk011h1Ln0rWkh3ESx+PgQMpA2/YwNKIvVGWDMpUfXCgdWFv1gMFRFi/kY74/7LrQ2metVXgzXWb43oML1KK/Gi8HeSOWnBWx/DzjA/DpjkdghOjauARHSNLTH+kHdc9PaXz6Y6u+moPD/VmEBPfMDqzpG+n6d3AsXjVxvb4tIwhl9TG/7uu74ClPUmKx+4JobaCVkO6sZ1oZYsK0hOzgTVv5e7tP7yEUx2siz3Eivsc3pCbiMoaACjIMgLdoKmzl9a36zQl5jzCuTOxr773//nsPmsGDvMFNdi854kCz+fbjYVo++MUTkodYyaL8rLNBRTvgSobc3saBAAbvwX/h9lpznzZbXVHoNDkjIZp6y0Xk4U0//YM4SgET03V7axRgOrVDZG6PDtbKCOcv1YvFiThTOBeRvGJ+i423/O7TO5SLBFHXDuUzrLS44zOSkZFrFpJcCTB9GXag+DIxQ++YAC+LDFfXhp+kBUuRYqCDFqowKbAlUdxAPaG4DSmiDxrraAKPmbIpNCcgLkXHtkByIjHv5YCbFMEj7bNgYWMudkkemzjhhKcpMAH1dNHNsS3d9L+UF2AnQSv/PgXgnwdsdaa6DyBOi1e/+YeUqU1wEvg4kHRgesT1p+smxx7i22Ts/+6iwLwNyL7s2t0fLY/3W0+R796tvYJV+vPFgliw3jH48qS+kq7093UyvB/wG9iuVNGQhhQ0KR6sArG5/68rlHrfqlfyYFUUHT2Fd0lDkr35IHg3ipdvOnb2zNnjB65E/REU9KLWM58ZbX9AHyFY8PZvc2jr3jWqU9LpwSkffTw4DqTAn0DVkkYSaFelcnn4BvjfsVMHLz3dwrhd+Pfz+VN5BAICQh5b9vr/t8nBAUiI2KP85zSHqYPECipsaTOaRXwVdbJ0oCjhjYCVtCCTTgkKemPDqyaGGxJeJYZ8vhBYo/Sn5xkUlBBuCQoauyftx5GCVMQu9GDAymNMfypeS5zOIrw78O+fFDgkPT2kFSvIFCKIyMzHiB/niwQFpW1yYhroSgCBRvbqq6lQ1d58ATcL7wFBBwTx4lGsVfLKwECoFtdk9fQQgoIgh3vbYtuv/sFuqik+j8RQTPs/oFDWbBkWHaI3P7R6fdZ/8ZxrMLbfbEUuASdz4GsrBUICNS3Xwel5XQ6kwtNaOYwvYivWWq4UQTePWaIIyKu7J+x8hLJIRRzF6uEEurMp8DQ4u/0yrTTAYo/XJQvnygSg9xF5Ijqs1/D1H2ZV6IoXmcE//KPRxqnqQSfXe1+xgVvU5AbvE8Km9fvsonNlXrLxAniyMG+e+sRHT6j0sPqCR++imOvsIMQ2Kom9zqvwnrRspD9EbjkcG4iqE2IB79aqSFm1g74jU/x6RCIdNqOvQf1k9GRBeNZrtQUhntQk2Gdx5VT3ovoWmeD3clzTiWoVOFnrvVlVJD542dz73tslQS96W2BLzhZV/Y/n/yzL/dXeippmMl2KTHI86sZOp7PQqKOxWzG+s47T08np5doHUJm1KCiqVZfBTIP+dGWq+1L9/JomcfGSGfZN86IViRpns5AxSOUgkjwJ2ungWD/5HZw8SS+BozMDzQsFxIwpT3ZP6wMo/XGjXOzYWbP55LIYca4IbX7auvG3kmQ7557wzraYPsjKsCcKVbsIlPQ7oY9MsPtUTyl13Z8SVXm6IbbErMru7eLI8e3s9NeVFUIqF64sIX5jUXiPcZQTyvn9Tw+n11ewihYCCvxy8NRfezS9/uRGz3Nok3E1VmzcIr4/n3k87y+D5H23MrP8V2MGeh8GBDOVbyzCSLR++P3X0wK5rnuapml5mG/jH573d1MN8Xn41TQ/+PnXI99qF0D8/rzPpp/+z7bY3X9HHu1Xg2p/wG1Pm0fG7kKGYGqRnoxYD96ZPCTQIGWa/ag+SP7BfMj0dyW85ReewGcIVtGq1lSbUb/m1HrltX1qvyOSST4b/cBgq5d2t62stzuN6fpsjXkIuuDCRvClrqBukxUUJmYQYbd01QoccwMdIZvW6p2Lt6x5eeCsaZfHmaiUscyDK4h0Y4uuKoVZZuk8axu4eK0pB2iGDSo1QAQEbRa7uZBeUDNdCvSsYah0YiHFwRz7rpioJuMuh7ydPRNRKxh3N9cA0p7aVx/kQZuxMSO3a18t5IiTbkyfnso0hQnrsw92e/3Rxau08KrynOBlfmOqWokYpWXfDFsWdrCh6YYOlSPImzOcy2apk/TOsRz1n1FNUOkFYHWUXzIwDQJKqD4O8Vk822y1Luk5vEYsmgUi9NwVerFzzZBEimy9iDhzQTN6J42rLv2mZLLBqIkBkQUIvyV5B7vNdtRp+thvdv79O0M5BffLDLh0KcjPfOiBT1pRZeBqUJvOe7ybteCJmDWz+SlwmLecXToRqvIWkHiu7E2iSQ7nPiveUz/KgtB1h3jLDGaldliZG9ZUYyn7+jqr9EK35ipzFJQSaJ6sXhp7ISIcV/mh1lXDdrBNwRTFpqGpmX1FaWzAqHdN3rYTgEW06ug1s09NAlYtDyUmFrC0P+mTkJnjQbd2lBRJ2ktuKJ8QPGuiBi7p1W9ffeP9L4psEyrUcpqBQq9ieZQQaouC7lFr5el9oqGpMFQC/hAV4prnbK16VuKdWfloNgtsQxdvmYZ+fpHd/XRDgDxQehF254Arobbo2MAXFqdjw3JIWJmuCxKfs4JpVGXEVIucIXjsfJxdUimNFxKwOLStdLGnI43vup0Ow9OIiJhULl9X0RYN+sXugKVp1gosck3Cp03KNQG09vvb73386X//7xb29o+K1XqzWa/VG9pqrdERsSRhmSiKZrqDVlL7vBe01YLrsLnsBF9alrm9JyMButY6rQ7Pd+ps5bx+US2XS6eHu39/gMC7zt2DqfGm6UqrBaULtTQ6262dVVP0tG2eoRbl30affN6nO7KtvVD0CmLFWJfJjPHu1dPjk5PTqntc2k+MRLN8z7NwQh4topqrH0jGgM0noyhSJ0dPxT04e07reFwr8BqR8BkdYYv4yq8Xt1xgHVHdwGv2f25iOpj+2YKkK5FKGjlBGuF2sHtmklRejh0bOwjeMREvrXV54WabLEIpOeARN6yZa0vtNiOqnsXSlLSqeT5IWtQUlXlBVPC8XiYTjy1kvc+FALJeqVzBCIWWPdD6XcI54Q6/5+r1x7KoYO1Q2Rdk+tKIIxlExFy8Lv6B9pp8MJLLv1fMLdFLfQgCePa0JJmFP7/TgD9/+Dv3ZTbPPK6zuYLAWxBKkOr/NRwFeUwLoKt13UsrKfaB8Fm1Ud7qERr0nyBnnWA87xoDMv2LMvk8AGONzCeXjDrD9kxRvgwJIKYBePfjl5tevv6z7P4rm+CYk7gPEMEAIOB/JFqUigM7nmyBMJZ3dHqIM+J+jkAhU2ycuAit5MWjzrOP+aAZV2nBojgqOZW2Kus8uKKCcUUyTRBo3BWlAUe1sNJi5g6AVHKgbDnPzgk8kNGUXNNRoh370EILGhK+nTVdJNAagm/HCs5BTigaYjQIDtXRoGxmvS45q2Qhnnv60coelPozeF/r9/OhvCczy0CzqX/xkbekzFX66ssZCFClDQ41rzzO+/3oGqVP/rKU0C38ILst5bKL/3+z8BE71DTQyin76j9HrUAl3zr3h9LoqG5cctO5L0bdhyOS7ihMu8FO+cYu/mMX+jepdZRKoV3YnBaP4v+p5rI86y6sas4RuoWW+h8+Q8x6jL9d58JboiIVeTgEoBYOcwMHI1GYoYErnFd8mTfv4y2RI/VBhIYqGSo5xqoZYEreV57GBAaLd3JtzsWPP9zSU5QH1j3Qd11cP3KPHBMllLQQJ42mHzTkeLyUgXE5cfJLj+Q9LkWvh4mNoH23P6fF/2SM4WznlVbx5Z0h2WDd7c71Ho9jsB46e9y8fjXsHceJQuWG2PrGbnUoeGm8yUlv8RlDncQ+JVkeTwEnDp9zL29zAnebC/TNo1rL0MVRbtOeDbVQIQsmxXj0gjg1FFXUwVeGapPojM6jDP14iPbU+J6DAfp7jgAFHwAeLvxvHsErgR7DksMTROWkJxFnhfciMK2eRkhMeyzCE70PAWSiZ2S8NvJ62sTtaUBn3nuDn/t+CUgd8EyQ6PRLIVSuZ0GEmOiLYRDK7Pd7PrBFA79S9XK0KlXHp5xJhVYazUr51Gth1aBew1kjg17HD4SHrHm4Fup4r4znSXzKFa37tPV4nAZMriq57j5Js0NxLYgKhfhKV6nWqlx5Nmohx+New+Wa+Q65dcncifrUWW54kKu+3UUbhMVXcTdywU1uNuMbphDgjsyvEtf7KdNaKGMvyIp1bWkozAuD8g1l7eiNZj+LmeG9KpkSpbAfUFGB5yiq+SXXfFfKr8ZhbRnm/nW/Bpxys7K9rYrvcEubspblZb0dz+BOeelmaUPiLpq/X8haZzr6gjoPYIKLIcIV6fbb7IBSb2LySvWMSIVh192wBhtHuituGnXLeuE356skcMMdmb5V5lsnvOVXUruGR7rtB1oj3iWvM5V+8R6dWO2L1ajn1+8DiAYGz8k1miNrshn4Sou7dpilXSd2sibQGuKR8nTAzDZXZ7/bDnsd9lcvJXEosNTfOL1nvv322U187IUBm+w2zv2tMuYWDf+/SJCYIERD3jBo3ksOr5nCCmR7kbQQ2OlfDlgKDT/qhCAfWAKTVCVUIFMTCn2+E+tr3+t30imndel2wUVeMPRmSst2XEJZUVZcSKVN3bRdP1jnQxyneVkPx9P5krbr7f54/vj56/efv//+g2lo6ejDfQZGVGGh87y1ERapTjxE8MRTZ/ClSLbGZwZsiBlClICsQEOimNEhJiV+tp5wbOHxVLw8mHx2DgUKORXBzeRSzM2jRKky5bwqVKpSzafm6+cdDc0N2r+gfghzder6jvpfD0wgksgUKo3OYLLYHC6PLxCKxBKpTK5QIipUrdHqYgWtD3wHR5MWvHqD0WS2WG12h9Pl9nh9flZ4GrCWkIIM7QMvxN7/71s/D+yjkyzJcvaR5jo8WX+qeCMiw06oAJatdzf/fxviDniYs50O39NWHVlQq0XUH7BNJOEWsAtZ+JQC6iFYryH0dky4QyEpHMLY7RIwqOc0IOTHQCm27cz2dFJfS2t+m4h9JYHKUxZ/3CVZs6t9PuUkuFsCYjRwqLZD7Wcr105EMzeKog2sVgvAQ8kCdiGg9IztNd1BAa2QAkdZ8GICd9JFBua8QDjWa5rOWmKoAodCGg6KkZnRpvASwFwcF1Pi2ySuOd/5pMIe8lcLKCtqqwvvEAgdarFpIwWZMRSaaySbK0M0XV57EzUp8WmGe1WFsDJH85ozQDv13so61NrxoFaexI6PHTMIRymW6xVxbGG/wtFsaQApwKLYpfktyH3j6erc79tjrOqRPXI9hyamaaAezV6Iw4Tcfo9uMp9kCtlwWCQkdQVFfqDTSjTuPWTDAZZ7I80Ys7iRRk8z5qYgo0a6uOXuPWrd/W6OPj48PnYcmBY3D5yc8EXX8yi0UZLZV+bRsNyjt+uDnj8+VM8pHU+kUSZ2j4j86N6DCvlqDcPGHXtwhdUznoC/i1z7CwJquBCaN9AiadhvqmpyuyUsBvG+KKa0G9ARyLXAGofNyKHDXRrDhzT53JHiJjGxNz/S1YwH811K+hRlULwi4+1SCTTzda4IT1PCa6w2iNQkFrxRpvSANT5OOcV43GcME9k3DoWkw0zasRzwjAa5QShObg60bEiyNR+YDlsaUY5FRaj24gUEjEKOdx0jUMjS152iOKAi6znN5ClY6+aQGyg/PmzqAppe/TplnFb8KaaqRSFIlDk7YDUIXBwkk7bzRe6U8VZufX2Us2C8eHJ+lwrxATkSNdSQUPNF4pwDVKYv2Pr1LO4dn6JR/Jn+eoq7ltPCnngDq88an2NdKoXqdm0GGBl9oD+iCgJquEFpPPT4IlJVxt2bVNyhnIDb79BtuqmL0/UC4p84EzV3O04zpcu2hHTvclQQHPraEFXLbC3gTNBbCw81EPB6YbgVhi7SQq59Ez3MnLKitWcJJJOl9CMpn2ngu6AGy9lEF+k1iAM4nyWBwIEwpxODYS0qRUgMnuo2+S0bUJGj9PBNnBZeVsBozZ/wB2g69LwLrOVINXQ3jP3/Vw71ve2/7zs=) format(&amp;#x27;woff2&amp;#x27;);&#10;      unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }&#10;  &amp;lt;/style&amp;gt;&#10;  &amp;lt;style&amp;gt;&#10;    /* ==========================================================&#10;       THEME VARIABLES — switch by toggling [data-theme] on &amp;lt;html&amp;gt;&#10;       ========================================================== */&#10;    :root,&#10;    [data-theme=&amp;quot;dark&amp;quot;] {&#10;      --bg: #020617;&#10;      --grid: #1e293b;&#10;      --text: #ffffff;&#10;      --text-muted: #94a3b8;&#10;      --text-dim: #475569;&#10;      /* UI chrome and menu hints need more contrast than SVG .t-dim accents */&#10;      --text-faint: #7d8da1;&#10;&#10;      --panel: rgba(15, 23, 42, 0.5);&#10;      --panel-border: #1e293b;&#10;      --lane-fill: rgba(15, 23, 42, 0.22);&#10;      --lane-stroke: #334155;&#10;&#10;      --arrow: #64748b;&#10;      --arrow-emphasis: #34d399;&#10;&#10;      /* Opaque mask color used behind semi-transparent component fills&#10;         so the arrows drawn underneath are properly hidden. */&#10;      --mask: #0f172a;&#10;&#10;      --frontend-fill:    rgba(8, 51, 68, 0.4);&#10;      --frontend-stroke:  #22d3ee;&#10;      --backend-fill:     rgba(6, 78, 59, 0.4);&#10;      --backend-stroke:   #34d399;&#10;      --database-fill:    rgba(76, 29, 149, 0.4);&#10;      --database-stroke:  #a78bfa;&#10;      --cloud-fill:       rgba(120, 53, 15, 0.3);&#10;      --cloud-stroke:     #fbbf24;&#10;      --security-fill:    rgba(136, 19, 55, 0.4);&#10;      --security-stroke:  #fb7185;&#10;      --messagebus-fill:  rgba(251, 146, 60, 0.3);&#10;      --messagebus-stroke:#fb923c;&#10;      --external-fill:    rgba(30, 41, 59, 0.5);&#10;      --external-stroke:  #94a3b8;&#10;&#10;      --toolbar-bg:       rgba(15, 23, 42, 0.8);&#10;      --toolbar-border:   #334155;&#10;      --toolbar-text:     #e2e8f0;&#10;      --toolbar-hover:    rgba(15, 23, 42, 0.95);&#10;      --toolbar-menu-bg:  #0f172a;&#10;    }&#10;&#10;    [data-theme=&amp;quot;light&amp;quot;] {&#10;      --bg: #f8fafc;&#10;      --grid: #e2e8f0;&#10;      --text: #0f172a;&#10;      --text-muted: #64748b;&#10;      --text-dim: #94a3b8;&#10;      --text-faint: #64748b;&#10;&#10;      --panel: #ffffff;&#10;      --panel-border: #e2e8f0;&#10;      --lane-fill: rgba(248, 250, 252, 0.65);&#10;      --lane-stroke: #cbd5e1;&#10;&#10;      --arrow: #94a3b8;&#10;      --arrow-emphasis: #059669;&#10;&#10;      --mask: #ffffff;&#10;&#10;      --frontend-fill:    rgba(34, 211, 238, 0.15);&#10;      --frontend-stroke:  #0891b2;&#10;      --backend-fill:     rgba(52, 211, 153, 0.18);&#10;      --backend-stroke:   #059669;&#10;      --database-fill:    rgba(167, 139, 250, 0.2);&#10;      --database-stroke:  #7c3aed;&#10;      --cloud-fill:       rgba(251, 191, 36, 0.18);&#10;      --cloud-stroke:     #d97706;&#10;      --security-fill:    rgba(251, 113, 133, 0.15);&#10;      --security-stroke:  #e11d48;&#10;      --messagebus-fill:  rgba(251, 146, 60, 0.15);&#10;      --messagebus-stroke:#ea580c;&#10;      --external-fill:    rgba(148, 163, 184, 0.18);&#10;      --external-stroke:  #64748b;&#10;&#10;      --toolbar-bg:       rgba(255, 255, 255, 0.92);&#10;      --toolbar-border:   #cbd5e1;&#10;      --toolbar-text:     #334155;&#10;      --toolbar-hover:    #ffffff;&#10;      --toolbar-menu-bg:  #ffffff;&#10;    }&#10;&#10;    /* ==========================================================&#10;       SIGNAL FLOW — an opt-in, motion-forward visual preset.&#10;       The variables also target a standalone exported SVG, whose&#10;       root carries data-preset and data-theme directly.&#10;       ========================================================== */&#10;    [data-preset=&amp;quot;signal-flow&amp;quot;][data-theme=&amp;quot;dark&amp;quot;] {&#10;      --bg: #030711;&#10;      --grid: #15233a;&#10;      --panel: rgba(6, 14, 28, 0.78);&#10;      --panel-border: #1d3350;&#10;      --lane-fill: rgba(9, 22, 40, 0.5);&#10;      --lane-stroke: #2c4564;&#10;      --text: #f5fbff;&#10;      --text-muted: #9eb0c7;&#10;      --text-dim: #52667f;&#10;      --text-faint: #7890ad;&#10;      --mask: #07101e;&#10;      --frontend-fill: rgba(6, 182, 212, 0.14);&#10;      --frontend-stroke: #67e8f9;&#10;      --backend-fill: rgba(16, 185, 129, 0.14);&#10;      --backend-stroke: #5eead4;&#10;      --database-fill: rgba(139, 92, 246, 0.16);&#10;      --database-stroke: #c4b5fd;&#10;      --cloud-fill: rgba(245, 158, 11, 0.13);&#10;      --cloud-stroke: #fcd34d;&#10;      --security-fill: rgba(244, 63, 94, 0.13);&#10;      --security-stroke: #fda4af;&#10;      --messagebus-fill: rgba(249, 115, 22, 0.13);&#10;      --messagebus-stroke: #fdba74;&#10;      --external-fill: rgba(71, 85, 105, 0.24);&#10;      --external-stroke: #a5b4c7;&#10;      --arrow: #7890ad;&#10;      --arrow-emphasis: #2dd4bf;&#10;      --toolbar-bg: rgba(7, 16, 30, 0.86);&#10;      --toolbar-border: #29415f;&#10;      --toolbar-menu-bg: #07101e;&#10;    }&#10;&#10;    [data-preset=&amp;quot;signal-flow&amp;quot;][data-theme=&amp;quot;light&amp;quot;] {&#10;      --bg: #f4f9fc;&#10;      --grid: #d4e5ee;&#10;      --panel: rgba(255, 255, 255, 0.82);&#10;      --panel-border: #bfd5e2;&#10;      --lane-fill: rgba(232, 243, 248, 0.62);&#10;      --lane-stroke: #a9c5d5;&#10;      --text: #102638;&#10;      --text-muted: #587287;&#10;      --text-dim: #8aa2b4;&#10;      --text-faint: #668397;&#10;      --mask: #ffffff;&#10;      --frontend-fill: rgba(6, 182, 212, 0.09);&#10;      --frontend-stroke: #0789a1;&#10;      --backend-fill: rgba(5, 150, 105, 0.09);&#10;      --backend-stroke: #087f69;&#10;      --database-fill: rgba(124, 58, 237, 0.09);&#10;      --database-stroke: #7254c7;&#10;      --cloud-fill: rgba(217, 119, 6, 0.08);&#10;      --cloud-stroke: #b9670b;&#10;      --security-fill: rgba(225, 29, 72, 0.08);&#10;      --security-stroke: #c53a59;&#10;      --messagebus-fill: rgba(234, 88, 12, 0.08);&#10;      --messagebus-stroke: #c65f27;&#10;      --external-fill: rgba(100, 116, 139, 0.1);&#10;      --external-stroke: #607a8c;&#10;      --arrow: #7b97aa;&#10;      --arrow-emphasis: #0d9488;&#10;    }&#10;&#10;    /* ==========================================================&#10;       BLUEPRINT — a review-first drafting preset for deployment,&#10;       infrastructure, and technical design documentation. It keeps&#10;       the same semantic palette and geometry while trading glow for&#10;       precise grid contrast, squared materials, and drafting marks.&#10;       ========================================================== */&#10;    [data-preset=&amp;quot;blueprint&amp;quot;][data-theme=&amp;quot;dark&amp;quot;] {&#10;      --bg: #06131f;&#10;      --grid: #17425a;&#10;      --panel: rgba(7, 27, 43, 0.9);&#10;      --panel-border: #27627f;&#10;      --lane-fill: rgba(10, 43, 66, 0.36);&#10;      --lane-stroke: #34799a;&#10;      --text: #e3f6ff;&#10;      --text-muted: #91b8ca;&#10;      --text-dim: #557e92;&#10;      --text-faint: #739caf;&#10;      --mask: #0a2031;&#10;      --frontend-fill: rgba(26, 157, 193, 0.14);&#10;      --frontend-stroke: #66d9ef;&#10;      --backend-fill: rgba(31, 155, 124, 0.13);&#10;      --backend-stroke: #69dfbd;&#10;      --database-fill: rgba(120, 105, 196, 0.14);&#10;      --database-stroke: #b4a8ff;&#10;      --cloud-fill: rgba(197, 145, 43, 0.13);&#10;      --cloud-stroke: #ffd166;&#10;      --security-fill: rgba(199, 76, 104, 0.13);&#10;      --security-stroke: #ff8da1;&#10;      --messagebus-fill: rgba(207, 112, 49, 0.13);&#10;      --messagebus-stroke: #ffad66;&#10;      --external-fill: rgba(84, 119, 139, 0.18);&#10;      --external-stroke: #a7cad9;&#10;      --arrow: #78a3b7;&#10;      --arrow-emphasis: #64dfc1;&#10;      --toolbar-bg: rgba(7, 28, 45, 0.92);&#10;      --toolbar-border: #34799a;&#10;      --toolbar-text: #d8f3ff;&#10;      --toolbar-hover: rgba(18, 58, 83, 0.95);&#10;      --toolbar-menu-bg: #0a2031;&#10;    }&#10;&#10;    [data-preset=&amp;quot;blueprint&amp;quot;][data-theme=&amp;quot;light&amp;quot;] {&#10;      --bg: #edf7fa;&#10;      --grid: #b5d5e1;&#10;      --panel: rgba(249, 253, 255, 0.94);&#10;      --panel-border: #78aabd;&#10;      --lane-fill: rgba(210, 232, 240, 0.42);&#10;      --lane-stroke: #83b2c4;&#10;      --text: #123344;&#10;      --text-muted: #4e7486;&#10;      --text-dim: #86a6b4;&#10;      --text-faint: #668c9d;&#10;      --mask: #f9fdff;&#10;      --frontend-fill: rgba(8, 145, 178, 0.08);&#10;      --frontend-stroke: #087f9c;&#10;      --backend-fill: rgba(5, 128, 101, 0.08);&#10;      --backend-stroke: #08755f;&#10;      --database-fill: rgba(100, 75, 180, 0.08);&#10;      --database-stroke: #6757a8;&#10;      --cloud-fill: rgba(181, 120, 15, 0.08);&#10;      --cloud-stroke: #a86609;&#10;      --security-fill: rgba(190, 48, 80, 0.07);&#10;      --security-stroke: #b32f50;&#10;      --messagebus-fill: rgba(196, 81, 22, 0.07);&#10;      --messagebus-stroke: #b65120;&#10;      --external-fill: rgba(79, 112, 128, 0.08);&#10;      --external-stroke: #506f7e;&#10;      --arrow: #6d93a5;&#10;      --arrow-emphasis: #087f69;&#10;      --toolbar-bg: rgba(247, 252, 254, 0.94);&#10;      --toolbar-border: #8ab5c5;&#10;      --toolbar-text: #294f61;&#10;      --toolbar-hover: #ffffff;&#10;      --toolbar-menu-bg: #f9fdff;&#10;    }&#10;&#10;    /* ==========================================================&#10;       EDITORIAL — a warm, publication-minded preset for design&#10;       reviews, launch notes, and documentation. The diagram keeps&#10;       the same semantic palette and exact geometry, but trades&#10;       software chrome for paper, ink, ruled structure, and one&#10;       restrained vermilion accent.&#10;       ========================================================== */&#10;    [data-preset=&amp;quot;editorial&amp;quot;][data-theme=&amp;quot;dark&amp;quot;] {&#10;      --bg: #181611;&#10;      --grid: #39342a;&#10;      --panel: rgba(35, 31, 24, 0.96);&#10;      --panel-border: #625a4a;&#10;      --lane-fill: rgba(52, 46, 35, 0.46);&#10;      --lane-stroke: #726957;&#10;      --text: #f4eddf;&#10;      --text-muted: #b9ae9b;&#10;      --text-dim: #776e60;&#10;      --text-faint: #9d917e;&#10;      --mask: #231f18;&#10;      --frontend-fill: rgba(43, 133, 142, 0.16);&#10;      --frontend-stroke: #7fc6c7;&#10;      --backend-fill: rgba(63, 132, 92, 0.16);&#10;      --backend-stroke: #8fc29e;&#10;      --database-fill: rgba(117, 91, 141, 0.17);&#10;      --database-stroke: #c0a4d0;&#10;      --cloud-fill: rgba(170, 119, 49, 0.16);&#10;      --cloud-stroke: #d8ad68;&#10;      --security-fill: rgba(157, 69, 65, 0.17);&#10;      --security-stroke: #df9085;&#10;      --messagebus-fill: rgba(174, 79, 42, 0.16);&#10;      --messagebus-stroke: #df946f;&#10;      --external-fill: rgba(126, 115, 96, 0.18);&#10;      --external-stroke: #b8ad99;&#10;      --arrow: #948978;&#10;      --arrow-emphasis: #dd6b3d;&#10;      --toolbar-bg: rgba(35, 31, 24, 0.92);&#10;      --toolbar-border: #625a4a;&#10;      --toolbar-text: #eee5d5;&#10;      --toolbar-hover: #302a20;&#10;      --toolbar-menu-bg: #231f18;&#10;    }&#10;&#10;    [data-preset=&amp;quot;editorial&amp;quot;][data-theme=&amp;quot;light&amp;quot;] {&#10;      --bg: #f2eee5;&#10;      --grid: #d8d0c2;&#10;      --panel: rgba(251, 248, 241, 0.97);&#10;      --panel-border: #c4b9a6;&#10;      --lane-fill: rgba(229, 221, 207, 0.42);&#10;      --lane-stroke: #b8aa94;&#10;      --text: #242018;&#10;      --text-muted: #6f6658;&#10;      --text-dim: #a09788;&#10;      --text-faint: #817767;&#10;      --mask: #fbf8f1;&#10;      --frontend-fill: rgba(31, 117, 126, 0.09);&#10;      --frontend-stroke: #287e84;&#10;      --backend-fill: rgba(42, 119, 75, 0.09);&#10;      --backend-stroke: #397b53;&#10;      --database-fill: rgba(105, 75, 130, 0.09);&#10;      --database-stroke: #765d86;&#10;      --cloud-fill: rgba(157, 103, 31, 0.1);&#10;      --cloud-stroke: #9a671f;&#10;      --security-fill: rgba(153, 58, 52, 0.09);&#10;      --security-stroke: #9e463f;&#10;      --messagebus-fill: rgba(182, 70, 27, 0.09);&#10;      --messagebus-stroke: #ad4b25;&#10;      --external-fill: rgba(101, 91, 75, 0.09);&#10;      --external-stroke: #746b5e;&#10;      --arrow: #8a806f;&#10;      --arrow-emphasis: #bb4c23;&#10;      --toolbar-bg: rgba(251, 248, 241, 0.94);&#10;      --toolbar-border: #c4b9a6;&#10;      --toolbar-text: #40392f;&#10;      --toolbar-hover: #fffdf8;&#10;      --toolbar-menu-bg: #fbf8f1;&#10;    }&#10;&#10;    * { margin: 0; padding: 0; box-sizing: border-box; }&#10;&#10;    body {&#10;      font-family: &amp;#x27;JetBrains Mono&amp;#x27;, ui-monospace, SFMono-Regular, Menlo, Consolas, &amp;#x27;DejaVu Sans Mono&amp;#x27;, &amp;#x27;Liberation Mono&amp;#x27;, &amp;#x27;Noto Sans Mono CJK SC&amp;#x27;, &amp;#x27;PingFang SC&amp;#x27;, &amp;#x27;Hiragino Sans GB&amp;#x27;, &amp;#x27;Microsoft YaHei&amp;#x27;, monospace;&#10;      background: var(--bg);&#10;      min-height: 100vh;&#10;      padding: 2rem;&#10;      color: var(--text);&#10;      transition: background 0.2s ease, color 0.2s ease;&#10;    }&#10;&#10;    html[data-preset=&amp;quot;signal-flow&amp;quot;] body {&#10;      background-image:&#10;        radial-gradient(circle at 18% -8%, rgba(34, 211, 238, 0.14), transparent 34rem),&#10;        radial-gradient(circle at 92% 18%, rgba(139, 92, 246, 0.12), transparent 30rem);&#10;      background-attachment: fixed;&#10;    }&#10;    html[data-preset=&amp;quot;signal-flow&amp;quot;][data-theme=&amp;quot;light&amp;quot;] body {&#10;      background-image:&#10;        radial-gradient(circle at 18% -8%, rgba(6, 182, 212, 0.12), transparent 34rem),&#10;        radial-gradient(circle at 92% 18%, rgba(139, 92, 246, 0.08), transparent 30rem);&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] body {&#10;      background-image:&#10;        linear-gradient(var(--grid) 1px, transparent 1px),&#10;        linear-gradient(90deg, var(--grid) 1px, transparent 1px);&#10;      background-size: 32px 32px;&#10;      background-position: -1px -1px;&#10;      background-attachment: fixed;&#10;    }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] body {&#10;      background-image:&#10;        linear-gradient(90deg, transparent 0, transparent 5.4rem, color-mix(in srgb, var(--security-stroke) 18%, transparent) 5.4rem, color-mix(in srgb, var(--security-stroke) 18%, transparent) calc(5.4rem + 1px), transparent calc(5.4rem + 1px)),&#10;        repeating-linear-gradient(0deg, transparent 0, transparent 31px, color-mix(in srgb, var(--grid) 36%, transparent) 31px, color-mix(in srgb, var(--grid) 36%, transparent) 32px);&#10;      background-attachment: fixed;&#10;    }&#10;&#10;    /* Gallery/embed mode keeps the generated artifact as the source of truth&#10;       while presenting only its diagram surface inside a proof card. */&#10;    html[data-embed=&amp;quot;true&amp;quot;] body {&#10;      min-height: 0;&#10;      padding: 0;&#10;      overflow: hidden;&#10;      background: var(--bg);&#10;      background-image: none;&#10;    }&#10;    html[data-embed=&amp;quot;true&amp;quot;] .toolbar,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .header,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .cards,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .diagram-nav,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .overview-map,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .focus-chip,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .route-probe,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .semantic-lens,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .diagram-guide,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .node-finder,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .guided-views { display: none !important; }&#10;    html[data-embed=&amp;quot;true&amp;quot;] .container { max-width: none; }&#10;    html[data-embed=&amp;quot;true&amp;quot;] .diagram-container {&#10;      padding: 0.5rem;&#10;      border: 0;&#10;      border-radius: 0;&#10;      box-shadow: none;&#10;    }&#10;    html[data-embed=&amp;quot;true&amp;quot;] .diagram-container svg { min-width: 0; }&#10;&#10;    /* Share Chapter Cue lives in the HTML viewer layer, not inside the SVG.&#10;       It gives one-shot embeds a title, authored note, truthful stop order,&#10;       and lifecycle state while canonical diagram geometry stays untouched. */&#10;    .share-chapter-cue { display: none; }&#10;    html[data-embed=&amp;quot;true&amp;quot;][data-share-playback=&amp;quot;true&amp;quot;] .share-chapter-cue:not([hidden]),&#10;    html[data-embed=&amp;quot;true&amp;quot;][data-share-moment=&amp;quot;true&amp;quot;] .share-chapter-cue:not([hidden]) {&#10;      position: absolute;&#10;      z-index: 18;&#10;      top: 0.85rem;&#10;      left: 50%;&#10;      display: grid;&#10;      grid-template-columns: auto minmax(9rem, 13.5rem) minmax(0, 1fr);&#10;      align-items: center;&#10;      gap: 0.45rem 0.85rem;&#10;      width: min(52rem, calc(100% - 1.5rem));&#10;      min-height: 3.35rem;&#10;      padding: 0.55rem 0.75rem 0.65rem;&#10;      overflow: hidden;&#10;      border: 1px solid color-mix(in srgb, var(--frontend-stroke) 42%, var(--toolbar-border));&#10;      border-radius: 0.75rem;&#10;      background:&#10;        linear-gradient(115deg, color-mix(in srgb, var(--frontend-fill) 52%, transparent), transparent 45%),&#10;        color-mix(in srgb, var(--toolbar-menu-bg) 92%, transparent);&#10;      color: var(--toolbar-text);&#10;      box-shadow: 0 14px 42px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.045);&#10;      backdrop-filter: blur(16px);&#10;      pointer-events: none;&#10;      animation: archify-share-cue-enter 280ms cubic-bezier(0.22, 1, 0.36, 1) both;&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .share-chapter-cue {&#10;      border-radius: 0.2rem;&#10;      background:&#10;        linear-gradient(90deg, color-mix(in srgb, var(--frontend-fill) 46%, transparent), transparent 36%),&#10;        var(--toolbar-menu-bg);&#10;      box-shadow: 0 10px 28px rgba(0, 0, 0, 0.2);&#10;      backdrop-filter: none;&#10;    }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .share-chapter-cue {&#10;      border-color: var(--panel-border);&#10;      background:&#10;        linear-gradient(90deg, color-mix(in srgb, var(--security-fill) 58%, transparent), transparent 42%),&#10;        var(--toolbar-menu-bg);&#10;      box-shadow: 0 10px 30px color-mix(in srgb, #000 18%, transparent);&#10;      backdrop-filter: none;&#10;    }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .share-chapter-state { color: var(--arrow-emphasis); }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .share-chapter-state::before {&#10;      border-radius: 0;&#10;      box-shadow: none;&#10;      transform: rotate(45deg) scale(0.8);&#10;    }&#10;    .share-chapter-index {&#10;      display: grid;&#10;      gap: 0.12rem;&#10;      min-width: 5rem;&#10;      padding-right: 0.75rem;&#10;      border-right: 1px solid var(--toolbar-border);&#10;    }&#10;    .share-chapter-state {&#10;      display: inline-flex;&#10;      align-items: center;&#10;      gap: 0.36rem;&#10;      color: var(--frontend-stroke);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.14em;&#10;      text-transform: uppercase;&#10;    }&#10;    .share-chapter-state::before {&#10;      width: 0.38rem;&#10;      height: 0.38rem;&#10;      border-radius: 50%;&#10;      background: currentColor;&#10;      box-shadow: 0 0 10px currentColor;&#10;      content: &amp;#x27;&amp;#x27;;&#10;    }&#10;    .share-chapter-cue[data-state=&amp;quot;playing&amp;quot;] .share-chapter-state::before {&#10;      animation: archify-share-cue-pulse 1.15s ease-in-out infinite;&#10;    }&#10;    .share-chapter-count {&#10;      color: var(--text-faint);&#10;      font-size: 0.5rem;&#10;      font-weight: 700;&#10;      letter-spacing: 0.08em;&#10;      text-transform: uppercase;&#10;    }&#10;    .share-chapter-copy { min-width: 0; }&#10;    .share-chapter-copy strong,&#10;    .share-chapter-copy small,&#10;    .share-chapter-route {&#10;      display: block;&#10;      overflow: hidden;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .share-chapter-copy strong {&#10;      color: var(--toolbar-text);&#10;      font-size: 0.6875rem;&#10;      line-height: 1.35;&#10;    }&#10;    .share-chapter-copy small {&#10;      margin-top: 0.08rem;&#10;      color: var(--text-muted);&#10;      font-size: 0.5rem;&#10;      line-height: 1.35;&#10;    }&#10;    .share-chapter-route {&#10;      color: color-mix(in srgb, var(--frontend-stroke) 76%, var(--text-muted));&#10;      font-size: 0.5625rem;&#10;      font-weight: 650;&#10;      letter-spacing: 0.015em;&#10;      text-align: right;&#10;    }&#10;    .share-chapter-progress {&#10;      position: absolute;&#10;      right: 0;&#10;      bottom: 0;&#10;      left: 0;&#10;      height: 2px;&#10;      overflow: hidden;&#10;      background: color-mix(in srgb, var(--toolbar-border) 72%, transparent);&#10;    }&#10;    .share-chapter-progress span {&#10;      display: block;&#10;      width: 100%;&#10;      height: 100%;&#10;      background: linear-gradient(90deg, var(--frontend-stroke), var(--database-stroke));&#10;      box-shadow: 0 0 12px var(--frontend-stroke);&#10;      transform: scaleX(0);&#10;      transform-origin: left center;&#10;    }&#10;&#10;    /* Presentation Stage is a viewer-only layer: it gives the live diagram&#10;       the viewport while keeping guided views, theme, focus, and exports real.&#10;       Embed mode wins when both query parameters are present. */&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) body {&#10;      height: 100dvh;&#10;      min-height: 0;&#10;      padding: 1rem;&#10;      overflow: hidden;&#10;    }&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .container {&#10;      display: flex;&#10;      flex-direction: column;&#10;      gap: 0.75rem;&#10;      width: 100%;&#10;      max-width: none;&#10;      height: calc(100dvh - 2rem);&#10;    }&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .header {&#10;      flex: none;&#10;      min-width: 0;&#10;      margin: 0;&#10;      padding-right: 23rem;&#10;    }&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .header-row { margin-bottom: 0.25rem; }&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .subtitle {&#10;      overflow: hidden;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-views {&#10;      flex: none;&#10;      margin-bottom: 0;&#10;    }&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container {&#10;      display: flex;&#10;      flex: 1 1 auto;&#10;      align-items: center;&#10;      justify-content: center;&#10;      min-height: 0;&#10;      padding: 0.75rem;&#10;      padding-bottom: calc(0.75rem + var(--archify-nav-reserve));&#10;    }&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container &amp;gt; svg {&#10;      flex: 1 1 auto;&#10;      height: 100%;&#10;      min-height: 0;&#10;      width: 100%;&#10;      min-width: 0;&#10;    }&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .cards { display: none; }&#10;    html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) #btn-present {&#10;      border-color: var(--frontend-stroke);&#10;      color: var(--frontend-stroke);&#10;    }&#10;&#10;    /* The reader owns only the outer scale. Wide diagrams keep one authored&#10;       SVG/viewBox while the runtime chooses a desktop width from the actual&#10;       vertical budget. This avoids device-specific files and breakpoint&#10;       jumps between a laptop and a tall monitor. */&#10;    .container {&#10;      width: 100%;&#10;      max-width: var(--archify-reader-width, 1440px);&#10;      margin: 0 auto;&#10;    }&#10;    @media (min-width: 768px) and (max-height: 920px) {&#10;      .header { margin-bottom: 1rem; }&#10;      .diagram-container { padding: 1rem; }&#10;      .cards { margin-top: 1rem; }&#10;      .card { padding: 1rem; }&#10;    }&#10;&#10;    .header { margin-bottom: 1.5rem; padding-right: 29.5rem; }&#10;&#10;    html[data-preset=&amp;quot;signal-flow&amp;quot;] .header,&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .header,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .header { padding-right: 29.5rem; }&#10;&#10;    .header-row {&#10;      display: flex;&#10;      align-items: center;&#10;      gap: 1rem;&#10;      margin-bottom: 0.5rem;&#10;    }&#10;&#10;    .pulse-dot {&#10;      width: 12px;&#10;      height: 12px;&#10;      background: var(--frontend-stroke);&#10;      border-radius: 50%;&#10;      animation: none;&#10;    }&#10;&#10;    html[data-motion-capable=&amp;quot;true&amp;quot;] .pulse-dot { animation: pulse 2s infinite; }&#10;&#10;    @keyframes pulse {&#10;      0%, 100% { opacity: 1; }&#10;      50% { opacity: 0.5; }&#10;    }&#10;&#10;    h1 {&#10;      font-size: 1.5rem;&#10;      font-weight: 700;&#10;      letter-spacing: -0.025em;&#10;    }&#10;&#10;    .subtitle {&#10;      color: var(--text-muted);&#10;      font-size: 0.875rem;&#10;      margin-left: 1.75rem;&#10;    }&#10;&#10;    html[data-preset=&amp;quot;signal-flow&amp;quot;] .header-row::after {&#10;      content: attr(data-preset-badge-signal-flow);&#10;      margin-left: auto;&#10;      color: var(--frontend-stroke);&#10;      border: 1px solid var(--frontend-stroke);&#10;      border-radius: 999px;&#10;      padding: 0.28rem 0.6rem;&#10;      font-size: 0.625rem;&#10;      letter-spacing: 0.12em;&#10;      opacity: 0.82;&#10;      box-shadow: 0 0 20px rgba(34, 211, 238, 0.12);&#10;      white-space: nowrap;&#10;    }&#10;&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .pulse-dot {&#10;      width: 10px;&#10;      height: 10px;&#10;      border: 1px solid var(--frontend-stroke);&#10;      border-radius: 1px;&#10;      background: transparent;&#10;      box-shadow: inset 0 0 0 2px var(--bg);&#10;      transform: rotate(45deg);&#10;      animation: none;&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .header-row::after {&#10;      content: attr(data-preset-badge-blueprint);&#10;      margin-left: auto;&#10;      padding: 0.28rem 0.55rem;&#10;      border-top: 1px solid var(--frontend-stroke);&#10;      border-bottom: 1px solid var(--frontend-stroke);&#10;      color: var(--frontend-stroke);&#10;      font-size: 0.5625rem;&#10;      font-weight: 700;&#10;      letter-spacing: 0.14em;&#10;      white-space: nowrap;&#10;    }&#10;&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] h1,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .card h3 {&#10;      font-family: Georgia, &amp;#x27;Times New Roman&amp;#x27;, &amp;#x27;Songti SC&amp;#x27;, STSong, serif;&#10;      letter-spacing: -0.02em;&#10;    }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] h1 { font-size: 1.72rem; font-weight: 600; }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .pulse-dot {&#10;      width: 9px;&#10;      height: 9px;&#10;      border: 1px solid var(--arrow-emphasis);&#10;      border-radius: 0;&#10;      background: var(--arrow-emphasis);&#10;      box-shadow: 0 0 0 3px color-mix(in srgb, var(--arrow-emphasis) 14%, transparent);&#10;      transform: rotate(45deg);&#10;      animation: none;&#10;    }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .header-row::after {&#10;      content: attr(data-preset-badge-editorial);&#10;      margin-left: auto;&#10;      padding: 0.32rem 0 0.24rem;&#10;      border-bottom: 2px solid var(--arrow-emphasis);&#10;      color: var(--arrow-emphasis);&#10;      font-family: Georgia, &amp;#x27;Times New Roman&amp;#x27;, serif;&#10;      font-size: 0.625rem;&#10;      font-style: italic;&#10;      font-weight: 600;&#10;      letter-spacing: 0.08em;&#10;      white-space: nowrap;&#10;    }&#10;&#10;    .diagram-container {&#10;      --archify-nav-reserve: 0px;&#10;      background: var(--panel);&#10;      border-radius: 1rem;&#10;      border: 1px solid var(--panel-border);&#10;      padding: 1.5rem;&#10;      padding-bottom: calc(1.5rem + var(--archify-nav-reserve));&#10;      overflow: hidden;&#10;      position: relative;&#10;    }&#10;&#10;    html[data-preset=&amp;quot;signal-flow&amp;quot;] .diagram-container {&#10;      position: relative;&#10;      overflow: hidden;&#10;      background: linear-gradient(180deg, rgba(8, 20, 38, 0.82), rgba(3, 8, 18, 0.94));&#10;      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), 0 28px 80px rgba(0, 0, 0, 0.34);&#10;    }&#10;    html[data-preset=&amp;quot;signal-flow&amp;quot;][data-theme=&amp;quot;light&amp;quot;] .diagram-container {&#10;      background: linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(237, 246, 250, 0.94));&#10;      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.72), 0 24px 60px rgba(45, 78, 99, 0.12);&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .diagram-container {&#10;      border-color: var(--panel-border);&#10;      border-radius: 0.35rem;&#10;      background: var(--panel);&#10;      box-shadow:&#10;        inset 0 0 0 1px color-mix(in srgb, var(--panel-border) 34%, transparent),&#10;        0 18px 48px rgba(0, 0, 0, 0.16);&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .diagram-container::after {&#10;      content: &amp;quot;&amp;quot;;&#10;      position: absolute;&#10;      z-index: 10;&#10;      inset: 0.7rem;&#10;      pointer-events: none;&#10;      background:&#10;        linear-gradient(var(--frontend-stroke), var(--frontend-stroke)) left top / 1.35rem 1px no-repeat,&#10;        linear-gradient(var(--frontend-stroke), var(--frontend-stroke)) left top / 1px 1.35rem no-repeat,&#10;        linear-gradient(var(--frontend-stroke), var(--frontend-stroke)) right top / 1.35rem 1px no-repeat,&#10;        linear-gradient(var(--frontend-stroke), var(--frontend-stroke)) right top / 1px 1.35rem no-repeat,&#10;        linear-gradient(var(--frontend-stroke), var(--frontend-stroke)) left bottom / 1.35rem 1px no-repeat,&#10;        linear-gradient(var(--frontend-stroke), var(--frontend-stroke)) left bottom / 1px 1.35rem no-repeat,&#10;        linear-gradient(var(--frontend-stroke), var(--frontend-stroke)) right bottom / 1.35rem 1px no-repeat,&#10;        linear-gradient(var(--frontend-stroke), var(--frontend-stroke)) right bottom / 1px 1.35rem no-repeat;&#10;      opacity: 0.58;&#10;    }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .diagram-container {&#10;      overflow: hidden;&#10;      border-color: var(--panel-border);&#10;      border-radius: 0.38rem;&#10;      background:&#10;        linear-gradient(90deg, color-mix(in srgb, var(--security-fill) 58%, transparent), transparent 12%),&#10;        var(--panel);&#10;      box-shadow:&#10;        0 1px 0 color-mix(in srgb, var(--text) 6%, transparent),&#10;        0 18px 48px color-mix(in srgb, #000 19%, transparent);&#10;    }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .diagram-container::after {&#10;      position: absolute;&#10;      z-index: 10;&#10;      top: 0.72rem;&#10;      right: 1.25rem;&#10;      padding: 0.2rem 0.52rem;&#10;      border: 1px solid var(--panel-border);&#10;      background: var(--panel);&#10;      color: var(--arrow-emphasis);&#10;      content: attr(data-preset-badge-editorial-plate);&#10;      font-family: Georgia, &amp;#x27;Times New Roman&amp;#x27;, serif;&#10;      font-size: 0.52rem;&#10;      font-style: italic;&#10;      font-weight: 600;&#10;      letter-spacing: 0.09em;&#10;      pointer-events: none;&#10;    }&#10;    html[data-embed=&amp;quot;true&amp;quot;][data-preset=&amp;quot;editorial&amp;quot;] .diagram-container::after { display: none; }&#10;    html[data-motion-capable=&amp;quot;true&amp;quot;][data-preset=&amp;quot;signal-flow&amp;quot;][data-ambient-motion=&amp;quot;running&amp;quot;] .diagram-container::before {&#10;      content: &amp;quot;&amp;quot;;&#10;      position: absolute;&#10;      inset: 0;&#10;      pointer-events: none;&#10;      background: linear-gradient(115deg, transparent 28%, rgba(103, 232, 249, 0.035) 48%, transparent 68%);&#10;      transform: translateX(-70%);&#10;      animation: archify-signal-scan 4.8s ease-in-out 1 both;&#10;    }&#10;&#10;    /* Motion Governor gives the reader a real static state and gives the&#10;       strongest semantic action the only motion budget. Atmosphere resets to&#10;       its authored base instead of freezing mid-cycle. Static artifacts never&#10;       start a decorative pulse or scan. */&#10;    html:not([data-motion-capable=&amp;quot;true&amp;quot;]) svg[data-animation=&amp;quot;trace&amp;quot;] [data-animate] {&#10;      animation: none !important;&#10;    }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .pulse-dot,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .diagram-container::before,&#10;    html[data-motion=&amp;quot;still&amp;quot;] svg[data-animation=&amp;quot;trace&amp;quot;] [data-animate],&#10;    html[data-motion-owner] .pulse-dot,&#10;    html[data-motion-owner] .diagram-container::before,&#10;    html[data-motion-owner] svg[data-animation=&amp;quot;trace&amp;quot;] [data-animate],&#10;    html[data-embed=&amp;quot;true&amp;quot;] .pulse-dot,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .diagram-container::before,&#10;    html[data-share-playback=&amp;quot;true&amp;quot;] .pulse-dot,&#10;    html[data-share-playback=&amp;quot;true&amp;quot;] .diagram-container::before,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .pulse-dot,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .diagram-container::before,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] svg[data-animation=&amp;quot;trace&amp;quot;] [data-animate] {&#10;      animation: none !important;&#10;    }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .diagram-container::before,&#10;    html[data-motion-owner] .diagram-container::before,&#10;    html[data-embed=&amp;quot;true&amp;quot;] .diagram-container::before,&#10;    html[data-share-playback=&amp;quot;true&amp;quot;] .diagram-container::before {&#10;      opacity: 0;&#10;    }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .guided-view-progress span,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .guided-story-caption,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .story-trail-flow,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .intent-trace-flow,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .route-probe-flow,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .route-journey-flow,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .semantic-lens-flow,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .diagram-guide,&#10;    html[data-motion=&amp;quot;still&amp;quot;] [data-story-step],&#10;    html[data-motion=&amp;quot;still&amp;quot;] .overview-map-live,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .guided-view-stop,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .share-chapter-cue,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .share-chapter-state::before,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .share-chapter-progress span,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .guided-view-progress span,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .story-trail-flow,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .intent-trace-flow,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .route-probe-flow,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .route-journey-flow,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .semantic-lens-flow,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .diagram-guide,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] [data-story-step],&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .overview-map-live,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .guided-view-stop,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .share-chapter-cue,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .share-chapter-state::before,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .share-chapter-progress span {&#10;      animation: none !important;&#10;    }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .guided-view-progress span {&#10;      transform: scaleX(1) !important;&#10;    }&#10;    html[data-motion=&amp;quot;still&amp;quot;] svg[data-story-playing=&amp;quot;true&amp;quot;] .story-trail-flow {&#10;      stroke-dasharray: none;&#10;      stroke-dashoffset: 0;&#10;      opacity: 0.55;&#10;    }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .intent-trace-flow,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .route-probe-flow {&#10;      stroke-dasharray: none;&#10;      stroke-dashoffset: 0;&#10;      opacity: 0.72;&#10;    }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .route-journey-overlay,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .route-journey-overlay { display: none !important; }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .relationship-pulse-overlay,&#10;    html[data-motion=&amp;quot;still&amp;quot;] .story-carrier-overlay,&#10;    html[data-document-hidden=&amp;quot;true&amp;quot;] .story-carrier-overlay { display: none !important; }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .chapter-handoff-overlay { display: none !important; }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .chapter-handoff-anchor { animation: none !important; }&#10;    html[data-motion=&amp;quot;still&amp;quot;] .guided-view-chapter,&#10;    html[data-motion=&amp;quot;still&amp;quot;] svg [data-node-id],&#10;    html[data-motion=&amp;quot;still&amp;quot;] svg [data-edge-from],&#10;    html[data-motion=&amp;quot;still&amp;quot;] svg [data-detail],&#10;    html[data-motion=&amp;quot;still&amp;quot;] svg [data-detail-anchor],&#10;    html[data-motion=&amp;quot;still&amp;quot;] svg [data-legend-hit],&#10;    html[data-motion=&amp;quot;still&amp;quot;] svg {&#10;      transition: none !important;&#10;    }&#10;&#10;    svg {&#10;      width: 100%;&#10;      min-width: min(900px, 100%);&#10;      display: block;&#10;      transform-origin: 0 0;&#10;      transition: transform 0.18s ease;&#10;    }&#10;&#10;    .diagram-container.is-camera-moving svg {&#10;      transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1);&#10;    }&#10;    .diagram-container.is-camera-transaction svg { transition: none; }&#10;    .diagram-container.is-pannable { cursor: grab; }&#10;    .diagram-container.is-panning { cursor: grabbing; user-select: none; }&#10;    .diagram-container.is-panning svg { transition: none; }&#10;&#10;    .diagram-nav {&#10;      position: absolute;&#10;      right: 1rem;&#10;      bottom: 1rem;&#10;      z-index: 12;&#10;      display: inline-flex;&#10;      align-items: center;&#10;      max-width: calc(100% - 2rem);&#10;      padding: 0.15rem;&#10;      gap: 0;&#10;      overflow-x: auto;&#10;      border: 1px solid color-mix(in srgb, var(--toolbar-border) 48%, transparent);&#10;      border-radius: 0.58rem;&#10;      background: color-mix(in srgb, var(--toolbar-bg) 82%, transparent);&#10;      box-shadow: 0 5px 14px rgba(0, 0, 0, 0.07);&#10;      backdrop-filter: blur(10px);&#10;      scrollbar-width: none;&#10;    }&#10;    .diagram-nav::-webkit-scrollbar { display: none; }&#10;    .diagram-nav button,&#10;    .focus-chip button,&#10;    .guided-views button {&#10;      border: 0;&#10;      background: transparent;&#10;      color: var(--toolbar-text);&#10;      font: inherit;&#10;      cursor: pointer;&#10;    }&#10;    .diagram-nav button {&#10;      min-width: 2rem;&#10;      height: 2rem;&#10;      padding: 0 0.35rem;&#10;      border-radius: 0.35rem;&#10;      color: color-mix(in srgb, var(--toolbar-text) 68%, transparent);&#10;      font-size: 0.56rem;&#10;      font-weight: 600;&#10;      letter-spacing: 0.02em;&#10;      transition: background 0.15s, color 0.15s;&#10;    }&#10;    .diagram-nav button:hover,&#10;    .diagram-nav button:focus-visible,&#10;    .focus-chip button:hover,&#10;    .focus-chip button:focus-visible,&#10;    .guided-views button:hover,&#10;    .guided-views button:focus-visible { background: var(--toolbar-hover); }&#10;    .diagram-nav button:focus-visible,&#10;    .focus-chip button:focus-visible,&#10;    .guided-views button:focus-visible {&#10;      outline: 2px solid var(--frontend-stroke);&#10;      outline-offset: 1px;&#10;    }&#10;    .diagram-nav button:disabled { opacity: 0.38; cursor: default; }&#10;    .diagram-nav button:disabled:hover { background: transparent; }&#10;    .diagram-nav #btn-route-probe,&#10;    .diagram-nav #btn-overview-map,&#10;    .diagram-nav #btn-semantic-lens {&#10;      min-width: auto;&#10;      padding-inline: 0.5rem;&#10;      color: color-mix(in srgb, var(--toolbar-text) 86%, transparent);&#10;      font-weight: 650;&#10;    }&#10;    .diagram-nav #btn-node-finder,&#10;    .diagram-nav [data-view=&amp;quot;out&amp;quot;] {&#10;      position: relative;&#10;      margin-left: 0.25rem;&#10;    }&#10;    .diagram-nav #btn-node-finder::before,&#10;    .diagram-nav [data-view=&amp;quot;out&amp;quot;]::before {&#10;      position: absolute;&#10;      top: 0.4rem;&#10;      bottom: 0.4rem;&#10;      left: -0.13rem;&#10;      width: 1px;&#10;      background: color-mix(in srgb, var(--toolbar-border) 62%, transparent);&#10;      content: &amp;quot;&amp;quot;;&#10;      pointer-events: none;&#10;    }&#10;    .diagram-nav-icon {&#10;      display: block;&#10;      width: 0.72rem;&#10;      height: 0.72rem;&#10;      margin: auto;&#10;      background: currentColor;&#10;      -webkit-mask-position: center;&#10;      -webkit-mask-repeat: no-repeat;&#10;      -webkit-mask-size: contain;&#10;      mask-position: center;&#10;      mask-repeat: no-repeat;&#10;      mask-size: contain;&#10;    }&#10;    .diagram-nav-icon.find {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Ccircle cx=&amp;#x27;8.5&amp;#x27; cy=&amp;#x27;8.5&amp;#x27; r=&amp;#x27;4.5&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.8&amp;#x27;/%3E%3Cpath d=&amp;#x27;m12 12 4 4&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.8&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Ccircle cx=&amp;#x27;8.5&amp;#x27; cy=&amp;#x27;8.5&amp;#x27; r=&amp;#x27;4.5&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.8&amp;#x27;/%3E%3Cpath d=&amp;#x27;m12 12 4 4&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.8&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .diagram-nav-icon.guide {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Ccircle cx=&amp;#x27;10&amp;#x27; cy=&amp;#x27;10&amp;#x27; r=&amp;#x27;7&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3Cpath d=&amp;#x27;M7.8 7.3a2.4 2.4 0 014.6.9c0 1.8-2.4 2-2.4 3.7M10 14.9h.01&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Ccircle cx=&amp;#x27;10&amp;#x27; cy=&amp;#x27;10&amp;#x27; r=&amp;#x27;7&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3Cpath d=&amp;#x27;M7.8 7.3a2.4 2.4 0 014.6.9c0 1.8-2.4 2-2.4 3.7M10 14.9h.01&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .diagram-nav-icon.minus {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M5 10h10&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.8&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M5 10h10&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.8&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .diagram-nav-icon.plus {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M10 5v10M5 10h10&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.8&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M10 5v10M5 10h10&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.8&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .diagram-nav [data-view=&amp;quot;reset&amp;quot;] {&#10;      display: inline-flex;&#10;      align-items: center;&#10;      justify-content: center;&#10;      gap: 0.2rem;&#10;      min-width: 3.1rem;&#10;      padding-inline: 0.35rem;&#10;    }&#10;    .diagram-nav [data-view=&amp;quot;reset&amp;quot;][data-detail-visible] {&#10;      min-width: 3.8rem;&#10;    }&#10;    .diagram-nav-detail {&#10;      color: color-mix(in srgb, var(--toolbar-text) 52%, transparent);&#10;      font-size: 0.44rem;&#10;      font-weight: 700;&#10;      line-height: 1;&#10;      letter-spacing: 0.07em;&#10;    }&#10;    .diagram-nav-percent {&#10;      color: color-mix(in srgb, var(--toolbar-text) 84%, transparent);&#10;      font-size: 0.55rem;&#10;      font-weight: 650;&#10;      line-height: 1;&#10;    }&#10;    .diagram-container[data-camera-indicator=&amp;quot;true&amp;quot;] .diagram-nav-detail,&#10;    .diagram-container[data-camera-indicator=&amp;quot;true&amp;quot;] .diagram-nav-percent { color: var(--frontend-stroke); }&#10;    .diagram-nav #btn-diagram-guide[aria-expanded=&amp;quot;true&amp;quot;] {&#10;      color: var(--cloud-stroke);&#10;      background: var(--toolbar-hover);&#10;    }&#10;&#10;    /* Semantic Radar is a deliberately simplified, viewer-only overview. It&#10;       uses authored node bounds and the live camera viewport rather than&#10;       cloning the canonical SVG, so IDs, filters, animation, and export state&#10;       stay singular and deterministic. */&#10;    .overview-map {&#10;      position: absolute;&#10;      right: 1rem;&#10;      bottom: calc(4.15rem + var(--archify-nav-reserve));&#10;      z-index: 12;&#10;      width: 11.25rem;&#10;      overflow: hidden;&#10;      border: 1px solid color-mix(in srgb, var(--frontend-stroke) 52%, var(--toolbar-border));&#10;      border-radius: 0.78rem;&#10;      background: var(--toolbar-menu-bg);&#10;      color: var(--toolbar-text);&#10;      box-shadow: 0 16px 42px rgba(0, 0, 0, 0.3);&#10;      backdrop-filter: blur(16px);&#10;      font-size: 0.625rem;&#10;    }&#10;    .overview-map[hidden] { display: none; }&#10;    .overview-map[data-docked=&amp;quot;true&amp;quot;] {&#10;      position: fixed;&#10;      right: var(--archify-radar-right, 1rem);&#10;      top: var(--archify-radar-top, 1rem);&#10;      bottom: auto;&#10;    }&#10;    .overview-map[data-docked=&amp;quot;true&amp;quot;][data-dock-side=&amp;quot;left&amp;quot;] {&#10;      right: auto;&#10;      left: var(--archify-radar-left, 1rem);&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .overview-map { border-radius: 0.28rem; }&#10;    .overview-map-head {&#10;      display: grid;&#10;      grid-template-columns: auto minmax(0, 1fr) auto;&#10;      align-items: center;&#10;      gap: 0.45rem;&#10;      min-height: 2.25rem;&#10;      padding: 0.42rem 0.48rem 0.38rem 0.55rem;&#10;      border-bottom: 1px solid var(--toolbar-border);&#10;      background: linear-gradient(110deg, color-mix(in srgb, var(--frontend-fill) 45%, transparent), transparent 68%);&#10;      cursor: grab;&#10;      touch-action: none;&#10;      user-select: none;&#10;    }&#10;    .overview-map[data-panel-dragging=&amp;quot;true&amp;quot;] .overview-map-head { cursor: grabbing; }&#10;    .overview-map[data-placement-invalid=&amp;quot;true&amp;quot;] {&#10;      border-color: var(--security-stroke);&#10;      box-shadow: 0 0 0 2px color-mix(in srgb, var(--security-stroke) 34%, transparent), 0 16px 42px rgba(0, 0, 0, 0.3);&#10;    }&#10;    .overview-map[data-compact=&amp;quot;true&amp;quot;] {&#10;      width: 7.4rem;&#10;    }&#10;    .overview-map[data-compact=&amp;quot;true&amp;quot;] .overview-map-head {&#10;      grid-template-columns: minmax(0, 1fr) auto;&#10;      gap: 0.24rem;&#10;      min-height: 1.5rem;&#10;      padding: 0.05rem 0.16rem 0.05rem 0.32rem;&#10;      border-bottom: 0;&#10;    }&#10;    .overview-map[data-compact=&amp;quot;true&amp;quot;] .overview-map-live,&#10;    .overview-map[data-compact=&amp;quot;true&amp;quot;] .overview-map-copy,&#10;    .overview-map[data-compact=&amp;quot;true&amp;quot;] .overview-map-surface,&#10;    .overview-map[data-compact=&amp;quot;true&amp;quot;] .overview-map-hint {&#10;      display: none;&#10;    }&#10;    .overview-map[data-compact=&amp;quot;true&amp;quot;] .overview-map-expand { display: inline-flex; }&#10;    .overview-map[data-compact=&amp;quot;true&amp;quot;] .overview-map-close {&#10;      width: 1.15rem;&#10;      height: 1.15rem;&#10;      font-size: 0.72rem;&#10;    }&#10;    .overview-map-live {&#10;      width: 0.42rem;&#10;      height: 0.42rem;&#10;      border-radius: 50%;&#10;      background: var(--backend-stroke);&#10;      box-shadow: 0 0 0 0 color-mix(in srgb, var(--backend-stroke) 52%, transparent);&#10;      animation: archify-radar-live 2.4s ease-out infinite;&#10;    }&#10;    .overview-map-copy { min-width: 0; line-height: 1.1; }&#10;    .overview-map-copy strong {&#10;      display: block;&#10;      overflow: hidden;&#10;      color: var(--frontend-stroke);&#10;      font-size: 0.59rem;&#10;      letter-spacing: 0.12em;&#10;      text-transform: uppercase;&#10;      white-space: nowrap;&#10;      text-overflow: ellipsis;&#10;    }&#10;    .overview-map-copy small {&#10;      display: block;&#10;      margin-top: 0.18rem;&#10;      overflow: hidden;&#10;      color: var(--text-faint);&#10;      font-size: 0.52rem;&#10;      letter-spacing: 0.04em;&#10;      white-space: nowrap;&#10;      text-overflow: ellipsis;&#10;    }&#10;    .overview-map-expand {&#10;      display: none;&#10;      align-items: center;&#10;      justify-content: center;&#10;      min-width: 0;&#10;      height: 1.2rem;&#10;      padding: 0 0.34rem;&#10;      overflow: hidden;&#10;      border: 0;&#10;      border-radius: 0.3rem;&#10;      background: transparent;&#10;      color: var(--frontend-stroke);&#10;      font: inherit;&#10;      font-size: 0.49rem;&#10;      font-weight: 700;&#10;      letter-spacing: 0.06em;&#10;      text-transform: uppercase;&#10;      white-space: nowrap;&#10;      cursor: pointer;&#10;    }&#10;    .overview-map-close {&#10;      width: 1.55rem;&#10;      height: 1.55rem;&#10;      padding: 0;&#10;      border: 0;&#10;      border-radius: 0.34rem;&#10;      background: transparent;&#10;      color: var(--toolbar-text);&#10;      font: inherit;&#10;      font-size: 0.9rem;&#10;      cursor: pointer;&#10;    }&#10;    .overview-map-expand:hover,&#10;    .overview-map-expand:focus-visible,&#10;    .overview-map-close:hover,&#10;    .overview-map-close:focus-visible { background: var(--toolbar-hover); }&#10;    .overview-map-expand:focus-visible,&#10;    .overview-map-close:focus-visible,&#10;    .overview-map-surface:focus-visible,&#10;    .overview-map-node:focus-visible {&#10;      outline: 2px solid var(--frontend-stroke);&#10;      outline-offset: 1px;&#10;    }&#10;    .overview-map-surface {&#10;      position: relative;&#10;      height: 7rem;&#10;      margin: 0.42rem;&#10;      overflow: hidden;&#10;      border: 1px solid color-mix(in srgb, var(--panel-border) 72%, transparent);&#10;      border-radius: 0.42rem;&#10;      background:&#10;        linear-gradient(color-mix(in srgb, var(--panel-border) 26%, transparent) 1px, transparent 1px),&#10;        linear-gradient(90deg, color-mix(in srgb, var(--panel-border) 26%, transparent) 1px, transparent 1px),&#10;        color-mix(in srgb, var(--bg) 86%, transparent);&#10;      background-size: 12px 12px;&#10;      cursor: crosshair;&#10;      touch-action: none;&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .overview-map-surface { border-radius: 0.1rem; }&#10;    .overview-map-surface &amp;gt; svg {&#10;      width: 100%;&#10;      height: 100%;&#10;      min-width: 0;&#10;      transform: none !important;&#10;      transition: none !important;&#10;      display: block;&#10;      overflow: visible;&#10;    }&#10;    .overview-map-node {&#10;      fill: var(--backend-stroke);&#10;      fill-opacity: 0.52;&#10;      stroke: var(--backend-stroke);&#10;      stroke-opacity: 0.86;&#10;      vector-effect: non-scaling-stroke;&#10;      cursor: pointer;&#10;      transition: fill-opacity 140ms ease, stroke-width 140ms ease, filter 140ms ease;&#10;    }&#10;    .overview-map-node[data-kind=&amp;quot;frontend&amp;quot;],&#10;    .overview-map-node[data-kind=&amp;quot;start&amp;quot;] { fill: var(--frontend-stroke); stroke: var(--frontend-stroke); }&#10;    .overview-map-node[data-kind=&amp;quot;database&amp;quot;],&#10;    .overview-map-node[data-kind=&amp;quot;success&amp;quot;] { fill: var(--database-stroke); stroke: var(--database-stroke); }&#10;    .overview-map-node[data-kind=&amp;quot;cloud&amp;quot;],&#10;    .overview-map-node[data-kind=&amp;quot;waiting&amp;quot;] { fill: var(--cloud-stroke); stroke: var(--cloud-stroke); }&#10;    .overview-map-node[data-kind=&amp;quot;messagebus&amp;quot;] { fill: var(--messagebus-stroke); stroke: var(--messagebus-stroke); }&#10;    .overview-map-node[data-kind=&amp;quot;security&amp;quot;],&#10;    .overview-map-node[data-kind=&amp;quot;decision&amp;quot;],&#10;    .overview-map-node[data-kind=&amp;quot;failure&amp;quot;] { fill: var(--security-stroke); stroke: var(--security-stroke); }&#10;    .overview-map-node[data-kind=&amp;quot;external&amp;quot;],&#10;    .overview-map-node[data-kind=&amp;quot;neutral&amp;quot;] { fill: var(--external-stroke); stroke: var(--external-stroke); }&#10;    .overview-map-node[data-radar-active=&amp;quot;true&amp;quot;],&#10;    .overview-map-node:hover,&#10;    .overview-map-node:focus-visible {&#10;      fill-opacity: 0.92;&#10;      stroke-width: 2.2;&#10;      filter: drop-shadow(0 0 3px currentColor);&#10;    }&#10;    .overview-map-viewport {&#10;      fill: color-mix(in srgb, var(--frontend-fill) 56%, transparent);&#10;      stroke: var(--frontend-stroke);&#10;      stroke-width: 2;&#10;      vector-effect: non-scaling-stroke;&#10;      pointer-events: none;&#10;      filter: drop-shadow(0 0 3px color-mix(in srgb, var(--frontend-stroke) 54%, transparent));&#10;    }&#10;    .overview-map-hint {&#10;      display: flex;&#10;      justify-content: space-between;&#10;      gap: 0.5rem;&#10;      padding: 0 0.52rem 0.46rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.49rem;&#10;      letter-spacing: 0.06em;&#10;      text-transform: uppercase;&#10;    }&#10;    .diagram-nav #btn-overview-map[aria-expanded=&amp;quot;true&amp;quot;] {&#10;      color: var(--frontend-stroke);&#10;      background: var(--toolbar-hover);&#10;    }&#10;    .overview-map-feedback {&#10;      position: absolute;&#10;      right: 1rem;&#10;      bottom: 4.15rem;&#10;      z-index: 13;&#10;      max-width: min(16rem, calc(100% - 2rem));&#10;      padding: 0.38rem 0.55rem;&#10;      border: 1px solid color-mix(in srgb, var(--frontend-stroke) 52%, var(--toolbar-border));&#10;      border-radius: 0.5rem;&#10;      background: var(--toolbar-menu-bg);&#10;      color: var(--toolbar-text);&#10;      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);&#10;      font-size: 0.52rem;&#10;      line-height: 1.35;&#10;      pointer-events: none;&#10;    }&#10;    .overview-map-feedback[hidden] { display: none; }&#10;    .focus-chip[data-radar-yielded=&amp;quot;true&amp;quot;] { display: none !important; }&#10;    .diagram-nav #btn-route-probe[aria-pressed=&amp;quot;true&amp;quot;] {&#10;      color: var(--backend-stroke);&#10;      background: var(--toolbar-hover);&#10;    }&#10;    .diagram-nav #btn-semantic-lens[aria-expanded=&amp;quot;true&amp;quot;],&#10;    .diagram-nav #btn-semantic-lens[aria-pressed=&amp;quot;true&amp;quot;] {&#10;      color: var(--database-stroke);&#10;      background: var(--toolbar-hover);&#10;    }&#10;&#10;    /* Semantic Lens turns the compiled node-kind palette into an analytical&#10;       legend. One kind reveals its real traffic; two kinds compare only their&#10;       direct authored relationships. Geometry and the canonical SVG stay put. */&#10;    .semantic-lens {&#10;      position: absolute;&#10;      right: 1rem;&#10;      bottom: calc(4.15rem + var(--archify-nav-reserve));&#10;      z-index: 24;&#10;      width: min(20rem, calc(100% - 2rem));&#10;      overflow: hidden;&#10;      border: 1px solid color-mix(in srgb, var(--database-stroke) 58%, var(--toolbar-border));&#10;      border-radius: 0.82rem;&#10;      background:&#10;        linear-gradient(135deg, color-mix(in srgb, var(--database-fill) 34%, transparent), transparent 48%),&#10;        var(--toolbar-menu-bg);&#10;      color: var(--toolbar-text);&#10;      box-shadow: 0 18px 52px rgba(0, 0, 0, 0.36);&#10;      backdrop-filter: blur(18px);&#10;      animation: archify-lens-in 180ms cubic-bezier(0.22, 1, 0.36, 1);&#10;    }&#10;    .semantic-lens[hidden] { display: none; }&#10;    .semantic-lens[data-dock-side=&amp;quot;left&amp;quot;] { left: 1rem; right: auto; }&#10;    .semantic-lens[data-dock-side=&amp;quot;right&amp;quot;] { left: auto; right: 1rem; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .semantic-lens { border-radius: 0.28rem; }&#10;    .semantic-lens-head {&#10;      display: grid;&#10;      grid-template-columns: minmax(0, 1fr) auto;&#10;      align-items: start;&#10;      gap: 0.75rem;&#10;      padding: 0.72rem 0.78rem 0.62rem;&#10;      border-bottom: 1px solid var(--toolbar-border);&#10;    }&#10;    .semantic-lens-eyebrow {&#10;      display: block;&#10;      color: var(--database-stroke);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.16em;&#10;      text-transform: uppercase;&#10;    }&#10;    .semantic-lens-title {&#10;      display: block;&#10;      margin-top: 0.16rem;&#10;      color: var(--text);&#10;      font-size: 0.82rem;&#10;      letter-spacing: -0.02em;&#10;    }&#10;    .semantic-lens-close {&#10;      width: 1.75rem;&#10;      height: 1.75rem;&#10;      padding: 0;&#10;      border: 0;&#10;      border-radius: 0.35rem;&#10;      background: transparent;&#10;      color: var(--toolbar-text);&#10;      font: inherit;&#10;      font-size: 1rem;&#10;      cursor: pointer;&#10;    }&#10;    .semantic-lens-close:hover,&#10;    .semantic-lens-close:focus-visible { background: var(--toolbar-hover); }&#10;    .semantic-lens-instruction {&#10;      margin: 0;&#10;      padding: 0.52rem 0.78rem 0.48rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.55rem;&#10;      line-height: 1.45;&#10;    }&#10;    .semantic-lens-kinds {&#10;      display: grid;&#10;      grid-template-columns: 1fr 1fr;&#10;      gap: 0.3rem;&#10;      max-height: min(15rem, 40vh);&#10;      padding: 0 0.5rem 0.5rem;&#10;      overflow-y: auto;&#10;      scrollbar-width: thin;&#10;    }&#10;    .semantic-lens-kind {&#10;      --lens-color: var(--external-stroke);&#10;      display: grid;&#10;      grid-template-columns: auto minmax(0, 1fr) auto;&#10;      align-items: center;&#10;      gap: 0.42rem;&#10;      min-width: 0;&#10;      min-height: 2.15rem;&#10;      padding: 0.35rem 0.42rem;&#10;      border: 1px solid color-mix(in srgb, var(--lens-color) 24%, var(--toolbar-border));&#10;      border-radius: 0.45rem;&#10;      background: color-mix(in srgb, var(--panel) 76%, transparent);&#10;      color: var(--toolbar-text);&#10;      font: inherit;&#10;      text-align: left;&#10;      cursor: pointer;&#10;      transition: border-color 140ms ease, background 140ms ease, opacity 140ms ease;&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .semantic-lens-kind { border-radius: 0.12rem; }&#10;    .semantic-lens-kind[data-kind=&amp;quot;frontend&amp;quot;],&#10;    .semantic-lens-kind[data-kind=&amp;quot;start&amp;quot;] { --lens-color: var(--frontend-stroke); }&#10;    .semantic-lens-kind[data-kind=&amp;quot;backend&amp;quot;],&#10;    .semantic-lens-kind[data-kind=&amp;quot;active&amp;quot;] { --lens-color: var(--backend-stroke); }&#10;    .semantic-lens-kind[data-kind=&amp;quot;database&amp;quot;],&#10;    .semantic-lens-kind[data-kind=&amp;quot;success&amp;quot;] { --lens-color: var(--database-stroke); }&#10;    .semantic-lens-kind[data-kind=&amp;quot;cloud&amp;quot;],&#10;    .semantic-lens-kind[data-kind=&amp;quot;waiting&amp;quot;] { --lens-color: var(--cloud-stroke); }&#10;    .semantic-lens-kind[data-kind=&amp;quot;messagebus&amp;quot;] { --lens-color: var(--messagebus-stroke); }&#10;    .semantic-lens-kind[data-kind=&amp;quot;security&amp;quot;],&#10;    .semantic-lens-kind[data-kind=&amp;quot;decision&amp;quot;],&#10;    .semantic-lens-kind[data-kind=&amp;quot;failure&amp;quot;] { --lens-color: var(--security-stroke); }&#10;    .semantic-lens-kind:hover,&#10;    .semantic-lens-kind:focus-visible,&#10;    .semantic-lens-kind[aria-pressed=&amp;quot;true&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--lens-color) 78%, var(--toolbar-border));&#10;      background: color-mix(in srgb, var(--lens-color) 11%, var(--panel));&#10;    }&#10;    .semantic-lens-kind:focus-visible,&#10;    .semantic-lens-close:focus-visible,&#10;    .semantic-lens-actions button:focus-visible {&#10;      outline: 2px solid var(--database-stroke);&#10;      outline-offset: 1px;&#10;    }&#10;    .semantic-lens-kind:disabled { opacity: 0.34; cursor: default; }&#10;    .semantic-lens-swatch {&#10;      width: 0.48rem;&#10;      height: 0.48rem;&#10;      border-radius: 50%;&#10;      background: var(--lens-color);&#10;      box-shadow: 0 0 8px color-mix(in srgb, var(--lens-color) 58%, transparent);&#10;    }&#10;    .semantic-lens-kind strong {&#10;      overflow: hidden;&#10;      color: var(--text);&#10;      font-size: 0.61rem;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .semantic-lens-kind em {&#10;      color: var(--lens-color);&#10;      font-size: 0.54rem;&#10;      font-style: normal;&#10;      font-weight: 800;&#10;    }&#10;    .semantic-lens-status {&#10;      min-height: 2.5rem;&#10;      margin: 0;&#10;      padding: 0.55rem 0.78rem;&#10;      border-top: 1px solid var(--toolbar-border);&#10;      color: var(--text-faint);&#10;      font-size: 0.55rem;&#10;      line-height: 1.45;&#10;    }&#10;    .semantic-lens-status strong { color: var(--database-stroke); font-weight: 800; }&#10;    .semantic-lens-actions {&#10;      display: flex;&#10;      justify-content: flex-end;&#10;      gap: 0.28rem;&#10;      padding: 0 0.62rem 0.62rem;&#10;    }&#10;    .semantic-lens-actions button {&#10;      min-height: 1.8rem;&#10;      padding: 0.28rem 0.48rem;&#10;      border: 0;&#10;      border-radius: 0.35rem;&#10;      background: transparent;&#10;      color: var(--toolbar-text);&#10;      font: inherit;&#10;      font-size: 0.56rem;&#10;      cursor: pointer;&#10;    }&#10;    .semantic-lens-actions button:hover { background: var(--toolbar-hover); }&#10;    .semantic-lens-actions #semantic-lens-copy { color: var(--database-stroke); }&#10;    @keyframes archify-lens-in {&#10;      from { opacity: 0; transform: translateY(5px) scale(0.985); }&#10;      to { opacity: 1; transform: translateY(0) scale(1); }&#10;    }&#10;&#10;    /* Route Probe answers a reader question over the compiled semantic graph:&#10;       choose two stable nodes and reveal the shortest authored directed route.&#10;       The receipt and signal live entirely in the viewer layer. */&#10;    .route-probe {&#10;      position: absolute;&#10;      left: 1rem;&#10;      bottom: calc(1rem + var(--archify-nav-reserve));&#10;      z-index: 12;&#10;      width: min(46rem, calc(100% - 25rem));&#10;      min-width: 18rem;&#10;      overflow: hidden;&#10;      border: 1px solid color-mix(in srgb, var(--backend-stroke) 62%, var(--toolbar-border));&#10;      border-radius: 0.82rem;&#10;      background:&#10;        linear-gradient(115deg, color-mix(in srgb, var(--backend-fill) 50%, transparent), transparent 62%),&#10;        var(--toolbar-menu-bg);&#10;      color: var(--toolbar-text);&#10;      box-shadow: 0 18px 48px rgba(0, 0, 0, 0.3);&#10;      backdrop-filter: blur(16px);&#10;      font-size: 0.625rem;&#10;    }&#10;    .route-probe[hidden] { display: none; }&#10;    .route-probe[data-route-dock=&amp;quot;top&amp;quot;] {&#10;      top: 1rem;&#10;      bottom: auto;&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .route-probe { border-radius: 0.25rem; }&#10;    .route-probe-head {&#10;      display: grid;&#10;      grid-template-columns: minmax(0, 1fr) auto;&#10;      align-items: start;&#10;      gap: 0.65rem;&#10;      padding: 0.52rem 0.58rem 0.44rem;&#10;      border-bottom: 1px solid color-mix(in srgb, var(--toolbar-border) 80%, transparent);&#10;    }&#10;    .route-probe-copy { min-width: 0; }&#10;    .route-probe-eyebrow {&#10;      display: block;&#10;      color: var(--backend-stroke);&#10;      font-size: 0.48rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.15em;&#10;      text-transform: uppercase;&#10;    }&#10;    .route-probe-title {&#10;      display: block;&#10;      margin-top: 0.14rem;&#10;      overflow: hidden;&#10;      color: var(--toolbar-text);&#10;      font-size: 0.72rem;&#10;      line-height: 1.25;&#10;      white-space: nowrap;&#10;      text-overflow: ellipsis;&#10;    }&#10;    .route-probe-actions { display: flex; gap: 0.2rem; }&#10;    .route-probe button {&#10;      min-height: 1.55rem;&#10;      padding: 0.25rem 0.42rem;&#10;      border: 0;&#10;      border-radius: 0.36rem;&#10;      background: transparent;&#10;      color: var(--toolbar-text);&#10;      font: inherit;&#10;      cursor: pointer;&#10;    }&#10;    .route-probe button:hover,&#10;    .route-probe button:focus-visible { background: var(--toolbar-hover); }&#10;    .route-probe button:focus-visible {&#10;      outline: 2px solid var(--backend-stroke);&#10;      outline-offset: 1px;&#10;    }&#10;    .route-probe-copy-link { color: var(--frontend-stroke) !important; }&#10;    .route-probe-find { color: var(--backend-stroke) !important; }&#10;    .route-probe-copy-link[hidden] { display: none; }&#10;    .route-probe-find[hidden] { display: none; }&#10;    .route-probe-path {&#10;      display: flex;&#10;      align-items: center;&#10;      min-height: 2.2rem;&#10;      padding: 0.42rem 0.58rem 0.24rem;&#10;      overflow-x: auto;&#10;      scrollbar-width: thin;&#10;      white-space: nowrap;&#10;    }&#10;    .route-probe-node,&#10;    .route-probe button.route-probe-node {&#10;      flex: none;&#10;      max-width: 9.5rem;&#10;      overflow: hidden;&#10;      min-height: 1.75rem !important;&#10;      padding: 0.22rem 0.38rem;&#10;      border: 1px solid color-mix(in srgb, var(--backend-stroke) 46%, var(--toolbar-border));&#10;      border-radius: 999px;&#10;      background: color-mix(in srgb, var(--backend-fill) 52%, transparent);&#10;      color: var(--text);&#10;      font-size: 0.56rem;&#10;      font-weight: 700;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .route-probe-node[data-endpoint=&amp;quot;start&amp;quot;] {&#10;      border-color: var(--frontend-stroke);&#10;      color: var(--frontend-stroke);&#10;    }&#10;    .route-probe-node[data-endpoint=&amp;quot;end&amp;quot;] {&#10;      border-color: var(--security-stroke);&#10;      color: var(--security-stroke);&#10;    }&#10;    .route-probe-node[data-route-journey-state=&amp;quot;past&amp;quot;] { opacity: 0.66; }&#10;    .route-probe-node[data-route-journey-state=&amp;quot;future&amp;quot;] { opacity: 0.48; }&#10;    .route-probe-node[aria-current=&amp;quot;step&amp;quot;] {&#10;      border-color: var(--backend-stroke);&#10;      background: color-mix(in srgb, var(--backend-fill) 82%, var(--toolbar-menu-bg));&#10;      color: var(--text);&#10;      box-shadow: 0 0 0 1px color-mix(in srgb, var(--backend-stroke) 42%, transparent), 0 0 14px color-mix(in srgb, var(--backend-stroke) 34%, transparent);&#10;      opacity: 1;&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .route-probe-node[aria-current=&amp;quot;step&amp;quot;] {&#10;      border-style: double;&#10;      border-width: 3px;&#10;      border-radius: 0.2rem;&#10;      box-shadow: none;&#10;    }&#10;    .route-probe-arrow {&#10;      flex: none;&#10;      padding: 0 0.28rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.65rem;&#10;    }&#10;    .route-probe-placeholder {&#10;      color: var(--text-faint);&#10;      font-size: 0.56rem;&#10;      letter-spacing: 0.03em;&#10;    }&#10;    .route-probe-status {&#10;      display: block;&#10;      min-height: 1.45rem;&#10;      padding: 0.08rem 0.58rem 0.44rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.52rem;&#10;      line-height: 1.35;&#10;    }&#10;    .route-journey-controls {&#10;      display: grid;&#10;      grid-template-columns: 2rem minmax(5.8rem, auto) 2rem minmax(4.8rem, auto);&#10;      justify-content: start;&#10;      gap: 0.22rem;&#10;      padding: 0.08rem 0.58rem 0.28rem;&#10;    }&#10;    .route-journey-controls[hidden] { display: none; }&#10;    .route-journey-controls button {&#10;      min-height: 1.8rem;&#10;      border: 1px solid color-mix(in srgb, var(--toolbar-border) 86%, transparent);&#10;      background: color-mix(in srgb, var(--toolbar-bg) 72%, transparent);&#10;      font-size: 0.54rem;&#10;      font-weight: 700;&#10;    }&#10;    .route-journey-controls button:disabled {&#10;      cursor: default;&#10;      opacity: 0.34;&#10;    }&#10;    .route-journey-play { color: var(--backend-stroke) !important; }&#10;    .route-journey-overview { color: var(--frontend-stroke) !important; }&#10;    .route-journey-controls[data-playing=&amp;quot;true&amp;quot;] .route-journey-play {&#10;      border-color: color-mix(in srgb, var(--backend-stroke) 64%, var(--toolbar-border));&#10;      background: color-mix(in srgb, var(--backend-fill) 62%, transparent);&#10;    }&#10;    .route-probe[data-state=&amp;quot;error&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--security-stroke) 72%, var(--toolbar-border));&#10;    }&#10;    .route-probe[data-state=&amp;quot;error&amp;quot;] .route-probe-status { color: var(--security-stroke); }&#10;&#10;    .focus-chip {&#10;      position: absolute;&#10;      left: 1rem;&#10;      top: 1rem;&#10;      z-index: 12;&#10;      display: block;&#10;      width: min(22rem, calc(100% - 13rem));&#10;      max-width: calc(100% - 13rem);&#10;      overflow: hidden;&#10;      border: 1px solid var(--frontend-stroke);&#10;      border-radius: 0.85rem;&#10;      background: var(--toolbar-menu-bg);&#10;      color: var(--toolbar-text);&#10;      box-shadow: 0 18px 48px rgba(0, 0, 0, 0.3);&#10;      backdrop-filter: blur(16px);&#10;      font-size: 0.6875rem;&#10;    }&#10;    .focus-chip[hidden] { display: none; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .focus-chip { border-radius: 0.3rem; }&#10;    .focus-chip button {&#10;      flex: none;&#10;      padding: 0.3rem 0.45rem;&#10;      border-radius: 0.35rem;&#10;      font-size: 0.625rem;&#10;    }&#10;    .relationship-lens-head {&#10;      display: grid;&#10;      grid-template-columns: minmax(0, 1fr) auto;&#10;      align-items: start;&#10;      gap: 0.75rem;&#10;      padding: 0.7rem 0.75rem 0.65rem;&#10;      border-bottom: 1px solid var(--toolbar-border);&#10;      background: linear-gradient(120deg, color-mix(in srgb, var(--frontend-fill) 34%, transparent), transparent 72%);&#10;    }&#10;    .relationship-lens-copy { min-width: 0; }&#10;    .relationship-lens-actions {&#10;      display: flex;&#10;      flex-direction: column;&#10;      align-items: flex-end;&#10;      gap: 0.18rem;&#10;    }&#10;    .relationship-lens-actions button { white-space: nowrap; }&#10;    .relationship-lens-actions #btn-focus-clear {&#10;      display: grid;&#10;      width: 1.75rem;&#10;      height: 1.75rem;&#10;      padding: 0;&#10;      place-items: center;&#10;      color: var(--text-muted);&#10;      font-size: 1rem;&#10;      line-height: 1;&#10;    }&#10;    .relationship-lens-actions #btn-focus-clear:hover,&#10;    .relationship-lens-actions #btn-focus-clear:focus-visible {&#10;      background: var(--toolbar-hover);&#10;      color: var(--text);&#10;    }&#10;    .relationship-lens-actions #btn-focus-copy { color: var(--frontend-stroke); }&#10;    .relationship-lens-actions #btn-focus-relations { display: none; }&#10;    .relationship-lens-eyebrow {&#10;      display: block;&#10;      margin-bottom: 0.18rem;&#10;      color: var(--frontend-stroke);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.14em;&#10;      text-transform: uppercase;&#10;    }&#10;    .relationship-lens-title {&#10;      display: block;&#10;      overflow: hidden;&#10;      color: var(--text);&#10;      font-size: 0.8rem;&#10;      line-height: 1.35;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .semantic-passport-detail {&#10;      display: block;&#10;      margin-top: 0.12rem;&#10;      overflow: hidden;&#10;      color: var(--text-muted);&#10;      font-size: 0.625rem;&#10;      line-height: 1.4;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .semantic-passport-detail[hidden] { display: none; }&#10;    .semantic-passport-meta {&#10;      display: flex;&#10;      flex-wrap: wrap;&#10;      gap: 0.24rem;&#10;      margin-top: 0.42rem;&#10;    }&#10;    .semantic-passport-meta span,&#10;    .semantic-passport-meta code {&#10;      max-width: 100%;&#10;      overflow: hidden;&#10;      padding: 0.14rem 0.34rem;&#10;      border: 1px solid color-mix(in srgb, var(--toolbar-border) 82%, transparent);&#10;      border-radius: 999px;&#10;      background: color-mix(in srgb, var(--panel) 68%, transparent);&#10;      color: var(--text-faint);&#10;      font: inherit;&#10;      font-size: 0.5rem;&#10;      letter-spacing: 0.04em;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .semantic-passport-meta [data-passport=&amp;quot;kind&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 50%, var(--toolbar-border));&#10;      color: var(--frontend-stroke);&#10;      font-weight: 800;&#10;      text-transform: uppercase;&#10;    }&#10;    .semantic-passport-meta [data-passport=&amp;quot;tag&amp;quot;] { color: var(--cloud-stroke); }&#10;    .semantic-passport-meta [data-passport=&amp;quot;brand&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--messagebus-stroke) 52%, var(--toolbar-border));&#10;      color: var(--messagebus-stroke);&#10;      font-weight: 700;&#10;    }&#10;    .semantic-passport-meta [hidden] { display: none; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .semantic-passport-meta span,&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .semantic-passport-meta code { border-radius: 0.1rem; }&#10;    .semantic-passport-evidence {&#10;      margin-top: 0.52rem;&#10;      padding: 0.5rem;&#10;      border: 1px solid color-mix(in srgb, var(--backend-stroke) 32%, var(--toolbar-border));&#10;      border-radius: 0.55rem;&#10;      background: color-mix(in srgb, var(--backend-fill) 18%, var(--panel));&#10;    }&#10;    .semantic-passport-evidence[hidden] { display: none; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .semantic-passport-evidence { border-radius: 0.18rem; }&#10;    .semantic-passport-evidence-head {&#10;      display: flex;&#10;      align-items: center;&#10;      justify-content: space-between;&#10;      gap: 0.55rem;&#10;      margin-bottom: 0.35rem;&#10;    }&#10;    .semantic-passport-evidence-status {&#10;      display: inline-flex;&#10;      align-items: center;&#10;      gap: 0.28rem;&#10;      color: var(--backend-stroke);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.08em;&#10;      text-transform: uppercase;&#10;    }&#10;    .semantic-passport-evidence-status::before {&#10;      content: &amp;#x27;&amp;#x27;;&#10;      width: 0.38rem;&#10;      height: 0.38rem;&#10;      border-radius: 50%;&#10;      background: var(--backend-stroke);&#10;      box-shadow: 0 0 0 3px color-mix(in srgb, var(--backend-stroke) 14%, transparent);&#10;    }&#10;    .semantic-passport-repository {&#10;      min-width: 0;&#10;      overflow: hidden;&#10;      color: var(--text-faint);&#10;      font-size: 0.5rem;&#10;      text-decoration: none;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .semantic-passport-repository:hover,&#10;    .semantic-passport-repository:focus-visible { color: var(--backend-stroke); }&#10;    .semantic-passport-evidence-links { display: grid; gap: 0.22rem; }&#10;    .semantic-passport-source {&#10;      display: grid;&#10;      grid-template-columns: minmax(0, 1fr) auto;&#10;      gap: 0.15rem 0.45rem;&#10;      align-items: center;&#10;      padding: 0.34rem 0.4rem;&#10;      border: 1px solid transparent;&#10;      border-radius: 0.38rem;&#10;      color: var(--text-muted);&#10;      text-decoration: none;&#10;    }&#10;    a.semantic-passport-source:hover,&#10;    a.semantic-passport-source:focus-visible {&#10;      border-color: color-mix(in srgb, var(--backend-stroke) 42%, transparent);&#10;      background: color-mix(in srgb, var(--backend-fill) 32%, transparent);&#10;      color: var(--text);&#10;    }&#10;    .semantic-passport-source strong {&#10;      overflow: hidden;&#10;      font-size: 0.5625rem;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .semantic-passport-source code {&#10;      color: var(--backend-stroke);&#10;      font: inherit;&#10;      font-size: 0.5rem;&#10;    }&#10;    .semantic-passport-source small {&#10;      grid-column: 1 / -1;&#10;      overflow: hidden;&#10;      color: var(--text-faint);&#10;      font-size: 0.5rem;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .relationship-lens-summary {&#10;      display: block;&#10;      margin-top: 0.12rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.5625rem;&#10;    }&#10;    .semantic-passport-reach {&#10;      display: grid;&#10;      gap: 0.28rem;&#10;      margin-top: 0.52rem;&#10;      padding-top: 0.48rem;&#10;      border-top: 1px solid color-mix(in srgb, var(--toolbar-border) 76%, transparent);&#10;    }&#10;    .semantic-passport-reach[hidden] { display: none; }&#10;    .semantic-passport-reach-label {&#10;      color: var(--text-faint);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.1em;&#10;      text-transform: uppercase;&#10;    }&#10;    .semantic-passport-reach-actions {&#10;      display: grid;&#10;      grid-template-columns: repeat(2, minmax(0, 1fr));&#10;      gap: 0.25rem;&#10;    }&#10;    .semantic-passport-reach-actions button {&#10;      display: flex;&#10;      align-items: center;&#10;      justify-content: space-between;&#10;      gap: 0.5rem;&#10;      min-width: 0;&#10;      min-height: 2rem;&#10;      padding: 0.32rem 0.42rem;&#10;      border: 1px solid color-mix(in srgb, var(--toolbar-border) 86%, transparent);&#10;      background: color-mix(in srgb, var(--panel) 70%, transparent);&#10;      color: var(--text-muted);&#10;      text-align: left;&#10;    }&#10;    .semantic-passport-reach-actions button:hover:not(:disabled),&#10;    .semantic-passport-reach-actions button:focus-visible {&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 62%, var(--toolbar-border));&#10;      color: var(--text);&#10;    }&#10;    .semantic-passport-reach-actions button:focus-visible {&#10;      outline: 2px solid var(--frontend-stroke);&#10;      outline-offset: 1px;&#10;    }&#10;    .semantic-passport-reach-actions button:disabled {&#10;      cursor: default;&#10;      opacity: 0.5;&#10;    }&#10;    .semantic-passport-reach-actions button[aria-pressed=&amp;quot;true&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--reach-color, var(--frontend-stroke)) 72%, var(--toolbar-border));&#10;      background: color-mix(in srgb, var(--reach-fill, var(--frontend-fill)) 48%, transparent);&#10;      color: var(--text);&#10;    }&#10;    #btn-reach-upstream {&#10;      --reach-color: var(--database-stroke);&#10;      --reach-fill: var(--database-fill);&#10;    }&#10;    #btn-reach-downstream {&#10;      --reach-color: var(--backend-stroke);&#10;      --reach-fill: var(--backend-fill);&#10;    }&#10;    .semantic-passport-reach-actions strong {&#10;      color: var(--reach-color, var(--frontend-stroke));&#10;      font-size: 0.625rem;&#10;    }&#10;    .semantic-passport-reach-status {&#10;      color: var(--text-faint);&#10;      font-size: 0.525rem;&#10;      line-height: 1.4;&#10;    }&#10;    .semantic-passport-reach-status[hidden] { display: none; }&#10;    .relationship-lens-list {&#10;      max-height: min(18rem, 46vh);&#10;      overflow: auto;&#10;      padding: 0.4rem;&#10;      scrollbar-width: thin;&#10;      scrollbar-color: var(--frontend-stroke) transparent;&#10;    }&#10;    .relationship-lens-list::-webkit-scrollbar { width: 4px; }&#10;    .relationship-lens-list::-webkit-scrollbar-thumb {&#10;      border-radius: 999px;&#10;      background: color-mix(in srgb, var(--frontend-stroke) 68%, transparent);&#10;    }&#10;    .relationship-lens-group + .relationship-lens-group { margin-top: 0.35rem; }&#10;    .relationship-lens-group-title {&#10;      display: block;&#10;      padding: 0.24rem 0.38rem 0.16rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.12em;&#10;      text-transform: uppercase;&#10;    }&#10;    .relationship-lens-row {&#10;      display: grid;&#10;      grid-template-columns: 2.1rem minmax(0, 1fr);&#10;      gap: 0.06rem 0.45rem;&#10;      width: 100%;&#10;      padding: 0.45rem 0.5rem !important;&#10;      text-align: left;&#10;    }&#10;    .relationship-lens-row:hover,&#10;    .relationship-lens-row:focus-visible,&#10;    .relationship-lens-row[data-preview-active=&amp;quot;true&amp;quot;] {&#10;      background: var(--toolbar-hover);&#10;      box-shadow: inset 2px 0 0 var(--frontend-stroke);&#10;    }&#10;    .relationship-lens-row:focus-visible {&#10;      outline: 2px solid var(--frontend-stroke);&#10;      outline-offset: -2px;&#10;    }&#10;    .relationship-lens-direction {&#10;      grid-row: 1 / 3;&#10;      align-self: center;&#10;      color: var(--frontend-stroke);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.08em;&#10;    }&#10;    .relationship-lens-row[data-direction=&amp;quot;in&amp;quot;] .relationship-lens-direction { color: var(--database-stroke); }&#10;    .relationship-lens-row[data-direction=&amp;quot;loop&amp;quot;] .relationship-lens-direction { color: var(--security-stroke); }&#10;    .relationship-lens-row strong {&#10;      overflow: hidden;&#10;      color: var(--text);&#10;      font-size: 0.6875rem;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .relationship-lens-row small {&#10;      overflow: hidden;&#10;      color: var(--text-faint);&#10;      font-size: 0.5625rem;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .relationship-lens-empty {&#10;      margin: 0;&#10;      padding: 0.75rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.625rem;&#10;      text-align: center;&#10;    }&#10;&#10;    /* Diagram Guide keeps the artifact&amp;#x27;s growing reader vocabulary&#10;       discoverable without widening the permanent control bar. It derives&#10;       honest counts at runtime and delegates every action to an existing&#10;       production interaction instead of creating a second command system. */&#10;    .diagram-guide {&#10;      position: absolute;&#10;      top: 1rem;&#10;      right: 1rem;&#10;      z-index: 26;&#10;      width: min(32rem, calc(100% - 2rem));&#10;      max-height: min(42rem, calc(100% - 2rem));&#10;      overflow: auto;&#10;      border: 1px solid color-mix(in srgb, var(--cloud-stroke) 58%, var(--toolbar-border));&#10;      border-radius: 0.82rem;&#10;      background:&#10;        linear-gradient(135deg, color-mix(in srgb, var(--cloud-fill) 32%, transparent), transparent 42%),&#10;        var(--toolbar-menu-bg);&#10;      color: var(--toolbar-text);&#10;      box-shadow: 0 22px 64px rgba(0, 0, 0, 0.4);&#10;      backdrop-filter: blur(18px);&#10;      animation: archify-guide-in 180ms cubic-bezier(0.22, 1, 0.36, 1);&#10;    }&#10;    .diagram-guide[hidden] { display: none; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .diagram-guide { border-radius: 0.28rem; }&#10;    .diagram-guide-head {&#10;      display: grid;&#10;      grid-template-columns: minmax(0, 1fr) auto;&#10;      align-items: start;&#10;      gap: 1rem;&#10;      padding: 0.82rem 0.9rem 0.68rem;&#10;      border-bottom: 1px solid var(--toolbar-border);&#10;    }&#10;    .diagram-guide-eyebrow {&#10;      display: block;&#10;      color: var(--cloud-stroke);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.16em;&#10;      text-transform: uppercase;&#10;    }&#10;    .diagram-guide-title {&#10;      display: block;&#10;      margin-top: 0.16rem;&#10;      color: var(--text);&#10;      font-size: 0.86rem;&#10;      letter-spacing: -0.02em;&#10;    }&#10;    .diagram-guide-close {&#10;      width: 1.8rem;&#10;      height: 1.8rem;&#10;      border: 0;&#10;      border-radius: 0.35rem;&#10;      background: transparent;&#10;      color: var(--toolbar-text);&#10;      font: inherit;&#10;      font-size: 1rem;&#10;      cursor: pointer;&#10;    }&#10;    .diagram-guide-close:hover,&#10;    .diagram-guide-close:focus-visible { background: var(--toolbar-hover); }&#10;    .diagram-guide-stats {&#10;      display: flex;&#10;      align-items: center;&#10;      gap: 0.5rem;&#10;      margin: 0;&#10;      padding: 0.54rem 0.9rem;&#10;      border-bottom: 1px solid color-mix(in srgb, var(--toolbar-border) 74%, transparent);&#10;      color: var(--text-faint);&#10;      font-size: 0.56rem;&#10;      letter-spacing: 0.025em;&#10;    }&#10;    .diagram-guide-stats::before {&#10;      content: &amp;#x27;&amp;#x27;;&#10;      width: 0.42rem;&#10;      height: 0.42rem;&#10;      flex: none;&#10;      border-radius: 50%;&#10;      background: var(--backend-stroke);&#10;      box-shadow: 0 0 10px color-mix(in srgb, var(--backend-stroke) 72%, transparent);&#10;    }&#10;    .diagram-guide-actions {&#10;      display: grid;&#10;      grid-template-columns: 1fr 1fr;&#10;      gap: 0.38rem;&#10;      padding: 0.62rem;&#10;    }&#10;    .diagram-guide-action {&#10;      --guide-accent: var(--frontend-stroke);&#10;      display: grid;&#10;      grid-template-columns: auto minmax(0, 1fr) auto;&#10;      align-items: center;&#10;      gap: 0.55rem;&#10;      min-height: 4.15rem;&#10;      padding: 0.55rem 0.58rem;&#10;      border: 1px solid color-mix(in srgb, var(--guide-accent) 22%, var(--toolbar-border));&#10;      border-radius: 0.55rem;&#10;      background: color-mix(in srgb, var(--panel) 78%, transparent);&#10;      color: var(--toolbar-text);&#10;      font: inherit;&#10;      text-align: left;&#10;      cursor: pointer;&#10;      transition: border-color 140ms ease, background 140ms ease, transform 140ms ease;&#10;    }&#10;    .diagram-guide-action[data-guide-action=&amp;quot;route&amp;quot;] { --guide-accent: var(--backend-stroke); }&#10;    .diagram-guide-action[data-guide-action=&amp;quot;map&amp;quot;] { --guide-accent: var(--database-stroke); }&#10;    .diagram-guide-action[data-guide-action=&amp;quot;lens&amp;quot;] { --guide-accent: var(--messagebus-stroke); }&#10;    .diagram-guide-action[data-guide-action=&amp;quot;story&amp;quot;] { --guide-accent: var(--security-stroke); }&#10;    .diagram-guide-action[data-guide-action=&amp;quot;present&amp;quot;] {&#10;      --guide-accent: var(--cloud-stroke);&#10;    }&#10;    .diagram-guide-action:hover,&#10;    .diagram-guide-action:focus-visible {&#10;      border-color: color-mix(in srgb, var(--guide-accent) 76%, var(--toolbar-border));&#10;      background: color-mix(in srgb, var(--guide-accent) 9%, var(--panel));&#10;      transform: translateY(-1px);&#10;    }&#10;    .diagram-guide-action:focus-visible,&#10;    .diagram-guide-close:focus-visible {&#10;      outline: 2px solid var(--cloud-stroke);&#10;      outline-offset: 1px;&#10;    }&#10;    .diagram-guide-action:disabled {&#10;      opacity: 0.42;&#10;      cursor: default;&#10;      transform: none;&#10;    }&#10;    .diagram-guide-index {&#10;      display: grid;&#10;      place-items: center;&#10;      width: 1.65rem;&#10;      height: 1.65rem;&#10;      border: 1px solid color-mix(in srgb, var(--guide-accent) 64%, var(--toolbar-border));&#10;      border-radius: 0.35rem;&#10;      color: var(--guide-accent);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.06em;&#10;    }&#10;    .diagram-guide-action-copy { min-width: 0; }&#10;    .diagram-guide-action strong {&#10;      display: block;&#10;      overflow: hidden;&#10;      color: var(--text);&#10;      font-size: 0.66rem;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .diagram-guide-action small {&#10;      display: -webkit-box;&#10;      margin-top: 0.18rem;&#10;      overflow: hidden;&#10;      color: var(--text-faint);&#10;      font-size: 0.5rem;&#10;      line-height: 1.35;&#10;      -webkit-box-orient: vertical;&#10;      -webkit-line-clamp: 2;&#10;    }&#10;    .diagram-guide kbd {&#10;      align-self: start;&#10;      min-width: 1.45rem;&#10;      padding: 0.12rem 0.3rem;&#10;      border: 1px solid var(--toolbar-border);&#10;      border-radius: 0.25rem;&#10;      color: var(--text-faint);&#10;      font: inherit;&#10;      font-size: 0.5rem;&#10;      text-align: center;&#10;    }&#10;    .diagram-guide-shortcuts {&#10;      display: flex;&#10;      flex-wrap: wrap;&#10;      gap: 0.34rem 0.62rem;&#10;      padding: 0.58rem 0.9rem 0.68rem;&#10;      border-top: 1px solid var(--toolbar-border);&#10;      color: var(--text-faint);&#10;      font-size: 0.5rem;&#10;    }&#10;    .diagram-guide-shortcuts span {&#10;      display: inline-flex;&#10;      align-items: center;&#10;      gap: 0.28rem;&#10;      white-space: nowrap;&#10;    }&#10;    .diagram-guide-feedback {&#10;      min-height: 1rem;&#10;      margin: -0.18rem 0.9rem 0.62rem;&#10;      color: var(--security-stroke);&#10;      font-size: 0.5rem;&#10;    }&#10;    .diagram-guide-feedback:empty { display: none; }&#10;    @keyframes archify-guide-in {&#10;      from { opacity: 0; transform: translateY(-5px) scale(0.985); }&#10;      to { opacity: 1; transform: translateY(0) scale(1); }&#10;    }&#10;&#10;    .node-finder {&#10;      position: absolute;&#10;      top: 1rem;&#10;      left: 1rem;&#10;      z-index: 24;&#10;      display: flex;&#10;      flex-direction: column;&#10;      width: min(22rem, calc(100% - 2rem));&#10;      max-height: calc(100% - 2rem);&#10;      overflow: hidden;&#10;      border: 1px solid var(--toolbar-border);&#10;      border-radius: 0.85rem;&#10;      background: var(--toolbar-menu-bg);&#10;      color: var(--toolbar-text);&#10;      box-shadow: 0 6px 8px rgba(0, 0, 0, 0.22);&#10;      backdrop-filter: blur(16px);&#10;    }&#10;    .node-finder[hidden] { display: none; }&#10;    .node-finder[data-context=&amp;quot;route-source&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 68%, var(--toolbar-border));&#10;    }&#10;    .node-finder[data-context=&amp;quot;route-target&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--security-stroke) 68%, var(--toolbar-border));&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .node-finder { border-radius: 0.3rem; }&#10;    .node-finder-head {&#10;      display: flex;&#10;      align-items: center;&#10;      justify-content: space-between;&#10;      gap: 1rem;&#10;      padding: 0.7rem 0.8rem 0.45rem;&#10;    }&#10;    .node-finder-head strong {&#10;      color: var(--text);&#10;      font-size: 0.6875rem;&#10;      letter-spacing: 0.08em;&#10;      text-transform: uppercase;&#10;    }&#10;    .node-finder[data-context=&amp;quot;route-source&amp;quot;] .node-finder-head strong { color: var(--frontend-stroke); }&#10;    .node-finder[data-context=&amp;quot;route-target&amp;quot;] .node-finder-head strong { color: var(--security-stroke); }&#10;    .node-finder-close {&#10;      width: 1.75rem;&#10;      height: 1.75rem;&#10;      border: 0;&#10;      border-radius: 0.35rem;&#10;      background: transparent;&#10;      color: var(--toolbar-text);&#10;      font: inherit;&#10;      font-size: 1rem;&#10;      cursor: pointer;&#10;    }&#10;    .node-finder-close:hover,&#10;    .node-finder-close:focus-visible { background: var(--toolbar-hover); }&#10;    .node-finder-close:focus-visible,&#10;    .node-finder-result:focus-visible {&#10;      outline: 2px solid var(--frontend-stroke);&#10;      outline-offset: -2px;&#10;    }&#10;    .node-finder-search {&#10;      display: grid;&#10;      grid-template-columns: auto minmax(0, 1fr) auto;&#10;      align-items: center;&#10;      gap: 0.55rem;&#10;      margin: 0 0.55rem 0.55rem;&#10;      padding: 0 0.7rem;&#10;      min-height: 2.6rem;&#10;      border: 1px solid var(--toolbar-border);&#10;      border-radius: 0.55rem;&#10;      background: color-mix(in srgb, var(--panel) 78%, transparent);&#10;      transition: border-color 160ms ease-out, box-shadow 160ms ease-out;&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .node-finder-search { border-radius: 0.18rem; }&#10;    .node-finder-search &amp;gt; span { color: var(--frontend-stroke); font-size: 0.875rem; }&#10;    .node-finder-search:focus-within {&#10;      border-color: var(--frontend-stroke);&#10;      box-shadow: 0 0 0 2px color-mix(in srgb, var(--frontend-stroke) 20%, transparent);&#10;    }&#10;    .node-finder-input {&#10;      appearance: none;&#10;      width: 100%;&#10;      min-width: 0;&#10;      border: 0;&#10;      outline: 0;&#10;      background: transparent;&#10;      color: var(--text);&#10;      font: inherit;&#10;      font-size: 0.75rem;&#10;    }&#10;    .node-finder-input:focus-visible { outline: none; }&#10;    .node-finder-input::placeholder { color: var(--text-faint); }&#10;    .node-finder kbd {&#10;      padding: 0.1rem 0.32rem;&#10;      border: 1px solid var(--toolbar-border);&#10;      border-radius: 0.25rem;&#10;      color: var(--text-faint);&#10;      font: inherit;&#10;      font-size: 0.5625rem;&#10;    }&#10;    .node-finder-results {&#10;      display: grid;&#10;      flex: 1 1 auto;&#10;      gap: 0;&#10;      min-height: 0;&#10;      max-height: min(18rem, 48vh);&#10;      margin: 0 0.55rem 0.45rem;&#10;      padding: 0;&#10;      overflow-y: auto;&#10;      overscroll-behavior: contain;&#10;      border: 1px solid color-mix(in srgb, var(--toolbar-border) 78%, transparent);&#10;      border-radius: 0.55rem;&#10;      background: color-mix(in srgb, var(--panel) 54%, transparent);&#10;      scroll-padding-block: 0.25rem;&#10;      scrollbar-width: thin;&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .node-finder-results { border-radius: 0.18rem; }&#10;    .node-finder-result {&#10;      display: grid;&#10;      grid-template-columns: minmax(0, 1fr) auto;&#10;      gap: 0.2rem 0.75rem;&#10;      width: 100%;&#10;      min-height: 3.25rem;&#10;      padding: 0.58rem 0.65rem;&#10;      border: 0;&#10;      border-radius: 0;&#10;      background: transparent;&#10;      color: var(--text);&#10;      font: inherit;&#10;      text-align: left;&#10;      cursor: pointer;&#10;      transition: background-color 160ms ease-out;&#10;    }&#10;    .node-finder-result:not(:last-child) {&#10;      border-bottom: 1px solid color-mix(in srgb, var(--toolbar-border) 62%, transparent);&#10;    }&#10;    .node-finder-result:hover,&#10;    .node-finder-result:focus-visible {&#10;      position: relative;&#10;      z-index: 1;&#10;      background: color-mix(in srgb, var(--frontend-fill) 48%, var(--toolbar-hover));&#10;    }&#10;    .node-finder-result strong {&#10;      overflow: hidden;&#10;      font-size: 0.75rem;&#10;      line-height: 1.25;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .node-finder-result small {&#10;      grid-column: 1 / -1;&#10;      overflow: hidden;&#10;      color: var(--text-faint);&#10;      font-size: 0.5625rem;&#10;      letter-spacing: 0.015em;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .node-finder-result em {&#10;      align-self: center;&#10;      color: var(--frontend-stroke);&#10;      font-size: 0.625rem;&#10;      font-style: normal;&#10;    }&#10;    .node-finder[data-context^=&amp;quot;route-&amp;quot;] .node-finder-result em {&#10;      padding: 0.1rem 0.3rem;&#10;      border: 1px solid color-mix(in srgb, currentColor 52%, transparent);&#10;      border-radius: 999px;&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.05em;&#10;      text-transform: uppercase;&#10;    }&#10;    .node-finder[data-context=&amp;quot;route-target&amp;quot;] .node-finder-result em { color: var(--security-stroke); }&#10;    .node-finder-empty {&#10;      padding: 1.1rem 0.75rem 1.25rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.6875rem;&#10;      text-align: center;&#10;    }&#10;    .node-finder-status {&#10;      margin: 0;&#10;      padding: 0.1rem 0.8rem 0.65rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.5625rem;&#10;    }&#10;&#10;    .guided-views {&#10;      display: grid;&#10;      grid-template-columns: 2.75rem minmax(0, 1fr) 2.75rem auto;&#10;      align-items: stretch;&#10;      gap: 0.35rem;&#10;      min-width: 0;&#10;      margin: 0 0 0.75rem;&#10;      padding: 0.35rem;&#10;      border: 1px solid var(--toolbar-border);&#10;      border-radius: 0.85rem;&#10;      background: var(--toolbar-bg);&#10;      background: linear-gradient(120deg, var(--toolbar-bg), color-mix(in srgb, var(--toolbar-bg) 82%, var(--frontend-fill)));&#10;      box-shadow: 0 12px 36px rgba(0, 0, 0, 0.16);&#10;      backdrop-filter: blur(12px);&#10;    }&#10;    .guided-views[hidden] { display: none; }&#10;&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-views {&#10;      border-color: var(--panel-border);&#10;      border-radius: 0.35rem;&#10;      background:&#10;        linear-gradient(90deg, color-mix(in srgb, var(--frontend-fill) 36%, transparent), transparent 24%),&#10;        var(--toolbar-bg);&#10;      box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12);&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-views button { border-radius: 0.2rem; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-view-progress { border-radius: 0; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-view-progress span { border-radius: 0; }&#10;    .guided-views button {&#10;      min-width: 0;&#10;      padding: 0.45rem 0.6rem;&#10;      border-radius: 0.55rem;&#10;      font-size: 0.75rem;&#10;    }&#10;    .guided-views &amp;gt; #guided-view-prev,&#10;    .guided-views &amp;gt; #guided-view-next { min-width: 2.75rem; min-height: 2.75rem; }&#10;    .guided-views button:disabled { opacity: 0.3; cursor: default; }&#10;    .guided-view-copy {&#10;      min-width: 0;&#10;      padding: 0.2rem 0.5rem;&#10;      border-left: 1px solid var(--toolbar-border);&#10;      overflow: hidden;&#10;    }&#10;    .guided-view-meta {&#10;      display: flex;&#10;      align-items: center;&#10;      gap: 0.5rem;&#10;      min-height: 1rem;&#10;      margin-bottom: 0.12rem;&#10;      color: var(--frontend-stroke);&#10;      font-size: 0.5625rem;&#10;      font-weight: 700;&#10;      letter-spacing: 0.12em;&#10;      text-transform: uppercase;&#10;    }&#10;    .guided-view-handoff {&#10;      box-sizing: border-box;&#10;      height: 1rem;&#10;      min-width: 0;&#10;      max-width: 15rem;&#10;      overflow: hidden;&#10;      padding: 0 0.38rem;&#10;      border: 1px solid color-mix(in srgb, var(--frontend-stroke) 46%, transparent);&#10;      border-radius: 999px;&#10;      color: var(--toolbar-text);&#10;      background: color-mix(in srgb, var(--frontend-fill) 44%, transparent);&#10;      font-size: 0.5rem;&#10;      line-height: calc(1rem - 2px);&#10;      letter-spacing: 0.06em;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .guided-view-handoff[hidden] { display: none; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-view-handoff { border-radius: 0.15rem; }&#10;    .chapter-handoff-overlay { pointer-events: none; }&#10;    .chapter-handoff-anchor {&#10;      fill: color-mix(in srgb, var(--frontend-fill) 10%, transparent);&#10;      stroke: var(--frontend-stroke);&#10;      stroke-width: 2;&#10;      stroke-dasharray: 4 4;&#10;      vector-effect: non-scaling-stroke;&#10;      opacity: 0.96;&#10;      animation: archify-chapter-anchor 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;&#10;    }&#10;    svg[data-chapter-handoff] [data-node-id][data-chapter-role=&amp;quot;stay&amp;quot;] { opacity: 1; }&#10;    svg[data-chapter-handoff] [data-node-id][data-chapter-role=&amp;quot;enter&amp;quot;] { opacity: 0.78; }&#10;    svg[data-chapter-handoff] [data-node-id][data-chapter-role=&amp;quot;leave&amp;quot;] { opacity: 0.26; }&#10;    @keyframes archify-chapter-anchor {&#10;      0% { opacity: 0.35; stroke-dashoffset: 8; }&#10;      45% { opacity: 1; }&#10;      100% { opacity: 0.72; stroke-dashoffset: 0; }&#10;    }&#10;    .guided-view-progress {&#10;      width: 3.5rem;&#10;      height: 2px;&#10;      overflow: hidden;&#10;      border-radius: 999px;&#10;      background: var(--toolbar-border);&#10;    }&#10;    .guided-view-progress span {&#10;      display: block;&#10;      width: 100%;&#10;      height: 100%;&#10;      border-radius: inherit;&#10;      background: var(--frontend-stroke);&#10;      transform: scaleX(0);&#10;      transform-origin: left center;&#10;    }&#10;    .guided-view-copy strong,&#10;    .guided-view-copy small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }&#10;    .guided-view-copy strong { color: var(--toolbar-text); font-size: 0.75rem; line-height: 1.35; }&#10;    .guided-view-copy small { margin-top: 0; color: var(--text-muted); font-size: 0.625rem; line-height: 1.35; }&#10;    .guided-story-caption {&#10;      display: grid;&#10;      grid-template-columns: auto minmax(0, 1fr) auto;&#10;      gap: 0.12rem 0.55rem;&#10;      align-items: center;&#10;      min-width: 0;&#10;      margin-top: 0.18rem;&#10;      padding: 0.3rem 0.5rem;&#10;      overflow: hidden;&#10;      border: 1px solid color-mix(in srgb, var(--frontend-stroke) 32%, var(--toolbar-border));&#10;      border-radius: 0.58rem;&#10;      background: color-mix(in srgb, var(--frontend-fill) 26%, transparent);&#10;      animation: archify-story-caption-in 140ms cubic-bezier(0.22, 1, 0.36, 1) both;&#10;    }&#10;    .guided-story-caption[hidden] { display: none; }&#10;    .guided-story-caption-index {&#10;      grid-row: 1 / span 2;&#10;      align-self: stretch;&#10;      display: inline-grid;&#10;      min-width: 3.3rem;&#10;      place-items: center;&#10;      padding-right: 0.52rem;&#10;      border-right: 1px solid color-mix(in srgb, var(--frontend-stroke) 28%, var(--toolbar-border));&#10;      color: var(--frontend-stroke);&#10;      font-size: 0.5625rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.08em;&#10;      text-transform: uppercase;&#10;    }&#10;    .guided-story-caption strong,&#10;    .guided-story-caption small {&#10;      display: block;&#10;      min-width: 0;&#10;      overflow: hidden;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .guided-story-caption strong { color: var(--toolbar-text); font-size: 0.6875rem; line-height: 1.3; }&#10;    .guided-story-caption small { color: var(--text-muted); font-size: 0.5625rem; line-height: 1.35; }&#10;    .guided-story-caption-next {&#10;      grid-column: 3;&#10;      grid-row: 1 / span 2;&#10;      display: grid;&#10;      min-width: 6.4rem;&#10;      max-width: 9.5rem;&#10;      align-self: stretch;&#10;      align-content: center;&#10;      padding-left: 0.58rem;&#10;      border-left: 1px solid color-mix(in srgb, var(--frontend-stroke) 22%, var(--toolbar-border));&#10;    }&#10;    .guided-story-caption-next[hidden] { display: none; }&#10;    .guided-story-caption-next small {&#10;      color: color-mix(in srgb, var(--frontend-stroke) 72%, var(--text-muted));&#10;      font-weight: 800;&#10;      letter-spacing: 0.09em;&#10;      text-transform: uppercase;&#10;    }&#10;    .guided-story-caption-next strong { color: var(--text-muted); font-weight: 700; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-story-caption { border-radius: 0.2rem; }&#10;    .guided-views[data-story-beat] .guided-view-copy &amp;gt; #guided-view-label,&#10;    .guided-views[data-story-beat] .guided-view-copy &amp;gt; #guided-view-note { display: none; }&#10;    @keyframes archify-story-caption-in {&#10;      from { opacity: 0; transform: translateY(3px); }&#10;      to { opacity: 1; transform: translateY(0); }&#10;    }&#10;    .guided-view-trail {&#10;      display: flex;&#10;      align-items: center;&#10;      gap: 0.28rem;&#10;      min-width: 0;&#10;      min-height: 1.7rem;&#10;      margin-top: 0;&#10;      padding: 0;&#10;      overflow-x: auto;&#10;      color: var(--text-faint);&#10;      overscroll-behavior-x: contain;&#10;      touch-action: pan-x;&#10;      scrollbar-width: none;&#10;      white-space: nowrap;&#10;    }&#10;    .guided-view-trail[hidden] { display: none; }&#10;    .guided-view-trail::-webkit-scrollbar { display: none; }&#10;    .guided-view-trail .guided-view-stop {&#10;      appearance: none;&#10;      box-sizing: border-box;&#10;      display: inline-flex;&#10;      flex: 0 0 auto;&#10;      align-items: center;&#10;      gap: 0.28rem;&#10;      min-height: 1.5rem;&#10;      padding: 0.1rem 0.3rem 0.1rem 0.18rem;&#10;      border: 1px solid transparent;&#10;      border-radius: 999px;&#10;      background: transparent;&#10;      color: var(--text-muted);&#10;      cursor: pointer;&#10;      font-family: inherit;&#10;      font-size: 0.5625rem;&#10;      font-weight: 650;&#10;      letter-spacing: 0.02em;&#10;      line-height: 1;&#10;      transition: background 140ms ease, border-color 140ms ease, color 140ms ease, opacity 140ms ease;&#10;    }&#10;    .guided-view-stop:hover {&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 36%, transparent);&#10;      background: color-mix(in srgb, var(--frontend-fill) 34%, transparent);&#10;    }&#10;    .guided-view-stop:focus-visible {&#10;      outline: 2px solid var(--frontend-stroke);&#10;      outline-offset: 1px;&#10;    }&#10;    .guided-view-stop:disabled { cursor: wait; }&#10;    .guided-view-stop::before {&#10;      display: inline-grid;&#10;      width: 1rem;&#10;      height: 1rem;&#10;      place-items: center;&#10;      border: 1px solid color-mix(in srgb, var(--frontend-stroke) 54%, var(--toolbar-border));&#10;      border-radius: 50%;&#10;      background: color-mix(in srgb, var(--frontend-fill) 58%, var(--toolbar-bg));&#10;      color: var(--frontend-stroke);&#10;      content: attr(data-story-number);&#10;      font-size: 0.5rem;&#10;      line-height: 1;&#10;    }&#10;    .guided-view-stop + .guided-view-stop::after {&#10;      order: -1;&#10;      color: color-mix(in srgb, var(--frontend-stroke) 58%, var(--text-faint));&#10;      content: &amp;#x27;\00b7&amp;#x27;;&#10;      font-size: 0.65rem;&#10;    }&#10;    .guided-view-stop[data-story-link=&amp;quot;forward&amp;quot;]::after { content: &amp;#x27;\2192&amp;#x27;; }&#10;    .guided-view-stop[data-story-link=&amp;quot;reverse&amp;quot;]::after { content: &amp;#x27;\2190&amp;#x27;; }&#10;    .guided-view-stop[data-story-link=&amp;quot;multiple&amp;quot;]::after { content: &amp;#x27;\21c4&amp;#x27;; }&#10;    .guided-view-stop[data-story-beat-state=&amp;quot;pending&amp;quot;] { opacity: 0.38; }&#10;    .guided-view-stop[data-story-beat-state=&amp;quot;next&amp;quot;] {&#10;      border-style: dashed;&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 42%, var(--toolbar-border));&#10;      color: color-mix(in srgb, var(--toolbar-text) 68%, var(--text-muted));&#10;      opacity: 0.58;&#10;    }&#10;    .guided-view-stop[data-story-beat-state=&amp;quot;past&amp;quot;] { color: var(--text-muted); opacity: 0.76; }&#10;    .guided-view-stop[data-story-beat-state=&amp;quot;active&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 72%, var(--toolbar-border));&#10;      background: color-mix(in srgb, var(--frontend-fill) 42%, transparent);&#10;      color: var(--toolbar-text);&#10;      font-weight: 800;&#10;      opacity: 1;&#10;    }&#10;    .guided-view-stop[data-story-beat-state=&amp;quot;active&amp;quot;]::before {&#10;      border-color: var(--frontend-stroke);&#10;      box-shadow: 0 0 10px color-mix(in srgb, var(--frontend-stroke) 54%, transparent);&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-view-stop,&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-view-stop::before { border-radius: 0.1rem; }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-view-stop[data-story-beat-state=&amp;quot;active&amp;quot;]::before { box-shadow: none; }&#10;    .guided-view-actions { display: flex; align-items: stretch; gap: 0.2rem; }&#10;    .guided-view-actions button { white-space: nowrap; }&#10;    .guided-view-play {&#10;      display: inline-flex;&#10;      align-items: center;&#10;      justify-content: center;&#10;      gap: 0.38rem;&#10;      min-width: 6.25rem !important;&#10;      color: var(--frontend-stroke) !important;&#10;      font-size: 0.625rem !important;&#10;    }&#10;    .guided-view-play[aria-pressed=&amp;quot;true&amp;quot;] { background: var(--toolbar-hover); }&#10;    .guided-view-all { min-width: 3.25rem !important; color: var(--text-muted) !important; font-size: 0.625rem !important; }&#10;    .guided-view-beat-link {&#10;      display: inline-flex;&#10;      align-items: center;&#10;      justify-content: center;&#10;      gap: 0.3rem;&#10;      min-width: 5.4rem !important;&#10;      min-height: 1.5rem;&#10;      color: var(--text-muted) !important;&#10;      font-size: 0.5625rem !important;&#10;      letter-spacing: 0.025em;&#10;      transition: background 140ms ease, border-color 140ms ease, color 140ms ease;&#10;    }&#10;    .guided-view-beat-link:not(:disabled):hover {&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 52%, var(--toolbar-border));&#10;      color: var(--frontend-stroke) !important;&#10;    }&#10;    .guided-view-beat-link[data-copy-state=&amp;quot;copied&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--backend-stroke) 58%, var(--toolbar-border));&#10;      background: color-mix(in srgb, var(--backend-fill) 46%, transparent);&#10;      color: var(--backend-stroke) !important;&#10;    }&#10;    .guided-view-index {&#10;      grid-column: 1 / -1;&#10;      min-width: 0;&#10;      padding: 0.28rem 0.12rem 0.08rem;&#10;      overflow: hidden;&#10;      border-top: 1px solid color-mix(in srgb, var(--toolbar-border) 72%, transparent);&#10;    }&#10;    @media (min-width: 721px) {&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-views[data-playing=&amp;quot;true&amp;quot;] .guided-view-index,&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-views[data-playing=&amp;quot;true&amp;quot;] .guided-view-beat-link,&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-views[data-playing=&amp;quot;true&amp;quot;] .guided-view-all,&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-views[data-playing=&amp;quot;true&amp;quot;] .guided-view-trail,&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-views[data-playing=&amp;quot;true&amp;quot;] .guided-view-copy &amp;gt; #guided-view-label,&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-views[data-playing=&amp;quot;true&amp;quot;] .guided-view-copy &amp;gt; #guided-view-note { display: none; }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-views[data-playing=&amp;quot;true&amp;quot;] .guided-story-caption { margin-top: 0.08rem; }&#10;    }&#10;    .guided-view-chapters {&#10;      display: flex;&#10;      gap: 0.28rem;&#10;      min-width: 0;&#10;      margin: 0;&#10;      padding: 0.08rem 0.05rem 0.2rem;&#10;      overflow-x: auto;&#10;      list-style: none;&#10;      scroll-padding-inline: 0.05rem;&#10;      scroll-snap-type: x proximity;&#10;      scrollbar-width: none;&#10;    }&#10;    .guided-view-chapters::-webkit-scrollbar { display: none; }&#10;    .guided-view-chapters li {&#10;      display: flex;&#10;      flex: 1 1 0;&#10;      min-width: 9.5rem;&#10;      scroll-snap-align: center;&#10;    }&#10;    .guided-view-chapter {&#10;      position: relative;&#10;      display: grid !important;&#10;      grid-template-columns: 1.55rem minmax(0, 1fr) auto;&#10;      align-items: center;&#10;      width: 100%;&#10;      min-height: 2.75rem;&#10;      padding: 0.36rem 0.48rem !important;&#10;      overflow: hidden;&#10;      border: 1px solid color-mix(in srgb, var(--toolbar-border) 86%, transparent) !important;&#10;      border-radius: 0.48rem !important;&#10;      background: color-mix(in srgb, var(--toolbar-bg) 88%, transparent) !important;&#10;      color: var(--text-muted) !important;&#10;      text-align: left;&#10;      transition: background 0.16s ease, border-color 0.16s ease, opacity 0.16s ease;&#10;    }&#10;    .guided-view-chapter:hover {&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 58%, var(--toolbar-border)) !important;&#10;      background: color-mix(in srgb, var(--frontend-fill) 42%, var(--toolbar-bg)) !important;&#10;    }&#10;    .guided-view-chapter:focus-visible {&#10;      outline: 2px solid var(--frontend-stroke);&#10;      outline-offset: 1px;&#10;    }&#10;    .guided-view-chapter-index {&#10;      display: inline-grid;&#10;      width: 1.32rem;&#10;      height: 1.32rem;&#10;      place-items: center;&#10;      border: 1px solid color-mix(in srgb, var(--frontend-stroke) 48%, var(--toolbar-border));&#10;      border-radius: 50%;&#10;      color: var(--frontend-stroke);&#10;      font-size: 0.5rem;&#10;      font-weight: 800;&#10;      letter-spacing: 0.03em;&#10;    }&#10;    .guided-view-chapter-title {&#10;      min-width: 0;&#10;      overflow: hidden;&#10;      color: var(--toolbar-text);&#10;      font-size: 0.625rem;&#10;      font-weight: 700;&#10;      line-height: 1.3;&#10;      text-overflow: ellipsis;&#10;      white-space: nowrap;&#10;    }&#10;    .guided-view-chapter-count {&#10;      grid-column: 3;&#10;      grid-row: 1;&#10;      margin-left: 0.38rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.5rem;&#10;      font-style: normal;&#10;      font-weight: 650;&#10;      white-space: nowrap;&#10;    }&#10;    .guided-view-chapter-delta {&#10;      display: inline-flex;&#10;      grid-column: 3;&#10;      grid-row: 1;&#10;      align-items: center;&#10;      gap: 0.22rem;&#10;      margin-left: 0.38rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.5rem;&#10;      font-weight: 750;&#10;      letter-spacing: 0.01em;&#10;      white-space: nowrap;&#10;    }&#10;    .guided-view-chapter-delta[hidden] { display: none; }&#10;    .guided-view-chapter-delta [data-delta-kind=&amp;quot;stay&amp;quot;] { color: var(--text-muted); }&#10;    .guided-view-chapter-delta [data-delta-kind=&amp;quot;enter&amp;quot;] { color: var(--frontend-stroke); }&#10;    .guided-view-chapter-delta [data-delta-kind=&amp;quot;leave&amp;quot;] { color: var(--security-stroke); }&#10;    .guided-view-chapter[data-preview-active=&amp;quot;true&amp;quot;] {&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 72%, var(--toolbar-border)) !important;&#10;      background: color-mix(in srgb, var(--frontend-fill) 54%, var(--toolbar-bg)) !important;&#10;    }&#10;    .guided-view-chapter[data-chapter-position=&amp;quot;current&amp;quot;] {&#10;      border: 2px solid var(--frontend-stroke) !important;&#10;      padding: calc(0.36rem - 1px) calc(0.48rem - 1px) !important;&#10;      box-shadow: inset 3px 0 0 var(--frontend-stroke);&#10;      color: var(--toolbar-text) !important;&#10;    }&#10;    .guided-view-chapter[data-chapter-position=&amp;quot;current&amp;quot;] .guided-view-chapter-index {&#10;      background: var(--frontend-stroke);&#10;      color: var(--bg);&#10;    }&#10;    .guided-view-chapter[data-chapter-position=&amp;quot;before&amp;quot;] {&#10;      border-style: solid !important;&#10;      opacity: 0.72;&#10;    }&#10;    .guided-view-chapter[data-chapter-position=&amp;quot;after&amp;quot;] { border-style: dashed !important; }&#10;    html[data-preset=&amp;quot;signal-flow&amp;quot;] .guided-view-chapter[data-chapter-position=&amp;quot;current&amp;quot;] {&#10;      box-shadow: inset 3px 0 0 var(--frontend-stroke), 0 0 18px color-mix(in srgb, var(--frontend-stroke) 18%, transparent);&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-view-chapter,&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .guided-view-chapter-index { border-radius: 0.12rem !important; }&#10;&#10;    /* Story Shelf — keep every authored chapter and the Play action visible,&#10;       but do not spend a second row on unavailable director controls before&#10;       the reader enters a chapter. Existing data-active-view state expands&#10;       the full guided surface without a new toggle or stored preference. */&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] {&#10;      grid-template-columns: minmax(11rem, .72fr) auto minmax(0, 2fr);&#10;      align-items: center;&#10;      padding: 0.28rem 0.35rem;&#10;    }&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] &amp;gt; #guided-view-prev,&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] &amp;gt; #guided-view-next,&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-beat-link,&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-all { display: none; }&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-copy {&#10;      grid-column: 1;&#10;      grid-row: 1;&#10;      padding: 0.1rem 0.55rem;&#10;    }&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-copy &amp;gt; #guided-view-note { display: none; }&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-actions {&#10;      display: block;&#10;      grid-column: 2;&#10;      grid-row: 1;&#10;    }&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-play { min-height: 2.75rem; }&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-index {&#10;      grid-column: 3;&#10;      grid-row: 1;&#10;      padding: 0 0.08rem 0 0.42rem;&#10;      border-top: 0;&#10;      border-left: 1px solid color-mix(in srgb, var(--toolbar-border) 72%, transparent);&#10;    }&#10;    .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-chapters {&#10;      gap: 0.3rem;&#10;      padding: 0;&#10;    }&#10;&#10;    .cards {&#10;      display: grid;&#10;      grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));&#10;      gap: 1rem;&#10;      margin-top: 2rem;&#10;    }&#10;&#10;    .card {&#10;      background: var(--panel);&#10;      border-radius: 0.75rem;&#10;      border: 1px solid var(--panel-border);&#10;      padding: 1.25rem;&#10;    }&#10;&#10;    html[data-preset=&amp;quot;signal-flow&amp;quot;] .card {&#10;      background: linear-gradient(145deg, rgba(10, 24, 43, 0.86), rgba(5, 12, 24, 0.92));&#10;      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.035);&#10;    }&#10;    html[data-preset=&amp;quot;signal-flow&amp;quot;][data-theme=&amp;quot;light&amp;quot;] .card {&#10;      background: linear-gradient(145deg, rgba(255, 255, 255, 0.92), rgba(237, 246, 250, 0.9));&#10;      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.82), 0 12px 32px rgba(45, 78, 99, 0.08);&#10;    }&#10;&#10;    /* Preserve the one-screen guarantee on ordinary laptop displays. The&#10;       high-screen expansion above must not trade a fuller canvas for page&#10;       scrolling at 900–1080px heights. */&#10;    @media (min-width: 768px) and (max-height: 1100px) {&#10;      .header { margin-bottom: 1rem; }&#10;      .diagram-container {&#10;        padding: 0.875rem;&#10;        padding-bottom: calc(0.875rem + var(--archify-nav-reserve));&#10;      }&#10;      .cards { margin-top: 1rem; }&#10;      .card { padding: 1rem; }&#10;    }&#10;    @media (min-width: 768px) and (max-height: 920px) {&#10;      body { padding-block: 1.25rem; }&#10;      .header { margin-bottom: 0.875rem; }&#10;      .cards { margin-top: 0.75rem; }&#10;      html[data-nav-stage-rail=&amp;quot;true&amp;quot;] body { padding-block: 0.375rem; }&#10;      html[data-nav-stage-rail=&amp;quot;true&amp;quot;] .header { margin-bottom: 0.5rem; }&#10;      html[data-nav-stage-rail=&amp;quot;true&amp;quot;] .guided-views { margin-bottom: 0.375rem; }&#10;      html[data-nav-stage-rail=&amp;quot;true&amp;quot;] .diagram-container[data-nav-stage-rail=&amp;quot;true&amp;quot;] { padding-top: 0.5rem; }&#10;      html[data-nav-stage-rail=&amp;quot;true&amp;quot;] .cards { margin-top: 0.375rem; }&#10;    }&#10;&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .card {&#10;      position: relative;&#10;      border-color: var(--panel-border);&#10;      border-radius: 0.3rem;&#10;      background: var(--panel);&#10;      box-shadow: none;&#10;    }&#10;    html[data-preset=&amp;quot;blueprint&amp;quot;] .card::before {&#10;      content: &amp;quot;&amp;quot;;&#10;      position: absolute;&#10;      top: -1px;&#10;      left: 1rem;&#10;      width: 2.5rem;&#10;      border-top: 2px solid var(--frontend-stroke);&#10;    }&#10;&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .card {&#10;      position: relative;&#10;      border-radius: 0.28rem;&#10;      background: var(--panel);&#10;      box-shadow: 0 10px 28px color-mix(in srgb, #000 10%, transparent);&#10;    }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .card::before {&#10;      position: absolute;&#10;      top: -1px;&#10;      left: 1.25rem;&#10;      width: 3.25rem;&#10;      border-top: 3px solid var(--arrow-emphasis);&#10;      content: &amp;quot;&amp;quot;;&#10;    }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .card-dot { border-radius: 0; transform: rotate(45deg) scale(0.78); }&#10;&#10;    .card-header {&#10;      display: flex;&#10;      align-items: center;&#10;      gap: 0.5rem;&#10;      margin-bottom: 0.75rem;&#10;    }&#10;&#10;    .card-dot {&#10;      width: 8px;&#10;      height: 8px;&#10;      border-radius: 50%;&#10;    }&#10;&#10;    .card-dot.cyan     { background: var(--frontend-stroke); }&#10;    .card-dot.emerald  { background: var(--backend-stroke); }&#10;    .card-dot.violet   { background: var(--database-stroke); }&#10;    .card-dot.amber    { background: var(--cloud-stroke); }&#10;    .card-dot.rose     { background: var(--security-stroke); }&#10;    .card-dot.orange   { background: var(--messagebus-stroke); }&#10;    .card-dot.slate    { background: var(--external-stroke); }&#10;&#10;    .card h3 { font-size: 0.875rem; font-weight: 600; color: var(--text); }&#10;&#10;    .card ul {&#10;      list-style: none;&#10;      color: var(--text-muted);&#10;      font-size: 0.75rem;&#10;    }&#10;&#10;    .card li { margin-bottom: 0.375rem; }&#10;&#10;    /* ==========================================================&#10;       Print stylesheet — hide interactive controls, force light,&#10;       drop the grid so the diagram doesn&amp;#x27;t waste ink, use landscape&#10;       so wide diagrams fit, pack summary cards into 2 columns to&#10;       avoid an orphan card on a trailing page.&#10;       ========================================================== */&#10;    @page { size: landscape; margin: 1.5cm; }&#10;&#10;    @media print {&#10;      /* Force the FULL light palette — including component fills/strokes and&#10;         lane/arrow colors — so printing from dark theme doesn&amp;#x27;t put neon&#10;         strokes and translucent dark fills on white paper. */&#10;      :root, [data-theme=&amp;quot;dark&amp;quot;], [data-theme=&amp;quot;light&amp;quot;] {&#10;        --bg: #ffffff;&#10;        --grid: transparent;&#10;        --panel: #ffffff;&#10;        --panel-border: #e2e8f0;&#10;        --text: #0f172a;&#10;        --text-muted: #475569;&#10;        --text-dim: #94a3b8;&#10;        --text-faint: #64748b;&#10;        --mask: #ffffff;&#10;        --lane-fill: rgba(248, 250, 252, 0.65);&#10;        --lane-stroke: #cbd5e1;&#10;        --arrow: #94a3b8;&#10;        --arrow-emphasis: #059669;&#10;        --frontend-fill:    rgba(34, 211, 238, 0.15);&#10;        --frontend-stroke:  #0891b2;&#10;        --backend-fill:     rgba(52, 211, 153, 0.18);&#10;        --backend-stroke:   #059669;&#10;        --database-fill:    rgba(167, 139, 250, 0.2);&#10;        --database-stroke:  #7c3aed;&#10;        --cloud-fill:       rgba(251, 191, 36, 0.18);&#10;        --cloud-stroke:     #d97706;&#10;        --security-fill:    rgba(251, 113, 133, 0.15);&#10;        --security-stroke:  #e11d48;&#10;        --messagebus-fill:  rgba(251, 146, 60, 0.15);&#10;        --messagebus-stroke:#ea580c;&#10;        --external-fill:    rgba(148, 163, 184, 0.18);&#10;        --external-stroke:  #64748b;&#10;      }&#10;      body { background: #ffffff !important; padding: 0; }&#10;      .container { max-width: none; }&#10;      .toolbar, .diagram-nav, .focus-chip, .guided-views, .archify-toast, .no-print { display: none !important; }&#10;      .chapter-handoff-overlay { display: none !important; }&#10;      svg [data-node-id][data-chapter-role] { opacity: 1 !important; }&#10;      svg[data-chapter-preview] [data-node-id],&#10;      svg[data-chapter-preview] [data-edge-from] { opacity: 1 !important; filter: none !important; }&#10;      .diagram-container, .card { box-shadow: none; border-color: #e2e8f0; }&#10;      .diagram-container { --archify-nav-reserve: 0px !important; }&#10;      html[data-preset=&amp;quot;signal-flow&amp;quot;] .diagram-container,&#10;      html[data-preset=&amp;quot;signal-flow&amp;quot;] .card { background: #ffffff; }&#10;      .cards { grid-template-columns: 1fr 1fr; }&#10;      /* Ensure elements break sensibly across pages */&#10;      .card { break-inside: avoid; page-break-inside: avoid; }&#10;      .diagram-container { break-inside: avoid; page-break-inside: avoid; }&#10;      .diagram-container svg [data-detail] {&#10;        opacity: 1 !important;&#10;        pointer-events: auto !important;&#10;      }&#10;      .diagram-container svg [data-detail-anchor] { transform: none !important; }&#10;      .diagram-container svg[data-lens-active] [data-node-id],&#10;      .diagram-container svg[data-lens-active] [data-edge-from],&#10;      .diagram-container svg[data-legend-preview-active] [data-node-id],&#10;      .diagram-container svg[data-legend-preview-active] [data-edge-from] {&#10;        opacity: 1 !important;&#10;        filter: none !important;&#10;      }&#10;      [data-legend-bridge-runtime] { display: none !important; }&#10;      .semantic-lens-overlay { display: none !important; }&#10;      .relationship-hit-overlay { display: none !important; }&#10;      .relationship-pulse-overlay { display: none !important; }&#10;      .route-probe-overlay, .route-journey-overlay { display: none !important; }&#10;      .story-trail-overlay,&#10;      .story-carrier-overlay { display: none !important; }&#10;      .diagram-container svg[data-focus-active] [data-node-id],&#10;      .diagram-container svg[data-focus-active] [data-edge-from],&#10;      .diagram-container svg[data-reach-active] [data-node-id],&#10;      .diagram-container svg[data-reach-active] [data-edge-from],&#10;      .diagram-container svg[data-story-beat] [data-story-step],&#10;      .diagram-container svg[data-story-beat] [data-edge-from][data-story-beat-step],&#10;      .diagram-container svg[data-route-active] [data-node-id],&#10;      .diagram-container svg[data-route-active] [data-edge-from] {&#10;        opacity: 1 !important;&#10;        filter: none !important;&#10;        animation: none !important;&#10;      }&#10;      h1, .subtitle { color: #0f172a; }&#10;    }&#10;&#10;    /* ==========================================================&#10;       TOOLBAR (theme toggle + export menu)&#10;       ========================================================== */&#10;    .toolbar {&#10;      position: fixed;&#10;      top: 1rem;&#10;      right: 1rem;&#10;      display: flex;&#10;      align-items: center;&#10;      gap: 0.5rem;&#10;      padding: 0;&#10;      border: 0;&#10;      background: transparent;&#10;      box-shadow: none;&#10;      z-index: 100;&#10;    }&#10;    .toolbar button {&#10;      background: var(--toolbar-bg);&#10;      color: var(--toolbar-text);&#10;      border: 1px solid var(--toolbar-border);&#10;      padding: 0.5rem 0.875rem;&#10;      border-radius: 0.625rem;&#10;      font-family: inherit;&#10;      font-size: 0.75rem;&#10;      font-weight: 500;&#10;      cursor: pointer;&#10;      white-space: nowrap;&#10;      backdrop-filter: blur(10px);&#10;      box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);&#10;      transition: background 0.15s, border-color 0.15s, color 0.15s;&#10;      display: inline-flex;&#10;      align-items: center;&#10;      gap: 0.375rem;&#10;      min-height: 2.75rem;&#10;    }&#10;    .toolbar button:hover {&#10;      background: var(--toolbar-hover);&#10;      border-color: color-mix(in srgb, var(--arrow) 62%, var(--toolbar-border));&#10;    }&#10;    .toolbar button[aria-expanded=&amp;quot;true&amp;quot;],&#10;    .toolbar button[aria-pressed=&amp;quot;true&amp;quot;]:not(#btn-theme) {&#10;      background: color-mix(in srgb, var(--frontend-stroke) 10%, var(--toolbar-hover));&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 48%, var(--toolbar-border));&#10;    }&#10;    .toolbar #btn-export {&#10;      padding-right: 0.82rem;&#10;      padding-left: 0.82rem;&#10;    }&#10;    .toolbar #btn-export:hover,&#10;    .toolbar #btn-export[aria-expanded=&amp;quot;true&amp;quot;] {&#10;      color: var(--toolbar-text);&#10;      background: color-mix(in srgb, var(--frontend-stroke) 10%, var(--toolbar-hover));&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 54%, var(--toolbar-border));&#10;    }&#10;    .toolbar button:focus-visible {&#10;      outline: 2px solid var(--frontend-stroke);&#10;      outline-offset: 2px;&#10;    }&#10;    .toolbar #btn-motion[hidden] { display: none !important; }&#10;    .toolbar #btn-motion { min-width: 4.4rem; }&#10;    .toolbar #btn-motion:disabled { cursor: default; opacity: 0.58; }&#10;    .toolbar .preset-wrap,&#10;    .toolbar .export-wrap {&#10;      position: relative;&#10;    }&#10;    .toolbar-icon {&#10;      display: inline-block;&#10;      width: 0.95rem;&#10;      height: 0.95rem;&#10;      flex: 0 0 auto;&#10;      background: currentColor;&#10;      -webkit-mask-position: center;&#10;      -webkit-mask-repeat: no-repeat;&#10;      -webkit-mask-size: contain;&#10;      mask-position: center;&#10;      mask-repeat: no-repeat;&#10;      mask-size: contain;&#10;    }&#10;    .toolbar-chevron {&#10;      width: 0.65rem;&#10;      height: 0.65rem;&#10;      transition: transform 0.15s ease;&#10;    }&#10;    [aria-expanded=&amp;quot;true&amp;quot;] &amp;gt; .toolbar-chevron { transform: rotate(180deg); }&#10;    [data-theme=&amp;quot;light&amp;quot;] #theme-icon {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cg fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;%3E%3Ccircle cx=&amp;#x27;10&amp;#x27; cy=&amp;#x27;10&amp;#x27; r=&amp;#x27;3.1&amp;#x27;/%3E%3Cpath d=&amp;#x27;M10 2.2v1.4M10 16.4v1.4M2.2 10h1.4M16.4 10h1.4M4.5 4.5l1 1M14.5 14.5l1 1M15.5 4.5l-1 1M5.5 14.5l-1 1&amp;#x27;/%3E%3C/g%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cg fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;%3E%3Ccircle cx=&amp;#x27;10&amp;#x27; cy=&amp;#x27;10&amp;#x27; r=&amp;#x27;3.1&amp;#x27;/%3E%3Cpath d=&amp;#x27;M10 2.2v1.4M10 16.4v1.4M2.2 10h1.4M16.4 10h1.4M4.5 4.5l1 1M14.5 14.5l1 1M15.5 4.5l-1 1M5.5 14.5l-1 1&amp;#x27;/%3E%3C/g%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    [data-theme=&amp;quot;dark&amp;quot;] #theme-icon {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M15.2 12.7A6.3 6.3 0 017.3 4.8a6.3 6.3 0 107.9 7.9Z&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linejoin=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M15.2 12.7A6.3 6.3 0 017.3 4.8a6.3 6.3 0 107.9 7.9Z&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linejoin=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    #btn-present[aria-pressed=&amp;quot;false&amp;quot;] #present-icon {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M7.2 3.2h-4v4M12.8 3.2h4v4M7.2 16.8h-4v-4M12.8 16.8h4v-4&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M7.2 3.2h-4v4M12.8 3.2h4v4M7.2 16.8h-4v-4M12.8 16.8h4v-4&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    #btn-present[aria-pressed=&amp;quot;true&amp;quot;] #present-icon {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M7.2 7.2h-4v-4M12.8 7.2h4v-4M7.2 12.8h-4v4M12.8 12.8h4v4&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M7.2 7.2h-4v-4M12.8 7.2h4v-4M7.2 12.8h-4v4M12.8 12.8h4v4&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .toolbar-chevron {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 12 12&amp;#x27;%3E%3Cpath d=&amp;#x27;m3 4.5 3 3 3-3&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27; stroke-linejoin=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 12 12&amp;#x27;%3E%3Cpath d=&amp;#x27;m3 4.5 3 3 3-3&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27; stroke-linejoin=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .toolbar #btn-preset { min-width: 5.4rem; }&#10;    .preset-control-mark {&#10;      width: 0.58rem;&#10;      height: 0.58rem;&#10;      flex: 0 0 auto;&#10;      border: 1px solid var(--frontend-stroke);&#10;      border-radius: 0.2rem;&#10;      background: color-mix(in srgb, var(--frontend-stroke) 28%, transparent);&#10;      transition: border-radius 0.15s, box-shadow 0.15s, transform 0.15s;&#10;    }&#10;    #btn-preset[data-preset-option=&amp;quot;signal-flow&amp;quot;] .preset-control-mark {&#10;      border-radius: 50%;&#10;      box-shadow: 0 0 10px color-mix(in srgb, var(--frontend-stroke) 78%, transparent);&#10;    }&#10;    #btn-preset[data-preset-option=&amp;quot;blueprint&amp;quot;] .preset-control-mark {&#10;      border-radius: 0.06rem;&#10;      background: transparent;&#10;      box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--frontend-stroke) 32%, transparent);&#10;      transform: rotate(45deg) scale(0.84);&#10;    }&#10;    #btn-preset[data-preset-option=&amp;quot;editorial&amp;quot;] .preset-control-mark {&#10;      border-color: var(--arrow-emphasis);&#10;      border-radius: 0;&#10;      background: var(--arrow-emphasis);&#10;      box-shadow: 0 0 0 2px color-mix(in srgb, var(--arrow-emphasis) 14%, transparent);&#10;      transform: rotate(45deg) scale(0.72);&#10;    }&#10;    .toolbar .preset-menu {&#10;      position: absolute;&#10;      top: calc(100% + 0.375rem);&#10;      right: 0;&#10;      display: none;&#10;      width: 18.5rem;&#10;      max-width: calc(100vw - 2rem);&#10;      padding: 0.45rem;&#10;      border: 1px solid var(--toolbar-border);&#10;      border-radius: 0.875rem;&#10;      background: var(--toolbar-menu-bg);&#10;      box-shadow: 0 18px 48px rgba(0, 0, 0, 0.24);&#10;    }&#10;    .toolbar .preset-menu.open { display: block; }&#10;    .toolbar .preset-menu.open,&#10;    .toolbar .export-menu.open {&#10;      animation: toolbar-menu-in 0.16s cubic-bezier(0.2, 0.8, 0.2, 1);&#10;      transform-origin: top right;&#10;    }&#10;    @keyframes toolbar-menu-in {&#10;      from { opacity: 0; transform: translateY(-0.25rem) scale(0.985); }&#10;      to { opacity: 1; transform: translateY(0) scale(1); }&#10;    }&#10;    .preset-menu-heading {&#10;      display: flex;&#10;      align-items: baseline;&#10;      justify-content: space-between;&#10;      gap: 1rem;&#10;      padding: 0.42rem 0.6rem 0.55rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.56rem;&#10;      letter-spacing: 0.13em;&#10;      text-transform: uppercase;&#10;    }&#10;    .preset-menu-heading span:last-child {&#10;      font-size: 0.52rem;&#10;      letter-spacing: 0.04em;&#10;      text-transform: none;&#10;    }&#10;    .toolbar .preset-option {&#10;      display: grid;&#10;      grid-template-columns: 2rem minmax(0, 1fr) 1rem;&#10;      align-items: center;&#10;      gap: 0.68rem;&#10;      width: 100%;&#10;      min-height: 3.35rem;&#10;      padding: 0.5rem 0.62rem;&#10;      border: 0;&#10;      border-radius: 0.5rem;&#10;      background: transparent;&#10;      box-shadow: none;&#10;      backdrop-filter: none;&#10;      text-align: left;&#10;    }&#10;    .toolbar .preset-option:hover,&#10;    .toolbar .preset-option:focus-visible { background: var(--toolbar-hover); }&#10;    .toolbar .preset-option[aria-checked=&amp;quot;true&amp;quot;] {&#10;      background: color-mix(in srgb, var(--frontend-stroke) 9%, transparent);&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 36%, transparent);&#10;    }&#10;    .preset-option-swatch {&#10;      position: relative;&#10;      width: 2rem;&#10;      height: 1.55rem;&#10;      overflow: hidden;&#10;      border: 1px solid #64748b;&#10;      border-radius: 0.24rem;&#10;      background: #0f172a;&#10;      box-shadow: inset 0 0 0 1px rgba(255,255,255,0.04);&#10;    }&#10;    .preset-option-swatch::before,&#10;    .preset-option-swatch::after { position: absolute; content: &amp;quot;&amp;quot;; }&#10;    .preset-option-swatch.classic::before {&#10;      top: 0.42rem;&#10;      right: 0.35rem;&#10;      bottom: 0.42rem;&#10;      left: 0.35rem;&#10;      border: 1px solid #22d3ee;&#10;      border-radius: 0.16rem;&#10;      background: rgba(34, 211, 238, 0.14);&#10;    }&#10;    .preset-option-swatch.signal-flow {&#10;      border-color: #29415f;&#10;      background: linear-gradient(135deg, #07101e 10%, #10243c 100%);&#10;    }&#10;    .preset-option-swatch.signal-flow::before {&#10;      top: 50%;&#10;      right: 0.2rem;&#10;      left: 0.2rem;&#10;      height: 1px;&#10;      background: linear-gradient(90deg, #67e8f9, #c4b5fd);&#10;      box-shadow: 0 0 8px #67e8f9;&#10;    }&#10;    .preset-option-swatch.signal-flow::after {&#10;      top: calc(50% - 0.13rem);&#10;      right: 0.28rem;&#10;      width: 0.26rem;&#10;      height: 0.26rem;&#10;      border-radius: 50%;&#10;      background: #67e8f9;&#10;      box-shadow: 0 0 7px #67e8f9;&#10;    }&#10;    .preset-option-swatch.blueprint {&#10;      border-color: #34799a;&#10;      border-radius: 0.08rem;&#10;      background-color: #0a2031;&#10;      background-image:&#10;        linear-gradient(rgba(102, 217, 239, 0.18) 1px, transparent 1px),&#10;        linear-gradient(90deg, rgba(102, 217, 239, 0.18) 1px, transparent 1px);&#10;      background-size: 0.42rem 0.42rem;&#10;    }&#10;    .preset-option-swatch.blueprint::before {&#10;      top: 0.34rem;&#10;      right: 0.38rem;&#10;      bottom: 0.34rem;&#10;      left: 0.38rem;&#10;      border: 1px solid #66d9ef;&#10;    }&#10;    .preset-option-swatch.editorial {&#10;      border-color: #b8aa94;&#10;      border-radius: 0.08rem;&#10;      background: repeating-linear-gradient(0deg, #f2eee5 0 0.34rem, #d8d0c2 0.36rem, #f2eee5 0.38rem);&#10;    }&#10;    .preset-option-swatch.editorial::before {&#10;      top: 0;&#10;      bottom: 0;&#10;      left: 0.42rem;&#10;      width: 1px;&#10;      background: #c9502d;&#10;      opacity: 0.72;&#10;    }&#10;    .preset-option-swatch.editorial::after {&#10;      top: 0.52rem;&#10;      right: 0.45rem;&#10;      width: 0.38rem;&#10;      height: 0.38rem;&#10;      background: #c9502d;&#10;      transform: rotate(45deg);&#10;    }&#10;    .preset-option-copy { min-width: 0; }&#10;    .preset-option-copy strong,&#10;    .preset-option-copy small { display: block; }&#10;    .preset-option-copy strong {&#10;      color: var(--toolbar-text);&#10;      font-size: 0.72rem;&#10;      font-weight: 600;&#10;    }&#10;    .preset-option-copy small {&#10;      margin-top: 0.16rem;&#10;      overflow: hidden;&#10;      color: var(--text-faint);&#10;      font-size: 0.57rem;&#10;      font-weight: 400;&#10;      white-space: nowrap;&#10;      text-overflow: ellipsis;&#10;    }&#10;    .preset-option-check {&#10;      display: inline-block;&#10;      width: 0.9rem;&#10;      height: 0.9rem;&#10;      color: var(--frontend-stroke);&#10;      background: currentColor;&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 16 16&amp;#x27;%3E%3Cpath d=&amp;#x27;m3 8.5 3 3 7-7&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;2&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27; stroke-linejoin=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      -webkit-mask-position: center;&#10;      -webkit-mask-repeat: no-repeat;&#10;      -webkit-mask-size: contain;&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 16 16&amp;#x27;%3E%3Cpath d=&amp;#x27;m3 8.5 3 3 7-7&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;2&amp;#x27; stroke-linecap=&amp;#x27;round&amp;#x27; stroke-linejoin=&amp;#x27;round&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-position: center;&#10;      mask-repeat: no-repeat;&#10;      mask-size: contain;&#10;      opacity: 0;&#10;    }&#10;    .preset-option[aria-checked=&amp;quot;true&amp;quot;] .preset-option-check { opacity: 1; }&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .toolbar button,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .preset-menu,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .export-menu,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .overview-map,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .semantic-lens,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .route-probe,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .focus-chip,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .diagram-guide,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .node-finder,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .guided-views,&#10;    html[data-preset=&amp;quot;editorial&amp;quot;] .share-chapter-cue {&#10;      border-radius: 0.3rem;&#10;    }&#10;    .motion-control-dot {&#10;      width: 0.46rem;&#10;      height: 0.46rem;&#10;      flex: 0 0 auto;&#10;      border: 1px solid var(--frontend-stroke);&#10;      border-radius: 50%;&#10;      background: var(--frontend-stroke);&#10;      box-shadow: 0 0 9px color-mix(in srgb, var(--frontend-stroke) 72%, transparent);&#10;    }&#10;    #btn-motion[aria-pressed=&amp;quot;false&amp;quot;] .motion-control-dot {&#10;      background: transparent;&#10;      box-shadow: none;&#10;    }&#10;    .toolbar .export-menu {&#10;      position: absolute;&#10;      top: calc(100% + 0.375rem);&#10;      right: 0;&#10;      background: var(--toolbar-menu-bg);&#10;      border: 1px solid var(--toolbar-border);&#10;      width: 19rem;&#10;      max-width: calc(100vw - 2rem);&#10;      max-height: calc(100vh - 5.5rem);&#10;      overflow-y: auto;&#10;      border-radius: 0.875rem;&#10;      padding: 0.55rem;&#10;      display: none;&#10;      flex-direction: column;&#10;      box-shadow: 0 18px 48px rgba(0,0,0,0.24);&#10;    }&#10;    .toolbar .export-menu.open { display: flex; }&#10;    .export-menu-header {&#10;      display: flex;&#10;      align-items: flex-start;&#10;      justify-content: space-between;&#10;      gap: 1rem;&#10;      padding: 0.5rem 0.55rem 0.72rem;&#10;    }&#10;    .export-menu-header strong,&#10;    .export-menu-header span { display: block; }&#10;    .export-menu-header strong {&#10;      color: var(--toolbar-text);&#10;      font-size: 0.78rem;&#10;      font-weight: 650;&#10;      letter-spacing: -0.015em;&#10;    }&#10;    .export-menu-header span {&#10;      margin-top: 0.16rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.56rem;&#10;    }&#10;    .export-menu-header kbd {&#10;      padding: 0.16rem 0.36rem;&#10;      border: 1px solid var(--toolbar-border);&#10;      border-radius: 0.3rem;&#10;      color: var(--text-faint);&#10;      background: color-mix(in srgb, var(--toolbar-border) 16%, transparent);&#10;      font-family: inherit;&#10;      font-size: 0.54rem;&#10;      font-weight: 600;&#10;    }&#10;    .export-menu-section {&#10;      display: grid;&#10;      grid-template-columns: minmax(0, 1fr);&#10;      gap: 0.18rem;&#10;    }&#10;    .export-menu-section + .export-menu-section {&#10;      margin-top: 0.42rem;&#10;      padding-top: 0.42rem;&#10;      border-top: 1px solid color-mix(in srgb, var(--toolbar-border) 68%, transparent);&#10;    }&#10;    .export-menu-heading {&#10;      grid-column: 1 / -1;&#10;      display: block;&#10;      padding: 0.24rem 0.55rem 0.2rem;&#10;      color: var(--text-faint);&#10;      font-size: 0.54rem;&#10;      font-weight: 600;&#10;      letter-spacing: 0.12em;&#10;      text-transform: uppercase;&#10;    }&#10;    .toolbar .export-menu button {&#10;      display: grid;&#10;      grid-template-columns: 1.15rem minmax(0, 1fr);&#10;      align-items: center;&#10;      column-gap: 0.52rem;&#10;      background: transparent;&#10;      border: 1px solid transparent;&#10;      box-shadow: none;&#10;      backdrop-filter: none;&#10;      width: 100%;&#10;      min-height: 3rem;&#10;      text-align: left;&#10;      padding: 0.48rem 0.55rem;&#10;      border-radius: 0.5rem;&#10;      white-space: nowrap;&#10;    }&#10;    .export-item-copy {&#10;      display: block;&#10;      min-width: 0;&#10;    }&#10;    .export-item-copy strong,&#10;    .export-item-copy small { display: block; }&#10;    .export-item-copy strong {&#10;      overflow: hidden;&#10;      color: inherit;&#10;      font-size: 0.7rem;&#10;      font-weight: 550;&#10;      text-overflow: ellipsis;&#10;    }&#10;    .export-item-copy small {&#10;      margin-top: 0.12rem;&#10;      overflow: hidden;&#10;      color: var(--text-faint);&#10;      font-size: 0.55rem;&#10;      font-weight: 450;&#10;      text-overflow: ellipsis;&#10;    }&#10;    .toolbar .export-menu button::before {&#10;      width: 1rem;&#10;      height: 1rem;&#10;      background: currentColor;&#10;      content: &amp;quot;&amp;quot;;&#10;      opacity: 0.72;&#10;      -webkit-mask-position: center;&#10;      -webkit-mask-repeat: no-repeat;&#10;      -webkit-mask-size: contain;&#10;      mask-position: center;&#10;      mask-repeat: no-repeat;&#10;      mask-size: contain;&#10;    }&#10;    .toolbar .export-menu button[data-format=&amp;quot;share-card&amp;quot;]::before,&#10;    .toolbar .export-menu button[data-action=&amp;quot;route-share-card&amp;quot;]::before,&#10;    .toolbar .export-menu button[data-action=&amp;quot;reach-share-card&amp;quot;]::before {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; d=&amp;#x27;M3 4.5h14v11H3zM6 12l2.5-2.5 2 2 1.5-1.5 2 2&amp;#x27;/%3E%3Ccircle cx=&amp;#x27;13.8&amp;#x27; cy=&amp;#x27;7.3&amp;#x27; r=&amp;#x27;1.2&amp;#x27; fill=&amp;#x27;black&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27; d=&amp;#x27;M3 4.5h14v11H3zM6 12l2.5-2.5 2 2 1.5-1.5 2 2&amp;#x27;/%3E%3Ccircle cx=&amp;#x27;13.8&amp;#x27; cy=&amp;#x27;7.3&amp;#x27; r=&amp;#x27;1.2&amp;#x27; fill=&amp;#x27;black&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .toolbar .export-menu button[data-action^=&amp;quot;copy&amp;quot;]::before {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Crect x=&amp;#x27;6&amp;#x27; y=&amp;#x27;6&amp;#x27; width=&amp;#x27;10&amp;#x27; height=&amp;#x27;10&amp;#x27; rx=&amp;#x27;1.5&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3Cpath d=&amp;#x27;M4 13H3.5A1.5 1.5 0 012 11.5v-8A1.5 1.5 0 013.5 2h8A1.5 1.5 0 0113 3.5V4&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Crect x=&amp;#x27;6&amp;#x27; y=&amp;#x27;6&amp;#x27; width=&amp;#x27;10&amp;#x27; height=&amp;#x27;10&amp;#x27; rx=&amp;#x27;1.5&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3Cpath d=&amp;#x27;M4 13H3.5A1.5 1.5 0 012 11.5v-8A1.5 1.5 0 013.5 2h8A1.5 1.5 0 0113 3.5V4&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .toolbar .export-menu button[data-format=&amp;quot;png&amp;quot;]::before,&#10;    .toolbar .export-menu button[data-format=&amp;quot;jpeg&amp;quot;]::before,&#10;    .toolbar .export-menu button[data-format=&amp;quot;webp&amp;quot;]::before {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M5 2.5h7l3 3v12H5zM12 2.5v3h3&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3Cpath d=&amp;#x27;M7.5 14l2-2 1.5 1.5 1.5-1.5&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M5 2.5h7l3 3v12H5zM12 2.5v3h3&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3Cpath d=&amp;#x27;M7.5 14l2-2 1.5 1.5 1.5-1.5&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .toolbar .export-menu button[data-format=&amp;quot;svg&amp;quot;]::before,&#10;    .toolbar .export-menu button[data-format=&amp;quot;webm&amp;quot;]::before {&#10;      -webkit-mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M10 2.5l7 4v7l-7 4-7-4v-7zM3 6.5l7 4 7-4M10 10.5v7&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;      mask-image: url(&amp;quot;data:image/svg+xml,%3Csvg xmlns=&amp;#x27;http://www.w3.org/2000/svg&amp;#x27; viewBox=&amp;#x27;0 0 20 20&amp;#x27;%3E%3Cpath d=&amp;#x27;M10 2.5l7 4v7l-7 4-7-4v-7zM3 6.5l7 4 7-4M10 10.5v7&amp;#x27; fill=&amp;#x27;none&amp;#x27; stroke=&amp;#x27;black&amp;#x27; stroke-width=&amp;#x27;1.7&amp;#x27;/%3E%3C/svg%3E&amp;quot;);&#10;    }&#10;    .toolbar .export-menu button[data-format=&amp;quot;share-card&amp;quot;],&#10;    .toolbar .export-menu button[data-action=&amp;quot;route-share-card&amp;quot;],&#10;    .toolbar .export-menu button[data-action=&amp;quot;reach-share-card&amp;quot;] {&#10;      min-height: 3.35rem;&#10;      color: var(--toolbar-text);&#10;      background: color-mix(in srgb, var(--frontend-stroke) 8%, transparent);&#10;      border-color: color-mix(in srgb, var(--frontend-stroke) 24%, var(--toolbar-border));&#10;    }&#10;    .toolbar .export-menu button[hidden] { display: none; }&#10;    .toolbar .export-menu button:hover {&#10;      background: var(--toolbar-hover);&#10;    }&#10;    .toolbar .export-menu button:focus-visible {&#10;      background: var(--toolbar-hover);&#10;      outline-offset: -2px;&#10;    }&#10;    .toolbar .export-menu button:disabled {&#10;      color: var(--text-faint);&#10;      background: color-mix(in srgb, var(--toolbar-border) 18%, transparent);&#10;      cursor: not-allowed;&#10;    }&#10;    .toolbar .export-menu button:disabled:hover {&#10;      border-color: transparent;&#10;    }&#10;    .toolbar .export-menu .hint {&#10;      color: var(--text-faint);&#10;      font-size: 0.55rem;&#10;    }&#10;&#10;    /* Toast — brief feedback for actions like &amp;quot;copied&amp;quot; */&#10;    .archify-toast {&#10;      position: fixed;&#10;      top: 1rem;&#10;      left: 50%;&#10;      transform: translateX(-50%) translateY(-8px);&#10;      background: var(--toolbar-menu-bg);&#10;      color: var(--text);&#10;      border: 1px solid var(--toolbar-border);&#10;      padding: 0.5rem 1rem;&#10;      border-radius: 0.5rem;&#10;      font-family: inherit;&#10;      font-size: 0.75rem;&#10;      opacity: 0;&#10;      transition: opacity 0.2s, transform 0.2s;&#10;      z-index: 200;&#10;      pointer-events: none;&#10;      box-shadow: 0 4px 20px rgba(0,0,0,0.25);&#10;    }&#10;    .archify-toast.show {&#10;      opacity: 1;&#10;      transform: translateX(-50%) translateY(0);&#10;    }&#10;&#10;    @media (max-width: 720px) {&#10;      body { padding: 1rem; }&#10;      .toolbar .preset-menu,&#10;      .toolbar .export-menu {&#10;        position: fixed;&#10;        top: 4.5rem;&#10;        right: 1rem;&#10;        left: 1rem;&#10;        width: auto;&#10;        max-width: none;&#10;      }&#10;      .toolbar {&#10;        position: relative;&#10;        justify-content: flex-end;&#10;        width: max-content;&#10;        max-width: 100%;&#10;        margin-left: auto;&#10;        margin-bottom: 1rem;&#10;      }&#10;      .header { margin-bottom: 1.25rem; padding-right: 0; }&#10;      html[data-preset=&amp;quot;signal-flow&amp;quot;] .header,&#10;      html[data-preset=&amp;quot;blueprint&amp;quot;] .header,&#10;      html[data-preset=&amp;quot;editorial&amp;quot;] .header { padding-right: 0; }&#10;      .header-row {&#10;        gap: 0.75rem;&#10;        align-items: flex-start;&#10;      }&#10;      html[data-preset=&amp;quot;signal-flow&amp;quot;] .header-row,&#10;      html[data-preset=&amp;quot;blueprint&amp;quot;] .header-row,&#10;      html[data-preset=&amp;quot;editorial&amp;quot;] .header-row { flex-wrap: wrap; }&#10;      html[data-preset=&amp;quot;signal-flow&amp;quot;] .header-row::after {&#10;        margin-left: 0;&#10;        order: 3;&#10;      }&#10;      html[data-preset=&amp;quot;blueprint&amp;quot;] .header-row::after {&#10;        margin-left: 0;&#10;        order: 3;&#10;      }&#10;      html[data-preset=&amp;quot;editorial&amp;quot;] .header-row::after {&#10;        margin-left: 0;&#10;        order: 3;&#10;      }&#10;      h1 {&#10;        font-size: 1.25rem;&#10;        line-height: 1.25;&#10;      }&#10;      .subtitle {&#10;        margin-left: 0;&#10;        font-size: 0.8125rem;&#10;        line-height: 1.55;&#10;      }&#10;      .diagram-container {&#10;        padding: 0.75rem;&#10;        border-radius: 0.75rem;&#10;      }&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container {&#10;        padding: 0.75rem 0.75rem 4.25rem;&#10;      }&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] {&#10;        overflow-x: auto;&#10;        overflow-y: hidden;&#10;        overscroll-behavior-x: contain;&#10;        scrollbar-width: thin;&#10;        scroll-behavior: smooth;&#10;      }&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] &amp;gt; svg {&#10;        min-width: 720px;&#10;      }&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] .diagram-nav,&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] .overview-map,&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] .focus-chip,&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] .route-probe,&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] .semantic-lens,&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] .diagram-guide,&#10;      html:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] .node-finder {&#10;        transform: translateX(var(--archify-scroll-x, 0px));&#10;      }&#10;      .diagram-nav { right: 0.5rem; bottom: 0.5rem; }&#10;      .diagram-nav button {&#10;        min-width: 2.75rem;&#10;        height: 2.75rem;&#10;      }&#10;      .diagram-nav [data-view=&amp;quot;reset&amp;quot;] { min-width: 3.75rem; }&#10;      .diagram-nav [data-view=&amp;quot;reset&amp;quot;][data-detail-visible] { min-width: 4.35rem; }&#10;      .overview-map {&#10;        right: 0.5rem;&#10;        bottom: 3.7rem;&#10;        width: min(10.25rem, calc(100% - 1rem));&#10;      }&#10;      .overview-map[data-docked=&amp;quot;true&amp;quot;] {&#10;        right: var(--archify-radar-right, 0.5rem);&#10;        top: var(--archify-radar-top, 0.5rem);&#10;        bottom: auto;&#10;        transform: none !important;&#10;      }&#10;      .overview-map[data-docked=&amp;quot;true&amp;quot;][data-dock-side=&amp;quot;left&amp;quot;] {&#10;        right: auto;&#10;        left: var(--archify-radar-left, 0.5rem);&#10;      }&#10;      .overview-map-surface { height: 4rem; }&#10;      .overview-map-feedback { right: 0.5rem; bottom: 3.7rem; }&#10;      .semantic-lens {&#10;        right: 0.5rem;&#10;        bottom: 3.7rem;&#10;        width: calc(100% - 1rem);&#10;        max-height: calc(100% - 4.2rem);&#10;      }&#10;      .semantic-lens[data-dock-side] { left: auto; right: 0.5rem; }&#10;      .semantic-lens-kinds { max-height: min(12rem, 34vh); }&#10;      .focus-chip {&#10;        left: 0.5rem;&#10;        top: 0.5rem;&#10;        width: calc(100% - 1rem);&#10;        max-width: none;&#10;      }&#10;      .relationship-lens-list { max-height: min(12rem, 38vh); }&#10;      .relationship-lens-actions #btn-focus-relations { display: block; color: var(--database-stroke); }&#10;      .focus-chip:not([data-relations-expanded=&amp;quot;true&amp;quot;]) .relationship-lens-head { border-bottom-color: transparent; }&#10;      .focus-chip:not([data-relations-expanded=&amp;quot;true&amp;quot;]) .relationship-lens-list { display: none; }&#10;      /* While a mobile reader previews one relationship, turn the full Lens&#10;         into a compact peek card. This keeps the exact source and target on&#10;         canvas instead of covering them with a long, scrollable list. */&#10;      .focus-chip[data-relationship-previewing=&amp;quot;true&amp;quot;] .relationship-lens-list {&#10;        max-height: none;&#10;        padding: 0.35rem;&#10;        overflow: hidden;&#10;      }&#10;      .focus-chip[data-relationship-previewing=&amp;quot;true&amp;quot;] .relationship-lens-group { margin: 0; }&#10;      .focus-chip[data-relationship-previewing=&amp;quot;true&amp;quot;] .relationship-lens-group-title,&#10;      .focus-chip[data-relationship-previewing=&amp;quot;true&amp;quot;] .relationship-lens-row:not([data-preview-active=&amp;quot;true&amp;quot;]) {&#10;        display: none;&#10;      }&#10;      .node-finder {&#10;        top: 0.5rem;&#10;        left: 0.5rem;&#10;        width: min(22rem, calc(100% - 1rem));&#10;        max-height: calc(100% - 1rem);&#10;      }&#10;      .diagram-guide {&#10;        top: 0.5rem;&#10;        right: 0.5rem;&#10;        left: 0.5rem;&#10;        width: auto;&#10;        max-height: calc(100% - 1rem);&#10;      }&#10;      .diagram-guide-head { padding: 0.62rem 0.7rem 0.52rem; }&#10;      .diagram-guide-stats { padding: 0.42rem 0.7rem; }&#10;      .diagram-guide-actions {&#10;        grid-template-columns: 1fr;&#10;        gap: 0.28rem;&#10;        padding: 0.42rem;&#10;      }&#10;      .diagram-guide-action {&#10;        min-height: 3.1rem;&#10;        padding: 0.42rem 0.48rem;&#10;      }&#10;      .diagram-guide-action small {&#10;        display: block;&#10;        overflow: hidden;&#10;        text-overflow: ellipsis;&#10;        white-space: nowrap;&#10;      }&#10;      .diagram-guide-index {&#10;        width: 1.5rem;&#10;        height: 1.5rem;&#10;      }&#10;      .diagram-guide-shortcuts { padding: 0.46rem 0.7rem 0.52rem; }&#10;      .diagram-guide-action[data-guide-action=&amp;quot;present&amp;quot;] { grid-column: auto; }&#10;      .route-probe[data-guide-open=&amp;quot;true&amp;quot;] {&#10;        visibility: hidden;&#10;        pointer-events: none;&#10;      }&#10;      .node-finder-results { max-height: min(16rem, 38vh); }&#10;      .route-probe {&#10;        left: 0.5rem;&#10;        bottom: 3.7rem;&#10;        width: calc(100% - 1rem);&#10;        min-width: 0;&#10;      }&#10;      .route-probe[data-route-dock=&amp;quot;top&amp;quot;] {&#10;        top: 0.5rem;&#10;        bottom: auto;&#10;      }&#10;      .route-probe[data-finder-open=&amp;quot;true&amp;quot;] {&#10;        visibility: hidden;&#10;        pointer-events: none;&#10;      }&#10;      .route-probe-head { padding: 0.45rem 0.48rem 0.38rem; }&#10;      .route-probe-path { padding: 0.35rem 0.48rem 0.2rem; }&#10;      .route-probe-node { min-height: 2.75rem !important; }&#10;      .route-journey-controls {&#10;        grid-template-columns: 2.75rem minmax(0, 1fr) 2.75rem minmax(0, 1fr);&#10;        padding: 0.08rem 0.48rem 0.32rem;&#10;      }&#10;      .route-journey-controls button { min-height: 2.75rem; }&#10;      .route-probe-status { padding: 0.05rem 0.48rem 0.38rem; }&#10;      .route-probe-node { max-width: 7.5rem; }&#10;      .guided-views {&#10;        grid-template-columns: 2.75rem minmax(0, 1fr) 2.75rem;&#10;        gap: 0.2rem;&#10;        padding: 0.25rem;&#10;      }&#10;      .guided-view-actions {&#10;        grid-column: 1 / -1;&#10;        display: grid;&#10;        grid-template-columns: repeat(3, minmax(0, 1fr));&#10;      }&#10;      .guided-views &amp;gt; #guided-view-prev,&#10;      .guided-views &amp;gt; #guided-view-next {&#10;        align-self: center;&#10;        height: 2.75rem;&#10;      }&#10;      .guided-view-play,&#10;      .guided-view-all,&#10;      .guided-view-beat-link { min-height: 2.75rem; }&#10;      .guided-view-copy small { white-space: normal; }&#10;      .guided-story-caption { padding: 0.32rem 0.45rem; }&#10;      .guided-story-caption-index { min-width: 2.9rem; padding-right: 0.42rem; }&#10;      .guided-story-caption strong,&#10;      .guided-story-caption small { white-space: normal; }&#10;      .guided-story-caption-next { display: none; }&#10;      .guided-view-trail { min-height: 2rem; }&#10;      .guided-view-trail .guided-view-stop {&#10;        min-height: 2rem;&#10;        padding: 0.22rem 0.42rem 0.22rem 0.28rem;&#10;      }&#10;      .guided-view-handoff { max-width: min(9rem, 32vw); }&#10;      .guided-view-index { padding-top: 0.35rem; }&#10;      .guided-view-chapters {&#10;        gap: 0.35rem;&#10;        scroll-padding-inline: 0.2rem;&#10;      }&#10;      .guided-view-chapters li {&#10;        flex: 0 0 min(14rem, 78vw);&#10;        min-width: 0;&#10;      }&#10;      .guided-view-chapter { min-height: 2.75rem; }&#10;      .guided-views[data-active-view=&amp;quot;all&amp;quot;] {&#10;        grid-template-columns: minmax(0, 1fr) auto;&#10;        gap: 0.2rem;&#10;        padding: 0.25rem;&#10;      }&#10;      .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-copy {&#10;        grid-column: 1;&#10;        grid-row: 1;&#10;      }&#10;      .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-actions {&#10;        grid-column: 2;&#10;        grid-row: 1;&#10;      }&#10;      .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-play {&#10;        min-width: 6rem !important;&#10;        min-height: 2.75rem;&#10;      }&#10;      .guided-views[data-active-view=&amp;quot;all&amp;quot;] .guided-view-index {&#10;        grid-column: 1 / -1;&#10;        grid-row: 2;&#10;        padding: 0.3rem 0.08rem 0;&#10;        border-top: 1px solid color-mix(in srgb, var(--toolbar-border) 72%, transparent);&#10;        border-left: 0;&#10;      }&#10;      html[data-embed=&amp;quot;true&amp;quot;][data-share-playback=&amp;quot;true&amp;quot;] .share-chapter-cue:not([hidden]),&#10;      html[data-embed=&amp;quot;true&amp;quot;][data-share-moment=&amp;quot;true&amp;quot;] .share-chapter-cue:not([hidden]) {&#10;        top: 0.5rem;&#10;        grid-template-columns: auto minmax(0, 1fr);&#10;        gap: 0.28rem 0.55rem;&#10;        width: calc(100% - 1rem);&#10;        min-height: 0;&#10;        padding: 0.45rem 0.55rem 0.55rem;&#10;      }&#10;      html[data-embed=&amp;quot;true&amp;quot;][data-share-playback=&amp;quot;true&amp;quot;] .diagram-container {&#10;        padding-top: 4.25rem;&#10;      }&#10;      html[data-embed=&amp;quot;true&amp;quot;][data-share-moment=&amp;quot;true&amp;quot;] .diagram-container {&#10;        padding-top: 4.25rem;&#10;      }&#10;      .share-chapter-index {&#10;        min-width: 4.4rem;&#10;        padding-right: 0.5rem;&#10;      }&#10;      .share-chapter-copy small { font-size: 0.46rem; }&#10;      .share-chapter-route {&#10;        grid-column: 1 / -1;&#10;        font-size: 0.5rem;&#10;        text-align: left;&#10;      }&#10;      .cards {&#10;        grid-template-columns: 1fr;&#10;        margin-top: 1rem;&#10;      }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) body { padding: 0.5rem; }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .container {&#10;        gap: 0.5rem;&#10;        height: calc(100dvh - 1rem);&#10;      }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .toolbar {&#10;        position: fixed;&#10;        top: 0.5rem;&#10;        right: 0.5rem;&#10;        margin: 0;&#10;        gap: 0.25rem;&#10;      }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .toolbar button {&#10;        min-height: 2.75rem;&#10;        padding: 0.42rem 0.58rem;&#10;      }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .header {&#10;        min-height: 2.25rem;&#10;        padding: 3.5rem 0 0;&#10;      }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .header-row {&#10;        min-height: 2.25rem;&#10;        margin: 0;&#10;        align-items: center;&#10;        flex-wrap: nowrap;&#10;      }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .header-row::after,&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .pulse-dot,&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .subtitle { display: none; }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) h1 {&#10;        flex: 1 1 auto;&#10;        min-width: 0;&#10;        max-width: 100%;&#10;        overflow: hidden;&#10;        font-size: 0.875rem;&#10;        text-overflow: ellipsis;&#10;        white-space: nowrap;&#10;      }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-views {&#10;        padding: 0.2rem;&#10;      }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-view-copy small { display: none; }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .guided-story-caption small { display: block; }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container { padding: 0.5rem 0.5rem 3.75rem; }&#10;      html[data-present=&amp;quot;true&amp;quot;]:not([data-embed=&amp;quot;true&amp;quot;]) .diagram-container[data-wide-diagram=&amp;quot;true&amp;quot;] &amp;gt; svg {&#10;        width: 720px;&#10;        height: auto;&#10;        min-width: 720px;&#10;      }&#10;    }&#10;&#10;    @media (max-width: 420px) {&#10;      .export-menu-section { grid-template-columns: 1fr; }&#10;      .export-menu-heading,&#10;      .toolbar .export-menu button[data-format=&amp;quot;share-card&amp;quot;],&#10;      .toolbar .export-menu button[data-action=&amp;quot;route-share-card&amp;quot;],&#10;      .toolbar .export-menu button[data-action=&amp;quot;reach-share-card&amp;quot;] { grid-column: 1; }&#10;    }&#10;&#10;    @media (prefers-reduced-motion: reduce) {&#10;      .guided-story-caption { animation: none !important; }&#10;      .toolbar .preset-menu.open,&#10;      .toolbar .export-menu.open { animation: none; }&#10;      .toolbar-chevron { transition: none; }&#10;    }&#10;&#10;    @media (max-width: 360px) {&#10;      .toolbar { gap: 0.25rem; }&#10;      .toolbar button { padding-right: 0.58rem; padding-left: 0.58rem; }&#10;      .toolbar #btn-motion { min-width: 4.4rem; padding-right: 0.58rem; padding-left: 0.58rem; }&#10;      #theme-label, #preset-label, #present-label { display: none; }&#10;      .guided-view-handoff { max-width: 6.5rem; }&#10;    }&#10;&#10;    /* ==========================================================&#10;       SVG SEMANTIC CLASSES — use these instead of inline fill/stroke&#10;       ========================================================== */&#10;    .c-grid       { stroke: var(--grid); fill: none; }&#10;    .c-mask       { fill: var(--mask); stroke: none; }&#10;&#10;    .c-frontend   { fill: var(--frontend-fill);   stroke: var(--frontend-stroke); }&#10;    .c-backend    { fill: var(--backend-fill);    stroke: var(--backend-stroke); }&#10;    .c-database   { fill: var(--database-fill);   stroke: var(--database-stroke); }&#10;    .c-cloud      { fill: var(--cloud-fill);      stroke: var(--cloud-stroke); }&#10;    .c-security   { fill: var(--security-fill);   stroke: var(--security-stroke); }&#10;    .c-messagebus { fill: var(--messagebus-fill); stroke: var(--messagebus-stroke); }&#10;    .c-external   { fill: var(--external-fill);   stroke: var(--external-stroke); }&#10;&#10;    /* Text helpers */&#10;    .t-primary { fill: var(--text); }&#10;    .t-muted   { fill: var(--text-muted); }&#10;    .t-dim     { fill: var(--text-dim); }&#10;    .t-frontend   { fill: var(--frontend-stroke); }&#10;    .t-backend    { fill: var(--backend-stroke); }&#10;    .t-database   { fill: var(--database-stroke); }&#10;    .t-cloud      { fill: var(--cloud-stroke); }&#10;    .t-security   { fill: var(--security-stroke); }&#10;    .t-messagebus { fill: var(--messagebus-stroke); }&#10;    .t-external   { fill: var(--external-stroke); }&#10;&#10;    /* Semantic Sigils are small authored role stamps, not icons from a brand&#10;       pack and not viewer controls. Prefix selectors with svg so the canonical&#10;       export&amp;#x27;s SVG-only stylesheet collector keeps them automatically. */&#10;    svg .semantic-sigil {&#10;      fill: none;&#10;      stroke: currentColor;&#10;      stroke-width: 1.35;&#10;      stroke-linecap: round;&#10;      stroke-linejoin: round;&#10;      opacity: 0.76;&#10;      pointer-events: none;&#10;    }&#10;    svg .semantic-sigil &amp;gt; * { vector-effect: non-scaling-stroke; }&#10;    svg .semantic-sigil .sigil-fill { fill: currentColor; stroke: none; }&#10;    svg .s-frontend   { color: var(--frontend-stroke); }&#10;    svg .s-backend    { color: var(--backend-stroke); }&#10;    svg .s-database   { color: var(--database-stroke); }&#10;    svg .s-cloud      { color: var(--cloud-stroke); }&#10;    svg .s-security   { color: var(--security-stroke); }&#10;    svg .s-messagebus { color: var(--messagebus-stroke); }&#10;    svg .s-external   { color: var(--external-stroke); }&#10;&#10;    /* Brand Marks are authored identity badges. Their color is contained&#10;       inside one neutral plate so vendor color never replaces Archify&amp;#x27;s&#10;       semantic node and relationship vocabulary. */&#10;    svg .brand-mark { pointer-events: none; }&#10;    svg .brand-mark-badge { fill: #fff; stroke: none; }&#10;    svg .brand-mark-frame {&#10;      fill: none;&#10;      stroke: #cbd5e1;&#10;      stroke-width: 0.8;&#10;      vector-effect: non-scaling-stroke;&#10;    }&#10;    svg .brand-mark-fallback {&#10;      fill: none;&#10;      stroke: #475569;&#10;      stroke-width: 1.15;&#10;      stroke-linecap: round;&#10;      stroke-linejoin: round;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .brand-mark-badge,&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .brand-mark-frame { rx: 1px; }&#10;&#10;    /* Reading Depth is a viewer-only level-of-detail layer. MAP preserves the&#10;       authored structure and primary labels, READ restores relationship labels&#10;       and node context, and FULL restores tags and fine annotations. Semantic&#10;       intent can reveal the relevant detail without moving any geometry. */&#10;    svg [data-detail] { transition: opacity 160ms ease; }&#10;    svg [data-detail-anchor] {&#10;      transform-box: fill-box;&#10;      transform-origin: center;&#10;      transition: transform 160ms ease;&#10;    }&#10;    .diagram-container[data-detail-level=&amp;quot;map&amp;quot;] svg [data-detail=&amp;quot;context&amp;quot;],&#10;    .diagram-container[data-detail-level=&amp;quot;map&amp;quot;] svg [data-detail=&amp;quot;fine&amp;quot;],&#10;    .diagram-container[data-detail-level=&amp;quot;read&amp;quot;] svg [data-detail=&amp;quot;fine&amp;quot;] {&#10;      opacity: 0;&#10;      pointer-events: none;&#10;    }&#10;    .diagram-container[data-detail-level=&amp;quot;map&amp;quot;] svg [data-detail-anchor] {&#10;      transform: translateY(8px);&#10;    }&#10;&#10;    /* Focus, lens, preview, route, and story states are stronger reader intent than&#10;       the global zoom level. Reveal only their exact semantic matches. */&#10;    svg[data-focus-active] [data-focus-match][data-detail],&#10;    svg[data-focus-active] [data-focus-match] [data-detail],&#10;    svg[data-reach-active] [data-reach-match][data-detail],&#10;    svg[data-reach-active] [data-reach-match] [data-detail],&#10;    svg[data-lens-active] [data-lens-match][data-detail],&#10;    svg[data-lens-active] [data-lens-match] [data-detail],&#10;    svg[data-legend-preview-active] [data-legend-preview-match][data-detail],&#10;    svg[data-legend-preview-active] [data-legend-preview-match] [data-detail],&#10;    svg[data-intent-trace-active] [data-intent-trace-match][data-detail],&#10;    svg[data-intent-trace-active] [data-intent-trace-match] [data-detail],&#10;    svg[data-route-active] [data-route-match][data-detail],&#10;    svg[data-route-active] [data-route-match] [data-detail],&#10;    svg[data-story-active] [data-story-step][data-detail],&#10;    svg[data-story-active] [data-story-step] [data-detail],&#10;    svg[data-relationship-preview-active] [data-relationship-preview][data-detail],&#10;    svg[data-relationship-preview-active] [data-relationship-preview] [data-detail],&#10;    svg [data-node-id]:hover [data-detail],&#10;    svg [data-node-id]:focus-visible [data-detail] {&#10;      opacity: 1;&#10;      pointer-events: auto;&#10;    }&#10;    svg[data-focus-active] [data-focus-match] [data-detail-anchor],&#10;    svg[data-reach-active] [data-reach-match] [data-detail-anchor],&#10;    svg[data-lens-active] [data-lens-match] [data-detail-anchor],&#10;    svg[data-legend-preview-active] [data-legend-preview-match] [data-detail-anchor],&#10;    svg[data-intent-trace-active] [data-intent-trace-match] [data-detail-anchor],&#10;    svg[data-route-active] [data-route-match] [data-detail-anchor],&#10;    svg[data-story-active] [data-story-step] [data-detail-anchor],&#10;    svg [data-node-id]:hover [data-detail-anchor],&#10;    svg [data-node-id]:focus-visible [data-detail-anchor] { transform: none; }&#10;&#10;    /* Arrows */&#10;    .a-default   { stroke: var(--arrow); fill: none; }&#10;    .a-emphasis  { stroke: var(--arrow-emphasis); fill: none; }&#10;    .a-security  { stroke: var(--security-stroke); fill: none; stroke-dasharray: 5,5; }&#10;    .a-dashed    { stroke: var(--database-stroke); fill: none; stroke-dasharray: 4,4; }&#10;&#10;    /* Arrowhead markers reference these */&#10;    .m-default   { fill: var(--arrow); }&#10;    .m-emphasis  { fill: var(--arrow-emphasis); }&#10;    .m-security  { fill: var(--security-stroke); }&#10;    .m-dashed    { fill: var(--database-stroke); }&#10;&#10;    /* Stable semantic exploration hooks emitted by every renderer. */&#10;    svg [data-node-id] {&#10;      cursor: pointer;&#10;      transition: opacity 0.18s ease, filter 0.18s ease;&#10;    }&#10;    svg [data-edge-from] { transition: opacity 0.18s ease, filter 0.18s ease; }&#10;    svg [data-node-id]:hover,&#10;    svg [data-node-id]:focus-visible {&#10;      filter: drop-shadow(0 0 7px var(--frontend-stroke));&#10;      outline: none;&#10;    }&#10;    /* Verified Source Beacons are installed at runtime only for nodes whose&#10;       repository evidence passed the local revision/blob/line checks. They&#10;       live inside the owning node so every focus, route, story, and guided&#10;       view keeps one coherent opacity state. Export serialization removes&#10;       them before producing the canonical SVG or any derived visual. */&#10;    .source-evidence-beacon {&#10;      pointer-events: none;&#10;      opacity: 0.76;&#10;      transition: opacity 160ms ease, filter 160ms ease;&#10;    }&#10;    .source-evidence-beacon rect {&#10;      fill: color-mix(in srgb, var(--mask) 92%, var(--backend-stroke));&#10;      stroke: color-mix(in srgb, var(--backend-stroke) 82%, var(--panel-border));&#10;      stroke-width: 1;&#10;      vector-effect: non-scaling-stroke;&#10;    }&#10;    .source-evidence-beacon text {&#10;      fill: var(--backend-stroke);&#10;      font-size: 5.5px;&#10;      font-weight: 800;&#10;      letter-spacing: 0.06em;&#10;      text-anchor: middle;&#10;      text-transform: uppercase;&#10;    }&#10;    svg [data-node-id]:hover .source-evidence-beacon,&#10;    svg [data-node-id]:focus-visible .source-evidence-beacon,&#10;    svg [data-node-id][data-focus-selected] .source-evidence-beacon {&#10;      opacity: 1;&#10;      filter: drop-shadow(0 0 4px color-mix(in srgb, var(--backend-stroke) 72%, transparent));&#10;    }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] .source-evidence-beacon { opacity: 0.9; }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .source-evidence-beacon rect {&#10;      rx: 0.8px;&#10;      filter: none;&#10;    }&#10;    svg [data-legend-kind][role=&amp;quot;button&amp;quot;] { cursor: pointer; }&#10;    svg [data-legend-kind]:focus { outline: none; }&#10;    svg [data-legend-hit] {&#10;      fill: transparent;&#10;      stroke: transparent;&#10;      stroke-width: 1.4;&#10;      pointer-events: all;&#10;      vector-effect: non-scaling-stroke;&#10;      transition: stroke 150ms ease, stroke-width 150ms ease, filter 150ms ease;&#10;    }&#10;    svg [data-legend-count-badge] { pointer-events: none; }&#10;    svg [data-legend-count-badge] rect {&#10;      fill: var(--mask);&#10;      stroke: var(--panel-border);&#10;      stroke-width: 1;&#10;      vector-effect: non-scaling-stroke;&#10;    }&#10;    svg [data-legend-count-badge] text {&#10;      fill: var(--text-muted);&#10;      font-size: 8px;&#10;      font-weight: 700;&#10;      text-anchor: middle;&#10;    }&#10;    svg [data-legend-kind][role=&amp;quot;button&amp;quot;]:hover [data-legend-hit] {&#10;      stroke: color-mix(in srgb, var(--database-stroke) 58%, transparent);&#10;    }&#10;    svg [data-legend-kind][role=&amp;quot;button&amp;quot;]:focus-visible [data-legend-hit] {&#10;      stroke: var(--frontend-stroke);&#10;      stroke-width: 1.8;&#10;      filter: drop-shadow(0 0 3px var(--frontend-stroke));&#10;    }&#10;    svg [data-legend-kind][data-legend-selected] [data-legend-hit] {&#10;      stroke: var(--database-stroke);&#10;      stroke-width: 2.2;&#10;      stroke-dasharray: 3 2;&#10;    }&#10;    svg [data-legend-kind][data-legend-selected] [data-legend-count-badge] rect {&#10;      stroke: var(--database-stroke);&#10;      stroke-width: 1.8;&#10;    }&#10;    svg [data-legend-kind][data-legend-zero] { opacity: 0.44; }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] [data-legend-kind][data-legend-selected] [data-legend-hit] {&#10;      filter: drop-shadow(0 0 4px var(--database-stroke));&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] [data-legend-hit],&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] [data-legend-count-badge] rect { rx: 0; filter: none; }&#10;    svg[data-legend-preview-active] [data-node-id],&#10;    svg[data-legend-preview-active] [data-edge-from] { opacity: 0.11; }&#10;    svg[data-legend-preview-active] [data-legend-preview-match] { opacity: 1; }&#10;    svg[data-legend-preview-active] [data-legend-preview-peer] { opacity: 0.62; }&#10;    svg[data-legend-preview-active] [data-legend-preview-selected] {&#10;      filter: drop-shadow(0 0 8px var(--database-stroke));&#10;    }&#10;    svg[data-lens-active] [data-node-id],&#10;    svg[data-lens-active] [data-edge-from] { opacity: 0.11; }&#10;    svg[data-lens-active] [data-lens-match] { opacity: 1; }&#10;    svg[data-lens-active] [data-lens-peer] { opacity: 0.62; }&#10;    svg[data-lens-active] [data-lens-selected] {&#10;      filter: drop-shadow(0 0 10px var(--database-stroke));&#10;    }&#10;    .semantic-lens-overlay { pointer-events: none; }&#10;    .semantic-lens-flow {&#10;      fill: none;&#10;      stroke-width: 3.05;&#10;      stroke-linecap: round;&#10;      stroke-dasharray: 0.075 0.925;&#10;      stroke-dashoffset: 0;&#10;      vector-effect: non-scaling-stroke;&#10;      opacity: 0.9;&#10;      animation: archify-semantic-lens-flow 1.35s linear 1 both;&#10;      animation-delay: var(--lens-flow-delay, 0s);&#10;    }&#10;    .semantic-lens-flow[data-direction=&amp;quot;out&amp;quot;],&#10;    .semantic-lens-flow[data-direction=&amp;quot;forward&amp;quot;] {&#10;      stroke: var(--frontend-stroke);&#10;      filter: drop-shadow(0 0 3px var(--frontend-stroke));&#10;    }&#10;    .semantic-lens-flow[data-direction=&amp;quot;in&amp;quot;],&#10;    .semantic-lens-flow[data-direction=&amp;quot;reverse&amp;quot;] {&#10;      stroke: var(--database-stroke);&#10;      filter: drop-shadow(0 0 3px var(--database-stroke));&#10;    }&#10;    .semantic-lens-flow[data-direction=&amp;quot;within&amp;quot;] {&#10;      stroke: var(--messagebus-stroke);&#10;      filter: drop-shadow(0 0 3px var(--messagebus-stroke));&#10;    }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] .semantic-lens-flow {&#10;      stroke-width: 3.7;&#10;      opacity: 1;&#10;    }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] .semantic-lens-flow[data-direction=&amp;quot;out&amp;quot;],&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] .semantic-lens-flow[data-direction=&amp;quot;forward&amp;quot;] {&#10;      filter: drop-shadow(0 0 6px var(--frontend-stroke));&#10;    }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] .semantic-lens-flow[data-direction=&amp;quot;in&amp;quot;],&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] .semantic-lens-flow[data-direction=&amp;quot;reverse&amp;quot;] {&#10;      filter: drop-shadow(0 0 6px var(--database-stroke));&#10;    }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] .semantic-lens-flow[data-direction=&amp;quot;within&amp;quot;] {&#10;      filter: drop-shadow(0 0 6px var(--messagebus-stroke));&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .semantic-lens-flow {&#10;      stroke-width: 2.45;&#10;      stroke-linecap: square;&#10;      filter: none;&#10;      opacity: 0.78;&#10;    }&#10;    html[data-embed=&amp;quot;true&amp;quot;] .semantic-lens-overlay { display: none; }&#10;    svg[data-focus-active] [data-node-id],&#10;    svg[data-focus-active] [data-edge-from] { opacity: 0.13; }&#10;    svg[data-focus-active] [data-focus-match] { opacity: 1; }&#10;    svg[data-focus-active] [data-focus-selected] {&#10;      filter: drop-shadow(0 0 10px var(--frontend-stroke));&#10;    }&#10;&#10;    /* Authored Reachability is a bounded graph query over the relationships&#10;       already present in the artifact. Upstream walks incoming edges;&#10;       downstream walks outgoing edges. It never claims runtime causality and&#10;       changes only viewer emphasis, not canonical geometry or export bytes. */&#10;    svg[data-reach-active] [data-node-id],&#10;    svg[data-reach-active] [data-edge-from] { opacity: 0.09; }&#10;    svg[data-reach-active] [data-reach-match] { opacity: 1; }&#10;    svg[data-reach-active=&amp;quot;upstream&amp;quot;] [data-reach-origin] {&#10;      filter: drop-shadow(0 0 11px var(--database-stroke));&#10;    }&#10;    svg[data-reach-active=&amp;quot;downstream&amp;quot;] [data-reach-origin] {&#10;      filter: drop-shadow(0 0 11px var(--backend-stroke));&#10;    }&#10;    svg[data-reach-active=&amp;quot;upstream&amp;quot;] [data-edge-from][data-reach-match] {&#10;      filter: drop-shadow(0 0 4px color-mix(in srgb, var(--database-stroke) 72%, transparent));&#10;    }&#10;    svg[data-reach-active=&amp;quot;downstream&amp;quot;] [data-edge-from][data-reach-match] {&#10;      filter: drop-shadow(0 0 4px color-mix(in srgb, var(--backend-stroke) 72%, transparent));&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-reach-active] [data-reach-origin],&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-reach-active] [data-edge-from][data-reach-match] {&#10;      filter: none;&#10;    }&#10;&#10;    /* Direct Relationship Explorer makes authored paths a real input surface&#10;       without changing their visible stroke or canonical SVG. A transparent&#10;       runtime rail supplies forgiving pointer geometry; the exact authored&#10;       path and endpoints continue to carry every visible state. */&#10;    .relationship-hit-overlay { pointer-events: none; }&#10;    .relationship-hit-target { outline: none; }&#10;    .relationship-hit-rail {&#10;      fill: none;&#10;      stroke: transparent;&#10;      stroke-width: 24;&#10;      stroke-linecap: round;&#10;      stroke-linejoin: round;&#10;      vector-effect: non-scaling-stroke;&#10;      pointer-events: stroke;&#10;      cursor: pointer;&#10;    }&#10;    .relationship-focus-rail {&#10;      fill: none;&#10;      stroke: color-mix(in srgb, var(--frontend-stroke) 34%, transparent);&#10;      stroke-width: 6;&#10;      stroke-dasharray: 2 4;&#10;      stroke-linecap: round;&#10;      stroke-linejoin: round;&#10;      vector-effect: non-scaling-stroke;&#10;      pointer-events: none;&#10;      opacity: 0;&#10;    }&#10;    .relationship-hit-target:focus-visible .relationship-focus-rail {&#10;      opacity: 1;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .relationship-hit-target:focus-visible .relationship-focus-rail {&#10;      stroke-linecap: square;&#10;      filter: none;&#10;    }&#10;    svg[data-relationship-direct-active] [data-node-id],&#10;    svg[data-relationship-direct-active] [data-edge-from] { opacity: 0.16; }&#10;    svg[data-relationship-direct-active] [data-relationship-preview],&#10;    svg[data-relationship-direct-active] [data-relationship-preview-node] { opacity: 1; }&#10;    svg[data-focus-active]:not([data-relationship-pin-active]) .relationship-hit-rail,&#10;    svg[data-story-active] .relationship-hit-rail,&#10;    svg[data-route-picking] .relationship-hit-rail,&#10;    svg[data-route-active] .relationship-hit-rail,&#10;    svg[data-lens-active] .relationship-hit-rail,&#10;    svg[data-chapter-preview] .relationship-hit-rail { pointer-events: none; }&#10;    html[data-embed=&amp;quot;true&amp;quot;] .relationship-hit-overlay { display: none; }&#10;    @media (hover: none), (pointer: coarse) {&#10;      .relationship-hit-rail { stroke-width: 24; }&#10;    }&#10;&#10;    /* Relationship Preview is temporary exploration state layered on top of&#10;       neighborhood focus. It changes emphasis only; exported geometry and the&#10;       relationship&amp;#x27;s original solid/dashed visual language stay untouched. */&#10;    svg[data-relationship-preview-active] [data-focus-match] { opacity: 0.18; }&#10;    svg[data-relationship-preview-active] [data-relationship-preview],&#10;    svg[data-relationship-preview-active] [data-relationship-preview-node] { opacity: 1; }&#10;    svg[data-relationship-preview-active] [data-relationship-preview] {&#10;      filter: drop-shadow(0 0 5px var(--arrow-emphasis));&#10;    }&#10;    svg[data-relationship-preview-active] [data-relationship-preview] path,&#10;    svg[data-relationship-preview-active] path[data-relationship-preview],&#10;    svg[data-relationship-preview-active] [data-relationship-preview] line,&#10;    svg[data-relationship-preview-active] line[data-relationship-preview],&#10;    svg[data-relationship-preview-active] [data-relationship-preview] polyline,&#10;    svg[data-relationship-preview-active] polyline[data-relationship-preview] {&#10;      stroke-width: 2.75;&#10;    }&#10;    svg[data-relationship-preview-active] [data-relationship-preview-source] {&#10;      filter: drop-shadow(0 0 7px var(--frontend-stroke));&#10;    }&#10;    svg[data-relationship-preview-active] [data-relationship-preview-target] {&#10;      filter: drop-shadow(0 0 7px var(--database-stroke));&#10;    }&#10;    .relationship-pulse-overlay { pointer-events: none; }&#10;    .relationship-flow-pulse {&#10;      fill: none;&#10;      stroke: var(--arrow-emphasis);&#10;      stroke-width: 3.35;&#10;      stroke-linecap: round;&#10;      stroke-dasharray: 0.085 0.915;&#10;      stroke-dashoffset: 0;&#10;      vector-effect: non-scaling-stroke;&#10;      opacity: 0;&#10;      filter: drop-shadow(0 0 4px var(--arrow-emphasis));&#10;      animation: archify-relationship-pulse 1.2s linear 1 both;&#10;    }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] .relationship-flow-pulse {&#10;      stroke: var(--frontend-stroke);&#10;      stroke-width: 3.85;&#10;      filter: drop-shadow(0 0 7px var(--frontend-stroke));&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .relationship-flow-pulse {&#10;      stroke-width: 2.5;&#10;      stroke-linecap: square;&#10;      filter: none;&#10;    }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] .relationship-flow-pulse {&#10;      stroke: var(--arrow-emphasis);&#10;      stroke-width: 2.75;&#10;      filter: none;&#10;    }&#10;    .semantic-flow-token {&#10;      color: var(--frontend-stroke);&#10;      opacity: 0;&#10;      pointer-events: none;&#10;    }&#10;    .relationship-flow-token {&#10;      animation: archify-relationship-token-life 1.2s linear 1 both;&#10;    }&#10;    .story-flow-token {&#10;      animation: archify-relationship-token-life 0.78s linear 1 both;&#10;    }&#10;    .semantic-flow-token-halo {&#10;      fill: var(--mask);&#10;      stroke: currentColor;&#10;      stroke-width: 1.1;&#10;      vector-effect: non-scaling-stroke;&#10;      opacity: 0.96;&#10;    }&#10;    .relationship-flow-token-shape {&#10;      fill: var(--mask);&#10;      stroke: currentColor;&#10;      stroke-width: 1.35;&#10;      stroke-linecap: round;&#10;      stroke-linejoin: round;&#10;      vector-effect: non-scaling-stroke;&#10;    }&#10;    .relationship-flow-token-ink {&#10;      fill: none;&#10;      stroke: currentColor;&#10;      stroke-width: 1.05;&#10;      stroke-linecap: round;&#10;      vector-effect: non-scaling-stroke;&#10;    }&#10;    .relationship-flow-token-dot { fill: currentColor; stroke: none; }&#10;    .semantic-flow-token[data-token-kind=&amp;quot;data&amp;quot;] { color: var(--database-stroke); }&#10;    .semantic-flow-token[data-token-kind=&amp;quot;event&amp;quot;] { color: var(--messagebus-stroke); }&#10;    .semantic-flow-token[data-token-kind=&amp;quot;security&amp;quot;] { color: var(--security-stroke); }&#10;    .semantic-flow-token[data-token-kind=&amp;quot;state&amp;quot;] { color: var(--cloud-stroke); }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;] .semantic-flow-token {&#10;      filter: drop-shadow(0 0 5px currentColor);&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .semantic-flow-token { filter: none; }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] .semantic-flow-token { filter: none; }&#10;    html[data-embed=&amp;quot;true&amp;quot;] .relationship-pulse-overlay { display: none; }&#10;&#10;    /* Intent Trace is a temporary, pre-click exploration layer. Related&#10;       topology stays readable while a short viewer-only signal runs over&#10;       cloned edge geometry; the authored edge remains untouched underneath. */&#10;    svg[data-intent-trace-active] [data-node-id],&#10;    svg[data-intent-trace-active] [data-edge-from] { opacity: 0.2; }&#10;    svg[data-intent-trace-active] [data-intent-trace-match] { opacity: 1; }&#10;    svg[data-intent-trace-active] [data-intent-trace-selected] {&#10;      filter: drop-shadow(0 0 10px var(--frontend-stroke));&#10;    }&#10;    .intent-trace-overlay { pointer-events: none; }&#10;    .intent-trace-flow {&#10;      fill: none;&#10;      stroke-width: 3.1;&#10;      stroke-linecap: round;&#10;      stroke-dasharray: 0.1 0.9;&#10;      stroke-dashoffset: 0;&#10;      vector-effect: non-scaling-stroke;&#10;      opacity: 0.94;&#10;      animation: archify-intent-trace-flow 1.15s linear 1 both;&#10;    }&#10;    /* Direction names describe each edge relative to the focused node only.&#10;       The cloned geometry already runs from the authored source to target, so&#10;       incoming and outgoing signals must share the same playback direction. */&#10;    .intent-trace-flow[data-direction=&amp;quot;out&amp;quot;] {&#10;      stroke: var(--frontend-stroke);&#10;      filter: drop-shadow(0 0 4px var(--frontend-stroke));&#10;    }&#10;    .intent-trace-flow[data-direction=&amp;quot;in&amp;quot;] {&#10;      stroke: var(--database-stroke);&#10;      filter: drop-shadow(0 0 4px var(--database-stroke));&#10;      animation-direction: normal;&#10;    }&#10;    .intent-trace-flow[data-direction=&amp;quot;loop&amp;quot;] {&#10;      stroke: var(--security-stroke);&#10;      filter: drop-shadow(0 0 4px var(--security-stroke));&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] [data-intent-trace-selected],&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .intent-trace-flow {&#10;      filter: none;&#10;      stroke-linecap: square;&#10;    }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] [data-intent-trace-selected],&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] .intent-trace-flow { filter: none; }&#10;    .intent-trace-status {&#10;      position: absolute;&#10;      width: 1px;&#10;      height: 1px;&#10;      padding: 0;&#10;      margin: -1px;&#10;      overflow: hidden;&#10;      clip: rect(0, 0, 0, 0);&#10;      clip-path: inset(50%);&#10;      white-space: nowrap;&#10;      border: 0;&#10;    }&#10;&#10;    /* Route Probe separates a durable two-point query from selection and&#10;       one-hop hover. Only the chosen shortest directed path stays prominent;&#10;       the traveling signal is cloned viewer geometry and never authored SVG. */&#10;    svg[data-route-picking=&amp;quot;target&amp;quot;] [data-node-id] { opacity: 0.24; }&#10;    svg[data-route-picking=&amp;quot;target&amp;quot;] [data-route-candidate],&#10;    svg[data-route-picking=&amp;quot;target&amp;quot;] [data-route-start] { opacity: 1; }&#10;    svg[data-route-picking] [data-node-id] { cursor: crosshair; }&#10;    svg[data-route-picking] [data-route-start] {&#10;      filter: drop-shadow(0 0 10px var(--frontend-stroke));&#10;    }&#10;    svg[data-route-active] [data-node-id],&#10;    svg[data-route-active] [data-edge-from] { opacity: 0.11; }&#10;    svg[data-route-active] [data-route-match] { opacity: 1; }&#10;    svg[data-route-active] [data-route-start] {&#10;      filter: drop-shadow(0 0 11px var(--frontend-stroke));&#10;    }&#10;    svg[data-route-active] [data-route-end] {&#10;      filter: drop-shadow(0 0 11px var(--security-stroke));&#10;    }&#10;    svg[data-route-active] [data-route-step]:not([data-route-start]):not([data-route-end]) {&#10;      filter: drop-shadow(0 0 7px var(--backend-stroke));&#10;    }&#10;    svg[data-route-journey] [data-route-match][data-route-journey-state=&amp;quot;past&amp;quot;] { opacity: 0.62; }&#10;    svg[data-route-journey] [data-route-match][data-route-journey-state=&amp;quot;future&amp;quot;] { opacity: 0.34; }&#10;    svg[data-route-journey] [data-route-match][data-route-journey-state=&amp;quot;current&amp;quot;] { opacity: 1; }&#10;    svg[data-route-journey] [data-node-id][data-route-journey-current] {&#10;      filter: drop-shadow(0 0 10px var(--backend-stroke));&#10;    }&#10;    svg[data-route-journey] [data-edge-from][data-route-journey-current] {&#10;      opacity: 1;&#10;      filter: drop-shadow(0 0 6px var(--backend-stroke));&#10;    }&#10;    .route-probe-overlay { pointer-events: none; }&#10;    .route-journey-overlay { pointer-events: none; }&#10;    .route-probe-flow {&#10;      fill: none;&#10;      stroke: var(--backend-stroke);&#10;      stroke-width: 3.25;&#10;      stroke-linecap: round;&#10;      stroke-dasharray: 0.085 0.915;&#10;      stroke-dashoffset: 0;&#10;      vector-effect: non-scaling-stroke;&#10;      opacity: 0.96;&#10;      filter: drop-shadow(0 0 5px var(--backend-stroke));&#10;      animation: archify-route-probe-flow 1.1s cubic-bezier(0.22, 1, 0.36, 1) 1 both;&#10;      animation-delay: calc(var(--route-step, 0) * 0.16s);&#10;    }&#10;    .route-journey-flow {&#10;      fill: none;&#10;      stroke: var(--backend-stroke);&#10;      stroke-width: 3.5;&#10;      stroke-linecap: round;&#10;      stroke-dasharray: 0.1 0.9;&#10;      stroke-dashoffset: 0;&#10;      vector-effect: non-scaling-stroke;&#10;      opacity: 0;&#10;      filter: drop-shadow(0 0 6px var(--backend-stroke));&#10;      animation: archify-route-journey-flow 780ms cubic-bezier(0.22, 1, 0.36, 1) 1 both;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] [data-route-start],&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] [data-route-end],&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] [data-route-step],&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .route-probe-flow {&#10;      filter: none;&#10;      stroke-linecap: square;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .route-journey-flow {&#10;      filter: none;&#10;      stroke-linecap: square;&#10;    }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] [data-route-start],&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] [data-route-end],&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] [data-route-step],&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] .route-probe-flow,&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] .route-journey-flow { filter: none; }&#10;&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] .c-grid {&#10;      stroke-dasharray: 1 4;&#10;      opacity: 0.48;&#10;    }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] .c-region {&#10;      fill: color-mix(in srgb, var(--cloud-fill) 48%, transparent);&#10;      stroke-dasharray: 9 4;&#10;    }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] [data-node-id]:hover,&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] [data-node-id]:focus-visible,&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;][data-focus-active] [data-focus-selected] {&#10;      filter: drop-shadow(0 2px 2px color-mix(in srgb, var(--text) 18%, transparent));&#10;    }&#10;&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .c-grid {&#10;      stroke-dasharray: 1 3;&#10;      opacity: 0.78;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .c-region {&#10;      fill: color-mix(in srgb, var(--cloud-fill) 58%, transparent);&#10;      stroke-dasharray: 12 4 2 4;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .c-security-group,&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .c-lane { stroke-dasharray: 7 3; }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] [data-node-id]:hover,&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] [data-node-id]:focus-visible {&#10;      filter: drop-shadow(0 0 3px var(--frontend-stroke));&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-focus-active] [data-focus-selected] {&#10;      filter: drop-shadow(0 0 3px var(--frontend-stroke));&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-focus-active][data-reach-active] [data-focus-selected][data-reach-origin] {&#10;      filter: none;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-relationship-preview-active] [data-relationship-preview],&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-relationship-preview-active] [data-relationship-preview-source],&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-relationship-preview-active] [data-relationship-preview-target] {&#10;      filter: drop-shadow(0 0 3px var(--frontend-stroke));&#10;    }&#10;&#10;    /* Story Trail is a viewer-only overlay derived from the ordered focus IDs&#10;       of the active guided view. The authored edge stays underneath with its&#10;       original color, dash pattern, marker, and geometry intact. */&#10;    .story-trail-overlay { pointer-events: none; }&#10;    .story-carrier-overlay { pointer-events: none; }&#10;    .story-trail-flow {&#10;      fill: none;&#10;      stroke: var(--frontend-stroke);&#10;      stroke-width: 2.8;&#10;      stroke-linecap: round;&#10;      vector-effect: non-scaling-stroke;&#10;      opacity: 0.34;&#10;      filter: drop-shadow(0 0 2px var(--frontend-stroke));&#10;    }&#10;    svg[data-story-beat] [data-story-step] {&#10;      opacity: 0.22;&#10;      filter: saturate(0.42);&#10;      transition: opacity 180ms ease, filter 180ms ease;&#10;    }&#10;    svg[data-story-beat] [data-story-step][data-story-beat-state=&amp;quot;past&amp;quot;] {&#10;      opacity: 0.72;&#10;      filter: saturate(0.82);&#10;    }&#10;    svg[data-story-beat] [data-story-step][data-story-beat-state=&amp;quot;next&amp;quot;] {&#10;      opacity: 0.5;&#10;      filter: saturate(0.66);&#10;    }&#10;    svg[data-story-beat] [data-story-step][data-story-beat-state=&amp;quot;active&amp;quot;] {&#10;      opacity: 1;&#10;      filter: drop-shadow(0 0 7px var(--frontend-stroke));&#10;      animation: archify-story-beat-node 360ms cubic-bezier(0.22, 1, 0.36, 1) both;&#10;    }&#10;    svg[data-story-beat] [data-edge-from][data-story-beat-step] {&#10;      opacity: 0.16;&#10;      transition: opacity 160ms ease;&#10;    }&#10;    svg[data-story-beat] [data-edge-from][data-story-beat-step][data-story-beat-state=&amp;quot;past&amp;quot;] { opacity: 0.58; }&#10;    svg[data-story-beat] [data-edge-from][data-story-beat-step][data-story-beat-state=&amp;quot;next&amp;quot;] { opacity: 0.34; }&#10;    svg[data-story-beat] [data-edge-from][data-story-beat-step][data-story-beat-state=&amp;quot;active&amp;quot;] { opacity: 1; }&#10;    svg[data-story-beat] .story-trail-flow { opacity: 0; transition: opacity 160ms ease; }&#10;    svg[data-story-beat] .story-trail-flow[data-story-beat-state=&amp;quot;past&amp;quot;] { opacity: 0.34; }&#10;    svg[data-story-beat] .story-trail-flow[data-story-beat-state=&amp;quot;next&amp;quot;] { opacity: 0.2; }&#10;    svg[data-story-beat] .story-trail-flow[data-story-beat-state=&amp;quot;active&amp;quot;] { opacity: 0.92; }&#10;    svg[data-story-beat] .story-trail-flow[data-story-pulse=&amp;quot;true&amp;quot;] {&#10;      stroke-dasharray: 2 13;&#10;      stroke-dashoffset: 30;&#10;      opacity: 0.92;&#10;      animation: archify-story-flow 0.78s linear 1 both;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;] .story-trail-flow {&#10;      stroke-linecap: square;&#10;      filter: none;&#10;      opacity: 0.5;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-story-beat] [data-story-step][data-story-beat-state=&amp;quot;active&amp;quot;] {&#10;      filter: none;&#10;      animation: none;&#10;    }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;] .story-trail-flow { filter: none; }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;][data-story-beat] [data-story-step][data-story-beat-state=&amp;quot;active&amp;quot;] {&#10;      filter: drop-shadow(0 2px 2px color-mix(in srgb, var(--text) 16%, transparent));&#10;    }&#10;&#10;    /* Chapter Delta Preview is a static, pre-commit comparison between two&#10;       chapter focus sets. Symbols in the rail carry the meaning without color;&#10;       these SVG rules only make exact stable-ID membership easier to scan. */&#10;    svg[data-chapter-preview] [data-node-id],&#10;    svg[data-chapter-preview] [data-edge-from] {&#10;      opacity: 0.1 !important;&#10;      filter: none !important;&#10;      transition: none !important;&#10;    }&#10;    svg[data-chapter-preview] .story-trail-overlay { opacity: 0.08 !important; }&#10;    svg[data-chapter-preview] [data-node-id][data-chapter-preview-role=&amp;quot;stay&amp;quot;] {&#10;      opacity: 0.76 !important;&#10;      filter: saturate(0.7) !important;&#10;    }&#10;    svg[data-chapter-preview] [data-node-id][data-chapter-preview-role=&amp;quot;enter&amp;quot;] {&#10;      opacity: 1 !important;&#10;      filter: saturate(1.2) !important;&#10;    }&#10;    svg[data-chapter-preview] [data-node-id][data-chapter-preview-role=&amp;quot;leave&amp;quot;] {&#10;      opacity: 0.28 !important;&#10;      filter: grayscale(0.72) !important;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-chapter-preview] [data-node-id] { filter: none !important; }&#10;&#10;    /* Dashed boundary variants */&#10;    .c-security-group { fill: transparent; stroke: var(--security-stroke); stroke-dasharray: 4,4; }&#10;    .c-region         { fill: rgba(251, 191, 36, 0.05); stroke: var(--cloud-stroke); stroke-dasharray: 8,4; }&#10;    .c-lane           { fill: var(--lane-fill); stroke: var(--lane-stroke); stroke-dasharray: 6,6; }&#10;&#10;    /* Optional trace animation, enabled only by meta.animation = &amp;quot;trace&amp;quot;.&#10;       The ordinary viewer performs one ambient pass and then restores the&#10;       authored solid/security/async line language. WebM samples the same&#10;       authored geometry into an explicit canvas timeline. */&#10;    html[data-ambient-motion=&amp;quot;running&amp;quot;] svg[data-animation=&amp;quot;trace&amp;quot;] [data-animate=&amp;quot;edge&amp;quot;] {&#10;      animation: archify-edge-flow 2.4s linear 1;&#10;      animation-delay: calc(var(--step, 0) * 160ms);&#10;    }&#10;    html[data-ambient-motion=&amp;quot;running&amp;quot;] svg[data-animation=&amp;quot;trace&amp;quot;] [data-animate=&amp;quot;node&amp;quot;] {&#10;      transform-box: fill-box;&#10;      transform-origin: center;&#10;      animation: archify-node-pulse 3.6s ease-in-out 1;&#10;      animation-delay: calc(var(--step, 0) * 160ms);&#10;    }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;][data-animation=&amp;quot;trace&amp;quot;] [data-animate=&amp;quot;edge&amp;quot;] {&#10;      stroke-linecap: round;&#10;      filter: drop-shadow(0 0 3px var(--arrow-emphasis));&#10;      animation-duration: 1.75s;&#10;    }&#10;    svg[data-preset=&amp;quot;signal-flow&amp;quot;][data-animation=&amp;quot;trace&amp;quot;] [data-animate=&amp;quot;node&amp;quot;] {&#10;      animation-duration: 3.1s;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-animation=&amp;quot;trace&amp;quot;] [data-animate=&amp;quot;edge&amp;quot;] {&#10;      stroke-linecap: square;&#10;      filter: none;&#10;      animation-duration: 2.15s;&#10;    }&#10;    svg[data-preset=&amp;quot;blueprint&amp;quot;][data-animation=&amp;quot;trace&amp;quot;] [data-animate=&amp;quot;node&amp;quot;] {&#10;      animation-name: archify-blueprint-node-pulse;&#10;      animation-duration: 3.8s;&#10;    }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;][data-animation=&amp;quot;trace&amp;quot;] [data-animate=&amp;quot;edge&amp;quot;] {&#10;      filter: none;&#10;      animation-duration: 2.2s;&#10;    }&#10;    svg[data-preset=&amp;quot;editorial&amp;quot;][data-animation=&amp;quot;trace&amp;quot;] [data-animate=&amp;quot;node&amp;quot;] {&#10;      animation-name: archify-editorial-node-pulse;&#10;      animation-duration: 3.5s;&#10;    }&#10;    /* Embedded proofs are static until a named Story Trail chapter is played.&#10;       This keeps proof grids calm and ensures ?play=1 stops all viewer motion&#10;       after one 3.2 second chapter instead of leaving ambient trace loops on. */&#10;    html[data-embed=&amp;quot;true&amp;quot;] svg[data-animation=&amp;quot;trace&amp;quot;] [data-animate],&#10;    html[data-share-playback=&amp;quot;true&amp;quot;] svg[data-animation=&amp;quot;trace&amp;quot;] [data-animate] {&#10;      animation: none !important;&#10;      stroke-dashoffset: 0;&#10;    }&#10;    @keyframes archify-edge-flow {&#10;      0% { stroke-dasharray: 10 8; stroke-dashoffset: 54; opacity: 0.42; }&#10;      88% { stroke-dasharray: 10 8; stroke-dashoffset: 0; opacity: 1; }&#10;      99.9% { stroke-dasharray: 10 8; stroke-dashoffset: 0; opacity: 1; }&#10;      100% { stroke-dashoffset: 0; opacity: 1; }&#10;    }&#10;    @keyframes archify-node-pulse {&#10;      0%, 72%, 100% { filter: none; stroke-width: 1.5; }&#10;      18%, 36% {&#10;        filter: drop-shadow(0 0 8px var(--arrow-emphasis));&#10;        stroke-width: 2.4;&#10;      }&#10;    }&#10;    @keyframes archify-blueprint-node-pulse {&#10;      0%, 72%, 100% { opacity: 1; filter: none; }&#10;      18%, 36% { opacity: 0.72; filter: drop-shadow(0 0 2px var(--frontend-stroke)); }&#10;    }&#10;    @keyframes archify-editorial-node-pulse {&#10;      0%, 72%, 100% { opacity: 1; filter: none; }&#10;      18%, 36% { opacity: 0.78; filter: drop-shadow(0 2px 2px color-mix(in srgb, var(--text) 18%, transparent)); }&#10;    }&#10;    @keyframes archify-signal-scan {&#10;      0%, 18% { opacity: 1; transform: translateX(-70%); }&#10;      70% { opacity: 1; transform: translateX(70%); }&#10;      100% { opacity: 0; transform: translateX(70%); }&#10;    }&#10;    @keyframes archify-radar-live {&#10;      0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--backend-stroke) 52%, transparent); }&#10;      55%, 100% { box-shadow: 0 0 0 0.32rem transparent; }&#10;    }&#10;    @keyframes archify-guided-progress {&#10;      from { transform: scaleX(var(--guided-progress-start, 0)); }&#10;      to { transform: scaleX(1); }&#10;    }&#10;    @keyframes archify-story-flow {&#10;      to { stroke-dashoffset: 0; }&#10;    }&#10;    @keyframes archify-intent-trace-flow {&#10;      0% { opacity: 0.28; stroke-dashoffset: 0; }&#10;      12%, 78% { opacity: 0.94; }&#10;      100% { opacity: 0; stroke-dashoffset: -1; }&#10;    }&#10;    @keyframes archify-route-probe-flow {&#10;      0% { stroke-dashoffset: 0; opacity: 0.96; }&#10;      78% { stroke-dashoffset: -1; opacity: 0.96; }&#10;      100% { stroke-dasharray: none; stroke-dashoffset: 0; opacity: 0.58; }&#10;    }&#10;    @keyframes archify-route-journey-flow {&#10;      0% { opacity: 0.16; stroke-dashoffset: 0; }&#10;      14%, 76% { opacity: 1; }&#10;      100% { opacity: 0; stroke-dashoffset: -1; }&#10;    }&#10;    @keyframes archify-semantic-lens-flow {&#10;      0% { opacity: 0.2; stroke-dashoffset: 0; }&#10;      12%, 78% { opacity: 0.9; }&#10;      100% { opacity: 0; stroke-dashoffset: -1; }&#10;    }&#10;    @keyframes archify-relationship-pulse {&#10;      0% { opacity: 0.18; stroke-dashoffset: 0; }&#10;      10%, 76% { opacity: 0.98; }&#10;      100% { opacity: 0; stroke-dashoffset: -1; }&#10;    }&#10;    @keyframes archify-relationship-token-life {&#10;      0%, 7% { opacity: 0; }&#10;      13%, 82% { opacity: 1; }&#10;      100% { opacity: 0; }&#10;    }&#10;    @keyframes archify-story-beat-node {&#10;      from { opacity: 0.48; filter: saturate(0.6); }&#10;      58% { opacity: 1; filter: drop-shadow(0 0 10px var(--frontend-stroke)); }&#10;      to { opacity: 1; filter: drop-shadow(0 0 7px var(--frontend-stroke)); }&#10;    }&#10;    @keyframes archify-share-cue-enter {&#10;      from { opacity: 0; transform: translate(-50%, -0.45rem); }&#10;      to { opacity: 1; transform: translate(-50%, 0); }&#10;    }&#10;    @keyframes archify-share-cue-pulse {&#10;      0%, 100% { opacity: 1; transform: scale(1); }&#10;      50% { opacity: 0.48; transform: scale(0.78); }&#10;    }&#10;    @media (prefers-reduced-motion: reduce) {&#10;      html[data-preset=&amp;quot;signal-flow&amp;quot;] .diagram-container::before {&#10;        animation: none !important;&#10;      }&#10;      .pulse-dot { animation: none !important; }&#10;      svg[data-animation=&amp;quot;trace&amp;quot;] [data-animate] {&#10;        animation: none !important;&#10;        stroke-dashoffset: 0;&#10;      }&#10;      .guided-view-progress span {&#10;        animation: none !important;&#10;        transform: scaleX(1) !important;&#10;      }&#10;      .story-trail-flow,&#10;      .intent-trace-flow,&#10;      .route-probe-flow,&#10;      .semantic-lens,&#10;      .diagram-guide,&#10;      [data-story-step],&#10;      .overview-map-live,&#10;      .guided-view-stop,&#10;      .share-chapter-cue,&#10;      .chapter-handoff-anchor,&#10;      .share-chapter-state::before,&#10;      .share-chapter-progress span { animation: none !important; }&#10;      .guided-view-chapter,&#10;      svg[data-chapter-preview] [data-node-id],&#10;      svg[data-chapter-preview] [data-edge-from] { transition: none !important; }&#10;      svg[data-story-playing=&amp;quot;true&amp;quot;] .story-trail-flow {&#10;        stroke-dasharray: none;&#10;        stroke-dashoffset: 0;&#10;        opacity: 0.55;&#10;      }&#10;      .intent-trace-flow {&#10;        animation: none !important;&#10;        stroke-dasharray: none;&#10;        stroke-dashoffset: 0;&#10;        opacity: 0.72;&#10;      }&#10;      .route-probe-flow {&#10;        animation: none !important;&#10;        stroke-dasharray: none;&#10;        stroke-dashoffset: 0;&#10;        opacity: 0.78;&#10;      }&#10;      .route-journey-overlay,&#10;      .story-carrier-overlay { display: none !important; }&#10;      .semantic-lens-flow {&#10;        animation: none !important;&#10;        stroke-dasharray: none;&#10;        stroke-width: 2.2;&#10;        opacity: 0.34;&#10;        filter: none;&#10;      }&#10;      .relationship-pulse-overlay { display: none !important; }&#10;      .guided-view-chapter { transition: none !important; }&#10;      .source-evidence-beacon,&#10;      svg [data-node-id], svg [data-edge-from], svg [data-detail], svg [data-detail-anchor], svg [data-legend-hit], svg { transition: none !important; }&#10;    }&#10;  &amp;lt;/style&amp;gt;&#10;&amp;lt;/head&amp;gt;&#10;&amp;lt;body&amp;gt;&#10;  &amp;lt;!-- Toolbar: theme, live visual style, trace motion, presentation stage, and export.&#10;       Motion appears only for trace-enabled artifacts and has no shortcut;&#10;       Keyboard: T toggles theme, S cycles style, F toggles the stage, E opens export. --&amp;gt;&#10;  &amp;lt;div class=&amp;quot;toolbar&amp;quot; role=&amp;quot;toolbar&amp;quot; aria-label=&amp;quot;图表操作&amp;quot;&amp;gt;&#10;    &amp;lt;button id=&amp;quot;btn-theme&amp;quot; type=&amp;quot;button&amp;quot;&#10;            title=&amp;quot;切换主题（T）&amp;quot;&#10;            aria-label=&amp;quot;切换颜色主题&amp;quot;&#10;            aria-pressed=&amp;quot;false&amp;quot;&amp;gt;&#10;      &amp;lt;span id=&amp;quot;theme-icon&amp;quot; class=&amp;quot;toolbar-icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;      &amp;lt;span id=&amp;quot;theme-label&amp;quot;&amp;gt;深色&amp;lt;/span&amp;gt;&#10;    &amp;lt;/button&amp;gt;&#10;    &amp;lt;div class=&amp;quot;preset-wrap&amp;quot;&amp;gt;&#10;      &amp;lt;button id=&amp;quot;btn-preset&amp;quot; type=&amp;quot;button&amp;quot;&#10;              title=&amp;quot;选择视觉风格（S 循环切换）&amp;quot;&#10;              aria-label=&amp;quot;选择视觉风格&amp;quot;&#10;              aria-haspopup=&amp;quot;menu&amp;quot;&#10;              aria-expanded=&amp;quot;false&amp;quot;&#10;              aria-controls=&amp;quot;preset-menu&amp;quot;&#10;              aria-keyshortcuts=&amp;quot;S&amp;quot;&amp;gt;&#10;        &amp;lt;span class=&amp;quot;preset-control-mark&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;        &amp;lt;span id=&amp;quot;preset-label&amp;quot;&amp;gt;风格&amp;lt;/span&amp;gt;&#10;        &amp;lt;span class=&amp;quot;toolbar-icon toolbar-chevron&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;      &amp;lt;/button&amp;gt;&#10;      &amp;lt;div class=&amp;quot;preset-menu&amp;quot; id=&amp;quot;preset-menu&amp;quot; role=&amp;quot;menu&amp;quot; aria-label=&amp;quot;视觉风格&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;preset-menu-heading&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;&amp;lt;span&amp;gt;视觉表达&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;S 循环切换&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#10;        &amp;lt;button class=&amp;quot;preset-option&amp;quot; data-preset-value=&amp;quot;classic&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitemradio&amp;quot; aria-checked=&amp;quot;false&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-swatch classic&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;经典&amp;lt;/strong&amp;gt;&amp;lt;small&amp;gt;稳定的技术默认风格&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-check&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;        &amp;lt;/button&amp;gt;&#10;        &amp;lt;button class=&amp;quot;preset-option&amp;quot; data-preset-value=&amp;quot;signal-flow&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitemradio&amp;quot; aria-checked=&amp;quot;false&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-swatch signal-flow&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;信号流&amp;lt;/strong&amp;gt;&amp;lt;small&amp;gt;突出动态流向&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-check&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;        &amp;lt;/button&amp;gt;&#10;        &amp;lt;button class=&amp;quot;preset-option&amp;quot; data-preset-value=&amp;quot;blueprint&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitemradio&amp;quot; aria-checked=&amp;quot;false&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-swatch blueprint&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;蓝图&amp;lt;/strong&amp;gt;&amp;lt;small&amp;gt;工程评审&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-check&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;        &amp;lt;/button&amp;gt;&#10;        &amp;lt;button class=&amp;quot;preset-option&amp;quot; data-preset-value=&amp;quot;editorial&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitemradio&amp;quot; aria-checked=&amp;quot;false&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-swatch editorial&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;编辑风格&amp;lt;/strong&amp;gt;&amp;lt;small&amp;gt;适合发布与上线说明&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;preset-option-check&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;        &amp;lt;/button&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;    &amp;lt;/div&amp;gt;&#10;    &amp;lt;button id=&amp;quot;btn-motion&amp;quot; type=&amp;quot;button&amp;quot; hidden&#10;            title=&amp;quot;暂停动效&amp;quot;&#10;            aria-label=&amp;quot;暂停动效&amp;quot;&#10;            aria-pressed=&amp;quot;true&amp;quot;&amp;gt;&#10;      &amp;lt;span class=&amp;quot;motion-control-dot&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;      &amp;lt;span id=&amp;quot;motion-label&amp;quot;&amp;gt;动态&amp;lt;/span&amp;gt;&#10;    &amp;lt;/button&amp;gt;&#10;    &amp;lt;button id=&amp;quot;btn-present&amp;quot; type=&amp;quot;button&amp;quot;&#10;            title=&amp;quot;演示模式（F）&amp;quot;&#10;            aria-label=&amp;quot;进入演示模式&amp;quot;&#10;            aria-pressed=&amp;quot;false&amp;quot;&amp;gt;&#10;      &amp;lt;span id=&amp;quot;present-icon&amp;quot; class=&amp;quot;toolbar-icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;      &amp;lt;span id=&amp;quot;present-label&amp;quot;&amp;gt;演示&amp;lt;/span&amp;gt;&#10;    &amp;lt;/button&amp;gt;&#10;    &amp;lt;div class=&amp;quot;export-wrap&amp;quot;&amp;gt;&#10;      &amp;lt;button id=&amp;quot;btn-export&amp;quot; type=&amp;quot;button&amp;quot;&#10;              title=&amp;quot;导出图表（E）&amp;quot;&#10;              aria-label=&amp;quot;导出图表&amp;quot;&#10;              aria-haspopup=&amp;quot;menu&amp;quot;&#10;              aria-expanded=&amp;quot;false&amp;quot;&#10;              aria-controls=&amp;quot;export-menu&amp;quot;&amp;gt;&#10;        导出 &amp;lt;span class=&amp;quot;toolbar-icon toolbar-chevron&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;      &amp;lt;/button&amp;gt;&#10;      &amp;lt;div class=&amp;quot;export-menu&amp;quot; id=&amp;quot;export-menu&amp;quot; role=&amp;quot;menu&amp;quot; aria-label=&amp;quot;导出&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;export-menu-header&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;&#10;          &amp;lt;div&amp;gt;&amp;lt;strong&amp;gt;导出图表&amp;lt;/strong&amp;gt;&amp;lt;span&amp;gt;便携、整洁的输出&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#10;          &amp;lt;kbd&amp;gt;E&amp;lt;/kbd&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;export-menu-section&amp;quot; role=&amp;quot;group&amp;quot; aria-label=&amp;quot;分享&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;export-menu-heading&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;分享&amp;lt;/span&amp;gt;&#10;          &amp;lt;button data-format=&amp;quot;share-card&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;分享卡片&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;1200&amp;amp;times;630 PNG&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;          &amp;lt;button data-action=&amp;quot;route-share-card&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot; hidden disabled&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;路径分享卡片&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;1200&amp;amp;times;630 PNG&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;          &amp;lt;button data-action=&amp;quot;reach-share-card&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot; hidden disabled&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;可达范围分享卡片&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;1200&amp;amp;times;630 PNG&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;          &amp;lt;button data-action=&amp;quot;copy-share-card&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;复制分享卡片&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;复制 PNG 到剪贴板&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;          &amp;lt;button data-action=&amp;quot;copy&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;复制图表&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;复制 PNG 到剪贴板&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;export-menu-section&amp;quot; role=&amp;quot;group&amp;quot; aria-label=&amp;quot;位图&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;export-menu-heading&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;图像&amp;lt;/span&amp;gt;&#10;          &amp;lt;button data-format=&amp;quot;png&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;PNG&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;无损图像&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;          &amp;lt;button data-format=&amp;quot;jpeg&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;JPEG&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;紧凑图像&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;          &amp;lt;button data-format=&amp;quot;webp&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;WebP&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;现代图像格式&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;export-menu-section&amp;quot; role=&amp;quot;group&amp;quot; aria-label=&amp;quot;矢量与动效&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;export-menu-heading&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;矢量与动效&amp;lt;/span&amp;gt;&#10;          &amp;lt;button data-format=&amp;quot;svg&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;SVG&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;可编辑矢量图&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;          &amp;lt;button data-format=&amp;quot;webm&amp;quot; type=&amp;quot;button&amp;quot; role=&amp;quot;menuitem&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;export-item-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;WebM&amp;lt;/strong&amp;gt;&amp;lt;small class=&amp;quot;hint&amp;quot;&amp;gt;6 秒动效&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;    &amp;lt;/div&amp;gt;&#10;  &amp;lt;/div&amp;gt;&#10;&#10;  &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;&#10;    &amp;lt;!-- Header --&amp;gt;&#10;    &amp;lt;div class=&amp;quot;header&amp;quot;&amp;gt;&#10;      &amp;lt;div class=&amp;quot;header-row&amp;quot;&#10;           data-preset-badge-signal-flow=&amp;quot;信号流&amp;quot;&#10;           data-preset-badge-blueprint=&amp;quot;蓝图 / 修订 01&amp;quot;&#10;           data-preset-badge-editorial=&amp;quot;编辑风格 / 现场笔记&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;pulse-dot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;        &amp;lt;h1&amp;gt;AI 推理服务：从请求到芯片&amp;lt;/h1&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;    &amp;lt;/div&amp;gt;&#10;&#10;    &amp;lt;script id=&amp;quot;archify-guided-views-data&amp;quot; type=&amp;quot;application/json&amp;quot;&amp;gt;[]&amp;lt;/script&amp;gt;&#10;&#10;    &amp;lt;script id=&amp;quot;archify-i18n-data&amp;quot; type=&amp;quot;application/json&amp;quot;&amp;gt;{&amp;quot;locale&amp;quot;:&amp;quot;zh-CN&amp;quot;,&amp;quot;messages&amp;quot;:{&amp;quot;viewer.kind.frontend&amp;quot;:&amp;quot;前端&amp;quot;,&amp;quot;viewer.kind.backend&amp;quot;:&amp;quot;后端&amp;quot;,&amp;quot;viewer.kind.database&amp;quot;:&amp;quot;数据库&amp;quot;,&amp;quot;viewer.kind.cloud&amp;quot;:&amp;quot;云服务&amp;quot;,&amp;quot;viewer.kind.security&amp;quot;:&amp;quot;安全&amp;quot;,&amp;quot;viewer.kind.messagebus&amp;quot;:&amp;quot;消息总线&amp;quot;,&amp;quot;viewer.kind.external&amp;quot;:&amp;quot;外部系统&amp;quot;,&amp;quot;viewer.kind.neutral&amp;quot;:&amp;quot;中性&amp;quot;,&amp;quot;viewer.kind.node&amp;quot;:&amp;quot;节点&amp;quot;,&amp;quot;viewer.kind.start&amp;quot;:&amp;quot;开始&amp;quot;,&amp;quot;viewer.kind.active&amp;quot;:&amp;quot;活动&amp;quot;,&amp;quot;viewer.kind.waiting&amp;quot;:&amp;quot;等待&amp;quot;,&amp;quot;viewer.kind.decision&amp;quot;:&amp;quot;决策&amp;quot;,&amp;quot;viewer.kind.success&amp;quot;:&amp;quot;成功&amp;quot;,&amp;quot;viewer.kind.failure&amp;quot;:&amp;quot;失败&amp;quot;,&amp;quot;viewer.toolbar.actions&amp;quot;:&amp;quot;图表操作&amp;quot;,&amp;quot;viewer.theme.toggle.title&amp;quot;:&amp;quot;切换主题（T）&amp;quot;,&amp;quot;viewer.theme.toggle&amp;quot;:&amp;quot;切换颜色主题&amp;quot;,&amp;quot;viewer.theme.dark&amp;quot;:&amp;quot;深色&amp;quot;,&amp;quot;viewer.theme.light&amp;quot;:&amp;quot;浅色&amp;quot;,&amp;quot;viewer.preset.choose.title&amp;quot;:&amp;quot;选择视觉风格（S 循环切换）&amp;quot;,&amp;quot;viewer.preset.choose&amp;quot;:&amp;quot;选择视觉风格&amp;quot;,&amp;quot;viewer.preset.style&amp;quot;:&amp;quot;风格&amp;quot;,&amp;quot;viewer.preset.menu&amp;quot;:&amp;quot;视觉风格&amp;quot;,&amp;quot;viewer.preset.identity&amp;quot;:&amp;quot;视觉表达&amp;quot;,&amp;quot;viewer.preset.cycles&amp;quot;:&amp;quot;S 循环切换&amp;quot;,&amp;quot;viewer.preset.classic&amp;quot;:&amp;quot;经典&amp;quot;,&amp;quot;viewer.preset.classic.short&amp;quot;:&amp;quot;经典&amp;quot;,&amp;quot;viewer.preset.classic.hint&amp;quot;:&amp;quot;稳定的技术默认风格&amp;quot;,&amp;quot;viewer.preset.flow&amp;quot;:&amp;quot;信号流&amp;quot;,&amp;quot;viewer.preset.flow.short&amp;quot;:&amp;quot;流动&amp;quot;,&amp;quot;viewer.preset.flow.hint&amp;quot;:&amp;quot;突出动态流向&amp;quot;,&amp;quot;viewer.preset.blueprint&amp;quot;:&amp;quot;蓝图&amp;quot;,&amp;quot;viewer.preset.blueprint.hint&amp;quot;:&amp;quot;工程评审&amp;quot;,&amp;quot;viewer.preset.editorial&amp;quot;:&amp;quot;编辑风格&amp;quot;,&amp;quot;viewer.preset.editorial.hint&amp;quot;:&amp;quot;适合发布与上线说明&amp;quot;,&amp;quot;viewer.preset.badge.signalFlow&amp;quot;:&amp;quot;信号流&amp;quot;,&amp;quot;viewer.preset.badge.blueprint&amp;quot;:&amp;quot;蓝图 / 修订 01&amp;quot;,&amp;quot;viewer.preset.badge.editorial&amp;quot;:&amp;quot;编辑风格 / 现场笔记&amp;quot;,&amp;quot;viewer.preset.badge.editorialPlate&amp;quot;:&amp;quot;ARCHIFY / 图版 04&amp;quot;,&amp;quot;viewer.preset.current&amp;quot;:&amp;quot;当前视觉风格：{style}。选择视觉风格&amp;quot;,&amp;quot;viewer.motion.live&amp;quot;:&amp;quot;动态&amp;quot;,&amp;quot;viewer.motion.still&amp;quot;:&amp;quot;静态&amp;quot;,&amp;quot;viewer.motion.pause&amp;quot;:&amp;quot;暂停动效&amp;quot;,&amp;quot;viewer.motion.resume&amp;quot;:&amp;quot;恢复动效&amp;quot;,&amp;quot;viewer.motion.reduced&amp;quot;:&amp;quot;已根据减少动态效果偏好暂停动效&amp;quot;,&amp;quot;viewer.motion.hidden&amp;quot;:&amp;quot;页面不可见时已暂停动效&amp;quot;,&amp;quot;viewer.motion.yielding&amp;quot;:&amp;quot;暂停动效；当前让位于{owner}&amp;quot;,&amp;quot;viewer.motion.yielding.title&amp;quot;:&amp;quot;动态预览已启用 · 正在让位于{owner}&amp;quot;,&amp;quot;viewer.owner.story&amp;quot;:&amp;quot;引导故事&amp;quot;,&amp;quot;viewer.owner.chapter&amp;quot;:&amp;quot;当前章节&amp;quot;,&amp;quot;viewer.owner.chapterPreview&amp;quot;:&amp;quot;章节差异预览&amp;quot;,&amp;quot;viewer.owner.handoff&amp;quot;:&amp;quot;章节交接&amp;quot;,&amp;quot;viewer.owner.route&amp;quot;:&amp;quot;路径探测&amp;quot;,&amp;quot;viewer.owner.lens&amp;quot;:&amp;quot;语义透镜&amp;quot;,&amp;quot;viewer.owner.relationship&amp;quot;:&amp;quot;关系预览&amp;quot;,&amp;quot;viewer.owner.intent&amp;quot;:&amp;quot;意图追踪&amp;quot;,&amp;quot;viewer.owner.focus&amp;quot;:&amp;quot;语义聚焦&amp;quot;,&amp;quot;viewer.owner.legend&amp;quot;:&amp;quot;图例预览&amp;quot;,&amp;quot;viewer.owner.reader&amp;quot;:&amp;quot;读者交互&amp;quot;,&amp;quot;viewer.present.enter&amp;quot;:&amp;quot;进入演示模式&amp;quot;,&amp;quot;viewer.present.enter.title&amp;quot;:&amp;quot;演示模式（F）&amp;quot;,&amp;quot;viewer.present.exit&amp;quot;:&amp;quot;退出演示模式&amp;quot;,&amp;quot;viewer.present.exit.title&amp;quot;:&amp;quot;退出演示模式（F 或 Escape）&amp;quot;,&amp;quot;viewer.present.present&amp;quot;:&amp;quot;演示&amp;quot;,&amp;quot;viewer.present.exit.label&amp;quot;:&amp;quot;退出&amp;quot;,&amp;quot;viewer.export.button&amp;quot;:&amp;quot;导出&amp;quot;,&amp;quot;viewer.export.button.title&amp;quot;:&amp;quot;导出图表（E）&amp;quot;,&amp;quot;viewer.export.diagram&amp;quot;:&amp;quot;导出图表&amp;quot;,&amp;quot;viewer.export.menu&amp;quot;:&amp;quot;导出&amp;quot;,&amp;quot;viewer.export.subtitle&amp;quot;:&amp;quot;便携、整洁的输出&amp;quot;,&amp;quot;viewer.export.share&amp;quot;:&amp;quot;分享&amp;quot;,&amp;quot;viewer.export.shareCard&amp;quot;:&amp;quot;分享卡片&amp;quot;,&amp;quot;viewer.export.routeShareCard&amp;quot;:&amp;quot;路径分享卡片&amp;quot;,&amp;quot;viewer.export.reachShareCard&amp;quot;:&amp;quot;可达范围分享卡片&amp;quot;,&amp;quot;viewer.export.copyShareCard&amp;quot;:&amp;quot;复制分享卡片&amp;quot;,&amp;quot;viewer.export.copyDiagram&amp;quot;:&amp;quot;复制图表&amp;quot;,&amp;quot;viewer.export.clipboardPng&amp;quot;:&amp;quot;复制 PNG 到剪贴板&amp;quot;,&amp;quot;viewer.export.raster&amp;quot;:&amp;quot;位图&amp;quot;,&amp;quot;viewer.export.image&amp;quot;:&amp;quot;图像&amp;quot;,&amp;quot;viewer.export.lossless&amp;quot;:&amp;quot;无损图像&amp;quot;,&amp;quot;viewer.export.compact&amp;quot;:&amp;quot;紧凑图像&amp;quot;,&amp;quot;viewer.export.modern&amp;quot;:&amp;quot;现代图像格式&amp;quot;,&amp;quot;viewer.export.vectorMotion&amp;quot;:&amp;quot;矢量与动效&amp;quot;,&amp;quot;viewer.export.vectorMotion.heading&amp;quot;:&amp;quot;矢量与动效&amp;quot;,&amp;quot;viewer.export.editable&amp;quot;:&amp;quot;可编辑矢量图&amp;quot;,&amp;quot;viewer.export.motion6s&amp;quot;:&amp;quot;6 秒动效&amp;quot;,&amp;quot;viewer.export.unsupported&amp;quot;:&amp;quot;当前浏览器不支持&amp;quot;,&amp;quot;viewer.export.clipboardUnsupported&amp;quot;:&amp;quot;当前浏览器不支持写入图片剪贴板&amp;quot;,&amp;quot;viewer.export.clipboardUnsupported.period&amp;quot;:&amp;quot;当前浏览器不支持写入图片剪贴板。&amp;quot;,&amp;quot;viewer.export.clipboardUnsupported.short&amp;quot;:&amp;quot;此浏览器不支持写入图片剪贴板。&amp;quot;,&amp;quot;viewer.export.motionUnavailable&amp;quot;:&amp;quot;当前浏览器无法录制动效&amp;quot;,&amp;quot;viewer.export.webmUnavailable&amp;quot;:&amp;quot;当前浏览器不支持 WebM&amp;quot;,&amp;quot;viewer.export.failed&amp;quot;:&amp;quot;导出失败：{message}&amp;quot;,&amp;quot;viewer.export.unknownVariant&amp;quot;:&amp;quot;未知的分享卡片类型：{variant}&amp;quot;,&amp;quot;viewer.export.routeRequired&amp;quot;:&amp;quot;请先追踪路径，再导出路径分享卡片&amp;quot;,&amp;quot;viewer.export.reachRequired&amp;quot;:&amp;quot;请先追踪编写可达范围，再导出可达范围分享卡片&amp;quot;,&amp;quot;viewer.export.unknown&amp;quot;:&amp;quot;未知错误&amp;quot;,&amp;quot;viewer.export.routeFailed&amp;quot;:&amp;quot;路径分享卡片导出失败：{message}&amp;quot;,&amp;quot;viewer.export.reachFailed&amp;quot;:&amp;quot;可达范围分享卡片导出失败：{message}&amp;quot;,&amp;quot;viewer.export.copyFailed&amp;quot;:&amp;quot;复制失败：{message}&amp;quot;,&amp;quot;viewer.export.copiedPng&amp;quot;:&amp;quot;已将 PNG 复制到剪贴板&amp;quot;,&amp;quot;viewer.export.copiedShare&amp;quot;:&amp;quot;已复制分享卡片&amp;quot;,&amp;quot;viewer.export.downloadedShare&amp;quot;:&amp;quot;已下载分享卡片&amp;quot;,&amp;quot;viewer.export.downloadedRoute&amp;quot;:&amp;quot;已下载路径分享卡片&amp;quot;,&amp;quot;viewer.export.downloadedReach&amp;quot;:&amp;quot;已下载可达范围分享卡片&amp;quot;,&amp;quot;viewer.export.downloadedWebm&amp;quot;:&amp;quot;已下载 WebM&amp;quot;,&amp;quot;viewer.export.recording&amp;quot;:&amp;quot;正在录制 6 秒动效…&amp;quot;,&amp;quot;viewer.export.card.routeSummary.one&amp;quot;:&amp;quot;路径：{source} → {target} · {count} 个有向跳转&amp;quot;,&amp;quot;viewer.export.card.routeSummary.other&amp;quot;:&amp;quot;路径：{source} → {target} · {count} 个有向跳转&amp;quot;,&amp;quot;viewer.export.card.reachSummary&amp;quot;:&amp;quot;从{origin}开始的编写{direction} · {nodes} · {links} · 最深 {hops}&amp;quot;,&amp;quot;viewer.export.card.node.one&amp;quot;:&amp;quot;{count} 个节点&amp;quot;,&amp;quot;viewer.export.card.node.other&amp;quot;:&amp;quot;{count} 个节点&amp;quot;,&amp;quot;viewer.export.card.link.one&amp;quot;:&amp;quot;{count} 条连接&amp;quot;,&amp;quot;viewer.export.card.link.other&amp;quot;:&amp;quot;{count} 条连接&amp;quot;,&amp;quot;viewer.export.card.hop.one&amp;quot;:&amp;quot;{count} 跳&amp;quot;,&amp;quot;viewer.export.card.hop.other&amp;quot;:&amp;quot;{count} 跳&amp;quot;,&amp;quot;viewer.export.card.routeBadge&amp;quot;:&amp;quot;ARCHIFY · 路径 · {hops}&amp;quot;,&amp;quot;viewer.export.card.reachBadge&amp;quot;:&amp;quot;ARCHIFY · {direction}可达范围&amp;quot;,&amp;quot;viewer.export.card.defaultBadge&amp;quot;:&amp;quot;ARCHIFY · {preset} · {theme}&amp;quot;,&amp;quot;viewer.export.direction.upstream&amp;quot;:&amp;quot;上游&amp;quot;,&amp;quot;viewer.export.direction.downstream&amp;quot;:&amp;quot;下游&amp;quot;,&amp;quot;viewer.export.error.canvasUnavailable&amp;quot;:&amp;quot;无法为{label}使用画布&amp;quot;,&amp;quot;viewer.export.error.contextUnavailable&amp;quot;:&amp;quot;无法为{label}创建二维画布上下文&amp;quot;,&amp;quot;viewer.export.error.toBlobUnavailable&amp;quot;:&amp;quot;{label}无法使用 canvas.toBlob&amp;quot;,&amp;quot;viewer.export.error.toBlobNull&amp;quot;:&amp;quot;{label}的 canvas.toBlob 未返回数据&amp;quot;,&amp;quot;viewer.export.error.variantsCombined&amp;quot;:&amp;quot;无法同时组合多种分享卡片类型&amp;quot;,&amp;quot;viewer.export.error.viewerState&amp;quot;:&amp;quot;分享卡片导出无法移除临时 Viewer 状态&amp;quot;,&amp;quot;viewer.export.error.routeState&amp;quot;:&amp;quot;路径卡片导出无法安全保留已解析路径&amp;quot;,&amp;quot;viewer.export.error.reachState&amp;quot;:&amp;quot;可达范围卡片导出无法安全保留编写的可达范围&amp;quot;,&amp;quot;viewer.export.error.webmRequirements&amp;quot;:&amp;quot;WebM 动效导出需要追踪动画及浏览器 MediaRecorder 支持&amp;quot;,&amp;quot;viewer.export.error.mediaRecorder&amp;quot;:&amp;quot;MediaRecorder 录制失败&amp;quot;,&amp;quot;viewer.export.error.emptyWebm&amp;quot;:&amp;quot;MediaRecorder 生成了空的 WebM&amp;quot;,&amp;quot;viewer.export.error.webmBackground&amp;quot;:&amp;quot;无法为 WebM 导出加载 SVG 背景&amp;quot;,&amp;quot;viewer.guided.region&amp;quot;:&amp;quot;图表引导视图&amp;quot;,&amp;quot;viewer.guided.previous&amp;quot;:&amp;quot;上一个引导视图&amp;quot;,&amp;quot;viewer.guided.previous.title&amp;quot;:&amp;quot;上一个引导视图（[）&amp;quot;,&amp;quot;viewer.guided.next&amp;quot;:&amp;quot;下一个引导视图&amp;quot;,&amp;quot;viewer.guided.next.title&amp;quot;:&amp;quot;下一个引导视图（]）&amp;quot;,&amp;quot;viewer.guided.views&amp;quot;:&amp;quot;引导视图&amp;quot;,&amp;quot;viewer.guided.explore&amp;quot;:&amp;quot;探索此系统&amp;quot;,&amp;quot;viewer.guided.intro&amp;quot;:&amp;quot;沿精选路径逐步查看，而不改变源图表。&amp;quot;,&amp;quot;viewer.guided.trail&amp;quot;:&amp;quot;故事轨迹&amp;quot;,&amp;quot;viewer.guided.beat&amp;quot;:&amp;quot;节点&amp;quot;,&amp;quot;viewer.guided.nextBeat&amp;quot;:&amp;quot;下一步&amp;quot;,&amp;quot;viewer.guided.play&amp;quot;:&amp;quot;播放引导故事&amp;quot;,&amp;quot;viewer.guided.play.title&amp;quot;:&amp;quot;播放引导故事（P）&amp;quot;,&amp;quot;viewer.guided.pause&amp;quot;:&amp;quot;暂停引导故事&amp;quot;,&amp;quot;viewer.guided.pause.title&amp;quot;:&amp;quot;暂停引导故事（P）&amp;quot;,&amp;quot;viewer.guided.replay&amp;quot;:&amp;quot;重播引导故事&amp;quot;,&amp;quot;viewer.guided.replay.title&amp;quot;:&amp;quot;重播引导故事（P）&amp;quot;,&amp;quot;viewer.guided.playStory&amp;quot;:&amp;quot;播放故事&amp;quot;,&amp;quot;viewer.guided.pauseStory&amp;quot;:&amp;quot;暂停&amp;quot;,&amp;quot;viewer.guided.replayStory&amp;quot;:&amp;quot;重播故事&amp;quot;,&amp;quot;viewer.guided.motionUnavailable&amp;quot;:&amp;quot;静态模式下无法播放故事&amp;quot;,&amp;quot;viewer.guided.enableMotion&amp;quot;:&amp;quot;切换为动态模式以播放引导故事&amp;quot;,&amp;quot;viewer.guided.selectBeatLink&amp;quot;:&amp;quot;选择故事节点以复制其精确链接&amp;quot;,&amp;quot;viewer.guided.copyMoment&amp;quot;:&amp;quot;复制此刻&amp;quot;,&amp;quot;viewer.guided.momentCopied&amp;quot;:&amp;quot;已复制时刻链接&amp;quot;,&amp;quot;viewer.guided.momentCopyFailed&amp;quot;:&amp;quot;无法复制故事时刻链接&amp;quot;,&amp;quot;viewer.guided.copied&amp;quot;:&amp;quot;已复制&amp;quot;,&amp;quot;viewer.guided.copyFailed&amp;quot;:&amp;quot;复制失败&amp;quot;,&amp;quot;viewer.guided.showAll&amp;quot;:&amp;quot;显示全部&amp;quot;,&amp;quot;viewer.guided.showAll.aria&amp;quot;:&amp;quot;显示完整图表&amp;quot;,&amp;quot;viewer.guided.chapters&amp;quot;:&amp;quot;故事章节&amp;quot;,&amp;quot;viewer.guided.storyTrail&amp;quot;:&amp;quot;{label}的故事轨迹：{count} 个节点&amp;quot;,&amp;quot;viewer.guided.chapter.open&amp;quot;:&amp;quot;打开第 {index}/{total} 章：{label}，{count} 个停靠点&amp;quot;,&amp;quot;viewer.guided.chapter.current&amp;quot;:&amp;quot;当前第 {index}/{total} 章：{label}，{count} 个停靠点&amp;quot;,&amp;quot;viewer.guided.chapter.selectedNodes&amp;quot;:&amp;quot;已选择 {count} 个节点&amp;quot;,&amp;quot;viewer.guided.chapter.stops&amp;quot;:&amp;quot;{count} 个停靠点&amp;quot;,&amp;quot;viewer.guided.chapter.stop.one&amp;quot;:&amp;quot;{count} 个停靠点&amp;quot;,&amp;quot;viewer.guided.chapter.stop.other&amp;quot;:&amp;quot;{count} 个停靠点&amp;quot;,&amp;quot;viewer.guided.chapter.current.title&amp;quot;:&amp;quot;{label} — 当前章节，{count} 个停靠点&amp;quot;,&amp;quot;viewer.guided.chapter.delta.expanded&amp;quot;:&amp;quot;{stay} 个保留，{enter} 个进入，{leave} 个离开&amp;quot;,&amp;quot;viewer.guided.chapter.delta.aria&amp;quot;:&amp;quot;打开第 {index}/{total} 章：{label}。章节聚焦差异：{delta}&amp;quot;,&amp;quot;viewer.guided.chapter.delta.title&amp;quot;:&amp;quot;{label} — 章节聚焦 {delta}&amp;quot;,&amp;quot;viewer.guided.handoff&amp;quot;:&amp;quot;{from} → {to} · 经由{label}&amp;quot;,&amp;quot;viewer.guided.share.chapter&amp;quot;:&amp;quot;章节 {index} / {total}&amp;quot;,&amp;quot;viewer.guided.share.initial&amp;quot;:&amp;quot;章节 01 / 01&amp;quot;,&amp;quot;viewer.guided.share.default&amp;quot;:&amp;quot;引导章节&amp;quot;,&amp;quot;viewer.guided.state.ready&amp;quot;:&amp;quot;就绪&amp;quot;,&amp;quot;viewer.guided.state.playing&amp;quot;:&amp;quot;播放中&amp;quot;,&amp;quot;viewer.guided.state.settled&amp;quot;:&amp;quot;已完成&amp;quot;,&amp;quot;viewer.guided.state.paused&amp;quot;:&amp;quot;已暂停&amp;quot;,&amp;quot;viewer.guided.state.pinned&amp;quot;:&amp;quot;已固定&amp;quot;,&amp;quot;viewer.guided.state.still&amp;quot;:&amp;quot;静态&amp;quot;,&amp;quot;viewer.guided.share.step&amp;quot;:&amp;quot;步骤 {index} / {total} · {label}&amp;quot;,&amp;quot;viewer.guided.share.staticMoment&amp;quot;:&amp;quot;{step} · 静态时刻&amp;quot;,&amp;quot;viewer.guided.share.complete&amp;quot;:&amp;quot;{count} 个步骤已完成 · {note}&amp;quot;,&amp;quot;viewer.guided.share.settled&amp;quot;:&amp;quot;路径已稳定，可供阅读。&amp;quot;,&amp;quot;viewer.guided.share.staticPath&amp;quot;:&amp;quot;{count} 个步骤 · 静态路径&amp;quot;,&amp;quot;viewer.guided.share.ready&amp;quot;:&amp;quot;{count} 个步骤 · 就绪&amp;quot;,&amp;quot;viewer.guided.share.aria&amp;quot;:&amp;quot;{state}，第 {index}/{total} 章：{label}。{beat}。{route}&amp;quot;,&amp;quot;viewer.guided.beat.start&amp;quot;:&amp;quot;节点 {index} / {total} · {label} · 起点&amp;quot;,&amp;quot;viewer.guided.beat.forward&amp;quot;:&amp;quot;节点 {index} / {total} · {from} → {to}&amp;quot;,&amp;quot;viewer.guided.beat.reverse&amp;quot;:&amp;quot;节点 {index} / {total} · {from} → {to} · 反向编写连接&amp;quot;,&amp;quot;viewer.guided.beat.multiple&amp;quot;:&amp;quot;节点 {index} / {total} · {from} ⇄ {to} · {count} 条编写连接&amp;quot;,&amp;quot;viewer.guided.beat.group&amp;quot;:&amp;quot;节点 {index} / {total} · {from} · {to} · 分组 · 无直接连接&amp;quot;,&amp;quot;viewer.guided.beat.aria.prefix&amp;quot;:&amp;quot;故事节点 {index}/{total}：{label}。&amp;quot;,&amp;quot;viewer.guided.beat.aria.start&amp;quot;:&amp;quot;起点。&amp;quot;,&amp;quot;viewer.guided.beat.aria.forward&amp;quot;:&amp;quot;从{from}经一条正向编写关系到达。&amp;quot;,&amp;quot;viewer.guided.beat.aria.reverse&amp;quot;:&amp;quot;从{from}出发；编写关系实际由{to}指向{from}。&amp;quot;,&amp;quot;viewer.guided.beat.aria.multiple&amp;quot;:&amp;quot;从{from}经 {count} 条编写关系到达；不使用任意动效。&amp;quot;,&amp;quot;viewer.guided.beat.aria.group&amp;quot;:&amp;quot;与{from}分组展示，没有直接编写关系。&amp;quot;,&amp;quot;viewer.guided.caption.start&amp;quot;:&amp;quot;起点&amp;quot;,&amp;quot;viewer.guided.caption.grouped&amp;quot;:&amp;quot;分组过渡 · 无直接编写连接&amp;quot;,&amp;quot;viewer.guided.caption.more&amp;quot;:&amp;quot; +另外 {count} 条&amp;quot;,&amp;quot;viewer.guided.caption.reverse&amp;quot;:&amp;quot;反向编写关系&amp;quot;,&amp;quot;viewer.guided.caption.relationships&amp;quot;:&amp;quot;{count} 条编写关系&amp;quot;,&amp;quot;viewer.guided.caption.relationship&amp;quot;:&amp;quot;编写关系&amp;quot;,&amp;quot;viewer.guided.caption.direction&amp;quot;:&amp;quot;编写方向：{from} → {to}&amp;quot;,&amp;quot;viewer.guided.caption.starting&amp;quot;:&amp;quot;编写起点&amp;quot;,&amp;quot;viewer.guided.beatLink&amp;quot;:&amp;quot;复制当前故事时刻链接：第 {index}/{total} 个节点：{label}&amp;quot;,&amp;quot;viewer.guided.noStory&amp;quot;:&amp;quot;此图表没有编写引导故事。&amp;quot;,&amp;quot;viewer.guide.eyebrow&amp;quot;:&amp;quot;图表指南&amp;quot;,&amp;quot;viewer.guide.close&amp;quot;:&amp;quot;关闭图表指南&amp;quot;,&amp;quot;viewer.guide.inspecting&amp;quot;:&amp;quot;正在检查已编译语义&amp;quot;,&amp;quot;viewer.guide.actions&amp;quot;:&amp;quot;图表探索操作&amp;quot;,&amp;quot;viewer.guide.find&amp;quot;:&amp;quot;查找任意节点&amp;quot;,&amp;quot;viewer.guide.find.hint&amp;quot;:&amp;quot;搜索标签、职责、类型和稳定 ID。&amp;quot;,&amp;quot;viewer.guide.route&amp;quot;:&amp;quot;追踪路径&amp;quot;,&amp;quot;viewer.guide.route.aria&amp;quot;:&amp;quot;追踪有向路径&amp;quot;,&amp;quot;viewer.guide.route.hint&amp;quot;:&amp;quot;查看两个语义节点如何按编写方向连接。&amp;quot;,&amp;quot;viewer.guide.map&amp;quot;:&amp;quot;查看完整系统&amp;quot;,&amp;quot;viewer.guide.map.hint&amp;quot;:&amp;quot;打开带实时视口和稳定节点的语义雷达。&amp;quot;,&amp;quot;viewer.guide.lens&amp;quot;:&amp;quot;比较语义类型&amp;quot;,&amp;quot;viewer.guide.lens.hint&amp;quot;:&amp;quot;统计角色、显示流量并比较直接编写的连接。&amp;quot;,&amp;quot;viewer.guide.story&amp;quot;:&amp;quot;播放引导故事&amp;quot;,&amp;quot;viewer.guide.story.hint&amp;quot;:&amp;quot;浏览已编写的章节和真实关系。&amp;quot;,&amp;quot;viewer.guide.present&amp;quot;:&amp;quot;进入演示模式&amp;quot;,&amp;quot;viewer.guide.present.hint&amp;quot;:&amp;quot;让实时图表占满视口，同时不改变导出。&amp;quot;,&amp;quot;viewer.guide.shortcuts&amp;quot;:&amp;quot;其他键盘快捷键&amp;quot;,&amp;quot;viewer.guide.shortcut.export&amp;quot;:&amp;quot;导出&amp;quot;,&amp;quot;viewer.guide.shortcut.theme&amp;quot;:&amp;quot;主题&amp;quot;,&amp;quot;viewer.guide.shortcut.style&amp;quot;:&amp;quot;风格&amp;quot;,&amp;quot;viewer.guide.shortcut.reset&amp;quot;:&amp;quot;重置&amp;quot;,&amp;quot;viewer.guide.shortcut.zoomIn&amp;quot;:&amp;quot;放大&amp;quot;,&amp;quot;viewer.guide.shortcut.zoomOut&amp;quot;:&amp;quot;缩小&amp;quot;,&amp;quot;viewer.guide.shortcut.close&amp;quot;:&amp;quot;关闭&amp;quot;,&amp;quot;viewer.guide.facts&amp;quot;:&amp;quot;{nodes} · {relationships} · {views}&amp;quot;,&amp;quot;viewer.guide.fact.node.one&amp;quot;:&amp;quot;{count} 个语义节点&amp;quot;,&amp;quot;viewer.guide.fact.node.other&amp;quot;:&amp;quot;{count} 个语义节点&amp;quot;,&amp;quot;viewer.guide.fact.relationship.one&amp;quot;:&amp;quot;{count} 条关系&amp;quot;,&amp;quot;viewer.guide.fact.relationship.other&amp;quot;:&amp;quot;{count} 条关系&amp;quot;,&amp;quot;viewer.guide.fact.view.one&amp;quot;:&amp;quot;{count} 个引导视图&amp;quot;,&amp;quot;viewer.guide.fact.view.other&amp;quot;:&amp;quot;{count} 个引导视图&amp;quot;,&amp;quot;viewer.guide.story.available.one&amp;quot;:&amp;quot;浏览 {count} 个已编写章节及其真实关系。&amp;quot;,&amp;quot;viewer.guide.story.available.other&amp;quot;:&amp;quot;浏览 {count} 个已编写章节及其真实关系。&amp;quot;,&amp;quot;viewer.guide.story.unavailable&amp;quot;:&amp;quot;此图表没有编写引导故事。&amp;quot;,&amp;quot;viewer.guide.open&amp;quot;:&amp;quot;打开图表指南&amp;quot;,&amp;quot;viewer.guide.noStory&amp;quot;:&amp;quot;此图表没有编写引导故事。&amp;quot;,&amp;quot;viewer.finder.title&amp;quot;:&amp;quot;查找节点&amp;quot;,&amp;quot;viewer.finder.close&amp;quot;:&amp;quot;关闭节点查找器&amp;quot;,&amp;quot;viewer.finder.placeholder&amp;quot;:&amp;quot;搜索标签或 ID&amp;quot;,&amp;quot;viewer.finder.search&amp;quot;:&amp;quot;搜索图表节点&amp;quot;,&amp;quot;viewer.finder.results&amp;quot;:&amp;quot;图表节点&amp;quot;,&amp;quot;viewer.finder.empty&amp;quot;:&amp;quot;没有匹配的节点&amp;quot;,&amp;quot;viewer.finder.result.focus&amp;quot;:&amp;quot;聚焦{label}&amp;quot;,&amp;quot;viewer.finder.result.routeStart&amp;quot;:&amp;quot;选择{label}作为路径起点&amp;quot;,&amp;quot;viewer.finder.result.routeTarget&amp;quot;:&amp;quot;选择{label}作为路径终点，{links}&amp;quot;,&amp;quot;viewer.finder.status.empty&amp;quot;:&amp;quot;没有匹配的节点&amp;quot;,&amp;quot;viewer.finder.status.count.one&amp;quot;:&amp;quot;{count} 个匹配节点&amp;quot;,&amp;quot;viewer.finder.status.count.other&amp;quot;:&amp;quot;{count} 个匹配节点&amp;quot;,&amp;quot;viewer.finder.noun.nodes&amp;quot;:&amp;quot;个节点&amp;quot;,&amp;quot;viewer.finder.link.one&amp;quot;:&amp;quot;{count} 条连接&amp;quot;,&amp;quot;viewer.finder.link.other&amp;quot;:&amp;quot;{count} 条连接&amp;quot;,&amp;quot;viewer.finder.result.focus.one&amp;quot;:&amp;quot;聚焦{label}，{count} 条相关连接&amp;quot;,&amp;quot;viewer.finder.result.focus.other&amp;quot;:&amp;quot;聚焦{label}，{count} 条相关连接&amp;quot;,&amp;quot;viewer.finder.status.filtered&amp;quot;:&amp;quot;{visible}/{available} {noun}&amp;quot;,&amp;quot;viewer.finder.status.all&amp;quot;:&amp;quot;{available} {noun}&amp;quot;,&amp;quot;viewer.passport.eyebrow&amp;quot;:&amp;quot;语义护照&amp;quot;,&amp;quot;viewer.passport.metadata&amp;quot;:&amp;quot;节点元数据&amp;quot;,&amp;quot;viewer.passport.evidence&amp;quot;:&amp;quot;已验证的源代码证据&amp;quot;,&amp;quot;viewer.passport.verified&amp;quot;:&amp;quot;已验证来源&amp;quot;,&amp;quot;viewer.passport.verificationScope&amp;quot;:&amp;quot;已按固定修订版本验证本地 Git 证据，未检查远程访问权限。&amp;quot;,&amp;quot;viewer.passport.reach&amp;quot;:&amp;quot;编写可达范围&amp;quot;,&amp;quot;viewer.passport.reach.trace&amp;quot;:&amp;quot;追踪编写的可达性&amp;quot;,&amp;quot;viewer.passport.upstream&amp;quot;:&amp;quot;上游&amp;quot;,&amp;quot;viewer.passport.downstream&amp;quot;:&amp;quot;下游&amp;quot;,&amp;quot;viewer.passport.upstream.trace&amp;quot;:&amp;quot;追踪上游编写可达性&amp;quot;,&amp;quot;viewer.passport.downstream.trace&amp;quot;:&amp;quot;追踪下游编写可达性&amp;quot;,&amp;quot;viewer.passport.close&amp;quot;:&amp;quot;关闭语义护照&amp;quot;,&amp;quot;viewer.passport.copy&amp;quot;:&amp;quot;复制链接&amp;quot;,&amp;quot;viewer.passport.copy.focus&amp;quot;:&amp;quot;复制聚焦节点的链接&amp;quot;,&amp;quot;viewer.passport.relations&amp;quot;:&amp;quot;关系&amp;quot;,&amp;quot;viewer.passport.relations.show&amp;quot;:&amp;quot;显示关联关系&amp;quot;,&amp;quot;viewer.passport.relations.hide&amp;quot;:&amp;quot;隐藏关联关系&amp;quot;,&amp;quot;viewer.passport.relations.list&amp;quot;:&amp;quot;关联关系&amp;quot;,&amp;quot;viewer.passport.copyRelation&amp;quot;:&amp;quot;复制关系&amp;quot;,&amp;quot;viewer.passport.copyNode&amp;quot;:&amp;quot;复制节点&amp;quot;,&amp;quot;viewer.passport.copyPinned&amp;quot;:&amp;quot;复制固定关系的链接&amp;quot;,&amp;quot;viewer.passport.copySource&amp;quot;:&amp;quot;复制来源节点的链接&amp;quot;,&amp;quot;viewer.passport.copy.focused.success&amp;quot;:&amp;quot;已复制聚焦节点链接&amp;quot;,&amp;quot;viewer.passport.copy.pinned.success&amp;quot;:&amp;quot;已复制固定关系链接&amp;quot;,&amp;quot;viewer.passport.copy.focused.failed&amp;quot;:&amp;quot;无法复制聚焦节点链接&amp;quot;,&amp;quot;viewer.passport.copy.pinned.failed&amp;quot;:&amp;quot;无法复制固定关系链接&amp;quot;,&amp;quot;viewer.passport.relationship.none&amp;quot;:&amp;quot;没有关联关系&amp;quot;,&amp;quot;viewer.passport.relationship.count.one&amp;quot;:&amp;quot;{count} 条关系&amp;quot;,&amp;quot;viewer.passport.relationship.count.other&amp;quot;:&amp;quot;{count} 条关系&amp;quot;,&amp;quot;viewer.passport.relationship.show.one&amp;quot;:&amp;quot;显示 {count} 条关联关系&amp;quot;,&amp;quot;viewer.passport.relationship.show.other&amp;quot;:&amp;quot;显示 {count} 条关联关系&amp;quot;,&amp;quot;viewer.passport.relationship.summary&amp;quot;:&amp;quot;{out} 条出向 · {in} 条入向{loops}&amp;quot;,&amp;quot;viewer.passport.relationship.loops&amp;quot;:&amp;quot; · {count} 条自环&amp;quot;,&amp;quot;viewer.passport.relationship.explorer&amp;quot;:&amp;quot;直接关系浏览器&amp;quot;,&amp;quot;viewer.passport.relationship.help&amp;quot;:&amp;quot;使用方向键浏览关系。按 Enter 或空格键固定详情；按 Escape 清除。&amp;quot;,&amp;quot;viewer.passport.relationship.loopsBack&amp;quot;:&amp;quot;回环&amp;quot;,&amp;quot;viewer.passport.relationship.connectsTo&amp;quot;:&amp;quot;连接到&amp;quot;,&amp;quot;viewer.passport.relationship.connectsFrom&amp;quot;:&amp;quot;连接自&amp;quot;,&amp;quot;viewer.passport.relationship.pinned&amp;quot;:&amp;quot;已固定关系 · {from} → {to} · {label}&amp;quot;,&amp;quot;viewer.passport.relationship.inspect&amp;quot;:&amp;quot;检查第 {index}/{total} 条关系：{from} 到 {to}，{label}。按 Enter 查看详情。&amp;quot;,&amp;quot;viewer.passport.relationship.group.out&amp;quot;:&amp;quot;出向&amp;quot;,&amp;quot;viewer.passport.relationship.group.in&amp;quot;:&amp;quot;入向&amp;quot;,&amp;quot;viewer.passport.relationship.group.loop&amp;quot;:&amp;quot;自环&amp;quot;,&amp;quot;viewer.passport.relationship.row&amp;quot;:&amp;quot;{group}：{relationship}，{neighbor}&amp;quot;,&amp;quot;viewer.passport.relationship.direction.out&amp;quot;:&amp;quot;出 →&amp;quot;,&amp;quot;viewer.passport.relationship.direction.in&amp;quot;:&amp;quot;← 入&amp;quot;,&amp;quot;viewer.passport.relationship.direction.loop&amp;quot;:&amp;quot;自环&amp;quot;,&amp;quot;viewer.passport.sourceCount.one&amp;quot;:&amp;quot;{count} 个已验证来源引用&amp;quot;,&amp;quot;viewer.passport.sourceCount.other&amp;quot;:&amp;quot;{count} 个已验证来源引用&amp;quot;,&amp;quot;viewer.passport.sourceMarker&amp;quot;:&amp;quot;来源&amp;quot;,&amp;quot;viewer.passport.beacon.one&amp;quot;:&amp;quot;{count} 个已验证来源；聚焦此节点以检查&amp;quot;,&amp;quot;viewer.passport.beacon.other&amp;quot;:&amp;quot;{count} 个已验证来源；聚焦此节点以检查&amp;quot;,&amp;quot;viewer.passport.repository.open&amp;quot;:&amp;quot;打开已验证的仓库修订版本 {revision}&amp;quot;,&amp;quot;viewer.passport.source.open&amp;quot;:&amp;quot;打开修订版本 {revision} 中已验证的来源 {path}&amp;quot;,&amp;quot;viewer.passport.source.openLink&amp;quot;:&amp;quot;打开 ↗&amp;quot;,&amp;quot;viewer.passport.reach.upstream.one&amp;quot;:&amp;quot;追踪 {count} 个上游编写节点&amp;quot;,&amp;quot;viewer.passport.reach.upstream.other&amp;quot;:&amp;quot;追踪 {count} 个上游编写节点&amp;quot;,&amp;quot;viewer.passport.reach.downstream.one&amp;quot;:&amp;quot;追踪 {count} 个下游编写节点&amp;quot;,&amp;quot;viewer.passport.reach.downstream.other&amp;quot;:&amp;quot;追踪 {count} 个下游编写节点&amp;quot;,&amp;quot;viewer.passport.reach.noUpstream&amp;quot;:&amp;quot;没有上游编写节点&amp;quot;,&amp;quot;viewer.passport.reach.noDownstream&amp;quot;:&amp;quot;没有下游编写节点&amp;quot;,&amp;quot;viewer.passport.reach.status&amp;quot;:&amp;quot;{direction} · {nodes} 个节点 · {links} 条连接 · 最深 {hops} 跳&amp;quot;,&amp;quot;viewer.route.eyebrow&amp;quot;:&amp;quot;路径探测&amp;quot;,&amp;quot;viewer.route.start&amp;quot;:&amp;quot;选择起点节点&amp;quot;,&amp;quot;viewer.route.start.find&amp;quot;:&amp;quot;查找起点&amp;quot;,&amp;quot;viewer.route.start.find.aria&amp;quot;:&amp;quot;查找路径起点&amp;quot;,&amp;quot;viewer.route.copy&amp;quot;:&amp;quot;复制链接&amp;quot;,&amp;quot;viewer.route.copy.aria&amp;quot;:&amp;quot;复制已追踪路径的链接&amp;quot;,&amp;quot;viewer.route.clear&amp;quot;:&amp;quot;清除&amp;quot;,&amp;quot;viewer.route.clear.aria&amp;quot;:&amp;quot;清除路径探测&amp;quot;,&amp;quot;viewer.route.traced&amp;quot;:&amp;quot;已追踪路径&amp;quot;,&amp;quot;viewer.route.pickTwo&amp;quot;:&amp;quot;在图表中选择两个语义节点&amp;quot;,&amp;quot;viewer.route.pickOne&amp;quot;:&amp;quot;在图表中选择一个语义节点&amp;quot;,&amp;quot;viewer.route.controls&amp;quot;:&amp;quot;路径旅程控制&amp;quot;,&amp;quot;viewer.route.previous&amp;quot;:&amp;quot;上一个路径位置&amp;quot;,&amp;quot;viewer.route.play&amp;quot;:&amp;quot;播放路径旅程&amp;quot;,&amp;quot;viewer.route.pause&amp;quot;:&amp;quot;暂停路径旅程&amp;quot;,&amp;quot;viewer.route.replay&amp;quot;:&amp;quot;重播路径旅程&amp;quot;,&amp;quot;viewer.route.next&amp;quot;:&amp;quot;下一个路径位置&amp;quot;,&amp;quot;viewer.route.journey&amp;quot;:&amp;quot;旅程&amp;quot;,&amp;quot;viewer.route.pause.label&amp;quot;:&amp;quot;暂停&amp;quot;,&amp;quot;viewer.route.replay.label&amp;quot;:&amp;quot;重播&amp;quot;,&amp;quot;viewer.route.overview&amp;quot;:&amp;quot;总览&amp;quot;,&amp;quot;viewer.route.overview.aria&amp;quot;:&amp;quot;显示完整路径总览&amp;quot;,&amp;quot;viewer.route.instructions&amp;quot;:&amp;quot;先选择来源，再选择目标；方向很重要。&amp;quot;,&amp;quot;viewer.route.destination&amp;quot;:&amp;quot;选择从{label}出发的目标&amp;quot;,&amp;quot;viewer.route.destination.find&amp;quot;:&amp;quot;查找目标&amp;quot;,&amp;quot;viewer.route.destination.find.aria&amp;quot;:&amp;quot;查找可达的路径目标&amp;quot;,&amp;quot;viewer.route.differentDestination&amp;quot;:&amp;quot;选择其他目标&amp;quot;,&amp;quot;viewer.route.distinct&amp;quot;:&amp;quot;一条路径需要两个不同的语义节点。&amp;quot;,&amp;quot;viewer.route.unreachable&amp;quot;:&amp;quot;没有通往{label}的有向路径&amp;quot;,&amp;quot;viewer.route.unreachable.detail&amp;quot;:&amp;quot;从{source}无法到达{target}。请选择高亮的目标。&amp;quot;,&amp;quot;viewer.route.start.instructions&amp;quot;:&amp;quot;选择来源。下一步只会显示有向可达的目标。&amp;quot;,&amp;quot;viewer.route.copy.success&amp;quot;:&amp;quot;已复制路径链接&amp;quot;,&amp;quot;viewer.route.copy.failed&amp;quot;:&amp;quot;无法复制路径链接&amp;quot;,&amp;quot;viewer.route.position&amp;quot;:&amp;quot;路径位置 {index}/{total}：{label}&amp;quot;,&amp;quot;viewer.route.step&amp;quot;:&amp;quot;第 {index}/{total} 步 · {phase} · {label}&amp;quot;,&amp;quot;viewer.route.motionRequired&amp;quot;:&amp;quot;自动旅程需要动态模式&amp;quot;,&amp;quot;viewer.route.trigger.clear&amp;quot;:&amp;quot;清除已追踪路径&amp;quot;,&amp;quot;viewer.route.overview.status&amp;quot;:&amp;quot;{nodes} · {hops} · 最短编写路径&amp;quot;,&amp;quot;viewer.route.overview.node.one&amp;quot;:&amp;quot;{count} 个节点&amp;quot;,&amp;quot;viewer.route.overview.node.other&amp;quot;:&amp;quot;{count} 个节点&amp;quot;,&amp;quot;viewer.route.overview.hop.one&amp;quot;:&amp;quot;{count} 个有向跳转&amp;quot;,&amp;quot;viewer.route.overview.hop.other&amp;quot;:&amp;quot;{count} 个有向跳转&amp;quot;,&amp;quot;viewer.route.phase.playing&amp;quot;:&amp;quot;播放中&amp;quot;,&amp;quot;viewer.route.phase.complete&amp;quot;:&amp;quot;已完成&amp;quot;,&amp;quot;viewer.route.phase.inspecting&amp;quot;:&amp;quot;检查中&amp;quot;,&amp;quot;viewer.route.destination.count.one&amp;quot;:&amp;quot;有 {count} 个有向目标可用。请选择高亮节点。&amp;quot;,&amp;quot;viewer.route.destination.count.other&amp;quot;:&amp;quot;有 {count} 个有向目标可用。请选择高亮节点。&amp;quot;,&amp;quot;viewer.route.noOutgoing&amp;quot;:&amp;quot;此处没有可用的出向路径。请清除后选择其他来源。&amp;quot;,&amp;quot;viewer.route.result.title&amp;quot;:&amp;quot;{source} 到 {target}&amp;quot;,&amp;quot;viewer.route.finder.source.title&amp;quot;:&amp;quot;选择路径起点&amp;quot;,&amp;quot;viewer.route.finder.source.placeholder&amp;quot;:&amp;quot;搜索路径来源&amp;quot;,&amp;quot;viewer.route.finder.source.empty&amp;quot;:&amp;quot;没有匹配的路径来源&amp;quot;,&amp;quot;viewer.route.finder.source.results&amp;quot;:&amp;quot;可作为路径起点的节点&amp;quot;,&amp;quot;viewer.route.finder.source.noun&amp;quot;:&amp;quot;个路径来源&amp;quot;,&amp;quot;viewer.route.finder.source.badge&amp;quot;:&amp;quot;起点&amp;quot;,&amp;quot;viewer.route.finder.target.title&amp;quot;:&amp;quot;从{label}出发的目标&amp;quot;,&amp;quot;viewer.route.finder.target.placeholder&amp;quot;:&amp;quot;搜索可达目标&amp;quot;,&amp;quot;viewer.route.finder.target.empty&amp;quot;:&amp;quot;没有匹配的可达目标&amp;quot;,&amp;quot;viewer.route.finder.target.results&amp;quot;:&amp;quot;可达路径目标&amp;quot;,&amp;quot;viewer.route.finder.target.noun&amp;quot;:&amp;quot;个可达目标&amp;quot;,&amp;quot;viewer.route.hop.one&amp;quot;:&amp;quot;{count} 跳&amp;quot;,&amp;quot;viewer.route.hop.other&amp;quot;:&amp;quot;{count} 跳&amp;quot;,&amp;quot;viewer.lens.eyebrow&amp;quot;:&amp;quot;语义透镜&amp;quot;,&amp;quot;viewer.lens.title&amp;quot;:&amp;quot;比较系统角色&amp;quot;,&amp;quot;viewer.lens.close&amp;quot;:&amp;quot;关闭语义透镜&amp;quot;,&amp;quot;viewer.lens.instruction&amp;quot;:&amp;quot;最多选择两种语义类型。选择一种可显示其真实流量；选择两种只比较直接编写的关系。&amp;quot;,&amp;quot;viewer.lens.kinds&amp;quot;:&amp;quot;语义类型&amp;quot;,&amp;quot;viewer.lens.choose&amp;quot;:&amp;quot;选择一种类型以检查其节点和相连关系。&amp;quot;,&amp;quot;viewer.lens.copy&amp;quot;:&amp;quot;复制语义透镜链接&amp;quot;,&amp;quot;viewer.lens.clear&amp;quot;:&amp;quot;清除语义透镜&amp;quot;,&amp;quot;viewer.lens.open&amp;quot;:&amp;quot;打开语义透镜&amp;quot;,&amp;quot;viewer.lens.openActive&amp;quot;:&amp;quot;打开当前语义透镜&amp;quot;,&amp;quot;viewer.lens.legend&amp;quot;:&amp;quot;语义图例&amp;quot;,&amp;quot;viewer.lens.legend.inspect.one&amp;quot;:&amp;quot;检查{label}，{count} 个节点&amp;quot;,&amp;quot;viewer.lens.legend.inspect.other&amp;quot;:&amp;quot;检查{label}，{count} 个节点&amp;quot;,&amp;quot;viewer.lens.kind.count.one&amp;quot;:&amp;quot;{label}，{count} 个节点&amp;quot;,&amp;quot;viewer.lens.kind.count.other&amp;quot;:&amp;quot;{label}，{count} 个节点&amp;quot;,&amp;quot;viewer.lens.compare.one&amp;quot;:&amp;quot;{first} → {second}：{forward} · {second} → {first}：{reverse} · 共 {count} 条直接关系&amp;quot;,&amp;quot;viewer.lens.compare.other&amp;quot;:&amp;quot;{first} → {second}：{forward} · {second} → {first}：{reverse} · 共 {count} 条直接关系&amp;quot;,&amp;quot;viewer.lens.single&amp;quot;:&amp;quot;{nodes} · {relationships} · 已连接节点保持可见&amp;quot;,&amp;quot;viewer.lens.node.one&amp;quot;:&amp;quot;{count} 个{label}节点&amp;quot;,&amp;quot;viewer.lens.node.other&amp;quot;:&amp;quot;{count} 个{label}节点&amp;quot;,&amp;quot;viewer.lens.relationship.one&amp;quot;:&amp;quot;{count} 条相连关系&amp;quot;,&amp;quot;viewer.lens.relationship.other&amp;quot;:&amp;quot;{count} 条相连关系&amp;quot;,&amp;quot;viewer.radar.title&amp;quot;:&amp;quot;语义雷达&amp;quot;,&amp;quot;viewer.radar.building&amp;quot;:&amp;quot;正在构建总览&amp;quot;,&amp;quot;viewer.radar.openFull&amp;quot;:&amp;quot;打开完整语义雷达&amp;quot;,&amp;quot;viewer.radar.open&amp;quot;:&amp;quot;打开雷达&amp;quot;,&amp;quot;viewer.radar.close&amp;quot;:&amp;quot;关闭语义雷达&amp;quot;,&amp;quot;viewer.radar.surface&amp;quot;:&amp;quot;图表总览。点击节点进行聚焦，或使用方向键平移。&amp;quot;,&amp;quot;viewer.radar.click&amp;quot;:&amp;quot;点击节点&amp;quot;,&amp;quot;viewer.radar.drag&amp;quot;:&amp;quot;拖动平移&amp;quot;,&amp;quot;viewer.radar.space&amp;quot;:&amp;quot;语义雷达需要更多地图可见空间。&amp;quot;,&amp;quot;viewer.radar.nodes&amp;quot;:&amp;quot;语义图表雷达节点&amp;quot;,&amp;quot;viewer.radar.focus&amp;quot;:&amp;quot;从语义雷达聚焦{label}&amp;quot;,&amp;quot;viewer.radar.status&amp;quot;:&amp;quot;{count} 个节点 · {viewport}&amp;quot;,&amp;quot;viewer.radar.fullMap&amp;quot;:&amp;quot;{count} 个节点 · 完整地图&amp;quot;,&amp;quot;viewer.radar.compacted&amp;quot;:&amp;quot;已收紧雷达，避免遮挡语义护照或地图控件。&amp;quot;,&amp;quot;viewer.radar.cancelWaiting&amp;quot;:&amp;quot;取消等待更多地图空间的语义雷达&amp;quot;,&amp;quot;viewer.radar.needsSpace&amp;quot;:&amp;quot;语义雷达需要更多可见地图空间&amp;quot;,&amp;quot;viewer.radar.viewport.full&amp;quot;:&amp;quot;完整地图&amp;quot;,&amp;quot;viewer.radar.viewport.width&amp;quot;:&amp;quot;宽度 {percent}%&amp;quot;,&amp;quot;viewer.radar.viewport.scale&amp;quot;:&amp;quot;视口 {percent}%&amp;quot;,&amp;quot;viewer.nav.controls&amp;quot;:&amp;quot;图表视图控制&amp;quot;,&amp;quot;viewer.nav.route&amp;quot;:&amp;quot;追踪有向路径&amp;quot;,&amp;quot;viewer.nav.route.title&amp;quot;:&amp;quot;追踪路径（R）&amp;quot;,&amp;quot;viewer.nav.route.short&amp;quot;:&amp;quot;路径&amp;quot;,&amp;quot;viewer.nav.radar&amp;quot;:&amp;quot;打开语义雷达&amp;quot;,&amp;quot;viewer.nav.radar.title&amp;quot;:&amp;quot;语义雷达（M）&amp;quot;,&amp;quot;viewer.nav.radar.short&amp;quot;:&amp;quot;地图&amp;quot;,&amp;quot;viewer.nav.lens&amp;quot;:&amp;quot;打开语义透镜&amp;quot;,&amp;quot;viewer.nav.lens.title&amp;quot;:&amp;quot;语义透镜（L）&amp;quot;,&amp;quot;viewer.nav.lens.short&amp;quot;:&amp;quot;透镜&amp;quot;,&amp;quot;viewer.nav.find&amp;quot;:&amp;quot;查找节点&amp;quot;,&amp;quot;viewer.nav.find.title&amp;quot;:&amp;quot;查找节点（/）&amp;quot;,&amp;quot;viewer.nav.guide&amp;quot;:&amp;quot;打开图表指南&amp;quot;,&amp;quot;viewer.nav.guide.title&amp;quot;:&amp;quot;图表指南（?）&amp;quot;,&amp;quot;viewer.nav.zoomOut&amp;quot;:&amp;quot;缩小&amp;quot;,&amp;quot;viewer.nav.zoomOut.title&amp;quot;:&amp;quot;缩小（-）&amp;quot;,&amp;quot;viewer.nav.reset&amp;quot;:&amp;quot;重置图表视图&amp;quot;,&amp;quot;viewer.nav.reset.title&amp;quot;:&amp;quot;重置视图（0）&amp;quot;,&amp;quot;viewer.nav.read&amp;quot;:&amp;quot;阅读&amp;quot;,&amp;quot;viewer.nav.zoomIn&amp;quot;:&amp;quot;放大&amp;quot;,&amp;quot;viewer.nav.zoomIn.title&amp;quot;:&amp;quot;放大（+）&amp;quot;,&amp;quot;viewer.nav.camera&amp;quot;:&amp;quot;{hint}。重置图表视图&amp;quot;,&amp;quot;viewer.nav.camera.title&amp;quot;:&amp;quot;{semantic}{hint} · 重置视图（0）&amp;quot;,&amp;quot;viewer.nav.camera.semantic&amp;quot;:&amp;quot;语义相机已启用 · &amp;quot;,&amp;quot;viewer.nav.level.map&amp;quot;:&amp;quot;概览&amp;quot;,&amp;quot;viewer.nav.level.read&amp;quot;:&amp;quot;阅读&amp;quot;,&amp;quot;viewer.nav.level.full&amp;quot;:&amp;quot;完整&amp;quot;,&amp;quot;viewer.nav.level.auto&amp;quot;:&amp;quot;自动&amp;quot;,&amp;quot;viewer.nav.detail.map&amp;quot;:&amp;quot;放大以显示关系标签和节点上下文&amp;quot;,&amp;quot;viewer.nav.detail.read&amp;quot;:&amp;quot;再次放大以显示标签和注释&amp;quot;,&amp;quot;viewer.nav.detail.full&amp;quot;:&amp;quot;完整图表详情&amp;quot;,&amp;quot;viewer.intent.summary&amp;quot;:&amp;quot;{label}。{out} 条出向，{in} 条入向{loops}。共 {total} 条连接。按 Enter 查看详情。&amp;quot;,&amp;quot;viewer.intent.loops&amp;quot;:&amp;quot;，{count} 条自环&amp;quot;,&amp;quot;viewer.common.copied&amp;quot;:&amp;quot;已复制&amp;quot;,&amp;quot;viewer.common.copyFailed&amp;quot;:&amp;quot;复制失败&amp;quot;,&amp;quot;viewer.common.copyLink&amp;quot;:&amp;quot;复制链接&amp;quot;,&amp;quot;viewer.common.clear&amp;quot;:&amp;quot;清除&amp;quot;,&amp;quot;viewer.common.close&amp;quot;:&amp;quot;关闭&amp;quot;}}&amp;lt;/script&amp;gt;&#10;    &amp;lt;div class=&amp;quot;guided-views no-print&amp;quot; id=&amp;quot;guided-views&amp;quot; hidden aria-label=&amp;quot;图表引导视图&amp;quot;&amp;gt;&#10;      &amp;lt;button id=&amp;quot;guided-view-prev&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;上一个引导视图&amp;quot; title=&amp;quot;上一个引导视图（[）&amp;quot;&amp;gt;&amp;amp;#8592;&amp;lt;/button&amp;gt;&#10;      &amp;lt;div class=&amp;quot;guided-view-copy&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;guided-view-meta&amp;quot;&amp;gt;&#10;          &amp;lt;span&amp;gt;引导视图&amp;lt;/span&amp;gt;&#10;          &amp;lt;span id=&amp;quot;guided-view-count&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;guided-view-progress&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;guided-view-progress-bar&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;guided-view-handoff&amp;quot; id=&amp;quot;guided-view-handoff&amp;quot; hidden aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;strong id=&amp;quot;guided-view-label&amp;quot;&amp;gt;探索此系统&amp;lt;/strong&amp;gt;&#10;        &amp;lt;small id=&amp;quot;guided-view-note&amp;quot; aria-live=&amp;quot;polite&amp;quot; aria-atomic=&amp;quot;true&amp;quot;&amp;gt;沿精选路径逐步查看，而不改变源图表。&amp;lt;/small&amp;gt;&#10;        &amp;lt;div class=&amp;quot;guided-view-trail&amp;quot; id=&amp;quot;guided-view-trail&amp;quot; hidden role=&amp;quot;group&amp;quot; aria-label=&amp;quot;故事轨迹&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;guided-story-caption&amp;quot; id=&amp;quot;guided-story-caption&amp;quot; hidden aria-live=&amp;quot;polite&amp;quot; aria-atomic=&amp;quot;true&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;guided-story-caption-index&amp;quot; id=&amp;quot;guided-story-caption-index&amp;quot;&amp;gt;节点&amp;lt;/span&amp;gt;&#10;          &amp;lt;strong id=&amp;quot;guided-story-caption-route&amp;quot;&amp;gt;&amp;lt;/strong&amp;gt;&#10;          &amp;lt;small id=&amp;quot;guided-story-caption-detail&amp;quot;&amp;gt;&amp;lt;/small&amp;gt;&#10;          &amp;lt;span class=&amp;quot;guided-story-caption-next&amp;quot; id=&amp;quot;guided-story-caption-next&amp;quot; hidden aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&#10;            &amp;lt;small&amp;gt;下一步&amp;lt;/small&amp;gt;&#10;            &amp;lt;strong id=&amp;quot;guided-story-caption-next-label&amp;quot;&amp;gt;&amp;lt;/strong&amp;gt;&#10;          &amp;lt;/span&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;      &amp;lt;button id=&amp;quot;guided-view-next&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;下一个引导视图&amp;quot; title=&amp;quot;下一个引导视图（]）&amp;quot;&amp;gt;&amp;amp;#8594;&amp;lt;/button&amp;gt;&#10;      &amp;lt;div class=&amp;quot;guided-view-actions&amp;quot;&amp;gt;&#10;        &amp;lt;button class=&amp;quot;guided-view-play&amp;quot; id=&amp;quot;guided-view-play&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;播放引导故事&amp;quot; aria-pressed=&amp;quot;false&amp;quot; title=&amp;quot;播放引导故事（P）&amp;quot;&amp;gt;&#10;          &amp;lt;span id=&amp;quot;guided-view-play-icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;amp;#9654;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span id=&amp;quot;guided-view-play-label&amp;quot;&amp;gt;播放故事&amp;lt;/span&amp;gt;&#10;        &amp;lt;/button&amp;gt;&#10;        &amp;lt;button class=&amp;quot;guided-view-beat-link&amp;quot; id=&amp;quot;guided-view-beat-link&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;选择故事节点以复制其精确链接&amp;quot; title=&amp;quot;选择故事节点以复制其精确链接&amp;quot; disabled&amp;gt;&#10;          &amp;lt;span aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;amp;#35;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span id=&amp;quot;guided-view-beat-link-label&amp;quot;&amp;gt;复制此刻&amp;lt;/span&amp;gt;&#10;        &amp;lt;/button&amp;gt;&#10;        &amp;lt;button class=&amp;quot;guided-view-all&amp;quot; id=&amp;quot;guided-view-all&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;显示完整图表&amp;quot;&amp;gt;显示全部&amp;lt;/button&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;      &amp;lt;nav class=&amp;quot;guided-view-index&amp;quot; id=&amp;quot;guided-view-index&amp;quot; aria-label=&amp;quot;故事章节&amp;quot;&amp;gt;&#10;        &amp;lt;ol class=&amp;quot;guided-view-chapters&amp;quot; id=&amp;quot;guided-view-chapters&amp;quot;&amp;gt;&amp;lt;/ol&amp;gt;&#10;      &amp;lt;/nav&amp;gt;&#10;    &amp;lt;/div&amp;gt;&#10;&#10;    &amp;lt;!-- Main Diagram --&amp;gt;&#10;    &amp;lt;div class=&amp;quot;diagram-container&amp;quot; data-detail-level=&amp;quot;read&amp;quot;&#10;         data-preset-badge-editorial-plate=&amp;quot;ARCHIFY / 图版 04&amp;quot;&amp;gt;&#10;      &amp;lt;svg viewBox=&amp;quot;0 0 1360 720&amp;quot; role=&amp;quot;img&amp;quot; lang=&amp;quot;zh-CN&amp;quot; aria-labelledby=&amp;quot;archify-diagram-title archify-diagram-description&amp;quot; data-preset=&amp;quot;classic&amp;quot; data-quality-profile=&amp;quot;showcase&amp;quot;&amp;gt;&#10;        &amp;lt;title id=&amp;quot;archify-diagram-title&amp;quot;&amp;gt;AI 推理服务：从请求到芯片&amp;lt;/title&amp;gt;&#10;        &amp;lt;desc id=&amp;quot;archify-diagram-description&amp;quot;&amp;gt;由 Archify 生成的架构图。&amp;lt;/desc&amp;gt;&#10;        &amp;lt;!-- Definitions --&amp;gt;&#10;        &amp;lt;defs&amp;gt;&#10;          &amp;lt;marker id=&amp;quot;arrowhead&amp;quot; markerWidth=&amp;quot;10&amp;quot; markerHeight=&amp;quot;7&amp;quot; refX=&amp;quot;9&amp;quot; refY=&amp;quot;3.5&amp;quot; orient=&amp;quot;auto&amp;quot;&amp;gt;&#10;            &amp;lt;polygon points=&amp;quot;0 0, 10 3.5, 0 7&amp;quot; class=&amp;quot;m-default&amp;quot; /&amp;gt;&#10;          &amp;lt;/marker&amp;gt;&#10;          &amp;lt;marker id=&amp;quot;arrowhead-emphasis&amp;quot; markerWidth=&amp;quot;10&amp;quot; markerHeight=&amp;quot;7&amp;quot; refX=&amp;quot;9&amp;quot; refY=&amp;quot;3.5&amp;quot; orient=&amp;quot;auto&amp;quot;&amp;gt;&#10;            &amp;lt;polygon points=&amp;quot;0 0, 10 3.5, 0 7&amp;quot; class=&amp;quot;m-emphasis&amp;quot; /&amp;gt;&#10;          &amp;lt;/marker&amp;gt;&#10;          &amp;lt;marker id=&amp;quot;arrowhead-security&amp;quot; markerWidth=&amp;quot;10&amp;quot; markerHeight=&amp;quot;7&amp;quot; refX=&amp;quot;9&amp;quot; refY=&amp;quot;3.5&amp;quot; orient=&amp;quot;auto&amp;quot;&amp;gt;&#10;            &amp;lt;polygon points=&amp;quot;0 0, 10 3.5, 0 7&amp;quot; class=&amp;quot;m-security&amp;quot; /&amp;gt;&#10;          &amp;lt;/marker&amp;gt;&#10;          &amp;lt;marker id=&amp;quot;arrowhead-dashed&amp;quot; markerWidth=&amp;quot;10&amp;quot; markerHeight=&amp;quot;7&amp;quot; refX=&amp;quot;9&amp;quot; refY=&amp;quot;3.5&amp;quot; orient=&amp;quot;auto&amp;quot;&amp;gt;&#10;            &amp;lt;polygon points=&amp;quot;0 0, 10 3.5, 0 7&amp;quot; class=&amp;quot;m-dashed&amp;quot; /&amp;gt;&#10;          &amp;lt;/marker&amp;gt;&#10;          &amp;lt;pattern id=&amp;quot;grid&amp;quot; width=&amp;quot;40&amp;quot; height=&amp;quot;40&amp;quot; patternUnits=&amp;quot;userSpaceOnUse&amp;quot;&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M 40 0 L 0 0 0 40&amp;quot; class=&amp;quot;c-grid&amp;quot; stroke-width=&amp;quot;0.5&amp;quot;/&amp;gt;&#10;          &amp;lt;/pattern&amp;gt;&#10;        &amp;lt;/defs&amp;gt;&#10;&#10;        &amp;lt;!-- Background Grid --&amp;gt;&#10;        &amp;lt;rect width=&amp;quot;100%&amp;quot; height=&amp;quot;100%&amp;quot; fill=&amp;quot;url(#grid)&amp;quot; /&amp;gt;&#10;&#10;        &amp;lt;!-- Boundaries (behind everything) --&amp;gt;&#10;&#10;&#10;        &amp;lt;!-- Connection paths (before components for correct z-order) --&amp;gt;&#10;        &amp;lt;path data-edge-from=&amp;quot;client&amp;quot; data-edge-to=&amp;quot;gateway&amp;quot; data-edge-label=&amp;quot;HTTP 请求&amp;quot; data-edge-key=&amp;quot;0&amp;quot; data-edge-id=&amp;quot;request&amp;quot; data-composition-points=&amp;quot;270,109;390,109&amp;quot; d=&amp;quot;M 270 109 L 390 109&amp;quot; class=&amp;quot;a-emphasis&amp;quot; stroke-width=&amp;quot;1.8&amp;quot; marker-end=&amp;quot;url(#arrowhead-emphasis)&amp;quot;/&amp;gt;&#10;        &amp;lt;path data-edge-from=&amp;quot;gateway&amp;quot; data-edge-to=&amp;quot;tokenizer&amp;quot; data-edge-label=&amp;quot;分配副本&amp;quot; data-edge-key=&amp;quot;1&amp;quot; data-edge-id=&amp;quot;dispatch&amp;quot; data-composition-points=&amp;quot;620,109;740,109&amp;quot; d=&amp;quot;M 620 109 L 740 109&amp;quot; class=&amp;quot;a-emphasis&amp;quot; stroke-width=&amp;quot;1.8&amp;quot; marker-end=&amp;quot;url(#arrowhead-emphasis)&amp;quot;/&amp;gt;&#10;        &amp;lt;path data-edge-from=&amp;quot;tokenizer&amp;quot; data-edge-to=&amp;quot;scheduler&amp;quot; data-edge-label=&amp;quot;请求入队&amp;quot; data-edge-key=&amp;quot;2&amp;quot; data-edge-id=&amp;quot;enqueue&amp;quot; data-composition-points=&amp;quot;855,148;855,290&amp;quot; d=&amp;quot;M 855 148 L 855 290&amp;quot; class=&amp;quot;a-emphasis&amp;quot; stroke-width=&amp;quot;1.8&amp;quot; marker-end=&amp;quot;url(#arrowhead-emphasis)&amp;quot;/&amp;gt;&#10;        &amp;lt;path data-edge-from=&amp;quot;scheduler&amp;quot; data-edge-to=&amp;quot;runner&amp;quot; data-edge-label=&amp;quot;调度批次&amp;quot; data-edge-key=&amp;quot;3&amp;quot; data-edge-id=&amp;quot;batch&amp;quot; data-composition-points=&amp;quot;740,329;620,329&amp;quot; d=&amp;quot;M 740 329 L 620 329&amp;quot; class=&amp;quot;a-emphasis&amp;quot; stroke-width=&amp;quot;1.8&amp;quot; marker-end=&amp;quot;url(#arrowhead-emphasis)&amp;quot;/&amp;gt;&#10;        &amp;lt;path data-edge-from=&amp;quot;scheduler&amp;quot; data-edge-to=&amp;quot;cache&amp;quot; data-edge-label=&amp;quot;查找与分配&amp;quot; data-edge-key=&amp;quot;4&amp;quot; data-edge-id=&amp;quot;kv&amp;quot; data-composition-points=&amp;quot;970,329;1090,329&amp;quot; d=&amp;quot;M 970 329 L 1090 329&amp;quot; class=&amp;quot;a-default&amp;quot; stroke-width=&amp;quot;1.5&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;/&amp;gt;&#10;        &amp;lt;path data-edge-from=&amp;quot;runner&amp;quot; data-edge-to=&amp;quot;output&amp;quot; data-edge-label=&amp;quot;输出 Token&amp;quot; data-edge-key=&amp;quot;5&amp;quot; data-edge-id=&amp;quot;stream&amp;quot; data-composition-points=&amp;quot;390,329;270,329&amp;quot; d=&amp;quot;M 390 329 L 270 329&amp;quot; class=&amp;quot;a-emphasis&amp;quot; stroke-width=&amp;quot;1.8&amp;quot; marker-end=&amp;quot;url(#arrowhead-emphasis)&amp;quot;/&amp;gt;&#10;        &amp;lt;path data-edge-from=&amp;quot;runner&amp;quot; data-edge-to=&amp;quot;kernels&amp;quot; data-edge-label=&amp;quot;执行算子&amp;quot; data-edge-key=&amp;quot;6&amp;quot; data-edge-id=&amp;quot;execute&amp;quot; data-composition-points=&amp;quot;505,368;505,540&amp;quot; d=&amp;quot;M 505 368 L 505 540&amp;quot; class=&amp;quot;a-default&amp;quot; stroke-width=&amp;quot;1.5&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;/&amp;gt;&#10;        &amp;lt;path data-edge-from=&amp;quot;kernels&amp;quot; data-edge-to=&amp;quot;hardware&amp;quot; data-edge-label=&amp;quot;设备调用&amp;quot; data-edge-key=&amp;quot;7&amp;quot; data-edge-id=&amp;quot;device&amp;quot; data-composition-points=&amp;quot;620,579;740,579&amp;quot; d=&amp;quot;M 620 579 L 740 579&amp;quot; class=&amp;quot;a-default&amp;quot; stroke-width=&amp;quot;1.5&amp;quot; marker-end=&amp;quot;url(#arrowhead)&amp;quot;/&amp;gt;&#10;&#10;        &amp;lt;!-- Components --&amp;gt;&#10;        &amp;lt;g id=&amp;quot;node-client&amp;quot; data-node-id=&amp;quot;client&amp;quot; data-node-label=&amp;quot;客户端 / Agent&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;button&amp;quot; aria-label=&amp;quot;聚焦客户端 / Agent，请求分布与延迟目标, 架构组件&amp;quot; aria-pressed=&amp;quot;false&amp;quot; data-node-kind=&amp;quot;external&amp;quot; data-node-sublabel=&amp;quot;请求分布与延迟目标&amp;quot; data-node-context=&amp;quot;架构组件&amp;quot;&amp;gt;&#10;          &amp;lt;title&amp;gt;客户端 / Agent · 请求分布与延迟目标 · 架构组件&amp;lt;/title&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;40&amp;quot; y=&amp;quot;70&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;40&amp;quot; y=&amp;quot;70&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-external&amp;quot; stroke-width=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;          &amp;lt;g aria-hidden=&amp;quot;true&amp;quot; data-semantic-sigil=&amp;quot;external&amp;quot; class=&amp;quot;semantic-sigil s-external&amp;quot; transform=&amp;quot;translate(46 76) scale(0.6875)&amp;quot;&amp;gt;&#10;            &amp;lt;rect x=&amp;quot;2.5&amp;quot; y=&amp;quot;5&amp;quot; width=&amp;quot;8.5&amp;quot; height=&amp;quot;8&amp;quot; rx=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M8 2.5h5.5V8M13.5 2.5 7.5 8.5&amp;quot;/&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;text data-node-label=&amp;quot;&amp;quot; data-detail-anchor=&amp;quot;&amp;quot; x=&amp;quot;155&amp;quot; y=&amp;quot;107&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;11&amp;quot; font-weight=&amp;quot;600&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;客户端 / Agent&amp;lt;/text&amp;gt;&#10;        &amp;lt;text data-detail=&amp;quot;context&amp;quot; x=&amp;quot;155&amp;quot; y=&amp;quot;123&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;9&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;请求分布与延迟目标&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;g id=&amp;quot;node-gateway&amp;quot; data-node-id=&amp;quot;gateway&amp;quot; data-node-label=&amp;quot;网关与请求路由&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;button&amp;quot; aria-label=&amp;quot;聚焦网关与请求路由，限流 · 取消 · 负载均衡, 架构组件&amp;quot; aria-pressed=&amp;quot;false&amp;quot; data-node-kind=&amp;quot;security&amp;quot; data-node-sublabel=&amp;quot;限流 · 取消 · 负载均衡&amp;quot; data-node-context=&amp;quot;架构组件&amp;quot;&amp;gt;&#10;          &amp;lt;title&amp;gt;网关与请求路由 · 限流 · 取消 · 负载均衡 · 架构组件&amp;lt;/title&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;390&amp;quot; y=&amp;quot;70&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;390&amp;quot; y=&amp;quot;70&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-security&amp;quot; stroke-width=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;          &amp;lt;g aria-hidden=&amp;quot;true&amp;quot; data-semantic-sigil=&amp;quot;security&amp;quot; class=&amp;quot;semantic-sigil s-security&amp;quot; transform=&amp;quot;translate(396 76) scale(0.6875)&amp;quot;&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M8 2.2 13 4v3.5c0 3.1-1.8 5.4-5 6.5-3.2-1.1-5-3.4-5-6.5V4Z&amp;quot;/&amp;gt;&#10;            &amp;lt;path d=&amp;quot;m5.8 8 1.5 1.5 3-3&amp;quot;/&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;text data-node-label=&amp;quot;&amp;quot; data-detail-anchor=&amp;quot;&amp;quot; x=&amp;quot;505&amp;quot; y=&amp;quot;107&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;11&amp;quot; font-weight=&amp;quot;600&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;网关与请求路由&amp;lt;/text&amp;gt;&#10;        &amp;lt;text data-detail=&amp;quot;context&amp;quot; x=&amp;quot;505&amp;quot; y=&amp;quot;123&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;9&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;限流 · 取消 · 负载均衡&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;g id=&amp;quot;node-tokenizer&amp;quot; data-node-id=&amp;quot;tokenizer&amp;quot; data-node-label=&amp;quot;输入预处理&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;button&amp;quot; aria-label=&amp;quot;聚焦输入预处理，Tokenizer / 多模态编码, 架构组件&amp;quot; aria-pressed=&amp;quot;false&amp;quot; data-node-kind=&amp;quot;backend&amp;quot; data-node-sublabel=&amp;quot;Tokenizer / 多模态编码&amp;quot; data-node-context=&amp;quot;架构组件&amp;quot;&amp;gt;&#10;          &amp;lt;title&amp;gt;输入预处理 · Tokenizer / 多模态编码 · 架构组件&amp;lt;/title&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;740&amp;quot; y=&amp;quot;70&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;740&amp;quot; y=&amp;quot;70&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-backend&amp;quot; stroke-width=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;          &amp;lt;g aria-hidden=&amp;quot;true&amp;quot; data-semantic-sigil=&amp;quot;backend&amp;quot; class=&amp;quot;semantic-sigil s-backend&amp;quot; transform=&amp;quot;translate(746 76) scale(0.6875)&amp;quot;&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M6 3 3 8l3 5M10 3l3 5-3 5&amp;quot;/&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;text data-node-label=&amp;quot;&amp;quot; data-detail-anchor=&amp;quot;&amp;quot; x=&amp;quot;855&amp;quot; y=&amp;quot;107&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;11&amp;quot; font-weight=&amp;quot;600&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;输入预处理&amp;lt;/text&amp;gt;&#10;        &amp;lt;text data-detail=&amp;quot;context&amp;quot; x=&amp;quot;855&amp;quot; y=&amp;quot;123&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;9&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;Tokenizer / 多模态编码&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;g id=&amp;quot;node-scheduler&amp;quot; data-node-id=&amp;quot;scheduler&amp;quot; data-node-label=&amp;quot;迭代调度器&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;button&amp;quot; aria-label=&amp;quot;聚焦迭代调度器，连续批处理 · Token 预算, 架构组件&amp;quot; aria-pressed=&amp;quot;false&amp;quot; data-node-kind=&amp;quot;backend&amp;quot; data-node-sublabel=&amp;quot;连续批处理 · Token 预算&amp;quot; data-node-context=&amp;quot;架构组件&amp;quot;&amp;gt;&#10;          &amp;lt;title&amp;gt;迭代调度器 · 连续批处理 · Token 预算 · 架构组件&amp;lt;/title&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;740&amp;quot; y=&amp;quot;290&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;740&amp;quot; y=&amp;quot;290&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-backend&amp;quot; stroke-width=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;          &amp;lt;g aria-hidden=&amp;quot;true&amp;quot; data-semantic-sigil=&amp;quot;backend&amp;quot; class=&amp;quot;semantic-sigil s-backend&amp;quot; transform=&amp;quot;translate(746 296) scale(0.6875)&amp;quot;&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M6 3 3 8l3 5M10 3l3 5-3 5&amp;quot;/&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;text data-node-label=&amp;quot;&amp;quot; data-detail-anchor=&amp;quot;&amp;quot; x=&amp;quot;855&amp;quot; y=&amp;quot;327&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;11&amp;quot; font-weight=&amp;quot;600&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;迭代调度器&amp;lt;/text&amp;gt;&#10;        &amp;lt;text data-detail=&amp;quot;context&amp;quot; x=&amp;quot;855&amp;quot; y=&amp;quot;343&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;9&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;连续批处理 · Token 预算&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;g id=&amp;quot;node-cache&amp;quot; data-node-id=&amp;quot;cache&amp;quot; data-node-label=&amp;quot;KV Cache 管理&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;button&amp;quot; aria-label=&amp;quot;聚焦KV Cache 管理，分页 · 前缀复用 · 回收, 架构组件&amp;quot; aria-pressed=&amp;quot;false&amp;quot; data-node-kind=&amp;quot;database&amp;quot; data-node-sublabel=&amp;quot;分页 · 前缀复用 · 回收&amp;quot; data-node-context=&amp;quot;架构组件&amp;quot;&amp;gt;&#10;          &amp;lt;title&amp;gt;KV Cache 管理 · 分页 · 前缀复用 · 回收 · 架构组件&amp;lt;/title&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;1090&amp;quot; y=&amp;quot;290&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;1090&amp;quot; y=&amp;quot;290&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-database&amp;quot; stroke-width=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;          &amp;lt;g aria-hidden=&amp;quot;true&amp;quot; data-semantic-sigil=&amp;quot;database&amp;quot; class=&amp;quot;semantic-sigil s-database&amp;quot; transform=&amp;quot;translate(1096 296) scale(0.6875)&amp;quot;&amp;gt;&#10;            &amp;lt;ellipse cx=&amp;quot;8&amp;quot; cy=&amp;quot;4&amp;quot; rx=&amp;quot;5&amp;quot; ry=&amp;quot;2&amp;quot;/&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M3 4v8c0 1.1 2.2 2 5 2s5-.9 5-2V4M3 8c0 1.1 2.2 2 5 2s5-.9 5-2&amp;quot;/&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;text data-node-label=&amp;quot;&amp;quot; data-detail-anchor=&amp;quot;&amp;quot; x=&amp;quot;1205&amp;quot; y=&amp;quot;327&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;11&amp;quot; font-weight=&amp;quot;600&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;KV Cache 管理&amp;lt;/text&amp;gt;&#10;        &amp;lt;text data-detail=&amp;quot;context&amp;quot; x=&amp;quot;1205&amp;quot; y=&amp;quot;343&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;9&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;分页 · 前缀复用 · 回收&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;g id=&amp;quot;node-runner&amp;quot; data-node-id=&amp;quot;runner&amp;quot; data-node-label=&amp;quot;模型执行器&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;button&amp;quot; aria-label=&amp;quot;聚焦模型执行器，Prefill / Decode · 采样, 架构组件&amp;quot; aria-pressed=&amp;quot;false&amp;quot; data-node-kind=&amp;quot;backend&amp;quot; data-node-sublabel=&amp;quot;Prefill / Decode · 采样&amp;quot; data-node-context=&amp;quot;架构组件&amp;quot;&amp;gt;&#10;          &amp;lt;title&amp;gt;模型执行器 · Prefill / Decode · 采样 · 架构组件&amp;lt;/title&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;390&amp;quot; y=&amp;quot;290&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;390&amp;quot; y=&amp;quot;290&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-backend&amp;quot; stroke-width=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;          &amp;lt;g aria-hidden=&amp;quot;true&amp;quot; data-semantic-sigil=&amp;quot;backend&amp;quot; class=&amp;quot;semantic-sigil s-backend&amp;quot; transform=&amp;quot;translate(396 296) scale(0.6875)&amp;quot;&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M6 3 3 8l3 5M10 3l3 5-3 5&amp;quot;/&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;text data-node-label=&amp;quot;&amp;quot; data-detail-anchor=&amp;quot;&amp;quot; x=&amp;quot;505&amp;quot; y=&amp;quot;327&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;11&amp;quot; font-weight=&amp;quot;600&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;模型执行器&amp;lt;/text&amp;gt;&#10;        &amp;lt;text data-detail=&amp;quot;context&amp;quot; x=&amp;quot;505&amp;quot; y=&amp;quot;343&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;9&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;Prefill / Decode · 采样&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;g id=&amp;quot;node-output&amp;quot; data-node-id=&amp;quot;output&amp;quot; data-node-label=&amp;quot;流式输出&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;button&amp;quot; aria-label=&amp;quot;聚焦流式输出，Detokenizer · SSE, 架构组件&amp;quot; aria-pressed=&amp;quot;false&amp;quot; data-node-kind=&amp;quot;frontend&amp;quot; data-node-sublabel=&amp;quot;Detokenizer · SSE&amp;quot; data-node-context=&amp;quot;架构组件&amp;quot;&amp;gt;&#10;          &amp;lt;title&amp;gt;流式输出 · Detokenizer · SSE · 架构组件&amp;lt;/title&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;40&amp;quot; y=&amp;quot;290&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;40&amp;quot; y=&amp;quot;290&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-frontend&amp;quot; stroke-width=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;          &amp;lt;g aria-hidden=&amp;quot;true&amp;quot; data-semantic-sigil=&amp;quot;frontend&amp;quot; class=&amp;quot;semantic-sigil s-frontend&amp;quot; transform=&amp;quot;translate(46 296) scale(0.6875)&amp;quot;&amp;gt;&#10;            &amp;lt;rect x=&amp;quot;2&amp;quot; y=&amp;quot;3&amp;quot; width=&amp;quot;12&amp;quot; height=&amp;quot;10&amp;quot; rx=&amp;quot;2&amp;quot;/&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M2 6.5h12&amp;quot;/&amp;gt;&#10;            &amp;lt;circle cx=&amp;quot;4.1&amp;quot; cy=&amp;quot;4.8&amp;quot; r=&amp;quot;.7&amp;quot; class=&amp;quot;sigil-fill&amp;quot;/&amp;gt;&#10;            &amp;lt;circle cx=&amp;quot;6.3&amp;quot; cy=&amp;quot;4.8&amp;quot; r=&amp;quot;.7&amp;quot; class=&amp;quot;sigil-fill&amp;quot;/&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;text data-node-label=&amp;quot;&amp;quot; data-detail-anchor=&amp;quot;&amp;quot; x=&amp;quot;155&amp;quot; y=&amp;quot;327&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;11&amp;quot; font-weight=&amp;quot;600&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;流式输出&amp;lt;/text&amp;gt;&#10;        &amp;lt;text data-detail=&amp;quot;context&amp;quot; x=&amp;quot;155&amp;quot; y=&amp;quot;343&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;9&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;Detokenizer · SSE&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;g id=&amp;quot;node-kernels&amp;quot; data-node-id=&amp;quot;kernels&amp;quot; data-node-label=&amp;quot;算子与运行时&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;button&amp;quot; aria-label=&amp;quot;聚焦算子与运行时，Attention · GEMM · 图执行, 架构组件&amp;quot; aria-pressed=&amp;quot;false&amp;quot; data-node-kind=&amp;quot;backend&amp;quot; data-node-sublabel=&amp;quot;Attention · GEMM · 图执行&amp;quot; data-node-context=&amp;quot;架构组件&amp;quot;&amp;gt;&#10;          &amp;lt;title&amp;gt;算子与运行时 · Attention · GEMM · 图执行 · 架构组件&amp;lt;/title&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;390&amp;quot; y=&amp;quot;540&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;390&amp;quot; y=&amp;quot;540&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-backend&amp;quot; stroke-width=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;          &amp;lt;g aria-hidden=&amp;quot;true&amp;quot; data-semantic-sigil=&amp;quot;backend&amp;quot; class=&amp;quot;semantic-sigil s-backend&amp;quot; transform=&amp;quot;translate(396 546) scale(0.6875)&amp;quot;&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M6 3 3 8l3 5M10 3l3 5-3 5&amp;quot;/&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;text data-node-label=&amp;quot;&amp;quot; data-detail-anchor=&amp;quot;&amp;quot; x=&amp;quot;505&amp;quot; y=&amp;quot;577&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;11&amp;quot; font-weight=&amp;quot;600&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;算子与运行时&amp;lt;/text&amp;gt;&#10;        &amp;lt;text data-detail=&amp;quot;context&amp;quot; x=&amp;quot;505&amp;quot; y=&amp;quot;593&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;9&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;Attention · GEMM · 图执行&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;g id=&amp;quot;node-hardware&amp;quot; data-node-id=&amp;quot;hardware&amp;quot; data-node-label=&amp;quot;设备与互连&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;button&amp;quot; aria-label=&amp;quot;聚焦设备与互连，GPU / MLU · 显存 · 通信, 架构组件&amp;quot; aria-pressed=&amp;quot;false&amp;quot; data-node-kind=&amp;quot;cloud&amp;quot; data-node-sublabel=&amp;quot;GPU / MLU · 显存 · 通信&amp;quot; data-node-context=&amp;quot;架构组件&amp;quot;&amp;gt;&#10;          &amp;lt;title&amp;gt;设备与互连 · GPU / MLU · 显存 · 通信 · 架构组件&amp;lt;/title&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;740&amp;quot; y=&amp;quot;540&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;740&amp;quot; y=&amp;quot;540&amp;quot; width=&amp;quot;230&amp;quot; height=&amp;quot;78&amp;quot; rx=&amp;quot;6&amp;quot; class=&amp;quot;c-cloud&amp;quot; stroke-width=&amp;quot;1.5&amp;quot;/&amp;gt;&#10;          &amp;lt;g aria-hidden=&amp;quot;true&amp;quot; data-semantic-sigil=&amp;quot;cloud&amp;quot; class=&amp;quot;semantic-sigil s-cloud&amp;quot; transform=&amp;quot;translate(746 546) scale(0.6875)&amp;quot;&amp;gt;&#10;            &amp;lt;path d=&amp;quot;M4.3 12.5h7.3a2.4 2.4 0 0 0 .2-4.8 4 4 0 0 0-7.5-1.3A3.1 3.1 0 0 0 4.3 12.5Z&amp;quot;/&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;text data-node-label=&amp;quot;&amp;quot; data-detail-anchor=&amp;quot;&amp;quot; x=&amp;quot;855&amp;quot; y=&amp;quot;577&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;11&amp;quot; font-weight=&amp;quot;600&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;设备与互连&amp;lt;/text&amp;gt;&#10;        &amp;lt;text data-detail=&amp;quot;context&amp;quot; x=&amp;quot;855&amp;quot; y=&amp;quot;593&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;9&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;GPU / MLU · 显存 · 通信&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;!-- Connection labels --&amp;gt;&#10;        &amp;lt;g data-detail=&amp;quot;context&amp;quot; data-edge-from=&amp;quot;client&amp;quot; data-edge-to=&amp;quot;gateway&amp;quot; data-edge-label=&amp;quot;HTTP 请求&amp;quot; data-edge-key=&amp;quot;0&amp;quot; data-edge-id=&amp;quot;request&amp;quot;&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;303.4&amp;quot; y=&amp;quot;89&amp;quot; width=&amp;quot;53.199999999999996&amp;quot; height=&amp;quot;14&amp;quot; rx=&amp;quot;3&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;text x=&amp;quot;330&amp;quot; y=&amp;quot;99&amp;quot; class=&amp;quot;t-backend&amp;quot; font-size=&amp;quot;8&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;HTTP 请求&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;        &amp;lt;g data-detail=&amp;quot;context&amp;quot; data-edge-from=&amp;quot;gateway&amp;quot; data-edge-to=&amp;quot;tokenizer&amp;quot; data-edge-label=&amp;quot;分配副本&amp;quot; data-edge-key=&amp;quot;1&amp;quot; data-edge-id=&amp;quot;dispatch&amp;quot;&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;655.8&amp;quot; y=&amp;quot;89&amp;quot; width=&amp;quot;48.4&amp;quot; height=&amp;quot;14&amp;quot; rx=&amp;quot;3&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;text x=&amp;quot;680&amp;quot; y=&amp;quot;99&amp;quot; class=&amp;quot;t-backend&amp;quot; font-size=&amp;quot;8&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;分配副本&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;        &amp;lt;g data-detail=&amp;quot;context&amp;quot; data-edge-from=&amp;quot;tokenizer&amp;quot; data-edge-to=&amp;quot;scheduler&amp;quot; data-edge-label=&amp;quot;请求入队&amp;quot; data-edge-key=&amp;quot;2&amp;quot; data-edge-id=&amp;quot;enqueue&amp;quot;&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;830.8&amp;quot; y=&amp;quot;212&amp;quot; width=&amp;quot;48.4&amp;quot; height=&amp;quot;14&amp;quot; rx=&amp;quot;3&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;text x=&amp;quot;855&amp;quot; y=&amp;quot;222&amp;quot; class=&amp;quot;t-backend&amp;quot; font-size=&amp;quot;8&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;请求入队&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;        &amp;lt;g data-detail=&amp;quot;context&amp;quot; data-edge-from=&amp;quot;scheduler&amp;quot; data-edge-to=&amp;quot;runner&amp;quot; data-edge-label=&amp;quot;调度批次&amp;quot; data-edge-key=&amp;quot;3&amp;quot; data-edge-id=&amp;quot;batch&amp;quot;&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;655.8&amp;quot; y=&amp;quot;309&amp;quot; width=&amp;quot;48.4&amp;quot; height=&amp;quot;14&amp;quot; rx=&amp;quot;3&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;text x=&amp;quot;680&amp;quot; y=&amp;quot;319&amp;quot; class=&amp;quot;t-backend&amp;quot; font-size=&amp;quot;8&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;调度批次&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;        &amp;lt;g data-detail=&amp;quot;context&amp;quot; data-edge-from=&amp;quot;scheduler&amp;quot; data-edge-to=&amp;quot;cache&amp;quot; data-edge-label=&amp;quot;查找与分配&amp;quot; data-edge-key=&amp;quot;4&amp;quot; data-edge-id=&amp;quot;kv&amp;quot;&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;1001&amp;quot; y=&amp;quot;309&amp;quot; width=&amp;quot;58&amp;quot; height=&amp;quot;14&amp;quot; rx=&amp;quot;3&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;text x=&amp;quot;1030&amp;quot; y=&amp;quot;319&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;8&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;查找与分配&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;        &amp;lt;g data-detail=&amp;quot;context&amp;quot; data-edge-from=&amp;quot;runner&amp;quot; data-edge-to=&amp;quot;output&amp;quot; data-edge-label=&amp;quot;输出 Token&amp;quot; data-edge-key=&amp;quot;5&amp;quot; data-edge-id=&amp;quot;stream&amp;quot;&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;301&amp;quot; y=&amp;quot;309&amp;quot; width=&amp;quot;58&amp;quot; height=&amp;quot;14&amp;quot; rx=&amp;quot;3&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;text x=&amp;quot;330&amp;quot; y=&amp;quot;319&amp;quot; class=&amp;quot;t-backend&amp;quot; font-size=&amp;quot;8&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;输出 Token&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;        &amp;lt;g data-detail=&amp;quot;context&amp;quot; data-edge-from=&amp;quot;runner&amp;quot; data-edge-to=&amp;quot;kernels&amp;quot; data-edge-label=&amp;quot;执行算子&amp;quot; data-edge-key=&amp;quot;6&amp;quot; data-edge-id=&amp;quot;execute&amp;quot;&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;480.8&amp;quot; y=&amp;quot;442&amp;quot; width=&amp;quot;48.4&amp;quot; height=&amp;quot;14&amp;quot; rx=&amp;quot;3&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;text x=&amp;quot;505&amp;quot; y=&amp;quot;452&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;8&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;执行算子&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;        &amp;lt;g data-detail=&amp;quot;context&amp;quot; data-edge-from=&amp;quot;kernels&amp;quot; data-edge-to=&amp;quot;hardware&amp;quot; data-edge-label=&amp;quot;设备调用&amp;quot; data-edge-key=&amp;quot;7&amp;quot; data-edge-id=&amp;quot;device&amp;quot;&amp;gt;&#10;          &amp;lt;rect x=&amp;quot;655.8&amp;quot; y=&amp;quot;559&amp;quot; width=&amp;quot;48.4&amp;quot; height=&amp;quot;14&amp;quot; rx=&amp;quot;3&amp;quot; class=&amp;quot;c-mask&amp;quot;/&amp;gt;&#10;          &amp;lt;text x=&amp;quot;680&amp;quot; y=&amp;quot;569&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;8&amp;quot; text-anchor=&amp;quot;middle&amp;quot;&amp;gt;设备调用&amp;lt;/text&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;&#10;        &amp;lt;!-- Boundary labels (foreground masks keep routes out of titles) --&amp;gt;&#10;&#10;&#10;        &amp;lt;!-- Legend --&amp;gt;&#10;        &amp;lt;g data-legend=&amp;quot;&amp;quot; data-legend-bridge=&amp;quot;&amp;quot;&amp;gt;&#10;          &amp;lt;text x=&amp;quot;40&amp;quot; y=&amp;quot;684&amp;quot; class=&amp;quot;t-primary&amp;quot; font-size=&amp;quot;12&amp;quot; font-weight=&amp;quot;650&amp;quot;&amp;gt;图例&amp;lt;/text&amp;gt;&#10;          &amp;lt;g data-legend-semantic-kind=&amp;quot;frontend&amp;quot; data-legend-kind=&amp;quot;frontend&amp;quot; data-legend-label=&amp;quot;前端&amp;quot; data-legend-x=&amp;quot;40&amp;quot; data-legend-baseline=&amp;quot;704&amp;quot; data-legend-width=&amp;quot;63&amp;quot;&amp;gt;&#10;            &amp;lt;rect x=&amp;quot;40&amp;quot; y=&amp;quot;695&amp;quot; width=&amp;quot;16&amp;quot; height=&amp;quot;10&amp;quot; rx=&amp;quot;2.5&amp;quot; class=&amp;quot;c-frontend&amp;quot; stroke-width=&amp;quot;1&amp;quot;/&amp;gt;&#10;            &amp;lt;text x=&amp;quot;62&amp;quot; y=&amp;quot;704&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;10&amp;quot; font-weight=&amp;quot;500&amp;quot;&amp;gt;前端&amp;lt;/text&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;g data-legend-semantic-kind=&amp;quot;backend&amp;quot; data-legend-kind=&amp;quot;backend&amp;quot; data-legend-label=&amp;quot;后端&amp;quot; data-legend-x=&amp;quot;125&amp;quot; data-legend-baseline=&amp;quot;704&amp;quot; data-legend-width=&amp;quot;63&amp;quot;&amp;gt;&#10;            &amp;lt;rect x=&amp;quot;125&amp;quot; y=&amp;quot;695&amp;quot; width=&amp;quot;16&amp;quot; height=&amp;quot;10&amp;quot; rx=&amp;quot;2.5&amp;quot; class=&amp;quot;c-backend&amp;quot; stroke-width=&amp;quot;1&amp;quot;/&amp;gt;&#10;            &amp;lt;text x=&amp;quot;147&amp;quot; y=&amp;quot;704&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;10&amp;quot; font-weight=&amp;quot;500&amp;quot;&amp;gt;后端&amp;lt;/text&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;g data-legend-semantic-kind=&amp;quot;database&amp;quot; data-legend-kind=&amp;quot;database&amp;quot; data-legend-label=&amp;quot;数据库&amp;quot; data-legend-x=&amp;quot;210&amp;quot; data-legend-baseline=&amp;quot;704&amp;quot; data-legend-width=&amp;quot;73&amp;quot;&amp;gt;&#10;            &amp;lt;rect x=&amp;quot;210&amp;quot; y=&amp;quot;695&amp;quot; width=&amp;quot;16&amp;quot; height=&amp;quot;10&amp;quot; rx=&amp;quot;2.5&amp;quot; class=&amp;quot;c-database&amp;quot; stroke-width=&amp;quot;1&amp;quot;/&amp;gt;&#10;            &amp;lt;text x=&amp;quot;232&amp;quot; y=&amp;quot;704&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;10&amp;quot; font-weight=&amp;quot;500&amp;quot;&amp;gt;数据库&amp;lt;/text&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;g data-legend-semantic-kind=&amp;quot;cloud&amp;quot; data-legend-kind=&amp;quot;cloud&amp;quot; data-legend-label=&amp;quot;云服务&amp;quot; data-legend-x=&amp;quot;305&amp;quot; data-legend-baseline=&amp;quot;704&amp;quot; data-legend-width=&amp;quot;73&amp;quot;&amp;gt;&#10;            &amp;lt;rect x=&amp;quot;305&amp;quot; y=&amp;quot;695&amp;quot; width=&amp;quot;16&amp;quot; height=&amp;quot;10&amp;quot; rx=&amp;quot;2.5&amp;quot; class=&amp;quot;c-cloud&amp;quot; stroke-width=&amp;quot;1&amp;quot;/&amp;gt;&#10;            &amp;lt;text x=&amp;quot;327&amp;quot; y=&amp;quot;704&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;10&amp;quot; font-weight=&amp;quot;500&amp;quot;&amp;gt;云服务&amp;lt;/text&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;g data-legend-semantic-kind=&amp;quot;security&amp;quot; data-legend-kind=&amp;quot;security&amp;quot; data-legend-label=&amp;quot;安全&amp;quot; data-legend-x=&amp;quot;400&amp;quot; data-legend-baseline=&amp;quot;704&amp;quot; data-legend-width=&amp;quot;63&amp;quot;&amp;gt;&#10;            &amp;lt;rect x=&amp;quot;400&amp;quot; y=&amp;quot;695&amp;quot; width=&amp;quot;16&amp;quot; height=&amp;quot;10&amp;quot; rx=&amp;quot;2.5&amp;quot; class=&amp;quot;c-security&amp;quot; stroke-width=&amp;quot;1&amp;quot;/&amp;gt;&#10;            &amp;lt;text x=&amp;quot;422&amp;quot; y=&amp;quot;704&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;10&amp;quot; font-weight=&amp;quot;500&amp;quot;&amp;gt;安全&amp;lt;/text&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;          &amp;lt;g data-legend-semantic-kind=&amp;quot;external&amp;quot; data-legend-kind=&amp;quot;external&amp;quot; data-legend-label=&amp;quot;外部系统&amp;quot; data-legend-x=&amp;quot;485&amp;quot; data-legend-baseline=&amp;quot;704&amp;quot; data-legend-width=&amp;quot;83&amp;quot;&amp;gt;&#10;            &amp;lt;rect x=&amp;quot;485&amp;quot; y=&amp;quot;695&amp;quot; width=&amp;quot;16&amp;quot; height=&amp;quot;10&amp;quot; rx=&amp;quot;2.5&amp;quot; class=&amp;quot;c-external&amp;quot; stroke-width=&amp;quot;1&amp;quot;/&amp;gt;&#10;            &amp;lt;text x=&amp;quot;507&amp;quot; y=&amp;quot;704&amp;quot; class=&amp;quot;t-muted&amp;quot; font-size=&amp;quot;10&amp;quot; font-weight=&amp;quot;500&amp;quot;&amp;gt;外部系统&amp;lt;/text&amp;gt;&#10;          &amp;lt;/g&amp;gt;&#10;        &amp;lt;/g&amp;gt;&#10;      &amp;lt;/svg&amp;gt;&#10;      &amp;lt;p class=&amp;quot;intent-trace-status no-print&amp;quot; id=&amp;quot;intent-trace-status&amp;quot; role=&amp;quot;status&amp;quot; aria-live=&amp;quot;polite&amp;quot; aria-atomic=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&#10;      &amp;lt;div class=&amp;quot;share-chapter-cue no-print&amp;quot; id=&amp;quot;share-chapter-cue&amp;quot; hidden role=&amp;quot;status&amp;quot; aria-live=&amp;quot;polite&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;share-chapter-index&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;share-chapter-state&amp;quot; id=&amp;quot;share-chapter-state&amp;quot;&amp;gt;就绪&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;share-chapter-count&amp;quot; id=&amp;quot;share-chapter-count&amp;quot;&amp;gt;章节 01 / 01&amp;lt;/span&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;share-chapter-copy&amp;quot;&amp;gt;&#10;          &amp;lt;strong id=&amp;quot;share-chapter-label&amp;quot;&amp;gt;引导章节&amp;lt;/strong&amp;gt;&#10;          &amp;lt;small id=&amp;quot;share-chapter-note&amp;quot;&amp;gt;&amp;lt;/small&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;span class=&amp;quot;share-chapter-route&amp;quot; id=&amp;quot;share-chapter-route&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;        &amp;lt;span class=&amp;quot;share-chapter-progress&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;share-chapter-progress-bar&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;      &amp;lt;div class=&amp;quot;diagram-guide no-print&amp;quot; id=&amp;quot;diagram-guide&amp;quot; hidden role=&amp;quot;dialog&amp;quot; aria-modal=&amp;quot;false&amp;quot; aria-labelledby=&amp;quot;diagram-guide-title&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;diagram-guide-head&amp;quot;&amp;gt;&#10;          &amp;lt;span&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-eyebrow&amp;quot;&amp;gt;图表指南&amp;lt;/span&amp;gt;&#10;            &amp;lt;strong class=&amp;quot;diagram-guide-title&amp;quot; id=&amp;quot;diagram-guide-title&amp;quot;&amp;gt;探索此系统&amp;lt;/strong&amp;gt;&#10;          &amp;lt;/span&amp;gt;&#10;          &amp;lt;button class=&amp;quot;diagram-guide-close&amp;quot; id=&amp;quot;diagram-guide-close&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;关闭图表指南&amp;quot;&amp;gt;&amp;amp;#215;&amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;p class=&amp;quot;diagram-guide-stats&amp;quot; id=&amp;quot;diagram-guide-stats&amp;quot;&amp;gt;正在检查已编译语义&amp;lt;/p&amp;gt;&#10;        &amp;lt;div class=&amp;quot;diagram-guide-actions&amp;quot; id=&amp;quot;diagram-guide-actions&amp;quot; role=&amp;quot;group&amp;quot; aria-label=&amp;quot;图表探索操作&amp;quot;&amp;gt;&#10;          &amp;lt;button class=&amp;quot;diagram-guide-action&amp;quot; type=&amp;quot;button&amp;quot; data-guide-action=&amp;quot;find&amp;quot; aria-label=&amp;quot;查找任意节点&amp;quot;&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-index&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;01&amp;lt;/span&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-action-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;查找任意节点&amp;lt;/strong&amp;gt;&amp;lt;small&amp;gt;搜索标签、职责、类型和稳定 ID。&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;            &amp;lt;kbd aria-hidden=&amp;quot;true&amp;quot;&amp;gt;/&amp;lt;/kbd&amp;gt;&#10;          &amp;lt;/button&amp;gt;&#10;          &amp;lt;button class=&amp;quot;diagram-guide-action&amp;quot; type=&amp;quot;button&amp;quot; data-guide-action=&amp;quot;route&amp;quot; aria-label=&amp;quot;追踪有向路径&amp;quot;&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-index&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;02&amp;lt;/span&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-action-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;追踪路径&amp;lt;/strong&amp;gt;&amp;lt;small&amp;gt;查看两个语义节点如何按编写方向连接。&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;            &amp;lt;kbd aria-hidden=&amp;quot;true&amp;quot;&amp;gt;R&amp;lt;/kbd&amp;gt;&#10;          &amp;lt;/button&amp;gt;&#10;          &amp;lt;button class=&amp;quot;diagram-guide-action&amp;quot; type=&amp;quot;button&amp;quot; data-guide-action=&amp;quot;map&amp;quot; aria-label=&amp;quot;查看完整系统&amp;quot;&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-index&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;03&amp;lt;/span&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-action-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;查看完整系统&amp;lt;/strong&amp;gt;&amp;lt;small&amp;gt;打开带实时视口和稳定节点的语义雷达。&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;            &amp;lt;kbd aria-hidden=&amp;quot;true&amp;quot;&amp;gt;M&amp;lt;/kbd&amp;gt;&#10;          &amp;lt;/button&amp;gt;&#10;          &amp;lt;button class=&amp;quot;diagram-guide-action&amp;quot; type=&amp;quot;button&amp;quot; data-guide-action=&amp;quot;lens&amp;quot; aria-label=&amp;quot;比较语义类型&amp;quot;&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-index&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;04&amp;lt;/span&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-action-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;比较语义类型&amp;lt;/strong&amp;gt;&amp;lt;small&amp;gt;统计角色、显示流量并比较直接编写的连接。&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;            &amp;lt;kbd aria-hidden=&amp;quot;true&amp;quot;&amp;gt;L&amp;lt;/kbd&amp;gt;&#10;          &amp;lt;/button&amp;gt;&#10;          &amp;lt;button class=&amp;quot;diagram-guide-action&amp;quot; type=&amp;quot;button&amp;quot; data-guide-action=&amp;quot;story&amp;quot; aria-label=&amp;quot;播放引导故事&amp;quot;&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-index&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;05&amp;lt;/span&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-action-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;播放引导故事&amp;lt;/strong&amp;gt;&amp;lt;small id=&amp;quot;diagram-guide-story-copy&amp;quot;&amp;gt;浏览已编写的章节和真实关系。&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;            &amp;lt;kbd aria-hidden=&amp;quot;true&amp;quot;&amp;gt;P&amp;lt;/kbd&amp;gt;&#10;          &amp;lt;/button&amp;gt;&#10;          &amp;lt;button class=&amp;quot;diagram-guide-action&amp;quot; type=&amp;quot;button&amp;quot; data-guide-action=&amp;quot;present&amp;quot; aria-label=&amp;quot;进入演示模式&amp;quot;&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-index&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;06&amp;lt;/span&amp;gt;&#10;            &amp;lt;span class=&amp;quot;diagram-guide-action-copy&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;进入演示模式&amp;lt;/strong&amp;gt;&amp;lt;small&amp;gt;让实时图表占满视口，同时不改变导出。&amp;lt;/small&amp;gt;&amp;lt;/span&amp;gt;&#10;            &amp;lt;kbd aria-hidden=&amp;quot;true&amp;quot;&amp;gt;F&amp;lt;/kbd&amp;gt;&#10;          &amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;diagram-guide-shortcuts&amp;quot; aria-label=&amp;quot;其他键盘快捷键&amp;quot;&amp;gt;&#10;          &amp;lt;span&amp;gt;&amp;lt;kbd&amp;gt;E&amp;lt;/kbd&amp;gt; 导出&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;kbd&amp;gt;T&amp;lt;/kbd&amp;gt; 主题&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;kbd&amp;gt;S&amp;lt;/kbd&amp;gt; 风格&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;kbd&amp;gt;0&amp;lt;/kbd&amp;gt; 重置&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;kbd&amp;gt;+&amp;lt;/kbd&amp;gt; 放大&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;kbd&amp;gt;-&amp;lt;/kbd&amp;gt; 缩小&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;&amp;lt;kbd&amp;gt;Esc&amp;lt;/kbd&amp;gt; 关闭&amp;lt;/span&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;p class=&amp;quot;diagram-guide-feedback&amp;quot; id=&amp;quot;diagram-guide-feedback&amp;quot; aria-live=&amp;quot;polite&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;      &amp;lt;div class=&amp;quot;node-finder no-print&amp;quot; id=&amp;quot;node-finder&amp;quot; hidden role=&amp;quot;dialog&amp;quot; aria-modal=&amp;quot;false&amp;quot; aria-labelledby=&amp;quot;node-finder-title&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;node-finder-head&amp;quot;&amp;gt;&#10;          &amp;lt;strong id=&amp;quot;node-finder-title&amp;quot;&amp;gt;查找节点&amp;lt;/strong&amp;gt;&#10;          &amp;lt;button class=&amp;quot;node-finder-close&amp;quot; id=&amp;quot;node-finder-close&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;关闭节点查找器&amp;quot;&amp;gt;&amp;amp;#215;&amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;node-finder-search&amp;quot;&amp;gt;&#10;          &amp;lt;span aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;amp;#8981;&amp;lt;/span&amp;gt;&#10;          &amp;lt;input class=&amp;quot;node-finder-input&amp;quot; id=&amp;quot;node-finder-input&amp;quot; type=&amp;quot;search&amp;quot; autocomplete=&amp;quot;off&amp;quot; spellcheck=&amp;quot;false&amp;quot; placeholder=&amp;quot;搜索标签或 ID&amp;quot; aria-label=&amp;quot;搜索图表节点&amp;quot; aria-describedby=&amp;quot;node-finder-status&amp;quot;&amp;gt;&#10;          &amp;lt;kbd aria-hidden=&amp;quot;true&amp;quot;&amp;gt;/&amp;lt;/kbd&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;node-finder-results&amp;quot; id=&amp;quot;node-finder-results&amp;quot; role=&amp;quot;group&amp;quot; aria-label=&amp;quot;图表节点&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;        &amp;lt;p class=&amp;quot;node-finder-empty&amp;quot; id=&amp;quot;node-finder-empty&amp;quot; hidden&amp;gt;没有匹配的节点&amp;lt;/p&amp;gt;&#10;        &amp;lt;p class=&amp;quot;node-finder-status&amp;quot; id=&amp;quot;node-finder-status&amp;quot; aria-live=&amp;quot;polite&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;      &amp;lt;div class=&amp;quot;focus-chip relationship-lens no-print&amp;quot; id=&amp;quot;focus-chip&amp;quot; hidden role=&amp;quot;region&amp;quot; aria-labelledby=&amp;quot;relationship-lens-title&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;relationship-lens-head&amp;quot;&amp;gt;&#10;          &amp;lt;div class=&amp;quot;relationship-lens-copy&amp;quot;&amp;gt;&#10;            &amp;lt;span class=&amp;quot;relationship-lens-eyebrow&amp;quot;&amp;gt;语义护照&amp;lt;/span&amp;gt;&#10;            &amp;lt;strong class=&amp;quot;relationship-lens-title&amp;quot; id=&amp;quot;relationship-lens-title&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;focus-label&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/strong&amp;gt;&#10;            &amp;lt;span class=&amp;quot;semantic-passport-detail&amp;quot; id=&amp;quot;focus-detail&amp;quot; hidden&amp;gt;&amp;lt;/span&amp;gt;&#10;            &amp;lt;div class=&amp;quot;semantic-passport-meta&amp;quot; id=&amp;quot;focus-passport-meta&amp;quot; aria-label=&amp;quot;节点元数据&amp;quot;&amp;gt;&#10;              &amp;lt;span id=&amp;quot;focus-kind&amp;quot; data-passport=&amp;quot;kind&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;              &amp;lt;span id=&amp;quot;focus-context&amp;quot; data-passport=&amp;quot;context&amp;quot; hidden&amp;gt;&amp;lt;/span&amp;gt;&#10;              &amp;lt;span id=&amp;quot;focus-tag&amp;quot; data-passport=&amp;quot;tag&amp;quot; hidden&amp;gt;&amp;lt;/span&amp;gt;&#10;              &amp;lt;span id=&amp;quot;focus-brand&amp;quot; data-passport=&amp;quot;brand&amp;quot; hidden&amp;gt;&amp;lt;/span&amp;gt;&#10;              &amp;lt;code id=&amp;quot;focus-id&amp;quot; data-passport=&amp;quot;id&amp;quot;&amp;gt;&amp;lt;/code&amp;gt;&#10;            &amp;lt;/div&amp;gt;&#10;            &amp;lt;div class=&amp;quot;semantic-passport-evidence&amp;quot; id=&amp;quot;focus-evidence&amp;quot; hidden aria-label=&amp;quot;已验证的源代码证据&amp;quot;&amp;gt;&#10;              &amp;lt;div class=&amp;quot;semantic-passport-evidence-head&amp;quot;&amp;gt;&#10;                &amp;lt;span class=&amp;quot;semantic-passport-evidence-status&amp;quot;&amp;gt;已验证来源&amp;lt;/span&amp;gt;&#10;                &amp;lt;a class=&amp;quot;semantic-passport-repository&amp;quot; id=&amp;quot;focus-repository&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener noreferrer&amp;quot; referrerpolicy=&amp;quot;no-referrer&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#10;              &amp;lt;/div&amp;gt;&#10;              &amp;lt;div class=&amp;quot;semantic-passport-evidence-links&amp;quot; id=&amp;quot;focus-evidence-links&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;            &amp;lt;/div&amp;gt;&#10;            &amp;lt;span class=&amp;quot;relationship-lens-summary&amp;quot; id=&amp;quot;focus-summary&amp;quot; aria-live=&amp;quot;polite&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;            &amp;lt;div class=&amp;quot;semantic-passport-reach&amp;quot; id=&amp;quot;focus-reach&amp;quot; hidden&amp;gt;&#10;              &amp;lt;span class=&amp;quot;semantic-passport-reach-label&amp;quot;&amp;gt;编写可达范围&amp;lt;/span&amp;gt;&#10;              &amp;lt;div class=&amp;quot;semantic-passport-reach-actions&amp;quot; role=&amp;quot;group&amp;quot; aria-label=&amp;quot;追踪编写的可达性&amp;quot;&amp;gt;&#10;                &amp;lt;button id=&amp;quot;btn-reach-upstream&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;追踪上游编写可达性&amp;quot; aria-pressed=&amp;quot;false&amp;quot;&amp;gt;&#10;                  &amp;lt;span&amp;gt;上游&amp;lt;/span&amp;gt;&amp;lt;strong id=&amp;quot;focus-reach-upstream-count&amp;quot;&amp;gt;0&amp;lt;/strong&amp;gt;&#10;                &amp;lt;/button&amp;gt;&#10;                &amp;lt;button id=&amp;quot;btn-reach-downstream&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;追踪下游编写可达性&amp;quot; aria-pressed=&amp;quot;false&amp;quot;&amp;gt;&#10;                  &amp;lt;span&amp;gt;下游&amp;lt;/span&amp;gt;&amp;lt;strong id=&amp;quot;focus-reach-downstream-count&amp;quot;&amp;gt;0&amp;lt;/strong&amp;gt;&#10;                &amp;lt;/button&amp;gt;&#10;              &amp;lt;/div&amp;gt;&#10;              &amp;lt;small class=&amp;quot;semantic-passport-reach-status&amp;quot; id=&amp;quot;focus-reach-status&amp;quot; hidden aria-live=&amp;quot;polite&amp;quot;&amp;gt;&amp;lt;/small&amp;gt;&#10;            &amp;lt;/div&amp;gt;&#10;          &amp;lt;/div&amp;gt;&#10;          &amp;lt;div class=&amp;quot;relationship-lens-actions&amp;quot;&amp;gt;&#10;            &amp;lt;button id=&amp;quot;btn-focus-clear&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;关闭语义护照&amp;quot; title=&amp;quot;关闭&amp;quot;&amp;gt;&amp;amp;#215;&amp;lt;/button&amp;gt;&#10;            &amp;lt;button id=&amp;quot;btn-focus-copy&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;复制聚焦节点的链接&amp;quot;&amp;gt;复制链接&amp;lt;/button&amp;gt;&#10;            &amp;lt;button id=&amp;quot;btn-focus-relations&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;显示关联关系&amp;quot; aria-expanded=&amp;quot;false&amp;quot; aria-controls=&amp;quot;relationship-lens-list&amp;quot;&amp;gt;关系&amp;lt;/button&amp;gt;&#10;          &amp;lt;/div&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;relationship-lens-list&amp;quot; id=&amp;quot;relationship-lens-list&amp;quot; aria-label=&amp;quot;关联关系&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;      &amp;lt;div class=&amp;quot;route-probe no-print&amp;quot; id=&amp;quot;route-probe&amp;quot; hidden role=&amp;quot;region&amp;quot; aria-labelledby=&amp;quot;route-probe-title&amp;quot; data-state=&amp;quot;idle&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;route-probe-head&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;route-probe-copy&amp;quot;&amp;gt;&#10;            &amp;lt;span class=&amp;quot;route-probe-eyebrow&amp;quot;&amp;gt;路径探测&amp;lt;/span&amp;gt;&#10;            &amp;lt;strong class=&amp;quot;route-probe-title&amp;quot; id=&amp;quot;route-probe-title&amp;quot;&amp;gt;选择起点节点&amp;lt;/strong&amp;gt;&#10;          &amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;route-probe-actions&amp;quot;&amp;gt;&#10;            &amp;lt;button class=&amp;quot;route-probe-find&amp;quot; id=&amp;quot;route-probe-find&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;查找路径起点&amp;quot; data-node-finder-trigger&amp;gt;查找起点&amp;lt;/button&amp;gt;&#10;            &amp;lt;button class=&amp;quot;route-probe-copy-link&amp;quot; id=&amp;quot;route-probe-copy&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;复制已追踪路径的链接&amp;quot; hidden&amp;gt;复制链接&amp;lt;/button&amp;gt;&#10;            &amp;lt;button id=&amp;quot;route-probe-clear&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;清除路径探测&amp;quot;&amp;gt;清除&amp;lt;/button&amp;gt;&#10;          &amp;lt;/span&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;route-probe-path&amp;quot; id=&amp;quot;route-probe-path&amp;quot; aria-label=&amp;quot;已追踪路径&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;route-probe-placeholder&amp;quot;&amp;gt;在图表中选择两个语义节点&amp;lt;/span&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;route-journey-controls&amp;quot; id=&amp;quot;route-journey-controls&amp;quot; hidden role=&amp;quot;group&amp;quot; aria-label=&amp;quot;路径旅程控制&amp;quot; data-playing=&amp;quot;false&amp;quot;&amp;gt;&#10;          &amp;lt;button id=&amp;quot;route-journey-prev&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;上一个路径位置&amp;quot; title=&amp;quot;上一个路径位置&amp;quot;&amp;gt;&amp;amp;#8592;&amp;lt;/button&amp;gt;&#10;          &amp;lt;button class=&amp;quot;route-journey-play&amp;quot; id=&amp;quot;route-journey-play&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;播放路径旅程&amp;quot; aria-pressed=&amp;quot;false&amp;quot; title=&amp;quot;播放路径旅程&amp;quot;&amp;gt;&#10;            &amp;lt;span id=&amp;quot;route-journey-play-icon&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;amp;#9654;&amp;lt;/span&amp;gt;&#10;            &amp;lt;span id=&amp;quot;route-journey-play-label&amp;quot;&amp;gt;旅程&amp;lt;/span&amp;gt;&#10;          &amp;lt;/button&amp;gt;&#10;          &amp;lt;button id=&amp;quot;route-journey-next&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;下一个路径位置&amp;quot; title=&amp;quot;下一个路径位置&amp;quot;&amp;gt;&amp;amp;#8594;&amp;lt;/button&amp;gt;&#10;          &amp;lt;button class=&amp;quot;route-journey-overview&amp;quot; id=&amp;quot;route-journey-overview&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;显示完整路径总览&amp;quot; title=&amp;quot;显示完整路径总览&amp;quot;&amp;gt;总览&amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;small class=&amp;quot;route-probe-status&amp;quot; id=&amp;quot;route-probe-status&amp;quot; aria-live=&amp;quot;polite&amp;quot;&amp;gt;先选择来源，再选择目标；方向很重要。&amp;lt;/small&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;      &amp;lt;div class=&amp;quot;semantic-lens no-print&amp;quot; id=&amp;quot;semantic-lens&amp;quot; hidden role=&amp;quot;dialog&amp;quot; aria-modal=&amp;quot;false&amp;quot; aria-labelledby=&amp;quot;semantic-lens-title&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;semantic-lens-head&amp;quot;&amp;gt;&#10;          &amp;lt;span&amp;gt;&#10;            &amp;lt;span class=&amp;quot;semantic-lens-eyebrow&amp;quot;&amp;gt;语义透镜&amp;lt;/span&amp;gt;&#10;            &amp;lt;strong class=&amp;quot;semantic-lens-title&amp;quot; id=&amp;quot;semantic-lens-title&amp;quot;&amp;gt;比较系统角色&amp;lt;/strong&amp;gt;&#10;          &amp;lt;/span&amp;gt;&#10;          &amp;lt;button class=&amp;quot;semantic-lens-close&amp;quot; id=&amp;quot;semantic-lens-close&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;关闭语义透镜&amp;quot;&amp;gt;&amp;amp;#215;&amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;p class=&amp;quot;semantic-lens-instruction&amp;quot;&amp;gt;最多选择两种语义类型。选择一种可显示其真实流量；选择两种只比较直接编写的关系。&amp;lt;/p&amp;gt;&#10;        &amp;lt;div class=&amp;quot;semantic-lens-kinds&amp;quot; id=&amp;quot;semantic-lens-kinds&amp;quot; role=&amp;quot;group&amp;quot; aria-label=&amp;quot;语义类型&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;        &amp;lt;p class=&amp;quot;semantic-lens-status&amp;quot; id=&amp;quot;semantic-lens-status&amp;quot; aria-live=&amp;quot;polite&amp;quot;&amp;gt;选择一种类型以检查其节点和相连关系。&amp;lt;/p&amp;gt;&#10;        &amp;lt;div class=&amp;quot;semantic-lens-actions&amp;quot;&amp;gt;&#10;          &amp;lt;button id=&amp;quot;semantic-lens-copy&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;复制语义透镜链接&amp;quot; hidden&amp;gt;复制链接&amp;lt;/button&amp;gt;&#10;          &amp;lt;button id=&amp;quot;semantic-lens-clear&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;清除语义透镜&amp;quot;&amp;gt;清除&amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;      &amp;lt;div class=&amp;quot;overview-map no-print&amp;quot; id=&amp;quot;overview-map&amp;quot; hidden role=&amp;quot;region&amp;quot; aria-labelledby=&amp;quot;overview-map-title&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;overview-map-head&amp;quot;&amp;gt;&#10;          &amp;lt;span class=&amp;quot;overview-map-live&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#10;          &amp;lt;span class=&amp;quot;overview-map-copy&amp;quot;&amp;gt;&#10;            &amp;lt;strong id=&amp;quot;overview-map-title&amp;quot;&amp;gt;语义雷达&amp;lt;/strong&amp;gt;&#10;            &amp;lt;small id=&amp;quot;overview-map-status&amp;quot; aria-live=&amp;quot;polite&amp;quot;&amp;gt;正在构建总览&amp;lt;/small&amp;gt;&#10;          &amp;lt;/span&amp;gt;&#10;          &amp;lt;button class=&amp;quot;overview-map-expand&amp;quot; id=&amp;quot;overview-map-expand&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;打开完整语义雷达&amp;quot;&amp;gt;打开雷达&amp;lt;/button&amp;gt;&#10;          &amp;lt;button class=&amp;quot;overview-map-close&amp;quot; id=&amp;quot;overview-map-close&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;关闭语义雷达&amp;quot;&amp;gt;&amp;amp;#215;&amp;lt;/button&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;overview-map-surface&amp;quot; id=&amp;quot;overview-map-surface&amp;quot; tabindex=&amp;quot;0&amp;quot; role=&amp;quot;group&amp;quot; aria-label=&amp;quot;图表总览。点击节点进行聚焦，或使用方向键平移。&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;        &amp;lt;div class=&amp;quot;overview-map-hint&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;span&amp;gt;点击节点&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt;拖动平移&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;      &amp;lt;p class=&amp;quot;overview-map-feedback no-print&amp;quot; id=&amp;quot;overview-map-feedback&amp;quot; role=&amp;quot;status&amp;quot; aria-live=&amp;quot;polite&amp;quot; hidden&amp;gt;语义雷达需要更多地图可见空间。&amp;lt;/p&amp;gt;&#10;      &amp;lt;div class=&amp;quot;diagram-nav no-print&amp;quot; role=&amp;quot;toolbar&amp;quot; aria-label=&amp;quot;图表视图控制&amp;quot;&amp;gt;&#10;        &amp;lt;button id=&amp;quot;btn-route-probe&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;追踪有向路径&amp;quot; aria-pressed=&amp;quot;false&amp;quot; aria-controls=&amp;quot;route-probe&amp;quot; title=&amp;quot;追踪路径（R）&amp;quot;&amp;gt;路径&amp;lt;/button&amp;gt;&#10;        &amp;lt;button id=&amp;quot;btn-overview-map&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;打开语义雷达&amp;quot; aria-expanded=&amp;quot;false&amp;quot; aria-controls=&amp;quot;overview-map&amp;quot; title=&amp;quot;语义雷达（M）&amp;quot;&amp;gt;地图&amp;lt;/button&amp;gt;&#10;        &amp;lt;button id=&amp;quot;btn-semantic-lens&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;打开语义透镜&amp;quot; aria-haspopup=&amp;quot;dialog&amp;quot; aria-expanded=&amp;quot;false&amp;quot; aria-pressed=&amp;quot;false&amp;quot; aria-controls=&amp;quot;semantic-lens&amp;quot; title=&amp;quot;语义透镜（L）&amp;quot;&amp;gt;透镜&amp;lt;/button&amp;gt;&#10;        &amp;lt;button id=&amp;quot;btn-node-finder&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;查找节点&amp;quot; aria-haspopup=&amp;quot;dialog&amp;quot; aria-expanded=&amp;quot;false&amp;quot; aria-controls=&amp;quot;node-finder&amp;quot; title=&amp;quot;查找节点（/）&amp;quot; data-node-finder-trigger&amp;gt;&amp;lt;span class=&amp;quot;diagram-nav-icon find&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;        &amp;lt;button id=&amp;quot;btn-diagram-guide&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;打开图表指南&amp;quot; aria-haspopup=&amp;quot;dialog&amp;quot; aria-expanded=&amp;quot;false&amp;quot; aria-controls=&amp;quot;diagram-guide&amp;quot; title=&amp;quot;图表指南（?）&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;diagram-nav-icon guide&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;        &amp;lt;button data-view=&amp;quot;out&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;缩小&amp;quot; title=&amp;quot;缩小（-）&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;diagram-nav-icon minus&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;        &amp;lt;button data-view=&amp;quot;reset&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;重置图表视图&amp;quot; title=&amp;quot;重置视图（0）&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;diagram-nav-detail&amp;quot; data-view-detail hidden&amp;gt;阅读&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;diagram-nav-percent&amp;quot; data-view-percent&amp;gt;100%&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;        &amp;lt;button data-view=&amp;quot;in&amp;quot; type=&amp;quot;button&amp;quot; aria-label=&amp;quot;放大&amp;quot; title=&amp;quot;放大（+）&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;diagram-nav-icon plus&amp;quot; aria-hidden=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/button&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;    &amp;lt;/div&amp;gt;&#10;&#10;    &amp;lt;!-- Info Cards --&amp;gt;&#10;    &amp;lt;div class=&amp;quot;cards&amp;quot;&amp;gt;&#10;      &amp;lt;div class=&amp;quot;card&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;card-header&amp;quot;&amp;gt;&#10;          &amp;lt;div class=&amp;quot;card-dot cyan&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;          &amp;lt;h3&amp;gt;衡量结果&amp;lt;/h3&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;ul&amp;gt;&#10;          &amp;lt;li&amp;gt;&amp;amp;bull; TTFT / TPOT / P99 / Goodput&amp;lt;/li&amp;gt;&#10;          &amp;lt;li&amp;gt;&amp;amp;bull; 队列、调度、执行与网络共同影响延迟&amp;lt;/li&amp;gt;&#10;        &amp;lt;/ul&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;&#10;      &amp;lt;div class=&amp;quot;card&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;card-header&amp;quot;&amp;gt;&#10;          &amp;lt;div class=&amp;quot;card-dot emerald&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;          &amp;lt;h3&amp;gt;优化边界&amp;lt;/h3&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;ul&amp;gt;&#10;          &amp;lt;li&amp;gt;&amp;amp;bull; 分页管内存；前缀复用省预填充&amp;lt;/li&amp;gt;&#10;          &amp;lt;li&amp;gt;&amp;amp;bull; FlashAttention 减少显存读写&amp;lt;/li&amp;gt;&#10;        &amp;lt;/ul&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;&#10;      &amp;lt;div class=&amp;quot;card&amp;quot;&amp;gt;&#10;        &amp;lt;div class=&amp;quot;card-header&amp;quot;&amp;gt;&#10;          &amp;lt;div class=&amp;quot;card-dot amber&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#10;          &amp;lt;h3&amp;gt;概念架构&amp;lt;/h3&amp;gt;&#10;        &amp;lt;/div&amp;gt;&#10;        &amp;lt;ul&amp;gt;&#10;          &amp;lt;li&amp;gt;&amp;amp;bull; 箭头展示主链路与调用关系&amp;lt;/li&amp;gt;&#10;          &amp;lt;li&amp;gt;&amp;amp;bull; 未展开反馈循环、TP 子组和监控旁路&amp;lt;/li&amp;gt;&#10;        &amp;lt;/ul&amp;gt;&#10;      &amp;lt;/div&amp;gt;&#10;    &amp;lt;/div&amp;gt;&#10;&#10;  &amp;lt;/div&amp;gt;&#10;&#10;  &amp;lt;script&amp;gt;&#10;    var Archify = {};&#10;    var archifyI18nData = (function () {&#10;      var node = document.getElementById(&amp;#x27;archify-i18n-data&amp;#x27;);&#10;      try { return JSON.parse(node ? node.textContent : &amp;#x27;{}&amp;#x27;); }&#10;      catch (_) { return { locale: &amp;#x27;en&amp;#x27;, messages: {} }; }&#10;    })();&#10;    Archify.locale = archifyI18nData.locale || &amp;#x27;en&amp;#x27;;&#10;&#10;    function viewerText(key, values) {&#10;      var messages = archifyI18nData.messages || {};&#10;      var template = Object.prototype.hasOwnProperty.call(messages, key) ? messages[key] : key;&#10;      return String(template).replace(/\{([a-zA-Z0-9_]+)\}/g, function (match, name) {&#10;        return values &amp;amp;&amp;amp; Object.prototype.hasOwnProperty.call(values, name) ? String(values[name]) : match;&#10;      });&#10;    }&#10;&#10;    function viewerCount(key, count, values) {&#10;      var suffix = Number(count) === 1 ? &amp;#x27;.one&amp;#x27; : &amp;#x27;.other&amp;#x27;;&#10;      var payload = Object.assign({}, values || {}, { count: count });&#10;      return viewerText(key + suffix, payload);&#10;    }&#10;&#10;    function viewerKindLabel(value) {&#10;      var normalized = String(value || &amp;#x27;node&amp;#x27;).toLowerCase();&#10;      var knownKey = &amp;#x27;viewer.kind.&amp;#x27; + normalized;&#10;      var known = viewerText(knownKey);&#10;      if (known !== knownKey) return known;&#10;      return normalized&#10;        .replace(/messagebus/gi, &amp;#x27;message bus&amp;#x27;)&#10;        .replace(/[-_]+/g, &amp;#x27; &amp;#x27;)&#10;        .replace(/\b\w/g, function (letter) { return letter.toUpperCase(); });&#10;    }&#10;&#10;    function hasDrawableGeometry(element) {&#10;      if (!element) return false;&#10;      var geometries = /^(path|line|polyline)$/i.test(element.tagName)&#10;        ? [element]&#10;        : Array.prototype.slice.call(element.querySelectorAll(&amp;#x27;path, line, polyline&amp;#x27;));&#10;      return geometries.some(function (geometry) {&#10;        var source = geometry.tagName.toLowerCase() === &amp;#x27;path&amp;#x27;&#10;          ? geometry.getAttribute(&amp;#x27;d&amp;#x27;)&#10;          : geometry.tagName.toLowerCase() === &amp;#x27;polyline&amp;#x27;&#10;            ? geometry.getAttribute(&amp;#x27;points&amp;#x27;)&#10;            : [geometry.getAttribute(&amp;#x27;x1&amp;#x27;), geometry.getAttribute(&amp;#x27;y1&amp;#x27;), geometry.getAttribute(&amp;#x27;x2&amp;#x27;), geometry.getAttribute(&amp;#x27;y2&amp;#x27;)].join(&amp;#x27; &amp;#x27;);&#10;        if (!source || /(?:^|[^a-z])(?:nan|infinity)(?:[^a-z]|$)/i.test(source) || typeof geometry.getTotalLength !== &amp;#x27;function&amp;#x27;) return false;&#10;        try {&#10;          var length = Number(geometry.getTotalLength());&#10;          return Number.isFinite(length) &amp;amp;&amp;amp; length &amp;gt; 0;&#10;        } catch (_) {&#10;          return false;&#10;        }&#10;      });&#10;    }&#10;&#10;    /* ============================================================&#10;       Visual style try-on — one topology, four bundled presets.&#10;       The reader&amp;#x27;s choice is intentionally session-only: it updates the&#10;       live page and canonical SVG together, but never rewrites the source,&#10;       URL, or a later diagram&amp;#x27;s authored default.&#10;       ============================================================ */&#10;    Archify.preset = (function () {&#10;      var PRESETS = [&amp;#x27;classic&amp;#x27;, &amp;#x27;signal-flow&amp;#x27;, &amp;#x27;blueprint&amp;#x27;, &amp;#x27;editorial&amp;#x27;];&#10;      var LABELS = {&#10;        classic: viewerText(&amp;#x27;viewer.preset.classic.short&amp;#x27;),&#10;        &amp;#x27;signal-flow&amp;#x27;: viewerText(&amp;#x27;viewer.preset.flow.short&amp;#x27;),&#10;        blueprint: viewerText(&amp;#x27;viewer.preset.blueprint&amp;#x27;),&#10;        editorial: viewerText(&amp;#x27;viewer.preset.editorial&amp;#x27;)&#10;      };&#10;      var html = document.documentElement;&#10;      var svg = document.querySelector(&amp;#x27;.diagram-container svg&amp;#x27;);&#10;      var btn = document.getElementById(&amp;#x27;btn-preset&amp;#x27;);&#10;      var label = document.getElementById(&amp;#x27;preset-label&amp;#x27;);&#10;      var menu = document.getElementById(&amp;#x27;preset-menu&amp;#x27;);&#10;      var options = function () {&#10;        return Array.prototype.slice.call(menu.querySelectorAll(&amp;#x27;[data-preset-value]&amp;#x27;));&#10;      };&#10;      var authored = PRESETS.indexOf(html.getAttribute(&amp;#x27;data-preset&amp;#x27;)) &amp;gt;= 0&#10;        ? html.getAttribute(&amp;#x27;data-preset&amp;#x27;)&#10;        : &amp;#x27;classic&amp;#x27;;&#10;&#10;      function current() {&#10;        var value = html.getAttribute(&amp;#x27;data-preset&amp;#x27;);&#10;        return PRESETS.indexOf(value) &amp;gt;= 0 ? value : authored;&#10;      }&#10;      function nextAfter(preset) {&#10;        return PRESETS[(PRESETS.indexOf(preset) + 1) % PRESETS.length];&#10;      }&#10;      function apply(preset) {&#10;        if (html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        if (PRESETS.indexOf(preset) &amp;lt; 0) return false;&#10;        html.setAttribute(&amp;#x27;data-preset&amp;#x27;, preset);&#10;        svg.setAttribute(&amp;#x27;data-preset&amp;#x27;, preset);&#10;        btn.setAttribute(&amp;#x27;data-preset-option&amp;#x27;, preset);&#10;        label.textContent = LABELS[preset];&#10;        btn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.preset.current&amp;#x27;, { style: LABELS[preset] }));&#10;        btn.title = viewerText(&amp;#x27;viewer.preset.choose.title&amp;#x27;);&#10;        options().forEach(function (option) {&#10;          var selected = option.getAttribute(&amp;#x27;data-preset-value&amp;#x27;) === preset;&#10;          option.setAttribute(&amp;#x27;aria-checked&amp;#x27;, String(selected));&#10;        });&#10;        return true;&#10;      }&#10;      function cycle() { return apply(nextAfter(current())); }&#10;&#10;      function isOpen() { return menu.classList.contains(&amp;#x27;open&amp;#x27;); }&#10;      function open(focusLast) {&#10;        if (html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        if (Archify.exportMenu &amp;amp;&amp;amp; Archify.exportMenu.isOpen()) Archify.exportMenu.close(false);&#10;        menu.classList.add(&amp;#x27;open&amp;#x27;);&#10;        btn.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        var available = options();&#10;        var selected = available.find(function (option) { return option.getAttribute(&amp;#x27;aria-checked&amp;#x27;) === &amp;#x27;true&amp;#x27;; });&#10;        var target = focusLast ? available[available.length - 1] : (selected || available[0]);&#10;        if (target) target.focus();&#10;        return true;&#10;      }&#10;      function close(focusTrigger) {&#10;        menu.classList.remove(&amp;#x27;open&amp;#x27;);&#10;        btn.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        if (focusTrigger) btn.focus();&#10;        return false;&#10;      }&#10;&#10;      apply(authored);&#10;      btn.addEventListener(&amp;#x27;click&amp;#x27;, function (e) {&#10;        e.stopPropagation();&#10;        if (isOpen()) close(false);&#10;        else open(false);&#10;      });&#10;      btn.addEventListener(&amp;#x27;keydown&amp;#x27;, function (e) {&#10;        if (e.key === &amp;#x27;ArrowDown&amp;#x27; || e.key === &amp;#x27;ArrowUp&amp;#x27;) {&#10;          e.preventDefault();&#10;          if (!isOpen()) open(e.key === &amp;#x27;ArrowUp&amp;#x27;);&#10;        }&#10;      });&#10;      document.addEventListener(&amp;#x27;click&amp;#x27;, function (e) {&#10;        if (!menu.contains(e.target) &amp;amp;&amp;amp; e.target !== btn) close(false);&#10;      });&#10;      menu.addEventListener(&amp;#x27;click&amp;#x27;, function (e) {&#10;        var option = e.target.closest(&amp;#x27;[data-preset-value]&amp;#x27;);&#10;        if (!option || !menu.contains(option)) return;&#10;        if (apply(option.getAttribute(&amp;#x27;data-preset-value&amp;#x27;))) close(true);&#10;      });&#10;      menu.addEventListener(&amp;#x27;keydown&amp;#x27;, function (e) {&#10;        if (e.key === &amp;#x27;Escape&amp;#x27;) { e.preventDefault(); close(true); return; }&#10;        if (e.key === &amp;#x27;Tab&amp;#x27;) { close(false); return; }&#10;        var available = options();&#10;        var active = available.indexOf(document.activeElement);&#10;        switch (e.key) {&#10;          case &amp;#x27;ArrowDown&amp;#x27;:&#10;            e.preventDefault();&#10;            if (available.length) available[(active + 1 + available.length) % available.length].focus();&#10;            break;&#10;          case &amp;#x27;ArrowUp&amp;#x27;:&#10;            e.preventDefault();&#10;            if (available.length) available[(active - 1 + available.length) % available.length].focus();&#10;            break;&#10;          case &amp;#x27;Home&amp;#x27;:&#10;            e.preventDefault();&#10;            if (available[0]) available[0].focus();&#10;            break;&#10;          case &amp;#x27;End&amp;#x27;:&#10;            e.preventDefault();&#10;            if (available.length) available[available.length - 1].focus();&#10;            break;&#10;        }&#10;      });&#10;      return { cycle: cycle, apply: apply, current: current, authored: authored, open: open, close: close, isOpen: isOpen };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Theme toggle — persists to localStorage, respects system pref&#10;       ============================================================ */&#10;&#10;    Archify.theme = (function () {&#10;      var STORAGE_KEY = &amp;#x27;archify-theme&amp;#x27;;&#10;      var html = document.documentElement;&#10;      var btn = document.getElementById(&amp;#x27;btn-theme&amp;#x27;);&#10;      var label = document.getElementById(&amp;#x27;theme-label&amp;#x27;);&#10;&#10;      // localStorage can throw (blocked cookies, sandboxed iframes); the whole&#10;      // script element dies on an uncaught error, so guard every access.&#10;      function readStored() {&#10;        try { return localStorage.getItem(STORAGE_KEY); } catch (_) { return null; }&#10;      }&#10;      function writeStored(value) {&#10;        try { localStorage.setItem(STORAGE_KEY, value); } catch (_) {}&#10;      }&#10;      function urlOverride() {&#10;        // URL param wins (useful for deterministic screenshots / share links)&#10;        try {&#10;          var param = new URLSearchParams(window.location.search).get(&amp;#x27;theme&amp;#x27;);&#10;          if (param === &amp;#x27;light&amp;#x27; || param === &amp;#x27;dark&amp;#x27;) return param;&#10;        } catch (_) {}&#10;        return null;&#10;      }&#10;&#10;      function resolveInitial() {&#10;        var fromUrl = urlOverride();&#10;        if (fromUrl) return fromUrl;&#10;        var saved = readStored();&#10;        if (saved === &amp;#x27;light&amp;#x27; || saved === &amp;#x27;dark&amp;#x27;) return saved;&#10;        return window.matchMedia(&amp;#x27;(prefers-color-scheme: light)&amp;#x27;).matches ? &amp;#x27;light&amp;#x27; : &amp;#x27;dark&amp;#x27;;&#10;      }&#10;&#10;      function apply(theme) {&#10;        html.setAttribute(&amp;#x27;data-theme&amp;#x27;, theme);&#10;        label.textContent = viewerText(theme === &amp;#x27;dark&amp;#x27; ? &amp;#x27;viewer.theme.dark&amp;#x27; : &amp;#x27;viewer.theme.light&amp;#x27;);&#10;        btn.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, theme === &amp;#x27;light&amp;#x27; ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;      }&#10;&#10;      function toggle() {&#10;        var next = html.getAttribute(&amp;#x27;data-theme&amp;#x27;) === &amp;#x27;dark&amp;#x27; ? &amp;#x27;light&amp;#x27; : &amp;#x27;dark&amp;#x27;;&#10;        apply(next);&#10;        writeStored(next);&#10;      }&#10;&#10;      apply(resolveInitial());&#10;      btn.addEventListener(&amp;#x27;click&amp;#x27;, toggle);&#10;&#10;      // Follow live OS theme changes while the user has no explicit preference.&#10;      try {&#10;        var media = window.matchMedia(&amp;#x27;(prefers-color-scheme: light)&amp;#x27;);&#10;        var onChange = function (e) {&#10;          var saved = readStored();&#10;          if (urlOverride() || saved === &amp;#x27;light&amp;#x27; || saved === &amp;#x27;dark&amp;#x27;) return;&#10;          apply(e.matches ? &amp;#x27;light&amp;#x27; : &amp;#x27;dark&amp;#x27;);&#10;        };&#10;        if (media.addEventListener) media.addEventListener(&amp;#x27;change&amp;#x27;, onChange);&#10;        else if (media.addListener) media.addListener(onChange);&#10;      } catch (_) {}&#10;&#10;      return { toggle: toggle };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Export — Share Card / PNG / JPEG / WebP / SVG / WebM and clipboard&#10;&#10;       Raster exports are always rendered at 4x source resolution for&#10;       maximum sharpness. The trick: we set the serialized SVG&amp;#x27;s&#10;       `width`/`height` to viewBox * 4 so the browser rasterizes the&#10;       vectors at that resolution natively. drawImage then draws at&#10;       the image&amp;#x27;s natural size (no upscaling = no blur).&#10;&#10;       JPEG/WebP paint the current theme&amp;#x27;s background explicitly since&#10;       those formats have no alpha channel.&#10;       ============================================================ */&#10;    (function () {&#10;      var RASTER_SCALE = 4;&#10;      var MOTION_DURATION = 6000;&#10;      var MOTION_FPS = 30;&#10;      var SHARE_CARD_WIDTH = 1200;&#10;      var SHARE_CARD_HEIGHT = 630;&#10;      var SHARE_CARD_PADDING = 36;&#10;      var SHARE_CARD_HEADER = 112;&#10;&#10;      function exportError(key, values) {&#10;        var error = new Error(viewerText(key, values));&#10;        error.archifyViewerMessage = true;&#10;        return error;&#10;      }&#10;&#10;      function exportMessage(error) {&#10;        return error &amp;amp;&amp;amp; error.archifyViewerMessage&#10;          ? error.message&#10;          : viewerText(&amp;#x27;viewer.export.unknown&amp;#x27;);&#10;      }&#10;&#10;      function diagramFilename() {&#10;        var title = (document.title || &amp;#x27;diagram&amp;#x27;)&#10;          .replace(/\s+Architecture(\s+Diagram)?$/i, &amp;#x27;&amp;#x27;)&#10;          .replace(/\s+Diagram$/i, &amp;#x27;&amp;#x27;)&#10;          .trim();&#10;        return title.replace(/[^a-z0-9_\-]+/gi, &amp;#x27;-&amp;#x27;)&#10;                    .toLowerCase()&#10;                    .replace(/^-+|-+$/g, &amp;#x27;&amp;#x27;) || &amp;#x27;diagram&amp;#x27;;&#10;      }&#10;&#10;      function currentBg() {&#10;        return getComputedStyle(document.body).backgroundColor || &amp;#x27;#ffffff&amp;#x27;;&#10;      }&#10;&#10;      function cleanExportClone(clone) {&#10;        // View transforms and neighborhood focus are HTML exploration state,&#10;        // never part of a downloaded full-diagram artifact.&#10;        clone.style.removeProperty(&amp;#x27;transform&amp;#x27;);&#10;        clone.style.removeProperty(&amp;#x27;clip-path&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-view-scale&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-focus-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-reach-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-lens-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-lens-flow-count&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-lens-flow-density&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-legend-preview-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-relationship-preview-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-relationship-direct-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-relationship-pin-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-intent-trace-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-route-picking&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-route-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-route-journey&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-share-route&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-share-reach&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-story-active&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-story-playing&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-story-beat&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-story-next&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-story-follow&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-chapter-handoff&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-chapter-anchor&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-chapter-preview&amp;#x27;);&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-chapter-handoff-overlay]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-chapter-role]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-chapter-role&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-chapter-preview-role]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-chapter-preview-role&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-story-overlay], [data-story-carrier-overlay]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-intent-trace-overlay]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-route-probe-overlay]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-route-journey-overlay]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-semantic-lens-overlay]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-legend-bridge-runtime]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-legend-kind]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-legend-kind&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-legend-label&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-legend-count&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-legend-zero&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-legend-selected&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;role&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;tabindex&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;aria-pressed&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;aria-haspopup&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;aria-controls&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;aria-expanded&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-legend-bridge]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-legend-bridge&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;role&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-relationship-pulse-overlay]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-relationship-hit-overlay]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-source-evidence-beacon]&amp;#x27;), function (el) {&#10;          el.remove();&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-source-evidence-count]&amp;#x27;), function (el) {&#10;          var originalLabel = el.getAttribute(&amp;#x27;data-source-evidence-original-label&amp;#x27;);&#10;          if (originalLabel == null || originalLabel === &amp;#x27;&amp;#x27;) el.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;          else el.setAttribute(&amp;#x27;aria-label&amp;#x27;, originalLabel);&#10;          el.removeAttribute(&amp;#x27;data-source-evidence-count&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-source-evidence-original-label&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-story-step], [data-story-beat-state], [data-story-beat-step]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-story-step&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-story-beat-state&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-story-beat-step&amp;#x27;);&#10;          el.style.removeProperty(&amp;#x27;--story-step&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-focus-match], [data-focus-selected]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-focus-match&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-focus-selected&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-reach-match], [data-reach-origin], [data-reach-depth]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-reach-match&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-reach-origin&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-reach-depth&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-lens-match], [data-lens-selected], [data-lens-peer]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-lens-match&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-lens-selected&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-lens-peer&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-legend-preview-match], [data-legend-preview-selected], [data-legend-preview-peer]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-legend-preview-match&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-legend-preview-selected&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-legend-preview-peer&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-relationship-preview], [data-relationship-preview-node], [data-relationship-preview-source], [data-relationship-preview-target]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-relationship-preview&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-relationship-preview-node&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-relationship-preview-source&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-relationship-preview-target&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-intent-trace-match], [data-intent-trace-selected]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-intent-trace-match&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-intent-trace-selected&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-route-match], [data-route-start], [data-route-end], [data-route-step], [data-route-candidate], [data-route-journey-state], [data-route-journey-current]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-route-match&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-route-start&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-route-end&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-route-step&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-route-candidate&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-route-journey-state&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-route-journey-current&amp;#x27;);&#10;          el.style.removeProperty(&amp;#x27;--route-step&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-share-route-match], [data-share-route-step], [data-share-route-start], [data-share-route-end], [data-share-route-middle]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-share-route-match&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-share-route-step&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-share-route-start&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-share-route-end&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-share-route-middle&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-share-reach-match], [data-share-reach-origin], [data-share-reach-depth]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-share-reach-match&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-share-reach-origin&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-share-reach-depth&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-detail], [data-detail-anchor]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-detail&amp;#x27;);&#10;          el.removeAttribute(&amp;#x27;data-detail-anchor&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-node-id][aria-pressed]&amp;#x27;), function (el) {&#10;          el.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        });&#10;        return !clone.hasAttribute(&amp;#x27;data-view-scale&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-focus-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-reach-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-lens-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-lens-flow-count&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-lens-flow-density&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-legend-preview-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-relationship-preview-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-relationship-direct-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-intent-trace-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-route-picking&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-route-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-route-journey&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-share-route&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-share-reach&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-story-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-story-playing&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-story-beat&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-story-next&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-story-follow&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-chapter-handoff&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-chapter-anchor&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-chapter-preview&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.style.getPropertyValue(&amp;#x27;transform&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.style.getPropertyValue(&amp;#x27;clip-path&amp;#x27;) &amp;amp;&amp;amp;&#10;          clone.querySelectorAll(&amp;#x27;[data-story-overlay], [data-story-carrier-overlay], [data-story-carrier-token], [data-story-step], [data-story-beat-state], [data-story-beat-step], [data-chapter-handoff-overlay], [data-chapter-role], [data-chapter-preview-role], [data-focus-match], [data-focus-selected], [data-reach-match], [data-reach-origin], [data-reach-depth], [data-semantic-lens-overlay], [data-lens-match], [data-lens-selected], [data-lens-peer], [data-legend-bridge], [data-legend-kind], [data-legend-bridge-runtime], [data-legend-count], [data-legend-zero], [data-legend-selected], [data-legend-preview-match], [data-legend-preview-selected], [data-legend-preview-peer], [data-relationship-hit-overlay], [data-relationship-pulse-overlay], [data-relationship-preview], [data-relationship-preview-node], [data-relationship-preview-source], [data-relationship-preview-target], [data-intent-trace-overlay], [data-intent-trace-match], [data-intent-trace-selected], [data-route-probe-overlay], [data-route-journey-overlay], [data-route-match], [data-route-start], [data-route-end], [data-route-step], [data-route-candidate], [data-route-journey-state], [data-route-journey-current], [data-share-route-match], [data-share-route-step], [data-share-route-start], [data-share-route-end], [data-share-route-middle], [data-share-reach-match], [data-share-reach-origin], [data-share-reach-depth], [data-source-evidence-beacon], [data-source-evidence-count], [data-source-evidence-original-label], [data-detail], [data-detail-anchor]&amp;#x27;).length === 0;&#10;      }&#10;&#10;&#10;      /**&#10;       * Serialize the main SVG into a standalone document.&#10;       *&#10;       * Two modes:&#10;       * - Default (opts.autoTheme=false) — locks the serialized SVG to the&#10;       *   viewer&amp;#x27;s current theme. Used by the raster pipeline&#10;       *   (PNG/JPEG/WebP/clipboard) because canvas rasterization needs&#10;       *   deterministic colors; a raster cannot react to&#10;       *   prefers-color-scheme after encoding.&#10;       * - autoTheme=true — emits BOTH dark and light variable sets plus a&#10;       *   `@media (prefers-color-scheme)` rule so the resulting SVG&#10;       *   self-themes when embedded in GitHub READMEs or other hosts that&#10;       *   expose a color scheme. Used for &amp;quot;Download SVG&amp;quot;.&#10;       */&#10;      function applyRouteSnapshot(clone, snapshot) {&#10;        if (!snapshot || !Array.isArray(snapshot.nodeIds) || !Array.isArray(snapshot.edges) ||&#10;            snapshot.nodeIds.length &amp;lt; 2 || snapshot.edges.length !== snapshot.nodeIds.length - 1 ||&#10;            snapshot.hops !== snapshot.edges.length ||&#10;            !snapshot.source || !snapshot.target ||&#10;            snapshot.source.id !== snapshot.nodeIds[0] ||&#10;            snapshot.target.id !== snapshot.nodeIds[snapshot.nodeIds.length - 1]) return false;&#10;&#10;        clone.removeAttribute(&amp;#x27;data-animation&amp;#x27;);&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-animate]&amp;#x27;), function (element) {&#10;          element.removeAttribute(&amp;#x27;data-animate&amp;#x27;);&#10;          element.style.removeProperty(&amp;#x27;--step&amp;#x27;);&#10;        });&#10;&#10;        var cloneNodes = Array.prototype.slice.call(clone.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;));&#10;        var cloneEdges = Array.prototype.slice.call(clone.querySelectorAll(&amp;#x27;[data-edge-key]&amp;#x27;));&#10;        var nodeIds = Object.create(null);&#10;        var edgeKeys = Object.create(null);&#10;        var nodeMatches = [];&#10;        var edgeMatches = [];&#10;&#10;        for (var nodeIndex = 0; nodeIndex &amp;lt; snapshot.nodeIds.length; nodeIndex++) {&#10;          var nodeId = snapshot.nodeIds[nodeIndex];&#10;          if (typeof nodeId !== &amp;#x27;string&amp;#x27; || !nodeId || nodeIds[nodeId]) return false;&#10;          var matchedNodes = cloneNodes.filter(function (candidate) {&#10;            return candidate.getAttribute(&amp;#x27;data-node-id&amp;#x27;) === nodeId;&#10;          });&#10;          if (matchedNodes.length !== 1) return false;&#10;          nodeIds[nodeId] = true;&#10;          nodeMatches.push(matchedNodes);&#10;        }&#10;&#10;        for (var edgeIndex = 0; edgeIndex &amp;lt; snapshot.edges.length; edgeIndex++) {&#10;          var edge = snapshot.edges[edgeIndex];&#10;          var fromId = snapshot.nodeIds[edgeIndex];&#10;          var toId = snapshot.nodeIds[edgeIndex + 1];&#10;          if (!edge || typeof edge.key !== &amp;#x27;string&amp;#x27; || !edge.key || edgeKeys[edge.key] ||&#10;              edge.from !== fromId || edge.to !== toId) return false;&#10;          var matchedEdges = cloneEdges.filter(function (candidate) {&#10;            return candidate.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) === edge.key;&#10;          });&#10;          var drawableMatches = matchedEdges.filter(hasDrawableGeometry);&#10;          if (!matchedEdges.length || drawableMatches.length !== 1 || !matchedEdges.every(function (candidate) {&#10;            return candidate.getAttribute(&amp;#x27;data-edge-from&amp;#x27;) === edge.from &amp;amp;&amp;amp;&#10;              candidate.getAttribute(&amp;#x27;data-edge-to&amp;#x27;) === edge.to &amp;amp;&amp;amp;&#10;              (candidate.getAttribute(&amp;#x27;data-edge-id&amp;#x27;) || &amp;#x27;&amp;#x27;) === (edge.id || &amp;#x27;&amp;#x27;);&#10;          })) return false;&#10;          edgeKeys[edge.key] = true;&#10;          edgeMatches.push(matchedEdges);&#10;        }&#10;&#10;        clone.setAttribute(&amp;#x27;data-share-route&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        nodeMatches.forEach(function (matches, step) {&#10;          matches.forEach(function (element) {&#10;            element.setAttribute(&amp;#x27;data-share-route-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            element.setAttribute(&amp;#x27;data-share-route-step&amp;#x27;, String(step));&#10;            if (step === 0) element.setAttribute(&amp;#x27;data-share-route-start&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            else if (step === snapshot.nodeIds.length - 1) element.setAttribute(&amp;#x27;data-share-route-end&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            else element.setAttribute(&amp;#x27;data-share-route-middle&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          });&#10;        });&#10;        edgeMatches.forEach(function (matches, step) {&#10;          matches.forEach(function (element) {&#10;            element.setAttribute(&amp;#x27;data-share-route-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            element.setAttribute(&amp;#x27;data-share-route-step&amp;#x27;, String(step));&#10;          });&#10;        });&#10;&#10;        return clone.hasAttribute(&amp;#x27;data-share-route&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-animation&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-route-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-route-journey&amp;#x27;) &amp;amp;&amp;amp;&#10;          clone.querySelectorAll(&amp;#x27;[data-animate], [data-route-match], [data-route-step], [data-route-start], [data-route-end], [data-route-journey-state], [data-route-journey-current], [data-route-journey-overlay]&amp;#x27;).length === 0 &amp;amp;&amp;amp;&#10;          clone.querySelectorAll(&amp;#x27;[data-share-route-match]&amp;#x27;).length ===&#10;            nodeMatches.reduce(function (count, matches) { return count + matches.length; }, 0) +&#10;            edgeMatches.reduce(function (count, matches) { return count + matches.length; }, 0);&#10;      }&#10;&#10;      function applyReachSnapshot(clone, snapshot) {&#10;        if (!snapshot || (snapshot.direction !== &amp;#x27;upstream&amp;#x27; &amp;amp;&amp;amp; snapshot.direction !== &amp;#x27;downstream&amp;#x27;) ||&#10;            !snapshot.origin || typeof snapshot.origin.id !== &amp;#x27;string&amp;#x27; || !snapshot.origin.id ||&#10;            typeof snapshot.origin.label !== &amp;#x27;string&amp;#x27; || !snapshot.origin.label.trim() ||&#10;            !Array.isArray(snapshot.nodeIds) || snapshot.nodeIds.length &amp;lt; 2 ||&#10;            !Array.isArray(snapshot.edges) || !snapshot.edges.length ||&#10;            !snapshot.depths || typeof snapshot.depths !== &amp;#x27;object&amp;#x27; ||&#10;            !Number.isInteger(snapshot.maxDepth) || snapshot.maxDepth &amp;lt; 1 ||&#10;            snapshot.nodeIds[0] !== snapshot.origin.id) return false;&#10;&#10;        clone.removeAttribute(&amp;#x27;data-animation&amp;#x27;);&#10;        Array.prototype.forEach.call(clone.querySelectorAll(&amp;#x27;[data-animate]&amp;#x27;), function (element) {&#10;          element.removeAttribute(&amp;#x27;data-animate&amp;#x27;);&#10;          element.style.removeProperty(&amp;#x27;--step&amp;#x27;);&#10;        });&#10;&#10;        var cloneNodes = Array.prototype.slice.call(clone.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;));&#10;        var cloneEdges = Array.prototype.slice.call(clone.querySelectorAll(&amp;#x27;[data-edge-key]&amp;#x27;));&#10;        var nodeIds = Object.create(null);&#10;        var edgeKeys = Object.create(null);&#10;        var nodeMatches = [];&#10;        var edgeMatches = [];&#10;        var measuredMaxDepth = 0;&#10;&#10;        for (var nodeIndex = 0; nodeIndex &amp;lt; snapshot.nodeIds.length; nodeIndex++) {&#10;          var nodeId = snapshot.nodeIds[nodeIndex];&#10;          var depth = snapshot.depths[nodeId];&#10;          if (typeof nodeId !== &amp;#x27;string&amp;#x27; || !nodeId || nodeIds[nodeId] ||&#10;              !Number.isInteger(depth) || depth &amp;lt; 0 || depth &amp;gt; snapshot.maxDepth ||&#10;              (nodeId === snapshot.origin.id ? depth !== 0 : depth &amp;lt; 1)) return false;&#10;          var matchedNodes = cloneNodes.filter(function (candidate) {&#10;            return candidate.getAttribute(&amp;#x27;data-node-id&amp;#x27;) === nodeId;&#10;          });&#10;          if (matchedNodes.length !== 1) return false;&#10;          nodeIds[nodeId] = true;&#10;          measuredMaxDepth = Math.max(measuredMaxDepth, depth);&#10;          nodeMatches.push({ elements: matchedNodes, id: nodeId, depth: depth });&#10;        }&#10;        if (measuredMaxDepth !== snapshot.maxDepth) return false;&#10;&#10;        for (var edgeIndex = 0; edgeIndex &amp;lt; snapshot.edges.length; edgeIndex++) {&#10;          var edge = snapshot.edges[edgeIndex];&#10;          if (!edge || typeof edge.key !== &amp;#x27;string&amp;#x27; || !edge.key || edgeKeys[edge.key] ||&#10;              !nodeIds[edge.from] || !nodeIds[edge.to] ||&#10;              !Number.isInteger(edge.depth) || edge.depth &amp;lt; 1 || edge.depth &amp;gt; snapshot.maxDepth ||&#10;              edge.depth !== Math.max(snapshot.depths[edge.from], snapshot.depths[edge.to])) return false;&#10;          var matchedEdges = cloneEdges.filter(function (candidate) {&#10;            return candidate.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) === edge.key;&#10;          });&#10;          var drawableMatches = matchedEdges.filter(hasDrawableGeometry);&#10;          if (!matchedEdges.length || drawableMatches.length !== 1 || !matchedEdges.every(function (candidate) {&#10;            return candidate.getAttribute(&amp;#x27;data-edge-from&amp;#x27;) === edge.from &amp;amp;&amp;amp;&#10;              candidate.getAttribute(&amp;#x27;data-edge-to&amp;#x27;) === edge.to &amp;amp;&amp;amp;&#10;              (candidate.getAttribute(&amp;#x27;data-edge-id&amp;#x27;) || &amp;#x27;&amp;#x27;) === (edge.id || &amp;#x27;&amp;#x27;);&#10;          })) return false;&#10;          edgeKeys[edge.key] = true;&#10;          edgeMatches.push({ elements: matchedEdges, depth: edge.depth });&#10;        }&#10;&#10;        clone.setAttribute(&amp;#x27;data-share-reach&amp;#x27;, snapshot.direction);&#10;        nodeMatches.forEach(function (match) {&#10;          match.elements.forEach(function (element) {&#10;            element.setAttribute(&amp;#x27;data-share-reach-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            element.setAttribute(&amp;#x27;data-share-reach-depth&amp;#x27;, String(match.depth));&#10;            if (match.id === snapshot.origin.id) element.setAttribute(&amp;#x27;data-share-reach-origin&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          });&#10;        });&#10;        edgeMatches.forEach(function (match) {&#10;          match.elements.forEach(function (element) {&#10;            element.setAttribute(&amp;#x27;data-share-reach-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            element.setAttribute(&amp;#x27;data-share-reach-depth&amp;#x27;, String(match.depth));&#10;          });&#10;        });&#10;&#10;        return clone.getAttribute(&amp;#x27;data-share-reach&amp;#x27;) === snapshot.direction &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-animation&amp;#x27;) &amp;amp;&amp;amp;&#10;          !clone.hasAttribute(&amp;#x27;data-reach-active&amp;#x27;) &amp;amp;&amp;amp;&#10;          clone.querySelectorAll(&amp;#x27;[data-animate], [data-reach-match], [data-reach-origin], [data-reach-depth]&amp;#x27;).length === 0 &amp;amp;&amp;amp;&#10;          clone.querySelectorAll(&amp;#x27;[data-share-reach-origin]&amp;#x27;).length === 1 &amp;amp;&amp;amp;&#10;          clone.querySelectorAll(&amp;#x27;[data-share-reach-match]&amp;#x27;).length ===&#10;            nodeMatches.reduce(function (count, match) { return count + match.elements.length; }, 0) +&#10;            edgeMatches.reduce(function (count, match) { return count + match.elements.length; }, 0);&#10;      }&#10;&#10;      function serializeSvg(scale, opts) {&#10;        // scale: integer multiplier for intrinsic SVG pixel dimensions used by&#10;        // the raster path. Defaults to 1 (natural size) for SVG download.&#10;        scale = scale || 1;&#10;        opts = opts || {};&#10;        var autoTheme = opts.autoTheme === true;&#10;        var svg = document.querySelector(&amp;#x27;.diagram-container svg&amp;#x27;);&#10;        var clone = svg.cloneNode(true);&#10;&#10;        var canonicalStateClean = cleanExportClone(clone);&#10;&#10;        var vb = svg.viewBox.baseVal;&#10;        var finiteSvgDimensions = Number.isFinite(vb.x) &amp;amp;&amp;amp; Number.isFinite(vb.y) &amp;amp;&amp;amp;&#10;          Number.isFinite(vb.width) &amp;amp;&amp;amp; Number.isFinite(vb.height) &amp;amp;&amp;amp; vb.width &amp;gt; 0 &amp;amp;&amp;amp; vb.height &amp;gt; 0;&#10;        var routeStateClean = opts.routeSnapshot&#10;          ? canonicalStateClean &amp;amp;&amp;amp; finiteSvgDimensions &amp;amp;&amp;amp; applyRouteSnapshot(clone, opts.routeSnapshot)&#10;          : null;&#10;        var reachStateClean = opts.reachSnapshot&#10;          ? canonicalStateClean &amp;amp;&amp;amp; finiteSvgDimensions &amp;amp;&amp;amp; !opts.routeSnapshot &amp;amp;&amp;amp; applyReachSnapshot(clone, opts.reachSnapshot)&#10;          : null;&#10;        // Scale width/height so the browser rasterizes the vectors at target&#10;        // resolution directly. viewBox stays unchanged so coordinates don&amp;#x27;t&#10;        // shift. This is the key to sharp rasters — do NOT scale later via&#10;        // canvas upscaling.&#10;        clone.setAttribute(&amp;#x27;width&amp;#x27;, vb.width * scale);&#10;        clone.setAttribute(&amp;#x27;height&amp;#x27;, vb.height * scale);&#10;        clone.setAttribute(&amp;#x27;xmlns&amp;#x27;, &amp;#x27;http://www.w3.org/2000/svg&amp;#x27;);&#10;&#10;        // Only the SVG-relevant rules: semantic classes, markers, and the&#10;        // theme variable blocks. Toolbar/cards/print CSS can never apply&#10;        // inside a standalone SVG and would only bloat the export.&#10;        var hostStyle = (function () {&#10;          var out = [];&#10;          Array.prototype.forEach.call(document.styleSheets, function (sheet) {&#10;            var rules;&#10;            try { rules = sheet.cssRules; } catch (_) { return; } // cross-origin&#10;            if (!rules) return;&#10;            Array.prototype.forEach.call(rules, function (rule) {&#10;              if (rule.type === 7 &amp;amp;&amp;amp; /^archify-/.test(rule.name || &amp;#x27;&amp;#x27;)) {&#10;                out.push(rule.cssText);&#10;                return;&#10;              }&#10;              if (rule.type !== 1) return; // plain style rules only&#10;              var sel = rule.selectorText || &amp;#x27;&amp;#x27;;&#10;              if (/(^|,)\s*(svg|:root|\[data-theme|\[data-preset|\.c-|\.t-|\.a-|\.m-)/.test(sel)) {&#10;                out.push(rule.cssText);&#10;              }&#10;            });&#10;          });&#10;          return out.join(&amp;#x27;\n&amp;#x27;);&#10;        })();&#10;&#10;        // Derive the variable list from the stylesheet so newly added theme&#10;        // variables can never be missed by the export pipeline again&#10;        // (--lane-fill/--lane-stroke once were).&#10;        var varNames = (function () {&#10;          var seen = {};&#10;          var names = [];&#10;          (hostStyle.match(/--[a-zA-Z0-9-]+(?=\s*:)/g) || []).forEach(function (n) {&#10;            if (!seen[n]) { seen[n] = true; names.push(n); }&#10;          });&#10;          return names;&#10;        })();&#10;&#10;        // Resolve the full variable set for a given data-theme via an&#10;        // off-DOM probe, independent of what the viewer is currently set to.&#10;        function resolveVars(themeAttr) {&#10;          var probe = document.createElement(&amp;#x27;div&amp;#x27;);&#10;          probe.setAttribute(&amp;#x27;data-theme&amp;#x27;, themeAttr);&#10;          probe.setAttribute(&amp;#x27;data-preset&amp;#x27;, document.documentElement.getAttribute(&amp;#x27;data-preset&amp;#x27;) || &amp;#x27;classic&amp;#x27;);&#10;          probe.style.cssText = &amp;#x27;position:absolute;width:0;height:0;visibility:hidden;&amp;#x27;;&#10;          document.body.appendChild(probe);&#10;          try {&#10;            var c = getComputedStyle(probe);&#10;            return varNames.map(function (n) {&#10;              return n + &amp;#x27;: &amp;#x27; + c.getPropertyValue(n).trim() + &amp;#x27;;&amp;#x27;;&#10;            }).join(&amp;#x27; &amp;#x27;);&#10;          } finally {&#10;            document.body.removeChild(probe);&#10;          }&#10;        }&#10;&#10;        // Keep the same font bytes, character coverage, and attribution in&#10;        // standalone SVGs and the SVG images used by every raster export.&#10;        var fontCss = document.getElementById(&amp;#x27;archify-fonts&amp;#x27;).textContent;&#10;&#10;        var style = document.createElementNS(&amp;#x27;http://www.w3.org/2000/svg&amp;#x27;, &amp;#x27;style&amp;#x27;);&#10;        var bgRect = document.createElementNS(&amp;#x27;http://www.w3.org/2000/svg&amp;#x27;, &amp;#x27;rect&amp;#x27;);&#10;        bgRect.setAttribute(&amp;#x27;width&amp;#x27;, &amp;#x27;100%&amp;#x27;);&#10;        bgRect.setAttribute(&amp;#x27;height&amp;#x27;, &amp;#x27;100%&amp;#x27;);&#10;&#10;        if (autoTheme) {&#10;          // Dual-theme SVG. Dark is the default (so hosts without&#10;          // prefers-color-scheme still render), light swaps in via media&#10;          // query, and svg[data-theme=&amp;quot;...&amp;quot;] still lets downstream&#10;          // consumers force a specific theme.&#10;          var darkVars = resolveVars(&amp;#x27;dark&amp;#x27;);&#10;          var lightVars = resolveVars(&amp;#x27;light&amp;#x27;);&#10;&#10;          style.textContent =&#10;            fontCss + &amp;quot;\n&amp;quot; +&#10;            &amp;quot;svg { font-family: &amp;#x27;JetBrains Mono&amp;#x27;, ui-monospace, SFMono-Regular, Menlo, Consolas, &amp;#x27;DejaVu Sans Mono&amp;#x27;, &amp;#x27;Liberation Mono&amp;#x27;, &amp;#x27;Noto Sans Mono CJK SC&amp;#x27;, &amp;#x27;PingFang SC&amp;#x27;, &amp;#x27;Hiragino Sans GB&amp;#x27;, &amp;#x27;Microsoft YaHei&amp;#x27;, monospace; }\n&amp;quot; +&#10;            hostStyle + &amp;quot;\n&amp;quot; +&#10;            &amp;quot;:root, svg { &amp;quot; + darkVars + &amp;quot; }\n&amp;quot; +&#10;            &amp;quot;@media (prefers-color-scheme: light) { :root, svg { &amp;quot; + lightVars + &amp;quot; } }\n&amp;quot; +&#10;            &amp;quot;svg[data-theme=\&amp;quot;light\&amp;quot;] { &amp;quot; + lightVars + &amp;quot; }\n&amp;quot; +&#10;            &amp;quot;svg[data-theme=\&amp;quot;dark\&amp;quot;] { &amp;quot; + darkVars + &amp;quot; }\n&amp;quot; +&#10;            &amp;quot;rect.c-bg-rect { fill: var(--bg); }\n&amp;quot;;&#10;&#10;          // Don&amp;#x27;t lock the serialized SVG to the viewer&amp;#x27;s current theme.&#10;          clone.removeAttribute(&amp;#x27;data-theme&amp;#x27;);&#10;          // Background follows the CSS variable, not a fixed color, so it&#10;          // swaps with the media query.&#10;          bgRect.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;c-bg-rect&amp;#x27;);&#10;        } else {&#10;          // Raster path: lock to the viewer&amp;#x27;s current theme.&#10;          var theme = document.documentElement.getAttribute(&amp;#x27;data-theme&amp;#x27;) || &amp;#x27;dark&amp;#x27;;&#10;          var themeHost = document.querySelector(&amp;#x27;[data-theme=&amp;quot;&amp;#x27; + theme + &amp;#x27;&amp;quot;]&amp;#x27;) || document.documentElement;&#10;          var computed = getComputedStyle(themeHost);&#10;          var vars = varNames.map(function (n) {&#10;            return n + &amp;#x27;: &amp;#x27; + computed.getPropertyValue(n).trim() + &amp;#x27;;&amp;#x27;;&#10;          }).join(&amp;#x27; &amp;#x27;);&#10;&#10;          // IMPORTANT: inject the resolved variables AFTER hostStyle,&#10;          // otherwise hostStyle&amp;#x27;s &amp;quot;:root, [data-theme=\&amp;quot;dark\&amp;quot;] { ... }&amp;quot; rule&#10;          // overrides our chosen theme via later-in-cascade equal-specificity.&#10;          // Keep this order.&#10;          style.textContent =&#10;            fontCss + &amp;quot;\n&amp;quot; +&#10;            &amp;quot;svg { font-family: &amp;#x27;JetBrains Mono&amp;#x27;, ui-monospace, SFMono-Regular, Menlo, Consolas, &amp;#x27;DejaVu Sans Mono&amp;#x27;, &amp;#x27;Liberation Mono&amp;#x27;, &amp;#x27;Noto Sans Mono CJK SC&amp;#x27;, &amp;#x27;PingFang SC&amp;#x27;, &amp;#x27;Hiragino Sans GB&amp;#x27;, &amp;#x27;Microsoft YaHei&amp;#x27;, monospace; }\n&amp;quot; +&#10;            hostStyle + &amp;quot;\n&amp;quot; +&#10;            &amp;quot;:root, svg { &amp;quot; + vars + &amp;quot; }\n&amp;quot;;&#10;&#10;          bgRect.setAttribute(&amp;#x27;fill&amp;#x27;, computed.getPropertyValue(&amp;#x27;--bg&amp;#x27;).trim() || &amp;#x27;#ffffff&amp;#x27;);&#10;        }&#10;&#10;        if (opts.routeSnapshot) {&#10;          style.textContent += &amp;quot;\nsvg[data-share-route] [data-node-id], svg[data-share-route] [data-edge-from] { opacity: 0.18; }\n&amp;quot; +&#10;            &amp;quot;svg[data-share-route] [data-share-route-match] { opacity: 1; }\n&amp;quot; +&#10;            &amp;quot;svg[data-share-route] [data-share-route-start] &amp;gt; :is(rect, circle, polygon):not(.c-mask) { stroke-width: 3; stroke-dasharray: 5 3; }\n&amp;quot; +&#10;            &amp;quot;svg[data-share-route] [data-share-route-middle] &amp;gt; :is(rect, circle, polygon):not(.c-mask) { stroke-width: 2.2; }\n&amp;quot; +&#10;            &amp;quot;svg[data-share-route] [data-share-route-end] &amp;gt; :is(rect, circle, polygon):not(.c-mask) { stroke-width: 3.4; stroke-dasharray: 1 0; }\n&amp;quot;;&#10;        }&#10;        if (opts.reachSnapshot) {&#10;          style.textContent += &amp;quot;\nsvg[data-share-reach] [data-node-id], svg[data-share-reach] [data-edge-from] { opacity: 0.14; }\n&amp;quot; +&#10;            &amp;quot;svg[data-share-reach] [data-share-reach-match] { opacity: 1; }\n&amp;quot; +&#10;            &amp;quot;svg[data-share-reach] [data-edge-from][data-share-reach-match] { stroke-width: 1.55; }\n&amp;quot; +&#10;            &amp;quot;svg[data-share-reach=\&amp;quot;upstream\&amp;quot;] [data-share-reach-origin] &amp;gt; :is(rect, circle, polygon):not(.c-mask) { stroke: var(--database-stroke); stroke-width: 3.4; stroke-dasharray: 5 3; }\n&amp;quot; +&#10;            &amp;quot;svg[data-share-reach=\&amp;quot;downstream\&amp;quot;] [data-share-reach-origin] &amp;gt; :is(rect, circle, polygon):not(.c-mask) { stroke: var(--backend-stroke); stroke-width: 3.4; stroke-dasharray: 1 0; }\n&amp;quot; +&#10;            &amp;quot;svg[data-preset=\&amp;quot;blueprint\&amp;quot;][data-share-reach] [data-share-reach-origin], svg[data-preset=\&amp;quot;blueprint\&amp;quot;][data-share-reach] [data-edge-from][data-share-reach-match] { filter: none; }\n&amp;quot;;&#10;        }&#10;&#10;        clone.insertBefore(style, clone.firstChild);&#10;        clone.insertBefore(bgRect, style.nextSibling);&#10;&#10;        return {&#10;          svgString: new XMLSerializer().serializeToString(clone),&#10;          width: vb.width * scale,&#10;          height: vb.height * scale,&#10;          canonicalStateClean: canonicalStateClean,&#10;          routeStateClean: routeStateClean,&#10;          reachStateClean: reachStateClean&#10;        };&#10;      }&#10;&#10;      function download(blob, filename) {&#10;        var url = URL.createObjectURL(blob);&#10;        var a = document.createElement(&amp;#x27;a&amp;#x27;);&#10;        a.href = url;&#10;        a.download = filename;&#10;        document.body.appendChild(a);&#10;        a.click();&#10;        a.remove();&#10;        setTimeout(function () { URL.revokeObjectURL(url); }, 1000);&#10;      }&#10;&#10;      // Conservative upper bound on total canvas pixels. Older Safari on iOS&#10;      // silently produces a blank canvas above ~16 Mpx; Chrome / Firefox /&#10;      // desktop Safari are far higher but start failing on memory-constrained&#10;      // devices. We pick the largest integer scale in {4,3,2,1} whose target&#10;      // pixel count fits under this cap.&#10;      var MAX_CANVAS_PIXELS = 16 * 1024 * 1024;&#10;&#10;      function pickSafeScale(vbW, vbH) {&#10;        for (var s = RASTER_SCALE; s &amp;gt;= 1; s--) {&#10;          if (vbW * s * vbH * s &amp;lt;= MAX_CANVAS_PIXELS) return s;&#10;        }&#10;        return 1;&#10;      }&#10;&#10;      function rasterize(format) {&#10;        // Serialize at a safe scale (RASTER_SCALE=4 by default, reduced if the&#10;        // resulting canvas would exceed MAX_CANVAS_PIXELS). The SVG itself is&#10;        // rasterized at target resolution natively; drawImage draws at natural&#10;        // size — no upsampling blur.&#10;        var svg = document.querySelector(&amp;#x27;.diagram-container svg&amp;#x27;);&#10;        var vb = svg.viewBox.baseVal;&#10;        var scale = pickSafeScale(vb.width, vb.height);&#10;        var data = serializeSvg(scale);&#10;        var svgBlob = new Blob([data.svgString], { type: &amp;#x27;image/svg+xml;charset=utf-8&amp;#x27; });&#10;        var svgUrl = URL.createObjectURL(svgBlob);&#10;&#10;        return new Promise(function (resolve, reject) {&#10;          var img = new Image();&#10;          img.onload = function () {&#10;            try {&#10;              var canvas = document.createElement(&amp;#x27;canvas&amp;#x27;);&#10;              canvas.width = data.width;&#10;              canvas.height = data.height;&#10;              var ctx = canvas2dOrThrow(canvas, format);&#10;              if (format === &amp;#x27;jpeg&amp;#x27;) {&#10;                ctx.fillStyle = currentBg();&#10;                ctx.fillRect(0, 0, canvas.width, canvas.height);&#10;              }&#10;              // Draw at natural size — SVG was already rasterized at target res.&#10;              ctx.drawImage(img, 0, 0);&#10;              URL.revokeObjectURL(svgUrl);&#10;              var mime = format === &amp;#x27;jpeg&amp;#x27; ? &amp;#x27;image/jpeg&amp;#x27; :&#10;                         format === &amp;#x27;webp&amp;#x27; ? &amp;#x27;image/webp&amp;#x27; : &amp;#x27;image/png&amp;#x27;;&#10;              var quality = format === &amp;#x27;png&amp;#x27; ? undefined : 0.95;&#10;              canvas.toBlob(function (blob) {&#10;                if (!blob) reject(exportError(&amp;#x27;viewer.export.error.toBlobNull&amp;#x27;, { label: format }));&#10;                else resolve(blob);&#10;              }, mime, quality);&#10;            } catch (error) {&#10;              URL.revokeObjectURL(svgUrl);&#10;              reject(error);&#10;            }&#10;          };&#10;          img.onerror = function (e) {&#10;            URL.revokeObjectURL(svgUrl);&#10;            reject(e);&#10;          };&#10;          img.src = svgUrl;&#10;        });&#10;      }&#10;&#10;      function fitCanvasText(ctx, text, maxWidth, startSize, minSize, weight) {&#10;        var value = String(text || &amp;#x27;&amp;#x27;).trim();&#10;        var size = startSize;&#10;        var family = &amp;quot;&amp;#x27;JetBrains Mono&amp;#x27;, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace&amp;quot;;&#10;        while (size &amp;gt; minSize) {&#10;          ctx.font = (weight || &amp;#x27;600&amp;#x27;) + &amp;#x27; &amp;#x27; + size + &amp;#x27;px &amp;#x27; + family;&#10;          if (ctx.measureText(value).width &amp;lt;= maxWidth) return value;&#10;          size -= 1;&#10;        }&#10;        ctx.font = (weight || &amp;#x27;600&amp;#x27;) + &amp;#x27; &amp;#x27; + minSize + &amp;#x27;px &amp;#x27; + family;&#10;        if (ctx.measureText(value).width &amp;lt;= maxWidth) return value;&#10;        var suffix = &amp;#x27;\u2026&amp;#x27;;&#10;        while (value.length &amp;gt; 1 &amp;amp;&amp;amp; ctx.measureText(value + suffix).width &amp;gt; maxWidth) {&#10;          value = value.slice(0, -1);&#10;        }&#10;        return value + suffix;&#10;      }&#10;&#10;      function canvas2dOrThrow(canvas, label) {&#10;        if (!canvas || typeof canvas.getContext !== &amp;#x27;function&amp;#x27;) {&#10;          throw exportError(&amp;#x27;viewer.export.error.canvasUnavailable&amp;#x27;, { label: label });&#10;        }&#10;        var ctx = canvas.getContext(&amp;#x27;2d&amp;#x27;);&#10;        if (!ctx) throw exportError(&amp;#x27;viewer.export.error.contextUnavailable&amp;#x27;, { label: label });&#10;        if (typeof canvas.toBlob !== &amp;#x27;function&amp;#x27;) throw exportError(&amp;#x27;viewer.export.error.toBlobUnavailable&amp;#x27;, { label: label });&#10;        return ctx;&#10;      }&#10;&#10;      function renderShareCard(options) {&#10;        options = options || {};&#10;        var routeSnapshot = options.routeSnapshot || null;&#10;        var reachSnapshot = options.reachSnapshot || null;&#10;        if (routeSnapshot &amp;amp;&amp;amp; reachSnapshot) return Promise.reject(exportError(&amp;#x27;viewer.export.error.variantsCombined&amp;#x27;));&#10;        var svg = document.querySelector(&amp;#x27;.diagram-container svg&amp;#x27;);&#10;        var vb = svg.viewBox.baseVal;&#10;        var sourceScale = Math.min(2, pickSafeScale(vb.width, vb.height));&#10;        var data = serializeSvg(sourceScale, { routeSnapshot: routeSnapshot, reachSnapshot: reachSnapshot });&#10;        if (!data.canonicalStateClean) return Promise.reject(exportError(&amp;#x27;viewer.export.error.viewerState&amp;#x27;));&#10;        if (routeSnapshot &amp;amp;&amp;amp; !data.routeStateClean) return Promise.reject(exportError(&amp;#x27;viewer.export.error.routeState&amp;#x27;));&#10;        if (reachSnapshot &amp;amp;&amp;amp; !data.reachStateClean) return Promise.reject(exportError(&amp;#x27;viewer.export.error.reachState&amp;#x27;));&#10;        var svgBlob = new Blob([data.svgString], { type: &amp;#x27;image/svg+xml;charset=utf-8&amp;#x27; });&#10;        var svgUrl = URL.createObjectURL(svgBlob);&#10;&#10;        return new Promise(function (resolve, reject) {&#10;          var img = new Image();&#10;          img.onload = function () {&#10;            try {&#10;              var canvas = document.createElement(&amp;#x27;canvas&amp;#x27;);&#10;              canvas.width = SHARE_CARD_WIDTH;&#10;              canvas.height = SHARE_CARD_HEIGHT;&#10;              var ctx = canvas2dOrThrow(canvas, viewerText(&amp;#x27;viewer.export.shareCard&amp;#x27;));&#10;              var computed = getComputedStyle(document.documentElement);&#10;              var bg = computed.getPropertyValue(&amp;#x27;--bg&amp;#x27;).trim() || currentBg();&#10;              var text = computed.getPropertyValue(&amp;#x27;--text&amp;#x27;).trim() || &amp;#x27;#ffffff&amp;#x27;;&#10;              var muted = computed.getPropertyValue(&amp;#x27;--text-muted&amp;#x27;).trim() || &amp;#x27;#94a3b8&amp;#x27;;&#10;              var border = computed.getPropertyValue(&amp;#x27;--panel-border&amp;#x27;).trim() || &amp;#x27;#334155&amp;#x27;;&#10;              var accentProperty = reachSnapshot&#10;                ? (reachSnapshot.direction === &amp;#x27;upstream&amp;#x27; ? &amp;#x27;--database-stroke&amp;#x27; : &amp;#x27;--backend-stroke&amp;#x27;)&#10;                : &amp;#x27;--frontend-stroke&amp;#x27;;&#10;              var accent = computed.getPropertyValue(accentProperty).trim() || &amp;#x27;#22d3ee&amp;#x27;;&#10;              var titleNode = document.querySelector(&amp;#x27;.header h1&amp;#x27;);&#10;              var subtitleNode = document.querySelector(&amp;#x27;.header .subtitle&amp;#x27;);&#10;              var title = titleNode ? titleNode.textContent : document.title;&#10;              var directionLabel = reachSnapshot&#10;                ? viewerText(&amp;#x27;viewer.export.direction.&amp;#x27; + reachSnapshot.direction)&#10;                : &amp;#x27;&amp;#x27;;&#10;              var subtitle = routeSnapshot&#10;                ? viewerCount(&amp;#x27;viewer.export.card.routeSummary&amp;#x27;, routeSnapshot.hops, {&#10;                    source: routeSnapshot.source.label,&#10;                    target: routeSnapshot.target.label&#10;                  })&#10;                : reachSnapshot&#10;                  ? viewerText(&amp;#x27;viewer.export.card.reachSummary&amp;#x27;, {&#10;                      direction: directionLabel,&#10;                      origin: reachSnapshot.origin.label,&#10;                      nodes: viewerCount(&amp;#x27;viewer.export.card.node&amp;#x27;, reachSnapshot.nodeIds.length - 1),&#10;                      links: viewerCount(&amp;#x27;viewer.export.card.link&amp;#x27;, reachSnapshot.edges.length),&#10;                      hops: viewerCount(&amp;#x27;viewer.export.card.hop&amp;#x27;, reachSnapshot.maxDepth)&#10;                    })&#10;                  : subtitleNode ? subtitleNode.textContent : &amp;#x27;&amp;#x27;;&#10;              var preset = document.documentElement.getAttribute(&amp;#x27;data-preset&amp;#x27;) || &amp;#x27;classic&amp;#x27;;&#10;              var theme = document.documentElement.getAttribute(&amp;#x27;data-theme&amp;#x27;) || &amp;#x27;dark&amp;#x27;;&#10;              var presetKey = preset === &amp;#x27;signal-flow&amp;#x27;&#10;                ? &amp;#x27;viewer.preset.flow.short&amp;#x27;&#10;                : &amp;#x27;viewer.preset.&amp;#x27; + preset;&#10;              var presetLabel = viewerText(presetKey).toUpperCase();&#10;              var themeLabel = viewerText(&amp;#x27;viewer.theme.&amp;#x27; + theme).toUpperCase();&#10;              var cardLabel = routeSnapshot&#10;                ? viewerText(&amp;#x27;viewer.export.card.routeBadge&amp;#x27;, {&#10;                    hops: viewerCount(&amp;#x27;viewer.export.card.hop&amp;#x27;, routeSnapshot.hops).toUpperCase()&#10;                  })&#10;                : reachSnapshot&#10;                  ? viewerText(&amp;#x27;viewer.export.card.reachBadge&amp;#x27;, { direction: directionLabel.toUpperCase() })&#10;                  : viewerText(&amp;#x27;viewer.export.card.defaultBadge&amp;#x27;, { preset: presetLabel, theme: themeLabel });&#10;&#10;              ctx.fillStyle = bg;&#10;              ctx.fillRect(0, 0, SHARE_CARD_WIDTH, SHARE_CARD_HEIGHT);&#10;&#10;              ctx.fillStyle = accent;&#10;              ctx.fillRect(SHARE_CARD_PADDING, 27, 42, 3);&#10;&#10;              ctx.textBaseline = &amp;#x27;alphabetic&amp;#x27;;&#10;              ctx.fillStyle = text;&#10;              var fittedTitle = fitCanvasText(ctx, title, SHARE_CARD_WIDTH - SHARE_CARD_PADDING * 2 - 330, 29, 18, &amp;#x27;700&amp;#x27;);&#10;              ctx.fillText(fittedTitle, SHARE_CARD_PADDING, 62);&#10;&#10;              ctx.fillStyle = muted;&#10;              var fittedSubtitle = fitCanvasText(ctx, subtitle, SHARE_CARD_WIDTH - SHARE_CARD_PADDING * 2 - 280, 13, 11, &amp;#x27;500&amp;#x27;);&#10;              ctx.fillText(fittedSubtitle, SHARE_CARD_PADDING, 87);&#10;&#10;              ctx.font = &amp;quot;600 12px &amp;#x27;JetBrains Mono&amp;#x27;, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace&amp;quot;;&#10;              ctx.textAlign = &amp;#x27;right&amp;#x27;;&#10;              ctx.fillStyle = accent;&#10;              ctx.fillText(cardLabel, SHARE_CARD_WIDTH - SHARE_CARD_PADDING, 50);&#10;              ctx.textAlign = &amp;#x27;left&amp;#x27;;&#10;&#10;              var availableWidth = SHARE_CARD_WIDTH - SHARE_CARD_PADDING * 2;&#10;              var availableHeight = SHARE_CARD_HEIGHT - SHARE_CARD_HEADER - SHARE_CARD_PADDING;&#10;              var fit = Math.min(availableWidth / data.width, availableHeight / data.height);&#10;              var drawWidth = data.width * fit;&#10;              var drawHeight = data.height * fit;&#10;              var drawX = SHARE_CARD_PADDING + (availableWidth - drawWidth) / 2;&#10;              var drawY = SHARE_CARD_HEADER + (availableHeight - drawHeight) / 2;&#10;&#10;              ctx.strokeStyle = border;&#10;              ctx.lineWidth = 1;&#10;              ctx.strokeRect(drawX - 0.5, drawY - 0.5, drawWidth + 1, drawHeight + 1);&#10;              ctx.drawImage(img, drawX, drawY, drawWidth, drawHeight);&#10;              URL.revokeObjectURL(svgUrl);&#10;&#10;              canvas.toBlob(function (blob) {&#10;                if (!blob) reject(exportError(&amp;#x27;viewer.export.error.toBlobNull&amp;#x27;, { label: viewerText(&amp;#x27;viewer.export.shareCard&amp;#x27;) }));&#10;                else resolve(blob);&#10;              }, &amp;#x27;image/png&amp;#x27;);&#10;            } catch (error) {&#10;              URL.revokeObjectURL(svgUrl);&#10;              reject(error);&#10;            }&#10;          };&#10;          img.onerror = function (e) {&#10;            URL.revokeObjectURL(svgUrl);&#10;            reject(e);&#10;          };&#10;          img.src = svgUrl;&#10;        });&#10;      }&#10;&#10;      function rasterizeShareCard(options) {&#10;        options = options || {};&#10;        if (!options.variant) return renderShareCard();&#10;        if (options.variant !== &amp;#x27;route&amp;#x27; &amp;amp;&amp;amp; options.variant !== &amp;#x27;reach&amp;#x27;) {&#10;          return Promise.reject(exportError(&amp;#x27;viewer.export.unknownVariant&amp;#x27;, { variant: options.variant }));&#10;        }&#10;        if (options.variant === &amp;#x27;route&amp;#x27;) {&#10;          var routeSnapshot = Archify.routeProbe &amp;amp;&amp;amp; Archify.routeProbe.exportSnapshot();&#10;          if (!routeSnapshot) return Promise.reject(exportError(&amp;#x27;viewer.export.routeRequired&amp;#x27;));&#10;          return renderShareCard({ routeSnapshot: routeSnapshot });&#10;        }&#10;        var snapshot = Archify.focus &amp;amp;&amp;amp; typeof Archify.focus.reachabilitySnapshot === &amp;#x27;function&amp;#x27;&#10;          ? Archify.focus.reachabilitySnapshot()&#10;          : null;&#10;        if (!snapshot) return Promise.reject(exportError(&amp;#x27;viewer.export.reachRequired&amp;#x27;));&#10;        return renderShareCard({ reachSnapshot: snapshot });&#10;      }&#10;&#10;      function motionMimeType() {&#10;        if (typeof MediaRecorder === &amp;#x27;undefined&amp;#x27;) return &amp;#x27;&amp;#x27;;&#10;        var candidates = [&#10;          &amp;#x27;video/webm;codecs=vp9&amp;#x27;,&#10;          &amp;#x27;video/webm;codecs=vp8&amp;#x27;,&#10;          &amp;#x27;video/webm&amp;#x27;&#10;        ];&#10;        for (var i = 0; i &amp;lt; candidates.length; i++) {&#10;          if (!MediaRecorder.isTypeSupported || MediaRecorder.isTypeSupported(candidates[i])) return candidates[i];&#10;        }&#10;        return &amp;#x27;&amp;#x27;;&#10;      }&#10;&#10;      function canRecordMotion() {&#10;        var svg = document.querySelector(&amp;#x27;.diagram-container svg&amp;#x27;);&#10;        return !!(svg &amp;amp;&amp;amp; svg.getAttribute(&amp;#x27;data-animation&amp;#x27;) === &amp;#x27;trace&amp;#x27; &amp;amp;&amp;amp;&#10;          typeof MediaRecorder !== &amp;#x27;undefined&amp;#x27; &amp;amp;&amp;amp; motionMimeType() &amp;amp;&amp;amp;&#10;          typeof HTMLCanvasElement !== &amp;#x27;undefined&amp;#x27; &amp;amp;&amp;amp;&#10;          typeof HTMLCanvasElement.prototype.captureStream === &amp;#x27;function&amp;#x27;);&#10;      }&#10;&#10;      // Record the live CSS animation without Puppeteer, ffmpeg, or a network&#10;      // dependency. SVG files loaded through Image are commonly rasterized as&#10;      // one cached bitmap, so repeatedly drawing that Image does not reliably&#10;      // advance its CSS animation. Keep one crisp static SVG background, then&#10;      // render an explicit time-varying signal scene over the real authored&#10;      // relationship geometry on every captured canvas frame.&#10;      function recordWebm(options) {&#10;        options = options || {};&#10;        if (!canRecordMotion()) {&#10;          return Promise.reject(exportError(&amp;#x27;viewer.export.error.webmRequirements&amp;#x27;));&#10;        }&#10;        var duration = Math.max(250, Number(options.duration) || MOTION_DURATION);&#10;        var fps = Math.max(1, Number(options.fps) || MOTION_FPS);&#10;        var svg = document.querySelector(&amp;#x27;.diagram-container svg&amp;#x27;);&#10;        var vb = svg.viewBox.baseVal;&#10;        var scale = Math.min(1, 1280 / vb.width);&#10;        var data = serializeSvg(scale);&#10;        var sourceUrl = URL.createObjectURL(new Blob([data.svgString], { type: &amp;#x27;image/svg+xml;charset=utf-8&amp;#x27; }));&#10;&#10;        function createMotionScene(root) {&#10;          var rootMatrix = root.getCTM ? root.getCTM() : null;&#10;&#10;          function pointInRoot(element, point) {&#10;            if (!rootMatrix || !element.getCTM || !point.matrixTransform) return { x: point.x, y: point.y };&#10;            try {&#10;              var elementMatrix = element.getCTM();&#10;              if (!elementMatrix) return { x: point.x, y: point.y };&#10;              var mapped = point.matrixTransform(rootMatrix.inverse().multiply(elementMatrix));&#10;              return { x: mapped.x, y: mapped.y };&#10;            } catch (_) {&#10;              return { x: point.x, y: point.y };&#10;            }&#10;          }&#10;&#10;          function samplesFor(element) {&#10;            if (typeof element.getTotalLength !== &amp;#x27;function&amp;#x27; || typeof element.getPointAtLength !== &amp;#x27;function&amp;#x27;) return [];&#10;            var length;&#10;            try { length = element.getTotalLength(); } catch (_) { return []; }&#10;            if (!Number.isFinite(length) || length &amp;lt;= 0) return [];&#10;            var count = Math.max(12, Math.min(72, Math.ceil(length / 12)));&#10;            var points = [];&#10;            for (var i = 0; i &amp;lt;= count; i++) {&#10;              points.push(pointInRoot(element, element.getPointAtLength(length * i / count)));&#10;            }&#10;            return points;&#10;          }&#10;&#10;          function authoredStep(element, fallback) {&#10;            var raw = element.style.getPropertyValue(&amp;#x27;--step&amp;#x27;) || getComputedStyle(element).getPropertyValue(&amp;#x27;--step&amp;#x27;);&#10;            var value = Number(raw);&#10;            return Number.isFinite(value) ? value : fallback;&#10;          }&#10;&#10;          var edges = Array.prototype.slice.call(root.querySelectorAll(&amp;#x27;[data-animate=&amp;quot;edge&amp;quot;]&amp;#x27;)).map(function (element, index) {&#10;            var computed = getComputedStyle(element);&#10;            return {&#10;              points: samplesFor(element),&#10;              color: computed.stroke &amp;amp;&amp;amp; computed.stroke !== &amp;#x27;none&amp;#x27; ? computed.stroke : &amp;#x27;#22d3ee&amp;#x27;,&#10;              width: Math.max(1.5, parseFloat(computed.strokeWidth) || 1.5),&#10;              delay: Math.min(12, authoredStep(element, index)) * 0.16&#10;            };&#10;          }).filter(function (edge) { return edge.points.length &amp;gt; 1; });&#10;&#10;          var nodes = Array.prototype.slice.call(root.querySelectorAll(&amp;#x27;[data-node-id][data-animate=&amp;quot;node&amp;quot;]&amp;#x27;)).map(function (element, index) {&#10;            var box;&#10;            try { box = element.getBBox(); } catch (_) { return null; }&#10;            var painted = element.querySelector(&amp;#x27;[class*=&amp;quot;c-&amp;quot;]&amp;#x27;) || element;&#10;            var computed = getComputedStyle(painted);&#10;            return {&#10;              x: box.x,&#10;              y: box.y,&#10;              width: box.width,&#10;              height: box.height,&#10;              color: computed.stroke &amp;amp;&amp;amp; computed.stroke !== &amp;#x27;none&amp;#x27; ? computed.stroke : &amp;#x27;#22d3ee&amp;#x27;,&#10;              delay: Math.min(12, authoredStep(element, index)) * 0.16&#10;            };&#10;          }).filter(Boolean);&#10;&#10;          return { edges: edges, nodes: nodes, x: vb.x, y: vb.y, width: vb.width, height: vb.height };&#10;        }&#10;&#10;        function pointAlong(points, progress) {&#10;          var scaled = Math.max(0, Math.min(1, progress)) * (points.length - 1);&#10;          var index = Math.min(points.length - 2, Math.floor(scaled));&#10;          var mix = scaled - index;&#10;          return {&#10;            x: points[index].x + (points[index + 1].x - points[index].x) * mix,&#10;            y: points[index].y + (points[index + 1].y - points[index].y) * mix&#10;          };&#10;        }&#10;&#10;        function roundedRectPath(ctx, x, y, width, height, radius) {&#10;          var r = Math.max(0, Math.min(radius, width / 2, height / 2));&#10;          ctx.beginPath();&#10;          ctx.moveTo(x + r, y);&#10;          ctx.lineTo(x + width - r, y);&#10;          ctx.quadraticCurveTo(x + width, y, x + width, y + r);&#10;          ctx.lineTo(x + width, y + height - r);&#10;          ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height);&#10;          ctx.lineTo(x + r, y + height);&#10;          ctx.quadraticCurveTo(x, y + height, x, y + height - r);&#10;          ctx.lineTo(x, y + r);&#10;          ctx.quadraticCurveTo(x, y, x + r, y);&#10;          ctx.closePath();&#10;        }&#10;&#10;        function drawMotionFrame(ctx, backgroundImage, motionScene, elapsed) {&#10;          ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);&#10;          ctx.drawImage(backgroundImage, 0, 0, ctx.canvas.width, ctx.canvas.height);&#10;          ctx.save();&#10;          ctx.scale(ctx.canvas.width / motionScene.width, ctx.canvas.height / motionScene.height);&#10;          ctx.translate(-motionScene.x, -motionScene.y);&#10;&#10;          motionScene.edges.forEach(function (edge) {&#10;            var duration = 1.75;&#10;            var progress = (elapsed - edge.delay) / duration;&#10;            if (progress &amp;lt; 0 || progress &amp;gt; 1) return;&#10;            var head = Math.max(0, Math.min(1, progress));&#10;            var tail = Math.max(0, head - 0.24);&#10;            var opacity = Math.sin(Math.PI * Math.min(1, progress));&#10;&#10;            ctx.save();&#10;            ctx.strokeStyle = edge.color;&#10;            ctx.fillStyle = edge.color;&#10;            ctx.lineCap = &amp;#x27;round&amp;#x27;;&#10;            ctx.lineJoin = &amp;#x27;round&amp;#x27;;&#10;            ctx.lineWidth = Math.max(3.2, edge.width * 2.2);&#10;            ctx.globalAlpha = 0.42 + opacity * 0.5;&#10;            ctx.shadowColor = edge.color;&#10;            ctx.shadowBlur = 10;&#10;            ctx.beginPath();&#10;            for (var i = 0; i &amp;lt;= 14; i++) {&#10;              var trailPoint = pointAlong(edge.points, tail + (head - tail) * i / 14);&#10;              if (i === 0) ctx.moveTo(trailPoint.x, trailPoint.y);&#10;              else ctx.lineTo(trailPoint.x, trailPoint.y);&#10;            }&#10;            ctx.stroke();&#10;&#10;            var point = pointAlong(edge.points, head);&#10;            ctx.globalAlpha = 0.95;&#10;            ctx.beginPath();&#10;            ctx.arc(point.x, point.y, 4.8, 0, Math.PI * 2);&#10;            ctx.fill();&#10;            ctx.restore();&#10;          });&#10;&#10;          motionScene.nodes.forEach(function (node) {&#10;            var progress = (elapsed - node.delay) / 2.6;&#10;            if (progress &amp;lt; 0 || progress &amp;gt; 1) return;&#10;            var pulse = Math.sin(Math.PI * progress);&#10;            if (pulse &amp;lt;= 0.02) return;&#10;            ctx.save();&#10;            ctx.strokeStyle = node.color;&#10;            ctx.lineWidth = 1.4 + pulse * 1.8;&#10;            ctx.globalAlpha = pulse * 0.5;&#10;            ctx.shadowColor = node.color;&#10;            ctx.shadowBlur = 12 * pulse;&#10;            var inset = 2 + pulse * 3;&#10;            roundedRectPath(ctx, node.x - inset, node.y - inset, node.width + inset * 2, node.height + inset * 2, 8);&#10;            ctx.stroke();&#10;            ctx.restore();&#10;          });&#10;&#10;          ctx.restore();&#10;        }&#10;&#10;        var motionScene = createMotionScene(svg);&#10;&#10;        return new Promise(function (resolve, reject) {&#10;          var backgroundImage = new Image();&#10;          backgroundImage.onload = function () {&#10;            var canvas = document.createElement(&amp;#x27;canvas&amp;#x27;);&#10;            canvas.width = Math.max(2, Math.round(data.width / 2) * 2);&#10;            canvas.height = Math.max(2, Math.round(data.height / 2) * 2);&#10;            var ctx = canvas.getContext(&amp;#x27;2d&amp;#x27;);&#10;            var stream = canvas.captureStream(fps);&#10;            var mime = motionMimeType();&#10;            var recorder;&#10;            try {&#10;              recorder = new MediaRecorder(stream, { mimeType: mime, videoBitsPerSecond: 6000000 });&#10;            } catch (err) {&#10;              URL.revokeObjectURL(sourceUrl);&#10;              stream.getTracks().forEach(function (track) { track.stop(); });&#10;              reject(err);&#10;              return;&#10;            }&#10;            var chunks = [];&#10;            var raf = 0;&#10;            var stopped = false;&#10;            var startedAt = performance.now();&#10;            function cleanup() {&#10;              if (stopped) return;&#10;              stopped = true;&#10;              cancelAnimationFrame(raf);&#10;              URL.revokeObjectURL(sourceUrl);&#10;              stream.getTracks().forEach(function (track) { track.stop(); });&#10;            }&#10;            function draw(now) {&#10;              var elapsed = Math.max(0, ((Number(now) || performance.now()) - startedAt) / 1000);&#10;              drawMotionFrame(ctx, backgroundImage, motionScene, elapsed);&#10;              raf = requestAnimationFrame(draw);&#10;            }&#10;            recorder.ondataavailable = function (event) {&#10;              if (event.data &amp;amp;&amp;amp; event.data.size) chunks.push(event.data);&#10;            };&#10;            recorder.onerror = function (event) {&#10;              cleanup();&#10;              reject(event.error || exportError(&amp;#x27;viewer.export.error.mediaRecorder&amp;#x27;));&#10;            };&#10;            recorder.onstop = function () {&#10;              cleanup();&#10;              var blob = new Blob(chunks, { type: recorder.mimeType || mime });&#10;              if (!blob.size) reject(exportError(&amp;#x27;viewer.export.error.emptyWebm&amp;#x27;));&#10;              else resolve(blob);&#10;            };&#10;            drawMotionFrame(ctx, backgroundImage, motionScene, 0);&#10;            recorder.start(250);&#10;            startedAt = performance.now();&#10;            raf = requestAnimationFrame(draw);&#10;            setTimeout(function () {&#10;              if (recorder.state === &amp;#x27;inactive&amp;#x27;) return;&#10;              // Chromium normally emits the final chunk during stop(), but&#10;              // some embedded browser shells need an explicit encoder flush&#10;              // first. Keep the short grace window bounded and harmless for&#10;              // browsers that already delivered timeslice chunks.&#10;              try { recorder.requestData(); } catch (_) {}&#10;              setTimeout(function () {&#10;                if (recorder.state !== &amp;#x27;inactive&amp;#x27;) recorder.stop();&#10;              }, 120);&#10;            }, duration);&#10;          };&#10;          backgroundImage.onerror = function () {&#10;            URL.revokeObjectURL(sourceUrl);&#10;            reject(exportError(&amp;#x27;viewer.export.error.webmBackground&amp;#x27;));&#10;          };&#10;          backgroundImage.src = sourceUrl;&#10;        });&#10;      }&#10;&#10;      var menu = document.getElementById(&amp;#x27;export-menu&amp;#x27;);&#10;      var btn = document.getElementById(&amp;#x27;btn-export&amp;#x27;);&#10;      var routeShareItem = menu.querySelector(&amp;#x27;button[data-action=&amp;quot;route-share-card&amp;quot;]&amp;#x27;);&#10;      var reachShareItem = menu.querySelector(&amp;#x27;button[data-action=&amp;quot;reach-share-card&amp;quot;]&amp;#x27;);&#10;      var items = function () {&#10;        return Array.prototype.slice.call(menu.querySelectorAll(&amp;#x27;button[role=&amp;quot;menuitem&amp;quot;]&amp;#x27;));&#10;      };&#10;&#10;      function syncRouteShareItem() {&#10;        var snapshot = Archify.routeProbe &amp;amp;&amp;amp; typeof Archify.routeProbe.exportSnapshot === &amp;#x27;function&amp;#x27;&#10;          ? Archify.routeProbe.exportSnapshot()&#10;          : null;&#10;        routeShareItem.hidden = !snapshot;&#10;        routeShareItem.disabled = !snapshot;&#10;        return snapshot;&#10;      }&#10;&#10;      function syncReachShareItem() {&#10;        var snapshot = Archify.focus &amp;amp;&amp;amp; typeof Archify.focus.reachabilitySnapshot === &amp;#x27;function&amp;#x27;&#10;          ? Archify.focus.reachabilitySnapshot()&#10;          : null;&#10;        reachShareItem.hidden = !snapshot;&#10;        reachShareItem.disabled = !snapshot;&#10;        return snapshot;&#10;      }&#10;&#10;      // ---- Clipboard support ----------------------------------------------&#10;      function canCopyImage() {&#10;        return typeof ClipboardItem !== &amp;#x27;undefined&amp;#x27; &amp;amp;&amp;amp;&#10;               navigator.clipboard &amp;amp;&amp;amp;&#10;               typeof navigator.clipboard.write === &amp;#x27;function&amp;#x27;;&#10;      }&#10;&#10;      // ---- Raster format detection ----------------------------------------&#10;      // canvas.toBlob(&amp;#x27;image/webp&amp;#x27;) silently returns a PNG on browsers without&#10;      // WebP encoding (older Safari), so detect explicitly.&#10;      function supports(format) {&#10;        if (format === &amp;#x27;share-card&amp;#x27;) return true;&#10;        if (format === &amp;#x27;svg&amp;#x27; || format === &amp;#x27;png&amp;#x27;) return true;&#10;        if (format === &amp;#x27;webm&amp;#x27;) return canRecordMotion();&#10;        var mime = format === &amp;#x27;jpeg&amp;#x27; ? &amp;#x27;image/jpeg&amp;#x27; : &amp;#x27;image/webp&amp;#x27;;&#10;        try {&#10;          var c = document.createElement(&amp;#x27;canvas&amp;#x27;);&#10;          c.width = c.height = 2;&#10;          return c.toDataURL(mime).indexOf(&amp;#x27;data:&amp;#x27; + mime) === 0;&#10;        } catch (_) { return false; }&#10;      }&#10;&#10;      // Gray out unsupported items.&#10;      items().forEach(function (it) {&#10;        if (it.dataset.format &amp;amp;&amp;amp; !supports(it.dataset.format)) {&#10;          it.disabled = true;&#10;          it.title = viewerText(&amp;#x27;viewer.export.unsupported&amp;#x27;);&#10;        }&#10;        if ((it.dataset.action === &amp;#x27;copy&amp;#x27; || it.dataset.action === &amp;#x27;copy-share-card&amp;#x27;) &amp;amp;&amp;amp; !canCopyImage()) {&#10;          it.disabled = true;&#10;          it.title = viewerText(&amp;#x27;viewer.export.clipboardUnsupported&amp;#x27;);&#10;        }&#10;      });&#10;&#10;      // ---- Toast ----------------------------------------------------------&#10;      // A live region only announces CHANGES to an existing node, so the toast&#10;      // element is created once up front and updated in place.&#10;      var toastEl = document.createElement(&amp;#x27;div&amp;#x27;);&#10;      toastEl.className = &amp;#x27;archify-toast&amp;#x27;;&#10;      toastEl.setAttribute(&amp;#x27;role&amp;#x27;, &amp;#x27;status&amp;#x27;);&#10;      document.body.appendChild(toastEl);&#10;      var toastTimer = null;&#10;&#10;      function toast(msg) {&#10;        toastEl.textContent = &amp;#x27;&amp;#x27;;&#10;        requestAnimationFrame(function () {&#10;          toastEl.textContent = msg;&#10;          toastEl.classList.add(&amp;#x27;show&amp;#x27;);&#10;        });&#10;        clearTimeout(toastTimer);&#10;        toastTimer = setTimeout(function () { toastEl.classList.remove(&amp;#x27;show&amp;#x27;); }, 1500);&#10;      }&#10;&#10;      function open(focusLast) {&#10;        if (Archify.preset &amp;amp;&amp;amp; Archify.preset.isOpen()) Archify.preset.close(false);&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; typeof Archify.semanticLens.clearPreview === &amp;#x27;function&amp;#x27;) Archify.semanticLens.clearPreview();&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; Archify.semanticLens.isOpen()) Archify.semanticLens.close({ restoreFocus: false });&#10;        syncRouteShareItem();&#10;        syncReachShareItem();&#10;        menu.classList.add(&amp;#x27;open&amp;#x27;);&#10;        btn.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        var available = items().filter(function (i) { return !i.hidden &amp;amp;&amp;amp; !i.disabled; });&#10;        var target = focusLast ? available[available.length - 1] : available[0];&#10;        if (target) target.focus();&#10;      }&#10;      function close(focusTrigger) {&#10;        menu.classList.remove(&amp;#x27;open&amp;#x27;);&#10;        btn.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        if (focusTrigger) btn.focus();&#10;      }&#10;      function isOpen() { return menu.classList.contains(&amp;#x27;open&amp;#x27;); }&#10;&#10;      btn.addEventListener(&amp;#x27;click&amp;#x27;, function (e) {&#10;        e.stopPropagation();&#10;        if (isOpen()) close(false);&#10;        else open();&#10;      });&#10;      // APG menu-button pattern: ArrowDown/ArrowUp on the trigger opens the menu.&#10;      btn.addEventListener(&amp;#x27;keydown&amp;#x27;, function (e) {&#10;        if (e.key === &amp;#x27;ArrowDown&amp;#x27; || e.key === &amp;#x27;ArrowUp&amp;#x27;) {&#10;          e.preventDefault();&#10;          if (!isOpen()) open(e.key === &amp;#x27;ArrowUp&amp;#x27;);&#10;        }&#10;      });&#10;      document.addEventListener(&amp;#x27;click&amp;#x27;, function (e) {&#10;        if (!menu.contains(e.target) &amp;amp;&amp;amp; e.target !== btn) close(false);&#10;      });&#10;&#10;      // Keyboard navigation inside the menu.&#10;      //   Menu items: Up/Down, Home/End.&#10;      //   Esc closes + returns focus to trigger; Tab closes.&#10;      menu.addEventListener(&amp;#x27;keydown&amp;#x27;, function (e) {&#10;        if (e.key === &amp;#x27;Escape&amp;#x27;) { e.preventDefault(); close(true); return; }&#10;        if (e.key === &amp;#x27;Tab&amp;#x27;)    { close(false); return; }&#10;&#10;        var available = items().filter(function (i) { return !i.hidden &amp;amp;&amp;amp; !i.disabled; });&#10;        var current = available.indexOf(document.activeElement);&#10;        switch (e.key) {&#10;          case &amp;#x27;ArrowDown&amp;#x27;:&#10;            e.preventDefault();&#10;            if (available.length) available[(current + 1 + available.length) % available.length].focus();&#10;            break;&#10;          case &amp;#x27;ArrowUp&amp;#x27;:&#10;            e.preventDefault();&#10;            if (available.length) available[(current - 1 + available.length) % available.length].focus();&#10;            break;&#10;          case &amp;#x27;Home&amp;#x27;:&#10;            e.preventDefault();&#10;            if (available[0]) available[0].focus();&#10;            break;&#10;          case &amp;#x27;End&amp;#x27;:&#10;            e.preventDefault();&#10;            if (available.length) available[available.length - 1].focus();&#10;            break;&#10;        }&#10;      });&#10;&#10;      function runExport(format) {&#10;        var base = diagramFilename();&#10;        close(true);&#10;        clearExportReceipt();&#10;        if (format === &amp;#x27;webm&amp;#x27;) toast(viewerText(&amp;#x27;viewer.export.recording&amp;#x27;));&#10;        return (format === &amp;#x27;share-card&amp;#x27;&#10;          ? rasterizeShareCard().then(function (blob) {&#10;              recordExportReceipt(&amp;#x27;share-card&amp;#x27;, blob, true, { width: SHARE_CARD_WIDTH, height: SHARE_CARD_HEIGHT });&#10;              download(blob, base + &amp;#x27;-share-card.png&amp;#x27;);&#10;              toast(viewerText(&amp;#x27;viewer.export.downloadedShare&amp;#x27;));&#10;            })&#10;          : format === &amp;#x27;svg&amp;#x27;&#10;          ? Promise.resolve(serializeSvg(1, { autoTheme: true })).then(function (d) {&#10;              var blob = new Blob([d.svgString], { type: &amp;#x27;image/svg+xml;charset=utf-8&amp;#x27; });&#10;              recordExportReceipt(&amp;#x27;svg&amp;#x27;, blob, d.canonicalStateClean);&#10;              download(blob, base + &amp;#x27;.svg&amp;#x27;);&#10;            })&#10;          : format === &amp;#x27;webm&amp;#x27;&#10;            ? recordWebm().then(function (blob) {&#10;                document.documentElement.setAttribute(&amp;#x27;data-last-motion-bytes&amp;#x27;, String(blob.size));&#10;                recordExportReceipt(&amp;#x27;webm&amp;#x27;, blob, true);&#10;                download(blob, base + &amp;#x27;.webm&amp;#x27;);&#10;                toast(viewerText(&amp;#x27;viewer.export.downloadedWebm&amp;#x27;));&#10;              })&#10;          : rasterize(format).then(function (blob) {&#10;              recordExportReceipt(format, blob, true);&#10;              download(blob, base + &amp;#x27;.&amp;#x27; + format);&#10;            })&#10;        ).catch(function (err) {&#10;          console.error(err);&#10;          var technicalMessage = err &amp;amp;&amp;amp; err.message ? err.message : format;&#10;          var message = exportMessage(err);&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-error-format&amp;#x27;, format);&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-error&amp;#x27;, technicalMessage);&#10;          if (format === &amp;#x27;webm&amp;#x27;) {&#10;            var motionItem = menu.querySelector(&amp;#x27;button[data-format=&amp;quot;webm&amp;quot;]&amp;#x27;);&#10;            if (motionItem) {&#10;              motionItem.disabled = true;&#10;              motionItem.title = viewerText(&amp;#x27;viewer.export.motionUnavailable&amp;#x27;);&#10;              motionItem.style.opacity = &amp;#x27;0.5&amp;#x27;;&#10;            }&#10;            toast(viewerText(&amp;#x27;viewer.export.webmUnavailable&amp;#x27;));&#10;            return;&#10;          }&#10;          alert(viewerText(&amp;#x27;viewer.export.failed&amp;#x27;, { message: message }));&#10;        });&#10;      }&#10;&#10;      function runRouteShareCard() {&#10;        close(false);&#10;        clearExportReceipt();&#10;        var snapshot = Archify.routeProbe &amp;amp;&amp;amp; Archify.routeProbe.exportSnapshot();&#10;        var blobPromise = snapshot&#10;          ? renderShareCard({ routeSnapshot: snapshot })&#10;          : Promise.reject(exportError(&amp;#x27;viewer.export.routeRequired&amp;#x27;));&#10;        return blobPromise.then(function (blob) {&#10;          recordExportReceipt(&amp;#x27;share-card&amp;#x27;, blob, false, { width: SHARE_CARD_WIDTH, height: SHARE_CARD_HEIGHT }, &amp;#x27;route&amp;#x27;, true);&#10;          download(blob, diagramFilename() + &amp;#x27;-route-share-card.png&amp;#x27;);&#10;          toast(viewerText(&amp;#x27;viewer.export.downloadedRoute&amp;#x27;));&#10;          return blob;&#10;        }).catch(function (err) {&#10;          console.error(err);&#10;          var technicalMessage = err &amp;amp;&amp;amp; err.message ? err.message : &amp;#x27;share-card&amp;#x27;;&#10;          var message = exportMessage(err);&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-error-format&amp;#x27;, &amp;#x27;share-card&amp;#x27;);&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-error&amp;#x27;, technicalMessage);&#10;          alert(viewerText(&amp;#x27;viewer.export.routeFailed&amp;#x27;, { message: message }));&#10;        });&#10;      }&#10;&#10;      function runReachShareCard() {&#10;        close(false);&#10;        clearExportReceipt();&#10;        var snapshot = Archify.focus &amp;amp;&amp;amp; typeof Archify.focus.reachabilitySnapshot === &amp;#x27;function&amp;#x27;&#10;          ? Archify.focus.reachabilitySnapshot()&#10;          : null;&#10;        var blobPromise = snapshot&#10;          ? renderShareCard({ reachSnapshot: snapshot })&#10;          : Promise.reject(exportError(&amp;#x27;viewer.export.reachRequired&amp;#x27;));&#10;        return blobPromise.then(function (blob) {&#10;          recordExportReceipt(&amp;#x27;share-card&amp;#x27;, blob, false, { width: SHARE_CARD_WIDTH, height: SHARE_CARD_HEIGHT }, &amp;#x27;reach&amp;#x27;, false, true);&#10;          download(blob, diagramFilename() + &amp;#x27;-&amp;#x27; + snapshot.direction + &amp;#x27;-reach-share-card.png&amp;#x27;);&#10;          toast(viewerText(&amp;#x27;viewer.export.downloadedReach&amp;#x27;));&#10;          return blob;&#10;        }).catch(function (err) {&#10;          console.error(err);&#10;          var technicalMessage = err &amp;amp;&amp;amp; err.message ? err.message : &amp;#x27;share-card&amp;#x27;;&#10;          var message = exportMessage(err);&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-error-format&amp;#x27;, &amp;#x27;share-card&amp;#x27;);&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-error&amp;#x27;, technicalMessage);&#10;          alert(viewerText(&amp;#x27;viewer.export.reachFailed&amp;#x27;, { message: message }));&#10;        });&#10;      }&#10;&#10;      // A compact, machine-readable receipt for local QA and generated proof&#10;      // galleries. It exposes no diagram contents, only the completed format,&#10;      // byte count, and whether temporary viewer state was excluded.&#10;      function recordExportReceipt(format, blob, canonical, dimensions, variant, routeStateClean, reachStateClean) {&#10;        document.documentElement.setAttribute(&amp;#x27;data-last-export-format&amp;#x27;, format);&#10;        document.documentElement.setAttribute(&amp;#x27;data-last-export-bytes&amp;#x27;, String(blob.size));&#10;        document.documentElement.setAttribute(&amp;#x27;data-last-export-canonical&amp;#x27;, canonical ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;        if (variant) {&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-variant&amp;#x27;, variant);&#10;        } else {&#10;          document.documentElement.removeAttribute(&amp;#x27;data-last-export-variant&amp;#x27;);&#10;        }&#10;        if (routeStateClean === true) {&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-route-state-clean&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        } else {&#10;          document.documentElement.removeAttribute(&amp;#x27;data-last-export-route-state-clean&amp;#x27;);&#10;        }&#10;        if (reachStateClean === true) {&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-reach-state-clean&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        } else {&#10;          document.documentElement.removeAttribute(&amp;#x27;data-last-export-reach-state-clean&amp;#x27;);&#10;        }&#10;        if (dimensions) {&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-width&amp;#x27;, String(dimensions.width));&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-height&amp;#x27;, String(dimensions.height));&#10;        } else {&#10;          document.documentElement.removeAttribute(&amp;#x27;data-last-export-width&amp;#x27;);&#10;          document.documentElement.removeAttribute(&amp;#x27;data-last-export-height&amp;#x27;);&#10;        }&#10;      }&#10;&#10;      function clearExportReceipt() {&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-format&amp;#x27;);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-bytes&amp;#x27;);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-canonical&amp;#x27;);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-width&amp;#x27;);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-height&amp;#x27;);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-variant&amp;#x27;);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-route-state-clean&amp;#x27;);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-reach-state-clean&amp;#x27;);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-error-format&amp;#x27;);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-last-export-error&amp;#x27;);&#10;      }&#10;&#10;      function writePngToClipboard(blobPromise) {&#10;        // WebKit requires ClipboardItem to be constructed synchronously inside&#10;        // the user gesture. Chromium accepts the same pending Promise&amp;lt;Blob&amp;gt;;&#10;        // engines that reject promise values fall back to an awaited Blob.&#10;        try {&#10;          return navigator.clipboard.write([new ClipboardItem({ &amp;#x27;image/png&amp;#x27;: blobPromise })]);&#10;        } catch (_) {&#10;          return blobPromise.then(function (blob) {&#10;            return navigator.clipboard.write([new ClipboardItem({ &amp;#x27;image/png&amp;#x27;: blob })]);&#10;          });&#10;        }&#10;      }&#10;&#10;      function runCopyShareCard() {&#10;        close(true);&#10;        clearExportReceipt();&#10;        if (!canCopyImage()) {&#10;          alert(viewerText(&amp;#x27;viewer.export.clipboardUnsupported.period&amp;#x27;));&#10;          return;&#10;        }&#10;        var blobPromise = rasterizeShareCard();&#10;        return writePngToClipboard(blobPromise).then(function () {&#10;          return blobPromise.then(function (blob) {&#10;            recordExportReceipt(&amp;#x27;share-card&amp;#x27;, blob, true, { width: SHARE_CARD_WIDTH, height: SHARE_CARD_HEIGHT });&#10;            toast(viewerText(&amp;#x27;viewer.export.copiedShare&amp;#x27;));&#10;          });&#10;        }).catch(function (err) {&#10;          console.error(err);&#10;          var technicalMessage = err &amp;amp;&amp;amp; err.message ? err.message : &amp;#x27;share-card&amp;#x27;;&#10;          var message = exportMessage(err);&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-error-format&amp;#x27;, &amp;#x27;share-card&amp;#x27;);&#10;          document.documentElement.setAttribute(&amp;#x27;data-last-export-error&amp;#x27;, technicalMessage);&#10;          alert(viewerText(&amp;#x27;viewer.export.copyFailed&amp;#x27;, { message: message }));&#10;        });&#10;      }&#10;&#10;      function runCopy() {&#10;        close(true);&#10;        clearExportReceipt();&#10;        if (!canCopyImage()) {&#10;          alert(viewerText(&amp;#x27;viewer.export.clipboardUnsupported.short&amp;#x27;));&#10;          return;&#10;        }&#10;        var blobPromise = rasterize(&amp;#x27;png&amp;#x27;);&#10;        return writePngToClipboard(blobPromise).then(function () {&#10;          toast(viewerText(&amp;#x27;viewer.export.copiedPng&amp;#x27;));&#10;        }).catch(function (err) {&#10;          console.error(err);&#10;          alert(viewerText(&amp;#x27;viewer.export.copyFailed&amp;#x27;, {&#10;            message: exportMessage(err)&#10;          }));&#10;        });&#10;      }&#10;&#10;      menu.addEventListener(&amp;#x27;click&amp;#x27;, function (e) {&#10;        var routeShareCardBtn = e.target.closest(&amp;#x27;button[data-action=&amp;quot;route-share-card&amp;quot;]&amp;#x27;);&#10;        if (routeShareCardBtn &amp;amp;&amp;amp; !routeShareCardBtn.disabled &amp;amp;&amp;amp; !routeShareCardBtn.hidden) { runRouteShareCard(); return; }&#10;&#10;        var reachShareCardBtn = e.target.closest(&amp;#x27;button[data-action=&amp;quot;reach-share-card&amp;quot;]&amp;#x27;);&#10;        if (reachShareCardBtn &amp;amp;&amp;amp; !reachShareCardBtn.disabled &amp;amp;&amp;amp; !reachShareCardBtn.hidden) { runReachShareCard(); return; }&#10;&#10;        var copyShareCardBtn = e.target.closest(&amp;#x27;button[data-action=&amp;quot;copy-share-card&amp;quot;]&amp;#x27;);&#10;        if (copyShareCardBtn &amp;amp;&amp;amp; !copyShareCardBtn.disabled) { runCopyShareCard(); return; }&#10;&#10;        var copyBtn = e.target.closest(&amp;#x27;button[data-action=&amp;quot;copy&amp;quot;]&amp;#x27;);&#10;        if (copyBtn &amp;amp;&amp;amp; !copyBtn.disabled) { runCopy(); return; }&#10;&#10;        var formatBtn = e.target.closest(&amp;#x27;button[data-format]&amp;#x27;);&#10;        if (formatBtn &amp;amp;&amp;amp; !formatBtn.disabled) { runExport(formatBtn.dataset.format); }&#10;      });&#10;&#10;      Archify.motion = { canRecord: canRecordMotion, recordWebm: recordWebm };&#10;      Archify.exportMenu = {&#10;        open: open,&#10;        close: close,&#10;        isOpen: isOpen,&#10;        run: runExport,&#10;        shareCard: rasterizeShareCard,&#10;        downloadRouteShareCard: runRouteShareCard,&#10;        downloadReachShareCard: runReachShareCard,&#10;        syncRouteShare: syncRouteShareItem,&#10;        syncReachShare: syncReachShareItem,&#10;        copyShareCard: runCopyShareCard&#10;      };&#10;&#10;      // Auto-open on page load for demo/screenshot purposes: ?openExport=1&#10;      // Wait for fonts (so the menu doesn&amp;#x27;t flash before typography lands)&#10;      // and paint before opening. Fallback timeout for browsers without the&#10;      // Font Loading API.&#10;      try {&#10;        if (new URLSearchParams(window.location.search).get(&amp;#x27;openExport&amp;#x27;) === &amp;#x27;1&amp;#x27;) {&#10;          var openWhenReady = function () {&#10;            requestAnimationFrame(function () { requestAnimationFrame(open); });&#10;          };&#10;          if (document.fonts &amp;amp;&amp;amp; document.fonts.ready) {&#10;            document.fonts.ready.then(openWhenReady);&#10;          } else {&#10;            setTimeout(openWhenReady, 200);&#10;          }&#10;        }&#10;      } catch (_) {}&#10;    })();&#10;&#10;    /* ============================================================&#10;       Motion Governor — one reader switch and one motion budget. Ambient&#10;       trace yields to the strongest semantic owner; Still also parks bounded&#10;       viewer signals without discarding their static meaning.&#10;       ============================================================ */&#10;    Archify.motionGovernor = (function () {&#10;      var STORAGE_KEY = &amp;#x27;archify-motion&amp;#x27;;&#10;      var html = document.documentElement;&#10;      var svg = document.querySelector(&amp;#x27;.diagram-container svg&amp;#x27;);&#10;      var btn = document.getElementById(&amp;#x27;btn-motion&amp;#x27;);&#10;      var label = document.getElementById(&amp;#x27;motion-label&amp;#x27;);&#10;      var motionQuery = window.matchMedia ? window.matchMedia(&amp;#x27;(prefers-reduced-motion: reduce)&amp;#x27;) : null;&#10;      var capable = !!(svg &amp;amp;&amp;amp; svg.getAttribute(&amp;#x27;data-animation&amp;#x27;) === &amp;#x27;trace&amp;#x27;);&#10;      var readerPaused = false;&#10;      var suspensions = Object.create(null);&#10;      var explicitOwner = &amp;#x27;&amp;#x27;;&#10;      var owner = &amp;#x27;&amp;#x27;;&#10;      var ownerToken = 0;&#10;      var ownerCleanup = null;&#10;      var lastEffectivePaused = null;&#10;      var ambientStarted = false;&#10;      var ambientPending = new Set();&#10;&#10;      function detachAmbientBoundary() {&#10;        if (!svg) return;&#10;        svg.removeEventListener(&amp;#x27;animationend&amp;#x27;, onAmbientBoundary, true);&#10;        svg.removeEventListener(&amp;#x27;animationcancel&amp;#x27;, onAmbientBoundary, true);&#10;      }&#10;      function settleAmbient(reason) {&#10;        if (!capable) return false;&#10;        ambientStarted = true;&#10;        ambientPending.clear();&#10;        detachAmbientBoundary();&#10;        html.setAttribute(&amp;#x27;data-ambient-motion&amp;#x27;, &amp;#x27;settled&amp;#x27;);&#10;        html.setAttribute(&amp;#x27;data-ambient-settle-reason&amp;#x27;, reason || &amp;#x27;complete&amp;#x27;);&#10;        return true;&#10;      }&#10;      function onAmbientBoundary(event) {&#10;        if (!ambientPending.has(event.target)) return;&#10;        ambientPending.delete(event.target);&#10;        if (!ambientPending.size) settleAmbient(&amp;#x27;complete&amp;#x27;);&#10;      }&#10;      function startAmbient() {&#10;        if (ambientStarted || !capable) return false;&#10;        ambientStarted = true;&#10;        ambientPending = new Set(Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-animate=&amp;quot;edge&amp;quot;], [data-animate=&amp;quot;node&amp;quot;]&amp;#x27;)));&#10;        if (!ambientPending.size) return settleAmbient(&amp;#x27;empty&amp;#x27;);&#10;        svg.addEventListener(&amp;#x27;animationend&amp;#x27;, onAmbientBoundary, true);&#10;        svg.addEventListener(&amp;#x27;animationcancel&amp;#x27;, onAmbientBoundary, true);&#10;        html.setAttribute(&amp;#x27;data-ambient-motion&amp;#x27;, &amp;#x27;running&amp;#x27;);&#10;        html.removeAttribute(&amp;#x27;data-ambient-settle-reason&amp;#x27;);&#10;        return true;&#10;      }&#10;&#10;      function readStored() {&#10;        try { return localStorage.getItem(STORAGE_KEY); } catch (_) { return null; }&#10;      }&#10;      function writeStored() {&#10;        try {&#10;          if (readerPaused) localStorage.setItem(STORAGE_KEY, &amp;#x27;still&amp;#x27;);&#10;          else localStorage.removeItem(STORAGE_KEY);&#10;        } catch (_) {}&#10;      }&#10;      function reducedMotion() {&#10;        return !!(motionQuery &amp;amp;&amp;amp; motionQuery.matches);&#10;      }&#10;      function hasSuspension() {&#10;        return Object.keys(suspensions).length &amp;gt; 0;&#10;      }&#10;      function effectivePaused() {&#10;        return readerPaused || reducedMotion() || hasSuspension();&#10;      }&#10;      function ownerLabel(value) {&#10;        if (value === &amp;#x27;story&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.story&amp;#x27;);&#10;        if (value === &amp;#x27;chapter&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.chapter&amp;#x27;);&#10;        if (value === &amp;#x27;chapter-preview&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.chapterPreview&amp;#x27;);&#10;        if (value === &amp;#x27;handoff&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.handoff&amp;#x27;);&#10;        if (value === &amp;#x27;route&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.route&amp;#x27;);&#10;        if (value === &amp;#x27;lens&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.lens&amp;#x27;);&#10;        if (value === &amp;#x27;relationship&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.relationship&amp;#x27;);&#10;        if (value === &amp;#x27;intent&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.intent&amp;#x27;);&#10;        if (value === &amp;#x27;focus&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.focus&amp;#x27;);&#10;        if (value === &amp;#x27;legend&amp;#x27;) return viewerText(&amp;#x27;viewer.owner.legend&amp;#x27;);&#10;        return viewerText(&amp;#x27;viewer.owner.reader&amp;#x27;);&#10;      }&#10;      function render() {&#10;        if (!capable) return;&#10;        var systemPaused = reducedMotion();&#10;        var paused = effectivePaused();&#10;        html.setAttribute(&amp;#x27;data-motion&amp;#x27;, paused ? &amp;#x27;still&amp;#x27; : &amp;#x27;live&amp;#x27;);&#10;        if (paused || owner || html.hasAttribute(&amp;#x27;data-embed&amp;#x27;) || html.hasAttribute(&amp;#x27;data-share-playback&amp;#x27;) || html.hasAttribute(&amp;#x27;data-document-hidden&amp;#x27;)) {&#10;          settleAmbient(&amp;#x27;suppressed&amp;#x27;);&#10;        } else if (!ambientStarted) {&#10;          startAmbient();&#10;        }&#10;        btn.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, paused ? &amp;#x27;false&amp;#x27; : &amp;#x27;true&amp;#x27;);&#10;        btn.disabled = systemPaused;&#10;        label.textContent = viewerText(paused ? &amp;#x27;viewer.motion.still&amp;#x27; : &amp;#x27;viewer.motion.live&amp;#x27;);&#10;        if (paused &amp;amp;&amp;amp; lastEffectivePaused !== true &amp;amp;&amp;amp; Archify.guidedViews &amp;amp;&amp;amp; Archify.guidedViews.isPlaying()) {&#10;          Archify.guidedViews.pause();&#10;        }&#10;        if (paused &amp;amp;&amp;amp; lastEffectivePaused !== true &amp;amp;&amp;amp; Archify.guidedViews &amp;amp;&amp;amp; Archify.guidedViews.settleHandoff) {&#10;          Archify.guidedViews.settleHandoff(systemPaused ? &amp;#x27;reduced-motion&amp;#x27; : (hasSuspension() ? &amp;#x27;hidden&amp;#x27; : &amp;#x27;still&amp;#x27;));&#10;        }&#10;        if (paused &amp;amp;&amp;amp; lastEffectivePaused !== true &amp;amp;&amp;amp; Archify.routeProbe &amp;amp;&amp;amp; Archify.routeProbe.isJourneyPlaying &amp;amp;&amp;amp; Archify.routeProbe.isJourneyPlaying()) {&#10;          Archify.routeProbe.pauseJourney({ preserveElapsed: true, reason: systemPaused ? &amp;#x27;reduced-motion&amp;#x27; : (hasSuspension() ? &amp;#x27;hidden&amp;#x27; : &amp;#x27;still&amp;#x27;) });&#10;        }&#10;        lastEffectivePaused = paused;&#10;        if (Archify.routeProbe &amp;amp;&amp;amp; typeof Archify.routeProbe.syncMotion === &amp;#x27;function&amp;#x27;) Archify.routeProbe.syncMotion();&#10;        if (systemPaused) {&#10;          btn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.motion.reduced&amp;#x27;));&#10;          btn.title = viewerText(&amp;#x27;viewer.motion.reduced&amp;#x27;);&#10;        } else if (hasSuspension()) {&#10;          btn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.motion.hidden&amp;#x27;));&#10;          btn.title = viewerText(&amp;#x27;viewer.motion.hidden&amp;#x27;);&#10;        } else if (paused) {&#10;          btn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.motion.resume&amp;#x27;));&#10;          btn.title = viewerText(&amp;#x27;viewer.motion.resume&amp;#x27;);&#10;        } else if (owner) {&#10;          btn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.motion.yielding&amp;#x27;, { owner: ownerLabel(owner) }));&#10;          btn.title = viewerText(&amp;#x27;viewer.motion.yielding.title&amp;#x27;, { owner: ownerLabel(owner) });&#10;        } else {&#10;          btn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.motion.pause&amp;#x27;));&#10;          btn.title = viewerText(&amp;#x27;viewer.motion.pause&amp;#x27;);&#10;        }&#10;      }&#10;      function setPaused(next, options) {&#10;        options = options || {};&#10;        readerPaused = !!next;&#10;        if (options.persist !== false) writeStored();&#10;        render();&#10;        return readerPaused;&#10;      }&#10;      function publishOwner() {&#10;        owner = explicitOwner || deriveOwner();&#10;        if (owner) html.setAttribute(&amp;#x27;data-motion-owner&amp;#x27;, owner);&#10;        else html.removeAttribute(&amp;#x27;data-motion-owner&amp;#x27;);&#10;        render();&#10;        return owner;&#10;      }&#10;      function deriveOwner() {&#10;        if (!svg) return &amp;#x27;&amp;#x27;;&#10;        if (svg.hasAttribute(&amp;#x27;data-story-playing&amp;#x27;) || svg.hasAttribute(&amp;#x27;data-story-follow&amp;#x27;)) return &amp;#x27;story&amp;#x27;;&#10;        if (svg.hasAttribute(&amp;#x27;data-story-active&amp;#x27;)) return &amp;#x27;chapter&amp;#x27;;&#10;        if (svg.hasAttribute(&amp;#x27;data-route-picking&amp;#x27;) || svg.hasAttribute(&amp;#x27;data-route-active&amp;#x27;)) return &amp;#x27;route&amp;#x27;;&#10;        if (svg.hasAttribute(&amp;#x27;data-lens-active&amp;#x27;)) return &amp;#x27;lens&amp;#x27;;&#10;        if (svg.hasAttribute(&amp;#x27;data-relationship-preview-active&amp;#x27;)) return &amp;#x27;relationship&amp;#x27;;&#10;        if (svg.hasAttribute(&amp;#x27;data-intent-trace-active&amp;#x27;)) return &amp;#x27;intent&amp;#x27;;&#10;        if (svg.hasAttribute(&amp;#x27;data-focus-active&amp;#x27;)) return &amp;#x27;focus&amp;#x27;;&#10;        if (svg.hasAttribute(&amp;#x27;data-legend-preview-active&amp;#x27;)) return &amp;#x27;legend&amp;#x27;;&#10;        return &amp;#x27;&amp;#x27;;&#10;      }&#10;      function clearClaim(preempted) {&#10;        var cleanup = ownerCleanup;&#10;        ownerCleanup = null;&#10;        explicitOwner = &amp;#x27;&amp;#x27;;&#10;        if (preempted &amp;amp;&amp;amp; cleanup) {&#10;          try { cleanup(); } catch (_) {}&#10;        }&#10;      }&#10;      function claim(next, cleanup) {&#10;        if (!capable || !next) return 0;&#10;        clearClaim(true);&#10;        ownerToken += 1;&#10;        explicitOwner = next;&#10;        ownerCleanup = typeof cleanup === &amp;#x27;function&amp;#x27; ? cleanup : null;&#10;        publishOwner();&#10;        return ownerToken;&#10;      }&#10;      function release(token) {&#10;        if (!capable || token !== ownerToken || !explicitOwner) return false;&#10;        clearClaim(false);&#10;        ownerToken += 1;&#10;        publishOwner();&#10;        return true;&#10;      }&#10;      function suspend(reason) {&#10;        var key = String(reason || &amp;#x27;runtime&amp;#x27;);&#10;        var active = true;&#10;        suspensions[key] = (suspensions[key] || 0) + 1;&#10;        render();&#10;        return function () {&#10;          if (!active) return false;&#10;          active = false;&#10;          if (suspensions[key] &amp;gt; 1) suspensions[key] -= 1;&#10;          else delete suspensions[key];&#10;          render();&#10;          return true;&#10;        };&#10;      }&#10;      function syncVisibility() {&#10;        if (document.hidden) {&#10;          suspensions.visibility = true;&#10;          html.setAttribute(&amp;#x27;data-document-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        } else {&#10;          delete suspensions.visibility;&#10;          html.removeAttribute(&amp;#x27;data-document-hidden&amp;#x27;);&#10;        }&#10;        render();&#10;      }&#10;&#10;      if (!capable) {&#10;        btn.hidden = true;&#10;        html.removeAttribute(&amp;#x27;data-motion-capable&amp;#x27;);&#10;        html.removeAttribute(&amp;#x27;data-motion&amp;#x27;);&#10;        html.removeAttribute(&amp;#x27;data-motion-owner&amp;#x27;);&#10;        html.removeAttribute(&amp;#x27;data-ambient-motion&amp;#x27;);&#10;        html.removeAttribute(&amp;#x27;data-ambient-settle-reason&amp;#x27;);&#10;        return {&#10;          capable: false,&#10;          pause: function () { return false; },&#10;          resume: function () { return false; },&#10;          toggle: function () { return false; },&#10;          setMode: function () { return &amp;#x27;still&amp;#x27;; },&#10;          mode: function () { return &amp;#x27;still&amp;#x27;; },&#10;          claim: function () { return 0; },&#10;          release: function () { return false; },&#10;          suspend: function () { return function () { return false; }; },&#10;          isPaused: function () { return true; },&#10;          owner: function () { return &amp;#x27;&amp;#x27;; }&#10;        };&#10;      }&#10;&#10;      html.setAttribute(&amp;#x27;data-motion-capable&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;      btn.hidden = false;&#10;      readerPaused = readStored() === &amp;#x27;still&amp;#x27;;&#10;      btn.addEventListener(&amp;#x27;click&amp;#x27;, function () { setPaused(!readerPaused); });&#10;      if (motionQuery) {&#10;        if (typeof motionQuery.addEventListener === &amp;#x27;function&amp;#x27;) motionQuery.addEventListener(&amp;#x27;change&amp;#x27;, render);&#10;        else if (typeof motionQuery.addListener === &amp;#x27;function&amp;#x27;) motionQuery.addListener(render);&#10;      }&#10;      document.addEventListener(&amp;#x27;visibilitychange&amp;#x27;, syncVisibility);&#10;      if (document.documentElement.getAttribute(&amp;#x27;data-embed&amp;#x27;) !== &amp;#x27;true&amp;#x27; &amp;amp;&amp;amp; typeof MutationObserver !== &amp;#x27;undefined&amp;#x27; &amp;amp;&amp;amp; typeof Node !== &amp;#x27;undefined&amp;#x27; &amp;amp;&amp;amp; svg instanceof Node) {&#10;        var ownerObserver = new MutationObserver(function () { publishOwner(); });&#10;        ownerObserver.observe(svg, {&#10;          attributes: true,&#10;          attributeFilter: [&#10;            &amp;#x27;data-story-playing&amp;#x27;, &amp;#x27;data-story-follow&amp;#x27;, &amp;#x27;data-story-active&amp;#x27;, &amp;#x27;data-route-picking&amp;#x27;, &amp;#x27;data-route-active&amp;#x27;,&#10;            &amp;#x27;data-lens-active&amp;#x27;, &amp;#x27;data-relationship-preview-active&amp;#x27;, &amp;#x27;data-intent-trace-active&amp;#x27;,&#10;            &amp;#x27;data-focus-active&amp;#x27;, &amp;#x27;data-legend-preview-active&amp;#x27;&#10;          ]&#10;        });&#10;      }&#10;      syncVisibility();&#10;      publishOwner();&#10;      render();&#10;&#10;      return {&#10;        capable: true,&#10;        pause: function () { return setPaused(true); },&#10;        resume: function () { return setPaused(false); },&#10;        toggle: function () { return setPaused(!readerPaused); },&#10;        setMode: function (next, options) {&#10;          setPaused(next === &amp;#x27;still&amp;#x27;, options);&#10;          return effectivePaused() ? &amp;#x27;still&amp;#x27; : &amp;#x27;live&amp;#x27;;&#10;        },&#10;        mode: function () { return effectivePaused() ? &amp;#x27;still&amp;#x27; : &amp;#x27;live&amp;#x27;; },&#10;        claim: claim,&#10;        release: release,&#10;        suspend: suspend,&#10;        isPaused: effectivePaused,&#10;        owner: function () { return owner; }&#10;      };&#10;    })();&#10;&#10;    /* Verified repository evidence is emitted only after the renderer checks&#10;       the authored GitHub revision, source blobs, and optional line ranges&#10;       against the explicit --repo-root. It remains outside the SVG so every&#10;       canonical visual export stays free of repository paths. */&#10;    Archify.sourceEvidence = (function () {&#10;      var element = document.getElementById(&amp;#x27;archify-source-evidence-data&amp;#x27;);&#10;      var payload = null;&#10;      var svgNamespace = &amp;#x27;http://www.w3.org/2000/svg&amp;#x27;;&#10;      if (element) {&#10;        try {&#10;          var parsed = JSON.parse(element.textContent || &amp;#x27;null&amp;#x27;);&#10;          if (parsed &amp;amp;&amp;amp; parsed.verified === true &amp;amp;&amp;amp; parsed.repository &amp;amp;&amp;amp; parsed.nodes) payload = parsed;&#10;        } catch (_) {}&#10;      }&#10;      function installBeacons() {&#10;        if (!payload) return 0;&#10;        var svg = document.querySelector(&amp;#x27;.diagram-container svg&amp;#x27;);&#10;        if (!svg) return 0;&#10;        var installed = 0;&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;), function (node) {&#10;          var id = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;          var sources = payload.nodes[id];&#10;          if (!Array.isArray(sources) || !sources.length || node.querySelector(&amp;#x27;[data-source-evidence-beacon]&amp;#x27;)) return;&#10;          var shape = node.querySelector(&amp;#x27;[data-animate=&amp;quot;node&amp;quot;]&amp;#x27;) || node.querySelector(&amp;#x27;[class*=&amp;quot;c-&amp;quot;]&amp;#x27;);&#10;          var box;&#10;          try { box = (shape || node).getBBox(); } catch (_) { return; }&#10;          if (!box || !Number.isFinite(box.x) || !Number.isFinite(box.y) || !Number.isFinite(box.width) || box.width &amp;lt; 36) return;&#10;&#10;          var count = sources.length;&#10;          var label = viewerCount(&amp;#x27;viewer.passport.beacon&amp;#x27;, count);&#10;          var beacon = document.createElementNS(svgNamespace, &amp;#x27;g&amp;#x27;);&#10;          beacon.classList.add(&amp;#x27;source-evidence-beacon&amp;#x27;);&#10;          beacon.setAttribute(&amp;#x27;data-source-evidence-beacon&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          beacon.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          var brandOffset = node.hasAttribute(&amp;#x27;data-node-brand&amp;#x27;) ? 24 : 0;&#10;          beacon.setAttribute(&amp;#x27;transform&amp;#x27;, &amp;#x27;translate(&amp;#x27; + (box.x + box.width - 35 - brandOffset) + &amp;#x27; &amp;#x27; + (box.y + 5) + &amp;#x27;)&amp;#x27;);&#10;          var title = document.createElementNS(svgNamespace, &amp;#x27;title&amp;#x27;);&#10;          title.textContent = label;&#10;          var plate = document.createElementNS(svgNamespace, &amp;#x27;rect&amp;#x27;);&#10;          plate.setAttribute(&amp;#x27;width&amp;#x27;, &amp;#x27;30&amp;#x27;);&#10;          plate.setAttribute(&amp;#x27;height&amp;#x27;, &amp;#x27;12&amp;#x27;);&#10;          plate.setAttribute(&amp;#x27;rx&amp;#x27;, &amp;#x27;6&amp;#x27;);&#10;          var text = document.createElementNS(svgNamespace, &amp;#x27;text&amp;#x27;);&#10;          text.setAttribute(&amp;#x27;x&amp;#x27;, &amp;#x27;15&amp;#x27;);&#10;          text.setAttribute(&amp;#x27;y&amp;#x27;, &amp;#x27;8.25&amp;#x27;);&#10;          text.textContent = viewerText(&amp;#x27;viewer.passport.sourceMarker&amp;#x27;) + &amp;#x27; &amp;#x27; + count;&#10;          beacon.appendChild(title);&#10;          beacon.appendChild(plate);&#10;          beacon.appendChild(text);&#10;          node.appendChild(beacon);&#10;&#10;          var originalLabel = node.getAttribute(&amp;#x27;aria-label&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;          node.setAttribute(&amp;#x27;data-source-evidence-count&amp;#x27;, String(count));&#10;          node.setAttribute(&amp;#x27;data-source-evidence-original-label&amp;#x27;, originalLabel);&#10;          node.setAttribute(&amp;#x27;aria-label&amp;#x27;, (originalLabel ? originalLabel + &amp;#x27;, &amp;#x27; : &amp;#x27;&amp;#x27;) + viewerCount(&amp;#x27;viewer.passport.sourceCount&amp;#x27;, count));&#10;          installed += 1;&#10;        });&#10;        return installed;&#10;      }&#10;      return {&#10;        available: function () { return Boolean(payload); },&#10;        repository: function () { return payload ? payload.repository : null; },&#10;        node: function (id) {&#10;          var sources = payload &amp;amp;&amp;amp; payload.nodes ? payload.nodes[id] : null;&#10;          return Array.isArray(sources) ? sources.slice() : [];&#10;        },&#10;        installBeacons: installBeacons&#10;      };&#10;    })();&#10;    Archify.sourceEvidence.installBeacons();&#10;&#10;    /* ============================================================&#10;       Explore — stable-ID neighborhood focus + dependency-free pan/zoom.&#10;       Renderer IDs become deep-linkable semantic hooks without turning the&#10;       standalone artifact into a canvas editor.&#10;       ============================================================ */&#10;    Archify.focus = (function () {&#10;      var html = document.documentElement;&#10;      var container = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var svg = container.querySelector(&amp;#x27;svg&amp;#x27;);&#10;      var chip = document.getElementById(&amp;#x27;focus-chip&amp;#x27;);&#10;      var label = document.getElementById(&amp;#x27;focus-label&amp;#x27;);&#10;      var detail = document.getElementById(&amp;#x27;focus-detail&amp;#x27;);&#10;      var kind = document.getElementById(&amp;#x27;focus-kind&amp;#x27;);&#10;      var context = document.getElementById(&amp;#x27;focus-context&amp;#x27;);&#10;      var tag = document.getElementById(&amp;#x27;focus-tag&amp;#x27;);&#10;      var semanticId = document.getElementById(&amp;#x27;focus-id&amp;#x27;);&#10;      var evidence = document.getElementById(&amp;#x27;focus-evidence&amp;#x27;);&#10;      var repositoryLink = document.getElementById(&amp;#x27;focus-repository&amp;#x27;);&#10;      var evidenceLinks = document.getElementById(&amp;#x27;focus-evidence-links&amp;#x27;);&#10;      var summary = document.getElementById(&amp;#x27;focus-summary&amp;#x27;);&#10;      var reachSection = document.getElementById(&amp;#x27;focus-reach&amp;#x27;);&#10;      var reachStatus = document.getElementById(&amp;#x27;focus-reach-status&amp;#x27;);&#10;      var upstreamBtn = document.getElementById(&amp;#x27;btn-reach-upstream&amp;#x27;);&#10;      var downstreamBtn = document.getElementById(&amp;#x27;btn-reach-downstream&amp;#x27;);&#10;      var upstreamCount = document.getElementById(&amp;#x27;focus-reach-upstream-count&amp;#x27;);&#10;      var downstreamCount = document.getElementById(&amp;#x27;focus-reach-downstream-count&amp;#x27;);&#10;      var relationshipList = document.getElementById(&amp;#x27;relationship-lens-list&amp;#x27;);&#10;      var copyBtn = document.getElementById(&amp;#x27;btn-focus-copy&amp;#x27;);&#10;      var relationsBtn = document.getElementById(&amp;#x27;btn-focus-relations&amp;#x27;);&#10;      var clearBtn = document.getElementById(&amp;#x27;btn-focus-clear&amp;#x27;);&#10;      var activeIds = [];&#10;      var hoveredRelationship = null;&#10;      var focusedRelationship = null;&#10;      var pinnedRelationship = null;&#10;      var pinnedRelationshipKey = null;&#10;      var activeRelationshipPreview = null;&#10;      var relationshipHitOverlay = null;&#10;      var relationshipHitTargets = [];&#10;      var directPreviewTimer = null;&#10;      var reachabilityMode = null;&#10;      var activeReachability = null;&#10;      var svgNamespace = &amp;#x27;http://www.w3.org/2000/svg&amp;#x27;;&#10;      var reducedMotionQuery = window.matchMedia ? window.matchMedia(&amp;#x27;(prefers-reduced-motion: reduce)&amp;#x27;) : null;&#10;      var finePointerQuery = window.matchMedia ? window.matchMedia(&amp;#x27;(hover: hover) and (pointer: fine)&amp;#x27;) : null;&#10;&#10;      function nodes() {&#10;        return Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;));&#10;      }&#10;      function edges() {&#10;        return Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-edge-from][data-edge-to]&amp;#x27;));&#10;      }&#10;      function nodeLabel(node, fallback) {&#10;        return node.getAttribute(&amp;#x27;data-node-label&amp;#x27;) || (node.getAttribute(&amp;#x27;aria-label&amp;#x27;) || fallback).replace(/^Focus\s+/, &amp;#x27;&amp;#x27;);&#10;      }&#10;      function reachabilityRelationships() {&#10;        var seen = Object.create(null);&#10;        var relationships = [];&#10;        edges().forEach(function (edge) {&#10;          var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;          var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;          var key = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) || (from + &amp;#x27;\u0000&amp;#x27; + to + &amp;#x27;\u0000&amp;#x27; + (edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;));&#10;          if (!from || !to || seen[key]) return;&#10;          seen[key] = true;&#10;          relationships.push({ key: key, from: from, to: to });&#10;        });&#10;        return relationships;&#10;      }&#10;      function computeReachability(originId, direction, relationships) {&#10;        if (typeof originId !== &amp;#x27;string&amp;#x27; || !originId ||&#10;            (direction !== &amp;#x27;upstream&amp;#x27; &amp;amp;&amp;amp; direction !== &amp;#x27;downstream&amp;#x27;) ||&#10;            !Array.isArray(relationships)) return null;&#10;        var records = [];&#10;        var seenKeys = Object.create(null);&#10;        relationships.forEach(function (relationship, index) {&#10;          if (!relationship || typeof relationship.from !== &amp;#x27;string&amp;#x27; || !relationship.from ||&#10;              typeof relationship.to !== &amp;#x27;string&amp;#x27; || !relationship.to) return;&#10;          var key = typeof relationship.key === &amp;#x27;string&amp;#x27; &amp;amp;&amp;amp; relationship.key&#10;            ? relationship.key : String(index);&#10;          if (seenKeys[key]) return;&#10;          seenKeys[key] = true;&#10;          records.push({ key: key, from: relationship.from, to: relationship.to });&#10;        });&#10;&#10;        var depths = Object.create(null);&#10;        var order = [];&#10;        var queue = [originId];&#10;        depths[originId] = 0;&#10;        for (var cursor = 0; cursor &amp;lt; queue.length; cursor += 1) {&#10;          var current = queue[cursor];&#10;          records.forEach(function (relationship) {&#10;            var next = null;&#10;            if (direction === &amp;#x27;downstream&amp;#x27; &amp;amp;&amp;amp; relationship.from === current) next = relationship.to;&#10;            else if (direction === &amp;#x27;upstream&amp;#x27; &amp;amp;&amp;amp; relationship.to === current) next = relationship.from;&#10;            if (next == null || Object.prototype.hasOwnProperty.call(depths, next)) return;&#10;            depths[next] = depths[current] + 1;&#10;            queue.push(next);&#10;          });&#10;        }&#10;        queue.forEach(function (id) { order.push(id); });&#10;&#10;        var edgeKeys = [];&#10;        records.forEach(function (relationship) {&#10;          if (Object.prototype.hasOwnProperty.call(depths, relationship.from) &amp;amp;&amp;amp;&#10;              Object.prototype.hasOwnProperty.call(depths, relationship.to)) edgeKeys.push(relationship.key);&#10;        });&#10;        var maxDepth = order.reduce(function (maximum, id) {&#10;          return Math.max(maximum, depths[id]);&#10;        }, 0);&#10;        return {&#10;          direction: direction,&#10;          originId: originId,&#10;          nodeIds: order,&#10;          edgeKeys: edgeKeys,&#10;          depths: depths,&#10;          maxDepth: maxDepth&#10;        };&#10;      }&#10;      function reachabilityFor(id, direction) {&#10;        return computeReachability(id, direction, reachabilityRelationships());&#10;      }&#10;      function resetReachabilityButtons() {&#10;        upstreamBtn.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        downstreamBtn.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;      }&#10;      function clearReachability(options) {&#10;        options = options || {};&#10;        reachabilityMode = null;&#10;        activeReachability = null;&#10;        svg.removeAttribute(&amp;#x27;data-reach-active&amp;#x27;);&#10;        chip.removeAttribute(&amp;#x27;data-reach-mode&amp;#x27;);&#10;        nodes().forEach(function (node) {&#10;          node.removeAttribute(&amp;#x27;data-reach-match&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-reach-origin&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-reach-depth&amp;#x27;);&#10;        });&#10;        edges().forEach(function (edge) {&#10;          edge.removeAttribute(&amp;#x27;data-reach-match&amp;#x27;);&#10;          edge.removeAttribute(&amp;#x27;data-reach-depth&amp;#x27;);&#10;        });&#10;        resetReachabilityButtons();&#10;        reachStatus.textContent = &amp;#x27;&amp;#x27;;&#10;        reachStatus.hidden = true;&#10;        if (Archify.exportMenu &amp;amp;&amp;amp; typeof Archify.exportMenu.syncReachShare === &amp;#x27;function&amp;#x27;) {&#10;          Archify.exportMenu.syncReachShare();&#10;        }&#10;        if (options.updateUrl === true &amp;amp;&amp;amp; activeIds.length === 1) {&#10;          try {&#10;            history.replaceState(null, &amp;#x27;&amp;#x27;, location.pathname + location.search + &amp;#x27;#focus=&amp;#x27; + encodeURIComponent(activeIds[0]));&#10;          } catch (_) {}&#10;        }&#10;      }&#10;      function renderReachabilityControls(id) {&#10;        var upstream = reachabilityFor(id, &amp;#x27;upstream&amp;#x27;);&#10;        var downstream = reachabilityFor(id, &amp;#x27;downstream&amp;#x27;);&#10;        var upstreamReach = upstream ? Math.max(0, upstream.nodeIds.length - 1) : 0;&#10;        var downstreamReach = downstream ? Math.max(0, downstream.nodeIds.length - 1) : 0;&#10;        upstreamCount.textContent = String(upstreamReach);&#10;        downstreamCount.textContent = String(downstreamReach);&#10;        upstreamBtn.disabled = upstreamReach === 0;&#10;        downstreamBtn.disabled = downstreamReach === 0;&#10;        upstreamBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, upstreamReach&#10;          ? viewerCount(&amp;#x27;viewer.passport.reach.upstream&amp;#x27;, upstreamReach)&#10;          : viewerText(&amp;#x27;viewer.passport.reach.noUpstream&amp;#x27;));&#10;        downstreamBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, downstreamReach&#10;          ? viewerCount(&amp;#x27;viewer.passport.reach.downstream&amp;#x27;, downstreamReach)&#10;          : viewerText(&amp;#x27;viewer.passport.reach.noDownstream&amp;#x27;));&#10;        reachSection.hidden = false;&#10;      }&#10;      function applyReachability(direction, options) {&#10;        options = options || {};&#10;        if (activeIds.length !== 1 || (direction !== &amp;#x27;upstream&amp;#x27; &amp;amp;&amp;amp; direction !== &amp;#x27;downstream&amp;#x27;)) return false;&#10;        if (reachabilityMode === direction &amp;amp;&amp;amp; options.toggle !== false) {&#10;          clearReachability({ updateUrl: options.updateUrl !== false });&#10;          return true;&#10;        }&#10;        var result = reachabilityFor(activeIds[0], direction);&#10;        if (!result || result.nodeIds.length &amp;lt;= 1) return false;&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; typeof Archify.guidedViews.showAll === &amp;#x27;function&amp;#x27;) {&#10;          Archify.guidedViews.showAll({ clearFocus: false, updateUrl: false, resetView: false });&#10;        }&#10;        clearRelationshipPreview({ clearPin: true });&#10;        clearReachability({ updateUrl: false });&#10;        reachabilityMode = direction;&#10;        activeReachability = result;&#10;        var edgeKeySet = Object.create(null);&#10;        result.edgeKeys.forEach(function (key) { edgeKeySet[key] = true; });&#10;        svg.setAttribute(&amp;#x27;data-reach-active&amp;#x27;, direction);&#10;        chip.setAttribute(&amp;#x27;data-reach-mode&amp;#x27;, direction);&#10;        nodes().forEach(function (node) {&#10;          var id = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;          if (!Object.prototype.hasOwnProperty.call(result.depths, id)) return;&#10;          node.setAttribute(&amp;#x27;data-reach-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          node.setAttribute(&amp;#x27;data-reach-depth&amp;#x27;, String(result.depths[id]));&#10;          if (id === result.originId) node.setAttribute(&amp;#x27;data-reach-origin&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        });&#10;        edges().forEach(function (edge) {&#10;          var key = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) || (&#10;            edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;) + &amp;#x27;\u0000&amp;#x27; +&#10;            edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;) + &amp;#x27;\u0000&amp;#x27; +&#10;            (edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;)&#10;          );&#10;          if (!edgeKeySet[key]) return;&#10;          edge.setAttribute(&amp;#x27;data-reach-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          var fromDepth = result.depths[edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;)];&#10;          var toDepth = result.depths[edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;)];&#10;          edge.setAttribute(&amp;#x27;data-reach-depth&amp;#x27;, String(Math.max(fromDepth || 0, toDepth || 0)));&#10;        });&#10;        resetReachabilityButtons();&#10;        var activeButton = direction === &amp;#x27;upstream&amp;#x27; ? upstreamBtn : downstreamBtn;&#10;        activeButton.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        var reachableCount = result.nodeIds.length - 1;&#10;        var directionLabel = viewerText(direction === &amp;#x27;upstream&amp;#x27;&#10;          ? &amp;#x27;viewer.passport.upstream&amp;#x27;&#10;          : &amp;#x27;viewer.passport.downstream&amp;#x27;);&#10;        reachStatus.textContent = viewerText(&amp;#x27;viewer.passport.reach.status&amp;#x27;, {&#10;          direction: directionLabel,&#10;          nodes: reachableCount,&#10;          links: result.edgeKeys.length,&#10;          hops: result.maxDepth&#10;        });&#10;        reachStatus.hidden = false;&#10;        if (Archify.exportMenu &amp;amp;&amp;amp; typeof Archify.exportMenu.syncReachShare === &amp;#x27;function&amp;#x27;) {&#10;          Archify.exportMenu.syncReachShare();&#10;        }&#10;        if (options.updateUrl !== false) {&#10;          try {&#10;            history.replaceState(null, &amp;#x27;&amp;#x27;, location.pathname + location.search + &amp;#x27;#focus=&amp;#x27; +&#10;              encodeURIComponent(activeIds[0]) + &amp;#x27;&amp;amp;reach=&amp;#x27; + direction);&#10;          } catch (_) {}&#10;        }&#10;        if (options.reveal !== false &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reveal(result.nodeIds, { includeNeighbors: false, reason: &amp;#x27;reachability&amp;#x27; });&#10;        }&#10;        requestLensPlacement();&#10;        return true;&#10;      }&#10;      function reachabilitySnapshot() {&#10;        if (!activeReachability || activeIds.length !== 1 ||&#10;            (reachabilityMode !== &amp;#x27;upstream&amp;#x27; &amp;amp;&amp;amp; reachabilityMode !== &amp;#x27;downstream&amp;#x27;) ||&#10;            activeReachability.direction !== reachabilityMode ||&#10;            activeReachability.originId !== activeIds[0] ||&#10;            svg.getAttribute(&amp;#x27;data-reach-active&amp;#x27;) !== reachabilityMode) return null;&#10;&#10;        var originId = activeReachability.originId;&#10;        var nodeIds = activeReachability.nodeIds.slice();&#10;        var edgeKeys = activeReachability.edgeKeys.slice();&#10;        if (nodeIds.length &amp;lt; 2 || nodeIds[0] !== originId || !edgeKeys.length ||&#10;            !activeReachability.depths || !Number.isInteger(activeReachability.maxDepth) ||&#10;            activeReachability.maxDepth &amp;lt; 1) return null;&#10;&#10;        var allNodes = nodes();&#10;        var allEdges = edges();&#10;        var seenNodeIds = Object.create(null);&#10;        var seenEdgeKeys = Object.create(null);&#10;        var nodeIdSet = Object.create(null);&#10;        var depths = Object.create(null);&#10;        var originNode = null;&#10;        var measuredMaxDepth = 0;&#10;&#10;        if (nodeIds.some(function (id) {&#10;          var depth = activeReachability.depths[id];&#10;          var matches = allNodes.filter(function (node) {&#10;            return node.getAttribute(&amp;#x27;data-node-id&amp;#x27;) === id;&#10;          });&#10;          if (typeof id !== &amp;#x27;string&amp;#x27; || !id || seenNodeIds[id] || matches.length !== 1 ||&#10;              !matches[0].hasAttribute(&amp;#x27;data-reach-match&amp;#x27;) ||&#10;              !Number.isInteger(depth) || depth &amp;lt; 0 || depth &amp;gt; activeReachability.maxDepth ||&#10;              (id === originId&#10;                ? (!matches[0].hasAttribute(&amp;#x27;data-reach-origin&amp;#x27;) || depth !== 0)&#10;                : depth &amp;lt; 1)) return true;&#10;          seenNodeIds[id] = true;&#10;          nodeIdSet[id] = true;&#10;          depths[id] = depth;&#10;          measuredMaxDepth = Math.max(measuredMaxDepth, depth);&#10;          if (id === originId) originNode = matches[0];&#10;          return false;&#10;        }) || !originNode || measuredMaxDepth !== activeReachability.maxDepth ||&#10;            allNodes.filter(function (node) { return node.hasAttribute(&amp;#x27;data-reach-match&amp;#x27;); }).length !== nodeIds.length) return null;&#10;&#10;        var edgeRecords = [];&#10;        if (edgeKeys.some(function (key) {&#10;          if (typeof key !== &amp;#x27;string&amp;#x27; || !key || seenEdgeKeys[key]) return true;&#10;          var fragments = allEdges.filter(function (edge) {&#10;            return edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) === key;&#10;          });&#10;          var drawableFragments = fragments.filter(hasDrawableGeometry);&#10;          if (!fragments.length || drawableFragments.length !== 1 ||&#10;              !fragments.every(function (fragment) { return fragment.hasAttribute(&amp;#x27;data-reach-match&amp;#x27;); })) return true;&#10;          var first = fragments[0];&#10;          var from = first.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;          var to = first.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;          var id = first.getAttribute(&amp;#x27;data-edge-id&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;          var labelValue = first.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;          if (!nodeIdSet[from] || !nodeIdSet[to] || !fragments.every(function (fragment) {&#10;            return fragment.getAttribute(&amp;#x27;data-edge-from&amp;#x27;) === from &amp;amp;&amp;amp;&#10;              fragment.getAttribute(&amp;#x27;data-edge-to&amp;#x27;) === to &amp;amp;&amp;amp;&#10;              (fragment.getAttribute(&amp;#x27;data-edge-id&amp;#x27;) || &amp;#x27;&amp;#x27;) === id;&#10;          })) return true;&#10;          seenEdgeKeys[key] = true;&#10;          edgeRecords.push({&#10;            key: key,&#10;            id: id,&#10;            from: from,&#10;            to: to,&#10;            label: labelValue,&#10;            depth: Math.max(depths[from], depths[to])&#10;          });&#10;          return false;&#10;        })) return null;&#10;&#10;        var liveEdgeKeys = Object.create(null);&#10;        if (allEdges.some(function (edge) {&#10;          if (!edge.hasAttribute(&amp;#x27;data-reach-match&amp;#x27;)) return false;&#10;          var key = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;);&#10;          if (!key || !seenEdgeKeys[key]) return true;&#10;          liveEdgeKeys[key] = true;&#10;          return false;&#10;        }) || Object.keys(liveEdgeKeys).length !== edgeKeys.length) return null;&#10;&#10;        return {&#10;          direction: reachabilityMode,&#10;          origin: { id: originId, label: nodeLabel(originNode, originId) },&#10;          nodeIds: nodeIds,&#10;          depths: depths,&#10;          maxDepth: activeReachability.maxDepth,&#10;          edges: edgeRecords&#10;        };&#10;      }&#10;      function setPassportValue(element, value) {&#10;        var normalized = value == null ? &amp;#x27;&amp;#x27; : String(value).trim();&#10;        element.textContent = normalized;&#10;        element.hidden = !normalized;&#10;      }&#10;      function renderSourceEvidence(id) {&#10;        evidenceLinks.textContent = &amp;#x27;&amp;#x27;;&#10;        repositoryLink.removeAttribute(&amp;#x27;href&amp;#x27;);&#10;        repositoryLink.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;        repositoryLink.textContent = &amp;#x27;&amp;#x27;;&#10;        var sources = Archify.sourceEvidence.node(id);&#10;        var repository = Archify.sourceEvidence.repository();&#10;        if (!repository || !sources.length) {&#10;          evidence.hidden = true;&#10;          return;&#10;        }&#10;        repositoryLink.textContent = repository.label + &amp;#x27; @ &amp;#x27; + repository.shortRevision;&#10;        if (repository.href) {&#10;          repositoryLink.href = repository.href;&#10;          repositoryLink.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.passport.repository.open&amp;#x27;, { revision: repository.revision }));&#10;        }&#10;        evidence.title = viewerText(&amp;#x27;viewer.passport.verificationScope&amp;#x27;);&#10;        sources.forEach(function (source) {&#10;          var link = document.createElement(source.href ? &amp;#x27;a&amp;#x27; : &amp;#x27;div&amp;#x27;);&#10;          link.className = &amp;#x27;semantic-passport-source&amp;#x27;;&#10;          if (source.href) {&#10;            link.href = source.href;&#10;            link.target = &amp;#x27;_blank&amp;#x27;;&#10;            link.rel = &amp;#x27;noopener noreferrer&amp;#x27;;&#10;            link.referrerPolicy = &amp;#x27;no-referrer&amp;#x27;;&#10;            link.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.passport.source.open&amp;#x27;, { path: source.path, revision: repository.shortRevision }));&#10;          }&#10;          var name = document.createElement(&amp;#x27;strong&amp;#x27;);&#10;          name.textContent = source.label || source.path.split(&amp;#x27;/&amp;#x27;).pop() || source.path;&#10;          var location = document.createElement(&amp;#x27;code&amp;#x27;);&#10;          location.textContent = source.line&#10;            ? &amp;#x27;L&amp;#x27; + source.line + (source.endLine &amp;amp;&amp;amp; source.endLine !== source.line ? &amp;#x27;–&amp;#x27; + source.endLine : &amp;#x27;&amp;#x27;) + (source.href ? &amp;#x27; ↗&amp;#x27; : &amp;#x27;&amp;#x27;)&#10;            : source.href ? viewerText(&amp;#x27;viewer.passport.source.openLink&amp;#x27;) : &amp;#x27;&amp;#x27;;&#10;          var sourcePath = document.createElement(&amp;#x27;small&amp;#x27;);&#10;          sourcePath.textContent = source.path;&#10;          link.appendChild(name);&#10;          link.appendChild(location);&#10;          link.appendChild(sourcePath);&#10;          evidenceLinks.appendChild(link);&#10;        });&#10;        evidence.hidden = false;&#10;      }&#10;      function renderPassport(id, node) {&#10;        setPassportValue(detail, node.getAttribute(&amp;#x27;data-node-sublabel&amp;#x27;));&#10;        setPassportValue(kind, viewerKindLabel(node.getAttribute(&amp;#x27;data-node-kind&amp;#x27;) || &amp;#x27;node&amp;#x27;));&#10;        setPassportValue(context, node.getAttribute(&amp;#x27;data-node-context&amp;#x27;));&#10;        setPassportValue(tag, node.getAttribute(&amp;#x27;data-node-tag&amp;#x27;));&#10;        setPassportValue(document.getElementById(&amp;#x27;focus-brand&amp;#x27;), node.getAttribute(&amp;#x27;data-node-brand&amp;#x27;));&#10;        semanticId.textContent = id;&#10;        semanticId.hidden = false;&#10;        renderSourceEvidence(id);&#10;      }&#10;      function relationshipsFor(id, byId) {&#10;        var seen = {};&#10;        var relationships = [];&#10;        edges().forEach(function (edge) {&#10;          var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;          var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;          if (from !== id &amp;amp;&amp;amp; to !== id) return;&#10;          var edgeLabel = edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;          var edgeKey = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) || (from + &amp;#x27;\u0000&amp;#x27; + to + &amp;#x27;\u0000&amp;#x27; + edgeLabel);&#10;          var edgeId = edge.getAttribute(&amp;#x27;data-edge-id&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;          if (seen[edgeKey]) return;&#10;          seen[edgeKey] = true;&#10;          var direction = from === id &amp;amp;&amp;amp; to === id ? &amp;#x27;loop&amp;#x27; : (from === id ? &amp;#x27;out&amp;#x27; : &amp;#x27;in&amp;#x27;);&#10;          var neighborId = direction === &amp;#x27;in&amp;#x27; ? from : to;&#10;          var neighbor = byId[neighborId];&#10;          relationships.push({&#10;            key: edgeKey,&#10;            id: edgeId,&#10;            from: from,&#10;            to: to,&#10;            direction: direction,&#10;            neighborId: neighborId,&#10;            neighborLabel: neighbor ? nodeLabel(neighbor, neighborId) : neighborId,&#10;            label: edgeLabel || viewerText(direction === &amp;#x27;loop&amp;#x27;&#10;              ? &amp;#x27;viewer.passport.relationship.loopsBack&amp;#x27;&#10;              : direction === &amp;#x27;out&amp;#x27;&#10;                ? &amp;#x27;viewer.passport.relationship.connectsTo&amp;#x27;&#10;                : &amp;#x27;viewer.passport.relationship.connectsFrom&amp;#x27;)&#10;          });&#10;        });&#10;        return relationships;&#10;      }&#10;      function relationshipEdgeShapes(edge) {&#10;        if (!edge) return [];&#10;        if (/^(path|line|polyline)$/i.test(edge.tagName || &amp;#x27;&amp;#x27;)) return [edge];&#10;        return Array.prototype.slice.call(edge.querySelectorAll(&amp;#x27;path, line, polyline&amp;#x27;));&#10;      }&#10;      function relationshipHitRecords() {&#10;        var recordsByKey = {};&#10;        var recordsById = {};&#10;        var byId = {};&#10;        nodes().forEach(function (node) { byId[node.getAttribute(&amp;#x27;data-node-id&amp;#x27;)] = node; });&#10;        var records = [];&#10;        edges().forEach(function (edge) {&#10;          var shapes = relationshipEdgeShapes(edge);&#10;          if (!shapes.length) return;&#10;          var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;          var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;          var labelValue = edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;          var edgeId = edge.getAttribute(&amp;#x27;data-edge-id&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;          var key = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) || (from + &amp;#x27;\u0000&amp;#x27; + to + &amp;#x27;\u0000&amp;#x27; + labelValue);&#10;          var existing = recordsByKey[key];&#10;          if (existing) {&#10;            if (existing.from !== from || existing.to !== to || existing.labelValue !== labelValue || existing.id !== edgeId) {&#10;              existing.invalid = true;&#10;              return;&#10;            }&#10;            shapes.forEach(function (shape) {&#10;              if (existing.shapes.indexOf(shape) === -1) existing.shapes.push(shape);&#10;            });&#10;            return;&#10;          }&#10;          var record = {&#10;            key: key,&#10;            id: edgeId,&#10;            from: from,&#10;            to: to,&#10;            fromLabel: byId[from] ? nodeLabel(byId[from], from) : from,&#10;            toLabel: byId[to] ? nodeLabel(byId[to], to) : to,&#10;            labelValue: labelValue,&#10;            label: labelValue || viewerText(from === to&#10;              ? &amp;#x27;viewer.passport.relationship.loopsBack&amp;#x27;&#10;              : &amp;#x27;viewer.passport.relationship.connectsTo&amp;#x27;),&#10;            edge: edge,&#10;            shapes: shapes,&#10;            invalid: false&#10;          };&#10;          recordsByKey[key] = record;&#10;          if (edgeId) {&#10;            if (recordsById[edgeId]) {&#10;              recordsById[edgeId].invalid = true;&#10;              record.invalid = true;&#10;            } else {&#10;              recordsById[edgeId] = record;&#10;            }&#10;          }&#10;          records.push(record);&#10;        });&#10;        return records.filter(function (record) { return !record.invalid &amp;amp;&amp;amp; record.from &amp;amp;&amp;amp; record.to; });&#10;      }&#10;      function relationshipRecordForKey(key) {&#10;        return relationshipHitRecords().find(function (record) { return record.key === key; }) || null;&#10;      }&#10;      function pinnedRelationshipRecord() {&#10;        return pinnedRelationshipKey ? relationshipRecordForKey(pinnedRelationshipKey) : null;&#10;      }&#10;      function renderRelationshipCopyAction() {&#10;        var record = pinnedRelationshipRecord();&#10;        if (record &amp;amp;&amp;amp; record.id) {&#10;          copyBtn.textContent = viewerText(&amp;#x27;viewer.passport.copyRelation&amp;#x27;);&#10;          copyBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.passport.copyPinned&amp;#x27;));&#10;        } else if (pinnedRelationshipKey) {&#10;          copyBtn.textContent = viewerText(&amp;#x27;viewer.passport.copyNode&amp;#x27;);&#10;          copyBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.passport.copySource&amp;#x27;));&#10;        } else {&#10;          copyBtn.textContent = viewerText(&amp;#x27;viewer.passport.copy&amp;#x27;);&#10;          copyBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.passport.copy.focus&amp;#x27;));&#10;        }&#10;      }&#10;      function relationshipHitGeometry(shape, className) {&#10;        var clone = shape.cloneNode(false);&#10;        clone.removeAttribute(&amp;#x27;id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;class&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;style&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;filter&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-start&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-mid&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-end&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;role&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;tabindex&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-labelledby&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-hidden&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-animate&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-key&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-label&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;class&amp;#x27;, className || &amp;#x27;relationship-hit-rail&amp;#x27;);&#10;        return clone;&#10;      }&#10;      function removeRelationshipPulse() {&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-relationship-pulse-overlay]&amp;#x27;), function (element) {&#10;          element.remove();&#10;        });&#10;      }&#10;      function relationshipPulseGeometry(shape) {&#10;        var clone = shape.cloneNode(false);&#10;        clone.removeAttribute(&amp;#x27;id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;class&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;style&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;transform&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;filter&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-start&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-mid&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-end&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;role&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;tabindex&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-hidden&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-animate&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-key&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-focus-match&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-relationship-preview&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;relationship-flow-pulse&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;pathLength&amp;#x27;, &amp;#x27;1&amp;#x27;);&#10;        return clone;&#10;      }&#10;      function relationshipTokenKind(edge) {&#10;        var shapes = relationshipEdgeShapes(edge);&#10;        var classEvidence = [edge.getAttribute(&amp;#x27;class&amp;#x27;) || &amp;#x27;&amp;#x27;].concat(shapes.map(function (shape) {&#10;          return shape.getAttribute(&amp;#x27;class&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;        })).join(&amp;#x27; &amp;#x27;);&#10;        var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;        var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;        var source = nodes().find(function (node) { return node.getAttribute(&amp;#x27;data-node-id&amp;#x27;) === from; });&#10;        var target = nodes().find(function (node) { return node.getAttribute(&amp;#x27;data-node-id&amp;#x27;) === to; });&#10;        var sourceKind = source ? source.getAttribute(&amp;#x27;data-node-kind&amp;#x27;) || &amp;#x27;neutral&amp;#x27; : &amp;#x27;neutral&amp;#x27;;&#10;        var targetKind = target ? target.getAttribute(&amp;#x27;data-node-kind&amp;#x27;) || &amp;#x27;neutral&amp;#x27; : &amp;#x27;neutral&amp;#x27;;&#10;        if (/\ba-security\b/.test(classEvidence) || sourceKind === &amp;#x27;security&amp;#x27; || targetKind === &amp;#x27;security&amp;#x27; || targetKind === &amp;#x27;failure&amp;#x27;) return &amp;#x27;security&amp;#x27;;&#10;        if (/\ba-dashed\b/.test(classEvidence) || sourceKind === &amp;#x27;messagebus&amp;#x27; || targetKind === &amp;#x27;messagebus&amp;#x27;) return &amp;#x27;event&amp;#x27;;&#10;        if (sourceKind === &amp;#x27;database&amp;#x27; || targetKind === &amp;#x27;database&amp;#x27;) return &amp;#x27;data&amp;#x27;;&#10;        if (targetKind === &amp;#x27;waiting&amp;#x27; || targetKind === &amp;#x27;success&amp;#x27;) return &amp;#x27;state&amp;#x27;;&#10;        return &amp;#x27;call&amp;#x27;;&#10;      }&#10;      function relationshipTokenPath(shape) {&#10;        if (!shape) return &amp;#x27;&amp;#x27;;&#10;        var tagName = String(shape.tagName || &amp;#x27;&amp;#x27;).toLowerCase();&#10;        if (tagName === &amp;#x27;path&amp;#x27;) return shape.getAttribute(&amp;#x27;d&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;        if (tagName === &amp;#x27;line&amp;#x27;) {&#10;          return &amp;#x27;M &amp;#x27; + shape.getAttribute(&amp;#x27;x1&amp;#x27;) + &amp;#x27; &amp;#x27; + shape.getAttribute(&amp;#x27;y1&amp;#x27;) +&#10;            &amp;#x27; L &amp;#x27; + shape.getAttribute(&amp;#x27;x2&amp;#x27;) + &amp;#x27; &amp;#x27; + shape.getAttribute(&amp;#x27;y2&amp;#x27;);&#10;        }&#10;        if (tagName === &amp;#x27;polyline&amp;#x27; &amp;amp;&amp;amp; shape.points &amp;amp;&amp;amp; shape.points.numberOfItems &amp;gt; 1) {&#10;          var commands = [];&#10;          for (var i = 0; i &amp;lt; shape.points.numberOfItems; i += 1) {&#10;            var point = shape.points.getItem(i);&#10;            commands.push((i === 0 ? &amp;#x27;M &amp;#x27; : &amp;#x27;L &amp;#x27;) + point.x + &amp;#x27; &amp;#x27; + point.y);&#10;          }&#10;          return commands.join(&amp;#x27; &amp;#x27;);&#10;        }&#10;        return &amp;#x27;&amp;#x27;;&#10;      }&#10;      function relationshipTokenPart(tagName, className, attrs) {&#10;        var part = document.createElementNS(svgNamespace, tagName);&#10;        part.setAttribute(&amp;#x27;class&amp;#x27;, className);&#10;        Object.keys(attrs || {}).forEach(function (name) { part.setAttribute(name, attrs[name]); });&#10;        return part;&#10;      }&#10;      function relationshipTokenGeometry(shape, kind, key, options) {&#10;        options = options || {};&#10;        var pathData = relationshipTokenPath(shape);&#10;        if (!pathData) return null;&#10;        var token = document.createElementNS(svgNamespace, &amp;#x27;g&amp;#x27;);&#10;        token.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;semantic-flow-token &amp;#x27; + (options.className || &amp;#x27;relationship-flow-token&amp;#x27;));&#10;        token.setAttribute(&amp;#x27;data-token-kind&amp;#x27;, kind);&#10;        token.setAttribute(&amp;#x27;data-token-edge-key&amp;#x27;, key);&#10;        token.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        token.appendChild(relationshipTokenPart(&amp;#x27;circle&amp;#x27;, &amp;#x27;semantic-flow-token-halo&amp;#x27;, { cx: &amp;#x27;0&amp;#x27;, cy: &amp;#x27;0&amp;#x27;, r: &amp;#x27;7&amp;#x27; }));&#10;        if (kind === &amp;#x27;data&amp;#x27;) {&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;rect&amp;#x27;, &amp;#x27;relationship-flow-token-shape&amp;#x27;, { x: &amp;#x27;-5&amp;#x27;, y: &amp;#x27;-4&amp;#x27;, width: &amp;#x27;10&amp;#x27;, height: &amp;#x27;8&amp;#x27;, rx: &amp;#x27;2&amp;#x27; }));&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;path&amp;#x27;, &amp;#x27;relationship-flow-token-ink&amp;#x27;, { d: &amp;#x27;M -2.8 -1.2 h 5.6 M -2.8 1.4 h 3.8&amp;#x27; }));&#10;        } else if (kind === &amp;#x27;event&amp;#x27;) {&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;rect&amp;#x27;, &amp;#x27;relationship-flow-token-shape&amp;#x27;, { x: &amp;#x27;-7&amp;#x27;, y: &amp;#x27;-3&amp;#x27;, width: &amp;#x27;4&amp;#x27;, height: &amp;#x27;6&amp;#x27;, rx: &amp;#x27;1&amp;#x27; }));&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;rect&amp;#x27;, &amp;#x27;relationship-flow-token-shape&amp;#x27;, { x: &amp;#x27;-2&amp;#x27;, y: &amp;#x27;-3&amp;#x27;, width: &amp;#x27;4&amp;#x27;, height: &amp;#x27;6&amp;#x27;, rx: &amp;#x27;1&amp;#x27; }));&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;rect&amp;#x27;, &amp;#x27;relationship-flow-token-shape&amp;#x27;, { x: &amp;#x27;3&amp;#x27;, y: &amp;#x27;-3&amp;#x27;, width: &amp;#x27;4&amp;#x27;, height: &amp;#x27;6&amp;#x27;, rx: &amp;#x27;1&amp;#x27; }));&#10;        } else if (kind === &amp;#x27;security&amp;#x27;) {&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;path&amp;#x27;, &amp;#x27;relationship-flow-token-shape&amp;#x27;, { d: &amp;#x27;M 0 -5 L 4 -3.4 V 0 c 0 3 -1.6 4.5 -4 5.5 C -2.4 4.5 -4 3 -4 0 v -3.4 Z&amp;#x27; }));&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;path&amp;#x27;, &amp;#x27;relationship-flow-token-ink&amp;#x27;, { d: &amp;#x27;m -2 .2 1.4 1.4 L 2 -1.4&amp;#x27; }));&#10;        } else if (kind === &amp;#x27;state&amp;#x27;) {&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;circle&amp;#x27;, &amp;#x27;relationship-flow-token-shape&amp;#x27;, { cx: &amp;#x27;0&amp;#x27;, cy: &amp;#x27;0&amp;#x27;, r: &amp;#x27;5&amp;#x27; }));&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;circle&amp;#x27;, &amp;#x27;relationship-flow-token-dot&amp;#x27;, { cx: &amp;#x27;0&amp;#x27;, cy: &amp;#x27;0&amp;#x27;, r: &amp;#x27;1.35&amp;#x27; }));&#10;        } else {&#10;          token.appendChild(relationshipTokenPart(&amp;#x27;path&amp;#x27;, &amp;#x27;relationship-flow-token-ink&amp;#x27;, { d: &amp;#x27;M -5 -3 L -1 0 L -5 3 M 0 -3 L 4 0 L 0 3&amp;#x27; }));&#10;        }&#10;        var motion = document.createElementNS(svgNamespace, &amp;#x27;animateMotion&amp;#x27;);&#10;        motion.setAttribute(&amp;#x27;path&amp;#x27;, pathData);&#10;        motion.setAttribute(&amp;#x27;dur&amp;#x27;, options.duration || &amp;#x27;1.2s&amp;#x27;);&#10;        motion.setAttribute(&amp;#x27;begin&amp;#x27;, &amp;#x27;0s&amp;#x27;);&#10;        motion.setAttribute(&amp;#x27;fill&amp;#x27;, &amp;#x27;freeze&amp;#x27;);&#10;        motion.setAttribute(&amp;#x27;rotate&amp;#x27;, &amp;#x27;auto&amp;#x27;);&#10;        motion.setAttribute(&amp;#x27;calcMode&amp;#x27;, &amp;#x27;spline&amp;#x27;);&#10;        motion.setAttribute(&amp;#x27;keyTimes&amp;#x27;, &amp;#x27;0;1&amp;#x27;);&#10;        motion.setAttribute(&amp;#x27;keySplines&amp;#x27;, &amp;#x27;.2 0 .2 1&amp;#x27;);&#10;        token.appendChild(motion);&#10;        return token;&#10;      }&#10;      function createSemanticFlowToken(edge, shape, options) {&#10;        if (!edge || !shape) return null;&#10;        var key = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) || (&#10;          edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;) + &amp;#x27;\u0000&amp;#x27; +&#10;          edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;) + &amp;#x27;\u0000&amp;#x27; +&#10;          (edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;)&#10;        );&#10;        return relationshipTokenGeometry(shape, relationshipTokenKind(edge), key, options);&#10;      }&#10;      Archify.flowTokens = {&#10;        create: createSemanticFlowToken,&#10;        kind: function (edge) { return relationshipTokenKind(edge); },&#10;        path: relationshipTokenPath&#10;      };&#10;      function renderRelationshipPulse(key) {&#10;        removeRelationshipPulse();&#10;        if (!key || document.documentElement.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        if (document.hidden || (Archify.motionGovernor &amp;amp;&amp;amp; Archify.motionGovernor.isPaused())) return false;&#10;        if (reducedMotionQuery &amp;amp;&amp;amp; reducedMotionQuery.matches) return false;&#10;        var matchingEdges = edges().filter(function (edge) {&#10;          return edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) === key;&#10;        });&#10;        if (!matchingEdges.length) return false;&#10;        var overlay = document.createElementNS(svgNamespace, &amp;#x27;g&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;relationship-pulse-overlay&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;data-relationship-pulse-overlay&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;data-relationship-pulse-key&amp;#x27;, key);&#10;        overlay.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        var tokenAdded = false;&#10;        matchingEdges.forEach(function (edge) {&#10;          var wrapper = document.createElementNS(svgNamespace, &amp;#x27;g&amp;#x27;);&#10;          if (edge.hasAttribute(&amp;#x27;transform&amp;#x27;)) wrapper.setAttribute(&amp;#x27;transform&amp;#x27;, edge.getAttribute(&amp;#x27;transform&amp;#x27;));&#10;          var shapes = relationshipEdgeShapes(edge);&#10;          shapes.forEach(function (shape) {&#10;            wrapper.appendChild(relationshipPulseGeometry(shape));&#10;          });&#10;          if (!tokenAdded &amp;amp;&amp;amp; shapes.length) {&#10;            var tokenKind = relationshipTokenKind(edge);&#10;            var token = relationshipTokenGeometry(shapes[0], tokenKind, key);&#10;            if (token) {&#10;              wrapper.appendChild(token);&#10;              overlay.setAttribute(&amp;#x27;data-relationship-token-kind&amp;#x27;, tokenKind);&#10;              tokenAdded = true;&#10;            }&#10;          }&#10;          if (wrapper.childNodes.length) overlay.appendChild(wrapper);&#10;        });&#10;        if (!overlay.childNodes.length) return false;&#10;        var finishPulse = function () {&#10;          if (overlay.parentNode) overlay.remove();&#10;        };&#10;        overlay.addEventListener(&amp;#x27;animationend&amp;#x27;, finishPulse, { once: true });&#10;        overlay.addEventListener(&amp;#x27;animationcancel&amp;#x27;, finishPulse, { once: true });&#10;        var firstNode = svg.querySelector(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (firstNode) svg.insertBefore(overlay, firstNode);&#10;        else svg.appendChild(overlay);&#10;        return true;&#10;      }&#10;      function clearRelationshipPreview(options) {&#10;        options = options || {};&#10;        if (directPreviewTimer) window.clearTimeout(directPreviewTimer);&#10;        directPreviewTimer = null;&#10;        removeRelationshipPulse();&#10;        activeRelationshipPreview = null;&#10;        svg.removeAttribute(&amp;#x27;data-relationship-preview-active&amp;#x27;);&#10;        svg.removeAttribute(&amp;#x27;data-relationship-direct-active&amp;#x27;);&#10;        if (options.clearPin === true) {&#10;          pinnedRelationship = null;&#10;          pinnedRelationshipKey = null;&#10;          svg.removeAttribute(&amp;#x27;data-relationship-pin-active&amp;#x27;);&#10;        }&#10;        chip.removeAttribute(&amp;#x27;data-relationship-previewing&amp;#x27;);&#10;        edges().forEach(function (edge) { edge.removeAttribute(&amp;#x27;data-relationship-preview&amp;#x27;); });&#10;        nodes().forEach(function (node) {&#10;          node.removeAttribute(&amp;#x27;data-relationship-preview-node&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-relationship-preview-source&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-relationship-preview-target&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(relationshipList.querySelectorAll(&amp;#x27;[data-preview-active]&amp;#x27;), function (button) {&#10;          button.removeAttribute(&amp;#x27;data-preview-active&amp;#x27;);&#10;        });&#10;        relationshipHitTargets.forEach(function (target) {&#10;          target.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, pinnedRelationshipKey &amp;amp;&amp;amp; target.getAttribute(&amp;#x27;data-relationship-key&amp;#x27;) === pinnedRelationshipKey ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;          target.removeAttribute(&amp;#x27;data-preview-active&amp;#x27;);&#10;        });&#10;        renderRelationshipCopyAction();&#10;        requestLensPlacement();&#10;      }&#10;      function previewRelationship(button, options) {&#10;        options = options || {};&#10;        if (pinnedRelationshipKey &amp;amp;&amp;amp; pinnedRelationship &amp;amp;&amp;amp; button !== pinnedRelationship) return;&#10;        clearRelationshipPreview();&#10;        if (!button) return;&#10;        var key = button.getAttribute(&amp;#x27;data-relationship-key&amp;#x27;);&#10;        var from = button.getAttribute(&amp;#x27;data-relationship-from&amp;#x27;);&#10;        var to = button.getAttribute(&amp;#x27;data-relationship-to&amp;#x27;);&#10;        if (!key || !from || !to) return;&#10;        svg.setAttribute(&amp;#x27;data-relationship-preview-active&amp;#x27;, key);&#10;        if (options.direct === true) svg.setAttribute(&amp;#x27;data-relationship-direct-active&amp;#x27;, key);&#10;        edges().forEach(function (edge) {&#10;          if (edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) === key) edge.setAttribute(&amp;#x27;data-relationship-preview&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        });&#10;        nodes().forEach(function (node) {&#10;          var id = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;          if (id !== from &amp;amp;&amp;amp; id !== to) return;&#10;          node.setAttribute(&amp;#x27;data-relationship-preview-node&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          if (id === from) node.setAttribute(&amp;#x27;data-relationship-preview-source&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          if (id === to) node.setAttribute(&amp;#x27;data-relationship-preview-target&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        });&#10;        button.setAttribute(&amp;#x27;data-preview-active&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        if (!chip.hidden &amp;amp;&amp;amp; options.direct !== true) chip.setAttribute(&amp;#x27;data-relationship-previewing&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        activeRelationshipPreview = button;&#10;        renderRelationshipPulse(key);&#10;        requestLensPlacement();&#10;      }&#10;      function syncRelationshipPreview() {&#10;        var next = pinnedRelationship || focusedRelationship || hoveredRelationship;&#10;        if (next === activeRelationshipPreview) return;&#10;        previewRelationship(next, { direct: !!(next &amp;amp;&amp;amp; next.hasAttribute(&amp;#x27;data-relationship-hit-key&amp;#x27;)) });&#10;      }&#10;      function directRelationshipBlocked() {&#10;        return html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27; ||&#10;          html.getAttribute(&amp;#x27;data-guide-open&amp;#x27;) === &amp;#x27;true&amp;#x27; ||&#10;          container.classList.contains(&amp;#x27;is-panning&amp;#x27;) ||&#10;          (activeIds.length &amp;gt; 0 &amp;amp;&amp;amp; !pinnedRelationshipKey) ||&#10;          svg.hasAttribute(&amp;#x27;data-story-active&amp;#x27;) ||&#10;          svg.hasAttribute(&amp;#x27;data-route-picking&amp;#x27;) ||&#10;          svg.hasAttribute(&amp;#x27;data-route-active&amp;#x27;) ||&#10;          svg.hasAttribute(&amp;#x27;data-lens-active&amp;#x27;) ||&#10;          svg.hasAttribute(&amp;#x27;data-chapter-preview&amp;#x27;);&#10;      }&#10;      function scheduleDirectRelationshipPreview(target) {&#10;        if (directPreviewTimer) window.clearTimeout(directPreviewTimer);&#10;        if (pinnedRelationshipKey) return;&#10;        directPreviewTimer = window.setTimeout(function () {&#10;          directPreviewTimer = null;&#10;          if (pinnedRelationshipKey || hoveredRelationship !== target || directRelationshipBlocked()) return;&#10;          previewRelationship(target, { direct: true });&#10;        }, reducedMotionQuery &amp;amp;&amp;amp; reducedMotionQuery.matches ? 0 : 90);&#10;      }&#10;      function relationshipHitTarget(key) {&#10;        return relationshipHitTargets.find(function (target) {&#10;          return target.getAttribute(&amp;#x27;data-relationship-key&amp;#x27;) === key;&#10;        }) || null;&#10;      }&#10;      function revealPinnedRelationship(record) {&#10;        function reveal() {&#10;          if (!record || pinnedRelationshipKey !== record.key) return true;&#10;          if (!Archify.view || typeof Archify.view.reveal !== &amp;#x27;function&amp;#x27;) return false;&#10;          Archify.view.reveal([record.from, record.to], { reason: &amp;#x27;relationship-direct&amp;#x27; });&#10;          return true;&#10;        }&#10;        if (!reveal()) requestAnimationFrame(reveal);&#10;      }&#10;      function inspectRelationship(key, options) {&#10;        options = options || {};&#10;        if (html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        if (directPreviewTimer) window.clearTimeout(directPreviewTimer);&#10;        directPreviewTimer = null;&#10;        hoveredRelationship = null;&#10;        focusedRelationship = null;&#10;        if (pinnedRelationshipKey === key) {&#10;          if (options.toggle === false) return true;&#10;          clear({ updateUrl: options.updateUrl !== false });&#10;          return true;&#10;        }&#10;        var record = relationshipRecordForKey(key);&#10;        if (!record) return false;&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; typeof Archify.guidedViews.showAll === &amp;#x27;function&amp;#x27;) {&#10;          Archify.guidedViews.showAll({ clearFocus: false, updateUrl: false });&#10;        }&#10;        set(record.from, { toggle: false, updateUrl: false });&#10;        var row = Array.prototype.slice.call(relationshipList.querySelectorAll(&amp;#x27;[data-relationship-key]&amp;#x27;)).find(function (candidate) {&#10;          return candidate.getAttribute(&amp;#x27;data-relationship-key&amp;#x27;) === key;&#10;        });&#10;        if (!row) return false;&#10;        previewRelationship(row);&#10;        pinnedRelationship = row;&#10;        pinnedRelationshipKey = key;&#10;        svg.setAttribute(&amp;#x27;data-relationship-pin-active&amp;#x27;, key);&#10;        var target = relationshipHitTarget(key);&#10;        if (target) target.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        renderRelationshipCopyAction();&#10;        summary.textContent = viewerText(&amp;#x27;viewer.passport.relationship.pinned&amp;#x27;, {&#10;          from: record.fromLabel,&#10;          to: record.toLabel,&#10;          label: record.label&#10;        });&#10;        revealPinnedRelationship(record);&#10;        if (options.updateUrl !== false &amp;amp;&amp;amp; record.id) {&#10;          try { history.replaceState(null, &amp;#x27;&amp;#x27;, location.pathname + location.search + &amp;#x27;#relation=&amp;#x27; + encodeURIComponent(record.id)); } catch (_) {}&#10;        }&#10;        return true;&#10;      }&#10;      function inspectRelationshipById(id, options) {&#10;        var record = relationshipHitRecords().find(function (item) { return item.id === id; });&#10;        return record ? inspectRelationship(record.key, options) : false;&#10;      }&#10;      function installRelationshipHitTargets() {&#10;        if (html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return 0;&#10;        var records = relationshipHitRecords();&#10;        if (!records.length) return 0;&#10;        relationshipHitOverlay = document.createElementNS(svgNamespace, &amp;#x27;g&amp;#x27;);&#10;        relationshipHitOverlay.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;relationship-hit-overlay&amp;#x27;);&#10;        relationshipHitOverlay.setAttribute(&amp;#x27;data-relationship-hit-overlay&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        relationshipHitOverlay.setAttribute(&amp;#x27;role&amp;#x27;, &amp;#x27;group&amp;#x27;);&#10;        relationshipHitOverlay.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.passport.relationship.explorer&amp;#x27;));&#10;        var relationshipHelp = document.createElementNS(svgNamespace, &amp;#x27;desc&amp;#x27;);&#10;        relationshipHelp.id = &amp;#x27;archify-relationship-help&amp;#x27;;&#10;        relationshipHelp.textContent = viewerText(&amp;#x27;viewer.passport.relationship.help&amp;#x27;);&#10;        relationshipHitOverlay.appendChild(relationshipHelp);&#10;        records.forEach(function (record, index) {&#10;          var target = document.createElementNS(svgNamespace, &amp;#x27;g&amp;#x27;);&#10;          target.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;relationship-hit-target&amp;#x27;);&#10;          target.setAttribute(&amp;#x27;data-relationship-hit-key&amp;#x27;, record.key);&#10;          target.setAttribute(&amp;#x27;data-relationship-key&amp;#x27;, record.key);&#10;          target.setAttribute(&amp;#x27;data-relationship-from&amp;#x27;, record.from);&#10;          target.setAttribute(&amp;#x27;data-relationship-to&amp;#x27;, record.to);&#10;          if (record.id) target.setAttribute(&amp;#x27;data-relationship-id&amp;#x27;, record.id);&#10;          target.setAttribute(&amp;#x27;role&amp;#x27;, &amp;#x27;button&amp;#x27;);&#10;          target.setAttribute(&amp;#x27;tabindex&amp;#x27;, index === 0 ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;          target.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;          target.setAttribute(&amp;#x27;aria-describedby&amp;#x27;, relationshipHelp.id);&#10;          var description = viewerText(&amp;#x27;viewer.passport.relationship.inspect&amp;#x27;, {&#10;            index: index + 1,&#10;            total: records.length,&#10;            from: record.fromLabel,&#10;            to: record.toLabel,&#10;            label: record.label&#10;          });&#10;          target.setAttribute(&amp;#x27;aria-label&amp;#x27;, description);&#10;          var title = document.createElementNS(svgNamespace, &amp;#x27;title&amp;#x27;);&#10;          title.textContent = record.fromLabel + &amp;#x27; \u2192 &amp;#x27; + record.toLabel + &amp;#x27; \u00b7 &amp;#x27; + record.label;&#10;          target.appendChild(title);&#10;          record.shapes.forEach(function (shape) {&#10;            target.appendChild(relationshipHitGeometry(shape));&#10;            target.appendChild(relationshipHitGeometry(shape, &amp;#x27;relationship-focus-rail&amp;#x27;));&#10;          });&#10;          if (target.childNodes.length &amp;gt; 1) {&#10;            relationshipHitTargets.push(target);&#10;            relationshipHitOverlay.appendChild(target);&#10;          }&#10;        });&#10;        if (!relationshipHitTargets.length) return 0;&#10;        var firstNode = svg.querySelector(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        var nodeLayer = firstNode;&#10;        while (nodeLayer &amp;amp;&amp;amp; nodeLayer.parentNode &amp;amp;&amp;amp; nodeLayer.parentNode !== svg) nodeLayer = nodeLayer.parentNode;&#10;        if (nodeLayer &amp;amp;&amp;amp; nodeLayer.parentNode === svg) svg.insertBefore(relationshipHitOverlay, nodeLayer);&#10;        else svg.appendChild(relationshipHitOverlay);&#10;&#10;        relationshipHitOverlay.addEventListener(&amp;#x27;pointerdown&amp;#x27;, function (event) {&#10;          if (event.target.closest(&amp;#x27;[data-relationship-hit-key]&amp;#x27;)) event.stopPropagation();&#10;        });&#10;        relationshipHitOverlay.addEventListener(&amp;#x27;pointerover&amp;#x27;, function (event) {&#10;          if (event.pointerType === &amp;#x27;touch&amp;#x27;) return;&#10;          if (finePointerQuery &amp;amp;&amp;amp; !finePointerQuery.matches) return;&#10;          var target = event.target.closest(&amp;#x27;[data-relationship-hit-key]&amp;#x27;);&#10;          if (!target || directRelationshipBlocked() || pinnedRelationshipKey) return;&#10;          if (event.relatedTarget &amp;amp;&amp;amp; target.contains(event.relatedTarget)) return;&#10;          hoveredRelationship = target;&#10;          scheduleDirectRelationshipPreview(target);&#10;        });&#10;        relationshipHitOverlay.addEventListener(&amp;#x27;pointerout&amp;#x27;, function (event) {&#10;          var target = event.target.closest(&amp;#x27;[data-relationship-hit-key]&amp;#x27;);&#10;          if (!target || (event.relatedTarget &amp;amp;&amp;amp; target.contains(event.relatedTarget))) return;&#10;          if (hoveredRelationship === target) hoveredRelationship = null;&#10;          syncRelationshipPreview();&#10;        });&#10;        relationshipHitOverlay.addEventListener(&amp;#x27;focusin&amp;#x27;, function (event) {&#10;          var target = event.target.closest(&amp;#x27;[data-relationship-hit-key]&amp;#x27;);&#10;          if (!target || directRelationshipBlocked()) return;&#10;          focusedRelationship = target;&#10;          if (!pinnedRelationshipKey) previewRelationship(target, { direct: true });&#10;        });&#10;        relationshipHitOverlay.addEventListener(&amp;#x27;focusout&amp;#x27;, function (event) {&#10;          var target = event.target.closest(&amp;#x27;[data-relationship-hit-key]&amp;#x27;);&#10;          if (!target || (event.relatedTarget &amp;amp;&amp;amp; target.contains(event.relatedTarget))) return;&#10;          if (focusedRelationship === target) focusedRelationship = null;&#10;          syncRelationshipPreview();&#10;        });&#10;        relationshipHitOverlay.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;          var target = event.target.closest(&amp;#x27;[data-relationship-hit-key]&amp;#x27;);&#10;          if (!target || directRelationshipBlocked()) return;&#10;          event.preventDefault();&#10;          event.stopPropagation();&#10;          focusedRelationship = null;&#10;          hoveredRelationship = null;&#10;          inspectRelationship(target.getAttribute(&amp;#x27;data-relationship-key&amp;#x27;));&#10;        });&#10;        relationshipHitOverlay.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;          var target = event.target.closest(&amp;#x27;[data-relationship-hit-key]&amp;#x27;);&#10;          if (!target) return;&#10;          if (event.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; pinnedRelationshipKey) {&#10;            event.preventDefault();&#10;            clear({ updateUrl: false });&#10;            return;&#10;          }&#10;          if (event.key === &amp;#x27;Enter&amp;#x27; || event.key === &amp;#x27; &amp;#x27;) {&#10;            event.preventDefault();&#10;            focusedRelationship = null;&#10;            hoveredRelationship = null;&#10;            inspectRelationship(target.getAttribute(&amp;#x27;data-relationship-key&amp;#x27;));&#10;            return;&#10;          }&#10;          if (event.key !== &amp;#x27;ArrowRight&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;ArrowLeft&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;ArrowDown&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;ArrowUp&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;Home&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;End&amp;#x27;) return;&#10;          var index = relationshipHitTargets.indexOf(target);&#10;          if (event.key === &amp;#x27;Home&amp;#x27;) index = 0;&#10;          else if (event.key === &amp;#x27;End&amp;#x27;) index = relationshipHitTargets.length - 1;&#10;          else if (event.key === &amp;#x27;ArrowRight&amp;#x27; || event.key === &amp;#x27;ArrowDown&amp;#x27;) index = (index + 1) % relationshipHitTargets.length;&#10;          else index = (index - 1 + relationshipHitTargets.length) % relationshipHitTargets.length;&#10;          event.preventDefault();&#10;          relationshipHitTargets.forEach(function (item, itemIndex) { item.setAttribute(&amp;#x27;tabindex&amp;#x27;, itemIndex === index ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;); });&#10;          try { relationshipHitTargets[index].focus({ preventScroll: true }); }&#10;          catch (_) { try { relationshipHitTargets[index].focus(); } catch (_) {} }&#10;        });&#10;        return relationshipHitTargets.length;&#10;      }&#10;      function renderRelationshipLens(id, byId) {&#10;        hoveredRelationship = null;&#10;        focusedRelationship = null;&#10;        clearRelationshipPreview({ clearPin: true });&#10;        renderPassport(id, byId[id]);&#10;        var relationships = relationshipsFor(id, byId);&#10;        chip.removeAttribute(&amp;#x27;data-relations-expanded&amp;#x27;);&#10;        relationsBtn.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        relationsBtn.textContent = viewerCount(&amp;#x27;viewer.passport.relationship.count&amp;#x27;, relationships.length);&#10;        relationsBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerCount(&amp;#x27;viewer.passport.relationship.show&amp;#x27;, relationships.length));&#10;        var counts = { out: 0, in: 0, loop: 0 };&#10;        relationships.forEach(function (relationship) { counts[relationship.direction] += 1; });&#10;        summary.textContent = viewerText(&amp;#x27;viewer.passport.relationship.summary&amp;#x27;, {&#10;          out: counts.out,&#10;          in: counts.in,&#10;          loops: counts.loop ? viewerText(&amp;#x27;viewer.passport.relationship.loops&amp;#x27;, { count: counts.loop }) : &amp;#x27;&amp;#x27;&#10;        });&#10;        renderReachabilityControls(id);&#10;        relationshipList.textContent = &amp;#x27;&amp;#x27;;&#10;        if (!relationships.length) {&#10;          var empty = document.createElement(&amp;#x27;p&amp;#x27;);&#10;          empty.className = &amp;#x27;relationship-lens-empty&amp;#x27;;&#10;          empty.textContent = viewerText(&amp;#x27;viewer.passport.relationship.none&amp;#x27;);&#10;          relationshipList.appendChild(empty);&#10;          return;&#10;        }&#10;&#10;        [&#10;          { id: &amp;#x27;out&amp;#x27;, label: viewerText(&amp;#x27;viewer.passport.relationship.group.out&amp;#x27;) },&#10;          { id: &amp;#x27;in&amp;#x27;, label: viewerText(&amp;#x27;viewer.passport.relationship.group.in&amp;#x27;) },&#10;          { id: &amp;#x27;loop&amp;#x27;, label: viewerText(&amp;#x27;viewer.passport.relationship.group.loop&amp;#x27;) }&#10;        ].forEach(function (group) {&#10;          var items = relationships.filter(function (relationship) { return relationship.direction === group.id; });&#10;          if (!items.length) return;&#10;          var section = document.createElement(&amp;#x27;div&amp;#x27;);&#10;          section.className = &amp;#x27;relationship-lens-group&amp;#x27;;&#10;          var heading = document.createElement(&amp;#x27;span&amp;#x27;);&#10;          heading.className = &amp;#x27;relationship-lens-group-title&amp;#x27;;&#10;          heading.textContent = group.label + &amp;#x27; · &amp;#x27; + items.length;&#10;          section.appendChild(heading);&#10;          items.forEach(function (relationship) {&#10;            var button = document.createElement(&amp;#x27;button&amp;#x27;);&#10;            button.type = &amp;#x27;button&amp;#x27;;&#10;            button.className = &amp;#x27;relationship-lens-row&amp;#x27;;&#10;            button.setAttribute(&amp;#x27;data-direction&amp;#x27;, relationship.direction);&#10;            button.setAttribute(&amp;#x27;data-relationship-target&amp;#x27;, relationship.neighborId);&#10;            button.setAttribute(&amp;#x27;data-relationship-key&amp;#x27;, relationship.key);&#10;            button.setAttribute(&amp;#x27;data-relationship-from&amp;#x27;, relationship.from);&#10;            button.setAttribute(&amp;#x27;data-relationship-to&amp;#x27;, relationship.to);&#10;            if (relationship.id) button.setAttribute(&amp;#x27;data-relationship-id&amp;#x27;, relationship.id);&#10;            button.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.passport.relationship.row&amp;#x27;, {&#10;              group: group.label,&#10;              relationship: relationship.label,&#10;              neighbor: relationship.neighborLabel&#10;            }));&#10;            var direction = document.createElement(&amp;#x27;span&amp;#x27;);&#10;            direction.className = &amp;#x27;relationship-lens-direction&amp;#x27;;&#10;            direction.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;            direction.textContent = viewerText(relationship.direction === &amp;#x27;out&amp;#x27;&#10;              ? &amp;#x27;viewer.passport.relationship.direction.out&amp;#x27;&#10;              : relationship.direction === &amp;#x27;in&amp;#x27;&#10;                ? &amp;#x27;viewer.passport.relationship.direction.in&amp;#x27;&#10;                : &amp;#x27;viewer.passport.relationship.direction.loop&amp;#x27;);&#10;            var target = document.createElement(&amp;#x27;strong&amp;#x27;);&#10;            target.textContent = relationship.neighborLabel;&#10;            var relation = document.createElement(&amp;#x27;small&amp;#x27;);&#10;            relation.textContent = relationship.label;&#10;            button.appendChild(direction);&#10;            button.appendChild(target);&#10;            button.appendChild(relation);&#10;            section.appendChild(button);&#10;          });&#10;          relationshipList.appendChild(section);&#10;        });&#10;      }&#10;      var lensFrame = 0;&#10;      function placeRelationshipLens() {&#10;        lensFrame = 0;&#10;        if (chip.hidden || activeIds.length !== 1) return;&#10;        var node = svg.querySelector(&amp;#x27;[data-node-id=&amp;quot;&amp;#x27; + activeIds[0] + &amp;#x27;&amp;quot;]&amp;#x27;);&#10;        if (!node) return;&#10;        var containerRect = container.getBoundingClientRect();&#10;        var nodeRect = node.getBoundingClientRect();&#10;        if (containerRect.bottom &amp;lt;= 0 || containerRect.top &amp;gt;= window.innerHeight) return;&#10;        var padding = window.innerWidth &amp;lt;= 720 ? 8 : 16;&#10;        var visibleTop = Math.max(padding, -containerRect.top + padding);&#10;        var visibleBottom = Math.min(containerRect.height - padding, window.innerHeight - containerRect.top - padding);&#10;        var maxTop = Math.max(padding, visibleBottom - chip.offsetHeight);&#10;        var minTop = Math.min(visibleTop, maxTop);&#10;        var nodeCenter = nodeRect.top - containerRect.top + nodeRect.height / 2;&#10;        var mobile = window.innerWidth &amp;lt;= 720;&#10;        var previewingOnMobile = mobile &amp;amp;&amp;amp; chip.getAttribute(&amp;#x27;data-relationship-previewing&amp;#x27;) === &amp;#x27;true&amp;#x27;;&#10;        var compactOnMobile = mobile &amp;amp;&amp;amp; chip.getAttribute(&amp;#x27;data-relations-expanded&amp;#x27;) !== &amp;#x27;true&amp;#x27;;&#10;        var preferred;&#10;        if (compactOnMobile) {&#10;          var nodeTop = nodeRect.top - containerRect.top;&#10;          var nodeBottom = nodeRect.bottom - containerRect.top;&#10;          var gap = 10;&#10;          var above = nodeTop - chip.offsetHeight - gap;&#10;          var below = nodeBottom + gap;&#10;          if (above &amp;gt;= visibleTop) preferred = above;&#10;          else if (below + chip.offsetHeight &amp;lt;= visibleBottom - 56) preferred = below;&#10;          else preferred = nodeCenter &amp;lt; (visibleTop + visibleBottom) / 2&#10;            ? Math.max(minTop, visibleBottom - chip.offsetHeight - 56)&#10;            : visibleTop;&#10;        } else if (previewingOnMobile) {&#10;          var pinnedTop = visibleTop;&#10;          var pinnedBottom = Math.max(minTop, visibleBottom - chip.offsetHeight - 56);&#10;          preferred = nodeCenter &amp;lt; (visibleTop + visibleBottom) / 2 ? pinnedBottom : pinnedTop;&#10;        } else {&#10;          preferred = nodeCenter - chip.offsetHeight / 2;&#10;        }&#10;        var top = Math.max(minTop, Math.min(maxTop, preferred));&#10;        var chipRect = chip.getBoundingClientRect();&#10;        var safeGap = 10;&#10;        var protectViewerChrome = !mobile || compactOnMobile || previewingOnMobile;&#10;        var protectedRects = (protectViewerChrome&#10;          ? [svg.querySelector(&amp;#x27;[data-legend]&amp;#x27;), container.querySelector(&amp;#x27;.diagram-nav&amp;#x27;)]&#10;          : [])&#10;          .filter(function (element) {&#10;            if (!element || element.hidden) return false;&#10;            var style = window.getComputedStyle(element);&#10;            return style.display !== &amp;#x27;none&amp;#x27; &amp;amp;&amp;amp; style.visibility !== &amp;#x27;hidden&amp;#x27;;&#10;          })&#10;          .map(function (element) { return element.getBoundingClientRect(); })&#10;          .filter(function (rect) {&#10;            return rect.width &amp;gt; 0 &amp;amp;&amp;amp; rect.height &amp;gt; 0 &amp;amp;&amp;amp;&#10;              chipRect.left &amp;lt; rect.right + safeGap &amp;amp;&amp;amp; chipRect.right &amp;gt; rect.left - safeGap;&#10;          });&#10;        if (protectedRects.length) {&#10;          var candidates = [top, minTop, maxTop];&#10;          protectedRects.forEach(function (rect) {&#10;            candidates.push(&#10;              rect.top - containerRect.top - chip.offsetHeight - safeGap,&#10;              rect.bottom - containerRect.top + safeGap&#10;            );&#10;          });&#10;          var valid = candidates.map(function (candidate) {&#10;            return Math.max(minTop, Math.min(maxTop, candidate));&#10;          }).filter(function (candidate, index, all) {&#10;            if (all.indexOf(candidate) !== index) return false;&#10;            var candidateTop = containerRect.top + candidate;&#10;            var candidateBottom = candidateTop + chip.offsetHeight;&#10;            return protectedRects.every(function (rect) {&#10;              return candidateBottom &amp;lt;= rect.top - safeGap || candidateTop &amp;gt;= rect.bottom + safeGap;&#10;            });&#10;          });&#10;          valid.sort(function (first, second) {&#10;            return Math.abs(first - preferred) - Math.abs(second - preferred);&#10;          });&#10;          if (valid.length) top = valid[0];&#10;        }&#10;        chip.style.top = Math.round(top) + &amp;#x27;px&amp;#x27;;&#10;        if (Archify.radar &amp;amp;&amp;amp; typeof Archify.radar.sync === &amp;#x27;function&amp;#x27;) Archify.radar.sync();&#10;      }&#10;      function requestLensPlacement() {&#10;        if (lensFrame) return;&#10;        lensFrame = requestAnimationFrame(placeRelationshipLens);&#10;      }&#10;      function clear(options) {&#10;        options = options || {};&#10;        var restoreNode = options.restoreFocus === true &amp;amp;&amp;amp; activeIds.length === 1&#10;          ? svg.querySelector(&amp;#x27;[data-node-id=&amp;quot;&amp;#x27; + activeIds[0] + &amp;#x27;&amp;quot;]&amp;#x27;)&#10;          : null;&#10;        clearReachability({ updateUrl: false });&#10;        if (Archify.intentTrace &amp;amp;&amp;amp; typeof Archify.intentTrace.clear === &amp;#x27;function&amp;#x27;) {&#10;          Archify.intentTrace.clear({ announce: false });&#10;        }&#10;        hoveredRelationship = null;&#10;        focusedRelationship = null;&#10;        clearRelationshipPreview({ clearPin: true });&#10;        activeIds = [];&#10;        svg.removeAttribute(&amp;#x27;data-focus-active&amp;#x27;);&#10;        nodes().forEach(function (node) {&#10;          node.removeAttribute(&amp;#x27;data-focus-match&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-focus-selected&amp;#x27;);&#10;          node.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        });&#10;        edges().forEach(function (edge) { edge.removeAttribute(&amp;#x27;data-focus-match&amp;#x27;); });&#10;        chip.hidden = true;&#10;        label.textContent = &amp;#x27;&amp;#x27;;&#10;        detail.textContent = &amp;#x27;&amp;#x27;;&#10;        detail.hidden = true;&#10;        kind.textContent = &amp;#x27;&amp;#x27;;&#10;        kind.hidden = true;&#10;        context.textContent = &amp;#x27;&amp;#x27;;&#10;        context.hidden = true;&#10;        tag.textContent = &amp;#x27;&amp;#x27;;&#10;        tag.hidden = true;&#10;        semanticId.textContent = &amp;#x27;&amp;#x27;;&#10;        semanticId.hidden = true;&#10;        evidence.hidden = true;&#10;        evidenceLinks.textContent = &amp;#x27;&amp;#x27;;&#10;        repositoryLink.removeAttribute(&amp;#x27;href&amp;#x27;);&#10;        repositoryLink.textContent = &amp;#x27;&amp;#x27;;&#10;        summary.textContent = &amp;#x27;&amp;#x27;;&#10;        reachSection.hidden = true;&#10;        upstreamCount.textContent = &amp;#x27;0&amp;#x27;;&#10;        downstreamCount.textContent = &amp;#x27;0&amp;#x27;;&#10;        upstreamBtn.disabled = true;&#10;        downstreamBtn.disabled = true;&#10;        relationshipList.textContent = &amp;#x27;&amp;#x27;;&#10;        copyBtn.textContent = viewerText(&amp;#x27;viewer.passport.copy&amp;#x27;);&#10;        copyBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.passport.copy.focus&amp;#x27;));&#10;        relationsBtn.textContent = viewerText(&amp;#x27;viewer.passport.relations&amp;#x27;);&#10;        relationsBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.passport.relations.show&amp;#x27;));&#10;        relationsBtn.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        chip.removeAttribute(&amp;#x27;data-relations-expanded&amp;#x27;);&#10;        chip.style.removeProperty(&amp;#x27;top&amp;#x27;);&#10;        if (options.preserveView !== true &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reset === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reset({ automatic: true });&#10;        }&#10;        if (options.updateUrl !== false) {&#10;          try { history.replaceState(null, &amp;#x27;&amp;#x27;, location.pathname + location.search); } catch (_) {}&#10;        }&#10;        if (restoreNode) {&#10;          try { restoreNode.focus({ preventScroll: true }); }&#10;          catch (_) { try { restoreNode.focus(); } catch (_) {} }&#10;        }&#10;      }&#10;&#10;      function setMany(ids, options) {&#10;        options = options || {};&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; typeof Archify.semanticLens.clearPreview === &amp;#x27;function&amp;#x27;) Archify.semanticLens.clearPreview();&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; Archify.semanticLens.active()) {&#10;          Archify.semanticLens.clear({ updateUrl: false, preserveView: true, closePanel: true });&#10;        }&#10;        if (options.preserveRoute !== true &amp;amp;&amp;amp; Archify.routeProbe &amp;amp;&amp;amp; typeof Archify.routeProbe.clear === &amp;#x27;function&amp;#x27;) {&#10;          Archify.routeProbe.clear({ updateUrl: false, restoreFocus: false });&#10;        }&#10;        var nodeList = nodes();&#10;        var byId = {};&#10;        nodeList.forEach(function (node) { byId[node.getAttribute(&amp;#x27;data-node-id&amp;#x27;)] = node; });&#10;        var normalized = [];&#10;        (ids || []).forEach(function (id) {&#10;          if (byId[id] &amp;amp;&amp;amp; normalized.indexOf(id) === -1) normalized.push(id);&#10;        });&#10;        if (!normalized.length) return false;&#10;        if (normalized.length === activeIds.length &amp;amp;&amp;amp; normalized.every(function (id, index) { return activeIds[index] === id; }) &amp;amp;&amp;amp; options.toggle !== false) {&#10;          clear();&#10;          return true;&#10;        }&#10;&#10;        clear({ updateUrl: false, preserveView: true });&#10;        activeIds = normalized;&#10;        var selected = {};&#10;        var related = {};&#10;        var seenEdges = {};&#10;        var matchedEdges = 0;&#10;        normalized.forEach(function (id) { selected[id] = true; related[id] = true; });&#10;        var selectionMode = options.mode === &amp;#x27;selection&amp;#x27; || normalized.length &amp;gt; 1;&#10;&#10;        edges().forEach(function (edge) {&#10;          var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;          var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;          var match = selectionMode ? selected[from] &amp;amp;&amp;amp; selected[to] : selected[from] || selected[to];&#10;          if (!match) return;&#10;          edge.setAttribute(&amp;#x27;data-focus-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          if (!selectionMode) { related[from] = true; related[to] = true; }&#10;          var edgeKey = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) || (from + &amp;#x27;\u0000&amp;#x27; + to + &amp;#x27;\u0000&amp;#x27; + (edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;));&#10;          if (!seenEdges[edgeKey]) { seenEdges[edgeKey] = true; matchedEdges += 1; }&#10;        });&#10;        nodeList.forEach(function (node) {&#10;          var nodeId = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;          if (related[nodeId]) node.setAttribute(&amp;#x27;data-focus-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          if (selected[nodeId]) {&#10;            node.setAttribute(&amp;#x27;data-focus-selected&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            node.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          }&#10;        });&#10;        svg.setAttribute(&amp;#x27;data-focus-active&amp;#x27;, normalized.join(&amp;#x27; &amp;#x27;));&#10;        var defaultLabel = normalized.length === 1&#10;          ? nodeLabel(byId[normalized[0]], normalized[0])&#10;          : viewerText(&amp;#x27;viewer.guided.chapter.selectedNodes&amp;#x27;, { count: normalized.length });&#10;        label.textContent = options.label || defaultLabel;&#10;        chip.hidden = options.hideChip === true || normalized.length !== 1 || selectionMode;&#10;        if (!chip.hidden) {&#10;          renderRelationshipLens(normalized[0], byId);&#10;          requestLensPlacement();&#10;        }&#10;        if (options.updateUrl !== false) {&#10;          var key = options.urlKey || &amp;#x27;focus&amp;#x27;;&#10;          var value = options.urlValue || normalized[0];&#10;          try { history.replaceState(null, &amp;#x27;&amp;#x27;, location.pathname + location.search + &amp;#x27;#&amp;#x27; + key + &amp;#x27;=&amp;#x27; + encodeURIComponent(value)); } catch (_) {}&#10;        }&#10;        return true;&#10;      }&#10;&#10;      function set(id, options) {&#10;        options = options || {};&#10;        options.mode = &amp;#x27;neighborhood&amp;#x27;;&#10;        return setMany([id], options);&#10;      }&#10;&#10;      function fallbackCopy(value) {&#10;        var field = document.createElement(&amp;#x27;textarea&amp;#x27;);&#10;        field.value = value;&#10;        field.setAttribute(&amp;#x27;readonly&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        field.style.position = &amp;#x27;fixed&amp;#x27;;&#10;        field.style.opacity = &amp;#x27;0&amp;#x27;;&#10;        document.body.appendChild(field);&#10;        field.select();&#10;        var copied = false;&#10;        try { copied = document.execCommand(&amp;#x27;copy&amp;#x27;); } catch (_) {}&#10;        field.remove();&#10;        return copied;&#10;      }&#10;&#10;      function copyFocusLink() {&#10;        if (activeIds.length !== 1) return Promise.resolve(false);&#10;        var record = pinnedRelationshipRecord();&#10;        var relationId = record &amp;amp;&amp;amp; record.id;&#10;        var value = location.href.replace(/#.*$/, &amp;#x27;&amp;#x27;) + (relationId&#10;          ? &amp;#x27;#relation=&amp;#x27; + encodeURIComponent(relationId)&#10;          : &amp;#x27;#focus=&amp;#x27; + encodeURIComponent(activeIds[0]) + (reachabilityMode ? &amp;#x27;&amp;amp;reach=&amp;#x27; + reachabilityMode : &amp;#x27;&amp;#x27;));&#10;        var copy = navigator.clipboard &amp;amp;&amp;amp; typeof navigator.clipboard.writeText === &amp;#x27;function&amp;#x27;&#10;          ? navigator.clipboard.writeText(value).then(function () { return true; }).catch(function () { return fallbackCopy(value); })&#10;          : Promise.resolve(fallbackCopy(value));&#10;        return copy.then(function (copied) {&#10;          copyBtn.textContent = viewerText(copied ? &amp;#x27;viewer.common.copied&amp;#x27; : &amp;#x27;viewer.common.copyFailed&amp;#x27;);&#10;          copyBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, copied&#10;            ? viewerText(relationId ? &amp;#x27;viewer.passport.copy.pinned.success&amp;#x27; : &amp;#x27;viewer.passport.copy.focused.success&amp;#x27;)&#10;            : viewerText(relationId ? &amp;#x27;viewer.passport.copy.pinned.failed&amp;#x27; : &amp;#x27;viewer.passport.copy.focused.failed&amp;#x27;));&#10;          window.setTimeout(function () {&#10;            renderRelationshipCopyAction();&#10;          }, 1600);&#10;          return copied;&#10;        });&#10;      }&#10;&#10;      svg.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        if (container.getAttribute(&amp;#x27;data-just-panned&amp;#x27;) === &amp;#x27;true&amp;#x27;) return;&#10;        var node = event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (node) {&#10;          var id = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;          set(id);&#10;          if (activeIds.indexOf(id) !== -1 &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;            Archify.view.reveal([id], { includeNeighbors: true, reason: &amp;#x27;focus&amp;#x27; });&#10;          }&#10;        }&#10;        else if (activeIds.length) clear();&#10;      });&#10;      svg.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        var node = event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (!node || (event.key !== &amp;#x27;Enter&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27; &amp;#x27;)) return;&#10;        event.preventDefault();&#10;        var id = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;        set(id);&#10;        if (activeIds.indexOf(id) !== -1 &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reveal([id], { includeNeighbors: true, reason: &amp;#x27;focus&amp;#x27; });&#10;        }&#10;      });&#10;      clearBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { clear({ restoreFocus: true }); });&#10;      copyBtn.addEventListener(&amp;#x27;click&amp;#x27;, copyFocusLink);&#10;      upstreamBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { applyReachability(&amp;#x27;upstream&amp;#x27;); });&#10;      downstreamBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { applyReachability(&amp;#x27;downstream&amp;#x27;); });&#10;      relationsBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () {&#10;        var expanded = chip.getAttribute(&amp;#x27;data-relations-expanded&amp;#x27;) === &amp;#x27;true&amp;#x27;;&#10;        if (expanded) chip.removeAttribute(&amp;#x27;data-relations-expanded&amp;#x27;);&#10;        else chip.setAttribute(&amp;#x27;data-relations-expanded&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        relationsBtn.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, expanded ? &amp;#x27;false&amp;#x27; : &amp;#x27;true&amp;#x27;);&#10;        relationsBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(expanded&#10;          ? &amp;#x27;viewer.passport.relations.show&amp;#x27;&#10;          : &amp;#x27;viewer.passport.relations.hide&amp;#x27;));&#10;        requestLensPlacement();&#10;      });&#10;      relationshipList.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-relationship-target]&amp;#x27;);&#10;        if (!button) return;&#10;        var id = button.getAttribute(&amp;#x27;data-relationship-target&amp;#x27;);&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; typeof Archify.guidedViews.showAll === &amp;#x27;function&amp;#x27;) {&#10;          Archify.guidedViews.showAll({ clearFocus: false, updateUrl: false });&#10;        }&#10;        set(id, { toggle: false });&#10;        if (Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reveal([id], { includeNeighbors: true, reason: &amp;#x27;relationship&amp;#x27; });&#10;        }&#10;        var node = svg.querySelector(&amp;#x27;[data-node-id=&amp;quot;&amp;#x27; + id + &amp;#x27;&amp;quot;]&amp;#x27;);&#10;        if (node) {&#10;          try { node.focus({ preventScroll: true }); } catch (_) { try { node.focus(); } catch (_) {} }&#10;        }&#10;      });&#10;      relationshipList.addEventListener(&amp;#x27;pointerover&amp;#x27;, function (event) {&#10;        if (event.pointerType === &amp;#x27;touch&amp;#x27;) return;&#10;        if (finePointerQuery &amp;amp;&amp;amp; !finePointerQuery.matches) return;&#10;        var button = event.target.closest(&amp;#x27;[data-relationship-key]&amp;#x27;);&#10;        if (!button || !relationshipList.contains(button)) return;&#10;        if (event.relatedTarget &amp;amp;&amp;amp; button.contains(event.relatedTarget)) return;&#10;        hoveredRelationship = button;&#10;        syncRelationshipPreview();&#10;      });&#10;      relationshipList.addEventListener(&amp;#x27;pointerout&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-relationship-key]&amp;#x27;);&#10;        if (!button || (event.relatedTarget &amp;amp;&amp;amp; button.contains(event.relatedTarget))) return;&#10;        if (hoveredRelationship === button) hoveredRelationship = null;&#10;        syncRelationshipPreview();&#10;      });&#10;      relationshipList.addEventListener(&amp;#x27;focusin&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-relationship-key]&amp;#x27;);&#10;        if (!button) return;&#10;        focusedRelationship = button;&#10;        syncRelationshipPreview();&#10;      });&#10;      relationshipList.addEventListener(&amp;#x27;focusout&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-relationship-key]&amp;#x27;);&#10;        if (!button || (event.relatedTarget &amp;amp;&amp;amp; button.contains(event.relatedTarget))) return;&#10;        if (focusedRelationship === button) focusedRelationship = null;&#10;        syncRelationshipPreview();&#10;      });&#10;      relationshipList.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        if (event.key !== &amp;#x27;ArrowDown&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;ArrowUp&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;Home&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;End&amp;#x27;) return;&#10;        var buttons = Array.prototype.slice.call(relationshipList.querySelectorAll(&amp;#x27;[data-relationship-target]&amp;#x27;));&#10;        if (!buttons.length) return;&#10;        var index = buttons.indexOf(document.activeElement);&#10;        if (event.key === &amp;#x27;Home&amp;#x27;) index = 0;&#10;        else if (event.key === &amp;#x27;End&amp;#x27;) index = buttons.length - 1;&#10;        else if (event.key === &amp;#x27;ArrowDown&amp;#x27;) index = Math.min(buttons.length - 1, Math.max(0, index + 1));&#10;        else index = Math.max(0, index &amp;lt; 0 ? 0 : index - 1);&#10;        event.preventDefault();&#10;        buttons[index].focus();&#10;      });&#10;      document.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        var target = event.target;&#10;        if (chip.hidden || !target || typeof target.closest !== &amp;#x27;function&amp;#x27; || chip.contains(target)) return;&#10;        if (container.getAttribute(&amp;#x27;data-just-panned&amp;#x27;) === &amp;#x27;true&amp;#x27;) return;&#10;        if (target.closest(&amp;#x27;[data-node-id], [data-relationship-hit-key], .overview-map&amp;#x27;)) return;&#10;        clear();&#10;      }, true);&#10;      window.addEventListener(&amp;#x27;scroll&amp;#x27;, requestLensPlacement, { passive: true });&#10;      window.addEventListener(&amp;#x27;resize&amp;#x27;, requestLensPlacement);&#10;      container.addEventListener(&amp;#x27;scroll&amp;#x27;, requestLensPlacement, { passive: true });&#10;      document.addEventListener(&amp;#x27;visibilitychange&amp;#x27;, function () {&#10;        if (document.hidden) removeRelationshipPulse();&#10;      });&#10;      function syncRelationshipMotionPreference(event) {&#10;        if (event.matches) removeRelationshipPulse();&#10;      }&#10;      if (reducedMotionQuery) {&#10;        if (typeof reducedMotionQuery.addEventListener === &amp;#x27;function&amp;#x27;) {&#10;          reducedMotionQuery.addEventListener(&amp;#x27;change&amp;#x27;, syncRelationshipMotionPreference);&#10;        } else if (typeof reducedMotionQuery.addListener === &amp;#x27;function&amp;#x27;) {&#10;          reducedMotionQuery.addListener(syncRelationshipMotionPreference);&#10;        }&#10;      }&#10;&#10;      installRelationshipHitTargets();&#10;&#10;      function syncFocusFromHash() {&#10;        try {&#10;          var params = new URLSearchParams(location.hash.replace(/^#/, &amp;#x27;&amp;#x27;));&#10;          var relation = params.get(&amp;#x27;relation&amp;#x27;);&#10;          var initial = params.get(&amp;#x27;focus&amp;#x27;);&#10;          var reach = params.get(&amp;#x27;reach&amp;#x27;);&#10;          if (relation) {&#10;            if (html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27; ||&#10;                !inspectRelationshipById(relation, { updateUrl: false, toggle: false })) clear({ updateUrl: false });&#10;          }&#10;          else if (initial) {&#10;            if (set(initial, { updateUrl: false, toggle: false }) &amp;amp;&amp;amp;&#10;                (reach === &amp;#x27;upstream&amp;#x27; || reach === &amp;#x27;downstream&amp;#x27;)) {&#10;              applyReachability(reach, { updateUrl: false, toggle: false, reveal: false });&#10;            }&#10;          }&#10;          else if (!params.get(&amp;#x27;view&amp;#x27;)) clear({ updateUrl: false });&#10;        } catch (_) {}&#10;      }&#10;&#10;      window.addEventListener(&amp;#x27;hashchange&amp;#x27;, syncFocusFromHash);&#10;      syncFocusFromHash();&#10;&#10;      return {&#10;        set: set,&#10;        setMany: setMany,&#10;        clear: clear,&#10;        copyLink: copyFocusLink,&#10;        reach: applyReachability,&#10;        clearReach: clearReachability,&#10;        reachabilitySnapshot: reachabilitySnapshot,&#10;        inspectRelationship: inspectRelationship,&#10;        inspectRelationshipById: inspectRelationshipById,&#10;        reposition: requestLensPlacement,&#10;        relationship: function () {&#10;          var record = pinnedRelationshipRecord();&#10;          return record ? { id: record.id || null, key: record.key, from: record.from, to: record.to, label: record.label } : null;&#10;        },&#10;        reachability: function () {&#10;          return activeReachability ? {&#10;            direction: activeReachability.direction,&#10;            originId: activeReachability.originId,&#10;            nodeIds: activeReachability.nodeIds.slice(),&#10;            edgeKeys: activeReachability.edgeKeys.slice(),&#10;            maxDepth: activeReachability.maxDepth&#10;          } : null;&#10;        },&#10;        active: function () { return activeIds.length === 0 ? null : (activeIds.length === 1 ? activeIds[0] : activeIds.slice()); }&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Intent Trace — temporary one-hop topology before durable focus.&#10;       Fine-pointer hover and keyboard focus share the same stable-ID preview;&#10;       touch continues directly to the existing click-to-focus contract.&#10;       ============================================================ */&#10;    Archify.intentTrace = (function () {&#10;      var html = document.documentElement;&#10;      var container = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var svg = container.querySelector(&amp;#x27;:scope &amp;gt; svg&amp;#x27;);&#10;      var status = document.getElementById(&amp;#x27;intent-trace-status&amp;#x27;);&#10;      var namespace = &amp;#x27;http://www.w3.org/2000/svg&amp;#x27;;&#10;      var activeId = null;&#10;      var hoveredNode = null;&#10;      var focusedNode = null;&#10;      var enterTimer = null;&#10;&#10;      function nodes() {&#10;        return Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;));&#10;      }&#10;      function edges() {&#10;        return Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-edge-from][data-edge-to]&amp;#x27;));&#10;      }&#10;      function nodeLabel(node, fallback) {&#10;        return node.getAttribute(&amp;#x27;data-node-label&amp;#x27;) ||&#10;          (node.getAttribute(&amp;#x27;aria-label&amp;#x27;) || fallback).replace(/^Focus\s+/, &amp;#x27;&amp;#x27;).split(&amp;#x27;,&amp;#x27;)[0];&#10;      }&#10;      function finePointer() {&#10;        return !window.matchMedia || window.matchMedia(&amp;#x27;(hover: hover) and (pointer: fine)&amp;#x27;).matches;&#10;      }&#10;      function reducedMotion() {&#10;        return !!(window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;(prefers-reduced-motion: reduce)&amp;#x27;).matches);&#10;      }&#10;      function blocked() {&#10;        return html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27; ||&#10;          html.getAttribute(&amp;#x27;data-guide-open&amp;#x27;) === &amp;#x27;true&amp;#x27; ||&#10;          container.classList.contains(&amp;#x27;is-panning&amp;#x27;) ||&#10;          svg.hasAttribute(&amp;#x27;data-lens-active&amp;#x27;) ||&#10;          svg.hasAttribute(&amp;#x27;data-story-active&amp;#x27;) ||&#10;          svg.hasAttribute(&amp;#x27;data-relationship-preview-active&amp;#x27;) ||&#10;          !!(Archify.routeProbe &amp;amp;&amp;amp; typeof Archify.routeProbe.active === &amp;#x27;function&amp;#x27; &amp;amp;&amp;amp; Archify.routeProbe.active()) ||&#10;          !!(Archify.focus &amp;amp;&amp;amp; typeof Archify.focus.active === &amp;#x27;function&amp;#x27; &amp;amp;&amp;amp; Archify.focus.active());&#10;      }&#10;      function edgeShapes(edge) {&#10;        if (/^(path|line|polyline)$/i.test(edge.tagName)) return [edge];&#10;        return Array.prototype.slice.call(edge.querySelectorAll(&amp;#x27;path, line, polyline&amp;#x27;));&#10;      }&#10;      function removeOverlay() {&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-intent-trace-overlay]&amp;#x27;), function (overlay) {&#10;          overlay.remove();&#10;        });&#10;      }&#10;      function clear(options) {&#10;        options = options || {};&#10;        if (enterTimer) window.clearTimeout(enterTimer);&#10;        enterTimer = null;&#10;        activeId = null;&#10;        svg.removeAttribute(&amp;#x27;data-intent-trace-active&amp;#x27;);&#10;        removeOverlay();&#10;        nodes().forEach(function (node) {&#10;          node.removeAttribute(&amp;#x27;data-intent-trace-match&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-intent-trace-selected&amp;#x27;);&#10;        });&#10;        edges().forEach(function (edge) { edge.removeAttribute(&amp;#x27;data-intent-trace-match&amp;#x27;); });&#10;        if (options.announce !== false) status.textContent = &amp;#x27;&amp;#x27;;&#10;      }&#10;      function traceGeometry(shape, direction) {&#10;        var clone = shape.cloneNode(false);&#10;        clone.removeAttribute(&amp;#x27;id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;class&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;style&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-start&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-mid&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-end&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;role&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-labelledby&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-animate&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-key&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-intent-trace-match&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-intent-trace-selected&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;intent-trace-flow&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;data-direction&amp;#x27;, direction);&#10;        clone.setAttribute(&amp;#x27;pathLength&amp;#x27;, &amp;#x27;1&amp;#x27;);&#10;        return clone;&#10;      }&#10;      function show(id, options) {&#10;        options = options || {};&#10;        if (!id || blocked()) {&#10;          clear({ announce: false });&#10;          return false;&#10;        }&#10;        if (activeId === id) return true;&#10;        clear({ announce: false });&#10;        var nodeList = nodes();&#10;        var edgeList = edges();&#10;        var byId = {};&#10;        nodeList.forEach(function (node) { byId[node.getAttribute(&amp;#x27;data-node-id&amp;#x27;)] = node; });&#10;        var selected = byId[id];&#10;        if (!selected) return false;&#10;&#10;        var overlay = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;intent-trace-overlay&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;data-intent-trace-overlay&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        var related = {};&#10;        var seen = {};&#10;        var counts = { out: 0, in: 0, loop: 0 };&#10;        related[id] = true;&#10;&#10;        edgeList.forEach(function (edge) {&#10;          var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;          var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;          if (from !== id &amp;amp;&amp;amp; to !== id) return;&#10;          var direction = from === id &amp;amp;&amp;amp; to === id ? &amp;#x27;loop&amp;#x27; : (from === id ? &amp;#x27;out&amp;#x27; : &amp;#x27;in&amp;#x27;);&#10;          var key = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) ||&#10;            (from + &amp;#x27;\u0000&amp;#x27; + to + &amp;#x27;\u0000&amp;#x27; + (edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;));&#10;          if (!seen[key]) {&#10;            seen[key] = true;&#10;            counts[direction] += 1;&#10;          }&#10;          related[from] = true;&#10;          related[to] = true;&#10;          edge.setAttribute(&amp;#x27;data-intent-trace-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          var wrapper = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;          if (edge.hasAttribute(&amp;#x27;transform&amp;#x27;)) wrapper.setAttribute(&amp;#x27;transform&amp;#x27;, edge.getAttribute(&amp;#x27;transform&amp;#x27;));&#10;          edgeShapes(edge).forEach(function (shape) {&#10;            wrapper.appendChild(traceGeometry(shape, direction));&#10;          });&#10;          if (wrapper.childNodes.length) overlay.appendChild(wrapper);&#10;        });&#10;&#10;        nodeList.forEach(function (node) {&#10;          var nodeId = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;          if (related[nodeId]) node.setAttribute(&amp;#x27;data-intent-trace-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          if (nodeId === id) node.setAttribute(&amp;#x27;data-intent-trace-selected&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        });&#10;        if (overlay.childNodes.length) {&#10;          var firstEdge = edgeList[0];&#10;          var firstNode = svg.querySelector(&amp;#x27;[data-node-id]&amp;#x27;);&#10;          if (firstEdge &amp;amp;&amp;amp; firstEdge.parentNode) firstEdge.parentNode.insertBefore(overlay, firstEdge);&#10;          else if (firstNode) svg.insertBefore(overlay, firstNode);&#10;          else svg.appendChild(overlay);&#10;        }&#10;        activeId = id;&#10;        svg.setAttribute(&amp;#x27;data-intent-trace-active&amp;#x27;, id);&#10;        if (options.announce === true) {&#10;          var total = counts.out + counts.in + counts.loop;&#10;          status.textContent = viewerText(&amp;#x27;viewer.intent.summary&amp;#x27;, {&#10;            label: nodeLabel(selected, id),&#10;            out: counts.out,&#10;            in: counts.in,&#10;            loops: counts.loop ? viewerText(&amp;#x27;viewer.intent.loops&amp;#x27;, { count: counts.loop }) : &amp;#x27;&amp;#x27;,&#10;            total: total&#10;          });&#10;        }&#10;        return true;&#10;      }&#10;      function schedule(node) {&#10;        if (enterTimer) window.clearTimeout(enterTimer);&#10;        enterTimer = window.setTimeout(function () {&#10;          enterTimer = null;&#10;          if (hoveredNode === node) show(node.getAttribute(&amp;#x27;data-node-id&amp;#x27;), { announce: false });&#10;        }, reducedMotion() ? 0 : 90);&#10;      }&#10;      function sync() {&#10;        var candidate = focusedNode || hoveredNode;&#10;        if (!candidate) {&#10;          clear();&#10;          return;&#10;        }&#10;        show(candidate.getAttribute(&amp;#x27;data-node-id&amp;#x27;), { announce: candidate === focusedNode });&#10;      }&#10;&#10;      svg.addEventListener(&amp;#x27;pointerover&amp;#x27;, function (event) {&#10;        var node = event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (!node || !finePointer() || event.pointerType === &amp;#x27;touch&amp;#x27;) return;&#10;        if (event.relatedTarget &amp;amp;&amp;amp; node.contains(event.relatedTarget)) return;&#10;        hoveredNode = node;&#10;        schedule(node);&#10;      });&#10;      svg.addEventListener(&amp;#x27;pointerout&amp;#x27;, function (event) {&#10;        var node = event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (!node || (event.relatedTarget &amp;amp;&amp;amp; node.contains(event.relatedTarget))) return;&#10;        if (hoveredNode === node) hoveredNode = null;&#10;        sync();&#10;      });&#10;      svg.addEventListener(&amp;#x27;focusin&amp;#x27;, function (event) {&#10;        var node = event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (!node) return;&#10;        focusedNode = node;&#10;        show(node.getAttribute(&amp;#x27;data-node-id&amp;#x27;), { announce: true });&#10;      });&#10;      svg.addEventListener(&amp;#x27;focusout&amp;#x27;, function (event) {&#10;        var node = event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (!node || (event.relatedTarget &amp;amp;&amp;amp; node.contains(event.relatedTarget))) return;&#10;        if (focusedNode === node) focusedNode = null;&#10;        sync();&#10;      });&#10;      container.addEventListener(&amp;#x27;pointerdown&amp;#x27;, function (event) {&#10;        if (!event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;)) clear({ announce: false });&#10;      });&#10;      window.addEventListener(&amp;#x27;blur&amp;#x27;, function () { clear({ announce: false }); });&#10;&#10;      return {&#10;        show: show,&#10;        clear: clear,&#10;        active: function () { return activeId; }&#10;      };&#10;    })();&#10;&#10;    Archify.guidedViews = (function () {&#10;      var data = document.getElementById(&amp;#x27;archify-guided-views-data&amp;#x27;);&#10;      var panel = document.getElementById(&amp;#x27;guided-views&amp;#x27;);&#10;      var prev = document.getElementById(&amp;#x27;guided-view-prev&amp;#x27;);&#10;      var next = document.getElementById(&amp;#x27;guided-view-next&amp;#x27;);&#10;      var all = document.getElementById(&amp;#x27;guided-view-all&amp;#x27;);&#10;      var play = document.getElementById(&amp;#x27;guided-view-play&amp;#x27;);&#10;      var playIcon = document.getElementById(&amp;#x27;guided-view-play-icon&amp;#x27;);&#10;      var playLabel = document.getElementById(&amp;#x27;guided-view-play-label&amp;#x27;);&#10;      var beatLink = document.getElementById(&amp;#x27;guided-view-beat-link&amp;#x27;);&#10;      var beatLinkLabel = document.getElementById(&amp;#x27;guided-view-beat-link-label&amp;#x27;);&#10;      var progressBar = document.getElementById(&amp;#x27;guided-view-progress-bar&amp;#x27;);&#10;      var count = document.getElementById(&amp;#x27;guided-view-count&amp;#x27;);&#10;      var handoffReceipt = document.getElementById(&amp;#x27;guided-view-handoff&amp;#x27;);&#10;      var label = document.getElementById(&amp;#x27;guided-view-label&amp;#x27;);&#10;      var note = document.getElementById(&amp;#x27;guided-view-note&amp;#x27;);&#10;      var trail = document.getElementById(&amp;#x27;guided-view-trail&amp;#x27;);&#10;      var storyCaption = document.getElementById(&amp;#x27;guided-story-caption&amp;#x27;);&#10;      var storyCaptionIndex = document.getElementById(&amp;#x27;guided-story-caption-index&amp;#x27;);&#10;      var storyCaptionRoute = document.getElementById(&amp;#x27;guided-story-caption-route&amp;#x27;);&#10;      var storyCaptionDetail = document.getElementById(&amp;#x27;guided-story-caption-detail&amp;#x27;);&#10;      var storyCaptionNext = document.getElementById(&amp;#x27;guided-story-caption-next&amp;#x27;);&#10;      var storyCaptionNextLabel = document.getElementById(&amp;#x27;guided-story-caption-next-label&amp;#x27;);&#10;      var chapterIndex = document.getElementById(&amp;#x27;guided-view-index&amp;#x27;);&#10;      var chapterList = document.getElementById(&amp;#x27;guided-view-chapters&amp;#x27;);&#10;      var shareCue = document.getElementById(&amp;#x27;share-chapter-cue&amp;#x27;);&#10;      var shareCueState = document.getElementById(&amp;#x27;share-chapter-state&amp;#x27;);&#10;      var shareCueCount = document.getElementById(&amp;#x27;share-chapter-count&amp;#x27;);&#10;      var shareCueLabel = document.getElementById(&amp;#x27;share-chapter-label&amp;#x27;);&#10;      var shareCueNote = document.getElementById(&amp;#x27;share-chapter-note&amp;#x27;);&#10;      var shareCueRoute = document.getElementById(&amp;#x27;share-chapter-route&amp;#x27;);&#10;      var shareCueProgress = document.getElementById(&amp;#x27;share-chapter-progress-bar&amp;#x27;);&#10;      var svg = document.querySelector(&amp;#x27;.diagram-container svg&amp;#x27;);&#10;      var views = [];&#10;      var activeIndex = -1;&#10;      var playing = false;&#10;      var storyBeatTimer = null;&#10;      var storyBeatIndex = -1;&#10;      var storyBeatStartedAt = 0;&#10;      var storyBeatElapsedMs = 0;&#10;      var storyBeatDwellMs = 0;&#10;      var storyPlaybackGeneration = 0;&#10;      var storyFollowGeneration = 0;&#10;      var storyPlaybackScope = &amp;#x27;story&amp;#x27;;&#10;      var storyPlaybackComplete = false;&#10;      var beatLinkFeedbackTimer = null;&#10;      var momentRestoreGeneration = 0;&#10;      var storySteps = [];&#10;      var storyPulseOwnerToken = 0;&#10;      var storyPulseGeneration = 0;&#10;      var autoplayPending = false;&#10;      var VIEW_INTERVAL_MS = 3200;&#10;      var STORY_FOLLOW_MIN_DWELL_MS = 1100;&#10;      var STORY_FOLLOW_DURATION_MS = 320;&#10;      var chapterButtons = [];&#10;      var handoffGeneration = 0;&#10;      var currentHandoff = null;&#10;      var previewGeneration = 0;&#10;      var pointerPreviewIntent = null;&#10;      var focusPreviewIntent = null;&#10;      var activePreviewIndex = -1;&#10;      var previewOwnerToken = 0;&#10;&#10;      try { views = JSON.parse(data.textContent || &amp;#x27;[]&amp;#x27;); } catch (_) { views = []; }&#10;      if (!views.length) return { count: 0, active: function () { return null; } };&#10;      var canonicalNodeIds = {};&#10;      Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;), function (node) {&#10;        canonicalNodeIds[node.getAttribute(&amp;#x27;data-node-id&amp;#x27;)] = true;&#10;      });&#10;      views.forEach(function (view) {&#10;        var seen = {};&#10;        view.focus = (view.focus || []).filter(function (id) {&#10;          if (!canonicalNodeIds[id] || seen[id]) return false;&#10;          seen[id] = true;&#10;          return true;&#10;        });&#10;      });&#10;      // Establish the compact cold state before exposing the panel so the&#10;      // full Director cannot flash during first paint. Hash restoration runs&#10;      // in the same task and replaces this state before paint when valid.&#10;      panel.setAttribute(&amp;#x27;data-active-view&amp;#x27;, &amp;#x27;all&amp;#x27;);&#10;      panel.hidden = false;&#10;      panel.setAttribute(&amp;#x27;data-view-interval-ms&amp;#x27;, String(VIEW_INTERVAL_MS));&#10;      panel.setAttribute(&amp;#x27;data-story-follow-min-dwell-ms&amp;#x27;, String(STORY_FOLLOW_MIN_DWELL_MS));&#10;      buildChapterIndex();&#10;&#10;      function reducedMotion() {&#10;        return !!(window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;(prefers-reduced-motion: reduce)&amp;#x27;).matches);&#10;      }&#10;&#10;      function findNode(id) {&#10;        return Array.prototype.find.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;), function (node) {&#10;          return node.getAttribute(&amp;#x27;data-node-id&amp;#x27;) === id;&#10;        }) || null;&#10;      }&#10;&#10;      function chapterDelta(previous, destination) {&#10;        var previousFocus = previous ? previous.focus : [];&#10;        var destinationFocus = destination ? destination.focus : [];&#10;        var previousIds = {};&#10;        var destinationIds = {};&#10;        previousFocus.forEach(function (id) { previousIds[id] = true; });&#10;        destinationFocus.forEach(function (id) { destinationIds[id] = true; });&#10;        return {&#10;          stay: previousFocus.filter(function (id) { return destinationIds[id]; }),&#10;          enter: destinationFocus.filter(function (id) { return !previousIds[id]; }),&#10;          leave: previousFocus.filter(function (id) { return !destinationIds[id]; })&#10;        };&#10;      }&#10;&#10;      function chapterAnchor(previous, destination, outgoingBeatIndex, delta) {&#10;        if (!previous || !destination) return &amp;#x27;&amp;#x27;;&#10;        var stayIds = {};&#10;        delta.stay.forEach(function (id) { stayIds[id] = true; });&#10;        var activeBeat = outgoingBeatIndex &amp;gt;= 0 ? previous.focus[outgoingBeatIndex] : &amp;#x27;&amp;#x27;;&#10;        if (activeBeat &amp;amp;&amp;amp; stayIds[activeBeat]) return activeBeat;&#10;        for (var index = previous.focus.length - 1; index &amp;gt;= 0; index -= 1) {&#10;          if (stayIds[previous.focus[index]]) return previous.focus[index];&#10;        }&#10;        return &amp;#x27;&amp;#x27;;&#10;      }&#10;&#10;      function handoffMotionAllowed() {&#10;        if (document.hidden || reducedMotion()) return false;&#10;        if (document.documentElement.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        if (window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;print&amp;#x27;).matches) return false;&#10;        return !(Archify.motionGovernor &amp;amp;&amp;amp; Archify.motionGovernor.capable &amp;amp;&amp;amp; Archify.motionGovernor.isPaused());&#10;      }&#10;&#10;      function classifyHandoff(delta, anchor) {&#10;        var roles = {};&#10;        delta.stay.forEach(function (id) { roles[id] = &amp;#x27;stay&amp;#x27;; });&#10;        delta.enter.forEach(function (id) { roles[id] = &amp;#x27;enter&amp;#x27;; });&#10;        delta.leave.forEach(function (id) { roles[id] = &amp;#x27;leave&amp;#x27;; });&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;), function (node) {&#10;          var id = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;          var role = roles[id] || &amp;#x27;&amp;#x27;;&#10;          if (role) node.setAttribute(&amp;#x27;data-chapter-role&amp;#x27;, role);&#10;          else node.removeAttribute(&amp;#x27;data-chapter-role&amp;#x27;);&#10;        });&#10;        svg.setAttribute(&amp;#x27;data-chapter-handoff&amp;#x27;, anchor ? &amp;#x27;anchor&amp;#x27; : &amp;#x27;no-anchor&amp;#x27;);&#10;        if (anchor) svg.setAttribute(&amp;#x27;data-chapter-anchor&amp;#x27;, anchor);&#10;        else svg.removeAttribute(&amp;#x27;data-chapter-anchor&amp;#x27;);&#10;      }&#10;&#10;      function drawHandoffAnchor(id) {&#10;        var node = findNode(id);&#10;        if (!node) return null;&#10;        var box;&#10;        try { box = node.getBBox(); } catch (_) { return null; }&#10;        var overlay = document.createElementNS(&amp;#x27;http://www.w3.org/2000/svg&amp;#x27;, &amp;#x27;g&amp;#x27;);&#10;        var ring = document.createElementNS(&amp;#x27;http://www.w3.org/2000/svg&amp;#x27;, &amp;#x27;rect&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;chapter-handoff-overlay&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;data-chapter-handoff-overlay&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        ring.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;chapter-handoff-anchor&amp;#x27;);&#10;        ring.setAttribute(&amp;#x27;x&amp;#x27;, String(box.x - 8));&#10;        ring.setAttribute(&amp;#x27;y&amp;#x27;, String(box.y - 8));&#10;        ring.setAttribute(&amp;#x27;width&amp;#x27;, String(box.width + 16));&#10;        ring.setAttribute(&amp;#x27;height&amp;#x27;, String(box.height + 16));&#10;        ring.setAttribute(&amp;#x27;rx&amp;#x27;, &amp;#x27;10&amp;#x27;);&#10;        overlay.appendChild(ring);&#10;        svg.appendChild(overlay);&#10;        return overlay;&#10;      }&#10;&#10;      function clearHandoffPresentation() {&#10;        svg.removeAttribute(&amp;#x27;data-chapter-handoff&amp;#x27;);&#10;        svg.removeAttribute(&amp;#x27;data-chapter-anchor&amp;#x27;);&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-chapter-handoff-overlay]&amp;#x27;), function (overlay) { overlay.remove(); });&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-chapter-role]&amp;#x27;), function (node) { node.removeAttribute(&amp;#x27;data-chapter-role&amp;#x27;); });&#10;        if (handoffReceipt) {&#10;          handoffReceipt.hidden = true;&#10;          handoffReceipt.textContent = &amp;#x27;&amp;#x27;;&#10;        }&#10;      }&#10;&#10;      function completeHandoff(handoff, outcome) {&#10;        if (!handoff || currentHandoff !== handoff) return false;&#10;        if (handoff.holdTimer) clearTimeout(handoff.holdTimer);&#10;        handoff.holdTimer = null;&#10;        currentHandoff = null;&#10;        clearHandoffPresentation();&#10;        if (handoff.ownerToken &amp;amp;&amp;amp; Archify.motionGovernor) Archify.motionGovernor.release(handoff.ownerToken);&#10;        handoff.resolve({ id: handoff.id, state: outcome || &amp;#x27;complete&amp;#x27;, anchor: handoff.anchor || null });&#10;        syncStoryControlsDisabled();&#10;        syncChapterPreview();&#10;        return true;&#10;      }&#10;&#10;      function settleHandoff(reason) {&#10;        var handoff = currentHandoff;&#10;        if (!handoff) return false;&#10;        if (handoff.holdTimer) clearTimeout(handoff.holdTimer);&#10;        handoff.holdTimer = null;&#10;        if (handoff.camera &amp;amp;&amp;amp; handoff.camera.cancel) handoff.camera.cancel(reason || &amp;#x27;settled&amp;#x27;, true);&#10;        else if (Archify.view &amp;amp;&amp;amp; Archify.view.reveal) Archify.view.reveal(handoff.focus, { instant: true, reason: reason || &amp;#x27;settled&amp;#x27; });&#10;        completeHandoff(handoff, reason || &amp;#x27;settled&amp;#x27;);&#10;        return true;&#10;      }&#10;&#10;      function cancelHandoff(reason) {&#10;        var handoff = currentHandoff;&#10;        if (!handoff) return false;&#10;        if (handoff.holdTimer) clearTimeout(handoff.holdTimer);&#10;        handoff.holdTimer = null;&#10;        if (handoff.camera &amp;amp;&amp;amp; handoff.camera.cancel) handoff.camera.cancel(reason || &amp;#x27;manual&amp;#x27;, false);&#10;        completeHandoff(handoff, reason || &amp;#x27;manual&amp;#x27;);&#10;        return true;&#10;      }&#10;&#10;      function afterHandoff(callback) {&#10;        if (!currentHandoff) { callback(); return; }&#10;        currentHandoff.finished.then(callback);&#10;      }&#10;&#10;      function beginHandoff(previousIndex, nextIndex, previous, destination, outgoingBeatIndex, reason) {&#10;        if (!Archify.view || !Archify.view.reveal) return null;&#10;        if (!previous || previousIndex === nextIndex) {&#10;          Archify.view.reveal(destination.focus, { reason: reason });&#10;          return null;&#10;        }&#10;        var delta = chapterDelta(previous, destination);&#10;        var anchor = chapterAnchor(previous, destination, outgoingBeatIndex, delta);&#10;        if (!handoffMotionAllowed()) {&#10;          Archify.view.reveal(destination.focus, { instant: true, reason: reason });&#10;          return null;&#10;        }&#10;        var resolver;&#10;        var handoff = {&#10;          id: ++handoffGeneration,&#10;          mode: anchor ? &amp;#x27;holding&amp;#x27; : &amp;#x27;no-anchor&amp;#x27;,&#10;          anchor: anchor,&#10;          focus: destination.focus.slice(),&#10;          holdTimer: null,&#10;          camera: null,&#10;          ownerToken: 0,&#10;          finished: new Promise(function (resolve) { resolver = resolve; }),&#10;          resolve: resolver&#10;        };&#10;        currentHandoff = handoff;&#10;        classifyHandoff(delta, anchor);&#10;        if (anchor) {&#10;          drawHandoffAnchor(anchor);&#10;          var node = findNode(anchor);&#10;          var nodeLabel = node ? (node.getAttribute(&amp;#x27;data-node-label&amp;#x27;) || anchor) : anchor;&#10;          handoffReceipt.textContent = viewerText(&amp;#x27;viewer.guided.handoff&amp;#x27;, {&#10;            from: (previousIndex + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (previousIndex + 1),&#10;            to: (nextIndex + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (nextIndex + 1),&#10;            label: nodeLabel&#10;          });&#10;          handoffReceipt.hidden = false;&#10;        }&#10;        if (Archify.motionGovernor) {&#10;          handoff.ownerToken = Archify.motionGovernor.claim(&amp;#x27;handoff&amp;#x27;, function () {&#10;            if (currentHandoff === handoff) settleHandoff(&amp;#x27;preempted&amp;#x27;);&#10;          });&#10;        }&#10;        var startCamera = function () {&#10;          if (currentHandoff !== handoff) return;&#10;          handoff.holdTimer = null;&#10;          handoff.mode = &amp;#x27;settling&amp;#x27;;&#10;          svg.setAttribute(&amp;#x27;data-chapter-handoff&amp;#x27;, anchor ? &amp;#x27;settling&amp;#x27; : &amp;#x27;no-anchor&amp;#x27;);&#10;          handoff.camera = Archify.view.reveal(destination.focus, { reason: reason, duration: 420 });&#10;          if (handoff.camera &amp;amp;&amp;amp; handoff.camera.finished) {&#10;            handoff.camera.finished.then(function (outcome) {&#10;              if (currentHandoff === handoff) completeHandoff(handoff, outcome &amp;amp;&amp;amp; outcome.state || &amp;#x27;complete&amp;#x27;);&#10;            });&#10;          } else {&#10;            completeHandoff(handoff, &amp;#x27;complete&amp;#x27;);&#10;          }&#10;        };&#10;        if (anchor) handoff.holdTimer = setTimeout(startCamera, 110);&#10;        else startCamera();&#10;        return handoff;&#10;      }&#10;&#10;      function centerChapterButton(button) {&#10;        if (!button || !chapterList) return false;&#10;        var target = Math.max(0, button.offsetLeft - (chapterList.clientWidth - button.offsetWidth) / 2);&#10;        if (typeof chapterList.scrollTo === &amp;#x27;function&amp;#x27;) chapterList.scrollTo({ left: target, behavior: &amp;#x27;auto&amp;#x27; });&#10;        else chapterList.scrollLeft = target;&#10;        return true;&#10;      }&#10;&#10;      function focusChapterButton(index) {&#10;        if (!chapterButtons.length) return false;&#10;        index = Math.max(0, Math.min(chapterButtons.length - 1, index));&#10;        chapterButtons.forEach(function (button, buttonIndex) {&#10;          button.setAttribute(&amp;#x27;tabindex&amp;#x27;, buttonIndex === index ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;        });&#10;        chapterButtons[index].focus();&#10;        centerChapterButton(chapterButtons[index]);&#10;        return true;&#10;      }&#10;&#10;      function buildChapterIndex() {&#10;        chapterButtons = [];&#10;        chapterList.textContent = &amp;#x27;&amp;#x27;;&#10;        views.forEach(function (view, index) {&#10;          var item = document.createElement(&amp;#x27;li&amp;#x27;);&#10;          var button = document.createElement(&amp;#x27;button&amp;#x27;);&#10;          button.type = &amp;#x27;button&amp;#x27;;&#10;          button.className = &amp;#x27;guided-view-chapter&amp;#x27;;&#10;          button.setAttribute(&amp;#x27;data-guided-view-id&amp;#x27;, view.id);&#10;          button.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;          button.setAttribute(&amp;#x27;tabindex&amp;#x27;, index === 0 ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;          button.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.guided.chapter.open&amp;#x27;, {&#10;            index: index + 1,&#10;            total: views.length,&#10;            label: view.label,&#10;            count: view.focus.length&#10;          }));&#10;          button.title = view.label + &amp;#x27; — &amp;#x27; + (view.note || viewerText(&amp;#x27;viewer.guided.chapter.selectedNodes&amp;#x27;, { count: view.focus.length }));&#10;          var position = document.createElement(&amp;#x27;span&amp;#x27;);&#10;          position.className = &amp;#x27;guided-view-chapter-index&amp;#x27;;&#10;          position.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          position.textContent = (index + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (index + 1);&#10;          var title = document.createElement(&amp;#x27;span&amp;#x27;);&#10;          title.className = &amp;#x27;guided-view-chapter-title&amp;#x27;;&#10;          title.textContent = view.label;&#10;          var stops = document.createElement(&amp;#x27;em&amp;#x27;);&#10;          stops.className = &amp;#x27;guided-view-chapter-count&amp;#x27;;&#10;          stops.textContent = viewerCount(&amp;#x27;viewer.guided.chapter.stop&amp;#x27;, view.focus.length);&#10;          var delta = document.createElement(&amp;#x27;span&amp;#x27;);&#10;          delta.className = &amp;#x27;guided-view-chapter-delta&amp;#x27;;&#10;          delta.hidden = true;&#10;          delta.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          [&amp;#x27;stay&amp;#x27;, &amp;#x27;enter&amp;#x27;, &amp;#x27;leave&amp;#x27;].forEach(function (kind) {&#10;            var value = document.createElement(&amp;#x27;span&amp;#x27;);&#10;            value.setAttribute(&amp;#x27;data-delta-kind&amp;#x27;, kind);&#10;            delta.appendChild(value);&#10;          });&#10;          button.appendChild(position);&#10;          button.appendChild(title);&#10;          button.appendChild(stops);&#10;          button.appendChild(delta);&#10;          item.appendChild(button);&#10;          chapterList.appendChild(item);&#10;          chapterButtons.push(button);&#10;        });&#10;      }&#10;&#10;      function syncChapterIndex() {&#10;        chapterButtons.forEach(function (button, index) {&#10;          var current = index === activeIndex;&#10;          var stops = button.querySelector(&amp;#x27;.guided-view-chapter-count&amp;#x27;);&#10;          var deltaLabel = button.querySelector(&amp;#x27;.guided-view-chapter-delta&amp;#x27;);&#10;          var position = activeIndex &amp;lt; 0 ? &amp;#x27;available&amp;#x27; : (current ? &amp;#x27;current&amp;#x27; : (index &amp;lt; activeIndex ? &amp;#x27;before&amp;#x27; : &amp;#x27;after&amp;#x27;));&#10;          button.setAttribute(&amp;#x27;data-chapter-position&amp;#x27;, position);&#10;          button.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, current ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;          button.setAttribute(&amp;#x27;tabindex&amp;#x27;, current || (activeIndex &amp;lt; 0 &amp;amp;&amp;amp; index === 0) ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;          if (current) {&#10;            stops.hidden = false;&#10;            deltaLabel.hidden = true;&#10;            button.removeAttribute(&amp;#x27;data-chapter-delta&amp;#x27;);&#10;            button.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.guided.chapter.current&amp;#x27;, {&#10;              index: index + 1,&#10;              total: views.length,&#10;              label: views[index].label,&#10;              count: views[index].focus.length&#10;            }));&#10;            button.title = viewerText(&amp;#x27;viewer.guided.chapter.current.title&amp;#x27;, {&#10;              label: views[index].label,&#10;              count: views[index].focus.length&#10;            });&#10;          } else {&#10;            var delta = chapterDelta(activeIndex &amp;gt;= 0 ? views[activeIndex] : null, views[index]);&#10;            var compact = &amp;#x27;=&amp;#x27; + delta.stay.length + &amp;#x27; +&amp;#x27; + delta.enter.length + &amp;#x27; \u2212&amp;#x27; + delta.leave.length;&#10;            var expanded = viewerText(&amp;#x27;viewer.guided.chapter.delta.expanded&amp;#x27;, {&#10;              stay: delta.stay.length,&#10;              enter: delta.enter.length,&#10;              leave: delta.leave.length&#10;            });&#10;            stops.hidden = true;&#10;            deltaLabel.hidden = false;&#10;            deltaLabel.querySelector(&amp;#x27;[data-delta-kind=&amp;quot;stay&amp;quot;]&amp;#x27;).textContent = &amp;#x27;=&amp;#x27; + delta.stay.length;&#10;            deltaLabel.querySelector(&amp;#x27;[data-delta-kind=&amp;quot;enter&amp;quot;]&amp;#x27;).textContent = &amp;#x27;+&amp;#x27; + delta.enter.length;&#10;            deltaLabel.querySelector(&amp;#x27;[data-delta-kind=&amp;quot;leave&amp;quot;]&amp;#x27;).textContent = &amp;#x27;\u2212&amp;#x27; + delta.leave.length;&#10;            button.setAttribute(&amp;#x27;data-chapter-delta&amp;#x27;, compact);&#10;            button.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.guided.chapter.delta.aria&amp;#x27;, {&#10;              index: index + 1,&#10;              total: views.length,&#10;              label: views[index].label,&#10;              delta: expanded&#10;            }));&#10;            button.title = viewerText(&amp;#x27;viewer.guided.chapter.delta.title&amp;#x27;, {&#10;              label: views[index].label,&#10;              delta: compact&#10;            });&#10;          }&#10;          if (current) button.setAttribute(&amp;#x27;aria-current&amp;#x27;, &amp;#x27;step&amp;#x27;);&#10;          else button.removeAttribute(&amp;#x27;aria-current&amp;#x27;);&#10;          if (button.parentElement) button.parentElement.setAttribute(&amp;#x27;data-chapter-position&amp;#x27;, position);&#10;        });&#10;        if (activeIndex &amp;gt;= 0) centerChapterButton(chapterButtons[activeIndex]);&#10;      }&#10;&#10;      function chapterPreviewBlocked() {&#10;        if (document.hidden || playing || currentHandoff) return true;&#10;        if (document.documentElement.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return true;&#10;        if (window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;print&amp;#x27;).matches) return true;&#10;        if (svg.hasAttribute(&amp;#x27;data-route-picking&amp;#x27;) || svg.hasAttribute(&amp;#x27;data-route-active&amp;#x27;)) return true;&#10;        if (svg.hasAttribute(&amp;#x27;data-lens-active&amp;#x27;) || svg.hasAttribute(&amp;#x27;data-legend-preview-active&amp;#x27;)) return true;&#10;        if (svg.hasAttribute(&amp;#x27;data-relationship-preview-active&amp;#x27;) || svg.hasAttribute(&amp;#x27;data-intent-trace-active&amp;#x27;)) return true;&#10;        return activeIndex &amp;lt; 0 &amp;amp;&amp;amp; svg.hasAttribute(&amp;#x27;data-focus-active&amp;#x27;);&#10;      }&#10;&#10;      function clearChapterPreviewPresentation() {&#10;        svg.removeAttribute(&amp;#x27;data-chapter-preview&amp;#x27;);&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-chapter-preview-role]&amp;#x27;), function (node) {&#10;          node.removeAttribute(&amp;#x27;data-chapter-preview-role&amp;#x27;);&#10;        });&#10;        chapterButtons.forEach(function (button) { button.removeAttribute(&amp;#x27;data-preview-active&amp;#x27;); });&#10;        activePreviewIndex = -1;&#10;        if (previewOwnerToken &amp;amp;&amp;amp; Archify.motionGovernor) {&#10;          var token = previewOwnerToken;&#10;          previewOwnerToken = 0;&#10;          Archify.motionGovernor.release(token);&#10;        }&#10;      }&#10;&#10;      function clearChapterPreview(options) {&#10;        options = options || {};&#10;        previewGeneration += 1;&#10;        if (options.clearIntents !== false) {&#10;          pointerPreviewIntent = null;&#10;          focusPreviewIntent = null;&#10;        }&#10;        clearChapterPreviewPresentation();&#10;        return true;&#10;      }&#10;&#10;      function winningChapterPreviewIntent() {&#10;        return [pointerPreviewIntent, focusPreviewIntent].filter(function (intent) {&#10;          return intent &amp;amp;&amp;amp; intent.index &amp;gt;= 0 &amp;amp;&amp;amp; intent.index &amp;lt; views.length &amp;amp;&amp;amp; intent.index !== activeIndex;&#10;        }).sort(function (left, right) { return right.generation - left.generation; })[0] || null;&#10;      }&#10;&#10;      function showChapterPreview(index) {&#10;        if (index &amp;lt; 0 || index &amp;gt;= views.length || index === activeIndex || chapterPreviewBlocked()) {&#10;          clearChapterPreviewPresentation();&#10;          return false;&#10;        }&#10;        if (activePreviewIndex === index &amp;amp;&amp;amp; svg.getAttribute(&amp;#x27;data-chapter-preview&amp;#x27;) === views[index].id) return true;&#10;        clearChapterPreviewPresentation();&#10;        var delta = chapterDelta(activeIndex &amp;gt;= 0 ? views[activeIndex] : null, views[index]);&#10;        var roles = {};&#10;        delta.stay.forEach(function (id) { roles[id] = &amp;#x27;stay&amp;#x27;; });&#10;        delta.enter.forEach(function (id) { roles[id] = &amp;#x27;enter&amp;#x27;; });&#10;        delta.leave.forEach(function (id) { roles[id] = &amp;#x27;leave&amp;#x27;; });&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;), function (node) {&#10;          var role = roles[node.getAttribute(&amp;#x27;data-node-id&amp;#x27;)];&#10;          if (role) node.setAttribute(&amp;#x27;data-chapter-preview-role&amp;#x27;, role);&#10;        });&#10;        svg.setAttribute(&amp;#x27;data-chapter-preview&amp;#x27;, views[index].id);&#10;        chapterButtons[index].setAttribute(&amp;#x27;data-preview-active&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        activePreviewIndex = index;&#10;        if (Archify.motionGovernor &amp;amp;&amp;amp; Archify.motionGovernor.capable) {&#10;          previewOwnerToken = Archify.motionGovernor.claim(&amp;#x27;chapter-preview&amp;#x27;, function () {&#10;            previewOwnerToken = 0;&#10;            clearChapterPreviewPresentation();&#10;          });&#10;        }&#10;        return true;&#10;      }&#10;&#10;      function syncChapterPreview() {&#10;        var intent = winningChapterPreviewIntent();&#10;        if (!intent || chapterPreviewBlocked()) {&#10;          clearChapterPreviewPresentation();&#10;          return false;&#10;        }&#10;        return showChapterPreview(intent.index);&#10;      }&#10;&#10;      function setChapterPreviewIntent(source, index) {&#10;        var intent = { index: index, generation: ++previewGeneration };&#10;        if (source === &amp;#x27;pointer&amp;#x27;) pointerPreviewIntent = intent;&#10;        else focusPreviewIntent = intent;&#10;        if (playing) pausePlayback();&#10;        return syncChapterPreview();&#10;      }&#10;&#10;      function clearChapterPreviewIntent(source, index) {&#10;        var intent = source === &amp;#x27;pointer&amp;#x27; ? pointerPreviewIntent : focusPreviewIntent;&#10;        if (intent &amp;amp;&amp;amp; (typeof index !== &amp;#x27;number&amp;#x27; || intent.index === index)) {&#10;          if (source === &amp;#x27;pointer&amp;#x27;) pointerPreviewIntent = null;&#10;          else focusPreviewIntent = null;&#10;          previewGeneration += 1;&#10;        }&#10;        return syncChapterPreview();&#10;      }&#10;&#10;      function hoverCapable() {&#10;        return !!(window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;(hover: hover)&amp;#x27;).matches);&#10;      }&#10;&#10;      function sharePlaybackRequested() {&#10;        try { return new URLSearchParams(location.search).get(&amp;#x27;play&amp;#x27;) === &amp;#x27;1&amp;#x27;; }&#10;        catch (_) { return false; }&#10;      }&#10;&#10;      autoplayPending = sharePlaybackRequested();&#10;      if (autoplayPending) {&#10;        document.documentElement.setAttribute(&amp;#x27;data-share-playback&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        setAutoplayState(&amp;#x27;pending&amp;#x27;);&#10;      }&#10;&#10;      function setAutoplayState(state) {&#10;        if (state) panel.setAttribute(&amp;#x27;data-autoplay&amp;#x27;, state);&#10;        else panel.removeAttribute(&amp;#x27;data-autoplay&amp;#x27;);&#10;        renderShareCue();&#10;      }&#10;&#10;      function shareCueStatus(state) {&#10;        return {&#10;          pending: viewerText(&amp;#x27;viewer.guided.state.ready&amp;#x27;),&#10;          playing: viewerText(&amp;#x27;viewer.guided.state.playing&amp;#x27;),&#10;          complete: viewerText(&amp;#x27;viewer.guided.state.settled&amp;#x27;),&#10;          interrupted: viewerText(&amp;#x27;viewer.guided.state.paused&amp;#x27;),&#10;          pinned: viewerText(&amp;#x27;viewer.guided.state.pinned&amp;#x27;),&#10;          &amp;#x27;reduced-motion&amp;#x27;: viewerText(&amp;#x27;viewer.guided.state.still&amp;#x27;)&#10;        }[state] || viewerText(&amp;#x27;viewer.guided.state.ready&amp;#x27;);&#10;      }&#10;&#10;      function shareCueBeatCopy(state, view, stops) {&#10;        var total = stops.length;&#10;        var activeStop = storyBeatIndex &amp;gt;= 0 ? stops[storyBeatIndex] : null;&#10;        if ((state === &amp;#x27;playing&amp;#x27; || state === &amp;#x27;interrupted&amp;#x27;) &amp;amp;&amp;amp; activeStop) {&#10;          return viewerText(&amp;#x27;viewer.guided.share.step&amp;#x27;, {&#10;            index: (storyBeatIndex + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (storyBeatIndex + 1),&#10;            total: (total &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + total,&#10;            label: activeStop.textContent&#10;          });&#10;        }&#10;        if (state === &amp;#x27;pinned&amp;#x27; &amp;amp;&amp;amp; activeStop) {&#10;          return storyBeatCopy(storySteps[storyBeatIndex], total);&#10;        }&#10;        if (state === &amp;#x27;reduced-motion&amp;#x27; &amp;amp;&amp;amp; activeStop &amp;amp;&amp;amp; hashBeatMatchesCurrent()) {&#10;          return viewerText(&amp;#x27;viewer.guided.share.staticMoment&amp;#x27;, {&#10;            step: viewerText(&amp;#x27;viewer.guided.share.step&amp;#x27;, {&#10;              index: (storyBeatIndex + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (storyBeatIndex + 1),&#10;              total: (total &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + total,&#10;              label: activeStop.textContent&#10;            })&#10;          });&#10;        }&#10;        if (state === &amp;#x27;complete&amp;#x27;) return viewerText(&amp;#x27;viewer.guided.share.complete&amp;#x27;, {&#10;          count: total,&#10;          note: view.note || viewerText(&amp;#x27;viewer.guided.share.settled&amp;#x27;)&#10;        });&#10;        if (state === &amp;#x27;reduced-motion&amp;#x27;) return viewerText(&amp;#x27;viewer.guided.share.staticPath&amp;#x27;, { count: total });&#10;        if (state === &amp;#x27;pending&amp;#x27;) return viewerText(&amp;#x27;viewer.guided.share.ready&amp;#x27;, { count: total });&#10;        return view.note || viewerText(&amp;#x27;viewer.guided.chapter.selectedNodes&amp;#x27;, { count: view.focus.length });&#10;      }&#10;&#10;      function renderShareCue() {&#10;        if (!shareCue) return;&#10;        var view = activeIndex &amp;gt;= 0 ? views[activeIndex] : null;&#10;        var shareMode = document.documentElement.getAttribute(&amp;#x27;data-share-playback&amp;#x27;) === &amp;#x27;true&amp;#x27;;&#10;        var embedMode = document.documentElement.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;;&#10;        var pinnedMode = !shareMode &amp;amp;&amp;amp; embedMode &amp;amp;&amp;amp; hashBeatMatchesCurrent();&#10;        if (pinnedMode) document.documentElement.setAttribute(&amp;#x27;data-share-moment&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        else document.documentElement.removeAttribute(&amp;#x27;data-share-moment&amp;#x27;);&#10;        shareCue.hidden = !(embedMode &amp;amp;&amp;amp; view &amp;amp;&amp;amp; (shareMode || pinnedMode));&#10;        if (shareCue.hidden) return;&#10;        var state = pinnedMode ? &amp;#x27;pinned&amp;#x27; : (panel.getAttribute(&amp;#x27;data-autoplay&amp;#x27;) || &amp;#x27;pending&amp;#x27;);&#10;        var stops = Array.prototype.slice.call(trail.querySelectorAll(&amp;#x27;[data-story-node]&amp;#x27;));&#10;        var route = stops.map(function (stop, index) {&#10;          if (index === 0) return stop.textContent;&#10;          var kind = stop.getAttribute(&amp;#x27;data-story-link&amp;#x27;);&#10;          var separator = kind === &amp;#x27;forward&amp;#x27; ? &amp;#x27;\u2192&amp;#x27; : (kind === &amp;#x27;reverse&amp;#x27; ? &amp;#x27;\u2190&amp;#x27; : (kind === &amp;#x27;multiple&amp;#x27; ? &amp;#x27;\u21c4&amp;#x27; : &amp;#x27;\u00b7&amp;#x27;));&#10;          return separator + &amp;#x27; &amp;#x27; + stop.textContent;&#10;        }).join(&amp;#x27; &amp;#x27;);&#10;        var beatCopy = shareCueBeatCopy(state, view, stops);&#10;        shareCue.setAttribute(&amp;#x27;data-state&amp;#x27;, state);&#10;        shareCue.setAttribute(&amp;#x27;aria-live&amp;#x27;, state === &amp;#x27;playing&amp;#x27; ? &amp;#x27;off&amp;#x27; : &amp;#x27;polite&amp;#x27;);&#10;        shareCueState.textContent = shareCueStatus(state);&#10;        shareCueCount.textContent = viewerText(&amp;#x27;viewer.guided.share.chapter&amp;#x27;, {&#10;          index: (activeIndex + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (activeIndex + 1),&#10;          total: (views.length &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + views.length&#10;        });&#10;        shareCueLabel.textContent = view.label;&#10;        shareCueNote.textContent = beatCopy;&#10;        shareCueRoute.textContent = route;&#10;        shareCue.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.guided.share.aria&amp;#x27;, {&#10;          state: shareCueStatus(state),&#10;          index: activeIndex + 1,&#10;          total: views.length,&#10;          label: view.label,&#10;          beat: beatCopy,&#10;          route: route&#10;        }));&#10;      }&#10;&#10;      function setShareCueProgress(fraction) {&#10;        if (!shareCueProgress) return;&#10;        shareCueProgress.style.animation = &amp;#x27;none&amp;#x27;;&#10;        shareCueProgress.style.setProperty(&amp;#x27;--guided-progress-start&amp;#x27;, String(Math.max(0, Math.min(1, fraction))));&#10;        shareCueProgress.style.transform = &amp;#x27;scaleX(&amp;#x27; + Math.max(0, Math.min(1, fraction)) + &amp;#x27;)&amp;#x27;;&#10;      }&#10;&#10;      function startShareCueProgress(fraction, duration) {&#10;        if (!shareCueProgress) return;&#10;        setShareCueProgress(fraction || 0);&#10;        void shareCueProgress.offsetWidth;&#10;        shareCueProgress.style.animation = &amp;#x27;archify-guided-progress &amp;#x27; + Math.max(1, duration || VIEW_INTERVAL_MS) + &amp;#x27;ms linear forwards&amp;#x27;;&#10;      }&#10;&#10;      function storyNodeLabel(node, fallback) {&#10;        if (!node) return fallback;&#10;        return node.getAttribute(&amp;#x27;data-node-label&amp;#x27;) ||&#10;          (node.getAttribute(&amp;#x27;aria-label&amp;#x27;) || fallback).replace(/^Focus\s+/, &amp;#x27;&amp;#x27;);&#10;      }&#10;&#10;      function storyEdgeKey(edge) {&#10;        return edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) || (&#10;          edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;) + &amp;#x27;\u0000&amp;#x27; +&#10;          edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;) + &amp;#x27;\u0000&amp;#x27; +&#10;          (edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;)&#10;        );&#10;      }&#10;&#10;      function uniqueStoryEdges(edgeList) {&#10;        var positions = {};&#10;        var unique = [];&#10;        edgeList.forEach(function (edge) {&#10;          var key = storyEdgeKey(edge);&#10;          if (!Object.prototype.hasOwnProperty.call(positions, key)) {&#10;            positions[key] = unique.length;&#10;            unique.push(edge);&#10;            return;&#10;          }&#10;          var index = positions[key];&#10;          if (!storyGeometry(unique[index]).length &amp;amp;&amp;amp; storyGeometry(edge).length) unique[index] = edge;&#10;        });&#10;        return unique;&#10;      }&#10;&#10;      function storyStep(view, index, edgeList, byId) {&#10;        var id = view.focus[index];&#10;        var node = byId[id];&#10;        var previousId = index &amp;gt; 0 ? view.focus[index - 1] : &amp;#x27;&amp;#x27;;&#10;        var forward = [];&#10;        var reverse = [];&#10;        if (previousId) {&#10;          edgeList.forEach(function (edge) {&#10;            var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;            var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;            if (from === previousId &amp;amp;&amp;amp; to === id) forward.push(edge);&#10;            else if (from === id &amp;amp;&amp;amp; to === previousId) reverse.push(edge);&#10;          });&#10;        }&#10;        forward = uniqueStoryEdges(forward);&#10;        reverse = uniqueStoryEdges(reverse);&#10;        var edges = forward.concat(reverse).sort(function (left, right) {&#10;          return edgeList.indexOf(left) - edgeList.indexOf(right);&#10;        });&#10;        var relation = index === 0 ? &amp;#x27;start&amp;#x27; : (!edges.length ? &amp;#x27;group&amp;#x27; : (&#10;          edges.length === 1 &amp;amp;&amp;amp; forward.length === 1 ? &amp;#x27;forward&amp;#x27; :&#10;          (edges.length === 1 &amp;amp;&amp;amp; reverse.length === 1 ? &amp;#x27;reverse&amp;#x27; : &amp;#x27;multiple&amp;#x27;)&#10;        ));&#10;        return {&#10;          index: index,&#10;          nodeId: id,&#10;          nodeLabel: storyNodeLabel(byId[id], id),&#10;          previousId: previousId,&#10;          previousLabel: previousId ? storyNodeLabel(byId[previousId], previousId) : &amp;#x27;&amp;#x27;,&#10;          relation: relation,&#10;          edges: edges,&#10;          edgeKeys: edges.map(storyEdgeKey),&#10;          edgeLabels: edges.map(function (edge) { return edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;; }).filter(function (value, edgeIndex, values) {&#10;            return value &amp;amp;&amp;amp; values.indexOf(value) === edgeIndex;&#10;          }),&#10;          responsibility: node ? (node.getAttribute(&amp;#x27;data-node-sublabel&amp;#x27;) || &amp;#x27;&amp;#x27;) : &amp;#x27;&amp;#x27;,&#10;          context: node ? (node.getAttribute(&amp;#x27;data-node-context&amp;#x27;) || &amp;#x27;&amp;#x27;) : &amp;#x27;&amp;#x27;&#10;        };&#10;      }&#10;&#10;      function storyBeatCopy(step, total) {&#10;        if (!step) return &amp;#x27;&amp;#x27;;&#10;        var position = (step.index + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (step.index + 1);&#10;        var countValue = (total &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + total;&#10;        if (step.relation === &amp;#x27;start&amp;#x27;) return viewerText(&amp;#x27;viewer.guided.beat.start&amp;#x27;, { index: position, total: countValue, label: step.nodeLabel });&#10;        if (step.relation === &amp;#x27;forward&amp;#x27;) return viewerText(&amp;#x27;viewer.guided.beat.forward&amp;#x27;, { index: position, total: countValue, from: step.previousLabel, to: step.nodeLabel });&#10;        if (step.relation === &amp;#x27;reverse&amp;#x27;) return viewerText(&amp;#x27;viewer.guided.beat.reverse&amp;#x27;, { index: position, total: countValue, from: step.nodeLabel, to: step.previousLabel });&#10;        if (step.relation === &amp;#x27;multiple&amp;#x27;) return viewerText(&amp;#x27;viewer.guided.beat.multiple&amp;#x27;, { index: position, total: countValue, from: step.previousLabel, to: step.nodeLabel, count: step.edges.length });&#10;        return viewerText(&amp;#x27;viewer.guided.beat.group&amp;#x27;, { index: position, total: countValue, from: step.previousLabel, to: step.nodeLabel });&#10;      }&#10;&#10;      function storyBeatAria(step, total) {&#10;        var prefix = viewerText(&amp;#x27;viewer.guided.beat.aria.prefix&amp;#x27;, { index: step.index + 1, total: total, label: step.nodeLabel });&#10;        if (step.relation === &amp;#x27;start&amp;#x27;) return prefix + viewerText(&amp;#x27;viewer.guided.beat.aria.start&amp;#x27;);&#10;        if (step.relation === &amp;#x27;forward&amp;#x27;) return prefix + viewerText(&amp;#x27;viewer.guided.beat.aria.forward&amp;#x27;, { from: step.previousLabel });&#10;        if (step.relation === &amp;#x27;reverse&amp;#x27;) return prefix + viewerText(&amp;#x27;viewer.guided.beat.aria.reverse&amp;#x27;, { from: step.previousLabel, to: step.nodeLabel });&#10;        if (step.relation === &amp;#x27;multiple&amp;#x27;) return prefix + viewerText(&amp;#x27;viewer.guided.beat.aria.multiple&amp;#x27;, { from: step.previousLabel, count: step.edges.length });&#10;        return prefix + viewerText(&amp;#x27;viewer.guided.beat.aria.group&amp;#x27;, { from: step.previousLabel });&#10;      }&#10;&#10;      function storyCaptionRouteCopy(step) {&#10;        if (step.relation === &amp;#x27;start&amp;#x27;) return step.nodeLabel + &amp;#x27; · &amp;#x27; + viewerText(&amp;#x27;viewer.guided.caption.start&amp;#x27;);&#10;        if (step.relation === &amp;#x27;reverse&amp;#x27;) return step.previousLabel + &amp;#x27; ← &amp;#x27; + step.nodeLabel;&#10;        if (step.relation === &amp;#x27;multiple&amp;#x27;) return step.previousLabel + &amp;#x27; ⇄ &amp;#x27; + step.nodeLabel;&#10;        if (step.relation === &amp;#x27;group&amp;#x27;) return step.previousLabel + &amp;#x27; · &amp;#x27; + step.nodeLabel;&#10;        return step.previousLabel + &amp;#x27; → &amp;#x27; + step.nodeLabel;&#10;      }&#10;&#10;      function storyCaptionDetailCopy(step) {&#10;        var facts = [];&#10;        if (step.relation === &amp;#x27;group&amp;#x27;) facts.push(viewerText(&amp;#x27;viewer.guided.caption.grouped&amp;#x27;));&#10;        else if (step.edgeLabels.length) facts.push(step.edgeLabels.slice(0, 3).join(&amp;#x27; + &amp;#x27;) + (step.edgeLabels.length &amp;gt; 3 ? viewerText(&amp;#x27;viewer.guided.caption.more&amp;#x27;, { count: step.edgeLabels.length - 3 }) : &amp;#x27;&amp;#x27;));&#10;        else if (step.relation === &amp;#x27;reverse&amp;#x27;) facts.push(viewerText(&amp;#x27;viewer.guided.caption.reverse&amp;#x27;));&#10;        else if (step.relation === &amp;#x27;multiple&amp;#x27;) facts.push(viewerText(&amp;#x27;viewer.guided.caption.relationships&amp;#x27;, { count: step.edges.length }));&#10;        else if (step.relation !== &amp;#x27;start&amp;#x27;) facts.push(viewerText(&amp;#x27;viewer.guided.caption.relationship&amp;#x27;));&#10;        if (step.relation === &amp;#x27;reverse&amp;#x27;) facts.push(viewerText(&amp;#x27;viewer.guided.caption.direction&amp;#x27;, { from: step.nodeLabel, to: step.previousLabel }));&#10;        if (step.responsibility) facts.push(step.responsibility);&#10;        if (step.context) facts.push(step.context);&#10;        if (!facts.length) facts.push(viewerText(&amp;#x27;viewer.guided.caption.starting&amp;#x27;));&#10;        return facts.join(&amp;#x27; · &amp;#x27;);&#10;      }&#10;&#10;      function renderStoryCaption(step, total, nextStep) {&#10;        if (!storyCaption) return;&#10;        if (!step) {&#10;          storyCaption.hidden = true;&#10;          storyCaption.removeAttribute(&amp;#x27;data-story-caption&amp;#x27;);&#10;          storyCaptionNext.hidden = true;&#10;          storyCaptionNextLabel.textContent = &amp;#x27;&amp;#x27;;&#10;          return;&#10;        }&#10;        storyCaption.hidden = false;&#10;        storyCaption.setAttribute(&amp;#x27;data-story-caption&amp;#x27;, step.relation);&#10;        storyCaption.setAttribute(&amp;#x27;aria-live&amp;#x27;, playing ? &amp;#x27;off&amp;#x27; : &amp;#x27;polite&amp;#x27;);&#10;        storyCaptionIndex.textContent = (step.index + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (step.index + 1) + &amp;#x27; / &amp;#x27; + (total &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + total;&#10;        storyCaptionRoute.textContent = storyCaptionRouteCopy(step);&#10;        storyCaptionDetail.textContent = storyCaptionDetailCopy(step);&#10;        storyCaptionNext.hidden = !nextStep;&#10;        storyCaptionNextLabel.textContent = nextStep&#10;          ? ((nextStep.index + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (nextStep.index + 1) + &amp;#x27; · &amp;#x27; + nextStep.nodeLabel)&#10;          : &amp;#x27;&amp;#x27;;&#10;        storyCaption.style.animation = &amp;#x27;none&amp;#x27;;&#10;        void storyCaption.offsetWidth;&#10;        storyCaption.style.removeProperty(&amp;#x27;animation&amp;#x27;);&#10;      }&#10;&#10;      function storyMomentLink() {&#10;        var view = activeIndex &amp;gt;= 0 ? views[activeIndex] : null;&#10;        var step = storyBeatIndex &amp;gt;= 0 ? storySteps[storyBeatIndex] : null;&#10;        if (!view || !step) return &amp;#x27;&amp;#x27;;&#10;        var url = new URL(location.href);&#10;        url.searchParams.delete(&amp;#x27;play&amp;#x27;);&#10;        url.hash = &amp;#x27;view=&amp;#x27; + encodeURIComponent(view.id) + &amp;#x27;&amp;amp;beat=&amp;#x27; + encodeURIComponent(step.nodeId);&#10;        return url.href;&#10;      }&#10;&#10;      function fallbackCopyStoryMoment(value) {&#10;        var field = document.createElement(&amp;#x27;textarea&amp;#x27;);&#10;        field.value = value;&#10;        field.setAttribute(&amp;#x27;readonly&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        field.style.position = &amp;#x27;fixed&amp;#x27;;&#10;        field.style.opacity = &amp;#x27;0&amp;#x27;;&#10;        document.body.appendChild(field);&#10;        field.select();&#10;        var copied = false;&#10;        try { copied = document.execCommand(&amp;#x27;copy&amp;#x27;); } catch (_) {}&#10;        field.remove();&#10;        return copied;&#10;      }&#10;&#10;      function resetBeatLinkFeedback() {&#10;        if (beatLinkFeedbackTimer) clearTimeout(beatLinkFeedbackTimer);&#10;        beatLinkFeedbackTimer = null;&#10;        beatLink.removeAttribute(&amp;#x27;data-copy-state&amp;#x27;);&#10;        beatLinkLabel.textContent = viewerText(&amp;#x27;viewer.guided.copyMoment&amp;#x27;);&#10;      }&#10;&#10;      function syncBeatLink() {&#10;        var step = storyBeatIndex &amp;gt;= 0 ? storySteps[storyBeatIndex] : null;&#10;        var available = !!(activeIndex &amp;gt;= 0 &amp;amp;&amp;amp; step &amp;amp;&amp;amp; !currentHandoff);&#10;        beatLink.disabled = !available;&#10;        if (!beatLink.hasAttribute(&amp;#x27;data-copy-state&amp;#x27;)) beatLinkLabel.textContent = viewerText(&amp;#x27;viewer.guided.copyMoment&amp;#x27;);&#10;        var description = available&#10;          ? viewerText(&amp;#x27;viewer.guided.beatLink&amp;#x27;, { index: step.index + 1, total: storySteps.length, label: step.nodeLabel })&#10;          : viewerText(&amp;#x27;viewer.guided.selectBeatLink&amp;#x27;);&#10;        beatLink.setAttribute(&amp;#x27;aria-label&amp;#x27;, description);&#10;        beatLink.title = description;&#10;      }&#10;&#10;      function setBeatLinkFeedback(copied) {&#10;        resetBeatLinkFeedback();&#10;        beatLink.setAttribute(&amp;#x27;data-copy-state&amp;#x27;, copied ? &amp;#x27;copied&amp;#x27; : &amp;#x27;failed&amp;#x27;);&#10;        beatLinkLabel.textContent = viewerText(copied ? &amp;#x27;viewer.guided.copied&amp;#x27; : &amp;#x27;viewer.guided.copyFailed&amp;#x27;);&#10;        beatLink.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(copied ? &amp;#x27;viewer.guided.momentCopied&amp;#x27; : &amp;#x27;viewer.guided.momentCopyFailed&amp;#x27;));&#10;        beatLinkFeedbackTimer = setTimeout(function () {&#10;          resetBeatLinkFeedback();&#10;          syncBeatLink();&#10;        }, 1600);&#10;      }&#10;&#10;      function copyStoryMomentLink() {&#10;        if (playing) pausePlayback();&#10;        var value = storyMomentLink();&#10;        if (!value) return Promise.resolve(false);&#10;        var copy = navigator.clipboard &amp;amp;&amp;amp; typeof navigator.clipboard.writeText === &amp;#x27;function&amp;#x27;&#10;          ? navigator.clipboard.writeText(value).then(function () { return true; }).catch(function () { return fallbackCopyStoryMoment(value); })&#10;          : Promise.resolve(fallbackCopyStoryMoment(value));&#10;        return copy.then(function (copied) {&#10;          setBeatLinkFeedback(copied);&#10;          return copied;&#10;        });&#10;      }&#10;&#10;      function hashBeatMatchesCurrent() {&#10;        var view = activeIndex &amp;gt;= 0 ? views[activeIndex] : null;&#10;        var step = storyBeatIndex &amp;gt;= 0 ? storySteps[storyBeatIndex] : null;&#10;        if (!view || !step) return false;&#10;        try {&#10;          var params = new URLSearchParams(location.hash.replace(/^#/, &amp;#x27;&amp;#x27;));&#10;          return params.get(&amp;#x27;view&amp;#x27;) === view.id &amp;amp;&amp;amp; params.get(&amp;#x27;beat&amp;#x27;) === step.nodeId;&#10;        } catch (_) { return false; }&#10;      }&#10;&#10;      function storyMotionAllowed() {&#10;        if (document.hidden || reducedMotion()) return false;&#10;        if (document.documentElement.getAttribute(&amp;#x27;data-motion&amp;#x27;) !== &amp;#x27;live&amp;#x27;) return false;&#10;        if (document.documentElement.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27; &amp;amp;&amp;amp;&#10;            document.documentElement.getAttribute(&amp;#x27;data-share-playback&amp;#x27;) !== &amp;#x27;true&amp;#x27;) return false;&#10;        if (window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;print&amp;#x27;).matches) return false;&#10;        return !(Archify.motionGovernor &amp;amp;&amp;amp; Archify.motionGovernor.isPaused());&#10;      }&#10;&#10;      function storyAutomaticPlaybackAllowed() {&#10;        if (document.hidden || reducedMotion()) return false;&#10;        if (window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;print&amp;#x27;).matches) return false;&#10;        if (Archify.motionGovernor &amp;amp;&amp;amp; Archify.motionGovernor.capable) return !Archify.motionGovernor.isPaused();&#10;        return true;&#10;      }&#10;&#10;      function clearStoryPulse(options) {&#10;        options = options || {};&#10;        storyPulseGeneration += 1;&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;.story-trail-flow[data-story-pulse]&amp;#x27;), function (flow) {&#10;          flow.removeAttribute(&amp;#x27;data-story-pulse&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-story-carrier-overlay]&amp;#x27;), function (overlay) {&#10;          overlay.remove();&#10;        });&#10;        if (storyPulseOwnerToken &amp;amp;&amp;amp; options.release !== false &amp;amp;&amp;amp; Archify.motionGovernor) {&#10;          var token = storyPulseOwnerToken;&#10;          storyPulseOwnerToken = 0;&#10;          Archify.motionGovernor.release(token);&#10;        } else if (options.release === false) storyPulseOwnerToken = 0;&#10;      }&#10;&#10;      function pulseStoryStep(step) {&#10;        clearStoryPulse();&#10;        if (!step || (step.relation !== &amp;#x27;forward&amp;#x27; &amp;amp;&amp;amp; step.relation !== &amp;#x27;reverse&amp;#x27;) || step.edges.length !== 1 || !storyMotionAllowed()) return false;&#10;        var flows = Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;.story-trail-flow[data-story-beat-step=&amp;quot;&amp;#x27; + step.index + &amp;#x27;&amp;quot;]&amp;#x27;));&#10;        if (!flows.length) return false;&#10;        var pulseGeneration = storyPulseGeneration;&#10;        if (Archify.motionGovernor &amp;amp;&amp;amp; Archify.motionGovernor.capable) {&#10;          storyPulseOwnerToken = Archify.motionGovernor.claim(&amp;#x27;story&amp;#x27;, function () {&#10;            clearStoryPulse({ release: false });&#10;          });&#10;        }&#10;        flows.forEach(function (flow) { flow.setAttribute(&amp;#x27;data-story-pulse&amp;#x27;, &amp;#x27;true&amp;#x27;); });&#10;        if (Archify.flowTokens &amp;amp;&amp;amp; typeof Archify.flowTokens.create === &amp;#x27;function&amp;#x27;) {&#10;          var edge = step.edges[0];&#10;          var shapes = storyGeometry(edge);&#10;          var carrier = shapes.length ? Archify.flowTokens.create(edge, shapes[0], {&#10;            className: &amp;#x27;story-flow-token&amp;#x27;,&#10;            duration: &amp;#x27;0.78s&amp;#x27;&#10;          }) : null;&#10;          if (carrier) {&#10;            var carrierOverlay = document.createElementNS(&amp;#x27;http://www.w3.org/2000/svg&amp;#x27;, &amp;#x27;g&amp;#x27;);&#10;            var carrierWrapper = document.createElementNS(&amp;#x27;http://www.w3.org/2000/svg&amp;#x27;, &amp;#x27;g&amp;#x27;);&#10;            carrierOverlay.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;story-carrier-overlay&amp;#x27;);&#10;            carrierOverlay.setAttribute(&amp;#x27;data-story-carrier-overlay&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            carrierOverlay.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;            if (edge.hasAttribute(&amp;#x27;transform&amp;#x27;)) carrierWrapper.setAttribute(&amp;#x27;transform&amp;#x27;, edge.getAttribute(&amp;#x27;transform&amp;#x27;));&#10;            carrier.setAttribute(&amp;#x27;data-story-carrier-token&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            carrier.setAttribute(&amp;#x27;data-story-beat-step&amp;#x27;, String(step.index));&#10;            carrierWrapper.appendChild(carrier);&#10;            carrierOverlay.appendChild(carrierWrapper);&#10;            var firstNode = svg.querySelector(&amp;#x27;[data-node-id]&amp;#x27;);&#10;            while (firstNode &amp;amp;&amp;amp; firstNode.parentNode !== svg) firstNode = firstNode.parentNode;&#10;            if (firstNode) svg.insertBefore(carrierOverlay, firstNode);&#10;            else svg.appendChild(carrierOverlay);&#10;          }&#10;        }&#10;        void flows[0].getBoundingClientRect();&#10;        flows[0].addEventListener(&amp;#x27;animationend&amp;#x27;, function () {&#10;          if (pulseGeneration === storyPulseGeneration) clearStoryPulse();&#10;        }, { once: true });&#10;        return true;&#10;      }&#10;&#10;      function stopStoryBeatTimer(options) {&#10;        options = options || {};&#10;        storyPlaybackGeneration += 1;&#10;        if (storyBeatTimer &amp;amp;&amp;amp; options.preserveElapsed === true &amp;amp;&amp;amp; storyBeatStartedAt) {&#10;          storyBeatElapsedMs = Math.min(storyBeatDwellMs, storyBeatElapsedMs + Math.max(0, Date.now() - storyBeatStartedAt));&#10;        }&#10;        if (storyBeatTimer) clearTimeout(storyBeatTimer);&#10;        storyBeatTimer = null;&#10;        storyBeatStartedAt = 0;&#10;      }&#10;&#10;      function centerStoryStop(stop) {&#10;        if (!stop || !trail) return false;&#10;        var bounds = stop.getBoundingClientRect();&#10;        var viewportLeft = trail.getBoundingClientRect().left + trail.clientLeft;&#10;        var target = Math.max(0, trail.scrollLeft + bounds.left - viewportLeft - (trail.clientWidth - bounds.width) / 2);&#10;        trail.scrollLeft = target;&#10;        return true;&#10;      }&#10;&#10;      function storyBeatDwell(total) {&#10;        return Math.max(STORY_FOLLOW_MIN_DWELL_MS, VIEW_INTERVAL_MS / Math.max(1, total));&#10;      }&#10;&#10;      function clearStoryFollow() {&#10;        storyFollowGeneration += 1;&#10;        svg.removeAttribute(&amp;#x27;data-story-follow&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-story-follow&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-story-follow-node&amp;#x27;);&#10;      }&#10;&#10;      function storyFrameIds(step) {&#10;        if (!step) return [];&#10;        var ids = [];&#10;        if (step.index &amp;gt; 0 &amp;amp;&amp;amp; storySteps[step.index - 1]) ids.push(storySteps[step.index - 1].nodeId);&#10;        ids.push(step.nodeId);&#10;        if (step.index + 1 &amp;lt; storySteps.length) ids.push(storySteps[step.index + 1].nodeId);&#10;        return ids;&#10;      }&#10;&#10;      function followStoryStep(step, options) {&#10;        options = options || {};&#10;        if (!step || document.hidden) return false;&#10;        if (!Archify.view || typeof Archify.view.reveal !== &amp;#x27;function&amp;#x27;) {&#10;          var deferredIndex = step.index;&#10;          var deferredGeneration = ++storyFollowGeneration;&#10;          requestAnimationFrame(function () {&#10;            if (deferredGeneration !== storyFollowGeneration || storyBeatIndex !== deferredIndex) return;&#10;            if (Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) followStoryStep(step, options);&#10;          });&#10;          return true;&#10;        }&#10;        if (window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;print&amp;#x27;).matches) return false;&#10;        var embed = document.documentElement.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;;&#10;        var explicitEmbedPlayback = document.documentElement.getAttribute(&amp;#x27;data-share-playback&amp;#x27;) === &amp;#x27;true&amp;#x27;;&#10;        if (embed &amp;amp;&amp;amp; !explicitEmbedPlayback &amp;amp;&amp;amp; options.linked !== true) return false;&#10;        var ids = storyFrameIds(step);&#10;        var generation = ++storyFollowGeneration;&#10;        svg.setAttribute(&amp;#x27;data-story-follow&amp;#x27;, step.nodeId);&#10;        panel.setAttribute(&amp;#x27;data-story-follow&amp;#x27;, &amp;#x27;moving&amp;#x27;);&#10;        panel.setAttribute(&amp;#x27;data-story-follow-node&amp;#x27;, step.nodeId);&#10;        var receipt = Archify.view.reveal(ids, {&#10;          reason: options.manual === true ? &amp;#x27;story-beat&amp;#x27; : &amp;#x27;story-follow&amp;#x27;,&#10;          padding: 64,&#10;          maxScale: 1.65,&#10;          duration: STORY_FOLLOW_DURATION_MS,&#10;          instant: options.instant === true || reducedMotion() || document.documentElement.getAttribute(&amp;#x27;data-motion&amp;#x27;) !== &amp;#x27;live&amp;#x27;&#10;        });&#10;        if (receipt &amp;amp;&amp;amp; receipt.finished &amp;amp;&amp;amp; typeof receipt.finished.then === &amp;#x27;function&amp;#x27;) {&#10;          receipt.finished.then(function (result) {&#10;            if (generation !== storyFollowGeneration || storyBeatIndex !== step.index) return;&#10;            svg.removeAttribute(&amp;#x27;data-story-follow&amp;#x27;);&#10;            panel.setAttribute(&amp;#x27;data-story-follow&amp;#x27;, result &amp;amp;&amp;amp; result.state === &amp;#x27;complete&amp;#x27; ? &amp;#x27;settled&amp;#x27; : &amp;#x27;interrupted&amp;#x27;);&#10;          });&#10;        } else if (generation === storyFollowGeneration) {&#10;          panel.setAttribute(&amp;#x27;data-story-follow&amp;#x27;, &amp;#x27;settled&amp;#x27;);&#10;        }&#10;        return receipt;&#10;      }&#10;&#10;      function setStoryBeat(index, options) {&#10;        options = options || {};&#10;        var stops = Array.prototype.slice.call(trail.querySelectorAll(&amp;#x27;[data-story-node]&amp;#x27;));&#10;        if (!stops.length) return false;&#10;        resetBeatLinkFeedback();&#10;        storyBeatIndex = Math.max(0, Math.min(stops.length - 1, index));&#10;        var nextStep = storyBeatIndex + 1 &amp;lt; storySteps.length ? storySteps[storyBeatIndex + 1] : null;&#10;        svg.setAttribute(&amp;#x27;data-story-beat&amp;#x27;, (storyBeatIndex + 1) + &amp;#x27;/&amp;#x27; + stops.length);&#10;        panel.setAttribute(&amp;#x27;data-story-beat&amp;#x27;, (storyBeatIndex + 1) + &amp;#x27;/&amp;#x27; + stops.length);&#10;        if (nextStep) {&#10;          svg.setAttribute(&amp;#x27;data-story-next&amp;#x27;, nextStep.nodeId);&#10;          panel.setAttribute(&amp;#x27;data-story-next&amp;#x27;, nextStep.nodeId);&#10;        } else {&#10;          svg.removeAttribute(&amp;#x27;data-story-next&amp;#x27;);&#10;          panel.removeAttribute(&amp;#x27;data-story-next&amp;#x27;);&#10;        }&#10;        function storyBeatState(step) {&#10;          if (step &amp;lt; storyBeatIndex) return &amp;#x27;past&amp;#x27;;&#10;          if (step === storyBeatIndex) return &amp;#x27;active&amp;#x27;;&#10;          if (step === storyBeatIndex + 1) return &amp;#x27;next&amp;#x27;;&#10;          return &amp;#x27;pending&amp;#x27;;&#10;        }&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-story-step]&amp;#x27;), function (node) {&#10;          var step = Number(node.getAttribute(&amp;#x27;data-story-step&amp;#x27;));&#10;          node.setAttribute(&amp;#x27;data-story-beat-state&amp;#x27;, storyBeatState(step));&#10;        });&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-story-beat-step]&amp;#x27;), function (edge) {&#10;          var step = Number(edge.getAttribute(&amp;#x27;data-story-beat-step&amp;#x27;));&#10;          edge.setAttribute(&amp;#x27;data-story-beat-state&amp;#x27;, storyBeatState(step));&#10;        });&#10;        stops.forEach(function (stop, step) {&#10;          stop.setAttribute(&amp;#x27;data-story-beat-state&amp;#x27;, storyBeatState(step));&#10;          if (step === storyBeatIndex) stop.setAttribute(&amp;#x27;aria-current&amp;#x27;, &amp;#x27;step&amp;#x27;);&#10;          else stop.removeAttribute(&amp;#x27;aria-current&amp;#x27;);&#10;        });&#10;        note.setAttribute(&amp;#x27;aria-live&amp;#x27;, &amp;#x27;off&amp;#x27;);&#10;        note.textContent = storyBeatCopy(storySteps[storyBeatIndex], stops.length);&#10;        renderStoryCaption(storySteps[storyBeatIndex], stops.length, nextStep);&#10;        if (options.center === true) centerStoryStop(stops[storyBeatIndex]);&#10;        if (options.pulse === true) pulseStoryStep(storySteps[storyBeatIndex]);&#10;        else clearStoryPulse();&#10;        if (options.follow === true) followStoryStep(storySteps[storyBeatIndex], {&#10;          manual: options.manual === true,&#10;          linked: options.linked === true,&#10;          instant: options.followInstant === true&#10;        });&#10;        renderShareCue();&#10;        syncBeatLink();&#10;        return true;&#10;      }&#10;&#10;      function settleStoryBeats() {&#10;        stopStoryBeatTimer();&#10;        clearStoryPulse();&#10;        clearStoryFollow();&#10;        resetBeatLinkFeedback();&#10;        storyBeatIndex = -1;&#10;        storyBeatElapsedMs = 0;&#10;        storyBeatDwellMs = 0;&#10;        svg.removeAttribute(&amp;#x27;data-story-beat&amp;#x27;);&#10;        svg.removeAttribute(&amp;#x27;data-story-next&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-story-beat&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-story-next&amp;#x27;);&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-story-beat-state]&amp;#x27;), function (el) {&#10;          el.removeAttribute(&amp;#x27;data-story-beat-state&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(trail.querySelectorAll(&amp;#x27;[data-story-beat-state]&amp;#x27;), function (stop) {&#10;          stop.removeAttribute(&amp;#x27;data-story-beat-state&amp;#x27;);&#10;          stop.removeAttribute(&amp;#x27;aria-current&amp;#x27;);&#10;        });&#10;        note.setAttribute(&amp;#x27;aria-live&amp;#x27;, &amp;#x27;polite&amp;#x27;);&#10;        if (activeIndex &amp;gt;= 0) note.textContent = views[activeIndex].note || viewerText(&amp;#x27;viewer.guided.chapter.selectedNodes&amp;#x27;, { count: views[activeIndex].focus.length });&#10;        renderStoryCaption(null, 0);&#10;        renderShareCue();&#10;        syncBeatLink();&#10;      }&#10;&#10;      function clearStoryTrail() {&#10;        stopStoryBeatTimer();&#10;        clearStoryPulse();&#10;        clearStoryFollow();&#10;        resetBeatLinkFeedback();&#10;        storyBeatIndex = -1;&#10;        storyBeatElapsedMs = 0;&#10;        storyBeatDwellMs = 0;&#10;        storySteps = [];&#10;        svg.removeAttribute(&amp;#x27;data-story-active&amp;#x27;);&#10;        svg.removeAttribute(&amp;#x27;data-story-playing&amp;#x27;);&#10;        svg.removeAttribute(&amp;#x27;data-story-beat&amp;#x27;);&#10;        svg.removeAttribute(&amp;#x27;data-story-next&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-story-beat&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-story-next&amp;#x27;);&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-story-overlay]&amp;#x27;), function (overlay) {&#10;          overlay.remove();&#10;        });&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-story-step], [data-story-beat-state]&amp;#x27;), function (node) {&#10;          node.removeAttribute(&amp;#x27;data-story-step&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-story-beat-state&amp;#x27;);&#10;          node.style.removeProperty(&amp;#x27;--story-step&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-edge-from][data-story-beat-step]&amp;#x27;), function (edge) {&#10;          edge.removeAttribute(&amp;#x27;data-story-beat-step&amp;#x27;);&#10;          edge.removeAttribute(&amp;#x27;data-story-beat-state&amp;#x27;);&#10;        });&#10;        trail.textContent = &amp;#x27;&amp;#x27;;&#10;        trail.hidden = true;&#10;        trail.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;        renderStoryCaption(null, 0);&#10;        syncBeatLink();&#10;      }&#10;&#10;      function storyGeometry(edge) {&#10;        if (/^(path|line|polyline)$/i.test(edge.tagName)) return [edge];&#10;        return Array.prototype.slice.call(edge.querySelectorAll(&amp;#x27;path, line, polyline&amp;#x27;));&#10;      }&#10;&#10;      function renderStoryTrail(view) {&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; typeof Archify.semanticLens.clearPreview === &amp;#x27;function&amp;#x27;) Archify.semanticLens.clearPreview();&#10;        clearStoryTrail();&#10;        if (!view) return;&#10;&#10;        var nodeList = Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;));&#10;        var edgeList = Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-edge-from][data-edge-to]&amp;#x27;));&#10;        var byId = {};&#10;        nodeList.forEach(function (node) { byId[node.getAttribute(&amp;#x27;data-node-id&amp;#x27;)] = node; });&#10;        storySteps = view.focus.map(function (_, index) { return storyStep(view, index, edgeList, byId); });&#10;        var labels = [];&#10;        storySteps.forEach(function (step, index) {&#10;          var id = step.nodeId;&#10;          var node = byId[id];&#10;          if (!node) return;&#10;          node.setAttribute(&amp;#x27;data-story-step&amp;#x27;, String(index));&#10;          node.style.setProperty(&amp;#x27;--story-step&amp;#x27;, String(index));&#10;          var nodeLabel = step.nodeLabel;&#10;          labels.push(nodeLabel);&#10;          var stop = document.createElement(&amp;#x27;button&amp;#x27;);&#10;          stop.type = &amp;#x27;button&amp;#x27;;&#10;          stop.className = &amp;#x27;guided-view-stop&amp;#x27;;&#10;          stop.setAttribute(&amp;#x27;data-story-node&amp;#x27;, id);&#10;          stop.setAttribute(&amp;#x27;data-story-index&amp;#x27;, String(index));&#10;          stop.setAttribute(&amp;#x27;data-story-relation&amp;#x27;, step.relation);&#10;          stop.setAttribute(&amp;#x27;data-story-number&amp;#x27;, (index + 1 &amp;lt; 10 ? &amp;#x27;0&amp;#x27; : &amp;#x27;&amp;#x27;) + (index + 1));&#10;          if (index &amp;gt; 0) stop.setAttribute(&amp;#x27;data-story-link&amp;#x27;, step.relation);&#10;          stop.style.setProperty(&amp;#x27;--story-step&amp;#x27;, String(index));&#10;          stop.setAttribute(&amp;#x27;aria-label&amp;#x27;, storyBeatAria(step, storySteps.length));&#10;          stop.title = storyBeatCopy(step, storySteps.length);&#10;          stop.textContent = nodeLabel;&#10;          trail.appendChild(stop);&#10;        });&#10;        trail.hidden = labels.length === 0;&#10;        trail.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.guided.storyTrail&amp;#x27;, { label: view.label, count: labels.length }));&#10;        trail.scrollLeft = 0;&#10;        svg.setAttribute(&amp;#x27;data-story-active&amp;#x27;, view.id);&#10;&#10;        var overlay = document.createElementNS(&amp;#x27;http://www.w3.org/2000/svg&amp;#x27;, &amp;#x27;g&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;story-trail-overlay&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;data-story-overlay&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        var copied = 0;&#10;        storySteps.forEach(function (step) {&#10;          step.edges.forEach(function (edge) {&#10;            var edgeBeat = step.index;&#10;            edge.setAttribute(&amp;#x27;data-story-beat-step&amp;#x27;, String(edgeBeat));&#10;            var wrapper = document.createElementNS(&amp;#x27;http://www.w3.org/2000/svg&amp;#x27;, &amp;#x27;g&amp;#x27;);&#10;            if (edge.hasAttribute(&amp;#x27;transform&amp;#x27;)) wrapper.setAttribute(&amp;#x27;transform&amp;#x27;, edge.getAttribute(&amp;#x27;transform&amp;#x27;));&#10;            storyGeometry(edge).forEach(function (shape) {&#10;              var clone = shape.cloneNode(false);&#10;              clone.removeAttribute(&amp;#x27;id&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;marker-start&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;marker-mid&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;marker-end&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;role&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;data-animate&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;data-edge-key&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;data-edge-id&amp;#x27;);&#10;              clone.removeAttribute(&amp;#x27;data-edge-label&amp;#x27;);&#10;              clone.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;story-trail-flow&amp;#x27;);&#10;              clone.setAttribute(&amp;#x27;data-story-beat-step&amp;#x27;, String(edgeBeat));&#10;              clone.style.setProperty(&amp;#x27;--story-step&amp;#x27;, String(edgeBeat));&#10;              wrapper.appendChild(clone);&#10;              copied += 1;&#10;            });&#10;            if (wrapper.childNodes.length) overlay.appendChild(wrapper);&#10;          });&#10;        });&#10;        if (copied) {&#10;          var firstEdge = edgeList[0];&#10;          if (firstEdge &amp;amp;&amp;amp; firstEdge.parentNode) firstEdge.parentNode.insertBefore(overlay, firstEdge);&#10;          else svg.insertBefore(overlay, svg.firstChild);&#10;        }&#10;      }&#10;&#10;      function syncStoryPlayback() {&#10;        var shouldPlay = playing &amp;amp;&amp;amp; activeIndex &amp;gt;= 0;&#10;        if (shouldPlay &amp;amp;&amp;amp; svg.getAttribute(&amp;#x27;data-story-playing&amp;#x27;) !== &amp;#x27;true&amp;#x27;) svg.setAttribute(&amp;#x27;data-story-playing&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        else if (!shouldPlay &amp;amp;&amp;amp; svg.hasAttribute(&amp;#x27;data-story-playing&amp;#x27;)) svg.removeAttribute(&amp;#x27;data-story-playing&amp;#x27;);&#10;      }&#10;&#10;      function resetProgress(fraction) {&#10;        fraction = Math.max(0, Math.min(1, Number(fraction) || 0));&#10;        progressBar.style.animation = &amp;#x27;none&amp;#x27;;&#10;        progressBar.style.setProperty(&amp;#x27;--guided-progress-start&amp;#x27;, String(fraction));&#10;        progressBar.style.transform = &amp;#x27;scaleX(&amp;#x27; + fraction + &amp;#x27;)&amp;#x27;;&#10;      }&#10;&#10;      function startProgress(fraction, duration) {&#10;        resetProgress(fraction);&#10;        void progressBar.offsetWidth;&#10;        progressBar.style.animation = &amp;#x27;archify-guided-progress &amp;#x27; + Math.max(1, duration || VIEW_INTERVAL_MS) + &amp;#x27;ms linear forwards&amp;#x27;;&#10;      }&#10;&#10;      function currentStoryProgress() {&#10;        var total = storySteps.length;&#10;        if (!total || storyBeatIndex &amp;lt; 0) return 0;&#10;        var elapsed = storyBeatElapsedMs;&#10;        if (playing &amp;amp;&amp;amp; storyBeatTimer &amp;amp;&amp;amp; storyBeatStartedAt) elapsed += Math.max(0, Date.now() - storyBeatStartedAt);&#10;        var dwell = storyBeatDwellMs || storyBeatDwell(total);&#10;        return Math.max(0, Math.min(1, (storyBeatIndex + Math.min(1, elapsed / dwell)) / total));&#10;      }&#10;&#10;      function renderPlayback() {&#10;        var automaticPlaybackAllowed = storyAutomaticPlaybackAllowed();&#10;        panel.setAttribute(&amp;#x27;data-playing&amp;#x27;, playing ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;        syncStoryPlayback();&#10;        play.disabled = !playing &amp;amp;&amp;amp; !automaticPlaybackAllowed;&#10;        play.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, playing ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;        play.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(playing&#10;          ? &amp;#x27;viewer.guided.pause&amp;#x27;&#10;          : !automaticPlaybackAllowed&#10;            ? &amp;#x27;viewer.guided.motionUnavailable&amp;#x27;&#10;            : storyPlaybackComplete&#10;              ? &amp;#x27;viewer.guided.replay&amp;#x27;&#10;              : &amp;#x27;viewer.guided.play&amp;#x27;));&#10;        play.title = viewerText(playing&#10;          ? &amp;#x27;viewer.guided.pause.title&amp;#x27;&#10;          : !automaticPlaybackAllowed&#10;            ? &amp;#x27;viewer.guided.enableMotion&amp;#x27;&#10;            : storyPlaybackComplete&#10;              ? &amp;#x27;viewer.guided.replay.title&amp;#x27;&#10;              : &amp;#x27;viewer.guided.play.title&amp;#x27;);&#10;        playIcon.textContent = playing ? &amp;#x27;\u2016&amp;#x27; : &amp;#x27;\u25b6&amp;#x27;;&#10;        playLabel.textContent = viewerText(playing&#10;          ? &amp;#x27;viewer.guided.pauseStory&amp;#x27;&#10;          : storyPlaybackComplete&#10;            ? &amp;#x27;viewer.guided.replayStory&amp;#x27;&#10;            : &amp;#x27;viewer.guided.playStory&amp;#x27;);&#10;        if (storyCaption &amp;amp;&amp;amp; !storyCaption.hidden) storyCaption.setAttribute(&amp;#x27;aria-live&amp;#x27;, playing ? &amp;#x27;off&amp;#x27; : &amp;#x27;polite&amp;#x27;);&#10;      }&#10;&#10;      function render() {&#10;        var view = views[activeIndex];&#10;        count.textContent = activeIndex &amp;lt; 0 ? &amp;#x27;0 / &amp;#x27; + views.length : (activeIndex + 1) + &amp;#x27; / &amp;#x27; + views.length;&#10;        label.textContent = view ? view.label : viewerText(&amp;#x27;viewer.guided.explore&amp;#x27;);&#10;        note.setAttribute(&amp;#x27;aria-live&amp;#x27;, storyBeatIndex &amp;gt;= 0 ? &amp;#x27;off&amp;#x27; : &amp;#x27;polite&amp;#x27;);&#10;        note.textContent = storyBeatIndex &amp;gt;= 0&#10;          ? storyBeatCopy(storySteps[storyBeatIndex], storySteps.length)&#10;          : (view&#10;            ? (view.note || viewerText(&amp;#x27;viewer.guided.chapter.selectedNodes&amp;#x27;, { count: view.focus.length }))&#10;            : viewerText(&amp;#x27;viewer.guided.intro&amp;#x27;));&#10;        prev.disabled = activeIndex &amp;lt; 0;&#10;        next.disabled = activeIndex &amp;gt;= views.length - 1;&#10;        all.disabled = activeIndex &amp;lt; 0;&#10;        panel.setAttribute(&amp;#x27;data-active-view&amp;#x27;, view ? view.id : &amp;#x27;all&amp;#x27;);&#10;        syncChapterIndex();&#10;        renderShareCue();&#10;        renderPlayback();&#10;        syncBeatLink();&#10;      }&#10;&#10;      function pausePlayback(options) {&#10;        options = options || {};&#10;        var progress = options.complete === true ? 1 : currentStoryProgress();&#10;        if (panel.getAttribute(&amp;#x27;data-autoplay&amp;#x27;) === &amp;#x27;playing&amp;#x27;) {&#10;          setShareCueProgress(progress);&#10;          setAutoplayState(options.complete === true ? &amp;#x27;complete&amp;#x27; : &amp;#x27;interrupted&amp;#x27;);&#10;        }&#10;        stopStoryBeatTimer({ preserveElapsed: options.complete !== true });&#10;        clearStoryPulse();&#10;        clearStoryFollow();&#10;        playing = false;&#10;        storyPlaybackComplete = options.complete === true;&#10;        resetProgress(progress);&#10;        renderPlayback();&#10;        renderShareCue();&#10;      }&#10;&#10;      function finishStoryChapter() {&#10;        if (!playing) return false;&#10;        if (storyPlaybackScope === &amp;#x27;chapter&amp;#x27;) {&#10;          pausePlayback({ complete: true });&#10;          return true;&#10;        }&#10;        if (activeIndex &amp;lt; views.length - 1) {&#10;          var destinationIndex = activeIndex + 1;&#10;          activate(destinationIndex, { playback: true });&#10;          afterHandoff(function () {&#10;            if (!playing || activeIndex !== destinationIndex) return;&#10;            storyBeatElapsedMs = 0;&#10;            setStoryBeat(0, { pulse: true, follow: true });&#10;            scheduleStoryPlayback();&#10;          });&#10;          return true;&#10;        }&#10;        pausePlayback({ complete: true });&#10;        return true;&#10;      }&#10;&#10;      function scheduleStoryPlayback() {&#10;        var total = storySteps.length;&#10;        if (!playing || !total || reducedMotion()) {&#10;          if (playing) pausePlayback();&#10;          return false;&#10;        }&#10;        storyBeatDwellMs = storyBeatDwell(total);&#10;        if (storyBeatIndex &amp;lt; 0) {&#10;          storyBeatElapsedMs = 0;&#10;          setStoryBeat(0, { pulse: true, follow: true });&#10;        }&#10;        storyBeatElapsedMs = Math.max(0, Math.min(storyBeatDwellMs, storyBeatElapsedMs));&#10;        var remainingDwell = Math.max(1, storyBeatDwellMs - storyBeatElapsedMs);&#10;        var progress = (storyBeatIndex + storyBeatElapsedMs / storyBeatDwellMs) / total;&#10;        var remainingChapter = remainingDwell + Math.max(0, total - storyBeatIndex - 1) * storyBeatDwellMs;&#10;        startProgress(progress, remainingChapter);&#10;        if (panel.getAttribute(&amp;#x27;data-autoplay&amp;#x27;) === &amp;#x27;playing&amp;#x27;) startShareCueProgress(progress, remainingChapter);&#10;        var generation = ++storyPlaybackGeneration;&#10;        storyBeatStartedAt = Date.now();&#10;        storyBeatTimer = setTimeout(function () {&#10;          if (!playing || generation !== storyPlaybackGeneration) return;&#10;          storyBeatTimer = null;&#10;          storyBeatStartedAt = 0;&#10;          storyBeatElapsedMs = 0;&#10;          if (storyBeatIndex &amp;lt; total - 1) {&#10;            setStoryBeat(storyBeatIndex + 1, { pulse: true, follow: true });&#10;            scheduleStoryPlayback();&#10;          } else finishStoryChapter();&#10;        }, remainingDwell);&#10;        return true;&#10;      }&#10;&#10;      function startPlayback() {&#10;        if (!storyAutomaticPlaybackAllowed()) {&#10;          renderPlayback();&#10;          return false;&#10;        }&#10;        autoplayPending = false;&#10;        setAutoplayState(null);&#10;        setShareCueProgress(0);&#10;        document.documentElement.removeAttribute(&amp;#x27;data-share-playback&amp;#x27;);&#10;        storyPlaybackScope = &amp;#x27;story&amp;#x27;;&#10;        if (storyPlaybackComplete) showAll({ updateUrl: false });&#10;        storyPlaybackComplete = false;&#10;        if (activeIndex &amp;lt; 0) activate(0, { playback: true });&#10;        playing = true;&#10;        renderPlayback();&#10;        afterHandoff(function () {&#10;          if (!playing) return;&#10;          if (storyBeatIndex &amp;gt;= 0) followStoryStep(storySteps[storyBeatIndex]);&#10;          scheduleStoryPlayback();&#10;        });&#10;        return true;&#10;      }&#10;&#10;      function startCurrentViewPlayback() {&#10;        if (document.hidden) return false;&#10;        autoplayPending = false;&#10;        document.documentElement.setAttribute(&amp;#x27;data-share-playback&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        storyPlaybackScope = &amp;#x27;chapter&amp;#x27;;&#10;        storyPlaybackComplete = false;&#10;        if (activeIndex &amp;lt; 0) activate(0, { playback: true, updateUrl: false });&#10;        if (!storyAutomaticPlaybackAllowed()) {&#10;          var preserveMoment = hashBeatMatchesCurrent();&#10;          setShareCueProgress(preserveMoment &amp;amp;&amp;amp; storySteps.length ? (storyBeatIndex + 1) / storySteps.length : 1);&#10;          setAutoplayState(&amp;#x27;reduced-motion&amp;#x27;);&#10;          playing = false;&#10;          if (preserveMoment) {&#10;            clearStoryPulse();&#10;            renderShareCue();&#10;          } else settleStoryBeats();&#10;          renderPlayback();&#10;          return false;&#10;        }&#10;        playing = true;&#10;        setAutoplayState(&amp;#x27;playing&amp;#x27;);&#10;        renderPlayback();&#10;        afterHandoff(function () {&#10;          if (!playing) return;&#10;          if (storyBeatIndex &amp;gt;= 0) followStoryStep(storySteps[storyBeatIndex]);&#10;          scheduleStoryPlayback();&#10;        });&#10;        return true;&#10;      }&#10;&#10;      function maybeStartSharePlayback() {&#10;        if (!autoplayPending || document.hidden) return false;&#10;        return startCurrentViewPlayback();&#10;      }&#10;&#10;      function togglePlayback() {&#10;        return playing ? (pausePlayback(), false) : startPlayback();&#10;      }&#10;&#10;      function syncStoryControlsDisabled() {&#10;        Array.prototype.forEach.call(trail.querySelectorAll(&amp;#x27;[data-story-node]&amp;#x27;), function (stop) {&#10;          stop.disabled = !!currentHandoff;&#10;        });&#10;        syncBeatLink();&#10;      }&#10;&#10;      function selectStoryBeat(index) {&#10;        if (currentHandoff || activeIndex &amp;lt; 0 || index &amp;lt; 0 || index &amp;gt;= storySteps.length) return false;&#10;        momentRestoreGeneration += 1;&#10;        clearChapterPreview({ clearIntents: true });&#10;        if (playing) pausePlayback();&#10;        else {&#10;          stopStoryBeatTimer();&#10;          clearStoryPulse();&#10;        }&#10;        storyPlaybackComplete = false;&#10;        storyPlaybackScope = &amp;#x27;story&amp;#x27;;&#10;        storyBeatElapsedMs = 0;&#10;        storyBeatDwellMs = storyBeatDwell(storySteps.length);&#10;        var view = views[activeIndex];&#10;        Archify.focus.setMany(view.focus, {&#10;          toggle: false,&#10;          updateUrl: false,&#10;          mode: &amp;#x27;selection&amp;#x27;,&#10;          label: view.label,&#10;          hideChip: true&#10;        });&#10;        setStoryBeat(index, { manual: true, center: true, pulse: true, follow: true });&#10;        resetProgress(index / storySteps.length);&#10;        renderPlayback();&#10;        return true;&#10;      }&#10;&#10;      function selectStoryBeatById(id, options) {&#10;        options = options || {};&#10;        var index = storySteps.findIndex(function (step) { return step.nodeId === id; });&#10;        if (index &amp;lt; 0) return false;&#10;        if (playing) pausePlayback();&#10;        else {&#10;          stopStoryBeatTimer();&#10;          clearStoryPulse();&#10;        }&#10;        storyPlaybackComplete = false;&#10;        storyPlaybackScope = &amp;#x27;story&amp;#x27;;&#10;        storyBeatElapsedMs = 0;&#10;        storyBeatDwellMs = storyBeatDwell(storySteps.length);&#10;        setStoryBeat(index, {&#10;          manual: false,&#10;          center: true,&#10;          pulse: false,&#10;          follow: options.follow === true,&#10;          linked: options.linked === true,&#10;          followInstant: options.followInstant === true&#10;        });&#10;        resetProgress(index / storySteps.length);&#10;        renderPlayback();&#10;        return true;&#10;      }&#10;&#10;      function updateUrl(view) {&#10;        try {&#10;          history.replaceState(null, &amp;#x27;&amp;#x27;, location.pathname + location.search + (view ? &amp;#x27;#view=&amp;#x27; + encodeURIComponent(view.id) : &amp;#x27;&amp;#x27;));&#10;        } catch (_) {}&#10;      }&#10;&#10;      function showAll(options) {&#10;        options = options || {};&#10;        if (options.restore !== true) momentRestoreGeneration += 1;&#10;        clearChapterPreview({ clearIntents: true });&#10;        if (playing &amp;amp;&amp;amp; options.playback !== true) pausePlayback();&#10;        if (options.playback !== true) storyPlaybackComplete = false;&#10;        cancelHandoff(&amp;#x27;overview&amp;#x27;);&#10;        activeIndex = -1;&#10;        renderStoryTrail(null);&#10;        if (options.clearFocus !== false) Archify.focus.clear({ updateUrl: false });&#10;        if (options.resetView !== false &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reset === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reset({ automatic: true });&#10;        }&#10;        render();&#10;        if (options.updateUrl !== false) updateUrl(null);&#10;      }&#10;&#10;      function activate(index, options) {&#10;        options = options || {};&#10;        if (options.restore !== true) momentRestoreGeneration += 1;&#10;        if (playing &amp;amp;&amp;amp; options.playback !== true) pausePlayback();&#10;        if (options.playback !== true) storyPlaybackComplete = false;&#10;        if (index &amp;lt; 0) { showAll(options); return true; }&#10;        if (index &amp;gt;= views.length) return false;&#10;        clearChapterPreview({ clearIntents: true });&#10;        var previousIndex = activeIndex;&#10;        var previous = previousIndex &amp;gt;= 0 ? views[previousIndex] : null;&#10;        var outgoingBeatIndex = storyBeatIndex;&#10;        cancelHandoff(&amp;#x27;replaced&amp;#x27;);&#10;        activeIndex = index;&#10;        var view = views[index];&#10;        Archify.focus.setMany(view.focus, {&#10;          toggle: false,&#10;          updateUrl: false,&#10;          mode: &amp;#x27;selection&amp;#x27;,&#10;          label: view.label,&#10;          hideChip: true&#10;        });&#10;        renderStoryTrail(view);&#10;        beginHandoff(previousIndex, index, previous, view, outgoingBeatIndex, options.playback === true ? &amp;#x27;playback&amp;#x27; : &amp;#x27;guided&amp;#x27;);&#10;        syncStoryControlsDisabled();&#10;        render();&#10;        if (options.updateUrl !== false) updateUrl(view);&#10;        return true;&#10;      }&#10;&#10;      function activateById(id, options) {&#10;        var index = views.findIndex(function (view) { return view.id === id; });&#10;        return index &amp;gt;= 0 &amp;amp;&amp;amp; activate(index, options);&#10;      }&#10;&#10;      prev.addEventListener(&amp;#x27;click&amp;#x27;, function () { activate(activeIndex - 1); });&#10;      next.addEventListener(&amp;#x27;click&amp;#x27;, function () { activate(activeIndex + 1); });&#10;      all.addEventListener(&amp;#x27;click&amp;#x27;, function () { showAll(); });&#10;      play.addEventListener(&amp;#x27;click&amp;#x27;, togglePlayback);&#10;      beatLink.addEventListener(&amp;#x27;click&amp;#x27;, copyStoryMomentLink);&#10;      trail.addEventListener(&amp;#x27;focusin&amp;#x27;, function (event) {&#10;        if (!event.target.closest(&amp;#x27;[data-story-node]&amp;#x27;)) return;&#10;        if (playing) pausePlayback();&#10;      });&#10;      trail.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        var stop = event.target.closest(&amp;#x27;[data-story-node]&amp;#x27;);&#10;        if (!stop || stop.disabled) return;&#10;        selectStoryBeat(Number(stop.getAttribute(&amp;#x27;data-story-index&amp;#x27;)));&#10;      });&#10;      trail.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        if (event.key !== &amp;#x27;Enter&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27; &amp;#x27;) return;&#10;        var stop = event.target.closest(&amp;#x27;[data-story-node]&amp;#x27;);&#10;        if (!stop || stop.disabled) return;&#10;        event.preventDefault();&#10;        selectStoryBeat(Number(stop.getAttribute(&amp;#x27;data-story-index&amp;#x27;)));&#10;      });&#10;      chapterList.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-guided-view-id]&amp;#x27;);&#10;        if (!button) return;&#10;        activateById(button.getAttribute(&amp;#x27;data-guided-view-id&amp;#x27;));&#10;      });&#10;      chapterList.addEventListener(&amp;#x27;pointerover&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-guided-view-id]&amp;#x27;);&#10;        if (!button || !hoverCapable() || event.pointerType === &amp;#x27;touch&amp;#x27;) return;&#10;        if (event.relatedTarget &amp;amp;&amp;amp; button.contains(event.relatedTarget)) return;&#10;        setChapterPreviewIntent(&amp;#x27;pointer&amp;#x27;, chapterButtons.indexOf(button));&#10;      });&#10;      chapterList.addEventListener(&amp;#x27;pointerout&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-guided-view-id]&amp;#x27;);&#10;        if (!button || (event.relatedTarget &amp;amp;&amp;amp; button.contains(event.relatedTarget))) return;&#10;        clearChapterPreviewIntent(&amp;#x27;pointer&amp;#x27;, chapterButtons.indexOf(button));&#10;      });&#10;      chapterIndex.addEventListener(&amp;#x27;focusin&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-guided-view-id]&amp;#x27;);&#10;        if (!button) return;&#10;        setChapterPreviewIntent(&amp;#x27;focus&amp;#x27;, chapterButtons.indexOf(button));&#10;      });&#10;      chapterIndex.addEventListener(&amp;#x27;focusout&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-guided-view-id]&amp;#x27;);&#10;        if (!button || (event.relatedTarget &amp;amp;&amp;amp; button.contains(event.relatedTarget))) return;&#10;        clearChapterPreviewIntent(&amp;#x27;focus&amp;#x27;, chapterButtons.indexOf(button));&#10;      });&#10;      chapterList.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-guided-view-id]&amp;#x27;);&#10;        var index = chapterButtons.indexOf(button);&#10;        if (index &amp;lt; 0) return;&#10;        var target = null;&#10;        if (event.key === &amp;#x27;ArrowRight&amp;#x27;) target = Math.min(chapterButtons.length - 1, index + 1);&#10;        else if (event.key === &amp;#x27;ArrowLeft&amp;#x27;) target = Math.max(0, index - 1);&#10;        else if (event.key === &amp;#x27;Home&amp;#x27;) target = 0;&#10;        else if (event.key === &amp;#x27;End&amp;#x27;) target = chapterButtons.length - 1;&#10;        if (target === null) return;&#10;        event.preventDefault();&#10;        focusChapterButton(target);&#10;      });&#10;&#10;      // A direct node exploration supersedes the curated view. Capture phase&#10;      // releases the view before the focus explorer writes its own deep link.&#10;      function releaseForNode(event) {&#10;        if (activeIndex &amp;gt;= 0 &amp;amp;&amp;amp; event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;)) {&#10;          pausePlayback();&#10;          showAll({ clearFocus: false, updateUrl: false });&#10;        }&#10;      }&#10;      svg.addEventListener(&amp;#x27;click&amp;#x27;, releaseForNode, true);&#10;      svg.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        if (event.key === &amp;#x27;Enter&amp;#x27; || event.key === &amp;#x27; &amp;#x27;) releaseForNode(event);&#10;      }, true);&#10;&#10;      document.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        if (event.metaKey || event.ctrlKey || event.altKey) return;&#10;        if (document.documentElement.getAttribute(&amp;#x27;data-guide-open&amp;#x27;) === &amp;#x27;true&amp;#x27;) return;&#10;        var target = event.target;&#10;        if (target &amp;amp;&amp;amp; (target.tagName === &amp;#x27;INPUT&amp;#x27; || target.tagName === &amp;#x27;TEXTAREA&amp;#x27; || target.isContentEditable)) return;&#10;        if (event.key === &amp;#x27;]&amp;#x27;) {&#10;          event.preventDefault();&#10;          if (activeIndex &amp;lt; views.length - 1) activate(activeIndex + 1);&#10;        } else if (event.key === &amp;#x27;[&amp;#x27;) {&#10;          event.preventDefault();&#10;          if (activeIndex &amp;gt;= 0) activate(activeIndex - 1);&#10;        } else if (event.key.toLowerCase() === &amp;#x27;p&amp;#x27;) {&#10;          event.preventDefault();&#10;          togglePlayback();&#10;        } else if (event.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; activePreviewIndex &amp;gt;= 0) {&#10;          event.preventDefault();&#10;          event.stopImmediatePropagation();&#10;          clearChapterPreview({ clearIntents: true });&#10;        } else if (event.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; activeIndex &amp;gt;= 0) {&#10;          event.preventDefault();&#10;          showAll();&#10;        }&#10;      }, true);&#10;&#10;      function syncViewFromHash() {&#10;        try {&#10;          var params = new URLSearchParams(location.hash.replace(/^#/, &amp;#x27;&amp;#x27;));&#10;          var initial = params.get(&amp;#x27;view&amp;#x27;);&#10;          var requestedBeat = params.get(&amp;#x27;beat&amp;#x27;);&#10;          var restoreGeneration = ++momentRestoreGeneration;&#10;          if (initial) {&#10;            var activated = activateById(initial, { updateUrl: false, restore: true });&#10;            if (!activated) {&#10;              showAll({ updateUrl: false, restore: true });&#10;              return;&#10;            }&#10;            if (requestedBeat) afterHandoff(function () {&#10;              if (restoreGeneration !== momentRestoreGeneration) return;&#10;              var latest = new URLSearchParams(location.hash.replace(/^#/, &amp;#x27;&amp;#x27;));&#10;              if (latest.get(&amp;#x27;view&amp;#x27;) !== initial || latest.get(&amp;#x27;beat&amp;#x27;) !== requestedBeat) return;&#10;              if (activeIndex &amp;lt; 0 || views[activeIndex].id !== initial) return;&#10;              selectStoryBeatById(requestedBeat, { linked: true, follow: true, followInstant: true });&#10;            });&#10;          } else if (params.get(&amp;#x27;focus&amp;#x27;) || params.get(&amp;#x27;relation&amp;#x27;)) {&#10;            activeIndex = -1;&#10;            render();&#10;          } else {&#10;            showAll({ updateUrl: false, restore: true });&#10;          }&#10;        } catch (_) { showAll({ updateUrl: false, restore: true }); }&#10;      }&#10;&#10;      window.addEventListener(&amp;#x27;hashchange&amp;#x27;, syncViewFromHash);&#10;      document.addEventListener(&amp;#x27;visibilitychange&amp;#x27;, function () {&#10;        if (document.hidden) {&#10;          clearChapterPreview({ clearIntents: true });&#10;          if (playing) pausePlayback();&#10;          else clearStoryPulse();&#10;          settleHandoff(&amp;#x27;hidden&amp;#x27;);&#10;        }&#10;        else if (!document.hidden) maybeStartSharePlayback();&#10;      });&#10;      if (window.matchMedia) {&#10;        var guidedMotionQuery = window.matchMedia(&amp;#x27;(prefers-reduced-motion: reduce)&amp;#x27;);&#10;        var onGuidedMotionChange = function () {&#10;          if (guidedMotionQuery.matches) {&#10;            if (playing) pausePlayback();&#10;            else clearStoryPulse();&#10;            settleHandoff(&amp;#x27;reduced-motion&amp;#x27;);&#10;          }&#10;        };&#10;        if (typeof guidedMotionQuery.addEventListener === &amp;#x27;function&amp;#x27;) guidedMotionQuery.addEventListener(&amp;#x27;change&amp;#x27;, onGuidedMotionChange);&#10;        else if (typeof guidedMotionQuery.addListener === &amp;#x27;function&amp;#x27;) guidedMotionQuery.addListener(onGuidedMotionChange);&#10;      }&#10;      if (document.documentElement.getAttribute(&amp;#x27;data-embed&amp;#x27;) !== &amp;#x27;true&amp;#x27; &amp;amp;&amp;amp; typeof MutationObserver !== &amp;#x27;undefined&amp;#x27; &amp;amp;&amp;amp; typeof Node !== &amp;#x27;undefined&amp;#x27; &amp;amp;&amp;amp; svg instanceof Node &amp;amp;&amp;amp; document.documentElement instanceof Node) {&#10;        var chapterPreviewOwnerObserver = new MutationObserver(syncChapterPreview);&#10;        chapterPreviewOwnerObserver.observe(svg, {&#10;          attributes: true,&#10;          attributeFilter: [&#10;            &amp;#x27;data-route-picking&amp;#x27;, &amp;#x27;data-route-active&amp;#x27;, &amp;#x27;data-lens-active&amp;#x27;,&#10;            &amp;#x27;data-legend-preview-active&amp;#x27;, &amp;#x27;data-relationship-preview-active&amp;#x27;,&#10;            &amp;#x27;data-intent-trace-active&amp;#x27;, &amp;#x27;data-focus-active&amp;#x27;&#10;          ]&#10;        });&#10;        var storyMotionObserver = new MutationObserver(function () {&#10;          if (document.documentElement.getAttribute(&amp;#x27;data-motion&amp;#x27;) !== &amp;#x27;live&amp;#x27;) clearStoryPulse();&#10;          renderPlayback();&#10;        });&#10;        storyMotionObserver.observe(document.documentElement, { attributes: true, attributeFilter: [&amp;#x27;data-motion&amp;#x27;] });&#10;      }&#10;      if (typeof ResizeObserver === &amp;#x27;function&amp;#x27;) {&#10;        var chapterViewportWidth = chapterList.clientWidth;&#10;        var trailViewportWidth = trail.clientWidth;&#10;        var storyScrollObserver = new ResizeObserver(function () {&#10;          var chapterWidth = chapterList.clientWidth;&#10;          var trailWidth = trail.clientWidth;&#10;          if (chapterWidth !== chapterViewportWidth &amp;amp;&amp;amp; activeIndex &amp;gt;= 0) centerChapterButton(chapterButtons[activeIndex]);&#10;          if (trailWidth !== trailViewportWidth &amp;amp;&amp;amp; storyBeatIndex &amp;gt;= 0) {&#10;            centerStoryStop(trail.querySelectorAll(&amp;#x27;[data-story-node]&amp;#x27;)[storyBeatIndex]);&#10;          }&#10;          chapterViewportWidth = chapterWidth;&#10;          trailViewportWidth = trailWidth;&#10;        });&#10;        storyScrollObserver.observe(chapterList);&#10;        storyScrollObserver.observe(trail);&#10;      }&#10;      window.addEventListener(&amp;#x27;beforeprint&amp;#x27;, function () {&#10;        clearChapterPreview({ clearIntents: true });&#10;        if (playing) pausePlayback();&#10;        else clearStoryPulse();&#10;        settleHandoff(&amp;#x27;print&amp;#x27;);&#10;      });&#10;      syncViewFromHash();&#10;      if (autoplayPending) {&#10;        requestAnimationFrame(function () {&#10;          requestAnimationFrame(maybeStartSharePlayback);&#10;        });&#10;      }&#10;&#10;      return {&#10;        count: views.length,&#10;        activate: activateById,&#10;        showAll: showAll,&#10;        play: startPlayback,&#10;        playCurrent: startCurrentViewPlayback,&#10;        pause: pausePlayback,&#10;        beatLink: storyMomentLink,&#10;        copyBeatLink: copyStoryMomentLink,&#10;        cancelHandoff: cancelHandoff,&#10;        settleHandoff: settleHandoff,&#10;        clearPreview: function () { return clearChapterPreview({ clearIntents: true }); },&#10;        isPlaying: function () { return playing; },&#10;        handoff: function () {&#10;          return currentHandoff ? { id: currentHandoff.id, mode: currentHandoff.mode, anchor: currentHandoff.anchor || null } : null;&#10;        },&#10;        active: function () { return activeIndex &amp;lt; 0 ? null : views[activeIndex].id; },&#10;        preview: function () { return activePreviewIndex &amp;lt; 0 ? null : views[activePreviewIndex].id; },&#10;        delta: function (id) {&#10;          var index = views.findIndex(function (view) { return view.id === id; });&#10;          if (index &amp;lt; 0) return null;&#10;          var value = chapterDelta(activeIndex &amp;gt;= 0 ? views[activeIndex] : null, views[index]);&#10;          return { stay: value.stay.slice(), enter: value.enter.slice(), leave: value.leave.slice() };&#10;        },&#10;        beat: function () {&#10;          var step = storyBeatIndex &amp;gt;= 0 ? storySteps[storyBeatIndex] : null;&#10;          return step ? {&#10;            index: step.index,&#10;            position: step.index + 1,&#10;            total: storySteps.length,&#10;            nodeId: step.nodeId,&#10;            relation: step.relation,&#10;            edgeKeys: step.edgeKeys.slice()&#10;          } : null;&#10;        },&#10;        focus: function () { return activeIndex &amp;lt; 0 ? [] : views[activeIndex].focus.slice(); }&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Adaptive Reader Shell — one diagram across laptop and monitor.&#10;       The canonical SVG and viewBox never change. On ordinary desktop pages,&#10;       wide diagrams receive only enough outer width to use the available&#10;       height without pushing summary cards below the viewport. Mobile,&#10;       embed, presentation, print, and non-wide diagrams retain their own&#10;       established layout contracts.&#10;       ============================================================ */&#10;    Archify.waitForStableLayout = function (options) {&#10;      options = options || {};&#10;      var maximumFrames = Math.max(1, Number(options.maximumFrames) || 240);&#10;      var fontsReady = document.fonts &amp;amp;&amp;amp; document.fonts.ready&#10;        ? document.fonts.ready.catch(function () {})&#10;        : Promise.resolve();&#10;      return fontsReady.then(function () {&#10;        if (typeof options.schedule === &amp;#x27;function&amp;#x27;) options.schedule();&#10;        return new Promise(function (resolve, reject) {&#10;          var previous = &amp;#x27;&amp;#x27;;&#10;          var stableFrames = 0;&#10;          var sampledFrames = 0;&#10;          function sample() {&#10;            sampledFrames += 1;&#10;            if (typeof options.pending === &amp;#x27;function&amp;#x27; &amp;amp;&amp;amp; options.pending()) {&#10;              previous = &amp;#x27;&amp;#x27;;&#10;              stableFrames = 0;&#10;            } else {&#10;              var current = typeof options.snapshot === &amp;#x27;function&amp;#x27; ? options.snapshot() : &amp;#x27;&amp;#x27;;&#10;              if (current === previous) stableFrames += 1;&#10;              else {&#10;                previous = current;&#10;                stableFrames = 0;&#10;              }&#10;              if (stableFrames &amp;gt;= 3) {&#10;                resolve({ stable: true, snapshot: current, sampledFrames: sampledFrames });&#10;                return;&#10;              }&#10;            }&#10;            if (sampledFrames &amp;gt;= maximumFrames) {&#10;              reject(new Error(options.timeoutMessage || &amp;#x27;Layout did not reach stable dimensions.&amp;#x27;));&#10;              return;&#10;            }&#10;            requestAnimationFrame(sample);&#10;          }&#10;          requestAnimationFrame(sample);&#10;        });&#10;      });&#10;    };&#10;&#10;    Archify.readerLayout = (function () {&#10;      var html = document.documentElement;&#10;      var body = document.body;&#10;      var shell = document.querySelector(&amp;#x27;.container&amp;#x27;);&#10;      var diagram = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var svg = diagram &amp;amp;&amp;amp; diagram.querySelector(&amp;#x27;:scope &amp;gt; svg&amp;#x27;);&#10;      var header = shell &amp;amp;&amp;amp; shell.querySelector(&amp;#x27;.header&amp;#x27;);&#10;      var guided = shell &amp;amp;&amp;amp; shell.querySelector(&amp;#x27;.guided-views&amp;#x27;);&#10;      var cards = shell &amp;amp;&amp;amp; shell.querySelector(&amp;#x27;.cards&amp;#x27;);&#10;      var viewBox = svg &amp;amp;&amp;amp; svg.viewBox &amp;amp;&amp;amp; svg.viewBox.baseVal;&#10;      var ratio = viewBox &amp;amp;&amp;amp; viewBox.height &amp;gt; 0 ? viewBox.width / viewBox.height : 0;&#10;      var frame = 0;&#10;      var settleFrame = 0;&#10;      var lastWidth = 0;&#10;      var WIDE_RATIO = 1.55;&#10;      var MIN_DESKTOP_WIDTH = 1024;&#10;      var MIN_READER_WIDTH = 960;&#10;      var MAX_READER_WIDTH = 1920;&#10;      var SAFE_BOTTOM_GAP = 12;&#10;&#10;      if (diagram &amp;amp;&amp;amp; ratio &amp;gt;= WIDE_RATIO) {&#10;        diagram.setAttribute(&amp;#x27;data-wide-diagram&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        html.setAttribute(&amp;#x27;data-diagram-shape&amp;#x27;, &amp;#x27;wide&amp;#x27;);&#10;      }&#10;&#10;      function number(value) {&#10;        var parsed = parseFloat(value);&#10;        return Number.isFinite(parsed) ? parsed : 0;&#10;      }&#10;      function visible(element) {&#10;        return Boolean(element &amp;amp;&amp;amp; !element.hidden &amp;amp;&amp;amp; window.getComputedStyle(element).display !== &amp;#x27;none&amp;#x27;);&#10;      }&#10;      function outerHeight(element) {&#10;        if (!visible(element)) return 0;&#10;        var style = window.getComputedStyle(element);&#10;        return element.getBoundingClientRect().height + number(style.marginTop) + number(style.marginBottom);&#10;      }&#10;      function eligible() {&#10;        return Boolean(&#10;          shell &amp;amp;&amp;amp; diagram &amp;amp;&amp;amp; svg &amp;amp;&amp;amp; ratio &amp;gt;= WIDE_RATIO &amp;amp;&amp;amp;&#10;          window.innerWidth &amp;gt;= MIN_DESKTOP_WIDTH &amp;amp;&amp;amp;&#10;          html.getAttribute(&amp;#x27;data-embed&amp;#x27;) !== &amp;#x27;true&amp;#x27; &amp;amp;&amp;amp;&#10;          html.getAttribute(&amp;#x27;data-present&amp;#x27;) !== &amp;#x27;true&amp;#x27; &amp;amp;&amp;amp;&#10;          (!window.matchMedia || !window.matchMedia(&amp;#x27;print&amp;#x27;).matches)&#10;        );&#10;      }&#10;      function clear() {&#10;        html.style.removeProperty(&amp;#x27;--archify-reader-width&amp;#x27;);&#10;        html.removeAttribute(&amp;#x27;data-reader-layout&amp;#x27;);&#10;        html.removeAttribute(&amp;#x27;data-reader-overflow&amp;#x27;);&#10;        lastWidth = 0;&#10;      }&#10;      function chromeMetrics() {&#10;        var bodyStyle = window.getComputedStyle(body);&#10;        var diagramStyle = window.getComputedStyle(diagram);&#10;        return {&#10;          bodyX: number(bodyStyle.paddingLeft) + number(bodyStyle.paddingRight),&#10;          bodyY: number(bodyStyle.paddingTop) + number(bodyStyle.paddingBottom),&#10;          diagramX: number(diagramStyle.paddingLeft) + number(diagramStyle.paddingRight) +&#10;            number(diagramStyle.borderLeftWidth) + number(diagramStyle.borderRightWidth),&#10;          diagramY: number(diagramStyle.paddingTop) + number(diagramStyle.paddingBottom) +&#10;            number(diagramStyle.borderTopWidth) + number(diagramStyle.borderBottomWidth)&#10;        };&#10;      }&#10;      function applyWidth(width) {&#10;        var rounded = Math.round(width);&#10;        if (Math.abs(rounded - lastWidth) &amp;lt; 1) return false;&#10;        lastWidth = rounded;&#10;        html.style.setProperty(&amp;#x27;--archify-reader-width&amp;#x27;, rounded + &amp;#x27;px&amp;#x27;);&#10;        html.setAttribute(&amp;#x27;data-reader-layout&amp;#x27;, &amp;#x27;adaptive&amp;#x27;);&#10;        return true;&#10;      }&#10;      function settleOverflow(minWidth) {&#10;        if (settleFrame) cancelAnimationFrame(settleFrame);&#10;        settleFrame = requestAnimationFrame(function () {&#10;          settleFrame = 0;&#10;          if (!eligible() || !lastWidth) return;&#10;          var overflow = Math.max(&#10;            document.documentElement.scrollHeight,&#10;            document.body.scrollHeight&#10;          ) - window.innerHeight;&#10;          if (overflow &amp;gt; 1 &amp;amp;&amp;amp; lastWidth &amp;gt; minWidth) {&#10;            applyWidth(Math.max(minWidth, lastWidth - overflow * ratio - 4));&#10;            html.setAttribute(&amp;#x27;data-reader-overflow&amp;#x27;, &amp;#x27;reduced&amp;#x27;);&#10;          } else if (overflow &amp;gt; 1) {&#10;            html.setAttribute(&amp;#x27;data-reader-overflow&amp;#x27;, &amp;#x27;authored&amp;#x27;);&#10;          } else {&#10;            html.removeAttribute(&amp;#x27;data-reader-overflow&amp;#x27;);&#10;          }&#10;        });&#10;      }&#10;      function measure() {&#10;        frame = 0;&#10;        if (!eligible()) {&#10;          clear();&#10;          return null;&#10;        }&#10;        var chrome = chromeMetrics();&#10;        var viewportCap = Math.max(0, window.innerWidth - chrome.bodyX);&#10;        var minWidth = Math.min(MIN_READER_WIDTH, viewportCap);&#10;        var maxWidth = Math.min(MAX_READER_WIDTH, viewportCap);&#10;        var fixedHeight = chrome.bodyY + chrome.diagramY + SAFE_BOTTOM_GAP +&#10;          outerHeight(header) + outerHeight(guided) + outerHeight(cards);&#10;        var availableSvgHeight = Math.max(1, window.innerHeight - fixedHeight);&#10;        var desiredWidth = availableSvgHeight * ratio + chrome.diagramX;&#10;        var width = Math.max(minWidth, Math.min(maxWidth, desiredWidth));&#10;        applyWidth(width);&#10;        settleOverflow(minWidth);&#10;        return {&#10;          ratio: ratio,&#10;          width: Math.round(width),&#10;          availableSvgHeight: Math.round(availableSvgHeight),&#10;          fixedHeight: Math.round(fixedHeight)&#10;        };&#10;      }&#10;      function schedule() {&#10;        if (frame) return;&#10;        frame = requestAnimationFrame(measure);&#10;      }&#10;      function stableSnapshot() {&#10;        var shellRect = shell ? shell.getBoundingClientRect() : { width: 0, height: 0 };&#10;        var diagramRect = diagram ? diagram.getBoundingClientRect() : { width: 0, height: 0 };&#10;        return [&#10;          lastWidth,&#10;          html.getAttribute(&amp;#x27;data-reader-layout&amp;#x27;) || &amp;#x27;&amp;#x27;,&#10;          html.getAttribute(&amp;#x27;data-reader-overflow&amp;#x27;) || &amp;#x27;&amp;#x27;,&#10;          Math.ceil(document.documentElement.scrollWidth),&#10;          Math.ceil(document.documentElement.scrollHeight),&#10;          Math.ceil(document.body.scrollWidth),&#10;          Math.ceil(document.body.scrollHeight),&#10;          Math.round(shellRect.width * 100) / 100,&#10;          Math.round(shellRect.height * 100) / 100,&#10;          Math.round(diagramRect.width * 100) / 100,&#10;          Math.round(diagramRect.height * 100) / 100&#10;        ].join(&amp;#x27;|&amp;#x27;);&#10;      }&#10;      function whenStable() {&#10;        return Archify.waitForStableLayout({&#10;          schedule: schedule,&#10;          pending: function () { return Boolean(frame || settleFrame); },&#10;          snapshot: stableSnapshot,&#10;          timeoutMessage: &amp;#x27;Adaptive reader layout did not reach stable dimensions.&amp;#x27;&#10;        });&#10;      }&#10;&#10;      window.addEventListener(&amp;#x27;resize&amp;#x27;, schedule, { passive: true });&#10;      window.addEventListener(&amp;#x27;load&amp;#x27;, schedule, { once: true });&#10;      if (document.fonts &amp;amp;&amp;amp; document.fonts.ready) document.fonts.ready.then(schedule).catch(function () {});&#10;      if (typeof ResizeObserver === &amp;#x27;function&amp;#x27;) {&#10;        var resizeObserver = new ResizeObserver(schedule);&#10;        [header, guided, cards].forEach(function (element) { if (element) resizeObserver.observe(element); });&#10;      }&#10;      if (typeof MutationObserver === &amp;#x27;function&amp;#x27;) {&#10;        var contentObserver = new MutationObserver(schedule);&#10;        if (guided) contentObserver.observe(guided, { attributes: true, childList: true, subtree: true });&#10;        if (cards) contentObserver.observe(cards, { attributes: true, childList: true, subtree: true });&#10;        contentObserver.observe(html, { attributes: true, attributeFilter: [&amp;#x27;data-embed&amp;#x27;, &amp;#x27;data-present&amp;#x27;] });&#10;      }&#10;      schedule();&#10;&#10;      return {&#10;        measure: measure,&#10;        schedule: schedule,&#10;        whenStable: whenStable,&#10;        active: function () { return html.getAttribute(&amp;#x27;data-reader-layout&amp;#x27;) === &amp;#x27;adaptive&amp;#x27;; },&#10;        receipt: function () { return { ratio: ratio, width: lastWidth }; }&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Viewer Chrome Layout — keep HTML controls clear of the canonical SVG&#10;       stage without changing authored geometry. The dock keeps its floating&#10;       appearance while a small bottom stage rail becomes part of the reader&#10;       budget whenever its zero-reserve position would enter the stage.&#10;       ============================================================ */&#10;    Archify.viewerChromeLayout = (function () {&#10;      var html = document.documentElement;&#10;      var container = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var svg = container &amp;amp;&amp;amp; container.querySelector(&amp;#x27;:scope &amp;gt; svg&amp;#x27;);&#10;      var nav = container &amp;amp;&amp;amp; container.querySelector(&amp;#x27;.diagram-nav&amp;#x27;);&#10;      var legend = svg &amp;amp;&amp;amp; svg.querySelector(&amp;#x27;[data-legend]&amp;#x27;);&#10;      var frame = 0;&#10;      var settleFrame = 0;&#10;      var reserve = 0;&#10;      var railLatched = false;&#10;      var probingBaseline = false;&#10;      var probePromise = null;&#10;      var baselineIntersectionArea = 0;&#10;      var baselineStageGap = null;&#10;      var restorableReserve = 0;&#10;      var probeFallbackReserve = 0;&#10;      var lastReceipt = null;&#10;      var SAFE_GAP = 10;&#10;&#10;      function visible(element) {&#10;        if (!element || element.hidden) return false;&#10;        var style = window.getComputedStyle(element);&#10;        return style.display !== &amp;#x27;none&amp;#x27; &amp;amp;&amp;amp; style.visibility !== &amp;#x27;hidden&amp;#x27;;&#10;      }&#10;      function usable(rect) {&#10;        return Boolean(rect &amp;amp;&amp;amp; rect.width &amp;gt; 0 &amp;amp;&amp;amp; rect.height &amp;gt; 0);&#10;      }&#10;      function intersectionArea(a, b) {&#10;        var width = Math.max(0, Math.min(a.right, b.right) - Math.max(a.left, b.left));&#10;        var height = Math.max(0, Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top));&#10;        return width * height;&#10;      }&#10;      function protectedStageRect() {&#10;        if (!svg) return null;&#10;        var rect = svg.getBoundingClientRect();&#10;        var transform = &amp;#x27;&amp;#x27;;&#10;        try { transform = window.getComputedStyle(svg).transform || &amp;#x27;&amp;#x27;; } catch (_) {}&#10;        var scaleX = 1;&#10;        var scaleY = 1;&#10;        var translateX = 0;&#10;        var translateY = 0;&#10;        var matrix = transform.match(/^matrix\(([^)]+)\)$/);&#10;        var matrix3d = transform.match(/^matrix3d\(([^)]+)\)$/);&#10;        if (matrix) {&#10;          var values = matrix[1].split(&amp;#x27;,&amp;#x27;).map(Number);&#10;          if (values.length === 6 &amp;amp;&amp;amp; values.every(Number.isFinite)) {&#10;            scaleX = Math.abs(values[0]) || 1;&#10;            scaleY = Math.abs(values[3]) || 1;&#10;            translateX = values[4];&#10;            translateY = values[5];&#10;          }&#10;        } else if (matrix3d) {&#10;          var values3d = matrix3d[1].split(&amp;#x27;,&amp;#x27;).map(Number);&#10;          if (values3d.length === 16 &amp;amp;&amp;amp; values3d.every(Number.isFinite)) {&#10;            scaleX = Math.abs(values3d[0]) || 1;&#10;            scaleY = Math.abs(values3d[5]) || 1;&#10;            translateX = values3d[12];&#10;            translateY = values3d[13];&#10;          }&#10;        }&#10;        var width = rect.width / scaleX;&#10;        var height = rect.height / scaleY;&#10;        var left = rect.left - translateX;&#10;        var top = rect.top - translateY;&#10;        return {&#10;          x: left,&#10;          y: top,&#10;          left: left,&#10;          top: top,&#10;          right: left + width,&#10;          bottom: top + height,&#10;          width: width,&#10;          height: height&#10;        };&#10;      }&#10;      function eligible() {&#10;        return Boolean(&#10;          container &amp;amp;&amp;amp; svg &amp;amp;&amp;amp; nav &amp;amp;&amp;amp;&#10;          window.innerWidth &amp;gt; 720 &amp;amp;&amp;amp;&#10;          html.getAttribute(&amp;#x27;data-embed&amp;#x27;) !== &amp;#x27;true&amp;#x27; &amp;amp;&amp;amp;&#10;          (!window.matchMedia || !window.matchMedia(&amp;#x27;print&amp;#x27;).matches) &amp;amp;&amp;amp;&#10;          visible(nav)&#10;        );&#10;      }&#10;      function cameraAtBaseline() {&#10;        var scale = Number(svg &amp;amp;&amp;amp; svg.getAttribute(&amp;#x27;data-view-scale&amp;#x27;));&#10;        return !Number.isFinite(scale) || Math.abs(scale - 1) &amp;lt; 0.001;&#10;      }&#10;      function writeReserve(next, options) {&#10;        options = options || {};&#10;        next = Math.max(0, Math.ceil(next));&#10;        if (Math.abs(next - reserve) &amp;lt; 1) return false;&#10;        reserve = next;&#10;        if (reserve) {&#10;          if (options.remember !== false) restorableReserve = reserve;&#10;          container.style.setProperty(&amp;#x27;--archify-nav-reserve&amp;#x27;, reserve + &amp;#x27;px&amp;#x27;);&#10;          container.setAttribute(&amp;#x27;data-nav-stage-rail&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          html.setAttribute(&amp;#x27;data-nav-stage-rail&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        } else {&#10;          container.style.removeProperty(&amp;#x27;--archify-nav-reserve&amp;#x27;);&#10;          container.removeAttribute(&amp;#x27;data-nav-stage-rail&amp;#x27;);&#10;          html.removeAttribute(&amp;#x27;data-nav-stage-rail&amp;#x27;);&#10;        }&#10;        if (Archify.readerLayout &amp;amp;&amp;amp; typeof Archify.readerLayout.schedule === &amp;#x27;function&amp;#x27;) {&#10;          Archify.readerLayout.schedule();&#10;        }&#10;        if (options.quiet !== true) {&#10;          if (settleFrame) cancelAnimationFrame(settleFrame);&#10;          settleFrame = requestAnimationFrame(function () {&#10;            settleFrame = 0;&#10;            schedule();&#10;          });&#10;        }&#10;        return true;&#10;      }&#10;      function clear(options) {&#10;        options = options || {};&#10;        railLatched = false;&#10;        if (options.preserveBaseline !== true) {&#10;          baselineIntersectionArea = 0;&#10;          baselineStageGap = null;&#10;          restorableReserve = 0;&#10;        }&#10;        writeReserve(0, { quiet: probingBaseline });&#10;        lastReceipt = {&#10;          eligible: false,&#10;          active: false,&#10;          reserve: 0,&#10;          gap: SAFE_GAP,&#10;          baselineStageGap: null,&#10;          stageGap: null,&#10;          stageIntersectionArea: 0,&#10;          baselineIntersectionArea: 0,&#10;          intersectionArea: 0&#10;        };&#10;        return lastReceipt;&#10;      }&#10;      function measure() {&#10;        frame = 0;&#10;        if (probingBaseline) return null;&#10;        if (!eligible()) return clear({ preserveBaseline: !cameraAtBaseline() });&#10;&#10;        /* Camera transforms enlarge and translate authored paint inside the&#10;           fixed, clipped root SVG viewport. They must not redefine the&#10;           reader&amp;#x27;s baseline rail.&#10;           Restore that baseline after temporary mobile/embed/print states.&#10;           Camera Reset preserves the established rail while viewport, mode,&#10;           and content changes remain responsible for baseline reprobes. */&#10;        if (!cameraAtBaseline()) {&#10;          if (reserve === 0 &amp;amp;&amp;amp; restorableReserve &amp;gt; 0) {&#10;            if (writeReserve(restorableReserve)) return null;&#10;          }&#10;          var cameraNavRect = nav.getBoundingClientRect();&#10;          var cameraLegendRect = visible(legend) ? legend.getBoundingClientRect() : null;&#10;          var cameraStageRect = protectedStageRect();&#10;          var cameraIntersectionArea = usable(cameraLegendRect) &amp;amp;&amp;amp; intersectionArea(cameraNavRect, cameraStageRect) &amp;gt; 0&#10;            ? intersectionArea(cameraNavRect, cameraLegendRect)&#10;            : 0;&#10;          lastReceipt = {&#10;            eligible: true,&#10;            active: reserve &amp;gt; 0,&#10;            reserve: reserve,&#10;            gap: SAFE_GAP,&#10;            baselineStageGap: baselineStageGap == null ? null : Math.round(baselineStageGap * 100) / 100,&#10;            stageGap: Math.round((cameraNavRect.top - cameraStageRect.bottom) * 100) / 100,&#10;            stageIntersectionArea: Math.round(intersectionArea(cameraNavRect, cameraStageRect) * 100) / 100,&#10;            baselineIntersectionArea: Math.round(baselineIntersectionArea * 100) / 100,&#10;            intersectionArea: Math.round(cameraIntersectionArea * 100) / 100&#10;          };&#10;          return lastReceipt;&#10;        }&#10;&#10;        var navRect = nav.getBoundingClientRect();&#10;        var legendRect = visible(legend) ? legend.getBoundingClientRect() : null;&#10;        var stageRect = protectedStageRect();&#10;        if (!usable(navRect) || !usable(stageRect)) return clear();&#10;&#10;        var actualIntersectionArea = usable(legendRect) ? intersectionArea(navRect, legendRect) : 0;&#10;        var stageGap = navRect.top - stageRect.bottom;&#10;        if (!railLatched &amp;amp;&amp;amp; reserve === 0) {&#10;          baselineIntersectionArea = actualIntersectionArea;&#10;          baselineStageGap = stageGap;&#10;          if (stageGap &amp;lt; SAFE_GAP) {&#10;            railLatched = true;&#10;            if (writeReserve(Math.max(0, SAFE_GAP - stageGap))) return null;&#10;          }&#10;        } else if (railLatched &amp;amp;&amp;amp; reserve &amp;gt; 0 &amp;amp;&amp;amp; stageGap &amp;lt; SAFE_GAP) {&#10;          /* Keep the decision latched while Adaptive Reader incorporates the&#10;             rail. Presentation and rounded layout values can require one&#10;             bounded follow-up before the full stage gap is established. */&#10;          var remaining = Math.max(1, SAFE_GAP - stageGap);&#10;          if (writeReserve(reserve + remaining)) return null;&#10;        }&#10;&#10;        navRect = nav.getBoundingClientRect();&#10;        legendRect = visible(legend) ? legend.getBoundingClientRect() : null;&#10;        stageRect = protectedStageRect();&#10;        stageGap = navRect.top - stageRect.bottom;&#10;        lastReceipt = {&#10;          eligible: true,&#10;          active: reserve &amp;gt; 0,&#10;          reserve: reserve,&#10;          gap: SAFE_GAP,&#10;          baselineStageGap: baselineStageGap == null ? null : Math.round(baselineStageGap * 100) / 100,&#10;          stageGap: Math.round(stageGap * 100) / 100,&#10;          stageIntersectionArea: Math.round(intersectionArea(navRect, stageRect) * 100) / 100,&#10;          baselineIntersectionArea: Math.round(baselineIntersectionArea * 100) / 100,&#10;          intersectionArea: Math.round((usable(legendRect) ? intersectionArea(navRect, legendRect) : 0) * 100) / 100&#10;        };&#10;        return lastReceipt;&#10;      }&#10;      function reprobe() {&#10;        if (probingBaseline) return probePromise || Promise.resolve(false);&#10;        if (!cameraAtBaseline()) {&#10;          schedule();&#10;          return Promise.resolve(false);&#10;        }&#10;        if (!reserve &amp;amp;&amp;amp; !railLatched &amp;amp;&amp;amp; !restorableReserve) {&#10;          schedule();&#10;          return Promise.resolve(false);&#10;        }&#10;        probeFallbackReserve = restorableReserve || reserve;&#10;        probingBaseline = true;&#10;        railLatched = false;&#10;        baselineIntersectionArea = 0;&#10;        baselineStageGap = null;&#10;        restorableReserve = 0;&#10;        writeReserve(0, { quiet: true });&#10;        var readerReady = Archify.readerLayout &amp;amp;&amp;amp; typeof Archify.readerLayout.whenStable === &amp;#x27;function&amp;#x27;&#10;          ? Archify.readerLayout.whenStable().catch(function () {})&#10;          : Promise.resolve();&#10;        probePromise = readerReady.then(function () {&#10;          probingBaseline = false;&#10;          probePromise = null;&#10;          if (!cameraAtBaseline() &amp;amp;&amp;amp; probeFallbackReserve &amp;gt; 0) {&#10;            restorableReserve = probeFallbackReserve;&#10;          }&#10;          probeFallbackReserve = 0;&#10;          schedule();&#10;          return true;&#10;        });&#10;        return probePromise;&#10;      }&#10;      function schedule() {&#10;        if (frame) return;&#10;        frame = requestAnimationFrame(measure);&#10;      }&#10;      function stableSnapshot() {&#10;        var containerRect = container ? container.getBoundingClientRect() : { width: 0, height: 0 };&#10;        var navRect = nav ? nav.getBoundingClientRect() : { top: 0, left: 0 };&#10;        var legendRect = legend ? legend.getBoundingClientRect() : { top: 0, left: 0 };&#10;        return [&#10;          reserve,&#10;          Math.round(containerRect.width * 100) / 100,&#10;          Math.round(containerRect.height * 100) / 100,&#10;          Math.round(navRect.left * 100) / 100,&#10;          Math.round(navRect.top * 100) / 100,&#10;          Math.round(legendRect.left * 100) / 100,&#10;          Math.round(legendRect.top * 100) / 100,&#10;          railLatched ? &amp;#x27;latched&amp;#x27; : &amp;#x27;clear&amp;#x27;,&#10;          lastReceipt ? lastReceipt.stageGap : &amp;#x27;&amp;#x27;&#10;        ].join(&amp;#x27;|&amp;#x27;);&#10;      }&#10;      function whenStable() {&#10;        return Archify.waitForStableLayout({&#10;          schedule: schedule,&#10;          pending: function () { return Boolean(frame || settleFrame || probingBaseline); },&#10;          snapshot: stableSnapshot,&#10;          timeoutMessage: &amp;#x27;Viewer chrome layout did not reach stable dimensions.&amp;#x27;&#10;        });&#10;      }&#10;&#10;      window.addEventListener(&amp;#x27;resize&amp;#x27;, reprobe, { passive: true });&#10;      window.addEventListener(&amp;#x27;load&amp;#x27;, schedule, { once: true });&#10;      window.addEventListener(&amp;#x27;beforeprint&amp;#x27;, schedule);&#10;      window.addEventListener(&amp;#x27;afterprint&amp;#x27;, reprobe);&#10;      if (document.fonts &amp;amp;&amp;amp; document.fonts.ready) document.fonts.ready.then(reprobe).catch(function () {});&#10;      if (typeof ResizeObserver === &amp;#x27;function&amp;#x27;) {&#10;        var resizeObserver = new ResizeObserver(schedule);&#10;        [nav, svg, legend].forEach(function (element) { if (element) resizeObserver.observe(element); });&#10;      }&#10;      if (typeof MutationObserver === &amp;#x27;function&amp;#x27;) {&#10;        var contentObserver = new MutationObserver(function (records) {&#10;          var viewerModeChanged = records.some(function (record) { return record.target === html; });&#10;          if (viewerModeChanged) reprobe();&#10;          else schedule();&#10;        });&#10;        if (legend) contentObserver.observe(legend, { attributes: true, childList: true, subtree: true });&#10;        contentObserver.observe(html, {&#10;          attributes: true,&#10;          attributeFilter: [&amp;#x27;data-embed&amp;#x27;, &amp;#x27;data-present&amp;#x27;, &amp;#x27;data-preset&amp;#x27;, &amp;#x27;data-theme&amp;#x27;]&#10;        });&#10;      }&#10;      schedule();&#10;&#10;      return {&#10;        measure: measure,&#10;        schedule: schedule,&#10;        reprobe: reprobe,&#10;        whenStable: whenStable,&#10;        stageRect: protectedStageRect,&#10;        active: function () { return reserve &amp;gt; 0; },&#10;        receipt: function () { return lastReceipt || measure(); }&#10;      };&#10;    })();&#10;&#10;    Archify.view = (function () {&#10;      var container = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var svg = container.querySelector(&amp;#x27;svg&amp;#x27;);&#10;      var outBtn = container.querySelector(&amp;#x27;[data-view=&amp;quot;out&amp;quot;]&amp;#x27;);&#10;      var resetBtn = container.querySelector(&amp;#x27;[data-view=&amp;quot;reset&amp;quot;]&amp;#x27;);&#10;      var resetDetailLabel = resetBtn.querySelector(&amp;#x27;[data-view-detail]&amp;#x27;);&#10;      var resetPercentLabel = resetBtn.querySelector(&amp;#x27;[data-view-percent]&amp;#x27;);&#10;      var inBtn = container.querySelector(&amp;#x27;[data-view=&amp;quot;in&amp;quot;]&amp;#x27;);&#10;      var state = { scale: 1, x: 0, y: 0, mode: &amp;#x27;overview&amp;#x27; };&#10;      var drag = null;&#10;      var cameraTimer = null;&#10;      var cameraFrame = null;&#10;      var cameraGeneration = 0;&#10;      var cameraTransaction = null;&#10;      var clipFrame = 0;&#10;      var resizeFrame = 0;&#10;      var autoScrollUntil = 0;&#10;&#10;      var viewBox = svg.viewBox &amp;amp;&amp;amp; svg.viewBox.baseVal;&#10;&#10;      function clamp() {&#10;        var width = svg.clientWidth || 1;&#10;        var height = svg.clientHeight || 1;&#10;        state.x = Math.min(0, Math.max(width - width * state.scale, state.x));&#10;        state.y = Math.min(0, Math.max(height - height * state.scale, state.y));&#10;      }&#10;      function reducedMotion() {&#10;        return window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;(prefers-reduced-motion: reduce)&amp;#x27;).matches;&#10;      }&#10;      function contentMetrics() {&#10;        if (!viewBox || viewBox.width &amp;lt;= 0 || viewBox.height &amp;lt;= 0) return null;&#10;        var width = svg.clientWidth || 1;&#10;        var height = svg.clientHeight || 1;&#10;        var scale = Math.min(width / viewBox.width, height / viewBox.height);&#10;        return {&#10;          width: width,&#10;          height: height,&#10;          scale: scale,&#10;          offsetX: (width - viewBox.width * scale) / 2,&#10;          offsetY: (height - viewBox.height * scale) / 2&#10;        };&#10;      }&#10;      function logicalViewport() {&#10;        var metrics = contentMetrics();&#10;        if (!metrics) return null;&#10;        var x;&#10;        var y;&#10;        var width;&#10;        var height;&#10;        if (window.innerWidth &amp;lt;= 720 &amp;amp;&amp;amp; container.hasAttribute(&amp;#x27;data-wide-diagram&amp;#x27;)) {&#10;          x = viewBox.x + container.scrollLeft / metrics.scale;&#10;          y = viewBox.y;&#10;          width = Math.min(viewBox.width, Math.max(1, container.clientWidth / metrics.scale));&#10;          height = viewBox.height;&#10;        } else {&#10;          x = viewBox.x + ((-state.x / state.scale) - metrics.offsetX) / metrics.scale;&#10;          y = viewBox.y + ((-state.y / state.scale) - metrics.offsetY) / metrics.scale;&#10;          width = Math.min(viewBox.width, metrics.width / state.scale / metrics.scale);&#10;          height = Math.min(viewBox.height, metrics.height / state.scale / metrics.scale);&#10;        }&#10;        width = Math.max(1, Math.min(viewBox.width, width));&#10;        height = Math.max(1, Math.min(viewBox.height, height));&#10;        x = Math.max(viewBox.x, Math.min(viewBox.x + viewBox.width - width, x));&#10;        y = Math.max(viewBox.y, Math.min(viewBox.y + viewBox.height - height, y));&#10;        return { x: x, y: y, width: width, height: height, scale: state.scale };&#10;      }&#10;      function detailLevel() {&#10;        if (state.mode === &amp;#x27;semantic&amp;#x27;) return &amp;#x27;full&amp;#x27;;&#10;        if (state.scale &amp;gt;= 1.75) return &amp;#x27;full&amp;#x27;;&#10;        if (state.scale &amp;gt;= 1) return &amp;#x27;read&amp;#x27;;&#10;        return &amp;#x27;map&amp;#x27;;&#10;      }&#10;      function renderControls() {&#10;        var semantic = state.mode === &amp;#x27;semantic&amp;#x27; &amp;amp;&amp;amp; state.scale &amp;gt; 1.01;&#10;        var detail = detailLevel();&#10;        var percent = Math.round(state.scale * 100) + &amp;#x27;%&amp;#x27;;&#10;        var levelLabel = viewerText(&amp;#x27;viewer.nav.level.&amp;#x27; + detail);&#10;        var detailHint = detail === &amp;#x27;map&amp;#x27;&#10;          ? viewerText(&amp;#x27;viewer.nav.detail.map&amp;#x27;)&#10;          : detail === &amp;#x27;read&amp;#x27;&#10;            ? viewerText(&amp;#x27;viewer.nav.detail.read&amp;#x27;)&#10;            : viewerText(&amp;#x27;viewer.nav.detail.full&amp;#x27;);&#10;        var resolvedLevel = semantic ? viewerText(&amp;#x27;viewer.nav.level.auto&amp;#x27;) : levelLabel;&#10;        var showDetailLevel = semantic || detail !== &amp;#x27;read&amp;#x27;;&#10;        if (resetDetailLabel) {&#10;          resetDetailLabel.textContent = resolvedLevel;&#10;          resetDetailLabel.hidden = !showDetailLevel;&#10;        }&#10;        if (resetPercentLabel) resetPercentLabel.textContent = percent;&#10;        resetBtn.toggleAttribute(&amp;#x27;data-detail-visible&amp;#x27;, showDetailLevel);&#10;        resetBtn.title = viewerText(&amp;#x27;viewer.nav.camera.title&amp;#x27;, {&#10;          semantic: semantic ? viewerText(&amp;#x27;viewer.nav.camera.semantic&amp;#x27;) : &amp;#x27;&amp;#x27;,&#10;          hint: detailHint&#10;        });&#10;        resetBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.nav.camera&amp;#x27;, { hint: detailHint }));&#10;        resetBtn.setAttribute(&amp;#x27;data-detail-level&amp;#x27;, detail);&#10;        container.setAttribute(&amp;#x27;data-detail-level&amp;#x27;, detail);&#10;        container.setAttribute(&amp;#x27;data-camera-mode&amp;#x27;, state.mode);&#10;        container.setAttribute(&amp;#x27;data-camera-indicator&amp;#x27;, semantic ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;      }&#10;      function clipToViewport(camera) {&#10;        camera = camera || state;&#10;        if (camera.scale &amp;lt;= 1.001) {&#10;          svg.style.removeProperty(&amp;#x27;clip-path&amp;#x27;);&#10;          return;&#10;        }&#10;        var width = svg.clientWidth || 1;&#10;        var height = svg.clientHeight || 1;&#10;        var scale = camera.scale;&#10;        var top = Math.max(0, Math.min(height, -camera.y / scale));&#10;        var left = Math.max(0, Math.min(width, -camera.x / scale));&#10;        var right = Math.max(0, Math.min(width, width - (width - camera.x) / scale));&#10;        var bottom = Math.max(0, Math.min(height, height - (height - camera.y) / scale));&#10;        svg.style.clipPath = &amp;#x27;inset(&amp;#x27; + [top, right, bottom, left].map(function (value) {&#10;          return Math.round(value * 1000) / 1000 + &amp;#x27;px&amp;#x27;;&#10;        }).join(&amp;#x27; &amp;#x27;) + &amp;#x27;)&amp;#x27;;&#10;      }&#10;      function cameraSettled(rendered) {&#10;        return Math.abs(rendered.scale - state.scale) &amp;lt; 0.001 &amp;amp;&amp;amp;&#10;          Math.abs(rendered.x - state.x) &amp;lt; 0.05 &amp;amp;&amp;amp;&#10;          Math.abs(rendered.y - state.y) &amp;lt; 0.05;&#10;      }&#10;      function syncViewportClip() {&#10;        if (clipFrame) cancelAnimationFrame(clipFrame);&#10;        clipFrame = 0;&#10;        function sample() {&#10;          clipFrame = 0;&#10;          var rendered = sampleRenderedState();&#10;          clipToViewport(rendered);&#10;          if (!cameraSettled(rendered)) clipFrame = requestAnimationFrame(sample);&#10;        }&#10;        sample();&#10;      }&#10;      function apply() {&#10;        clamp();&#10;        svg.style.transform = &amp;#x27;translate(&amp;#x27; + state.x + &amp;#x27;px,&amp;#x27; + state.y + &amp;#x27;px) scale(&amp;#x27; + state.scale + &amp;#x27;)&amp;#x27;;&#10;        syncViewportClip();&#10;        renderControls();&#10;        outBtn.disabled = state.scale &amp;lt;= 1;&#10;        inBtn.disabled = state.scale &amp;gt;= 3;&#10;        container.classList.toggle(&amp;#x27;is-pannable&amp;#x27;, state.scale &amp;gt; 1);&#10;        svg.setAttribute(&amp;#x27;data-view-scale&amp;#x27;, String(state.scale));&#10;        if (Archify.radar &amp;amp;&amp;amp; typeof Archify.radar.sync === &amp;#x27;function&amp;#x27;) Archify.radar.sync();&#10;        if (Archify.viewerChromeLayout &amp;amp;&amp;amp; typeof Archify.viewerChromeLayout.schedule === &amp;#x27;function&amp;#x27;) {&#10;          Archify.viewerChromeLayout.schedule();&#10;        }&#10;      }&#10;      function sampleRenderedState() {&#10;        var transform = &amp;#x27;&amp;#x27;;&#10;        try { transform = getComputedStyle(svg).transform || &amp;#x27;&amp;#x27;; } catch (_) {}&#10;        var match = transform.match(/^matrix\(([^)]+)\)$/);&#10;        if (!match) return { scale: state.scale, x: state.x, y: state.y, mode: state.mode };&#10;        var values = match[1].split(&amp;#x27;,&amp;#x27;).map(Number);&#10;        if (values.length !== 6 || !values.every(Number.isFinite)) {&#10;          return { scale: state.scale, x: state.x, y: state.y, mode: state.mode };&#10;        }&#10;        return { scale: values[0], x: values[4], y: values[5], mode: state.mode };&#10;      }&#10;      function finishCameraTransaction(transaction, outcome) {&#10;        if (!transaction || transaction.settled) return false;&#10;        transaction.settled = true;&#10;        transaction.state = outcome || &amp;#x27;complete&amp;#x27;;&#10;        if (transaction.frame) cancelAnimationFrame(transaction.frame);&#10;        if (transaction.timer) clearTimeout(transaction.timer);&#10;        transaction.frame = null;&#10;        transaction.timer = null;&#10;        if (cameraTransaction === transaction) cameraTransaction = null;&#10;        cameraFrame = null;&#10;        cameraTimer = null;&#10;        container.classList.remove(&amp;#x27;is-camera-moving&amp;#x27;);&#10;        container.classList.remove(&amp;#x27;is-camera-transaction&amp;#x27;);&#10;        container.removeAttribute(&amp;#x27;data-camera-transaction&amp;#x27;);&#10;        if (Archify.focus &amp;amp;&amp;amp; Archify.focus.reposition) Archify.focus.reposition();&#10;        transaction.resolve({ id: transaction.id, state: transaction.state });&#10;        return true;&#10;      }&#10;      function cameraReceipt(target, options) {&#10;        var resolver;&#10;        var transaction = {&#10;          id: ++cameraGeneration,&#10;          state: &amp;#x27;running&amp;#x27;,&#10;          target: target,&#10;          settled: false,&#10;          frame: null,&#10;          timer: null,&#10;          finished: new Promise(function (resolve) { resolver = resolve; }),&#10;          resolve: resolver,&#10;          cancel: function (reason, commitTarget) {&#10;            if (transaction.settled) return false;&#10;            if (commitTarget &amp;amp;&amp;amp; transaction.target) {&#10;              if (Object.prototype.hasOwnProperty.call(transaction.target, &amp;#x27;scrollLeft&amp;#x27;)) {&#10;                container.scrollLeft = transaction.target.scrollLeft;&#10;              } else {&#10;                state = {&#10;                  scale: transaction.target.scale,&#10;                  x: transaction.target.x,&#10;                  y: transaction.target.y,&#10;                  mode: transaction.target.mode&#10;                };&#10;                apply();&#10;              }&#10;            }&#10;            return finishCameraTransaction(transaction, reason || &amp;#x27;cancelled&amp;#x27;);&#10;          }&#10;        };&#10;        return transaction;&#10;      }&#10;      function stopCameraMotion(reason, commitTarget) {&#10;        if (cameraTransaction &amp;amp;&amp;amp; !cameraTransaction.settled) {&#10;          cameraTransaction.cancel(reason || &amp;#x27;cancelled&amp;#x27;, commitTarget === true);&#10;          return;&#10;        }&#10;        if (cameraTimer) clearTimeout(cameraTimer);&#10;        if (cameraFrame) cancelAnimationFrame(cameraFrame);&#10;        cameraTimer = null;&#10;        cameraFrame = null;&#10;        container.classList.remove(&amp;#x27;is-camera-moving&amp;#x27;);&#10;        container.classList.remove(&amp;#x27;is-camera-transaction&amp;#x27;);&#10;        container.removeAttribute(&amp;#x27;data-camera-transaction&amp;#x27;);&#10;      }&#10;      function interruptCamera(reason) {&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; Archify.guidedViews.cancelHandoff) {&#10;          Archify.guidedViews.cancelHandoff(reason || &amp;#x27;manual&amp;#x27;);&#10;        }&#10;        var rendered = sampleRenderedState();&#10;        stopCameraMotion(reason || &amp;#x27;manual&amp;#x27;, false);&#10;        state = rendered;&#10;        state.mode = &amp;#x27;manual&amp;#x27;;&#10;        apply();&#10;        renderControls();&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; Archify.guidedViews.isPlaying &amp;amp;&amp;amp; Archify.guidedViews.isPlaying()) {&#10;          Archify.guidedViews.pause();&#10;        }&#10;        if (Archify.routeProbe &amp;amp;&amp;amp; Archify.routeProbe.isJourneyPlaying &amp;amp;&amp;amp; Archify.routeProbe.isJourneyPlaying()) {&#10;          Archify.routeProbe.pauseJourney({ preserveElapsed: true, reason: reason || &amp;#x27;manual&amp;#x27; });&#10;        }&#10;      }&#10;      function zoom(next, options) {&#10;        options = options || {};&#10;        if (options.manual !== false) interruptCamera();&#10;        var previous = state.scale;&#10;        next = Math.max(1, Math.min(3, Math.round(next * 4) / 4));&#10;        if (next === previous) return;&#10;        var centerX = (svg.clientWidth || 1) / 2;&#10;        var centerY = (svg.clientHeight || 1) / 2;&#10;        var contentX = (centerX - state.x) / previous;&#10;        var contentY = (centerY - state.y) / previous;&#10;        state.scale = next;&#10;        state.x = centerX - contentX * next;&#10;        state.y = centerY - contentY * next;&#10;        apply();&#10;      }&#10;      function reset(options) {&#10;        options = options || {};&#10;        if (options.automatic !== true) interruptCamera();&#10;        else stopCameraMotion(&amp;#x27;reset&amp;#x27;, false);&#10;        state = { scale: 1, x: 0, y: 0, mode: &amp;#x27;overview&amp;#x27; };&#10;        apply();&#10;      }&#10;      function centerAt(logicalX, logicalY, options) {&#10;        options = options || {};&#10;        logicalX = Number(logicalX);&#10;        logicalY = Number(logicalY);&#10;        var metrics = contentMetrics();&#10;        if (!metrics || !Number.isFinite(logicalX) || !Number.isFinite(logicalY)) return false;&#10;        interruptCamera();&#10;        if (window.innerWidth &amp;lt;= 720 &amp;amp;&amp;amp; container.hasAttribute(&amp;#x27;data-wide-diagram&amp;#x27;)) {&#10;          state.scale = 1;&#10;          state.x = 0;&#10;          state.y = 0;&#10;          state.mode = &amp;#x27;manual&amp;#x27;;&#10;          apply();&#10;          var mobileTarget = (logicalX - viewBox.x) * metrics.scale - container.clientWidth / 2;&#10;          mobileTarget = Math.max(0, Math.min(svg.clientWidth - container.clientWidth, mobileTarget));&#10;          autoScrollUntil = Date.now() + 80;&#10;          try { container.scrollTo({ left: mobileTarget, behavior: options.instant ? &amp;#x27;auto&amp;#x27; : &amp;#x27;smooth&amp;#x27; }); }&#10;          catch (_) { container.scrollLeft = mobileTarget; }&#10;          return true;&#10;        }&#10;        var minimumScale = Math.max(1, Math.min(3, Number(options.minimumScale) || 1));&#10;        var requestedScale = Number(options.scale);&#10;        state.scale = Math.max(minimumScale, Math.min(3, Number.isFinite(requestedScale) ? requestedScale : state.scale));&#10;        var contentX = metrics.offsetX + (logicalX - viewBox.x) * metrics.scale;&#10;        var contentY = metrics.offsetY + (logicalY - viewBox.y) * metrics.scale;&#10;        state.x = metrics.width / 2 - contentX * state.scale;&#10;        state.y = metrics.height / 2 - contentY * state.scale;&#10;        state.mode = &amp;#x27;manual&amp;#x27;;&#10;        apply();&#10;        if (Archify.focus &amp;amp;&amp;amp; Archify.focus.reposition) Archify.focus.reposition();&#10;        return true;&#10;      }&#10;      function semanticIds(ids, includeNeighbors) {&#10;        var seeds = {};&#10;        var wanted = {};&#10;        (ids || []).forEach(function (id) { seeds[id] = true; wanted[id] = true; });&#10;        if (includeNeighbors) {&#10;          Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-edge-from][data-edge-to]&amp;#x27;), function (edge) {&#10;            var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;            var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;            if (seeds[from] || seeds[to]) { wanted[from] = true; wanted[to] = true; }&#10;          });&#10;        }&#10;        return wanted;&#10;      }&#10;      function boxesFor(ids, includeNeighbors) {&#10;        var wanted = semanticIds(ids, includeNeighbors);&#10;        return Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;))&#10;          .filter(function (node) { return wanted[node.getAttribute(&amp;#x27;data-node-id&amp;#x27;)]; })&#10;          .map(function (node) {&#10;            try { return node.getBBox(); } catch (_) { return null; }&#10;          })&#10;          .filter(Boolean);&#10;      }&#10;      function frameDesktop(ids, options) {&#10;        options = options || {};&#10;        var boxes = boxesFor(ids, options.includeNeighbors === true);&#10;        if (!boxes.length || !viewBox || viewBox.width &amp;lt;= 0 || viewBox.height &amp;lt;= 0) return false;&#10;        var svgWidth = svg.clientWidth || 1;&#10;        var svgHeight = svg.clientHeight || 1;&#10;        var contentScale = Math.min(svgWidth / viewBox.width, svgHeight / viewBox.height);&#10;        var contentOffsetX = (svgWidth - viewBox.width * contentScale) / 2;&#10;        var contentOffsetY = (svgHeight - viewBox.height * contentScale) / 2;&#10;        var minX = Math.min.apply(Math, boxes.map(function (box) { return box.x; }));&#10;        var minY = Math.min.apply(Math, boxes.map(function (box) { return box.y; }));&#10;        var maxX = Math.max.apply(Math, boxes.map(function (box) { return box.x + box.width; }));&#10;        var maxY = Math.max.apply(Math, boxes.map(function (box) { return box.y + box.height; }));&#10;        var bounds = {&#10;          x: contentOffsetX + minX * contentScale,&#10;          y: contentOffsetY + minY * contentScale,&#10;          width: Math.max(1, (maxX - minX) * contentScale),&#10;          height: Math.max(1, (maxY - minY) * contentScale)&#10;        };&#10;        var padding = options.padding || 48;&#10;        var left = padding;&#10;        var right = svgWidth - padding;&#10;        var top = padding;&#10;        var bottom = svgHeight - Math.max(padding, 72);&#10;        var containerRect = container.getBoundingClientRect();&#10;        var visibleTop = Math.max(0, -containerRect.top);&#10;        var visibleBottom = Math.min(svgHeight, window.innerHeight - containerRect.top);&#10;        if (visibleBottom - visibleTop &amp;gt;= 240) {&#10;          top = Math.max(top, visibleTop + padding);&#10;          bottom = Math.min(bottom, visibleBottom - Math.max(padding, 72));&#10;        }&#10;        var chip = document.getElementById(&amp;#x27;focus-chip&amp;#x27;);&#10;        if (chip &amp;amp;&amp;amp; !chip.hidden) {&#10;          var lensEnd = chip.offsetLeft + chip.offsetWidth + 24 - (svg.offsetLeft || 0);&#10;          left = Math.max(left, Math.min(svgWidth * 0.42, lensEnd));&#10;        }&#10;        var routeReceipt = document.getElementById(&amp;#x27;route-probe&amp;#x27;);&#10;        if (routeReceipt &amp;amp;&amp;amp; !routeReceipt.hidden &amp;amp;&amp;amp; routeReceipt.hasAttribute(&amp;#x27;data-route-journey&amp;#x27;)) {&#10;          var receiptTop = routeReceipt.offsetTop;&#10;          var receiptBottom = receiptTop + routeReceipt.offsetHeight;&#10;          if (receiptTop &amp;lt; svgHeight / 2) top = Math.max(top, receiptBottom + 24);&#10;          else bottom = Math.min(bottom, receiptTop - 24);&#10;        }&#10;        if (right &amp;lt;= left || bottom &amp;lt;= top) return false;&#10;        var maxScale = options.maxScale || (options.includeNeighbors ? 1.9 : 2.15);&#10;        var targetScale = Math.min((right - left) / bounds.width, (bottom - top) / bounds.height) * 0.9;&#10;        targetScale = Math.max(1, Math.min(maxScale, targetScale));&#10;        if (targetScale &amp;lt; 1.08) targetScale = 1;&#10;        var target = {&#10;          scale: Math.round(targetScale * 100) / 100,&#10;          x: 0,&#10;          y: 0,&#10;          mode: &amp;#x27;semantic&amp;#x27;&#10;        };&#10;        target.x = (left + right) / 2 - (bounds.x + bounds.width / 2) * target.scale;&#10;        target.y = (top + bottom) / 2 - (bounds.y + bounds.height / 2) * target.scale;&#10;        var start = sampleRenderedState();&#10;        stopCameraMotion(&amp;#x27;replaced&amp;#x27;, false);&#10;        var transaction = cameraReceipt(target, options);&#10;        cameraTransaction = transaction;&#10;        var instant = options.instant === true || reducedMotion() || document.hidden;&#10;        if (instant) {&#10;          state = target;&#10;          apply();&#10;          finishCameraTransaction(transaction, reducedMotion() ? &amp;#x27;reduced-motion&amp;#x27; : (document.hidden ? &amp;#x27;hidden&amp;#x27; : &amp;#x27;complete&amp;#x27;));&#10;          return transaction;&#10;        }&#10;        var duration = Math.max(180, Math.min(520, Number(options.duration) || 420));&#10;        var startedAt = 0;&#10;        state = start;&#10;        state.mode = &amp;#x27;semantic&amp;#x27;;&#10;        apply();&#10;        container.classList.add(&amp;#x27;is-camera-moving&amp;#x27;);&#10;        container.classList.add(&amp;#x27;is-camera-transaction&amp;#x27;);&#10;        container.setAttribute(&amp;#x27;data-camera-transaction&amp;#x27;, String(transaction.id));&#10;        var step = function (timestamp) {&#10;          if (cameraTransaction !== transaction || transaction.settled) return;&#10;          if (!startedAt) startedAt = timestamp;&#10;          var fraction = Math.max(0, Math.min(1, (timestamp - startedAt) / duration));&#10;          var eased = 1 - Math.pow(1 - fraction, 3);&#10;          state = {&#10;            scale: start.scale + (target.scale - start.scale) * eased,&#10;            x: start.x + (target.x - start.x) * eased,&#10;            y: start.y + (target.y - start.y) * eased,&#10;            mode: &amp;#x27;semantic&amp;#x27;&#10;          };&#10;          apply();&#10;          if (fraction &amp;lt; 1) {&#10;            transaction.frame = requestAnimationFrame(step);&#10;            cameraFrame = transaction.frame;&#10;          } else {&#10;            state = target;&#10;            apply();&#10;            finishCameraTransaction(transaction, &amp;#x27;complete&amp;#x27;);&#10;          }&#10;        };&#10;        transaction.frame = requestAnimationFrame(step);&#10;        cameraFrame = transaction.frame;&#10;        return transaction;&#10;      }&#10;      function reveal(ids, options) {&#10;        options = options || {};&#10;        if (window.innerWidth &amp;gt; 720) return frameDesktop(ids, options);&#10;        stopCameraMotion(&amp;#x27;replaced&amp;#x27;, false);&#10;        state.scale = 1;&#10;        state.x = 0;&#10;        state.y = 0;&#10;        state.mode = &amp;#x27;semantic&amp;#x27;;&#10;        apply();&#10;        if (!container.hasAttribute(&amp;#x27;data-wide-diagram&amp;#x27;)) {&#10;          var contained = cameraReceipt({ scale: 1, x: 0, y: 0, mode: &amp;#x27;semantic&amp;#x27; }, options);&#10;          cameraTransaction = contained;&#10;          finishCameraTransaction(contained, &amp;#x27;complete&amp;#x27;);&#10;          return contained;&#10;        }&#10;        var boxes = boxesFor(ids, options.includeNeighbors === true);&#10;        if (!boxes.length || !viewBox || viewBox.width &amp;lt;= 0) return false;&#10;        var minX = Math.min.apply(Math, boxes.map(function (box) { return box.x; }));&#10;        var maxX = Math.max.apply(Math, boxes.map(function (box) { return box.x + box.width; }));&#10;        var center = ((minX + maxX) / 2 / viewBox.width) * (svg.clientWidth || 1);&#10;        var target = Math.max(0, Math.min(svg.clientWidth - container.clientWidth, center - container.clientWidth / 2));&#10;        var transaction = cameraReceipt({ scrollLeft: target }, options);&#10;        cameraTransaction = transaction;&#10;        var instant = options.instant === true || reducedMotion() || document.hidden;&#10;        autoScrollUntil = Date.now() + (instant ? 50 : 470);&#10;        try { container.scrollTo({ left: target, behavior: instant ? &amp;#x27;auto&amp;#x27; : &amp;#x27;smooth&amp;#x27; }); }&#10;        catch (_) { container.scrollLeft = target; }&#10;        if (instant) finishCameraTransaction(transaction, reducedMotion() ? &amp;#x27;reduced-motion&amp;#x27; : (document.hidden ? &amp;#x27;hidden&amp;#x27; : &amp;#x27;complete&amp;#x27;));&#10;        else {&#10;          transaction.timer = setTimeout(function () { finishCameraTransaction(transaction, &amp;#x27;complete&amp;#x27;); }, 460);&#10;          cameraTimer = transaction.timer;&#10;          container.classList.add(&amp;#x27;is-camera-moving&amp;#x27;);&#10;          container.setAttribute(&amp;#x27;data-camera-transaction&amp;#x27;, String(transaction.id));&#10;        }&#10;        return transaction;&#10;      }&#10;      function syncSemantic() {&#10;        var guided = Archify.guidedViews &amp;amp;&amp;amp; typeof Archify.guidedViews.focus === &amp;#x27;function&amp;#x27;&#10;          ? Archify.guidedViews.focus() : [];&#10;        if (guided &amp;amp;&amp;amp; guided.length) return reveal(guided, { reason: &amp;#x27;guided-sync&amp;#x27; });&#10;        var active = Archify.focus &amp;amp;&amp;amp; typeof Archify.focus.active === &amp;#x27;function&amp;#x27; ? Archify.focus.active() : null;&#10;        if (typeof active === &amp;#x27;string&amp;#x27;) return reveal([active], { includeNeighbors: true, reason: &amp;#x27;focus-sync&amp;#x27; });&#10;        if (Array.isArray(active) &amp;amp;&amp;amp; active.length) return reveal(active, { reason: &amp;#x27;selection-sync&amp;#x27; });&#10;        return false;&#10;      }&#10;      function pinControls() {&#10;        container.style.setProperty(&amp;#x27;--archify-scroll-x&amp;#x27;, container.scrollLeft + &amp;#x27;px&amp;#x27;);&#10;      }&#10;      function onScroll() {&#10;        pinControls();&#10;        if (Archify.radar &amp;amp;&amp;amp; typeof Archify.radar.sync === &amp;#x27;function&amp;#x27;) Archify.radar.sync();&#10;        if (window.innerWidth &amp;lt;= 720 &amp;amp;&amp;amp; container.hasAttribute(&amp;#x27;data-wide-diagram&amp;#x27;) &amp;amp;&amp;amp; Date.now() &amp;gt; autoScrollUntil) {&#10;          interruptCamera();&#10;        }&#10;      }&#10;      function onPointerEnd(event) {&#10;        if (!drag) return;&#10;        var moved = drag.moved;&#10;        drag = null;&#10;        container.classList.remove(&amp;#x27;is-panning&amp;#x27;);&#10;        try { container.releasePointerCapture(event.pointerId); } catch (_) {}&#10;        if (moved) {&#10;          container.setAttribute(&amp;#x27;data-just-panned&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          setTimeout(function () { container.removeAttribute(&amp;#x27;data-just-panned&amp;#x27;); }, 80);&#10;        }&#10;      }&#10;&#10;      inBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { zoom(state.scale + 0.25); });&#10;      outBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { zoom(state.scale - 0.25); });&#10;      resetBtn.addEventListener(&amp;#x27;click&amp;#x27;, reset);&#10;      container.addEventListener(&amp;#x27;pointerdown&amp;#x27;, function (event) {&#10;        if (state.scale &amp;lt;= 1 || event.button !== 0 || event.target.closest(&amp;#x27;.diagram-nav, .focus-chip, .node-finder, .diagram-guide, .overview-map, .route-probe, .semantic-lens&amp;#x27;) || event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;) || event.target.closest(&amp;#x27;[data-relationship-hit-key]&amp;#x27;)) return;&#10;        interruptCamera();&#10;        drag = { startX: event.clientX, startY: event.clientY, x: state.x, y: state.y, moved: false };&#10;        container.classList.add(&amp;#x27;is-panning&amp;#x27;);&#10;        try { container.setPointerCapture(event.pointerId); } catch (_) {}&#10;      });&#10;      container.addEventListener(&amp;#x27;pointermove&amp;#x27;, function (event) {&#10;        if (!drag) return;&#10;        var dx = event.clientX - drag.startX;&#10;        var dy = event.clientY - drag.startY;&#10;        if (Math.abs(dx) + Math.abs(dy) &amp;gt; 3) drag.moved = true;&#10;        state.x = drag.x + dx;&#10;        state.y = drag.y + dy;&#10;        apply();&#10;      });&#10;      container.addEventListener(&amp;#x27;pointerup&amp;#x27;, onPointerEnd);&#10;      container.addEventListener(&amp;#x27;pointercancel&amp;#x27;, onPointerEnd);&#10;      container.addEventListener(&amp;#x27;scroll&amp;#x27;, onScroll, { passive: true });&#10;      window.addEventListener(&amp;#x27;resize&amp;#x27;, function () {&#10;        if (resizeFrame) cancelAnimationFrame(resizeFrame);&#10;        resizeFrame = requestAnimationFrame(function () {&#10;          resizeFrame = 0;&#10;          if (state.mode === &amp;#x27;semantic&amp;#x27;) syncSemantic();&#10;          else apply();&#10;        });&#10;      });&#10;      window.addEventListener(&amp;#x27;hashchange&amp;#x27;, function () { requestAnimationFrame(syncSemantic); });&#10;      apply();&#10;      pinControls();&#10;      requestAnimationFrame(syncSemantic);&#10;&#10;      return {&#10;        zoomIn: function () { zoom(state.scale + 0.25); },&#10;        zoomOut: function () { zoom(state.scale - 0.25); },&#10;        reset: reset,&#10;        reveal: reveal,&#10;        centerAt: centerAt,&#10;        logicalViewport: logicalViewport,&#10;        sync: syncSemantic,&#10;        state: function () { return { scale: state.scale, x: state.x, y: state.y, mode: state.mode }; }&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Semantic Radar — simplified semantic bounds + live viewport.&#10;       The radar is built at runtime so the checked artifact still contains&#10;       one canonical SVG block, and export serialization remains untouched.&#10;       ============================================================ */&#10;    Archify.radar = (function () {&#10;      var container = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var diagram = container.querySelector(&amp;#x27;:scope &amp;gt; svg&amp;#x27;);&#10;      var panel = document.getElementById(&amp;#x27;overview-map&amp;#x27;);&#10;      var panelHead = panel.querySelector(&amp;#x27;.overview-map-head&amp;#x27;);&#10;      var surface = document.getElementById(&amp;#x27;overview-map-surface&amp;#x27;);&#10;      var status = document.getElementById(&amp;#x27;overview-map-status&amp;#x27;);&#10;      var trigger = document.getElementById(&amp;#x27;btn-overview-map&amp;#x27;);&#10;      var closeBtn = document.getElementById(&amp;#x27;overview-map-close&amp;#x27;);&#10;      var expandBtn = document.getElementById(&amp;#x27;overview-map-expand&amp;#x27;);&#10;      var feedback = document.getElementById(&amp;#x27;overview-map-feedback&amp;#x27;);&#10;      var navigation = container.querySelector(&amp;#x27;.diagram-nav&amp;#x27;);&#10;      var passport = document.getElementById(&amp;#x27;focus-chip&amp;#x27;);&#10;      var namespace = &amp;#x27;http://www.w3.org/2000/svg&amp;#x27;;&#10;      var viewBox = diagram.viewBox &amp;amp;&amp;amp; diagram.viewBox.baseVal;&#10;      var mapSvg = document.createElementNS(namespace, &amp;#x27;svg&amp;#x27;);&#10;      var nodeLayer = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;      var viewport = document.createElementNS(namespace, &amp;#x27;rect&amp;#x27;);&#10;      var nodes = [];&#10;      var viewportDrag = null;&#10;      var panelDrag = null;&#10;      var manualPosition = null;&#10;      var lastPlacement = null;&#10;      var requestedOpen = false;&#10;      var passportYielded = false;&#10;      var passportPreviousAriaHidden = null;&#10;      var syncFrame = 0;&#10;      var spaceRetryTimer = 0;&#10;      var spaceRetryCount = 0;&#10;      var placementGap = 16;&#10;&#10;      mapSvg.setAttribute(&amp;#x27;role&amp;#x27;, &amp;#x27;group&amp;#x27;);&#10;      mapSvg.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.radar.nodes&amp;#x27;));&#10;      mapSvg.setAttribute(&amp;#x27;preserveAspectRatio&amp;#x27;, &amp;#x27;xMidYMid meet&amp;#x27;);&#10;      nodeLayer.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;overview-map-nodes&amp;#x27;);&#10;      viewport.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;overview-map-viewport&amp;#x27;);&#10;      viewport.setAttribute(&amp;#x27;rx&amp;#x27;, &amp;#x27;3&amp;#x27;);&#10;      viewport.setAttribute(&amp;#x27;ry&amp;#x27;, &amp;#x27;3&amp;#x27;);&#10;      mapSvg.appendChild(nodeLayer);&#10;      mapSvg.appendChild(viewport);&#10;      surface.appendChild(mapSvg);&#10;&#10;      function nodeLabel(node, fallback) {&#10;        return node.getAttribute(&amp;#x27;data-node-label&amp;#x27;) ||&#10;          (node.getAttribute(&amp;#x27;aria-label&amp;#x27;) || fallback).replace(/^Focus\s+/, &amp;#x27;&amp;#x27;).split(&amp;#x27;,&amp;#x27;)[0];&#10;      }&#10;      function build() {&#10;        if (!viewBox || viewBox.width &amp;lt;= 0 || viewBox.height &amp;lt;= 0) return false;&#10;        mapSvg.setAttribute(&amp;#x27;viewBox&amp;#x27;, [viewBox.x, viewBox.y, viewBox.width, viewBox.height].join(&amp;#x27; &amp;#x27;));&#10;        nodeLayer.textContent = &amp;#x27;&amp;#x27;;&#10;        nodes = [];&#10;        Array.prototype.forEach.call(diagram.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;), function (node) {&#10;          var box;&#10;          try { box = node.getBBox(); } catch (_) { box = null; }&#10;          if (!box || box.width &amp;lt;= 0 || box.height &amp;lt;= 0) return;&#10;          var id = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;          var rect = document.createElementNS(namespace, &amp;#x27;rect&amp;#x27;);&#10;          rect.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;overview-map-node&amp;#x27;);&#10;          rect.setAttribute(&amp;#x27;x&amp;#x27;, String(box.x));&#10;          rect.setAttribute(&amp;#x27;y&amp;#x27;, String(box.y));&#10;          rect.setAttribute(&amp;#x27;width&amp;#x27;, String(Math.max(3, box.width)));&#10;          rect.setAttribute(&amp;#x27;height&amp;#x27;, String(Math.max(3, box.height)));&#10;          rect.setAttribute(&amp;#x27;rx&amp;#x27;, String(Math.max(2, Math.min(8, Math.min(box.width, box.height) * 0.1))));&#10;          rect.setAttribute(&amp;#x27;data-radar-node-id&amp;#x27;, id);&#10;          rect.setAttribute(&amp;#x27;data-kind&amp;#x27;, node.getAttribute(&amp;#x27;data-node-kind&amp;#x27;) || &amp;#x27;neutral&amp;#x27;);&#10;          rect.setAttribute(&amp;#x27;tabindex&amp;#x27;, &amp;#x27;0&amp;#x27;);&#10;          rect.setAttribute(&amp;#x27;role&amp;#x27;, &amp;#x27;button&amp;#x27;);&#10;          rect.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.radar.focus&amp;#x27;, { label: nodeLabel(node, id) }));&#10;          nodeLayer.appendChild(rect);&#10;          nodes.push({ id: id, node: node, rect: rect });&#10;        });&#10;        status.textContent = viewerText(&amp;#x27;viewer.radar.fullMap&amp;#x27;, { count: nodes.length });&#10;        return true;&#10;      }&#10;      function visibleRect(element) {&#10;        if (!element || element.hidden) return null;&#10;        var rect = element.getBoundingClientRect();&#10;        if (rect.width &amp;lt;= 0 || rect.height &amp;lt;= 0 || rect.right &amp;lt;= 0 || rect.bottom &amp;lt;= 0 || rect.left &amp;gt;= window.innerWidth || rect.top &amp;gt;= window.innerHeight) return null;&#10;        return { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom, width: rect.width, height: rect.height };&#10;      }&#10;      function panelRectAt(position) {&#10;        return {&#10;          left: position.left,&#10;          top: position.top,&#10;          right: position.left + panel.offsetWidth,&#10;          bottom: position.top + panel.offsetHeight,&#10;          width: panel.offsetWidth,&#10;          height: panel.offsetHeight&#10;        };&#10;      }&#10;      function rectsIntersect(first, second, gap) {&#10;        gap = Number(gap) || 0;&#10;        return first.left &amp;lt; second.right + gap &amp;amp;&amp;amp;&#10;          first.right &amp;gt; second.left - gap &amp;amp;&amp;amp;&#10;          first.top &amp;lt; second.bottom + gap &amp;amp;&amp;amp;&#10;          first.bottom &amp;gt; second.top - gap;&#10;      }&#10;      function intersectionArea(first, second) {&#10;        var width = Math.max(0, Math.min(first.right, second.right) - Math.max(first.left, second.left));&#10;        var height = Math.max(0, Math.min(first.bottom, second.bottom) - Math.max(first.top, second.top));&#10;        return width * height;&#10;      }&#10;      function clamp(value, minimum, maximum) {&#10;        if (maximum &amp;lt; minimum) return minimum;&#10;        return Math.max(minimum, Math.min(maximum, value));&#10;      }&#10;      function placementContext() {&#10;        var containerRect = visibleRect(container);&#10;        if (!containerRect) return null;&#10;        var controlRect = visibleRect(navigation);&#10;        var left = Math.max(placementGap, containerRect.left + placementGap);&#10;        var top = Math.max(placementGap, containerRect.top + placementGap);&#10;        var right = Math.min(window.innerWidth - placementGap, containerRect.right - placementGap);&#10;        var bottom = Math.min(window.innerHeight - placementGap, containerRect.bottom - placementGap);&#10;        if (controlRect) bottom = Math.min(bottom, controlRect.top - placementGap);&#10;        var lens = document.getElementById(&amp;#x27;focus-chip&amp;#x27;);&#10;        var lensRect = visibleRect(lens);&#10;        var legendRect = visibleRect(diagram.querySelector(&amp;#x27;[data-legend]&amp;#x27;));&#10;        var active = diagram.querySelector(&amp;#x27;[data-focus-selected]&amp;#x27;);&#10;        var activeRect = visibleRect(active);&#10;        return {&#10;          bounds: { left: left, top: top, right: right, bottom: bottom },&#10;          hardBlockers: [lensRect, controlRect, legendRect].filter(Boolean),&#10;          softBlockers: [activeRect].filter(Boolean),&#10;          preferredSide: !activeRect || activeRect.left + activeRect.width / 2 &amp;gt; window.innerWidth / 2 ? &amp;#x27;left&amp;#x27; : &amp;#x27;right&amp;#x27;&#10;        };&#10;      }&#10;      function positionIsValid(position, context) {&#10;        if (!position || !context) return false;&#10;        var rect = panelRectAt(position);&#10;        var bounds = context.bounds;&#10;        if (rect.left &amp;lt; bounds.left || rect.top &amp;lt; bounds.top || rect.right &amp;gt; bounds.right || rect.bottom &amp;gt; bounds.bottom) return false;&#10;        return context.hardBlockers.every(function (blocker) { return !rectsIntersect(rect, blocker, placementGap); });&#10;      }&#10;      function cornerCandidates(context) {&#10;        var bounds = context.bounds;&#10;        var left = bounds.left;&#10;        var right = Math.max(left, bounds.right - panel.offsetWidth);&#10;        var top = bounds.top;&#10;        var bottom = Math.max(top, bounds.bottom - panel.offsetHeight);&#10;        var preferredLeft = context.preferredSide === &amp;#x27;left&amp;#x27; ? left : right;&#10;        var alternateLeft = context.preferredSide === &amp;#x27;left&amp;#x27; ? right : left;&#10;        return [&#10;          { left: preferredLeft, top: bottom },&#10;          { left: alternateLeft, top: bottom },&#10;          { left: preferredLeft, top: top },&#10;          { left: alternateLeft, top: top }&#10;        ].filter(function (candidate, index, all) {&#10;          return all.findIndex(function (other) { return other.left === candidate.left &amp;amp;&amp;amp; other.top === candidate.top; }) === index;&#10;        });&#10;      }&#10;      function nearbyCandidates(context, reference) {&#10;        var bounds = context.bounds;&#10;        var maximumLeft = bounds.right - panel.offsetWidth;&#10;        var maximumTop = bounds.bottom - panel.offsetHeight;&#10;        var requested = reference ? {&#10;          left: clamp(reference.left, bounds.left, maximumLeft),&#10;          top: clamp(reference.top, bounds.top, maximumTop)&#10;        } : null;&#10;        var horizontal = [bounds.left, maximumLeft];&#10;        var vertical = [bounds.top, maximumTop];&#10;        if (requested) {&#10;          horizontal.push(requested.left);&#10;          vertical.push(requested.top);&#10;        }&#10;        context.hardBlockers.forEach(function (blocker) {&#10;          horizontal.push(&#10;            blocker.left - placementGap - panel.offsetWidth,&#10;            blocker.right + placementGap&#10;          );&#10;          vertical.push(&#10;            blocker.top - placementGap - panel.offsetHeight,&#10;            blocker.bottom + placementGap&#10;          );&#10;        });&#10;        horizontal = horizontal.map(function (left) { return clamp(left, bounds.left, maximumLeft); });&#10;        vertical = vertical.map(function (top) { return clamp(top, bounds.top, maximumTop); });&#10;        var candidates = [];&#10;        horizontal.forEach(function (left) {&#10;          vertical.forEach(function (top) { candidates.push({ left: left, top: top }); });&#10;        });&#10;        return candidates.filter(function (candidate, index, all) {&#10;          return all.findIndex(function (other) { return other.left === candidate.left &amp;amp;&amp;amp; other.top === candidate.top; }) === index;&#10;        });&#10;      }&#10;      function placementScore(position, context, reference, softWeight) {&#10;        var rect = panelRectAt(position);&#10;        var referenceLeft = reference ? reference.left : (context.preferredSide === &amp;#x27;left&amp;#x27; ? context.bounds.left : context.bounds.right - panel.offsetWidth);&#10;        var referenceTop = reference ? reference.top : context.bounds.bottom - panel.offsetHeight;&#10;        var distance = Math.pow(position.left - referenceLeft, 2) + Math.pow(position.top - referenceTop, 2);&#10;        var softOverlap = context.softBlockers.reduce(function (total, blocker) { return total + intersectionArea(rect, blocker); }, 0);&#10;        return distance + softOverlap * softWeight;&#10;      }&#10;      function chooseRadarPlacement(context, reference, options) {&#10;        options = options || {};&#10;        var softWeight = Number.isFinite(options.softWeight) ? options.softWeight : 100;&#10;        var candidates = nearbyCandidates(context, reference).concat(cornerCandidates(context));&#10;        var valid = candidates.filter(function (candidate) { return positionIsValid(candidate, context); });&#10;        valid.sort(function (first, second) {&#10;          return placementScore(first, context, reference, softWeight) - placementScore(second, context, reference, softWeight);&#10;        });&#10;        return valid.length ? valid[0] : null;&#10;      }&#10;      function applyPlacement(position, remember) {&#10;        var useLeft = position.left + panel.offsetWidth / 2 &amp;lt;= window.innerWidth / 2;&#10;        panel.setAttribute(&amp;#x27;data-docked&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        panel.setAttribute(&amp;#x27;data-dock-side&amp;#x27;, useLeft ? &amp;#x27;left&amp;#x27; : &amp;#x27;right&amp;#x27;);&#10;        if (useLeft) {&#10;          panel.style.setProperty(&amp;#x27;--archify-radar-left&amp;#x27;, Math.round(position.left) + &amp;#x27;px&amp;#x27;);&#10;          panel.style.removeProperty(&amp;#x27;--archify-radar-right&amp;#x27;);&#10;        } else {&#10;          panel.style.setProperty(&amp;#x27;--archify-radar-right&amp;#x27;, Math.round(window.innerWidth - position.left - panel.offsetWidth) + &amp;#x27;px&amp;#x27;);&#10;          panel.style.removeProperty(&amp;#x27;--archify-radar-left&amp;#x27;);&#10;        }&#10;        panel.style.setProperty(&amp;#x27;--archify-radar-top&amp;#x27;, Math.round(position.top) + &amp;#x27;px&amp;#x27;);&#10;        if (remember !== false) lastPlacement = { left: position.left, top: position.top };&#10;      }&#10;      function resetDockingStyles() {&#10;        panel.removeAttribute(&amp;#x27;data-docked&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-dock-side&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-panel-dragging&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-placement-invalid&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-placement-degraded&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-placement-unavailable&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-compact&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;title&amp;#x27;);&#10;        panel.style.removeProperty(&amp;#x27;visibility&amp;#x27;);&#10;        panel.style.removeProperty(&amp;#x27;--archify-radar-right&amp;#x27;);&#10;        panel.style.removeProperty(&amp;#x27;--archify-radar-left&amp;#x27;);&#10;        panel.style.removeProperty(&amp;#x27;--archify-radar-top&amp;#x27;);&#10;      }&#10;      function updateDocking() {&#10;        var options = arguments[0] || {};&#10;        if (panel.hidden) return false;&#10;        if (panelDrag) return true;&#10;        panel.removeAttribute(&amp;#x27;data-compact&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-placement-degraded&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-placement-invalid&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-placement-unavailable&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;title&amp;#x27;);&#10;        panel.style.removeProperty(&amp;#x27;visibility&amp;#x27;);&#10;        var context = placementContext();&#10;        if (!context) {&#10;          resetDockingStyles();&#10;          return false;&#10;        }&#10;        var reference = manualPosition || lastPlacement;&#10;        var placementOptions = { softWeight: manualPosition ? 0 : 100 };&#10;        var placement = manualPosition &amp;amp;&amp;amp; positionIsValid(manualPosition, context)&#10;          ? manualPosition&#10;          : chooseRadarPlacement(context, reference, placementOptions);&#10;        var compact = false;&#10;        if (!placement &amp;amp;&amp;amp; options.allowCompact !== false) {&#10;          compact = true;&#10;          panel.setAttribute(&amp;#x27;data-compact&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          panel.setAttribute(&amp;#x27;data-placement-degraded&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          panel.setAttribute(&amp;#x27;title&amp;#x27;, viewerText(&amp;#x27;viewer.radar.compacted&amp;#x27;));&#10;          context = placementContext();&#10;          placement = chooseRadarPlacement(context, reference, placementOptions);&#10;        }&#10;        if (!placement) {&#10;          resetDockingStyles();&#10;          panel.setAttribute(&amp;#x27;data-placement-unavailable&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          return false;&#10;        }&#10;        if (manualPosition &amp;amp;&amp;amp; !compact) manualPosition = { left: placement.left, top: placement.top };&#10;        applyPlacement(placement, true);&#10;        return true;&#10;      }&#10;      function clearSpaceRetry() {&#10;        if (spaceRetryTimer) window.clearTimeout(spaceRetryTimer);&#10;        spaceRetryTimer = 0;&#10;      }&#10;      function yieldPassport() {&#10;        if (!passport || passport.hidden || passportYielded) return passportYielded;&#10;        passportPreviousAriaHidden = passport.getAttribute(&amp;#x27;aria-hidden&amp;#x27;);&#10;        passportYielded = true;&#10;        passport.setAttribute(&amp;#x27;data-radar-yielded&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        passport.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        return true;&#10;      }&#10;      function restorePassport() {&#10;        if (!passport || !passportYielded) return;&#10;        passportYielded = false;&#10;        passport.removeAttribute(&amp;#x27;data-radar-yielded&amp;#x27;);&#10;        if (passportPreviousAriaHidden === null) passport.removeAttribute(&amp;#x27;aria-hidden&amp;#x27;);&#10;        else passport.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, passportPreviousAriaHidden);&#10;        passportPreviousAriaHidden = null;&#10;      }&#10;      function reflectVisible() {&#10;        panel.hidden = false;&#10;        panel.removeAttribute(&amp;#x27;data-placement-unavailable&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        trigger.removeAttribute(&amp;#x27;data-radar-space-limited&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.radar.close&amp;#x27;));&#10;        trigger.title = viewerText(&amp;#x27;viewer.nav.radar.title&amp;#x27;);&#10;        feedback.hidden = true;&#10;      }&#10;      function scheduleSpaceRetry() {&#10;        if (!requestedOpen || spaceRetryTimer || spaceRetryCount &amp;gt;= 4) return;&#10;        spaceRetryCount += 1;&#10;        spaceRetryTimer = window.setTimeout(function () {&#10;          spaceRetryTimer = 0;&#10;          attemptRequestedOpen();&#10;        }, 60);&#10;      }&#10;      function reflectUnavailable() {&#10;        restorePassport();&#10;        panel.hidden = true;&#10;        panel.setAttribute(&amp;#x27;data-placement-unavailable&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.radar.cancelWaiting&amp;#x27;));&#10;        trigger.setAttribute(&amp;#x27;data-radar-space-limited&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        trigger.title = viewerText(&amp;#x27;viewer.radar.needsSpace&amp;#x27;);&#10;        feedback.hidden = false;&#10;        scheduleSpaceRetry();&#10;      }&#10;      function attemptRequestedOpen(options) {&#10;        options = options || {};&#10;        if (!requestedOpen) return false;&#10;        panel.hidden = false;&#10;        if (!updateDocking(options)) {&#10;          reflectUnavailable();&#10;          return false;&#10;        }&#10;        clearSpaceRetry();&#10;        spaceRetryCount = 0;&#10;        reflectVisible();&#10;        sync();&#10;        if (options.focus === true &amp;amp;&amp;amp; !panel.hasAttribute(&amp;#x27;data-compact&amp;#x27;)) surface.focus();&#10;        return true;&#10;      }&#10;      function expandCompactRadar() {&#10;        if (!requestedOpen || panel.hidden || !panel.hasAttribute(&amp;#x27;data-compact&amp;#x27;)) return false;&#10;        yieldPassport();&#10;        if (!updateDocking({ allowCompact: false })) {&#10;          restorePassport();&#10;          if (!updateDocking()) {&#10;            reflectUnavailable();&#10;            return false;&#10;          }&#10;        }&#10;        reflectVisible();&#10;        sync();&#10;        if (!panel.hasAttribute(&amp;#x27;data-compact&amp;#x27;)) surface.focus();&#10;        return !panel.hasAttribute(&amp;#x27;data-compact&amp;#x27;);&#10;      }&#10;      function syncNow() {&#10;        syncFrame = 0;&#10;        if (panel.hidden || !Archify.view || typeof Archify.view.logicalViewport !== &amp;#x27;function&amp;#x27;) return;&#10;        if (!updateDocking()) {&#10;          reflectUnavailable();&#10;          return;&#10;        }&#10;        if (passportYielded &amp;amp;&amp;amp; panel.hasAttribute(&amp;#x27;data-compact&amp;#x27;)) {&#10;          restorePassport();&#10;          if (!updateDocking()) {&#10;            reflectUnavailable();&#10;            return;&#10;          }&#10;        }&#10;        reflectVisible();&#10;        var visible = Archify.view.logicalViewport();&#10;        if (!visible) return;&#10;        viewport.setAttribute(&amp;#x27;x&amp;#x27;, String(visible.x));&#10;        viewport.setAttribute(&amp;#x27;y&amp;#x27;, String(visible.y));&#10;        viewport.setAttribute(&amp;#x27;width&amp;#x27;, String(visible.width));&#10;        viewport.setAttribute(&amp;#x27;height&amp;#x27;, String(visible.height));&#10;        var full = visible.width &amp;gt;= viewBox.width * 0.98 &amp;amp;&amp;amp; visible.height &amp;gt;= viewBox.height * 0.98;&#10;        var mobileWide = window.innerWidth &amp;lt;= 720 &amp;amp;&amp;amp; container.hasAttribute(&amp;#x27;data-wide-diagram&amp;#x27;);&#10;        var viewportCopy = full&#10;          ? viewerText(&amp;#x27;viewer.radar.viewport.full&amp;#x27;)&#10;          : (mobileWide&#10;            ? viewerText(&amp;#x27;viewer.radar.viewport.width&amp;#x27;, { percent: Math.round(visible.width / viewBox.width * 100) })&#10;            : viewerText(&amp;#x27;viewer.radar.viewport.scale&amp;#x27;, { percent: Math.round(visible.scale * 100) }));&#10;        status.textContent = viewerText(&amp;#x27;viewer.radar.status&amp;#x27;, { count: nodes.length, viewport: viewportCopy });&#10;        nodes.forEach(function (item) {&#10;          var active = item.node.hasAttribute(&amp;#x27;data-focus-selected&amp;#x27;) ||&#10;            item.node.getAttribute(&amp;#x27;data-story-beat-state&amp;#x27;) === &amp;#x27;active&amp;#x27;;&#10;          if (active) item.rect.setAttribute(&amp;#x27;data-radar-active&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          else item.rect.removeAttribute(&amp;#x27;data-radar-active&amp;#x27;);&#10;        });&#10;      }&#10;      function sync() {&#10;        if (requestedOpen &amp;amp;&amp;amp; panel.hidden) {&#10;          attemptRequestedOpen();&#10;          return;&#10;        }&#10;        if (syncFrame) return;&#10;        syncFrame = requestAnimationFrame(syncNow);&#10;      }&#10;      function setOpen(next, options) {&#10;        options = options || {};&#10;        next = Boolean(next);&#10;        if (next &amp;amp;&amp;amp; Archify.semanticLens &amp;amp;&amp;amp; typeof Archify.semanticLens.clearPreview === &amp;#x27;function&amp;#x27;) Archify.semanticLens.clearPreview();&#10;        if (next &amp;amp;&amp;amp; Archify.semanticLens &amp;amp;&amp;amp; Archify.semanticLens.isOpen()) {&#10;          Archify.semanticLens.close({ restoreFocus: false });&#10;        }&#10;        requestedOpen = next;&#10;        if (next) {&#10;          clearSpaceRetry();&#10;          spaceRetryCount = 0;&#10;          build();&#10;          attemptRequestedOpen(options);&#10;        } else {&#10;          clearSpaceRetry();&#10;          spaceRetryCount = 0;&#10;          viewportDrag = null;&#10;          panelDrag = null;&#10;          container.classList.remove(&amp;#x27;is-panning&amp;#x27;);&#10;          panel.hidden = true;&#10;          resetDockingStyles();&#10;          restorePassport();&#10;          feedback.hidden = true;&#10;          trigger.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;          trigger.removeAttribute(&amp;#x27;data-radar-space-limited&amp;#x27;);&#10;          trigger.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.nav.radar&amp;#x27;));&#10;          trigger.title = viewerText(&amp;#x27;viewer.nav.radar.title&amp;#x27;);&#10;          if (options.restoreFocus === true) trigger.focus();&#10;        }&#10;        return next;&#10;      }&#10;      function toggle() { return setOpen(!requestedOpen, { focus: false }); }&#10;      function close(options) { return setOpen(false, options); }&#10;      function bringNodeIntoWindow(node) {&#10;        var delay = window.matchMedia &amp;amp;&amp;amp; window.matchMedia(&amp;#x27;(prefers-reduced-motion: reduce)&amp;#x27;).matches ? 0 : 540;&#10;        window.setTimeout(function () {&#10;          var rect = node.getBoundingClientRect();&#10;          var safeTop = 64;&#10;          var safeBottom = window.innerHeight - 64;&#10;          if (rect.top &amp;gt;= safeTop &amp;amp;&amp;amp; rect.bottom &amp;lt;= safeBottom) return;&#10;          var top = Math.max(0, window.scrollY + rect.top + rect.height / 2 - window.innerHeight / 2);&#10;          try { window.scrollTo({ top: top, behavior: delay ? &amp;#x27;smooth&amp;#x27; : &amp;#x27;auto&amp;#x27; }); }&#10;          catch (_) { window.scrollTo(0, top); }&#10;        }, delay);&#10;      }&#10;      function focusNode(id) {&#10;        var main = diagram.querySelector(&amp;#x27;[data-node-id=&amp;quot;&amp;#x27; + id + &amp;#x27;&amp;quot;]&amp;#x27;);&#10;        if (!main) return false;&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; typeof Archify.guidedViews.showAll === &amp;#x27;function&amp;#x27;) {&#10;          Archify.guidedViews.showAll({ clearFocus: false, updateUrl: false });&#10;        }&#10;        if (Archify.focus &amp;amp;&amp;amp; typeof Archify.focus.set === &amp;#x27;function&amp;#x27;) {&#10;          Archify.focus.set(id, { toggle: false });&#10;        }&#10;        if (Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reveal([id], { includeNeighbors: true, reason: &amp;#x27;radar&amp;#x27; });&#10;        }&#10;        bringNodeIntoWindow(main);&#10;        try { main.focus({ preventScroll: true }); } catch (_) { try { main.focus(); } catch (_) {} }&#10;        sync();&#10;        return true;&#10;      }&#10;      function diagramPoint(event) {&#10;        var matrix = mapSvg.getScreenCTM();&#10;        if (!matrix) return null;&#10;        var point = mapSvg.createSVGPoint();&#10;        point.x = event.clientX;&#10;        point.y = event.clientY;&#10;        return point.matrixTransform(matrix.inverse());&#10;      }&#10;      function navigate(event) {&#10;        var point = diagramPoint(event);&#10;        if (!point || !Archify.view || typeof Archify.view.centerAt !== &amp;#x27;function&amp;#x27;) return;&#10;        Archify.view.centerAt(point.x, point.y, { minimumScale: 1.5, instant: true });&#10;        sync();&#10;      }&#10;      function endViewportDrag(event) {&#10;        if (!viewportDrag) return;&#10;        viewportDrag = null;&#10;        panel.removeAttribute(&amp;#x27;data-dragging&amp;#x27;);&#10;        container.classList.remove(&amp;#x27;is-panning&amp;#x27;);&#10;        try { surface.releasePointerCapture(event.pointerId); } catch (_) {}&#10;      }&#10;      function beginPanelDrag(event) {&#10;        if (event.button !== 0 || event.target.closest(&amp;#x27;button, a, input, [role=&amp;quot;button&amp;quot;]&amp;#x27;)) return;&#10;        var context = placementContext();&#10;        if (!context) return;&#10;        var rect = panel.getBoundingClientRect();&#10;        event.preventDefault();&#10;        event.stopPropagation();&#10;        panelDrag = {&#10;          pointerId: event.pointerId,&#10;          originX: event.clientX,&#10;          originY: event.clientY,&#10;          start: { left: rect.left, top: rect.top },&#10;          current: { left: rect.left, top: rect.top },&#10;          previousManual: manualPosition ? { left: manualPosition.left, top: manualPosition.top } : null&#10;        };&#10;        panel.setAttribute(&amp;#x27;data-panel-dragging&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        try { panelHead.setPointerCapture(event.pointerId); } catch (_) {}&#10;      }&#10;      function movePanelDrag(event) {&#10;        if (!panelDrag || panelDrag.pointerId !== event.pointerId) return;&#10;        var context = placementContext();&#10;        if (!context) return;&#10;        event.preventDefault();&#10;        event.stopPropagation();&#10;        var bounds = context.bounds;&#10;        var position = {&#10;          left: clamp(panelDrag.start.left + event.clientX - panelDrag.originX, bounds.left, bounds.right - panel.offsetWidth),&#10;          top: clamp(panelDrag.start.top + event.clientY - panelDrag.originY, bounds.top, bounds.bottom - panel.offsetHeight)&#10;        };&#10;        panelDrag.current = position;&#10;        if (positionIsValid(position, context)) panel.removeAttribute(&amp;#x27;data-placement-invalid&amp;#x27;);&#10;        else panel.setAttribute(&amp;#x27;data-placement-invalid&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        applyPlacement(position, false);&#10;      }&#10;      function finishPanelDrag(event, cancel) {&#10;        if (!panelDrag || panelDrag.pointerId !== event.pointerId) return;&#10;        event.preventDefault();&#10;        event.stopPropagation();&#10;        var activeDrag = panelDrag;&#10;        panelDrag = null;&#10;        panel.removeAttribute(&amp;#x27;data-panel-dragging&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-placement-invalid&amp;#x27;);&#10;        try { panelHead.releasePointerCapture(event.pointerId); } catch (_) {}&#10;        var context = placementContext();&#10;        if (!context) return;&#10;        if (cancel) {&#10;          manualPosition = activeDrag.previousManual;&#10;          lastPlacement = { left: activeDrag.start.left, top: activeDrag.start.top };&#10;          updateDocking();&#10;          return;&#10;        }&#10;        var requested = activeDrag.current;&#10;        manualPosition = { left: requested.left, top: requested.top };&#10;        updateDocking();&#10;      }&#10;&#10;      trigger.addEventListener(&amp;#x27;click&amp;#x27;, toggle);&#10;      closeBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { close({ restoreFocus: true }); });&#10;      expandBtn.addEventListener(&amp;#x27;click&amp;#x27;, expandCompactRadar);&#10;      panelHead.addEventListener(&amp;#x27;pointerdown&amp;#x27;, beginPanelDrag);&#10;      panelHead.addEventListener(&amp;#x27;pointermove&amp;#x27;, movePanelDrag);&#10;      panelHead.addEventListener(&amp;#x27;pointerup&amp;#x27;, function (event) { finishPanelDrag(event, false); });&#10;      panelHead.addEventListener(&amp;#x27;pointercancel&amp;#x27;, function (event) { finishPanelDrag(event, true); });&#10;      surface.addEventListener(&amp;#x27;pointerdown&amp;#x27;, function (event) {&#10;        if (event.button !== 0 || event.target.closest(&amp;#x27;[data-radar-node-id]&amp;#x27;)) return;&#10;        event.preventDefault();&#10;        viewportDrag = { pointerId: event.pointerId };&#10;        panel.setAttribute(&amp;#x27;data-dragging&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        container.classList.add(&amp;#x27;is-panning&amp;#x27;);&#10;        try { surface.setPointerCapture(event.pointerId); } catch (_) {}&#10;        navigate(event);&#10;      });&#10;      surface.addEventListener(&amp;#x27;pointermove&amp;#x27;, function (event) {&#10;        if (!viewportDrag || viewportDrag.pointerId !== event.pointerId) return;&#10;        navigate(event);&#10;      });&#10;      surface.addEventListener(&amp;#x27;pointerup&amp;#x27;, endViewportDrag);&#10;      surface.addEventListener(&amp;#x27;pointercancel&amp;#x27;, endViewportDrag);&#10;      surface.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        var node = event.target.closest(&amp;#x27;[data-radar-node-id]&amp;#x27;);&#10;        if (node) focusNode(node.getAttribute(&amp;#x27;data-radar-node-id&amp;#x27;));&#10;      });&#10;      surface.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        if (event.key === &amp;#x27;Escape&amp;#x27;) {&#10;          event.preventDefault();&#10;          event.stopPropagation();&#10;          close({ restoreFocus: true });&#10;          return;&#10;        }&#10;        var node = event.target.closest(&amp;#x27;[data-radar-node-id]&amp;#x27;);&#10;        if (node &amp;amp;&amp;amp; (event.key === &amp;#x27;Enter&amp;#x27; || event.key === &amp;#x27; &amp;#x27;)) {&#10;          event.preventDefault();&#10;          focusNode(node.getAttribute(&amp;#x27;data-radar-node-id&amp;#x27;));&#10;          return;&#10;        }&#10;        if (event.key !== &amp;#x27;ArrowLeft&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;ArrowRight&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;ArrowUp&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;ArrowDown&amp;#x27;) return;&#10;        var visible = Archify.view &amp;amp;&amp;amp; Archify.view.logicalViewport ? Archify.view.logicalViewport() : null;&#10;        if (!visible) return;&#10;        event.preventDefault();&#10;        var x = visible.x + visible.width / 2;&#10;        var y = visible.y + visible.height / 2;&#10;        var stepX = Math.max(12, visible.width * 0.24);&#10;        var stepY = Math.max(12, visible.height * 0.24);&#10;        if (event.key === &amp;#x27;ArrowLeft&amp;#x27;) x -= stepX;&#10;        else if (event.key === &amp;#x27;ArrowRight&amp;#x27;) x += stepX;&#10;        else if (event.key === &amp;#x27;ArrowUp&amp;#x27;) y -= stepY;&#10;        else y += stepY;&#10;        Archify.view.centerAt(x, y, { minimumScale: 1.5, instant: true });&#10;        sync();&#10;      });&#10;      document.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        if (!panelDrag || event.key !== &amp;#x27;Escape&amp;#x27;) return;&#10;        finishPanelDrag({&#10;          pointerId: panelDrag.pointerId,&#10;          preventDefault: function () { event.preventDefault(); },&#10;          stopPropagation: function () { event.stopPropagation(); }&#10;        }, true);&#10;      }, true);&#10;      function reflow() {&#10;        if (!requestedOpen) return;&#10;        clearSpaceRetry();&#10;        spaceRetryCount = 0;&#10;        sync();&#10;      }&#10;      window.addEventListener(&amp;#x27;resize&amp;#x27;, reflow);&#10;      window.addEventListener(&amp;#x27;scroll&amp;#x27;, reflow, { passive: true });&#10;      if (typeof ResizeObserver === &amp;#x27;function&amp;#x27;) {&#10;        var radarResizeObserver = new ResizeObserver(function (entries) {&#10;          if (!requestedOpen) return;&#10;          if (panel.hidden &amp;amp;&amp;amp; entries.every(function (entry) { return entry.target === panel; })) return;&#10;          reflow();&#10;        });&#10;        [container, navigation, document.getElementById(&amp;#x27;focus-chip&amp;#x27;), panel].filter(Boolean).forEach(function (element) {&#10;          radarResizeObserver.observe(element);&#10;        });&#10;      }&#10;      requestAnimationFrame(build);&#10;&#10;      return {&#10;        open: function () { return setOpen(true); },&#10;        close: close,&#10;        toggle: toggle,&#10;        sync: sync,&#10;        focus: focusNode,&#10;        isOpen: function () { return requestedOpen; },&#10;        count: function () { return nodes.length; }&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Presentation Stage — a shareable, viewport-filling live view.&#10;       It changes only HTML layout and URL state; SVG semantics and export&#10;       serialization remain untouched. Escape first clears an active guided&#10;       view/focus, then exits the stage.&#10;       ============================================================ */&#10;    Archify.presentation = (function () {&#10;      var html = document.documentElement;&#10;      var btn = document.getElementById(&amp;#x27;btn-present&amp;#x27;);&#10;      var label = document.getElementById(&amp;#x27;present-label&amp;#x27;);&#10;      var previousScrollY = 0;&#10;&#10;      function active() { return html.getAttribute(&amp;#x27;data-present&amp;#x27;) === &amp;#x27;true&amp;#x27;; }&#10;&#10;      function updateUrl(next) {&#10;        try {&#10;          var url = new URL(window.location.href);&#10;          if (next) url.searchParams.set(&amp;#x27;present&amp;#x27;, &amp;#x27;1&amp;#x27;);&#10;          else url.searchParams.delete(&amp;#x27;present&amp;#x27;);&#10;          history.replaceState(null, &amp;#x27;&amp;#x27;, url.pathname + url.search + url.hash);&#10;        } catch (_) {}&#10;      }&#10;&#10;      function render(next) {&#10;        btn.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, next ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;        btn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(next ? &amp;#x27;viewer.present.exit&amp;#x27; : &amp;#x27;viewer.present.enter&amp;#x27;));&#10;        btn.title = viewerText(next ? &amp;#x27;viewer.present.exit.title&amp;#x27; : &amp;#x27;viewer.present.enter.title&amp;#x27;);&#10;        label.textContent = viewerText(next ? &amp;#x27;viewer.present.exit.label&amp;#x27; : &amp;#x27;viewer.present.present&amp;#x27;);&#10;      }&#10;&#10;      function setActive(next, options) {&#10;        options = options || {};&#10;        next = Boolean(next);&#10;        if (next === active()) {&#10;          render(next);&#10;          return next;&#10;        }&#10;        if (next) {&#10;          if (Archify.semanticLens &amp;amp;&amp;amp; typeof Archify.semanticLens.clearPreview === &amp;#x27;function&amp;#x27;) Archify.semanticLens.clearPreview();&#10;          previousScrollY = window.scrollY || 0;&#10;          html.setAttribute(&amp;#x27;data-present&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          try { window.scrollTo(0, 0); } catch (_) {}&#10;        } else {&#10;          html.removeAttribute(&amp;#x27;data-present&amp;#x27;);&#10;        }&#10;        render(next);&#10;        if (options.updateUrl !== false) updateUrl(next);&#10;        requestAnimationFrame(function () {&#10;          if (Archify.view &amp;amp;&amp;amp; typeof Archify.view.reset === &amp;#x27;function&amp;#x27;) {&#10;            Archify.view.reset({ automatic: true });&#10;            requestAnimationFrame(function () {&#10;              if (Archify.view &amp;amp;&amp;amp; typeof Archify.view.sync === &amp;#x27;function&amp;#x27;) Archify.view.sync();&#10;            });&#10;          }&#10;          if (!next &amp;amp;&amp;amp; previousScrollY) {&#10;            try { window.scrollTo(0, previousScrollY); } catch (_) {}&#10;          }&#10;        });&#10;        return next;&#10;      }&#10;&#10;      function toggle() { return setActive(!active()); }&#10;&#10;      render(active());&#10;      btn.addEventListener(&amp;#x27;click&amp;#x27;, toggle);&#10;&#10;      return {&#10;        enter: function () { return setActive(true); },&#10;        exit: function () { return setActive(false); },&#10;        toggle: toggle,&#10;        active: active&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Node Finder — stable-ID search over the existing semantic SVG.&#10;       Search never changes the IR or SVG geometry: selecting a result resets&#10;       the viewport, releases a guided view, and delegates to semantic focus.&#10;       ============================================================ */&#10;    Archify.finder = (function () {&#10;      var html = document.documentElement;&#10;      var container = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var svg = container.querySelector(&amp;#x27;svg&amp;#x27;);&#10;      var trigger = document.getElementById(&amp;#x27;btn-node-finder&amp;#x27;);&#10;      var panel = document.getElementById(&amp;#x27;node-finder&amp;#x27;);&#10;      var heading = document.getElementById(&amp;#x27;node-finder-title&amp;#x27;);&#10;      var closeBtn = document.getElementById(&amp;#x27;node-finder-close&amp;#x27;);&#10;      var input = document.getElementById(&amp;#x27;node-finder-input&amp;#x27;);&#10;      var results = document.getElementById(&amp;#x27;node-finder-results&amp;#x27;);&#10;      var empty = document.getElementById(&amp;#x27;node-finder-empty&amp;#x27;);&#10;      var status = document.getElementById(&amp;#x27;node-finder-status&amp;#x27;);&#10;      var visibleItems = [];&#10;&#10;      function defaultContext() {&#10;        return {&#10;          kind: &amp;#x27;focus&amp;#x27;,&#10;          title: viewerText(&amp;#x27;viewer.finder.title&amp;#x27;),&#10;          placeholder: viewerText(&amp;#x27;viewer.finder.placeholder&amp;#x27;),&#10;          empty: viewerText(&amp;#x27;viewer.finder.empty&amp;#x27;),&#10;          resultsLabel: viewerText(&amp;#x27;viewer.finder.results&amp;#x27;),&#10;          availableNoun: viewerText(&amp;#x27;viewer.finder.noun.nodes&amp;#x27;),&#10;          allowedIds: null,&#10;          badges: null&#10;        };&#10;      }&#10;&#10;      var context = defaultContext();&#10;&#10;      function semanticType(node) {&#10;        var authored = node.getAttribute(&amp;#x27;data-node-kind&amp;#x27;);&#10;        if (authored) return authored;&#10;        var types = [&amp;#x27;frontend&amp;#x27;, &amp;#x27;backend&amp;#x27;, &amp;#x27;database&amp;#x27;, &amp;#x27;cloud&amp;#x27;, &amp;#x27;security&amp;#x27;, &amp;#x27;messagebus&amp;#x27;, &amp;#x27;external&amp;#x27;];&#10;        return types.find(function (type) { return node.querySelector(&amp;#x27;.c-&amp;#x27; + type); }) || &amp;#x27;node&amp;#x27;;&#10;      }&#10;&#10;      function connectionsFor(id) {&#10;        var count = 0;&#10;        var seen = {};&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-edge-from][data-edge-to]&amp;#x27;), function (edge) {&#10;          var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;          var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;          var key = from + &amp;#x27;\u0000&amp;#x27; + to;&#10;          if ((from === id || to === id) &amp;amp;&amp;amp; !seen[key]) {&#10;            seen[key] = true;&#10;            count += 1;&#10;          }&#10;        });&#10;        return count;&#10;      }&#10;&#10;      var items = Array.prototype.map.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;), function (node) {&#10;        var id = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;        var label = node.getAttribute(&amp;#x27;data-node-label&amp;#x27;) || (node.getAttribute(&amp;#x27;aria-label&amp;#x27;) || id).replace(/^Focus\s+/, &amp;#x27;&amp;#x27;);&#10;        var text = (node.textContent || &amp;#x27;&amp;#x27;).replace(/\s+/g, &amp;#x27; &amp;#x27;).trim();&#10;        var sublabel = node.getAttribute(&amp;#x27;data-node-sublabel&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;        var context = node.getAttribute(&amp;#x27;data-node-context&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;        var tag = node.getAttribute(&amp;#x27;data-node-tag&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;        var brand = node.getAttribute(&amp;#x27;data-node-brand&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;        var type = semanticType(node);&#10;        var sources = Archify.sourceEvidence.node(id);&#10;        var sourceSearch = sources.map(function (source) {&#10;          return [source.path, source.label, source.line, source.endLine].filter(Boolean).join(&amp;#x27; &amp;#x27;);&#10;        }).join(&amp;#x27; &amp;#x27;);&#10;        return {&#10;          id: id,&#10;          label: label,&#10;          type: type,&#10;          sublabel: sublabel,&#10;          context: context,&#10;          tag: tag,&#10;          brand: brand,&#10;          sources: sources,&#10;          links: connectionsFor(id),&#10;          search: (id + &amp;#x27; &amp;#x27; + label + &amp;#x27; &amp;#x27; + type + &amp;#x27; &amp;#x27; + sublabel + &amp;#x27; &amp;#x27; + context + &amp;#x27; &amp;#x27; + tag + &amp;#x27; &amp;#x27; + sourceSearch + &amp;#x27; &amp;#x27; + text).toLowerCase() + &amp;#x27; &amp;#x27; + brand.toLowerCase(),&#10;          node: node&#10;        };&#10;      });&#10;&#10;      function resultButtons() {&#10;        return Array.prototype.slice.call(results.querySelectorAll(&amp;#x27;.node-finder-result&amp;#x27;));&#10;      }&#10;&#10;      function resolveContext(options) {&#10;        var requested = options &amp;amp;&amp;amp; options.context ? options.context : null;&#10;        if (!requested &amp;amp;&amp;amp; Archify.routeProbe &amp;amp;&amp;amp; typeof Archify.routeProbe.finderContext === &amp;#x27;function&amp;#x27;) {&#10;          requested = Archify.routeProbe.finderContext();&#10;        }&#10;        if (!requested) return defaultContext();&#10;        var resolved = defaultContext();&#10;        Object.keys(requested).forEach(function (key) { resolved[key] = requested[key]; });&#10;        return resolved;&#10;      }&#10;&#10;      function availableItems() {&#10;        if (!context.allowedIds) return items.slice();&#10;        return items.filter(function (item) { return context.allowedIds.indexOf(item.id) !== -1; });&#10;      }&#10;&#10;      function applyContext() {&#10;        panel.setAttribute(&amp;#x27;data-context&amp;#x27;, context.kind);&#10;        heading.textContent = context.title;&#10;        input.placeholder = context.placeholder;&#10;        empty.textContent = context.empty;&#10;        results.setAttribute(&amp;#x27;aria-label&amp;#x27;, context.resultsLabel);&#10;      }&#10;&#10;      function select(id) {&#10;        var item = items.find(function (candidate) { return candidate.id === id; });&#10;        if (!item) return false;&#10;        var routeSelection = context.kind === &amp;#x27;route-source&amp;#x27; || context.kind === &amp;#x27;route-target&amp;#x27;;&#10;        if (routeSelection) {&#10;          if (!Archify.routeProbe || typeof Archify.routeProbe.choose !== &amp;#x27;function&amp;#x27; || !Archify.routeProbe.choose(id)) return false;&#10;          if (Archify.routeProbe.active() === &amp;#x27;target&amp;#x27; &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;            Archify.view.reveal([id], { includeNeighbors: true, reason: &amp;#x27;route-pick&amp;#x27; });&#10;          }&#10;          close({ restoreFocus: false });&#10;          try { item.node.focus({ preventScroll: true }); } catch (_) { try { item.node.focus(); } catch (_) {} }&#10;          return true;&#10;        }&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; typeof Archify.guidedViews.showAll === &amp;#x27;function&amp;#x27;) {&#10;          Archify.guidedViews.showAll({ clearFocus: false, updateUrl: false });&#10;        }&#10;        if (Archify.view &amp;amp;&amp;amp; typeof Archify.view.reset === &amp;#x27;function&amp;#x27;) Archify.view.reset({ automatic: true });&#10;        Archify.focus.set(id, { toggle: false });&#10;        if (Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reveal([id], { includeNeighbors: true, reason: &amp;#x27;finder&amp;#x27; });&#10;        }&#10;        close({ restoreFocus: false });&#10;        try { item.node.focus({ preventScroll: true }); } catch (_) { try { item.node.focus(); } catch (_) {} }&#10;        return true;&#10;      }&#10;&#10;      function render(query) {&#10;        query = (query || &amp;#x27;&amp;#x27;).trim().toLowerCase();&#10;        var available = availableItems();&#10;        visibleItems = available.filter(function (item) { return !query || item.search.indexOf(query) !== -1; });&#10;        results.textContent = &amp;#x27;&amp;#x27;;&#10;        visibleItems.forEach(function (item) {&#10;          var button = document.createElement(&amp;#x27;button&amp;#x27;);&#10;          button.type = &amp;#x27;button&amp;#x27;;&#10;          button.className = &amp;#x27;node-finder-result&amp;#x27;;&#10;          button.setAttribute(&amp;#x27;data-node-id&amp;#x27;, item.id);&#10;          var badge = context.badges &amp;amp;&amp;amp; context.badges[item.id]&#10;            ? context.badges[item.id]&#10;            : context.kind === &amp;#x27;focus&amp;#x27;&#10;              ? viewerCount(&amp;#x27;viewer.finder.link&amp;#x27;, item.links)&#10;              : String(item.links);&#10;          var action = context.kind === &amp;#x27;route-source&amp;#x27;&#10;            ? viewerText(&amp;#x27;viewer.finder.result.routeStart&amp;#x27;, { label: item.label })&#10;            : context.kind === &amp;#x27;route-target&amp;#x27;&#10;              ? viewerText(&amp;#x27;viewer.finder.result.routeTarget&amp;#x27;, { label: item.label, links: badge })&#10;              : viewerCount(&amp;#x27;viewer.finder.result.focus&amp;#x27;, item.links, { label: item.label });&#10;          button.setAttribute(&amp;#x27;aria-label&amp;#x27;, action);&#10;&#10;          var name = document.createElement(&amp;#x27;strong&amp;#x27;);&#10;          name.textContent = item.label;&#10;          var links = document.createElement(&amp;#x27;em&amp;#x27;);&#10;          links.textContent = badge;&#10;          links.title = context.kind === &amp;#x27;focus&amp;#x27; ? badge : action;&#10;          var meta = document.createElement(&amp;#x27;small&amp;#x27;);&#10;          meta.textContent = [viewerKindLabel(item.type), item.id, item.sublabel, item.tag].filter(Boolean).join(&amp;#x27; \u00b7 &amp;#x27;);&#10;          meta.title = [viewerKindLabel(item.type), item.id, item.context, item.sublabel, item.tag].filter(Boolean).join(&amp;#x27; \u00b7 &amp;#x27;);&#10;          button.appendChild(name);&#10;          button.appendChild(links);&#10;          button.appendChild(meta);&#10;          button.addEventListener(&amp;#x27;click&amp;#x27;, function () { select(item.id); });&#10;          results.appendChild(button);&#10;        });&#10;        empty.hidden = visibleItems.length !== 0;&#10;        status.textContent = query&#10;          ? viewerText(&amp;#x27;viewer.finder.status.filtered&amp;#x27;, {&#10;              visible: visibleItems.length,&#10;              available: available.length,&#10;              noun: context.availableNoun&#10;            })&#10;          : viewerText(&amp;#x27;viewer.finder.status.all&amp;#x27;, { available: available.length, noun: context.availableNoun });&#10;      }&#10;&#10;      function open(options) {&#10;        if (html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; typeof Archify.semanticLens.clearPreview === &amp;#x27;function&amp;#x27;) Archify.semanticLens.clearPreview();&#10;        if (Archify.exportMenu &amp;amp;&amp;amp; Archify.exportMenu.isOpen()) Archify.exportMenu.close(false);&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; Archify.semanticLens.isOpen()) Archify.semanticLens.close({ restoreFocus: false });&#10;        context = resolveContext(options || {});&#10;        applyContext();&#10;        panel.hidden = false;&#10;        trigger.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        if (context.kind.indexOf(&amp;#x27;route-&amp;#x27;) === 0 &amp;amp;&amp;amp; Archify.routeProbe &amp;amp;&amp;amp; typeof Archify.routeProbe.finderOpening === &amp;#x27;function&amp;#x27;) {&#10;          Archify.routeProbe.finderOpening();&#10;        }&#10;        input.value = &amp;#x27;&amp;#x27;;&#10;        render(&amp;#x27;&amp;#x27;);&#10;        requestAnimationFrame(function () { input.focus(); });&#10;        return true;&#10;      }&#10;&#10;      function close(options) {&#10;        options = options || {};&#10;        var routeContext = context.kind.indexOf(&amp;#x27;route-&amp;#x27;) === 0;&#10;        panel.hidden = true;&#10;        trigger.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        input.value = &amp;#x27;&amp;#x27;;&#10;        if (routeContext &amp;amp;&amp;amp; Archify.routeProbe &amp;amp;&amp;amp; typeof Archify.routeProbe.finderClosed === &amp;#x27;function&amp;#x27;) {&#10;          Archify.routeProbe.finderClosed({ restoreFocus: options.restoreFocus !== false });&#10;        } else if (options.restoreFocus !== false) {&#10;          trigger.focus();&#10;        }&#10;      }&#10;&#10;      function toggle() { return panel.hidden ? open() : (close(), false); }&#10;&#10;      trigger.addEventListener(&amp;#x27;click&amp;#x27;, toggle);&#10;      closeBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { close(); });&#10;      input.addEventListener(&amp;#x27;input&amp;#x27;, function () { render(input.value); });&#10;      input.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        var buttons = resultButtons();&#10;        if (event.key === &amp;#x27;ArrowDown&amp;#x27; &amp;amp;&amp;amp; buttons.length) {&#10;          event.preventDefault();&#10;          buttons[0].focus();&#10;        } else if (event.key === &amp;#x27;Enter&amp;#x27; &amp;amp;&amp;amp; visibleItems.length) {&#10;          event.preventDefault();&#10;          select(visibleItems[0].id);&#10;        }&#10;      });&#10;      results.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        var buttons = resultButtons();&#10;        var index = buttons.indexOf(document.activeElement);&#10;        if (index &amp;lt; 0 || !buttons.length) return;&#10;        var next = null;&#10;        if (event.key === &amp;#x27;ArrowDown&amp;#x27;) next = (index + 1) % buttons.length;&#10;        else if (event.key === &amp;#x27;ArrowUp&amp;#x27;) next = (index - 1 + buttons.length) % buttons.length;&#10;        else if (event.key === &amp;#x27;Home&amp;#x27;) next = 0;&#10;        else if (event.key === &amp;#x27;End&amp;#x27;) next = buttons.length - 1;&#10;        if (next !== null) {&#10;          event.preventDefault();&#10;          buttons[next].focus();&#10;        }&#10;      });&#10;      panel.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        if (event.key !== &amp;#x27;Escape&amp;#x27;) return;&#10;        event.preventDefault();&#10;        event.stopPropagation();&#10;        close();&#10;      });&#10;      document.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        if (!panel.hidden &amp;amp;&amp;amp; !panel.contains(event.target) &amp;amp;&amp;amp; !event.target.closest(&amp;#x27;[data-node-finder-trigger]&amp;#x27;)) close({ restoreFocus: false });&#10;      });&#10;&#10;      render(&amp;#x27;&amp;#x27;);&#10;      return {&#10;        open: open,&#10;        close: close,&#10;        toggle: toggle,&#10;        select: select,&#10;        isOpen: function () { return !panel.hidden; },&#10;        context: function () { return context.kind; },&#10;        count: items.length&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Route Probe — shortest directed path over compiled semantics.&#10;       The graph is read from renderer-owned stable IDs and relationship&#10;       endpoints. BFS order follows authored DOM edge order, so equal-length&#10;       choices are deterministic without adding weights or a graph runtime.&#10;       ============================================================ */&#10;    Archify.routeProbe = (function () {&#10;      var html = document.documentElement;&#10;      var container = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var svg = container.querySelector(&amp;#x27;:scope &amp;gt; svg&amp;#x27;);&#10;      var trigger = document.getElementById(&amp;#x27;btn-route-probe&amp;#x27;);&#10;      var panel = document.getElementById(&amp;#x27;route-probe&amp;#x27;);&#10;      var title = document.getElementById(&amp;#x27;route-probe-title&amp;#x27;);&#10;      var path = document.getElementById(&amp;#x27;route-probe-path&amp;#x27;);&#10;      var status = document.getElementById(&amp;#x27;route-probe-status&amp;#x27;);&#10;      var findBtn = document.getElementById(&amp;#x27;route-probe-find&amp;#x27;);&#10;      var copyBtn = document.getElementById(&amp;#x27;route-probe-copy&amp;#x27;);&#10;      var clearBtn = document.getElementById(&amp;#x27;route-probe-clear&amp;#x27;);&#10;      var journeyControls = document.getElementById(&amp;#x27;route-journey-controls&amp;#x27;);&#10;      var journeyPrevBtn = document.getElementById(&amp;#x27;route-journey-prev&amp;#x27;);&#10;      var journeyPlayBtn = document.getElementById(&amp;#x27;route-journey-play&amp;#x27;);&#10;      var journeyPlayIcon = document.getElementById(&amp;#x27;route-journey-play-icon&amp;#x27;);&#10;      var journeyPlayLabel = document.getElementById(&amp;#x27;route-journey-play-label&amp;#x27;);&#10;      var journeyNextBtn = document.getElementById(&amp;#x27;route-journey-next&amp;#x27;);&#10;      var journeyOverviewBtn = document.getElementById(&amp;#x27;route-journey-overview&amp;#x27;);&#10;      var namespace = &amp;#x27;http://www.w3.org/2000/svg&amp;#x27;;&#10;      var mode = &amp;#x27;idle&amp;#x27;;&#10;      var startId = null;&#10;      var endId = null;&#10;      var activeNodeIds = [];&#10;      var activeEdges = [];&#10;      var journeyIndex = -1;&#10;      var journeyPlaying = false;&#10;      var journeyComplete = false;&#10;      var journeyGeneration = 0;&#10;      var journeyTimer = null;&#10;      var journeyStartedAt = 0;&#10;      var journeyElapsedMs = 0;&#10;      var journeyOwnerToken = 0;&#10;      var JOURNEY_DWELL_MS = 1100;&#10;&#10;      function nodes() {&#10;        return Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;));&#10;      }&#10;      function edges() {&#10;        return Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-edge-from][data-edge-to]&amp;#x27;));&#10;      }&#10;      function nodesById() {&#10;        var out = Object.create(null);&#10;        nodes().forEach(function (node) { out[node.getAttribute(&amp;#x27;data-node-id&amp;#x27;)] = node; });&#10;        return out;&#10;      }&#10;      function nodeLabel(node, fallback) {&#10;        return node.getAttribute(&amp;#x27;data-node-label&amp;#x27;) ||&#10;          (node.getAttribute(&amp;#x27;aria-label&amp;#x27;) || fallback).replace(/^Focus\s+/, &amp;#x27;&amp;#x27;).split(&amp;#x27;,&amp;#x27;)[0];&#10;      }&#10;      function exportSnapshot() {&#10;        if (mode !== &amp;#x27;result&amp;#x27; || activeNodeIds.length &amp;lt; 2 || activeEdges.length !== activeNodeIds.length - 1) return null;&#10;        var allNodes = nodes();&#10;        var byId = nodesById();&#10;        var seenNodeIds = Object.create(null);&#10;        var seenEdgeKeys = Object.create(null);&#10;        if (startId !== activeNodeIds[0] || endId !== activeNodeIds[activeNodeIds.length - 1] ||&#10;            activeNodeIds.some(function (id) {&#10;              if (seenNodeIds[id] || allNodes.filter(function (node) {&#10;                return node.getAttribute(&amp;#x27;data-node-id&amp;#x27;) === id;&#10;              }).length !== 1) return true;&#10;              seenNodeIds[id] = true;&#10;              return !byId[id];&#10;            }) ||&#10;            activeEdges.some(function (edge, index) {&#10;              if (!edge || !svg.contains(edge)) return true;&#10;              var edgeKey = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;);&#10;              var edgeId = edge.getAttribute(&amp;#x27;data-edge-id&amp;#x27;) || &amp;#x27;&amp;#x27;;&#10;              if (!edgeKey || seenEdgeKeys[edgeKey]) return true;&#10;              seenEdgeKeys[edgeKey] = true;&#10;              var fragments = Array.prototype.slice.call(svg.querySelectorAll(&amp;#x27;[data-edge-key]&amp;#x27;)).filter(function (candidate) {&#10;                return candidate.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) === edgeKey;&#10;              });&#10;              var drawableFragments = fragments.filter(hasDrawableGeometry);&#10;              return !fragments.length || !fragments.every(function (fragment) {&#10;                return fragment.getAttribute(&amp;#x27;data-edge-from&amp;#x27;) === activeNodeIds[index] &amp;amp;&amp;amp;&#10;                  fragment.getAttribute(&amp;#x27;data-edge-to&amp;#x27;) === activeNodeIds[index + 1] &amp;amp;&amp;amp;&#10;                  (fragment.getAttribute(&amp;#x27;data-edge-id&amp;#x27;) || &amp;#x27;&amp;#x27;) === edgeId;&#10;              }) || drawableFragments.length !== 1 || drawableFragments[0] !== edge ||&#10;                edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;) !== activeNodeIds[index] ||&#10;                edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;) !== activeNodeIds[index + 1];&#10;            })) return null;&#10;        return {&#10;          source: { id: startId, label: nodeLabel(byId[startId], startId) },&#10;          target: { id: endId, label: nodeLabel(byId[endId], endId) },&#10;          nodeIds: activeNodeIds.slice(),&#10;          hops: activeEdges.length,&#10;          edges: activeEdges.map(function (edge) {&#10;            return {&#10;              key: edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;),&#10;              id: edge.getAttribute(&amp;#x27;data-edge-id&amp;#x27;) || &amp;#x27;&amp;#x27;,&#10;              from: edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;),&#10;              to: edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;),&#10;              label: edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;&#10;            };&#10;          })&#10;        };&#10;      }&#10;      function edgeShapes(edge) {&#10;        if (/^(path|line|polyline)$/i.test(edge.tagName)) return [edge];&#10;        return Array.prototype.slice.call(edge.querySelectorAll(&amp;#x27;path, line, polyline&amp;#x27;));&#10;      }&#10;      function removeOverlay() {&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-route-probe-overlay]&amp;#x27;), function (overlay) {&#10;          overlay.remove();&#10;        });&#10;      }&#10;      function removeJourneyPulse(options) {&#10;        options = options || {};&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-route-journey-overlay]&amp;#x27;), function (overlay) {&#10;          overlay.remove();&#10;        });&#10;        if (journeyOwnerToken &amp;amp;&amp;amp; options.release !== false &amp;amp;&amp;amp; Archify.motionGovernor) {&#10;          var token = journeyOwnerToken;&#10;          journeyOwnerToken = 0;&#10;          Archify.motionGovernor.release(token);&#10;        }&#10;      }&#10;      function stopJourneyTimer(options) {&#10;        options = options || {};&#10;        journeyGeneration += 1;&#10;        if (journeyTimer) {&#10;          if (options.preserveElapsed === true &amp;amp;&amp;amp; journeyStartedAt) {&#10;            journeyElapsedMs = Math.min(JOURNEY_DWELL_MS, journeyElapsedMs + Math.max(0, Date.now() - journeyStartedAt));&#10;          }&#10;          window.clearTimeout(journeyTimer);&#10;        }&#10;        journeyTimer = null;&#10;        journeyStartedAt = 0;&#10;        if (options.preserveElapsed !== true) journeyElapsedMs = 0;&#10;      }&#10;      function clearJourneyPresentation(options) {&#10;        options = options || {};&#10;        removeJourneyPulse();&#10;        svg.removeAttribute(&amp;#x27;data-route-journey&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-route-journey&amp;#x27;);&#10;        nodes().forEach(function (node) {&#10;          node.removeAttribute(&amp;#x27;data-route-journey-state&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-route-journey-current&amp;#x27;);&#10;        });&#10;        edges().forEach(function (edge) {&#10;          edge.removeAttribute(&amp;#x27;data-route-journey-state&amp;#x27;);&#10;          edge.removeAttribute(&amp;#x27;data-route-journey-current&amp;#x27;);&#10;        });&#10;        Array.prototype.forEach.call(path.querySelectorAll(&amp;#x27;[data-route-journey-index]&amp;#x27;), function (button, index) {&#10;          button.removeAttribute(&amp;#x27;data-route-journey-state&amp;#x27;);&#10;          button.removeAttribute(&amp;#x27;aria-current&amp;#x27;);&#10;          button.setAttribute(&amp;#x27;tabindex&amp;#x27;, index === 0 ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;        });&#10;        if (options.keepControls !== true) journeyControls.hidden = true;&#10;        journeyControls.setAttribute(&amp;#x27;data-playing&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;      }&#10;      function resetJourneyState() {&#10;        stopJourneyTimer();&#10;        journeyPlaying = false;&#10;        journeyComplete = false;&#10;        journeyIndex = -1;&#10;        clearJourneyPresentation();&#10;      }&#10;      function cleanSvgState() {&#10;        resetJourneyState();&#10;        svg.removeAttribute(&amp;#x27;data-route-picking&amp;#x27;);&#10;        svg.removeAttribute(&amp;#x27;data-route-active&amp;#x27;);&#10;        removeOverlay();&#10;        nodes().forEach(function (node) {&#10;          node.removeAttribute(&amp;#x27;data-route-match&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-route-start&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-route-end&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-route-step&amp;#x27;);&#10;          node.removeAttribute(&amp;#x27;data-route-candidate&amp;#x27;);&#10;          node.style.removeProperty(&amp;#x27;--route-step&amp;#x27;);&#10;        });&#10;        edges().forEach(function (edge) {&#10;          edge.removeAttribute(&amp;#x27;data-route-match&amp;#x27;);&#10;          edge.removeAttribute(&amp;#x27;data-route-step&amp;#x27;);&#10;          edge.style.removeProperty(&amp;#x27;--route-step&amp;#x27;);&#10;        });&#10;        panel.removeAttribute(&amp;#x27;data-route-dock&amp;#x27;);&#10;      }&#10;      function replaceRouteHash(value) {&#10;        try {&#10;          history.replaceState(null, &amp;#x27;&amp;#x27;, location.pathname + location.search + (value ? &amp;#x27;#route=&amp;#x27; + value : &amp;#x27;&amp;#x27;));&#10;        } catch (_) {}&#10;      }&#10;      function renderPlaceholder(copy) {&#10;        path.textContent = &amp;#x27;&amp;#x27;;&#10;        var placeholder = document.createElement(&amp;#x27;span&amp;#x27;);&#10;        placeholder.className = &amp;#x27;route-probe-placeholder&amp;#x27;;&#10;        placeholder.textContent = copy;&#10;        path.appendChild(placeholder);&#10;      }&#10;      function renderPath(ids, options) {&#10;        options = options || {};&#10;        var byId = nodesById();&#10;        path.textContent = &amp;#x27;&amp;#x27;;&#10;        ids.forEach(function (id, index) {&#10;          if (index) {&#10;            var arrow = document.createElement(&amp;#x27;span&amp;#x27;);&#10;            arrow.className = &amp;#x27;route-probe-arrow&amp;#x27;;&#10;            arrow.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;            arrow.textContent = &amp;#x27;\u2192&amp;#x27;;&#10;            path.appendChild(arrow);&#10;          }&#10;          var item = document.createElement(options.interactive === true ? &amp;#x27;button&amp;#x27; : &amp;#x27;span&amp;#x27;);&#10;          if (options.interactive === true) {&#10;            item.type = &amp;#x27;button&amp;#x27;;&#10;            item.setAttribute(&amp;#x27;data-route-journey-index&amp;#x27;, String(index));&#10;            item.setAttribute(&amp;#x27;data-route-node-id&amp;#x27;, id);&#10;            item.setAttribute(&amp;#x27;tabindex&amp;#x27;, index === 0 ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;            item.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.route.position&amp;#x27;, {&#10;              index: index + 1,&#10;              total: ids.length,&#10;              label: nodeLabel(byId[id], id)&#10;            }));&#10;          }&#10;          item.className = &amp;#x27;route-probe-node&amp;#x27;;&#10;          item.textContent = nodeLabel(byId[id], id);&#10;          item.title = nodeLabel(byId[id], id) + &amp;#x27; · &amp;#x27; + id;&#10;          if (index === 0) item.setAttribute(&amp;#x27;data-endpoint&amp;#x27;, &amp;#x27;start&amp;#x27;);&#10;          if (index === ids.length - 1 &amp;amp;&amp;amp; ids.length &amp;gt; 1) item.setAttribute(&amp;#x27;data-endpoint&amp;#x27;, &amp;#x27;end&amp;#x27;);&#10;          path.appendChild(item);&#10;        });&#10;      }&#10;      function setTrigger(active) {&#10;        trigger.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, active ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(active ? &amp;#x27;viewer.route.trigger.clear&amp;#x27; : &amp;#x27;viewer.guide.route.aria&amp;#x27;));&#10;      }&#10;      function clear(options) {&#10;        options = options || {};&#10;        var wasActive = mode !== &amp;#x27;idle&amp;#x27;;&#10;        if (Archify.finder &amp;amp;&amp;amp; Archify.finder.isOpen() &amp;amp;&amp;amp; typeof Archify.finder.context === &amp;#x27;function&amp;#x27; &amp;amp;&amp;amp; Archify.finder.context().indexOf(&amp;#x27;route-&amp;#x27;) === 0) {&#10;          Archify.finder.close({ restoreFocus: false });&#10;        }&#10;        mode = &amp;#x27;idle&amp;#x27;;&#10;        startId = null;&#10;        endId = null;&#10;        activeNodeIds = [];&#10;        activeEdges = [];&#10;        cleanSvgState();&#10;        panel.hidden = true;&#10;        panel.setAttribute(&amp;#x27;data-state&amp;#x27;, &amp;#x27;idle&amp;#x27;);&#10;        panel.removeAttribute(&amp;#x27;data-finder-open&amp;#x27;);&#10;        title.textContent = viewerText(&amp;#x27;viewer.route.start&amp;#x27;);&#10;        renderPlaceholder(viewerText(&amp;#x27;viewer.route.pickTwo&amp;#x27;));&#10;        status.textContent = viewerText(&amp;#x27;viewer.route.instructions&amp;#x27;);&#10;        findBtn.hidden = true;&#10;        findBtn.textContent = viewerText(&amp;#x27;viewer.route.start.find&amp;#x27;);&#10;        findBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.route.start.find.aria&amp;#x27;));&#10;        copyBtn.hidden = true;&#10;        copyBtn.textContent = viewerText(&amp;#x27;viewer.route.copy&amp;#x27;);&#10;        if (Archify.exportMenu &amp;amp;&amp;amp; typeof Archify.exportMenu.syncRouteShare === &amp;#x27;function&amp;#x27;) Archify.exportMenu.syncRouteShare();&#10;        setTrigger(false);&#10;        if (wasActive &amp;amp;&amp;amp; options.preserveView !== true &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reset === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reset({ automatic: true });&#10;        }&#10;        if (options.updateUrl !== false) replaceRouteHash(&amp;#x27;&amp;#x27;);&#10;        if (options.restoreFocus === true) trigger.focus();&#10;      }&#10;      function outgoingByNode() {&#10;        var byId = nodesById();&#10;        var outgoing = {};&#10;        edges().forEach(function (edge) {&#10;          var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;          var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;          if (!byId[from] || !byId[to] || from === to) return;&#10;          if (!outgoing[from]) outgoing[from] = [];&#10;          outgoing[from].push({ edge: edge, to: to });&#10;        });&#10;        return outgoing;&#10;      }&#10;      function reachableFrom(source) {&#10;        var outgoing = outgoingByNode();&#10;        var reached = {};&#10;        var queue = [source];&#10;        reached[source] = true;&#10;        for (var cursor = 0; cursor &amp;lt; queue.length; cursor += 1) {&#10;          var links = outgoing[queue[cursor]] || [];&#10;          links.forEach(function (link) {&#10;            if (reached[link.to]) return;&#10;            reached[link.to] = true;&#10;            queue.push(link.to);&#10;          });&#10;        }&#10;        return reached;&#10;      }&#10;      function hopDistancesFrom(source) {&#10;        var outgoing = outgoingByNode();&#10;        var distances = {};&#10;        var queue = [source];&#10;        distances[source] = 0;&#10;        for (var cursor = 0; cursor &amp;lt; queue.length; cursor += 1) {&#10;          var links = outgoing[queue[cursor]] || [];&#10;          links.forEach(function (link) {&#10;            if (Object.prototype.hasOwnProperty.call(distances, link.to)) return;&#10;            distances[link.to] = distances[queue[cursor]] + 1;&#10;            queue.push(link.to);&#10;          });&#10;        }&#10;        return distances;&#10;      }&#10;      function shortestDirectedPath(source, target) {&#10;        if (source === target) return null;&#10;        var outgoing = outgoingByNode();&#10;        var previous = {};&#10;        var queue = [source];&#10;        previous[source] = null;&#10;        for (var cursor = 0; cursor &amp;lt; queue.length &amp;amp;&amp;amp; !Object.prototype.hasOwnProperty.call(previous, target); cursor += 1) {&#10;          var links = outgoing[queue[cursor]] || [];&#10;          links.some(function (link) {&#10;            if (Object.prototype.hasOwnProperty.call(previous, link.to)) return false;&#10;            previous[link.to] = { from: queue[cursor], edge: link.edge };&#10;            queue.push(link.to);&#10;            return link.to === target;&#10;          });&#10;        }&#10;        if (!Object.prototype.hasOwnProperty.call(previous, target)) return null;&#10;        var nodeIds = [target];&#10;        var routeEdges = [];&#10;        var current = target;&#10;        while (current !== source) {&#10;          var step = previous[current];&#10;          if (!step) return null;&#10;          routeEdges.unshift(step.edge);&#10;          nodeIds.unshift(step.from);&#10;          current = step.from;&#10;        }&#10;        return { nodes: nodeIds, edges: routeEdges };&#10;      }&#10;      function traceGeometry(shape, step) {&#10;        var clone = shape.cloneNode(false);&#10;        clone.removeAttribute(&amp;#x27;id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;class&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;style&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-start&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-mid&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-end&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;role&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-labelledby&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-animate&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-key&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-route-match&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-route-step&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;route-probe-flow&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;pathLength&amp;#x27;, &amp;#x27;1&amp;#x27;);&#10;        clone.style.setProperty(&amp;#x27;--route-step&amp;#x27;, String(step));&#10;        return clone;&#10;      }&#10;      function renderOverlay(routeEdges) {&#10;        removeOverlay();&#10;        if (!routeEdges.length) return;&#10;        var overlay = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;route-probe-overlay&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;data-route-probe-overlay&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        routeEdges.forEach(function (edge, step) {&#10;          var wrapper = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;          if (edge.hasAttribute(&amp;#x27;transform&amp;#x27;)) wrapper.setAttribute(&amp;#x27;transform&amp;#x27;, edge.getAttribute(&amp;#x27;transform&amp;#x27;));&#10;          edgeShapes(edge).forEach(function (shape) { wrapper.appendChild(traceGeometry(shape, step)); });&#10;          if (wrapper.childNodes.length) overlay.appendChild(wrapper);&#10;        });&#10;        var firstNode = svg.querySelector(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (firstNode) svg.insertBefore(overlay, firstNode);&#10;        else svg.appendChild(overlay);&#10;      }&#10;      function journeyButtons() {&#10;        return Array.prototype.slice.call(path.querySelectorAll(&amp;#x27;[data-route-journey-index]&amp;#x27;));&#10;      }&#10;      function journeyMotionAllowed() {&#10;        return html.getAttribute(&amp;#x27;data-embed&amp;#x27;) !== &amp;#x27;true&amp;#x27; &amp;amp;&amp;amp;&#10;          !document.hidden &amp;amp;&amp;amp;&#10;          Archify.motionGovernor &amp;amp;&amp;amp;&#10;          Archify.motionGovernor.capable === true &amp;amp;&amp;amp;&#10;          !Archify.motionGovernor.isPaused();&#10;      }&#10;      function routeOverviewStatus() {&#10;        return viewerText(&amp;#x27;viewer.route.overview.status&amp;#x27;, {&#10;          nodes: viewerCount(&amp;#x27;viewer.route.overview.node&amp;#x27;, activeNodeIds.length),&#10;          hops: viewerCount(&amp;#x27;viewer.route.overview.hop&amp;#x27;, activeEdges.length)&#10;        });&#10;      }&#10;      function centerJourneyButton(button) {&#10;        if (!button) return;&#10;        var target = button.offsetLeft - Math.max(0, (path.clientWidth - button.offsetWidth) / 2);&#10;        path.scrollLeft = Math.max(0, target);&#10;      }&#10;      function focusJourneyButton(index) {&#10;        var buttons = journeyButtons();&#10;        if (!buttons.length) return false;&#10;        var next = Math.max(0, Math.min(buttons.length - 1, index));&#10;        buttons.forEach(function (button, buttonIndex) {&#10;          button.setAttribute(&amp;#x27;tabindex&amp;#x27;, buttonIndex === next ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;        });&#10;        try { buttons[next].focus({ preventScroll: true }); } catch (_) { buttons[next].focus(); }&#10;        centerJourneyButton(buttons[next]);&#10;        return true;&#10;      }&#10;      function renderJourneyControls() {&#10;        var hasRoute = mode === &amp;#x27;result&amp;#x27; &amp;amp;&amp;amp; activeNodeIds.length &amp;gt; 1;&#10;        var canPlay = hasRoute &amp;amp;&amp;amp; journeyMotionAllowed();&#10;        journeyControls.hidden = !hasRoute;&#10;        journeyControls.setAttribute(&amp;#x27;data-playing&amp;#x27;, journeyPlaying ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;        journeyPrevBtn.disabled = !hasRoute || journeyIndex &amp;lt;= 0;&#10;        journeyNextBtn.disabled = !hasRoute || journeyIndex &amp;gt;= activeNodeIds.length - 1;&#10;        journeyOverviewBtn.disabled = !hasRoute || journeyIndex &amp;lt; 0;&#10;        journeyPlayBtn.disabled = !canPlay;&#10;        journeyPlayBtn.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, journeyPlaying ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;        if (journeyPlaying) {&#10;          journeyPlayIcon.textContent = &amp;#x27;\u275a\u275a&amp;#x27;;&#10;          journeyPlayLabel.textContent = viewerText(&amp;#x27;viewer.route.pause.label&amp;#x27;);&#10;          journeyPlayBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.route.pause&amp;#x27;));&#10;          journeyPlayBtn.title = viewerText(&amp;#x27;viewer.route.pause&amp;#x27;);&#10;        } else if (journeyComplete || journeyIndex === activeNodeIds.length - 1) {&#10;          journeyPlayIcon.textContent = &amp;#x27;\u21bb&amp;#x27;;&#10;          journeyPlayLabel.textContent = viewerText(&amp;#x27;viewer.route.replay.label&amp;#x27;);&#10;          journeyPlayBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.route.replay&amp;#x27;));&#10;          journeyPlayBtn.title = viewerText(canPlay ? &amp;#x27;viewer.route.replay&amp;#x27; : &amp;#x27;viewer.route.motionRequired&amp;#x27;);&#10;        } else {&#10;          journeyPlayIcon.textContent = &amp;#x27;\u25b6&amp;#x27;;&#10;          journeyPlayLabel.textContent = viewerText(&amp;#x27;viewer.route.journey&amp;#x27;);&#10;          journeyPlayBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.route.play&amp;#x27;));&#10;          journeyPlayBtn.title = viewerText(canPlay ? &amp;#x27;viewer.route.play&amp;#x27; : &amp;#x27;viewer.route.motionRequired&amp;#x27;);&#10;        }&#10;      }&#10;      function journeyGeometry(shape) {&#10;        var clone = shape.cloneNode(false);&#10;        clone.removeAttribute(&amp;#x27;id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;class&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;style&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-start&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-mid&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-end&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;role&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-labelledby&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-animate&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-key&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-route-match&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-route-step&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-route-journey-state&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-route-journey-current&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;route-journey-flow&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;pathLength&amp;#x27;, &amp;#x27;1&amp;#x27;);&#10;        return clone;&#10;      }&#10;      function renderJourneyPulse(edge) {&#10;        removeJourneyPulse();&#10;        if (!edge || !journeyMotionAllowed()) return false;&#10;        var overlay = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;route-journey-overlay&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;data-route-journey-overlay&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        var wrapper = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;        if (edge.hasAttribute(&amp;#x27;transform&amp;#x27;)) wrapper.setAttribute(&amp;#x27;transform&amp;#x27;, edge.getAttribute(&amp;#x27;transform&amp;#x27;));&#10;        edgeShapes(edge).forEach(function (shape) { wrapper.appendChild(journeyGeometry(shape)); });&#10;        if (!wrapper.childNodes.length) return false;&#10;        overlay.appendChild(wrapper);&#10;        var firstNode = svg.querySelector(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (firstNode) svg.insertBefore(overlay, firstNode);&#10;        else svg.appendChild(overlay);&#10;        if (Archify.motionGovernor &amp;amp;&amp;amp; Archify.motionGovernor.capable) {&#10;          var token = 0;&#10;          token = Archify.motionGovernor.claim(&amp;#x27;route&amp;#x27;, function () {&#10;            if (journeyOwnerToken === token) journeyOwnerToken = 0;&#10;            removeJourneyPulse({ release: false });&#10;          });&#10;          journeyOwnerToken = token;&#10;        }&#10;        overlay.addEventListener(&amp;#x27;animationend&amp;#x27;, function () {&#10;          if (overlay.isConnected) removeJourneyPulse();&#10;        }, { once: true });&#10;        window.setTimeout(function () {&#10;          if (overlay.isConnected) removeJourneyPulse();&#10;        }, 860);&#10;        return true;&#10;      }&#10;      function applyJourneyState(index, options) {&#10;        options = options || {};&#10;        if (mode !== &amp;#x27;result&amp;#x27; || !activeNodeIds.length) return false;&#10;        var byId = nodesById();&#10;        journeyIndex = Math.max(0, Math.min(activeNodeIds.length - 1, index));&#10;        removeJourneyPulse();&#10;        svg.setAttribute(&amp;#x27;data-route-journey&amp;#x27;, (journeyIndex + 1) + &amp;#x27;/&amp;#x27; + activeNodeIds.length);&#10;        panel.setAttribute(&amp;#x27;data-route-journey&amp;#x27;, String(journeyIndex));&#10;        activeNodeIds.forEach(function (id, step) {&#10;          var node = byId[id];&#10;          if (!node) return;&#10;          var state = step &amp;lt; journeyIndex ? &amp;#x27;past&amp;#x27; : (step === journeyIndex ? &amp;#x27;current&amp;#x27; : &amp;#x27;future&amp;#x27;);&#10;          node.setAttribute(&amp;#x27;data-route-journey-state&amp;#x27;, state);&#10;          if (step === journeyIndex) node.setAttribute(&amp;#x27;data-route-journey-current&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          else node.removeAttribute(&amp;#x27;data-route-journey-current&amp;#x27;);&#10;        });&#10;        activeEdges.forEach(function (edge, step) {&#10;          var destination = step + 1;&#10;          var state = destination &amp;lt; journeyIndex ? &amp;#x27;past&amp;#x27; : (destination === journeyIndex ? &amp;#x27;current&amp;#x27; : &amp;#x27;future&amp;#x27;);&#10;          edge.setAttribute(&amp;#x27;data-route-journey-state&amp;#x27;, state);&#10;          if (destination === journeyIndex) edge.setAttribute(&amp;#x27;data-route-journey-current&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          else edge.removeAttribute(&amp;#x27;data-route-journey-current&amp;#x27;);&#10;        });&#10;        var buttons = journeyButtons();&#10;        buttons.forEach(function (button, step) {&#10;          var state = step &amp;lt; journeyIndex ? &amp;#x27;past&amp;#x27; : (step === journeyIndex ? &amp;#x27;current&amp;#x27; : &amp;#x27;future&amp;#x27;);&#10;          button.setAttribute(&amp;#x27;data-route-journey-state&amp;#x27;, state);&#10;          button.setAttribute(&amp;#x27;tabindex&amp;#x27;, step === journeyIndex ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;          if (step === journeyIndex) button.setAttribute(&amp;#x27;aria-current&amp;#x27;, &amp;#x27;step&amp;#x27;);&#10;          else button.removeAttribute(&amp;#x27;aria-current&amp;#x27;);&#10;        });&#10;        if (options.center !== false) centerJourneyButton(buttons[journeyIndex]);&#10;        var phase = viewerText(journeyPlaying&#10;          ? &amp;#x27;viewer.route.phase.playing&amp;#x27;&#10;          : journeyComplete&#10;            ? &amp;#x27;viewer.route.phase.complete&amp;#x27;&#10;            : &amp;#x27;viewer.route.phase.inspecting&amp;#x27;);&#10;        status.textContent = viewerText(&amp;#x27;viewer.route.step&amp;#x27;, {&#10;          index: journeyIndex + 1,&#10;          total: activeNodeIds.length,&#10;          phase: phase,&#10;          label: nodeLabel(byId[activeNodeIds[journeyIndex]], activeNodeIds[journeyIndex])&#10;        });&#10;        if (options.pulse === true &amp;amp;&amp;amp; journeyIndex &amp;gt; 0) renderJourneyPulse(activeEdges[journeyIndex - 1]);&#10;        if (options.reveal !== false &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reveal(activeNodeIds.slice(Math.max(0, journeyIndex - 1), Math.min(activeNodeIds.length, journeyIndex + 2)), {&#10;            includeNeighbors: false,&#10;            reason: &amp;#x27;route-journey&amp;#x27;,&#10;            maxScale: 1.65,&#10;            padding: 64,&#10;            duration: 360,&#10;            instant: !journeyMotionAllowed()&#10;          });&#10;        }&#10;        renderJourneyControls();&#10;        requestDocking();&#10;        return true;&#10;      }&#10;      function pauseJourney(options) {&#10;        options = options || {};&#10;        if (!journeyPlaying &amp;amp;&amp;amp; options.complete !== true) {&#10;          renderJourneyControls();&#10;          return false;&#10;        }&#10;        stopJourneyTimer({ preserveElapsed: options.complete !== true &amp;amp;&amp;amp; options.preserveElapsed !== false });&#10;        journeyPlaying = false;&#10;        journeyComplete = options.complete === true;&#10;        if (journeyComplete) journeyElapsedMs = 0;&#10;        removeJourneyPulse();&#10;        if (journeyIndex &amp;gt;= 0) applyJourneyState(journeyIndex, { center: false, pulse: false, reveal: false });&#10;        else renderJourneyControls();&#10;        return true;&#10;      }&#10;      function selectJourneyIndex(index) {&#10;        if (mode !== &amp;#x27;result&amp;#x27;) return false;&#10;        stopJourneyTimer();&#10;        journeyPlaying = false;&#10;        journeyComplete = false;&#10;        return applyJourneyState(index, { pulse: true, reveal: true });&#10;      }&#10;      function showJourneyOverview(options) {&#10;        options = options || {};&#10;        if (mode !== &amp;#x27;result&amp;#x27;) return false;&#10;        stopJourneyTimer();&#10;        journeyPlaying = false;&#10;        journeyComplete = false;&#10;        journeyIndex = -1;&#10;        clearJourneyPresentation({ keepControls: true });&#10;        status.textContent = routeOverviewStatus();&#10;        renderJourneyControls();&#10;        if (options.reveal !== false &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reveal(activeNodeIds, { includeNeighbors: false, reason: &amp;#x27;route&amp;#x27;, instant: !journeyMotionAllowed() });&#10;        }&#10;        requestDocking();&#10;        return true;&#10;      }&#10;      function scheduleJourney() {&#10;        if (!journeyPlaying || !journeyMotionAllowed()) {&#10;          pauseJourney({ preserveElapsed: true });&#10;          return false;&#10;        }&#10;        var generation = ++journeyGeneration;&#10;        var remaining = Math.max(0, JOURNEY_DWELL_MS - journeyElapsedMs);&#10;        journeyStartedAt = Date.now();&#10;        journeyTimer = window.setTimeout(function () {&#10;          if (generation !== journeyGeneration || !journeyPlaying) return;&#10;          journeyTimer = null;&#10;          journeyStartedAt = 0;&#10;          journeyElapsedMs = 0;&#10;          if (journeyIndex &amp;gt;= activeNodeIds.length - 1) {&#10;            pauseJourney({ complete: true, preserveElapsed: false });&#10;            return;&#10;          }&#10;          applyJourneyState(journeyIndex + 1, { pulse: true, reveal: true });&#10;          // Camera and motion-owner handoff are allowed to synchronously&#10;          // settle the previous step. The new step always starts with a fresh&#10;          // dwell; never carry cleanup time into the next scheduler lease.&#10;          journeyElapsedMs = 0;&#10;          journeyStartedAt = 0;&#10;          scheduleJourney();&#10;        }, remaining);&#10;        return true;&#10;      }&#10;      function playJourney() {&#10;        if (mode !== &amp;#x27;result&amp;#x27; || activeNodeIds.length &amp;lt; 2 || !journeyMotionAllowed()) {&#10;          renderJourneyControls();&#10;          return false;&#10;        }&#10;        if (journeyPlaying) return true;&#10;        if (journeyComplete || journeyIndex &amp;gt;= activeNodeIds.length - 1) {&#10;          journeyIndex = -1;&#10;          journeyElapsedMs = 0;&#10;          journeyComplete = false;&#10;        }&#10;        journeyPlaying = true;&#10;        if (journeyIndex &amp;lt; 0) applyJourneyState(0, { pulse: false, reveal: true });&#10;        else applyJourneyState(journeyIndex, { center: false, pulse: false, reveal: false });&#10;        scheduleJourney();&#10;        return true;&#10;      }&#10;      function toggleJourney() {&#10;        return journeyPlaying ? pauseJourney({ preserveElapsed: true }) : playJourney();&#10;      }&#10;      function previousJourney() {&#10;        return selectJourneyIndex(Math.max(0, journeyIndex &amp;lt; 0 ? 0 : journeyIndex - 1));&#10;      }&#10;      function nextJourney() {&#10;        return selectJourneyIndex(Math.min(activeNodeIds.length - 1, journeyIndex + 1));&#10;      }&#10;      function overlapArea(a, b) {&#10;        var width = Math.max(0, Math.min(a.right, b.right) - Math.max(a.left, b.left));&#10;        var height = Math.max(0, Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top));&#10;        return width * height;&#10;      }&#10;      function updateDocking() {&#10;        if (panel.hidden) {&#10;          panel.removeAttribute(&amp;#x27;data-route-dock&amp;#x27;);&#10;          return;&#10;        }&#10;        var containerRect = container.getBoundingClientRect();&#10;        var width = panel.offsetWidth;&#10;        var height = panel.offsetHeight;&#10;        if (!width || !height) return;&#10;        var currentRect = panel.getBoundingClientRect();&#10;        var left = currentRect.left;&#10;        var topCandidate = {&#10;          left: left,&#10;          right: left + width,&#10;          top: containerRect.top + 8,&#10;          bottom: containerRect.top + 8 + height&#10;        };&#10;        var nav = container.querySelector(&amp;#x27;.diagram-nav&amp;#x27;);&#10;        var navRect = nav ? nav.getBoundingClientRect() : null;&#10;        var bottom = navRect ? navRect.top - 9 : containerRect.bottom - 8;&#10;        var bottomCandidate = {&#10;          left: left,&#10;          right: left + width,&#10;          top: bottom - height,&#10;          bottom: bottom&#10;        };&#10;        var byId = nodesById();&#10;        var relevant = activeNodeIds.length ? activeNodeIds : (startId ? [startId] : []);&#10;        var blockers = relevant.map(function (id) { return byId[id]; }).filter(Boolean).map(function (node) {&#10;          return node.getBoundingClientRect();&#10;        });&#10;        function score(candidate) {&#10;          var value = blockers.reduce(function (sum, rect) { return sum + overlapArea(candidate, rect); }, 0);&#10;          if (navRect) value += overlapArea(candidate, navRect) * 4;&#10;          if (candidate.top &amp;lt; containerRect.top || candidate.bottom &amp;gt; containerRect.bottom) value += 1000000;&#10;          return value;&#10;        }&#10;        if (score(topCandidate) &amp;lt;= score(bottomCandidate)) panel.setAttribute(&amp;#x27;data-route-dock&amp;#x27;, &amp;#x27;top&amp;#x27;);&#10;        else panel.setAttribute(&amp;#x27;data-route-dock&amp;#x27;, &amp;#x27;bottom&amp;#x27;);&#10;      }&#10;      function requestDocking() {&#10;        requestAnimationFrame(updateDocking);&#10;        window.setTimeout(updateDocking, 120);&#10;        window.setTimeout(updateDocking, 560);&#10;      }&#10;      function chooseStart(id) {&#10;        var byId = nodesById();&#10;        if (!byId[id]) return false;&#10;        cleanSvgState();&#10;        startId = id;&#10;        endId = null;&#10;        mode = &amp;#x27;target&amp;#x27;;&#10;        var reached = reachableFrom(id);&#10;        byId[id].setAttribute(&amp;#x27;data-route-start&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        byId[id].setAttribute(&amp;#x27;data-route-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        Object.keys(reached).forEach(function (candidateId) {&#10;          if (candidateId !== id &amp;amp;&amp;amp; byId[candidateId]) byId[candidateId].setAttribute(&amp;#x27;data-route-candidate&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        });&#10;        svg.setAttribute(&amp;#x27;data-route-picking&amp;#x27;, &amp;#x27;target&amp;#x27;);&#10;        panel.setAttribute(&amp;#x27;data-state&amp;#x27;, &amp;#x27;target&amp;#x27;);&#10;        title.textContent = viewerText(&amp;#x27;viewer.route.destination&amp;#x27;, { label: nodeLabel(byId[id], id) });&#10;        renderPath([id]);&#10;        var count = Math.max(0, Object.keys(reached).length - 1);&#10;        status.textContent = count&#10;          ? viewerCount(&amp;#x27;viewer.route.destination.count&amp;#x27;, count)&#10;          : viewerText(&amp;#x27;viewer.route.noOutgoing&amp;#x27;);&#10;        findBtn.hidden = false;&#10;        findBtn.textContent = viewerText(&amp;#x27;viewer.route.destination.find&amp;#x27;);&#10;        findBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.route.destination.find.aria&amp;#x27;));&#10;        requestDocking();&#10;        return true;&#10;      }&#10;      function showResult(result, options) {&#10;        options = options || {};&#10;        var byId = nodesById();&#10;        cleanSvgState();&#10;        mode = &amp;#x27;result&amp;#x27;;&#10;        startId = result.nodes[0];&#10;        endId = result.nodes[result.nodes.length - 1];&#10;        activeNodeIds = result.nodes.slice();&#10;        activeEdges = result.edges.slice();&#10;        result.nodes.forEach(function (id, step) {&#10;          var node = byId[id];&#10;          if (!node) return;&#10;          node.setAttribute(&amp;#x27;data-route-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          node.setAttribute(&amp;#x27;data-route-step&amp;#x27;, String(step));&#10;          node.style.setProperty(&amp;#x27;--route-step&amp;#x27;, String(step));&#10;          if (step === 0) node.setAttribute(&amp;#x27;data-route-start&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          if (step === result.nodes.length - 1) node.setAttribute(&amp;#x27;data-route-end&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        });&#10;        result.edges.forEach(function (edge, step) {&#10;          edge.setAttribute(&amp;#x27;data-route-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          edge.setAttribute(&amp;#x27;data-route-step&amp;#x27;, String(step));&#10;          edge.style.setProperty(&amp;#x27;--route-step&amp;#x27;, String(step));&#10;        });&#10;        svg.setAttribute(&amp;#x27;data-route-active&amp;#x27;, startId + &amp;#x27;~&amp;#x27; + endId);&#10;        renderOverlay(result.edges);&#10;        renderPath(result.nodes, { interactive: true });&#10;        panel.setAttribute(&amp;#x27;data-state&amp;#x27;, &amp;#x27;result&amp;#x27;);&#10;        panel.hidden = false;&#10;        title.textContent = viewerText(&amp;#x27;viewer.route.result.title&amp;#x27;, {&#10;          source: nodeLabel(byId[startId], startId),&#10;          target: nodeLabel(byId[endId], endId)&#10;        });&#10;        findBtn.hidden = true;&#10;        copyBtn.hidden = false;&#10;        setTrigger(true);&#10;        if (Archify.exportMenu &amp;amp;&amp;amp; typeof Archify.exportMenu.syncRouteShare === &amp;#x27;function&amp;#x27;) Archify.exportMenu.syncRouteShare();&#10;        if (options.updateUrl !== false) {&#10;          replaceRouteHash(encodeURIComponent(startId) + &amp;#x27;~&amp;#x27; + encodeURIComponent(endId));&#10;        }&#10;        showJourneyOverview({ reveal: false });&#10;        if (Archify.view &amp;amp;&amp;amp; typeof Archify.view.reveal === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reveal(result.nodes, { includeNeighbors: false, reason: &amp;#x27;route&amp;#x27; });&#10;        }&#10;        return true;&#10;      }&#10;      function choose(id, options) {&#10;        options = options || {};&#10;        var byId = nodesById();&#10;        if (!byId[id]) return false;&#10;        if (mode === &amp;#x27;source&amp;#x27;) return chooseStart(id);&#10;        if (mode !== &amp;#x27;target&amp;#x27;) return false;&#10;        if (id === startId) {&#10;          panel.setAttribute(&amp;#x27;data-state&amp;#x27;, &amp;#x27;error&amp;#x27;);&#10;          title.textContent = viewerText(&amp;#x27;viewer.route.differentDestination&amp;#x27;);&#10;          status.textContent = viewerText(&amp;#x27;viewer.route.distinct&amp;#x27;);&#10;          return false;&#10;        }&#10;        var result = shortestDirectedPath(startId, id);&#10;        if (!result) {&#10;          panel.setAttribute(&amp;#x27;data-state&amp;#x27;, &amp;#x27;error&amp;#x27;);&#10;          title.textContent = viewerText(&amp;#x27;viewer.route.unreachable&amp;#x27;, { label: nodeLabel(byId[id], id) });&#10;          status.textContent = viewerText(&amp;#x27;viewer.route.unreachable.detail&amp;#x27;, {&#10;            target: nodeLabel(byId[id], id),&#10;            source: nodeLabel(byId[startId], startId)&#10;          });&#10;          return false;&#10;        }&#10;        return showResult(result, options);&#10;      }&#10;      function begin(options) {&#10;        options = options || {};&#10;        if (html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; typeof Archify.semanticLens.clearPreview === &amp;#x27;function&amp;#x27;) Archify.semanticLens.clearPreview();&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; Archify.semanticLens.active()) {&#10;          Archify.semanticLens.clear({ updateUrl: false, preserveView: true, closePanel: true });&#10;        }&#10;        var focused = options.source || (Archify.focus &amp;amp;&amp;amp; typeof Archify.focus.active === &amp;#x27;function&amp;#x27; ? Archify.focus.active() : null);&#10;        if (Array.isArray(focused)) focused = null;&#10;        clear({ updateUrl: false, preserveView: true, restoreFocus: false });&#10;        if (Archify.intentTrace &amp;amp;&amp;amp; typeof Archify.intentTrace.clear === &amp;#x27;function&amp;#x27;) Archify.intentTrace.clear({ announce: false });&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; typeof Archify.guidedViews.showAll === &amp;#x27;function&amp;#x27;) {&#10;          Archify.guidedViews.showAll({ clearFocus: false, updateUrl: false });&#10;        }&#10;        if (Archify.focus &amp;amp;&amp;amp; typeof Archify.focus.clear === &amp;#x27;function&amp;#x27;) {&#10;          Archify.focus.clear({ updateUrl: false, preserveView: true });&#10;        }&#10;        if (Archify.finder &amp;amp;&amp;amp; Archify.finder.isOpen()) Archify.finder.close({ restoreFocus: false });&#10;        if (Archify.radar &amp;amp;&amp;amp; Archify.radar.isOpen()) Archify.radar.close({ restoreFocus: false });&#10;        mode = &amp;#x27;source&amp;#x27;;&#10;        panel.hidden = false;&#10;        panel.setAttribute(&amp;#x27;data-state&amp;#x27;, &amp;#x27;source&amp;#x27;);&#10;        svg.setAttribute(&amp;#x27;data-route-picking&amp;#x27;, &amp;#x27;source&amp;#x27;);&#10;        title.textContent = viewerText(&amp;#x27;viewer.route.start&amp;#x27;);&#10;        renderPlaceholder(viewerText(&amp;#x27;viewer.route.pickOne&amp;#x27;));&#10;        status.textContent = viewerText(&amp;#x27;viewer.route.start.instructions&amp;#x27;);&#10;        findBtn.hidden = false;&#10;        findBtn.textContent = viewerText(&amp;#x27;viewer.route.start.find&amp;#x27;);&#10;        findBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.route.start.find.aria&amp;#x27;));&#10;        copyBtn.hidden = true;&#10;        setTrigger(true);&#10;        if (focused &amp;amp;&amp;amp; nodesById()[focused]) chooseStart(focused);&#10;        if (options.focusNode === true &amp;amp;&amp;amp; !focused) {&#10;          var first = nodes()[0];&#10;          if (first) {&#10;            try { first.focus({ preventScroll: true }); } catch (_) { try { first.focus(); } catch (_) {} }&#10;          }&#10;        }&#10;        return true;&#10;      }&#10;      function toggle(options) {&#10;        if (mode !== &amp;#x27;idle&amp;#x27;) {&#10;          clear({ restoreFocus: true });&#10;          return false;&#10;        }&#10;        return begin(options);&#10;      }&#10;      function finderContext() {&#10;        var byId = nodesById();&#10;        if (mode === &amp;#x27;source&amp;#x27;) {&#10;          var outgoing = outgoingByNode();&#10;          var sourceIds = nodes().map(function (node) { return node.getAttribute(&amp;#x27;data-node-id&amp;#x27;); }).filter(function (id) {&#10;            return outgoing[id] &amp;amp;&amp;amp; outgoing[id].length;&#10;          });&#10;          var sourceBadges = {};&#10;          sourceIds.forEach(function (id) { sourceBadges[id] = viewerText(&amp;#x27;viewer.route.finder.source.badge&amp;#x27;); });&#10;          return {&#10;            kind: &amp;#x27;route-source&amp;#x27;,&#10;            title: viewerText(&amp;#x27;viewer.route.finder.source.title&amp;#x27;),&#10;            placeholder: viewerText(&amp;#x27;viewer.route.finder.source.placeholder&amp;#x27;),&#10;            empty: viewerText(&amp;#x27;viewer.route.finder.source.empty&amp;#x27;),&#10;            resultsLabel: viewerText(&amp;#x27;viewer.route.finder.source.results&amp;#x27;),&#10;            availableNoun: viewerText(&amp;#x27;viewer.route.finder.source.noun&amp;#x27;),&#10;            allowedIds: sourceIds,&#10;            badges: sourceBadges&#10;          };&#10;        }&#10;        if (mode === &amp;#x27;target&amp;#x27; &amp;amp;&amp;amp; startId &amp;amp;&amp;amp; byId[startId]) {&#10;          var distances = hopDistancesFrom(startId);&#10;          var targetIds = Object.keys(distances).filter(function (id) { return id !== startId &amp;amp;&amp;amp; byId[id]; });&#10;          var targetBadges = {};&#10;          targetIds.forEach(function (id) {&#10;            targetBadges[id] = viewerCount(&amp;#x27;viewer.route.hop&amp;#x27;, distances[id]);&#10;          });&#10;          return {&#10;            kind: &amp;#x27;route-target&amp;#x27;,&#10;            title: viewerText(&amp;#x27;viewer.route.finder.target.title&amp;#x27;, { label: nodeLabel(byId[startId], startId) }),&#10;            placeholder: viewerText(&amp;#x27;viewer.route.finder.target.placeholder&amp;#x27;),&#10;            empty: viewerText(&amp;#x27;viewer.route.finder.target.empty&amp;#x27;),&#10;            resultsLabel: viewerText(&amp;#x27;viewer.route.finder.target.results&amp;#x27;),&#10;            availableNoun: viewerText(&amp;#x27;viewer.route.finder.target.noun&amp;#x27;),&#10;            allowedIds: targetIds,&#10;            badges: targetBadges&#10;          };&#10;        }&#10;        return null;&#10;      }&#10;      function finderOpening() {&#10;        panel.setAttribute(&amp;#x27;data-finder-open&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;      }&#10;      function finderClosed(options) {&#10;        options = options || {};&#10;        panel.removeAttribute(&amp;#x27;data-finder-open&amp;#x27;);&#10;        requestDocking();&#10;        if (options.restoreFocus === true &amp;amp;&amp;amp; !findBtn.hidden) findBtn.focus();&#10;      }&#10;      function openFinder() {&#10;        var context = finderContext();&#10;        if (!context || !Archify.finder) return false;&#10;        return Archify.finder.open({ context: context });&#10;      }&#10;      function fallbackCopy(value) {&#10;        var field = document.createElement(&amp;#x27;textarea&amp;#x27;);&#10;        field.value = value;&#10;        field.setAttribute(&amp;#x27;readonly&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        field.style.position = &amp;#x27;fixed&amp;#x27;;&#10;        field.style.opacity = &amp;#x27;0&amp;#x27;;&#10;        document.body.appendChild(field);&#10;        field.select();&#10;        var copied = false;&#10;        try { copied = document.execCommand(&amp;#x27;copy&amp;#x27;); } catch (_) {}&#10;        field.remove();&#10;        return copied;&#10;      }&#10;      function copyLink() {&#10;        if (mode !== &amp;#x27;result&amp;#x27;) return Promise.resolve(false);&#10;        var value = location.href.replace(/#.*$/, &amp;#x27;&amp;#x27;) + &amp;#x27;#route=&amp;#x27; + encodeURIComponent(startId) + &amp;#x27;~&amp;#x27; + encodeURIComponent(endId);&#10;        var copy = navigator.clipboard &amp;amp;&amp;amp; typeof navigator.clipboard.writeText === &amp;#x27;function&amp;#x27;&#10;          ? navigator.clipboard.writeText(value).then(function () { return true; }).catch(function () { return fallbackCopy(value); })&#10;          : Promise.resolve(fallbackCopy(value));&#10;        return copy.then(function (copied) {&#10;          copyBtn.textContent = viewerText(copied ? &amp;#x27;viewer.common.copied&amp;#x27; : &amp;#x27;viewer.common.copyFailed&amp;#x27;);&#10;          copyBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(copied ? &amp;#x27;viewer.route.copy.success&amp;#x27; : &amp;#x27;viewer.route.copy.failed&amp;#x27;));&#10;          window.setTimeout(function () {&#10;            copyBtn.textContent = viewerText(&amp;#x27;viewer.route.copy&amp;#x27;);&#10;            copyBtn.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.route.copy.aria&amp;#x27;));&#10;          }, 1600);&#10;          return copied;&#10;        });&#10;      }&#10;      function interceptSelection(event) {&#10;        if (mode !== &amp;#x27;source&amp;#x27; &amp;amp;&amp;amp; mode !== &amp;#x27;target&amp;#x27;) return;&#10;        if (container.getAttribute(&amp;#x27;data-just-panned&amp;#x27;) === &amp;#x27;true&amp;#x27;) return;&#10;        var node = event.target.closest(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (!node) return;&#10;        if (event.type === &amp;#x27;keydown&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27;Enter&amp;#x27; &amp;amp;&amp;amp; event.key !== &amp;#x27; &amp;#x27;) return;&#10;        event.preventDefault();&#10;        event.stopImmediatePropagation();&#10;        choose(node.getAttribute(&amp;#x27;data-node-id&amp;#x27;));&#10;      }&#10;      function syncFromHash() {&#10;        try {&#10;          var params = new URLSearchParams(location.hash.replace(/^#/, &amp;#x27;&amp;#x27;));&#10;          var route = params.get(&amp;#x27;route&amp;#x27;);&#10;          if (!route) {&#10;            if (mode !== &amp;#x27;idle&amp;#x27;) clear({ updateUrl: false, restoreFocus: false });&#10;            return;&#10;          }&#10;          var parts = route.split(&amp;#x27;~&amp;#x27;);&#10;          if (parts.length !== 2) return;&#10;          var byId = nodesById();&#10;          if (!byId[parts[0]] || !byId[parts[1]]) return;&#10;          begin({ source: parts[0], focusNode: false });&#10;          choose(parts[1], { updateUrl: false });&#10;        } catch (_) {}&#10;      }&#10;      function escapeRoute(options) {&#10;        options = options || {};&#10;        if (journeyPlaying) {&#10;          pauseJourney({ preserveElapsed: true });&#10;          if (options.restoreFocus === true) journeyPlayBtn.focus();&#10;          return &amp;#x27;paused&amp;#x27;;&#10;        }&#10;        if (journeyIndex &amp;gt;= 0) {&#10;          showJourneyOverview({ reveal: true });&#10;          if (options.restoreFocus === true) journeyOverviewBtn.focus();&#10;          return &amp;#x27;overview&amp;#x27;;&#10;        }&#10;        clear({ restoreFocus: options.restoreFocus === true });&#10;        return &amp;#x27;cleared&amp;#x27;;&#10;      }&#10;      function syncJourneyMotion() {&#10;        if (journeyPlaying &amp;amp;&amp;amp; !journeyMotionAllowed()) pauseJourney({ preserveElapsed: true });&#10;        renderJourneyControls();&#10;        return journeyMotionAllowed();&#10;      }&#10;&#10;      trigger.addEventListener(&amp;#x27;click&amp;#x27;, function () { toggle({ focusNode: false }); });&#10;      findBtn.addEventListener(&amp;#x27;click&amp;#x27;, openFinder);&#10;      clearBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { clear({ restoreFocus: true }); });&#10;      copyBtn.addEventListener(&amp;#x27;click&amp;#x27;, copyLink);&#10;      journeyPrevBtn.addEventListener(&amp;#x27;click&amp;#x27;, previousJourney);&#10;      journeyPlayBtn.addEventListener(&amp;#x27;click&amp;#x27;, toggleJourney);&#10;      journeyNextBtn.addEventListener(&amp;#x27;click&amp;#x27;, nextJourney);&#10;      journeyOverviewBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { showJourneyOverview({ reveal: true }); });&#10;      path.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-route-journey-index]&amp;#x27;);&#10;        if (!button) return;&#10;        selectJourneyIndex(Number(button.getAttribute(&amp;#x27;data-route-journey-index&amp;#x27;)));&#10;      });&#10;      path.addEventListener(&amp;#x27;focusin&amp;#x27;, function (event) {&#10;        if (journeyPlaying &amp;amp;&amp;amp; event.target.closest(&amp;#x27;[data-route-journey-index]&amp;#x27;)) pauseJourney({ preserveElapsed: true });&#10;      });&#10;      path.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-route-journey-index]&amp;#x27;);&#10;        if (!button) return;&#10;        var index = Number(button.getAttribute(&amp;#x27;data-route-journey-index&amp;#x27;));&#10;        var next = null;&#10;        if (event.key === &amp;#x27;ArrowRight&amp;#x27;) next = Math.min(activeNodeIds.length - 1, index + 1);&#10;        else if (event.key === &amp;#x27;ArrowLeft&amp;#x27;) next = Math.max(0, index - 1);&#10;        else if (event.key === &amp;#x27;Home&amp;#x27;) next = 0;&#10;        else if (event.key === &amp;#x27;End&amp;#x27;) next = activeNodeIds.length - 1;&#10;        if (next !== null) {&#10;          event.preventDefault();&#10;          focusJourneyButton(next);&#10;          return;&#10;        }&#10;        if (event.key === &amp;#x27;Enter&amp;#x27; || event.key === &amp;#x27; &amp;#x27;) {&#10;          event.preventDefault();&#10;          selectJourneyIndex(index);&#10;        }&#10;      });&#10;      svg.addEventListener(&amp;#x27;click&amp;#x27;, interceptSelection, true);&#10;      svg.addEventListener(&amp;#x27;keydown&amp;#x27;, interceptSelection, true);&#10;      container.addEventListener(&amp;#x27;scroll&amp;#x27;, updateDocking, { passive: true });&#10;      window.addEventListener(&amp;#x27;resize&amp;#x27;, requestDocking);&#10;      window.addEventListener(&amp;#x27;beforeprint&amp;#x27;, function () {&#10;        if (journeyPlaying) pauseJourney({ preserveElapsed: true, reason: &amp;#x27;print&amp;#x27; });&#10;        else removeJourneyPulse();&#10;      });&#10;      window.addEventListener(&amp;#x27;hashchange&amp;#x27;, function () { requestAnimationFrame(syncFromHash); });&#10;      syncFromHash();&#10;&#10;      return {&#10;        begin: begin,&#10;        choose: choose,&#10;        clear: clear,&#10;        toggle: toggle,&#10;        escape: escapeRoute,&#10;        copyLink: copyLink,&#10;        playJourney: playJourney,&#10;        pauseJourney: pauseJourney,&#10;        showOverview: showJourneyOverview,&#10;        selectJourneyIndex: selectJourneyIndex,&#10;        syncMotion: syncJourneyMotion,&#10;        isJourneyPlaying: function () { return journeyPlaying; },&#10;        finderContext: finderContext,&#10;        finderOpening: finderOpening,&#10;        finderClosed: finderClosed,&#10;        openFinder: openFinder,&#10;        exportSnapshot: exportSnapshot,&#10;        active: function () { return mode === &amp;#x27;idle&amp;#x27; ? null : mode; },&#10;        result: function () {&#10;          return mode === &amp;#x27;result&amp;#x27;&#10;            ? { source: startId, target: endId, nodes: activeNodeIds.slice(), hops: activeEdges.length, journey: journeyIndex, playing: journeyPlaying }&#10;            : null;&#10;        }&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Semantic Lens — a counted, viewer-only legend over data-node-kind.&#10;       One selected kind reveals every authored relationship touching it.&#10;       Two selected kinds compare only direct cross-kind relationships while&#10;       preserving the full diagram as a dimmed spatial reference.&#10;       ============================================================ */&#10;    Archify.semanticLens = (function () {&#10;      var html = document.documentElement;&#10;      var container = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var svg = container.querySelector(&amp;#x27;:scope &amp;gt; svg&amp;#x27;);&#10;      var trigger = document.getElementById(&amp;#x27;btn-semantic-lens&amp;#x27;);&#10;      var panel = document.getElementById(&amp;#x27;semantic-lens&amp;#x27;);&#10;      var closeBtn = document.getElementById(&amp;#x27;semantic-lens-close&amp;#x27;);&#10;      var kindsRoot = document.getElementById(&amp;#x27;semantic-lens-kinds&amp;#x27;);&#10;      var status = document.getElementById(&amp;#x27;semantic-lens-status&amp;#x27;);&#10;      var copyBtn = document.getElementById(&amp;#x27;semantic-lens-copy&amp;#x27;);&#10;      var clearBtn = document.getElementById(&amp;#x27;semantic-lens-clear&amp;#x27;);&#10;      var legendBridge = svg.querySelector(&amp;#x27;[data-legend-bridge]&amp;#x27;);&#10;      var legendEntries = [];&#10;      var hoveredLegendEntry = null;&#10;      var focusedLegendEntry = null;&#10;      var activeLegendPreview = null;&#10;      var lensOpener = trigger;&#10;      var selectedKinds = [];&#10;      var namespace = &amp;#x27;http://www.w3.org/2000/svg&amp;#x27;;&#10;      var finePointerQuery = window.matchMedia ? window.matchMedia(&amp;#x27;(hover: hover) and (pointer: fine)&amp;#x27;) : null;&#10;      var MAX_LENS_FLOW_EDGES = 24;&#10;&#10;      function nodesById() {&#10;        var byId = {};&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-node-id][data-node-kind]&amp;#x27;), function (node) {&#10;          var id = node.getAttribute(&amp;#x27;data-node-id&amp;#x27;);&#10;          if (id &amp;amp;&amp;amp; !byId[id]) byId[id] = node;&#10;        });&#10;        return byId;&#10;      }&#10;      function collectKinds() {&#10;        var kinds = {};&#10;        var byId = nodesById();&#10;        Object.keys(byId).forEach(function (id) {&#10;          var node = byId[id];&#10;          var value = node.getAttribute(&amp;#x27;data-node-kind&amp;#x27;) || &amp;#x27;neutral&amp;#x27;;&#10;          var kind = kinds[value] || (kinds[value] = { id: value, label: viewerKindLabel(value), nodes: [] });&#10;          kind.nodes.push(node);&#10;        });&#10;        return Object.keys(kinds).map(function (key) { return kinds[key]; }).sort(function (a, b) {&#10;          return b.nodes.length - a.nodes.length || a.label.localeCompare(b.label);&#10;        });&#10;      }&#10;      function edgeGroups() {&#10;        var groups = {};&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-edge-from][data-edge-to]&amp;#x27;), function (edge) {&#10;          var from = edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;          var to = edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;          var key = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) || [from, to, edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;].join(&amp;#x27;\u0000&amp;#x27;);&#10;          if (!groups[key]) groups[key] = { key: key, from: from, to: to, members: [] };&#10;          groups[key].members.push(edge);&#10;        });&#10;        return Object.keys(groups).map(function (key) { return groups[key]; });&#10;      }&#10;      function edgeShapes(edge) {&#10;        if (!edge) return [];&#10;        if (/^(path|line|polyline)$/i.test(edge.tagName || &amp;#x27;&amp;#x27;)) return [edge];&#10;        return Array.prototype.slice.call(edge.querySelectorAll(&amp;#x27;path, line, polyline&amp;#x27;));&#10;      }&#10;      function legendSourceBounds(entry) {&#10;        var bounds = null;&#10;        Array.prototype.forEach.call(entry.children, function (child) {&#10;          if (child.hasAttribute(&amp;#x27;data-legend-bridge-runtime&amp;#x27;)) return;&#10;          var box;&#10;          try { box = child.getBBox(); } catch (_) { return; }&#10;          if (!box || !Number.isFinite(box.x) || !Number.isFinite(box.y)) return;&#10;          var next = { left: box.x, top: box.y, right: box.x + box.width, bottom: box.y + box.height };&#10;          if (!bounds) bounds = next;&#10;          else {&#10;            bounds.left = Math.min(bounds.left, next.left);&#10;            bounds.top = Math.min(bounds.top, next.top);&#10;            bounds.right = Math.max(bounds.right, next.right);&#10;            bounds.bottom = Math.max(bounds.bottom, next.bottom);&#10;          }&#10;        });&#10;        return bounds;&#10;      }&#10;      function layoutLegendEntry(entry) {&#10;        var bounds = legendSourceBounds(entry);&#10;        var hit = entry.querySelector(&amp;#x27;[data-legend-hit]&amp;#x27;);&#10;        var badge = entry.querySelector(&amp;#x27;[data-legend-count-badge]&amp;#x27;);&#10;        if (!bounds || !hit || !badge) return false;&#10;        var count = entry.getAttribute(&amp;#x27;data-legend-count&amp;#x27;) || &amp;#x27;0&amp;#x27;;&#10;        var centerY = (bounds.top + bounds.bottom) / 2;&#10;        var badgeWidth = Math.max(14, count.length * 5 + 8);&#10;        var badgeX = bounds.right + 3;&#10;        var hitX = bounds.left - 5;&#10;        var hitRight = badgeX + badgeWidth + 4;&#10;        hit.setAttribute(&amp;#x27;x&amp;#x27;, hitX.toFixed(2));&#10;        hit.setAttribute(&amp;#x27;y&amp;#x27;, (centerY - 12).toFixed(2));&#10;        hit.setAttribute(&amp;#x27;width&amp;#x27;, Math.max(24, hitRight - hitX).toFixed(2));&#10;        hit.setAttribute(&amp;#x27;height&amp;#x27;, &amp;#x27;24&amp;#x27;);&#10;        hit.setAttribute(&amp;#x27;rx&amp;#x27;, &amp;#x27;4&amp;#x27;);&#10;        var badgeRect = badge.querySelector(&amp;#x27;rect&amp;#x27;);&#10;        var badgeText = badge.querySelector(&amp;#x27;text&amp;#x27;);&#10;        badgeRect.setAttribute(&amp;#x27;x&amp;#x27;, badgeX.toFixed(2));&#10;        badgeRect.setAttribute(&amp;#x27;y&amp;#x27;, (centerY - 7).toFixed(2));&#10;        badgeRect.setAttribute(&amp;#x27;width&amp;#x27;, badgeWidth.toFixed(2));&#10;        badgeRect.setAttribute(&amp;#x27;height&amp;#x27;, &amp;#x27;14&amp;#x27;);&#10;        badgeRect.setAttribute(&amp;#x27;rx&amp;#x27;, &amp;#x27;7&amp;#x27;);&#10;        badgeText.setAttribute(&amp;#x27;x&amp;#x27;, (badgeX + badgeWidth / 2).toFixed(2));&#10;        badgeText.setAttribute(&amp;#x27;y&amp;#x27;, (centerY + 2.5).toFixed(2));&#10;        return true;&#10;      }&#10;      function layoutLegendBridge() {&#10;        legendEntries.forEach(layoutLegendEntry);&#10;        if (!legendBridge) return;&#10;        Array.prototype.forEach.call(legendBridge.querySelectorAll(&amp;#x27;[data-legend-zero]&amp;#x27;), layoutLegendEntry);&#10;      }&#10;      function decorateLegendBridge() {&#10;        legendEntries = [];&#10;        if (!legendBridge || html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        var facts = {};&#10;        collectKinds().forEach(function (kind) { facts[kind.id] = kind; });&#10;        Array.prototype.forEach.call(legendBridge.querySelectorAll(&amp;#x27;[data-legend-kind]&amp;#x27;), function (entry) {&#10;          var kind = entry.getAttribute(&amp;#x27;data-legend-kind&amp;#x27;);&#10;          var fact = facts[kind];&#10;          var count = fact ? fact.nodes.length : 0;&#10;          entry.setAttribute(&amp;#x27;data-legend-count&amp;#x27;, String(count));&#10;          var hit = document.createElementNS(namespace, &amp;#x27;rect&amp;#x27;);&#10;          hit.setAttribute(&amp;#x27;data-legend-bridge-runtime&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          hit.setAttribute(&amp;#x27;data-legend-hit&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          hit.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          entry.insertBefore(hit, entry.firstChild);&#10;          var badge = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;          badge.setAttribute(&amp;#x27;data-legend-bridge-runtime&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          badge.setAttribute(&amp;#x27;data-legend-count-badge&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          badge.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          badge.appendChild(document.createElementNS(namespace, &amp;#x27;rect&amp;#x27;));&#10;          var countText = document.createElementNS(namespace, &amp;#x27;text&amp;#x27;);&#10;          countText.textContent = String(count);&#10;          badge.appendChild(countText);&#10;          entry.appendChild(badge);&#10;          if (!fact || !count) {&#10;            entry.setAttribute(&amp;#x27;data-legend-zero&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            return;&#10;          }&#10;          entry.setAttribute(&amp;#x27;role&amp;#x27;, &amp;#x27;button&amp;#x27;);&#10;          entry.setAttribute(&amp;#x27;tabindex&amp;#x27;, legendEntries.length ? &amp;#x27;-1&amp;#x27; : &amp;#x27;0&amp;#x27;);&#10;          var visibleLabel = entry.getAttribute(&amp;#x27;data-legend-label&amp;#x27;) || fact.label;&#10;          entry.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerCount(&amp;#x27;viewer.lens.legend.inspect&amp;#x27;, count, { label: visibleLabel }));&#10;          entry.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;          entry.setAttribute(&amp;#x27;aria-haspopup&amp;#x27;, &amp;#x27;dialog&amp;#x27;);&#10;          entry.setAttribute(&amp;#x27;aria-controls&amp;#x27;, &amp;#x27;semantic-lens&amp;#x27;);&#10;          entry.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;          legendEntries.push(entry);&#10;        });&#10;        if (!legendEntries.length) return false;&#10;        legendBridge.setAttribute(&amp;#x27;role&amp;#x27;, legendEntries.length &amp;gt;= 3 ? &amp;#x27;toolbar&amp;#x27; : &amp;#x27;group&amp;#x27;);&#10;        legendBridge.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.lens.legend&amp;#x27;));&#10;        syncLegendBridge();&#10;        layoutLegendBridge();&#10;        try {&#10;          if (document.fonts &amp;amp;&amp;amp; document.fonts.ready) document.fonts.ready.then(layoutLegendBridge);&#10;        } catch (_) {}&#10;        return true;&#10;      }&#10;      function syncLegendBridge() {&#10;        legendEntries.forEach(function (entry) {&#10;          var selected = selectedKinds.indexOf(entry.getAttribute(&amp;#x27;data-legend-kind&amp;#x27;)) &amp;gt;= 0;&#10;          entry.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, selected ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;          entry.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, !panel.hidden &amp;amp;&amp;amp; lensOpener === entry ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;          if (selected) entry.setAttribute(&amp;#x27;data-legend-selected&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          else entry.removeAttribute(&amp;#x27;data-legend-selected&amp;#x27;);&#10;        });&#10;      }&#10;      function clearLegendPreview() {&#10;        activeLegendPreview = null;&#10;        svg.removeAttribute(&amp;#x27;data-legend-preview-active&amp;#x27;);&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-legend-preview-match], [data-legend-preview-selected], [data-legend-preview-peer]&amp;#x27;), function (element) {&#10;          element.removeAttribute(&amp;#x27;data-legend-preview-match&amp;#x27;);&#10;          element.removeAttribute(&amp;#x27;data-legend-preview-selected&amp;#x27;);&#10;          element.removeAttribute(&amp;#x27;data-legend-preview-peer&amp;#x27;);&#10;        });&#10;      }&#10;      function strongerLegendOwnerActive() {&#10;        return selectedKinds.length &amp;gt; 0 || !panel.hidden || html.getAttribute(&amp;#x27;data-present&amp;#x27;) === &amp;#x27;true&amp;#x27; ||&#10;          svg.hasAttribute(&amp;#x27;data-focus-active&amp;#x27;) || svg.hasAttribute(&amp;#x27;data-intent-trace-active&amp;#x27;) ||&#10;          svg.hasAttribute(&amp;#x27;data-route-picking&amp;#x27;) || svg.hasAttribute(&amp;#x27;data-route-active&amp;#x27;) ||&#10;          svg.hasAttribute(&amp;#x27;data-story-active&amp;#x27;) || svg.hasAttribute(&amp;#x27;data-relationship-preview-active&amp;#x27;);&#10;      }&#10;      function previewLegendKind(entry) {&#10;        clearLegendPreview();&#10;        if (!entry || strongerLegendOwnerActive()) return false;&#10;        var kind = entry.getAttribute(&amp;#x27;data-legend-kind&amp;#x27;);&#10;        var byId = nodesById();&#10;        var matches = Object.keys(byId).filter(function (id) {&#10;          return (byId[id].getAttribute(&amp;#x27;data-node-kind&amp;#x27;) || &amp;#x27;neutral&amp;#x27;) === kind;&#10;        });&#10;        if (!matches.length) return false;&#10;        var chosen = {};&#10;        matches.forEach(function (id) {&#10;          chosen[id] = true;&#10;          byId[id].setAttribute(&amp;#x27;data-legend-preview-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          byId[id].setAttribute(&amp;#x27;data-legend-preview-selected&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        });&#10;        edgeGroups().forEach(function (edge) {&#10;          if (!chosen[edge.from] &amp;amp;&amp;amp; !chosen[edge.to]) return;&#10;          edge.members.forEach(function (member) { member.setAttribute(&amp;#x27;data-legend-preview-match&amp;#x27;, &amp;#x27;&amp;#x27;); });&#10;          [edge.from, edge.to].forEach(function (id) {&#10;            if (!byId[id] || chosen[id]) return;&#10;            byId[id].setAttribute(&amp;#x27;data-legend-preview-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            byId[id].setAttribute(&amp;#x27;data-legend-preview-peer&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          });&#10;        });&#10;        svg.setAttribute(&amp;#x27;data-legend-preview-active&amp;#x27;, kind);&#10;        activeLegendPreview = entry;&#10;        return true;&#10;      }&#10;      function syncLegendPreview() {&#10;        var next = focusedLegendEntry || hoveredLegendEntry;&#10;        if (next === activeLegendPreview) return;&#10;        clearLegendPreview();&#10;        if (next) previewLegendKind(next);&#10;      }&#10;      function activateLegendEntry(entry) {&#10;        if (!entry || entry.getAttribute(&amp;#x27;role&amp;#x27;) !== &amp;#x27;button&amp;#x27;) return false;&#10;        clearLegendPreview();&#10;        select(entry.getAttribute(&amp;#x27;data-legend-kind&amp;#x27;));&#10;        return open({ opener: entry });&#10;      }&#10;      function removeFlowOverlay() {&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-semantic-lens-overlay]&amp;#x27;), function (element) {&#10;          element.remove();&#10;        });&#10;        svg.removeAttribute(&amp;#x27;data-lens-flow-count&amp;#x27;);&#10;        svg.removeAttribute(&amp;#x27;data-lens-flow-density&amp;#x27;);&#10;      }&#10;      function flowGeometry(shape, direction, step) {&#10;        var clone = shape.cloneNode(false);&#10;        clone.removeAttribute(&amp;#x27;id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;class&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;style&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-start&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-mid&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;marker-end&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;role&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;aria-hidden&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-animate&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-from&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-to&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-key&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-id&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-edge-label&amp;#x27;);&#10;        clone.removeAttribute(&amp;#x27;data-lens-match&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;semantic-lens-flow&amp;#x27;);&#10;        clone.setAttribute(&amp;#x27;data-direction&amp;#x27;, direction);&#10;        clone.setAttribute(&amp;#x27;pathLength&amp;#x27;, &amp;#x27;1&amp;#x27;);&#10;        clone.style.setProperty(&amp;#x27;--lens-flow-delay&amp;#x27;, (step * 0.08).toFixed(2) + &amp;#x27;s&amp;#x27;);&#10;        return clone;&#10;      }&#10;      function renderFlowOverlay(entries) {&#10;        removeFlowOverlay();&#10;        svg.setAttribute(&amp;#x27;data-lens-flow-count&amp;#x27;, String(entries.length));&#10;        if (!entries.length || html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        if (entries.length &amp;gt; MAX_LENS_FLOW_EDGES) {&#10;          svg.setAttribute(&amp;#x27;data-lens-flow-density&amp;#x27;, &amp;#x27;quiet&amp;#x27;);&#10;          return false;&#10;        }&#10;        var overlay = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;class&amp;#x27;, &amp;#x27;semantic-lens-overlay&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;data-semantic-lens-overlay&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        overlay.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        entries.forEach(function (entry, step) {&#10;          var wrapper = document.createElementNS(namespace, &amp;#x27;g&amp;#x27;);&#10;          if (entry.edge.members[0].hasAttribute(&amp;#x27;transform&amp;#x27;)) {&#10;            wrapper.setAttribute(&amp;#x27;transform&amp;#x27;, entry.edge.members[0].getAttribute(&amp;#x27;transform&amp;#x27;));&#10;          }&#10;          edgeShapes(entry.edge.members[0]).forEach(function (shape) {&#10;            wrapper.appendChild(flowGeometry(shape, entry.direction, step));&#10;          });&#10;          if (wrapper.childNodes.length) overlay.appendChild(wrapper);&#10;        });&#10;        if (!overlay.childNodes.length) return false;&#10;        var firstNode = svg.querySelector(&amp;#x27;[data-node-id]&amp;#x27;);&#10;        if (firstNode) svg.insertBefore(overlay, firstNode);&#10;        else svg.appendChild(overlay);&#10;        return true;&#10;      }&#10;      function cleanSvgState() {&#10;        removeFlowOverlay();&#10;        svg.removeAttribute(&amp;#x27;data-lens-active&amp;#x27;);&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-lens-match], [data-lens-selected], [data-lens-peer]&amp;#x27;), function (element) {&#10;          element.removeAttribute(&amp;#x27;data-lens-match&amp;#x27;);&#10;          element.removeAttribute(&amp;#x27;data-lens-selected&amp;#x27;);&#10;          element.removeAttribute(&amp;#x27;data-lens-peer&amp;#x27;);&#10;        });&#10;      }&#10;      function renderKinds() {&#10;        kindsRoot.textContent = &amp;#x27;&amp;#x27;;&#10;        collectKinds().forEach(function (kind) {&#10;          var button = document.createElement(&amp;#x27;button&amp;#x27;);&#10;          button.type = &amp;#x27;button&amp;#x27;;&#10;          button.className = &amp;#x27;semantic-lens-kind&amp;#x27;;&#10;          button.setAttribute(&amp;#x27;data-kind&amp;#x27;, kind.id);&#10;          button.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, selectedKinds.indexOf(kind.id) &amp;gt;= 0 ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;          button.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerCount(&amp;#x27;viewer.lens.kind.count&amp;#x27;, kind.nodes.length, { label: kind.label }));&#10;          button.disabled = selectedKinds.length &amp;gt;= 2 &amp;amp;&amp;amp; selectedKinds.indexOf(kind.id) === -1;&#10;          var swatch = document.createElement(&amp;#x27;span&amp;#x27;);&#10;          swatch.className = &amp;#x27;semantic-lens-swatch&amp;#x27;;&#10;          swatch.setAttribute(&amp;#x27;aria-hidden&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;          var label = document.createElement(&amp;#x27;strong&amp;#x27;);&#10;          label.textContent = kind.label;&#10;          var count = document.createElement(&amp;#x27;em&amp;#x27;);&#10;          count.textContent = String(kind.nodes.length);&#10;          button.appendChild(swatch);&#10;          button.appendChild(label);&#10;          button.appendChild(count);&#10;          kindsRoot.appendChild(button);&#10;        });&#10;      }&#10;      function updateHash() {&#10;        try {&#10;          var hash = selectedKinds.length&#10;            ? &amp;#x27;#lens=&amp;#x27; + selectedKinds.map(encodeURIComponent).join(&amp;#x27;~&amp;#x27;)&#10;            : &amp;#x27;&amp;#x27;;&#10;          history.replaceState(null, &amp;#x27;&amp;#x27;, location.pathname + location.search + hash);&#10;        } catch (_) {}&#10;      }&#10;      function updateTrigger() {&#10;        var active = selectedKinds.length &amp;gt; 0;&#10;        trigger.setAttribute(&amp;#x27;aria-pressed&amp;#x27;, active ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(active ? &amp;#x27;viewer.lens.openActive&amp;#x27; : &amp;#x27;viewer.lens.open&amp;#x27;));&#10;        copyBtn.hidden = !active;&#10;        syncLegendBridge();&#10;      }&#10;      function overlapArea(a, b) {&#10;        var width = Math.max(0, Math.min(a.right, b.right) - Math.max(a.left, b.left));&#10;        var height = Math.max(0, Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top));&#10;        return width * height;&#10;      }&#10;      function dockPanel(byId) {&#10;        panel.removeAttribute(&amp;#x27;data-dock-side&amp;#x27;);&#10;        if (panel.hidden || window.innerWidth &amp;lt;= 720) return &amp;#x27;right&amp;#x27;;&#10;        var panelRect = panel.getBoundingClientRect();&#10;        var containerRect = container.getBoundingClientRect();&#10;        if (!panelRect.width || !panelRect.height) return &amp;#x27;right&amp;#x27;;&#10;        var selectedRects = Object.keys(byId).filter(function (id) {&#10;          return selectedKinds.indexOf(byId[id].getAttribute(&amp;#x27;data-node-kind&amp;#x27;) || &amp;#x27;neutral&amp;#x27;) &amp;gt;= 0;&#10;        }).map(function (id) { return byId[id].getBoundingClientRect(); });&#10;        var top = panelRect.top;&#10;        var width = panelRect.width;&#10;        var leftCandidate = { left: containerRect.left + 16, right: containerRect.left + 16 + width, top: top, bottom: panelRect.bottom };&#10;        var rightCandidate = { left: containerRect.right - 16 - width, right: containerRect.right - 16, top: top, bottom: panelRect.bottom };&#10;        var leftScore = selectedRects.reduce(function (score, rect) { return score + overlapArea(leftCandidate, rect); }, 0);&#10;        var rightScore = selectedRects.reduce(function (score, rect) { return score + overlapArea(rightCandidate, rect); }, 0);&#10;        var legend = svg.querySelector(&amp;#x27;[data-legend]&amp;#x27;);&#10;        var nav = container.querySelector(&amp;#x27;.diagram-nav&amp;#x27;);&#10;        var protectedRects = [legend, nav].filter(function (element) {&#10;          return element &amp;amp;&amp;amp; !element.hidden &amp;amp;&amp;amp; window.getComputedStyle(element).display !== &amp;#x27;none&amp;#x27;;&#10;        }).map(function (element) { return element.getBoundingClientRect(); });&#10;        leftScore += protectedRects.reduce(function (score, rect) {&#10;          return score + overlapArea(leftCandidate, rect) * 1000;&#10;        }, 0);&#10;        rightScore += protectedRects.reduce(function (score, rect) {&#10;          return score + overlapArea(rightCandidate, rect) * 1000;&#10;        }, 0);&#10;        var side = leftScore &amp;lt; rightScore ? &amp;#x27;left&amp;#x27; : &amp;#x27;right&amp;#x27;;&#10;        panel.setAttribute(&amp;#x27;data-dock-side&amp;#x27;, side);&#10;        return side;&#10;      }&#10;      function applySelection(options) {&#10;        options = options || {};&#10;        cleanSvgState();&#10;        var byId = nodesById();&#10;        var nodeKind = {};&#10;        Object.keys(byId).forEach(function (id) { nodeKind[id] = byId[id].getAttribute(&amp;#x27;data-node-kind&amp;#x27;) || &amp;#x27;neutral&amp;#x27;; });&#10;        if (!selectedKinds.length) {&#10;          status.textContent = viewerText(&amp;#x27;viewer.lens.choose&amp;#x27;);&#10;          updateTrigger();&#10;          renderKinds();&#10;          dockPanel(byId);&#10;          if (options.updateUrl !== false) updateHash();&#10;          return false;&#10;        }&#10;&#10;        var chosen = {};&#10;        selectedKinds.forEach(function (kind) { chosen[kind] = true; });&#10;        Object.keys(byId).forEach(function (id) {&#10;          if (!chosen[nodeKind[id]]) return;&#10;          byId[id].setAttribute(&amp;#x27;data-lens-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;          byId[id].setAttribute(&amp;#x27;data-lens-selected&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        });&#10;&#10;        var touching = 0;&#10;        var forward = 0;&#10;        var reverse = 0;&#10;        var crossKind = selectedKinds.length === 2;&#10;        var matchedFlow = [];&#10;        edgeGroups().forEach(function (edge) {&#10;          var fromKind = nodeKind[edge.from];&#10;          var toKind = nodeKind[edge.to];&#10;          var match = false;&#10;          if (crossKind) {&#10;            if (fromKind === selectedKinds[0] &amp;amp;&amp;amp; toKind === selectedKinds[1]) { match = true; forward += 1; }&#10;            if (fromKind === selectedKinds[1] &amp;amp;&amp;amp; toKind === selectedKinds[0]) { match = true; reverse += 1; }&#10;          } else if (fromKind === selectedKinds[0] || toKind === selectedKinds[0]) {&#10;            match = true;&#10;            touching += 1;&#10;          }&#10;          if (!match) return;&#10;          var direction = &amp;#x27;within&amp;#x27;;&#10;          if (crossKind) {&#10;            direction = fromKind === selectedKinds[0] ? &amp;#x27;forward&amp;#x27; : &amp;#x27;reverse&amp;#x27;;&#10;          } else {&#10;            direction = fromKind === selectedKinds[0] &amp;amp;&amp;amp; toKind !== selectedKinds[0] ? &amp;#x27;out&amp;#x27;&#10;              : (toKind === selectedKinds[0] &amp;amp;&amp;amp; fromKind !== selectedKinds[0] ? &amp;#x27;in&amp;#x27; : &amp;#x27;within&amp;#x27;);&#10;          }&#10;          matchedFlow.push({ edge: edge, direction: direction });&#10;          edge.members.forEach(function (member) { member.setAttribute(&amp;#x27;data-lens-match&amp;#x27;, &amp;#x27;&amp;#x27;); });&#10;          if (!crossKind) {&#10;            [edge.from, edge.to].forEach(function (id) {&#10;              if (!byId[id]) return;&#10;              byId[id].setAttribute(&amp;#x27;data-lens-match&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;              if (!chosen[nodeKind[id]]) byId[id].setAttribute(&amp;#x27;data-lens-peer&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;            });&#10;          }&#10;        });&#10;&#10;        svg.setAttribute(&amp;#x27;data-lens-active&amp;#x27;, selectedKinds.join(&amp;#x27; &amp;#x27;));&#10;        renderFlowOverlay(matchedFlow);&#10;        if (crossKind) {&#10;          var total = forward + reverse;&#10;          status.textContent = viewerCount(&amp;#x27;viewer.lens.compare&amp;#x27;, total, {&#10;            first: viewerKindLabel(selectedKinds[0]),&#10;            second: viewerKindLabel(selectedKinds[1]),&#10;            forward: forward,&#10;            reverse: reverse&#10;          });&#10;        } else {&#10;          var nodeCount = collectKinds().filter(function (kind) { return kind.id === selectedKinds[0]; })[0].nodes.length;&#10;          status.textContent = viewerText(&amp;#x27;viewer.lens.single&amp;#x27;, {&#10;            nodes: viewerCount(&amp;#x27;viewer.lens.node&amp;#x27;, nodeCount, { label: viewerKindLabel(selectedKinds[0]) }),&#10;            relationships: viewerCount(&amp;#x27;viewer.lens.relationship&amp;#x27;, touching)&#10;          });&#10;        }&#10;        updateTrigger();&#10;        renderKinds();&#10;        dockPanel(byId);&#10;        if (options.updateUrl !== false) updateHash();&#10;        return true;&#10;      }&#10;      function prepareForLens() {&#10;        clearLegendPreview();&#10;        if (Archify.focus &amp;amp;&amp;amp; typeof Archify.focus.clear === &amp;#x27;function&amp;#x27;) {&#10;          Archify.focus.clear({ updateUrl: false, preserveView: true });&#10;        }&#10;        if (Archify.routeProbe &amp;amp;&amp;amp; typeof Archify.routeProbe.clear === &amp;#x27;function&amp;#x27;) {&#10;          Archify.routeProbe.clear({ updateUrl: false, restoreFocus: false });&#10;        }&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; typeof Archify.guidedViews.showAll === &amp;#x27;function&amp;#x27;) {&#10;          Archify.guidedViews.showAll({ clearFocus: false, updateUrl: false });&#10;        }&#10;        if (Archify.intentTrace &amp;amp;&amp;amp; typeof Archify.intentTrace.clear === &amp;#x27;function&amp;#x27;) {&#10;          Archify.intentTrace.clear({ announce: false });&#10;        }&#10;      }&#10;      function select(kind, options) {&#10;        options = options || {};&#10;        clearLegendPreview();&#10;        var exists = collectKinds().some(function (entry) { return entry.id === kind; });&#10;        if (!exists) return false;&#10;        var index = selectedKinds.indexOf(kind);&#10;        if (index &amp;gt;= 0) selectedKinds.splice(index, 1);&#10;        else {&#10;          if (selectedKinds.length &amp;gt;= 2) return false;&#10;          if (!selectedKinds.length) prepareForLens();&#10;          selectedKinds.push(kind);&#10;        }&#10;        return applySelection(options);&#10;      }&#10;      function close(options) {&#10;        options = options || {};&#10;        panel.hidden = true;&#10;        trigger.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        updateTrigger();&#10;        if (options.restoreFocus !== false &amp;amp;&amp;amp; lensOpener &amp;amp;&amp;amp; typeof lensOpener.focus === &amp;#x27;function&amp;#x27;) lensOpener.focus();&#10;        return false;&#10;      }&#10;      function open(options) {&#10;        options = options || {};&#10;        if (html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        lensOpener = options.opener || trigger;&#10;        if (Archify.exportMenu &amp;amp;&amp;amp; Archify.exportMenu.isOpen()) Archify.exportMenu.close(false);&#10;        if (Archify.finder &amp;amp;&amp;amp; Archify.finder.isOpen()) Archify.finder.close({ restoreFocus: false });&#10;        if (Archify.radar &amp;amp;&amp;amp; Archify.radar.isOpen()) Archify.radar.close({ restoreFocus: false });&#10;        if (Archify.guide &amp;amp;&amp;amp; Archify.guide.isOpen()) Archify.guide.close({ restoreFocus: false });&#10;        renderKinds();&#10;        panel.hidden = false;&#10;        trigger.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        updateTrigger();&#10;        requestAnimationFrame(function () {&#10;          dockPanel(nodesById());&#10;          var activeButton = kindsRoot.querySelector(&amp;#x27;[aria-pressed=&amp;quot;true&amp;quot;]&amp;#x27;);&#10;          var firstButton = activeButton || kindsRoot.querySelector(&amp;#x27;button:not(:disabled)&amp;#x27;);&#10;          if (firstButton) firstButton.focus();&#10;        });&#10;        return true;&#10;      }&#10;      function toggle() { return panel.hidden ? open({ opener: trigger }) : close(); }&#10;      function clear(options) {&#10;        options = options || {};&#10;        selectedKinds = [];&#10;        cleanSvgState();&#10;        panel.removeAttribute(&amp;#x27;data-dock-side&amp;#x27;);&#10;        updateTrigger();&#10;        renderKinds();&#10;        status.textContent = viewerText(&amp;#x27;viewer.lens.choose&amp;#x27;);&#10;        if (options.updateUrl !== false) updateHash();&#10;        if (options.preserveView !== true &amp;amp;&amp;amp; Archify.view &amp;amp;&amp;amp; typeof Archify.view.reset === &amp;#x27;function&amp;#x27;) {&#10;          Archify.view.reset({ automatic: true });&#10;        }&#10;        if (options.closePanel === true) close({ restoreFocus: false });&#10;        return false;&#10;      }&#10;      function fallbackCopy(value) {&#10;        var field = document.createElement(&amp;#x27;textarea&amp;#x27;);&#10;        field.value = value;&#10;        field.setAttribute(&amp;#x27;readonly&amp;#x27;, &amp;#x27;&amp;#x27;);&#10;        field.style.position = &amp;#x27;fixed&amp;#x27;;&#10;        field.style.opacity = &amp;#x27;0&amp;#x27;;&#10;        document.body.appendChild(field);&#10;        field.select();&#10;        var copied = false;&#10;        try { copied = document.execCommand(&amp;#x27;copy&amp;#x27;); } catch (_) {}&#10;        field.remove();&#10;        return copied;&#10;      }&#10;      function copyLink() {&#10;        if (!selectedKinds.length) return Promise.resolve(false);&#10;        var value = location.href.replace(/#.*$/, &amp;#x27;&amp;#x27;) + &amp;#x27;#lens=&amp;#x27; + selectedKinds.map(encodeURIComponent).join(&amp;#x27;~&amp;#x27;);&#10;        var copy = navigator.clipboard &amp;amp;&amp;amp; typeof navigator.clipboard.writeText === &amp;#x27;function&amp;#x27;&#10;          ? navigator.clipboard.writeText(value).then(function () { return true; }).catch(function () { return fallbackCopy(value); })&#10;          : Promise.resolve(fallbackCopy(value));&#10;        return copy.then(function (copied) {&#10;          copyBtn.textContent = viewerText(copied ? &amp;#x27;viewer.common.copied&amp;#x27; : &amp;#x27;viewer.common.copyFailed&amp;#x27;);&#10;          window.setTimeout(function () { copyBtn.textContent = viewerText(&amp;#x27;viewer.common.copyLink&amp;#x27;); }, 1600);&#10;          return copied;&#10;        });&#10;      }&#10;      function syncFromHash() {&#10;        try {&#10;          var params = new URLSearchParams(location.hash.replace(/^#/, &amp;#x27;&amp;#x27;));&#10;          var value = params.get(&amp;#x27;lens&amp;#x27;);&#10;          if (!value) {&#10;            if (selectedKinds.length) clear({ updateUrl: false, preserveView: true });&#10;            return;&#10;          }&#10;          var available = collectKinds().map(function (kind) { return kind.id; });&#10;          var requested = value.split(&amp;#x27;~&amp;#x27;).filter(function (kind, index, list) {&#10;            return available.indexOf(kind) &amp;gt;= 0 &amp;amp;&amp;amp; list.indexOf(kind) === index;&#10;          }).slice(0, 2);&#10;          if (!requested.length) return;&#10;          prepareForLens();&#10;          selectedKinds = requested;&#10;          applySelection({ updateUrl: false });&#10;        } catch (_) {}&#10;      }&#10;&#10;      trigger.addEventListener(&amp;#x27;click&amp;#x27;, toggle);&#10;      if (decorateLegendBridge()) {&#10;        legendBridge.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;          var entry = event.target.closest(&amp;#x27;[data-legend-kind][role=&amp;quot;button&amp;quot;]&amp;#x27;);&#10;          if (entry) activateLegendEntry(entry);&#10;        });&#10;        legendBridge.addEventListener(&amp;#x27;pointerover&amp;#x27;, function (event) {&#10;          if (event.pointerType === &amp;#x27;touch&amp;#x27; || (finePointerQuery &amp;amp;&amp;amp; !finePointerQuery.matches)) return;&#10;          var entry = event.target.closest(&amp;#x27;[data-legend-kind][role=&amp;quot;button&amp;quot;]&amp;#x27;);&#10;          if (!entry || (event.relatedTarget &amp;amp;&amp;amp; entry.contains(event.relatedTarget))) return;&#10;          hoveredLegendEntry = entry;&#10;          syncLegendPreview();&#10;        });&#10;        legendBridge.addEventListener(&amp;#x27;pointerout&amp;#x27;, function (event) {&#10;          var entry = event.target.closest(&amp;#x27;[data-legend-kind][role=&amp;quot;button&amp;quot;]&amp;#x27;);&#10;          if (!entry || (event.relatedTarget &amp;amp;&amp;amp; entry.contains(event.relatedTarget))) return;&#10;          if (hoveredLegendEntry === entry) hoveredLegendEntry = null;&#10;          syncLegendPreview();&#10;        });&#10;        legendBridge.addEventListener(&amp;#x27;focusin&amp;#x27;, function (event) {&#10;          var entry = event.target.closest(&amp;#x27;[data-legend-kind][role=&amp;quot;button&amp;quot;]&amp;#x27;);&#10;          if (!entry) return;&#10;          focusedLegendEntry = entry;&#10;          legendEntries.forEach(function (candidate) {&#10;            candidate.setAttribute(&amp;#x27;tabindex&amp;#x27;, candidate === entry ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;          });&#10;          syncLegendPreview();&#10;        });&#10;        legendBridge.addEventListener(&amp;#x27;focusout&amp;#x27;, function (event) {&#10;          var entry = event.target.closest(&amp;#x27;[data-legend-kind][role=&amp;quot;button&amp;quot;]&amp;#x27;);&#10;          if (!entry || (event.relatedTarget &amp;amp;&amp;amp; entry.contains(event.relatedTarget))) return;&#10;          if (focusedLegendEntry === entry) focusedLegendEntry = null;&#10;          syncLegendPreview();&#10;        });&#10;        legendBridge.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;          var entry = event.target.closest(&amp;#x27;[data-legend-kind][role=&amp;quot;button&amp;quot;]&amp;#x27;);&#10;          if (!entry) return;&#10;          if (event.key === &amp;#x27;Enter&amp;#x27; || event.key === &amp;#x27; &amp;#x27;) {&#10;            event.preventDefault();&#10;            activateLegendEntry(entry);&#10;            return;&#10;          }&#10;          var index = legendEntries.indexOf(entry);&#10;          var next = null;&#10;          if (event.key === &amp;#x27;ArrowRight&amp;#x27;) next = (index + 1) % legendEntries.length;&#10;          else if (event.key === &amp;#x27;ArrowLeft&amp;#x27;) next = (index - 1 + legendEntries.length) % legendEntries.length;&#10;          else if (event.key === &amp;#x27;Home&amp;#x27;) next = 0;&#10;          else if (event.key === &amp;#x27;End&amp;#x27;) next = legendEntries.length - 1;&#10;          if (next === null) return;&#10;          event.preventDefault();&#10;          legendEntries.forEach(function (candidate, candidateIndex) {&#10;            candidate.setAttribute(&amp;#x27;tabindex&amp;#x27;, candidateIndex === next ? &amp;#x27;0&amp;#x27; : &amp;#x27;-1&amp;#x27;);&#10;          });&#10;          legendEntries[next].focus();&#10;        });&#10;      }&#10;      closeBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { close(); });&#10;      clearBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { clear({ preserveView: true }); });&#10;      copyBtn.addEventListener(&amp;#x27;click&amp;#x27;, copyLink);&#10;      kindsRoot.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-kind]&amp;#x27;);&#10;        if (!button || button.disabled) return;&#10;        select(button.getAttribute(&amp;#x27;data-kind&amp;#x27;));&#10;      });&#10;      kindsRoot.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        var buttons = Array.prototype.slice.call(kindsRoot.querySelectorAll(&amp;#x27;button:not(:disabled)&amp;#x27;));&#10;        var index = buttons.indexOf(document.activeElement);&#10;        var next = null;&#10;        if (index &amp;gt;= 0 &amp;amp;&amp;amp; (event.key === &amp;#x27;ArrowRight&amp;#x27; || event.key === &amp;#x27;ArrowDown&amp;#x27;)) next = (index + 1) % buttons.length;&#10;        else if (index &amp;gt;= 0 &amp;amp;&amp;amp; (event.key === &amp;#x27;ArrowLeft&amp;#x27; || event.key === &amp;#x27;ArrowUp&amp;#x27;)) next = (index - 1 + buttons.length) % buttons.length;&#10;        else if (event.key === &amp;#x27;Home&amp;#x27; &amp;amp;&amp;amp; buttons.length) next = 0;&#10;        else if (event.key === &amp;#x27;End&amp;#x27; &amp;amp;&amp;amp; buttons.length) next = buttons.length - 1;&#10;        if (next !== null) { event.preventDefault(); buttons[next].focus(); }&#10;      });&#10;      panel.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        if (event.key !== &amp;#x27;Escape&amp;#x27;) return;&#10;        event.preventDefault();&#10;        event.stopPropagation();&#10;        close();&#10;      });&#10;      document.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        var eventPath = typeof event.composedPath === &amp;#x27;function&amp;#x27; ? event.composedPath() : [];&#10;        var clickedInside = eventPath.indexOf(panel) &amp;gt;= 0 || panel.contains(event.target);&#10;        var clickedLauncher = event.target === trigger || legendEntries.some(function (entry) {&#10;          return event.target === entry || entry.contains(event.target);&#10;        });&#10;        if (!panel.hidden &amp;amp;&amp;amp; !clickedInside &amp;amp;&amp;amp; !clickedLauncher) close({ restoreFocus: false });&#10;      });&#10;      window.addEventListener(&amp;#x27;hashchange&amp;#x27;, syncFromHash);&#10;      window.addEventListener(&amp;#x27;resize&amp;#x27;, function () {&#10;        if (!panel.hidden &amp;amp;&amp;amp; selectedKinds.length) dockPanel(nodesById());&#10;        layoutLegendBridge();&#10;      });&#10;      renderKinds();&#10;      syncFromHash();&#10;&#10;      return {&#10;        open: open,&#10;        close: close,&#10;        toggle: toggle,&#10;        clear: clear,&#10;        clearPreview: clearLegendPreview,&#10;        select: select,&#10;        copyLink: copyLink,&#10;        isOpen: function () { return !panel.hidden; },&#10;        active: function () { return selectedKinds.length ? selectedKinds.slice() : null; },&#10;        kinds: function () { return collectKinds().map(function (kind) { return { id: kind.id, count: kind.nodes.length }; }); }&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Diagram Guide — a factual command deck over existing interactions.&#10;       Counts come from compiled semantics; actions delegate to Finder, Route&#10;       Probe, Semantic Radar, Semantic Lens, Story Trail, Presentation, theme, export, and&#10;       camera without adding a second command implementation or SVG state.&#10;       ============================================================ */&#10;    Archify.guide = (function () {&#10;      var html = document.documentElement;&#10;      var container = document.querySelector(&amp;#x27;.diagram-container&amp;#x27;);&#10;      var svg = container.querySelector(&amp;#x27;:scope &amp;gt; svg&amp;#x27;);&#10;      var trigger = document.getElementById(&amp;#x27;btn-diagram-guide&amp;#x27;);&#10;      var panel = document.getElementById(&amp;#x27;diagram-guide&amp;#x27;);&#10;      var closeBtn = document.getElementById(&amp;#x27;diagram-guide-close&amp;#x27;);&#10;      var stats = document.getElementById(&amp;#x27;diagram-guide-stats&amp;#x27;);&#10;      var actions = document.getElementById(&amp;#x27;diagram-guide-actions&amp;#x27;);&#10;      var feedback = document.getElementById(&amp;#x27;diagram-guide-feedback&amp;#x27;);&#10;      var storyBtn = actions.querySelector(&amp;#x27;[data-guide-action=&amp;quot;story&amp;quot;]&amp;#x27;);&#10;      var storyCopy = document.getElementById(&amp;#x27;diagram-guide-story-copy&amp;#x27;);&#10;      var routePanel = document.getElementById(&amp;#x27;route-probe&amp;#x27;);&#10;&#10;      function viewCount() {&#10;        return Archify.guidedViews &amp;amp;&amp;amp; Number(Archify.guidedViews.count) || 0;&#10;      }&#10;      function relationshipCount() {&#10;        var seen = {};&#10;        Array.prototype.forEach.call(svg.querySelectorAll(&amp;#x27;[data-edge-from][data-edge-to]&amp;#x27;), function (edge) {&#10;          var key = edge.getAttribute(&amp;#x27;data-edge-key&amp;#x27;) || [&#10;            edge.getAttribute(&amp;#x27;data-edge-from&amp;#x27;),&#10;            edge.getAttribute(&amp;#x27;data-edge-to&amp;#x27;),&#10;            edge.getAttribute(&amp;#x27;data-edge-label&amp;#x27;) || &amp;#x27;&amp;#x27;&#10;          ].join(&amp;#x27;\u0000&amp;#x27;);&#10;          seen[key] = true;&#10;        });&#10;        return Object.keys(seen).length;&#10;      }&#10;      function renderFacts() {&#10;        var nodes = svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;).length;&#10;        var relationships = relationshipCount();&#10;        var views = viewCount();&#10;        stats.textContent = viewerText(&amp;#x27;viewer.guide.facts&amp;#x27;, {&#10;          nodes: viewerCount(&amp;#x27;viewer.guide.fact.node&amp;#x27;, nodes),&#10;          relationships: viewerCount(&amp;#x27;viewer.guide.fact.relationship&amp;#x27;, relationships),&#10;          views: viewerCount(&amp;#x27;viewer.guide.fact.view&amp;#x27;, views)&#10;        });&#10;        storyBtn.disabled = views === 0;&#10;        storyBtn.setAttribute(&amp;#x27;aria-disabled&amp;#x27;, views === 0 ? &amp;#x27;true&amp;#x27; : &amp;#x27;false&amp;#x27;);&#10;        storyCopy.textContent = views&#10;          ? viewerCount(&amp;#x27;viewer.guide.story.available&amp;#x27;, views)&#10;          : viewerText(&amp;#x27;viewer.guide.story.unavailable&amp;#x27;);&#10;      }&#10;      function actionButtons() {&#10;        return Array.prototype.slice.call(actions.querySelectorAll(&amp;#x27;.diagram-guide-action:not(:disabled)&amp;#x27;));&#10;      }&#10;      function close(options) {&#10;        options = options || {};&#10;        panel.hidden = true;&#10;        html.removeAttribute(&amp;#x27;data-guide-open&amp;#x27;);&#10;        routePanel.removeAttribute(&amp;#x27;data-guide-open&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;false&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.guide.open&amp;#x27;));&#10;        feedback.textContent = &amp;#x27;&amp;#x27;;&#10;        if (options.restoreFocus !== false) trigger.focus();&#10;        return false;&#10;      }&#10;      function open() {&#10;        if (html.getAttribute(&amp;#x27;data-embed&amp;#x27;) === &amp;#x27;true&amp;#x27;) return false;&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; typeof Archify.semanticLens.clearPreview === &amp;#x27;function&amp;#x27;) Archify.semanticLens.clearPreview();&#10;        if (Archify.exportMenu &amp;amp;&amp;amp; Archify.exportMenu.isOpen()) Archify.exportMenu.close(false);&#10;        if (Archify.finder &amp;amp;&amp;amp; Archify.finder.isOpen()) Archify.finder.close({ restoreFocus: false });&#10;        if (Archify.radar &amp;amp;&amp;amp; Archify.radar.isOpen()) Archify.radar.close({ restoreFocus: false });&#10;        if (Archify.semanticLens &amp;amp;&amp;amp; Archify.semanticLens.isOpen()) Archify.semanticLens.close({ restoreFocus: false });&#10;        if (Archify.guidedViews &amp;amp;&amp;amp; Archify.guidedViews.isPlaying &amp;amp;&amp;amp; Archify.guidedViews.isPlaying()) {&#10;          Archify.guidedViews.pause();&#10;        }&#10;        if (Archify.routeProbe &amp;amp;&amp;amp; Archify.routeProbe.isJourneyPlaying &amp;amp;&amp;amp; Archify.routeProbe.isJourneyPlaying()) {&#10;          Archify.routeProbe.pauseJourney({ preserveElapsed: true, reason: &amp;#x27;guide&amp;#x27; });&#10;        }&#10;        renderFacts();&#10;        panel.hidden = false;&#10;        html.setAttribute(&amp;#x27;data-guide-open&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        routePanel.setAttribute(&amp;#x27;data-guide-open&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-expanded&amp;#x27;, &amp;#x27;true&amp;#x27;);&#10;        trigger.setAttribute(&amp;#x27;aria-label&amp;#x27;, viewerText(&amp;#x27;viewer.guide.close&amp;#x27;));&#10;        feedback.textContent = &amp;#x27;&amp;#x27;;&#10;        requestAnimationFrame(function () {&#10;          var first = actionButtons()[0];&#10;          if (first) first.focus();&#10;        });&#10;        return true;&#10;      }&#10;      function toggle() { return panel.hidden ? open() : close(); }&#10;      function execute(action) {&#10;        feedback.textContent = &amp;#x27;&amp;#x27;;&#10;        if (action === &amp;#x27;story&amp;#x27; &amp;amp;&amp;amp; !viewCount()) {&#10;          feedback.textContent = viewerText(&amp;#x27;viewer.guide.noStory&amp;#x27;);&#10;          return false;&#10;        }&#10;        close({ restoreFocus: false });&#10;        if (action === &amp;#x27;find&amp;#x27;) return Archify.finder.open();&#10;        if (action === &amp;#x27;route&amp;#x27;) return Archify.routeProbe.begin({ focusNode: true });&#10;        if (action === &amp;#x27;map&amp;#x27;) return Archify.radar.open();&#10;        if (action === &amp;#x27;lens&amp;#x27;) return Archify.semanticLens.open();&#10;        if (action === &amp;#x27;story&amp;#x27;) return Archify.guidedViews.play();&#10;        if (action === &amp;#x27;present&amp;#x27;) return Archify.presentation.enter();&#10;        if (action === &amp;#x27;export&amp;#x27;) return Archify.exportMenu.open();&#10;        if (action === &amp;#x27;theme&amp;#x27;) return Archify.theme.toggle();&#10;        if (action === &amp;#x27;preset&amp;#x27;) return Archify.preset.cycle();&#10;        if (action === &amp;#x27;reset&amp;#x27;) return Archify.view.reset();&#10;        if (action === &amp;#x27;zoom-in&amp;#x27;) return Archify.view.zoomIn();&#10;        if (action === &amp;#x27;zoom-out&amp;#x27;) return Archify.view.zoomOut();&#10;        return false;&#10;      }&#10;      function actionForKey(key) {&#10;        return {&#10;          &amp;#x27;/&amp;#x27;: &amp;#x27;find&amp;#x27;,&#10;          r: &amp;#x27;route&amp;#x27;,&#10;          m: &amp;#x27;map&amp;#x27;,&#10;          l: &amp;#x27;lens&amp;#x27;,&#10;          p: &amp;#x27;story&amp;#x27;,&#10;          f: &amp;#x27;present&amp;#x27;,&#10;          e: &amp;#x27;export&amp;#x27;,&#10;          t: &amp;#x27;theme&amp;#x27;,&#10;          s: &amp;#x27;preset&amp;#x27;,&#10;          &amp;#x27;0&amp;#x27;: &amp;#x27;reset&amp;#x27;,&#10;          &amp;#x27;+&amp;#x27;: &amp;#x27;zoom-in&amp;#x27;,&#10;          &amp;#x27;=&amp;#x27;: &amp;#x27;zoom-in&amp;#x27;,&#10;          &amp;#x27;-&amp;#x27;: &amp;#x27;zoom-out&amp;#x27;&#10;        }[key] || null;&#10;      }&#10;&#10;      trigger.addEventListener(&amp;#x27;click&amp;#x27;, toggle);&#10;      closeBtn.addEventListener(&amp;#x27;click&amp;#x27;, function () { close(); });&#10;      actions.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        var button = event.target.closest(&amp;#x27;[data-guide-action]&amp;#x27;);&#10;        if (!button || button.disabled) return;&#10;        event.stopPropagation();&#10;        execute(button.getAttribute(&amp;#x27;data-guide-action&amp;#x27;));&#10;      });&#10;      panel.addEventListener(&amp;#x27;keydown&amp;#x27;, function (event) {&#10;        if (event.key === &amp;#x27;Escape&amp;#x27; || event.key === &amp;#x27;?&amp;#x27;) {&#10;          event.preventDefault();&#10;          event.stopPropagation();&#10;          close();&#10;          return;&#10;        }&#10;        var buttons = actionButtons();&#10;        var index = buttons.indexOf(document.activeElement);&#10;        var next = null;&#10;        if (index &amp;gt;= 0 &amp;amp;&amp;amp; event.key === &amp;#x27;ArrowRight&amp;#x27;) next = (index + 1) % buttons.length;&#10;        else if (index &amp;gt;= 0 &amp;amp;&amp;amp; event.key === &amp;#x27;ArrowDown&amp;#x27;) next = (index + 1) % buttons.length;&#10;        else if (index &amp;gt;= 0 &amp;amp;&amp;amp; event.key === &amp;#x27;ArrowLeft&amp;#x27;) next = (index - 1 + buttons.length) % buttons.length;&#10;        else if (index &amp;gt;= 0 &amp;amp;&amp;amp; event.key === &amp;#x27;ArrowUp&amp;#x27;) next = (index - 1 + buttons.length) % buttons.length;&#10;        else if (event.key === &amp;#x27;Home&amp;#x27; &amp;amp;&amp;amp; buttons.length) next = 0;&#10;        else if (event.key === &amp;#x27;End&amp;#x27; &amp;amp;&amp;amp; buttons.length) next = buttons.length - 1;&#10;        if (next !== null) {&#10;          event.preventDefault();&#10;          event.stopPropagation();&#10;          buttons[next].focus();&#10;          return;&#10;        }&#10;        var action = actionForKey(event.key.length === 1 ? event.key.toLowerCase() : event.key);&#10;        if (!action) return;&#10;        event.preventDefault();&#10;        event.stopPropagation();&#10;        execute(action);&#10;      });&#10;      document.addEventListener(&amp;#x27;click&amp;#x27;, function (event) {&#10;        if (!panel.hidden &amp;amp;&amp;amp; !panel.contains(event.target) &amp;amp;&amp;amp; event.target !== trigger) close({ restoreFocus: false });&#10;      });&#10;&#10;      renderFacts();&#10;      return {&#10;        open: open,&#10;        close: close,&#10;        toggle: toggle,&#10;        execute: execute,&#10;        isOpen: function () { return !panel.hidden; },&#10;        facts: function () {&#10;          return {&#10;            nodes: svg.querySelectorAll(&amp;#x27;[data-node-id]&amp;#x27;).length,&#10;            relationships: relationshipCount(),&#10;            views: viewCount()&#10;          };&#10;        }&#10;      };&#10;    })();&#10;&#10;    /* ============================================================&#10;       Global keyboard shortcuts&#10;       ? -&amp;gt; open Diagram Guide&#10;       T -&amp;gt; toggle theme&#10;       S -&amp;gt; cycle visual style&#10;       E -&amp;gt; open export menu&#10;         F -&amp;gt; toggle presentation stage&#10;         M -&amp;gt; toggle Semantic Radar&#10;         L -&amp;gt; toggle Semantic Lens&#10;         R -&amp;gt; start/clear Route Probe&#10;         / -&amp;gt; open node finder or the active route endpoint picker&#10;         + / - -&amp;gt; zoom, 0 -&amp;gt; reset view&#10;         Escape -&amp;gt; clear temporary trace/focus/view first, then exit presentation&#10;       Ignored when focus is inside an input/textarea/contenteditable.&#10;       ============================================================ */&#10;    document.addEventListener(&amp;#x27;keydown&amp;#x27;, function (e) {&#10;      if (e.metaKey || e.ctrlKey || e.altKey) return;&#10;      if (e.defaultPrevented) return;&#10;      var t = e.target;&#10;      if (t &amp;amp;&amp;amp; (t.tagName === &amp;#x27;INPUT&amp;#x27; || t.tagName === &amp;#x27;TEXTAREA&amp;#x27; || t.isContentEditable)) return;&#10;      if (Archify.preset &amp;amp;&amp;amp; Archify.preset.isOpen() &amp;amp;&amp;amp; e.key !== &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; e.key !== &amp;#x27;s&amp;#x27; &amp;amp;&amp;amp; e.key !== &amp;#x27;S&amp;#x27;) {&#10;        Archify.preset.close(false);&#10;      }&#10;      if (e.key === &amp;#x27;?&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.guide.toggle();&#10;      } else if (e.key === &amp;#x27;/&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.finder.open();&#10;      } else if (e.key === &amp;#x27;t&amp;#x27; || e.key === &amp;#x27;T&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.theme.toggle();&#10;      } else if (e.key === &amp;#x27;s&amp;#x27; || e.key === &amp;#x27;S&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.preset.cycle();&#10;      } else if (e.key === &amp;#x27;e&amp;#x27; || e.key === &amp;#x27;E&amp;#x27;) {&#10;        e.preventDefault();&#10;        if (!Archify.exportMenu.isOpen()) Archify.exportMenu.open();&#10;      } else if (e.key === &amp;#x27;f&amp;#x27; || e.key === &amp;#x27;F&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.presentation.toggle();&#10;      } else if (e.key === &amp;#x27;m&amp;#x27; || e.key === &amp;#x27;M&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.radar.toggle();&#10;      } else if (e.key === &amp;#x27;l&amp;#x27; || e.key === &amp;#x27;L&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.semanticLens.toggle();&#10;      } else if (e.key === &amp;#x27;r&amp;#x27; || e.key === &amp;#x27;R&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.routeProbe.toggle({ focusNode: true });&#10;      } else if (e.key === &amp;#x27;+&amp;#x27; || e.key === &amp;#x27;=&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.view.zoomIn();&#10;      } else if (e.key === &amp;#x27;-&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.view.zoomOut();&#10;      } else if (e.key === &amp;#x27;0&amp;#x27;) {&#10;        e.preventDefault();&#10;        Archify.view.reset();&#10;      } else if (e.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; Archify.preset.isOpen()) {&#10;        e.preventDefault();&#10;        Archify.preset.close(true);&#10;      } else if (e.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; Archify.semanticLens.isOpen()) {&#10;        e.preventDefault();&#10;        Archify.semanticLens.close({ restoreFocus: true });&#10;      } else if (e.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; Archify.semanticLens.active()) {&#10;        e.preventDefault();&#10;        Archify.semanticLens.clear({ preserveView: true });&#10;      } else if (e.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; Archify.guide.isOpen()) {&#10;        e.preventDefault();&#10;        Archify.guide.close({ restoreFocus: true });&#10;      } else if (e.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; Archify.radar.isOpen()) {&#10;        e.preventDefault();&#10;        Archify.radar.close({ restoreFocus: true });&#10;      } else if (e.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; Archify.routeProbe.active()) {&#10;        e.preventDefault();&#10;        Archify.routeProbe.escape({ restoreFocus: true });&#10;      } else if (e.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; Archify.intentTrace.active()) {&#10;        e.preventDefault();&#10;        Archify.intentTrace.clear();&#10;      } else if (e.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; Archify.focus.active()) {&#10;        e.preventDefault();&#10;        Archify.focus.clear({ restoreFocus: true });&#10;      } else if (e.key === &amp;#x27;Escape&amp;#x27; &amp;amp;&amp;amp; Archify.presentation.active()) {&#10;        e.preventDefault();&#10;        Archify.presentation.exit();&#10;      }&#10;    });&#10;  &amp;lt;/script&amp;gt;&#10;&amp;lt;/body&amp;gt;&#10;&amp;lt;/html&amp;gt;&#10;&quot;&gt;&lt;/iframe&gt;&lt;/section&gt;&#10;    &lt;section id=&quot;mindmap-online&quot;&gt;&lt;h2&gt;AI Infra 系统知识思维导图&lt;/h2&gt;&lt;p&gt;点击分支可跳到手册对应章节。P0 为本次必会，P1 为必要补充。&lt;/p&gt;&lt;div class=&quot;online-map&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 1500 1060&quot; role=&quot;img&quot; aria-labelledby=&quot;mapTitle mapDesc&quot;&gt;&#10;&lt;title id=&quot;mapTitle&quot;&gt;AI Infra 系统知识思维导图&lt;/title&gt;&lt;desc id=&quot;mapDesc&quot;&gt;以质量、延迟、吞吐与成本为中心，连接模型数据、训练、硬件算子、平台可靠性、推理运行时、KV低精度、并行通信、指标实验八个知识分支。&lt;/desc&gt;&#10;&lt;rect width=&quot;1500&quot; height=&quot;1060&quot; fill=&quot;#f6f8fc&quot;/&gt;&#10;&lt;g fill=&quot;none&quot; stroke-width=&quot;2.5&quot; opacity=&quot;.55&quot;&gt;&#10;&lt;path stroke=&quot;#2768ad&quot; d=&quot;M596 524 H535 V120 H464&quot;/&gt;&#10;&lt;path stroke=&quot;#8365b1&quot; d=&quot;M596 524 H535 V340 H464&quot;/&gt;&#10;&lt;path stroke=&quot;#b56c28&quot; d=&quot;M596 524 H535 V688 H464&quot;/&gt;&#10;&lt;path stroke=&quot;#507785&quot; d=&quot;M596 524 H535 V908 H464&quot;/&gt;&#10;&lt;path stroke=&quot;#168363&quot; d=&quot;M904 524 H965 V120 H1036&quot;/&gt;&#10;&lt;path stroke=&quot;#2672b7&quot; d=&quot;M904 524 H965 V340 H1036&quot;/&gt;&#10;&lt;path stroke=&quot;#a55a68&quot; d=&quot;M904 524 H965 V688 H1036&quot;/&gt;&#10;&lt;path stroke=&quot;#827025&quot; d=&quot;M904 524 H965 V908 H1036&quot;/&gt;&#10;&lt;/g&gt;&#10;&lt;rect x=&quot;596&quot; y=&quot;435&quot; width=&quot;308&quot; height=&quot;178&quot; rx=&quot;22&quot; fill=&quot;#163658&quot;/&gt;&#10;&lt;g text-anchor=&quot;middle&quot; font-family=&quot;Microsoft YaHei, sans-serif&quot; fill=&quot;white&quot;&gt;&lt;text x=&quot;750&quot; y=&quot;482&quot; font-size=&quot;28&quot; font-weight=&quot;700&quot;&gt;AI Infra&lt;/text&gt;&lt;text x=&quot;750&quot; y=&quot;518&quot; font-size=&quot;19&quot;&gt;质量约束下的系统效率&lt;/text&gt;&lt;text x=&quot;750&quot; y=&quot;550&quot; font-size=&quot;17&quot;&gt;延迟 · 吞吐 · 成本 · 可靠性&lt;/text&gt;&lt;text x=&quot;750&quot; y=&quot;582&quot; font-size=&quot;15&quot; fill=&quot;#bcd4ec&quot;&gt;指标 → 瓶颈 → 改动 → 验证&lt;/text&gt;&lt;/g&gt;&#10;&lt;a href=&quot;#core&quot;&gt;&lt;g font-family=&quot;Microsoft YaHei, sans-serif&quot;&gt;&lt;rect x=&quot;24&quot; y=&quot;32&quot; width=&quot;440&quot; height=&quot;176&quot; rx=&quot;14&quot; fill=&quot;white&quot; stroke=&quot;#2768ad&quot; stroke-width=&quot;1.8&quot;/&gt;&lt;rect x=&quot;24&quot; y=&quot;52&quot; width=&quot;5&quot; height=&quot;135&quot; rx=&quot;2&quot; fill=&quot;#2768ad&quot;/&gt;&lt;text x=&quot;46&quot; y=&quot;67&quot; fill=&quot;#2768ad&quot; font-size=&quot;23&quot; font-weight=&quot;700&quot;&gt;模型与数据&lt;/text&gt;&lt;text x=&quot;46&quot; y=&quot;94&quot; fill=&quot;#556980&quot; font-size=&quot;14&quot;&gt;P1 · 理解工作负载的来源&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;126&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;Transformer / GQA / MoE / VLM&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;155&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;数据版本 · LoRA · SFT · 蒸馏&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;184&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;质量门槛与独立评估集&lt;/text&gt;&#10;&lt;/g&gt;&lt;/a&gt;&#10;&lt;a href=&quot;#training&quot;&gt;&lt;g font-family=&quot;Microsoft YaHei, sans-serif&quot;&gt;&lt;rect x=&quot;24&quot; y=&quot;252&quot; width=&quot;440&quot; height=&quot;176&quot; rx=&quot;14&quot; fill=&quot;white&quot; stroke=&quot;#8365b1&quot; stroke-width=&quot;1.8&quot;/&gt;&lt;rect x=&quot;24&quot; y=&quot;272&quot; width=&quot;5&quot; height=&quot;135&quot; rx=&quot;2&quot; fill=&quot;#8365b1&quot;/&gt;&lt;text x=&quot;46&quot; y=&quot;287&quot; fill=&quot;#8365b1&quot; font-size=&quot;23&quot; font-weight=&quot;700&quot;&gt;训练系统&lt;/text&gt;&lt;text x=&quot;46&quot; y=&quot;314&quot; fill=&quot;#556980&quot; font-size=&quot;14&quot;&gt;P1 · 对应岗位名称的必要基础&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;346&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;参数 / 梯度 / 优化器 / 激活&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;375&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;DDP · ZeRO / FSDP · TP / PP&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;404&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;混合精度 · 重计算 · 梯度累积&lt;/text&gt;&#10;&lt;/g&gt;&lt;/a&gt;&#10;&lt;a href=&quot;#core&quot;&gt;&lt;g font-family=&quot;Microsoft YaHei, sans-serif&quot;&gt;&lt;rect x=&quot;24&quot; y=&quot;600&quot; width=&quot;440&quot; height=&quot;176&quot; rx=&quot;14&quot; fill=&quot;white&quot; stroke=&quot;#b56c28&quot; stroke-width=&quot;1.8&quot;/&gt;&lt;rect x=&quot;24&quot; y=&quot;620&quot; width=&quot;5&quot; height=&quot;135&quot; rx=&quot;2&quot; fill=&quot;#b56c28&quot;/&gt;&lt;text x=&quot;46&quot; y=&quot;635&quot; fill=&quot;#b56c28&quot; font-size=&quot;23&quot; font-weight=&quot;700&quot;&gt;硬件与算子&lt;/text&gt;&lt;text x=&quot;46&quot; y=&quot;662&quot; fill=&quot;#556980&quot; font-size=&quot;14&quot;&gt;P0 · 计算、访存和执行开销&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;694&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;Roofline · GEMM · 显存带宽&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;723&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;FlashAttention · 融合 · 图执行&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;752&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;设备运行时 · MLU 后端适配&lt;/text&gt;&#10;&lt;/g&gt;&lt;/a&gt;&#10;&lt;a href=&quot;#design&quot;&gt;&lt;g font-family=&quot;Microsoft YaHei, sans-serif&quot;&gt;&lt;rect x=&quot;24&quot; y=&quot;820&quot; width=&quot;440&quot; height=&quot;176&quot; rx=&quot;14&quot; fill=&quot;white&quot; stroke=&quot;#507785&quot; stroke-width=&quot;1.8&quot;/&gt;&lt;rect x=&quot;24&quot; y=&quot;840&quot; width=&quot;5&quot; height=&quot;135&quot; rx=&quot;2&quot; fill=&quot;#507785&quot;/&gt;&lt;text x=&quot;46&quot; y=&quot;855&quot; fill=&quot;#507785&quot; font-size=&quot;23&quot; font-weight=&quot;700&quot;&gt;平台与可靠性&lt;/text&gt;&lt;text x=&quot;46&quot; y=&quot;882&quot; fill=&quot;#556980&quot; font-size=&quot;14&quot;&gt;P1 · 把引擎变成可用服务&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;914&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;路由 · 限流 · 背压 · 超时&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;943&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;取消回收 · 健康检查 · 回滚&lt;/text&gt;&#10;&lt;text x=&quot;46&quot; y=&quot;972&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;模型制品 · 容器 · 资源调度&lt;/text&gt;&#10;&lt;/g&gt;&lt;/a&gt;&#10;&lt;a href=&quot;#sglang&quot;&gt;&lt;g font-family=&quot;Microsoft YaHei, sans-serif&quot;&gt;&lt;rect x=&quot;1036&quot; y=&quot;32&quot; width=&quot;440&quot; height=&quot;176&quot; rx=&quot;14&quot; fill=&quot;white&quot; stroke=&quot;#168363&quot; stroke-width=&quot;1.8&quot;/&gt;&lt;rect x=&quot;1036&quot; y=&quot;52&quot; width=&quot;5&quot; height=&quot;135&quot; rx=&quot;2&quot; fill=&quot;#168363&quot;/&gt;&lt;text x=&quot;1058&quot; y=&quot;67&quot; fill=&quot;#168363&quot; font-size=&quot;23&quot; font-weight=&quot;700&quot;&gt;推理运行时&lt;/text&gt;&lt;text x=&quot;1058&quot; y=&quot;94&quot; fill=&quot;#556980&quot; font-size=&quot;14&quot;&gt;P0 · 两个 30 分钟的学习重点&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;126&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;Prefill / Decode · 请求生命周期&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;155&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;连续批处理 · Chunked Prefill&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;184&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;SGLang Scheduler / vLLM EngineCore&lt;/text&gt;&#10;&lt;/g&gt;&lt;/a&gt;&#10;&lt;a href=&quot;#core&quot;&gt;&lt;g font-family=&quot;Microsoft YaHei, sans-serif&quot;&gt;&lt;rect x=&quot;1036&quot; y=&quot;252&quot; width=&quot;440&quot; height=&quot;176&quot; rx=&quot;14&quot; fill=&quot;white&quot; stroke=&quot;#2672b7&quot; stroke-width=&quot;1.8&quot;/&gt;&lt;rect x=&quot;1036&quot; y=&quot;272&quot; width=&quot;5&quot; height=&quot;135&quot; rx=&quot;2&quot; fill=&quot;#2672b7&quot;/&gt;&lt;text x=&quot;1058&quot; y=&quot;287&quot; fill=&quot;#2672b7&quot; font-size=&quot;23&quot; font-weight=&quot;700&quot;&gt;KV 与低精度&lt;/text&gt;&lt;text x=&quot;1058&quot; y=&quot;314&quot; fill=&quot;#556980&quot; font-size=&quot;14&quot;&gt;P0 · 简历 FP8 工作线&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;346&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;容量公式 · 分页与块管理&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;375&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;前缀复用 · Radix / 块哈希&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;404&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;FP8 KV / 权重 · 精度与吞吐权衡&lt;/text&gt;&#10;&lt;/g&gt;&lt;/a&gt;&#10;&lt;a href=&quot;#parallel&quot;&gt;&lt;g font-family=&quot;Microsoft YaHei, sans-serif&quot;&gt;&lt;rect x=&quot;1036&quot; y=&quot;600&quot; width=&quot;440&quot; height=&quot;176&quot; rx=&quot;14&quot; fill=&quot;white&quot; stroke=&quot;#a55a68&quot; stroke-width=&quot;1.8&quot;/&gt;&lt;rect x=&quot;1036&quot; y=&quot;620&quot; width=&quot;5&quot; height=&quot;135&quot; rx=&quot;2&quot; fill=&quot;#a55a68&quot;/&gt;&lt;text x=&quot;1058&quot; y=&quot;635&quot; fill=&quot;#a55a68&quot; font-size=&quot;23&quot; font-weight=&quot;700&quot;&gt;并行与通信&lt;/text&gt;&lt;text x=&quot;1058&quot; y=&quot;662&quot; fill=&quot;#556980&quot; font-size=&quot;14&quot;&gt;P0 · 简历多卡与死锁工作线&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;694&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;TP / DP / DP Attention / EP&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;723&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;collective · rank / group / root&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;752&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;idle batch · 控制消息 · 拓扑&lt;/text&gt;&#10;&lt;/g&gt;&lt;/a&gt;&#10;&lt;a href=&quot;#design&quot;&gt;&lt;g font-family=&quot;Microsoft YaHei, sans-serif&quot;&gt;&lt;rect x=&quot;1036&quot; y=&quot;820&quot; width=&quot;440&quot; height=&quot;176&quot; rx=&quot;14&quot; fill=&quot;white&quot; stroke=&quot;#827025&quot; stroke-width=&quot;1.8&quot;/&gt;&lt;rect x=&quot;1036&quot; y=&quot;840&quot; width=&quot;5&quot; height=&quot;135&quot; rx=&quot;2&quot; fill=&quot;#827025&quot;/&gt;&lt;text x=&quot;1058&quot; y=&quot;855&quot; fill=&quot;#827025&quot; font-size=&quot;23&quot; font-weight=&quot;700&quot;&gt;指标与实验&lt;/text&gt;&lt;text x=&quot;1058&quot; y=&quot;882&quot; fill=&quot;#556980&quot; font-size=&quot;14&quot;&gt;P0 · 解释每一个性能数字&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;914&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;TTFT / ITL / TPOT / Goodput&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;943&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;队列 · profile · 质量与成本&lt;/text&gt;&#10;&lt;text x=&quot;1058&quot; y=&quot;972&quot; fill=&quot;#24374d&quot; font-size=&quot;17&quot;&gt;同负载对照 · 消融 · 归因边界&lt;/text&gt;&#10;&lt;/g&gt;&lt;/a&gt;&#10;&lt;/svg&gt;&lt;/div&gt;&lt;/section&gt;&#10;    &lt;section id=&quot;core&quot;&gt;&lt;h2&gt;02 · 推理加速核心知识 &lt;span class=&quot;tag&quot;&gt;P0&lt;/span&gt;&lt;/h2&gt;&#10;&lt;h3&gt;2.1 先理解模型到底在算什么&lt;/h3&gt;&lt;p&gt;自回归 Transformer 每层通常包含归一化、Q/K/V 投影、注意力、输出投影、MLP 和残差。对序列位置生成 Q、K、V，计算 &lt;code&gt;softmax(QKᵀ / √d + mask)V&lt;/code&gt;。因果 mask 保证当前位置不读取未来位置。GQA 让多个 Q 头共享较少的 KV 头，减少 KV 存储与读取量；它是模型结构，不是缓存策略。&lt;/p&gt;&#10;&lt;div class=&quot;grid&quot;&gt;&lt;div class=&quot;card&quot;&gt;&lt;h3&gt;Prefill：处理输入前缀&lt;/h3&gt;&lt;p&gt;一次处理很多输入 token，形成各层 KV，并得到首个生成 token 所需的 logits。相对于单请求逐 token decode，通常有更大的矩阵运算、权重重用更充分。&lt;/p&gt;&lt;p&gt;&lt;b&gt;常见约束：&lt;/b&gt;计算、长序列 attention、临时激活、图像编码。长输入不代表永远纯计算瓶颈。&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;card&quot;&gt;&lt;h3&gt;Decode：生成后续 token&lt;/h3&gt;&lt;p&gt;每条活跃序列每步通常新增一个 token，读取已有 KV；多个请求可以合批。KV Cache 避免重复生成历史 K/V，但新 Q 仍要与历史 K/V 做 attention。&lt;/p&gt;&lt;p&gt;&lt;b&gt;常见约束：&lt;/b&gt;小 batch 权重读取、长上下文 KV 带宽、跨卡通信和 launch。大 batch、MoE 等负载会改变瓶颈。&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;h3&gt;2.2 指标：吞吐翻倍不等于用户快了两倍&lt;/h3&gt;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;指标&lt;/th&gt;&lt;th&gt;定义 / 口径&lt;/th&gt;&lt;th&gt;追问点&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TTFT&lt;/td&gt;&lt;td&gt;客户端发出请求到收到第一个输出 token 的时间&lt;/td&gt;&lt;td&gt;包含排队、网络、预处理、prefill；必须说明计时边界&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ITL&lt;/td&gt;&lt;td&gt;相邻输出 token 到达时间差&lt;/td&gt;&lt;td&gt;流式 chunk 可能包含多个 token；采集方式影响结果&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TPOT&lt;/td&gt;&lt;td&gt;常用请求级口径：(E2E − TTFT)/(输出 token 数 − 1)，要求输出 &amp;gt; 1&lt;/td&gt;&lt;td&gt;平均值会掩盖抖动；请求级 TPOT 分位数不等于逐 token ITL 分位数&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;输出吞吐&lt;/td&gt;&lt;td&gt;测量窗内生成的输出 token 总数 / 窗口时长&lt;/td&gt;&lt;td&gt;说明窗口是否覆盖排空过程、失败是否剔除&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;总 token 吞吐&lt;/td&gt;&lt;td&gt;输入与输出 token 数之和 / 时间&lt;/td&gt;&lt;td&gt;不能和只计输出的吞吐横比&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Goodput&lt;/td&gt;&lt;td&gt;符合质量与延迟 SLO 的有效请求数或 token 数 / 时间&lt;/td&gt;&lt;td&gt;必须声明统计单位；不能靠无限排队换“高吞吐”&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;p&gt;近似分解：&lt;code&gt;E2E ≈ TTFT + (Nout − 1) × TPOT&lt;/code&gt;。稳定系统中 Little 定律 &lt;code&gt;L = λW&lt;/code&gt;：平均在途请求数等于完成率乘平均停留时间；固定并发、固定请求速率是不同压测模式，不要把它们混为一个参数。&lt;/p&gt;&#10;&lt;h3&gt;2.3 KV Cache：会手算，再谈优化&lt;/h3&gt;&lt;div class=&quot;formula&quot;&gt;标准全注意力 KV 字节数 ≈ 2 × 层数 L × KV 头数 Hkv × 头维度 D × 每元素字节数 s × Σ各序列已缓存 token 数&lt;/div&gt;&#10;&lt;p&gt;前面的 2 对应 K 与 V。等长时 Σtoken = batch × context。这个公式不含页内浪费、元数据、量化 scale、临时缓冲；MLA、滑窗、混合状态模型要按实际结构另算。TP 下只有真正分片的部分才能除以 TP；KV 头复制和并行布局会改变单卡开销。&lt;/p&gt;&#10;&lt;div class=&quot;callout&quot;&gt;&lt;b&gt;教学算例，非你的模型参数：&lt;/b&gt;32 层、8 个 KV 头、头维 128、BF16 2 字节。每 token 为 131072 字节 = 128 KiB；8192 token 约 1 GiB/序列；16 条序列约 16 GiB。改用 FP8，KV 主数据约减半。权重、激活、图缓冲和框架开销没有跟着减半。&lt;/div&gt;&#10;&lt;p&gt;权重显存的粗估：参数量 × 每参数字节数。32B × BF16 ≈ 64 GB（约 59.6 GiB），还要再加 KV 和其他开销。&lt;b&gt;“32B 单卡放不下”不能直接推出“必须 TP8”&lt;/b&gt;，应根据精度、单卡容量、并发、上下文和通信代价决定。&lt;/p&gt;&#10;&lt;h3&gt;2.4 三个容易混淆的机制&lt;/h3&gt;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;机制&lt;/th&gt;&lt;th&gt;核心问题&lt;/th&gt;&lt;th&gt;解决方式&lt;/th&gt;&lt;th&gt;没有解决什么&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;PagedAttention / 分页 KV&lt;/td&gt;&lt;td&gt;序列长度动态变化，连续预分配浪费显存&lt;/td&gt;&lt;td&gt;把逻辑 KV 分块映射到物理块，按需分配、共享和回收&lt;/td&gt;&lt;td&gt;不自动改变 attention 数学复杂度；仍有块尾浪费和寻址成本&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Prefix Caching / RadixAttention&lt;/td&gt;&lt;td&gt;不同请求有完全一致的前缀，被重复 prefill&lt;/td&gt;&lt;td&gt;查找前缀身份，复用其 KV；radix tree 或链式块哈希可实现索引&lt;/td&gt;&lt;td&gt;不是相似语义缓存，不等于缓存最终答案；decode 仍读取历史 KV&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;FlashAttention&lt;/td&gt;&lt;td&gt;标准 attention 将大中间矩阵反复写入/读出设备显存&lt;/td&gt;&lt;td&gt;分块、片上存储和在线 softmax，减少显存 IO&lt;/td&gt;&lt;td&gt;精确 attention 的渐近计算复杂度仍为平方级；不是“自动删除 KV”&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;p&gt;&lt;b&gt;在线 softmax 的直觉：&lt;/b&gt;为每个 Q 行维护已见分块的最大值 m、归一化和 l、加权输出累加器。新块到来后更新最大值，并把旧累加量按新的指数基准缩放，避免保存完整注意力分数矩阵。数学等价不等于不同浮点实现逐 bit 相同。&lt;/p&gt;&#10;&lt;p class=&quot;source&quot;&gt;机制来源：&lt;a href=&quot;https://arxiv.org/abs/2309.06180&quot;&gt;PagedAttention 论文&lt;/a&gt;、&lt;a href=&quot;https://arxiv.org/abs/2312.07104&quot;&gt;SGLang 论文&lt;/a&gt;、&lt;a href=&quot;https://arxiv.org/abs/2205.14135&quot;&gt;FlashAttention 论文&lt;/a&gt;。以上机制可组合，不能据此给两个框架贴互斥标签。&lt;/p&gt;&#10;&lt;h3&gt;2.5 调度：连续批处理、Chunked Prefill、PD 分离&lt;/h3&gt;&lt;p&gt;&lt;b&gt;连续批处理：&lt;/b&gt;以解码迭代为调度边界，已完成请求退出，新请求进入，减少传统静态 batch 等最慢请求的浪费。代价是动态状态管理和显存压力；并发太高会使每个用户等待更久。&lt;/p&gt;&lt;p&gt;&lt;b&gt;Chunked Prefill：&lt;/b&gt;把长输入的预填充分成多个块，在 token 预算内与 decode 交错执行。较小 chunk 通常改善 ITL、公平性和激活峰值，但会增加轮数，可能损害该长请求 TTFT 或吞吐。应扫参数找满足 SLO 的点。&lt;/p&gt;&lt;p&gt;&lt;b&gt;PD 分离：&lt;/b&gt;让 Prefill 和 Decode 采用独立调度或资源池，缓解长 prefill 对 decode 的干扰。跨设备分离需要传输 KV，收益取决于传输体积、带宽、并发、拓扑与路由。你的 EdgeAcc 是历史内部“同卡逻辑分离”方案，不能等同于所有跨机 PD 架构。&lt;/p&gt;&lt;p class=&quot;source&quot;&gt;&lt;a href=&quot;https://docs.vllm.ai/en/latest/configuration/optimization/&quot;&gt;vLLM 调度调优文档&lt;/a&gt;；当前 V1 文档描述 decode 优先并用剩余 token 预算调度 prefill。具体实现随版本变化，面试解释原理后再注明版本。&lt;/p&gt;&#10;&lt;h3&gt;2.6 低精度：存储更省，执行未必更快&lt;/h3&gt;&lt;p&gt;&lt;b&gt;权重量化&lt;/b&gt;减小权重存储与读取；&lt;b&gt;激活量化&lt;/b&gt;影响 GEMM 计算路径；&lt;b&gt;KV 量化&lt;/b&gt;降低缓存存储和读取成本。必须分别交代 dtype、scale 粒度、校准方式、内核支持和质量影响。FP8 E4M3 和 E5M2 在有效位精度与动态范围间取舍；精确数值范围还取决于具体格式变体。&lt;/p&gt;&lt;p&gt;量化后一般需要 scale 和反量化/重标定。若转换没有融合进 attention kernel，额外 kernel 和读写可能抵消收益。&lt;b&gt;显存容量增加 → 可接纳更多序列 → 聚合吞吐提高&lt;/b&gt;，不保证单请求 TPOT 改善，也不保证整个服务并发严格翻倍。&lt;/p&gt;&lt;p class=&quot;source&quot;&gt;&lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/quantized_kv_cache&quot;&gt;SGLang KV 量化说明&lt;/a&gt;特别强调后端兼容与融合反量化的重要性。&lt;/p&gt;&#10;&lt;h3&gt;2.7 图执行、融合和投机解码&lt;/h3&gt;&lt;p&gt;&lt;b&gt;算子融合：&lt;/b&gt;减少中间 tensor 读写和 kernel launch，例如归一化/残差等相邻操作；复杂融合也可能增加寄存器压力。&lt;b&gt;CUDA Graph：&lt;/b&gt;捕获并重放执行图以降低 CPU launch 开销，需要处理形状、地址、捕获条件及额外内存。&lt;b&gt;torch.compile：&lt;/b&gt;面向图捕获、编译优化等能力，与 CUDA Graph 不是同义词。&lt;/p&gt;&lt;p&gt;&lt;b&gt;投机解码：&lt;/b&gt;草稿模型或预测头先提出多个 token，目标模型批量验证；正确的采样修正算法在相应假设下保持目标分布。性能取决于“每轮实际接受的 token 数”与“草稿 + 验证 + 调度开销”，不只取决于草稿速度。&lt;/p&gt;&lt;div class=&quot;formula&quot;&gt;是否加速：T草稿 + T验证 + T附加开销 &amp;lt; k有效接受 × T普通单步&lt;br&gt;粗略速度比 ≈ k有效接受 × T普通单步 / T一轮投机&lt;/div&gt;&lt;p&gt;若报告的“接受长度”包含 bonus token，先统一定义再代公式。高 batch 时基线已充分利用设备，额外草稿可能抢资源；低接受率、分布偏移、长验证树、通信开销都可能使收益消失。&lt;/p&gt;&lt;p class=&quot;source&quot;&gt;&lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/speculative_decoding&quot;&gt;SGLang 投机解码文档&lt;/a&gt;。你的 EAGLE3 结果是特定历史负载观察，不代表该方法普遍无效。&lt;/p&gt;&#10;&lt;h3&gt;2.8 用 Roofline 建立直觉&lt;/h3&gt;&lt;div class=&quot;formula&quot;&gt;算术强度 I = FLOPs / 从显存搬运的字节数&lt;br&gt;计算性能上界 ≈ min(峰值算力, 显存带宽 × I)&lt;/div&gt;&lt;p&gt;这只是设备计算与显存的粗略模型，不包含排队、CPU、通信和同步。小 batch decode 往往重读大权重，增大 batch 可提高权重复用；长上下文使 KV 读取占比增加。GPU utilization 高不能单独证明计算饱和，要结合算子时间、带宽、通信轨迹和队列数据。&lt;/p&gt;&lt;/section&gt;&#10;&#10;&lt;section id=&quot;parallel&quot;&gt;&lt;h2&gt;03 · 并行与通信：你的核心追问区&lt;/h2&gt;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;方式&lt;/th&gt;&lt;th&gt;切什么&lt;/th&gt;&lt;th&gt;主要代价&lt;/th&gt;&lt;th&gt;面试要点&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;推理 DP&lt;/td&gt;&lt;td&gt;多个模型副本处理不同请求&lt;/td&gt;&lt;td&gt;每副本重复权重；路由可能破坏前缀命中&lt;/td&gt;&lt;td&gt;普通独立 DP 不需像训练 DDP 一样同步梯度&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TP&lt;/td&gt;&lt;td&gt;一层的矩阵/头分片&lt;/td&gt;&lt;td&gt;层内集合通信频繁，小消息延迟敏感&lt;/td&gt;&lt;td&gt;减权重显存，不保证线性加速；先测互连拓扑&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;PP&lt;/td&gt;&lt;td&gt;按层分到不同 stage&lt;/td&gt;&lt;td&gt;pipeline bubble、激活传输、负载不均衡&lt;/td&gt;&lt;td&gt;微批填流水线；在线低并发可能效率不佳&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DP Attention&lt;/td&gt;&lt;td&gt;attention 按请求分组；其他层按配置协作&lt;/td&gt;&lt;td&gt;跨组拼接/归约、批次对齐与空闲组同步&lt;/td&gt;&lt;td&gt;不是完整独立副本；具体 MLP/专家路径看实现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;EP&lt;/td&gt;&lt;td&gt;MoE 专家分布在不同设备&lt;/td&gt;&lt;td&gt;token dispatch/combine 的 all-to-all、专家负载倾斜&lt;/td&gt;&lt;td&gt;别把 dense Qwen3-32B 的工作说成 MoE EP 实战&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CP / SP&lt;/td&gt;&lt;td&gt;上下文或序列相关维度&lt;/td&gt;&lt;td&gt;需要交换相应状态/激活&lt;/td&gt;&lt;td&gt;P2 了解长上下文扩展目的，术语按框架说明&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;p class=&quot;source&quot;&gt;DP 与 DP Attention 的区分参考 &lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/dp_dpa_smg_guide&quot;&gt;SGLang 官方说明&lt;/a&gt;；你的历史参数关系以本地项目记录为准。&lt;/p&gt;&#10;&lt;h3&gt;3.1 集合通信四件事&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;all-reduce：&lt;/b&gt;各 rank 同形状数据做归约，每个 rank 得到完整结果。&lt;/li&gt;&lt;li&gt;&lt;b&gt;all-gather：&lt;/b&gt;把各 rank 分片拼接，每个 rank 得到完整拼接结果。&lt;/li&gt;&lt;li&gt;&lt;b&gt;reduce-scatter：&lt;/b&gt;先归约，再把结果分片分发；与 all-gather 组合可实现 all-reduce 的效果。&lt;/li&gt;&lt;li&gt;&lt;b&gt;broadcast：&lt;/b&gt;指定 root 将数据复制给组中其他 rank；root/rank 编号的解释依 API 和进程组而定。&lt;/li&gt;&lt;/ul&gt;&#10;&lt;div class=&quot;callout warn&quot;&gt;&lt;b&gt;死锁不变量：&lt;/b&gt;同一通信组中，各 rank 必须以兼容的顺序参与对应 collective，满足 count、dtype 等协议约束。rank 没有业务请求，并不表示它能跳过该组的 collective。额外加 barrier 不能修复错误的控制流。&lt;/div&gt;&#10;&lt;p class=&quot;source&quot;&gt;&lt;a href=&quot;https://docs.nvidia.com/deeplearning/nccl/user-guide/docs/usage/collectives.html&quot;&gt;NCCL collective 定义与参与约束&lt;/a&gt;。&lt;/p&gt;&#10;&lt;h3&gt;3.2 把你的死锁画出来&lt;/h3&gt;&lt;pre&gt;历史示例：总 TP 域 8 个 rank，DP=2，attn_tp=4&#10;Attention 组 A = {0,1,2,3}    Attention 组 B = {4,5,6,7}&#10;&#10;旧行为：A 有请求 → 进入前向 → 等待跨组 collective&#10;        B 无请求 → 跳过 run_batch → 没有进入 collective&#10;        结果：A 永远等不到 B&#10;&#10;修复：  所有相关组先对齐调度/通信状态&#10;        B 通过框架支持的 idle batch 参与必要同步&#10;        idle 结果不作为真实请求转给 Decode&#10;        控制消息只在所属 attn_tp 子组广播&lt;/pre&gt;&#10;&lt;p&gt;&lt;b&gt;必须讲清：&lt;/b&gt;“attention 分组独立”不意味着“整个 forward 独立”；更大的 MLP/同步域把多个 attention 组关联起来。历史博客的 &lt;code&gt;tp_size = dp_size × attn_tp_size&lt;/code&gt; 仅是该实现的组织关系，不是全世界 DP/TP 的统一公式。&lt;/p&gt;&#10;&lt;h3&gt;3.3 定位挂死的顺序&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;保留出问题的请求分布，特别是单组有流量、另一组空闲；区分 CPU 阻塞、GPU 内核阻塞与进程退出。&lt;/li&gt;&lt;li&gt;在 collective 前后记录 rank、group 成员、序号、shape、dtype；找出各 rank 最后一个共同通信点。&lt;/li&gt;&lt;li&gt;核对进程启动、rank 映射、组创建顺序、root、ready 信号和异常退出路径。&lt;/li&gt;&lt;li&gt;修复后覆盖忙/闲切换、全部空闲、不均匀长短请求、取消、错误处理和 TP/DP/DP Attention 老模式回归。&lt;/li&gt;&lt;/ol&gt;&#10;&lt;p&gt;&lt;b&gt;硬件口径：&lt;/b&gt;8×4090 无 NVLink 是已确认背景；PCIe 拓扑、跨 NUMA 和实际 P2P 通路仍须测。设置 &lt;code&gt;NCCL_P2P_DISABLE=0&lt;/code&gt; 或 &lt;code&gt;NCCL_P2P_LEVEL=SYS&lt;/code&gt; 不是 P2P 已生效的证据，更不是收益证明。&lt;/p&gt;&lt;/section&gt;&#10;&#10;&lt;section id=&quot;sglang&quot;&gt;&lt;h2&gt;04 · SGLang：30 分钟学习单&lt;/h2&gt;&lt;div class=&quot;timer&quot; data-timer=&quot;sglang&quot;&gt;&lt;span class=&quot;clock&quot;&gt;30:00&lt;/span&gt;&lt;button data-action=&quot;start&quot;&gt;开始 / 继续&lt;/button&gt;&lt;button data-action=&quot;pause&quot;&gt;暂停&lt;/button&gt;&lt;button data-action=&quot;reset&quot;&gt;重置&lt;/button&gt;&lt;small&gt;只计本节学习；安装与下载不在 30 分钟内。&lt;/small&gt;&lt;/div&gt;&#10;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;分钟&lt;/th&gt;&lt;th&gt;读什么 / 做什么&lt;/th&gt;&lt;th&gt;当场输出&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;00–05&lt;/td&gt;&lt;td&gt;阅读下方请求路径；打开 &lt;a href=&quot;https://docs.sglang.io/docs/get-started/quickstart&quot;&gt;官方 Quickstart&lt;/a&gt;&lt;/td&gt;&lt;td&gt;口述从 HTTP 到首 token 的 6 个步骤&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;05–12&lt;/td&gt;&lt;td&gt;看 RadixAttention 机制，用两个公共前缀请求推演命中&lt;/td&gt;&lt;td&gt;画“公共系统提示 → 两个用户分支”的 radix tree&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12–18&lt;/td&gt;&lt;td&gt;理解 Scheduler 如何在运行/等待队列与 KV 预算之间决策&lt;/td&gt;&lt;td&gt;解释长 prefill 为什么拖慢 decode；chunk 的取舍&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18–24&lt;/td&gt;&lt;td&gt;看下面的 4 个源码入口，每个只找职责和关键调用&lt;/td&gt;&lt;td&gt;指出简历的 rank、idle batch、group 问题位于哪一层&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;24–28&lt;/td&gt;&lt;td&gt;读参数表；推演“prefill OOM”和“decode 吞吐低”&lt;/td&gt;&lt;td&gt;为每个现象选择 1 个观测指标和 1 个可验证改动&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;28–30&lt;/td&gt;&lt;td&gt;合上材料回答本节 3 个自测&lt;/td&gt;&lt;td&gt;完成一段 90 秒 SGLang 总述&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;div class=&quot;flow&quot;&gt;&lt;b&gt;TokenizerManager&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;Scheduler + RadixCache&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;ModelRunner / worker&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;采样与 Detokenizer&lt;/b&gt;&lt;/div&gt;&#10;&lt;p&gt;&lt;b&gt;90 秒核心：&lt;/b&gt;SGLang 将输入处理、调度与设备执行分工。Scheduler 管理请求和每轮批次；缓存层查找可复用前缀及分配 KV；执行层调用模型和后端算子。RadixAttention 使用前缀树组织缓存复用，连续批处理和分块预填充改善动态负载利用率。Overlap scheduling 的目标是把可并行的 CPU 调度工作与设备计算重叠，不意味着所有操作都没有依赖，也不能解决通信协议错误。&lt;/p&gt;&#10;&lt;h3&gt;前缀命中推演&lt;/h3&gt;&lt;pre&gt;请求 A: [固定 system][相同工具定义][用户问题 A]&#10;请求 B: [固定 system][相同工具定义][用户问题 B]&#10;复用：相同 token 前缀的 KV；只 prefill B 的未命中后缀。&#10;&#10;若把当前时间戳放到最前面 → 很早就分叉 → 长公共后缀不能当相同前缀复用。&#10;若同样的图像占位 token 对应不同图片 → 不能只按占位 token 判断缓存身份。&lt;/pre&gt;&lt;p&gt;缓存使用需要模型、adapter、tokenizer/模板与多模态输入身份一致。活跃缓存有引用保护，淘汰应选择可回收部分。前缀亲和路由提高命中率，但可能把热点都压到同一副本。&lt;/p&gt;&#10;&lt;h3&gt;只看四个源码入口&lt;/h3&gt;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;官方 main 路径（本次已核实存在）&lt;/th&gt;&lt;th&gt;看什么&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/managers/tokenizer_manager.py&quot;&gt;managers/tokenizer_manager.py&lt;/a&gt;&lt;/td&gt;&lt;td&gt;TokenizerManager：请求如何进入后端、结果如何返回&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/managers/scheduler.py&quot;&gt;managers/scheduler.py&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Scheduler：调度循环、prefill/decode 批次与状态流转；实际方法可能拆在 mixin 中&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/mem_cache/radix_cache.py&quot;&gt;mem_cache/radix_cache.py&lt;/a&gt;&lt;/td&gt;&lt;td&gt;RadixCache：prefix match、insert、引用保护与 eviction&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/model_executor/model_runner.py&quot;&gt;model_executor/model_runner.py&lt;/a&gt;&lt;/td&gt;&lt;td&gt;ModelRunner：设备加载、模型执行与后端选择&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;div class=&quot;callout warn&quot;&gt;你做过的是历史内部 &lt;code&gt;v0.5.3-edge-acc&lt;/code&gt; 分支。上面是当前开源 main 的阅读入口；不能说内部 EdgeAcc 的同卡 PD 功能就是开源默认功能，也不能照搬内部启动参数。&lt;/div&gt;&#10;&lt;h3&gt;参数与瓶颈的对应关系&lt;/h3&gt;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;参数&lt;/th&gt;&lt;th&gt;改变什么&lt;/th&gt;&lt;th&gt;代价 / 验证&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;--mem-fraction-static&lt;/code&gt;&lt;/td&gt;&lt;td&gt;权重与静态 KV 池的显存预算比例&lt;/td&gt;&lt;td&gt;更大可能挤压激活/图缓冲；分 prefill 和 decode 测峰值&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;--chunked-prefill-size&lt;/code&gt;&lt;/td&gt;&lt;td&gt;长 prefill 每次处理的 token 数&lt;/td&gt;&lt;td&gt;扫 TTFT、P99 ITL、吞吐与峰值显存&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;--max-running-requests&lt;/code&gt;&lt;/td&gt;&lt;td&gt;活跃请求上限&lt;/td&gt;&lt;td&gt;过高会增加缓存压力和用户延迟；过低设备可能吃不满&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;--tp-size&lt;/code&gt; / &lt;code&gt;--dp-size&lt;/code&gt;&lt;/td&gt;&lt;td&gt;模型分片与并发请求组织方式&lt;/td&gt;&lt;td&gt;兼容性、权重预算、通信和组映射需联合检查&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;--disable-radix-cache&lt;/code&gt;&lt;/td&gt;&lt;td&gt;前缀复用的对照开关&lt;/td&gt;&lt;td&gt;固定请求 token 和冷暖状态；别把暖缓存和冷缓存结果直接比较&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;p class=&quot;source&quot;&gt;参数概念参考 &lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/hyperparameter_tuning&quot;&gt;调优指南&lt;/a&gt;、&lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/server_arguments&quot;&gt;参数文档&lt;/a&gt;。运行前以目标安装版 &lt;code&gt;--help&lt;/code&gt; 为准。&lt;/p&gt;&#10;&lt;details&gt;&lt;summary&gt;自测 1：RadixAttention 是近似 attention 吗？&lt;/summary&gt;&lt;p&gt;不是。核心是组织并复用完全匹配前缀的 KV，避免重复 prefill；不要与 sparse attention、近似 attention 混淆。&lt;/p&gt;&lt;/details&gt;&lt;details&gt;&lt;summary&gt;自测 2：把 KV 池设得越大越好吗？&lt;/summary&gt;&lt;p&gt;不是。还要给激活、临时工作区、图执行等留余量。先区分静态容量不足与运行峰值 OOM，再调整缓存、chunk 或并发。&lt;/p&gt;&lt;/details&gt;&lt;details&gt;&lt;summary&gt;自测 3：空闲 DP 组没有请求，为什么还要前向同步？&lt;/summary&gt;&lt;p&gt;因为 attention 组外可能仍共享 MLP/collective 通信域。通过正确 idle batch 满足通信协议，且不能制造真实输出或污染 Decode。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;可选实验：已有兼容环境时运行（不属于必做 30 分钟）&lt;/summary&gt;&lt;p&gt;本次未安装、未连接服务器、未运行 GPU 基准。以下为 Linux GPU 环境模板。使用已存在的兼容环境和模型路径；不要把这段命令当作 Windows 或 MLU 原生安装指南。&lt;/p&gt;&lt;pre&gt;# 当前官方 Quickstart 使用 sglang serve；先检查安装版帮助&#10;sglang serve --help&#10;sglang serve /path/to/model --host 127.0.0.1 --port 30000&#10;&#10;# 历史项目使用 python -m sglang.launch_server，按历史环境复现&#10;# 不混用两套版本的参数。&lt;/pre&gt;&lt;p&gt;发两组等长请求：A/B 共享长前缀，C/D 不共享；固定输出长度与采样，分别记录冷缓存和暖缓存 TTFT、命中 token 数、输出正确性。单次更快只能作现象，至少重复并报告分布。&lt;/p&gt;&lt;/details&gt;&lt;/section&gt;&#10;&#10;&lt;section id=&quot;vllm&quot;&gt;&lt;h2&gt;05 · vLLM：30 分钟学习单&lt;/h2&gt;&lt;div class=&quot;timer&quot; data-timer=&quot;vllm&quot;&gt;&lt;span class=&quot;clock&quot;&gt;30:00&lt;/span&gt;&lt;button data-action=&quot;start&quot;&gt;开始 / 继续&lt;/button&gt;&lt;button data-action=&quot;pause&quot;&gt;暂停&lt;/button&gt;&lt;button data-action=&quot;reset&quot;&gt;重置&lt;/button&gt;&lt;small&gt;按 V1 架构学习；不背旧版类名替代机制。&lt;/small&gt;&lt;/div&gt;&#10;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;分钟&lt;/th&gt;&lt;th&gt;读什么 / 做什么&lt;/th&gt;&lt;th&gt;当场输出&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;00–05&lt;/td&gt;&lt;td&gt;读 &lt;a href=&quot;https://docs.vllm.ai/en/latest/design/arch_overview/&quot;&gt;V1 进程架构&lt;/a&gt; 中 Engine Core / Worker 部分&lt;/td&gt;&lt;td&gt;画 API → EngineCore → worker / runner&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;05–12&lt;/td&gt;&lt;td&gt;用块大小 16、长度 33 的序列推演分页&lt;/td&gt;&lt;td&gt;逻辑需要 3 块，最后一块使用 1 个位置；说明内部碎片&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12–18&lt;/td&gt;&lt;td&gt;读前缀缓存和 token-budget 调度说明&lt;/td&gt;&lt;td&gt;解释块哈希为什么包含前缀身份；推演长 prefill 与 decode 共批&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18–24&lt;/td&gt;&lt;td&gt;看 3 个源码入口与参数映射&lt;/td&gt;&lt;td&gt;定位 admission、KV 分配、输出状态更新&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;24–28&lt;/td&gt;&lt;td&gt;完成与 SGLang 对比表&lt;/td&gt;&lt;td&gt;用机制、兼容性、负载与 SLO 比较，避免“谁一定更快”&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;28–30&lt;/td&gt;&lt;td&gt;无笔记回答 3 个自测&lt;/td&gt;&lt;td&gt;90 秒介绍 vLLM；30 秒解释自己实战深度边界&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;div class=&quot;flow&quot;&gt;&lt;b&gt;API / Async 接口&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;EngineCore&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;Scheduler + KVCacheManager&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;Executor / workers&lt;/b&gt;&lt;span&gt;→&lt;/span&gt;&lt;b&gt;模型执行与输出&lt;/b&gt;&lt;/div&gt;&#10;&lt;p&gt;&lt;b&gt;V1 核心：&lt;/b&gt;API 层处理输入与流式结果；EngineCore 运行调度循环、管理 KV 并协调执行；设备 worker 承载模型前向。理解“进程间职责”和“逐步状态更新”比背进程总数重要。每轮调度既受 token 预算约束，也受序列数量与可用 KV 容量约束。&lt;/p&gt;&#10;&lt;h3&gt;分页与前缀复用推演&lt;/h3&gt;&lt;pre&gt;逻辑序列：  [token 0..15] [token 16..31] [token 32]&#10;逻辑块号：       0              1              2&#10;物理块号：      17              4             29&#10;&#10;逻辑连续不要求物理连续。序列结束时释放引用；共享块必须考虑引用计数。&#10;块尾仍有浪费：长度 33、块大小 16 → 分配 48 个位置，末块空 15 个。&#10;前缀复用还需要“身份索引”：前缀哈希 + 本块 token + adapter/多模态等额外信息。&lt;/pre&gt;&lt;p&gt;哈希相同的设计目标是定位相同上下文的 KV，不能只对当前块 token 做哈希，因为相同词语在不同前文中的 K/V 可能不同。当前 V1 文档描述完整块的复用，并考虑多模态输入等附加身份。&lt;/p&gt;&lt;p class=&quot;source&quot;&gt;&lt;a href=&quot;https://docs.vllm.ai/en/latest/design/prefix_caching/&quot;&gt;vLLM V1 前缀缓存设计&lt;/a&gt;。块索引与底层 attention kernel 是不同层次，实际后端可以变化。&lt;/p&gt;&#10;&lt;h3&gt;只看三个源码入口&lt;/h3&gt;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;官方 main 路径（已核实存在）&lt;/th&gt;&lt;th&gt;问题&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/vllm-project/vllm/blob/main/vllm/v1/engine/core.py&quot;&gt;vllm/v1/engine/core.py&lt;/a&gt;&lt;/td&gt;&lt;td&gt;EngineCore 如何串起调度、执行和结果更新？&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/vllm-project/vllm/blob/main/vllm/v1/core/sched/scheduler.py&quot;&gt;vllm/v1/core/sched/scheduler.py&lt;/a&gt;&lt;/td&gt;&lt;td&gt;哪些请求能进入本轮？预算不足如何处理？&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/vllm-project/vllm/blob/main/vllm/v1/core/kv_cache_manager.py&quot;&gt;vllm/v1/core/kv_cache_manager.py&lt;/a&gt;&lt;/td&gt;&lt;td&gt;如何查可复用块、分配新块、释放完成请求的引用？&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;h3&gt;和 SGLang 的对应关系&lt;/h3&gt;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;维度&lt;/th&gt;&lt;th&gt;SGLang&lt;/th&gt;&lt;th&gt;vLLM V1&lt;/th&gt;&lt;th&gt;你应该说什么&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;请求调度&lt;/td&gt;&lt;td&gt;Scheduler 与相关 mixin / worker&lt;/td&gt;&lt;td&gt;EngineCore 中调度器、执行器协作&lt;/td&gt;&lt;td&gt;两者都管理动态请求和执行预算&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;KV 内存与复用&lt;/td&gt;&lt;td&gt;内存池 / 分页机制与 RadixCache 等实现&lt;/td&gt;&lt;td&gt;KVCacheManager、块管理与哈希前缀复用&lt;/td&gt;&lt;td&gt;分页和前缀缓存不是彼此替代&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;长 prefill 干扰&lt;/td&gt;&lt;td&gt;Chunked Prefill 等调度机制&lt;/td&gt;&lt;td&gt;Chunked Prefill、token 预算等机制&lt;/td&gt;&lt;td&gt;比较实际 SLO、负载与版本&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;执行优化&lt;/td&gt;&lt;td&gt;量化、图执行、不同 attention 后端等&lt;/td&gt;&lt;td&gt;量化、图执行、不同 attention 后端等&lt;/td&gt;&lt;td&gt;支持矩阵和默认值随模型/硬件/版本变化&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;自己的经验&lt;/td&gt;&lt;td&gt;历史内部引擎适配与调度/通信修复&lt;/td&gt;&lt;td&gt;本次学习架构、源码入口和实验设计&lt;/td&gt;&lt;td&gt;没有实做的 vLLM 源码改动不声称做过&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;p&gt;&lt;b&gt;调优映射：&lt;/b&gt;&lt;code&gt;--max-num-batched-tokens&lt;/code&gt; 控制每轮 token 预算；&lt;code&gt;--max-num-seqs&lt;/code&gt; 控制序列数量；&lt;code&gt;--gpu-memory-utilization&lt;/code&gt; 影响该实例显存预算；&lt;code&gt;--max-model-len&lt;/code&gt; 是请求长度能力边界。它们不能互相替代。TP 需要模型、头数、量化与硬件支持共同满足。&lt;/p&gt;&#10;&lt;details&gt;&lt;summary&gt;自测 1：PagedAttention 可以和 FlashAttention 同时存在吗？&lt;/summary&gt;&lt;p&gt;可以组合相应的分页存储和高效 attention kernel。一个重点是 KV 布局和管理，一个重点是计算执行中的 IO；具体可组合路径依框架后端实现而定。&lt;/p&gt;&lt;/details&gt;&lt;details&gt;&lt;summary&gt;自测 2：调小 token budget，什么改善、什么可能变差？&lt;/summary&gt;&lt;p&gt;减少大 prefill 对 decode 的阻塞，常有利于 ITL；长请求 prefill 可能需要更多轮，TTFT 或吞吐可能变差。用同负载扫参确认。&lt;/p&gt;&lt;/details&gt;&lt;details&gt;&lt;summary&gt;自测 3：为什么 vLLM 不能说成“不支持前缀缓存”？&lt;/summary&gt;&lt;p&gt;V1 有自动前缀缓存设计，通过块哈希和 KV 管理器支持复用。框架特性在演进，比较必须注明版本。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;可选实验模板：已有兼容环境时执行&lt;/summary&gt;&lt;pre&gt;# Linux GPU 环境示意；不在本机默认安装或运行&#10;vllm serve --help&#10;vllm serve /path/to/model --host 127.0.0.1 --port 8000 \&#10;  --max-model-len 4096 --max-num-batched-tokens 2048 \&#10;  --max-num-seqs 16 --gpu-memory-utilization 0.80&#10;&#10;# 使用同一 tokenizer、请求集、采样配置、输出长度比较；参数为教学起点。&#10;# 先运行已安装版本的 benchmark --help，再按官方 CLI 生成压测命令。&lt;/pre&gt;&lt;p&gt;只改变 &lt;code&gt;max-num-batched-tokens&lt;/code&gt;，测试 1024/2048/4096，并记录 TTFT、P99 ITL、输出吞吐和峰值显存。确认实际已启用 chunked prefill。实验没有在本次任务中执行。&lt;/p&gt;&lt;p class=&quot;source&quot;&gt;&lt;a href=&quot;https://docs.vllm.ai/en/latest/getting_started/quickstart/&quot;&gt;官方 Quickstart&lt;/a&gt;；&lt;a href=&quot;https://docs.vllm.ai/en/latest/configuration/optimization/&quot;&gt;优化文档&lt;/a&gt;。&lt;/p&gt;&lt;/details&gt;&lt;/section&gt;&#10;&#10;&lt;section id=&quot;resume&quot;&gt;&lt;h2&gt;06 · 针对 AI Infra 简历定点补课&lt;/h2&gt;&lt;p&gt;以下依据当前“大模型推理部署方向”成品简历，并用个人事实主档约束解释。&lt;b&gt;已写入简历不等于每个数字都已有完整可复现日志。&lt;/b&gt;历史博客中的宽泛归因，以主档中更严格的确认边界为准。&lt;/p&gt;&#10;&lt;h3&gt;6.1 多卡引擎适配与死锁修复 &lt;span class=&quot;tag&quot;&gt;最高优先级 · 20 分钟&lt;/span&gt;&lt;/h3&gt;&#10;&lt;p&gt;&lt;b&gt;简历锚点：&lt;/b&gt;8×RTX 4090 24GB、Qwen3-32B、内部 EdgeAcc、DP/DP Attention、idle batch、子组广播。&lt;/p&gt;&lt;p&gt;&lt;b&gt;必补基础：&lt;/b&gt;进程与线程、rank / world size / process group、TP 与 DP、collective 协议、IPC、producer-consumer、消息归属、ready/health/readiness 的区别。&lt;/p&gt;&#10;&lt;div class=&quot;callout&quot;&gt;&lt;b&gt;3 分钟叙述框架：&lt;/b&gt;“我基于已有内部 EdgeAcc 引擎扩展 DP 和 DP Attention。问题只在组间负载不均时暴露：空闲组跳过前向，而活跃组进入共同 collective，导致通信参与不一致。我通过对齐调度同步、使用框架 idle batch 让相关 rank 参与必要通信，并阻止 idle 结果进入 Decode；控制消息改为所属 attention 子组广播。我负责启动、rank 映射、路由、调度/通信缺陷修复与回归，没有从零实现 MPS 或 CUDA IPC。”&lt;/div&gt;&#10;&lt;details&gt;&lt;summary&gt;追问：为什么一个 barrier 不能修好？&lt;/summary&gt;&lt;p&gt;barrier 只增加另一个同步点，没有让本来被跳过的 collective 被正确参与。必须修正各 rank 的控制流和通信协议；错误 barrier 还会引入新的挂死点。&lt;/p&gt;&lt;/details&gt;&lt;details&gt;&lt;summary&gt;追问：zero-length tensor 与 idle batch 是一回事吗？&lt;/summary&gt;&lt;p&gt;不是。idle batch 是框架中的语义状态，必须走其支持的 shape、metadata、同步和结果处理路径。任意创建零长度 tensor 不能保证所有 kernel 和 collective 支持，也不等于修复完成。&lt;/p&gt;&lt;/details&gt;&lt;details&gt;&lt;summary&gt;追问：如何证明不再跨 DP 组串请求？&lt;/summary&gt;&lt;p&gt;为两个组注入不同 request ID、明显不同输入和取消/清理消息；记录 routing、group/root、输出 ID 以及状态回收。除了能返回文本，还要验证每条消息只影响对应组及对应请求。&lt;/p&gt;&lt;/details&gt;&#10;&lt;p&gt;&lt;b&gt;口径边界：&lt;/b&gt;本地资料记载的是包含 7 处精确替换、命中校验和备份的补丁脚本；不能说“修了 7 个独立 bug”，也不能仅凭命中检查声称重复执行幂等。OpenSpec/TDD 是开发方法，不是推理加速组件。&lt;/p&gt;&#10;&lt;h3&gt;6.2 FP8 KV 与 FlashInfer 适配 &lt;span class=&quot;tag&quot;&gt;15 分钟&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;b&gt;简历锚点：&lt;/b&gt;RTX 5090（sm_120）历史 FP8 路径适配；510 → 738 token/s；叠加权重与内核优化达 1019；TTFT 3944 → 1488 ms。&lt;/p&gt;&lt;p&gt;&lt;b&gt;必补基础：&lt;/b&gt;浮点格式与 scale、BF16/FP16/FP8 区别、KV 容量公式、编译目标架构、CUDA/编译器/PyTorch ABI 与依赖兼容、kernel dispatch、reference correctness 与微基准。&lt;/p&gt;&#10;&lt;div class=&quot;callout&quot;&gt;&lt;b&gt;2 分钟叙述框架：&lt;/b&gt;“我遇到的是当时版本在 sm_120 上 FP8 路径不完整，重编译并适配 FlashInfer 打通路径。FP8 KV 使 KV 主数据每元素从 2 字节降到 1 字节，改善容量；同口径聚合吞吐从 510 到 738，约 +44.7%。叠加 FP8 权重和内核优化后是 1019，约为基线 2 倍。这是组合配置的结果；单请求 TPOT 还受到转换和内核效率影响，不能只用聚合吞吐证明单请求更快。”&lt;/div&gt;&#10;&lt;details&gt;&lt;summary&gt;追问：编译成功为什么还不够？&lt;/summary&gt;&lt;p&gt;需要确认目标架构产物真正被加载、运行时没有 fallback；用参考实现检查输出误差和边界形状，用 microbenchmark 量算子时间，再做服务压测。版本、编译参数、dtype、shape 和后端都要入记录。&lt;/p&gt;&lt;/details&gt;&lt;details&gt;&lt;summary&gt;追问：你具体改了哪个算子、哪几行？&lt;/summary&gt;&lt;p&gt;主档目前没有完整修复 diff 和准确依赖版本。只讲能够定位和提供证据的内容；可以说明自己承担源码重编译与适配，但不能临场编造 kernel 算法、上游 PR 或算子级加速数字。原始 diff 找回前保留这个证据缺口。&lt;/p&gt;&lt;/details&gt;&#10;&lt;p&gt;&lt;b&gt;不要混用两条工作线：&lt;/b&gt;FP8 线的模型、并发、完整参数和版本尚待原始日志补证；&lt;b&gt;不能把 32B/128 并发那组参数填到 FP8 线里，也不能自行认定 FP8 线模型是 8B。&lt;/b&gt;主档明确撤回了缺证的“MXFP8 零长度断言修复”成果，不用于面试。&lt;/p&gt;&#10;&lt;h3&gt;6.3 整体性能压测 &lt;span class=&quot;tag&quot;&gt;10 分钟&lt;/span&gt;&lt;/h3&gt;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;历史记录指标&lt;/th&gt;&lt;th&gt;数值&lt;/th&gt;&lt;th&gt;应怎么说&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;负载&lt;/td&gt;&lt;td&gt;Qwen3-32B；128 并发；2560 请求；输入/输出约 2860/2180 token&lt;/td&gt;&lt;td&gt;这些是这条压测线的历史条件；完整双方命令、基线版本和原始日志仍待补证&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;总吞吐&lt;/td&gt;&lt;td&gt;6289 → 12702 token/s，约 2.02×&lt;/td&gt;&lt;td&gt;整体方案对比；不是死锁修复的单变量收益&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;输出吞吐&lt;/td&gt;&lt;td&gt;2732 → 5487 token/s，约 2.01×&lt;/td&gt;&lt;td&gt;与总吞吐区分；这项来自主档/博客补充，当前简历未单列&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;中位 TTFT&lt;/td&gt;&lt;td&gt;15028 → 1263 ms&lt;/td&gt;&lt;td&gt;约降 91.6%；不能写成所有请求、所有负载均提速 12 倍&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;P99 ITL&lt;/td&gt;&lt;td&gt;1843 → 111 ms&lt;/td&gt;&lt;td&gt;尾部 token 间延迟明显改善；不是平均 TPOT&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;p&gt;&lt;b&gt;最常见追问：&lt;/b&gt;“2 倍到底是谁的功劳？”答：“数字来自适配后 EdgeAcc 整体方案与开源方案的对比，包含既有引擎设计与相关配置。我个人交付是 DP/DP Attention 扩展及稳定性修复，没有足够单变量消融把全部性能收益归因于自己的某一处改动。”&lt;/p&gt;&#10;&lt;h3&gt;6.4 EAGLE3 没加速：准备一个有价值的负结果 &lt;span class=&quot;badge&quot;&gt;主档补充，未单列于当前简历&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;历史负载平均接受长度约 1.28–1.40。先解释接受长度定义，再按“草稿耗时、验证耗时、每轮有效 token、batch/并发、质量和采样配置”拆解。提出可验证假设：草稿分布不匹配、接受长度不足以摊销开销、基线已饱和、调度/通信额外成本。没有剖析证据时，说“待验证原因”，不要把推测包装成定位结果。&lt;/p&gt;&#10;&lt;h3&gt;6.5 VLM + LoRA 与蒸馏 &lt;span class=&quot;tag&quot;&gt;10 分钟&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;b&gt;简历锚点：&lt;/b&gt;Qwen3-VL-8B 三阶段 LoRA；动作决策 94.8%；10 账号/534 步/121 任务成功率 93.4%；NL2SQL 教师 32B → 学生 7B，1895 条 SFT，held-out 69/76=90.8%，资源 4 卡 → 单卡。&lt;/p&gt;&#10;&lt;ul&gt;&lt;li&gt;&lt;b&gt;LoRA：&lt;/b&gt;冻结基础权重，学习低秩增量 &lt;code&gt;ΔW = (α/r)BA&lt;/code&gt;，对 m×n 矩阵增加约 r(m+n) 参数。减少可训练状态，不意味着基础模型或所有激活都消失；推理是否 merge 依实现与多 adapter 场景。&lt;/li&gt;&lt;li&gt;&lt;b&gt;SFT：&lt;/b&gt;在给定上下文上最小化目标 token 的负对数似然；监督区域和 loss mask 决定模型学什么。三阶段数据分布变化要关注遗忘与固定评测集。&lt;/li&gt;&lt;li&gt;&lt;b&gt;VLM 开销：&lt;/b&gt;图像分辨率/视觉 token 数影响编码成本、prefill、KV 和 batching。诊断慢请求应拆 encoder 与语言模型阶段。&lt;/li&gt;&lt;li&gt;&lt;b&gt;轨迹蒸馏：&lt;/b&gt;本项目是用教师生成并经执行过滤的轨迹做 SFT；没有证据表明使用教师 logits 的 KL 蒸馏，不要混称。&lt;/li&gt;&lt;li&gt;&lt;b&gt;质量口径：&lt;/b&gt;动作准确率、任务成功率、SQL 可执行率和 SQL 语义正确率是不同指标。49/49 固定回归不代表泛化 100%；69/76 held-out 也受样本量、分层和独立性限制。&lt;/li&gt;&lt;li&gt;&lt;b&gt;成本口径：&lt;/b&gt;4 卡 → 单卡是资源配置减少，不足以推出成本精确下降 75%；还需相同质量、吞吐、延迟和利用率条件。&lt;/li&gt;&lt;/ul&gt;&#10;&lt;h3&gt;6.6 其余项目与技能：只补容易被追问的地基 &lt;span class=&quot;tag&quot;&gt;5 分钟&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;b&gt;腾讯开悟：&lt;/b&gt;能说明 CNN/MLP 各处理什么输入，LSTM 为何建模时序，Target Attention 如何对候选目标加权，Actor 输出策略、Critic 估计价值。若问策略梯度，解释 &lt;code&gt;∇log π(a|s) × advantage&lt;/code&gt; 及 baseline 降方差；若问 PPO，说明 ratio clipping 限制更新，但只有确实参与过的实现才称实战。面试主线仍放在模型执行、训练吞吐和工程取舍。&lt;/p&gt;&lt;p&gt;&lt;b&gt;Python/PyTorch/Linux：&lt;/b&gt;张量 shape/stride/contiguous；view 与拷贝；设备异步执行导致计时前后需正确同步；&lt;code&gt;no_grad&lt;/code&gt; 与 &lt;code&gt;eval&lt;/code&gt; 分别控制梯度记录和模块训练行为；线程/进程、锁/队列、超时/资源回收。C++ 可补 RAII、引用/指针、生命周期；当前简历没有 C++ 实战主张，不临时包装。&lt;/p&gt;&lt;p&gt;&lt;b&gt;论文：&lt;/b&gt;只按当前简历说 LogoLLM 三作、Neurocomputing 在投；准备自己的具体贡献，不能声称已录用或承担全部工作。&lt;/p&gt;&lt;/section&gt;&#10;&#10;&lt;section id=&quot;training&quot;&gt;&lt;h2&gt;07 · 训练优化与寒武纪 MLU 适配&lt;/h2&gt;&lt;p&gt;岗位名称含“训练优化”，这一节属于必须补齐的基础；下面是面试能力准备建议，不声称来自未找到的完整 JD。&lt;/p&gt;&#10;&lt;h3&gt;7.1 训练显存为什么比推理大？&lt;/h3&gt;&lt;div class=&quot;formula&quot;&gt;训练显存 ≈ 参数 + 梯度 + 优化器状态 + 主权重（若有）+ 激活 + 临时缓冲&lt;br&gt;推理显存 ≈ 参数 + KV Cache + 执行激活/工作区 + 图/通信/框架缓冲&lt;/div&gt;&lt;p&gt;以常见混合精度 Adam 配置举例：BF16 参数 2 字节、BF16 梯度 2 字节、FP32 主权重 4 字节、一二阶矩各 4 字节，合计约 16 字节/参数，&lt;b&gt;尚未算激活&lt;/b&gt;。具体实现可能没有独立主权重或梯度 dtype 不同，应按实际 tensor 清单计算，不能把 16 当恒定真理。&lt;/p&gt;&#10;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;减少什么&lt;/th&gt;&lt;th&gt;付出什么&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;混合精度&lt;/td&gt;&lt;td&gt;部分 tensor 存储、计算时间&lt;/td&gt;&lt;td&gt;数值范围/累加精度、溢出检查；FP16 通常需关注 loss scaling，BF16 仍要质量验证&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;梯度累积&lt;/td&gt;&lt;td&gt;用小 microbatch 实现较大有效 batch&lt;/td&gt;&lt;td&gt;多次前后向；不能消除参数/优化器常驻开销。有效 batch = microbatch × DP × 累积步数&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Activation checkpointing&lt;/td&gt;&lt;td&gt;保存的中间激活&lt;/td&gt;&lt;td&gt;反向时重算；与“保存训练断点文件”不是同一件事&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ZeRO Stage 1/2/3&lt;/td&gt;&lt;td&gt;逐步切分优化器状态、梯度、参数&lt;/td&gt;&lt;td&gt;参数收集/梯度归约等通信和管理复杂度；阶段并非只改变一个开关&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;FSDP&lt;/td&gt;&lt;td&gt;通过分片参数及相关状态降低单卡占用&lt;/td&gt;&lt;td&gt;计算前后 all-gather / reduce-scatter，需考虑 wrap、预取和内存峰值&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;序列 packing / 高效 attention&lt;/td&gt;&lt;td&gt;padding 浪费 / attention 中间存储与 IO&lt;/td&gt;&lt;td&gt;mask、位置编码、样本边界与 loss 正确性必须保持&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;p class=&quot;source&quot;&gt;&lt;a href=&quot;https://docs.pytorch.org/tutorials/intermediate/FSDP_tutorial.html&quot;&gt;PyTorch FSDP2 教程&lt;/a&gt;说明分片及计算前收集的基本机制；实际训练栈版本要单独核实。&lt;/p&gt;&#10;&lt;h3&gt;7.2 训练慢，先拆 step time&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Tstep ≈ 数据等待 + 前向 + 反向 + 优化器 + 未被隐藏的通信/同步&lt;/code&gt;。有 overlap 时不能简单把所有 profiler 时间相加。先看数据加载/拷贝、设备空洞、热点算子、collective 和最慢 rank，再选数据预取、融合、微批、重计算、并行策略或通信重叠。速度评估要同时关注 loss 收敛、最终质量与达到目标质量的总时间。&lt;/p&gt;&#10;&lt;h3&gt;7.3 如何把 NVIDIA 上的经验迁移到寒武纪？&lt;/h3&gt;&lt;p&gt;寒武纪官方维护 &lt;a href=&quot;https://github.com/Cambricon/vllm-mlu&quot;&gt;vllm-mlu&lt;/a&gt;，仓库描述其通过 vLLM 插件机制提供 MLU 推理服务。可以把它作为框架后端适配的真实入口；不要据此推断所有模型、算子和特性组合都已覆盖。&lt;a href=&quot;https://github.com/sgl-project/sglang/issues/26438&quot;&gt;SGLang 的 MLU in-tree 支持 RFC&lt;/a&gt;是提案证据，不能单靠 issue 宣称已完成主线支持。&lt;/p&gt;&#10;&lt;ol&gt;&lt;li&gt;&lt;b&gt;列兼容矩阵：&lt;/b&gt;芯片型号、SDK/驱动、框架插件、PyTorch 适配层、模型架构、dtype、attention/量化/通信特性。&lt;/li&gt;&lt;li&gt;&lt;b&gt;先做正确性：&lt;/b&gt;单算子 reference 对比，验证 shape、dtype、layout、边界输入与误差；再测单层和单卡端到端。&lt;/li&gt;&lt;li&gt;&lt;b&gt;替换设备相关部分：&lt;/b&gt;设备抽象、内存分配与 stream/event、算子/编译后端、collective、图执行。CUDA 专用二进制或 PTX 不能直接在 MLU 上运行。&lt;/li&gt;&lt;li&gt;&lt;b&gt;逐层性能定位：&lt;/b&gt;算子 microbenchmark → 单卡模型 → 多卡通信 → 完整服务；使用目标平台 profiler，而不是假设 NVIDIA 工具直接适用。&lt;/li&gt;&lt;li&gt;&lt;b&gt;最后服务验证：&lt;/b&gt;质量、TTFT/ITL、Goodput、OOM、并发、取消、长输入、异常恢复与版本回滚。&lt;/li&gt;&lt;/ol&gt;&#10;&lt;div class=&quot;callout&quot;&gt;&lt;b&gt;30 秒回答：&lt;/b&gt;“我可迁移的是负载建模、KV/调度理解、进程组通信不变量和验证方法。CUDA、FlashInfer、NCCL 的具体实现需要换成目标平台支持的运行时、算子和通信后端。我会先打通单算子到单卡正确性，再扩多卡和服务压测；目前不把 NVIDIA 适配经历说成已有 MLU 实战。”&lt;/div&gt;&lt;/section&gt;&#10;&#10;&lt;section id=&quot;design&quot;&gt;&lt;h2&gt;08 · 系统设计与压测：把知识用起来&lt;/h2&gt;&lt;h3&gt;设计题：8 张消费级 GPU 部署 32B，怎样兼顾长输入和低延迟？&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;澄清目标：&lt;/b&gt;模型/精度、最大与典型输入输出长度、并发或到达率、共享前缀比例、TTFT/ITL SLO、质量门槛及拓扑。&lt;/li&gt;&lt;li&gt;&lt;b&gt;做容量预算：&lt;/b&gt;权重 + KV + 激活 + runtime 余量，评估可行 TP 与副本数。对比 TP8 单副本与其他可行分组；不预先认定某方案最优。&lt;/li&gt;&lt;li&gt;&lt;b&gt;建立简单基线：&lt;/b&gt;先验证单请求质量、常规并发和取消回收，记录队列、token budget、缓存与通信。&lt;/li&gt;&lt;li&gt;&lt;b&gt;定位瓶颈：&lt;/b&gt;长 prefill 阻塞 decode → chunk；KV 容量限制 → KV 量化/缓存回收；通信限制 → 减少通信域/调整分组；CPU launch 限制 → overlap/graph。&lt;/li&gt;&lt;li&gt;&lt;b&gt;再考虑复杂方案：&lt;/b&gt;PD 分离须算 KV 迁移成本；投机解码须测接受长度与额外成本；模型量化/蒸馏须过质量门槛。&lt;/li&gt;&lt;li&gt;&lt;b&gt;验证与上线：&lt;/b&gt;在同负载下比较延迟分位数、Goodput、失败率和成本；灰度、回滚、健康检查、限流、排队上限与超时。&lt;/li&gt;&lt;/ol&gt;&#10;&lt;h3&gt;看到症状时，先收什么证据？&lt;/h3&gt;&lt;div class=&quot;tablewrap&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;现象&lt;/th&gt;&lt;th&gt;优先观测&lt;/th&gt;&lt;th&gt;可验证假设&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TTFT 随到达率陡增&lt;/td&gt;&lt;td&gt;队列等待、入队率/完成率、prefill 时间、前缀命中&lt;/td&gt;&lt;td&gt;系统接近饱和；先限流或扩副本，再判断算子是否慢&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;长请求进入时 P99 ITL 抖动&lt;/td&gt;&lt;td&gt;prefill/decode 时间线、chunk 长度、迭代耗时&lt;/td&gt;&lt;td&gt;prefill 干扰；扫 chunk 和 token budget&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;加 TP 后反而变慢&lt;/td&gt;&lt;td&gt;collective 时间、消息大小、拓扑与负载&lt;/td&gt;&lt;td&gt;通信超过计算收益；尝试较小 TP、多副本&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;prefill OOM&lt;/td&gt;&lt;td&gt;输入长度、视觉 token、激活与临时工作区峰值&lt;/td&gt;&lt;td&gt;chunk/长度上限/静态池占用不合理&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;decode 缓存耗尽或频繁抢占&lt;/td&gt;&lt;td&gt;活跃序列、总已缓存 token、可回收块、泄漏&lt;/td&gt;&lt;td&gt;并发/长度过高或生命周期回收错误&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GPU 间歇空闲、请求仍排队&lt;/td&gt;&lt;td&gt;CPU tokenize、调度、同步、数据拷贝时间线&lt;/td&gt;&lt;td&gt;host bottleneck 或过度同步；不能仅凭 GPU 利用率下结论&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;h3&gt;一份可信的压测记录至少包含&lt;/h3&gt;&lt;p&gt;硬件/拓扑/驱动；模型与 tokenizer revision；框架 commit/版本与完整命令；dtype 和后端；真实 token 长度分布与图像条件；并发或到达率模式；采样配置；冷暖缓存与预热；预填充/解码阶段；成功/超时/取消/OOM；重复次数；TTFT/TPOT/ITL 的计时定义与分位数；输入吞吐与输出吞吐；质量变化。&lt;/p&gt;&#10;&lt;p&gt;&lt;b&gt;建议消融设计：&lt;/b&gt;同一基础配置 → 只开 KV 量化 → 只开权重量化/对应内核 → 组合；另一组独立比较 chunk/PD。一次只改一个可归因因素，记录所有隐藏默认值。多重复取分布，不能只报最快一次。&lt;/p&gt;&lt;div class=&quot;callout warn&quot;&gt;&lt;b&gt;切勿过度归因：&lt;/b&gt;缓存命中、模型/长度、量化、图执行、batch、后端、版本、预热、测量窗任一不同，都可能造成“看起来提速”。整体方案比较可以有价值，但必须按整体方案报告。&lt;/div&gt;&lt;/section&gt;&#10;&#10;&lt;section id=&quot;quiz&quot;&gt;&lt;h2&gt;09 · 自测与口述卡&lt;/h2&gt;&lt;p&gt;先答再展开。每题按 &lt;b&gt;0 = 说不清，1 = 能下定义，2 = 能解释机制，3 = 能联系项目并说清代价&lt;/b&gt; 自评。P0 题达到 2，简历相关题争取达到 3。&lt;/p&gt;&lt;input class=&quot;search&quot; id=&quot;quizsearch&quot; placeholder=&quot;搜索自测：如 KV、死锁、量化、训练&quot; aria-label=&quot;搜索自测题&quot;&gt;&#10;&lt;div id=&quot;quizlist&quot;&gt;&#10;&lt;details&gt;&lt;summary&gt;P0 · 1. 为什么 KV Cache 不缓存历史 Q？&lt;/summary&gt;&lt;p&gt;自回归新位置需要用新 Q 查询历史 K/V。历史位置的 Q 已完成输出计算，未来位置通常不再用它，因此标准增量 decode 不需要保存历史 Q。缓存 K/V 不会消除新 Q 对历史上下文的 attention。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P0 · 2. GQA 如何改变 KV 大小？&lt;/summary&gt;&lt;p&gt;KV 大小按 KV 头数而非 Q 头数计。其他维度相同时，减少 Hkv 线性减少 KV 主数据容量。实际 TP 布局可能存在复制，单卡结果不能机械再除以 TP。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P0 · 3. Prefix Caching 能直接加速每个 decode token 吗？&lt;/summary&gt;&lt;p&gt;它主要省去命中前缀的重复 prefill，并可能省共享 KV 存储；decode 仍要读取相关上下文。端到端可能间接受益，但不能声称命中后历史 KV 不再被 attention 访问。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P0 · 4. FlashAttention、PagedAttention、RadixAttention 分别优化什么？&lt;/summary&gt;&lt;p&gt;FlashAttention：attention 执行的显存 IO；PagedAttention：动态 KV 内存管理与访问；RadixAttention：公共前缀 KV 的组织和复用。可组合，不能只凭名称判断框架优劣。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P0 · 5. FP8 KV 后吞吐变高，为什么单请求还可能更慢？&lt;/summary&gt;&lt;p&gt;容量增大可支持更大 batch，从而提高聚合吞吐；单请求可能受转换、反量化、后端支持或额外调度开销影响。分别测容量、单请求 TPOT、聚合吞吐和质量。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P0 · 6. 构造 idle batch 为什么能修死锁？&lt;/summary&gt;&lt;p&gt;它让空闲组沿框架认可的路径参与必要 collective，修复通信参与不一致。前提是 batch 元数据和调用顺序正确；idle 结果不能转成真实 Decode 请求。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P0 · 7. 你说的吞吐 2.02×，是个人一处代码带来的收益吗？&lt;/summary&gt;&lt;p&gt;不是。是适配后的内部 EdgeAcc 整体方案和开源方案对比。个人负责多卡扩展与稳定性修复；没有严格单变量消融证明某个补丁独自带来 2.02×。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P0 · 8. 为何不能说 32B 就必须 TP8？&lt;/summary&gt;&lt;p&gt;权重容量只给出起点，精度、KV、激活、卡容量、通信与 SLO 决定具体方案。BF16 32B 权重约 64 GB，但可有多种分片/副本组合；先预算再测。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 9. chunk 越小为什么不一定越快？&lt;/summary&gt;&lt;p&gt;小 chunk 降低单次 prefill 阻塞和临时峰值，却增加调度/执行次数，并可能降低矩阵效率。ITL、TTFT、吞吐要联合看。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 10. 多卡 all-reduce 的成本怎么估？&lt;/summary&gt;&lt;p&gt;粗略由启动延迟、参与 rank 数、传输字节数和有效带宽决定；ring 的带宽项可写为约 2(N−1)/N × 消息大小/带宽，再加多步延迟。真实算法选择与拓扑不同，不能当精确预测。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 11. PD 分离怎样判断划算？&lt;/summary&gt;&lt;p&gt;比较干扰减少和资源独立扩缩带来的收益，与 KV 传输、额外路由/排队、故障处理成本。先估 KV 体积/有效带宽，再用实际负载验证；同卡与跨机分离分别讨论。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 12. EAGLE3 接受长度 1.3 说明什么？&lt;/summary&gt;&lt;p&gt;先问这个长度包含哪些 token、在什么采样与负载下测得。若每轮节约的普通解码时间不及草稿+验证开销，就不会加速；它不能单独指出根因，也不能否定方法整体。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 13. 训练 DDP 和推理 DP 的区别？&lt;/summary&gt;&lt;p&gt;DDP 的数据并行训练需同步梯度以保持副本更新一致；普通推理 DP 各副本只处理独立请求，一般没有梯度同步。DP Attention/某些 MoE 模式可能仍有跨组协作，应另说。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 14. 训练 OOM，梯度累积为什么不一定解决？&lt;/summary&gt;&lt;p&gt;它主要允许较小 microbatch，降低与 batch 相关的激活占用；参数、优化器状态、某些缓冲仍常驻。若这些占主导，需要分片、低精度、offload 等方案。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 15. 量化后应该怎样检查质量？&lt;/summary&gt;&lt;p&gt;与原精度在同模型/样本/解码设置比较算子误差和端到端任务指标；覆盖长上下文、极端数值、输出约束与典型业务。小误差不必然代表任务质量无损，文本不同也不必然代表质量下降。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 16. 4 卡教师到单卡学生，怎么说是优化？&lt;/summary&gt;&lt;p&gt;分别报告资源配置、质量与服务指标。69/76 是 held-out 语义准确率，不是所有线上请求准确率；还需验证同质量门槛下的吞吐、延迟和实际成本。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 17. 用户取消后应清理什么？&lt;/summary&gt;&lt;p&gt;从等待/运行队列和输出状态解除；释放本请求 KV 引用、预留资源与其他关联状态；保护仍被其他请求共享的缓存；处理执行在途结果，避免重复释放和迟到输出。&lt;/p&gt;&lt;/details&gt;&#10;&lt;details&gt;&lt;summary&gt;P1 · 18. 你如何回答“能在寒武纪平台做什么”？&lt;/summary&gt;&lt;p&gt;从已做过的调度、缓存、通信定位和验证能力回答，提出后端兼容矩阵、单算子正确性、单卡到多卡、服务压测的落地路径。明确还需熟悉 MLU SDK，不编造 MLU 实战。&lt;/p&gt;&lt;/details&gt;&#10;&lt;/div&gt;&#10;&lt;h3&gt;90 秒自我介绍提纲&lt;/h3&gt;&lt;div class=&quot;callout&quot;&gt;“我是四川大学计算机技术硕士，预计 2027 年毕业。阿里云实习主要做大模型推理部署和优化。我的工作集中在三块：一是基于已有 SGLang 内部引擎扩展多卡 DP/DP Attention，处理启动、rank 映射和请求路由；二是定位空闲组参与 collective 不一致导致的死锁，并处理控制消息的子组边界；三是在历史版本中适配 FP8 路径，评估 KV 量化对容量、吞吐与延迟的影响。我也做过 VLM LoRA 训练与教师到小模型的轨迹蒸馏，能把模型质量和服务资源一起评估。希望进一步做框架运行时、调度通信和硬件后端优化。”&lt;/div&gt;&lt;p&gt;这是依据材料组织的口述提纲，用自己的语言讲；被追问没有证据的实现细节时，说明边界。&lt;/p&gt;&#10;&lt;h3&gt;面试前 20 分钟&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;5 分钟：默画请求链路，解释 TTFT / ITL / 输出吞吐。&lt;/li&gt;&lt;li&gt;7 分钟：讲死锁修复，复习 FP8 与性能数字的口径。&lt;/li&gt;&lt;li&gt;5 分钟：训练显存、FSDP/ZeRO、MLU 适配路径。&lt;/li&gt;&lt;li&gt;3 分钟：准备反问，例如岗位主要瓶颈在训练算子、通信、框架调度还是部署适配；新人验证任务通常以什么基准和质量门槛验收。&lt;/li&gt;&lt;/ol&gt;&lt;/section&gt;&#10;&#10;&lt;section id=&quot;sources&quot;&gt;&lt;h2&gt;10 · 来源、版本与事实边界&lt;/h2&gt;&lt;p&gt;材料编制于 2026-10-14（北京时间）。当前官方文档用于学习框架机制；main 源码入口已通过官方原始文件访问核实存在，链接会随上游更新。历史项目讲解以当时分支和本地确认记录为准。本次没有修改简历、个人事实库或投递日程，也没有执行 GPU 实验。&lt;/p&gt;&#10;&lt;h3&gt;本地事实来源&lt;/h3&gt;&lt;ul class=&quot;sources&quot;&gt;&lt;li&gt;当前大模型推理部署方向 PDF（本地核验，未附原始文件）：逐条经历与简历指标；本次通过 PDF 文本提取核对内容。&lt;/li&gt;&lt;li&gt;个人事实主档（本地核验，未附原始文件）：个人贡献、历史版本、补丁与 P2P/MXFP8 的证据边界。&lt;/li&gt;&lt;li&gt;权威求职日程（本地核验，未附原始文件）及现有招聘系统数据：正式邀约时间、轮次、双机位与已投简历方向。旧条目的“结束时间待核”不能覆盖后续正式邮件记录。&lt;/li&gt;&lt;li&gt;本地博客存档：&lt;code&gt;zh__sglang-32b-edgeacc-dp-deployment.md&lt;/code&gt;。用于历史技术细节；原文“幂等”“必须 TP8”“性能归因”等宽泛表述以主档修正口径为准。&lt;/li&gt;&lt;/ul&gt;&#10;&lt;h3&gt;官方阅读入口&lt;/h3&gt;&lt;ul class=&quot;sources&quot;&gt;&lt;li&gt;&lt;a href=&quot;https://docs.sglang.io/docs/get-started/quickstart&quot;&gt;SGLang Quickstart&lt;/a&gt; · &lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/server_arguments&quot;&gt;Server Arguments&lt;/a&gt; · &lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/hyperparameter_tuning&quot;&gt;调优&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/dp_dpa_smg_guide&quot;&gt;DP / DP Attention&lt;/a&gt; · &lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/quantized_kv_cache&quot;&gt;KV 量化&lt;/a&gt; · &lt;a href=&quot;https://docs.sglang.io/docs/advanced_features/speculative_decoding&quot;&gt;投机解码&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://docs.vllm.ai/en/latest/design/arch_overview/&quot;&gt;vLLM V1 架构&lt;/a&gt; · &lt;a href=&quot;https://docs.vllm.ai/en/latest/design/prefix_caching/&quot;&gt;前缀缓存设计&lt;/a&gt; · &lt;a href=&quot;https://docs.vllm.ai/en/latest/configuration/optimization/&quot;&gt;调优&lt;/a&gt; · &lt;a href=&quot;https://docs.vllm.ai/en/latest/getting_started/quickstart/&quot;&gt;Quickstart&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/2205.14135&quot;&gt;FlashAttention 原论文&lt;/a&gt; · &lt;a href=&quot;https://arxiv.org/abs/2309.06180&quot;&gt;PagedAttention 原论文&lt;/a&gt; · &lt;a href=&quot;https://arxiv.org/abs/2312.07104&quot;&gt;SGLang 原论文&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://docs.nvidia.com/deeplearning/nccl/user-guide/docs/usage/collectives.html&quot;&gt;NCCL 集合通信&lt;/a&gt; · &lt;a href=&quot;https://docs.pytorch.org/tutorials/intermediate/FSDP_tutorial.html&quot;&gt;PyTorch FSDP2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/Cambricon/vllm-mlu&quot;&gt;寒武纪 vllm-mlu&lt;/a&gt; · &lt;a href=&quot;https://github.com/sgl-project/sglang/issues/26438&quot;&gt;SGLang MLU RFC（提案）&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&#10;&lt;div class=&quot;callout warn&quot;&gt;&lt;b&gt;仍有证据缺口：&lt;/b&gt;完整 JD 正文；32B 对照双方完整启动命令/开源基线版本/原始日志；5090 FP8 线的模型、版本与压测参数；原始修复 diff。学习材料已给出可回答的范围，不用其他工作线的数据代填。&lt;/div&gt;&lt;/section&gt;&#10;&lt;footer&gt;面试学习材料 · 在线发布于 Cortex CC（2026-10-15）；本地保留完整原件 · 不作为投递进度表或日程替代品。所有教学算例与实验模板均已区分于个人实测结果。&lt;/footer&gt;&#10;&lt;/main&gt;&#10;&lt;script&gt;&#10;const key=&#x27;cambricon-aiinfra-20261016-checks&#x27;;let saved={};try{saved=JSON.parse(localStorage.getItem(key)||&#x27;{}&#x27;)}catch(e){};const boxes=[...document.querySelectorAll(&#x27;[data-check]&#x27;)];function progress(){const n=boxes.filter(x=&gt;x.checked).length;document.querySelector(&#x27;#progressbar&#x27;).style.width=(n/boxes.length*100)+&#x27;%&#x27;;document.querySelector(&#x27;#progresslabel&#x27;).textContent=n+&#x27; / &#x27;+boxes.length+&#x27; 项已勾选&#x27;}boxes.forEach(b=&gt;{b.checked=!!saved[b.dataset.check];b.addEventListener(&#x27;change&#x27;,()=&gt;{saved[b.dataset.check]=b.checked;try{localStorage.setItem(key,JSON.stringify(saved))}catch(e){}progress()})});progress();&#10;document.querySelectorAll(&#x27;[data-timer]&#x27;).forEach(el=&gt;{let remaining=1800000,deadline=null;const display=el.querySelector(&#x27;.clock&#x27;);function show(){const r=deadline===null?remaining:Math.max(0,deadline-Date.now());const s=Math.ceil(r/1000);display.textContent=String(Math.floor(s/60)).padStart(2,&#x27;0&#x27;)+&#x27;:&#x27;+String(s%60).padStart(2,&#x27;0&#x27;);if(deadline!==null&amp;&amp;r===0){remaining=0;deadline=null;display.textContent=&#x27;已完成&#x27;}}el.querySelector(&#x27;[data-action=start]&#x27;).onclick=()=&gt;{if(deadline===null&amp;&amp;remaining&gt;0)deadline=Date.now()+remaining;show()};el.querySelector(&#x27;[data-action=pause]&#x27;).onclick=()=&gt;{if(deadline!==null){remaining=Math.max(0,deadline-Date.now());deadline=null}show()};el.querySelector(&#x27;[data-action=reset]&#x27;).onclick=()=&gt;{remaining=1800000;deadline=null;show()};setInterval(show,250);show()});&#10;document.querySelector(&#x27;#quizsearch&#x27;).addEventListener(&#x27;input&#x27;,e=&gt;{const q=e.target.value.toLowerCase().trim();document.querySelectorAll(&#x27;#quizlist details&#x27;).forEach(d=&gt;d.hidden=!d.textContent.toLowerCase().includes(q))});function printAll(){document.querySelectorAll(&#x27;details&#x27;).forEach(d=&gt;d.open=true);document.querySelectorAll(&#x27;#quizlist details&#x27;).forEach(d=&gt;d.hidden=false);window.print()}&#10;&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;&#10;"></iframe>
    </div>