cuju-render 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. cuju/render/__init__.py +759 -0
  2. cuju/render/__main__.py +1065 -0
  3. cuju/render/_export/__init__.py +3 -0
  4. cuju/render/_export/feed.py +542 -0
  5. cuju/render/_export/sizes.py +157 -0
  6. cuju/render/_export/video.py +1618 -0
  7. cuju/render/_export/video_jobs.py +408 -0
  8. cuju/render/_format/__init__.py +3 -0
  9. cuju/render/_format/annotations.py +235 -0
  10. cuju/render/_format/codec.py +307 -0
  11. cuju/render/_format/keep.py +121 -0
  12. cuju/render/_format/recording.py +860 -0
  13. cuju/render/_format/writer.py +54 -0
  14. cuju/render/_guide/__init__.py +3 -0
  15. cuju/render/_guide/doctor.py +523 -0
  16. cuju/render/_guide/help.py +62 -0
  17. cuju/render/_guide/tutorial.py +254 -0
  18. cuju/render/_http/__init__.py +3 -0
  19. cuju/render/_http/commands.py +57 -0
  20. cuju/render/_http/headers.py +103 -0
  21. cuju/render/_http/launch.py +500 -0
  22. cuju/render/_http/launchers.py +408 -0
  23. cuju/render/_http/pwa.py +128 -0
  24. cuju/render/_http/server.py +2105 -0
  25. cuju/render/_http/window.py +360 -0
  26. cuju/render/_moments/__init__.py +3 -0
  27. cuju/render/_moments/captions.py +284 -0
  28. cuju/render/_moments/events.py +1123 -0
  29. cuju/render/_moments/search.py +694 -0
  30. cuju/render/_packages/__init__.py +3 -0
  31. cuju/render/_packages/glsl.py +746 -0
  32. cuju/render/_packages/loudness.py +334 -0
  33. cuju/render/_packages/pack.py +1959 -0
  34. cuju/render/_packages/presentation.py +1376 -0
  35. cuju/render/_packages/vocabulary.py +609 -0
  36. cuju/render/_playing/__init__.py +3 -0
  37. cuju/render/_playing/achievements.py +463 -0
  38. cuju/render/_playing/bench.py +609 -0
  39. cuju/render/_playing/challenges.py +1813 -0
  40. cuju/render/_playing/demo.py +323 -0
  41. cuju/render/_playing/draw.py +211 -0
  42. cuju/render/_playing/errors.py +20 -0
  43. cuju/render/_playing/game.py +645 -0
  44. cuju/render/_playing/limits.py +339 -0
  45. cuju/render/_playing/play.py +926 -0
  46. cuju/render/_playing/policy_worker.py +250 -0
  47. cuju/render/_playing/strict.py +810 -0
  48. cuju/render/_registry/__init__.py +3 -0
  49. cuju/render/_registry/clips.py +394 -0
  50. cuju/render/_registry/joints.py +108 -0
  51. cuju/render/_registry/teams.py +2058 -0
  52. cuju/render/_store/__init__.py +3 -0
  53. cuju/render/_store/home.py +70 -0
  54. cuju/render/_store/library.py +604 -0
  55. cuju/render/_store/samples.py +163 -0
  56. cuju/render/_text/__init__.py +3 -0
  57. cuju/render/_text/languages.py +637 -0
  58. cuju/render/_text/messages.py +1396 -0
  59. cuju/render/_tournaments/__init__.py +3 -0
  60. cuju/render/_tournaments/results.py +547 -0
  61. cuju/render/_tournaments/tournament.py +2742 -0
  62. cuju/render/_tournaments/tournament_cli.py +587 -0
  63. cuju/render/_tournaments/tournament_runner.py +1975 -0
  64. cuju/render/_version.py +6 -0
  65. cuju/render/_watch/__init__.py +3 -0
  66. cuju/render/_watch/grid.py +265 -0
  67. cuju/render/_watch/live.py +664 -0
  68. cuju/render/_watch/notebook.py +79 -0
  69. cuju/render/_watch/show.py +171 -0
  70. cuju/render/samples/sample-11v11.cjr +0 -0
  71. cuju/render/samples/sample-5v5.cjr +0 -0
  72. cuju/render/samples/teams/starter/main.py +33 -0
  73. cuju/render/scenarios/benchmark_full_game_11_vs_11_easy.py +46 -0
  74. cuju/render/scenarios/benchmark_full_game_11_vs_11_hard.py +46 -0
  75. cuju/render/scenarios/benchmark_full_game_11_vs_11_medium.py +46 -0
  76. cuju/render/scenarios/benchmark_full_game_5_vs_5_easy.py +34 -0
  77. cuju/render/scenarios/benchmark_full_game_5_vs_5_hard.py +34 -0
  78. cuju/render/scenarios/benchmark_full_game_5_vs_5_medium.py +34 -0
  79. cuju/render/web/assets/adboard_polygon.webp +0 -0
  80. cuju/render/web/assets/adboard_your_ad_here.webp +0 -0
  81. cuju/render/web/assets/animations/kaykit-rig-medium-combatmelee.glb +0 -0
  82. cuju/render/web/assets/animations/kaykit-rig-medium-general.glb +0 -0
  83. cuju/render/web/assets/animations/kaykit-rig-medium-movementadvanced.glb +0 -0
  84. cuju/render/web/assets/animations/kaykit-rig-medium-movementbasic.glb +0 -0
  85. cuju/render/web/assets/animations/kaykit-rig-medium-simulation.glb +0 -0
  86. cuju/render/web/assets/animations/kaykit-rig-medium-special.glb +0 -0
  87. cuju/render/web/assets/ball.glb +0 -0
  88. cuju/render/web/assets/challenges/3_vs_1_with_keeper.mp4 +0 -0
  89. cuju/render/web/assets/challenges/3_vs_1_with_keeper.webp +0 -0
  90. cuju/render/web/assets/challenges/corner.mp4 +0 -0
  91. cuju/render/web/assets/challenges/corner.webp +0 -0
  92. cuju/render/web/assets/challenges/counterattack_easy.mp4 +0 -0
  93. cuju/render/web/assets/challenges/counterattack_easy.webp +0 -0
  94. cuju/render/web/assets/challenges/counterattack_hard.mp4 +0 -0
  95. cuju/render/web/assets/challenges/counterattack_hard.webp +0 -0
  96. cuju/render/web/assets/challenges/empty_goal.mp4 +0 -0
  97. cuju/render/web/assets/challenges/empty_goal.webp +0 -0
  98. cuju/render/web/assets/challenges/empty_goal_close.mp4 +0 -0
  99. cuju/render/web/assets/challenges/empty_goal_close.webp +0 -0
  100. cuju/render/web/assets/challenges/manifest.json +375 -0
  101. cuju/render/web/assets/challenges/one_on_one.mp4 +0 -0
  102. cuju/render/web/assets/challenges/one_on_one.webp +0 -0
  103. cuju/render/web/assets/challenges/one_on_one_hard.mp4 +0 -0
  104. cuju/render/web/assets/challenges/one_on_one_hard.webp +0 -0
  105. cuju/render/web/assets/challenges/pass_and_shoot_with_keeper.mp4 +0 -0
  106. cuju/render/web/assets/challenges/pass_and_shoot_with_keeper.webp +0 -0
  107. cuju/render/web/assets/challenges/run_pass_and_shoot_with_keeper.mp4 +0 -0
  108. cuju/render/web/assets/challenges/run_pass_and_shoot_with_keeper.webp +0 -0
  109. cuju/render/web/assets/challenges/run_to_score.mp4 +0 -0
  110. cuju/render/web/assets/challenges/run_to_score.webp +0 -0
  111. cuju/render/web/assets/challenges/run_to_score_with_keeper.mp4 +0 -0
  112. cuju/render/web/assets/challenges/run_to_score_with_keeper.webp +0 -0
  113. cuju/render/web/assets/challenges/single_goal_versus_lazy.mp4 +0 -0
  114. cuju/render/web/assets/challenges/single_goal_versus_lazy.webp +0 -0
  115. cuju/render/web/assets/crowd.webp +0 -0
  116. cuju/render/web/assets/crowd_normal.webp +0 -0
  117. cuju/render/web/assets/cuju-logo-384.png +0 -0
  118. cuju/render/web/assets/cuju-logo.png +0 -0
  119. cuju/render/web/assets/cuju-logo.svg +46 -0
  120. cuju/render/web/assets/cuju-mark-light.svg +33 -0
  121. cuju/render/web/assets/cuju-mark.svg +33 -0
  122. cuju/render/web/assets/goal.glb +0 -0
  123. cuju/render/web/assets/grass.webp +0 -0
  124. cuju/render/web/assets/hair_black.png +0 -0
  125. cuju/render/web/assets/hair_blonde.png +0 -0
  126. cuju/render/web/assets/hair_brown.png +0 -0
  127. cuju/render/web/assets/hair_darkblonde.png +0 -0
  128. cuju/render/web/assets/hair_long01.glb +0 -0
  129. cuju/render/web/assets/hair_long02.glb +0 -0
  130. cuju/render/web/assets/hair_medium01.glb +0 -0
  131. cuju/render/web/assets/hair_red.png +0 -0
  132. cuju/render/web/assets/hair_short01.glb +0 -0
  133. cuju/render/web/assets/hair_short02.glb +0 -0
  134. cuju/render/web/assets/icons/cuju-192.png +0 -0
  135. cuju/render/web/assets/icons/cuju-512.png +0 -0
  136. cuju/render/web/assets/icons/cuju-maskable-512.png +0 -0
  137. cuju/render/web/assets/kit_goalkeeper.webp +0 -0
  138. cuju/render/web/assets/kit_mask.png +0 -0
  139. cuju/render/web/assets/kit_normal.webp +0 -0
  140. cuju/render/web/assets/manifest.json +601 -0
  141. cuju/render/web/assets/models/kaykit-barbarian.glb +0 -0
  142. cuju/render/web/assets/models/kaykit-barbarian.json +23 -0
  143. cuju/render/web/assets/models/kaykit-knight.glb +0 -0
  144. cuju/render/web/assets/models/kaykit-knight.json +23 -0
  145. cuju/render/web/assets/models/kaykit-mage.glb +0 -0
  146. cuju/render/web/assets/models/kaykit-mage.json +23 -0
  147. cuju/render/web/assets/models/kaykit-mannequin-medium.glb +0 -0
  148. cuju/render/web/assets/models/kaykit-mannequin-medium.json +23 -0
  149. cuju/render/web/assets/models/kaykit-ranger.glb +0 -0
  150. cuju/render/web/assets/models/kaykit-ranger.json +23 -0
  151. cuju/render/web/assets/models/kaykit-rogue-hooded.glb +0 -0
  152. cuju/render/web/assets/models/kaykit-rogue-hooded.json +23 -0
  153. cuju/render/web/assets/models/kaykit-rogue.glb +0 -0
  154. cuju/render/web/assets/models/kaykit-rogue.json +23 -0
  155. cuju/render/web/assets/models/kaykit-skeleton-mage.glb +0 -0
  156. cuju/render/web/assets/models/kaykit-skeleton-mage.json +23 -0
  157. cuju/render/web/assets/models/kaykit-skeleton-minion.glb +0 -0
  158. cuju/render/web/assets/models/kaykit-skeleton-minion.json +23 -0
  159. cuju/render/web/assets/models/kaykit-skeleton-rogue.glb +0 -0
  160. cuju/render/web/assets/models/kaykit-skeleton-rogue.json +23 -0
  161. cuju/render/web/assets/models/kaykit-skeleton-warrior.glb +0 -0
  162. cuju/render/web/assets/models/kaykit-skeleton-warrior.json +23 -0
  163. cuju/render/web/assets/pitch.webp +0 -0
  164. cuju/render/web/assets/pitch_normal.webp +0 -0
  165. cuju/render/web/assets/player.glb +0 -0
  166. cuju/render/web/assets/shoe.webp +0 -0
  167. cuju/render/web/assets/shoe_sole.png +0 -0
  168. cuju/render/web/assets/skin_01.png +0 -0
  169. cuju/render/web/assets/skin_02.png +0 -0
  170. cuju/render/web/assets/skin_03.png +0 -0
  171. cuju/render/web/assets/skin_04.png +0 -0
  172. cuju/render/web/assets/sounds/applause.ogg +0 -0
  173. cuju/render/web/assets/sounds/beach-wave-1.ogg +0 -0
  174. cuju/render/web/assets/sounds/beach-wave-2.ogg +0 -0
  175. cuju/render/web/assets/sounds/beach-wave-3.ogg +0 -0
  176. cuju/render/web/assets/sounds/beach-wave-4.ogg +0 -0
  177. cuju/render/web/assets/sounds/city-horn.ogg +0 -0
  178. cuju/render/web/assets/sounds/city-loop.ogg +0 -0
  179. cuju/render/web/assets/sounds/city-siren.ogg +0 -0
  180. cuju/render/web/assets/sounds/crowd-cheer.ogg +0 -0
  181. cuju/render/web/assets/sounds/crowd-loop.ogg +0 -0
  182. cuju/render/web/assets/sounds/crowd-ooh.ogg +0 -0
  183. cuju/render/web/assets/sounds/gulls.ogg +0 -0
  184. cuju/render/web/assets/sounds/neon-sting.ogg +0 -0
  185. cuju/render/web/assets/sounds/rain-loop.ogg +0 -0
  186. cuju/render/web/assets/sounds/sounds.json +46 -0
  187. cuju/render/web/assets/sounds/space-beep.ogg +0 -0
  188. cuju/render/web/assets/sounds/space-hum.ogg +0 -0
  189. cuju/render/web/assets/sounds/space-radio.ogg +0 -0
  190. cuju/render/web/assets/sounds/whistle-long.ogg +0 -0
  191. cuju/render/web/assets/sounds/whistle-short.ogg +0 -0
  192. cuju/render/web/assets/sounds/wind-loop.ogg +0 -0
  193. cuju/render/web/easy.css +357 -0
  194. cuju/render/web/export.html +23 -0
  195. cuju/render/web/feed.css +262 -0
  196. cuju/render/web/feed.html +28 -0
  197. cuju/render/web/flat.css +120 -0
  198. cuju/render/web/home.css +837 -0
  199. cuju/render/web/index.html +373 -0
  200. cuju/render/web/js/boot.js +50 -0
  201. cuju/render/web/js/broadcast/audio.js +2141 -0
  202. cuju/render/web/js/broadcast/celebrate.js +1238 -0
  203. cuju/render/web/js/broadcast/decisions.js +609 -0
  204. cuju/render/web/js/broadcast/hud.js +352 -0
  205. cuju/render/web/js/broadcast/show.js +3614 -0
  206. cuju/render/web/js/broadcast/transition.js +2231 -0
  207. cuju/render/web/js/broadcast/voices.js +153 -0
  208. cuju/render/web/js/capture.js +101 -0
  209. cuju/render/web/js/core/accessibility.js +90 -0
  210. cuju/render/web/js/core/api.js +429 -0
  211. cuju/render/web/js/core/comfort.js +135 -0
  212. cuju/render/web/js/core/i18n.js +705 -0
  213. cuju/render/web/js/core/icons.js +167 -0
  214. cuju/render/web/js/core/input-settings.js +156 -0
  215. cuju/render/web/js/core/keys.js +277 -0
  216. cuju/render/web/js/core/language-ui.js +125 -0
  217. cuju/render/web/js/core/menu.js +853 -0
  218. cuju/render/web/js/core/names.js +113 -0
  219. cuju/render/web/js/core/page-structure.js +110 -0
  220. cuju/render/web/js/core/scenarios.js +109 -0
  221. cuju/render/web/js/core/spoilers.js +236 -0
  222. cuju/render/web/js/core/typeahead.js +38 -0
  223. cuju/render/web/js/export/dom-picture.js +330 -0
  224. cuju/render/web/js/export/export-host.js +97 -0
  225. cuju/render/web/js/export/feed-dialog.js +191 -0
  226. cuju/render/web/js/export/feed-params.js +266 -0
  227. cuju/render/web/js/export/feed.js +363 -0
  228. cuju/render/web/js/export/mp4-mux.js +295 -0
  229. cuju/render/web/js/export/photo-core.js +313 -0
  230. cuju/render/web/js/export/photo.js +1314 -0
  231. cuju/render/web/js/export/safe-frame.js +59 -0
  232. cuju/render/web/js/export/size-fields.js +103 -0
  233. cuju/render/web/js/export/sizes.js +178 -0
  234. cuju/render/web/js/export/video-boot.js +55 -0
  235. cuju/render/web/js/export/video-browser.js +325 -0
  236. cuju/render/web/js/export/video-export.js +417 -0
  237. cuju/render/web/js/export/video-plan.js +207 -0
  238. cuju/render/web/js/export/video-range.js +185 -0
  239. cuju/render/web/js/export/webm-mux.js +198 -0
  240. cuju/render/web/js/feed-boot.js +151 -0
  241. cuju/render/web/js/feed-frame.js +101 -0
  242. cuju/render/web/js/help/doctor.js +488 -0
  243. cuju/render/web/js/help/firstrun.js +379 -0
  244. cuju/render/web/js/help/help-center.js +438 -0
  245. cuju/render/web/js/help/install-offer.js +164 -0
  246. cuju/render/web/js/help/install-state.js +104 -0
  247. cuju/render/web/js/help/lessons-core.js +207 -0
  248. cuju/render/web/js/help/lessons.js +463 -0
  249. cuju/render/web/js/help/palette.js +584 -0
  250. cuju/render/web/js/help/pwa.js +257 -0
  251. cuju/render/web/js/help/tour-core.js +241 -0
  252. cuju/render/web/js/help/tour.js +461 -0
  253. cuju/render/web/js/main.js +2513 -0
  254. cuju/render/web/js/pages/draw.js +188 -0
  255. cuju/render/web/js/pages/fieldpage.js +530 -0
  256. cuju/render/web/js/pages/home.js +521 -0
  257. cuju/render/web/js/pages/matches.js +779 -0
  258. cuju/render/web/js/pages/moments-ui.js +359 -0
  259. cuju/render/web/js/pages/queue-filters.js +63 -0
  260. cuju/render/web/js/pages/recording-groups.js +80 -0
  261. cuju/render/web/js/pages/recordings.js +1069 -0
  262. cuju/render/web/js/play/bench.js +347 -0
  263. cuju/render/web/js/play/challenges.js +1302 -0
  264. cuju/render/web/js/play/medals.js +127 -0
  265. cuju/render/web/js/play/play.js +1953 -0
  266. cuju/render/web/js/play/teasers.js +196 -0
  267. cuju/render/web/js/play/touch.js +350 -0
  268. cuju/render/web/js/play/tournament-layout.js +487 -0
  269. cuju/render/web/js/play/tournament-results.js +441 -0
  270. cuju/render/web/js/play/tournament-strict.js +560 -0
  271. cuju/render/web/js/play/tournament.js +2585 -0
  272. cuju/render/web/js/players/animate.js +972 -0
  273. cuju/render/web/js/players/clips.js +224 -0
  274. cuju/render/web/js/players/kaykit.js +162 -0
  275. cuju/render/web/js/players/kits.js +676 -0
  276. cuju/render/web/js/players/number-patch.js +82 -0
  277. cuju/render/web/js/players/players.js +2694 -0
  278. cuju/render/web/js/players/recolor.js +893 -0
  279. cuju/render/web/js/players/retarget.js +325 -0
  280. cuju/render/web/js/players/rig-numbers.js +174 -0
  281. cuju/render/web/js/presentation/animator.js +231 -0
  282. cuju/render/web/js/presentation/assign.js +85 -0
  283. cuju/render/web/js/presentation/behaviors.js +440 -0
  284. cuju/render/web/js/presentation/budget.js +209 -0
  285. cuju/render/web/js/presentation/catalog.js +1674 -0
  286. cuju/render/web/js/presentation/clocks.js +72 -0
  287. cuju/render/web/js/presentation/commands.js +301 -0
  288. cuju/render/web/js/presentation/contract.js +240 -0
  289. cuju/render/web/js/presentation/effects.js +904 -0
  290. cuju/render/web/js/presentation/flash.js +605 -0
  291. cuju/render/web/js/presentation/freeze-worklet.js +22 -0
  292. cuju/render/web/js/presentation/glsl.js +464 -0
  293. cuju/render/web/js/presentation/host.js +323 -0
  294. cuju/render/web/js/presentation/index.js +2066 -0
  295. cuju/render/web/js/presentation/loudness-worklet.js +235 -0
  296. cuju/render/web/js/presentation/loudness.js +740 -0
  297. cuju/render/web/js/presentation/moments.js +536 -0
  298. cuju/render/web/js/presentation/post.js +327 -0
  299. cuju/render/web/js/presentation/preview.js +180 -0
  300. cuju/render/web/js/presentation/protocol.js +174 -0
  301. cuju/render/web/js/presentation/reach.js +158 -0
  302. cuju/render/web/js/presentation/rigging.js +130 -0
  303. cuju/render/web/js/presentation/sandbox.js +157 -0
  304. cuju/render/web/js/presentation/shaders.js +235 -0
  305. cuju/render/web/js/presentation/stage.js +402 -0
  306. cuju/render/web/js/presentation/teamaudio.js +722 -0
  307. cuju/render/web/js/presentation/tracks.js +197 -0
  308. cuju/render/web/js/presentation/values.js +81 -0
  309. cuju/render/web/js/recording/annotation-data.js +203 -0
  310. cuju/render/web/js/recording/captions.js +491 -0
  311. cuju/render/web/js/recording/codec.js +185 -0
  312. cuju/render/web/js/recording/decode-worker.js +70 -0
  313. cuju/render/web/js/recording/decode.js +94 -0
  314. cuju/render/web/js/recording/episodes.js +46 -0
  315. cuju/render/web/js/recording/format.js +461 -0
  316. cuju/render/web/js/recording/live.js +348 -0
  317. cuju/render/web/js/recording/moments-query.js +59 -0
  318. cuju/render/web/js/recording/moments.js +149 -0
  319. cuju/render/web/js/recording/pose.js +86 -0
  320. cuju/render/web/js/recording/timeline.js +275 -0
  321. cuju/render/web/js/teams/art.js +50 -0
  322. cuju/render/web/js/teams/clip-editor.js +293 -0
  323. cuju/render/web/js/teams/editor.js +1979 -0
  324. cuju/render/web/js/teams/library.js +344 -0
  325. cuju/render/web/js/teams/painter.js +633 -0
  326. cuju/render/web/js/teams/surprise-ui.js +195 -0
  327. cuju/render/web/js/teams/surprise.js +497 -0
  328. cuju/render/web/js/teams/team-check.js +127 -0
  329. cuju/render/web/js/watch/annotations.js +270 -0
  330. cuju/render/web/js/watch/flat.js +366 -0
  331. cuju/render/web/js/watch/grid.js +436 -0
  332. cuju/render/web/js/watch/pitch2d.js +289 -0
  333. cuju/render/web/js/watch/player-tools.js +192 -0
  334. cuju/render/web/js/watch/presets.js +201 -0
  335. cuju/render/web/js/world/arenas.js +997 -0
  336. cuju/render/web/js/world/ball.js +204 -0
  337. cuju/render/web/js/world/cameras.js +982 -0
  338. cuju/render/web/js/world/crowd.js +376 -0
  339. cuju/render/web/js/world/field.js +227 -0
  340. cuju/render/web/js/world/framing.js +145 -0
  341. cuju/render/web/js/world/occlusion.js +48 -0
  342. cuju/render/web/js/world/pitch.js +703 -0
  343. cuju/render/web/js/world/scene.js +395 -0
  344. cuju/render/web/js/world/sky.js +325 -0
  345. cuju/render/web/js/world/stadium.js +1262 -0
  346. cuju/render/web/js/world/vendor-sky.js +367 -0
  347. cuju/render/web/js/world/weather.js +264 -0
  348. cuju/render/web/languages/en.json +4750 -0
  349. cuju/render/web/lessons.json +137 -0
  350. cuju/render/web/manifest.webmanifest +23 -0
  351. cuju/render/web/style.css +8399 -0
  352. cuju/render/web/sw.js +235 -0
  353. cuju/render/web/vendor/fabric/LICENSE +16 -0
  354. cuju/render/web/vendor/fabric/fabric.min.mjs +1 -0
  355. cuju/render/web/vendor/lucide/LICENSE +43 -0
  356. cuju/render/web/vendor/lucide/icons.js +141 -0
  357. cuju/render/web/vendor/three/LICENSE +21 -0
  358. cuju/render/web/vendor/three/build/three.core.js +60586 -0
  359. cuju/render/web/vendor/three/build/three.module.js +19719 -0
  360. cuju/render/web/vendor/three/examples/jsm/loaders/GLTFLoader.js +4925 -0
  361. cuju/render/web/vendor/three/examples/jsm/postprocessing/EffectComposer.js +365 -0
  362. cuju/render/web/vendor/three/examples/jsm/postprocessing/MaskPass.js +195 -0
  363. cuju/render/web/vendor/three/examples/jsm/postprocessing/OutputPass.js +148 -0
  364. cuju/render/web/vendor/three/examples/jsm/postprocessing/Pass.js +191 -0
  365. cuju/render/web/vendor/three/examples/jsm/postprocessing/RenderPass.js +193 -0
  366. cuju/render/web/vendor/three/examples/jsm/postprocessing/ShaderPass.js +135 -0
  367. cuju/render/web/vendor/three/examples/jsm/postprocessing/UnrealBloomPass.js +541 -0
  368. cuju/render/web/vendor/three/examples/jsm/shaders/CopyShader.js +52 -0
  369. cuju/render/web/vendor/three/examples/jsm/shaders/LuminosityHighPassShader.js +68 -0
  370. cuju/render/web/vendor/three/examples/jsm/shaders/OutputShader.js +103 -0
  371. cuju/render/web/vendor/three/examples/jsm/utils/BufferGeometryUtils.js +1501 -0
  372. cuju/render/web/vendor/three/examples/jsm/utils/SkeletonUtils.js +496 -0
  373. cuju_render-0.1.0.dist-info/METADATA +116 -0
  374. cuju_render-0.1.0.dist-info/RECORD +382 -0
  375. cuju_render-0.1.0.dist-info/WHEEL +4 -0
  376. cuju_render-0.1.0.dist-info/licenses/LICENSE +202 -0
  377. cuju_render-0.1.0.dist-info/licenses/LICENSES/CC-BY-4.0.txt +396 -0
  378. cuju_render-0.1.0.dist-info/licenses/LICENSES/CC0-1.0.txt +127 -0
  379. cuju_render-0.1.0.dist-info/licenses/LICENSES/ISC.txt +16 -0
  380. cuju_render-0.1.0.dist-info/licenses/LICENSES/MIT.txt +24 -0
  381. cuju_render-0.1.0.dist-info/licenses/LICENSES/Unlicense.txt +13 -0
  382. cuju_render-0.1.0.dist-info/licenses/NOTICE +35 -0
