# Graphics Insertion — Dual Preview (PVW + PGM) — Figma Handoff

> **Date**: 2026-05-19 (v1) · 2026-05-20 (v2/v3/v4/v5/v6/v7/v8/v9)
> **Product**: MicroApps · Graphics Insertion
> **Task type**: mockup (US-3 existing product, new feature design)
> **Final layout**: **v9 = v8 + PVW/PGM PP-style visual polish (colored borders + gradient bg + interior chips)**

## v9 visual polish (2026-05-20 PM late, PP reference applied to PVW/PGM)

User noted the v8 PVW/PGM rendering was "very bad" — flat green/navy fills with big corner badges looked like placeholders, not real broadcast UI. Referenced PP-2025-2026 node `2002:7240` (Studio-overlay) for how PVW/PGM should be visually delivered.

**PP reference's signature visual elements** (applied to v9):

| Element | v8 (before) | v9 (after, PP style) |
|---|---|---|
| PVW state signal | big green badge top-left corner | **3px brand-green stroke border** (subtle, identifying) |
| PGM state signal | big red "ON AIR" badge | **3px red stroke border** |
| Background fill | single flat color | **vertical gradient** (top dark → bottom mid-tone, suggests video depth) |
| Top-left chip | (none) | small black-translucent chip with source-name (`● PVW · Cam 1 · Stadium` / `● PGM · LIVE · 13:42:18`) |
| Top-right chip | (none) | small black-translucent timecode chip (`00:32:14:08`) |

**v9 changes applied via single batch:**
1. Removed PVW top-corner brand-green badge `4107:445` (replaced by 3px stroke)
2. Removed PGM top-corner red ON-AIR badge `4107:450` (replaced by 3px stroke)
3. PVW `strokes` = `[{type:SOLID, color: BRAND}]`, `strokeWeight=3`, `strokeAlign=INSIDE`
4. PGM `strokes` = `[{type:SOLID, color: RED}]`, `strokeWeight=3`, `strokeAlign=INSIDE`
5. PVW fills replaced with `GRADIENT_LINEAR` (3 stops: dark `#1a2d12` → mid `#355a22` → bottom `#4a6b2b`)
6. PGM fills replaced with `GRADIENT_LINEAR` (3 stops: very-dark `#0a162a` → `#142442` → `#1a2c4a`)
7. Added per-preview top-left source-name chip (HORIZONTAL auto-layout, black@65% opacity, small colored dot + text)
8. Added per-preview top-right timecode chip (HORIZONTAL auto-layout, black@65%, timecode text in brand color)

**Still pending vs PP reference** (no realistic images yet):
- PP shows actual basketball stadium / player photos as video content. I can't easily upload images via plugin API; gradient + chips substitute. Future improvement: use `figma.createImage` with base64 stock photo if user wants closer match.
- PP also has a multi-source camera grid (4×2 = 8 thumbnails) below previews. Out of scope for current Graphics Insertion (no PRD requirement for multi-source grid).

## v8 final spec (2026-05-20 PM late, M31 compliance refactor)

User caught a critical violation: v1-v7 used Frame absolute positioning instead of Auto Layout — **violated existing M31** (mockup-conventions.md §M31 "Layout function decision tree: Auto Layout 默认，absolute 只用于浮层"). I read M31 at session start but failed to apply it across 7 iterations.

### v8 refactor — auto-layout containment tree

Replaced all macro-level absolute positioning with nested auto-layout containers:

```
After frame (1920×1080, FIXED) — top-level Figma container, OK absolute
├── Top bar (library instance, absolute x=0, y=0) — frozen
└── Main Row (HORIZONTAL auto-layout, x=40, y=72, 1840×952, itemSpacing=20)
    ├── Left Column (VERTICAL auto-layout, 1360w × 952h, FILL height)
    │   ├── URL Row (FILL horizontal, HUG vertical)
    │   ├── Video Area (HORIZONTAL auto-layout, FILL width + height,
    │   │              primaryAxisAlignItems=CENTER, counterAxisAlignItems=CENTER)
    │   │   ├── PVW + Meter Group (HORIZONTAL auto-layout, HUG, itemSpacing=0)
    │   │   │   ├── PVW Preview (640×360, FIXED — has overlays inside, OK absolute)
    │   │   │   └── PVW Audio Meter (cloned Group 61)
    │   │   └── PGM + Meter Group (HORIZONTAL auto-layout, HUG, itemSpacing=0)
    │   │       ├── PGM Preview (640×360, FIXED — has overlays inside, OK absolute)
    │   │       └── PGM Audio Meter (cloned Group 61)
    │   └── Bottom Toolbar (FILL horizontal, HUG vertical)
    └── Right Layer Panel (FIXED 460w, FILL vertical, cloned instance)

PVW/PGM Bottom Strips (FIXED 640×44, HORIZONTAL auto-layout,
  primaryAxisAlignItems=SPACE_BETWEEN, counterAxisAlignItems=CENTER):
  [layer-icons | label | action-button] now space-between distributed
```

### Audit (v8)

