jasondo OpenAI Codex commited on
Commit
92853cc
·
1 Parent(s): c5339c8

Add hackathon presentation deck

Browse files

Co-authored-by: OpenAI Codex <codex@openai.com>

AGENTS.md CHANGED
@@ -399,6 +399,17 @@ technical cutaway animation.
399
  assembly` at `0.65` confidence with an emitted motion axis of
400
  `[1.0, 0.0, 0.0]`, and `/generate_scene` returned `renderer: three`,
401
  `render_mode: three`, and no HTML field.
 
 
 
 
 
 
 
 
 
 
 
402
 
403
  ## Next Work
404
 
@@ -406,8 +417,10 @@ technical cutaway animation.
406
  tune token/context/timeout values down if valid JSON remains reliable with
407
  lower latency. The synthetic Modal check now succeeds with the current
408
  `4096` output token, `8192` context, `300s` timeout settings.
409
- - Keep the Hugging Face Space private until the user explicitly approves making
410
- it public for submission.
 
 
411
  - Keep the README opening hook intact: "You find a small metal cylinder at a
412
  flea market. What is it? How does it work inside?" Maintain the judge-facing
413
  YAML tags and public pitch if future README updates are needed.
 
399
  assembly` at `0.65` confidence with an emitted motion axis of
400
  `[1.0, 0.0, 0.0]`, and `/generate_scene` returned `renderer: three`,
401
  `render_mode: three`, and no HTML field.
402
+ - User made Hugging Face Space `jasondo111/Snap2Sim` public on June 15, 2026.
403
+ Verification confirmed Hub metadata `private=false`, the public Space page
404
+ returned `200`, and the public app host
405
+ `https://jasondo111-snap2sim.hf.space` returned the trusted shell with the
406
+ confidence slider present. The Space has not been transferred to
407
+ `build-small-hackathon/Snap2Sim`; that target repo did not exist at the time
408
+ of verification.
409
+ - Public endpoint smoke verification on June 15, 2026 passed: `/generate_scene`
410
+ returned `renderer: three` with no HTML field for `EXAMPLE_ANALYSIS`, and
411
+ `/analyze_image` returned a real Modal analysis for a synthetic target-like
412
+ image as `rotary indexer` at `0.6` confidence with 3 parts.
413
 
414
  ## Next Work
415
 
 
417
  tune token/context/timeout values down if valid JSON remains reliable with
418
  lower latency. The synthetic Modal check now succeeds with the current
419
  `4096` output token, `8192` context, `300s` timeout settings.
420
+ - The Hugging Face Space is now public under `jasondo111/Snap2Sim`. If the
421
+ submission requires org ownership, transfer it to
422
+ `build-small-hackathon/Snap2Sim`, then update README, presentation links, and
423
+ `.github/workflows/sync_to_hf.yml`.
424
  - Keep the README opening hook intact: "You find a small metal cylinder at a
425
  flea market. What is it? How does it work inside?" Maintain the judge-facing
426
  YAML tags and public pitch if future README updates are needed.
