我已走完本仓 onboarding 链路（L-core 4 份全文 + AGENTS 硬规则/Onboarding Gate + `code-conventions` 起手必读段与命中的 R 规则 + `domain-tvu` 全文 + `design-process` 命中段 + `figma-component-catalog`），并逐一读了要 mirror 的活源组件与 token。下面先给必需的自检产出，再给单文件 HTML。

## 起手判定（R7 + Task Entry Mode）

**intent classified as 场景 3.2（Greenfield 单页 · 用 TVU 构建）/ US-2** ⇒ R1/R2/R3/R15 强约束，R8/R9/R12/R13/R14/R16/R23 全部 fire。视觉真源 = TVU library（不是任何外部稿）。

## M48 起手规则覆盖清单（交付前已逐条回核）

| 命中规则 | 本页怎么落地 |
|---|---|
| **M1** Top bar 必 instance | 顶栏 1:1 mirror `components/TopBar/TopBar.vue`（64px · `--bg-topbar` · brand/menu/right 三区）；页面级元素（筛选/搜索）放**顶栏下方独立 strip**，未塞进 slot |
| **M3** 广播 ON AIR 色 | Live=`--red`、告警=`--orange`、离线=中性灰。**没有**用 SaaS 默认「绿=正常」 |
| **M4** 监控台仅 dark | 只出 dark，无 theme toggle、无浅色并排 |
| **M5** 监控页不放创建入口 | 无 `+ New Source`（CRUD 自检里写了 rationale） |
| **M7** actions > identifiers > status | 操作列用正规 M 尺寸(32px) Button；ID 用 tips 级；状态 pill 为描边/暗块，不抢焦点 |
| **M9** literal 动词 | `Stop Streaming` / `Restart` / `Set Source and Receiver`，无图标替代文字 |
| **M10** 离线必分两子型 | `SRC-0977` = Idle（`Last ran 09:12 → 11:40 · 148 min`）；`SRC-1130` = NeverStarted（`Never started` + CTA） |
| **M11** trend 双层信号 | 阈值→icon(`navigation/arrow-down`) **且** 数值染色(`--orange`)；stable 无 icon 中性色 |
| **M12** 异步事件不静默 | 停流/重启后出 `Notification form=slide` 告知 + 行内前进路径 |
| **R15/R1** library-first | Top bar / Table / Button / Badge / Tab-Item / input box filled / Tooltips / Notification 全部 mirror canonical；11 个图标全部逐字取自 `src/icons/**`，**零自画 SVG** |
| **R2** 零硬编码色 | 全部 `var(--*)`，token 块逐字复制 `src/tokens/variables.css` |
| **R14** layout 原语 | flex/grid；仅遮罩层/tooltip/toast 用 fixed/absolute 且**均带注释** |
| **R16** 产品文案单语 | 全部 UI 串走 `const T = {…}`（EN 单语，无中英混排） |
| **R23** 受限单元格溢出 | 名称 tail-ellipsis + `scrollWidth>clientWidth` 实测；URL 走 R23 给的 `centerEllipsis()`；仅**真截断**才挂 library Tooltip + `aria-describedby` + `title` 双保险 + `tabindex=0` 可键盘触发 |

**CRUD 自检（M-LIFECYCLE-CRUD）**：Read = 本页列表+状态+历史 meta；Update = 行内 Stop/Restart（URL/Receiver 字段属 Details，非本页）；Delete = **本页不提供**；Create = **本页不提供** —— 后两项 rationale = M5（源由后端/MicroApp 创建后 push 到监控台，dashboard 只做查看/启停/跳转）。
**Cardinality**：Source persistent（非 transient）· 1 Source : 1 Receiver（N 源可指向同一 Receiver，已在数据里体现 Frankfurt-01 / New York-04 / Lisbon-01 各带 2 条）· 状态机 `live ⇄ alarm → offline(idle) / offline(never)`。

**R9 交互态推断表**：hover = active 的弱版本（行 `--bg-layer3`、ghost 按钮取 `PALETTE_SPEC.hover` 原值）；focus = `outline 2px --brand`（照 Button/MenuList 既有做法给 Tab/Item 补上，DS 侧缺此态）；disabled = **照 Figma 真值**（ghost red disabled 保留 `opacity .4` —— 那是 Figma 提取值，非偷懒；灰/绿档走 `--text-placeholder` / `--brand-disable` token）。
**R13 affordance trace（趋势指示）**：① affordance = 方向/趋势指示 ② 同义词面 `arrow-down / down / trend / sorting / double-down` 扫 `navigation` + `arrow` 两层 ③ 选 `navigation/arrow-down`（`IconArrowDown`，实心单箭头、语义=下降），排除 `arrow/sorting`（排序双箭头）与 `action/double-down`（批量移动）。

## 两处如实登记的偏差（不是静默处理）

1. **状态 pill 家族**：`Live`/`Alarm` 用 `Badge Type=Rectangle Color=Red|Orange Tag=Line`，`Offline` 用 `Color=Neutral Tag=Filled` —— 同一 semanticRole 混了 Line/Filled，**M49 exception 理由**：`Badge Neutral/Line` 的文字绑 `--text-body`（最亮），会让最不重要的态最响，直接撞 M7；且 catalog 里 `Tag=Filled` 红/绿+白字那条 extension 正是 M7 立规时点名的反例。⚠️ 另：published `Pill Status` 只有 On-air/Preview/Analyzing/Inactive **四态、没有告警档**，所以我没去发明第五个 status（硬规则 #3），改用 Badge 既有 Orange 档 —— 「Pill Status 缺 warning」值得立一条 backlog（本 session 只读，未写）。
2. **单文件约束 vs R2.1**：R2.1 要求页面 `<link>` 构建时拷出的 `tvu-tokens.css`，单文件下不可行 ⇒ token 块**逐字内联**、值与 `src/tokens/variables.css` 一致（未手调任何色值）。另 `Notification` 的 `border-radius: 6px` 是组件自身字面量（DS 无对应 `--r-*`），照抄未改。

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Sources · TVU Grid</title>
<style>
/* ==========================================================================
 * TVU Design System — "Live Sources" operator console (single-file mockup)
 * R7 intent: 场景 3.2 greenfield single page, visual truth = TVU library.
 *
 * BLOCK 1  design tokens        — verbatim copy of src/tokens/variables.css (dark :root only, M4)
 * BLOCK 2  element base layer   — verbatim subset of variables.css "Element base layer"
 * BLOCK 3  mirrored canonicals  — TopBar / MenuList / Button / Badge / TabItem / Input /
 *                                 Table / Tooltip / Notification  (R3: 1:1 mirror, no re-design)
 * BLOCK 4  page composition     — consumer-side layout only, tokens only (R2)
 * ========================================================================== */

/* ── BLOCK 1 · tokens ─────────────────────────────────────────────────────── */
:root {
  /* Neutrals */
  --color-white: #ffffff;
  --color-grey-2: #f8f8f8;
  --color-grey-3: #f0f0f0;
  --color-grey-4: #dbdbdb;
  --color-grey-5: #cccccc;
  --color-grey-6: #9e9e9e;
  --color-grey-7: #7b7b7b;
  --color-grey-8: #595959;
  --color-grey-9: #434343;
  --color-grey-10: #353535;
  --color-grey-11: #262626;
  --color-grey-12: #1f1f1f;
  --color-grey-13: #141414;
  --color-grey-14: #000000;

  /* Brand & status */
  --brand: #2fb54e;
  --brand-hover: #41c760;
  --brand-match: #0b2b13;
  --brand-disable: #1a652c;
  --red: #ea4233;
  --red-hover: #ed5b4e;
  --red-bg: #fff1f0;
  --orange: #f68512;
  --orange-hover: #f89c3e;
  --orange-bg: #fff3db;
  --blue: #3892f3;
  --blue-hover: #62a9f6;
  --blue-bg: #e1eefd;

  /* Text */
  --text-heading: #ffffff;
  --text-body: #f8f8f8;
  --text-2: #cccccc;
  --text-tips: #9e9e9e;
  --text-placeholder: #7b7b7b;
  --text-disabled: #595959;
  --text-primary-btn: #f8f8f8;

  /* Icon */
  --icon-active: #f8f8f8;
  --icon-default: #9e9e9e;
  --icon-disabled: #595959;
  --icon-placeholder: #7b7b7b;

  /* Surface */
  --bg-layer1: #141414;
  --bg-layer2: #1f1f1f;
  --bg-layer3: #262626;
  --bg-layer4: #353535;
  --bg-topbar: #000000;
  --bg-grey-btn-hv: #595959;
  --bg-grey-btn-en: #434343;
  --bg-grey-btn-dis: #434343;

  /* Line */
  --line-border: #595959;
  --line-deep: #353535;
  --line-light: #434343;

  /* Input / select aliases */
  --input-line-border: var(--color-grey-8);
  --input-disabled-border: var(--color-grey-8);

  /* Spacing */
  --sp-xxs: 4px;
  --sp-xs: 8px;
  --sp-s: 12px;
  --sp-m: 16px;
  --sp-l: 24px;
  --sp-xl: 32px;
  --sp-xxl: 40px;
  --sp-xxxl: 56px;

  /* Radius */
  --r-xs: 2px;
  --r-s: 4px;
  --r-m: 8px;
  --r-l: 12px;
  --r-xl: 16px;
  --r-xxl: 20px;

  /* Z-Index / Elevation — DS deliberately has NO --z-toast (no measured consumer). */
  --z-dropdown: 1000;
  --z-tooltip: 1000;
  --z-modal: 1000;
  --z-select-portal: 1100;

  /* Layout breakpoints (media-query literals must stay inside this value set) */
  --bp-sm: 640px;
  --bp-md: 960px;
  --bp-lg: 1100px;
  --bp-xl: 1280px;

  /* Layout containers */
  --container-narrow: 720px;
  --container-prose: 840px;
  --container-page: 1600px;
  --container-wide: 1800px;

  /* Typography — no separate monospace font exists in this system. */
  --font-family-en: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans',
    'Droid Sans', 'Helvetica Neue', sans-serif;
  --font-family-zh: 'PingFang SC', 'Microsoft YaHei', Helvetica, Arial, sans-serif;
  --font-family-base: var(--font-family-en), var(--font-family-zh);

  /* Component-variant / structural tokens */
  --notification-bg-dark: var(--color-grey-10);
  --tooltip-bg-dark: var(--color-grey-10);
  --tooltip-border-dark: var(--color-grey-8);
  --tooltip-text-dark: var(--color-grey-2);
  --tooltip-max-width: 320px;
  --notification-width-default: 480px;
  --notification-width-side-pop: 320px;
  --badge-circle-size: 24px;
  --topbar-section-gap: 80px;
  --topbar-height: 64px;
  --control-height-xxs: 32px;

  /* Effect styles — Figma 3-layered drop shadows */
  --shadow-l1:
    0 5px 12px 4px #00000017,
    0 3px 6px 0 #0000001f,
    0 1px 2px -2px #00000029;
  --shadow-l2:
    0 9px 28px 8px #0000000d,
    0 6px 16px 0 #00000014,
    0 3px 6px -4px #0000001f;
  --shadow-l3:
    0 12px 48px 16px #00000008,
    0 9px 28px 0 #0000000d,
    0 6px 16px -8px #00000014;
  --mask-overlay: rgba(0, 0, 0, 0.6);
  --mask-overlay-blur: 8px;

  /* Text styles */
  --text-style-tips:           400 12px/16px var(--font-family-base);
  --text-style-body:           400 14px/21px var(--font-family-base);
  --text-style-pop-title:      600 16px/24px var(--font-family-base);
  --text-style-headline-2:     600 18px/27px var(--font-family-base);
  --text-style-headline-1:     600 20px/30px var(--font-family-base);
  --font-size-tips: 12px;
  --font-size-body: 14px;
  --line-height-tips: 16px;
  --line-height-body: 21px;
  --font-weight-regular: 400;
  --font-weight-semibold: 600;

  /* Derived aliases */
  --input-filled-bg: var(--bg-layer4);
  --green-bg: var(--brand-match);
  --control-disabled-bg: var(--line-deep);
  --control-disabled-border: var(--line-border);
  --control-disabled-text: var(--text-disabled);
}

/* ── BLOCK 2 · element base layer (verbatim subset) ───────────────────────── */
body {
  font: var(--text-style-body);
  font-family: var(--font-family-base);
}
h1 { font: var(--text-style-headline-1); color: var(--text-body); }
h2 { font: var(--text-style-headline-2); color: var(--text-body); }
h3 { font: var(--text-style-pop-title); color: var(--text-body); }
label { font: var(--text-style-body); color: var(--text-body); }
a { color: var(--brand); }
button {
  font: var(--text-style-body);
  color: inherit;
  border-radius: var(--r-s);
}
input {
  font: var(--text-style-body);
  color: var(--text-body);
  background: var(--input-filled-bg);
  border: 1px solid var(--line-border);
  border-radius: var(--r-s);
  padding: var(--sp-xs) var(--sp-s);
}
input::placeholder { color: var(--text-placeholder); }
table {
  font: var(--text-style-body);
  color: var(--text-body);
  border-collapse: collapse;
}
th {
  font-weight: 600;
  color: var(--text-body);
  text-align: left;
  padding: var(--sp-xs) var(--sp-s);
}
td {
  padding: var(--sp-xs) var(--sp-s);
  border-top: 1px solid var(--line-border);
}
[role="dialog"] { font: var(--text-style-body); color: var(--text-body); background: var(--bg-layer2); border-radius: var(--r-l); }

/* ── BLOCK 3 · mirrored canonical components ──────────────────────────────── */

/* Icon — mirror of src/components/Icon/Icon.vue */
.icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.icon svg { width: 100%; height: 100%; }
.icon--12 { width: 12px; height: 12px; }
.icon--16 { width: 16px; height: 16px; }
.icon--24 { width: 24px; height: 24px; }
/* Protocol wordmark indicators keep their published intrinsic 10px height. */
.proto { display: inline-flex; align-items: center; flex-shrink: 0; height: 10px; }
.proto svg { height: 100%; width: auto; display: block; }

