@rig-c/review 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/web/compare.css CHANGED
@@ -1,8 +1,11 @@
1
- :root{font:13px/1.5 Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#e0eeec;background:#10212a;color-scheme:dark}*{box-sizing:border-box}body{margin:0}button,input,select{font:inherit}button{padding:7px 10px;border:1px solid #486574;border-radius:6px;color:inherit;background:#28414c;cursor:pointer}button:hover{background:#385763}button:disabled{opacity:.4;cursor:default}.primary{background:#b7dfcb;color:#183c2c;border-color:#b7dfcb}.primary:hover{background:#d0eddf}input,select{border:1px solid #4b6c7c;background:#102833;border-radius:6px;color:inherit;padding:8px;max-width:100%;width:100%}input[type=range],input[type=checkbox]{accent-color:#b6dec9;padding:0}input[type=checkbox]{width:auto}input[type=range]{min-width:60px}button:focus-visible,input:focus-visible,select:focus-visible,summary:focus-visible{outline:2px solid #d0eada;outline-offset:3px}header{padding:15px 21px;display:flex;align-items:center;gap:24px;border-bottom:1px solid #355563;background:#152c36;flex-wrap:wrap}.brand{font-size:19px;letter-spacing:-.5px;white-space:nowrap}.brand span{font-size:10px;letter-spacing:.08em;display:block;color:#b5dcc9}h1{font-size:14px;font-weight:500;margin:0}h2{font-size:13px;font-weight:500;margin:0 0 13px}.hint{font-size:11px;color:#a6c2cf}.actions{display:flex;align-items:center;gap:7px;margin-left:auto;flex-wrap:wrap}.actions button{font-size:11px}.layout{display:grid;grid-template-columns:minmax(0,1fr) 300px;min-height:calc(100vh - 118px)}main{min-width:0;display:flex;flex-direction:column}.toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:12px 16px;border-bottom:1px solid #34515e;font-size:11px;color:#b6cfd9}.row{display:flex;gap:5px;align-items:center;flex-wrap:wrap}.row button{font-size:11px;padding:4px 8px}.row output{font:11px ui-monospace,SFMono-Regular,monospace;padding:0 4px}.stages{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;padding:12px;flex:1;min-height:500px}.pane{display:flex;flex-direction:column;min-width:0;border:1px solid #3b5d6c;border-radius:8px;overflow:hidden;background:#152d39}.pane-head{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid #385762;font-size:11px;color:#b4cfd9;min-height:45px;flex-wrap:wrap}.pane-head strong{font-weight:500}.side-label{display:inline-grid;place-items:center;width:23px;height:23px;border:1px solid #7aab95;border-radius:5px;color:#ccead9;flex:none}.rig-viewport,.reference-viewport{position:relative;min-height:420px;overflow:hidden;flex:1;background:radial-gradient(ellipse at 50% 40%,#294754,#102631 75%)}.rig-viewport{background-image:radial-gradient(#8eb7c637 .7px,transparent .7px);background-size:22px 22px}.rig-root{position:absolute;transform-origin:0 0}video{width:100%;height:100%;position:absolute;inset:0;object-fit:contain;background:#07171f}.empty{position:absolute;inset:50px 16px 30px;display:grid;place-items:center;text-align:center;font-size:12px;color:#a9c7d4;line-height:1.7;overflow-wrap:anywhere}.pane-foot{display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap;padding:10px 11px;border-top:1px solid #385762;color:#b5ccd7;font:11px ui-monospace,SFMono-Regular,monospace;min-height:42px}.pane-foot label{display:flex;align-items:center;gap:4px;font:11px -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}.transport{display:flex;gap:11px;align-items:center;flex-wrap:wrap;padding:13px 17px;border-top:1px solid #3b5b69;background:#17313d}.transport input[type=range]{flex:1}.transport input[type=number]{width:100px}.transport output{font:11px ui-monospace,SFMono-Regular,monospace;white-space:nowrap;color:#c2dae2}.compare-info{display:flex;justify-content:space-between;gap:9px;flex-wrap:wrap;padding:9px 17px;color:#a4c0ce;font-size:11px}.trace{font-size:11px;color:#abc6d1;padding:4px 17px}.trace summary,.provenance summary{cursor:pointer}.trace pre{font:11px/1.6 ui-monospace,SFMono-Regular,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.boundary{font-size:11px;color:#91b2c1;padding:7px 17px;margin:0}aside{background:#192f3b;padding:21px 17px;border-left:1px solid #3b5b69}.eyebrow{font-size:11px;letter-spacing:.08em;color:#b3ccd4;margin-bottom:15px}aside label{display:block;font-size:11px;color:#b1cbd5;margin:12px 0 6px}.provenance{padding:13px 11px;margin-top:22px;background:#223c47;border:1px solid #4b6a77;border-radius:7px;font-size:11px}.provenance p{margin:7px 0;color:#b8d1db;overflow-wrap:anywhere}.provenance details{margin-top:12px}.provenance pre{font:11px/1.6 ui-monospace,SFMono-Regular,monospace;overflow-wrap:anywhere;white-space:pre-wrap}.feedback-form{border-top:1px solid #405f6c;margin-top:24px;padding-top:21px}.frame-range{display:grid;grid-template-columns:1fr 1fr;gap:9px}.block{width:100%;margin-top:14px}.feedback-item{font-size:11px;overflow-wrap:anywhere;padding:12px 0;border-top:1px solid #426372;margin-top:13px}.feedback-item strong{display:block;font-weight:500;color:#d2e7e2}.feedback-item button{padding:3px 7px;font-size:11px;margin-top:7px}.dirty{color:#e1c697!important}.error{color:#f2baab!important}footer{display:flex;justify-content:space-between;gap:13px;flex-wrap:wrap;padding:11px 18px;background:#142a35;border-top:1px solid #365966;font-size:11px;color:#b5cfd9}[hidden]{display:none!important}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
1
+ /* Theme tokens: site values copied from rig-c.org styles.css (dark); light and --rv-* are review-local derivations. No literal colour outside these blocks. */
2
+ :root{--font-sans:Inter,system-ui,sans-serif;--font-display:Inter,system-ui,sans-serif;--font-mono:"JetBrains Mono",ui-monospace,monospace;--radius:10px;--bg:#070b18;--fg:#c9d4e8;--fg-strong:#f3f6fc;--fg-soft:#aebbd4;--fg-muted:#7f8ba6;--border:#18213a;--border-strong:#2a3657;--hover-bg:#0f1730;--active-bg:#142042;--link:#7cc8ff;--link-hover:#b3e0ff;--btn-fg:#08101f;--code-bg:#050814;--code-fg:#d6e2f5;--code-border:#18213a;--code-inline-bg:#121a30;--footer-bg:#050813;--pass:#30d158;--warn:#ffcc00;--fail:#ff453a;--rv-bar:#0b1124;--rv-panel:#0d152b;--rv-raised:var(--code-inline-bg);--rv-control:var(--code-inline-bg);--rv-control-hover:var(--active-bg);--rv-field:var(--code-bg);--rv-segmented:var(--code-bg);--rv-pressed-bg:#133733;--rv-pressed-border:#207c44;--rv-pressed-fg:var(--fg-strong);--rv-focus:var(--link-hover);--rv-backdrop:rgba(7,11,24,.82);--rv-pane-hi:#142042;--rv-pane-lo:#070b18;--rv-pane-label-bg:rgba(7,11,24,.85);--rv-stage-fg:#aebbd4;--rv-grid-dot:rgba(127,139,166,.2);--rv-media-bg:#0b1020}
3
+ :root[data-theme=light]{--bg:#f5f7fb;--fg:#26324a;--fg-strong:#0c1324;--fg-soft:#3b4864;--fg-muted:#5d6982;--border:#d5dcea;--border-strong:#b3bed3;--hover-bg:#e8edf6;--active-bg:#dbe3f3;--link:#1a6fc0;--link-hover:#0f528f;--btn-fg:#ffffff;--code-bg:#eef1f7;--code-fg:#1d2940;--code-border:#d5dcea;--code-inline-bg:#e3e8f2;--footer-bg:#eceff6;--pass:#1e8a3c;--warn:#8a6400;--fail:#b3261e;--rv-bar:#edf1f7;--rv-panel:#e9eef6;--rv-raised:var(--code-inline-bg);--rv-control:var(--code-inline-bg);--rv-control-hover:#d5ddec;--rv-field:#ffffff;--rv-segmented:var(--code-inline-bg);--rv-pressed-bg:#c9ded8;--rv-pressed-border:#6fb286;--rv-pressed-fg:var(--fg-strong);--rv-focus:var(--link);--rv-backdrop:rgba(12,19,36,.45);--rv-pane-hi:#142042;--rv-pane-lo:#070b18;--rv-pane-label-bg:rgba(7,11,24,.85);--rv-stage-fg:#aebbd4;--rv-grid-dot:rgba(127,139,166,.2);--rv-media-bg:#0b1020}
4
+ :root{font:13px/1.5 var(--font-sans);color:var(--fg);background:var(--bg);color-scheme:dark}*{box-sizing:border-box}body{margin:0}button,input,select{font:inherit}button{padding:7px 10px;border:1px solid var(--border-strong);border-radius:6px;color:inherit;background:var(--rv-control);cursor:pointer}button:hover{background:var(--rv-control-hover)}button:disabled{opacity:.4;cursor:default}.primary{background:var(--link);color:var(--btn-fg);border-color:var(--link)}.primary:hover{background:var(--link-hover)}input,select{border:1px solid var(--border-strong);background:var(--rv-field);border-radius:6px;color:inherit;padding:8px;max-width:100%;width:100%}input[type=range],input[type=checkbox]{accent-color:var(--link);padding:0}input[type=checkbox]{width:auto}input[type=range]{min-width:60px}button:focus-visible,input:focus-visible,select:focus-visible,summary:focus-visible{outline:2px solid var(--rv-focus);outline-offset:3px}header{padding:15px 21px;display:flex;align-items:center;gap:24px;border-bottom:1px solid var(--border);background:var(--rv-bar);flex-wrap:wrap}.brand{font-size:19px;letter-spacing:-.5px;white-space:nowrap}.brand span{font-size:10px;letter-spacing:.08em;display:block;color:var(--fg-muted)}h1{font-size:14px;font-weight:500;margin:0}h2{font-size:13px;font-weight:500;margin:0 0 13px}.hint{font-size:11px;color:var(--fg-muted)}.actions{display:flex;align-items:center;gap:7px;margin-left:auto;flex-wrap:wrap}.actions button{font-size:11px}.layout{display:grid;grid-template-columns:minmax(0,1fr) 300px;min-height:calc(100vh - 118px)}main{min-width:0;display:flex;flex-direction:column}.toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:12px 16px;border-bottom:1px solid var(--border);font-size:11px;color:var(--fg-muted)}.row{display:flex;gap:5px;align-items:center;flex-wrap:wrap}.row button{font-size:11px;padding:4px 8px}.row output{font:11px var(--font-mono);padding:0 4px}.stages{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;padding:12px;flex:1;min-height:500px}.pane{display:flex;flex-direction:column;min-width:0;border:1px solid var(--border-strong);border-radius:8px;overflow:hidden;background:var(--rv-panel)}.pane-head{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--border);font-size:11px;color:var(--fg-soft);min-height:45px;flex-wrap:wrap}.pane-head strong{font-weight:500}.side-label{display:inline-grid;place-items:center;width:23px;height:23px;border:1px solid var(--rv-pressed-border);border-radius:5px;color:var(--rv-pressed-fg);flex:none}.rig-viewport,.reference-viewport{position:relative;min-height:420px;overflow:hidden;flex:1;background:radial-gradient(ellipse at 50% 40%,var(--rv-pane-hi),var(--rv-pane-lo) 75%)}.rig-viewport{background-image:radial-gradient(var(--rv-grid-dot) .7px,transparent .7px);background-size:22px 22px}.rig-root{position:absolute;transform-origin:0 0}video{width:100%;height:100%;position:absolute;inset:0;object-fit:contain;background:var(--rv-media-bg)}.empty{position:absolute;inset:50px 16px 30px;display:grid;place-items:center;text-align:center;font-size:12px;color:var(--rv-stage-fg);line-height:1.7;overflow-wrap:anywhere}.pane-foot{display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap;padding:10px 11px;border-top:1px solid var(--border);color:var(--fg-muted);font:11px var(--font-mono);min-height:42px}.pane-foot label{display:flex;align-items:center;gap:4px;font:11px -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}.transport{display:flex;gap:11px;align-items:center;flex-wrap:wrap;padding:13px 17px;border-top:1px solid var(--border);background:var(--rv-panel)}.transport input[type=range]{flex:1}.transport input[type=number]{width:100px}.transport output{font:11px var(--font-mono);white-space:nowrap;color:var(--fg-muted)}.compare-info{display:flex;justify-content:space-between;gap:9px;flex-wrap:wrap;padding:9px 17px;color:var(--fg-muted);font-size:11px}.trace{font-size:11px;color:var(--fg-muted);padding:4px 17px}.trace summary,.provenance summary{cursor:pointer}.trace pre{font:11px/1.6 var(--font-mono);white-space:pre-wrap;overflow-wrap:anywhere}.boundary{font-size:11px;color:var(--fg-muted);padding:7px 17px;margin:0}aside{background:var(--rv-panel);padding:21px 17px;border-left:1px solid var(--border)}.eyebrow{font-size:11px;letter-spacing:.08em;color:var(--fg-muted);margin-bottom:15px}aside label{display:block;font-size:11px;color:var(--fg-muted);margin:12px 0 6px}.provenance{padding:13px 11px;margin-top:22px;background:var(--rv-raised);border:1px solid var(--border-strong);border-radius:7px;font-size:11px}.provenance p{margin:7px 0;color:var(--fg-muted);overflow-wrap:anywhere}.provenance details{margin-top:12px}.provenance pre{font:11px/1.6 var(--font-mono);overflow-wrap:anywhere;white-space:pre-wrap}.feedback-form{border-top:1px solid var(--border);margin-top:24px;padding-top:21px}.frame-range{display:grid;grid-template-columns:1fr 1fr;gap:9px}.block{width:100%;margin-top:14px}.feedback-item{font-size:11px;overflow-wrap:anywhere;padding:12px 0;border-top:1px solid var(--border);margin-top:13px}.feedback-item strong{display:block;font-weight:500;color:var(--fg-strong)}.feedback-item button{padding:3px 7px;font-size:11px;margin-top:7px}.dirty{color:var(--warn)!important}.error{color:var(--fail)!important}footer{display:flex;justify-content:space-between;gap:13px;flex-wrap:wrap;padding:11px 18px;background:var(--footer-bg);border-top:1px solid var(--border);font-size:11px;color:var(--fg-soft)}[hidden]{display:none!important}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
2
5
  @media(min-width:1600px){.rig-viewport,.reference-viewport{min-height:620px}.layout{grid-template-columns:minmax(0,1fr) 320px}}
3
6
  @media(max-width:1100px){.layout{grid-template-columns:minmax(0,1fr) 260px}aside{padding:17px 12px}.stages{gap:7px;padding:9px;min-height:430px}.rig-viewport,.reference-viewport{min-height:380px}.pane-head{padding:9px}.pane-foot{padding:9px 7px}}
4
- @media(max-width:850px){.layout{grid-template-columns:1fr}aside{border-left:0;border-top:1px solid #3b5b69;display:grid;grid-template-columns:1fr 1fr;gap:12px 24px}aside>.eyebrow,aside>label,aside>select{grid-column:1/-1}.feedback-form,.provenance{margin-top:0}.feedback-form{padding-top:0;border-top:0}.actions{margin-left:0}.rig-viewport,.reference-viewport{min-height:420px}}
5
- @media(max-width:550px){header{gap:12px;padding:13px}.stages{grid-template-columns:repeat(2,minmax(0,1fr));gap:7px}.pane:first-child{grid-column:1/-1}.reference-viewport{min-height:240px}.rig-viewport{min-height:365px}.pane-head{padding:7px}.pane-foot{font-size:11px}aside{display:block}.feedback-form{margin-top:23px;padding-top:20px;border-top:1px solid #405f6c}.toolbar{padding:11px 13px}.transport{padding:12px;gap:8px}.transport input[type=range]{min-width:130px}.transport input[type=number]{width:84px}.provenance{margin-top:18px}}
7
+ @media(max-width:850px){.layout{grid-template-columns:1fr}aside{border-left:0;border-top:1px solid var(--border);display:grid;grid-template-columns:1fr 1fr;gap:12px 24px}aside>.eyebrow,aside>label,aside>select{grid-column:1/-1}.feedback-form,.provenance{margin-top:0}.feedback-form{padding-top:0;border-top:0}.actions{margin-left:0}.rig-viewport,.reference-viewport{min-height:420px}}
8
+ @media(max-width:550px){header{gap:12px;padding:13px}.stages{grid-template-columns:repeat(2,minmax(0,1fr));gap:7px}.pane:first-child{grid-column:1/-1}.reference-viewport{min-height:240px}.rig-viewport{min-height:365px}.pane-head{padding:7px}.pane-foot{font-size:11px}aside{display:block}.feedback-form{margin-top:23px;padding-top:20px;border-top:1px solid var(--border)}.toolbar{padding:11px 13px}.transport{padding:12px;gap:8px}.transport input[type=range]{min-width:130px}.transport input[type=number]{width:84px}.provenance{margin-top:18px}}
6
9
  @media(pointer:coarse){button{min-height:42px}input,select{font-size:16px}.row button{min-width:38px}}
7
10
 
8
11
  /* Inspection layout is bounded independently of pane content and review forms. */
@@ -13,37 +16,19 @@
13
16
  #stage-layout [data-panning=true]{cursor:grabbing!important}
14
17
  #stage-layout img{-webkit-user-drag:none;user-select:none}
15
18
  .rig-overlay{position:absolute;inset:0;pointer-events:none;width:100%;height:100%;z-index:1}
16
- .inspection-controls{display:flex;align-items:center;gap:8px 14px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid #35515e;font-size:11px;background:#172f3b}
19
+ .inspection-controls{display:flex;align-items:center;gap:8px 14px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--border);font-size:11px;background:var(--rv-panel)}
17
20
  .inspection-controls label{display:inline-flex;align-items:center;gap:5px;margin:0;white-space:nowrap}
18
21
  .inspection-controls select{width:auto;padding:4px;font-size:11px}
19
22
  .inspection-controls input[type=checkbox]{width:auto;margin:0}
20
23
  .inspection-controls fieldset{display:flex;gap:10px;align-items:center;border:0;padding:0;margin:0;min-width:0;flex-wrap:wrap}
21
24
  .inspection-controls legend{float:left;margin-right:9px;font-size:11px}
22
25
  #control-state:empty{display:none}
23
- :root[data-theme=light]{color-scheme:light;color:#233c47;background:#f4f7f9}
26
+ :root[data-theme=light]{color-scheme:light}
24
27
  :root[data-theme=dark]{color-scheme:dark}
25
- [data-theme=light] body,[data-theme=light] main{background:#f4f7f9;color:#233c47}
26
- [data-theme=light] header,[data-theme=light] .topbar,[data-theme=light] .workspaces,[data-theme=light] footer{background:#edf3f5;border-color:#bacbd3;color:#294552}
27
- [data-theme=light] aside,[data-theme=light] .transport,[data-theme=light] .frame-controls,[data-theme=light] .inspection-controls,[data-theme=light] .sound-panel,[data-theme=light] .angle-panel,[data-theme=light] .report-panel{background:#e9f0f3;border-color:#b7c9d1;color:#294552}
28
- [data-theme=light] button{background:#e2ebef;border-color:#a6bdc8;color:#264652}
29
- [data-theme=light] button:hover{background:#d0e2e8}
30
- [data-theme=light] button.primary,[data-theme=light] .primary{background:#24694d;border-color:#24694d;color:#fff}
31
- [data-theme=light] input,[data-theme=light] select,[data-theme=light] textarea{background:#fff;border-color:#8faab7;color:#243e4a;accent-color:#276c50}
32
- [data-theme=light] input::placeholder,[data-theme=light] textarea::placeholder{color:#607986}
33
- [data-theme=light] .hint,[data-theme=light] .subtle,[data-theme=light] .label,[data-theme=light] .eyebrow,[data-theme=light] aside label,[data-theme=light] .tool small,[data-theme=light] .stage-footer,[data-theme=light] .compare-info,[data-theme=light] .boundary,[data-theme=light] .trace,[data-theme=light] .transport output,[data-theme=light] .zoom-controls output,[data-theme=light] .frame-range label,[data-theme=light] .frame-controls label{color:#496774}
34
- [data-theme=light] .workspaces button,[data-theme=light] .segmented button{color:#3e5c69}
35
- [data-theme=light] .workspaces button[aria-pressed=true]{color:#185738;border-bottom-color:#276c50}
36
- [data-theme=light] .workspaces button span{color:#58727e}
37
- [data-theme=light] .segmented,[data-theme=light] .provenance,[data-theme=light] .report-selection pre{background:#e1ebef;border-color:#9cb5c0;color:#294552}
38
- [data-theme=light] .segmented button[aria-pressed=true],[data-theme=light] .checkpoint[aria-current=true],[data-theme=light] .report-event-list button[aria-current=true]{background:#cde4d8;border-color:#56866e;color:#1f4937}
39
- [data-theme=light] .checkpoint small{color:#4b6c59}
40
- [data-theme=light] .provenance p,[data-theme=light] .provenance-row span,[data-theme=light] .provenance details,[data-theme=light] .report-selection details,[data-theme=light] .report-event-list small{color:#486470}
41
- [data-theme=light] .report-event-list button,[data-theme=light] .report-empty-categories span{background:#e5eef2;border-color:#acbfca;color:#294552}
42
- [data-theme=light] .feedback-item strong{color:#1e4e3b}
43
- [data-theme=light] a{color:#175f48}
44
- [data-theme=light] .error{color:#a03225!important}
45
- [data-theme=light] .dirty,[data-theme=light] .report-event-list .no-time{color:#875800!important}
46
- [data-theme=light] :focus-visible{outline-color:#24694d}
28
+
29
+ input::placeholder,textarea::placeholder{color:var(--fg-muted)}
30
+
31
+ :focus-visible{outline-color:var(--rv-focus)}
47
32
  /* Source pixels retain their original color; the neutral stage stays dark in both themes. */
48
33
 
49
34
  #stage-layout{grid-template-columns:repeat(3,minmax(0,1fr))}#stage-layout[data-orientation=vertical]{grid-template-columns:minmax(0,1fr);grid-template-rows:repeat(3,minmax(0,1fr))}
@@ -55,12 +40,12 @@ html,body{height:100%;overflow:hidden}body{height:100dvh}#app{height:100dvh;disp
55
40
  main{min-height:0;overflow:hidden;display:flex;flex-direction:column}
56
41
  .left-panel{min-height:0;overflow:auto;padding:13px 10px}
57
42
  #stage-layout{height:auto;min-height:0;flex:1;overflow:hidden;padding:8px;gap:7px}
58
- .inspector{height:clamp(205px,32dvh,340px);min-height:180px;flex:none;display:flex;flex-direction:column;border-top:1px solid #49616d;background:#182d38;overflow:hidden}
59
- .inspector-heading{display:flex;align-items:center;gap:16px;flex-wrap:wrap;padding:7px 12px;border-bottom:1px solid #3e5c69;flex:none;font-size:11px}
43
+ .inspector{height:clamp(205px,32dvh,340px);min-height:180px;flex:none;display:flex;flex-direction:column;border-top:1px solid var(--border);background:var(--rv-panel);overflow:hidden}
44
+ .inspector-heading{display:flex;align-items:center;gap:16px;flex-wrap:wrap;padding:7px 12px;border-bottom:1px solid var(--border);flex:none;font-size:11px}
60
45
  .inspector-heading strong{font-size:10px;letter-spacing:.08em;font-weight:500}
61
46
  .inspector-heading [role=tablist]{display:flex;gap:4px}
62
47
  .inspector-heading button{padding:4px 9px;font-size:11px}
63
- .inspector-heading button[aria-selected=true]{background:#3d5d4d;color:#e0f3e7;border-color:#7fa98e}
48
+ .inspector-heading button[aria-selected=true]{background:var(--rv-pressed-bg);color:var(--rv-pressed-fg);border-color:var(--rv-pressed-border)}
64
49
  .inspector-body{flex:1;min-height:0;overflow:hidden}
65
50
  .inspector-body>[role=tabpanel]{height:100%;overflow:auto;padding:12px 15px;min-height:0}
66
51
  .inspector .inspection-controls{padding:0;border:0;background:transparent}
@@ -77,9 +62,7 @@ main{min-height:0;overflow:hidden;display:flex;flex-direction:column}
77
62
  #inspector-rig #part-set{max-width:190px}
78
63
  #inspector-playback #motion-tools{display:flex;gap:8px;flex-wrap:wrap}
79
64
  #inspector-playback .tool{width:auto}
80
- [data-theme=light] .inspector{background:#edf3f5;border-color:#a6bec8;color:#294552}
81
- [data-theme=light] .inspector-heading{border-color:#b3c6d0}
82
- [data-theme=light] .inspector-heading button[aria-selected=true]{background:#cde4d8;color:#1e4d36;border-color:#59836b}
65
+
83
66
  @media(max-width:780px){.layout{grid-template-columns:130px minmax(0,1fr)!important}.inspector{height:36dvh}.stage-meta{padding:6px 10px 0}.stage-footer{padding:5px 10px}.inspector-heading>.hint{display:none}}
84
67
  @media(max-width:540px){.layout{grid-template-columns:minmax(0,1fr)!important}.left-panel{display:block;padding:8px;font-size:11px}.layout{grid-template-columns:105px minmax(0,1fr)!important}.topbar,header{padding:7px 10px;gap:8px}.topbar .brand,header .brand{font-size:14px}.top-actions,.actions{gap:4px}.top-actions button,.actions button{padding:4px 6px;font-size:10px}.workspaces button{padding:6px}.inspector{height:40dvh;min-height:150px}.inspector-heading{gap:8px;padding:5px 8px}.inspector-heading button{padding:4px 7px}.stage-footer{display:none}}
85
68
 
@@ -91,12 +74,12 @@ body{display:grid;grid-template-rows:auto minmax(0,1fr) auto}.layout{grid-templa
91
74
 
92
75
  .rig-layer-controls{display:flex;gap:14px;align-items:center;flex-wrap:wrap;margin-bottom:12px;font-size:11px}.rig-layer-controls fieldset{display:flex;gap:12px;align-items:center;flex-wrap:wrap;border:0;margin:0;padding:0}.rig-layer-controls legend{float:left;margin-right:10px}.rig-layer-controls label{display:inline-flex;gap:5px;align-items:center}.rig-layer-controls input[type=checkbox]{width:auto}
93
76
 
94
- .numeric-view{font:11px/1.5 ui-monospace,SFMono-Regular,monospace;white-space:pre-wrap;overflow-wrap:anywhere;max-width:100%;padding:8px;background:#14232c;color:#c9dfe7;border-radius:5px}.view-link-controls{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:8px}.draft-notice{flex:none;font-size:11px;padding:0 12px;color:#e0c58e}.draft-notice:has(#draft-state:empty){display:none}.draft-notice #draft-recovery{display:inline-flex;gap:8px;margin-left:8px;flex-wrap:wrap}.draft-notice button{font-size:11px;padding:2px 6px}[data-theme=light] .numeric-view{background:#e1eaee;color:#264653}[data-theme=light] .draft-notice{color:#80521a}[data-theme=light] .outcome legend,[data-theme=light] .brand span,[data-theme=light] .toolbar{color:#496774}
77
+ .numeric-view{font:11px/1.5 var(--font-mono);white-space:pre-wrap;overflow-wrap:anywhere;max-width:100%;padding:8px;background:var(--code-bg);color:var(--code-fg);border-radius:5px}.view-link-controls{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:8px}.draft-notice{flex:none;font-size:11px;padding:0 12px;color:var(--warn)}.draft-notice:has(#draft-state:empty){display:none}.draft-notice #draft-recovery{display:inline-flex;gap:8px;margin-left:8px;flex-wrap:wrap}.draft-notice button{font-size:11px;padding:2px 6px}
95
78
 
96
79
  .camera-sync{display:inline-flex;align-items:center;gap:5px;font-size:11px;white-space:nowrap}.camera-sync input[type=checkbox]{width:auto;flex:none;margin:0}
97
80
 
98
81
  /* Slot explorer shares the stage row; bottom Inspector remains in the main column. */
99
- .layout{grid-template-columns:150px minmax(0,1fr) 235px!important}.parts-explorer{display:block;grid-template-columns:none;gap:normal;min-width:0;min-height:0;overflow:auto;border-left:1px solid #49616d;background:#182d38;padding:12px;overscroll-behavior:contain}.parts-explorer h2{font-size:12px;margin:0 0 10px}.parts-explorer>label{display:block;font-size:11px;margin-top:12px}.parts-explorer input[type=search]{width:100%;min-width:0}.parts-explorer .part-solo{display:flex;gap:6px;align-items:center}.parts-explorer ul{list-style:none;margin:8px 0;padding:0;display:grid;gap:4px}.parts-explorer li{min-width:0}.parts-explorer li button{display:block;width:100%;text-align:left;overflow-wrap:anywhere;font-size:11px}.parts-explorer button[aria-pressed=true]{background:#355445;border-color:#9cd3b4}.parts-explorer h2,#selected-part h3{font-weight:600}#selected-part{margin-bottom:12px}#selected-part h3{margin:0 0 8px;overflow-wrap:anywhere}#selected-part p{overflow-wrap:anywhere}[data-theme=light] .parts-explorer{background:#edf3f5;border-color:#a6bec8;color:#294552}[data-theme=light] .parts-explorer button[aria-pressed=true]{background:#c5ddcd;color:#183c2c}
82
+ .layout{grid-template-columns:150px minmax(0,1fr) 235px!important}.parts-explorer{display:block;grid-template-columns:none;gap:normal;min-width:0;min-height:0;overflow:auto;border-left:1px solid var(--border);background:var(--rv-panel);padding:12px;overscroll-behavior:contain}.parts-explorer h2{font-size:12px;margin:0 0 10px}.parts-explorer>label{display:block;font-size:11px;margin-top:12px}.parts-explorer input[type=search]{width:100%;min-width:0}.parts-explorer .part-solo{display:flex;gap:6px;align-items:center}.parts-explorer ul{list-style:none;margin:8px 0;padding:0;display:grid;gap:4px}.parts-explorer li{min-width:0}.parts-explorer li button{display:block;width:100%;text-align:left;overflow-wrap:anywhere;font-size:11px}.parts-explorer button[aria-pressed=true]{background:var(--rv-pressed-bg);border-color:var(--rv-pressed-border)}.parts-explorer h2,#selected-part h3{font-weight:600}#selected-part{margin-bottom:12px}#selected-part h3{margin:0 0 8px;overflow-wrap:anywhere}#selected-part p{overflow-wrap:anywhere}
100
83
  @media(max-width:1050px){.layout{grid-template-columns:110px minmax(0,1fr) 185px!important}.parts-explorer{padding:8px}}
101
84
  @media(max-width:700px){.layout{grid-template-columns:minmax(0,1fr) 165px!important}.left-panel{display:none!important}}
102
85
  @media(max-width:460px){.layout{grid-template-columns:minmax(0,1fr) 132px!important}.parts-explorer{padding:6px}.parts-explorer li button{padding:6px}.parts-explorer>.hint{font-size:10px}}
@@ -108,9 +91,9 @@ body{display:grid;grid-template-rows:auto minmax(0,1fr) auto}.layout{grid-templa
108
91
  .workspace-layout>main{display:grid;min-width:0;min-height:0;overflow:hidden;grid-column:3;grid-row:1}
109
92
  .workspace-stage-stack{grid-row:1;display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden}
110
93
  .workspace-stage-stack>#stage-layout{flex:1;min-height:0;height:auto;overflow:hidden}
111
- .workspace-layout>.left-panel{grid-column:1;grid-row:1;display:flex!important;flex-direction:column;overflow:hidden;min-width:0;padding:0;border-right:1px solid #49616d}
94
+ .workspace-layout>.left-panel{grid-column:1;grid-row:1;display:flex!important;flex-direction:column;overflow:hidden;min-width:0;padding:0;border-right:1px solid var(--border)}
112
95
  .workspace-sources{flex:1;min-height:0;overflow:auto;padding:10px;overscroll-behavior:contain}
113
- .workspace-settings{flex:none;max-height:65%;overflow:auto;padding:10px;border-top:1px solid #49616d}
96
+ .workspace-settings{flex:none;max-height:65%;overflow:auto;padding:10px;border-top:1px solid var(--border)}
114
97
  .workspace-settings h2{font-size:12px;margin:0 0 8px}
115
98
  .workspace-settings label{display:flex;align-items:center;gap:6px;font-size:11px;margin:7px 0}
116
99
  .workspace-settings select{width:auto;min-width:0;flex:1}
@@ -118,23 +101,23 @@ body{display:grid;grid-template-rows:auto minmax(0,1fr) auto}.layout{grid-templa
118
101
  .workspace-settings input[type=checkbox]{width:auto;flex:none}
119
102
  .workspace-layout>.parts-explorer{display:block;grid-template-columns:none;grid-column:5;grid-row:1;width:auto;min-width:0;min-height:0;height:auto;overflow:auto}
120
103
  .workspace-layout .inspector{grid-row:3;height:auto!important;min-height:0!important;max-height:none;overflow:hidden}
121
- .workspace-separator{position:relative;z-index:3;background:#34515e;touch-action:none;cursor:col-resize;min-width:0;min-height:0}
104
+ .workspace-separator{position:relative;z-index:3;background:var(--border-strong);touch-action:none;cursor:col-resize;min-width:0;min-height:0}
122
105
  .workspace-separator::after{content:'';position:absolute;inset:0 -4px}
123
- .workspace-separator:focus-visible{outline:2px solid #c8e8d6;outline-offset:-2px;background:#719581}
124
- .workspace-separator[data-resizing=true]{background:#8ac9a3}
106
+ .workspace-separator:focus-visible{outline:2px solid var(--rv-focus);outline-offset:-2px;background:var(--link)}
107
+ .workspace-separator[data-resizing=true]{background:var(--link-hover)}
125
108
  .workspace-leftWidth{grid-column:2;grid-row:1}.workspace-rightWidth{grid-column:4;grid-row:1}
126
109
  .workspace-inspectorHeight{grid-row:2;cursor:row-resize}.workspace-inspectorHeight::after{inset:-4px 0}
127
110
  .workspace-drawer-triggers{display:flex;gap:6px;flex-wrap:wrap;flex:none;padding:4px 8px;min-height:0}
128
111
  .workspace-drawer-triggers:not(:has(button:not([hidden]))){display:none}
129
112
  .workspace-drawer-triggers button{padding:4px 7px;font-size:11px;min-height:28px}
130
- .workspace-drawer{position:fixed;inset:0;width:min(94vw,950px);height:min(92dvh,850px);max-width:94vw;max-height:92dvh;margin:auto;padding:8px;border:1px solid #739383;border-radius:8px;background:#182d38;color:inherit;overflow:hidden;z-index:20}
113
+ .workspace-drawer{position:fixed;inset:0;width:min(94vw,950px);height:min(92dvh,850px);max-width:94vw;max-height:92dvh;margin:auto;padding:8px;border:1px solid var(--border-strong);border-radius:8px;background:var(--rv-panel);color:inherit;overflow:hidden;z-index:20}
131
114
  .workspace-drawer:not([open]){display:none}.workspace-drawer[open]{display:flex;flex-direction:column;gap:8px}
132
- .workspace-drawer::backdrop{background:#07141ed0}
115
+ .workspace-drawer::backdrop{background:var(--rv-backdrop)}
133
116
  .workspace-drawer-close{align-self:flex-end;flex:none}
117
+ .workspace-drawer-header{display:flex;align-items:center;justify-content:space-between;gap:8px;flex:none}
134
118
  .workspace-drawer>.left-panel{display:flex!important;flex-direction:column;flex:1;overflow:hidden;min-height:0;padding:0}
135
119
  .workspace-drawer>.parts-explorer{display:block;grid-template-columns:none;flex:1;width:auto;min-width:0;min-height:0;height:auto;overflow:auto}
136
120
  .workspace-drawer>.inspector{flex:1;height:auto!important;min-height:0!important;max-height:none;overflow:hidden}
137
- [data-theme=light] .workspace-settings,[data-theme=light] .workspace-drawer{background:#edf3f5;color:#294552;border-color:#a6bec8}
138
- [data-theme=light] .workspace-separator{background:#b2c7cf}[data-theme=light] .workspace-separator:focus-visible{outline-color:#24694d;background:#70a58c}
121
+
139
122
  @media(pointer:coarse){.workspace-separator::after{inset:0 -7px}.workspace-inspectorHeight::after{inset:-7px 0}.workspace-drawer-triggers button{min-height:38px}}
140
123
  #stage-layout[data-panes="1"]{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr)}
package/web/index.html CHANGED
@@ -3,11 +3,9 @@
3
3
  <head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>rig review</title><link rel="stylesheet" href="styles.css"></head>
4
4
  <body>
5
5
  <div id="app">
6
- <header class="topbar"><div class="brand"><span class="brand-mark">r</span>rig review</div><div><strong id="package-title">Review package</strong><span id="revision" class="subtle"></span></div><div class="top-actions"><span id="dirty" class="subtle">Loading…</span><button id="export">Feedback JSON</button><button id="export-markdown">Issue Markdown</button><button id="save" class="primary" disabled>Submit review</button></div></header>
6
+ <header class="topbar"><div class="brand"><span class="brand-mark">r</span>rig review</div><div><strong id="package-title">Review package</strong><span id="revision" class="subtle"></span></div><div class="mode-switch" role="group" aria-label="Mode"><button type="button" data-mode="rig" data-inspector="rig" aria-controls="inspector-rig" aria-pressed="true">Setup</button><button type="button" data-mode="playback" data-inspector="playback" aria-controls="inspector-playback" aria-pressed="false">Animate</button></div><div class="top-actions"><span id="dirty" class="subtle">Loading…</span><button id="write-review" type="button" class="primary" aria-haspopup="dialog" aria-controls="review-dialog">Write review</button></div></header>
7
7
  <div class="layout">
8
- <aside class="left-panel"><div class="eyebrow">CHECKPOINTS</div><nav id="checkpoints" aria-label="Checkpoints"></nav><section><label for="reference-select" class="label">Reference</label><select id="reference-select"></select><div id="reference-info" class="hint"></div><div id="person-control" hidden><label for="person-select" class="label space-top">Person in input pose</label><select id="person-select"></select></div></section><section><div class="eyebrow">SOURCE FILES · READ ONLY</div><div id="source-files"></div></section></aside>
9
- <main><div class="viewbar"><div class="segmented" aria-label="View"><button data-view="compare" aria-pressed="true">Side by side</button><button data-view="reference" aria-pressed="false">Reference</button><button data-view="rig" aria-pressed="false">Rig</button></div><div class="zoom-controls"><label class="camera-sync"><input id="camera-sync" type="checkbox" checked>Sync cameras</label><button id="zoom-out" aria-label="Zoom out">−</button><output id="zoom-value">100%</output><button id="zoom-in" aria-label="Zoom in">+</button><button id="fit">Fit</button></div></div><div class="stage-meta"><span id="checkpoint-title">Select a checkpoint</span><span id="player-state" class="subtle">No rig supplied</span><span id="layout-state" class="subtle" role="status" aria-label="Effective layout">Loading inputs…</span><span id="renderer-state" class="subtle" aria-label="Last draw backend" title="DOM images for rigid parts; WebGL meshes when available, Canvas2D fallback.">Not rendered</span></div><div id="stage-layout" class="stages"><section id="reference-pane" class="stage-pane" aria-label="Reference"><span id="reference-label" class="pane-label">Reference</span><div id="reference-viewport" class="viewport"><div id="reference-content" class="reference-content"></div><div id="reference-empty" class="empty">No reference supplied.</div></div></section><section id="rig-pane" class="stage-pane" aria-label="Rig"><span class="pane-label">Generated rig · read only</span><div id="rig-viewport" class="viewport"><div id="rig-root"></div><canvas id="rig-overlay" class="rig-overlay" aria-label="Actual rig mesh and bone overlay"></canvas><div id="rig-empty" class="empty">No compiled model supplied.</div></div></section></div><div class="stage-footer"><span id="coordinates">Drag to pan · scroll to zoom · cameras synchronized</span><span>Source files remain unchanged.</span></div><section class="inspector" aria-label="Inspection controls"><div class="inspector-heading"><strong>INSPECTOR</strong><div role="tablist" aria-label="Inspector sections"><button role="tab" id="tab-view" data-inspector="view" aria-controls="inspector-view" aria-selected="true" tabindex="0">View</button><button role="tab" id="tab-rig" data-inspector="rig" aria-controls="inspector-rig" aria-selected="false" tabindex="-1">Rig</button><button role="tab" id="tab-playback" data-inspector="playback" aria-controls="inspector-playback" aria-selected="false" tabindex="-1">Playback</button><button role="tab" id="tab-feedback" data-inspector="feedback" aria-controls="inspector-feedback" aria-selected="false" tabindex="-1">Feedback</button></div><span class="hint">Local view controls · source files stay unchanged</span></div><div class="draft-notice"><span id="draft-state" role="status" aria-live="polite"></span><div id="draft-recovery"></div></div><div class="inspector-body"><section id="inspector-view" role="tabpanel" aria-labelledby="tab-view" data-inspector-panel="view"><div class="view-link-controls"><button id="copy-view" type="button">Copy view link</button><span class="hint">Numeric source region · opening this link restores a paused inspection</span></div><pre id="view-coordinates" class="numeric-view" aria-label="Current numeric inspection region"></pre><div class="inspection-controls" aria-label="Inspection display controls"><label>Appearance <select id="appearance"><option value="system">System</option><option value="dark">Dark</option><option value="light">Light</option></select></label><label><input id="idle-repeat" type="checkbox" checked>Repeat idle</label><span id="idle-state" class="hint" role="status">Idle preview unavailable</span><span id="control-state" class="hint" role="status"></span></div><p class="hint">Sync cameras links fit-relative zoom and viewport-relative pan across visible panes. Turn it off to inspect each pane independently. Toolbar zoom and Fit use the last active pane. Hold Space while dragging a video to pan without taking over its native controls.</p></section><section id="inspector-rig" role="tabpanel" aria-labelledby="tab-rig" data-inspector-panel="rig" hidden><section id="selected-part" aria-label="Selected part" aria-live="polite"></section><div class="rig-layer-controls"><fieldset id="layer-controls"><legend>Rig layers</legend><label><input id="layer-images" type="checkbox" checked disabled>Images</label><label><input id="layer-mesh" type="checkbox" disabled>Mesh edges</label><label><input id="layer-bones" type="checkbox" disabled>Bone points</label></fieldset><span id="layer-state" class="hint">No rig supplied</span></div><section id="modeling-tools"><div class="eyebrow">MODELING REVIEW</div><button data-proposal="mesh" class="tool">Mesh density <small>Add feedback</small></button><button data-proposal="contour" class="tool">Contour curvature <small>Add feedback</small></button><button data-proposal="chest" class="tool">Chest position <small>Add feedback</small></button><button data-proposal="angle" class="tool">Angle inspection <small id="axis-state">No inspection axes supplied</small></button><label for="part-set" class="label space-top">Part presets</label><select id="part-set" disabled><option>No sets supplied</option></select><p class="hint">Preview only · does not create motion keys.</p></section><section id="angle-panel" class="angle-panel" hidden><label for="axis-select">Rig inspection axis</label><select id="axis-select"></select><label id="axis-label" for="axis-value"></label><input id="axis-value" type="range" disabled><output id="axis-value-label"></output><p class="hint">Maps one inspection axis to its animation time. This does not rotate the camera.</p></section></section><section id="inspector-playback" role="tabpanel" aria-labelledby="tab-playback" data-inspector-panel="playback" hidden><section id="transport" class="transport"><button id="play" aria-label="Play" disabled>▶</button><label for="animation-select" class="sr-only">Animation</label><select id="animation-select" disabled><option>No animations supplied</option></select><input id="scrub" type="range" min="0" max="1" step="0.001" value="0" aria-label="Playback time"><output id="time-label">0.0000 / 0.0000 s</output><output id="frame-label">rate unknown</output></section><section id="frame-controls" class="frame-controls" hidden aria-label="Frame navigation using the explicit clock"><label for="frame-number">Frame</label><input id="frame-number" type="number" min="0" step="1" inputmode="numeric" aria-label="Frame number to inspect"><button id="frame-jump" type="button">Go</button><input id="frame-scrub" type="range" min="0" max="1" step="1" value="0" aria-label="Scrub by frame"><span id="frame-clock-label" class="hint"></span><p id="frame-outside" class="hint" hidden>The current time is outside the explicit frame range. Enter a frame number to go to its exact time.</p></section><section id="motion-tools"><div class="eyebrow">MOTION · READ ONLY</div><button data-proposal="pose" class="tool">Inspect pose <small>Add feedback</small></button><button data-proposal="timing" class="tool">Inspect interval <small>Add feedback</small></button><button data-proposal="audio" class="tool">Audio links <small>Add feedback</small></button></section><section id="sound-panel" class="sound-panel"><div class="row"><span class="eyebrow">SOUND CUES</span><label><input id="sync-audio" type="checkbox">Play cue audio in sync</label></div><div id="cues"></div><div class="row"><label for="audio-volume">Audio volume</label><input id="audio-volume" type="range" min="0" max="1" step="0.05" value="0.8"><output id="audio-volume-label">80%</output></div><div id="event-log" class="hint" aria-live="polite">Runtime events: none</div></section><section id="report-panel" class="report-panel" aria-labelledby="report-heading"><div class="report-header"><h2 id="report-heading">Report events</h2><span id="report-summary" class="subtle"></span><a id="report-source-link" target="_blank" rel="noopener" hidden>Source report</a></div><p id="report-unavailable" class="hint" hidden>No rig-pose-report/1 events supplied.</p><div id="report-browser"><div class="report-controls"><label for="report-category" class="sr-only">Report event category</label><select id="report-category"><option value="all">All events</option></select><button id="report-previous" type="button" aria-label="Previous event page">Previous</button><output id="report-page"></output><button id="report-next" type="button" aria-label="Next event page">Next</button></div><div id="report-empty-categories" class="report-empty-categories"></div><p id="report-missing" class="hint" hidden></p><ol id="report-events" class="report-event-list" aria-label="Read-only report events"></ol><section id="report-selection" class="report-selection" hidden aria-labelledby="report-selection-heading"><h3 id="report-selection-heading"></h3><p id="report-timing" class="hint"></p><div class="report-controls"><label id="report-time-label" for="report-time" hidden>Select explicit time</label><select id="report-time" hidden></select><button id="report-seek" type="button" disabled>Go to explicit time</button></div><div id="report-target-control" hidden><label for="report-target" class="label space-top">Select a target named in the report</label><select id="report-target"></select></div><p id="report-prefill-note" class="hint"></p><p id="report-provenance" class="hint"></p><details><summary>Source event details</summary><pre id="report-details"></pre></details></section></div></section></section><section id="inspector-feedback" role="tabpanel" aria-labelledby="tab-feedback" data-inspector-panel="feedback" hidden><div class="review-summary"><div class="eyebrow">REVIEW</div><label for="review-status" class="label">Review status</label><select id="review-status"><option value="pending">Pending</option><option value="approved">Approved</option><option value="changes-requested">Changes requested</option></select><section class="provenance" aria-label="Reviewed source"><div class="eyebrow">REVIEWED SOURCE</div><div class="provenance-row"><span>Package revision</span><strong id="provenance-version">—</strong></div><div class="provenance-row"><span>rig SHA-256</span><code id="provenance-rig">—</code></div><div class="provenance-row"><span>motion SHA-256</span><code id="provenance-motion">—</code></div><details><summary>Full provenance</summary><pre id="provenance-full"></pre></details><p class="hint">Submits server-verified file hashes and tool versions. Your selected review status is preserved.</p></section><div class="divider"></div></div><div id="checkpoint-detail"><div class="eyebrow">SELECTED CHECKPOINT</div><h1 id="detail-title">Checkpoint</h1><p id="detail-note" class="hint"></p><fieldset class="outcome"><legend>Checkpoint outcome</legend><label><input type="radio" name="outcome" value="pending" checked>Pending</label><label><input type="radio" name="outcome" value="pass">Pass</label><label><input type="radio" name="outcome" value="fail">Needs changes</label></fieldset><label for="checkpoint-note" class="label space-top">Review notes</label><textarea id="checkpoint-note" rows="5" placeholder="Describe the part, conditions and what looks wrong."></textarea></div><div class="divider"></div><section id="proposal-panel"><div class="eyebrow">STRUCTURED FEEDBACK</div><div class="label">Frame range · inclusive</div><div class="frame-range"><label>Start<input id="feedback-start" type="number" min="0" step="1" inputmode="numeric" placeholder="e.g. 18"></label><label>End<input id="feedback-end" type="number" min="0" step="1" inputmode="numeric" placeholder="e.g. 32"></label></div><p id="feedback-range-hint" class="hint">Checking frame bounds…</p><label for="feedback-target-kind" class="label space-top">Target type</label><select id="feedback-target-kind"><option value="">Select target</option><option value="rig">Entire rig</option><option value="bone">Bone</option><option value="slot">Slot</option></select><label for="feedback-target-name" class="label space-top">Target name</label><input id="feedback-target-name" type="text" list="feedback-target-names" autocomplete="off" placeholder="Actual bone or slot name"><datalist id="feedback-target-names"></datalist><p id="feedback-target-hint" class="hint"></p><label for="feedback-category" class="label space-top">Category</label><select id="feedback-category"><option value="">Select category</option><option value="defect">Defect</option><option value="quality">Quality</option></select><label for="feedback-summary" class="label space-top">One-line summary</label><input id="feedback-summary" type="text" maxlength="1000" placeholder="e.g. The left wrist moves outside the sleeve"><button id="add-proposal" class="outline block">Add feedback</button><p id="proposal-boundary" class="hint">Records the current checkpoint, time, reference, camera and inspection axis. Motion is read only: inspect, mark ranges and export feedback. No keys or source files are edited.</p><p id="feedback-warnings" class="hint" role="status" hidden></p><div id="proposal-list"></div></section><details id="strip-panel" class="report-panel"><summary>Export frame strip</summary><p class="hint">Uses the feedback form start and end frames, inclusive. Inspection time and source files remain unchanged.</p><label for="strip-scope" class="label">Export range</label><select id="strip-scope"><option value="interval">Entered start–end frames</option><option value="feedback">All feedback ranges</option></select><label for="strip-reference" class="label space-top">Reference video</label><select id="strip-reference"><option value="">Select reference video</option></select><label for="strip-format" class="label space-top">Format</label><select id="strip-format"><option value="png">PNG strip</option><option value="json">JSON frames and provenance</option></select><p class="hint">PNG requires frameTimes in the selected report. Without it, JSON preserves requested frames with time: null. Batch export requires every feedback item to match the selected animation. Unsubmitted feedback is included; exporting does not submit the review.</p><button id="strip-export" type="button" disabled>Download strip</button><p id="strip-status" class="hint" role="status" aria-live="polite">Loading package…</p></details></section></div></section></main><aside id="parts-explorer" class="parts-explorer" aria-label="Parts explorer"><h2>PARTS</h2><button type="button" data-part-whole aria-pressed="true">Whole rig</button><label for="part-search">Find slot</label><input id="part-search" data-part-search type="search" autocomplete="off" placeholder="Exact slot name or text"><label class="part-solo"><input id="part-solo" data-part-solo type="checkbox" disabled>Solo selected slot</label><p data-part-status class="hint" role="status">Loading actual slots…</p><ul data-part-list aria-label="Actual rig slots"></ul><p class="hint">Select in context or enable Solo. Type icons and main preview represent actual slots; atlas pages are not part thumbnails.</p></aside>
10
-
11
- </div><footer><span id="message" role="status" aria-live="polite">Loading local review package…</span><span id="source-hash" class="subtle"></span></footer>
12
- </div><script type="module" src="main.js"></script>
8
+ <aside class="left-panel"><div class="left-header parts-header"><h2>PARTS</h2><label for="part-search">Find slot</label><input id="part-search" data-part-search type="search" autocomplete="off" placeholder="Exact slot name or text"></div><details id="package-context" class="package-context"><summary><span class="eyebrow">CHECKPOINTS</span><span id="checkpoint-title">Select a checkpoint</span></summary><nav id="checkpoints" aria-label="Checkpoints"></nav><section><label for="reference-select" class="label">Reference</label><select id="reference-select"></select><div id="reference-info" class="hint"></div><div id="person-control" hidden><label for="person-select" class="label space-top">Person in input pose</label><select id="person-select"></select></div></section></details><aside id="parts-explorer" class="parts-explorer" aria-label="Parts explorer"><button type="button" data-part-whole aria-pressed="true">Whole rig</button><label class="part-solo"><input id="part-solo" data-part-solo type="checkbox" disabled>Solo selected slot</label><p data-part-status class="hint" role="status">Loading actual slots…</p><ul data-part-list aria-label="Actual rig slots"></ul><p class="hint">Select in context or enable Solo. Type icons and main preview represent actual slots; atlas pages are not part thumbnails.</p></aside></aside>
9
+ <main><div class="viewbar"><fieldset id="layer-controls" class="layer-toggles"><legend class="sr-only">Rig layers</legend><label class="layer-toggle" title="No rig supplied"><input aria-keyshortcuts="I" id="layer-images" type="checkbox" checked disabled><span>Images</span><kbd aria-hidden="true">I</kbd></label><label class="layer-toggle" title="No rig supplied"><input aria-keyshortcuts="M" id="layer-mesh" type="checkbox" disabled><span>Mesh edges</span><kbd aria-hidden="true">M</kbd></label><label class="layer-toggle" title="No rig supplied"><input aria-keyshortcuts="B" id="layer-bones" type="checkbox" disabled><span>Bone points</span><kbd aria-hidden="true">B</kbd></label></fieldset><div class="zoom-controls"><label class="camera-sync"><input id="camera-sync" type="checkbox" checked>Sync cameras</label><button id="zoom-out" aria-label="Zoom out">−</button><output id="zoom-value">100%</output><button id="zoom-in" aria-label="Zoom in">+</button><button id="fit">Fit</button></div><details id="view-menu" class="view-menu"><summary aria-label="View layout">View: <span id="view-menu-label">Side by side</span></summary><div class="view-menu-list" role="group" aria-label="View"><button type="button" data-view="compare" aria-pressed="true">Side by side</button><button type="button" data-view="reference" aria-pressed="false">Reference</button><button type="button" data-view="rig" aria-pressed="false">Rig</button></div></details></div><div id="stage-layout" class="stages"><section id="reference-pane" class="stage-pane" aria-label="Reference"><span id="reference-label" class="pane-label">Reference</span><div id="reference-viewport" class="viewport"><div id="reference-content" class="reference-content"></div><div id="reference-empty" class="empty">No reference supplied.</div></div></section><section id="rig-pane" class="stage-pane" aria-label="Rig"><span class="pane-label">Generated rig · read only</span><div id="rig-viewport" class="viewport"><div id="rig-root"></div><canvas id="rig-overlay" class="rig-overlay" aria-label="Actual rig mesh and bone overlay"></canvas><div id="rig-empty" class="empty">No compiled model supplied.</div></div></section></div><div class="stage-footer"><span id="coordinates">Drag to pan · scroll to zoom · cameras synchronized</span><span>Source files remain unchanged.</span></div><section class="inspector" aria-label="Inspection controls"><div class="inspector-heading sticky-header"><strong>INSPECTOR</strong><span class="hint">Local view controls · source files stay unchanged</span></div><div class="inspector-body"><section id="inspector-rig" aria-label="Setup" data-inspector-panel="rig"><section id="selected-part" aria-label="Selected part" aria-live="polite"></section><section id="modeling-tools"><div class="eyebrow">MODELING REVIEW</div><button data-proposal="mesh" class="tool">Mesh density <small>Add feedback</small></button><button data-proposal="contour" class="tool">Contour curvature <small>Add feedback</small></button><button data-proposal="chest" class="tool">Chest position <small>Add feedback</small></button><label for="part-set" class="label space-top">Part presets</label><select id="part-set" disabled><option>No sets supplied</option></select><p class="hint">Preview only · does not create motion keys.</p></section><section id="chest-regions" class="chest-regions" aria-labelledby="chest-regions-heading"><div class="eyebrow" id="chest-regions-heading">CHEST REGIONS · DESIGNATION ONLY</div><p class="hint">Crop pixels, x screen-right and y down (<code>family-chest-regions/1</code>). Numeric fields only; the rig pane draws each core as the generator's 32-sample polygon. Exporting writes nothing into the package and is not an approval.</p><p id="chest-mapping" class="hint"></p><div class="chest-grid"><label>Crop width<input id="chest-crop-w" type="number" step="any" inputmode="decimal"></label><label>Crop height<input id="chest-crop-h" type="number" step="any" inputmode="decimal"></label></div><fieldset class="chest-row"><legend>Region 1</legend><label>Name<input id="chest-0-name" type="text" autocomplete="off" spellcheck="false"></label><label>Bone<select id="chest-0-bone"><option value="">Select bone</option></select></label><label>Centre x<input id="chest-0-cx" type="number" step="any" inputmode="decimal"></label><label>Centre y<input id="chest-0-cy" type="number" step="any" inputmode="decimal"></label><label>Semi-axis x<input id="chest-0-ax" type="number" step="any" inputmode="decimal"></label><label>Semi-axis y<input id="chest-0-ay" type="number" step="any" inputmode="decimal"></label><label>Spacing<input id="chest-0-spacing" type="number" step="any" inputmode="decimal"></label><label>Band<input id="chest-0-band" type="number" step="any" inputmode="decimal"></label><label>Medial clip x<input id="chest-0-clip" type="number" step="any" inputmode="decimal" placeholder="none"></label></fieldset><fieldset class="chest-row"><legend>Region 2</legend><label>Name<input id="chest-1-name" type="text" autocomplete="off" spellcheck="false"></label><label>Bone<select id="chest-1-bone"><option value="">Select bone</option></select></label><label>Centre x<input id="chest-1-cx" type="number" step="any" inputmode="decimal"></label><label>Centre y<input id="chest-1-cy" type="number" step="any" inputmode="decimal"></label><label>Semi-axis x<input id="chest-1-ax" type="number" step="any" inputmode="decimal"></label><label>Semi-axis y<input id="chest-1-ay" type="number" step="any" inputmode="decimal"></label><label>Spacing<input id="chest-1-spacing" type="number" step="any" inputmode="decimal"></label><label>Band<input id="chest-1-band" type="number" step="any" inputmode="decimal"></label><label>Medial clip x<input id="chest-1-clip" type="number" step="any" inputmode="decimal" placeholder="none"></label></fieldset><fieldset class="chest-row"><legend>Contour</legend><label>Tolerance<input id="chest-tolerance" type="number" step="any" inputmode="decimal"></label><label>Margin<input id="chest-margin" type="number" step="any" inputmode="decimal"></label><label>Spacing<input id="chest-spacing" type="number" step="any" inputmode="decimal"></label><label>Max edge<input id="chest-max-edge" type="number" step="any" inputmode="decimal"></label><label>Stray<input id="chest-stray" type="number" step="any" inputmode="decimal"></label><label class="chest-check"><input id="chest-bridges" type="checkbox">Bridges</label></fieldset><details class="chest-more"><summary>Generator and mesh fields</summary><label for="chest-generator" class="label space-top">Public generator</label><input id="chest-generator" type="text" autocomplete="off" spellcheck="false" placeholder="Generator that will read this file"><label for="chest-r" class="label space-top">Mesh r (optional)</label><input id="chest-r" type="number" step="any" inputmode="decimal"><label for="chest-segments" class="label space-top">Mesh segments JSON (optional)</label><textarea id="chest-segments" rows="3" spellcheck="false"></textarea><label for="chest-source-rule" class="label space-top">Source rule (optional)</label><input id="chest-source-rule" type="text" autocomplete="off"></details><p id="chest-status" class="hint" aria-live="polite"></p><button id="chest-export" type="button" class="outline block">Download chest-regions.json</button></section></section><section id="inspector-playback" aria-label="Animate" data-inspector-panel="playback" hidden><section id="transport" class="transport"><button id="play" aria-label="Play" disabled>▶</button><label for="animation-select" class="sr-only">Animation</label><select id="animation-select" disabled><option>No animations supplied</option></select><input id="scrub" type="range" min="0" max="1" step="0.001" value="0" aria-label="Playback time"><output id="time-label">0.0000 / 0.0000 s</output><output id="frame-label">rate unknown</output><label class="idle-repeat"><input id="idle-repeat" type="checkbox" checked>Repeat idle</label></section><section id="frame-controls" class="frame-controls" hidden aria-label="Frame navigation using the explicit clock"><label for="frame-number">Frame</label><input id="frame-number" type="number" min="0" step="1" inputmode="numeric" aria-label="Frame number to inspect"><button id="frame-jump" type="button">Go</button><input id="frame-scrub" type="range" min="0" max="1" step="1" value="0" aria-label="Scrub by frame"><span id="frame-clock-label" class="hint"></span><p id="frame-outside" class="hint" hidden>The current time is outside the explicit frame range. Enter a frame number to go to its exact time.</p></section><section id="motion-tools"><div class="eyebrow">MOTION · READ ONLY</div><button data-proposal="pose" class="tool">Inspect pose <small>Add feedback</small></button><button data-proposal="timing" class="tool">Inspect interval <small>Add feedback</small></button><button data-proposal="audio" class="tool">Audio links <small>Add feedback</small></button><button data-proposal="angle" class="tool">Angle inspection <small id="axis-state">No inspection axes supplied</small></button></section><section id="angle-panel" class="angle-panel" hidden><label for="axis-select">Rig inspection axis</label><select id="axis-select"></select><label id="axis-label" for="axis-value"></label><input id="axis-value" type="range" disabled><output id="axis-value-label"></output><p class="hint">Maps one inspection axis to its animation time. This does not rotate the camera.</p></section><section id="sound-panel" class="sound-panel"><div class="row"><span class="eyebrow">SOUND CUES</span><label><input id="sync-audio" type="checkbox">Play cue audio in sync</label></div><div id="cues"></div><div class="row"><label for="audio-volume">Audio volume</label><input id="audio-volume" type="range" min="0" max="1" step="0.05" value="0.8"><output id="audio-volume-label">80%</output></div><div id="event-log" class="hint" aria-live="polite">Runtime events: none</div></section><section id="report-panel" class="report-panel" aria-labelledby="report-heading"><div class="report-header"><h2 id="report-heading">Report events</h2><span id="report-summary" class="subtle"></span><a id="report-source-link" target="_blank" rel="noopener" hidden>Source report</a></div><p id="report-unavailable" class="hint" hidden>No rig-pose-report/1 events supplied.</p><div id="report-browser"><div class="report-controls"><label for="report-category" class="sr-only">Report event category</label><select id="report-category"><option value="all">All events</option></select><button id="report-previous" type="button" aria-label="Previous event page">Previous</button><output id="report-page"></output><button id="report-next" type="button" aria-label="Next event page">Next</button></div><div id="report-empty-categories" class="report-empty-categories"></div><p id="report-missing" class="hint" hidden></p><ol id="report-events" class="report-event-list" aria-label="Read-only report events"></ol><section id="report-selection" class="report-selection" hidden aria-labelledby="report-selection-heading"><h3 id="report-selection-heading"></h3><p id="report-timing" class="hint"></p><div class="report-controls"><label id="report-time-label" for="report-time" hidden>Select explicit time</label><select id="report-time" hidden></select><button id="report-seek" type="button" disabled>Go to explicit time</button></div><div id="report-target-control" hidden><label for="report-target" class="label space-top">Select a target named in the report</label><select id="report-target"></select></div><p id="report-prefill-note" class="hint"></p><p id="report-provenance" class="hint"></p><details><summary>Source event details</summary><pre id="report-details"></pre></details></section></div></section></section></div></section></main></div><footer class="status-bar"><span id="message" class="status-message" role="status" aria-live="polite">Loading local review package…</span><div class="status-readouts" aria-label="Status"><span id="player-state" class="subtle">No rig supplied</span><span id="layout-state" class="subtle" role="status" aria-label="Effective layout">Loading inputs…</span><span id="renderer-state" class="subtle" aria-label="Last draw backend" title="DOM images for rigid parts; WebGL meshes when available, Canvas2D fallback.">Not rendered</span><span id="layer-state" class="hint">No rig supplied</span><span id="idle-state" class="hint" role="status">Idle preview unavailable</span><span id="control-state" class="hint" role="status"></span><div class="draft-notice"><span id="draft-state" role="status" aria-live="polite"></span><div id="draft-recovery"></div></div></div><div class="status-source"><details class="view-region"><summary>View region</summary><div class="view-region-body"><span class="hint">Numeric source region · opening this link restores a paused inspection</span><pre id="view-coordinates" class="numeric-view" aria-label="Current numeric inspection region"></pre><p class="hint">Sync cameras links fit-relative zoom and viewport-relative pan across visible panes. Turn it off to inspect each pane independently. Toolbar zoom and Fit use the last active pane. Hold Space while dragging a video to pan without taking over its native controls.</p></div></details><span id="source-hash" class="subtle"></span></div></footer><dialog id="review-dialog" class="review-dialog" aria-labelledby="review-dialog-title"><div class="review-dialog-header"><h2 id="review-dialog-title">Write review</h2><span class="hint">Drafts save locally as you type · nothing is submitted until you press Submit</span><button id="review-dialog-close" type="button">Close</button></div><section id="inspector-feedback" class="review-dialog-body" aria-label="Feedback"><div class="review-summary"><div class="eyebrow">REVIEW</div><label for="review-status" class="label">Review status</label><select id="review-status"><option value="pending">Pending</option><option value="approved">Approved</option><option value="changes-requested">Changes requested</option></select><section class="provenance" aria-label="Reviewed source"><div class="eyebrow">REVIEWED SOURCE</div><div class="provenance-row"><span>Package revision</span><strong id="provenance-version">—</strong></div><div class="provenance-row"><span>rig SHA-256</span><code id="provenance-rig">—</code></div><div class="provenance-row"><span>motion SHA-256</span><code id="provenance-motion">—</code></div><details><summary>Full provenance</summary><pre id="provenance-full"></pre></details><div class="source-files"><div class="eyebrow">SOURCE FILES · READ ONLY</div><div id="source-files"></div></div><p class="hint">Submits server-verified file hashes and tool versions. Your selected review status is preserved.</p></section><div class="divider"></div></div><div id="checkpoint-detail"><div class="eyebrow">SELECTED CHECKPOINT</div><h1 id="detail-title">Checkpoint</h1><p id="detail-note" class="hint"></p><fieldset class="outcome"><legend>Checkpoint outcome</legend><label><input type="radio" name="outcome" value="pending" checked>Pending</label><label><input type="radio" name="outcome" value="pass">Pass</label><label><input type="radio" name="outcome" value="fail">Needs changes</label></fieldset><label for="checkpoint-note" class="label space-top">Review notes</label><textarea id="checkpoint-note" rows="5" placeholder="Describe the part, conditions and what looks wrong."></textarea></div><div class="divider"></div><section id="proposal-panel"><div class="eyebrow">STRUCTURED FEEDBACK</div><div class="label">Frame range · inclusive</div><div class="frame-range"><label>Start<input id="feedback-start" type="number" min="0" step="1" inputmode="numeric" placeholder="e.g. 18"></label><label>End<input id="feedback-end" type="number" min="0" step="1" inputmode="numeric" placeholder="e.g. 32"></label></div><p id="feedback-range-hint" class="hint">Checking frame bounds…</p><label for="feedback-target-kind" class="label space-top">Target type</label><select id="feedback-target-kind"><option value="">Select target</option><option value="rig">Entire rig</option><option value="bone">Bone</option><option value="slot">Slot</option></select><label for="feedback-target-name" class="label space-top">Target name</label><input id="feedback-target-name" type="text" list="feedback-target-names" autocomplete="off" placeholder="Actual bone or slot name"><datalist id="feedback-target-names"></datalist><p id="feedback-target-hint" class="hint"></p><label for="feedback-category" class="label space-top">Category</label><select id="feedback-category"><option value="">Select category</option><option value="defect">Defect</option><option value="quality">Quality</option></select><label for="feedback-summary" class="label space-top">One-line summary</label><input id="feedback-summary" type="text" maxlength="1000" placeholder="e.g. The left wrist moves outside the sleeve"><button id="add-proposal" class="outline block">Add feedback</button><p id="proposal-boundary" class="hint">Records the current checkpoint, time, reference, camera and inspection axis. Motion is read only: inspect, mark ranges and export feedback. No keys or source files are edited.</p><p id="feedback-warnings" class="hint" role="status" hidden></p><div id="proposal-list"></div></section><details id="strip-panel" class="report-panel"><summary>Export frame strip</summary><p class="hint">Uses the feedback form start and end frames, inclusive. Inspection time and source files remain unchanged.</p><label for="strip-scope" class="label">Export range</label><select id="strip-scope"><option value="interval">Entered start–end frames</option><option value="feedback">All feedback ranges</option></select><label for="strip-reference" class="label space-top">Reference video</label><select id="strip-reference"><option value="">Select reference video</option></select><label for="strip-format" class="label space-top">Format</label><select id="strip-format"><option value="png">PNG strip</option><option value="json">JSON frames and provenance</option></select><p class="hint">PNG requires frameTimes in the selected report. Without it, JSON preserves requested frames with time: null. Batch export requires every feedback item to match the selected animation. Unsubmitted feedback is included; exporting does not submit the review.</p><button id="strip-export" type="button" disabled>Download strip</button><p id="strip-status" class="hint" role="status" aria-live="polite">Loading package…</p></details></section><div class="review-dialog-actions"><span id="review-message" class="review-message" role="status" aria-live="polite"></span><span id="review-draft-state" class="review-draft-state" role="status" aria-live="polite"></span><button id="save" class="primary" disabled>Submit review</button></div></dialog></div>
10
+ <script type="module" src="main.js"></script>
13
11
  </body></html>