PRESENTATION_PROMPT.md ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # PRESENTATION_PROMPT.md
2
+
3
+ > Build instructions for Codex. Goal: produce a **self-contained HTML slide deck**
4
+ > that markets Snap2Sim — "Inside the Machine" to **Build Small Hackathon judges**.
5
+ > Tone: interesting, intuitive, fun, concise, beautifully formatted. This file is
6
+ > a spec, not the deck. Follow the deliverable + slide plan below.
7
+
8
+ ---
9
+
10
+ ## 1. Deliverable
11
+
12
+ Create `presentation/deck.html` — a single, **self-contained** reveal.js deck.
13
+
14
+ - Use the [reveal.js](https://revealjs.com/) CDN (`<script src="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/reveal.js">` + matching CSS), so there is **no build step**. Opens in any browser.
15
+ - Put any standalone assets (exported screenshots, fonts you self-host if needed) in `presentation/assets/`. Prefer inline SVG over external images so the deck stays portable.
16
+ - The architecture diagram must be **inline SVG (or Mermaid rendered to inline SVG)** so the deck has no broken-image risk during a live demo.
17
+ - Keyboard nav, speaker notes (`data-notes` / the reveal notes plugin), and a PDF export path (`?print-pdf`) should all work.
18
+ - No external API calls, no tracking, no network dependency beyond the reveal.js + font CDNs.
19
+
20
+ ### Match the product's visual identity (this is a "technical field-manual / cutaway" aesthetic)
21
+
22
+ Pull the theme straight from `index.html` so the deck feels like the same product:
23
+
24
+ ```
25
+ --bg: #0F1318 (near-black blue)
26
+ --bg-panel: #161B22
27
+ --bg-lift: #1E2530
28
+ --amber: #E8A33D (primary accent — headings, key numbers)
29
+ --cyan: #5FD4D0 (secondary accent — labels, links, diagram lines)
30
+ --text: #C8C0AC (warm off-white body)
31
+ --text-muted:#9CA3AF
32
+ --danger: #F07F5A
33
+ --grid: rgba(255,255,255,0.04)
34
+ ```
35
+
36
+ - Fonts: **"Chakra Petch"** for headings/UI and **"Fira Code"** (monospace) for data, labels, code, and stat callouts. Load from Google Fonts.
37
+ - Texture cues to carry over from the app: faint blueprint **grid background**, thin **cyan scan-line / divider rules**, amber section kickers, a subtle vignette. Keep it tasteful — readability first, one or two motion flourishes max.
38
+ - Every slide: small monospace **kicker label** top-left (e.g. `01 · THE PROBLEM`) and a faint `SNAP2SIM // INSIDE THE MACHINE` watermark. This mirrors the in-app component watermark + reticle styling.
39
+
40
+ ---
41
+
42
+ ## 2. Slide plan (in order)
43
+
44
+ The user explicitly required slides 1–3 in this order. Build the full deck below.
45
+
46
+ ### Slide 1 — The Problem (REQUIRED, first)
47
+ Lead with the product's own hook, verbatim, as the emotional opening:
48
+
49
+ > "You find a small metal cylinder at a flea market. What is it? How does it work inside?"
50
+
51
+ Then frame the problem crisply:
52
+ - Curious makers, repair hobbyists, thrift scavengers, and robotics students constantly hold **mystery hardware** and can't see what's happening inside.
53
+ - Existing image AI **stops at a label** ("this is a valve") — it never answers the real question: *what moves, and why?*
54
+ - Teardowns, manuals, and exploded diagrams are scattered, intimidating, or don't exist for that exact part.
55
+
56
+ Keep it to 3 tight bullets + the hook. Don't over-explain.
57
+
58
+ ### Slide 2 — The Solution (REQUIRED, second)
59
+ One-line positioning statement (make it pop in amber):
60
+
61
+ > **Snap a photo. Watch the mechanism come alive.**
62
+
63
+ Then: Snap2Sim turns a single photo of a hardware component into a **narrated, animated 3D mechanical cutaway** — it names the internal parts and shows the hidden motion: the plunger sliding, the spring loading, the rotor spinning, the pawl catching, the port opening.
64
+
65
+ Three short "what you get" pillars (use icon-ish monospace chips):
66
+ 1. **Identify** — the likely mechanism + confidence, not just a class name.
67
+ 2. **Explain** — internal parts, the trigger, and the motion sequence in plain language.
68
+ 3. **Animate** — a moving Three.js field-manual cutaway you can orbit, zoom, and reset.
69
+
70
+ Add the honesty angle as a one-liner: when a confident 3D reconstruction isn't justified, it **falls back to annotated callouts on the original photo instead of pretending.** (Judges love that it doesn't hallucinate geometry.)
71
+
72
+ ### Slide 3 — How It Works / Architecture Diagram (REQUIRED, third)
73
+ An **inline SVG** flow diagram of the real pipeline. Nodes and flow (left → right), styled with cyan connectors and amber node borders on dark panels:
74
+
75
+ ```
76
+ [ Photo upload ]
77
+ │ same-origin POST /analyze_image
78
+
79
+ [ Hugging Face Space (gradio.Server, cpu-basic) ]
80
+ │ bearer-token, server-side secret
81
+
82
+ [ Modal GPU endpoint ]
83
+ │ llama.cpp + llama-mtmd-cli
84
+
85
+ [ NVIDIA Nemotron 3 Nano Omni 30B-A3B GGUF (UD-Q4_K_M + mmproj-F16) ]
86
+ │ returns structured mechanism JSON
87
+
88
+ [ /generate_scene → JSON schema validation → render-mode select ]
89
+
90
+
91
+ [ Browser renders DETERMINISTIC Three.js cutaway ] ──(low confidence)──▶ [ Annotated-photo fallback ]
92
+ ```
93
+
94
+ Caption the key architectural decision under the diagram:
95
+ > **The model describes the mechanism. The browser owns the rendering.** No model-authored HTML/JS ever touches the page — that keeps the demo reliable and safe.
96
+
97
+ If you use Mermaid, render it to inline SVG at build time or load Mermaid from CDN and let it render on slide-ready; either way it must display with zero external image files.
98
+
99
+ ### Slide 4 — Live Demo / "The Moment"
100
+ - Frame the demo: photo in → cutaway out, in seconds.
101
+ - Use the in-theme demo mockup currently in the deck, or replace it later with intentionally captured product screenshots in `presentation/assets/`.
102
+ - Callout the interactivity: orbit / zoom / reset, play-pause, confidence slider.
103
+ - Speaker note: "Drop in a valve, lock, pump, gear train, fan, or latch."
104
+
105
+ ### Slide 5 — What Makes It Different
106
+ Tight comparison. Most image demos stop at a label; Snap2Sim answers *"what would I see if I cut this open?"*
107
+ - Mechanism explanation, not a class name.
108
+ - Maps internal parts into a moving technical cutaway.
109
+ - Honest uncertainty: confidence threshold + photo-annotation fallback.
110
+ - Custom branded maker tool, not a default chat/form UI.
111
+ - Secrets + GPU endpoints stay server-side; client calls only same-origin APIs.
112
+
113
+ ### Slide 6 — Tech Stack & Hackathon Fit (the judge-credibility slide)
114
+ Two columns.
115
+
116
+ **Stack** (monospace list):
117
+ - Frontend: plain `index.html` + CSS + JS served by `gradio.Server`.
118
+ - Rendering: deterministic Three.js primitives (box, cylinder, cone, capsule, sphere, rod, gear, torus, spring), OrbitControls, camera fitting, annotated-photo fallback.
119
+ - Model: NVIDIA Nemotron 3 Nano Omni 30B-A3B GGUF (~30B total / ~3B active per MoE token — **under the 32B budget**) via llama.cpp.
120
+ - GPU: Modal, weights cached in a Modal Volume, bearer-token protected.
121
+ - Contract: JSON schema validation before anything renders.
122
+
123
+ **Badges we're claiming** (render as themed chips — confirmed ones in amber, pending in muted):
124
+ | Badge | Status |
125
+ |---|---|
126
+ | Backyard AI (track) | core fit |
127
+ | Llama Champion | confirmed |
128
+ | NVIDIA Nemotron Quest | confirmed |
129
+ | Modal Award | confirmed |
130
+ | Off-Brand | confirmed |
131
+ | OpenAI Codex | confirmed |
132
+ | Best Demo / Sharing is Caring | pending demo video + social post |
133
+ | Off the Grid | not claimed (inference runs on Modal) |
134
+
135
+ ### Slide 7 — Closing / Call to Action
136
+ - Restate the one-liner: **Snap a photo. See inside the machine.**
137
+ - Links: GitHub source of truth `https://github.com/Bigstonks1/Snap2Sim`; Hugging Face Space `https://huggingface.co/spaces/jasondo111/Snap2Sim` (public submission Space; transfer to `build-small-hackathon/Snap2Sim` is pending if required).
138
+ - Credit line: "Built by Jason Do with implementation assistance from OpenAI Codex."
139
+ - End on the hook image/line for symmetry with slide 1.
140
+
141
+ ---
142
+
143
+ ## 3. Findings from the codebase review (source material — all verified in-repo)
144
+
145
+ Use these as the factual backbone. Do **not** invent metrics or claims beyond these.
146
+
147
+ - **Product**: Snap2Sim / "Inside the Machine" — photo of a hardware component → identified mechanism → animated 3D technical cutaway with named internal parts, trigger, and motion sequence. (`README.md`, `AGENTS.md`)
148
+ - **The hook** (keep verbatim, per AGENTS.md "Next Work" — do not alter): *"You find a small metal cylinder at a flea market. What is it? How does it work inside?"*
149
+ - **Audience**: garage tinkerers, repair hobbyists, thrift-store scavengers, robotics students — "people who learn by taking things apart." (`README.md` Hackathon Fit)
150
+ - **Pipeline** (`README.md` How It Works): browser → same-origin `/analyze_image` on the HF Space → secured Modal endpoint → Nemotron via llama.cpp/`llama-mtmd-cli` → structured mechanism JSON → `/generate_scene` validates + picks render mode → browser renders deterministic Three.js, or annotated-photo fallback.
151
+ - **Key safety/architecture decision**: "The model describes the mechanism. The browser owns the rendering." No model-authored HTML/JS injection. Schema validation in `snap2sim/schema.py` gates rendering. (`README.md`, `AGENTS.md`)
152
+ - **Renderer vocabulary** (`snap2sim/prompts.py`, `snap2sim/schema.py`): shapes = box, cylinder, cone, capsule, sphere, rod, gear, torus, spring; motions = static, rotate, oscillate, translate, screw, orbit, pulse; 2–6 parts per scene.
153
+ - **Honesty features**: confidence threshold slider (default 0.5), render-mode selection (`three` / `annotate` / `unavailable`), annotated-photo fallback with numbered markers + leader lines. (`docs/features/`)
154
+ - **Model**: `unsloth/NVIDIA-Nemotron-3-Nano-Omni-30B-A3B-Reasoning-GGUF`, quant `UD-Q4_K_M` + `mmproj-F16.gguf`. ~30B total / ~3B active per MoE token → under the hackathon's 32B budget. (`README.md` Tech Stack)
155
+ - **Infra**: HF Space on `cpu-basic`; GPU inference on Modal with Modal Volume asset caching; bearer-token auth between Space and Modal (secret `snap2sim-api-auth` / `SNAP2SIM_API_TOKEN`); unauthenticated requests return `401`. Space is public for submission. (`AGENTS.md`, `SECURITY.md`)
156
+ - **Security posture** (`docs/reviews/security-hardening.md`): rate limiting on both endpoints, upload-size caps, PIL decompression-bomb handling, temp-file cleanup, no model-authored scene HTML.
157
+ - **Badges** confirmed per AGENTS.md: Llama Champion, NVIDIA Nemotron Quest, Modal Award, Off-Brand, OpenAI Codex. Off the Grid is explicitly **not** claimed (Modal inference). Best Demo / Sharing is Caring pending public demo video + social post.
158
+ - **Visual identity tokens**: see Section 1 (sourced from `index.html`).
159
+ - **Credit**: Built by Jason Do with implementation assistance from OpenAI Codex. Commit trailer convention: `Co-authored-by: OpenAI Codex <codex@openai.com>`.
160
+
161
+ ### Marketing angles worth leaning into (for tone)
162
+ - The emotional payoff: "the moment a curious maker gets to **see the hidden motion**." (Pulled from README — this is the strongest line in the repo.)
163
+ - "Most image demos stop at a label. Snap2Sim answers the next question: *what would I see if I cut this open?*"
164
+ - The honesty differentiator: it shows uncertainty instead of hallucinating geometry. Judges reward this.
165
+
166
+ ---
167
+
168
+ ## 4. Next steps for Codex (in build order)
169
+
170
+ 1. Scaffold `presentation/deck.html` with reveal.js CDN, the theme tokens from Section 1, Chakra Petch + Fira Code fonts, grid/scan-line/vignette texture, and the per-slide kicker + watermark chrome.
171
+ 2. Build slides 1–3 exactly as specified (Problem → Solution → inline-SVG architecture diagram). These are the required core.
172
+ 3. Build the inline-SVG (or CDN-Mermaid-to-SVG) pipeline diagram for slide 3 from the flow in Section 2.
173
+ 4. Add slides 4–7.
174
+ 5. Keep the in-theme demo mockup on slide 4 unless real product screenshots are intentionally captured and added later.
175
+ 6. Verify: open in a browser, arrow through all slides, confirm the diagram renders inline with no broken images, confirm `?print-pdf` exports cleanly, confirm no horizontal overflow at 1280×720 and 1920×1080.
176
+ 7. Keep all private endpoint URLs and tokens **out** of the deck — only the public GitHub + HF Space links from Section 3.
177
+ 8. Do not claim Off the Grid. Do not mark Best Demo / Sharing is Caring as confirmed.
178
+
179
+ ### Open items / placeholders to flag in the deck
180
+ - Public demo video + social post link (needed before Best Demo / Sharing is Caring can be claimed).
181
+ - Space is public under `jasondo111/Snap2Sim`; org transfer remains pending if the submission process requires it.
README.md CHANGED
@@ -45,9 +45,9 @@ the pawl catching, the port opening.
45
  - App host: https://jasondo111-snap2sim.hf.space