- 58 total frames in After
- **47 auto-layout** (81%)
- 11 absolute — all M31-legal exceptions:
  - PVW/PGM Preview frames: "Stand-alone overlay container" (video screen + badge/chyron/overlay/strip overlays)
  - Layer panel widget cards: cloned library content
  - Top bar internals: frozen library instance
- 16:9 ratio still exact 1.7778 ✓

### Why this matters

Auto-layout makes the mockup **manually editable in Figma**:
- Move PVW left/right → PGM auto-spaces
- Add a 4th item to mid-ops → distribution auto-rebalances
- Resize URL row text length → input auto-extends
- Move bottom toolbar up → other content reflows

Absolute positioning froze the layout — every manual edit required recomputing 5+ coords. v8 fixes this.

### Process gap (logged, not new rule)

I read M31 at session start (mockup-conventions.md fully loaded) but defaulted to absolute positioning anyway for 7 iterations. This is an **AI-discipline gap, not a TVU rule gap** — M31 already covers this. User had to remind me explicitly to enforce.

Self-correction: tag this session in memory as "M31 violator session" so future @TVU mockup invocations start with explicit auto-layout intent.

## v7 final spec (2026-05-20 PM late, asset reuse + state machine delivery)

User instructed to reuse two existing references instead of self-drawing:
1. **Audio meter** — clone `Group 61` (id `1240:15412`) from existing "Edit Stinger" frame (node `1240:15357`) in same Figma file. Replaces self-drawn gradient bars + tick text.
2. **Overlay Cut delivery format** — reference PP-2025-2026 file `tmVCFjx1BCfb7EP5OPD1AP` node `1665:9076` Studio-overlay layer cut pattern (state mini-frames + arrows + action chip labels).

### v7 changes (from v6)

**(1) Audio meter swap**
- Removed self-drawn meter frames `4107:456` (PVW) + `4107:476` (PGM)
- Cloned `Group 61` (1240:15412) from Edit Stinger twice, rescale 0.527 to fit h=360
- New IDs: PVW meter `4195:426`, PGM meter `4195:452`
- Both contain TVU library `icon/sound/on 1` instance, real L+R level bars (2 background + 2 fill rectangles), full dB tick column (0/-2/-4/.../-40)
- Visual width ~17.6w (was 20w self-drawn)

