diff --git a/CLAUDE.md b/CLAUDE.md index 53b3ccb..3e0b715 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1737,3 +1737,13 @@ a preservation requirement rather than a claim of complete web simulation. Keep it distinct from the simulated mockup. Synthetic API captures exclude GPU video/scopes; installed, physical/high-DPI and live meeting acceptance remain open. Its feedback link reuses the existing sources-table-v1 private form. + +## Volt graphics review page + +`site-assets/reviews/volt-graphics/` is the standalone Pro graphics design review +(no main-header link). Its images are native DirectWrite/D2D/WIC reference +thumbnails; its browser controls simulate workflows and do not control the app. +`review-feedback.js` isolates `volt-graphics-v1` notes in the existing private KV +service. Rebuild with `npm run build`; publish through Deploy Site when the local +Cloudflare login is unavailable. Do not describe this page as an installed beta +or claim full-output qualification from its reference images. diff --git a/review-feedback.js b/review-feedback.js index 62cfe26..9ecfcd2 100644 --- a/review-feedback.js +++ b/review-feedback.js @@ -1,5 +1,5 @@ const AREAS = new Set(['Overall workflow','Source list and identity','Layout and compact view','Picture controls and live edits','Audio controls','Lower-third text','Live versus draft behavior','Health and status clarity']); -const REVIEWS = new Map([['sources-table-v1',AREAS],['sources-workspace-v1',AREAS],['workflow-review-v1',new Set(['Overall workflow','Source list and identity','Lower-third designer','Grade curves and scope ROI','Preservation requirements'])],['operator-uiux-v1',new Set(['Overall workflow','Starter scenes','Lower-third designer','Shared sliders and resets','Grade curves and scope ROI','Settings and Health','Source list and identity'])]]); +const REVIEWS = new Map([['volt-graphics-v1',new Set(['Overall workflow','Template library','Live operation','Designer controls','Styles and brand','Animation and clocks','Automation rules','Preservation and gaps'])],['sources-table-v1',AREAS],['sources-workspace-v1',AREAS],['workflow-review-v1',new Set(['Overall workflow','Source list and identity','Lower-third designer','Grade curves and scope ROI','Preservation requirements'])],['operator-uiux-v1',new Set(['Overall workflow','Starter scenes','Lower-third designer','Shared sliders and resets','Grade curves and scope ROI','Settings and Health','Source list and identity'])]]); const VERDICTS = new Set(['changes','approve','question']); const SCENARIOS = new Set(['populated','offline','returns','unassigned']); const response = (value,status=200)=>new Response(JSON.stringify(value),{status,headers:{'content-type':'application/json; charset=utf-8','cache-control':'no-store','x-content-type-options':'nosniff','x-robots-tag':'noindex, nofollow'}}); diff --git a/site-assets/reviews/volt-graphics/catalog.json b/site-assets/reviews/volt-graphics/catalog.json new file mode 100644 index 0000000..e7df7fd --- /dev/null +++ b/site-assets/reviews/volt-graphics/catalog.json @@ -0,0 +1,1617 @@ +{ + "nativeBaseCommit": "ef59d88", + "source": "Native DirectWrite / D2D / WIC reference render, development worktree 2026-10-17", + "limitations": "Native thumbnails of reference appearance, not full-resolution output captures or installed app screenshots. Browser controls simulate intended workflows.", + "templates": [ + { + "family": "lower-third", + "name": "compact-solid", + "runtime": "compatibility", + "templateId": "compact-solid", + "templateVersion": 1, + "thumbnail": { + "appearance": "reference", + "backend": "d3d11-native", + "height": 36, + "reason": "", + "state": "ready", + "width": 320, + "url": "renders/compact-solid.png" + } + }, + { + "family": "lower-third", + "name": "minimal-accent", + "runtime": "compatibility", + "templateId": "minimal-accent", + "templateVersion": 1, + "thumbnail": { + "appearance": "reference", + "backend": "d3d11-native", + "height": 35, + "reason": "", + "state": "ready", + "width": 320, + "url": "renders/minimal-accent.png" + } + }, + { + "family": "lower-third", + "name": "broadcast", + "runtime": "compatibility", + "templateId": "broadcast", + "templateVersion": 1, + "thumbnail": { + "appearance": "reference", + "backend": "d3d11-native", + "height": 35, + "reason": "", + "state": "ready", + "width": 320, + "url": "renders/broadcast.png" + } + }, + { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "bounds": { + "height": 288, + "width": 1440 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "center", + "scale": 1, + "x": 0, + "y": 0 + }, + "definition": { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "bounds": { + "height": 288, + "width": 1440 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "center", + "scale": 1, + "x": 0, + "y": 0 + }, + "family": "title", + "fields": [ + { + "default": "Welcome", + "id": "heading", + "maxLength": 256, + "required": true, + "type": "string" + }, + { + "default": "Live conversation", + "id": "subtitle", + "maxLength": 512, + "type": "string" + }, + { + "default": 64, + "id": "text-size", + "maximum": 120, + "minimum": 24, + "type": "number" + } + ], + "layers": [ + { + "cornerRadius": 18, + "fill": { + "token": "brand.primary" + }, + "height": 288, + "id": "plate", + "type": "rect", + "width": 1440, + "x": 0, + "y": 0 + }, + { + "align": "center", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": { + "field": "text-size" + }, + "fontWeight": 600, + "height": 100, + "id": "heading-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "heading" + }, + "type": "text", + "width": 1344, + "x": 48, + "y": 52 + }, + { + "align": "center", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 32, + "fontWeight": 600, + "height": 58, + "id": "subtitle-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "subtitle" + }, + "type": "text", + "width": 1344, + "x": 48, + "y": 174 + } + ], + "name": "Centered title", + "schemaVersion": 1, + "templateId": "centered-title", + "templateVersion": 1 + }, + "family": "title", + "fields": [ + { + "default": "Welcome", + "id": "heading", + "maxLength": 256, + "required": true, + "type": "string" + }, + { + "default": "Live conversation", + "id": "subtitle", + "maxLength": 512, + "type": "string" + }, + { + "default": 64, + "id": "text-size", + "maximum": 120, + "minimum": 24, + "type": "number" + } + ], + "layers": [ + { + "cornerRadius": 18, + "fill": { + "token": "brand.primary" + }, + "height": 288, + "id": "plate", + "type": "rect", + "width": 1440, + "x": 0, + "y": 0 + }, + { + "align": "center", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": { + "field": "text-size" + }, + "fontWeight": 600, + "height": 100, + "id": "heading-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "heading" + }, + "type": "text", + "width": 1344, + "x": 48, + "y": 52 + }, + { + "align": "center", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 32, + "fontWeight": 600, + "height": 58, + "id": "subtitle-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "subtitle" + }, + "type": "text", + "width": 1344, + "x": 48, + "y": 174 + } + ], + "manifestHash": "64961187a2f04090509a8332b1917f0b13737d7ab1f1a5609f5579f07caf84b0", + "name": "Centered title", + "runtime": "declarative", + "schemaVersion": 1, + "templateId": "centered-title", + "templateVersion": 1, + "thumbnail": { + "appearance": "reference", + "backend": "d3d11-native", + "height": 64, + "reason": "", + "state": "ready", + "width": 320, + "url": "renders/centered-title.png" + } + }, + { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "bounds": { + "height": 150, + "width": 420 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "upper-right", + "scale": 1, + "x": -64, + "y": 48 + }, + "definition": { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "bounds": { + "height": 150, + "width": 420 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "upper-right", + "scale": 1, + "x": -64, + "y": 48 + }, + "family": "clock", + "fields": [ + { + "default": "LIVE", + "id": "label", + "maxLength": 128, + "type": "string" + }, + { + "default": "00:00:00", + "id": "time", + "maxLength": 32, + "required": true, + "type": "string" + }, + { + "default": 56, + "id": "text-size", + "maximum": 90, + "minimum": 24, + "type": "number" + } + ], + "layers": [ + { + "cornerRadius": 12, + "fill": { + "token": "brand.primary" + }, + "height": 150, + "id": "plate", + "type": "rect", + "width": 420, + "x": 0, + "y": 0 + }, + { + "align": "center", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 24, + "fontWeight": 600, + "height": 38, + "id": "label-text", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "label" + }, + "type": "text", + "width": 380, + "x": 20, + "y": 12 + }, + { + "align": "center", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": { + "field": "text-size" + }, + "fontWeight": 600, + "height": 76, + "id": "clock-text", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "time" + }, + "type": "text", + "width": 380, + "x": 20, + "y": 55 + } + ], + "name": "Clock and countdown", + "schemaVersion": 1, + "templateId": "clock-panel", + "templateVersion": 1 + }, + "family": "clock", + "fields": [ + { + "default": "LIVE", + "id": "label", + "maxLength": 128, + "type": "string" + }, + { + "default": "00:00:00", + "id": "time", + "maxLength": 32, + "required": true, + "type": "string" + }, + { + "default": 56, + "id": "text-size", + "maximum": 90, + "minimum": 24, + "type": "number" + } + ], + "layers": [ + { + "cornerRadius": 12, + "fill": { + "token": "brand.primary" + }, + "height": 150, + "id": "plate", + "type": "rect", + "width": 420, + "x": 0, + "y": 0 + }, + { + "align": "center", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 24, + "fontWeight": 600, + "height": 38, + "id": "label-text", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "label" + }, + "type": "text", + "width": 380, + "x": 20, + "y": 12 + }, + { + "align": "center", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": { + "field": "text-size" + }, + "fontWeight": 600, + "height": 76, + "id": "clock-text", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "time" + }, + "type": "text", + "width": 380, + "x": 20, + "y": 55 + } + ], + "manifestHash": "15895c8d46681f06592f93063bf3342a176d981451e48e82340a81320a970f89", + "name": "Clock and countdown", + "runtime": "declarative", + "schemaVersion": 1, + "templateId": "clock-panel", + "templateVersion": 1, + "thumbnail": { + "appearance": "reference", + "backend": "d3d11-native", + "height": 114, + "reason": "", + "state": "ready", + "width": 320, + "url": "renders/clock-panel.png" + } + }, + { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "assets": [ + { + "file": "assets/5c998247459cadf4c7229c685d5ca8257e92e1154a19767a4be874c69def0d09.png", + "id": "logo", + "sha256": "5c998247459cadf4c7229c685d5ca8257e92e1154a19767a4be874c69def0d09" + } + ], + "bounds": { + "height": 192, + "width": 192 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "upper-right", + "scale": 1, + "x": -64, + "y": 48 + }, + "definition": { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "assets": [ + { + "file": "assets/5c998247459cadf4c7229c685d5ca8257e92e1154a19767a4be874c69def0d09.png", + "id": "logo", + "sha256": "5c998247459cadf4c7229c685d5ca8257e92e1154a19767a4be874c69def0d09" + } + ], + "bounds": { + "height": 192, + "width": 192 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "upper-right", + "scale": 1, + "x": -64, + "y": 48 + }, + "family": "bug", + "fields": [ + { + "default": "logo", + "id": "logo", + "type": "image" + }, + { + "default": true, + "id": "show-logo", + "type": "boolean" + } + ], + "layers": [ + { + "align": "center", + "asset": { + "field": "logo" + }, + "fit": "contain", + "height": 168, + "id": "logo-image", + "type": "image", + "verticalAlign": "center", + "visible": { + "field": "show-logo" + }, + "width": 168, + "x": 12, + "y": 12 + } + ], + "name": "Corner logo bug", + "schemaVersion": 1, + "templateId": "corner-logo", + "templateVersion": 1 + }, + "family": "bug", + "fields": [ + { + "default": "logo", + "id": "logo", + "type": "image" + }, + { + "default": true, + "id": "show-logo", + "type": "boolean" + } + ], + "layers": [ + { + "align": "center", + "asset": { + "field": "logo" + }, + "fit": "contain", + "height": 168, + "id": "logo-image", + "type": "image", + "verticalAlign": "center", + "visible": { + "field": "show-logo" + }, + "width": 168, + "x": 12, + "y": 12 + } + ], + "manifestHash": "5e2a31231137a532fe771b84a56efa4e0fe9eb9f23c36975ce5ef177c9cd63b2", + "name": "Corner logo bug", + "runtime": "declarative", + "schemaVersion": 1, + "templateId": "corner-logo", + "templateVersion": 1, + "thumbnail": { + "appearance": "reference", + "backend": "d3d11-native", + "height": 180, + "reason": "", + "state": "ready", + "width": 180, + "url": "renders/corner-logo.png" + } + }, + { + "animations": { + "in": { + "direction": "left", + "durationMs": 400, + "easing": "ease-out", + "type": "slide" + }, + "out": { + "durationMs": 300, + "easing": "linear", + "type": "fade" + } + }, + "bounds": { + "height": 176, + "width": 1050 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "definition": { + "animations": { + "in": { + "direction": "left", + "durationMs": 400, + "easing": "ease-out", + "type": "slide" + }, + "out": { + "durationMs": 300, + "easing": "linear", + "type": "fade" + } + }, + "bounds": { + "height": 176, + "width": 1050 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "family": "lower-third", + "fields": [ + { + "bindable": true, + "default": "", + "id": "name", + "maxLength": 256, + "required": true, + "type": "string" + }, + { + "bindable": true, + "default": "", + "id": "title", + "maxLength": 512, + "required": false, + "type": "string" + } + ], + "layers": [ + { + "cornerRadius": 8, + "fill": { + "token": "brand.primary" + }, + "height": 176, + "id": "plate", + "opacity": 0.92, + "type": "rect", + "width": 1050, + "x": 0, + "y": 0 + }, + { + "children": [ + { + "align": "left", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 42, + "fontWeight": 600, + "height": 62, + "id": "name-text", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "name" + }, + "type": "text", + "width": 1002 + }, + { + "align": "left", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimaryMuted" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 28, + "fontWeight": 400, + "height": 42, + "id": "title-text", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "title" + }, + "type": "text", + "width": 1002 + } + ], + "flow": "vertical", + "gap": 8, + "height": 136, + "id": "text-stack", + "type": "group", + "width": 1002, + "x": 24, + "y": 20 + } + ], + "name": "Corporate lower third", + "schemaVersion": 1, + "templateId": "corporate-lower-third", + "templateVersion": 1 + }, + "family": "lower-third", + "fields": [ + { + "bindable": true, + "default": "", + "id": "name", + "maxLength": 256, + "required": true, + "type": "string" + }, + { + "bindable": true, + "default": "", + "id": "title", + "maxLength": 512, + "required": false, + "type": "string" + } + ], + "layers": [ + { + "cornerRadius": 8, + "fill": { + "token": "brand.primary" + }, + "height": 176, + "id": "plate", + "opacity": 0.92, + "type": "rect", + "width": 1050, + "x": 0, + "y": 0 + }, + { + "children": [ + { + "align": "left", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 42, + "fontWeight": 600, + "height": 62, + "id": "name-text", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "name" + }, + "type": "text", + "width": 1002 + }, + { + "align": "left", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimaryMuted" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 28, + "fontWeight": 400, + "height": 42, + "id": "title-text", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "title" + }, + "type": "text", + "width": 1002 + } + ], + "flow": "vertical", + "gap": 8, + "height": 136, + "id": "text-stack", + "type": "group", + "width": 1002, + "x": 24, + "y": 20 + } + ], + "manifestHash": "b4192a72419d4d18e94d49c9a7df7770953850a566ba866c3a89cf55a43059fc", + "name": "Corporate lower third", + "runtime": "declarative", + "schemaVersion": 1, + "templateId": "corporate-lower-third", + "templateVersion": 1, + "thumbnail": { + "appearance": "reference", + "backend": "d3d11-native", + "height": 54, + "reason": "", + "state": "ready", + "width": 320, + "url": "renders/corporate-lower-third.png" + } + }, + { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "assets": [ + { + "file": "assets/5c998247459cadf4c7229c685d5ca8257e92e1154a19767a4be874c69def0d09.png", + "id": "logo", + "sha256": "5c998247459cadf4c7229c685d5ca8257e92e1154a19767a4be874c69def0d09" + } + ], + "bounds": { + "height": 168, + "width": 1060 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "lower-left", + "scale": 1, + "x": 96, + "y": -54 + }, + "definition": { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "assets": [ + { + "file": "assets/5c998247459cadf4c7229c685d5ca8257e92e1154a19767a4be874c69def0d09.png", + "id": "logo", + "sha256": "5c998247459cadf4c7229c685d5ca8257e92e1154a19767a4be874c69def0d09" + } + ], + "bounds": { + "height": 168, + "width": 1060 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "lower-left", + "scale": 1, + "x": 96, + "y": -54 + }, + "family": "lower-third", + "fields": [ + { + "bindable": true, + "default": "Example guest", + "id": "name", + "maxLength": 256, + "required": true, + "type": "string" + }, + { + "bindable": true, + "default": "Producer", + "id": "title", + "maxLength": 512, + "type": "string" + }, + { + "default": 42, + "id": "text-size", + "maximum": 100, + "minimum": 16, + "type": "number" + }, + { + "default": "logo", + "id": "logo", + "type": "image" + }, + { + "default": true, + "id": "show-logo", + "type": "boolean" + } + ], + "layers": [ + { + "cornerRadius": 12, + "fill": { + "token": "brand.primary" + }, + "height": 168, + "id": "plate", + "type": "rect", + "width": 1060, + "x": 0, + "y": 0 + }, + { + "fill": { + "token": "brand.accent" + }, + "height": 168, + "id": "accent", + "type": "rect", + "width": 8, + "x": 0, + "y": 0 + }, + { + "align": "center", + "asset": { + "field": "logo" + }, + "fit": "contain", + "height": 120, + "id": "logo-image", + "type": "image", + "verticalAlign": "center", + "visible": { + "field": "show-logo" + }, + "width": 120, + "x": 24, + "y": 24 + }, + { + "align": "left", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": { + "field": "text-size" + }, + "fontWeight": 600, + "height": 62, + "id": "name-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "name" + }, + "type": "text", + "width": 860, + "x": 168, + "y": 27 + }, + { + "align": "left", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 28, + "fontWeight": 600, + "height": 42, + "id": "secondary-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "title" + }, + "type": "text", + "width": 860, + "x": 168, + "y": 94 + } + ], + "name": "Logo accent lower third", + "schemaVersion": 1, + "templateId": "logo-accent", + "templateVersion": 1 + }, + "family": "lower-third", + "fields": [ + { + "bindable": true, + "default": "Example guest", + "id": "name", + "maxLength": 256, + "required": true, + "type": "string" + }, + { + "bindable": true, + "default": "Producer", + "id": "title", + "maxLength": 512, + "type": "string" + }, + { + "default": 42, + "id": "text-size", + "maximum": 100, + "minimum": 16, + "type": "number" + }, + { + "default": "logo", + "id": "logo", + "type": "image" + }, + { + "default": true, + "id": "show-logo", + "type": "boolean" + } + ], + "layers": [ + { + "cornerRadius": 12, + "fill": { + "token": "brand.primary" + }, + "height": 168, + "id": "plate", + "type": "rect", + "width": 1060, + "x": 0, + "y": 0 + }, + { + "fill": { + "token": "brand.accent" + }, + "height": 168, + "id": "accent", + "type": "rect", + "width": 8, + "x": 0, + "y": 0 + }, + { + "align": "center", + "asset": { + "field": "logo" + }, + "fit": "contain", + "height": 120, + "id": "logo-image", + "type": "image", + "verticalAlign": "center", + "visible": { + "field": "show-logo" + }, + "width": 120, + "x": 24, + "y": 24 + }, + { + "align": "left", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": { + "field": "text-size" + }, + "fontWeight": 600, + "height": 62, + "id": "name-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "name" + }, + "type": "text", + "width": 860, + "x": 168, + "y": 27 + }, + { + "align": "left", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 28, + "fontWeight": 600, + "height": 42, + "id": "secondary-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "title" + }, + "type": "text", + "width": 860, + "x": 168, + "y": 94 + } + ], + "manifestHash": "298a499c42f5adceacaaa38f58a21137fffcc0155e7be79e8fbd2dce9f6279f9", + "name": "Logo accent lower third", + "runtime": "declarative", + "schemaVersion": 1, + "templateId": "logo-accent", + "templateVersion": 1, + "thumbnail": { + "appearance": "reference", + "backend": "d3d11-native", + "height": 51, + "reason": "", + "state": "ready", + "width": 320, + "url": "renders/logo-accent.png" + } + }, + { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "bounds": { + "height": 148, + "width": 1120 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "lower-left", + "scale": 1, + "x": 96, + "y": -54 + }, + "definition": { + "animations": { + "in": { + "durationMs": 250, + "easing": "ease-out", + "type": "fade" + }, + "out": { + "durationMs": 200, + "easing": "ease-in", + "type": "fade" + } + }, + "bounds": { + "height": 148, + "width": 1120 + }, + "brandTokens": [ + "brand.primary", + "brand.onPrimary", + "brand.onPrimaryMuted", + "brand.fontBody", + "brand.accent" + ], + "canvas": { + "height": 1080, + "width": 1920 + }, + "defaultPlacement": { + "anchor": "lower-left", + "scale": 1, + "x": 96, + "y": -54 + }, + "family": "lower-third", + "fields": [ + { + "bindable": true, + "default": "Example guest", + "id": "name", + "maxLength": 256, + "required": true, + "type": "string" + }, + { + "bindable": true, + "default": "Producer", + "id": "title", + "maxLength": 512, + "type": "string" + }, + { + "default": 42, + "id": "text-size", + "maximum": 100, + "minimum": 16, + "type": "number" + } + ], + "layers": [ + { + "fill": { + "token": "brand.accent" + }, + "height": 132, + "id": "accent", + "type": "rect", + "width": 6, + "x": 0, + "y": 0 + }, + { + "align": "left", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": { + "field": "text-size" + }, + "fontWeight": 600, + "height": 64, + "id": "name-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "name" + }, + "type": "text", + "width": 1090, + "x": 24, + "y": 8 + }, + { + "align": "left", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 28, + "fontWeight": 600, + "height": 42, + "id": "secondary-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "title" + }, + "type": "text", + "width": 1090, + "x": 24, + "y": 82 + } + ], + "name": "Transparent name", + "schemaVersion": 1, + "templateId": "transparent-name", + "templateVersion": 1 + }, + "family": "lower-third", + "fields": [ + { + "bindable": true, + "default": "Example guest", + "id": "name", + "maxLength": 256, + "required": true, + "type": "string" + }, + { + "bindable": true, + "default": "Producer", + "id": "title", + "maxLength": 512, + "type": "string" + }, + { + "default": 42, + "id": "text-size", + "maximum": 100, + "minimum": 16, + "type": "number" + } + ], + "layers": [ + { + "fill": { + "token": "brand.accent" + }, + "height": 132, + "id": "accent", + "type": "rect", + "width": 6, + "x": 0, + "y": 0 + }, + { + "align": "left", + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": { + "field": "text-size" + }, + "fontWeight": 600, + "height": 64, + "id": "name-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "name" + }, + "type": "text", + "width": 1090, + "x": 24, + "y": 8 + }, + { + "align": "left", + "collapseWhenEmpty": true, + "color": { + "token": "brand.onPrimary" + }, + "font": { + "token": "brand.fontBody" + }, + "fontSize": 28, + "fontWeight": 600, + "height": 42, + "id": "secondary-label", + "lineHeight": 1.2, + "maxLines": 1, + "overflow": "ellipsis", + "text": { + "field": "title" + }, + "type": "text", + "width": 1090, + "x": 24, + "y": 82 + } + ], + "manifestHash": "d68b3e08ded3c4497c2f921ab5afb8ad441dfdc6001c23f9fff86ad2a8dee593", + "name": "Transparent name", + "runtime": "declarative", + "schemaVersion": 1, + "templateId": "transparent-name", + "templateVersion": 1, + "thumbnail": { + "appearance": "reference", + "backend": "d3d11-native", + "height": 42, + "reason": "", + "state": "ready", + "width": 320, + "url": "renders/transparent-name.png" + } + } + ] +} diff --git a/site-assets/reviews/volt-graphics/index.html b/site-assets/reviews/volt-graphics/index.html new file mode 100644 index 0000000..bea1ac3 --- /dev/null +++ b/site-assets/reviews/volt-graphics/index.html @@ -0,0 +1,19 @@ +Volt Graphics · CoreVideo review +
COREVIDEO PRO
PRODUCT REVIEW / 01 17 OCT 2026
Leave feedback ↗
+

