yxma's picture
add overlay(A) + mask(B) results + videos; final verdict
a5117e2 verified
Raw
History Blame Contribute Delete
29.9 kB
<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>VTWM — action conditioning</title><style>
:root{
--bg:#f7f7f8; --panel:#ffffff; --ink:#16181d; --sub:#5c6270; --line:#e6e8ec;
--accent:#4f46e5; --accent2:#0ea5e9;
--ok:#0f9d58; --okbg:#e7f6ee; --warn:#c77700; --warnbg:#fdf3e3; --bad:#d92d20; --badbg:#fdeceb;
--win:#0f9d58; --winbg:#e7f6ee;
--radius:16px; --shadow:0 1px 2px rgba(16,24,40,.04),0 8px 24px rgba(16,24,40,.06);
}
@media(prefers-color-scheme:dark){:root{
--bg:#0d0f14; --panel:#151922; --ink:#eaecef; --sub:#98a1b3; --line:#232936;
--accent:#8b8cf7; --accent2:#38bdf8;
--ok:#37d399; --okbg:#0f2a20; --warn:#f2b34b; --warnbg:#2a2110; --bad:#f77066; --badbg:#2a1414;
--win:#37d399; --winbg:#0f2a20;
--shadow:0 1px 2px rgba(0,0,0,.3),0 8px 24px rgba(0,0,0,.35);
}}
*{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:96px}
body{margin:0;background:var(--bg);color:var(--ink);
font:15px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased}
.wrap{max-width:1200px;margin:0 auto;padding:0 20px}
.hero{padding:56px 0 26px}
.hero .kick{color:var(--accent);font-weight:700;letter-spacing:.08em;text-transform:uppercase;font-size:12px}
.hero h1{margin:.25em 0 .35em;font-size:clamp(26px,4vw,40px);line-height:1.1;letter-spacing:-.02em}
.hero p.lede{margin:0;color:var(--sub);max-width:74ch;font-size:16px}
.reading{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
padding:14px 18px;margin:18px 0 4px;box-shadow:var(--shadow);font-size:13.5px;color:var(--sub)}
.reading b{color:var(--ink)}
.dot{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:5px}
.legend{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px;margin:22px 0 4px}
.chip{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:12px 14px;box-shadow:var(--shadow)}
.chip b{display:block;font-size:14px;margin-bottom:3px}.chip span{color:var(--sub);font-size:12.5px;line-height:1.45}
nav.sticky{position:sticky;top:0;z-index:20;background:color-mix(in srgb,var(--bg) 82%,transparent);
backdrop-filter:saturate(150%) blur(10px);border-bottom:1px solid var(--line);margin-top:24px}
nav.sticky .wrap{display:flex;gap:7px;flex-wrap:wrap;align-items:center;padding-top:10px;padding-bottom:10px}
nav.sticky a{color:var(--sub);text-decoration:none;font-weight:600;font-size:13px;padding:5px 11px;border-radius:999px;border:1px solid transparent}
nav.sticky a:hover{color:var(--ink);border-color:var(--line);background:var(--panel)}
nav.sticky .ngrp{color:var(--accent);font-weight:700;text-transform:uppercase;letter-spacing:.06em;font-size:10.5px;padding-left:8px}
.band{border-top:1px solid var(--line);margin-top:8px}
.band-h{padding:34px 0 2px}.band-h .t{font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
.band-h h2.big{margin:.2em 0 .1em;font-size:24px;letter-spacing:-.01em}
.band-h p{margin:0;color:var(--sub);max-width:80ch;font-size:14.5px}
section.run{padding:30px 0;border-top:1px solid var(--line)}
.run-head h2{margin:0 0 4px;font-size:20px;letter-spacing:-.01em}
.run-head p{margin:0 0 18px;color:var(--sub);max-width:82ch}
.cols{display:grid;grid-template-columns:minmax(400px,1fr) minmax(430px,1.15fr);gap:26px;align-items:start}
@media(max-width:980px){.cols{grid-template-columns:1fr}}
.xwrap{display:grid;grid-template-columns:minmax(280px,.7fr) minmax(520px,1.6fr);gap:26px;align-items:start}
@media(max-width:980px){.xwrap{grid-template-columns:1fr}}
h3{font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:var(--sub);margin:0 0 12px}
.qt{width:100%;border-collapse:collapse;background:var(--panel);border:1px solid var(--line);
border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);font-variant-numeric:tabular-nums}
.qt th{text-align:right;font-size:12px;color:var(--sub);font-weight:600;padding:11px 14px;border-bottom:1px solid var(--line)}
.qt th:first-child{text-align:left}
.qt td{padding:9px 14px;border-bottom:1px solid var(--line)}
.qt tr:last-child td{border-bottom:none}
.qt .mname{font-weight:500}.qt .arrow{color:var(--sub);font-size:11px}
.qt .num{text-align:right}
.qt tr.grp td{background:color-mix(in srgb,var(--accent) 7%,var(--panel));font-size:11px;text-transform:uppercase;
letter-spacing:.05em;color:var(--sub);font-weight:700;padding:7px 14px}
.gap-ok{color:var(--ok);background:var(--okbg);font-weight:600;border-radius:6px}
.gap-warn{color:var(--warn);background:var(--warnbg);font-weight:600;border-radius:6px}
.gap-bad{color:var(--bad);background:var(--badbg);font-weight:700;border-radius:6px}
.win{color:var(--win);background:var(--winbg);font-weight:700;border-radius:6px}
.seg{display:inline-flex;background:var(--panel);border:1px solid var(--line);border-radius:999px;padding:3px;margin-bottom:14px}
.seg-b{border:none;background:transparent;color:var(--sub);font:inherit;font-weight:600;font-size:13px;padding:5px 16px;border-radius:999px;cursor:pointer}
.seg-b.active{background:var(--accent);color:#fff}
.pane{display:none}.pane.show{display:block}
.grid{display:grid;grid-template-columns:repeat(2,1fr);gap:14px}
@media(max-width:560px){.grid{grid-template-columns:1fr}}
.xgal{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media(max-width:720px){.xgal{grid-template-columns:1fr}}
.xcol-h{font-size:12px;font-weight:700;letter-spacing:.03em;color:var(--ink);margin:0 0 10px;
padding:6px 10px;background:var(--panel);border:1px solid var(--line);border-radius:8px;display:inline-block}
.cgrid{display:grid;grid-template-columns:1fr;gap:12px}
.scard{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:10px;box-shadow:var(--shadow)}
.scard-h{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--sub);font-weight:700;margin:2px 4px 8px}
.vid{margin:0 0 8px}.vid:last-of-type{margin-bottom:2px}
.vid video{width:100%;display:block;border-radius:8px;background:#000;aspect-ratio:2/1;object-fit:cover}
.vid figcaption{font-size:11.5px;color:var(--sub);margin-top:4px;display:flex;justify-content:space-between}
.vid .gtp{color:var(--accent2);font-weight:600}
.empty{color:var(--sub);font-style:italic;padding:16px}
.ctrl{display:flex;align-items:center;gap:9px;margin-top:8px;padding:2px 2px 0}
.pp{flex:0 0 auto;width:30px;height:30px;border-radius:8px;border:1px solid var(--line);background:var(--panel);
color:var(--ink);font-size:12px;cursor:pointer;display:grid;place-items:center}
.pp:hover{border-color:var(--accent)}
.scrub{flex:1 1 auto;-webkit-appearance:none;appearance:none;height:5px;border-radius:999px;background:var(--line);cursor:pointer;outline:none}
.scrub::-webkit-slider-thumb{-webkit-appearance:none;width:14px;height:14px;border-radius:50%;background:var(--accent);border:2px solid var(--panel);box-shadow:0 1px 3px rgba(0,0,0,.3)}
.scrub::-moz-range-thumb{width:14px;height:14px;border-radius:50%;background:var(--accent);border:2px solid var(--panel)}
.tlabel{flex:0 0 auto;font-size:11px;color:var(--sub);font-variant-numeric:tabular-nums;min-width:38px;text-align:right}
footer{border-top:1px solid var(--line);padding:26px 0 50px;color:var(--sub);font-size:12.5px;margin-top:20px}
</style></head><body><div class="wrap">
<header class="hero"><div class="kick">Tactile world model · action conditioning</div>
<h1>Does spatial sensor-pose conditioning help contact dynamics?</h1>
<p class="lede">Goal: a better action-conditioning method for visuo-tactile contact. We render each GelSight
sensor's projected image location as a per-frame Gaussian heatmap and inject it (zero-init) into the view
tokens — CameraCtrl/EA-WM style. <b>Result across all representations (heatmap channel, mask channel, in-target overlay): in-target &gt; side-channel (novel ablation), but none beats contact-supervision (contactw1 0.202).</b> Below: exactly what each model adds, the added
input, and the prediction results.</p></header>
<div class="band-h"><div class="t">1 · What each model adds (single-variable chain)</div></div>
<table class="qt"><thead><tr><th>knob</th><th>p01rand</th><th>contactw1</th><th>senshm(σ1.6)</th><th>senshm(σ0.6)</th><th>senshm+depth</th></tr></thead><tbody>
<tr><td class="mname">contact-region supervision</td><td class="num"></td><td class="num win">✓ w1.0</td><td class="num"></td><td class="num"></td><td class="num"></td></tr>
<tr><td class="mname">sensor-pose heatmap (spatial cond)</td><td class="num"></td><td class="num"></td><td class="num"></td><td class="num"></td><td class="num"></td></tr>
<tr><td class="mname">heatmap σ</td><td class="num"></td><td class="num"></td><td class="num">1.6</td><td class="num">0.6</td><td class="num">0.6</td></tr>
<tr><td class="mname">depth channel</td><td class="num"></td><td class="num"></td><td class="num"></td><td class="num"></td><td class="num"></td></tr></tbody></table>
<div class="band-h"><div class="t">2 · Contact IoU (val) — spatial conditioning HURTS</div></div>
<table class="qt"><thead><tr><th>run</th><th>contact IoU (val)↑</th><th>view LPIPS↓</th><th>tactile-L LPIPS↓</th></tr></thead><tbody>
<tr><td class="mname">p01rand</td><td class="num">0.173</td><td class="num"></td><td class="num"></td></tr>
<tr><td class="mname">contactw1 (best)</td><td class="num win">0.202</td><td class="num win">0.046</td><td class="num">0.094</td></tr>
<tr><td class="mname">senshm σ1.6</td><td class="num bad">0.147</td><td class="num bad">0.069</td><td class="num">0.095</td></tr>
<tr><td class="mname">senshm heatmap (σ0.6/depth)</td><td class="num bad">0.146 / 0.157</td><td class="num"></td><td class="num"></td></tr><tr><td class="mname">B · mask channel</td><td class="num bad">0.158</td><td class="num"></td><td class="num"></td></tr><tr><td class="mname">A · overlay-in-target</td><td class="num">0.169</td><td class="num"></td><td class="num"></td></tr></tbody></table><p style="color:var(--sub);font-size:13px"><b>Key ablation (novel):</b> in-target overlay (0.169) &gt; side-channel mask (0.158) &gt; heatmap (0.15) — representation ordering matches Genima/In-Video-Instructions. But all &lt; contactw1 (0.202): spatial pose re-representation adds no held-out contact signal (camera-frame ≠ gel-frame).</p>
<p style="color:var(--sub);font-size:13.5px">Adding the heatmap degraded <b>both</b> visual and tactile, train and val — while latent val_loss stayed ~equal (0.0467). The signal is <b>redundant</b> (pose already in the global action tokens + visible in the views) and a <b>harmful perturbation</b>; and the camera-frame location doesn't map to gel-frame contact.</p>
<div class="band-h"><div class="t">3 · The added INPUT — sensor-pose heatmap</div>
<p>Each GelSight sensor's 3D pose is projected (calibrated) into every camera view and rendered as a Gaussian. Left: it tracks the sensors over time across 3 views. Right: the 16×16 heatmap the model receives.</p></div>
<img src="proj_track.png" style="max-width:100%;border:1px solid var(--line);border-radius:12px;margin-bottom:12px">
<img src="input_heatmap.png" style="max-width:100%;border:1px solid var(--line);border-radius:12px">
<div class="band-h"><div class="t">4 · Input + prediction (contact maps)</div>
<p>Columns: <b>view + sensor heatmap (INPUT) · GT contact · contactw1 pred · senshm pred</b> (red = above τ=8).</p></div>
<img src="why_figure.png" style="max-width:100%;border:1px solid var(--line);border-radius:12px">
<div class="band-h"><div class="t">5 · Prediction videos — p01rand | contactw1 | senshm</div>
<p>Matched val windows. Play/scrub; view is the clock.</p></div>
<section class="run"><div class="run-head"><h2>window 0</h2><p>2026-05-10__episode_005.pt · t=606 — GT ‖ prediction. rows: middle view, tactile L/R.</p></div><div class="xgal" style="grid-template-columns:1fr 1fr 1fr"><div class="scard"><div class="scard-h">contactw1</div><figure class="vid"><video src="media/w0_contactw1_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w0_contactw1_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w0_contactw1_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">overlay</div><figure class="vid"><video src="media/w0_overlay_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w0_overlay_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w0_overlay_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">mask</div><figure class="vid"><video src="media/w0_mask_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w0_mask_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w0_mask_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div></div></section><section class="run"><div class="run-head"><h2>window 1</h2><p>2026-05-10__episode_006.pt · t=1116 — GT ‖ prediction. rows: middle view, tactile L/R.</p></div><div class="xgal" style="grid-template-columns:1fr 1fr 1fr"><div class="scard"><div class="scard-h">contactw1</div><figure class="vid"><video src="media/w1_contactw1_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w1_contactw1_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w1_contactw1_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">overlay</div><figure class="vid"><video src="media/w1_overlay_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w1_overlay_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w1_overlay_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">mask</div><figure class="vid"><video src="media/w1_mask_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w1_mask_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w1_mask_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div></div></section><section class="run"><div class="run-head"><h2>window 2</h2><p>2026-05-10__episode_006.pt · t=1226 — GT ‖ prediction. rows: middle view, tactile L/R.</p></div><div class="xgal" style="grid-template-columns:1fr 1fr 1fr"><div class="scard"><div class="scard-h">contactw1</div><figure class="vid"><video src="media/w2_contactw1_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w2_contactw1_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w2_contactw1_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">overlay</div><figure class="vid"><video src="media/w2_overlay_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w2_overlay_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w2_overlay_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">mask</div><figure class="vid"><video src="media/w2_mask_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w2_mask_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w2_mask_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div></div></section><section class="run"><div class="run-head"><h2>window 3</h2><p>2026-05-10__episode_006.pt · t=1238 — GT ‖ prediction. rows: middle view, tactile L/R.</p></div><div class="xgal" style="grid-template-columns:1fr 1fr 1fr"><div class="scard"><div class="scard-h">contactw1</div><figure class="vid"><video src="media/w3_contactw1_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w3_contactw1_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w3_contactw1_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">overlay</div><figure class="vid"><video src="media/w3_overlay_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w3_overlay_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w3_overlay_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">mask</div><figure class="vid"><video src="media/w3_mask_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w3_mask_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w3_mask_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div></div></section><section class="run"><div class="run-head"><h2>window 4</h2><p>2026-05-10__episode_006.pt · t=1420 — GT ‖ prediction. rows: middle view, tactile L/R.</p></div><div class="xgal" style="grid-template-columns:1fr 1fr 1fr"><div class="scard"><div class="scard-h">contactw1</div><figure class="vid"><video src="media/w4_contactw1_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w4_contactw1_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w4_contactw1_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">overlay</div><figure class="vid"><video src="media/w4_overlay_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w4_overlay_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w4_overlay_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">mask</div><figure class="vid"><video src="media/w4_mask_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w4_mask_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w4_mask_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div></div></section><section class="run"><div class="run-head"><h2>window 5</h2><p>2026-05-10__episode_006.pt · t=2460 — GT ‖ prediction. rows: middle view, tactile L/R.</p></div><div class="xgal" style="grid-template-columns:1fr 1fr 1fr"><div class="scard"><div class="scard-h">contactw1</div><figure class="vid"><video src="media/w5_contactw1_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w5_contactw1_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w5_contactw1_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">overlay</div><figure class="vid"><video src="media/w5_overlay_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w5_overlay_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w5_overlay_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div><div class="scard"><div class="scard-h">mask</div><figure class="vid"><video src="media/w5_mask_view.mp4" muted playsinline preload="auto" data-lead="1"></video><figcaption>middle view <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w5_mask_tl.mp4" muted playsinline preload="auto"></video><figcaption>tactile · left <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><figure class="vid"><video src="media/w5_mask_tr.mp4" muted playsinline preload="auto"></video><figcaption>tactile · right <span class="gtp">GT&nbsp;·&nbsp;pred</span></figcaption></figure><div class="ctrl"><button class="pp"></button><input class="scrub" type="range" min="0" max="1000" value="0" step="1"></input><span class="tlabel">0/16</span></div></div></div></section>
</div><script>
document.querySelectorAll('.qual').forEach(q=>{
const panes=q.querySelectorAll('.pane'), btns=q.querySelectorAll('.seg-b');
function sel(t){panes.forEach(p=>p.classList.toggle('show',p.dataset.split===t));
btns.forEach(b=>b.classList.toggle('active',b.dataset.t===t));}
btns.forEach(b=>b.addEventListener('click',()=>sel(b.dataset.t)));
});
const FPS=6;
document.querySelectorAll('.scard').forEach(card=>{
const vids=[...card.querySelectorAll('video')];
const lead=card.querySelector('video[data-lead]')||vids[0];
const bar=card.querySelector('.scrub'), btn=card.querySelector('.pp'), lbl=card.querySelector('.tlabel');
let userPaused=false, visible=false, dur=0, nF=16;
function seekAll(t){vids.forEach(v=>{if(Math.abs(v.currentTime-t)>0.03){try{v.currentTime=t;}catch(e){}}});}
function paint(){const t=lead.currentTime; if(dur) bar.value=Math.round(t/dur*1000);
lbl.textContent=Math.min(Math.round(t*FPS),nF)+'/'+nF;}
lead.addEventListener('loadedmetadata',()=>{dur=lead.duration||0;nF=Math.max(1,Math.round(dur*FPS));paint();});
lead.addEventListener('timeupdate',()=>{
vids.forEach(v=>{if(v!==lead&&Math.abs(v.currentTime-lead.currentTime)>0.05){try{v.currentTime=lead.currentTime;}catch(e){}}});paint();});
lead.addEventListener('ended',()=>{seekAll(0); if(!userPaused&&visible) playAll();});
function playAll(){btn.textContent='⏸';vids.forEach(v=>v.play().catch(()=>{}));}
function pauseAll(){btn.textContent='▶';vids.forEach(v=>v.pause());}
btn.addEventListener('click',()=>{ if(lead.paused){userPaused=false;playAll();} else {userPaused=true;pauseAll();} });
bar.addEventListener('input',()=>{userPaused=true;pauseAll();seekAll(parseInt(bar.value,10)/1000*(dur||0));paint();});
new IntersectionObserver(es=>es.forEach(e=>{visible=e.isIntersecting;
if(visible&&!userPaused) playAll(); else if(!visible) pauseAll();}),{threshold:0.2}).observe(card);
});
</script></body></html>