46
  - Source of truth: https://github.com/Bigstonks1/Snap2Sim
47
 
48
- The Space is private until final submission approval. The app is built as a
49
- Gradio Space with a custom `gradio.Server` shell and can be made public from the
50
- same repository when ready.
51
 
52
  ## Hackathon Fit
53
 
@@ -122,11 +122,14 @@ question: "what would I see if I cut this open?"
122
 
123
  Recent local and deployed checks confirmed:
124
 
125
- - The private Space serves the trusted `index.html` shell.
126
  - `/analyze_image` returns validated mechanism payloads through the secured
127
  Modal bearer-token flow.
 
 
 
128
  - `/generate_scene` returns a deterministic Three.js scene descriptor, not raw
129
- HTML.
130
  - The renderer handles six-part scenes, axial orientation from geometry sizes,
131
  geometry-aware motion-axis fallback, fitted camera framing, orbit controls,
132
  reset view, mobile layout, and annotated-photo fallbacks.
@@ -178,6 +181,7 @@ $env:PYTHONIOENCODING="utf-8"; python -m modal run modal_app.py::run_runtime_pre
178
  - `app.py` - Gradio Server app, same-origin APIs, image validation, rate limits.
179
  - `index.html` - upload flow, analysis panel, Three.js renderer, fallback UI.
180
  - `modal_app.py` - Modal deployment, llama.cpp runtime, diagnostics.
 
181
  - `docs/` - implementation notes, review passes, and representative fixtures.
182
  - `snap2sim/backend.py` - backend selection and authenticated Modal client.
183
  - `snap2sim/prompts.py` - vision prompt contract.
 
45
  - App host: https://jasondo111-snap2sim.hf.space
46
  - Source of truth: https://github.com/Bigstonks1/Snap2Sim
47
 
48
+ The Space is public for submission. The app is built as a Gradio Space with a
49
+ custom `gradio.Server` shell; GitHub remains the source of truth for code
50
+ changes.
51
 
52
  ## Hackathon Fit
53
 
 
122
 
123
  Recent local and deployed checks confirmed:
124
 
125
+ - The public Space serves the trusted `index.html` shell.
126
  - `/analyze_image` returns validated mechanism payloads through the secured
127
  Modal bearer-token flow.
128
+ - A public smoke test on June 15, 2026 returned a real Modal analysis for a
129
+ synthetic target-like image as `rotary indexer` at `0.6` confidence with 3
130
+ parts.
131
  - `/generate_scene` returns a deterministic Three.js scene descriptor, not raw
132
+ HTML; a public smoke test returned `renderer: three`.
133
  - The renderer handles six-part scenes, axial orientation from geometry sizes,
134
  geometry-aware motion-axis fallback, fitted camera framing, orbit controls,
135
  reset view, mobile layout, and annotated-photo fallbacks.
 
181
  - `app.py` - Gradio Server app, same-origin APIs, image validation, rate limits.
182
  - `index.html` - upload flow, analysis panel, Three.js renderer, fallback UI.
183
  - `modal_app.py` - Modal deployment, llama.cpp runtime, diagnostics.
184
+ - `presentation/deck.html` - reveal.js judging deck for the hackathon pitch.
185
  - `docs/` - implementation notes, review passes, and representative fixtures.
186
  - `snap2sim/backend.py` - backend selection and authenticated Modal client.
187
  - `snap2sim/prompts.py` - vision prompt contract.