OVERLAYS · LOWER THIRDS · BRAND · AUTOMATION

Volt Graphics.

Build a look privately. Cue it with confidence.
Put it on air when you decide.

+ +

01 / THE WORKSPACE

One library. A private canvas. Explicit live controls.

BROWSER SIMULATION
+
+
+
PRIVATE DRAFTChoose a look
ACCEPTED CUENothing cued
PROGRAMHidden
+
Private native reference
EXAMPLE SOURCE · NOT CONNECTED TO A MEETING
Native rendered graphic reference1920 × 1080 reference canvas
+
Native thumbnail · reference appearance. Not a full-resolution output capture.PRIVATE

Choose a look to explore. Nothing is on air.

+
+ +
+
+

02 / REVIEW ONE REAL TASK

Introduce a guest, then change their title.

1

Choose & bind

Select Logo accent. Create a hidden cue. Choose the exact current subject; source name/title overrides and explicit blanks remain available.

2

Build privately

Edit text, style and placement. Open Design layers for text boxes, groups, images, fills and gradients. Compare and Undo remain local.

3

Cue, then Show

Cue accepts a complete revision on Preview. Show puts that Cue on Program after native preparation. Editing a later draft cannot change the accepted Cue.

4

Update & recover

Change the title, then Update on air. Hide or Clear. Save and restore hidden; explicitly rebind sources and re-arm automation.

