asdfasdfqrqwer's picture
Complete previews for every Explorer event
ad08800
Raw
History Blame Contribute Delete
35.5 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="An interactive view of UniversalLabeler: language surfaces compress into evidence-linked semantic claims, then expand without discarding world information.">
<title>UniversalLabeler — Meaning, packed.</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Bodoni+Moda:opsz,wght@6..96,400;6..96,600&amp;family=DM+Mono:wght@300;400;500&amp;display=swap" rel="stylesheet">
<style>
:root {
--paper: #071116;
--paper-deep: #0d1a21;
--ink: #edf7f8;
--muted: #7e969e;
--signal: #53d9f5;
--signal-soft: #b7f2ff;
--line: rgba(157, 199, 210, .16);
--line-strong: rgba(174, 216, 226, .38);
--serif: "Bodoni Moda", "Iowan Old Style", "Times New Roman", serif;
--mono: "DM Mono", "SFMono-Regular", Consolas, monospace;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
color: var(--ink);
background:
radial-gradient(circle at 50% -10%, rgba(42, 105, 121, .18), transparent 38%),
linear-gradient(90deg, transparent calc(50% - .5px), rgba(140,190,202,.035) 50%, transparent calc(50% + .5px)),
var(--paper);
font-family: var(--mono);
overflow-x: hidden;
}
body::before {
content: "";
position: fixed;
inset: 0;
opacity: .035;
pointer-events: none;
z-index: 20;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.45'/%3E%3C/svg%3E");
mix-blend-mode: screen;
}
button, a { font: inherit; }
button { color: inherit; }
::selection { background: var(--signal); color: var(--paper); }
.shell { width: min(1600px, 100%); margin: 0 auto; padding: 0 28px; }
.topbar {
height: 72px;
border-bottom: 1px solid var(--line-strong);
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
position: relative;
z-index: 5;
}
.mark { display: flex; align-items: center; gap: 12px; font-size: 11px; letter-spacing: .14em; text-transform: uppercase; }
.mark-glyph { width: 28px; height: 28px; border: 1px solid var(--ink); display: grid; place-items: center; font-weight: 500; }
.top-center { font-size: 10px; letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }
.top-right { justify-self: end; display: flex; align-items: center; gap: 18px; font-size: 10px; text-transform: uppercase; letter-spacing: .12em; }
.status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--signal); box-shadow: 0 0 0 4px rgba(83,217,245,.1), 0 0 18px rgba(83,217,245,.35); animation: breathe 4s ease-in-out infinite; }
.hero {
min-height: calc(100vh - 72px);
display: grid;
grid-template-rows: auto 1fr auto;
padding-top: 44px;
padding-bottom: 24px;
}
.hero-heading {
display: grid;
grid-template-columns: 1.25fr .75fr;
align-items: end;
gap: 40px;
margin-bottom: 40px;
}
h1 { margin: 0; font: 400 clamp(52px, 7vw, 118px)/.82 var(--serif); letter-spacing: -.055em; max-width: 980px; }
h1 em { color: var(--signal); font-style: italic; }
.lede { margin: 0 0 6px auto; max-width: 440px; font-size: 12px; line-height: 1.75; color: var(--muted); }
.lede strong { color: var(--ink); font-weight: 500; }
.machine {
min-height: 470px;
border-top: 1px solid var(--line-strong);
border-bottom: 1px solid var(--line-strong);
display: grid;
grid-template-columns: minmax(260px, .85fr) minmax(360px, 1.15fr) minmax(320px, 1fr);
position: relative;
isolation: isolate;
}
.machine::after {
content: "";
position: absolute;
inset: 0;
background-image: linear-gradient(var(--line) 1px, transparent 1px), linear-gradient(90deg, var(--line) 1px, transparent 1px);
background-size: 44px 44px;
opacity: .32;
pointer-events: none;
z-index: -1;
}
.panel { padding: 22px; min-width: 0; position: relative; }
.panel + .panel { border-left: 1px solid var(--line-strong); }
.panel-label { display: flex; align-items: center; justify-content: space-between; margin-bottom: 24px; font-size: 10px; letter-spacing: .16em; text-transform: uppercase; }
.panel-label span:last-child { color: var(--muted); }
.source-panel { display: flex; flex-direction: column; }
.evidence-window {
background: #02080b;
color: var(--ink);
min-height: 220px;
position: relative;
overflow: hidden;
padding: 16px;
display: flex;
align-items: end;
box-shadow: inset 0 0 0 1px rgba(183,242,255,.08), inset 0 -70px 80px rgba(24,78,91,.14);
}
.evidence-window::after {
content: "";
position: absolute;
inset: 0;
z-index: 1;
pointer-events: none;
background: linear-gradient(180deg, rgba(2,8,11,.08) 24%, rgba(2,8,11,.3) 57%, rgba(2,8,11,.94) 100%);
}
.evidence-window::before {
content: "";
position: absolute;
width: 260px;
height: 260px;
border: 1px solid rgba(183,242,255,.16);
border-radius: 50%;
top: -122px;
right: -82px;
box-shadow: 0 0 0 34px rgba(83,217,245,.025), 0 0 0 68px rgba(83,217,245,.018);
}
.evidence-preview { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 48%; filter: saturate(.76) brightness(.76) contrast(1.08); opacity: .9; }
.evidence-preview[hidden] { display: none; }
.scene-glyph { position: absolute; inset: 0; z-index: 2; opacity: .16; transition: opacity .25s; }
.evidence-window:not(.has-preview) .scene-glyph { opacity: .78; }
.surface-line { position: relative; z-index: 3; font: 400 clamp(21px, 2vw, 32px)/1.06 var(--serif); max-width: 92%; text-shadow: 0 2px 18px #02080b; }
.surface-line span { transition: color .35s, background .35s; }
.surface-line .hot { color: var(--signal-soft); }
.framecode { position: absolute; z-index: 3; top: 14px; left: 16px; color: rgba(183,242,255,.74); font-size: 9px; letter-spacing: .12em; text-shadow: 0 1px 8px #02080b; }
.preview-kind { position: absolute; z-index: 3; top: 14px; right: 16px; color: rgba(183,242,255,.64); font-size: 8px; letter-spacing: .1em; text-transform: uppercase; text-shadow: 0 1px 8px #02080b; }
.scope-line { position: absolute; z-index: 4; bottom: 0; left: 0; height: 2px; width: 100%; background: rgba(183,242,255,.1); }
.scope-line::after { content: ""; display: block; height: 100%; width: var(--progress, 0%); background: var(--signal); box-shadow: 0 0 12px rgba(83,217,245,.48); transition: width 1.1s cubic-bezier(.22,.8,.3,1); }
.evidence-meta { margin-top: auto; padding-top: 20px; display: grid; gap: 9px; font-size: 10px; }
.meta-row { display: flex; justify-content: space-between; border-bottom: 1px solid var(--line); padding-bottom: 8px; }
.meta-row span:last-child { color: var(--muted); text-align: right; }
.core-panel { overflow: hidden; }
.core-stage { height: 355px; position: relative; display: grid; place-items: center; }
.orbit { position: absolute; border: 1px solid var(--line); border-radius: 50%; }
.orbit.one { width: 326px; height: 326px; }
.orbit.two { width: 250px; height: 250px; border-style: dashed; opacity: .7; }
.orbit::before, .orbit::after { content: ""; position: absolute; width: 6px; height: 6px; background: var(--signal); border-radius: 50%; box-shadow: 0 0 14px rgba(83,217,245,.5); }
.orbit::before { left: 50%; top: -4px; }
.orbit::after { left: 50%; bottom: -3px; background: var(--muted); box-shadow: none; }
.core {
width: 178px;
height: 178px;
border-radius: 50%;
background: #02080b;
color: var(--ink);
position: relative;
display: grid;
place-items: center;
text-align: center;
box-shadow: 0 0 0 12px var(--paper), 0 0 0 13px rgba(183,242,255,.7), 0 0 48px rgba(83,217,245,.1);
z-index: 3;
}
.core::before { content: ""; position: absolute; inset: 16px; border: 1px dashed rgba(183,242,255,.28); border-radius: 50%; }
.core-copy { position: relative; }
.core-kicker { font-size: 9px; letter-spacing: .18em; color: var(--signal-soft); }
.core-name { display: block; margin: 9px 0 5px; font: 400 25px/1 var(--serif); }
.core-count { font-size: 9px; letter-spacing: .08em; color: rgba(183,242,255,.48); }
.claim-node { position: absolute; font-size: 8px; letter-spacing: .08em; text-transform: uppercase; background: #0a171d; border: 1px solid rgba(183,242,255,.46); padding: 5px 7px; z-index: 4; transition: border-color .4s, background .4s, color .4s, box-shadow .4s; }
.claim-node.active { background: rgba(83,217,245,.13); color: var(--signal-soft); border-color: var(--signal); box-shadow: 0 0 14px rgba(83,217,245,.16); }
.n1{top:14px;left:19%}.n2{top:49px;right:6%}.n3{top:139px;right:0}.n4{bottom:58px;right:8%}.n5{bottom:8px;right:29%}.n6{bottom:18px;left:14%}.n7{bottom:92px;left:0}.n8{top:117px;left:0}.n9{top:45px;left:5%}
.compression-meter { position: absolute; inset: auto 0 0; display: grid; grid-template-columns: repeat(3,1fr); border-top: 1px solid var(--line); }
.metric { padding: 11px; border-right: 1px solid var(--line); }
.metric:last-child { border: 0; }
.metric b { display: block; font: 400 22px/1 var(--serif); }
.metric span { font-size: 8px; color: var(--muted); letter-spacing: .1em; text-transform: uppercase; }
.outputs { display: flex; flex-direction: column; gap: 0; }
.output {
appearance: none;
border: 0;
border-top: 1px solid var(--line);
background: transparent;
padding: 14px 0;
display: grid;
grid-template-columns: 58px 1fr 20px;
align-items: baseline;
gap: 10px;
text-align: left;
cursor: pointer;
transition: padding .25s, color .25s;
}
.output:first-child { border-top: 0; }
.output:hover, .output.active { padding-left: 10px; color: var(--signal-soft); background: linear-gradient(90deg, rgba(83,217,245,.07), transparent 72%); }
.output-code { font-size: 9px; color: var(--muted); text-transform: uppercase; }
.output-text { font: 400 clamp(17px, 1.45vw, 24px)/1.15 var(--serif); }
.output-check { font-size: 11px; opacity: .3; }
.output.active .output-check { opacity: 1; }
.ledger { margin-top: auto; background: var(--paper-deep); padding: 13px; font-size: 9px; line-height: 1.8; }
.ledger-line { display: flex; justify-content: space-between; }
.ledger-line b { font-weight: 400; color: var(--signal); }
.scenario-strip { display: grid; grid-template-columns: auto repeat(4, 1fr) auto; align-items: stretch; min-height: 66px; }
.strip-label { padding: 0 18px 0 0; display: flex; align-items: center; font-size: 9px; text-transform: uppercase; letter-spacing: .15em; }
.scenario {
appearance: none; background: transparent; border: 0; border-left: 1px solid var(--line); padding: 12px 16px; text-align: left; cursor: pointer; position: relative; transition: background .35s;
}
.scenario:hover, .scenario.active { background: rgba(83,217,245,.045); }
.scenario::after { content: ""; position: absolute; left: 0; right: 100%; bottom: 0; height: 3px; background: var(--signal); transition: right .35s; }
.scenario.active::after { right: 0; }
.scenario-num { display: block; color: var(--muted); font-size: 8px; margin-bottom: 5px; }
.scenario-name { font: 400 15px/1 var(--serif); }
.pause { appearance: none; border: 0; border-left: 1px solid var(--line); background: transparent; width: 58px; cursor: pointer; font-size: 15px; }
.particle { position: fixed; z-index: 30; pointer-events: none; width: 6px; height: 6px; padding: 0; overflow: hidden; color: transparent; font-size: 0; background: var(--signal); border: 1px solid var(--signal-soft); border-radius: 50%; box-shadow: 0 0 16px rgba(83,217,245,.75); transition: transform .95s cubic-bezier(.2,.7,.2,1), opacity .28s .65s; }
.machine.is-updating .surface-line, .machine.is-updating .outputs, .machine.is-updating .evidence-meta { opacity: .32; transform: translateY(3px); }
.surface-line, .outputs, .evidence-meta { transition: opacity .22s ease, transform .22s ease; }
.thesis { padding: 108px 0 90px; display: grid; grid-template-columns: .8fr 1.2fr; gap: 8vw; border-bottom: 1px solid var(--line-strong); }
.thesis-index { font-size: 10px; letter-spacing: .15em; text-transform: uppercase; color: var(--muted); }
.thesis h2 { font: 400 clamp(42px, 5vw, 82px)/.94 var(--serif); letter-spacing: -.04em; margin: 0; }
.thesis h2 em { color: var(--signal); }
.thesis-copy { display: grid; grid-template-columns: 1fr 1fr; gap: 34px; margin-top: 54px; font-size: 11px; line-height: 1.8; color: var(--muted); }
.thesis-copy strong { color: var(--ink); font-weight: 500; }
.packet-section { padding: 72px 0 100px; }
.section-head { display: flex; justify-content: space-between; align-items: end; border-bottom: 1px solid var(--line-strong); padding-bottom: 18px; }
.section-head h2 { margin: 0; font: 400 clamp(38px,4vw,64px)/1 var(--serif); letter-spacing: -.035em; }
.section-head p { max-width: 440px; font-size: 10px; line-height: 1.7; color: var(--muted); margin: 0; }
.packet-table { display: grid; }
.packet-row { display: grid; grid-template-columns: 42px 180px 1fr 95px; gap: 18px; align-items: center; min-height: 64px; border-bottom: 1px solid var(--line); transition: background .2s; }
.packet-row:hover { background: rgba(83,217,245,.045); }
.packet-row .idx { color: var(--muted); font-size: 9px; }
.packet-row .field { text-transform: uppercase; font-size: 9px; letter-spacing: .12em; }
.packet-row .value { font: 400 19px/1.2 var(--serif); }
.packet-row .state { justify-self: end; font-size: 8px; text-transform: uppercase; letter-spacing: .1em; color: var(--signal); }
footer { background: #02080b; color: var(--ink); padding: 28px; border-top: 1px solid rgba(183,242,255,.16); }
.footer-inner { width: min(1544px,100%); margin: auto; display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 30px; }
.footer-title { font: 400 clamp(38px,6vw,92px)/.86 var(--serif); letter-spacing: -.045em; }
.footer-meta { text-align: right; font-size: 9px; line-height: 1.9; color: rgba(183,242,255,.46); }
.footer-meta a { color: var(--ink); text-decoration-color: var(--signal); text-underline-offset: 4px; }
@keyframes breathe { 50% { opacity: .5; box-shadow: 0 0 0 6px rgba(83,217,245,.06), 0 0 24px rgba(83,217,245,.42); } }
@media (max-width: 1050px) {
.hero-heading { grid-template-columns: 1fr; }
.lede { margin-left: 0; }
.machine { grid-template-columns: 1fr 1.25fr; }
.source-panel { display: none; }
.core-panel { border-left: 0 !important; }
.scenario-strip { grid-template-columns: repeat(4,1fr) auto; }
.strip-label { display: none; }
}
@media (max-width: 700px) {
.shell { padding: 0 16px; }
.topbar { grid-template-columns: 1fr auto; height: 62px; }
.top-center { display: none; }
.top-right span:not(.status-dot) { display: none; }
.hero { padding-top: 30px; }
h1 { font-size: clamp(48px,16vw,74px); }
.machine { display: block; }
.core-panel { height: 430px; border-bottom: 1px solid var(--line-strong); }
.outputs-panel { min-height: 420px; border-left: 0 !important; }
.scenario-strip { grid-template-columns: 1fr 1fr; }
.scenario { border-bottom: 1px solid var(--line); }
.pause { position: absolute; top: 14px; right: 16px; border: 1px solid var(--line); width: 36px; height: 30px; z-index: 8; }
.thesis { grid-template-columns: 1fr; padding: 72px 0; }
.thesis-copy { grid-template-columns: 1fr; margin-top: 34px; }
.section-head { display: block; }
.section-head p { margin-top: 20px; }
.packet-row { grid-template-columns: 28px 100px 1fr; gap: 8px; }
.packet-row .state { display: none; }
.packet-row .value { font-size: 16px; }
.footer-inner { grid-template-columns: 1fr; }
.footer-meta { text-align: left; }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; }
.particle { display: none; }
}
</style>
</head>
<body>
<header class="shell topbar">
<div class="mark"><span class="mark-glyph">U</span><span>UniversalLabeler</span></div>
<div class="top-center">Loss-resistant annotation translation</div>
<div class="top-right"><span class="status-dot" aria-hidden="true"></span><span>v1.0.5 / Public spec</span></div>
</header>
<main>
<section class="shell hero" aria-labelledby="hero-title">
<div class="hero-heading">
<h1 id="hero-title">Language changes.<br>The <em>event</em> does not.</h1>
<p class="lede"><strong>Pack the world, not just the sentence.</strong> UniversalLabeler turns an annotation into addressable claims—action, actors, hands, objects, state, place, time, outcome and evidence—then renders each language from the same packet.</p>
</div>
<div class="machine" id="machine">
<section class="panel source-panel" aria-label="Source evidence">
<div class="panel-label"><span>01 / Observe</span><span id="source-locale">EN source</span></div>
<div class="evidence-window">
<img class="evidence-preview" id="evidence-preview" src="../assets/evidence-fold-towel-v1.png" alt="Synthetic first-person preview of two hands folding a pale blue towel on a dark table">
<div class="framecode" id="framecode">FRAME 01:00:01.000—01:00:08.000</div>
<div class="preview-kind" id="preview-kind">synthetic visual preview</div>
<svg class="scene-glyph" viewBox="0 0 420 260" aria-hidden="true">
<g fill="none" stroke="rgba(183,242,255,.24)" stroke-width="1.4">
<path d="M38 190H382M94 190v42M330 190v42"/>
<path id="object-shape" d="M145 154 Q210 126 275 154 L260 182H157Z"/>
<path d="M45 94Q93 105 142 151M375 92Q328 106 276 151"/>
<circle cx="45" cy="94" r="9"/><circle cx="375" cy="92" r="9"/>
</g>
<g fill="#53d9f5"><circle cx="142" cy="151" r="4"/><circle cx="276" cy="151" r="4"/></g>
<text x="51" y="86" fill="rgba(183,242,255,.52)" font-family="monospace" font-size="8">LEFT / STABILIZE</text>
<text x="283" y="84" fill="rgba(183,242,255,.52)" font-family="monospace" font-size="8">RIGHT / ACT</text>
</svg>
<div class="surface-line" id="source-text">Fold the <span class="hot">towel</span> on the table with both hands.</div>
<div class="scope-line" id="scope-line"></div>
</div>
<div class="evidence-meta">
<div class="meta-row"><span>EVIDENCE</span><span>head_video · hand_pose</span></div>
<div class="meta-row"><span>ENVIRONMENT</span><span id="environment">indoor · laundry area</span></div>
<div class="meta-row"><span>TIME SCOPE</span><span id="time-scope">7.00 s · episode_clock</span></div>
<div class="meta-row"><span>PROVENANCE</span><span>source-bound · reviewed</span></div>
</div>
</section>
<section class="panel core-panel" aria-label="Semantic packet">
<div class="panel-label"><span>02 / Pack</span><span>UAP core v1</span></div>
<div class="core-stage">
<div class="orbit one"></div><div class="orbit two"></div>
<span class="claim-node n1" data-claim="action">action</span>
<span class="claim-node n2" data-claim="patient">object</span>
<span class="claim-node n3" data-claim="hands">hands</span>
<span class="claim-node n4" data-claim="state">state Δ</span>
<span class="claim-node n5" data-claim="outcome">outcome</span>
<span class="claim-node n6" data-claim="evidence">evidence</span>
<span class="claim-node n7" data-claim="time">time</span>
<span class="claim-node n8" data-claim="place">place</span>
<span class="claim-node n9" data-claim="roles">roles</span>
<div class="core" id="core">
<div class="core-copy"><span class="core-kicker">CONTENT-BOUND</span><span class="core-name">meaning<br>packet</span><span class="core-count">10 / 10 claims</span></div>
</div>
<div class="compression-meter">
<div class="metric"><b id="claim-count">10</b><span>atomic claims</span></div>
<div class="metric"><b>0</b><span>silent drops</span></div>
<div class="metric"><b>5</b><span>projections</span></div>
</div>
</div>
</section>
<section class="panel outputs-panel" aria-label="Language projections">
<div class="panel-label"><span>03 / Project</span><span>one packet → many surfaces</span></div>
<div class="outputs" id="outputs"></div>
<div class="ledger">
<div class="ledger-line"><span>CLAIMS REPRESENTED</span><b id="represented">10 / 10</b></div>
<div class="ledger-line"><span>CLAIMS OMITTED</span><b>0</b></div>
<div class="ledger-line"><span>REVIEW STATE</span><b>CONFORMANCE</b></div>
</div>
</section>
</div>
<nav class="scenario-strip" aria-label="Example events">
<span class="strip-label">Select event</span>
<button class="scenario active" data-scene="0"><span class="scenario-num">01</span><span class="scenario-name">Fold textile</span></button>
<button class="scenario" data-scene="1"><span class="scenario-num">02</span><span class="scenario-name">Open container</span></button>
<button class="scenario" data-scene="2"><span class="scenario-num">03</span><span class="scenario-name">Place object</span></button>
<button class="scenario" data-scene="3"><span class="scenario-num">04</span><span class="scenario-name">Cut ingredient</span></button>
<button class="pause" id="pause" aria-label="Play automatic examples" title="Play examples"></button>
</nav>
</section>
<section class="shell thesis">
<div class="thesis-index">00 / Design principle</div>
<div>
<h2>Compress the <em>description.</em><br>Keep the world.</h2>
<div class="thesis-copy">
<p><strong>A universal vocabulary is not an infinite dictionary.</strong> It is a compositional address space. New actions and nouns become concept IDs; roles describe how they participate; evidence says why each claim is believed.</p>
<p><strong>Fluent text is a view, not the database.</strong> English, Chinese, Tagalog, Spanish and Hindi can choose their own word order and grammar without becoming the authority for hands, state, timing or geometry.</p>
</div>
</div>
</section>
<section class="shell packet-section" aria-labelledby="packet-title">
<div class="section-head">
<h2 id="packet-title">Inside one event.</h2>
<p>The visible sentence is short. The packet remains explicit. Click an event above and every value below updates from the same semantic frame.</p>
</div>
<div class="packet-table" id="packet-table"></div>
</section>
</main>
<footer>
<div class="footer-inner">
<div class="footer-title">Meaning,<br>packed.</div>
<div class="footer-meta">UNIVERSAL LABELER / RELEASE 1.0.5<br>5 HUMAN LANGUAGES · 22 WORLD DIMENSIONS<br><a href="https://huggingface.co/datasets/itspublu/UniversalLabeler">VIEW DATA + SCHEMAS ↗</a></div>
</div>
</footer>
<script>
const scenes = [
{
name: "fold_towel", source: "Fold the towel on the table with both hands.", hot: "towel",
preview: "../assets/evidence-fold-towel-v1.png",
previewAlt: "Synthetic first-person preview of two hands folding a pale blue towel on a dark table",
environment: "indoor · laundry area", duration: "7.00 s · episode_clock", claims: 10,
values: { action: "fold", agent: "human performer", roles: "left stabilizes · right acts", object: "towel_01 · patient", place: "table · laundry area", before: "unfolded · dry", after: "folded · dry", time: "1.00—8.00 s", outcome: "success", evidence: "RGB · hand pose · narration" },
text: { en: "Fold the towel on the table with both hands.", zh: "用双手在桌上把毛巾叠好。", tl: "Tiklupin ang tuwalya sa mesa gamit ang dalawang kamay.", es: "Dobla la toalla sobre la mesa con ambas manos.", hi: "दोनों हाथों से मेज़ पर तौलिया मोड़ें।" }
},
{
name: "open_jar", source: "Hold the jar with the left hand and unscrew the lid with the right.", hot: "unscrew",
preview: "../assets/evidence-open-jar-v1.png",
previewAlt: "Synthetic first-person preview of the left hand stabilizing a glass jar while the right hand unscrews its lid",
environment: "indoor · kitchen counter", duration: "4.20 s · episode_clock", claims: 11,
values: { action: "unscrew", agent: "human performer", roles: "left stabilizes · right rotates", object: "lid_01 · patient", place: "jar · kitchen counter", before: "jar sealed", after: "jar open", time: "12.30—16.50 s", outcome: "success", evidence: "RGB · hand pose · object track" },
text: { en: "Hold the jar with the left hand and unscrew the lid with the right.", zh: "左手扶稳罐子,右手拧开盖子。", tl: "Hawakan ang garapon sa kaliwang kamay at pihitin ang takip gamit ang kanan.", es: "Sujeta el frasco con la izquierda y desenrosca la tapa con la derecha.", hi: "बाएँ हाथ से जार को थामें और दाएँ हाथ से ढक्कन खोलें।" }
},
{
name: "place_mug", source: "Place the blue mug upright on the upper shelf using the right hand.", hot: "upper shelf",
preview: "../assets/evidence-place-mug-v1.png",
previewAlt: "Synthetic first-person preview of the right hand placing a blue mug upright on an upper cabinet shelf while the left hand remains idle",
environment: "indoor · storage cabinet", duration: "2.80 s · episode_clock", claims: 10,
values: { action: "place", agent: "human performer", roles: "right acts · left idle", object: "blue_mug_01 · patient", place: "upper_shelf · destination", before: "held · tilted", after: "supported · upright", time: "21.10—23.90 s", outcome: "stable placement", evidence: "RGB · depth · object pose" },
text: { en: "Place the blue mug upright on the upper shelf using the right hand.", zh: "用右手把蓝色杯子直立放到上层架子上。", tl: "Ilagay nang patayo ang asul na tasa sa itaas na estante gamit ang kanang kamay.", es: "Coloca la taza azul en posición vertical sobre el estante superior con la mano derecha.", hi: "दाएँ हाथ से नीले मग को ऊपरी शेल्फ़ पर सीधा रखें।" }
},
{
name: "slice_tomato", source: "Stabilize the tomato with the left hand and slice it with the knife.", hot: "knife",
preview: "../assets/evidence-slice-tomato-v1.png",
previewAlt: "Synthetic first-person preview of the left hand stabilizing a tomato while the right hand slices it with a kitchen knife",
environment: "indoor · food prep station", duration: "5.60 s · episode_clock", claims: 12,
values: { action: "slice", agent: "human performer", roles: "left stabilizes · right cuts", object: "tomato_01 · patient", place: "cutting_board · support", before: "whole tomato", after: "separated slices", time: "31.00—36.60 s", outcome: "cut completed", evidence: "RGB · contact · temporal span" },
text: { en: "Stabilize the tomato with the left hand and slice it with the knife.", zh: "左手扶稳番茄,用刀将它切片。", tl: "Hawakan nang matatag ang kamatis sa kaliwang kamay at hiwain ito gamit ang kutsilyo.", es: "Sujeta el tomate con la mano izquierda y córtalo en rodajas con el cuchillo.", hi: "बाएँ हाथ से टमाटर को स्थिर रखें और चाकू से उसके टुकड़े काटें।" }
}
];
const languageNames = { en: "English", zh: "简体中文", tl: "Tagalog", es: "Español", hi: "हिन्दी" };
scenes.forEach(scene => { const image = new Image(); image.src = scene.preview; });
const output = document.querySelector("#outputs");
const table = document.querySelector("#packet-table");
const core = document.querySelector("#core");
const machine = document.querySelector("#machine");
let sceneIndex = 0;
let activeLanguage = "tl";
let playing = false;
let timer;
function renderOutputs(scene) {
output.innerHTML = Object.entries(scene.text).map(([code, value]) => `
<button class="output ${code === activeLanguage ? "active" : ""}" data-language="${code}" aria-label="Highlight ${languageNames[code]}">
<span class="output-code">${code}</span><span class="output-text" lang="${code}">${value}</span><span class="output-check">✓</span>
</button>`).join("");
output.querySelectorAll(".output").forEach(button => button.addEventListener("click", () => {
activeLanguage = button.dataset.language;
renderOutputs(scenes[sceneIndex]);
launchSignal();
}));
}
function renderTable(scene) {
const rows = [
["action", scene.values.action], ["agent", scene.values.agent], ["effector roles", scene.values.roles],
["primary object", scene.values.object], ["environment", scene.values.place], ["state before", scene.values.before],
["state after", scene.values.after], ["temporal scope", scene.values.time], ["outcome", scene.values.outcome], ["evidence", scene.values.evidence]
];
table.innerHTML = rows.map((row, i) => `<div class="packet-row"><span class="idx">${String(i+1).padStart(2,"0")}</span><span class="field">${row[0]}</span><span class="value">${row[1]}</span><span class="state">preserved</span></div>`).join("");
}
function launchSignal() {
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
const source = document.querySelector("#source-text");
const target = output.querySelector(".output.active .output-text") || output.querySelector(".output-text");
if (!source || !target || window.innerWidth < 720) return;
const a = source.getBoundingClientRect(), c = core.getBoundingClientRect(), b = target.getBoundingClientRect();
[0, 1].forEach((i) => {
const p = document.createElement("span");
p.className = "particle";
p.style.left = `${a.right - 8}px`; p.style.top = `${a.top + a.height / 2 + (i ? 9 : -9)}px`; p.style.opacity = "1";
document.body.appendChild(p);
setTimeout(() => {
p.style.transform = `translate(${c.left + c.width/2 - a.right}px, ${c.top + c.height/2 - a.top - a.height/2 - (i ? 9 : -9)}px)`;
}, i * 120);
setTimeout(() => {
p.style.transition = "transform 1.05s cubic-bezier(.2,.7,.2,1), opacity .28s .72s";
p.style.transform = `translate(${b.left - a.right + 8}px, ${b.top + b.height/2 - a.top - a.height/2 - (i ? 9 : -9)}px) scale(.55)`;
p.style.opacity = "0";
}, 980 + i * 120);
setTimeout(() => p.remove(), 2150 + i * 120);
});
const nodes = [...document.querySelectorAll(".claim-node")];
nodes.forEach((node, i) => setTimeout(() => { node.classList.add("active"); setTimeout(() => node.classList.remove("active"), 420); }, 430 + i*55));
}
function applyScene(index) {
sceneIndex = index;
const scene = scenes[index];
document.querySelectorAll(".scenario").forEach((b, i) => b.classList.toggle("active", i === index));
const source = scene.source.replace(scene.hot, `<span class="hot">${scene.hot}</span>`);
document.querySelector("#source-text").innerHTML = source;
document.querySelector("#environment").textContent = scene.environment;
document.querySelector("#time-scope").textContent = scene.duration;
document.querySelector("#framecode").textContent = `EVENT / ${scene.name.toUpperCase()}`;
const preview = document.querySelector("#evidence-preview");
const previewWindow = document.querySelector(".evidence-window");
if (scene.preview) {
preview.src = scene.preview;
preview.alt = scene.previewAlt;
preview.hidden = false;
previewWindow.classList.add("has-preview");
document.querySelector("#preview-kind").textContent = "synthetic visual preview";
} else {
preview.hidden = true;
previewWindow.classList.remove("has-preview");
document.querySelector("#preview-kind").textContent = "semantic schematic";
}
document.querySelector("#claim-count").textContent = scene.claims;
document.querySelector(".core-count").textContent = `${scene.claims} / ${scene.claims} claims`;
document.querySelector("#represented").textContent = `${scene.claims} / ${scene.claims}`;
document.querySelector("#scope-line").style.setProperty("--progress", "0%");
requestAnimationFrame(() => document.querySelector("#scope-line").style.setProperty("--progress", "100%"));
renderOutputs(scene); renderTable(scene);
}
function setScene(index, animate = true) {
if (!animate) { applyScene(index); return; }
machine.classList.add("is-updating");
setTimeout(() => {
applyScene(index);
machine.classList.remove("is-updating");
setTimeout(launchSignal, 180);
}, 180);
}
function schedule() {
clearInterval(timer);
if (playing) timer = setInterval(() => setScene((sceneIndex + 1) % scenes.length), 6200);
}
document.querySelectorAll(".scenario").forEach(button => button.addEventListener("click", () => {
setScene(Number(button.dataset.scene)); schedule();
}));
document.querySelector("#pause").addEventListener("click", (event) => {
playing = !playing; event.currentTarget.textContent = playing ? "Ⅱ" : "▶";
event.currentTarget.setAttribute("aria-label", playing ? "Pause automatic examples" : "Play automatic examples"); schedule();
});
setScene(0, false); schedule();
</script>
</body>
</html>