presentation/assets/.gitkeep ADDED
@@ -0,0 +1 @@
 
 
1
+
presentation/deck.html ADDED
@@ -0,0 +1,938 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Snap2Sim // Inside the Machine</title>
7
+ <link rel="icon" href="data:,">
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <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">
11
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/reset.css">
12
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/reveal.css">
13
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/theme/black.css" id="theme">
14
+ <style>
15
+ :root {
16
+ --bg: #0F1318;
17
+ --bg-panel: #161B22;
18
+ --bg-lift: #1E2530;
19
+ --amber: #E8A33D;
20
+ --cyan: #5FD4D0;
21
+ --text: #C8C0AC;
22
+ --text-muted: #9CA3AF;
23
+ --danger: #F07F5A;
24
+ --grid: rgba(255,255,255,0.04);
25
+ --line: rgba(95,212,208,0.34);
26
+ --amber-line: rgba(232,163,61,0.45);
27
+ }
28
+
29
+ html,
30
+ body {
31
+ background: var(--bg);
32
+ }
33
+
34
+ body::before,
35
+ body::after {
36
+ content: "";
37
+ position: fixed;
38
+ inset: 0;
39
+ pointer-events: none;
40
+ z-index: 1;
41
+ }
42
+
43
+ body::before {
44
+ background:
45
+ linear-gradient(var(--grid) 1px, transparent 1px),
46
+ linear-gradient(90deg, var(--grid) 1px, transparent 1px);
47
+ background-size: 32px 32px;
48
+ opacity: 0.9;
49
+ }
50
+
51
+ body::after {
52
+ background:
53
+ radial-gradient(circle at 50% 42%, transparent 48%, rgba(0,0,0,0.52)),
54
+ linear-gradient(90deg, rgba(0,0,0,0.2), transparent 22%, transparent 78%, rgba(0,0,0,0.24));
55
+ mix-blend-mode: multiply;
56
+ }
57
+
58
+ .reveal {
59
+ color: var(--text);
60
+ font-family: "Chakra Petch", "Aptos", sans-serif;
61
+ letter-spacing: 0;
62
+ }
63
+
64
+ .reveal .slides {
65
+ text-align: left;
66
+ }
67
+
68
+ .reveal .slides > section {
69
+ height: 100%;
70
+ max-height: 100%;
71
+ overflow: hidden;
72
+ min-height: 100%;
73
+ padding: 50px 56px 46px;
74
+ box-sizing: border-box;
75
+ }
76
+
77
+ .slide-grid {
78
+ display: grid;
79
+ gap: 24px;
80
+ height: 100%;
81
+ min-height: 0;
82
+ }
83
+
84
+ .two-col {
85
+ display: grid;
86
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
87
+ gap: 30px;
88
+ align-items: stretch;
89
+ }
90
+
91
+ .kicker {
92
+ position: absolute;
93
+ top: 26px;
94
+ left: 36px;
95
+ color: var(--amber);
96
+ font-family: "Fira Code", monospace;
97
+ font-size: 13px;
98
+ font-weight: 600;
99
+ letter-spacing: 0;
100
+ text-transform: uppercase;
101
+ }
102
+
103
+ .watermark {
104
+ position: absolute;
105
+ right: 34px;
106
+ bottom: 24px;
107
+ color: rgba(200,192,172,0.13);
108
+ font-family: "Fira Code", monospace;
109
+ font-size: 12px;
110
+ letter-spacing: 0;
111
+ text-transform: uppercase;
112
+ }
113
+
114
+ .section-rule {
115
+ height: 2px;
116
+ background: linear-gradient(90deg, transparent, var(--cyan), transparent);
117
+ box-shadow: 0 0 20px rgba(95,212,208,0.42);
118
+ }
119
+
120
+ h1,
121
+ h2,
122
+ h3 {
123
+ margin: 0;
124
+ color: var(--text);
125
+ font-family: "Chakra Petch", "Aptos Display", sans-serif;
126
+ font-weight: 700;
127
+ letter-spacing: 0;
128
+ text-transform: uppercase;
129
+ }
130
+
131
+ h1 {
132
+ max-width: 920px;
133
+ font-size: 54px;
134
+ line-height: 0.96;
135
+ }
136
+
137
+ h2 {
138
+ font-size: 38px;
139
+ line-height: 1.04;
140
+ }
141
+
142
+ h3 {
143
+ color: var(--cyan);
144
+ font-size: 22px;
145
+ line-height: 1.12;
146
+ }
147
+
148
+ .hook {
149
+ max-width: 960px;
150
+ color: var(--amber);
151
+ font-size: 52px;
152
+ font-weight: 700;
153
+ line-height: 1.02;
154
+ text-transform: none;
155
+ }
156
+
157
+ .positioning {
158
+ color: var(--amber);
159
+ font-size: 46px;
160
+ font-weight: 700;
161
+ line-height: 1;
162
+ text-transform: uppercase;
163
+ }
164
+
165
+ p {
166
+ margin: 0;
167
+ color: var(--text);
168
+ font-size: 20px;
169
+ line-height: 1.38;
170
+ }
171
+
172
+ strong {
173
+ color: var(--amber);
174
+ font-weight: 700;
175
+ }
176
+
177
+ em {
178
+ color: var(--cyan);
179
+ font-style: normal;
180
+ }
181
+
182
+ ul {
183
+ margin: 0;
184
+ padding: 0;
185
+ list-style: none;
186
+ }
187
+
188
+ li {
189
+ position: relative;
190
+ margin: 0 0 11px;
191
+ padding-left: 22px;
192
+ color: var(--text);
193
+ font-size: 19px;
194
+ line-height: 1.34;
195
+ }
196
+
197
+ li::before {
198
+ content: "";
199
+ position: absolute;
200
+ left: 0;
201
+ top: 0.58em;
202
+ width: 8px;
203
+ height: 8px;
204
+ border: 1px solid var(--cyan);
205
+ transform: rotate(45deg);
206
+ background: rgba(95,212,208,0.12);
207
+ }
208
+
209
+ .panel,
210
+ .card,
211
+ .chip,
212
+ .screen {
213
+ border: 1px solid var(--amber-line);
214
+ background: linear-gradient(180deg, rgba(30,37,48,0.92), rgba(22,27,34,0.96));
215
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 18px 60px rgba(0,0,0,0.22);
216
+ }
217
+
218
+ .panel {
219
+ padding: 22px;
220
+ }
221
+
222
+ .card {
223
+ padding: 18px;
224
+ }
225
+
226
+ .chip {
227
+ display: inline-grid;
228
+ place-items: center;
229
+ min-height: 34px;
230
+ padding: 0 12px;
231
+ color: var(--cyan);
232
+ font-family: "Fira Code", monospace;
233
+ font-size: 15px;
234
+ font-weight: 600;
235
+ text-transform: uppercase;
236
+ white-space: nowrap;
237
+ }
238
+
239
+ .chip.confirmed {
240
+ color: var(--amber);
241
+ border-color: var(--amber);
242
+ background: rgba(232,163,61,0.12);
243
+ }
244
+
245
+ .chip.pending {
246
+ color: var(--text-muted);
247
+ border-color: rgba(156,163,175,0.36);
248
+ background: rgba(156,163,175,0.08);
249
+ }
250
+
251
+ .pillars {
252
+ display: grid;
253
+ grid-template-columns: repeat(3, 1fr);
254
+ gap: 18px;
255
+ }
256
+
257
+ .pillar {
258
+ display: grid;
259
+ gap: 12px;
260
+ min-height: 138px;
261
+ }
262
+
263
+ .pillar p {
264
+ color: var(--text-muted);
265
+ font-size: 18px;
266
+ }
267
+
268
+ .mono {
269
+ font-family: "Fira Code", monospace;
270
+ }
271
+
272
+ .stat {
273
+ color: var(--amber);
274
+ font-family: "Fira Code", monospace;
275
+ font-size: 54px;
276
+ font-weight: 600;
277
+ line-height: 1;
278
+ }
279
+
280
+ .subtle {
281
+ color: var(--text-muted);
282
+ }
283
+
284
+ .caption {
285
+ color: var(--text-muted);
286
+ font-family: "Fira Code", monospace;
287
+ font-size: 13px;
288
+ line-height: 1.45;
289
+ }
290
+
291
+ .diagram-wrap {
292
+ display: grid;
293
+ grid-template-rows: minmax(0, 1fr) auto;
294
+ gap: 16px;
295
+ height: 100%;
296
+ min-height: 0;
297
+ }
298
+
299
+ .architecture {
300
+ width: 100%;
301
+ height: 100%;
302
+ min-height: 420px;
303
+ display: block;
304
+ }
305
+
306
+ .demo-grid {
307
+ display: grid;
308
+ grid-template-columns: 1.42fr 0.9fr;
309
+ gap: 22px;
310
+ align-items: stretch;
311
+ min-height: 0;
312
+ }
313
+
314
+ .screen {
315
+ position: relative;
316
+ overflow: hidden;
317
+ min-height: 0;
318
+ padding: 22px;
319
+ }
320
+
321
+ .screen::before {
322
+ content: "";
323
+ position: absolute;
324
+ inset: 0;
325
+ background:
326
+ linear-gradient(rgba(255,255,255,0.035) 1px, transparent 1px),
327
+ linear-gradient(90deg, rgba(255,255,255,0.035) 1px, transparent 1px);
328
+ background-size: 24px 24px;
329
+ pointer-events: none;
330
+ }
331
+
332
+ .mock-shell {
333
+ position: relative;
334
+ z-index: 1;
335
+ display: grid;
336
+ grid-template-columns: 1.5fr 0.82fr;
337
+ gap: 16px;
338
+ height: 100%;
339
+ }
340
+
341
+ .mock-viewport,
342
+ .mock-panel {
343
+ border: 1px solid rgba(95,212,208,0.28);
344
+ background: rgba(15,19,24,0.72);
345
+ }
346
+
347
+ .mock-viewport {
348
+ position: relative;
349
+ min-height: 0;
350
+ overflow: hidden;
351
+ }
352
+
353
+ .mock-viewport svg {
354
+ position: absolute;
355
+ inset: 18px;
356
+ width: calc(100% - 36px);
357
+ height: calc(100% - 36px);
358
+ }
359
+
360
+ .mock-panel {
361
+ display: grid;
362
+ grid-template-rows: auto auto 1fr;
363
+ gap: 12px;
364
+ padding: 16px;
365
+ }
366
+
367
+ .mock-title {
368
+ color: var(--cyan);
369
+ font-size: 22px;
370
+ font-weight: 700;
371
+ line-height: 1;
372
+ text-transform: uppercase;
373
+ }
374
+
375
+ .mock-line {
376
+ height: 9px;
377
+ background: rgba(200,192,172,0.2);
378
+ }
379
+
380
+ .compare {
381
+ display: grid;
382
+ gap: 14px;
383
+ }
384
+
385
+ .compare-row {
386
+ display: grid;
387
+ grid-template-columns: 0.86fr 1.14fr;
388
+ gap: 16px;
389
+ align-items: stretch;
390
+ }
391
+
392
+ .compare-row > div {
393
+ border: 1px solid rgba(95,212,208,0.22);
394
+ padding: 15px;
395
+ background: rgba(15,19,24,0.52);
396
+ }
397
+
398
+ .compare-row b {
399
+ display: block;
400
+ margin-bottom: 6px;
401
+ color: var(--amber);
402
+ font-size: 17px;
403
+ text-transform: uppercase;
404
+ }
405
+
406
+ .compare-row span {
407
+ color: var(--text);
408
+ font-size: 18px;
409
+ line-height: 1.25;
410
+ }
411
+
412
+ .stack-list {
413
+ display: grid;
414
+ gap: 11px;
415
+ }
416
+
417
+ .stack-list li {
418
+ margin: 0;
419
+ color: var(--text-muted);
420
+ font-family: "Fira Code", monospace;
421
+ font-size: 15px;
422
+ line-height: 1.35;
423
+ }
424
+
425
+ .badge-grid {
426
+ display: flex;
427
+ flex-wrap: wrap;
428
+ gap: 10px;
429
+ align-content: start;
430
+ }
431
+
432
+ .closing-links {
433
+ display: grid;
434
+ gap: 16px;
435
+ margin-top: 8px;
436
+ }
437
+
438
+ .link-row {
439
+ display: grid;
440
+ grid-template-columns: 160px minmax(0, 1fr);
441
+ gap: 16px;
442
+ align-items: baseline;
443
+ border-bottom: 1px solid rgba(95,212,208,0.2);
444
+ padding-bottom: 10px;
445
+ }
446
+
447
+ .link-row span {
448
+ color: var(--amber);
449
+ font-family: "Fira Code", monospace;
450
+ font-size: 14px;
451
+ text-transform: uppercase;
452
+ }
453
+
454
+ .link-row a,
455
+ .link-row p {
456
+ color: var(--cyan);
457
+ font-family: "Fira Code", monospace;
458
+ font-size: 16px;
459
+ line-height: 1.35;
460
+ text-decoration: none;
461
+ overflow-wrap: anywhere;
462
+ }
463
+
464
+ .reticle {
465
+ position: absolute;
466
+ right: 72px;
467
+ top: 92px;
468
+ width: 170px;
469
+ height: 170px;
470
+ border: 1px solid rgba(95,212,208,0.36);
471
+ border-radius: 50%;
472
+ opacity: 0.55;
473
+ }
474
+
475
+ .reticle::before,
476
+ .reticle::after {
477
+ content: "";
478
+ position: absolute;
479
+ background: rgba(95,212,208,0.42);
480
+ }
481
+
482
+ .reticle::before {
483
+ left: 50%;
484
+ top: -18px;
485
+ width: 1px;
486
+ height: calc(100% + 36px);
487
+ }
488
+
489
+ .reticle::after {
490
+ top: 50%;
491
+ left: -18px;
492
+ height: 1px;
493
+ width: calc(100% + 36px);
494
+ }
495
+
496
+ .scanline {
497
+ position: absolute;
498
+ left: 0;
499
+ right: 0;
500
+ top: 0;
501
+ height: 2px;
502
+ background: linear-gradient(90deg, transparent, var(--cyan), transparent);
503
+ opacity: 0.8;
504
+ animation: scan 7s ease-in-out infinite;
505
+ box-shadow: 0 0 18px rgba(95,212,208,0.72);
506
+ }
507
+
508
+ .reveal h1,
509
+ .reveal h2,
510
+ .reveal h3 {
511
+ margin: 0;
512
+ color: var(--text);
513
+ font-family: "Chakra Petch", "Aptos Display", sans-serif;
514
+ font-weight: 700;
515
+ letter-spacing: 0;
516
+ text-transform: uppercase;
517
+ text-shadow: none;
518
+ }
519
+
520
+ .reveal h1 {
521
+ max-width: 920px;
522
+ font-size: 54px;
523
+ line-height: 0.96;
524
+ }
525
+
526
+ .reveal h2 {
527
+ font-size: 38px;
528
+ line-height: 1.04;
529
+ }
530
+
531
+ .reveal h3 {
532
+ color: var(--cyan);
533
+ font-size: 22px;
534
+ line-height: 1.12;
535
+ }
536
+
537
+ .reveal p {
538
+ margin: 0;
539
+ color: var(--text);
540
+ font-size: 20px;
541
+ line-height: 1.38;
542
+ }
543
+
544
+ .reveal ul {
545
+ margin: 0;
546
+ padding: 0;
547
+ list-style: none;
548
+ }
549
+
550
+ .reveal li {
551
+ margin: 0 0 11px;
552
+ color: var(--text);
553
+ font-size: 19px;
554
+ line-height: 1.34;
555
+ }
556
+
557
+ .reveal .hook {
558
+ color: var(--amber);
559
+ font-size: 52px;
560
+ line-height: 1.02;
561
+ text-transform: none;
562
+ }
563
+
564
+ .reveal .positioning {
565
+ color: var(--amber);
566
+ font-size: 46px;
567
+ line-height: 1;
568
+ text-transform: uppercase;
569
+ }
570
+
571
+ @keyframes scan {
572
+ 0%, 22% { transform: translateY(0); opacity: 0; }
573
+ 28%, 58% { opacity: 1; }
574
+ 70%, 100% { transform: translateY(100vh); opacity: 0; }
575
+ }
576
+
577
+ @media (max-width: 900px) {
578
+ .reveal .slides > section {
579
+ padding: 48px 34px 48px;
580
+ }
581
+
582
+ .hook,
583
+ .positioning {
584
+ font-size: 40px;
585
+ }
586
+
587
+ h1 {
588
+ font-size: 42px;
589
+ }
590
+
591
+ h2 {
592
+ font-size: 34px;
593
+ }
594
+
595
+ p,
596
+ li {
597
+ font-size: 18px;
598
+ }
599
+
600
+ .two-col,
601
+ .demo-grid,
602
+ .mock-shell,
603
+ .compare-row {
604
+ grid-template-columns: 1fr;
605
+ }
606
+
607
+ .pillars {
608
+ grid-template-columns: 1fr;
609
+ }
610
+ }
611
+
612
+ @media print {
613
+ body::before,
614
+ body::after,
615
+ .scanline {
616
+ display: none;
617
+ }
618
+
619
+ .reveal .slides > section {
620
+ background: var(--bg) !important;
621
+ }
622
+ }
623
+ </style>
624
+ </head>
625
+ <body>
626
+ <div class="reveal">
627
+ <div class="slides">
628
+ <section data-transition="fade">
629
+ <div class="scanline" aria-hidden="true"></div>
630
+ <div class="reticle" aria-hidden="true"></div>
631
+ <div class="kicker">01 / THE PROBLEM</div>
632
+ <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div>
633
+ <div class="slide-grid" style="grid-template-rows: auto auto 1fr;">
634
+ <div class="hook">"You find a small metal cylinder at a flea market. What is it? How does it work inside?"</div>
635
+ <div class="section-rule"></div>
636
+ <ul>
637
+ <li>Curious makers, repair hobbyists, thrift scavengers, and robotics students constantly hold <strong>mystery hardware</strong> and cannot see what is happening inside.</li>
638
+ <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>
639
+ <li>Teardowns, manuals, and exploded diagrams are scattered, intimidating, or do not exist for that exact part.</li>
640
+ </ul>
641
+ </div>
642
+ <aside class="notes">
643
+ Open with the flea-market object. The point is not recognition; it is curiosity about hidden motion.
644
+ </aside>
645
+ </section>
646
+
647
+ <section data-transition="fade">
648
+ <div class="scanline" aria-hidden="true"></div>
649
+ <div class="kicker">02 / THE SOLUTION</div>
650
+ <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div>
651
+ <div class="slide-grid" style="grid-template-rows: auto auto auto 1fr;">
652
+ <div class="positioning">Snap a photo. Watch the mechanism come alive.</div>
653
+ <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>
654
+ <div class="pillars">
655
+ <div class="card pillar">
656
+ <span class="chip">[ identify ]</span>
657
+ <h3>Likely mechanism</h3>
658
+ <p>Confidence and mechanism type, not just a class name.</p>
659
+ </div>
660
+ <div class="card pillar">
661
+ <span class="chip">[ explain ]</span>
662
+ <h3>Plain-language motion</h3>
663
+ <p>Internal parts, trigger, and sequence: plunger, spring, rotor, pawl, port.</p>
664
+ </div>
665
+ <div class="card pillar">
666
+ <span class="chip">[ animate ]</span>
667
+ <h3>Orbit the cutaway</h3>
668
+ <p>Three.js field-manual view with orbit, zoom, reset, and play/pause.</p>
669
+ </div>
670
+ </div>
671
+ <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>
672
+ </div>
673
+ <aside class="notes">
674
+ Stress that the fallback is a feature, not a failure. The demo has a confidence threshold so uncertainty is visible and controllable.
675
+ </aside>
676
+ </section>
677
+
678
+ <section data-transition="fade">
679
+ <div class="kicker">03 / HOW IT WORKS</div>
680
+ <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div>
681
+ <div class="diagram-wrap">
682
+ <svg class="architecture" viewBox="0 0 1110 550" role="img" aria-labelledby="archTitle archDesc">
683
+ <title id="archTitle">Snap2Sim architecture flow</title>
684
+ <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>
685
+ <defs>
686
+ <filter id="glow" x="-30%" y="-30%" width="160%" height="160%">
687
+ <feGaussianBlur stdDeviation="3" result="coloredBlur"/>
688
+ <feMerge>
689
+ <feMergeNode in="coloredBlur"/>
690
+ <feMergeNode in="SourceGraphic"/>
691
+ </feMerge>
692
+ </filter>
693
+ <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
694
+ <path d="M 0 0 L 10 5 L 0 10 z" fill="#5FD4D0"/>
695
+ </marker>
696
+ </defs>
697
+ <rect x="6" y="6" width="1098" height="538" fill="rgba(15,19,24,0.58)" stroke="rgba(95,212,208,0.22)"/>
698
+ <g font-family="Fira Code, monospace" font-size="14" fill="#C8C0AC">
699
+ <g transform="translate(45 45)">
700
+ <rect width="210" height="78" rx="0" fill="#161B22" stroke="#E8A33D" stroke-width="2"/>
701
+ <text x="105" y="34" text-anchor="middle" fill="#E8A33D" font-weight="600">Photo upload</text>
702
+ <text x="105" y="56" text-anchor="middle" fill="#9CA3AF">component image</text>
703
+ </g>
704
+ <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)"/>
705
+ <text x="300" y="68" text-anchor="middle" fill="#5FD4D0" font-size="12">POST /analyze_image</text>
706
+
707
+ <g transform="translate(346 45)">
708
+ <rect width="250" height="78" fill="#161B22" stroke="#E8A33D" stroke-width="2"/>
709
+ <text x="125" y="30" text-anchor="middle" fill="#E8A33D" font-weight="600">Hugging Face Space</text>
710
+ <text x="125" y="52" text-anchor="middle" fill="#9CA3AF">gradio.Server / cpu-basic</text>
711
+ </g>
712
+ <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)"/>
713
+ <text x="640" y="68" text-anchor="middle" fill="#5FD4D0" font-size="12">bearer-token secret</text>
714
+
715
+ <g transform="translate(686 45)">
716
+ <rect width="210" height="78" fill="#161B22" stroke="#E8A33D" stroke-width="2"/>
717
+ <text x="105" y="30" text-anchor="middle" fill="#E8A33D" font-weight="600">Modal GPU endpoint</text>
718
+ <text x="105" y="52" text-anchor="middle" fill="#9CA3AF">llama.cpp + mtmd</text>
719
+ </g>
720
+
721
+ <path d="M 791 123 L 791 166" stroke="#5FD4D0" stroke-width="2.4" fill="none" marker-end="url(#arrow)" filter="url(#glow)"/>
722
+ <g transform="translate(626 166)">
723
+ <rect width="330" height="86" fill="#161B22" stroke="#E8A33D" stroke-width="2"/>
724
+ <text x="165" y="30" text-anchor="middle" fill="#E8A33D" font-weight="600">NVIDIA Nemotron 3 Nano Omni</text>
725
+ <text x="165" y="52" text-anchor="middle" fill="#9CA3AF">30B-A3B GGUF / UD-Q4_K_M</text>
726
+ <text x="165" y="72" text-anchor="middle" fill="#9CA3AF">mmproj-F16 returns JSON</text>
727
+ </g>
728
+
729
+ <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)"/>
730
+ <g transform="translate(246 166)">
731
+ <rect width="260" height="86" fill="#161B22" stroke="#E8A33D" stroke-width="2"/>
732
+ <text x="130" y="30" text-anchor="middle" fill="#E8A33D" font-weight="600">/generate_scene</text>
733
+ <text x="130" y="52" text-anchor="middle" fill="#9CA3AF">schema validation</text>
734
+ <text x="130" y="72" text-anchor="middle" fill="#9CA3AF">render-mode select</text>
735
+ </g>
736
+
737
+ <path d="M 376 252 L 376 314" stroke="#5FD4D0" stroke-width="2.4" fill="none" marker-end="url(#arrow)" filter="url(#glow)"/>
738
+ <g transform="translate(190 314)">
739
+ <rect width="372" height="92" fill="#161B22" stroke="#E8A33D" stroke-width="2"/>
740
+ <text x="186" y="34" text-anchor="middle" fill="#E8A33D" font-weight="600">Browser renders deterministic</text>
741
+ <text x="186" y="58" text-anchor="middle" fill="#9CA3AF">Three.js cutaway</text>
742
+ <text x="186" y="78" text-anchor="middle" fill="#9CA3AF">orbit / zoom / reset / play</text>
743
+ </g>
744
+
745
+ <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"/>
746
+ <text x="652" y="342" text-anchor="middle" fill="#5FD4D0" font-size="12">low confidence</text>
747
+ <g transform="translate(744 314)">
748
+ <rect width="250" height="92" fill="#161B22" stroke="rgba(156,163,175,0.65)" stroke-width="2"/>
749
+ <text x="125" y="35" text-anchor="middle" fill="#9CA3AF" font-weight="600">Annotated-photo</text>
750
+ <text x="125" y="59" text-anchor="middle" fill="#9CA3AF">fallback</text>
751
+ </g>
752
+
753
+ <g transform="translate(90 456)">
754
+ <rect width="930" height="42" fill="rgba(95,212,208,0.08)" stroke="rgba(95,212,208,0.28)"/>
755
+ <text x="465" y="27" text-anchor="middle" fill="#C8C0AC" font-size="16">
756
+ The model describes the mechanism. The browser owns the rendering.
757
+ </text>
758
+ </g>
759
+ </g>
760
+ </svg>
761
+ <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>
762
+ </div>
763
+ <aside class="notes">
764
+ The important architectural decision is separation of concerns: Modal and Nemotron infer the mechanism, while trusted browser code renders it deterministically.
765
+ </aside>
766
+ </section>
767
+
768
+ <section data-transition="fade">
769
+ <div class="kicker">04 / LIVE DEMO</div>
770
+ <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div>
771
+ <div class="slide-grid" style="grid-template-rows: auto 1fr;">
772
+ <h2>The moment: photo in, cutaway out.</h2>
773
+ <div class="demo-grid">
774
+ <div class="screen" aria-label="In-theme product demo mockup">
775
+ <div class="mock-shell">
776
+ <div class="mock-viewport">
777
+ <svg viewBox="0 0 440 300" aria-hidden="true">
778
+ <rect x="0" y="0" width="440" height="300" fill="rgba(15,19,24,0.35)"/>
779
+ <g stroke="#5FD4D0" stroke-width="2" fill="none" opacity="0.7">
780
+ <circle cx="218" cy="150" r="88"/>
781
+ <line x1="218" y1="32" x2="218" y2="268"/>
782
+ <line x1="100" y1="150" x2="336" y2="150"/>
783
+ </g>
784
+ <g transform="translate(112 76)">
785
+ <rect x="38" y="54" width="166" height="52" fill="#1E2530" stroke="#E8A33D" stroke-width="3"/>
786
+ <circle cx="77" cy="80" r="30" fill="rgba(95,212,208,0.22)" stroke="#5FD4D0" stroke-width="4"/>
787
+ <rect x="160" y="36" width="26" height="88" fill="rgba(232,163,61,0.24)" stroke="#E8A33D" stroke-width="3"/>
788
+ <path d="M 184 80 C 218 52 236 108 270 80" stroke="#F07F5A" stroke-width="5"/>
789
+ </g>
790
+ <text x="34" y="270" fill="#9CA3AF" font-family="Fira Code" font-size="12">Drag to orbit / scroll to zoom</text>
791
+ <text x="270" y="88" fill="#5FD4D0" font-family="Fira Code" font-size="13">spring preload</text>
792
+ <text x="246" y="210" fill="#5FD4D0" font-family="Fira Code" font-size="13">sliding plunger</text>
793
+ </svg>
794
+ </div>
795
+ <div class="mock-panel">
796
+ <div class="chip confirmed">CUTAWAY READY</div>
797
+ <div class="mock-title">Piston Mechanism</div>
798
+ <div class="mono subtle">confidence 85%</div>
799
+ <div class="mock-line" style="width: 92%;"></div>
800
+ <div class="mock-line" style="width: 74%;"></div>
801
+ <div class="mock-line" style="width: 86%;"></div>
802
+ <div class="mock-line" style="width: 62%; background: rgba(95,212,208,0.28);"></div>
803
+ </div>
804
+ </div>
805
+ </div>
806
+ <div class="panel">
807
+ <h3>Judges should feel the handoff.</h3>
808
+ <ul>
809
+ <li>Upload a mystery part photo.</li>
810
+ <li>Watch analysis become named parts and motion.</li>
811
+ <li>Orbit, zoom, reset, and play/pause the deterministic scene.</li>
812
+ <li>Move the confidence slider and see fallback behavior stay honest.</li>
813
+ </ul>
814
+ </div>
815
+ </div>
816
+ </div>
817
+ <aside class="notes">
818
+ Drop in a valve, lock, pump, gear train, fan, or latch.
819
+ </aside>
820
+ </section>
821
+
822
+ <section data-transition="fade">
823
+ <div class="kicker">05 / DIFFERENTIATION</div>
824
+ <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div>
825
+ <div class="slide-grid" style="grid-template-rows: auto auto 1fr;">
826
+ <h2>Most image demos stop at a label.</h2>
827
+ <p>Snap2Sim answers the maker's next question: <em>what would I see if I cut this open?</em></p>
828
+ <div class="compare">
829
+ <div class="compare-row">
830
+ <div><b>Typical image demo</b><span>"This is a valve."</span></div>
831
+ <div><b>Snap2Sim</b><span>Likely mechanism, internal parts, trigger, and motion sequence.</span></div>
832
+ </div>
833
+ <div class="compare-row">
834
+ <div><b>Static output</b><span>Caption, chat answer, or generic class label.</span></div>
835
+ <div><b>Moving cutaway</b><span>Maps parts into a technical field-manual scene with animation.</span></div>
836
+ </div>
837
+ <div class="compare-row">
838
+ <div><b>Overconfident</b><span>Looks plausible even when geometry is unsupported.</span></div>
839
+ <div><b>Honest uncertainty</b><span>Confidence threshold plus annotated-photo fallback.</span></div>
840
+ </div>
841
+ <div class="compare-row">
842
+ <div><b>Default app shell</b><span>Generic chat or form UI.</span></div>
843
+ <div><b>Branded maker tool</b><span>Cutaway aesthetic, same-origin client calls, server-side secrets.</span></div>
844
+ </div>
845
+ </div>
846
+ </div>
847
+ <aside class="notes">
848
+ This is the Off-Brand angle: it feels like a purpose-built instrument, not a wrapper around a model response.
849
+ </aside>
850
+ </section>
851
+
852
+ <section data-transition="fade">
853
+ <div class="kicker">06 / TECH STACK + HACKATHON FIT</div>
854
+ <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div>
855
+ <div class="two-col" style="height: 100%;">
856
+ <div class="panel">
857
+ <h3>Stack</h3>
858
+ <ul class="stack-list">
859
+ <li>Frontend: plain index.html + CSS + JS served by gradio.Server.</li>
860
+ <li>Rendering: deterministic Three.js primitives: box, cylinder, cone, capsule, sphere, rod, gear, torus, spring.</li>
861
+ <li>Controls: OrbitControls, camera fitting, reset view, confidence threshold, annotated-photo fallback.</li>
862
+ <li>Model: NVIDIA Nemotron 3 Nano Omni 30B-A3B GGUF, UD-Q4_K_M + mmproj-F16.</li>
863
+ <li>Budget: ~30B total / ~3B active per MoE token, under the 32B single-model budget.</li>
864
+ <li>GPU: Modal with weights cached in a Modal Volume and bearer-token protection.</li>
865
+ <li>Contract: JSON schema validation before anything renders.</li>
866
+ </ul>
867
+ </div>
868
+ <div class="panel">
869
+ <h3>Badges we are claiming</h3>
870
+ <div class="badge-grid" style="margin-top: 18px;">
871
+ <span class="chip confirmed">Backyard AI / core fit</span>
872
+ <span class="chip confirmed">Llama Champion</span>
873
+ <span class="chip confirmed">NVIDIA Nemotron Quest</span>
874
+ <span class="chip confirmed">Modal Award</span>
875
+ <span class="chip confirmed">Off-Brand</span>
876
+ <span class="chip confirmed">OpenAI Codex</span>
877
+ <span class="chip pending">Best Demo / pending video</span>
878
+ <span class="chip pending">Sharing is Caring / pending post</span>
879
+ <span class="chip pending">Off the Grid / not claimed</span>
880
+ </div>
881
+ <p class="caption" style="margin-top: 22px;">Inference currently runs on Modal, so Off the Grid is intentionally not claimed.</p>
882
+ </div>
883
+ </div>
884
+ <aside class="notes">
885
+ Keep this factual. The strongest credibility points are the real Modal/Nemotron path, schema gate, deterministic renderer, and honest fallback.
886
+ </aside>
887
+ </section>
888
+
889
+ <section data-transition="fade">
890
+ <div class="scanline" aria-hidden="true"></div>
891
+ <div class="reticle" aria-hidden="true"></div>
892
+ <div class="kicker">07 / CLOSE</div>
893
+ <div class="watermark">SNAP2SIM // INSIDE THE MACHINE</div>
894
+ <div class="slide-grid" style="grid-template-rows: auto auto 1fr auto;">
895
+ <h1>Snap a photo. See inside the machine.</h1>
896
+ <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>
897
+ <div class="panel closing-links">
898
+ <div class="link-row">
899
+ <span>GitHub</span>
900
+ <a href="https://github.com/Bigstonks1/Snap2Sim">https://github.com/Bigstonks1/Snap2Sim</a>
901
+ </div>
902
+ <div class="link-row">
903
+ <span>HF Space</span>
904
+ <p>https://huggingface.co/spaces/jasondo111/Snap2Sim<br><span class="subtle">Public submission Space; transfer to the Build Small org is still pending if required.</span></p>
905
+ </div>
906
+ <div class="link-row">
907
+ <span>Credit</span>
908
+ <p>Built by Jason Do with implementation assistance from OpenAI Codex.</p>
909
+ </div>
910
+ </div>
911
+ <p class="caption">Snap2Sim // Inside the Machine // Build Small Hackathon</p>
912
+ </div>
913
+ <aside class="notes">
914
+ End with the same hook. The product promise is short: snap a photo, see the hidden mechanism, and learn by looking inside.
915
+ </aside>
916
+ </section>
917
+ </div>
918
+ </div>
919
+
920
+ <script src="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/reveal.js"></script>
921
+ <script src="https://cdn.jsdelivr.net/npm/reveal.js@5/plugin/notes/notes.js"></script>
922
+ <script>
923
+ Reveal.initialize({
924
+ hash: true,
925
+ controls: true,
926
+ progress: true,
927
+ center: false,
928
+ slideNumber: "c/t",
929
+ transition: "fade",
930
+ backgroundTransition: "fade",
931
+ width: 1440,
932
+ height: 810,
933
+ margin: 0.06,
934
+ plugins: [RevealNotes]
935
+ });
936
+ </script>
937
+ </body>
938
+ </html>