**(2) Overlay Cut state-machine delivery section (PP-2025-2026 style)**
- Section header chip "Overlay Cut · State Machine Spec" placed at canvas (2320, 2280) — below the M23 rules card
- **State A · Before Overlay Cut** mini-frame (560×380) at (2320, 2360) — shows mini dual preview: PVW with Team1 overlay (editing), PGM empty
- **State B · After Overlay Cut** mini-frame (560×380) at (2920, 2360) — both PVW + PGM now show Team1 overlay (on-air sync'd)
- Brand-green arrow + pill "✂ Click Overlay Cut" between states (action chip + VECTOR arrow)
- Bilingual captions under each state mini

### Pattern comparison: TVU M23 vs PP-2025-2026 layer cut delivery

| Aspect | TVU M23 (current annotation layer) | PP-2025-2026 (used for Overlay Cut spec) |
|---|---|---|
| Annotation primitive | navy `#2B2D42` chips with bilingual text | **actual UI mini-frame state visuals** + inline text labels |
| Flow indicator | VECTOR connectors with arrowheads | curved arrows + brand-green action pill |
| State expression | text describing the state | **visual rendering of the UI in that state** |
| Best for | rules / specs / feature lists | **interaction state machines / before-after transitions** |

The Overlay Cut deliverable uses PP pattern because it's a state transition (before-cut → after-cut), which is hard to express in pure navy text chips. The two patterns coexist on the page — M23 chips for the broader spec, PP-style mini-frames for the cut interaction.

### Iteration trail extended

- v1-v6: see below
- **v7 (2026-05-20 PM late) — final**: Asset reuse + PP-style cut delivery. Replaces self-drawn audio meter with cloned Group 61. Adds Overlay Cut state machine delivery section in PP-2025-2026 reference style.

## v6 final spec (2026-05-20 PM late, structural refinement)

User clarified the structural hierarchy: the page should be **left-right split overall, with the left column further divided top-middle-bottom**. The right Layer panel is a **full-height sidebar** (top bar bottom to frame bottom), NOT a constrained "main row only" panel.

v6 changes (from v5):

| Element | v5 | v6 | Change |
|---|---|---|---|
| Top URL Row | full-width 1840 | **1360 (left-column-only)** | shrink → contained in left col |
| Bottom Toolbar | full-width 1840 | **1360 (left-column-only)** | shrink → contained in left col |
| Layer Panel | (1420, 146, 460, 794) | **(1420, 72, 460, 952)** | y -74, h +158 → full-height sidebar |
| PVW / PGM / meters | unchanged | unchanged | 16:9 ratio preserved |

Result: Layer panel becomes a substantial full-height sidebar, visually balancing the heavy left work area. The previously cut-off widget cards (logo / dual-skier images cloned from `1747:2764`) now render visible — Layer panel feels more "loaded" matching real-world layer composition density.

### Iteration trail (v1 → v6)

- v1 (2026-05-19): Initial. Mid Ops column + Video Cut + section labels.
- v2 (2026-05-20 AM): 16:9 (512×288). Over-engineered with `●` section labels + moved Preset to right panel. ❌
- v3 (2026-05-20 noon): Reverted Preset. Acknowledged section labels violated M33.
- v4 (2026-05-20 PM): Scheme E (Embedded Strip) adopted from Standard Conversion reference. Mid Ops removed. Controls embedded in bottom strips. Previews 560×315.
- v5 (2026-05-20 PM): 1+3 balance combo — previews 640×360, right panel narrowed to 460w, vertically centered (y=365). Balanced left-half whitespace.
- **v6 (2026-05-20 PM late) — final**: Structural refinement — URL row + Bottom toolbar resized to left-column-width 1360; Layer panel extended to full-height sidebar (y=72, h=952). Matches Standard Conversion universal structural hierarchy exactly.

## v5 final spec (2026-05-20 PM, balance refinements)

User feedback on v4: too much vertical whitespace below previews + left video area looks "floating top" vs right Layer panel that extends full main row height. Adopted **1+3 combo** to rebalance:

1. **Preview enlargement (修法 1)** — PVW + PGM resized from 560×315 to **640 × 360** (k=40, still exact 16:9 ratio = 1.7778). Audio meters resized to 360h to match.
2. **Right Layer panel narrowed** — from 648w to **460w** (x=1420). Widget cards still legible. Internal orphan "Frame 3070" placeholder removed. `clipsContent=true` set on panel.
3. **Vertical centering (修法 3)** — previews repositioned from top-anchored y=200 to vertically-centered y=365. Above-space = 223 px, below-space = 255 px (diff 32 px, visually symmetric).
4. **Audio meters glued to preview right edges** — PVW meter at x=694, PGM meter at x=1366 (each w=20, h=360). Strict option B convention.
5. **PVW/PGM bottom strips re-fitted to 640w** — children (layer btn group, label, action button) reflowed within new strip width.
6. **M23 connectors rebuilt** with v5 target positions; reconnect map v5 = 932 bytes.

### Math reality acknowledged

For dual-16:9 side-by-side under the MicroApps universal frame constraint, "filling vertical like Standard Conversion single preview" is **mathematically impossible** — single preview h ≈ 650 forces dual preview h ≤ 360 (each ≤ half the width). The v5 1+3 combo accepts the math and resolves visually via (a) maximum-feasible preview size + (b) symmetric padding instead of top-anchored.

### Iteration trail (v1 → v5)

- v1 (2026-05-19): Initial. Mid Ops column with 3 layer btns + Overlay Cut + Video Cut. Section labels. Long PRD card.
- v2 (2026-05-20 AM): Removed Video Cut + format dropdown + transition support. Resized to 16:9 (512×288). Over-corrected layout into separate Input / Video Preview / Output / Settings sections with `●` section dots + hint texts. Moved Preset to right panel.
- v3 (2026-05-20 noon): Reverted Preset back to bottom row. Acknowledged section labels violated M33.
- v4 (2026-05-20 PM): Scheme E adopted (Embedded Strip) after Standard Conversion universal layout reference clarified by user. Mid Ops removed. Controls embedded in bottom strips. Top URL row + bottom toolbar verbatim cloned from Before. Previews 560×315.
- **v5 (2026-05-20 PM) — final**: 1+3 balance combo. Previews enlarged to 640×360. Right panel narrowed to 460w. Previews vertically centered. M23 v4 annotation layer kept (scheme E description still accurate); connectors only rebuilt for new target positions.

## v4 final spec (2026-05-20, scheme E adopted)

After user clarified the MicroApps universal layout convention via the Standard Conversion reference image — **only the central video preview area is hackable; top bar + top URL row + right Layer panel + bottom toolbar are frozen** — the layout was redesigned end-to-end as scheme E:

1. **Universal frame frozen + cloned from Before (1747:2764)** — top URL row (input + ID button) at y=78 + bottom toolbar (Default Preset + SRT URL + Go Live) at y=980 are both verbatim clones from the reference frame's existing content rows. No section labels, no hint texts, no app-invented chrome added.
2. **No Mid Ops column** — all action controls embedded into PVW/PGM bottom strips (44h overlays on each preview's bottom 12 px).
3. **PVW bottom strip layout**: `[L1 L2 L3 layer/template quick-switch icons]` · `🎧 + "Preview" label` · `Clear overlay button (ghost gray)`.
4. **PGM bottom strip layout**: `[⊙ Overlay Cut button, brand-green filling, primary]` · `🎧 + "Program" label` · `Remove overlay button (ghost red)`.
5. **Audio meter convention** — each meter inside-right of its preview frame (`PVW meter at x=600, PGM meter at x=1192`), matching Standard Conversion single-preview convention. Both 20w × 315h.
6. **Preview dims** — PVW + PGM at `560 × 315` each (k=35, exact 16:9 ratio = 1.7778). Confirmed via post-build probe.
7. **Right Layer panel** — clone of `1747:2764`'s right side, repositioned to x=1232 y=146 w=648 h=794.
8. **Audit**: I3 wrap = 0 overflow on After (maxR=1920 maxB=1044 ≤ 1080). Rules card = 0 overflow. PVW/PGM ratio = exact 1.7778. All 75 instances in After are library instances (remote=true).

### Iteration trail (v1 → v4)

- v1 (2026-05-19): Initial. Mid Ops column with 3 layer btns + Overlay Cut + Video Cut. Section labels. Long PRD card.
- v2 (2026-05-20 AM): Removed Video Cut + format dropdown + transition support. Resized to 16:9 (512×288). Over-corrected layout into separate "Input / Video Preview / Output / Settings" sections with `●` section dots + hint texts. Moved Preset to right panel.
- v3 (2026-05-20 noon): Reverted Preset back to bottom row. Acknowledged that section labels violate M33 (annotation/product-UI separation) and over-engineered the layout.
- **v4 = scheme E (2026-05-20 PM)**: Adopted user-specified Standard Conversion universal layout. Mid Ops column removed entirely. Controls embedded in preview bottom strips. Top URL row + bottom toolbar verbatim cloned from Before. Previews resized to 560×315 to balance with right Layer panel. v3 annotation layer + rules card fully rebuilt for scheme E.

## Process Gaps — Local Lessons (project-specific record)

> 本段记录的是 Graphics Insertion 这次 6 轮 retrofit 的**项目层级具体决策与教训**。
> 抽象后的通用规则（应回流到 TVU Design System）见末尾 §"TVU 回流候选清单"。

### 决策落点（Graphics Insertion 特有）

| 决策 | v# 拍板 | 备注 |
|---|---|---|
| Mid Ops 中间操作列删除 | v4 | dual 16:9 + 通用框架冻结 + 右栏 frozen 场景下，Mid Ops 列范式不适用 |
| Overlay Cut 归宿 = PGM 底 strip 左侧主操作 | v4 | brand-green filling，"Cut → Program" 语义 |
| 3 Layer/版式切换归宿 = PVW 底 strip 左侧 | v4 | 小图标按钮组 (28×28) |
| 视频比例锁 16:9 | v2 | PRD 明确 fixed，不做 aspect dropdown |
| 不要 Video Cut / 转场 / Dissolve | v2 | PRD 反馈 |
| Audio meter = 各预览右内侧 (option B) | v4 | 跟 Standard Conversion 单预览惯例一致 |
| 预览尺寸 = 640×360 (k=40, exact 16:9) | v5 | 左栏 1360w 几何上限；Layer panel 缩到 460w 换取 |
| 预览垂直居中 y=365 | v5 | 上下留白对称 223/255 px diff=32 |
| 左右整体分栏 + 左内三段 + 右全高 sidebar | v6 | 最终结构 — URL 行 + Bottom toolbar 缩到 1360w 左栏宽，Layer panel y=72 / h=952 全高 |

### Library swap pending (next session)

- [ ] `Color Type/Background/Layer_1` variable binding 到 After frame bg（M-COLOR §C3）— v1 起就 deferred
- [ ] Mid-ops 已删；但若未来要恢复 layer 按钮的"active state"语义，建议用 `Button/dark M` icon-only variant 替代自画 frame
- [ ] Audio meter 自画 — 🟡 入 TVU library backlog `AudioMeter` 候选

### 6 轮迭代根因总结（项目层级）

| 轮次 | 主要错误 | 根因 |
|---|---|---|
| v1 | Mid Ops + Video Cut + 长 PRD card | 凭 PRD 文字自由发挥，没问通用约定 |
| v2 | `● Input/Output/Settings` section 标签 + Preset 移右栏 | 误读 "左 = 输入/输出/预览" 语义，把 universal frame 元素当 app 内 section |
| v3 | 回退 Preset 但留 section 标签 | partial 修正未到位 |
| v4 | URL 行 + toolbar 还是 full-width；Layer panel 只占 main row 高 | scheme E 范式 OK 但通用结构 partial 实现 |
| v5 | 通用结构仍未到位（URL 行/toolbar 还是全宽） | 预览空白对称化解决了视觉但没解决结构 |
| v6 | 结构修正到位 | 用户用 "X 结构，X 内再 Y 结构" 描述后才精确 |

**根因共性**：起手没要求用户描述结构层级 + 没索取通用约定参考图 + 没算几何上限。

---

## TVU 回流候选清单（待用户确认后再写入 TVU Design System）

> 以下规则**不是项目特有**，是从这次 6 轮 retrofit 抽象出来的通用 AI 工作约束。
> 用户拍板"是规则级"后再写入对应 TVU Design System 文件。本段只**整理**，不动 TVU 文件。

### 候选 1 · **MicroApps Universal Layout Contract** (新 M/T 规则)

- **建议落点**: `docs/internal/domain-tvu.md`（TVU 业务规则，跟 M3-M9 一组）
- **内容大纲**:
  - 任何 MicroApp 类 mockup 任务**默认遵循以下结构**：
    ```
    Top bar (full-width frozen)
    └── Main area (split L/R)
        ├── LEFT column (top-bottom 三段)
        │   ├── TOP: input URL row
        │   ├── MIDDLE: app-specific work area (视频预览 / 表单 / table 等)
        │   └── BOTTOM: action toolbar (preset / URL / Go Live 类)
        └── RIGHT column (full-height sidebar)
            └── settings / Layer panel / Transcode setting / ...
    ```
  - URL 行 + Bottom toolbar 宽度 = 左栏宽，**不**跨右栏
  - 右栏从 top bar 下方一直到帧底，**不**只占 main row
  - 已知实例：Standard Conversion（参考样本）/ Graphics Insertion v6
- **实证**: Graphics Insertion v1-v6 6 轮 retrofit；v4/v5 都 partial 实现这个 contract，v6 才精确
- **Acceptance**: 起手 MicroApp 类任务时，AI 必须 echo 这个结构给用户，确认是否适用本 app
- **Legacy ID 映射**: 无（新规则）

### 候选 2 · **Pre-Design Structure Echo Protocol** (新 process 规则)

- **建议落点**: `docs/internal/design-process.md`（process 规则）
- **内容大纲**:
  - 任何产品 UI mockup 任务起手，AI **必须输出结构理解 echo** 给用户校验：
    > "我理解的页面结构是：**X 结构**，X 内再分 **Y 结构**。" （用嵌套描述法）
  - 用户回 OK 后才进 Phase 0；否则反复 echo 直到达成共识
  - 这一步在 Pre-Phase 0 之前
- **实证**: Graphics Insertion v6 用户主动用 "左右结构，左边再上下" 描述后，AI 才精确实现 — 之前 v1-v5 都因为 AI 自己脑补结构而 partial 实现
- **Acceptance**: AI 起手第一个回复必含 "我理解的结构是 ..." 一句

### 候选 3 · **Geometric Upper-Bound Pre-flight** (新 process 规则)

- **建议落点**: `docs/internal/design-process.md`
- **内容大纲**:
  - 任务涉及几何约束（aspect ratio + side-by-side + frozen frame）时，AI **必须在画之前算几何上限并 echo**:
    > "几何上限：dual 16:9 并排 + 左栏可用宽 W + 右栏 frozen → 每个预览 max = W/2 - meter - gap。垂直最大 = max-w × 9/16。"
  - 提醒用户"如果想填满垂直，要么 (a) 缩右栏 (b) 加下方内容 (c) 接受对称留白"
- **实证**: Graphics Insertion v4/v5 都没算几何上限就开画，导致"空白太多"反馈 → v5 retrofit
- **Acceptance**: 涉及几何约束的任务，AI 起手必含一段"几何上限计算 + 留白预估"

### 候选 4 · **Universal Reference Image Request** (新 process 规则 / skill 起手协议补)

- **建议落点**: `docs/internal/design-process.md` + `tvu-design-mockup` skill 起手协议 step 0
- **内容大纲**:
  - broadcast/streaming/MicroApp 类任务起手时，若用户只给文字 PRD：
    > "有没有同产品系列已有的参考图 / 已发布的 sibling app screenshot？我需要继承通用约定。"
  - 没有参考图时不开画，等用户提供或明示"无参考、自由发挥"
- **实证**: Graphics Insertion v1-v3 都凭 PRD 文字自由发挥踩坑 → v4 用户主动提供 Standard Conversion 截图后才校正
- **Acceptance**: skill 起手 step 0 加 "若 broadcast/streaming app 类，必索取通用约定参考图"

### 候选 5 · **Retrospection File** (历史复盘归档)

- **建议落点**: `docs/internal/retrospection/2026-05-20-graphics-insertion-6-round-retrofit.md`
- **内容大纲**:
  - v1-v6 6 轮 iteration 完整 retrospect
  - 同源根因：起手没问通用约定参考图 + 没让用户描述结构层级 + 没算几何上限
  - 上述 4 条新规则的"实证"指向这份文件

---

## v2 spec revision (2026-05-20) — applied changes (historical)

1. **Video aspect fixed at 16:9** — PVW + PGM resized from 500×540 to **512×288** (ratio exactly 1.7778).
2. **No transition controls** — removed `Video Cut` button + the divider rectangle from mid-ops column. Mid-ops now contains only 3 layer/layout switchers + Overlay Cut (the sole action).
3. **Output area = Go Live only** — removed format/aspect-ratio dropdown from PGM bottom strip; Program label moved to the right side of PGM strip.
4. **Strict left/right layout contract** — left = Input (top) + Video Preview (middle) + Output (bottom); right = Settings (Default Preset + Layer panel). SRT URL moved into Input section. Default Preset moved into right Settings panel (was in bottom row before).
5. **M23 annotation refreshed** — 5 chips now reflect Input / Video Preview / Mid Ops · Overlay Cut / Output Go Live / Settings (Video Cut chip dropped). Connector tips re-targeted to new positions. Rules card rewritten with new sections (Background / Layout Contract / Core Requirements / Reference Comparison).
> **Figma file**: `Micro-Apps-20250923` (key `DtZcMkhNy6qh6jbQQnhreQ`)
> **Target page**: `Separate Graphics app PVW and PGM into two separate previews 20260519` (id `4083:10338`)
> **Reference frame (Before / current production)**: [`1747:2764`](https://www.figma.com/design/DtZcMkhNy6qh6jbQQnhreQ/Micro-Apps-20250923?node-id=1747-2764) — single-preview Graphics Insertion App

---

## 1 · Summary

Iterated the Graphics Insertion App from a **single-preview-with-PVW/PGM-toggle** workflow to a **side-by-side PVW + PGM dual-preview** workflow. Delivered on a fresh empty Figma page as a Before / After sibling pair plus a bilingual M23 PRD annotation layer.

- **Before frame** (`4105:85`) — clone of `1747:2764`, current production
- **After frame** (`4105:269`) — new dual preview design, 1920×1080
- **M23 annotation layer** — header chip + 5 state chips + 5 connectors + comprehensive PRD rules card (sections: Background / Core Requirements / Reference Comparison)

## 2 · Layout (After frame)

```
[ Top bar (TVU library instance, product-name = "Graphics Insertion") ]  y=0  h=56
[ SRT URL input row — input box/filled, dark theme, 1840w ]               y=88  h=38
─────────────────────────────────────────────────────────────────────────
LEFT (video area, x=40→1224, w=1184)              │  RIGHT (Layer panel, x=1260→1880)
 ┌────┬────────┬──┬────────┬────┐                  │  cloned from reference frame
 │ L  │  PVW   │M │  PGM   │ R  │                  │  Layer header + Add btn
 │meter│ 500w  │id │ 500w   │meter│                 │  + Widget 1 / Widget 2 cards
 │20w │ 540h  │96│ 540h    │20w │                  │
 │    │ 16:9  │  │ 16:9    │    │                  │
 │    │ green │  │ navy    │    │                  │
 │    │ grass │  │ CNN     │    │                  │
 │    │       │  │ chyron  │    │
 │    │ ┌Preview bar┐ │ ┌─Program bar─┐│
 │    │ 🎧Preview │  │ │Remove ovl|🎧Program|16:9▼│
 │    │  · Clear ovl│  │             │ │
 └────┴───────┴──┴───────┴────┘
─────────────────────────────────────────────────────────────────────────
[ Default Preset ▼ | srt://... input | Go Live ]      y=988  h=44
```

Mid-ops column (x=584, w=96, y=180→720):
1. Layer 1 (Layout icon, active green) — 56×56 icon button
2. Layer 2 (Grid view icon) — 56×56
3. Layer 3 (Sidebar icon) — 56×56
4. Overlay Cut (80×72, brand-green filling, icon=Cut/Hard cut + label below)
5. Video Cut (80×60, ghost gray, icon=Cut/Hard cut + label below)

## 3 · Phase 0 (M0) Mapping Table — final state

| Element | Source | Key | Variant | Status |
|---|---|---|---|---|
| Top bar | TVU library `Top bar` | `918b928e4541f1573de5c98c32b408af663d7f2f` | `Tag=After Login`, `Show Menu=false`, `Show Search box=false`, product-name overridden | ✅ verified |
| SRT URL Input | TVU library `input box/filled` | `1f513914bde7e5e2844e785eefe427f0693f6d20` | dark theme=on, size=M, feature=no | 🟡→ ✅ verified (variants: dark theme / status / enable / UX / size / feature / Content slot) |
| Button (Clear/Remove/Go Live) | TVU library `Button/dark M` | `12b38c8b68cd67dd3978e0d68712bc646f1e97c1` | per-use: ghost gray / ghost red / filling green; icon=left | ✅ verified (variant axes: icon / style / color / status / radius / fixed width) |
| PVW preview container | self-drawn FRAME (500×540, green-grass placeholder) | — | — | ⚠️ real gap — video player is not a library component scope; placeholder OK |
| PGM preview container | self-drawn FRAME (500×540, navy placeholder + CNN-style red chyron) | — | — | ⚠️ real gap (same as above) |
| Audio meter (L + R outer) | self-drawn FRAME with gradient bars + dB ticks | — | — | ⚠️ real gap — **`AudioMeter` component is a 🟡 library backlog candidate**; consider adding |
| PVW/PGM badge (green/red, "PVW" / "● PGM · ON AIR") | self-drawn chip on preview top-left | — | — | trivial overlay |
| `icon/audio/Headphone on` (PVW + PGM monitor) | TVU library icon | `365dbeff0b225a3242090f1ab77d0d6b10937d06` | — | ✅ verified |
| `icon/Cut/Hard cut` (Overlay/Video Cut) | TVU library icon | `5719c0da3a3ae194554071b9b025e8c0784485d3` | — | ✅ verified |
| `icon/mark/wait for delete` (Clear/Remove overlay) | TVU library icon | `833b867487a0f43356ed83ab3b537a4ffa686dc9` | — | ✅ verified |
| `icon/Preview/Layout` (Layer 1) | TVU library icon | `76f23233c100f9d2ffd941859ed2619ea3cc8b78` | — | ✅ verified |
| `icon/Preview/grid view` (Layer 2) | TVU library icon | `301206fa43b380236df529891c60088446721f7d` | — | ✅ verified |
| `icon/Preview/sidebar` (Layer 3) | TVU library icon | `2edf26729d98acafec5a981f73f2861e00662def` | — | ✅ verified |
| Format dropdown (16:9) | TVU library `select box/filled` | `ca2ff89d2fc24bad4cb29c8512d8102c04a2c352` | dark theme=on, default selection overridden to "16:9" | 🟡→ ✅ verified |
| Default Preset dropdown / SRT URL input / Go Live | cloned from reference Before frame's `Content` row (id `4105:130/Content`) | — | inherits reference contract | ✅ via clone (M21 visual contract preservation) |
| Layer panel (right) | cloned from reference Before frame's "Left" frame (id `4105:167`) | — | unchanged | ✅ via clone (M21) |
| M23 annotation chips + rules card | self-drawn navy `#2B2D42` per M23 verbatim | — | bilingual EN + Noto Sans SC 10px@0.45 opacity | ✅ per M23 / M23.6 / M33 |

### M0 ledger summary

- Element 行数: 22 distinct
- 🟡 命中: 3 (input box, select box, slider/audio-meter probe)
- 🟡→✅ 升级: 3 (input box, select box, Cut/Hard cut verified during build)
- ⚠️ 真 gap: 3 (PVW/PGM video container, Audio meter, video-player frame as composite)

## 4 · M35 Affordance Trace (mandatory 3-line)

```
1. Affordance: action-primary-broadcast (intent: 把 PVW overlay 切到 PGM 播出)
   → Overlay Cut button — TVU brand-green filling + icon/Cut/Hard cut (`5719c0da...`)

2. Affordance: action-secondary-broadcast (intent: 视频源硬切)
   → Video Cut button — ghost gray + icon/Cut/Hard cut

3. Affordance: dismissive (intent: 移除 PVW / PGM 已加的 overlay)
   Vocabulary scan: [icon/mark/wait-for-delete (✅ match), icon/Edit/Clip (semantic mismatch — clipping ≠ removing)]
   → Chosen: icon/mark/wait for delete (`833b867487a0f43356ed83ab3b537a4ffa686dc9`)
     - PVW side: ghost gray (neutral remove on edit-pane)
     - PGM side: ghost red (destructive — removes from on-air)
```

## 5 · Audit Results

### M-INTEGRITY (umbrella, all 3 sub-clauses)

| Sub | Result | Detail |
|---|---|---|
| §I1 Sibling layout consistency | ✅ pass — trivial | Empty target page, no sibling SECTION existed; Before / After pair is the established baseline |
| §I2 Sibling section overlap | ✅ pass — trivial | 0 SECTIONs on the target page |
| §I3 Children-bbox wrap | ✅ pass | After frame: 0 overflow (maxR=1920, maxB=1044 ≤ 1080); Rules card: 0 overflow (auto-layout VERTICAL hugs children) |

### M-COLOR (umbrella, all 3 sub-clauses)

| Sub | Result | Detail |
|---|---|---|
| §C1 Icon fill bound to Color Variable | ⚠️ partial | TVU library icons (Headphone / Cut / mark-delete / Preview/*) inherit library bindings; `icon/Search/Search` probed with `boundColor=true` ✓. Two icon paths show `boundColor=false` but those are TVU brand logo glyphs (the C1 exemption "third-party logo / app icon" applies). Custom self-drawn audio meter bars use gradient fills (no Color Variable binding for gradients — flagged for future) |
| §C2 State color discipline (hover ≠ brand) | ⚠️ not applicable — static mockup | No hover state mocks needed. If/when hover variants are added, must use `UX/Brand/Hover` (not `UX/Brand/Brand`) |
| §C3 BG-vs-Text grey discipline | ⚠️ deferred — **bind Layer_1 to After bg in next session** | After frame fill currently hex `#0a0a0a` (visually correct Layer_1). Mid-ops icon button backgrounds use hex `#2a2a2a` (Layer_3-ish). PVW/PGM placeholder fills (green grass / navy) are illustrative video content, not UI surfaces — C3 doesn't apply to video placeholders. **Action**: import `Color Type/Background/Layer_1` (key TBD via `search_design_system` with variable filter) and bind via Q2 two-step |

### M1 (Top bar)

✅ TVU library `Top bar` instance used. Show Menu / Show Search hidden. Product-name slot overridden to "Graphics Insertion". No self-drawn top bar.

### M21 (Sibling visual contract preservation)

✅ Before frame is a verbatim clone of `1747:2764`. After frame **preserves** the MicroApps invariant **"left = video preview / right = Layer panel"**. Bottom row (Default Preset / SRT URL / Go Live) is cloned from Before to preserve contract.

### M23 / M23.6 (Annotation protocol)

| Check | Result |
|---|---|
| Navy `#2B2D42` chips | ✅ all annotation elements |
| Accent `#33A4FD` (titles + connectors + left-stroke) | ✅ |
| ZH Noto Sans SC opacity 0.45, font-size EN -2px | ✅ Layout A-逐行 applied to header chip + 5 state chips + 3 rules-card sections |
| Header chip / Rules card 3px left accent stroke | ✅ rules card; header chip uses left-stroke pattern |
| Reconnect map written to `page.setSharedPluginData('ux_annotation', 'graphics_insertion_dual_preview_reconnect_map')` | ✅ 1069 bytes — 5 arrows with `tipCanvas` field per M23.6 |
| Connector tip accuracy | ⚠️ visual approximation — each connector uses 3-seg L routing (vertical-first), tip set to absolute coords of target element. Numerical post-audit not run (no `audit:consumer-mockup` token available in cwd) — recommend running `pnpm audit:mockup:integrity` from tvu-design-system repo with this fileKey/pageId next session |

### M33 (Annotation vs Product UI language isolation)

✅ All annotation chips + rules card = bilingual EN + ZH (Noto Sans SC @ 0.45 opacity). All product UI labels inside After frame = English single-language only (Preview / Program / Clear overlay / Remove overlay / Overlay Cut / Video Cut / 16:9 / Default Preset / Go Live). No product UI label contains Noto Sans SC.

### M32 / M30 (Library-first)

- TVU library components used: `Top bar`, `input box/filled`, `select box/filled`, `Button/dark M` (×3+ instances for Clear / Remove / Go Live / inherited from Before clone), 7 library icons.
- Custom drawn (with documented gap rationale): PVW + PGM video containers, L/R audio meters, mid-ops layer icon buttons (custom frame with library icon inside — could be replaced with `Button/dark M` icon-only variant in a follow-up; chose custom for visual control of active state).

## 6 · Backlog candidates / next session actions

1. **Bind `Color Type/Background/Layer_1` (and Layer_3 for mid-ops icon button bg) to the After frame + mid-ops button fills** — currently hex literals. Needed for full M-COLOR §C3 compliance. Variable key requires `search_design_system` query with `includeVariables: true` filter.
2. **🟡 Library backlog: `AudioMeter` component** — current implementation is custom-drawn (gradient stereo bars + dB tick text), and the same shape appears in the Before frame and likely other MicroApps with audio-monitoring needs. Worth promoting into TVU UX Design System library.
3. **Mid-ops layer buttons: refactor to `Button/dark M` icon-only variant** — preserves library contract; current custom frame is visually equivalent but doesn't carry library variant states (hover / active / disabled). The "active = brand green fill" semantic mismatches `Button` color axis (gray 1 / green / orange / red — green works but lacks proper "selected" status).
4. **Format dropdown options enumeration** — currently shows "16:9" only; product spec should enumerate full list (16:9 / 9:16 / 4:3 / 1:1 etc.) before dev implementation.
5. **Connector tip accuracy programmatic audit** — run `audit-mockup-integrity.mjs` (or successor) against this file with `pageId=4083:10338` to numerically verify the 5 connector tips fall inside their declared target bboxes (M23.6 acceptance).
6. **Empty-state mini frames** — currently no PVW/PGM empty / loading / error variant mocks. If devs need these, add Row 2 of state mini frames per M0 scope clarification.

## 7 · File state

- Target page `4083:10338` now contains 16 top-level children:
  - 2 frames (Before / After)
  - 2 small label chips (BEFORE / AFTER)
  - 1 header chip
  - 5 state-group GROUPs (each wrapping a state chip)
  - 5 VECTOR connectors
  - 1 PRD rules card

No SECTION created (kept page-level for simplicity given the empty starting state). If a future session wants section-level organization, wrap all above in a single SECTION named `Graphics Insertion · Dual Preview Spec` and run §I2 overlap probe before committing.

## 8 · Decision log (during build)

| Decision | User confirmed | Where |
|---|---|---|
| Before / After sibling pair layout (vs After-only) | ✅ | Q1 in session |
| M23 navy annotation panel + connectors (vs separate prose card) | ✅ | Q2 |
| Mid-ops column natural order from reference image 2 (3 layer btns → Overlay Cut → Video Cut) | ✅ | Q3 |
| Layout invariant "left = video / right = Layer panel" must be preserved (MicroApps convention) | ✅ | Q4 follow-up clarification |
| Overlay Cut uses TVU brand green (not gradient filling green variant) | ✅ | Approval after M0 mapping |
| Before frame = instance/clone of `1747:2764` (vs duplicate vs screenshot) | ✅ | M0 follow-up |

## 9 · Time + cost rough estimate

- 6 `use_figma` build batches + 4 search calls + 2 metadata probes + final screenshot
- Approximate Figma plugin API time: ~4–6 minutes wallclock
- One M23 navy chip with bilingual styling per session takes 2 use_figma batches in worst case — this delivery achieved ~6 annotation elements in 2 batches (header + 5 state + connectors + rules card spread across 3 batches D1-D3).

## 10 · Open questions for product owner / dev review

1. **Overlay Cut behavior on rapid double-tap** — should second click cancel pending cut, or queue a re-cut?
2. **Audio meter source binding** — does PVW meter follow PVW source, or follow the selected layer within PVW? (Affects whether dB readings change as user navigates Layer panel.)
3. **Format dropdown — frame-only or also re-encode output stream?** — i.e. is 16:9/9:16 a viewport setting or an actual SRT output transcode parameter?
4. **Remove overlay scope** — does it remove all overlays at once, or only the topmost active overlay on PGM?
5. **3 layer/template buttons** — are these PVW-side preset switches, or scene-template thumbnails (à la NDI scene switching)?

---

**Co-author**: Claude Opus 4.7 (1M context) — `@TVU mockup` skill session