@@ -0,0 +1,357 @@
1
+ /*
2
+ Copyright 2026 The cuju Authors
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ /* The parts that make the page easy to start with, the command palette, the presets of the
7
+ settings, the first run tips and hints, and the touch controls of Play and Watch. */
8
+
9
+ /* The command palette, a search field over a list, high on the page above everything else. */
10
+ #palette {
11
+ position: fixed;
12
+ inset: 0;
13
+ z-index: 80;
14
+ display: flex;
15
+ justify-content: center;
16
+ align-items: flex-start;
17
+ padding: max(48px, 12vh) 8px 8px;
18
+ background: var(--scrim);
19
+ }
20
+
21
+ #palette[hidden] {
22
+ display: none;
23
+ }
24
+
25
+ .palette-box {
26
+ display: flex;
27
+ flex-direction: column;
28
+ width: min(560px, 100%);
29
+ max-height: min(520px, 100%);
30
+ border: 1px solid var(--border);
31
+ border-top: 2px solid var(--accent);
32
+ background: var(--surface);
33
+ box-shadow: 0 12px 32px var(--shade, rgba(0, 0, 0, 0.45));
34
+ }
35
+
36
+ #palette-input {
37
+ flex: none;
38
+ margin: 10px;
39
+ padding: 8px 10px;
40
+ font-size: 16px;
41
+ }
42
+
43
+ #palette-list {
44
+ flex: 1;
45
+ min-height: 0;
46
+ margin: 0;
47
+ padding: 0 0 4px;
48
+ overflow-y: auto;
49
+ overscroll-behavior: contain;
50
+ list-style: none;
51
+ }
52
+
53
+ #palette-list [role="option"] {
54
+ display: grid;
55
+ grid-template-columns: minmax(0, 1fr) auto;
56
+ column-gap: 12px;
57
+ row-gap: 1px;
58
+ padding: 6px 14px;
59
+ border-left: 3px solid transparent;
60
+ cursor: pointer;
61
+ }
62
+
63
+ #palette-list [aria-selected="true"] {
64
+ border-left-color: var(--accent);
65
+ background: var(--surface-2);
66
+ }
67
+
68
+ #palette-list .palette-title,
69
+ #palette-list .palette-group {
70
+ grid-column: 1;
71
+ }
72
+
73
+ /* The shortcut of an action, at the right of its two lines. */
74
+ .palette-keys {
75
+ grid-column: 2;
76
+ grid-row: 1 / span 2;
77
+ align-self: center;
78
+ }
79
+
80
+ .palette-group,
81
+ .palette-count {
82
+ color: var(--muted);
83
+ font-size: 12px;
84
+ }
85
+
86
+ .palette-count {
87
+ flex: none;
88
+ margin: 0;
89
+ padding: 6px 14px 8px;
90
+ border-top: 1px solid var(--border);
91
+ }
92
+
93
+ /* The presets of the settings panel, three buttons in a row that read as one choice. */
94
+ .presets {
95
+ display: flex;
96
+ border: 1px solid var(--border);
97
+ }
98
+
99
+ .preset-btn {
100
+ flex: 1;
101
+ min-height: 32px;
102
+ padding: 4px 6px;
103
+ border: 0;
104
+ border-left: 1px solid var(--border);
105
+ background: transparent;
106
+ color: var(--text);
107
+ cursor: pointer;
108
+ }
109
+
110
+ .preset-btn:first-child {
111
+ border-left: 0;
112
+ }
113
+
114
+ .preset-btn[aria-checked="true"] {
115
+ background: var(--accent);
116
+ color: var(--on-accent);
117
+ }
118
+
119
+ .preset-btn[aria-disabled="true"] {
120
+ color: var(--muted);
121
+ cursor: default;
122
+ }
123
+
124
+ .preset-note {
125
+ margin: 0;
126
+ }
127
+
128
+ /* A tip of the first run, in the lower left corner, above the controls of Watch. */
129
+ .tip {
130
+ position: fixed;
131
+ left: 12px;
132
+ bottom: 12px;
133
+ z-index: 35;
134
+ width: min(320px, calc(100vw - 24px));
135
+ padding: 10px 12px;
136
+ border: 1px solid var(--border);
137
+ border-left: 3px solid var(--accent);
138
+ background: var(--surface);
139
+ box-shadow: 0 8px 24px var(--shade, rgba(0, 0, 0, 0.45));
140
+ }
141
+
142
+ .tip[hidden] {
143
+ display: none;
144
+ }
145
+
146
+ #app[data-page="watch"] .tip,
147
+ #app[data-page="play"] .tip {
148
+ bottom: 120px;
149
+ }
150
+
151
+ /* A tip that would cover a control of the page or a notice takes another corner. */
152
+ #app .tip[data-spot$="right"] {
153
+ left: auto;
154
+ right: 12px;
155
+ }
156
+
157
+ #app .tip[data-spot^="top"] {
158
+ top: calc(var(--bar, 46px) + 12px);
159
+ bottom: auto;
160
+ }
161
+
162
+ .tip-text {
163
+ margin: 0 0 8px;
164
+ }
165
+
166
+ .tip-actions {
167
+ display: flex;
168
+ align-items: center;
169
+ gap: 12px;
170
+ }
171
+
172
+ /* The line of help of a control, beside the control that has the focus or the pointer. */
173
+ .help-tip {
174
+ position: fixed;
175
+ z-index: 90;
176
+ max-width: min(280px, calc(100vw - 16px));
177
+ padding: 4px 8px;
178
+ border: 1px solid var(--border);
179
+ background: var(--surface-2);
180
+ color: var(--text);
181
+ font-size: 13px;
182
+ pointer-events: none;
183
+ }
184
+
185
+ .help-tip[hidden] {
186
+ display: none;
187
+ }
188
+
189
+ .empty-actions {
190
+ display: flex;
191
+ flex-wrap: wrap;
192
+ justify-content: center;
193
+ gap: 8px;
194
+ }
195
+
196
+ .teams-first {
197
+ margin: 12px 0 0;
198
+ padding: 12px;
199
+ }
200
+
201
+ #watch-empty .watch-next {
202
+ margin-top: 10px;
203
+ }
204
+
205
+ /* The touch pad of Play, a stick in the lower left corner and the buttons of GRF's layout in the
206
+ lower right, laid out as a controller's face buttons with sprint and dribble above them. */
207
+ .touch-pad {
208
+ position: absolute;
209
+ inset: 0;
210
+ z-index: 6;
211
+ pointer-events: none;
212
+ user-select: none;
213
+ -webkit-user-select: none;
214
+ -webkit-touch-callout: none;
215
+ }
216
+
217
+ .touch-pad[hidden] {
218
+ display: none;
219
+ }
220
+
221
+ .touch-stick,
222
+ .touch-btn,
223
+ .touch-pause {
224
+ pointer-events: auto;
225
+ touch-action: none;
226
+ }
227
+
228
+ .touch-stick {
229
+ position: absolute;
230
+ left: max(16px, env(safe-area-inset-left));
231
+ bottom: max(20px, env(safe-area-inset-bottom));
232
+ width: 140px;
233
+ height: 140px;
234
+ border: 2px solid rgba(255, 255, 255, 0.5);
235
+ border-radius: 50%;
236
+ background: rgba(0, 0, 0, 0.25);
237
+ }
238
+
239
+ .touch-knob {
240
+ position: absolute;
241
+ left: 50%;
242
+ top: 50%;
243
+ width: 60px;
244
+ height: 60px;
245
+ margin: -30px 0 0 -30px;
246
+ border-radius: 50%;
247
+ background: rgba(255, 255, 255, 0.55);
248
+ }
249
+
250
+ .touch-stick.held .touch-knob {
251
+ background: rgba(255, 255, 255, 0.8);
252
+ }
253
+
254
+ .touch-cluster {
255
+ position: absolute;
256
+ right: max(16px, env(safe-area-inset-right));
257
+ bottom: max(16px, env(safe-area-inset-bottom));
258
+ display: grid;
259
+ grid-template-columns: repeat(3, 60px);
260
+ grid-template-rows: repeat(4, 60px);
261
+ gap: 6px;
262
+ grid-template-areas:
263
+ "dribble . sprint"
264
+ ". long ."
265
+ "high . shot"
266
+ ". pass .";
267
+ }
268
+
269
+ .touch-btn {
270
+ width: 60px;
271
+ height: 60px;
272
+ padding: 0;
273
+ border: 2px solid rgba(255, 255, 255, 0.55);
274
+ border-radius: 50%;
275
+ background: rgba(0, 0, 0, 0.35);
276
+ color: #fff;
277
+ font-size: 12px;
278
+ cursor: pointer;
279
+ }
280
+
281
+ .touch-btn.held {
282
+ background: rgba(255, 255, 255, 0.45);
283
+ color: #000;
284
+ }
285
+
286
+ .touch-long_pass { grid-area: long; }
287
+ .touch-high_pass { grid-area: high; }
288
+ .touch-shot { grid-area: shot; }
289
+ .touch-short_pass { grid-area: pass; }
290
+ .touch-sprint { grid-area: sprint; border-radius: 12px; }
291
+ .touch-dribble { grid-area: dribble; border-radius: 12px; }
292
+
293
+ .touch-pause {
294
+ position: absolute;
295
+ left: 50%;
296
+ top: 12px;
297
+ min-width: 64px;
298
+ min-height: 40px;
299
+ transform: translateX(-50%);
300
+ border: 2px solid rgba(255, 255, 255, 0.55);
301
+ background: rgba(0, 0, 0, 0.35);
302
+ color: #fff;
303
+ }
304
+
305
+ /* On a touch screen, the controls of Watch and the bar above them take the size of a finger, and
306
+ the timeline gives the finger a taller strip to swipe along. */
307
+ @media (pointer: coarse) {
308
+ #app #controls .icon-btn,
309
+ #app #controls .text-btn,
310
+ #app #watch-bar .bar-btn {
311
+ min-width: 44px;
312
+ min-height: 44px;
313
+ }
314
+
315
+ #app #timeline {
316
+ height: 36px;
317
+ }
318
+
319
+ #app #timeline .track,
320
+ #app #timeline-fill {
321
+ top: 16px;
322
+ }
323
+
324
+ #app #timeline-thumb {
325
+ top: 9px;
326
+ height: 18px;
327
+ }
328
+
329
+ #app .marker {
330
+ top: 11px;
331
+ }
332
+ }
333
+
334
+ #app.touch #controls .icon-btn,
335
+ #app.touch #controls .text-btn,
336
+ #app.touch #watch-bar .bar-btn {
337
+ min-width: 44px;
338
+ min-height: 44px;
339
+ }
340
+
341
+ #app.touch #timeline {
342
+ height: 36px;
343
+ }
344
+
345
+ #app.touch #timeline .track,
346
+ #app.touch #timeline-fill {
347
+ top: 16px;
348
+ }
349
+
350
+ #app.touch #timeline-thumb {
351
+ top: 9px;
352
+ height: 18px;
353
+ }
354
+
355
+ #app.touch .marker {
356
+ top: 11px;
357
+ }
@@ -0,0 +1,23 @@
1
+ <!doctype html>
2
+ <!--
3
+ Copyright 2026 The cuju Authors
4
+ SPDX-License-Identifier: Apache-2.0
5
+
6
+ The page of the command cuju render video. A headless browser opens it, and the export of the
7
+ browser itself draws the recording in a frame of the Watch page and encodes it, see
8
+ js/export/export-host.js.
9
+ -->
10
+ <html lang="en-US">
11
+ <head>
12
+ <meta charset="utf-8">
13
+ <meta name="viewport" content="width=device-width, initial-scale=1">
14
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src 'self' data: blob:; connect-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self'; frame-src 'self'; object-src 'none'; base-uri 'self'; form-action 'none'">
15
+ <title>Cuju</title>
16
+ <style>
17
+ html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; background: #000; color-scheme: dark; }
18
+ </style>
19
+ <script type="module" src="js/export/export-host.js"></script>
20
+ </head>
21
+ <body>
22
+ </body>
23
+ </html>
@@ -0,0 +1,262 @@
1
+ /*
2
+ Copyright 2026 The cuju Authors
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ /* A picture of fixed size, the clean feed and the video export. js/export/safe-frame.js marks the app as
7
+ framed, sets the margins of the safe area as --safe-top, --safe-right, --safe-bottom and
8
+ --safe-left, and names the shape of the picture as shape-wide, shape-square or shape-tall. The
9
+ graphics then keep inside the safe area at every size and shape. */
10
+
11
+ #app.framed[data-page] #scoreboard {
12
+ top: var(--safe-top);
13
+ left: var(--safe-left);
14
+ max-width: calc(100% - var(--safe-left) - var(--safe-right));
15
+ }
16
+
17
+ #app.framed[data-page] #mode-banner {
18
+ top: calc(var(--safe-top) + 44px);
19
+ max-width: calc(100% - var(--safe-left) - var(--safe-right));
20
+ }
21
+
22
+ #app.framed[data-page] #replay-badge {
23
+ top: var(--safe-top);
24
+ right: var(--safe-right);
25
+ }
26
+
27
+ #app.framed[data-page] #goal-banner,
28
+ #app.framed[data-page] #follow-label {
29
+ left: var(--safe-left);
30
+ bottom: var(--safe-bottom);
31
+ max-width: calc(100% - var(--safe-left) - var(--safe-right));
32
+ }
33
+
34
+ #app.framed[data-page] .captions {
35
+ left: var(--safe-left);
36
+ right: var(--safe-right);
37
+ bottom: calc(var(--safe-bottom) + 56px);
38
+ }
39
+
40
+ #app.framed[data-page] .decision-banner,
41
+ #app.framed[data-page] .card-third {
42
+ left: var(--safe-left);
43
+ bottom: calc(var(--safe-bottom) + 10px);
44
+ max-width: calc(100% - var(--safe-left) - var(--safe-right));
45
+ }
46
+
47
+ #app.framed[data-page] .title-card {
48
+ padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left);
49
+ box-sizing: border-box;
50
+ }
51
+
52
+ #app.framed[data-page] .tc-inner {
53
+ box-sizing: border-box;
54
+ min-width: min(720px, 100%);
55
+ max-width: 100%;
56
+ }
57
+
58
+ /* The team sheets take the band under the scoreboard and the banner of the kick off, centered
59
+ in it, so they cover neither at any shape. */
60
+ #app.framed[data-page] #lineups {
61
+ --lineups-top: calc(var(--safe-top) + 80px);
62
+ box-sizing: border-box;
63
+ top: var(--lineups-top);
64
+ bottom: var(--safe-bottom);
65
+ width: min(860px, calc(100% - var(--safe-left) - var(--safe-right)));
66
+ height: fit-content;
67
+ max-height: calc(100% - var(--lineups-top) - var(--safe-bottom));
68
+ margin: auto 0;
69
+ transform: translateX(-50%);
70
+ animation-name: lineups-in-framed;
71
+ }
72
+
73
+ @keyframes lineups-in-framed {
74
+ from {
75
+ opacity: 0;
76
+ transform: translate(-50%, 4%);
77
+ }
78
+ to {
79
+ opacity: 1;
80
+ transform: translateX(-50%);
81
+ }
82
+ }
83
+
84
+ #app.framed.shape-tall[data-page] #lineups,
85
+ #app.framed.shape-square[data-page] #lineups {
86
+ --lineups-top: calc(var(--safe-top) + 124px);
87
+ }
88
+
89
+ /* A square or tall picture keeps the badge of a replay under the scoreboard, which takes most of
90
+ the width, and gives the lower thirds the whole width of the safe area. */
91
+ #app.framed.shape-tall[data-page] #scoreboard,
92
+ #app.framed.shape-square[data-page] #scoreboard {
93
+ right: var(--safe-right);
94
+ }
95
+
96
+ /* There each team takes half of what the scores and the clock leave, its name beside its chip. */
97
+ #app.framed.shape-tall[data-page] #scoreboard .team,
98
+ #app.framed.shape-square[data-page] #scoreboard .team {
99
+ flex: 1 1 0;
100
+ min-width: 0;
101
+ max-width: none;
102
+ }
103
+
104
+ #app.framed.shape-tall[data-page] #scoreboard .name,
105
+ #app.framed.shape-square[data-page] #scoreboard .name {
106
+ flex: 1 1 auto;
107
+ }
108
+
109
+ #app.framed.shape-tall[data-page] #scoreboard .team.right .name,
110
+ #app.framed.shape-square[data-page] #scoreboard .team.right .name {
111
+ text-align: right;
112
+ }
113
+
114
+ #app.framed.shape-tall[data-page] #replay-badge,
115
+ #app.framed.shape-square[data-page] #replay-badge {
116
+ top: calc(var(--safe-top) + 44px);
117
+ }
118
+
119
+ #app.framed.shape-tall[data-page] #mode-banner,
120
+ #app.framed.shape-square[data-page] #mode-banner {
121
+ top: calc(var(--safe-top) + 88px);
122
+ }
123
+
124
+ #app.framed.shape-tall[data-page] #goal-banner,
125
+ #app.framed.shape-tall[data-page] #follow-label,
126
+ #app.framed.shape-tall[data-page] .decision-banner,
127
+ #app.framed.shape-tall[data-page] .card-third {
128
+ right: var(--safe-right);
129
+ min-width: 0;
130
+ }
131
+
132
+ /* The clean feed shows the picture and its broadcast graphics alone, with no pointer, no
133
+ controls, no messages and no buttons, over the background that its address names. */
134
+
135
+ html.cuju-feed,
136
+ html.cuju-feed body {
137
+ background: var(--feed-background, #000);
138
+ cursor: none;
139
+ }
140
+
141
+ html.cuju-feed #app,
142
+ html.cuju-feed #pages,
143
+ html.cuju-feed #page-watch,
144
+ html.cuju-feed #watch {
145
+ background: transparent;
146
+ }
147
+
148
+ html.cuju-feed #app {
149
+ pointer-events: none;
150
+ cursor: none;
151
+ user-select: none;
152
+ }
153
+
154
+ html.cuju-feed .skip-link,
155
+ html.cuju-feed #topbar,
156
+ html.cuju-feed #watch-bar,
157
+ html.cuju-feed #controls,
158
+ html.cuju-feed #watch-empty,
159
+ html.cuju-feed #drop-hint,
160
+ html.cuju-feed #toast,
161
+ html.cuju-feed #tv-hint,
162
+ html.cuju-feed #loading,
163
+ html.cuju-feed #waiting,
164
+ html.cuju-feed #fatal,
165
+ html.cuju-feed #settings,
166
+ html.cuju-feed #match-menu,
167
+ html.cuju-feed #view-menu,
168
+ html.cuju-feed #tip,
169
+ html.cuju-feed #help-tip,
170
+ html.cuju-feed #flat-suggest,
171
+ html.cuju-feed .touch-pad,
172
+ html.cuju-feed .player-labels,
173
+ html.cuju-feed dialog,
174
+ html.cuju-feed #watch button,
175
+ html.cuju-feed .post-hint,
176
+ html.cuju-feed #cuju-home-veil {
177
+ display: none !important;
178
+ }
179
+
180
+ html.cuju-feed.feed-no-score #scoreboard {
181
+ display: none !important;
182
+ }
183
+
184
+ /* While nothing shows, and in a feed of the graphics alone, the background takes the picture's
185
+ place. */
186
+ html.cuju-feed #app.no-source #stage,
187
+ html.cuju-feed #app.feed-idle #stage,
188
+ html.cuju-feed #app.feed-idle #hud,
189
+ html.cuju-feed[data-feed-layer="graphics"] #stage,
190
+ html.cuju-feed[data-feed-layer="graphics"] #flat-view {
191
+ visibility: hidden;
192
+ }
193
+
194
+ #feed-slate {
195
+ position: absolute;
196
+ inset: 0;
197
+ z-index: 30;
198
+ display: flex;
199
+ flex-direction: column;
200
+ align-items: center;
201
+ justify-content: center;
202
+ gap: 14px;
203
+ padding: var(--safe-top, 5%) var(--safe-right, 5%) var(--safe-bottom, 5%) var(--safe-left, 5%);
204
+ color: #f4f4f4;
205
+ font: 600 20px/1.3 var(--broadcast-font, var(--font));
206
+ letter-spacing: 0.02em;
207
+ text-align: center;
208
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
209
+ opacity: 0;
210
+ visibility: hidden;
211
+ transition: opacity 0.6s, visibility 0s linear 0.6s;
212
+ }
213
+
214
+ #feed-slate.show {
215
+ opacity: 1;
216
+ visibility: visible;
217
+ transition: opacity 0.6s;
218
+ }
219
+
220
+ /* The slate's bare mark lies over whatever the stream puts behind the feed, as its light words do,
221
+ so it takes their shadow and an outline that keeps it on a light picture. */
222
+ #feed-slate img {
223
+ width: 68px;
224
+ height: 68px;
225
+ filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.85)) drop-shadow(0 1px 3px rgba(0, 0, 0, 0.6));
226
+ }
227
+
228
+ /* The Copy feed address dialog of the Watch page. */
229
+ dialog.feed-address {
230
+ width: min(600px, calc(100% - 24px));
231
+ max-height: calc(100% - 24px);
232
+ padding: 16px 20px;
233
+ border: 1px solid var(--border);
234
+ background: var(--surface);
235
+ color: var(--text);
236
+ }
237
+
238
+ dialog.feed-address::backdrop {
239
+ background: rgba(0, 0, 0, 0.6);
240
+ }
241
+
242
+ dialog.feed-address #fa-url {
243
+ box-sizing: border-box;
244
+ width: 100%;
245
+ font-family: var(--mono, monospace);
246
+ font-size: 13px;
247
+ }
248
+
249
+ /* The fields of a custom size in the dialogs that take a size. */
250
+ .size-custom {
251
+ display: inline-flex;
252
+ align-items: center;
253
+ gap: 6px;
254
+ }
255
+
256
+ .size-custom[hidden] {
257
+ display: none;
258
+ }
259
+
260
+ .size-custom input {
261
+ width: 84px;
262
+ }
@@ -0,0 +1,28 @@
1
+ <!doctype html>
2
+ <!--
3
+ Copyright 2026 The cuju Authors
4
+ SPDX-License-Identifier: Apache-2.0
5
+
6
+ The clean feed of the renderer, a picture of fixed size for a streaming program such as OBS. It
7
+ holds the Watch page in a frame laid out at the size that keeps the graphics in proportion and
8
+ scales the frame to the picture, see js/feed-frame.js.
9
+ -->
10
+ <html lang="en-US">
11
+ <head>
12
+ <meta charset="utf-8">
13
+ <meta name="viewport" content="width=device-width, initial-scale=1">
14
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'; frame-src 'self'; object-src 'none'; base-uri 'self'; form-action 'none'">
15
+ <title data-i18n="feed.page.title">Cuju feed</title>
16
+ <link rel="icon" type="image/png" sizes="128x128" href="assets/cuju-logo.png">
17
+ <link rel="icon" type="image/svg+xml" sizes="any" href="assets/cuju-logo.svg">
18
+ <style>
19
+ html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; background: transparent; cursor: none; }
20
+ #feed-frame { position: absolute; left: 0; top: 0; border: 0; transform-origin: 0 0; background: transparent; pointer-events: none; color-scheme: dark; }
21
+ </style>
22
+ <script type="application/json" id="cuju-languages"></script>
23
+ <script type="module" src="js/feed-frame.js"></script>
24
+ </head>
25
+ <body>
26
+ <iframe id="feed-frame" title="Cuju feed" data-i18n-title="feed.page.frame" scrolling="no" tabindex="-1"></iframe>
27
+ </body>
28
+ </html>