/* TopBar — mirror of src/components/TopBar/TopBar.vue */
.topbar {
  display: flex;
  align-items: center;
  padding: var(--sp-xs) var(--sp-m);
  background: var(--bg-topbar);
  border: 1px solid var(--line-deep);
  gap: var(--topbar-section-gap);
  flex-shrink: 0;
  width: 100%;
  box-sizing: border-box;
}
.topbar--after-login { height: var(--topbar-height); }
.topbar-brand { display: flex; align-items: center; gap: var(--sp-m); flex-shrink: 0; }
.topbar-title { font: var(--text-style-pop-title); color: var(--text-heading); white-space: nowrap; }
.topbar-menu { display: flex; align-items: center; gap: var(--sp-xxl); flex: 1; }
.topbar-right { display: flex; align-items: center; gap: var(--sp-xs); flex-shrink: 0; margin-left: auto; }

/* MenuList horizontal — mirror of src/components/MenuList/MenuList.vue
   Figma truth = Menu sub-component inside published Top bar (4771:7173):
   active vs normal differ ONLY in text colour. There is NO underline. */
.menu-list { list-style: none; margin: 0; padding: 0; display: flex; box-sizing: border-box; }
.menu-list--horizontal { flex-direction: row; align-items: center; gap: var(--sp-m); }
.menu-list--horizontal .menu-list__item {
  display: flex;
  align-items: center;
  gap: var(--sp-xxs);
  padding: 0 var(--sp-xs);
  font: var(--text-style-headline-2);
  color: var(--text-tips);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.menu-list--horizontal .menu-list__item:hover:not(.is-disabled) { color: var(--text-heading); }
.menu-list--horizontal .menu-list__item.is-active { color: var(--text-body); }
.menu-list__item:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

/* Button — mirror of src/components/Button/Button.vue (SIZE_GEOMETRY + PALETTE_SPEC) */
.btn {
  --btn-bg: transparent;
  --btn-color: var(--text-2);
  --btn-border: transparent;
  --btn-bg-hover: transparent;
  --btn-color-hover: var(--text-2);
  --btn-border-hover: transparent;
  --btn-opacity: 1;
  --btn-height: 32px;
  --btn-font-size: 14px;
  --btn-line-height: 21px;
  --btn-gap: 0px;
  --btn-padding-inline: 16px;
  --btn-border-width: 1px;
  --btn-radius-square: 4px;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--btn-gap);
  min-width: 0;
  padding-inline: var(--btn-padding-inline);
  height: var(--btn-height);
  border: var(--btn-border-width) solid var(--btn-border);
  background: var(--btn-bg);
  color: var(--btn-color);
  opacity: var(--btn-opacity);
  font-family: var(--font-family-base);
  font-size: var(--btn-font-size);
  font-weight: 400;
  line-height: var(--btn-line-height);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s, opacity 0.15s;
  white-space: nowrap;
  outline: none;
  user-select: none;
  box-sizing: border-box;
}
.btn--radius-square { border-radius: var(--btn-radius-square); }
.btn--m { --btn-height: 32px; --btn-font-size: 14px; --btn-line-height: 21px; --btn-padding-inline: 16px; --btn-radius-square: 4px; }
.btn:hover:not(:disabled) {
  background: var(--btn-bg-hover);
  color: var(--btn-color-hover);
  border-color: var(--btn-border-hover);
}
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.btn:disabled { cursor: not-allowed; }
/* style=ghost → 1.2px border (Button.vue borderWidth) */
.btn--ghost-gray {
  --btn-border-width: 1.2px;
  --btn-bg: transparent; --btn-color: var(--text-2); --btn-border: var(--bg-grey-btn-en);
  --btn-bg-hover: var(--bg-grey-btn-en); --btn-color-hover: var(--text-2); --btn-border-hover: var(--bg-grey-btn-en);
}
.btn--ghost-gray:disabled { --btn-color: var(--text-placeholder); --btn-border: var(--bg-grey-btn-en); }
.btn--ghost-red {
  --btn-border-width: 1.2px;
  --btn-bg: transparent; --btn-color: var(--red); --btn-border: var(--red);
  --btn-bg-hover: var(--red-bg); --btn-color-hover: var(--red); --btn-border-hover: var(--red);
}
/* red/orange disable+loading carry the Figma-extracted container opacity 0.4 */
.btn--ghost-red:disabled { --btn-opacity: 0.4; }
.btn--ghost-green {
  --btn-border-width: 1.2px;
  --btn-bg: transparent; --btn-color: var(--brand); --btn-border: var(--brand);
  --btn-bg-hover: var(--green-bg); --btn-color-hover: var(--brand); --btn-border-hover: var(--brand);
}
.btn--ghost-green:disabled { --btn-color: var(--brand-disable); --btn-border: var(--brand-disable); }
.btn--fill-red {
  --btn-bg: var(--red); --btn-color: var(--text-primary-btn); --btn-border: transparent;
  --btn-bg-hover: var(--red-hover); --btn-color-hover: var(--text-primary-btn); --btn-border-hover: transparent;
}
.btn--text-green {
  --btn-bg: transparent; --btn-color: var(--brand); --btn-border: transparent;
  --btn-bg-hover: var(--green-bg); --btn-color-hover: var(--brand); --btn-border-hover: transparent;
}

/* Badge — mirror of src/canonical/Badge.vue */
.canonical-badge {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--badge-width, auto);
  width: var(--badge-width, auto);
  height: var(--badge-circle-size);
  padding-block: var(--badge-padding-block, var(--sp-xxs));
  padding-inline: var(--badge-padding-inline, var(--sp-s));
  border: 1px solid var(--badge-border, transparent);
  border-radius: var(--r-xl);
  box-sizing: border-box;
  background: var(--badge-bg, transparent);
  color: var(--badge-text, var(--text-body));
  font: var(--text-style-tips);
  white-space: nowrap;
}
.canonical-badge--rectangle { width: auto; }
.badge--red-line     { --badge-bg: transparent;      --badge-border: var(--red);       --badge-text: var(--red); }
.badge--orange-line  { --badge-bg: transparent;      --badge-border: var(--orange);    --badge-text: var(--orange); }
.badge--neutral-fill { --badge-bg: var(--bg-layer4); --badge-border: transparent;      --badge-text: var(--text-body); }

/* Tab/Item filled — mirror of src/components/Tab/TabItem.vue (Figma 4452:7118 rebind) */
.tab-item {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-xs);
  height: 32px;
  padding: 0 var(--sp-m);
  font: var(--text-style-body);
  color: var(--text-tips);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
  border: 0;
}
.tab-item--filled { border-radius: var(--r-s); }
.tab-item--filled.tab-item--normal { background: var(--bg-layer3); color: var(--text-2); }
.tab-item--filled.tab-item--active-green { background: var(--brand); color: var(--text-primary-btn); }
.tab-item--filled.tab-item--normal:hover { color: var(--text-body); }
/* R9: DS models only active|Normal, focus ring added consumer-side for keyboard a11y */
.tab-item:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* input box/filled — mirror of src/components/Input/Input.vue (feature=no, per catalog search-field) */
.tvu-input-wrap { position: relative; display: block; width: 100%; }
.tvu-input {
  display: block;
  width: 100%;
  padding: var(--sp-xs) var(--sp-s);
  background: transparent;
  border: 1px solid var(--input-line-border);
  border-radius: var(--r-s);
  color: var(--text-body);
  font-size: 14px;
  font-family: var(--font-family-base);
  outline: none;
  transition: border-color 0.15s;
  box-sizing: border-box;
}
.tvu-input::placeholder { color: var(--text-placeholder); }
.tvu-input--m { height: 32px; }
.tvu-input--filled { background: var(--input-filled-bg); border-color: transparent; }
.tvu-input--filled:hover:not(:disabled) { border-color: var(--brand); }
.tvu-input--filled:focus:not(:disabled) { border-color: var(--brand); }

/* Table — mirror of src/components/Table/Table.vue (CANONICAL-029 cell padding L0/R8/T8/B8) */
.tbl-wrap { position: relative; }
.tbl {
  width: 100%;
  border-collapse: collapse;
  font: var(--text-style-body);
  color: var(--text-body);
  background: var(--bg-layer2);
}
/* INFRA-F129 ①: neutralise the global `td { border-top: … --line-border }` base layer,
   which wins the border-collapse conflict against .tbl-body .tbl-row. Figma tbody
   cells have strokes: [] — that border is code-drawn, not design truth. */
.tbl td { border-top: 0; }
.tbl-head .tbl-cell {
  padding: var(--sp-xs) var(--sp-xs) var(--sp-xs) 0;
  font: var(--text-style-body);
  font-weight: 700;
  color: var(--text-tips);
  background: transparent;
  border-bottom: 1px solid var(--line-deep);
  white-space: nowrap;
}
.tbl-body .tbl-row { border-bottom: 1px solid var(--line-light); transition: background 0.12s; }
.tbl-body .tbl-row:last-child { border-bottom: none; }
.tbl-body .tbl-row:hover { background: var(--bg-layer3); }
.tbl-body .tbl-cell {
  padding: var(--sp-xs) var(--sp-xs) var(--sp-xs) 0;
  font: var(--text-style-body);
  color: var(--text-body);
  vertical-align: middle;
}
.tbl-cell__content { display: flex; align-items: center; gap: var(--sp-xxs); }
.tbl-cell--left .tbl-cell__content { justify-content: flex-start; }
.tbl-cell--right .tbl-cell__content { justify-content: flex-end; }
.tbl-empty { text-align: center; padding: var(--sp-m) var(--sp-xs); color: var(--text-tips); }
.tbl-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Tooltips — mirror of src/components/Tooltip/Tooltip.vue (theme=dark variant).
   v-show/hovered/focused state is replaced by :hover / :focus-within, and the box
   element is a <span> so it stays valid inside inline table-cell content. */
.tooltip-wrap { position: relative; display: inline-flex; isolation: isolate; min-width: 0; }
.tooltip-trigger { display: inline-flex; min-width: 0; }
.tooltip-box {
  /* R14: overlay, anchored to its trigger — no layout semantics. */
  position: absolute;
  z-index: var(--z-tooltip);
  display: none;
  white-space: nowrap;
  max-width: var(--tooltip-max-width);
  padding: var(--sp-xxs) var(--sp-xs);
  border-radius: var(--r-s);
  background: var(--tooltip-bg);
  border: 1px solid var(--tooltip-border);
  color: var(--tooltip-text);
  font: var(--text-style-tips);
  pointer-events: none;
  box-shadow: var(--shadow-l3);
}
.tooltip-box--dark { --tooltip-bg: var(--tooltip-bg-dark); --tooltip-text: var(--tooltip-text-dark); --tooltip-border: var(--tooltip-border-dark); }
.tooltip-box--top-start { bottom: calc(100% + 6px); left: 0; }
.tooltip-content { display: block; overflow: hidden; text-overflow: ellipsis; }
.tooltip-arrow {
  /* R14: overlay decoration pinned to the tooltip box edge. */
  position: absolute;
  width: 8.5px;
  height: 8.5px;
  background: var(--tooltip-bg);
  transform: rotate(45deg);
}
.tooltip-arrow--top-start { bottom: -5px; left: var(--sp-s); border-right: 1px solid var(--tooltip-border); border-bottom: 1px solid var(--tooltip-border); }
.tooltip-wrap.is-truncated:hover > .tooltip-box,
.tooltip-wrap.is-truncated:focus-within > .tooltip-box { display: block; }

/* Notification — mirror of src/components/Notification/Notification.vue
   form=pop confirm (Cancel+Confirm, no category icon) / form=slide (passive toast). */
.notif {
  display: grid;
  box-sizing: border-box;
  gap: var(--sp-xl);
  width: var(--notification-width-default);
  padding: var(--sp-m) var(--sp-l);
  border-radius: 6px;
  border: 1.2px solid var(--line-light);
  box-shadow: var(--shadow-l3);
}
.notif--dark { background: var(--notification-bg-dark); border-color: var(--line-light); color: var(--text-body); }
.notif--slide { width: var(--notification-width-side-pop); gap: var(--sp-s); }
.notif__main { display: flex; align-items: flex-start; gap: var(--sp-m); }
.notif__icon { flex: 0 0 auto; width: 24px; height: 24px; }
.notif__body { flex: 1 1 auto; min-width: 0; display: grid; gap: var(--sp-s); }
.notif__header { display: flex; align-items: center; gap: var(--sp-m); }
.notif__title { flex: 1 1 auto; min-width: 0; margin: 0; font: var(--text-style-pop-title); }
.notif__desc { margin: 0; font: var(--text-style-body); color: var(--text-tips); }
.notif--pop-confirm .notif__desc { color: var(--text-body); }
.notif__close {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--icon-default);
  cursor: pointer;
}
.notif__close:hover { color: var(--icon-active); }
.notif__close:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.notif__actions { display: flex; justify-content: flex-end; gap: var(--sp-m); }

/* PopupBox overlay — mirror of src/components/PopupBox/PopupBox.vue .popup-overlay
   (Figma effect style "Mask blur8 #000-60%"). R14: modal backdrop, no layout role. */
.popup-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--mask-overlay);
  backdrop-filter: blur(var(--mask-overlay-blur));
}
.popup-overlay[hidden] { display: none; }

/* ── BLOCK 4 · page composition (consumer side) ───────────────────────────── */
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg-layer1);
  color: var(--text-body);
  -webkit-font-smoothing: antialiased;
}
.page {
  width: 100%;
  max-width: var(--container-page);
  margin: 0 auto;
  padding: var(--sp-l) var(--sp-l) var(--sp-xxl);
  display: flex;
  flex-direction: column;
  gap: var(--sp-m);
}
.topbar-user {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-xs);
  height: var(--control-height-xxs);
  padding: 0 var(--sp-s);
  border: 0;
  border-radius: var(--r-s);
  background: transparent;
  color: var(--text-2);
  font: var(--text-style-body);
  cursor: pointer;
}
.topbar-user:hover { background: var(--bg-layer3); color: var(--text-heading); }
.topbar-user:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* page-level strip: filters + search live BELOW the top bar, never inside its slots */
.toolbar { display: flex; align-items: center; gap: var(--sp-m); flex-wrap: wrap; }
.filters { display: flex; align-items: center; gap: var(--sp-xs); flex-wrap: wrap; }
.toolbar-side { display: flex; align-items: center; gap: var(--sp-m); margin-left: auto; }
.search { flex: 0 1 240px; min-width: 180px; } /* content width; DS has no search-field width token */
.toolbar-meta { font: var(--text-style-tips); color: var(--text-tips); white-space: nowrap; }

