orbit-card
by HeyGen · official repository
A single feature card orbits a dot sphere on approved Blender camera motion. HyperFrames block, 1920×1080, 10s, 4 variables.
OfficialRuns commands5 scripts
Labels from its files: runs commands. 13 files, read Oct 21, 2026. Nothing was run.
npx skills add https://github.com/heygen-com/hyperframes --skill orbit-cardWhat it lets an agent do
Each label, and the line in the skill's files that set it.
- Runs commands
Allows a shell or ships scripts the agent runs.
- It ships 5 scripts the agent can run.
Findings
Matches of fixed checks, with the text they matched.
No check matched anything in this skill's files.
Not a safety rating, and no finding is not a safety guarantee. These are fixed checks of the files as read on Oct 21, 2026. Nothing was run. How skills are checked.
SKILL.md
As the publisher wrote it. Shown as text, never rendered.
---
name: orbit-card
description: A single feature card orbits a dot sphere on approved Blender camera motion. HyperFrames block, 1920×1080, 10s, 4 variables.
---
# Orbit Card
One centred feature card with a circular cut-out framing a dot sphere. The card enters from the right (0.25–1.80 s), holds with a subtle bob and depth drift, orbits a full turn around the sphere's centre (smoothstep between 4.97 and 5.97 s), and exits left (7.35–8.55 s). The camera path and card F-curves are exported from the approved Blender rig at 30 fps and interpolated; the sphere keeps its own translation and a constant spin. Title, description, accent and the orbit angle are variables; 180° and 720° work without touching keys.
Composition id: `orbit-card`. Duration 10 s at 30 fps, 1920×1080.
## Files
- `orbit-card.html` (3 KB)
- `assets/Archivo-LICENSE.txt` (4 KB)
- `assets/Three-LICENSE.txt` (1 KB)
- `assets/archivo-regular.ttf` (108 KB)
- `assets/archivo-semibold.ttf` (109 KB)
- `assets/gsap-3.14.2.min.js` (128 KB)
- `assets/GSAP-NOTICE.txt` (1 KB)
- `assets/orbit-motion.js` (59 KB)
- `assets/orbit-scene.js` (8 KB)
- `assets/three.core.min.js` (554 KB)
- `assets/three.module.min.js` (468 KB)
## Install
Install with `npx hyperframes add orbit-card`; by default the files above land under `compositions/orbit-card/`. Then mount the block from the host `index.html`:
```html
<div
data-composition-id="orbit-card"
data-composition-src="compositions/orbit-card/orbit-card.html"
data-start="0"
data-duration="10"
data-track-index="1"
data-width="1920"
data-height="1080"
></div>
```
Render with custom values by targeting the composition file directly:
```sh
npx --yes hyperframes@0.8.12 render 'compositions/orbit-card/orbit-card.html' --variables '{"feature1Title":"Always in sync","feature1Desc":"Changes reach every screen the moment they happen."}'
```
## Variables
Read at runtime via `window.__hyperframes.getVariables()`; declared on the composition root as `data-composition-variables` (single-quoted attribute, plain JSON).
| id | type | default | label / range |
| ------------------ | ------ | ------------------------------------------------------ | -------------------------------------- |
| `feature1Title` | string | `"Always in sync"` | Card title max 28 chars |
| `feature1Desc` | string | `"Changes reach every screen the moment they happen."` | Card description max 110 chars |
| `feature1Accent` | color | `"#4cc9ff"` | Card accent |
| `cardOrbitDegrees` | number | `360` | Card orbit degrees -36000–36000 step 1 |
## Runtime contract
- One paused GSAP timeline registered as `window.__timelines["orbit-card"]`.
- Re-syncs on the `hf-seek` CustomEvent; every frame is a closed-form function of time (seeded PRNG only, no rAF loops, no Date.now).
- Renderer: GSAP.
- External runtime dependencies: none (served locally).
- Local fonts: assets/archivo-regular.ttf, assets/archivo-semibold.ttf.
## Editing rules (from the source project)
1. Keep `data-composition-variables` a single-quoted attribute with plain `"` JSON. Never save it through Studio's Design panel.
2. Do not put `<canvas>` in static markup; create it at runtime.
3. Keep every visual state a function of t; seek-safety is what makes the block renderable.
Scripts (2)
Read as text. anlyon.dev never runs them.
assets/orbit-motion.jsShowHide
// Approved Blender motion, frame 1 = 0 seconds; generated from the existing saved-rig export.
export const MOTION = {
fps: 30,
duration: 10,
frameStart: 1,
orbitFrames: [150, 180],
source: "orbit-card-motion-rig.blend",
cameraPositions: [
[-2.296356201171875, -16.33942222595215, 3.4000000953674316],
[-2.3544795513153076, -16.294174194335938, 3.3541200160980225],
[-2.4167428016662598, -16.2471923828125, 3.307447910308838],
[-2.4831795692443848, -16.198558807373047, 3.260138988494873],
[-2.553802490234375, -16.14834976196289, 3.2123301029205322],
[-2.6287219524383545, -16.09668731689453, 3.164271593093872],
[-2.7079529762268066, -16.043655395507812, 3.116119146347046],
[-2.791311025619507, -15.989262580871582, 3.0677871704101562],
[-2.878965139389038, -15.933662414550781, 3.0196213722229004],
[-2.970623254776001, -15.876802444458008, 2.9713850021362305],
[-3.066295623779297, -15.818763732910156, 2.9232170581817627],
[-3.1658143997192383, -15.75953483581543, 2.8750150203704834],
[-3.2689826488494873, -15.699081420898438, 2.826619863510132],
[-3.3756215572357178, -15.637365341186523, 2.7778806686401367],
[-3.4855005741119385, -15.574316024780273, 2.7285614013671875],
[-3.598336696624756, -15.509821891784668, 2.6783363819122314],
[-3.713792085647583, -15.44373893737793, 2.6267919540405273],
[-3.831458568572998, -15.37588119506836, 2.5734140872955322],
[-3.9508509635925293, -15.306032180786133, 2.517594814300537],
[-4.071385860443115, -15.233942985534668, 2.4586267471313477],
[-4.192359447479248, -15.159344673156738, 2.39570689201355],
[-4.312758445739746, -15.081888198852539, 2.327739715576172],
[-4.431484222412109, -15.00129508972168, 2.253708600997925],
[-4.547026634216309, -14.917274475097656, 2.172365188598633],
[-4.657764911651611, -14.829689979553223, 2.0826616287231445],
[-4.7612128257751465, -14.738431930541992, 1.9831593036651611],
[-4.8553948402404785, -14.643819808959961, 1.873386025428772],
[-4.938038349151611, -14.546354293823242, 1.7530319690704346],
[-5.007168769836426, -14.446808815002441, 1.6223820447921753],
[-5.061079502105713, -14.346155166625977, 1.482191801071167],
[-5.099876403808594, -14.245325088500977, 1.3340585231781006],
[-5.123626708984375, -14.145113945007324, 1.179348111152649],
[-5.134164810180664, -14.0462646484375, 1.0192029476165771],
[-5.137066841125488, -13.9500150680542, 0.8531267642974854],
[-5.133103370666504, -13.856842994689941, 0.6815893650054932],
[-5.121823310852051, -13.767148971557617, 0.5052593350410461],
[-5.1028594970703125, -13.681248664855957, 0.32488197088241577],
[-5.075922012329102, -13.59937858581543, 0.1412583887577057],
[-5.040799140930176, -13.521696090698242, -0.04476466402411461],
[-4.997351169586182, -13.448286056518555, -0.23231667280197144],
[-4.945509910583496, -13.37916374206543, -0.42050692439079285],
[-4.885269641876221, -13.314288139343262, -0.6084402799606323],
[-4.816690444946289, -13.253562927246094, -0.7952184677124023],
[-4.739887237548828, -13.196846961975098, -0.979955792427063],
[-4.655035972595215, -13.143963813781738, -1.1617716550827026],
[-4.562270641326904, -13.094741821289062, -1.339762568473816],
[-4.461907863616943, -13.04892635345459, -1.5130805969238281],
[-4.3543925285339355, -13.006229400634766, -1.6809507608413696],
[-4.240151882171631, -12.966384887695312, -1.842597484588623],
[-4.1196770668029785, -12.929119110107422, -1.997291922569275],
[-3.9935359954833984, -12.894159317016602, -2.1443538665771484],
[-3.8623690605163574, -12.861238479614258, -2.2831718921661377],
[-3.726898670196533, -12.830101013183594, -2.4132139682769775],
[-3.587920665740967, -12.800506591796875, -2.5340495109558105],
[-3.4463093280792236, -12.772237777709961, -2.6453657150268555],
[-3.3030052185058594, -12.745107650756836, -2.7469892501831055],
[-3.1588289737701416, -12.718964576721191, -2.8386199474334717],
[-3.014827251434326, -12.693676948547363, -2.9203414916992188],
[-2.8721818923950195, -12.669160842895508, -2.9926557540893555],
[-2.731796979904175, -12.645368576049805, -3.05574631690979],
[-2.5945355892181396, -12.622268676757812, -3.1097257137298584],
[-2.4615423679351807, -12.599906921386719, -3.1556997299194336],
[-2.3335649967193604, -12.578307151794434, -3.193892002105713],
[-2.211430311203003, -12.557536125183105, -3.224975109100342],
[-2.095973014831543, -12.537712097167969, -3.250009059906006],
[-1.9878480434417725, -12.518930435180664, -3.269618511199951],
[-1.8876709938049316, -12.50130844116211, -3.284496784210205],
[-1.796013355255127, -12.48497486114502, -3.2953977584838867],
[-1.7083287239074707, -12.46951961517334, -3.3032867908477783],
[-1.5956157445907593, -12.449946403503418, -3.311473846435547],
[-1.454040288925171, -12.4273042678833, -3.315826416015625],
[-1.2853654623031616, -12.40260124206543, -3.3140316009521484],
[-1.0915610790252686, -12.377933502197266, -3.3004915714263916],
[-0.8751382827758789, -12.354619026184082, -3.2721850872039795],
[-0.6397754549980164, -12.33553409576416, -3.221660614013672],
[-0.38979172706604004, -12.322421073913574, -3.145188093185425],
[-0.1305622011423111, -12.317288398742676, -3.0385022163391113],
[0.13212686777114868, -12.321534156799316, -2.899287700653076],
[0.3926160931587219, -12.335890769958496, -2.7270655632019043],
[0.6478863954544067, -12.359476089477539, -2.5253496170043945],
[0.8945276141166687, -12.39178466796875, -2.2963218688964844],
[1.132986068725586, -12.43087387084961, -2.0454039573669434],
[1.3627723455429077, -12.475435256958008, -1.7759804725646973],
[1.585869550704956, -12.52357292175293, -1.4927480220794678],
[1.8034486770629883, -12.57377815246582, -1.1990938186645508],
[2.017613172531128, -12.624470710754395, -0.8987165093421936],
[2.230046272277832, -12.67418098449707, -0.5947535634040833],
[2.4425511360168457, -12.721600532531738, -0.29036444425582886],
[2.656787395477295, -12.765281677246094, 0.01139821857213974],
[2.873889684677124, -12.804241180419922, 0.3076726198196411],
[3.0951762199401855, -12.83711051940918, 0.5953041315078735],
[3.321059465408325, -12.863075256347656, 0.8714796304702759],
[3.5514841079711914, -12.881449699401855, 1.1334623098373413],
[3.786051034927368, -12.891620635986328, 1.3784939050674438],
[4.023809432983398, -12.893182754516602, 1.603926420211792],
[4.2624969482421875, -12.886564254760742, 1.8082115650177002],
[4.499540328979492, -12.872371673583984, 1.9901739358901978],
[4.732144832611084, -12.851359367370605, 2.148940324783325],
[4.956848621368408, -12.824898719787598, 2.284851551055908],
[5.169670581817627, -12.795123100280762, 2.400050640106201],
[5.377266883850098, -12.765110969543457, 2.505131721496582],
[5.587342262268066, -12.737619400024414, 2.611464738845825],
[5.799549579620361, -12.712259292602539, 2.7185144424438477],
[6.013572692871094, -12.688591957092285, 2.8257412910461426],
[6.229104042053223, -12.666139602661133, 2.9325876235961914],
[6.445834159851074, -12.644391059875488, 3.0384795665740967],
[6.663467884063721, -12.622802734375, 3.142834424972534],
[6.881735324859619, -12.600772857666016, 3.244982957839966],
[7.100310802459717, -12.577674865722656, 3.344303607940674],
[7.318847179412842, -12.552898406982422, 3.4401886463165283],
[7.536980152130127, -12.525812149047852, 3.5319833755493164],
[7.754336833953857, -12.495664596557617, 3.618879556655884],
[7.970444679260254, -12.461793899536133, 3.7001748085021973],
[8.184738159179688, -12.423666954040527, 3.775266647338867],
[8.396600723266602, -12.38071346282959, 3.84346604347229],
[8.605324745178223, -12.332067489624023, 3.9037251472473145],
[8.81003475189209, -12.277645111083984, 3.955756187438965],
[9.00979995727539, -12.217201232910156, 3.9990360736846924],
[9.20359992980957, -12.15066909790039, 4.033168792724609],
[9.39029312133789, -12.077995300292969, 4.057697296142578],
[9.568824768066406, -11.999858856201172, 4.072905540466309],
[9.738216400146484, -11.917038917541504, 4.07917594909668],
[9.897623062133789, -11.830536842346191, 4.077136993408203],
[10.046424865722656, -11.741539001464844, 4.067673206329346],
[10.183948516845703, -11.651015281677246, 4.0514235496521],
[10.310334205627441, -11.560749053955078, 4.030130386352539],
[10.425529479980469, -11.471914291381836, 4.004863739013672],
[10.529668807983398, -11.385740280151367, 3.976818084716797],
[10.622894287109375, -11.303258895874023, 3.946998119354248],
[10.705809593200684, -11.225711822509766, 3.9167990684509277],
[10.778718948364258, -11.153974533081055, 3.8871383666992188],
[10.84199333190918, -11.088895797729492, 3.8589370250701904],
[10.896087646484375, -11.031275749206543, 3.833099126815796],
[10.94085693359375, -10.98157787322998, 3.809969902038574],
[10.979164123535156, -10.938003540039062, 3.789368152618408],
[11.023574829101562, -10.885120391845703, 3.7637500762939453],
[11.075085639953613, -10.820236206054688, 3.7315773963928223],
[11.132166862487793, -10.743227005004883, 3.692338228225708],
[11.192913055419922, -10.653932571411133, 3.6453466415405273],
[11.255414962768555, -10.552389144897461, 3.589982509613037],
[11.31764030456543, -10.438774108886719, 3.5256166458129883],
[11.377182006835938, -10.313423156738281, 3.4515042304992676],
[11.43161392211914, -10.176973342895508, 3.3669729232788086],
[11.478759765625, -10.03039836883545, 3.2715351581573486],
[11.516324996948242, -9.874969482421875, 3.164712429046631],
[11.54214859008789, -9.712302207946777, 3.0461251735687256],
[11.554464340209961, -9.544317245483398, 2.915590286254883],
[11.55190658569336, -9.373152732849121, 2.7730894088745117],
[11.533018112182617, -9.201324462890625, 2.618558883666992],
[11.497414588928223, -9.03122329711914, 2.4523301124572754],
[11.44424819946289, -8.865798950195312, 2.2745392322540283],
[11.373781204223633, -8.707618713378906, 2.0857112407684326],
[11.286213874816895, -8.559553146362305, 1.8863608837127686],
[11.182117462158203, -8.424473762512207, 1.6771615743637085],
[11.062405586242676, -8.305185317993164, 1.4589524269104004],
[10.928345680236816, -8.20437240600586, 1.2327861785888672],
[10.78152084350586, -8.124479293823242, 0.9999111294746399],
[10.62331771850586, -8.06200122833252, 0.7571786046028137],
[10.454304695129395, -8.013195991516113, 0.5017957091331482],
[10.274815559387207, -7.980984210968018, 0.23577143251895905],
[10.085182189941406, -7.968592643737793, -0.03837496042251587],
[9.886054992675781, -7.977306365966797, -0.31790611147880554],
[9.678144454956055, -8.007933616638184, -0.5999369621276855],
[9.461858749389648, -8.062294006347656, -0.8810098171234131],
[9.238161087036133, -8.13849925994873, -1.1585872173309326],
[9.007431030273438, -8.236916542053223, -1.4291603565216064],
[8.770506858825684, -8.354729652404785, -1.6906977891921997],
[8.52788257598877, -8.490181922912598, -1.9407424926757812],
[8.28005313873291, -8.640876770019531, -2.177196502685547],
[8.02773380279541, -8.803604125976562, -2.3990566730499268],
[7.771289825439453, -8.975980758666992, -2.6045193672180176],
[7.511535167694092, -9.15477180480957, -2.793243646621704],
[7.249129772186279, -9.33729362487793, -2.964431047439575],
[6.985007286071777, -9.520764350891113, -3.1179347038269043],
[6.720092296600342, -9.70267391204834, -3.253507614135742],
[6.4558210372924805, -9.880617141723633, -3.3718674182891846],
[6.193366050720215, -10.052496910095215, -3.4730451107025146],
[5.934305667877197, -10.216436386108398, -3.557809829711914],
[5.680482864379883, -10.370925903320312, -3.627352714538574],
[5.433744430541992, -10.514756202697754, -3.682826280593872],
[5.19606876373291, -10.647089004516602, -3.725665807723999],
[4.969182014465332, -10.76700496673584, -3.7566728591918945],
[4.755459785461426, -10.874608993530273, -3.778282642364502],
[4.55672550201416, -10.969650268554688, -3.791696548461914],
[4.375059127807617, -11.052543640136719, -3.7989487648010254],
[4.21217679977417, -11.12327766418457, -3.8011467456817627],
[4.069930076599121, -11.18238639831543, -3.7999958992004395],
[3.9198110103607178, -11.243413925170898, -3.794541120529175],
[3.7341485023498535, -11.318947792053223, -3.7809596061706543],
[3.516174077987671, -11.407697677612305, -3.7539079189300537],
[3.269444465637207, -11.508208274841309, -3.70941162109375],
[2.9984207153320312, -11.618635177612305, -3.640866756439209],
[2.7083797454833984, -11.736737251281738, -3.542534351348877],
[2.4049649238586426, -11.860060691833496, -3.4105005264282227],
[2.094017744064331, -11.986008644104004, -3.2423174381256104],
[1.7814030647277832, -12.111894607543945, -3.036903142929077],
[1.4715560674667358, -12.235579490661621, -2.7963626384735107],
[1.167121171951294, -12.355653762817383, -2.5249648094177246],
[0.8692965507507324, -12.471296310424805, -2.2279200553894043],
[0.5778228044509888, -12.58231258392334, -1.9111415147781372],
[0.2914241850376129, -12.688955307006836, -1.5806957483291626],
[0.008281180635094643, -12.791749000549316, -1.2425451278686523],
[-0.2736029028892517, -12.89134407043457, -0.9024065732955933],
[-0.5560566186904907, -12.98838996887207, -0.5657340288162231],
[-0.8404777646064758, -13.083450317382812, -0.23765991628170013],
[-1.127701759338379, -13.176929473876953, 0.07695219665765762],
[-1.4178755283355713, -13.269044876098633, 0.3735084533691406],
[-1.7096309661865234, -13.359687805175781, 0.6486383676528931],
[-2.00146484375, -13.448583602905273, 0.8987144231796265],
[-2.289924144744873, -13.53504753112793, 1.1222543716430664],
[-2.5715301036834717, -13.61829948425293, 1.3179045915603638],
[-2.8420968055725098, -13.697369575500488, 1.4854199886322021],
[-3.096914529800415, -13.771150588989258, 1.62583589553833],
[-3.330993175506592, -13.838454246520996, 1.7415523529052734],
[-3.542015314102173, -13.899024963378906, 1.8354686498641968],
[-3.746011257171631, -13.959517478942871, 1.9181013107299805],
[-3.9469733238220215, -14.021245956420898, 1.9925389289855957],
[-4.144732475280762, -14.08379077911377, 2.059140205383301],
[-4.339210510253906, -14.146828651428223, 2.1179308891296387],
[-4.530211448669434, -14.209796905517578, 2.1697659492492676],
[-4.717659950256348, -14.27229118347168, 2.2150368690490723],
[-4.901486396789551, -14.333873748779297, 2.254261016845703],
[-5.081610202789307, -14.394116401672363, 2.288259983062744],
[-5.258023262023926, -14.452645301818848, 2.317595958709717],
[-5.430734157562256, -14.509099960327148, 2.342877149581909],
[-5.599727630615234, -14.563201904296875, 2.364865779876709],
[-5.765032768249512, -14.614712715148926, 2.3841586112976074],
[-5.926675319671631, -14.663429260253906, 2.4013209342956543],
[-6.084688186645508, -14.709200859069824, 2.416877269744873],
[-6.239089012145996, -14.751919746398926, 2.431302070617676],
[-6.389901161193848, -14.791524887084961, 2.4450159072875977],
[-6.537127494812012, -14.8280029296875, 2.458375930786133],
[-6.680776596069336, -14.86138916015625, 2.471677303314209],
[-6.820830821990967, -14.89175796508789, 2.4851460456848145],
[-6.9572978019714355, -14.919233322143555, 2.49894380569458],
[-7.090181350708008, -14.943760871887207, 2.51326847076416],
[-7.219457149505615, -14.965599060058594, 2.528160810470581],
[-7.345133304595947, -14.984899520874023, 2.54365873336792],
[-7.467211723327637, -15.00169563293457, 2.5598535537719727],
[-7.585694313049316, -15.01624870300293, 2.576676845550537],
[-7.700594425201416, -15.028759002685547, 2.594069719314575],
[-7.811943531036377, -15.03915023803711, 2.6121625900268555],
[-7.919748306274414, -15.047807693481445, 2.6307311058044434],
[-8.024070739746094, -15.054852485656738, 2.649738311767578],
[-8.12493896484375, -15.060410499572754, 2.669131278991699],
[-8.222393989562988, -15.064600944519043, 2.688852310180664],
[-8.316493034362793, -15.067549705505371, 2.7088382244110107],
[-8.407295227050781, -15.069379806518555, 2.7290210723876953],
[-8.494860649108887, -15.070213317871094, 2.749329090118408],
[-8.579242706298828, -15.070167541503906, 2.7696824073791504],
[-8.660530090332031, -15.06936264038086, 2.790008544921875],
[-8.739532470703125, -15.067873001098633, 2.8102779388427734],
[-8.820507049560547, -15.06541633605957, 2.8314592838287354],
[-8.904031753540039, -15.061846733093262, 2.8535914421081543],
[-8.989941596984863, -15.05705738067627, 2.876662254333496],
[-9.078069686889648, -15.050947189331055, 2.9006574153900146],
[-9.168238639831543, -15.043427467346191, 2.9255552291870117],
[-9.260241508483887, -15.034221649169922, 2.9513797760009766],
[-9.35392951965332, -15.023399353027344, 2.978074312210083],
[-9.449127197265625, -15.010932922363281, 3.0056021213531494],
[-9.545620918273926, -14.996604919433594, 3.033968448638916],
[-9.643241882324219, -14.980398178100586, 3.0631351470947266],
[-9.741827964782715, -14.962392807006836, 3.0930399894714355],
[-9.841136932373047, -14.942333221435547, 3.123689651489258],
[-9.941080093383789, -14.920491218566895, 3.15498948097229],
[-10.04140853881836, -14.89664363861084, 3.186937093734741],
[-10.142021179199219, -14.871034622192383, 3.2194395065307617],
[-10.242735862731934, -14.84364128112793, 3.2524566650390625],
[-10.343405723571777, -14.814552307128906, 3.2859275341033936],
[-10.443941116333008, -14.783988952636719, 3.3197686672210693],
[-10.544161796569824, -14.751934051513672, 3.3539390563964844],
[-10.644013404846191, -14.718660354614258, 3.3883492946624756],
[-10.74338436126709, -14.684357643127441, 3.4229207038879395],
[-10.842159271240234, -14.649084091186523, 3.457606792449951],
[-10.940293312072754, -14.613149642944336, 3.492312431335449],
[-11.037701606750488, -14.5767183303833, 3.5269699096679688],
[-11.134292602539062, -14.53994369506836, 3.561514377593994],
[-11.23001766204834, -14.503074645996094, 3.5958659648895264],
[-11.324787139892578, -14.46625804901123, 3.629960536956787],
[-11.418539047241211, -14.429689407348633, 3.6637299060821533],
[-11.511194229125977, -14.393525123596191, 3.697110891342163],
[-11.602663040161133, -14.357925415039062, 3.730036973953247],
[-11.692855834960938, -14.323022842407227, 3.7624471187591553],
[-11.781673431396484, -14.288942337036133, 3.7942848205566406],
[-11.86902141571045, -14.255819320678711, 3.8254873752593994],
[-11.95477294921875, -14.223705291748047, 3.856009006500244],
[-12.038812637329102, -14.19271469116211, 3.885789394378662],
[-12.12102222442627, -14.16293716430664, 3.914773941040039],
[-12.201274871826172, -14.134380340576172, 3.942927360534668],
[-12.279417037963867, -14.107101440429688, 3.9701972007751465],
[-12.35531234741211, -14.081136703491211, 3.9965362548828125],
[-12.428826332092285, -14.056512832641602, 4.021905422210693],
[-12.499802589416504, -14.033251762390137, 4.046257972717285],
[-12.568099975585938, -14.011359214782715, 4.069556713104248],
[-12.633554458618164, -13.990837097167969, 4.091760635375977],
[-12.696022033691406, -13.971670150756836, 4.112835884094238],
[-12.75532341003418, -13.953842163085938, 4.132741928100586],… [40106 more characters not shown]assets/orbit-scene.jsShowHide
import * as THREE from "./three.module.min.js";
import { MOTION } from "./orbit-motion.js";
// Built per call from the variables the mounting module passes in: an imported
// module only sees the page's __hyperframes, not its composition's.
export function createOrbitScene(V) {
// Blender X/Y/Z -> Three X/Z/-Y. 100 original CSS pixels = one rig unit.
const number = (v, fallback) => (Number.isFinite(Number(v)) ? Number(v) : fallback);
const degrees = Math.max(-36000, Math.min(36000, number(V.cardOrbitDegrees, 360)));
const title = String(V.feature1Title || "Always in sync");
const description = String(
V.feature1Desc || "Changes reach every screen the moment they happen.",
);
const accent = /^#[0-9a-f]{6}$/i.test(V.feature1Accent) ? V.feature1Accent : "#4cc9ff";
const stage = document.getElementById("oc-stage");
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false });
renderer.setPixelRatio(1);
renderer.setSize(1920, 1080);
renderer.setClearColor("#161718");
renderer.outputColorSpace = THREE.SRGBColorSpace;
renderer.domElement.setAttribute(
"aria-label",
"Orbit Card: approved Blender camera and card animation",
);
stage.appendChild(renderer.domElement);
const scene = new THREE.Scene();
// Saved rig: 30 mm lens, 36 mm sensor, 1920 x 1080.
const camera = new THREE.PerspectiveCamera(
(2 * Math.atan(36 / (1920 / 1080) / 60) * 180) / Math.PI,
1920 / 1080,
0.1,
200,
);
scene.add(new THREE.HemisphereLight(0xffffff, 0x414753, 2.1));
const keyLight = new THREE.DirectionalLight(0xf0f5ff, 3.0);
keyLight.position.set(-5, 8, 8);
scene.add(keyLight);
const rimLight = new THREE.DirectionalLight(0x8fbad2, 2.0);
rimLight.position.set(5, 3, -5);
scene.add(rimLight);
const sourceRig = new THREE.Group();
sourceRig.name = "Card_Rig_EDIT_ME";
scene.add(sourceRig);
const orbitPivot = new THREE.Group();
orbitPivot.name = "Card_Orbit_EDIT_ME";
orbitPivot.position.set(0, 0.94, 0);
sourceRig.add(orbitPivot);
const card = new THREE.Group();
card.position.copy(orbitPivot.position).multiplyScalar(-1);
orbitPivot.add(card);
function roundedRect(w, h, r) {
const s = new THREE.Shape(),
x = -w / 2,
y = -h / 2;
s.moveTo(x + r, y);
s.lineTo(x + w - r, y);
s.quadraticCurveTo(x + w, y, x + w, y + r);
s.lineTo(x + w, y + h - r);
s.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
s.lineTo(x + r, y + h);
s.quadraticCurveTo(x, y + h, x, y + h - r);
s.lineTo(x, y + r);
s.quadraticCurveTo(x, y, x + r, y);
return s;
}
const shape = roundedRect(4.4, 5.4, 0.24);
const hole = new THREE.Path();
hole.absarc(0, 0.94, 1.08, 0, Math.PI * 2, true);
shape.holes.push(hole);
const plateGeometry = new THREE.ExtrudeGeometry(shape, {
depth: 0.16,
bevelEnabled: true,
bevelSize: 0.025,
bevelThickness: 0.02,
bevelSegments: 3,
steps: 1,
curveSegments: 64,
});
plateGeometry.translate(0, 0, -0.08);
const plate = new THREE.Mesh(
plateGeometry,
new THREE.MeshStandardMaterial({ color: "#16191d", metalness: 0.32, roughness: 0.38 }),
);
plate.name = "Orbit_Card";
card.add(plate);
const outlineMaterial = new THREE.LineBasicMaterial({
color: "#58616b",
transparent: true,
opacity: 0.45,
});
const outline = new THREE.LineLoop(
new THREE.BufferGeometry().setFromPoints(
shape.getPoints(96).map((p) => new THREE.Vector3(p.x, p.y, 0.103)),
),
outlineMaterial,
);
card.add(outline);
const apertureRim = new THREE.Mesh(
new THREE.TorusGeometry(1.08, 0.009, 6, 128),
new THREE.MeshBasicMaterial({ color: accent, transparent: true, opacity: 0.3 }),
);
apertureRim.position.set(0, 0.94, 0.103);
card.add(apertureRim);
// The aperture is open through the plate: no separate circular backplate.
const copyCanvas = document.createElement("canvas");
copyCanvas.width = 1440;
copyCanvas.height = 500;
const copyContext = copyCanvas.getContext("2d");
const copyTexture = new THREE.CanvasTexture(copyCanvas);
copyTexture.colorSpace = THREE.SRGBColorSpace;
copyTexture.anisotropy = Math.min(8, renderer.capabilities.getMaxAnisotropy());
const copy = new THREE.Mesh(
new THREE.PlaneGeometry(3.6, 1.25),
new THREE.MeshBasicMaterial({
map: copyTexture,
transparent: true,
side: THREE.FrontSide,
depthWrite: false,
}),
);
copy.position.set(0, -1.525, 0.106);
card.add(copy);
function paintCopy() {
const g = copyContext,
k = 4;
g.clearRect(0, 0, 1440, 500);
g.fillStyle = accent;
g.fillRect(0, 10, 30 * k, 3 * k);
g.fillStyle = "#f0f3f5";
g.font = "600 108px Archivo";
g.fillText(title, 0, 165, 1440);
g.fillStyle = "#a4a8ad";
g.font = "400 66px Archivo";
const words = description.split(/\s+/);
let line = "",
y = 305;
for (const word of words) {
if (g.measureText(line + word).width > 1420 && line) {
g.fillText(line.trim(), 0, y);
y += 99;
line = "";
}
line += word + " ";
}
g.fillText(line.trim(), 0, y);
copyTexture.needsUpdate = true;
}
paintCopy();
// A sibling branch of the orbit control: the sphere retains its own spin.
const sphereTilt = new THREE.Group();
sphereTilt.name = "Sphere_Tilt_FROM_SOURCE";
sphereTilt.position.set(0, 0.94, 0);
sphereTilt.rotation.x = -0.32;
sourceRig.add(sphereTilt);
const sphere = new THREE.Group();
sphere.name = "Dot_Sphere_Proxy";
sphereTilt.add(sphere);
const dotGeometry = new THREE.IcosahedronGeometry(0.012, 0);
const dotMaterial = new THREE.MeshStandardMaterial({
color: "#ecf0f4",
roughness: 0.45,
emissive: "#c4d5df",
emissiveIntensity: 0.18,
});
const dots = new THREE.InstancedMesh(dotGeometry, dotMaterial, 640);
const dummy = new THREE.Object3D();
const golden = Math.PI * (3 - Math.sqrt(5));
for (let i = 0; i < 640; i++) {
const y = 1 - (i / 639) * 2,
radius = Math.sqrt(Math.max(0, 1 - y * y)),
a = golden * i;
dummy.position.set(Math.cos(a) * radius, -y, Math.sin(a) * radius);
dummy.updateMatrix();
dots.setMatrixAt(i, dummy.matrix);
}
sphere.add(dots);
const clamp = (u) => Math.max(0, Math.min(1, u));
const smooth = (u) => u * u * (3 - 2 * u);
// Saved Blender F-curves: linear time handles, exact cubic value handles.
function channelAt(keys, frame) {
if (frame <= keys[0][0][0]) return keys[0][0][1];
for (let i = 1; i < keys.length; i++) {
const a = keys[i - 1],
b = keys[i];
if (frame <= b[0][0]) {
const u = (frame - a[0][0]) / (b[0][0] - a[0][0]),
v = 1 - u;
return a[3] === "LINEAR"
? a[0][1] * v + b[0][1] * u
: v ** 3 * a[0][1] + 3 * v * v * u * a[2][1] + 3 * v * u * u * b[1][1] + u ** 3 * b[0][1];
}
}
return keys[keys.length - 1][0][1];
}
// Camera positions are the saved rig's evaluated 30 fps export, not a new orbit.
function cameraAt(time) {
const f = Math.min(300, Math.max(0, time * 30)),
i = Math.min(299, Math.floor(f)),
u = f - i;
const a = MOTION.cameraPositions[i],
b = MOTION.cameraPositions[i + 1];
camera.position.set(
a[0] + (b[0] - a[0]) * u,
a[2] + (b[2] - a[2]) * u,
-a[1] - (b[1] - a[1]) * u,
);
const frame = 1 + time * 30;
let aim = MOTION.aimKeys.at(-1)[1];
for (let j = 1; j < MOTION.aimKeys.length; j++) {
const a = MOTION.aimKeys[j - 1],
b = MOTION.aimKeys[j];
if (frame <= b[0]) {
aim = THREE.MathUtils.lerp(a[1], b[1], smooth(clamp((frame - a[0]) / (b[0] - a[0]))));
break;
}
}
camera.lookAt(0, aim, 0);
}
const channels = MOTION.cardChannels;
let currentTime = 0;
function renderAt(time) {
currentTime = Math.max(0, Math.min(10, time));
const frame = 1 + currentTime * 30;
const values = channels.map((c) => channelAt(c.keys, frame));
sourceRig.position.set(values[0], values[2], -values[1]);
sourceRig.rotation.y = values[3];
orbitPivot.rotation.y = THREE.MathUtils.degToRad(degrees) * smooth(clamp((frame - 150) / 30));
sphere.rotation.y = currentTime * 0.5;
sphere.scale.setScalar(channelAt(MOTION.sphereScale, frame));
cameraAt(currentTime);
renderer.render(scene, camera);
}
renderAt(0);
document.fonts.ready.then(() => {
paintCopy();
renderAt(currentTime);
});
// Read-only inspection aid for the live workbench; no extra animation clock.
window.__orbitCardMotion = {
fps: 30,
duration: 10,
orbitFrames: [150, 180],
degrees,
get pose() {
const center = sphereTilt.getWorldPosition(new THREE.Vector3());
return {
frame: 1 + currentTime * 30,
camera: camera.position.toArray(),
cardOrbitDegrees: THREE.MathUtils.radToDeg(orbitPivot.rotation.y),
sphereCenter: center.toArray(),
sphereSpin: sphere.rotation.y,
};
},
};
return renderAt;
}