Review question: can you tell, at every step, what is private, what is cued, and what is actually on Program?

Leave workflow feedback ↗
+

03 / FULL GRAPHICS OPTIONS

The controls, grouped by the job.

+

04 / PRESERVATION & ACCEPTANCE

Keep the wins. Make the gaps visible.

PRESERVE

Existing production behavior

  • All three legacy looks, saved appearances, source naming and intentionally blank secondary lines.
  • Scene/Tiles layers, transforms, grades and scopes-only ROI.
  • Captions and the webcam-only OH framer/LUFS overlay retain their separate controls.
  • Source ISOs stay clean. Graphics do not alter recording, stream destinations, camera registration or audio settings.
  • Old/new lower-third authorities never render the same family together.
STILL TO QUALIFY

This is not a finished beta claim

  • Remaining package/logo repair, saved workflow and migration integration.
  • Qualified automation, manual priority and the director-to-native execution trace.
  • Complete cue-rack polish and end-to-end native UI workflow review.
  • Enabled-output pixels and scheduled deadlines, packaged launch, and sustained real-meeting acceptance.
  • Windows evidence does not establish Metal/macOS or physical-display continuity.

The installed app has not been replaced. Your design feedback will shape the complete review candidate; no issue closes from approving this webpage.

+

05 / YOUR REVIEW

What should feel different?

No login needed. Submitted notes are saved privately for CoreVideo for 180 days. Unsent drafts stay in this browser. Mention the look, workflow step or control you mean.