.panel {
  background: var(--bg-layer2);
  border: 1px solid var(--line-deep);
  border-radius: var(--r-m);
  padding: var(--sp-xs) var(--sp-m) var(--sp-s);
  overflow-x: auto;
}
.tbl { min-width: 980px; } /* content width — 6-column operator grid; scrolls inside .panel */

.cell-stack { display: flex; flex-direction: column; gap: var(--sp-xxs); min-width: 0; }
.cell-strong { font: var(--text-style-body); color: var(--text-body); }
.cell-meta { font: var(--text-style-tips); color: var(--text-tips); }
.cell-meta--alarm { color: var(--orange); display: inline-flex; align-items: center; gap: var(--sp-xxs); }
.cell-none { color: var(--text-placeholder); }
.mono-num { font-variant-numeric: tabular-nums; }

/* R23 single-line tail-ellipsis; width is constrained by the parent cell (min-width:0) */
.clip {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.clip:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.col-source .cell-stack { max-width: 240px; }
.url-cell { display: flex; align-items: center; gap: var(--sp-xs); min-width: 0; }
.url-wrap { max-width: 240px; }
.url-text { font: var(--text-style-body); color: var(--text-2); }
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  border-radius: var(--r-s);
  background: transparent;
  color: var(--icon-default);
  cursor: pointer;
}
.icon-btn:hover { color: var(--icon-active); background: var(--bg-layer4); }
.icon-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.row-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-xs); }
.trend { display: inline-flex; align-items: center; gap: var(--sp-xxs); }
.trend--diverging { color: var(--orange); }

/* Transient notification layer. R14: fixed overlay stack, no layout role.
   DS has no --z-toast (see §Z-Index: no measured consumer) → reuse the nearest
   existing overlay tier. Candidate for a --z-toast token. */
.toast-layer {
  position: fixed;
  top: var(--sp-l);
  right: var(--sp-l);
  z-index: var(--z-modal);
  display: flex;
  flex-direction: column;
  gap: var(--sp-s);
}
.toast-enter { animation: toast-in 0.16s ease-out; }
@keyframes toast-in { from { opacity: 0; transform: translateX(var(--sp-s)); } to { opacity: 1; transform: none; } }

