Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>Snap2Sim // Inside the Machine</title> | |
| <link rel="icon" href="data:,"> | |
| <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=Chakra+Petch:wght@400;500;600;700&family=Fira+Code:wght@400;500;600&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/reset.css"> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/reveal.css"> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/theme/black.css" id="theme"> | |
| <style> | |
| :root { | |
| --bg: #0F1318; | |
| --bg-panel: #161B22; | |
| --bg-lift: #1E2530; | |
| --amber: #E8A33D; | |
| --cyan: #5FD4D0; | |
| --text: #C8C0AC; | |
| --text-muted: #9CA3AF; | |
| --danger: #F07F5A; | |
| --grid: rgba(255,255,255,0.04); | |
| --line: rgba(95,212,208,0.34); | |
| --amber-line: rgba(232,163,61,0.45); | |
| } | |
| html, | |
| body { | |
| background: var(--bg); | |
| } | |
| body::before, | |
| body::after { | |
| content: ""; | |
| position: fixed; | |
| inset: 0; | |
| pointer-events: none; | |
| z-index: 1; | |
| } | |
| body::before { | |
| background: | |
| linear-gradient(var(--grid) 1px, transparent 1px), | |
| linear-gradient(90deg, var(--grid) 1px, transparent 1px); | |
| background-size: 32px 32px; | |
| opacity: 0.9; | |
| } | |
| body::after { | |
| background: | |
| radial-gradient(circle at 50% 42%, transparent 48%, rgba(0,0,0,0.52)), | |
| linear-gradient(90deg, rgba(0,0,0,0.2), transparent 22%, transparent 78%, rgba(0,0,0,0.24)); | |
| mix-blend-mode: multiply; | |
| } | |
| .reveal { | |
| color: var(--text); | |
| font-family: "Chakra Petch", "Aptos", sans-serif; | |
| letter-spacing: 0; | |
| } | |
| .reveal .slides { | |
| text-align: left; | |
| } | |
| .reveal .slides > section { | |
| height: 100%; | |
| max-height: 100%; | |
| overflow: hidden; | |
| min-height: 100%; | |
| padding: 50px 56px 46px; | |
| box-sizing: border-box; | |
| } | |
| .slide-grid { | |
| display: grid; | |
| gap: 24px; | |
| height: 100%; | |
| min-height: 0; | |
| } | |
| .two-col { | |
| display: grid; | |
| grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); | |
| gap: 30px; | |
| align-items: stretch; | |
| } | |
| .kicker { | |
| position: absolute; | |
| top: 26px; | |
| left: 36px; | |
| color: var(--amber); | |
| font-family: "Fira Code", monospace; | |
| font-size: 13px; | |
| font-weight: 600; | |
| letter-spacing: 0; | |
| text-transform: uppercase; | |
| } | |
| .watermark { | |
| position: absolute; | |
| right: 34px; | |
| bottom: 24px; | |
| color: rgba(200,192,172,0.13); | |
| font-family: "Fira Code", monospace; | |
| font-size: 12px; | |
| letter-spacing: 0; | |
| text-transform: uppercase; | |
| } | |
| .section-rule { | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, var(--cyan), transparent); | |
| box-shadow: 0 0 20px rgba(95,212,208,0.42); | |
| } | |
| h1, | |
| h2, | |
| h3 { | |
| margin: 0; | |
| color: var(--text); | |
| font-family: "Chakra Petch", "Aptos Display", sans-serif; | |
| font-weight: 700; | |
| letter-spacing: 0; | |
| text-transform: uppercase; | |
| } | |
| h1 { | |
| max-width: 920px; | |
| font-size: 54px; | |
| line-height: 0.96; | |
| } | |
| h2 { | |
| font-size: 38px; | |
| line-height: 1.04; | |
| } | |
| h3 { | |
| color: var(--cyan); | |
| font-size: 22px; | |
| line-height: 1.12; | |
| } | |
| .hook { | |
| max-width: 960px; | |
| color: var(--amber); | |
| font-size: 52px; | |
| font-weight: 700; | |
| line-height: 1.02; | |
| text-transform: none; | |
| } | |
| .positioning { | |
| color: var(--amber); | |
| font-size: 46px; | |
| font-weight: 700; | |
| line-height: 1; | |
| text-transform: uppercase; | |
| } | |
| p { | |
| margin: 0; | |
| color: var(--text); | |
| font-size: 20px; | |
| line-height: 1.38; | |
| } | |
| strong { | |
| color: var(--amber); | |
| font-weight: 700; | |
| } | |
| em { | |
| color: var(--cyan); | |
| font-style: normal; | |
| } | |
| ul { | |
| margin: 0; | |
| padding: 0; | |
| list-style: none; | |
| } | |
| li { | |
| position: relative; | |
| margin: 0 0 11px; | |
| padding-left: 22px; | |
| color: var(--text); | |
| font-size: 19px; | |
| line-height: 1.34; | |
| } | |
| li::before { | |
| content: ""; | |
| position: absolute; | |
| left: 0; | |
| top: 0.58em; | |
| width: 8px; | |
| height: 8px; | |
| border: 1px solid var(--cyan); | |
| transform: rotate(45deg); | |
| background: rgba(95,212,208,0.12); | |
| } | |
| .panel, | |
| .card, | |
| .chip, | |
| .screen { | |
| border: 1px solid var(--amber-line); | |
| background: linear-gradient(180deg, rgba(30,37,48,0.92), rgba(22,27,34,0.96)); | |
| box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 18px 60px rgba(0,0,0,0.22); | |
| } | |
| .panel { | |
| padding: 22px; | |
| } | |
| .card { | |
| padding: 18px; | |
| } | |
| .chip { | |
| display: inline-grid; | |
| place-items: center; | |
| min-height: 34px; | |
| padding: 0 12px; | |
| color: var(--cyan); | |
| font-family: "Fira Code", monospace; | |
| font-size: 15px; | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| white-space: nowrap; | |
| } | |
| .chip.confirmed { | |
| color: var(--amber); | |
| border-color: var(--amber); | |
| background: rgba(232,163,61,0.12); | |
| } | |
| .chip.pending { | |
| color: var(--text-muted); | |
| border-color: rgba(156,163,175,0.36); | |
| background: rgba(156,163,175,0.08); | |
| } | |
| .pillars { | |
| display: grid; | |
| grid-template-columns: repeat(3, 1fr); | |
| gap: 18px; | |
| } | |
| .pillar { | |
| display: grid; | |
| gap: 12px; | |
| min-height: 138px; | |
| } | |
| .pillar p { | |
| color: var(--text-muted); | |
| font-size: 18px; | |
| } | |
| .mono { | |
| font-family: "Fira Code", monospace; | |
| } | |
| .stat { | |
| color: var(--amber); | |
| font-family: "Fira Code", monospace; | |
| font-size: 54px; | |
| font-weight: 600; | |
| line-height: 1; | |
| } | |
| .subtle { | |
| color: var(--text-muted); | |
| } | |
| .caption { | |
| color: var(--text-muted); | |
| font-family: "Fira Code", monospace; | |
| font-size: 13px; | |
| line-height: 1.45; | |
| } | |
| .diagram-wrap { | |
| display: grid; | |
| grid-template-rows: minmax(0, 1fr) auto; | |
| gap: 16px; | |
| height: 100%; | |
| min-height: 0; | |
| } | |
| .architecture { | |
| width: 100%; | |
| height: 100%; | |
| min-height: 420px; | |
| display: block; | |
| } | |
| .demo-grid { | |
| display: grid; | |
| grid-template-columns: 1.42fr 0.9fr; | |
| gap: 22px; | |
| align-items: stretch; | |
| min-height: 0; | |
| } | |
| .screen { | |
| position: relative; | |
| overflow: hidden; | |
| min-height: 0; | |
| padding: 22px; | |
| } | |
| .screen::before { | |
| content: ""; | |
| position: absolute; | |
| inset: 0; | |
| background: | |
| linear-gradient(rgba(255,255,255,0.035) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(255,255,255,0.035) 1px, transparent 1px); | |
| background-size: 24px 24px; | |
| pointer-events: none; | |
| } | |
| .mock-shell { | |
| position: relative; | |
| z-index: 1; | |
| display: grid; | |
| grid-template-columns: 1.5fr 0.82fr; | |
| gap: 16px; | |
| height: 100%; | |
| } | |
| .mock-viewport, | |
| .mock-panel { | |
| border: 1px solid rgba(95,212,208,0.28); | |
| background: rgba(15,19,24,0.72); | |
| } | |
| .mock-viewport { | |
| position: relative; | |
| min-height: 0; | |
| overflow: hidden; | |
| } | |
| .mock-viewport svg { | |
| position: absolute; | |
| inset: 18px; | |
| width: calc(100% - 36px); | |
| height: calc(100% - 36px); | |
| } | |
| .mock-panel { | |
| display: grid; | |
| grid-template-rows: auto auto 1fr; | |
| gap: 12px; | |
| padding: 16px; | |
| } | |
| .mock-title { | |
| color: var(--cyan); | |
| font-size: 22px; | |
| font-weight: 700; | |
| line-height: 1; | |
| text-transform: uppercase; | |
| } | |
| .mock-line { | |
| height: 9px; | |
| background: rgba(200,192,172,0.2); | |
| } | |
| .compare { | |
| display: grid; | |
| gap: 14px; | |
| } | |
| .compare-row { | |
| display: grid; | |
| grid-template-columns: 0.86fr 1.14fr; | |
| gap: 16px; | |
| align-items: stretch; | |
| } | |
| .compare-row > div { | |
| border: 1px solid rgba(95,212,208,0.22); | |
| padding: 15px; | |
| background: rgba(15,19,24,0.52); | |
| } | |
| .compare-row b { | |
| display: block; | |
| margin-bottom: 6px; | |
| color: var(--amber); | |
| font-size: 17px; | |
| text-transform: uppercase; | |
| } | |
| .compare-row span { | |
| color: var(--text); | |
| font-size: 18px; | |
| line-height: 1.25; | |
| } | |
| .stack-list { | |
| display: grid; | |
| gap: 11px; | |
| } | |
| .stack-list li { | |
| margin: 0; | |
| color: var(--text-muted); | |
| font-family: "Fira Code", monospace; | |
| font-size: 15px; | |
| line-height: 1.35; | |
| } | |
| .badge-grid { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 10px; | |
| align-content: start; | |
| } | |
| .closing-links { | |
| display: grid; | |
| gap: 16px; | |
| margin-top: 8px; | |
| } | |
| .link-row { | |
| display: grid; | |
| grid-template-columns: 160px minmax(0, 1fr); | |
| gap: 16px; | |
| align-items: baseline; | |
| border-bottom: 1px solid rgba(95,212,208,0.2); | |
| padding-bottom: 10px; | |
| } | |
| .link-row span { | |
| color: var(--amber); | |
| font-family: "Fira Code", monospace; | |
| font-size: 14px; | |
| text-transform: uppercase; | |
| } | |
| .link-row a, | |
| .link-row p { | |
| color: var(--cyan); | |
| font-family: "Fira Code", monospace; | |
| font-size: 16px; | |
| line-height: 1.35; | |
| text-decoration: none; | |
| overflow-wrap: anywhere; | |
| } | |
| .reticle { | |
| position: absolute; | |
| right: 72px; | |
| top: 92px; | |
| width: 170px; | |
| height: 170px; | |
| border: 1px solid rgba(95,212,208,0.36); | |
| border-radius: 50%; | |
| opacity: 0.55; | |
| } | |
| .reticle::before, | |
| .reticle::after { | |
| content: ""; | |
| position: absolute; | |
| background: rgba(95,212,208,0.42); | |
| } | |
| .reticle::before { | |
| left: 50%; | |
| top: -18px; | |
| width: 1px; | |
| height: calc(100% + 36px); | |
| } | |
| .reticle::after { | |
| top: 50%; | |
| left: -18px; | |
| height: 1px; | |
| width: calc(100% + 36px); | |
| } | |
| .scanline { | |
| position: absolute; | |
| left: 0; | |
| right: 0; | |
| top: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, var(--cyan), transparent); | |
| opacity: 0.8; | |
| animation: scan 7s ease-in-out infinite; | |
| box-shadow: 0 0 18px rgba(95,212,208,0.72); | |
| } | |
| .reveal h1, | |
| .reveal h2, | |
| .reveal h3 { | |
| margin: 0; | |
| color: var(--text); | |
| font-family: "Chakra Petch", "Aptos Display", sans-serif; | |
| font-weight: 700; | |
| letter-spacing: 0; | |
| text-transform: uppercase; | |
| text-shadow: none; | |
| } | |
| .reveal h1 { | |
| max-width: 920px; | |
| font-size: 54px; | |
| line-height: 0.96; | |
| } | |
| .reveal h2 { | |
| font-size: 38px; | |
| line-height: 1.04; | |
| } | |
| .reveal h3 { | |
| color: var(--cyan); | |
| font-size: 22px; | |
| line-height: 1.12; | |
| } | |
| .reveal p { | |
| margin: 0; | |
| color: var(--text); | |
| font-size: 20px; | |
| line-height: 1.38; | |
| } | |
| .reveal ul { | |
| margin: 0; | |
| padding: 0; | |
| list-style: none; | |
| } | |
| .reveal li { | |
| margin: 0 0 11px; | |
| color: var(--text); | |
| font-size: 19px; | |
| line-height: 1.34; | |
| } | |
| .reveal .hook { | |
| color: var(--amber); | |
| font-size: 52px; | |
| line-height: 1.02; | |
| text-transform: none; | |
| } | |
| .reveal .positioning { | |
| color: var(--amber); | |
| font-size: 46px; | |
| line-height: 1; | |
| text-transform: uppercase; | |
| } | |
| @keyframes scan { | |
| 0%, 22% { transform: translateY(0); opacity: 0; } | |
| 28%, 58% { opacity: 1; } | |
| 70%, 100% { transform: translateY(100vh); opacity: 0; } | |
| } | |
| @media (max-width: 900px) { | |
| .reveal .slides > section { | |
| padding: 48px 34px 48px; | |
| } | |
| .hook, | |
| .positioning { | |
| font-size: 40px; | |
| } | |
| h1 { | |
| font-size: 42px; | |
| } | |
| h2 { | |
| font-size: 34px; | |
| } | |
| p, | |
| li { | |
| font-size: 18px; | |
| } | |
| .two-col, | |
| .demo-grid, | |
| .mock-shell, | |
| .compare-row { | |
| grid-template-columns: 1fr; | |
| } | |
| .pillars { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| @media print { | |
| body::before, | |
| body::after, | |
| .scanline { | |
| display: none; | |
| } | |
| .reveal .slides > section { | |
| background: var(--bg) ; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="reveal"> | |
| <div class="slides"> | |
| <section data-transition="fade"> | |
| <div class="scanline" aria-hidden="true"></div> | |
| <div class="reticle" aria-hidden="true"></div> | |
| <div class="kicker">01 / THE PROBLEM</div> | |
| <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div> | |
| <div class="slide-grid" style="grid-template-rows: auto auto 1fr;"> | |
| <div class="hook">"You find a small metal cylinder at a flea market. What is it? How does it work inside?"</div> | |
| <div class="section-rule"></div> | |
| <ul> | |
| <li>Curious makers, repair hobbyists, thrift scavengers, and robotics students constantly hold <strong>mystery hardware</strong> and cannot see what is happening inside.</li> | |
| <li>Existing image AI <strong>stops at a label</strong> - "this is a valve" - instead of answering the real question: <em>what moves, and why?</em></li> | |
| <li>Teardowns, manuals, and exploded diagrams are scattered, intimidating, or do not exist for that exact part.</li> | |
| </ul> | |
| </div> | |
| <aside class="notes"> | |
| Open with the flea-market object. The point is not recognition; it is curiosity about hidden motion. | |
| </aside> | |
| </section> | |
| <section data-transition="fade"> | |
| <div class="scanline" aria-hidden="true"></div> | |
| <div class="kicker">02 / THE SOLUTION</div> | |
| <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div> | |
| <div class="slide-grid" style="grid-template-rows: auto auto auto 1fr;"> | |
| <div class="positioning">Snap a photo. Watch the mechanism come alive.</div> | |
| <p>Snap2Sim turns a single photo of a hardware component into a <strong>narrated, animated 3D mechanical cutaway</strong> - naming internal parts and showing hidden motion.</p> | |
| <div class="pillars"> | |
| <div class="card pillar"> | |
| <span class="chip">[ identify ]</span> | |
| <h3>Likely mechanism</h3> | |
| <p>Confidence and mechanism type, not just a class name.</p> | |
| </div> | |
| <div class="card pillar"> | |
| <span class="chip">[ explain ]</span> | |
| <h3>Plain-language motion</h3> | |
| <p>Internal parts, trigger, and sequence: plunger, spring, rotor, pawl, port.</p> | |
| </div> | |
| <div class="card pillar"> | |
| <span class="chip">[ animate ]</span> | |
| <h3>Orbit the cutaway</h3> | |
| <p>Three.js field-manual view with orbit, zoom, reset, and play/pause.</p> | |
| </div> | |
| </div> | |
| <p class="caption">Honesty is part of the product: when confident 3D reconstruction is not justified, Snap2Sim falls back to annotated callouts on the original photo instead of pretending.</p> | |
| </div> | |
| <aside class="notes"> | |
| Stress that the fallback is a feature, not a failure. The demo has a confidence threshold so uncertainty is visible and controllable. | |
| </aside> | |
| </section> | |
| <section data-transition="fade"> | |
| <div class="kicker">03 / HOW IT WORKS</div> | |
| <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div> | |
| <div class="diagram-wrap"> | |
| <svg class="architecture" viewBox="0 0 1110 550" role="img" aria-labelledby="archTitle archDesc"> | |
| <title id="archTitle">Snap2Sim architecture flow</title> | |
| <desc id="archDesc">Photo upload flows through the Hugging Face Space, Modal GPU endpoint, NVIDIA Nemotron with llama.cpp, JSON validation, and deterministic browser rendering, with low confidence going to an annotated-photo fallback.</desc> | |
| <defs> | |
| <filter id="glow" x="-30%" y="-30%" width="160%" height="160%"> | |
| <feGaussianBlur stdDeviation="3" result="coloredBlur"/> | |
| <feMerge> | |
| <feMergeNode in="coloredBlur"/> | |
| <feMergeNode in="SourceGraphic"/> | |
| </feMerge> | |
| </filter> | |
| <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> | |
| <path d="M 0 0 L 10 5 L 0 10 z" fill="#5FD4D0"/> | |
| </marker> | |
| </defs> | |
| <rect x="6" y="6" width="1098" height="538" fill="rgba(15,19,24,0.58)" stroke="rgba(95,212,208,0.22)"/> | |
| <g font-family="Fira Code, monospace" font-size="14" fill="#C8C0AC"> | |
| <g transform="translate(45 45)"> | |
| <rect width="210" height="78" rx="0" fill="#161B22" stroke="#E8A33D" stroke-width="2"/> | |
| <text x="105" y="34" text-anchor="middle" fill="#E8A33D" font-weight="600">Photo upload</text> | |
| <text x="105" y="56" text-anchor="middle" fill="#9CA3AF">component image</text> | |
| </g> | |
| <path d="M 255 84 C 302 84 302 84 346 84" stroke="#5FD4D0" stroke-width="2.4" fill="none" marker-end="url(#arrow)" filter="url(#glow)"/> | |
| <text x="300" y="68" text-anchor="middle" fill="#5FD4D0" font-size="12">POST /analyze_image</text> | |
| <g transform="translate(346 45)"> | |
| <rect width="250" height="78" fill="#161B22" stroke="#E8A33D" stroke-width="2"/> | |
| <text x="125" y="30" text-anchor="middle" fill="#E8A33D" font-weight="600">Hugging Face Space</text> | |
| <text x="125" y="52" text-anchor="middle" fill="#9CA3AF">gradio.Server / cpu-basic</text> | |
| </g> | |
| <path d="M 596 84 C 642 84 642 84 686 84" stroke="#5FD4D0" stroke-width="2.4" fill="none" marker-end="url(#arrow)" filter="url(#glow)"/> | |
| <text x="640" y="68" text-anchor="middle" fill="#5FD4D0" font-size="12">bearer-token secret</text> | |
| <g transform="translate(686 45)"> | |
| <rect width="210" height="78" fill="#161B22" stroke="#E8A33D" stroke-width="2"/> | |
| <text x="105" y="30" text-anchor="middle" fill="#E8A33D" font-weight="600">Modal GPU endpoint</text> | |
| <text x="105" y="52" text-anchor="middle" fill="#9CA3AF">llama.cpp + mtmd</text> | |
| </g> | |
| <path d="M 791 123 L 791 166" stroke="#5FD4D0" stroke-width="2.4" fill="none" marker-end="url(#arrow)" filter="url(#glow)"/> | |
| <g transform="translate(626 166)"> | |
| <rect width="330" height="86" fill="#161B22" stroke="#E8A33D" stroke-width="2"/> | |
| <text x="165" y="30" text-anchor="middle" fill="#E8A33D" font-weight="600">NVIDIA Nemotron 3 Nano Omni</text> | |
| <text x="165" y="52" text-anchor="middle" fill="#9CA3AF">30B-A3B GGUF / UD-Q4_K_M</text> | |
| <text x="165" y="72" text-anchor="middle" fill="#9CA3AF">mmproj-F16 returns JSON</text> | |
| </g> | |
| <path d="M 626 209 C 560 209 560 209 506 209" stroke="#5FD4D0" stroke-width="2.4" fill="none" marker-end="url(#arrow)" filter="url(#glow)"/> | |
| <g transform="translate(246 166)"> | |
| <rect width="260" height="86" fill="#161B22" stroke="#E8A33D" stroke-width="2"/> | |
| <text x="130" y="30" text-anchor="middle" fill="#E8A33D" font-weight="600">/generate_scene</text> | |
| <text x="130" y="52" text-anchor="middle" fill="#9CA3AF">schema validation</text> | |
| <text x="130" y="72" text-anchor="middle" fill="#9CA3AF">render-mode select</text> | |
| </g> | |
| <path d="M 376 252 L 376 314" stroke="#5FD4D0" stroke-width="2.4" fill="none" marker-end="url(#arrow)" filter="url(#glow)"/> | |
| <g transform="translate(190 314)"> | |
| <rect width="372" height="92" fill="#161B22" stroke="#E8A33D" stroke-width="2"/> | |
| <text x="186" y="34" text-anchor="middle" fill="#E8A33D" font-weight="600">Browser renders deterministic</text> | |
| <text x="186" y="58" text-anchor="middle" fill="#9CA3AF">Three.js cutaway</text> | |
| <text x="186" y="78" text-anchor="middle" fill="#9CA3AF">orbit / zoom / reset / play</text> | |
| </g> | |
| <path d="M 562 360 C 640 360 672 360 744 360" stroke="#5FD4D0" stroke-width="2.4" fill="none" marker-end="url(#arrow)" stroke-dasharray="8 8"/> | |
| <text x="652" y="342" text-anchor="middle" fill="#5FD4D0" font-size="12">low confidence</text> | |
| <g transform="translate(744 314)"> | |
| <rect width="250" height="92" fill="#161B22" stroke="rgba(156,163,175,0.65)" stroke-width="2"/> | |
| <text x="125" y="35" text-anchor="middle" fill="#9CA3AF" font-weight="600">Annotated-photo</text> | |
| <text x="125" y="59" text-anchor="middle" fill="#9CA3AF">fallback</text> | |
| </g> | |
| <g transform="translate(90 456)"> | |
| <rect width="930" height="42" fill="rgba(95,212,208,0.08)" stroke="rgba(95,212,208,0.28)"/> | |
| <text x="465" y="27" text-anchor="middle" fill="#C8C0AC" font-size="16"> | |
| The model describes the mechanism. The browser owns the rendering. | |
| </text> | |
| </g> | |
| </g> | |
| </svg> | |
| <p class="caption"><strong>No model-authored HTML/JS touches the page.</strong> The renderer consumes validated mechanism JSON, which keeps the live demo reliable and safe.</p> | |
| </div> | |
| <aside class="notes"> | |
| The important architectural decision is separation of concerns: Modal and Nemotron infer the mechanism, while trusted browser code renders it deterministically. | |
| </aside> | |
| </section> | |
| <section data-transition="fade"> | |
| <div class="kicker">04 / LIVE DEMO</div> | |
| <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div> | |
| <div class="slide-grid" style="grid-template-rows: auto 1fr;"> | |
| <h2>The moment: photo in, cutaway out.</h2> | |
| <div class="demo-grid"> | |
| <div class="screen" aria-label="In-theme product demo mockup"> | |
| <div class="mock-shell"> | |
| <div class="mock-viewport"> | |
| <svg viewBox="0 0 440 300" aria-hidden="true"> | |
| <rect x="0" y="0" width="440" height="300" fill="rgba(15,19,24,0.35)"/> | |
| <g stroke="#5FD4D0" stroke-width="2" fill="none" opacity="0.7"> | |
| <circle cx="218" cy="150" r="88"/> | |
| <line x1="218" y1="32" x2="218" y2="268"/> | |
| <line x1="100" y1="150" x2="336" y2="150"/> | |
| </g> | |
| <g transform="translate(112 76)"> | |
| <rect x="38" y="54" width="166" height="52" fill="#1E2530" stroke="#E8A33D" stroke-width="3"/> | |
| <circle cx="77" cy="80" r="30" fill="rgba(95,212,208,0.22)" stroke="#5FD4D0" stroke-width="4"/> | |
| <rect x="160" y="36" width="26" height="88" fill="rgba(232,163,61,0.24)" stroke="#E8A33D" stroke-width="3"/> | |
| <path d="M 184 80 C 218 52 236 108 270 80" stroke="#F07F5A" stroke-width="5"/> | |
| </g> | |
| <text x="34" y="270" fill="#9CA3AF" font-family="Fira Code" font-size="12">Drag to orbit / scroll to zoom</text> | |
| <text x="270" y="88" fill="#5FD4D0" font-family="Fira Code" font-size="13">spring preload</text> | |
| <text x="246" y="210" fill="#5FD4D0" font-family="Fira Code" font-size="13">sliding plunger</text> | |
| </svg> | |
| </div> | |
| <div class="mock-panel"> | |
| <div class="chip confirmed">CUTAWAY READY</div> | |
| <div class="mock-title">Piston Mechanism</div> | |
| <div class="mono subtle">confidence 85%</div> | |
| <div class="mock-line" style="width: 92%;"></div> | |
| <div class="mock-line" style="width: 74%;"></div> | |
| <div class="mock-line" style="width: 86%;"></div> | |
| <div class="mock-line" style="width: 62%; background: rgba(95,212,208,0.28);"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="panel"> | |
| <h3>Judges should feel the handoff.</h3> | |
| <ul> | |
| <li>Upload a mystery part photo.</li> | |
| <li>Watch analysis become named parts and motion.</li> | |
| <li>Orbit, zoom, reset, and play/pause the deterministic scene.</li> | |
| <li>Move the confidence slider and see fallback behavior stay honest.</li> | |
| </ul> | |
| </div> | |
| </div> | |
| </div> | |
| <aside class="notes"> | |
| Drop in a valve, lock, pump, gear train, fan, or latch. | |
| </aside> | |
| </section> | |
| <section data-transition="fade"> | |
| <div class="kicker">05 / DIFFERENTIATION</div> | |
| <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div> | |
| <div class="slide-grid" style="grid-template-rows: auto auto 1fr;"> | |
| <h2>Most image demos stop at a label.</h2> | |
| <p>Snap2Sim answers the maker's next question: <em>what would I see if I cut this open?</em></p> | |
| <div class="compare"> | |
| <div class="compare-row"> | |
| <div><b>Typical image demo</b><span>"This is a valve."</span></div> | |
| <div><b>Snap2Sim</b><span>Likely mechanism, internal parts, trigger, and motion sequence.</span></div> | |
| </div> | |
| <div class="compare-row"> | |
| <div><b>Static output</b><span>Caption, chat answer, or generic class label.</span></div> | |
| <div><b>Moving cutaway</b><span>Maps parts into a technical field-manual scene with animation.</span></div> | |
| </div> | |
| <div class="compare-row"> | |
| <div><b>Overconfident</b><span>Looks plausible even when geometry is unsupported.</span></div> | |
| <div><b>Honest uncertainty</b><span>Confidence threshold plus annotated-photo fallback.</span></div> | |
| </div> | |
| <div class="compare-row"> | |
| <div><b>Default app shell</b><span>Generic chat or form UI.</span></div> | |
| <div><b>Branded maker tool</b><span>Cutaway aesthetic, same-origin client calls, server-side secrets.</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| <aside class="notes"> | |
| This is the Off-Brand angle: it feels like a purpose-built instrument, not a wrapper around a model response. | |
| </aside> | |
| </section> | |
| <section data-transition="fade"> | |
| <div class="kicker">06 / TECH STACK + HACKATHON FIT</div> | |
| <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div> | |
| <div class="two-col" style="height: 100%;"> | |
| <div class="panel"> | |
| <h3>Stack</h3> | |
| <ul class="stack-list"> | |
| <li>Frontend: plain index.html + CSS + JS served by gradio.Server.</li> | |
| <li>Rendering: deterministic Three.js primitives: box, cylinder, cone, capsule, sphere, rod, gear, torus, spring.</li> | |
| <li>Controls: OrbitControls, camera fitting, reset view, confidence threshold, annotated-photo fallback.</li> | |
| <li>Model: NVIDIA Nemotron 3 Nano Omni 30B-A3B GGUF, UD-Q4_K_M + mmproj-F16.</li> | |
| <li>Budget: ~30B total / ~3B active per MoE token, under the 32B single-model budget.</li> | |
| <li>GPU: Modal with weights cached in a Modal Volume and bearer-token protection.</li> | |
| <li>Contract: JSON schema validation before anything renders.</li> | |
| </ul> | |
| </div> | |
| <div class="panel"> | |
| <h3>Badges we are claiming</h3> | |
| <div class="badge-grid" style="margin-top: 18px;"> | |
| <span class="chip confirmed">Backyard AI / core fit</span> | |
| <span class="chip confirmed">Llama Champion</span> | |
| <span class="chip confirmed">NVIDIA Nemotron Quest</span> | |
| <span class="chip confirmed">Modal Award</span> | |
| <span class="chip confirmed">Off-Brand</span> | |
| <span class="chip confirmed">OpenAI Codex</span> | |
| <span class="chip pending">Best Demo / pending video</span> | |
| <span class="chip pending">Sharing is Caring / pending post</span> | |
| <span class="chip pending">Off the Grid / not claimed</span> | |
| </div> | |
| <p class="caption" style="margin-top: 22px;">Inference currently runs on Modal, so Off the Grid is intentionally not claimed.</p> | |
| </div> | |
| </div> | |
| <aside class="notes"> | |
| Keep this factual. The strongest credibility points are the real Modal/Nemotron path, schema gate, deterministic renderer, and honest fallback. | |
| </aside> | |
| </section> | |
| <section data-transition="fade"> | |
| <div class="scanline" aria-hidden="true"></div> | |
| <div class="reticle" aria-hidden="true"></div> | |
| <div class="kicker">07 / CLOSE</div> | |
| <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div> | |
| <div class="slide-grid" style="grid-template-rows: auto auto 1fr auto;"> | |
| <h1>Snap a photo. See inside the machine.</h1> | |
| <p class="hook" style="font-size: 38px; max-width: 880px;">"You find a small metal cylinder at a flea market. What is it? How does it work inside?"</p> | |
| <div class="panel closing-links"> | |
| <div class="link-row"> | |
| <span>GitHub</span> | |
| <a href="https://github.com/Bigstonks1/Snap2Sim">https://github.com/Bigstonks1/Snap2Sim</a> | |
| </div> | |
| <div class="link-row"> | |
| <span>HF Space</span> | |
| <p>https://huggingface.co/spaces/build-small-hackathon/Snap2Sim<br><span class="subtle">Public submission Space under the Build Small Hackathon organization.</span></p> | |
| </div> | |
| <div class="link-row"> | |
| <span>Credit</span> | |
| <p>Built by Jason Do with implementation assistance from OpenAI Codex.</p> | |
| </div> | |
| </div> | |
| <p class="caption">Snap2Sim // Inside the Machine // Build Small Hackathon</p> | |
| </div> | |
| <aside class="notes"> | |
| End with the same hook. The product promise is short: snap a photo, see the hidden mechanism, and learn by looking inside. | |
| </aside> | |
| </section> | |
| </div> | |
| </div> | |
| <script src="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/reveal.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/reveal.js@5/plugin/notes/notes.js"></script> | |
| <script> | |
| Reveal.initialize({ | |
| hash: true, | |
| controls: true, | |
| progress: true, | |
| center: false, | |
| slideNumber: "c/t", | |
| transition: "fade", | |
| backgroundTransition: "fade", | |
| width: 1440, | |
| height: 810, | |
| margin: 0.06, | |
| plugins: [RevealNotes] | |
| }); | |
| </script> | |
| </body> | |
| </html> | |