+
\ No newline at end of file diff --git a/site-assets/reviews/volt-graphics/renders/broadcast.png b/site-assets/reviews/volt-graphics/renders/broadcast.png new file mode 100644 index 0000000..7e95e75 Binary files /dev/null and b/site-assets/reviews/volt-graphics/renders/broadcast.png differ diff --git a/site-assets/reviews/volt-graphics/renders/centered-title.png b/site-assets/reviews/volt-graphics/renders/centered-title.png new file mode 100644 index 0000000..256ee24 Binary files /dev/null and b/site-assets/reviews/volt-graphics/renders/centered-title.png differ diff --git a/site-assets/reviews/volt-graphics/renders/clock-panel.png b/site-assets/reviews/volt-graphics/renders/clock-panel.png new file mode 100644 index 0000000..04553f8 Binary files /dev/null and b/site-assets/reviews/volt-graphics/renders/clock-panel.png differ diff --git a/site-assets/reviews/volt-graphics/renders/compact-solid.png b/site-assets/reviews/volt-graphics/renders/compact-solid.png new file mode 100644 index 0000000..38eea28 Binary files /dev/null and b/site-assets/reviews/volt-graphics/renders/compact-solid.png differ diff --git a/site-assets/reviews/volt-graphics/renders/corner-logo.png b/site-assets/reviews/volt-graphics/renders/corner-logo.png new file mode 100644 index 0000000..ba364e6 Binary files /dev/null and b/site-assets/reviews/volt-graphics/renders/corner-logo.png differ diff --git a/site-assets/reviews/volt-graphics/renders/corporate-lower-third.png b/site-assets/reviews/volt-graphics/renders/corporate-lower-third.png new file mode 100644 index 0000000..91c5ed1 Binary files /dev/null and b/site-assets/reviews/volt-graphics/renders/corporate-lower-third.png differ diff --git a/site-assets/reviews/volt-graphics/renders/logo-accent.png b/site-assets/reviews/volt-graphics/renders/logo-accent.png new file mode 100644 index 0000000..6946504 Binary files /dev/null and b/site-assets/reviews/volt-graphics/renders/logo-accent.png differ diff --git a/site-assets/reviews/volt-graphics/renders/minimal-accent.png b/site-assets/reviews/volt-graphics/renders/minimal-accent.png new file mode 100644 index 0000000..28104ef Binary files /dev/null and b/site-assets/reviews/volt-graphics/renders/minimal-accent.png differ diff --git a/site-assets/reviews/volt-graphics/renders/transparent-name.png b/site-assets/reviews/volt-graphics/renders/transparent-name.png new file mode 100644 index 0000000..f687429 Binary files /dev/null and b/site-assets/reviews/volt-graphics/renders/transparent-name.png differ diff --git a/site-assets/reviews/volt-graphics/review.css b/site-assets/reviews/volt-graphics/review.css new file mode 100644 index 0000000..2ba66d1 --- /dev/null +++ b/site-assets/reviews/volt-graphics/review.css @@ -0,0 +1 @@ +:root{color-scheme:dark;--bg:#101216;--panel:#191d24;--panel2:#202630;--line:#303845;--text:#e8edf4;--muted:#a1adbd;--mint:#5ce2be;--amber:#f0c27a}*{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:25px}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.55 'Segoe UI',system-ui,sans-serif}button,input,select,textarea{font:inherit}button{cursor:pointer;border:1px solid #424d5b;background:#262d38;color:var(--text);border-radius:6px;padding:8px 11px;transition:background .13s}button:hover{background:#354153}button:disabled{cursor:default;opacity:.42}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible{outline:2px solid var(--mint);outline-offset:3px}input,select,textarea{width:100%;min-width:0;border:1px solid #414b59;border-radius:5px;color:var(--text);background:#11161d;padding:8px 10px}input[type=checkbox]{width:auto;accent-color:var(--mint)}input[type=range]{padding:0;border:none;accent-color:var(--mint)}input[type=color]{height:35px;padding:3px}label{display:block;font-size:12px;color:#b8c3d0;margin:10px 0}label input,label select{margin-top:5px}.inline{display:flex;align-items:center;gap:6px;margin:0}.inline input{margin:0}p{margin:0 0 12px}a{color:var(--mint);text-decoration:none}header{max-width:1700px;margin:auto;display:flex;align-items:center;justify-content:space-between;padding:25px 40px;border-bottom:1px solid var(--line)}.wordmark{font-size:17px;font-weight:750;letter-spacing:1px;color:white}.wordmark span{color:var(--mint);font-size:10px;vertical-align:top}.review-label{font-size:11px;letter-spacing:1.5px;color:#c9d2df}.review-label span{color:#7f8b9c;margin-left:18px}.feedback-link{font-size:13px}main{max-width:1700px;padding:0 40px;margin:auto}.intro{display:flex;justify-content:space-between;align-items:center;gap:50px;padding:58px 0 40px}.eyebrow{font-size:10px;font-weight:700;letter-spacing:2px;color:var(--mint);margin:0 0 12px}h1{font-size:clamp(38px,5vw,70px);line-height:1.05;letter-spacing:-2.5px;margin:0 0 18px}h2{font-size:27px;letter-spacing:-.6px;line-height:1.25;margin:0 0 18px}h3{font-size:14px;line-height:1.4;margin:0 0 10px}.lede{font-size:21px;color:#b6c3d3;line-height:1.5}.intro-note{max-width:390px;color:#aeb9c8;font-size:13px;border-left:1px solid #455062;padding-left:22px}.badge{display:inline-block;border:1px solid #42515f;color:#bac8d5;letter-spacing:.65px;font-size:9px;font-weight:700;padding:4px 7px;border-radius:4px;white-space:normal}.badge.amber{border-color:#6a5233;color:var(--amber)}.intro-note .badge{margin-bottom:12px}.review-nav{display:flex;gap:30px;flex-wrap:wrap;border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:16px 0;margin-bottom:42px;font-size:12px}.review-nav a{color:#b4c0ce}.section-heading{display:flex;justify-content:space-between;gap:20px;align-items:center;margin-bottom:18px}.section-heading h2{margin:0}.workspace{display:grid;grid-template-columns:240px minmax(360px,1fr) 285px;border:1px solid #3a4351;border-radius:10px;background:var(--panel);overflow:hidden;box-shadow:0 30px 80px #0003}.library,.inspector{padding:16px;min-width:0}.library{border-right:1px solid var(--line)}.inspector{border-left:1px solid var(--line)}.panel-title{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}.panel-title h3{margin:0}.text-button{border:none;background:transparent;color:var(--mint);font-size:11px;padding:3px}.template-list{display:grid;gap:7px;max-height:460px;overflow:auto;margin-top:12px;padding-right:3px}.template{border:1px solid #35404e;background:#151a21;border-radius:6px;text-align:left;display:block;padding:9px;width:100%}.template.selected{border-color:var(--mint);box-shadow:inset 3px 0 var(--mint);background:#1c2c2c}.template strong{display:block;font-size:12px}.template small{font-size:10px;color:var(--muted)}.template figure{margin:7px 0 0;padding:6px;background:repeating-conic-gradient(#242b34 0% 25%,#1b222a 0% 50%) 0/14px 14px;height:75px;display:flex;align-items:center;justify-content:center;border-radius:4px}.template figure img{max-height:64px;max-width:100%;object-fit:contain}.template-list.compact figure{display:none}.subsection{margin-top:20px;padding-top:17px;border-top:1px solid var(--line)}.subsection h3{display:flex;justify-content:space-between}.subsection h3 span{font-weight:400;font-size:10px;color:var(--muted)}.rack{display:grid;gap:6px;font-size:12px}.rack button{text-align:left;font-size:11px}.micro{font-size:11px;color:var(--muted);line-height:1.6;margin-top:9px}.muted{color:var(--muted)}.full{width:100%}.primary{background:#59d6b4;color:#09271f;border-color:#59d6b4;font-weight:650}.primary:hover{background:#7deacb}.stage-column{padding:16px;min-width:0;background:#171b22}.modebar{display:flex;gap:5px;border-bottom:1px solid var(--line);padding-bottom:13px;margin-bottom:16px}.modebar button{font-size:12px;background:transparent;border-color:transparent;color:var(--muted)}.modebar [aria-selected=true]{background:#2b3542;border-color:#455363;color:white}.state-strip{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:17px}.state-strip>div{padding:10px;background:#11161d;border:1px solid #303945;border-radius:5px;min-width:0}.state-strip small{font-size:8px;letter-spacing:.8px;color:var(--muted)}.state-strip strong{display:block;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:3px}.state-dot{display:inline-block;width:5px;height:5px;border-radius:50%;background:#95a1b4;margin-right:5px}.state-dot.cue{background:#73a9f4}.state-dot.program{background:#f17b8b}.canvas-toolbar{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:10px;padding:0 0 8px;color:var(--muted)}.canvas-toolbar .inline{font-size:10px}.canvas{width:100%;aspect-ratio:16/9;position:relative;overflow:hidden;border:1px solid #404d5b;border-radius:5px;background:radial-gradient(ellipse at 26% 20%,#395263,transparent 45%),radial-gradient(ellipse at 80% 35%,#313f53,transparent 48%),#18232c;isolation:isolate}.source-label{position:absolute;left:12px;top:12px;font-size:8px;letter-spacing:.9px;color:#c0d3dd;background:#13212eb3;border-radius:3px;padding:4px 6px}.subject{position:absolute;inset:11% 18% 0;opacity:.8;overflow:hidden}.subject .head{position:absolute;left:32%;top:10%;width:36%;height:46%;border-radius:46% 46% 43% 43%;background:linear-gradient(120deg,#566e7d,#344e60 60%,#22394c)}.subject .shoulders{position:absolute;left:5%;top:53%;width:90%;height:90%;border-radius:45% 45% 0 0;background:linear-gradient(120deg,#435f70,#273d50 60%,#20364b)}.safe-guide{position:absolute;inset:5%;border:1px dashed #b9d2dc45;pointer-events:none}.canvas-corner{position:absolute;bottom:8px;right:10px;font-size:8px;color:#90aabd}.graphic{position:absolute;z-index:3;object-fit:contain;pointer-events:none}.selection-box{position:absolute;border:1px solid var(--mint);pointer-events:none;z-index:4}.canvas-foot{display:flex;justify-content:space-between;gap:15px;font-size:9px;color:#9eabbc;margin-top:7px;min-height:28px}.canvas-foot span:last-child{color:var(--mint);white-space:nowrap}.transports{display:flex;gap:7px;flex-wrap:wrap;margin-top:8px}.transports button{font-size:11px;padding:9px 11px}.cue-action{background:#243c59;border-color:#5f8ab8}.live-action{background:#4c2632;border-color:#bf6274}.danger-quiet{color:#f39aa7}.action-status{font-size:11px;margin:12px 0;color:#b9c8d8;min-height:32px}.secondary-actions{display:flex;gap:7px;flex-wrap:wrap;border-bottom:1px solid var(--line);padding-bottom:14px}.secondary-actions button{font-size:10px;background:transparent}.inspector-tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);padding-bottom:9px;margin-bottom:12px;flex-wrap:wrap}.inspector-tabs button{border:none;background:none;font-size:11px;padding:5px 7px;color:var(--muted)}.inspector-tabs [aria-selected=true]{background:#2c3845;color:var(--mint)}.range-pair{display:flex;gap:8px;align-items:center}.range-pair input[type=number]{width:64px}.range-pair span{font-size:10px}.callout{border:1px solid #405144;background:#1b2c28;border-radius:6px;padding:12px;font-size:11px;margin:18px 0}.callout p{margin:5px 0 0;color:#b4c7c0}.callout strong{font-size:12px}.two{display:grid;grid-template-columns:1fr 1fr;gap:12px}details{margin-top:16px;border-top:1px solid var(--line);padding-top:12px;color:var(--muted);font-size:11px}summary{cursor:pointer;color:#c5d1df;margin-bottom:9px}dl{font-size:11px}dt{color:#8795a7;margin-top:9px}dd{margin:2px 0 0}.inline-link{display:inline-block;font-size:12px;margin-top:14px}.button-row{display:flex;gap:6px;flex-wrap:wrap}.button-row button{font-size:11px}#design-panel{margin-top:22px}#design-panel>.panel-title{margin-bottom:5px}.design-grid{display:grid;grid-template-columns:42% 1fr;gap:14px;padding:14px 0}.layers{display:grid;gap:4px;max-height:220px;overflow:auto;margin-bottom:10px}.layers button{text-align:left;font-size:11px;padding:7px 8px}.layers button[aria-pressed=true]{border-color:var(--mint);color:var(--mint)}#layer-properties{font-size:11px}#layer-properties label{margin-top:0}.automation-modes{display:flex;gap:7px;flex-wrap:wrap;margin:20px 0 12px}.automation-modes [aria-pressed=true]{border-color:var(--mint);color:var(--mint)}#automation-panel>h3{font-size:23px;margin-top:18px}#automation-panel>p{font-size:13px;color:var(--muted)}.trace{background:#11171e;border:1px solid var(--line);border-radius:5px;padding:12px 12px 12px 30px;max-height:230px;overflow:auto;font-size:11px}.trace li{padding:5px;color:#bdd0da}.walkthrough,#inventory,#preservation,#feedback{margin-top:65px;padding-top:25px;border-top:1px solid var(--line)}.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:25px;margin-top:25px}.steps article b{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:1px solid #5c827a;border-radius:50%;color:var(--mint);font-size:12px;margin-bottom:14px}.steps h3{font-size:16px}.steps p{font-size:13px;color:var(--muted)}.review-question{margin-top:24px;color:#cdd9e5;max-width:1000px}.inventory{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:25px}.inventory article{border:1px solid var(--line);border-radius:8px;padding:21px;background:#171c23}.inventory h3{font-size:16px}.inventory ul,.preservation ul{padding-left:18px;font-size:12px;color:#adbbca}.inventory li,.preservation li{margin:7px 0}.inventory .implemented{color:var(--mint)}.inventory .pending{color:var(--amber)}.preservation{display:grid;grid-template-columns:1fr 1fr;gap:30px}.preservation article{padding:23px;border:1px solid var(--line);border-radius:8px}.preservation h3{font-size:18px;margin-top:15px}.review-feedback{max-width:900px;border:1px solid #415348;border-radius:10px;padding:28px!important;background:#18211f}.review-feedback p{color:var(--muted);font-size:13px}.review-feedback form{display:grid;gap:6px}.review-feedback h2{margin-bottom:10px}footer{font-size:11px;color:#8393a7;padding:36px 0 45px;line-height:1.8}.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}[hidden]{display:none!important}@media(min-width:1500px){.workspace{grid-template-columns:255px minmax(360px,1fr) 305px}.template figure{height:85px}.template figure img{max-height:74px}}@media(max-width:1150px){.workspace{grid-template-columns:210px minmax(350px,1fr)}.inspector{grid-column:1/-1;border-left:none;border-top:1px solid var(--line)}#properties{display:grid;grid-template-columns:repeat(3,1fr);gap:0 20px}.inspector .private-copy{margin-bottom:0}.canvas-toolbar{flex-wrap:wrap}.steps{grid-template-columns:1fr 1fr}}@media(max-width:760px){header{padding:18px}.review-label{display:none}main{padding:0 16px}.intro{display:block;padding:35px 0 25px}.intro-note{max-width:none;margin-top:25px}.lede{font-size:18px}.review-nav{gap:14px;margin-bottom:30px}.section-heading{display:block}.section-heading>.badge{margin-top:12px}.workspace{display:flex;flex-direction:column}.library{border-right:0;border-bottom:1px solid var(--line)}.template-list{grid-template-columns:repeat(2,minmax(0,1fr));max-height:260px}.library .subsection{margin-top:12px}.stage-column{padding:12px}.inspector{padding:15px}#properties{grid-template-columns:1fr 1fr}.state-strip{gap:5px}.state-strip>div{padding:7px}.state-strip strong{font-size:9px}.canvas-toolbar>span{width:100%}.source-label{font-size:6px;left:7px;top:7px}.canvas-corner{font-size:6px}.inventory,.preservation{grid-template-columns:1fr}.steps{gap:15px}.steps p{font-size:12px}.review-nav a{font-size:11px}h2{font-size:23px}.design-grid{grid-template-columns:1fr}.review-feedback{padding:20px!important}}@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*{transition:none!important}} \ No newline at end of file diff --git a/site-assets/reviews/volt-graphics/review.js b/site-assets/reviews/volt-graphics/review.js new file mode 100644 index 0000000..4eaa462 --- /dev/null +++ b/site-assets/reviews/volt-graphics/review.js @@ -0,0 +1,24 @@ +const $=id=>document.getElementById(id);const clone=value=>structuredClone(value);const esc=value=>String(value??'').replace(/[&<>"']/g,ch=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[ch])); +let templates=[],selected=null,draft=null,original=null,cue=null,program=null,rack=[],saved=null,history=[],tab='content',mode='operate',auto='manual',layerId='',fieldsChanged=false; +const names={'compact-solid':'Compact solid','minimal-accent':'Minimal accent','broadcast':'Broadcast','corporate-lower-third':'Corporate · reference template'}; +const stateName=value=>value?`${value.name} · ${names[value.templateId]||templates.find(t=>t.templateId===value.templateId)?.name||value.templateId}`:'Hidden'; +const status=text=>$('action-status').textContent=text;const snapshot=()=>draft?clone(draft):null; +function edit(change){if(!draft)return;history.push(snapshot());if(history.length>32)history.shift();change(draft);fieldsChanged=true;$('draft-status').textContent='EDITED · NOT APPLIED';$('render-note').textContent='Edited copy / style is simulated. Pixels remain the native reference appearance.';updateCanvas();} +function newDraft(template){return {id:crypto.randomUUID(),templateId:template.templateId,name:'Guest introduction',scope:$('scope').value,fields:Object.fromEntries((template.fields||[]).map(f=>[f.id,f.default??(f.type==='boolean'?false:f.type==='number'?0:'')])),style:{font:'Segoe UI',nameSize:42,titleSize:28,nameColor:'#f4f7fa',titleColor:'#44c1a1',backgroundColor:'#0c1118',accentColor:'#44c1a1',opacity:90,padding:20,width:60,radius:8,showLogo:true},placement:{anchor:template.defaultPlacement?.anchor||'lower-left',x:template.defaultPlacement?.x??96,y:template.defaultPlacement?.y??-54,scale:1},motion:{in:'fade',out:'fade',inMs:250,outMs:200,direction:'down',easing:'ease-out'},layers:clone(template.layers||[])};} +function listTemplates(){const found=templates.filter(t=>($('family').value==='all'||t.family===$('family').value)&&(`${t.name} ${t.templateId}`.toLowerCase().includes($('search').value.toLowerCase())));$('templates').replaceChildren();for(const template of found){const button=document.createElement('button');button.className='template'+(selected?.templateId===template.templateId?' selected':'');button.setAttribute('role','listitem');button.innerHTML=`${esc(names[template.templateId]||template.name)}${esc(template.family)} · v${template.templateVersion}
Native ${esc(template.name)} reference
`;button.onclick=()=>choose(template);$('templates').append(button);}if(!found.length)$('templates').textContent='No matching looks.';} +function choose(template){selected=template;draft=newDraft(template);if(!Object.hasOwn(draft.fields,'name')&&template.runtime==='compatibility'){draft.fields={name:'Example guest',title:'Producer'};}if(draft.fields.name==='')draft.fields.name='Example guest';original=snapshot();history=[];fieldsChanged=false;layerId='';$('draft-status').textContent='PRIVATE REFERENCE';$('render-note').textContent='Native thumbnail · reference appearance. Not a full-resolution output capture.';$('cue-name').value=draft.name;listTemplates();renderInspector();renderLayers();renderState();status('Private library preview. Create a hidden cue before Cue or Show. Program is unchanged.');} +function renderState(){$('draft-label').textContent=draft?stateName(draft):'Choose a look';$('cue-label').textContent=cue?stateName(cue):'Nothing cued';$('program-label').textContent=stateName(program);$('template-fact').textContent=selected?`${selected.templateId} · immutable v${selected.templateVersion}`:'Select a look';$('rack-count').textContent=`${rack.length} / 8`;$('create').disabled=!draft||rack.length>=8;$('cue').disabled=!draft||!rack.some(c=>c.id===draft.id);$('show').disabled=!cue;$('update').disabled=!program||!draft||!rack.some(c=>c.id===draft.id);$('hide').disabled=!program;$('undo').disabled=!history.length;$('rack').replaceChildren();for(const item of rack){const button=document.createElement('button');button.textContent=`${item.name} · ${program?.id===item.id?'ON AIR':cue?.id===item.id?'CUED':'HIDDEN'}`;button.onclick=()=>{draft=clone(item);selected=templates.find(t=>t.templateId===draft.templateId);original=snapshot();history=[];$('cue-name').value=draft.name;listTemplates();renderInspector();renderLayers();renderState();status('Selected a cue. No live action occurred.');};$('rack').append(button);}updateCanvas();} +function updateCanvas(){if(!selected||!draft)return;const view=$('compare').checked&&original?original:draft;const template=templates.find(t=>t.templateId===view.templateId)||selected;const image=$('reference');image.src=template.thumbnail.url;image.alt=`Native ${template.name} reference graphic`;const box=template.bounds||{width:1152,height:130},p=view.placement;const scale=p.scale||1;image.style.width=`${box.width/1920*100*scale}%`;image.style.height='auto';image.style.left='';image.style.right='';image.style.top='';image.style.bottom='';const right=p.anchor.includes('right'),centerX=p.anchor.includes('center')&&!p.anchor.startsWith('center-'),centerY=p.anchor==='center'||p.anchor.startsWith('center-');image.style.left=right?'':centerX?'50%':`${p.x/1920*100}%`;image.style.right=right?`${Math.abs(p.x)/1920*100}%`:'';image.style.top=p.anchor.startsWith('upper')?`${Math.abs(p.y)/1080*100}%`:centerY?'50%':'';image.style.bottom=!p.anchor.startsWith('upper')&&!centerY?`${Math.abs(p.y)/1080*100}%`:'';image.style.transform=`${centerX?'translateX(-50%)':''} ${centerY?'translateY(-50%)':''}`.trim();$('canvas-title').textContent=$('compare').checked?'Original private reference':`${names[template.templateId]||template.name} · private draft`;$('canvas').querySelector('.safe-guide').hidden=!$('safe-guides').checked;} +function input(label,value,callback,options={}){const holder=document.createElement('label');holder.textContent=label;let control;if(options.choices){control=document.createElement('select');for(const choice of options.choices){const option=document.createElement('option');option.value=typeof choice==='object'?choice.value:choice;option.textContent=typeof choice==='object'?choice.label:choice;control.append(option);}control.value=String(value);}else{control=document.createElement('input');control.type=options.type||(typeof value==='boolean'?'checkbox':'text');if(control.type==='checkbox')control.checked=value;else control.value=String(value??'');if(options.min!=null)control.min=options.min;if(options.max!=null)control.max=options.max;if(options.step!=null)control.step=options.step;}control.addEventListener('change',()=>callback(control.type==='checkbox'?control.checked:control.type==='number'?Number(control.value):control.value));holder.append(control);return holder;} +function range(label,value,min,max,step,callback,suffix=''){const holder=document.createElement('label');holder.textContent=label;const pair=document.createElement('div');pair.className='range-pair';const slider=document.createElement('input'),number=document.createElement('input');slider.type='range';number.type='number';for(const control of[slider,number]){control.min=min;control.max=max;control.step=step;control.value=value;control.oninput=()=>{const current=Math.max(min,Math.min(max,Number(control.value)));slider.value=number.value=current;};control.onchange=()=>callback(Number(control.value));}pair.append(slider,number);const unit=document.createElement('span');unit.textContent=suffix;pair.append(unit);holder.append(pair);return holder;} +function renderInspector(){const pane=$('properties');pane.replaceChildren();if(!draft||!selected)return;const add=node=>pane.append(node);if(tab==='content'){add(input('Subject binding','unbound',v=>{edit(d=>d.subject=v);status('Subject choice is simulated. App binding uses an exact native source generation.');},{choices:[{value:'unbound',label:'Unbound · selected scope'},{value:'example',label:'Example guest · current generation'}]}));const descriptors=selected.fields?.length?selected.fields:[{id:'name',type:'string',maxLength:256},{id:'title',type:'string',maxLength:512}];for(const field of descriptors){if(field.id==='time'){const note=document.createElement('p');note.className='micro';note.textContent='Clock time is generated by the native controller; see Clock.';add(note);continue;}const value=draft.fields[field.id]??field.default;const apply=v=>edit(d=>d.fields[field.id]=v);if(field.type==='number')add(range(field.id.replaceAll('-',' '),value,field.minimum??0,field.maximum??100,1,apply));else if(field.type==='color')add(input(field.id,value,apply,{type:'color'}));else if(field.type==='boolean')add(input(field.id.replaceAll('-',' '),value,apply));else if(field.choices?.length)add(input(field.id,value,apply,{choices:field.choices}));else if(field.type==='image')add(input(field.id,value,apply,{choices:[{value:'logo',label:'Verified package logo'}]}));else add(input(field.id==='name'?'Name':field.id==='title'?'Secondary line (blank hides it)':field.id,value,apply));}const note=document.createElement('p');note.className='micro';note.textContent='Use source defaults · retain operator overrides · explicitly hide a secondary line. Example text edits in this webpage do not regenerate native pixels.';add(note);}else if(tab==='look'){add(input('Saved style','Current brand',()=>status('Style selection is a design simulation; applying a style must preserve name/title and intentional blanks.'),{choices:['Current brand','Interview · clean','Broadcast · bold']}));add(input('Font family',draft.style.font,v=>edit(d=>d.style.font=v),{choices:['Segoe UI','Arial','Custom installed font…']}));for(const [key,label]of[['nameColor','Primary text'],['titleColor','Secondary text'],['backgroundColor','Plate'],['accentColor','Accent']])add(input(label,draft.style[key],v=>edit(d=>d.style[key]=v),{type:'color'}));if(selected.runtime==='compatibility'){for(const[key,label,min,max]of[['nameSize','Name size',16,120],['titleSize','Secondary size',12,80],['padding','Padding',0,64],['width','Plate width',15,95],['radius','Corner radius',0,60]])add(range(label,draft.style[key],min,max,1,v=>edit(d=>d.style[key]=v)));add(input('Show logo',draft.style.showLogo,v=>edit(d=>d.style.showLogo=v)));}add(range('Background opacity',draft.style.opacity,0,100,1,v=>edit(d=>d.style.opacity=v),'%'));const note=document.createElement('p');note.className='micro';note.textContent='Declarative typography, padding and fill belong to the template layer inspector. Enabled controls must have a real native consumer; unsupported compatibility controls do not silently pass through.';add(note);}else if(tab==='placement'){add(input('Anchor',draft.placement.anchor,v=>edit(d=>d.placement.anchor=v),{choices:['upper-left','upper-center','upper-right','center-left','center','center-right','lower-left','lower-center','lower-right']}));add(range('Horizontal offset',draft.placement.x,-3840,3840,1,v=>edit(d=>d.placement.x=v),'px'));add(range('Vertical offset',draft.placement.y,-2160,2160,1,v=>edit(d=>d.placement.y=v),'px'));add(range('Scale',draft.placement.scale,.1,4,.05,v=>edit(d=>d.placement.scale=v),'×'));const p=document.createElement('p');p.className='micro';p.textContent='Whole-graphic placement is separate from moving or resizing a selected template layer. App canvas also supports drag/resize, one-pixel nudges and Shift for larger steps.';add(p);}else if(tab==='motion'){for(const phase of['in','out']){add(input(phase==='in'?'Build in':'Build out',draft.motion[phase],v=>edit(d=>d.motion[phase]=v),{choices:['none','fade','slide']}));add(range(`${phase==='in'?'In':'Out'} duration`,draft.motion[phase+'Ms'],0,3000,10,v=>edit(d=>d.motion[phase+'Ms']=v),'ms'));}add(input('Slide direction',draft.motion.direction,v=>edit(d=>d.motion.direction=v),{choices:['left','right','up','down']}));add(input('Easing',draft.motion.easing,v=>edit(d=>d.motion.easing=v),{choices:['linear','ease-in','ease-out','ease-in-out']}));add(input('Hold behavior','Hold until hidden',()=>status('Hold/auto-hide controls are part of remaining integration.'),{choices:['Hold until hidden','Auto-hide after duration']}));}else{const supported=['clock','countdown'].includes(selected.family);const note=document.createElement('p');note.className='micro';note.textContent=supported?'Native clock controls are implemented; this web page displays a fixed native reference. It does not run an actual output clock.':'Choose Wall clock or Countdown in the library to review this controller.';add(note);for(const node of[input('Mode',selected.family==='countdown'?'Countdown':'Wall clock',()=>{}, {choices:['Wall clock','Countdown']}),input('Timezone','Computer local time',()=>{},{choices:['Computer local time','UTC','UTC with fixed offset']}),input('Display','Hours : minutes : seconds',()=>{},{choices:['Hours : minutes','Hours : minutes : seconds']}),range('Countdown duration',300,1,86400,1,()=>{},'s'),input('At zero','Hold at zero',()=>{},{choices:['Hold at zero','Hide graphic','Suggest next cue']})]){node.querySelector('input,select').disabled=!supported;add(node);}const buttons=document.createElement('div');buttons.className='button-row';for(const command of['Apply settings','Start','Pause','Resume','Reset']){const button=document.createElement('button');button.textContent=command;button.disabled=!supported;button.onclick=()=>status(`Clock ${command.toLowerCase()} simulated. Clock state and visibility are separate.`);buttons.append(button);}add(buttons);}} +function flatten(layers,depth=0){return layers.flatMap(layer=>[{...layer,depth},...flatten(layer.children||[],depth+1)]);}function realLayer(id,layers=draft?.layers||[]){for(const layer of layers){if(layer.id===id)return layer;const child=realLayer(id,layer.children||[]);if(child)return child;}return null;} +function renderLayers(){const pane=$('layers');pane.replaceChildren();$('layer-properties').replaceChildren();if(!draft||!selected)return;if(selected.runtime==='compatibility'){pane.textContent='Compatibility look: use Look controls. Declarative looks expose their actual layer tree.';for(const id of['add-layer','layer-up','layer-down','duplicate-layer','save-version'])$(id).disabled=true;return;}for(const id of['add-layer','layer-up','layer-down','duplicate-layer','save-version'])$(id).disabled=false;const rows=flatten(draft.layers).reverse();if(!rows.some(n=>n.id===layerId))layerId=rows[0]?.id||'';for(const node of rows){const button=document.createElement('button');button.style.paddingLeft=(8+node.depth*12)+'px';button.textContent=`${node.type==='group'?'▱':node.type==='image'?'▧':node.type==='text'?'T':'▣'} ${node.id}`;button.setAttribute('aria-pressed',String(node.id===layerId));button.onclick=()=>{layerId=node.id;renderLayers();};pane.append(button);}const node=realLayer(layerId);if(!node)return;const properties=$('layer-properties');properties.append(input('Layer name',node.id,()=>status('Layer identity is stable; friendly labels and locks are edited separately in the app.')));properties.append(input('Visible',node.visible!==false,v=>edit(()=>node.visible=v)));properties.append(input('Lock layer',!!node.metadata?.editorLocked,v=>edit(()=>node.metadata={...node.metadata,editorLocked:v})));for(const key of['x','y','width','height']){const value=typeof node[key]==='number'?node[key]:0;properties.append(range(key,value,key==='width'||key==='height'?1:-3840,key==='width'||key==='height'?8192:3840,1,v=>edit(()=>node[key]=v),'px'));}if(node.type==='text'){properties.append(input('Text / field',typeof node.text==='string'?node.text:`Field: ${node.text?.field||'copy'}`,v=>edit(()=>node.text=v)));properties.append(input('Weight',String(node.fontWeight||400),v=>edit(()=>node.fontWeight=Number(v)),{choices:[{value:'400',label:'Regular · 400'},{value:'500',label:'Medium · 500'},{value:'600',label:'Semibold · 600'},{value:'700',label:'Bold · 700'}]}));properties.append(input('Overflow',node.overflow||'ellipsis',v=>edit(()=>node.overflow=v),{choices:['ellipsis','wrap-then-ellipsis']}));properties.append(input('Maximum lines',String(node.maxLines||1),v=>edit(()=>node.maxLines=Number(v)),{choices:['1','2','3']}));}if(node.type==='rect'){properties.append(input('Fill mode','Solid',()=>status('Solid, two-stop gradients and declared brand roles are supported in the app layer editor.'),{choices:['Solid','Two-stop gradient','Brand role']}));properties.append(input('Fill color',typeof node.fill==='string'?node.fill.slice(0,7):'#0c1118',v=>edit(()=>node.fill=v),{type:'color'}));}if(node.type==='image')properties.append(input('Image fit',node.fit||'contain',v=>edit(()=>node.fit=v),{choices:['contain','cover']}));} +const inventory=[['Library & packages','implemented',['Eight curated looks: 3 legacy lower thirds, logo accent, transparent name, centered title, corner logo, clock/countdown families.','A ninth corporate template remains available as a reference.','Search, family filters, cards/compact view and true native reference thumbnails.','Typed fields, package-local PNG/JPEG, hash checks, named font/asset errors.']],['Private designer','implemented',['Native private canvas; select, move, resize, nudge, safe guides and whole-graphic placement.','Text, rectangles, groups and images; front/back order, visibility, lock, duplicate and reparent.','Exact entry plus sliders; 4 font weights, 1–3 lines, wrap/ellipsis, alignment and bounded boxes.','Solid/two-stop gradient/brand fills; contain/cover image fit; immutable version saves.']],['Live operation','implemented',['Independent private Draft, accepted Cue and Program revisions.','Explicit Cue, Show, Hide, Update and Clear; same values do not replay animation.','Global vs scene scope; exact subject-generation binding and source-text copy.','Preparation failures retain the accepted look; actual draw is distinct from command admission.']],['Brand & styles','implemented',['Name/secondary/plate/accent colours, opacity, installed fonts and brand roles.','Legacy sizing, padding, width, radius and logo scale stay supported.','Declarative style fields are saved separately from guest copy and image choices.','Compare Original/Edited, bounded gesture Undo and explicit Cancel.']],['Motion & controllers','implemented',['Cut, fade and slide; four directions, 0–3000 ms, four easing modes.','Native wall clock: local, UTC or fixed offset; hours/minutes/seconds formats.','Countdown configure/start/pause/resume/reset; hold zero, hide, or suggest next.','Restore does not start a countdown, Show, meeting, network request or output.']],['Automation & safe restore','pending',['Manual, Suggest, Rehearsal and separately armed Automatic controls.','Qualified rendered-subject change, dwell/cooldown and bounded decision history.','Manual Hide/Clear wins; clear inhibition and explicit re-arm; no reconnect replay.','Atomic graphics documents, old-look/source override migration, pinned packages and private saved drafts. Remaining integration/acceptance is not claimed complete.']],['Output separation','implemented',['Scene graphics follow their scene; global bug/clock survive scene changes.','Captions remain downstream; webcam-only framer/LUFS remains output-specific.','Editor guides and scope ROI are not burned into Program.','Clean source ISOs retain their own output semantics. Full enabled-output qualification remains open.']],['Preservation & APIs','pending',['One legacy-or-managed authority per migrated family; no duplicate lower-third rendering.','Existing key/API controls target the managed lower third after migration.','Exact source names, explicit blank titles, legacy look/timing/logo references and saved styles.','Package round-trip, repair, cue-rack polish and complete installed review still need final acceptance.']],['Later graphics expansion','pending',['Data connectors: bounded HTTP JSON, CSV/XLSX, RSS and mapping.','Data freshness / stale-state policy with credential references.','Tables/leaderboards, keyed transitions, cached crawls and deterministic playlists.','These are later milestones and are not included in this first-milestone completion claim.']]]; +$('option-inventory').innerHTML=inventory.map(([title,state,items])=>`

${state==='implemented'?'IMPLEMENTED PATH · ACCEPTANCE OPEN':'INTEGRATION / LATER · SEE DETAILS'}

${esc(title)}

`).join(''); +$('search').oninput=listTemplates;$('family').onchange=listTemplates;$('density').onclick=()=>{const compact=$('templates').classList.toggle('compact');$('density').textContent=compact?'Show cards':'Compact list';$('density').setAttribute('aria-pressed',String(compact));};$('safe-guides').onchange=updateCanvas;$('compare').onchange=updateCanvas;$('cue-name').onchange=()=>{edit(d=>d.name=$('cue-name').value);renderState();}; +$('create').onclick=()=>{if(!draft||rack.length>=8)return;draft.id=crypto.randomUUID();draft.scope=$('scope').value;rack.push(snapshot());original=snapshot();renderState();status('Hidden cue created in the simulated rack. Cue and Program are unchanged.');};$('cue').onclick=()=>{if(!draft)return;cue=snapshot();const index=rack.findIndex(c=>c.id===draft.id);if(index>=0)rack[index]=snapshot();renderState();status('Simulation: complete revision accepted on Cue. Program is unchanged. Native preparation is verified in the app, not by this page.');};$('show').onclick=()=>{if(!cue)return;program=clone(cue);renderState();status('Simulation: accepted Cue shown. Private edits made after Cue were not adopted. No actual output is connected.');};$('update').onclick=()=>{if(!draft||!program)return;program=snapshot();renderState();status('Simulation: current private revision explicitly updated on Program. No extra reveal.');};$('hide').onclick=()=>{program=null;$('auto-armed').checked=false;renderState();status('Simulation: hidden; pending automation cancelled. Cue retained.');};$('clear').onclick=()=>{program=null;$('auto-armed').checked=false;renderState();status('Simulation: Program graphics cleared. Automation inhibited until explicit re-arm; legacy graphics stay suppressed.');};$('undo').onclick=()=>{if(history.length){draft=history.pop();renderInspector();renderLayers();renderState();status('One private edit undone. Cue and Program are unchanged.');}};$('cancel').onclick=()=>{if(original){draft=clone(original);history=[];renderInspector();renderLayers();renderState();status('Private draft cancelled. Cue and Program are unchanged.');}};$('save').onclick=()=>{if(!draft)return;saved=snapshot();status('Simulation: saved this draft in page memory. No app settings were written. Restore remains hidden.');};$('restore').onclick=()=>{if(!saved){status('Save a simulated cue first.');return;}if(rack.length>=8){status('Eight-instance capacity reached. Previous cues retained.');return;}draft=clone(saved);draft.id=crypto.randomUUID();rack.push(snapshot());selected=templates.find(t=>t.templateId===draft.templateId);original=snapshot();history=[];renderInspector();renderLayers();renderState();status('Simulation: restored a hidden cue. Nothing shown and no automation re-armed.');}; +for(const button of document.querySelectorAll('[data-tab]'))button.onclick=()=>{tab=button.dataset.tab;document.querySelectorAll('[data-tab]').forEach(b=>b.setAttribute('aria-selected',String(b===button)));renderInspector();};for(const button of document.querySelectorAll('[data-mode]'))button.onclick=()=>{mode=button.dataset.mode;document.querySelectorAll('[data-mode]').forEach(b=>b.setAttribute('aria-selected',String(b===button)));$('operate-design').hidden=mode==='automation';$('automation-panel').hidden=mode!=='automation';$('design-panel').hidden=mode!=='design';renderLayers();}; +$('add-layer').onclick=()=>{edit(d=>d.layers.push({id:'text-'+(d.layers.length+1),type:'text',text:'Title',x:20,y:20,width:600,height:100,fontSize:42,fontWeight:600}));renderLayers();status('Added private text layer in the review model. Reference pixels remain unchanged.');};$('duplicate-layer').onclick=()=>{const node=realLayer(layerId);if(!node)return;edit(d=>d.layers.push({...clone(node),id:node.id+'-copy'}));renderLayers();};function moveLayer(delta){const index=draft?.layers.findIndex(n=>n.id===layerId)??-1;if(index<0){status('Group-child order uses its own siblings in the app.');return;}const other=Math.max(0,Math.min(draft.layers.length-1,index+delta));edit(d=>[d.layers[index],d.layers[other]]=[d.layers[other],d.layers[index]]);renderLayers();}$('layer-up').onclick=()=>moveLayer(1);$('layer-down').onclick=()=>moveLayer(-1);$('save-version').onclick=()=>status('Simulation: new immutable template version saved. Actual package validation and explicit Cue/Update adoption happen in the app.'); +const helps={manual:'Manual: every Cue, Show, Update and Hide is an explicit operator action.',suggest:'Suggest: show the proposed subject and reason. No automatic Preview or Program mutation.',rehearsal:'Rehearsal: exercise the decision path in a private preview. Program is never changed.',automatic:'Automatic: only an explicitly armed, qualified rule can act. Scene auto-Take remains separately controlled.'};for(const button of document.querySelectorAll('[data-auto]'))button.onclick=()=>{auto=button.dataset.auto;document.querySelectorAll('[data-auto]').forEach(b=>b.setAttribute('aria-pressed',String(b===button)));$('mode-help').textContent=helps[auto];$('auto-armed').checked=false;};$('simulate-subject').onclick=()=>{const entry=document.createElement('li');entry.textContent=auto==='manual'?'Manual: observed subject change; no action.':auto==='suggest'?'Suggested: cue Example guest after qualified source dwell. No native action executed.':auto==='rehearsal'?'Rehearsal: qualified event → private preview proposal. Program unchanged.':!$('auto-armed').checked?'Automatic is not armed. Action refused.':'Simulation only: qualified event → dwell/cooldown → bound cue → native preparation → Show proposal. No actual app command sent.';$('decision-trace').prepend(entry);while($('decision-trace').children.length>12)$('decision-trace').lastElementChild.remove();};document.querySelectorAll('.automation-modes~.two .range-pair').forEach(pair=>{const inputs=[...pair.querySelectorAll('input')];inputs.forEach(control=>control.oninput=()=>inputs.forEach(other=>other.value=control.value));}); +fetch('catalog.json').then(response=>{if(!response.ok)throw Error('Native catalog unavailable');return response.json();}).then(catalog=>{templates=catalog.templates;choose(templates.find(t=>t.templateId==='logo-accent')||templates[0]);}).catch(error=>{$('templates').textContent=error.message;status('Native examples could not load. Please reload; no app is connected.');}); diff --git a/tests/review-feedback.test.mjs b/tests/review-feedback.test.mjs index f9a0efb..54392e3 100644 --- a/tests/review-feedback.test.mjs +++ b/tests/review-feedback.test.mjs @@ -14,3 +14,5 @@ test('table-first alternative keeps feedback isolated from earlier Sources revie test('guided workflow feedback saves requirements without widening other reviews',async()=>{const kv=storage(),env={REVIEW_FEEDBACK:kv};const result=await handleReviewFeedback(request({review:'workflow-review-v1',area:'Preservation requirements'}),env);assert.equal(result.status,201);const receipt=await result.json();assert.ok(kv.values.has('feedback:workflow-review-v1:'+receipt.id));assert.equal((await handleReviewFeedback(request({area:'Preservation requirements'}),env)).status,400);assert.equal((await handleReviewFeedback(request({review:'workflow-review-v1',area:'Unknown area'}),env)).status,400);}); test('operator review has independent areas and receipt namespace',async()=>{const kv=storage(),env={REVIEW_FEEDBACK:kv},submissionId=randomUUID();for(const area of ['Starter scenes','Lower-third designer','Shared sliders and resets','Grade curves and scope ROI','Settings and Health'])assert.equal((await handleReviewFeedback(request({review:'operator-uiux-v1',area}),env)).status,201);assert.equal((await handleReviewFeedback(request({review:'sources-workspace-v1',area:'Starter scenes'}),env)).status,400);assert.equal((await handleReviewFeedback(request({review:'operator-uiux-v1',area:'Audio controls'}),env)).status,400);assert.equal((await handleReviewFeedback(request({submissionId}),env)).status,201);assert.equal((await handleReviewFeedback(request({submissionId,review:'operator-uiux-v1'}),env)).status,201);assert.ok(kv.values.has('feedback:sources-workspace-v1:'+submissionId));assert.ok(kv.values.has('feedback:operator-uiux-v1:'+submissionId));}); test('malformed JSON is rejected and burst submissions are bounded',async()=>{const kv=storage(),env={REVIEW_FEEDBACK:kv};const bad=new Request('https://corevideo.io/reviews/api/feedback',{method:'POST',headers:{origin:'https://corevideo.io','content-type':'application/json'},body:'{'});assert.equal((await handleReviewFeedback(bad,env)).status,400);for(let n=0;n<8;n++)assert.equal((await handleReviewFeedback(request(),env)).status,201);assert.equal((await handleReviewFeedback(request(),env)).status,429);}); + +test('Volt review saves distinct areas without accepting them in other reviews',async()=>{const kv=storage(),env={REVIEW_FEEDBACK:kv};for(const area of ['Template library','Live operation','Designer controls','Styles and brand','Animation and clocks','Automation rules','Preservation and gaps'])assert.equal((await handleReviewFeedback(request({review:'volt-graphics-v1',area}),env)).status,201);assert.equal((await handleReviewFeedback(request({review:'workflow-review-v1',area:'Automation rules'}),env)).status,400);assert.equal((await handleReviewFeedback(request({review:'volt-graphics-v1',area:'Unknown'}),env)).status,400);assert.ok([...kv.values.keys()].some(key=>key.startsWith('feedback:volt-graphics-v1:')));});