@media (max-width: 1100px) {
  .topbar { gap: var(--sp-l); }
  .topbar-menu { gap: var(--sp-m); }
  .toolbar-side { margin-left: 0; width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .btn, .tab-item, .tbl-body .tbl-row, .tvu-input { transition: none; }
  .toast-enter { animation: none; }
}
</style>
</head>
<body>

<header class="topbar topbar--after-login" data-figma-component="TopBar" data-figma-tag="After Login">
  <div class="topbar-brand">
    <span class="icon icon--24" aria-hidden="true" data-icon="brand/logo-tvu"></span>
    <span class="topbar-title">TVU Grid</span>
  </div>
  <nav class="topbar-menu" aria-label="Product sections">
    <ul class="menu-list menu-list--horizontal" role="menu" data-figma-component="MenuList">
      <li class="menu-list__item is-active" role="menuitem" aria-current="true" tabindex="0"><span class="menu-list__label">Sources</span></li>
      <li class="menu-list__item" role="menuitem" tabindex="0"><span class="menu-list__label">Receivers</span></li>
      <li class="menu-list__item" role="menuitem" tabindex="0"><span class="menu-list__label">Routing</span></li>
      <li class="menu-list__item" role="menuitem" tabindex="0"><span class="menu-list__label">Alerts</span></li>
    </ul>
  </nav>
  <div class="topbar-right">
    <button class="topbar-user" type="button">
      <span class="icon icon--16" aria-hidden="true" data-icon="user/user"></span>
      <span>NOC Operator</span>
    </button>
  </div>
</header>

<main class="page">
  <h1 class="tbl-sr-only">Sources</h1>

  <section class="toolbar" aria-label="Source list controls">
    <div class="filters" role="tablist" aria-label="Filter sources by status" id="filters">
      <button class="tab-item tab-item--filled tab-item--active-green" role="tab" aria-selected="true" tabindex="0" data-filter="all">All<span class="mono-num" data-count="all">7</span></button>
      <button class="tab-item tab-item--filled tab-item--normal" role="tab" aria-selected="false" tabindex="-1" data-filter="live">Live<span class="mono-num" data-count="live">3</span></button>
      <button class="tab-item tab-item--filled tab-item--normal" role="tab" aria-selected="false" tabindex="-1" data-filter="alarm">Alarm<span class="mono-num" data-count="alarm">2</span></button>
      <button class="tab-item tab-item--filled tab-item--normal" role="tab" aria-selected="false" tabindex="-1" data-filter="offline">Offline<span class="mono-num" data-count="offline">2</span></button>
    </div>
    <div class="toolbar-side">
      <div class="search">
        <div class="tvu-input-wrap">
          <input id="search" class="tvu-input tvu-input--m tvu-input--filled" type="search" placeholder="Search sources" aria-label="Search sources" autocomplete="off" />
        </div>
      </div>
      <span class="toolbar-meta" id="updated-at"></span>
    </div>
  </section>

  <section class="panel" aria-label="Sources">
    <div class="tbl-wrap">
      <table class="tbl" data-figma-component="Table" data-figma-align="Left" data-figma-type="Tbody">
        <thead class="tbl-head">
          <tr>
            <th scope="col" class="tbl-cell tbl-cell--left" style="width: 22%"><span class="tbl-cell__content"><span>Source</span></span></th>
            <th scope="col" class="tbl-cell tbl-cell--left" style="width: 26%"><span class="tbl-cell__content"><span>Source address</span></span></th>
            <th scope="col" class="tbl-cell tbl-cell--left" style="width: 16%"><span class="tbl-cell__content"><span>Receiver</span></span></th>
            <th scope="col" class="tbl-cell tbl-cell--left" style="width: 18%"><span class="tbl-cell__content"><span>Status</span></span></th>
            <th scope="col" class="tbl-cell tbl-cell--right" style="width: 8%"><span class="tbl-cell__content"><span>Bitrate</span></span></th>
            <th scope="col" class="tbl-cell tbl-cell--right" style="width: 10%"><span class="tbl-cell__content"><span>Actions</span></span></th>
          </tr>
        </thead>
        <tbody class="tbl-body" id="rows"></tbody>
      </table>
    </div>
  </section>
</main>

<div class="popup-overlay" id="overlay" hidden>
  <div class="notif notif--dark notif--pop-confirm notif--type-danger" role="dialog" aria-modal="true" aria-labelledby="dlg-title" aria-describedby="dlg-desc" tabindex="-1" data-figma-component="Notification" data-figma-form="pop confirm" data-figma-type="danger" data-figma-theme="dark">
    <div class="notif__main">
      <div class="notif__body">
        <div class="notif__header">
          <p class="notif__title" id="dlg-title"></p>
          <button class="notif__close" type="button" aria-label="Close" id="dlg-close">
            <span class="icon icon--12" aria-hidden="true" data-icon="action/close"></span>
          </button>
        </div>
        <p class="notif__desc" id="dlg-desc"></p>
      </div>
    </div>
    <div class="notif__actions">
      <button class="btn btn--m btn--radius-square btn--ghost-gray" type="button" id="dlg-cancel">Cancel</button>
      <button class="btn btn--m btn--radius-square btn--fill-red" type="button" id="dlg-confirm"></button>
    </div>
  </div>
</div>

<div class="toast-layer" id="toasts" role="region" aria-live="polite" aria-label="Notifications"></div>

<script>
(function () {
  'use strict';

  /* ---- Library icon assets — copied verbatim from src/icons (R1/R15: never hand-drawn) ---- */
  var ICONS = {
    /* brand/logo-tvu = LogoTVU */
    'brand/logo-tvu': '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.9933 8.68971V8.6898V8.6899V8.69001C15.9962 8.96317 16 9.31582 16 9.81499V13.9033C16 13.9033 16 16 13.6733 15.9997H7.99586L7.98791 15.9998L7.97996 16H7.97102H7.93922C7.93922 16 7.94419 16 7.9538 15.9997C3.55876 15.9857 0 12.4098 0 8.00017C0 3.5819 3.573 0 7.97996 0C12.1057 0 15.5005 3.13931 15.9165 7.16512L15.9182 7.16545L15.9185 7.18106C15.946 7.45033 15.99 7.97375 15.99 8.25C15.99 8.37606 15.9915 8.51693 15.9933 8.68953L15.9933 8.68971ZM1.19653 7.97028C1.19653 11.7388 4.24392 14.7937 8.00305 14.7937C11.7622 14.7937 14.8096 11.7388 14.8096 7.97028C14.8096 4.20178 11.7622 1.14681 8.00305 1.14681C4.24392 1.14681 1.19653 4.20178 1.19653 7.97028ZM13.4204 15.2121V13.212L15.0122 14.2386L13.4204 15.2121ZM12.6575 12.0533C12.7649 12.0533 12.8543 12.0186 12.926 11.9492C12.9973 11.8798 13.0333 11.7951 13.033 11.6953C13.033 11.6246 13.0119 11.5608 12.9701 11.5041C12.9273 11.448 12.8468 11.39 12.7279 11.3296C12.6304 11.2805 12.5665 11.2378 12.5359 11.2011C12.5057 11.1651 12.4904 11.1274 12.4904 11.088C12.4904 11.0433 12.5087 11.0042 12.5457 10.9705C12.5828 10.9368 12.627 10.9201 12.6789 10.9201C12.7605 10.9201 12.8441 10.9605 12.9293 11.0419L13.032 10.9378C12.9161 10.8281 12.8013 10.7733 12.6871 10.7733C12.5889 10.7733 12.5077 10.804 12.4435 10.8651C12.3793 10.9265 12.347 11.0032 12.347 11.0957C12.347 11.1667 12.367 11.2298 12.4075 11.2849C12.4476 11.3399 12.5237 11.396 12.6358 11.4527C12.7401 11.5051 12.8074 11.5481 12.8369 11.5825C12.8665 11.6175 12.8814 11.6576 12.8814 11.7023C12.8814 11.7567 12.859 11.8041 12.8142 11.8444C12.7693 11.8848 12.7146 11.9048 12.6507 11.9048C12.5593 11.9048 12.473 11.8595 12.3915 11.7694L12.2913 11.8812C12.3337 11.9349 12.3874 11.9769 12.4527 12.0076C12.5175 12.038 12.5858 12.0533 12.6575 12.0533ZM11.9733 12.0533L11.3829 11.4987V12.0533H11.2319V10.3467H11.3829V11.3188L11.9264 10.8219H12.148L11.5037 11.4093L12.1856 12.0533H11.9733ZM10.6556 10.9878C10.7049 10.916 10.7569 10.8623 10.8117 10.8267C10.8665 10.7911 10.9234 10.7733 10.9826 10.7733C11.0274 10.7733 11.075 10.7874 11.126 10.8157L11.0416 10.9512C11.0078 10.9365 10.9792 10.9293 10.9561 10.9293C10.902 10.9293 10.85 10.9512 10.8 10.9953C10.7501 11.0391 10.7118 11.1075 10.6856 11.1999C10.6656 11.271 10.6556 11.4147 10.6556 11.6312V12.0533H10.4902V10.8055H10.6556V10.9878ZM9.64269 10.7733C9.83034 10.7733 9.98595 10.8411 10.1095 10.9769C10.2217 11.1007 10.2778 11.2472 10.2781 11.4167C10.2781 11.5868 10.2187 11.7353 10.1001 11.8625C9.9816 11.9896 9.82934 12.0533 9.64302 12.0533C9.45603 12.0533 9.3031 11.9896 9.18456 11.8625C9.06569 11.7353 9.00659 11.5868 9.00659 11.4167C9.00659 11.2482 9.06269 11.102 9.17488 10.9782C9.29809 10.8417 9.45403 10.7733 9.64269 10.7733ZM9.88152 11.8421C9.95431 11.8007 10.0121 11.742 10.0548 11.6659C10.0976 11.5899 10.1189 11.5081 10.1186 11.4197C10.1186 11.2832 10.0718 11.1667 9.97768 11.0706C9.88352 10.9742 9.77166 10.9262 9.6421 10.9262C9.51155 10.9262 9.39969 10.9745 9.30586 11.0706C9.21203 11.1667 9.16528 11.2832 9.16528 11.4197C9.16528 11.5078 9.18665 11.5899 9.22939 11.6659C9.27213 11.742 9.3299 11.8007 9.40269 11.8421C9.47548 11.8835 9.55529 11.9042 9.6421 11.9042C9.72892 11.9042 9.80872 11.8835 9.88152 11.8421ZM8.33623 12.0533H8.36592L8.90069 10.7733H8.73604L8.35108 11.7025L7.95565 10.7733H7.92698L7.53391 11.7025L7.15637 10.7733H6.99341L7.5194 12.0533H7.5491L7.9425 11.1368L8.33623 12.0533ZM6.88747 10.9474H6.63214V12.0533H6.4714V10.9474H6.25171V10.8089H6.4714V10.3467H6.63214V10.8089H6.88747V10.9474ZM5.83626 11.7904C5.79475 11.8261 5.74412 11.8548 5.68505 11.8761C5.62564 11.8978 5.56454 11.9085 5.5021 11.9085C5.37214 11.9085 5.26278 11.8635 5.17434 11.773C5.08591 11.6826 5.04034 11.5668 5.0373 11.4253H6.14579C6.1441 11.2592 6.09887 11.1204 6.00976 11.0092C5.8842 10.8517 5.71644 10.7733 5.50648 10.7733C5.30261 10.7733 5.13958 10.8501 5.01806 11.0039C4.9222 11.1247 4.87427 11.2622 4.87427 11.4167C4.87427 11.5808 4.93097 11.728 5.04439 11.8581C5.1578 11.9883 5.31476 12.0533 5.51594 12.0533C5.60674 12.0533 5.68775 12.0396 5.75964 12.0126C5.83154 11.9853 5.89601 11.9456 5.95339 11.8935C6.01077 11.8414 6.06141 11.7727 6.10529 11.6876L5.97162 11.6182C5.92301 11.697 5.87778 11.7547 5.83626 11.7904ZM5.19687 11.0383C5.28395 10.9615 5.38758 10.9232 5.50875 10.9232C5.582 10.9232 5.65187 10.9385 5.71837 10.9689C5.78486 10.9996 5.8382 11.0396 5.8787 11.0897C5.91921 11.1397 5.94992 11.2065 5.97119 11.2899H5.05273C5.08548 11.1781 5.13341 11.094 5.19687 11.0383ZM4.45639 10.8445C4.38617 10.7969 4.30564 10.7733 4.21478 10.7733C4.1256 10.7733 4.04273 10.7945 3.96686 10.8369C3.89098 10.8793 3.82176 10.9433 3.75919 11.0291V10.8055H3.60278V12.053H3.75919V11.5954C3.75919 11.4309 3.76652 11.3181 3.78149 11.2562C3.80545 11.1615 3.85471 11.0818 3.92958 11.0178C4.00446 10.9535 4.08899 10.9214 4.1835 10.9214C4.26603 10.9214 4.33326 10.9423 4.38451 10.984C4.43576 11.0257 4.4707 11.0876 4.48867 11.1704C4.50032 11.2186 4.50597 11.3143 4.50597 11.4583V12.0533H4.66239V11.4114C4.66239 11.2418 4.64575 11.1167 4.61213 11.0366C4.57852 10.9556 4.52661 10.8917 4.45639 10.8445ZM12.8146 8.39867V5.86667H13.669V8.41467C13.669 8.90067 13.6164 9.27267 13.3229 9.53167C13.0294 9.79067 12.5968 9.92 12.0253 9.92C11.4538 9.92 11.022 9.79034 10.7291 9.53167C10.4366 9.273 10.3843 8.90134 10.3843 8.41734V5.86667H11.2394V8.39867C11.2394 8.67167 11.2963 8.875 11.4098 9.00867C11.5233 9.14233 11.7705 9.20934 12.0257 9.20934C12.2772 9.20934 12.524 9.14534 12.6402 9.01667C12.7564 8.888 12.8146 8.682 12.8146 8.39867ZM9.02194 5.86667L8.01441 8.853L7.00721 5.86667H6.03979L7.53984 9.92H8.46061L9.96033 5.86667H9.02194ZM3.48276 6.554H2.2251V5.86667H5.61583V6.554H4.35817V9.92H3.48276V6.554Z" fill="#56AF31"/></svg>',
    /* user/user = IconUserUser */
    'user/user': '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.7 4.7C11.7 6.74345 10.0434 8.4 7.99999 8.4C5.95653 8.4 4.29999 6.74345 4.29999 4.7C4.29999 2.65655 5.95653 1 7.99999 1C10.0434 1 11.7 2.65655 11.7 4.7ZM10.5 4.69922C10.5 3.31851 9.38071 2.19922 8 2.19922C6.61929 2.19922 5.5 3.31851 5.5 4.69922C5.5 6.07993 6.61929 7.19922 8 7.19922C9.38071 7.19922 10.5 6.07993 10.5 4.69922ZM8.00001 9.39844C6.24958 9.39844 4.57085 10.0938 3.33311 11.3315C2.52087 12.1438 1.94222 13.1459 1.64035 14.2335C1.55173 14.5528 1.73874 14.8835 2.05804 14.9721C2.37734 15.0607 2.70802 14.8737 2.79664 14.5544C3.04365 13.6645 3.5171 12.8446 4.18164 12.1801C5.19433 11.1674 6.56784 10.5984 8.00001 10.5984C9.43218 10.5984 10.8057 11.1674 11.8184 12.1801C12.4829 12.8446 12.9564 13.6645 13.2034 14.5544C13.292 14.8737 13.6227 15.0607 13.942 14.9721C14.2613 14.8835 14.4483 14.5528 14.3597 14.2335C14.0578 13.1459 13.4791 12.1438 12.6669 11.3315C11.4292 10.0938 9.75044 9.39844 8.00001 9.39844Z" fill="currentColor"/></svg>',
    /* edit/copy = IconEditCopy */
    'edit/copy': '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2.2 1C1.53726 1 1 1.53726 1 2.2V11.4C1 12.0627 1.53726 12.6 2.2 12.6H3.40002V13.8004C3.40002 14.4631 3.93728 15.0004 4.60002 15.0004H13.8C14.4628 15.0004 15 14.4631 15 13.8004V4.60039C15 3.93765 14.4628 3.40039 13.8 3.40039H12.6V2.2C12.6 1.53726 12.0627 1 11.4 1H2.2ZM11.4 3.40039H4.60002C3.93728 3.40039 3.40002 3.93765 3.40002 4.60039V11.3992H2.60001C2.3791 11.3992 2.20001 11.2201 2.20001 10.9992V2.59922C2.20001 2.3783 2.3791 2.19922 2.60001 2.19922H11C11.2209 2.19922 11.4 2.3783 11.4 2.59922V3.40039ZM4.60004 4.99961C4.60004 4.77869 4.77912 4.59961 5.00004 4.59961H13.4C13.621 4.59961 13.8 4.7787 13.8 4.99961V13.3996C13.8 13.6205 13.621 13.7996 13.4 13.7996H5.00004C4.77912 13.7996 4.60004 13.6205 4.60004 13.3996V4.99961Z" fill="currentColor"/></svg>',
    /* action/close = IconClose */
    'action/close': '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12.5758 13.4247C12.8101 13.659 13.19 13.659 13.4243 13.4247C13.6586 13.1903 13.6586 12.8104 13.4243 12.5761L8.84898 8.00082L13.4248 3.42543C13.6591 3.19113 13.6591 2.81123 13.4248 2.5769C13.1905 2.34258 12.8106 2.34256 12.5763 2.57687L8.00045 7.15229L3.42429 2.57613C3.18997 2.34181 2.81007 2.34181 2.57576 2.57613C2.34145 2.81044 2.34145 3.19034 2.57576 3.42465L7.15188 8.00078L2.57596 12.5763C2.34163 12.8106 2.34161 13.1905 2.57592 13.4248C2.81022 13.6592 3.19012 13.6592 3.42445 13.4249L8.00041 8.84931L12.5758 13.4247Z" fill="currentColor"/></svg>',
    /* status/warning = IconStatusWarning */
    'status/warning': '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 1C4.13438 1 1 4.13438 1 8C1 11.8656 4.13438 15 8 15C11.8656 15 15 11.8656 15 8C15 4.13438 11.8656 1 8 1ZM7.9999 4C8.33127 4 8.5999 4.26863 8.5999 4.6V9C8.5999 9.33137 8.33127 9.6 7.9999 9.6C7.66853 9.6 7.3999 9.33137 7.3999 9V4.6C7.3999 4.26863 7.66853 4 7.9999 4ZM7.9999 12C7.66853 12 7.3999 11.7314 7.3999 11.4C7.3999 11.0686 7.66853 10.8 7.9999 10.8C8.33127 10.8 8.5999 11.0686 8.5999 11.4C8.5999 11.7314 8.33127 12 7.9999 12Z" fill="currentColor"/></svg>',
    /* navigation/arrow-down = IconArrowDown */
    'navigation/arrow-down': '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.26364 8.81581C3.02933 8.58149 2.64943 8.58149 2.41512 8.81581C2.1808 9.05012 2.1808 9.43002 2.41512 9.66434L7.56068 14.8099C7.56594 14.8156 7.57133 14.8212 7.57685 14.8267C7.81116 15.061 8.19106 15.061 8.42538 14.8267L13.5873 9.66482C13.8216 9.43051 13.8216 9.05061 13.5873 8.81629C13.3529 8.58198 12.973 8.58198 12.7387 8.81629L8.60094 12.9541L8.60094 1.6C8.60094 1.26863 8.33231 1 8.00094 1C7.66957 1 7.40094 1.26863 7.40094 1.6L7.40094 12.9531L3.26364 8.81581Z" fill="currentColor"/></svg>',
    /* message/success-2 — baked semantic colour (published asset) */
    'message/success-2': '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15ZM5.22424 7.37564L7.03029 9.18159C7.10839 9.2597 7.23502 9.25969 7.31313 9.18159L10.6017 5.89303C10.836 5.65871 11.2159 5.65871 11.4502 5.89303C11.6846 6.12735 11.6846 6.50725 11.4502 6.74156L7.80811 10.3837C7.45664 10.7351 6.88681 10.7351 6.53533 10.3837L4.37573 8.22419C4.14141 7.98988 4.1414 7.60998 4.37571 7.37566C4.61002 7.14134 4.98991 7.14133 5.22424 7.37564Z" fill="#2FB54E"/></svg>',
    /* indicator/srt-caller */
    'indicator/srt-caller': '<svg width="43" height="10" viewBox="0 0 43 10" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_2427_15473)"><path d="M13.132 0.00066545H23.4424C23.4424 0.00066545 25.6401 -0.120614 25.6401 2.9114C25.6401 5.94341 23.4424 5.70085 23.4424 5.70085H21.0004L25.518 9.94567H23.5644L17.7039 4.36676H23.1982C23.1982 4.36676 24.1749 4.31257 24.1749 2.9114C24.1749 1.51022 23.1982 1.45603 23.1982 1.45603H14.6966V9.94567H13.132V0.00066545ZM37.3723 1.45806V0.110059H25.7621C25.7621 0.110059 26.3726 0.607069 26.4705 1.49422H30.8595V9.94567H32.3918V1.45806H37.3723ZM12.3648 3.16951C12.2946 1.38483 11.6684 0.365016 10.4487 0.146226V0.148035H1.95065C0.765676 0.365016 0.139462 1.24018 0 2.73373V2.98869C0.0692755 3.71648 0.278925 4.33669 0.592488 4.81043C0.905139 5.28327 1.35816 5.61236 1.95065 5.72085H9.64752C9.99572 5.72085 10.2391 5.86641 10.4487 6.12136C10.6575 6.37632 10.7969 6.74067 10.8662 7.17825C10.7969 7.68815 10.693 8.01543 10.4834 8.23422C10.2756 8.45301 10.0313 8.56241 9.68307 8.56241H2.71633C2.01993 8.56241 1.63709 8.01634 1.56781 6.88622H0C0.104825 8.70706 0.731039 9.69162 1.95065 9.9086H10.4834C11.6337 9.69071 12.2599 8.81646 12.3994 7.3229V7.06795C12.3301 6.33925 12.1205 5.71995 11.8069 5.2462C11.4943 4.77246 11.0412 4.44427 10.4487 4.33578L2.78652 4.37195C2.47295 4.37195 2.19494 4.26255 1.98529 4.0076C1.77655 3.78881 1.63709 3.42536 1.56781 2.98778C1.63709 2.47788 1.741 2.07736 1.95065 1.85857C2.12384 1.60272 2.40368 1.49423 2.71633 1.49423H9.68307C10.3795 1.49423 10.7623 2.0403 10.8325 3.16951H12.3648ZM35.1964 8.33603C35.1873 8.2749 35.1668 8.21944 35.1349 8.16963C35.103 8.11756 35.0631 8.07229 35.0152 8.0338C34.9674 7.99531 34.9127 7.96588 34.8511 7.94551C34.7919 7.92287 34.7292 7.91155 34.6631 7.91155C34.5423 7.91155 34.4398 7.93532 34.3554 7.98286C34.2711 8.02814 34.2027 8.0904 34.1503 8.16963C34.0979 8.24661 34.0592 8.3349 34.0341 8.43451C34.0113 8.53412 33.9999 8.63713 33.9999 8.74353C33.9999 8.84541 34.0113 8.94502 34.0341 9.04237C34.0592 9.13745 34.0979 9.22348 34.1503 9.30045C34.2027 9.37743 34.2711 9.43968 34.3554 9.48722C34.4398 9.5325 34.5423 9.55514 34.6631 9.55514C34.8272 9.55514 34.9548 9.50534 35.046 9.40572C35.1395 9.30611 35.1964 9.17481 35.2169 9.0118H35.7366C35.7229 9.16349 35.6876 9.30045 35.6306 9.4227C35.5736 9.54495 35.4984 9.64909 35.405 9.73512C35.3115 9.82115 35.2021 9.8868 35.0768 9.93208C34.9514 9.97736 34.8135 10 34.6631 10C34.4762 10 34.3076 9.9683 34.1572 9.90491C34.009 9.83926 33.8837 9.74984 33.7811 9.63664C33.6785 9.52345 33.5999 9.39101 33.5452 9.23933C33.4905 9.08538 33.4632 8.92012 33.4632 8.74353C33.4632 8.56242 33.4905 8.39489 33.5452 8.24095C33.5999 8.08474 33.6785 7.9489 33.7811 7.83344C33.8837 7.71798 34.009 7.62743 34.1572 7.56178C34.3076 7.49612 34.4762 7.4633 34.6631 7.4633C34.7976 7.4633 34.9241 7.48254 35.0426 7.52102C35.1634 7.55951 35.2705 7.61611 35.3639 7.69082C35.4597 7.76326 35.5383 7.85382 35.5998 7.96249C35.6614 8.07115 35.7001 8.19567 35.7161 8.33603H35.1964ZM38.0286 7.52103H38.514V9.94567H38.0286V7.52103ZM39.3954 7.52103H38.91V9.94567H39.3954V7.52103ZM40.9674 8.87936C40.9446 8.75711 40.9035 8.66429 40.8443 8.6009C40.7873 8.53751 40.6996 8.50582 40.581 8.50582C40.5035 8.50582 40.4386 8.5194 40.3862 8.54657C40.336 8.57147 40.295 8.60317 40.2631 8.64165C40.2335 8.68014 40.2118 8.72089 40.1981 8.76391C40.1868 8.80692 40.1799 8.84541 40.1776 8.87936H40.9674ZM40.1776 9.18499C40.1845 9.3412 40.2244 9.4544 40.2973 9.52458C40.3702 9.59476 40.4751 9.62985 40.6118 9.62985C40.7098 9.62985 40.7941 9.60608 40.8648 9.55854C40.9354 9.50873 40.9787 9.45666 40.9947 9.40233H41.422C41.3537 9.61287 41.2488 9.76342 41.1075 9.85397C40.9662 9.94453 40.7953 9.98981 40.5947 9.98981C40.4557 9.98981 40.3303 9.9683 40.2187 9.92529C40.107 9.88001 40.0124 9.81662 39.9349 9.73512C39.8574 9.65362 39.797 9.55627 39.7537 9.44308C39.7127 9.32988 39.6922 9.20537 39.6922 9.06953C39.6922 8.93823 39.7138 8.81598 39.7571 8.70278C39.8004 8.58959 39.862 8.49224 39.9417 8.41074C40.0215 8.32697 40.1161 8.26132 40.2255 8.21378C40.3372 8.16623 40.4602 8.14246 40.5947 8.14246C40.7451 8.14246 40.8762 8.1719 40.9879 8.23076C41.0995 8.28735 41.1907 8.36433 41.2614 8.46167C41.3343 8.55902 41.3867 8.66995 41.4186 8.79447C41.4505 8.91898 41.4619 9.04916 41.4528 9.18499H40.1776ZM41.7407 8.19001H42.2022V8.51601H42.209C42.2318 8.46167 42.2626 8.41187 42.3013 8.36659C42.3401 8.31905 42.3845 8.27943 42.4347 8.24774C42.4848 8.21378 42.5384 8.18774 42.5954 8.16963C42.6523 8.15152 42.7116 8.14246 42.7731 8.14246C42.805 8.14246 42.8404 8.14812 42.8791 8.15944V8.6077C42.8563 8.60317 42.829 8.59977 42.7971 8.59751C42.7651 8.59298 42.7344 8.59072 42.7047 8.59072C42.6159 8.59072 42.5406 8.60543 42.4791 8.63486C42.4176 8.66429 42.3674 8.70504 42.3287 8.75711C42.2922 8.80692 42.266 8.86578 42.2501 8.9337C42.2341 9.00162 42.2261 9.07519 42.2261 9.15443V9.94566H41.7407V8.19001ZM36.1168 8.44809C36.0666 8.5228 36.0382 8.61675 36.0313 8.72995H36.5168C36.5259 8.63486 36.5578 8.56695 36.6125 8.5262C36.6672 8.48545 36.7424 8.46507 36.8381 8.46507C36.8814 8.46507 36.9213 8.46847 36.9578 8.47526C36.9965 8.47979 37.0296 8.49111 37.0569 8.50922C37.0865 8.52506 37.1093 8.54883 37.1253 8.58053C37.1435 8.60996 37.1526 8.65071 37.1526 8.70278C37.1549 8.75259 37.1401 8.79107 37.1082 8.81824C37.0763 8.84314 37.033 8.86238 36.9783 8.87597C36.9236 8.88955 36.8609 8.89974 36.7903 8.90653C36.7196 8.91332 36.6478 8.92238 36.5749 8.9337C36.5019 8.94502 36.429 8.96087 36.3561 8.98124C36.2854 8.99935 36.2216 9.02765 36.1646 9.06614C36.1099 9.10462 36.0644 9.15669 36.0279 9.22235C35.9937 9.28574 35.9766 9.36724 35.9766 9.46685C35.9766 9.5574 35.9914 9.63551 36.0211 9.70116C36.053 9.76681 36.0963 9.82115 36.151 9.86416C36.2057 9.90718 36.2695 9.93887 36.3424 9.95925C36.4153 9.97962 36.494 9.98981 36.5783 9.98981C36.6877 9.98981 36.7948 9.97396 36.8997 9.94227C37.0045 9.91057 37.0957 9.85511 37.1731 9.77587C37.1754 9.8053 37.1788 9.83473 37.1834 9.86416C37.1902 9.89133 37.1982 9.9185 37.2073 9.94566H37.6996C37.6768 9.90944 37.6609 9.85511 37.6518 9.78266C37.6426 9.71022 37.6381 9.63438 37.6381 9.55514V8.64165C37.6381 8.53525 37.6142 8.45035 37.5663 8.38697C37.5184 8.32131 37.4569 8.27037 37.3817 8.23415C37.3065 8.19793 37.2233 8.17416 37.1321 8.16284C37.041 8.14926 36.9509 8.14246 36.8621 8.14246C36.764 8.14246 36.666 8.15265 36.568 8.17303C36.4723 8.19114 36.3857 8.22283 36.3082 8.26811C36.2307 8.31339 36.1669 8.37338 36.1168 8.44809ZM37.074 9.13066C37.1059 9.11934 37.1321 9.10462 37.1526 9.08651V9.26649C37.1526 9.29366 37.1492 9.32988 37.1424 9.37516C37.1378 9.42044 37.123 9.46572 37.0979 9.51099C37.0729 9.55401 37.0341 9.59136 36.9817 9.62306C36.9293 9.65475 36.8552 9.6706 36.7595 9.6706C36.7207 9.6706 36.6831 9.6672 36.6467 9.66041C36.6102 9.65362 36.5783 9.6423 36.551 9.62645C36.5236 9.60834 36.5019 9.58457 36.486 9.55514C36.47 9.52571 36.4621 9.48949 36.4621 9.44647C36.4621 9.40119 36.47 9.36384 36.486 9.33441C36.5019 9.30498 36.5225 9.28121 36.5475 9.2631C36.5749 9.24272 36.6057 9.22687 36.6398 9.21555C36.6763 9.20423 36.7128 9.19518 36.7492 9.18839C36.788 9.1816 36.8267 9.17594 36.8655 9.17141C36.9042 9.16688 36.9407 9.16122 36.9749 9.15443C37.0113 9.14764 37.0444 9.13971 37.074 9.13066Z" fill="#999999"/></g><defs><clipPath id="clip0_2427_15473"><rect width="43" height="10" fill="white"/></clipPath></defs></svg>',
    /* indicator/srt-listener */
    'indicator/srt-listener': '<svg width="47" height="10" viewBox="0 0 47 10" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_2427_15519)"><path d="M13.2928 0.00066613H23.7293C23.7293 0.00066613 25.9539 -0.120737 25.9539 2.91437C25.9539 5.94947 23.7293 5.70666 23.7293 5.70666H21.2575L25.8303 9.95581H23.8529L17.9206 4.37121H23.4821C23.4821 4.37121 24.4708 4.31697 24.4708 2.91437C24.4708 1.51176 23.4821 1.45752 23.4821 1.45752H14.8765V9.95581H13.2928V0.00066613ZM37.8298 1.45955V0.110172H26.0775C26.0775 0.110172 26.6955 0.607688 26.7946 1.49575H31.2373V9.9558H32.7883V1.45955H37.8298ZM12.5161 3.17274C12.4451 1.38624 11.8112 0.365389 10.5767 0.146376V0.148186H1.97453C0.775049 0.365389 0.14117 1.24144 0 2.73652V2.99174C0.0701235 3.72027 0.282339 4.34111 0.599741 4.81534C0.916219 5.28866 1.37479 5.61808 1.97453 5.72668H9.76562C10.1181 5.72668 10.3644 5.87239 10.5767 6.1276C10.788 6.38282 10.9291 6.74754 10.9992 7.18556C10.9291 7.69599 10.8239 8.02361 10.6117 8.24262C10.4013 8.46163 10.1541 8.57114 9.80161 8.57114H2.74958C2.04465 8.57114 1.65713 8.02451 1.58701 6.89324H0C0.106108 8.71594 0.739988 9.7015 1.97453 9.9187H10.6117C11.7761 9.70059 12.41 8.82545 12.5512 7.33037V7.07515C12.4811 6.34571 12.2688 5.72578 11.9514 5.25155C11.635 4.77733 11.1764 4.44881 10.5767 4.3402L2.82063 4.3764C2.50323 4.3764 2.22181 4.2669 2.00959 4.01168C1.7983 3.79267 1.65713 3.42886 1.58701 2.99083C1.65713 2.4804 1.76232 2.07948 1.97453 1.86047C2.14984 1.60435 2.4331 1.49575 2.74958 1.49575H9.80161C10.5065 1.49575 10.8941 2.04238 10.9651 3.17274H12.5161ZM33.8553 7.52869H34.3986V9.5071H35.6029V9.95581H33.8553V7.52869ZM35.8685 7.92641H36.3599V7.52869H35.8685V7.92641ZM36.3599 8.19836H35.8685V9.95581H36.3599V8.19836ZM39.5883 8.19836H39.2284V7.67147H38.737V8.19836H38.4394V8.5213H38.737V9.55809C38.737 9.64647 38.752 9.71786 38.782 9.77225C38.812 9.82664 38.8524 9.86856 38.9031 9.89802C38.9562 9.92748 39.0162 9.94674 39.0831 9.95581C39.1523 9.96714 39.225 9.97281 39.3011 9.97281C39.3495 9.97281 39.3991 9.97167 39.4499 9.96941C39.5006 9.96714 39.5468 9.96261 39.5883 9.95581V9.58188C39.5652 9.58642 39.541 9.58982 39.5156 9.59208C39.4903 9.59435 39.4637 9.59548 39.4361 9.59548C39.353 9.59548 39.2976 9.58188 39.2699 9.55469C39.2423 9.5275 39.2284 9.47311 39.2284 9.39152V8.5213H39.5883V8.19836ZM41.0264 8.88842C41.0033 8.76605 40.9618 8.67313 40.9018 8.60968C40.8441 8.54623 40.7553 8.5145 40.6353 8.5145C40.5569 8.5145 40.4912 8.5281 40.4381 8.55529C40.3873 8.58022 40.3458 8.61195 40.3135 8.65047C40.2835 8.689 40.2616 8.72979 40.2478 8.77285C40.2362 8.8159 40.2293 8.85443 40.227 8.88842H41.0264ZM40.227 9.19436C40.2339 9.35073 40.2743 9.46404 40.3481 9.53429C40.4219 9.60455 40.5281 9.63967 40.6665 9.63967C40.7657 9.63967 40.8511 9.61588 40.9226 9.56829C40.9941 9.51843 41.0379 9.46631 41.0541 9.41192H41.4866C41.4174 9.62268 41.3113 9.77338 41.1683 9.86403C41.0252 9.95468 40.8522 10 40.6492 10C40.5085 10 40.3816 9.97847 40.2685 9.93541C40.1555 9.89009 40.0597 9.82664 39.9813 9.74505C39.9029 9.66347 39.8417 9.56602 39.7979 9.45271C39.7564 9.3394 39.7356 9.21476 39.7356 9.07878C39.7356 8.94734 39.7575 8.82497 39.8014 8.71166C39.8452 8.59835 39.9075 8.5009 39.9882 8.41932C40.069 8.33547 40.1647 8.26975 40.2755 8.22216C40.3885 8.17457 40.5131 8.15077 40.6492 8.15077C40.8015 8.15077 40.9341 8.18023 41.0471 8.23915C41.1602 8.29581 41.2525 8.37286 41.324 8.47031C41.3978 8.56775 41.4509 8.6788 41.4832 8.80344C41.5155 8.92808 41.527 9.05839 41.5178 9.19436H40.227ZM42.2764 8.19836H41.8092V9.95581H42.3006V9.03459C42.3006 8.85556 42.3306 8.72752 42.3906 8.65047C42.4506 8.57115 42.5475 8.5315 42.6813 8.5315C42.799 8.5315 42.8809 8.56775 42.927 8.64027C42.9731 8.71053 42.9962 8.81817 42.9962 8.96321V9.95581H43.4876V8.87483C43.4876 8.76605 43.4772 8.66747 43.4565 8.57909C43.438 8.48844 43.4045 8.41252 43.3561 8.35133C43.3076 8.28788 43.2407 8.23915 43.1554 8.20516C43.0723 8.1689 42.9651 8.15077 42.8336 8.15077C42.7297 8.15077 42.6282 8.17457 42.529 8.22216C42.4298 8.26748 42.3491 8.34113 42.2868 8.44311H42.2764V8.19836ZM45.0648 8.88842C45.0417 8.76605 45.0002 8.67313 44.9402 8.60968C44.8825 8.54623 44.7937 8.5145 44.6737 8.5145C44.5953 8.5145 44.5296 8.5281 44.4765 8.55529C44.4257 8.58022 44.3842 8.61195 44.3519 8.65047C44.3219 8.689 44.3 8.72979 44.2862 8.77285C44.2746 8.8159 44.2677 8.85443 44.2654 8.88842H45.0648ZM44.2654 9.19436C44.2723 9.35073 44.3127 9.46404 44.3865 9.53429C44.4603 9.60455 44.5665 9.63967 44.7049 9.63967C44.8041 9.63967 44.8895 9.61588 44.961 9.56829C45.0325 9.51843 45.0763 9.46631 45.0925 9.41192H45.525C45.4558 9.62268 45.3497 9.77338 45.2067 9.86403C45.0636 9.95468 44.8906 10 44.6876 10C44.5469 10 44.42 9.97847 44.3069 9.93541C44.1939 9.89009 44.0981 9.82664 44.0197 9.74505C43.9413 9.66347 43.8801 9.56602 43.8363 9.45271C43.7948 9.3394 43.774 9.21476 43.774 9.07878C43.774 8.94734 43.7959 8.82497 43.8398 8.71166C43.8836 8.59835 43.9459 8.5009 44.0266 8.41932C44.1074 8.33547 44.2031 8.26975 44.3139 8.22216C44.4269 8.17457 44.5515 8.15077 44.6876 8.15077C44.8399 8.15077 44.9725 8.18023 45.0855 8.23915C45.1986 8.29581 45.2909 8.37286 45.3624 8.47031C45.4362 8.56775 45.4893 8.6788 45.5216 8.80344C45.5539 8.92808 45.5654 9.05839 45.5562 9.19436H44.2654ZM45.8476 8.19836H46.3148V8.5247H46.3217C46.3448 8.47031 46.376 8.42045 46.4152 8.37513C46.4544 8.32754 46.4994 8.28788 46.5501 8.25615C46.6009 8.22216 46.6551 8.1961 46.7128 8.17797C46.7705 8.15984 46.8304 8.15077 46.8927 8.15077C46.925 8.15077 46.9608 8.15644 47 8.16777V8.61648C46.9769 8.61195 46.9492 8.60855 46.9169 8.60628C46.8846 8.60175 46.8535 8.59948 46.8235 8.59948C46.7335 8.59948 46.6574 8.61421 46.5951 8.64367C46.5328 8.67313 46.4821 8.71393 46.4429 8.76605C46.4059 8.8159 46.3794 8.87483 46.3633 8.94281C46.3471 9.0108 46.339 9.08445 46.339 9.16377V9.95581H45.8476V8.19836ZM37.1275 9.38472C37.1275 9.43685 37.1379 9.48217 37.1587 9.5207C37.1817 9.55696 37.2106 9.58755 37.2452 9.61248C37.2798 9.63514 37.319 9.65214 37.3628 9.66347C37.409 9.6748 37.4563 9.68046 37.5047 9.68046C37.5393 9.68046 37.5751 9.67706 37.612 9.67027C37.6512 9.6612 37.6858 9.64874 37.7158 9.63287C37.7481 9.61474 37.7746 9.59208 37.7954 9.56489C37.8162 9.53543 37.8265 9.49917 37.8265 9.45611C37.8265 9.38359 37.7769 9.3292 37.6777 9.29294C37.5808 9.25668 37.4447 9.22042 37.2694 9.18416C37.1979 9.1683 37.1275 9.15017 37.0583 9.12978C36.9914 9.10711 36.9314 9.07878 36.8784 9.04479C36.8253 9.00853 36.7826 8.96434 36.7503 8.91222C36.718 8.85783 36.7019 8.79211 36.7019 8.71506C36.7019 8.60175 36.7238 8.50883 36.7676 8.43631C36.8138 8.3638 36.8737 8.30714 36.9476 8.26635C37.0214 8.22329 37.1044 8.19383 37.1967 8.17797C37.289 8.15984 37.3836 8.15077 37.4805 8.15077C37.5774 8.15077 37.6708 8.15984 37.7608 8.17797C37.8531 8.1961 37.935 8.22669 38.0065 8.26975C38.078 8.31281 38.1368 8.37059 38.183 8.44311C38.2314 8.51337 38.2603 8.60288 38.2695 8.71166H37.8023C37.7954 8.61874 37.7596 8.55642 37.695 8.5247C37.6304 8.4907 37.5543 8.47371 37.4666 8.47371C37.439 8.47371 37.409 8.47597 37.3767 8.48051C37.3444 8.48277 37.3144 8.48957 37.2867 8.5009C37.2613 8.51223 37.2394 8.52923 37.2209 8.55189C37.2025 8.57229 37.1933 8.60061 37.1933 8.63687C37.1933 8.67993 37.2094 8.71506 37.2417 8.74225C37.274 8.76945 37.3155 8.79211 37.3663 8.81024C37.4193 8.8261 37.4793 8.84083 37.5462 8.85443C37.6131 8.86803 37.6812 8.88276 37.7504 8.89862C37.8219 8.91448 37.8911 8.93375 37.958 8.95641C38.0272 8.97907 38.0884 9.00967 38.1414 9.04819C38.1945 9.08445 38.2372 9.13091 38.2695 9.18756C38.3018 9.24195 38.3179 9.30994 38.3179 9.39152C38.3179 9.5071 38.2937 9.60455 38.2453 9.68386C38.1991 9.76091 38.138 9.82324 38.0619 9.87083C37.9857 9.91842 37.8981 9.95128 37.7989 9.96941C37.702 9.9898 37.6028 10 37.5012 10C37.3974 10 37.2959 9.9898 37.1967 9.96941C37.0975 9.94901 37.0087 9.91502 36.9303 9.86743C36.8541 9.81984 36.7907 9.75751 36.7399 9.68046C36.6915 9.60115 36.665 9.50257 36.6603 9.38472H37.1275Z" fill="#999999"/></g><defs><clipPath id="clip0_2427_15519"><rect width="47" height="10" fill="white"/></clipPath></defs></svg>',
    /* indicator/rtmp-push */
    'indicator/rtmp-push': '<svg width="40" height="10" viewBox="0 0 40 10" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_2427_15937)"><path d="M2.08294 4.50331H4.36489C4.8425 4.50331 5.20072 4.39177 5.43953 4.1687C5.67833 3.94563 5.79774 3.58313 5.79774 3.08121C5.79774 2.59789 5.67833 2.24933 5.43953 2.03555C5.20072 1.81248 4.8425 1.70094 4.36489 1.70094H2.08294V4.50331ZM0 0H5.10785C5.5324 0 5.91272 0.0743582 6.24882 0.223075C6.59377 0.362496 6.88564 0.557686 7.12445 0.808644C7.37211 1.0596 7.55785 1.35239 7.68167 1.687C7.81434 2.01232 7.88068 2.36552 7.88068 2.7466C7.88068 3.33217 7.76127 3.83874 7.52247 4.26629C7.2925 4.69385 6.91218 5.01917 6.38149 5.24224V5.27013C6.63799 5.34449 6.85026 5.46067 7.01832 5.61868C7.18637 5.7674 7.32346 5.94865 7.4296 6.16243C7.53573 6.36691 7.61091 6.59463 7.65514 6.84559C7.70821 7.09655 7.74358 7.34751 7.76127 7.59847C7.77012 7.75648 7.77896 7.94237 7.78781 8.15615C7.79665 8.36993 7.80992 8.58836 7.82761 8.81143C7.85414 9.03451 7.88952 9.24829 7.93375 9.45277C7.98682 9.64796 8.062 9.81527 8.15929 9.95469H6.07635C5.96137 9.63867 5.89061 9.26223 5.86407 8.82537C5.83754 8.38852 5.79774 7.97026 5.74467 7.57058C5.67391 7.05008 5.52355 6.66899 5.29359 6.42733C5.06362 6.18566 4.68772 6.06483 4.16588 6.06483H2.08294V9.95469H0V0ZM8.59845 1.84036H11.4376V9.95469H13.5206V1.84036H16.3597V0H8.59845V1.84036ZM17.452 0H20.384L22.5996 6.84559H22.6262L24.7224 0H27.6544V9.95469H25.7041V2.89996H25.6776L23.3559 9.95469H21.7505L19.4288 2.96968H19.4023V9.95469H17.452V0ZM31.5712 4.68456H33.1898C33.4286 4.68456 33.6586 4.66597 33.8797 4.62879C34.1008 4.59161 34.2954 4.5219 34.4635 4.41966C34.6315 4.30812 34.7642 4.15476 34.8615 3.95957C34.9676 3.76438 35.0207 3.50877 35.0207 3.19275C35.0207 2.87673 34.9676 2.62112 34.8615 2.42593C34.7642 2.23074 34.6315 2.08203 34.4635 1.97978C34.2954 1.86825 34.1008 1.79389 33.8797 1.75671C33.6586 1.71953 33.4286 1.70094 33.1898 1.70094H31.5712V4.68456ZM29.4883 0H33.7603C34.3529 0 34.857 0.0929478 35.2728 0.278843C35.6885 0.455444 36.0246 0.69246 36.2811 0.989892C36.5464 1.28732 36.7366 1.62658 36.8515 2.00767C36.9754 2.38875 37.0373 2.78378 37.0373 3.19275C37.0373 3.59242 36.9754 3.98745 36.8515 4.37783C36.7366 4.75892 36.5464 5.09818 36.2811 5.39561C36.0246 5.69304 35.6885 5.9347 35.2728 6.1206C34.857 6.2972 34.3529 6.3855 33.7603 6.3855H31.5712V9.95469H29.4883V0ZM33.002 8.63716H33.4067C33.4664 8.63716 33.5238 8.63251 33.5791 8.62321C33.6344 8.61392 33.6831 8.59649 33.7251 8.57093C33.7671 8.54305 33.8003 8.50471 33.8246 8.45591C33.8511 8.40711 33.8644 8.34321 33.8644 8.2642C33.8644 8.1852 33.8511 8.1213 33.8246 8.0725C33.8003 8.0237 33.7671 7.98652 33.7251 7.96096C33.6831 7.93308 33.6344 7.91449 33.5791 7.90519C33.5238 7.8959 33.4664 7.89125 33.4067 7.89125H33.002V8.63716ZM32.4813 7.46602H33.5493C33.6974 7.46602 33.8235 7.48925 33.9274 7.53573C34.0313 7.57988 34.1153 7.63913 34.1795 7.71349C34.2458 7.78785 34.2933 7.87266 34.3221 7.96793C34.353 8.06321 34.3685 8.16196 34.3685 8.2642C34.3685 8.36412 34.353 8.46288 34.3221 8.56048C34.2933 8.65575 34.2458 8.74056 34.1795 8.81492C34.1153 8.88928 34.0313 8.94969 33.9274 8.99617C33.8235 9.04032 33.6974 9.06239 33.5493 9.06239H33.002V9.95469H32.4813V7.46602ZM38.3914 7.46602H38.8624V8.40363H38.8723C38.932 8.29906 39.0083 8.22354 39.1012 8.17707C39.194 8.12827 39.2847 8.10387 39.3731 8.10387C39.4992 8.10387 39.602 8.12246 39.6816 8.15964C39.7634 8.19449 39.8275 8.24445 39.874 8.30952C39.9204 8.37226 39.9525 8.4501 39.9702 8.54305C39.9901 8.63367 40 8.73475 40 8.84629V9.95469H39.529V8.93691C39.529 8.7882 39.5069 8.67782 39.4627 8.60579C39.4185 8.53143 39.34 8.49425 39.2272 8.49425C39.099 8.49425 39.0061 8.53491 38.9486 8.61624C38.8911 8.69525 38.8624 8.82654 38.8624 9.01011V9.95469H38.3914V7.46602ZM36.9747 9.36912C36.9747 9.42257 36.9847 9.46904 37.0046 9.50854C37.0267 9.54572 37.0543 9.57709 37.0875 9.60265C37.1207 9.62589 37.1583 9.64332 37.2003 9.65494C37.2445 9.66655 37.2898 9.67236 37.3363 9.67236C37.3694 9.67236 37.4037 9.66888 37.4391 9.66191C37.4767 9.65261 37.5098 9.63983 37.5386 9.62357C37.5695 9.60498 37.595 9.58174 37.6149 9.55386C37.6348 9.52365 37.6447 9.48647 37.6447 9.44232C37.6447 9.36796 37.5972 9.31219 37.5021 9.27501C37.4092 9.23783 37.2788 9.20065 37.1107 9.16348C37.0422 9.14721 36.9747 9.12862 36.9084 9.10771C36.8443 9.08447 36.7868 9.05542 36.7359 9.02057C36.6851 8.98339 36.6442 8.93808 36.6132 8.88463C36.5822 8.82886 36.5668 8.76148 36.5668 8.68247C36.5668 8.56629 36.5878 8.47102 36.6298 8.39666C36.674 8.3223 36.7315 8.26421 36.8023 8.22238C36.873 8.17823 36.9526 8.14802 37.0411 8.13176C37.1295 8.11317 37.2202 8.10387 37.313 8.10387C37.4059 8.10387 37.4955 8.11317 37.5817 8.13176C37.6702 8.15035 37.7486 8.18172 37.8172 8.22587C37.8857 8.27002 37.9421 8.32927 37.9863 8.40363C38.0328 8.47566 38.0604 8.56745 38.0693 8.67899H37.6215C37.6149 8.58372 37.5806 8.51981 37.5187 8.48728C37.4568 8.45243 37.3838 8.435 37.2998 8.435C37.2732 8.435 37.2445 8.43732 37.2135 8.44197C37.1826 8.44429 37.1538 8.45126 37.1273 8.46288C37.103 8.4745 37.082 8.49193 37.0643 8.51517C37.0466 8.53608 37.0378 8.56513 37.0378 8.6023C37.0378 8.64645 37.0532 8.68247 37.0842 8.71036C37.1151 8.73824 37.1549 8.76148 37.2036 8.78007C37.2544 8.79633 37.3119 8.81144 37.3761 8.82538C37.4402 8.83932 37.5054 8.85443 37.5718 8.87069C37.6403 8.88696 37.7066 8.90671 37.7708 8.92994C37.8371 8.95318 37.8957 8.98455 37.9465 9.02405C37.9974 9.06123 38.0383 9.10887 38.0693 9.16696C38.1002 9.22273 38.1157 9.29244 38.1157 9.37609C38.1157 9.4946 38.0925 9.59452 38.0461 9.67585C38.0018 9.75485 37.9432 9.81876 37.8703 9.86755C37.7973 9.91635 37.7133 9.95004 37.6182 9.96863C37.5253 9.98955 37.4302 10 37.3329 10C37.2334 10 37.1361 9.98955 37.0411 9.96863C36.946 9.94772 36.8609 9.91287 36.7857 9.86407C36.7127 9.81527 36.6519 9.75137 36.6033 9.67236C36.5568 9.59103 36.5314 9.48995 36.527 9.36912H36.9747ZM35.8047 9.95469H36.2524V8.15267H35.7815V9.09725C35.7815 9.28082 35.7527 9.41327 35.6952 9.4946C35.6377 9.5736 35.5449 9.61311 35.4166 9.61311C35.3038 9.61311 35.2253 9.57709 35.1811 9.50505C35.1369 9.4307 35.1148 9.31916 35.1148 9.17044V8.15267H34.6438V9.26107C34.6438 9.3726 34.6526 9.47485 34.6703 9.56779C34.6902 9.65842 34.7234 9.73626 34.7698 9.80132C34.8163 9.86406 34.8793 9.91286 34.9589 9.94772C35.0407 9.98257 35.1446 10 35.2707 10C35.3702 10 35.4675 9.97676 35.5625 9.93029C35.6576 9.88382 35.735 9.8083 35.7947 9.70373H35.8047V9.95469Z" fill="#B54A4A"/></g><defs><clipPath id="clip0_2427_15937"><rect width="40" height="10" fill="white"/></clipPath></defs></svg>',
    /* indicator/udp */
    'indicator/udp': '<svg width="27" height="10" viewBox="0 0 27 10" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6.93918 9.0411C7.64887 8.3927 8.00371 7.40639 8.00371 6.08219V0H5.94036V6.08219C5.94036 6.81279 5.80017 7.3516 5.5198 7.69863C5.23943 8.03653 4.73126 8.20548 3.99529 8.20548C3.57473 8.20548 3.23741 8.14612 2.98332 8.0274C2.738 7.89954 2.54524 7.73973 2.40506 7.54795C2.26487 7.34703 2.17287 7.11872 2.12907 6.86301C2.08526 6.60731 2.06335 6.34703 2.06335 6.08219V0H0V6.08219C0 7.41553 0.346083 8.40183 1.03825 9.0411C1.73918 9.68037 2.72486 10 3.99529 10C5.24819 10 6.22949 9.68037 6.93918 9.0411ZM11.8441 7.9726H13.684C13.9819 7.9726 14.271 7.92238 14.5514 7.82192C14.8318 7.72146 15.0815 7.55708 15.3005 7.32877C15.5195 7.09132 15.6948 6.78539 15.8262 6.41096C15.9576 6.03653 16.0233 5.57991 16.0233 5.0411C16.0233 4.54795 15.9751 4.10502 15.8788 3.71233C15.7912 3.3105 15.6422 2.96804 15.4319 2.68493C15.2217 2.40183 14.9413 2.18722 14.5908 2.0411C14.2491 1.88585 13.8242 1.80822 13.316 1.80822H11.8441V7.9726ZM9.7807 0H13.8286C14.4331 0 14.9938 0.100457 15.5108 0.30137C16.0365 0.502283 16.4877 0.803653 16.8644 1.20548C17.25 1.60731 17.5479 2.10959 17.7581 2.71233C17.9772 3.31507 18.0867 4.02283 18.0867 4.83562C18.0867 5.54795 17.9991 6.20548 17.8238 6.80822C17.6486 7.41096 17.3814 7.93151 17.0222 8.36986C16.6717 8.80822 16.2292 9.15525 15.6948 9.41096C15.1691 9.65753 14.547 9.78082 13.8286 9.78082H9.7807V0ZM21.5853 4.60274H23.1887C23.4253 4.60274 23.6531 4.58448 23.8721 4.54795C24.0912 4.51142 24.2839 4.44292 24.4504 4.34247C24.6168 4.23288 24.7483 4.08219 24.8446 3.89041C24.9498 3.69863 25.0024 3.44749 25.0024 3.13699C25.0024 2.82648 24.9498 2.57534 24.8446 2.38356C24.7483 2.19178 24.6168 2.04566 24.4504 1.94521C24.2839 1.83562 24.0912 1.76256 23.8721 1.72603C23.6531 1.6895 23.4253 1.67123 23.1887 1.67123H21.5853V4.60274ZM19.522 0H23.7538C24.3409 0 24.8403 0.0913244 25.2521 0.273973C25.6639 0.447489 25.9968 0.680366 26.2509 0.972603C26.5137 1.26484 26.7021 1.59817 26.816 1.9726C26.9387 2.34703 27 2.73516 27 3.13699C27 3.52968 26.9387 3.91781 26.816 4.30137C26.7021 4.6758 26.5137 5.00913 26.2509 5.30137C25.9968 5.59361 25.6639 5.83105 25.2521 6.0137C24.8403 6.18722 24.3409 6.27397 23.7538 6.27397H21.5853V9.78082H19.522V0Z" fill="#B54A4A"/></svg>'
  };

  /* ---- R16: every product-facing string lives here, single language (EN) ---- */
  var T = {
    stop: 'Stop Streaming',
    restart: 'Restart',
    setRoute: 'Set Source and Receiver',
    copyUrl: 'Copy source address',
    notSet: 'Not set',
    none: '—',
    empty: 'No data',
    cancel: 'Cancel',
    close: 'Close',
    live: 'Live',
    alarm: 'Alarm',
    offline: 'Offline',
    neverStarted: 'Never started',
    onAir: 'On air ',
    updated: 'Updated ',
    stopTitle: 'Stop streaming?',
    stopDesc: function (s) {
      return '“' + s.name + '” is on air to ' + s.receiver + '. Stopping ends the live output on that receiver immediately.';
    },
    restartTitle: 'Restart streaming?',
    restartDesc: function (s) {
      return '“' + s.name + '” is on air to ' + s.receiver + '. Restarting drops the live output for a few seconds while the source reconnects.';
    },
    stoppedTitle: 'Streaming stopped',
    stoppedDesc: function (s) { return '“' + s.name + '” is offline. ' + s.receiver + ' has no incoming feed.'; },
    restartedTitle: 'Streaming restarted',
    restartedDesc: function (s) { return '“' + s.name + '” is on air to ' + s.receiver + ' again.'; },
    startedTitle: 'Streaming started',
    startedDesc: function (s) { return '“' + s.name + '” is on air to ' + s.receiver + '.'; },
    unroutedTitle: 'Source not configured',
    unroutedDesc: 'Assign a source address and a receiver to start this feed.',
    copiedTitle: 'Address copied',
    copiedDesc: function (s) { return 'The source address of ' + s.id + ' is on the clipboard.'; }
  };

  /* ---- Mock data. M10: offline splits into idle vs never-started. ---- */
  var SOURCES = [
    { id: 'SRC-1042', name: 'Stadium Cam A', proto: 'indicator/srt-caller',
      url: 'srt://ingest-fra.tvu.net:9001?streamid=stadium-cam-a&latency=200',
      receiver: 'RCV Frankfurt-01', site: 'DE · Frankfurt', state: 'live',
      startedAt: '09:23', uptime: '02:41:18', bitrate: '8.2', trend: 'stable' },
    { id: 'SRC-1043', name: 'Stadium Cam B', proto: 'indicator/srt-caller',
      url: 'srt://ingest-fra.tvu.net:9002?streamid=stadium-cam-b&latency=200',
      receiver: 'RCV Frankfurt-01', site: 'DE · Frankfurt', state: 'live',
      startedAt: '09:23', uptime: '02:41:05', bitrate: '7.9', trend: 'stable' },
    { id: 'SRC-1088', name: 'Studio Feed New York', proto: 'indicator/rtmp-push',
      url: 'rtmp://ingest-nyc.tvu.net:1935/live/studio-feed-ny',
      receiver: 'RCV New York-04', site: 'US · New York', state: 'live',
      startedAt: '00:57', uptime: '11:07:52', bitrate: '12.1', trend: 'stable' },
    { id: 'SRC-1104', name: 'Mobile Unit 7 — Lisbon Marathon Relay', proto: 'indicator/udp',
      url: 'udp://10.42.118.203:5004?pkt_size=1316&fifo_size=1000000',
      receiver: 'RCV Lisbon-01', site: 'PT · Lisbon', state: 'alarm',
      startedAt: '10:46', alarm: 'Packet loss 12.4% · last 3 min', bitrate: '2.4', trend: 'diverging' },
    { id: 'SRC-1121', name: 'Field Van Porto', proto: 'indicator/srt-listener',
      url: 'srt://0.0.0.0:9101?mode=listener&latency=300',
      receiver: 'RCV Lisbon-01', site: 'PT · Lisbon', state: 'alarm',
      startedAt: '11:02', alarm: 'Receiver reconnecting · 2 retries', bitrate: '4.6', trend: 'diverging' },
    { id: 'SRC-0977', name: 'Backup Studio B', proto: 'indicator/rtmp-push',
      url: 'rtmp://ingest-nyc.tvu.net:1935/live/backup-studio-b',
      receiver: 'RCV New York-04', site: 'US · New York', state: 'offline',
      offlineKind: 'idle', lastRun: 'Last ran 09:12 → 11:40 · 148 min' },
    { id: 'SRC-1130', name: 'New Remote Kit', proto: null, url: null,
      receiver: null, site: null, state: 'offline', offlineKind: 'never' }
  ];

  var STATE_BADGE = {
    live:    { label: T.live,    cls: 'badge--red-line' },
    alarm:   { label: T.alarm,   cls: 'badge--orange-line' },
    offline: { label: T.offline, cls: 'badge--neutral-fill' }
  };

  var rowsEl = document.getElementById('rows');
  var filtersEl = document.getElementById('filters');
  var searchEl = document.getElementById('search');
  var toastsEl = document.getElementById('toasts');
  var overlayEl = document.getElementById('overlay');
  var dlgEl = overlayEl.firstElementChild;
  var dlgTitle = document.getElementById('dlg-title');
  var dlgDesc = document.getElementById('dlg-desc');
  var dlgConfirm = document.getElementById('dlg-confirm');
  var dlgCancel = document.getElementById('dlg-cancel');
  var dlgClose = document.getElementById('dlg-close');
  var updatedEl = document.getElementById('updated-at');

  var filter = 'all';
  var pending = null;
  var lastFocus = null;
  var tipSeq = 0;

  function esc(s) {
    return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
  }
  function icon(name, px) {
    return '<span class="icon icon--' + px + '" aria-hidden="true" data-icon="' + name + '"></span>';
  }
  function hhmmss(d) {
    function p(n) { return (n < 10 ? '0' : '') + n; }
    return p(d.getHours()) + ':' + p(d.getMinutes()) + ':' + p(d.getSeconds());
  }
  function hhmm(d) {
    function p(n) { return (n < 10 ? '0' : '') + n; }
    return p(d.getHours()) + ':' + p(d.getMinutes());
  }
  function minutesSince(hm) {
    var parts = hm.split(':');
    var now = new Date();
    var then = new Date();
    then.setHours(+parts[0], +parts[1], 0, 0);
    var mins = Math.round((now - then) / 60000);
    return mins > 0 ? mins : 0;
  }

  /* R23 center-ellipsis for URL / path fields (CSS has no native support). */
  function centerEllipsis(text, head, tail) {
    if (text.length <= head + tail + 1) return text;
    return text.slice(0, head) + '...' + text.slice(-tail);
  }

  /* Library Tooltip markup (theme=dark, pointing=top-start). Attached only when
     the content is really truncated — see applyTruncation(). */
  function tipWrap(inner, full, extraClass) {
    var id = 'tip-' + (++tipSeq);
    return '<span class="tooltip-wrap ' + extraClass + '" data-full="' + esc(full) + '" data-tip-id="' + id + '">' +
             '<span class="tooltip-trigger">' + inner + '</span>' +
             '<span class="tooltip-box tooltip-box--dark tooltip-box--top-start" role="tooltip" id="' + id + '">' +
               '<span class="tooltip-content">' + esc(full) + '</span>' +
               '<span class="tooltip-arrow tooltip-arrow--dark tooltip-arrow--top-start"></span>' +
             '</span>' +
           '</span>';
  }

  function statusCell(s) {
    var b = STATE_BADGE[s.state];
    var badge = '<span class="canonical-badge canonical-badge--rectangle ' + b.cls +
      '" data-figma-component="Badge" data-figma-type="Rectangle">' + esc(b.label) + '</span>';
    var meta = '';
    if (s.state === 'live') {
      meta = '<span class="cell-meta mono-num">' + T.onAir + esc(s.uptime) + '</span>';
    } else if (s.state === 'alarm') {
      meta = '<span class="cell-meta cell-meta--alarm">' + icon('status/warning', 16) +
             '<span>' + esc(s.alarm) + '</span></span>';
    } else if (s.offlineKind === 'idle') {
      meta = '<span class="cell-meta mono-num">' + esc(s.lastRun) + '</span>';
    } else {
      meta = '<span class="cell-meta">' + T.neverStarted + '</span>' +
             '<span><button class="btn btn--m btn--radius-square btn--text-green" type="button" ' +
             'data-act="route" data-id="' + s.id + '" style="padding-inline:0">' + T.setRoute + '</button></span>';
    }
    return '<span class="cell-stack">' + badge + meta + '</span>';
  }

  function bitrateCell(s) {
    if (s.state === 'offline') return '<span class="cell-none">' + T.none + '</span>';
    /* M11 trend rule — icon threshold AND value colour, both token-bound:
       bitrate is "higher is better", so a falling reading is diverging
       ⇒ navigation/arrow-down + --orange on BOTH icon and number;
       stable (within threshold) ⇒ no icon, neutral --text-body. */
    if (s.trend === 'diverging') {
      return '<span class="trend trend--diverging">' + icon('navigation/arrow-down', 16) +
             '<span class="mono-num">' + esc(s.bitrate) + ' Mbps</span></span>';
    }
    return '<span class="mono-num">' + esc(s.bitrate) + ' Mbps</span>';
  }

  function urlCell(s) {
    if (!s.url) return '<span class="cell-none">' + T.notSet + '</span>';
    var clipped = centerEllipsis(s.url, 22, 12);
    var body = '<span class="url-text clip">' + esc(clipped) + '</span>';
    var wrapped = clipped === s.url
      ? '<span class="url-wrap" style="min-width:0">' + body + '</span>'
      : tipWrap(body, s.url, 'url-wrap');
    return '<span class="url-cell">' +
             (s.proto ? '<span class="proto" aria-hidden="true" data-icon="' + s.proto + '"></span>' : '') +
             wrapped +
             '<button class="icon-btn" type="button" data-act="copy" data-id="' + s.id + '" title="' + T.copyUrl +
               '" aria-label="' + T.copyUrl + '">' + icon('edit/copy', 16) + '</button>' +
           '</span>';
  }

  function rowHtml(s) {
    var stoppable = s.state === 'live' || s.state === 'alarm';
    var restartable = s.state !== 'offline' || s.offlineKind === 'idle';
    return '<tr class="tbl-row" data-id="' + s.id + '">' +
      '<td class="tbl-cell tbl-cell--left col-source"><span class="tbl-cell__content">' +
        '<span class="cell-stack">' +
          '<span class="cell-strong js-name" data-full="' + esc(s.name) + '"><span class="clip">' + esc(s.name) + '</span></span>' +
          '<span class="cell-meta mono-num">' + esc(s.id) + '</span>' +
        '</span></span></td>' +
      '<td class="tbl-cell tbl-cell--left"><span class="tbl-cell__content">' + urlCell(s) + '</span></td>' +
      '<td class="tbl-cell tbl-cell--left"><span class="tbl-cell__content">' +
        (s.receiver
          ? '<span class="cell-stack"><span class="cell-strong">' + esc(s.receiver) + '</span>' +
            '<span class="cell-meta">' + esc(s.site) + '</span></span>'
          : '<span class="cell-none">' + T.notSet + '</span>') +
        '</span></td>' +
      '<td class="tbl-cell tbl-cell--left"><span class="tbl-cell__content">' + statusCell(s) + '</span></td>' +
      '<td class="tbl-cell tbl-cell--right"><span class="tbl-cell__content">' + bitrateCell(s) + '</span></td>' +
      '<td class="tbl-cell tbl-cell--right"><span class="tbl-cell__content"><span class="row-actions">' +
        '<button class="btn btn--m btn--radius-square btn--ghost-red" type="button" data-act="stop" data-id="' +
          s.id + '"' + (stoppable ? '' : ' disabled') + '>' + T.stop + '</button>' +
        '<button class="btn btn--m btn--radius-square btn--ghost-gray" type="button" data-act="restart" data-id="' +
          s.id + '"' + (restartable ? '' : ' disabled') + '>' + T.restart + '</button>' +
      '</span></span></td>' +
    '</tr>';
  }

  function byId(id) {
    for (var i = 0; i < SOURCES.length; i++) if (SOURCES[i].id === id) return SOURCES[i];
    return null;
  }
  function matches(s, q) {
    if (!q) return true;
    var hay = [s.id, s.name, s.url || '', s.receiver || '', s.site || ''].join(' ').toLowerCase();
    return hay.indexOf(q) !== -1;
  }

  function paintIcons(scope) {
    var nodes = scope.querySelectorAll('[data-icon]');
    for (var i = 0; i < nodes.length; i++) {
      var n = nodes[i];
      if (n.getAttribute('data-painted') === '1') continue;
      var svg = ICONS[n.getAttribute('data-icon')];
      if (svg) { n.innerHTML = svg; n.setAttribute('data-painted', '1'); }
    }
  }

  /* R23 truncation detection — measure, then attach or drop the tooltip. */
  function applyTruncation() {
    var names = rowsEl.querySelectorAll('.js-name');
    for (var i = 0; i < names.length; i++) {
      var holder = names[i];
      var clip = holder.querySelector('.clip');
      var full = holder.getAttribute('data-full');
      var truncated = clip && clip.scrollWidth > clip.clientWidth;
      var existing = holder.querySelector('.tooltip-wrap');
      if (truncated && !existing) {
        holder.innerHTML = tipWrap('<span class="clip" tabindex="0">' + esc(full) + '</span>', full, 'name-wrap');
      } else if (!truncated && existing) {
        holder.innerHTML = '<span class="clip">' + esc(full) + '</span>';
      }
    }
    var wraps = rowsEl.querySelectorAll('.tooltip-wrap');
    for (var j = 0; j < wraps.length; j++) {
      var w = wraps[j];
      var box = w.querySelector('.tooltip-box');
      var trigger = w.querySelector('.tooltip-trigger');
      var target = trigger.querySelector('.clip') || trigger;
      /* a11y double safety per R23: aria-describedby (rich tooltip) + title (no-JS / touch) */
      w.classList.add('is-truncated');
      target.setAttribute('aria-describedby', box.id);
      target.setAttribute('title', w.getAttribute('data-full'));
      if (!target.hasAttribute('tabindex')) target.setAttribute('tabindex', '0');
    }
  }

  function updateCounts() {
    var c = { all: SOURCES.length, live: 0, alarm: 0, offline: 0 };
    for (var i = 0; i < SOURCES.length; i++) c[SOURCES[i].state]++;
    var nodes = filtersEl.querySelectorAll('[data-count]');
    for (var j = 0; j < nodes.length; j++) {
      nodes[j].textContent = c[nodes[j].getAttribute('data-count')];
    }
  }

  function render() {
    var q = searchEl.value.trim().toLowerCase();
    var visible = SOURCES.filter(function (s) {
      return (filter === 'all' || s.state === filter) && matches(s, q);
    });
    rowsEl.innerHTML = visible.length
      ? visible.map(rowHtml).join('')
      : '<tr class="tbl-empty-row"><td colspan="6" class="tbl-empty">' + T.empty + '</td></tr>';
    paintIcons(rowsEl);
    applyTruncation();
    updateCounts();
  }

  function stamp() { updatedEl.textContent = T.updated + hhmmss(new Date()); }

  /* ---- Notification form=slide (passive toast, no action row) ---- */
  function toast(kind, title, desc) {
    var el = document.createElement('div');
    el.className = 'notif notif--dark notif--slide notif--type-' + kind + ' toast-enter';
    el.setAttribute('data-figma-component', 'Notification');
    el.setAttribute('data-figma-form', 'slide');
    el.setAttribute('data-figma-type', kind);
    el.setAttribute('data-figma-theme', 'dark');
    el.innerHTML =
      '<div class="notif__main">' +
        (kind === 'success' ? '<span class="notif__icon icon icon--24" aria-hidden="true" data-icon="message/success-2"></span>' : '') +
        '<div class="notif__body"><div class="notif__header">' +
          '<p class="notif__title">' + esc(title) + '</p>' +
          '<button class="notif__close" type="button" aria-label="' + T.close + '">' +
            '<span class="icon icon--12" aria-hidden="true" data-icon="action/close"></span></button>' +
        '</div><p class="notif__desc">' + esc(desc) + '</p></div>' +
      '</div>';
    toastsEl.appendChild(el);
    paintIcons(el);
    var timer = setTimeout(function () { el.remove(); }, 4000);
    el.querySelector('.notif__close').addEventListener('click', function () {
      clearTimeout(timer);
      el.remove();
    });
  }

  /* ---- Notification form=pop confirm (destructive second confirmation) ---- */
  function focusables() {
    return Array.prototype.filter.call(
      dlgEl.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),
      function (el) { return !el.disabled && el.tabIndex !== -1; }
    );
  }
  function onKeydown(e) {
    if (e.key === 'Escape') { e.preventDefault(); closeDialog(); return; }
    if (e.key !== 'Tab') return;
    var f = focusables();
    if (!f.length) { e.preventDefault(); dlgEl.focus(); return; }
    var first = f[0], last = f[f.length - 1];
    if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
    else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
  }
  function openDialog(action, s) {
    pending = { action: action, id: s.id };
    dlgTitle.textContent = action === 'stop' ? T.stopTitle : T.restartTitle;
    dlgDesc.textContent = action === 'stop' ? T.stopDesc(s) : T.restartDesc(s);
    dlgConfirm.textContent = action === 'stop' ? T.stop : T.restart;
    lastFocus = document.activeElement;
    overlayEl.hidden = false;
    document.body.style.overflow = 'hidden';
    window.addEventListener('keydown', onKeydown);
    requestAnimationFrame(function () { (focusables()[0] || dlgEl).focus(); });
  }
  function closeDialog() {
    pending = null;
    overlayEl.hidden = true;
    document.body.style.overflow = '';
    window.removeEventListener('keydown', onKeydown);
    if (lastFocus && lastFocus.focus) lastFocus.focus();
    lastFocus = null;
  }
  function commit() {
    if (!pending) return;
    var s = byId(pending.id);
    var action = pending.action;
    closeDialog();
    if (!s) return;
    if (action === 'stop') {
      var mins = s.startedAt ? minutesSince(s.startedAt) : 0;
      s.state = 'offline';
      s.offlineKind = 'idle';
      s.lastRun = 'Last ran ' + s.startedAt + ' → ' + hhmm(new Date()) + ' · ' + mins + ' min';
      delete s.alarm;
      render(); stamp();
      toast('success', T.stoppedTitle, T.stoppedDesc(s));
    } else {
      s.state = 'live';
      s.startedAt = hhmm(new Date());
      s.uptime = '00:00:04';
      s.trend = 'stable';
      s.bitrate = s.bitrate && s.bitrate !== '—' ? s.bitrate : '6.0';
      delete s.alarm; delete s.offlineKind; delete s.lastRun;
      render(); stamp();
      toast('success', T.restartedTitle, T.restartedDesc(s));
    }
  }

  /* ---- events ---- */
  rowsEl.addEventListener('click', function (e) {
    var btn = e.target.closest('[data-act]');
    if (!btn || btn.disabled) return;
    var s = byId(btn.getAttribute('data-id'));
    if (!s) return;
    var act = btn.getAttribute('data-act');
    if (act === 'stop') {
      openDialog('stop', s);
    } else if (act === 'restart') {
      /* Second confirmation is tied to business impact: restarting an on-air
         feed interrupts output; restarting an idle source interrupts nothing. */
      if (s.state === 'live' || s.state === 'alarm') {
        openDialog('restart', s);
      } else {
        s.state = 'live';
        s.startedAt = hhmm(new Date());
        s.uptime = '00:00:02';
        s.trend = 'stable';
        s.bitrate = '6.0';
        delete s.offlineKind; delete s.lastRun;
        render(); stamp();
        toast('success', T.startedTitle, T.startedDesc(s));
      }
    } else if (act === 'route') {
      toast('default', T.unroutedTitle, T.unroutedDesc);
    } else if (act === 'copy') {
      if (navigator.clipboard && s.url) navigator.clipboard.writeText(s.url);
      toast('default', T.copiedTitle, T.copiedDesc(s));
    }
  });

  filtersEl.addEventListener('click', function (e) {
    var chip = e.target.closest('[data-filter]');
    if (!chip) return;
    selectChip(chip);
  });
  filtersEl.addEventListener('keydown', function (e) {
    if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return;
    var chips = Array.prototype.slice.call(filtersEl.querySelectorAll('[data-filter]'));
    var i = chips.indexOf(document.activeElement);
    if (i === -1) return;
    e.preventDefault();
    var next = chips[(i + (e.key === 'ArrowRight' ? 1 : chips.length - 1)) % chips.length];
    selectChip(next);
    next.focus();
  });
  function selectChip(chip) {
    var chips = filtersEl.querySelectorAll('[data-filter]');
    for (var i = 0; i < chips.length; i++) {
      var on = chips[i] === chip;
      chips[i].classList.toggle('tab-item--active-green', on);
      chips[i].classList.toggle('tab-item--normal', !on);
      chips[i].setAttribute('aria-selected', on ? 'true' : 'false');
      chips[i].tabIndex = on ? 0 : -1;
    }
    filter = chip.getAttribute('data-filter');
    render();
  }

  searchEl.addEventListener('input', render);
  dlgConfirm.addEventListener('click', commit);
  dlgCancel.addEventListener('click', closeDialog);
  dlgClose.addEventListener('click', closeDialog);
  /* closeOnBackdrop mirrors PopupBox's default (false): a destructive confirm
     must not be dismissed by a stray click. */
  overlayEl.addEventListener('click', function (e) { if (e.target === overlayEl) e.stopPropagation(); });

  var rafId = 0;
  window.addEventListener('resize', function () {
    cancelAnimationFrame(rafId);
    rafId = requestAnimationFrame(applyTruncation);
  });

  paintIcons(document);
  render();
  stamp();
})();
</script>
</body>
</html>
```

**用到的 library primitives**（R15 Acceptance 要求的一行）：`Top bar (After Login)` · `MenuList (horizontal)` · `Table (Tbody)` · `Button (dark M · ghost gray/red/green · filling red · rimless green)` · `Badge (Rectangle × Red/Orange/Neutral × Line/Filled)` · `Tab/Item (Filled × Active-Green/Normal-White)` · `input box/filled (size M · feature=no)` · `Tooltips (dark · top-start)` · `Notification (pop confirm × danger / slide × success·default)` · `Popup Box` 的遮罩规格（Mask blur8 #000-60%）· 11 个图标全部取自 `src/icons/**`。

**打开后可试**：筛选 chip（单选 + 方向键）/ 搜索 / hover 第 4 行名称与各行地址看 tooltip（只有真截断的才弹）/ 点 `Stop Streaming` → pop confirm（Esc、Cancel、backdrop 不关）→ 确认后行转 Offline-Idle 并按真实时钟生成 `Last ran … · N min` + slide toast / 对 Offline-Idle 行点 `Restart` 直接启动（无中断 ⇒ 不设二次确认）/ 最后一行两个操作按钮为 Figma disabled 真值（ghost red 带 0.4 容器透明度）。

**留给 owner 的两条**（本 session 只读，未写入仓库）：① `Pill Status` 缺 warning/告警档，建议立 backlog（现用 Badge Orange 顶替）② DS 无 `--z-toast`，本页复用 `--z-modal`，值得评估是否补一档 token。

```text
下个 session 续跑 prompt（可直接粘贴）

在 tvu-design-system 仓库继续「直播源管理 mockup」这条线。上一轮（2026-08-25，只读会话）已产出一份单文件高保真 HTML（TVU Grid · Sources 运营台），
产物只存在于对话里、未落仓库。请先走完 docs/STATUS.md §起手必读链路 的两层 onboarding（mockup/UI 代码任务：L-core 四份 + AGENTS §硬规则/§Onboarding Gate
+ docs/internal/code-conventions.md 顶部起手必读段 + domain-tvu.md 全文），然后从这三件里挑用户指定的接着做：

1) 把那份 HTML 落地成仓库内产物（建议 playground/public/ 下的自包含页，或 react-pilot/docs demo 页）——落地前先确认放哪、要不要 <link> 构建期拷出的
   tvu-tokens.css 取代内联 token 块（R2.1 真源要求），并按 §Mockup Write Gate / 快车道判据决定 changeset 与 VISUAL_COMMIT_APPROVED（⛔ AI 不自设该变量）。
2) 补两条已识别的 DS 缺口 entry（取号先 `pnpm new-backlog INFRA`，⛔ 别凭印象选号）：
   (a) published `Pill Status` 只有 On-air/Preview/Analyzing/Inactive 四态、无 warning/告警档，消费侧只能改用 Badge Orange/Line 顶替；
   (b) `src/tokens/variables.css` §Z-Index 无 `--z-toast`（原注释写「无消费者不凭空造」），本轮 toast 实测复用了 `--z-modal`，即已出现消费者。
3) 若要把这页推成 Figma mockup：先走 AGENTS §Mockup Write Gate 4 步前置 + §必读链路 7-11 整链（含 `pnpm pattern:lookup <figma URL>`，⬜ 命中要先采一次再查）。

纪律提醒（本轮踩到过的坑）：
· 状态色按 domain-tvu M3（Live=红 / Preview=绿 / Inactive=灰），⛔ 别套 SaaS「绿=正常」；告警走 --orange。
· M7：操作按钮必须正规 M 尺寸、状态 pill 最安静；M5：监控台不放创建入口；M10：离线必分 Idle / NeverStarted 两子型。
· ghost red 的 hover 底色是 --red-bg(#fff1f0)、disabled 带 opacity 0.4 —— 那都是 Figma 真值，⛔ 别当 bug「修」。
· MenuList horizontal 的 active 只改文字色，⛔ 不要加 brand 下划线（owner 2026-08-14 已裁定删除，勿复原）。
· 工作树内跑闸前先确认 node_modules / dist / .env（Worktree 六坑），闸的挂载事实读脚本头注释、别 grep 调用点。
```