From 39d072aa89f67e832f39da643a79824e29d37ba1 Mon Sep 17 00:00:00 2001 From: Asicosilomu Date: Thu, 12 Jun 2025 17:43:22 +0300 Subject: [PATCH] alpha-1 --- README.md | 138 + app/app.css | 241 + app/app.js | 697 + app/controls/FlyCamera.js | 135 + app/controls/PointerLockControls.js | 272 + app/datamodel/DataModelUtils.js | 5 + app/etc/Helpers.js | 12 + app/http/AssetManager.js | 79 + app/http/TryToFetch.js | 12 + app/rendering/StudioLiteRenderer.js | 495 + app/rendering/mesh/MeshParser.js | 153 + app/thirdparty/7.css | 4 + app/thirdparty/jstree/32px.png | Bin 0 -> 2988 bytes app/thirdparty/jstree/jquery.min.js | 5 + app/thirdparty/jstree/jstree.min.js | 5 + app/thirdparty/jstree/style.min.css | 1 + app/thirdparty/jstree/throbber.gif | Bin 0 -> 19358 bytes app/thirdparty/jstree/throbber_old.gif | Bin 0 -> 1720 bytes app/thirdparty/rbxBinaryParser.js | 1 + app/thirdparty/three/stats.module.js | 167 + app/thirdparty/three/three.core.js | 57986 ++++++++++++++++ app/thirdparty/three/three.module.js | 18021 +++++ asset/10055744.png | Bin 0 -> 50416 bytes asset/1008743.png | Bin 0 -> 37437 bytes asset/1008744.png | Bin 0 -> 55907 bytes asset/1008745.png | Bin 0 -> 51767 bytes asset/1008748.png | Bin 0 -> 41917 bytes asset/10124534.png | Bin 0 -> 127084 bytes asset/1013849.png | Bin 0 -> 171978 bytes asset/1013850.png | Bin 0 -> 179720 bytes asset/1013851.png | Bin 0 -> 179012 bytes asset/1013852.png | Bin 0 -> 151437 bytes asset/1013853.png | Bin 0 -> 40928 bytes asset/1013854.png | Bin 0 -> 176168 bytes asset/101840086.png | Bin 0 -> 61303 bytes asset/101840172.mesh | 3 + asset/10470600.png | Bin 0 -> 61115 bytes asset/10470609.mesh | 3 + asset/10759411.png | Bin 0 -> 69375 bytes asset/107706048.png | Bin 0 -> 33204 bytes asset/1091940.mesh | 3 + asset/1091942.png | Bin 0 -> 44883 bytes asset/1136139.mesh | 3 + asset/1136146.png | Bin 0 -> 53635 bytes asset/1136349.png | Bin 0 -> 22753 bytes asset/1136350.png | Bin 0 -> 24992 bytes asset/1138386.png | Bin 0 -> 33116 bytes asset/1138387.png | Bin 0 -> 45776 bytes asset/1139750.png | Bin 0 -> 58195 bytes asset/1139751.png | Bin 0 -> 32709 bytes asset/1139752.png | Bin 0 -> 39546 bytes asset/1140961.png | Bin 0 -> 30938 bytes asset/1140964.png | Bin 0 -> 33406 bytes asset/1143109.png | Bin 0 -> 59402 bytes asset/1143110.png | Bin 0 -> 44558 bytes asset/115289510.mesh | 3 + asset/115296503.mesh | 3 + asset/115340918.png | Bin 0 -> 36081 bytes asset/115955313.mesh | 3 + asset/115955343.png | Bin 0 -> 55076 bytes asset/116439976.mesh | 3 + asset/116440028.png | Bin 0 -> 271459 bytes asset/116620938.png | Bin 0 -> 11918 bytes asset/116620941.png | Bin 0 -> 5309 bytes asset/1181642.png | Bin 0 -> 22943 bytes asset/11820196.png | Bin 0 -> 25835 bytes asset/11821197.mesh | 3 + asset/118869704.png | Bin 0 -> 60724 bytes asset/1193159.png | Bin 0 -> 25885 bytes asset/119364093.png | Bin 0 -> 48062 bytes asset/119875584.mesh | 3 + asset/119875721.png | Bin 0 -> 63513 bytes asset/12212520.mesh | 3 + asset/123115084.mesh | 3 + asset/123115105.png | Bin 0 -> 46281 bytes asset/1239456.png | Bin 0 -> 64378 bytes asset/1290033.mesh | 3 + asset/13319240.mesh | 3 + asset/13319242.png | Bin 0 -> 7164 bytes asset/13425802.mesh | 3 + asset/13425822.png | Bin 0 -> 48356 bytes asset/143675742.png | Bin 0 -> 31049 bytes asset/14655345.png | Bin 0 -> 105946 bytes asset/14655367.mesh | 3 + asset/146872602.png | Bin 0 -> 6843 bytes asset/147037195.png | Bin 0 -> 3747 bytes asset/147831825.mesh | 3 + asset/147831861.png | Bin 0 -> 95024 bytes asset/15952494.png | Bin 0 -> 84645 bytes asset/15952512.mesh | 3 + asset/161240005.png | Bin 0 -> 118576 bytes asset/165443860.png | Bin 0 -> 123955 bytes asset/165853672.png | Bin 0 -> 1015702 bytes asset/16606141.png | Bin 0 -> 72933 bytes asset/16606212.mesh | 3 + asset/16659355.png | Bin 0 -> 80719 bytes asset/16659363.mesh | 3 + asset/16922886.png | Bin 0 -> 238 bytes asset/17230185.png | Bin 0 -> 93691 bytes asset/17230208.mesh | 3 + asset/173781040.png | Bin 0 -> 121936 bytes asset/178434732.png | Bin 0 -> 221757 bytes asset/19059111.png | Bin 0 -> 57668 bytes asset/19059116.mesh | 3 + asset/192488915.mesh | 3 + asset/192488947.png | Bin 0 -> 67390 bytes asset/212302951.mesh | 3 + asset/212303049.png | Bin 0 -> 74612 bytes asset/2204142.png | Bin 0 -> 3324 bytes asset/243848567.png | Bin 0 -> 131031 bytes asset/25077555.png | Bin 0 -> 38478 bytes asset/25078175.mesh | 3 + asset/25095762.png | Bin 0 -> 13629 bytes asset/25096532.mesh | 3 + asset/258209444.png | Bin 0 -> 774609 bytes asset/27039535.mesh | 3 + asset/27039641.png | Bin 0 -> 62608 bytes asset/27787143.mesh | 3 + asset/27787168.png | Bin 0 -> 48435 bytes asset/28501599.mesh | 3 + asset/28501623.png | Bin 0 -> 52909 bytes asset/2861779.png | Bin 0 -> 141407 bytes asset/28872862.png | Bin 0 -> 6565 bytes asset/29515949.png | Bin 0 -> 19568 bytes asset/29515975.mesh | 3 + asset/31183234.mesh | 3 + asset/31183303.png | Bin 0 -> 51636 bytes asset/324896283.png | Bin 0 -> 288377 bytes asset/324896348.png | Bin 0 -> 177907 bytes asset/3270017.mesh | 3 + asset/331852588.png | Bin 0 -> 974411 bytes asset/332043631.png | Bin 0 -> 377931 bytes asset/336946240.png | Bin 0 -> 21666 bytes asset/345936256.png | Bin 0 -> 60322 bytes asset/345988271.png | Bin 0 -> 1392980 bytes asset/345995058.png | Bin 0 -> 47219 bytes asset/345995475.png | Bin 0 -> 69516 bytes asset/346001941.png | Bin 0 -> 89679 bytes asset/36365793.png | Bin 0 -> 109874 bytes asset/36365830.mesh | 3 + asset/365603813.png | Bin 0 -> 33605 bytes asset/367726197.png | Bin 0 -> 672259 bytes asset/37065186.png | Bin 0 -> 182055 bytes asset/41385900.png | Bin 0 -> 105046 bytes asset/41434307.mesh | 3 + asset/41707557.mesh | 3 + asset/41708405.png | Bin 0 -> 82039 bytes asset/4639675.png | Bin 0 -> 47728 bytes asset/5009999.png | Bin 0 -> 77996 bytes asset/51498309.png | Bin 0 -> 21553 bytes asset/54031359.mesh | 3 + asset/54031415.png | Bin 0 -> 110333 bytes asset/57718359.png | Bin 0 -> 109112 bytes asset/57718450.mesh | 3 + asset/60112675.png | Bin 0 -> 47564 bytes asset/60112959.png | Bin 0 -> 54429 bytes asset/60502701.png | Bin 0 -> 3291 bytes asset/6372755229.png | Bin 0 -> 1415 bytes asset/6412503613.png | Bin 0 -> 195294 bytes asset/6444884337.png | Bin 0 -> 417415 bytes asset/6444884785.png | Bin 0 -> 567323 bytes asset/8057767.png | Bin 0 -> 14462 bytes asset/8331089.png | Bin 0 -> 42746 bytes asset/84132548.png | Bin 0 -> 36366 bytes asset/84313478.mesh | 3 + asset/84313555.mesh | 3 + asset/84313638.png | Bin 0 -> 55131 bytes asset/8798201.png | Bin 0 -> 30314 bytes asset/89348280.png | Bin 0 -> 91410 bytes asset/89627839.png | Bin 0 -> 14849 bytes asset/98151581.png | Bin 0 -> 60382 bytes asset/99170547.png | Bin 0 -> 65936 bytes content/Textures/ArrowCursor.png | Bin 0 -> 4327 bytes content/Textures/ArrowFarCursor.png | Bin 0 -> 4327 bytes content/Textures/ImageError.png | Bin 0 -> 15212 bytes content/Textures/SpawnLocation.png | Bin 0 -> 2672 bytes content/icons/Accessory.png | Bin 0 -> 666 bytes content/icons/Accoutrement.png | Bin 0 -> 644 bytes content/icons/Actor.png | Bin 0 -> 326 bytes content/icons/AdGui.png | Bin 0 -> 190 bytes content/icons/AdPortal.png | Bin 0 -> 640 bytes content/icons/AdService.png | Bin 0 -> 764 bytes content/icons/AdvancedDragger.png | Bin 0 -> 313 bytes content/icons/AirController.png | Bin 0 -> 313 bytes content/icons/AlignOrientation.png | Bin 0 -> 649 bytes content/icons/AlignPosition.png | Bin 0 -> 620 bytes content/icons/AnalysticsService.png | Bin 0 -> 643 bytes content/icons/AnalysticsSettings.png | Bin 0 -> 643 bytes content/icons/AnalyticsService.png | Bin 0 -> 643 bytes content/icons/AngularVelocity.png | Bin 0 -> 583 bytes content/icons/Animation.png | Bin 0 -> 689 bytes content/icons/AnimationClip.png | Bin 0 -> 629 bytes content/icons/AnimationClipProvider.png | Bin 0 -> 629 bytes content/icons/AnimationController.png | Bin 0 -> 689 bytes .../AnimationFromVideoCreatorService.png | Bin 0 -> 629 bytes ...AnimationFromVideoCreatorStudioService.png | Bin 0 -> 826 bytes content/icons/AnimationRigData.png | Bin 0 -> 848 bytes content/icons/AnimationStreamTrack.png | Bin 0 -> 826 bytes content/icons/AnimationTrack.png | Bin 0 -> 826 bytes content/icons/Animator.png | Bin 0 -> 689 bytes content/icons/AppStorageService.png | Bin 0 -> 658 bytes content/icons/AppUpdateService.png | Bin 0 -> 660 bytes content/icons/ArcHandles.png | Bin 0 -> 406 bytes content/icons/AssetCounterService.png | Bin 0 -> 514 bytes content/icons/AssetDeliveryProxy.png | Bin 0 -> 514 bytes content/icons/AssetImportService.png | Bin 0 -> 514 bytes content/icons/AssetImportSession.png | Bin 0 -> 656 bytes content/icons/AssetManagerService.png | Bin 0 -> 817 bytes content/icons/AssetService.png | Bin 0 -> 817 bytes content/icons/AssetSoundEffect.png | Bin 0 -> 313 bytes content/icons/Atmosphere.png | Bin 0 -> 830 bytes content/icons/Attachment.png | Bin 0 -> 570 bytes content/icons/AvatarEditorService.png | Bin 0 -> 861 bytes content/icons/AvatarImportService.png | Bin 0 -> 861 bytes content/icons/Backpack.png | Bin 0 -> 754 bytes content/icons/BackpackItem.png | Bin 0 -> 313 bytes content/icons/BadgeService.png | Bin 0 -> 595 bytes content/icons/BallSocketConstraint.png | Bin 0 -> 482 bytes content/icons/BasePart.png | Bin 0 -> 215 bytes content/icons/BasePlayerGui.png | Bin 0 -> 313 bytes content/icons/BaseScript.png | Bin 0 -> 313 bytes content/icons/BaseWrap.png | Bin 0 -> 339 bytes content/icons/Beam.png | Bin 0 -> 502 bytes content/icons/BevelMesh.png | Bin 0 -> 313 bytes content/icons/BillboardGui.png | Bin 0 -> 589 bytes content/icons/BinaryStringValue.png | Bin 0 -> 313 bytes content/icons/BindableEvent.png | Bin 0 -> 169 bytes content/icons/BindableFunction.png | Bin 0 -> 447 bytes content/icons/BlockMesh.png | Bin 0 -> 218 bytes content/icons/BloomEffect.png | Bin 0 -> 830 bytes content/icons/BlurEffect.png | Bin 0 -> 830 bytes content/icons/BodyAngularVelocity.png | Bin 0 -> 644 bytes content/icons/BodyColor.png | Bin 0 -> 5220 bytes content/icons/BodyColors.png | Bin 0 -> 5220 bytes content/icons/BodyForce.png | Bin 0 -> 644 bytes content/icons/BodyGyro.png | Bin 0 -> 644 bytes content/icons/BodyMover.png | Bin 0 -> 334 bytes content/icons/BodyPosition.png | Bin 0 -> 644 bytes content/icons/BodyThrust.png | Bin 0 -> 644 bytes content/icons/BodyVelocity.png | Bin 0 -> 644 bytes content/icons/Bone.png | Bin 0 -> 602 bytes content/icons/BoolValue.png | Bin 0 -> 219 bytes content/icons/BoxHandleAdornment.png | Bin 0 -> 278 bytes content/icons/Breakpoint.png | Bin 0 -> 313 bytes content/icons/BreakpointManager.png | Bin 0 -> 313 bytes content/icons/BrickColor.png | Bin 0 -> 219 bytes content/icons/BrickColorValue.png | Bin 0 -> 219 bytes content/icons/BrowserService.png | Bin 0 -> 473 bytes content/icons/BubbleChatConfiguration.png | Bin 0 -> 313 bytes content/icons/BulkImportService.png | Bin 0 -> 730 bytes content/icons/BuoyancySensor.png | Bin 0 -> 510 bytes content/icons/CFrameValue.png | Bin 0 -> 219 bytes content/icons/CSGDictionaryService.png | Bin 0 -> 659 bytes content/icons/CacheableContentProvider.png | Bin 0 -> 693 bytes content/icons/CalloutService.png | Bin 0 -> 313 bytes content/icons/Camera.png | Bin 0 -> 762 bytes content/icons/CanvasGroup.png | Bin 0 -> 502 bytes content/icons/CatalogPages.png | Bin 0 -> 419 bytes content/icons/ChangeHistoryService.png | Bin 0 -> 797 bytes content/icons/ChannelSelectorSoundEffect.png | Bin 0 -> 701 bytes content/icons/CharacterAppearance.png | Bin 0 -> 747 bytes content/icons/CharacterMesh.png | Bin 0 -> 689 bytes content/icons/Chat.png | Bin 0 -> 464 bytes content/icons/ChatInputBarConfiguration.png | Bin 0 -> 463 bytes content/icons/ChatWindowConfiguration.png | Bin 0 -> 609 bytes content/icons/ChorusSoundEffect.png | Bin 0 -> 194 bytes content/icons/ClickDetector.png | Bin 0 -> 254 bytes content/icons/ClientReplicator.png | Bin 0 -> 776 bytes content/icons/ClimbController.png | Bin 0 -> 5371 bytes content/icons/Clothing.png | Bin 0 -> 652 bytes content/icons/Clouds.png | Bin 0 -> 635 bytes content/icons/ClusterPacketCache.png | Bin 0 -> 557 bytes content/icons/CollectionService.png | Bin 0 -> 753 bytes content/icons/Color3Value.png | Bin 0 -> 219 bytes content/icons/ColorCorrectionEffect.png | Bin 0 -> 830 bytes content/icons/CommandInstance.png | Bin 0 -> 313 bytes content/icons/CommandService.png | Bin 0 -> 502 bytes content/icons/CompressorSoundEffect.png | Bin 0 -> 194 bytes content/icons/ConeHandleAdornment.png | Bin 0 -> 421 bytes content/icons/Configuration.png | Bin 0 -> 743 bytes content/icons/ConfigureServerService.png | Bin 0 -> 721 bytes content/icons/Constraint.png | Bin 0 -> 313 bytes content/icons/ContentProvider.png | Bin 0 -> 705 bytes content/icons/ContextActionService.png | Bin 0 -> 566 bytes content/icons/Controller.png | Bin 0 -> 552 bytes content/icons/ControllerBase.png | Bin 0 -> 652 bytes content/icons/ControllerManager.png | Bin 0 -> 5141 bytes content/icons/ControllerService.png | Bin 0 -> 552 bytes content/icons/CookiesService.png | Bin 0 -> 377 bytes content/icons/CoreGui.png | Bin 0 -> 633 bytes content/icons/CorePackages.png | Bin 0 -> 260 bytes content/icons/CoreScript.png | Bin 0 -> 837 bytes content/icons/CoreScriptSyncService.png | Bin 0 -> 514 bytes content/icons/CornerWedgePart.png | Bin 0 -> 525 bytes content/icons/CrossDMScriptChangeListener.png | Bin 0 -> 826 bytes content/icons/CurveAnimation.png | Bin 0 -> 598 bytes content/icons/CustomEvent.png | Bin 0 -> 219 bytes content/icons/CustomEventReceiver.png | Bin 0 -> 219 bytes content/icons/CustomSoundEffect.png | Bin 0 -> 313 bytes content/icons/CylinderHandleAdornment.png | Bin 0 -> 361 bytes content/icons/CylinderMesh.png | Bin 0 -> 218 bytes content/icons/CylindricalConstraint.png | Bin 0 -> 480 bytes content/icons/DataModel.png | Bin 0 -> 314 bytes content/icons/DataModelMesh.png | Bin 0 -> 492 bytes content/icons/DataModelPatchService.png | Bin 0 -> 434 bytes content/icons/DataModelSession.png | Bin 0 -> 314 bytes content/icons/DataStore.png | Bin 0 -> 536 bytes content/icons/DataStoreIncrementOptions.png | Bin 0 -> 417 bytes content/icons/DataStoreInfo.png | Bin 0 -> 403 bytes content/icons/DataStoreKey.png | Bin 0 -> 313 bytes content/icons/DataStoreKeyInfo.png | Bin 0 -> 313 bytes content/icons/DataStoreKeyPages.png | Bin 0 -> 313 bytes content/icons/DataStoreListingPages.png | Bin 0 -> 357 bytes content/icons/DataStoreObjectVersionInfo.png | Bin 0 -> 313 bytes content/icons/DataStoreOptions.png | Bin 0 -> 417 bytes content/icons/DataStorePages.png | Bin 0 -> 357 bytes content/icons/DataStoreService.png | Bin 0 -> 653 bytes content/icons/DataStoreSetOptions.png | Bin 0 -> 417 bytes content/icons/DataStoreVersionPages.png | Bin 0 -> 387 bytes content/icons/Debris.png | Bin 0 -> 215 bytes content/icons/DebugSettings.png | Bin 0 -> 313 bytes content/icons/DebuggablePluginWatcher.png | Bin 0 -> 313 bytes content/icons/DebuggerBreakpoint.png | Bin 0 -> 313 bytes content/icons/DebuggerConnection.png | Bin 0 -> 313 bytes content/icons/DebuggerConnectionManager.png | Bin 0 -> 313 bytes content/icons/DebuggerLuaResponse.png | Bin 0 -> 313 bytes content/icons/DebuggerManager.png | Bin 0 -> 313 bytes content/icons/DebuggerUIService.png | Bin 0 -> 313 bytes content/icons/DebuggerVariable.png | Bin 0 -> 313 bytes content/icons/Decal.png | Bin 0 -> 695 bytes content/icons/DepthOfFieldEffect.png | Bin 0 -> 830 bytes content/icons/DeviceIdService.png | Bin 0 -> 302 bytes content/icons/Dialog.png | Bin 0 -> 363 bytes content/icons/DialogChoice.png | Bin 0 -> 416 bytes content/icons/DistortionSoundEffect.png | Bin 0 -> 194 bytes content/icons/DockWidgetPluginGui.png | Bin 0 -> 432 bytes content/icons/DoubleConstrainedValue.png | Bin 0 -> 219 bytes content/icons/DraftsService.png | Bin 0 -> 313 bytes content/icons/DragDetector.png | Bin 0 -> 691 bytes content/icons/Dragger.png | Bin 0 -> 297 bytes content/icons/DraggerService.png | Bin 0 -> 514 bytes content/icons/DynamicRotate.png | Bin 0 -> 528 bytes content/icons/EchoSoundEffect.png | Bin 0 -> 194 bytes content/icons/EmotesPages.png | Bin 0 -> 359 bytes content/icons/EqualizerSoundEffect.png | Bin 0 -> 194 bytes content/icons/EulerRotationCurve.png | Bin 0 -> 453 bytes content/icons/EventIngestService.png | Bin 0 -> 303 bytes content/icons/Explosion.png | Bin 0 -> 527 bytes content/icons/FaceAnimatorService.png | Bin 0 -> 328 bytes content/icons/FaceControls.png | Bin 0 -> 399 bytes content/icons/FaceInstance.png | Bin 0 -> 263 bytes .../icons/FacialAnimationRecordingService.png | Bin 0 -> 271 bytes .../icons/FacialAnimationStreamingService.png | Bin 0 -> 776 bytes content/icons/Feature.png | Bin 0 -> 294 bytes content/icons/File.png | Bin 0 -> 207 bytes content/icons/FileMesh.png | Bin 0 -> 492 bytes content/icons/FilteredSelection.png | Bin 0 -> 652 bytes content/icons/Fire.png | Bin 0 -> 890 bytes content/icons/Flag.png | Bin 0 -> 662 bytes content/icons/FlagStand.png | Bin 0 -> 642 bytes content/icons/FlagStandService.png | Bin 0 -> 313 bytes content/icons/FlangeSoundEffect.png | Bin 0 -> 194 bytes content/icons/FloatCurve.png | Bin 0 -> 469 bytes content/icons/FloorWire.png | Bin 0 -> 219 bytes content/icons/FlyweightService.png | Bin 0 -> 357 bytes content/icons/Folder.png | Bin 0 -> 522 bytes content/icons/ForceField.png | Bin 0 -> 615 bytes content/icons/FormFactorPart.png | Bin 0 -> 215 bytes content/icons/Frame.png | Bin 0 -> 483 bytes content/icons/FriendPages.png | Bin 0 -> 297 bytes content/icons/FriendService.png | Bin 0 -> 803 bytes content/icons/FunctionalTest.png | Bin 0 -> 313 bytes content/icons/GamePassService.png | Bin 0 -> 498 bytes content/icons/GamepadService.png | Bin 0 -> 712 bytes content/icons/GenericSettings.png | Bin 0 -> 399 bytes content/icons/Geometry.png | Bin 0 -> 368 bytes content/icons/GetTextBoundsParams.png | Bin 0 -> 246 bytes content/icons/GlobalDataStore.png | Bin 0 -> 481 bytes content/icons/GlobalSettings.png | Bin 0 -> 523 bytes content/icons/Glue.png | Bin 0 -> 254 bytes .../icons/GoogleAnalyticsConfiguration.png | Bin 0 -> 253 bytes content/icons/GroundController.png | Bin 0 -> 5339 bytes content/icons/GroupService.png | Bin 0 -> 774 bytes content/icons/GuiBase.png | Bin 0 -> 225 bytes content/icons/GuiBase2d.png | Bin 0 -> 225 bytes content/icons/GuiBase3d.png | Bin 0 -> 281 bytes content/icons/GuiButton.png | Bin 0 -> 132 bytes content/icons/GuiLabel.png | Bin 0 -> 218 bytes content/icons/GuiMain.png | Bin 0 -> 432 bytes content/icons/GuiObject.png | Bin 0 -> 225 bytes content/icons/GuiService.png | Bin 0 -> 432 bytes content/icons/GuidRegistryService.png | Bin 0 -> 673 bytes content/icons/HSRDataContentProvider.png | Bin 0 -> 405 bytes content/icons/HandleAdornment.png | Bin 0 -> 235 bytes content/icons/Handles.png | Bin 0 -> 388 bytes content/icons/HandlesBase.png | Bin 0 -> 202 bytes content/icons/HapticService.png | Bin 0 -> 712 bytes content/icons/Hat.png | Bin 0 -> 323 bytes content/icons/HeightmapImportService.png | Bin 0 -> 586 bytes content/icons/HeightmapImporterService.png | Bin 0 -> 311 bytes content/icons/HiddenSurfaceRemovalAsset.png | Bin 0 -> 430 bytes content/icons/Highlight.png | Bin 0 -> 713 bytes content/icons/HingeConstraint.png | Bin 0 -> 320 bytes content/icons/Hint.png | Bin 0 -> 485 bytes content/icons/Hole.png | Bin 0 -> 244 bytes content/icons/Hopper.png | Bin 0 -> 273 bytes content/icons/HopperBin.png | Bin 0 -> 589 bytes content/icons/HttpRbxApiService.png | Bin 0 -> 907 bytes content/icons/HttpRequest.png | Bin 0 -> 907 bytes content/icons/HttpService.png | Bin 0 -> 907 bytes content/icons/Humanoid.png | Bin 0 -> 199 bytes content/icons/HumanoidController.png | Bin 0 -> 421 bytes content/icons/HumanoidDescription.png | Bin 0 -> 392 bytes content/icons/IKControl.png | Bin 0 -> 313 bytes content/icons/ILegacyStudioBridge.png | Bin 0 -> 313 bytes content/icons/IXPService.png | Bin 0 -> 920 bytes content/icons/ImageButton.png | Bin 0 -> 646 bytes content/icons/ImageHandleAdornment.png | Bin 0 -> 406 bytes content/icons/ImageLabel.png | Bin 0 -> 666 bytes content/icons/ImporterAnimationSettings.png | Bin 0 -> 354 bytes content/icons/ImporterBaseSettings.png | Bin 0 -> 331 bytes content/icons/ImporterFacsSettings.png | Bin 0 -> 327 bytes content/icons/ImporterGroupSettings.png | Bin 0 -> 315 bytes content/icons/ImporterJointSettings.png | Bin 0 -> 354 bytes content/icons/ImporterMaterialSettings.png | Bin 0 -> 354 bytes content/icons/ImporterMeshSettings.png | Bin 0 -> 346 bytes content/icons/ImporterRootSettings.png | Bin 0 -> 331 bytes content/icons/IncrementalPatchBuilder.png | Bin 0 -> 434 bytes content/icons/InputObject.png | Bin 0 -> 253 bytes content/icons/InsertService.png | Bin 0 -> 809 bytes content/icons/Instance.png | Bin 0 -> 666 bytes content/icons/InstanceAdornment.png | Bin 0 -> 407 bytes content/icons/IntConstrainedValue.png | Bin 0 -> 219 bytes content/icons/IntValue.png | Bin 0 -> 219 bytes content/icons/InventoryPages.png | Bin 0 -> 434 bytes content/icons/JointInstance.png | Bin 0 -> 291 bytes content/icons/JointsService.png | Bin 0 -> 508 bytes content/icons/KeyboardService.png | Bin 0 -> 552 bytes content/icons/Keyframe.png | Bin 0 -> 629 bytes content/icons/KeyframeMarker.png | Bin 0 -> 629 bytes content/icons/KeyframeSequence.png | Bin 0 -> 689 bytes content/icons/KeyframeSequenceProvider.png | Bin 0 -> 662 bytes content/icons/LSPFileSyncService.png | Bin 0 -> 401 bytes content/icons/LanguageService.png | Bin 0 -> 729 bytes content/icons/LayerCollector.png | Bin 0 -> 258 bytes content/icons/LegacyStudioBridge.png | Bin 0 -> 319 bytes content/icons/Light.png | Bin 0 -> 294 bytes content/icons/Lighting.png | Bin 0 -> 777 bytes content/icons/LineForce.png | Bin 0 -> 378 bytes content/icons/LineHandleAdornment.png | Bin 0 -> 222 bytes content/icons/LinearVelocity.png | Bin 0 -> 268 bytes content/icons/LocalDebuggerConnection.png | Bin 0 -> 417 bytes content/icons/LocalScript.png | Bin 0 -> 943 bytes content/icons/LocalStorageService.png | Bin 0 -> 228 bytes content/icons/LocalizationService.png | Bin 0 -> 809 bytes content/icons/LocalizationTable.png | Bin 0 -> 600 bytes content/icons/LodDataEntity.png | Bin 0 -> 377 bytes content/icons/LodDataService.png | Bin 0 -> 682 bytes content/icons/LogService.png | Bin 0 -> 702 bytes content/icons/LoginService.png | Bin 0 -> 234 bytes content/icons/LuaSettings.png | Bin 0 -> 309 bytes content/icons/LuaSourceContainer.png | Bin 0 -> 145 bytes content/icons/LuaWebService.png | Bin 0 -> 553 bytes content/icons/LuauScriptAnalyzerService.png | Bin 0 -> 826 bytes content/icons/ManualGlue.png | Bin 0 -> 227 bytes content/icons/ManualSurfaceJointInstance.png | Bin 0 -> 302 bytes content/icons/ManualWeld.png | Bin 0 -> 392 bytes content/icons/MarkerCurve.png | Bin 0 -> 533 bytes content/icons/MarketplaceService.png | Bin 0 -> 653 bytes content/icons/MaterialGenerationService.png | Bin 0 -> 291 bytes content/icons/MaterialService.png | Bin 0 -> 582 bytes content/icons/MaterialVariant.png | Bin 0 -> 625 bytes content/icons/MemStorageConnection.png | Bin 0 -> 752 bytes content/icons/MemStorageService.png | Bin 0 -> 692 bytes content/icons/MemoryStoreQueue.png | Bin 0 -> 452 bytes content/icons/MemoryStoreService.png | Bin 0 -> 376 bytes content/icons/MemoryStoreSortedMap.png | Bin 0 -> 473 bytes content/icons/MeshContentProvider.png | Bin 0 -> 865 bytes content/icons/MeshPart.png | Bin 0 -> 617 bytes content/icons/Message.png | Bin 0 -> 485 bytes content/icons/MessageBusConnection.png | Bin 0 -> 539 bytes content/icons/MessageBusService.png | Bin 0 -> 539 bytes content/icons/MessagingService.png | Bin 0 -> 268 bytes content/icons/MetaBreakpoint.png | Bin 0 -> 596 bytes content/icons/MetaBreakpointContext.png | Bin 0 -> 424 bytes content/icons/MetaBreakpointManager.png | Bin 0 -> 496 bytes content/icons/Model.png | Bin 0 -> 813 bytes content/icons/ModuleScript.png | Bin 0 -> 803 bytes content/icons/Motor.png | Bin 0 -> 468 bytes content/icons/Motor6D.png | Bin 0 -> 468 bytes content/icons/MotorFeature.png | Bin 0 -> 468 bytes content/icons/MouseService.png | Bin 0 -> 693 bytes .../MultipleDocumentInterfaceInstance.png | Bin 0 -> 220 bytes content/icons/NegateOperation.png | Bin 0 -> 532 bytes content/icons/NetworkClient.png | Bin 0 -> 218 bytes content/icons/NetworkMarker.png | Bin 0 -> 278 bytes content/icons/NetworkPeer.png | Bin 0 -> 256 bytes content/icons/NetworkReplicator.png | Bin 0 -> 253 bytes content/icons/NetworkServer.png | Bin 0 -> 671 bytes content/icons/NetworkSettings.png | Bin 0 -> 394 bytes content/icons/NoCollisionConstraint.png | Bin 0 -> 336 bytes .../NonReplicatedCSGDictionaryService.png | Bin 0 -> 659 bytes content/icons/NotificationService.png | Bin 0 -> 761 bytes content/icons/NumberPose.png | Bin 0 -> 294 bytes content/icons/NumberValue.png | Bin 0 -> 219 bytes content/icons/ObjectValue.png | Bin 0 -> 219 bytes content/icons/OrderedDataStore.png | Bin 0 -> 427 bytes content/icons/OutfitPages.png | Bin 0 -> 359 bytes content/icons/PVAdornment.png | Bin 0 -> 235 bytes content/icons/PVInstance.png | Bin 0 -> 307 bytes content/icons/PackageLink.png | Bin 0 -> 861 bytes content/icons/PackageService.png | Bin 0 -> 518 bytes content/icons/PackageUIService.png | Bin 0 -> 630 bytes content/icons/Pages.png | Bin 0 -> 205 bytes content/icons/Pants.png | Bin 0 -> 472 bytes content/icons/ParabolaAdornment.png | Bin 0 -> 315 bytes content/icons/Part.png | Bin 0 -> 525 bytes content/icons/PartAdornment.png | Bin 0 -> 407 bytes content/icons/PartOperation.png | Bin 0 -> 666 bytes content/icons/PartOperationAsset.png | Bin 0 -> 628 bytes content/icons/ParticleEmitter.png | Bin 0 -> 755 bytes content/icons/PatchMapping.png | Bin 0 -> 434 bytes content/icons/Path.png | Bin 0 -> 320 bytes content/icons/PathfindingLink.png | Bin 0 -> 534 bytes content/icons/PathfindingModifier.png | Bin 0 -> 610 bytes content/icons/PathfindingService.png | Bin 0 -> 537 bytes content/icons/PausedState.png | Bin 0 -> 208 bytes content/icons/PausedStateBreakpoint.png | Bin 0 -> 354 bytes content/icons/PausedStateException.png | Bin 0 -> 276 bytes content/icons/PermissionsService.png | Bin 0 -> 674 bytes content/icons/PhysicsService.png | Bin 0 -> 570 bytes content/icons/PhysicsSettings.png | Bin 0 -> 476 bytes content/icons/PitchShiftSoundEffect.png | Bin 0 -> 194 bytes content/icons/Plane.png | Bin 0 -> 551 bytes content/icons/PlaneConstraint.png | Bin 0 -> 551 bytes content/icons/Platform.png | Bin 0 -> 258 bytes content/icons/Player.png | Bin 0 -> 710 bytes content/icons/PlayerEmulatorService.png | Bin 0 -> 708 bytes content/icons/PlayerGui.png | Bin 0 -> 643 bytes content/icons/PlayerMouse.png | Bin 0 -> 280 bytes content/icons/PlayerScripts.png | Bin 0 -> 764 bytes content/icons/Players.png | Bin 0 -> 749 bytes content/icons/Plugin.png | Bin 0 -> 275 bytes content/icons/PluginAction.png | Bin 0 -> 293 bytes content/icons/PluginDebugService.png | Bin 0 -> 416 bytes content/icons/PluginDragEvent.png | Bin 0 -> 344 bytes content/icons/PluginGui.png | Bin 0 -> 219 bytes content/icons/PluginGuiService.png | Bin 0 -> 704 bytes content/icons/PluginManagementService.png | Bin 0 -> 268 bytes content/icons/PluginManager.png | Bin 0 -> 268 bytes content/icons/PluginManagerInterface.png | Bin 0 -> 247 bytes content/icons/PluginMenu.png | Bin 0 -> 334 bytes content/icons/PluginMouse.png | Bin 0 -> 302 bytes content/icons/PluginPolicyService.png | Bin 0 -> 623 bytes content/icons/PluginToolbar.png | Bin 0 -> 209 bytes content/icons/PluginToolbarButton.png | Bin 0 -> 194 bytes content/icons/PointLight.png | Bin 0 -> 777 bytes content/icons/PointsService.png | Bin 0 -> 770 bytes content/icons/PolicyService.png | Bin 0 -> 623 bytes content/icons/Pose.png | Bin 0 -> 702 bytes content/icons/PoseBase.png | Bin 0 -> 266 bytes content/icons/PostEffect.png | Bin 0 -> 382 bytes content/icons/PrismaticConstraint.png | Bin 0 -> 391 bytes .../icons/ProcessInstancePhysicsService.png | Bin 0 -> 570 bytes content/icons/ProximityPrompt.png | Bin 0 -> 494 bytes content/icons/ProximityPromptService.png | Bin 0 -> 613 bytes content/icons/PublishService.png | Bin 0 -> 724 bytes content/icons/QWidgetPluginGui.png | Bin 0 -> 432 bytes content/icons/RayValue.png | Bin 0 -> 219 bytes content/icons/RbxAnalyticsService.png | Bin 0 -> 738 bytes content/icons/ReflectionMetadata.png | Bin 0 -> 803 bytes content/icons/ReflectionMetadataCallbacks.png | Bin 0 -> 803 bytes content/icons/ReflectionMetadataClass.png | Bin 0 -> 803 bytes content/icons/ReflectionMetadataClasses.png | Bin 0 -> 459 bytes content/icons/ReflectionMetadataEnum.png | Bin 0 -> 803 bytes content/icons/ReflectionMetadataEnumItem.png | Bin 0 -> 803 bytes content/icons/ReflectionMetadataEnums.png | Bin 0 -> 803 bytes content/icons/ReflectionMetadataEvents.png | Bin 0 -> 803 bytes content/icons/ReflectionMetadataFunctions.png | Bin 0 -> 803 bytes content/icons/ReflectionMetadataItem.png | Bin 0 -> 803 bytes content/icons/ReflectionMetadataMember.png | Bin 0 -> 803 bytes .../icons/ReflectionMetadataProperties.png | Bin 0 -> 803 bytes .../ReflectionMetadataYieldFunctions.png | Bin 0 -> 803 bytes content/icons/RemoteDebuggerServer.png | Bin 0 -> 872 bytes content/icons/RemoteEvent.png | Bin 0 -> 215 bytes content/icons/RemoteFunction.png | Bin 0 -> 426 bytes content/icons/RenderHooksService.png | Bin 0 -> 313 bytes content/icons/RenderSettings.png | Bin 0 -> 394 bytes content/icons/RenderingTest.png | Bin 0 -> 656 bytes content/icons/ReplicatedFirst.png | Bin 0 -> 316 bytes content/icons/ReplicatedStorage.png | Bin 0 -> 316 bytes content/icons/ReverbSoundEffect.png | Bin 0 -> 194 bytes content/icons/RigidConstraint.png | Bin 0 -> 173 bytes content/icons/RobloxPluginGuiService.png | Bin 0 -> 704 bytes content/icons/RobloxReplicatedStorage.png | Bin 0 -> 316 bytes content/icons/RocketPropulsion.png | Bin 0 -> 644 bytes content/icons/RodConstraint.png | Bin 0 -> 446 bytes content/icons/RopeConstraint.png | Bin 0 -> 282 bytes content/icons/RotateP.png | Bin 0 -> 343 bytes content/icons/RotateV.png | Bin 0 -> 343 bytes content/icons/RotationCurve.png | Bin 0 -> 533 bytes content/icons/RtMessagingService.png | Bin 0 -> 225 bytes content/icons/RunService.png | Bin 0 -> 782 bytes content/icons/RunningAverageItemDouble.png | Bin 0 -> 435 bytes content/icons/RunningAverageItemInt.png | Bin 0 -> 435 bytes .../icons/RunningAverageTimeIntervalItem.png | Bin 0 -> 435 bytes content/icons/RuntimeScriptService.png | Bin 0 -> 848 bytes content/icons/ScreenGui.png | Bin 0 -> 521 bytes content/icons/ScreenshotHud.png | Bin 0 -> 603 bytes content/icons/Script.png | Bin 0 -> 911 bytes content/icons/ScriptChangeService.png | Bin 0 -> 847 bytes content/icons/ScriptCloneWatcher.png | Bin 0 -> 289 bytes content/icons/ScriptCloneWatcherHelper.png | Bin 0 -> 847 bytes content/icons/ScriptContext.png | Bin 0 -> 847 bytes content/icons/ScriptDebugger.png | Bin 0 -> 348 bytes content/icons/ScriptDocument.png | Bin 0 -> 880 bytes content/icons/ScriptEditorService.png | Bin 0 -> 847 bytes content/icons/ScriptRegistrationService.png | Bin 0 -> 826 bytes content/icons/ScriptService.png | Bin 0 -> 830 bytes content/icons/ScrollingFrame.png | Bin 0 -> 483 bytes content/icons/Seat.png | Bin 0 -> 436 bytes content/icons/Selection.png | Bin 0 -> 229 bytes content/icons/SelectionBox.png | Bin 0 -> 272 bytes content/icons/SelectionLasso.png | Bin 0 -> 429 bytes content/icons/SelectionPartLasso.png | Bin 0 -> 429 bytes content/icons/SelectionPointLasso.png | Bin 0 -> 429 bytes content/icons/SelectionSphere.png | Bin 0 -> 272 bytes content/icons/ServerReplicator.png | Bin 0 -> 820 bytes content/icons/ServerScriptService.png | Bin 0 -> 774 bytes content/icons/ServerStorage.png | Bin 0 -> 541 bytes content/icons/ServiceProvider.png | Bin 0 -> 329 bytes content/icons/ServiceVisibilityService.png | Bin 0 -> 746 bytes content/icons/SessionService.png | Bin 0 -> 640 bytes content/icons/Shirt.png | Bin 0 -> 530 bytes content/icons/ShirtGraphic.png | Bin 0 -> 195 bytes content/icons/ShorelineUpgraderService.png | Bin 0 -> 715 bytes content/icons/SkateboardController.png | Bin 0 -> 454 bytes content/icons/SkateboardPlatform.png | Bin 0 -> 436 bytes content/icons/Skin.png | Bin 0 -> 313 bytes content/icons/Sky.png | Bin 0 -> 564 bytes content/icons/SlidingBallConstraint.png | Bin 0 -> 369 bytes content/icons/Smoke.png | Bin 0 -> 748 bytes content/icons/Snap.png | Bin 0 -> 508 bytes content/icons/SnippetService.png | Bin 0 -> 560 bytes content/icons/SocialService.png | Bin 0 -> 868 bytes content/icons/SolidModelContentProvider.png | Bin 0 -> 705 bytes content/icons/Sound.png | Bin 0 -> 612 bytes content/icons/SoundEffect.png | Bin 0 -> 175 bytes content/icons/SoundGroup.png | Bin 0 -> 455 bytes content/icons/SoundService.png | Bin 0 -> 441 bytes content/icons/Sparkles.png | Bin 0 -> 227 bytes content/icons/SpawnLocation.png | Bin 0 -> 549 bytes content/icons/SpawnerService.png | Bin 0 -> 360 bytes content/icons/Speaker.png | Bin 0 -> 577 bytes content/icons/SpecialMesh.png | Bin 0 -> 218 bytes content/icons/SphereHandleAdornment.png | Bin 0 -> 356 bytes content/icons/SpotLight.png | Bin 0 -> 777 bytes content/icons/SpringConstraint.png | Bin 0 -> 737 bytes content/icons/StackFrame.png | Bin 0 -> 169 bytes content/icons/StandalonePluginScripts.png | Bin 0 -> 646 bytes content/icons/StandardPages.png | Bin 0 -> 205 bytes content/icons/StarterCharacterScripts.png | Bin 0 -> 705 bytes content/icons/StarterGear.png | Bin 0 -> 754 bytes content/icons/StarterGui.png | Bin 0 -> 643 bytes content/icons/StarterPack.png | Bin 0 -> 754 bytes content/icons/StarterPlayer.png | Bin 0 -> 764 bytes content/icons/StarterPlayerScripts.png | Bin 0 -> 764 bytes content/icons/Stats.png | Bin 0 -> 507 bytes content/icons/StatsItem.png | Bin 0 -> 681 bytes content/icons/Status.png | Bin 0 -> 5062 bytes content/icons/StopWatchReporter.png | Bin 0 -> 280 bytes content/icons/StringValue.png | Bin 0 -> 219 bytes content/icons/Studio.png | Bin 0 -> 334 bytes content/icons/StudioAssetService.png | Bin 0 -> 739 bytes content/icons/StudioData.png | Bin 0 -> 739 bytes content/icons/StudioDeviceEmulatorService.png | Bin 0 -> 214 bytes content/icons/StudioHighDpiService.png | Bin 0 -> 673 bytes content/icons/StudioPublishService.png | Bin 0 -> 673 bytes .../icons/StudioScriptDebugEventListener.png | Bin 0 -> 371 bytes content/icons/StudioService.png | Bin 0 -> 879 bytes content/icons/StudioTheme.png | Bin 0 -> 348 bytes content/icons/SunRaysEffect.png | Bin 0 -> 830 bytes content/icons/SurfaceAppearance.png | Bin 0 -> 209 bytes content/icons/SurfaceGui.png | Bin 0 -> 589 bytes content/icons/SurfaceGuiBase.png | Bin 0 -> 258 bytes content/icons/SurfaceLight.png | Bin 0 -> 777 bytes content/icons/SurfaceSelection.png | Bin 0 -> 290 bytes content/icons/SwimController.png | Bin 0 -> 5205 bytes content/icons/Team.png | Bin 0 -> 741 bytes content/icons/TeamCreateService.png | Bin 0 -> 872 bytes content/icons/Teams.png | Bin 0 -> 703 bytes content/icons/TeleportAsyncResult.png | Bin 0 -> 386 bytes content/icons/TeleportOptions.png | Bin 0 -> 636 bytes content/icons/TeleportService.png | Bin 0 -> 415 bytes content/icons/TemporaryCageMeshProvider.png | Bin 0 -> 865 bytes content/icons/TemporaryScriptService.png | Bin 0 -> 790 bytes content/icons/Terrain.png | Bin 0 -> 557 bytes content/icons/TerrainDetail.png | Bin 0 -> 665 bytes content/icons/TerrainRegion.png | Bin 0 -> 557 bytes content/icons/TestService.png | Bin 0 -> 315 bytes content/icons/TextBox.png | Bin 0 -> 626 bytes content/icons/TextBoxService.png | Bin 0 -> 693 bytes content/icons/TextButton.png | Bin 0 -> 626 bytes content/icons/TextChannel.png | Bin 0 -> 633 bytes content/icons/TextChatCommand.png | Bin 0 -> 485 bytes content/icons/TextChatConfigurations.png | Bin 0 -> 333 bytes content/icons/TextChatMessage.png | Bin 0 -> 240 bytes content/icons/TextChatMessageProperties.png | Bin 0 -> 537 bytes content/icons/TextChatService.png | Bin 0 -> 654 bytes content/icons/TextFilterResult.png | Bin 0 -> 280 bytes content/icons/TextLabel.png | Bin 0 -> 683 bytes content/icons/TextService.png | Bin 0 -> 299 bytes content/icons/TextSource.png | Bin 0 -> 246 bytes content/icons/Texture.png | Bin 0 -> 209 bytes content/icons/ThirdPartyUserService.png | Bin 0 -> 248 bytes content/icons/ThreadState.png | Bin 0 -> 242 bytes content/icons/TimerService.png | Bin 0 -> 797 bytes content/icons/ToastNotificationService.png | Bin 0 -> 749 bytes content/icons/Tool.png | Bin 0 -> 564 bytes content/icons/ToolScript.png | Bin 0 -> 809 bytes content/icons/ToolboxService.png | Bin 0 -> 330 bytes content/icons/Torque.png | Bin 0 -> 638 bytes content/icons/TorsionSpringConstraint.png | Bin 0 -> 737 bytes content/icons/TotalCountTimeIntervalItem.png | Bin 0 -> 435 bytes content/icons/TouchInputService.png | Bin 0 -> 254 bytes content/icons/TouchTransmitter.png | Bin 0 -> 615 bytes content/icons/TracerService.png | Bin 0 -> 321 bytes content/icons/TrackerStreamAnimation.png | Bin 0 -> 374 bytes content/icons/Trail.png | Bin 0 -> 424 bytes content/icons/Translator.png | Bin 0 -> 388 bytes content/icons/TremoloSoundEffect.png | Bin 0 -> 194 bytes content/icons/TriangleMeshPart.png | Bin 0 -> 400 bytes content/icons/TrussPart.png | Bin 0 -> 525 bytes content/icons/Tween.png | Bin 0 -> 598 bytes content/icons/TweenBase.png | Bin 0 -> 401 bytes content/icons/TweenService.png | Bin 0 -> 400 bytes content/icons/UGCAvatarService.png | Bin 0 -> 313 bytes content/icons/UGCValidationService.png | Bin 0 -> 721 bytes content/icons/UIAspectRatioConstraint.png | Bin 0 -> 434 bytes content/icons/UIBase.png | Bin 0 -> 298 bytes content/icons/UIComponent.png | Bin 0 -> 298 bytes content/icons/UIConstraint.png | Bin 0 -> 263 bytes content/icons/UICorner.png | Bin 0 -> 434 bytes content/icons/UIGradient.png | Bin 0 -> 434 bytes content/icons/UIGridLayout.png | Bin 0 -> 434 bytes content/icons/UIGridStyleLayout.png | Bin 0 -> 148 bytes content/icons/UILayout.png | Bin 0 -> 162 bytes content/icons/UIListLayout.png | Bin 0 -> 434 bytes content/icons/UIPadding.png | Bin 0 -> 434 bytes content/icons/UIPageLayout.png | Bin 0 -> 434 bytes content/icons/UIScale.png | Bin 0 -> 434 bytes content/icons/UISizeConstraint.png | Bin 0 -> 434 bytes content/icons/UIStroke.png | Bin 0 -> 434 bytes content/icons/UITableLayout.png | Bin 0 -> 434 bytes content/icons/UITextSizeConstraint.png | Bin 0 -> 434 bytes content/icons/UnionOperation.png | Bin 0 -> 617 bytes content/icons/UniversalConstraint.png | Bin 0 -> 583 bytes content/icons/UnvalidatedAssetService.png | Bin 0 -> 306 bytes content/icons/UserGameSettings.png | Bin 0 -> 421 bytes content/icons/UserInputService.png | Bin 0 -> 721 bytes content/icons/UserService.png | Bin 0 -> 684 bytes content/icons/UserSettings.png | Bin 0 -> 311 bytes content/icons/UserStorageService.png | Bin 0 -> 243 bytes content/icons/VRService.png | Bin 0 -> 287 bytes content/icons/ValueBase.png | Bin 0 -> 278 bytes content/icons/Vector3Curve.png | Bin 0 -> 533 bytes content/icons/Vector3Value.png | Bin 0 -> 219 bytes content/icons/VectorForce.png | Bin 0 -> 277 bytes content/icons/VehicleController.png | Bin 0 -> 399 bytes content/icons/VehicleSeat.png | Bin 0 -> 436 bytes content/icons/VelocityMotor.png | Bin 0 -> 644 bytes content/icons/VersionControlService.png | Bin 0 -> 510 bytes content/icons/VideoCaptureService.png | Bin 0 -> 757 bytes content/icons/VideoFrame.png | Bin 0 -> 670 bytes content/icons/ViewportFrame.png | Bin 0 -> 654 bytes content/icons/VirtualInputManager.png | Bin 0 -> 552 bytes content/icons/VirtualUser.png | Bin 0 -> 180 bytes content/icons/VisibilityService.png | Bin 0 -> 189 bytes content/icons/Visit.png | Bin 0 -> 474 bytes content/icons/VoiceChannel.png | Bin 0 -> 313 bytes content/icons/VoiceChatInternal.png | Bin 0 -> 269 bytes content/icons/VoiceChatService.png | Bin 0 -> 555 bytes content/icons/VoiceSource.png | Bin 0 -> 322 bytes content/icons/WedgePart.png | Bin 0 -> 525 bytes content/icons/Weld.png | Bin 0 -> 392 bytes content/icons/WeldConstraint.png | Bin 0 -> 347 bytes content/icons/WireframeHandleAdornment.png | Bin 0 -> 5587 bytes content/icons/Workspace.png | Bin 0 -> 998 bytes content/icons/WorldModel.png | Bin 0 -> 998 bytes content/icons/WorldRoot.png | Bin 0 -> 401 bytes content/icons/WrapLayer.png | Bin 0 -> 779 bytes content/icons/WrapLayerYellowWarning.png | Bin 0 -> 767 bytes content/icons/WrapTarget.png | Bin 0 -> 785 bytes content/icons/WrapTargetYellowWarning.png | Bin 0 -> 772 bytes content/icons/shield_go.png | Bin 0 -> 775 bytes content/sky/null_plainsky512_bk.jpg | Bin 0 -> 49277 bytes content/sky/null_plainsky512_dn.jpg | Bin 0 -> 33668 bytes content/sky/null_plainsky512_ft.jpg | Bin 0 -> 47691 bytes content/sky/null_plainsky512_lf.jpg | Bin 0 -> 43657 bytes content/sky/null_plainsky512_rt.jpg | Bin 0 -> 50201 bytes content/sky/null_plainsky512_up.jpg | Bin 0 -> 35512 bytes examples/City.rbxl | Bin 0 -> 264071 bytes examples/Classic-Crossroads.rbxl | Bin 0 -> 80259 bytes examples/Dilapidated-House.rbxm | Bin 0 -> 16589 bytes examples/Suburban.rbxl | Bin 0 -> 1332217 bytes examples/Western-Lounge.rbxm | Bin 0 -> 34380 bytes favicon.ico | Bin 0 -> 1150 bytes images/assets.png | Bin 0 -> 57119 bytes images/billboard.png | Bin 0 -> 251503 bytes images/car.png | Bin 0 -> 85360 bytes images/cashier.png | Bin 0 -> 30195 bytes images/crossroads8k.png | Bin 0 -> 2360017 bytes images/explorer.png | Bin 0 -> 296586 bytes images/fridge.png | Bin 0 -> 241841 bytes images/house.png | Bin 0 -> 15418 bytes images/library.png | Bin 0 -> 187195 bytes images/lounge.png | Bin 0 -> 24272 bytes images/render.png | Bin 0 -> 207500 bytes images/screen.png | Bin 0 -> 1086246 bytes images/script.png | Bin 0 -> 214411 bytes images/suburban8k.png | Bin 0 -> 2221419 bytes images/three.png | Bin 0 -> 196750 bytes index.html | 205 + 823 files changed, 78751 insertions(+) create mode 100644 README.md create mode 100644 app/app.css create mode 100644 app/app.js create mode 100644 app/controls/FlyCamera.js create mode 100644 app/controls/PointerLockControls.js create mode 100644 app/datamodel/DataModelUtils.js create mode 100644 app/etc/Helpers.js create mode 100644 app/http/AssetManager.js create mode 100644 app/http/TryToFetch.js create mode 100644 app/rendering/StudioLiteRenderer.js create mode 100644 app/rendering/mesh/MeshParser.js create mode 100644 app/thirdparty/7.css create mode 100644 app/thirdparty/jstree/32px.png create mode 100644 app/thirdparty/jstree/jquery.min.js create mode 100644 app/thirdparty/jstree/jstree.min.js create mode 100644 app/thirdparty/jstree/style.min.css create mode 100644 app/thirdparty/jstree/throbber.gif create mode 100644 app/thirdparty/jstree/throbber_old.gif create mode 100644 app/thirdparty/rbxBinaryParser.js create mode 100644 app/thirdparty/three/stats.module.js create mode 100644 app/thirdparty/three/three.core.js create mode 100644 app/thirdparty/three/three.module.js create mode 100644 asset/10055744.png create mode 100644 asset/1008743.png create mode 100644 asset/1008744.png create mode 100644 asset/1008745.png create mode 100644 asset/1008748.png create mode 100644 asset/10124534.png create mode 100644 asset/1013849.png create mode 100644 asset/1013850.png create mode 100644 asset/1013851.png create mode 100644 asset/1013852.png create mode 100644 asset/1013853.png create mode 100644 asset/1013854.png create mode 100644 asset/101840086.png create mode 100644 asset/101840172.mesh create mode 100644 asset/10470600.png create mode 100644 asset/10470609.mesh create mode 100644 asset/10759411.png create mode 100644 asset/107706048.png create mode 100644 asset/1091940.mesh create mode 100644 asset/1091942.png create mode 100644 asset/1136139.mesh create mode 100644 asset/1136146.png create mode 100644 asset/1136349.png create mode 100644 asset/1136350.png create mode 100644 asset/1138386.png create mode 100644 asset/1138387.png create mode 100644 asset/1139750.png create mode 100644 asset/1139751.png create mode 100644 asset/1139752.png create mode 100644 asset/1140961.png create mode 100644 asset/1140964.png create mode 100644 asset/1143109.png create mode 100644 asset/1143110.png create mode 100644 asset/115289510.mesh create mode 100644 asset/115296503.mesh create mode 100644 asset/115340918.png create mode 100644 asset/115955313.mesh create mode 100644 asset/115955343.png create mode 100644 asset/116439976.mesh create mode 100644 asset/116440028.png create mode 100644 asset/116620938.png create mode 100644 asset/116620941.png create mode 100644 asset/1181642.png create mode 100644 asset/11820196.png create mode 100644 asset/11821197.mesh create mode 100644 asset/118869704.png create mode 100644 asset/1193159.png create mode 100644 asset/119364093.png create mode 100644 asset/119875584.mesh create mode 100644 asset/119875721.png create mode 100644 asset/12212520.mesh create mode 100644 asset/123115084.mesh create mode 100644 asset/123115105.png create mode 100644 asset/1239456.png create mode 100644 asset/1290033.mesh create mode 100644 asset/13319240.mesh create mode 100644 asset/13319242.png create mode 100644 asset/13425802.mesh create mode 100644 asset/13425822.png create mode 100644 asset/143675742.png create mode 100644 asset/14655345.png create mode 100644 asset/14655367.mesh create mode 100644 asset/146872602.png create mode 100644 asset/147037195.png create mode 100644 asset/147831825.mesh create mode 100644 asset/147831861.png create mode 100644 asset/15952494.png create mode 100644 asset/15952512.mesh create mode 100644 asset/161240005.png create mode 100644 asset/165443860.png create mode 100644 asset/165853672.png create mode 100644 asset/16606141.png create mode 100644 asset/16606212.mesh create mode 100644 asset/16659355.png create mode 100644 asset/16659363.mesh create mode 100644 asset/16922886.png create mode 100644 asset/17230185.png create mode 100644 asset/17230208.mesh create mode 100644 asset/173781040.png create mode 100644 asset/178434732.png create mode 100644 asset/19059111.png create mode 100644 asset/19059116.mesh create mode 100644 asset/192488915.mesh create mode 100644 asset/192488947.png create mode 100644 asset/212302951.mesh create mode 100644 asset/212303049.png create mode 100644 asset/2204142.png create mode 100644 asset/243848567.png create mode 100644 asset/25077555.png create mode 100644 asset/25078175.mesh create mode 100644 asset/25095762.png create mode 100644 asset/25096532.mesh create mode 100644 asset/258209444.png create mode 100644 asset/27039535.mesh create mode 100644 asset/27039641.png create mode 100644 asset/27787143.mesh create mode 100644 asset/27787168.png create mode 100644 asset/28501599.mesh create mode 100644 asset/28501623.png create mode 100644 asset/2861779.png create mode 100644 asset/28872862.png create mode 100644 asset/29515949.png create mode 100644 asset/29515975.mesh create mode 100644 asset/31183234.mesh create mode 100644 asset/31183303.png create mode 100644 asset/324896283.png create mode 100644 asset/324896348.png create mode 100644 asset/3270017.mesh create mode 100644 asset/331852588.png create mode 100644 asset/332043631.png create mode 100644 asset/336946240.png create mode 100644 asset/345936256.png create mode 100644 asset/345988271.png create mode 100644 asset/345995058.png create mode 100644 asset/345995475.png create mode 100644 asset/346001941.png create mode 100644 asset/36365793.png create mode 100644 asset/36365830.mesh create mode 100644 asset/365603813.png create mode 100644 asset/367726197.png create mode 100644 asset/37065186.png create mode 100644 asset/41385900.png create mode 100644 asset/41434307.mesh create mode 100644 asset/41707557.mesh create mode 100644 asset/41708405.png create mode 100644 asset/4639675.png create mode 100644 asset/5009999.png create mode 100644 asset/51498309.png create mode 100644 asset/54031359.mesh create mode 100644 asset/54031415.png create mode 100644 asset/57718359.png create mode 100644 asset/57718450.mesh create mode 100644 asset/60112675.png create mode 100644 asset/60112959.png create mode 100644 asset/60502701.png create mode 100644 asset/6372755229.png create mode 100644 asset/6412503613.png create mode 100644 asset/6444884337.png create mode 100644 asset/6444884785.png create mode 100644 asset/8057767.png create mode 100644 asset/8331089.png create mode 100644 asset/84132548.png create mode 100644 asset/84313478.mesh create mode 100644 asset/84313555.mesh create mode 100644 asset/84313638.png create mode 100644 asset/8798201.png create mode 100644 asset/89348280.png create mode 100644 asset/89627839.png create mode 100644 asset/98151581.png create mode 100644 asset/99170547.png create mode 100644 content/Textures/ArrowCursor.png create mode 100644 content/Textures/ArrowFarCursor.png create mode 100644 content/Textures/ImageError.png create mode 100644 content/Textures/SpawnLocation.png create mode 100644 content/icons/Accessory.png create mode 100644 content/icons/Accoutrement.png create mode 100644 content/icons/Actor.png create mode 100644 content/icons/AdGui.png create mode 100644 content/icons/AdPortal.png create mode 100644 content/icons/AdService.png create mode 100644 content/icons/AdvancedDragger.png create mode 100644 content/icons/AirController.png create mode 100644 content/icons/AlignOrientation.png create mode 100644 content/icons/AlignPosition.png create mode 100644 content/icons/AnalysticsService.png create mode 100644 content/icons/AnalysticsSettings.png create mode 100644 content/icons/AnalyticsService.png create mode 100644 content/icons/AngularVelocity.png create mode 100644 content/icons/Animation.png create mode 100644 content/icons/AnimationClip.png create mode 100644 content/icons/AnimationClipProvider.png create mode 100644 content/icons/AnimationController.png create mode 100644 content/icons/AnimationFromVideoCreatorService.png create mode 100644 content/icons/AnimationFromVideoCreatorStudioService.png create mode 100644 content/icons/AnimationRigData.png create mode 100644 content/icons/AnimationStreamTrack.png create mode 100644 content/icons/AnimationTrack.png create mode 100644 content/icons/Animator.png create mode 100644 content/icons/AppStorageService.png create mode 100644 content/icons/AppUpdateService.png create mode 100644 content/icons/ArcHandles.png create mode 100644 content/icons/AssetCounterService.png create mode 100644 content/icons/AssetDeliveryProxy.png create mode 100644 content/icons/AssetImportService.png create mode 100644 content/icons/AssetImportSession.png create mode 100644 content/icons/AssetManagerService.png create mode 100644 content/icons/AssetService.png create mode 100644 content/icons/AssetSoundEffect.png create mode 100644 content/icons/Atmosphere.png create mode 100644 content/icons/Attachment.png create mode 100644 content/icons/AvatarEditorService.png create mode 100644 content/icons/AvatarImportService.png create mode 100644 content/icons/Backpack.png create mode 100644 content/icons/BackpackItem.png create mode 100644 content/icons/BadgeService.png create mode 100644 content/icons/BallSocketConstraint.png create mode 100644 content/icons/BasePart.png create mode 100644 content/icons/BasePlayerGui.png create mode 100644 content/icons/BaseScript.png create mode 100644 content/icons/BaseWrap.png create mode 100644 content/icons/Beam.png create mode 100644 content/icons/BevelMesh.png create mode 100644 content/icons/BillboardGui.png create mode 100644 content/icons/BinaryStringValue.png create mode 100644 content/icons/BindableEvent.png create mode 100644 content/icons/BindableFunction.png create mode 100644 content/icons/BlockMesh.png create mode 100644 content/icons/BloomEffect.png create mode 100644 content/icons/BlurEffect.png create mode 100644 content/icons/BodyAngularVelocity.png create mode 100644 content/icons/BodyColor.png create mode 100644 content/icons/BodyColors.png create mode 100644 content/icons/BodyForce.png create mode 100644 content/icons/BodyGyro.png create mode 100644 content/icons/BodyMover.png create mode 100644 content/icons/BodyPosition.png create mode 100644 content/icons/BodyThrust.png create mode 100644 content/icons/BodyVelocity.png create mode 100644 content/icons/Bone.png create mode 100644 content/icons/BoolValue.png create mode 100644 content/icons/BoxHandleAdornment.png create mode 100644 content/icons/Breakpoint.png create mode 100644 content/icons/BreakpointManager.png create mode 100644 content/icons/BrickColor.png create mode 100644 content/icons/BrickColorValue.png create mode 100644 content/icons/BrowserService.png create mode 100644 content/icons/BubbleChatConfiguration.png create mode 100644 content/icons/BulkImportService.png create mode 100644 content/icons/BuoyancySensor.png create mode 100644 content/icons/CFrameValue.png create mode 100644 content/icons/CSGDictionaryService.png create mode 100644 content/icons/CacheableContentProvider.png create mode 100644 content/icons/CalloutService.png create mode 100644 content/icons/Camera.png create mode 100644 content/icons/CanvasGroup.png create mode 100644 content/icons/CatalogPages.png create mode 100644 content/icons/ChangeHistoryService.png create mode 100644 content/icons/ChannelSelectorSoundEffect.png create mode 100644 content/icons/CharacterAppearance.png create mode 100644 content/icons/CharacterMesh.png create mode 100644 content/icons/Chat.png create mode 100644 content/icons/ChatInputBarConfiguration.png create mode 100644 content/icons/ChatWindowConfiguration.png create mode 100644 content/icons/ChorusSoundEffect.png create mode 100644 content/icons/ClickDetector.png create mode 100644 content/icons/ClientReplicator.png create mode 100644 content/icons/ClimbController.png create mode 100644 content/icons/Clothing.png create mode 100644 content/icons/Clouds.png create mode 100644 content/icons/ClusterPacketCache.png create mode 100644 content/icons/CollectionService.png create mode 100644 content/icons/Color3Value.png create mode 100644 content/icons/ColorCorrectionEffect.png create mode 100644 content/icons/CommandInstance.png create mode 100644 content/icons/CommandService.png create mode 100644 content/icons/CompressorSoundEffect.png create mode 100644 content/icons/ConeHandleAdornment.png create mode 100644 content/icons/Configuration.png create mode 100644 content/icons/ConfigureServerService.png create mode 100644 content/icons/Constraint.png create mode 100644 content/icons/ContentProvider.png create mode 100644 content/icons/ContextActionService.png create mode 100644 content/icons/Controller.png create mode 100644 content/icons/ControllerBase.png create mode 100644 content/icons/ControllerManager.png create mode 100644 content/icons/ControllerService.png create mode 100644 content/icons/CookiesService.png create mode 100644 content/icons/CoreGui.png create mode 100644 content/icons/CorePackages.png create mode 100644 content/icons/CoreScript.png create mode 100644 content/icons/CoreScriptSyncService.png create mode 100644 content/icons/CornerWedgePart.png create mode 100644 content/icons/CrossDMScriptChangeListener.png create mode 100644 content/icons/CurveAnimation.png create mode 100644 content/icons/CustomEvent.png create mode 100644 content/icons/CustomEventReceiver.png create mode 100644 content/icons/CustomSoundEffect.png create mode 100644 content/icons/CylinderHandleAdornment.png create mode 100644 content/icons/CylinderMesh.png create mode 100644 content/icons/CylindricalConstraint.png create mode 100644 content/icons/DataModel.png create mode 100644 content/icons/DataModelMesh.png create mode 100644 content/icons/DataModelPatchService.png create mode 100644 content/icons/DataModelSession.png create mode 100644 content/icons/DataStore.png create mode 100644 content/icons/DataStoreIncrementOptions.png create mode 100644 content/icons/DataStoreInfo.png create mode 100644 content/icons/DataStoreKey.png create mode 100644 content/icons/DataStoreKeyInfo.png create mode 100644 content/icons/DataStoreKeyPages.png create mode 100644 content/icons/DataStoreListingPages.png create mode 100644 content/icons/DataStoreObjectVersionInfo.png create mode 100644 content/icons/DataStoreOptions.png create mode 100644 content/icons/DataStorePages.png create mode 100644 content/icons/DataStoreService.png create mode 100644 content/icons/DataStoreSetOptions.png create mode 100644 content/icons/DataStoreVersionPages.png create mode 100644 content/icons/Debris.png create mode 100644 content/icons/DebugSettings.png create mode 100644 content/icons/DebuggablePluginWatcher.png create mode 100644 content/icons/DebuggerBreakpoint.png create mode 100644 content/icons/DebuggerConnection.png create mode 100644 content/icons/DebuggerConnectionManager.png create mode 100644 content/icons/DebuggerLuaResponse.png create mode 100644 content/icons/DebuggerManager.png create mode 100644 content/icons/DebuggerUIService.png create mode 100644 content/icons/DebuggerVariable.png create mode 100644 content/icons/Decal.png create mode 100644 content/icons/DepthOfFieldEffect.png create mode 100644 content/icons/DeviceIdService.png create mode 100644 content/icons/Dialog.png create mode 100644 content/icons/DialogChoice.png create mode 100644 content/icons/DistortionSoundEffect.png create mode 100644 content/icons/DockWidgetPluginGui.png create mode 100644 content/icons/DoubleConstrainedValue.png create mode 100644 content/icons/DraftsService.png create mode 100644 content/icons/DragDetector.png create mode 100644 content/icons/Dragger.png create mode 100644 content/icons/DraggerService.png create mode 100644 content/icons/DynamicRotate.png create mode 100644 content/icons/EchoSoundEffect.png create mode 100644 content/icons/EmotesPages.png create mode 100644 content/icons/EqualizerSoundEffect.png create mode 100644 content/icons/EulerRotationCurve.png create mode 100644 content/icons/EventIngestService.png create mode 100644 content/icons/Explosion.png create mode 100644 content/icons/FaceAnimatorService.png create mode 100644 content/icons/FaceControls.png create mode 100644 content/icons/FaceInstance.png create mode 100644 content/icons/FacialAnimationRecordingService.png create mode 100644 content/icons/FacialAnimationStreamingService.png create mode 100644 content/icons/Feature.png create mode 100644 content/icons/File.png create mode 100644 content/icons/FileMesh.png create mode 100644 content/icons/FilteredSelection.png create mode 100644 content/icons/Fire.png create mode 100644 content/icons/Flag.png create mode 100644 content/icons/FlagStand.png create mode 100644 content/icons/FlagStandService.png create mode 100644 content/icons/FlangeSoundEffect.png create mode 100644 content/icons/FloatCurve.png create mode 100644 content/icons/FloorWire.png create mode 100644 content/icons/FlyweightService.png create mode 100644 content/icons/Folder.png create mode 100644 content/icons/ForceField.png create mode 100644 content/icons/FormFactorPart.png create mode 100644 content/icons/Frame.png create mode 100644 content/icons/FriendPages.png create mode 100644 content/icons/FriendService.png create mode 100644 content/icons/FunctionalTest.png create mode 100644 content/icons/GamePassService.png create mode 100644 content/icons/GamepadService.png create mode 100644 content/icons/GenericSettings.png create mode 100644 content/icons/Geometry.png create mode 100644 content/icons/GetTextBoundsParams.png create mode 100644 content/icons/GlobalDataStore.png create mode 100644 content/icons/GlobalSettings.png create mode 100644 content/icons/Glue.png create mode 100644 content/icons/GoogleAnalyticsConfiguration.png create mode 100644 content/icons/GroundController.png create mode 100644 content/icons/GroupService.png create mode 100644 content/icons/GuiBase.png create mode 100644 content/icons/GuiBase2d.png create mode 100644 content/icons/GuiBase3d.png create mode 100644 content/icons/GuiButton.png create mode 100644 content/icons/GuiLabel.png create mode 100644 content/icons/GuiMain.png create mode 100644 content/icons/GuiObject.png create mode 100644 content/icons/GuiService.png create mode 100644 content/icons/GuidRegistryService.png create mode 100644 content/icons/HSRDataContentProvider.png create mode 100644 content/icons/HandleAdornment.png create mode 100644 content/icons/Handles.png create mode 100644 content/icons/HandlesBase.png create mode 100644 content/icons/HapticService.png create mode 100644 content/icons/Hat.png create mode 100644 content/icons/HeightmapImportService.png create mode 100644 content/icons/HeightmapImporterService.png create mode 100644 content/icons/HiddenSurfaceRemovalAsset.png create mode 100644 content/icons/Highlight.png create mode 100644 content/icons/HingeConstraint.png create mode 100644 content/icons/Hint.png create mode 100644 content/icons/Hole.png create mode 100644 content/icons/Hopper.png create mode 100644 content/icons/HopperBin.png create mode 100644 content/icons/HttpRbxApiService.png create mode 100644 content/icons/HttpRequest.png create mode 100644 content/icons/HttpService.png create mode 100644 content/icons/Humanoid.png create mode 100644 content/icons/HumanoidController.png create mode 100644 content/icons/HumanoidDescription.png create mode 100644 content/icons/IKControl.png create mode 100644 content/icons/ILegacyStudioBridge.png create mode 100644 content/icons/IXPService.png create mode 100644 content/icons/ImageButton.png create mode 100644 content/icons/ImageHandleAdornment.png create mode 100644 content/icons/ImageLabel.png create mode 100644 content/icons/ImporterAnimationSettings.png create mode 100644 content/icons/ImporterBaseSettings.png create mode 100644 content/icons/ImporterFacsSettings.png create mode 100644 content/icons/ImporterGroupSettings.png create mode 100644 content/icons/ImporterJointSettings.png create mode 100644 content/icons/ImporterMaterialSettings.png create mode 100644 content/icons/ImporterMeshSettings.png create mode 100644 content/icons/ImporterRootSettings.png create mode 100644 content/icons/IncrementalPatchBuilder.png create mode 100644 content/icons/InputObject.png create mode 100644 content/icons/InsertService.png create mode 100644 content/icons/Instance.png create mode 100644 content/icons/InstanceAdornment.png create mode 100644 content/icons/IntConstrainedValue.png create mode 100644 content/icons/IntValue.png create mode 100644 content/icons/InventoryPages.png create mode 100644 content/icons/JointInstance.png create mode 100644 content/icons/JointsService.png create mode 100644 content/icons/KeyboardService.png create mode 100644 content/icons/Keyframe.png create mode 100644 content/icons/KeyframeMarker.png create mode 100644 content/icons/KeyframeSequence.png create mode 100644 content/icons/KeyframeSequenceProvider.png create mode 100644 content/icons/LSPFileSyncService.png create mode 100644 content/icons/LanguageService.png create mode 100644 content/icons/LayerCollector.png create mode 100644 content/icons/LegacyStudioBridge.png create mode 100644 content/icons/Light.png create mode 100644 content/icons/Lighting.png create mode 100644 content/icons/LineForce.png create mode 100644 content/icons/LineHandleAdornment.png create mode 100644 content/icons/LinearVelocity.png create mode 100644 content/icons/LocalDebuggerConnection.png create mode 100644 content/icons/LocalScript.png create mode 100644 content/icons/LocalStorageService.png create mode 100644 content/icons/LocalizationService.png create mode 100644 content/icons/LocalizationTable.png create mode 100644 content/icons/LodDataEntity.png create mode 100644 content/icons/LodDataService.png create mode 100644 content/icons/LogService.png create mode 100644 content/icons/LoginService.png create mode 100644 content/icons/LuaSettings.png create mode 100644 content/icons/LuaSourceContainer.png create mode 100644 content/icons/LuaWebService.png create mode 100644 content/icons/LuauScriptAnalyzerService.png create mode 100644 content/icons/ManualGlue.png create mode 100644 content/icons/ManualSurfaceJointInstance.png create mode 100644 content/icons/ManualWeld.png create mode 100644 content/icons/MarkerCurve.png create mode 100644 content/icons/MarketplaceService.png create mode 100644 content/icons/MaterialGenerationService.png create mode 100644 content/icons/MaterialService.png create mode 100644 content/icons/MaterialVariant.png create mode 100644 content/icons/MemStorageConnection.png create mode 100644 content/icons/MemStorageService.png create mode 100644 content/icons/MemoryStoreQueue.png create mode 100644 content/icons/MemoryStoreService.png create mode 100644 content/icons/MemoryStoreSortedMap.png create mode 100644 content/icons/MeshContentProvider.png create mode 100644 content/icons/MeshPart.png create mode 100644 content/icons/Message.png create mode 100644 content/icons/MessageBusConnection.png create mode 100644 content/icons/MessageBusService.png create mode 100644 content/icons/MessagingService.png create mode 100644 content/icons/MetaBreakpoint.png create mode 100644 content/icons/MetaBreakpointContext.png create mode 100644 content/icons/MetaBreakpointManager.png create mode 100644 content/icons/Model.png create mode 100644 content/icons/ModuleScript.png create mode 100644 content/icons/Motor.png create mode 100644 content/icons/Motor6D.png create mode 100644 content/icons/MotorFeature.png create mode 100644 content/icons/MouseService.png create mode 100644 content/icons/MultipleDocumentInterfaceInstance.png create mode 100644 content/icons/NegateOperation.png create mode 100644 content/icons/NetworkClient.png create mode 100644 content/icons/NetworkMarker.png create mode 100644 content/icons/NetworkPeer.png create mode 100644 content/icons/NetworkReplicator.png create mode 100644 content/icons/NetworkServer.png create mode 100644 content/icons/NetworkSettings.png create mode 100644 content/icons/NoCollisionConstraint.png create mode 100644 content/icons/NonReplicatedCSGDictionaryService.png create mode 100644 content/icons/NotificationService.png create mode 100644 content/icons/NumberPose.png create mode 100644 content/icons/NumberValue.png create mode 100644 content/icons/ObjectValue.png create mode 100644 content/icons/OrderedDataStore.png create mode 100644 content/icons/OutfitPages.png create mode 100644 content/icons/PVAdornment.png create mode 100644 content/icons/PVInstance.png create mode 100644 content/icons/PackageLink.png create mode 100644 content/icons/PackageService.png create mode 100644 content/icons/PackageUIService.png create mode 100644 content/icons/Pages.png create mode 100644 content/icons/Pants.png create mode 100644 content/icons/ParabolaAdornment.png create mode 100644 content/icons/Part.png create mode 100644 content/icons/PartAdornment.png create mode 100644 content/icons/PartOperation.png create mode 100644 content/icons/PartOperationAsset.png create mode 100644 content/icons/ParticleEmitter.png create mode 100644 content/icons/PatchMapping.png create mode 100644 content/icons/Path.png create mode 100644 content/icons/PathfindingLink.png create mode 100644 content/icons/PathfindingModifier.png create mode 100644 content/icons/PathfindingService.png create mode 100644 content/icons/PausedState.png create mode 100644 content/icons/PausedStateBreakpoint.png create mode 100644 content/icons/PausedStateException.png create mode 100644 content/icons/PermissionsService.png create mode 100644 content/icons/PhysicsService.png create mode 100644 content/icons/PhysicsSettings.png create mode 100644 content/icons/PitchShiftSoundEffect.png create mode 100644 content/icons/Plane.png create mode 100644 content/icons/PlaneConstraint.png create mode 100644 content/icons/Platform.png create mode 100644 content/icons/Player.png create mode 100644 content/icons/PlayerEmulatorService.png create mode 100644 content/icons/PlayerGui.png create mode 100644 content/icons/PlayerMouse.png create mode 100644 content/icons/PlayerScripts.png create mode 100644 content/icons/Players.png create mode 100644 content/icons/Plugin.png create mode 100644 content/icons/PluginAction.png create mode 100644 content/icons/PluginDebugService.png create mode 100644 content/icons/PluginDragEvent.png create mode 100644 content/icons/PluginGui.png create mode 100644 content/icons/PluginGuiService.png create mode 100644 content/icons/PluginManagementService.png create mode 100644 content/icons/PluginManager.png create mode 100644 content/icons/PluginManagerInterface.png create mode 100644 content/icons/PluginMenu.png create mode 100644 content/icons/PluginMouse.png create mode 100644 content/icons/PluginPolicyService.png create mode 100644 content/icons/PluginToolbar.png create mode 100644 content/icons/PluginToolbarButton.png create mode 100644 content/icons/PointLight.png create mode 100644 content/icons/PointsService.png create mode 100644 content/icons/PolicyService.png create mode 100644 content/icons/Pose.png create mode 100644 content/icons/PoseBase.png create mode 100644 content/icons/PostEffect.png create mode 100644 content/icons/PrismaticConstraint.png create mode 100644 content/icons/ProcessInstancePhysicsService.png create mode 100644 content/icons/ProximityPrompt.png create mode 100644 content/icons/ProximityPromptService.png create mode 100644 content/icons/PublishService.png create mode 100644 content/icons/QWidgetPluginGui.png create mode 100644 content/icons/RayValue.png create mode 100644 content/icons/RbxAnalyticsService.png create mode 100644 content/icons/ReflectionMetadata.png create mode 100644 content/icons/ReflectionMetadataCallbacks.png create mode 100644 content/icons/ReflectionMetadataClass.png create mode 100644 content/icons/ReflectionMetadataClasses.png create mode 100644 content/icons/ReflectionMetadataEnum.png create mode 100644 content/icons/ReflectionMetadataEnumItem.png create mode 100644 content/icons/ReflectionMetadataEnums.png create mode 100644 content/icons/ReflectionMetadataEvents.png create mode 100644 content/icons/ReflectionMetadataFunctions.png create mode 100644 content/icons/ReflectionMetadataItem.png create mode 100644 content/icons/ReflectionMetadataMember.png create mode 100644 content/icons/ReflectionMetadataProperties.png create mode 100644 content/icons/ReflectionMetadataYieldFunctions.png create mode 100644 content/icons/RemoteDebuggerServer.png create mode 100644 content/icons/RemoteEvent.png create mode 100644 content/icons/RemoteFunction.png create mode 100644 content/icons/RenderHooksService.png create mode 100644 content/icons/RenderSettings.png create mode 100644 content/icons/RenderingTest.png create mode 100644 content/icons/ReplicatedFirst.png create mode 100644 content/icons/ReplicatedStorage.png create mode 100644 content/icons/ReverbSoundEffect.png create mode 100644 content/icons/RigidConstraint.png create mode 100644 content/icons/RobloxPluginGuiService.png create mode 100644 content/icons/RobloxReplicatedStorage.png create mode 100644 content/icons/RocketPropulsion.png create mode 100644 content/icons/RodConstraint.png create mode 100644 content/icons/RopeConstraint.png create mode 100644 content/icons/RotateP.png create mode 100644 content/icons/RotateV.png create mode 100644 content/icons/RotationCurve.png create mode 100644 content/icons/RtMessagingService.png create mode 100644 content/icons/RunService.png create mode 100644 content/icons/RunningAverageItemDouble.png create mode 100644 content/icons/RunningAverageItemInt.png create mode 100644 content/icons/RunningAverageTimeIntervalItem.png create mode 100644 content/icons/RuntimeScriptService.png create mode 100644 content/icons/ScreenGui.png create mode 100644 content/icons/ScreenshotHud.png create mode 100644 content/icons/Script.png create mode 100644 content/icons/ScriptChangeService.png create mode 100644 content/icons/ScriptCloneWatcher.png create mode 100644 content/icons/ScriptCloneWatcherHelper.png create mode 100644 content/icons/ScriptContext.png create mode 100644 content/icons/ScriptDebugger.png create mode 100644 content/icons/ScriptDocument.png create mode 100644 content/icons/ScriptEditorService.png create mode 100644 content/icons/ScriptRegistrationService.png create mode 100644 content/icons/ScriptService.png create mode 100644 content/icons/ScrollingFrame.png create mode 100644 content/icons/Seat.png create mode 100644 content/icons/Selection.png create mode 100644 content/icons/SelectionBox.png create mode 100644 content/icons/SelectionLasso.png create mode 100644 content/icons/SelectionPartLasso.png create mode 100644 content/icons/SelectionPointLasso.png create mode 100644 content/icons/SelectionSphere.png create mode 100644 content/icons/ServerReplicator.png create mode 100644 content/icons/ServerScriptService.png create mode 100644 content/icons/ServerStorage.png create mode 100644 content/icons/ServiceProvider.png create mode 100644 content/icons/ServiceVisibilityService.png create mode 100644 content/icons/SessionService.png create mode 100644 content/icons/Shirt.png create mode 100644 content/icons/ShirtGraphic.png create mode 100644 content/icons/ShorelineUpgraderService.png create mode 100644 content/icons/SkateboardController.png create mode 100644 content/icons/SkateboardPlatform.png create mode 100644 content/icons/Skin.png create mode 100644 content/icons/Sky.png create mode 100644 content/icons/SlidingBallConstraint.png create mode 100644 content/icons/Smoke.png create mode 100644 content/icons/Snap.png create mode 100644 content/icons/SnippetService.png create mode 100644 content/icons/SocialService.png create mode 100644 content/icons/SolidModelContentProvider.png create mode 100644 content/icons/Sound.png create mode 100644 content/icons/SoundEffect.png create mode 100644 content/icons/SoundGroup.png create mode 100644 content/icons/SoundService.png create mode 100644 content/icons/Sparkles.png create mode 100644 content/icons/SpawnLocation.png create mode 100644 content/icons/SpawnerService.png create mode 100644 content/icons/Speaker.png create mode 100644 content/icons/SpecialMesh.png create mode 100644 content/icons/SphereHandleAdornment.png create mode 100644 content/icons/SpotLight.png create mode 100644 content/icons/SpringConstraint.png create mode 100644 content/icons/StackFrame.png create mode 100644 content/icons/StandalonePluginScripts.png create mode 100644 content/icons/StandardPages.png create mode 100644 content/icons/StarterCharacterScripts.png create mode 100644 content/icons/StarterGear.png create mode 100644 content/icons/StarterGui.png create mode 100644 content/icons/StarterPack.png create mode 100644 content/icons/StarterPlayer.png create mode 100644 content/icons/StarterPlayerScripts.png create mode 100644 content/icons/Stats.png create mode 100644 content/icons/StatsItem.png create mode 100644 content/icons/Status.png create mode 100644 content/icons/StopWatchReporter.png create mode 100644 content/icons/StringValue.png create mode 100644 content/icons/Studio.png create mode 100644 content/icons/StudioAssetService.png create mode 100644 content/icons/StudioData.png create mode 100644 content/icons/StudioDeviceEmulatorService.png create mode 100644 content/icons/StudioHighDpiService.png create mode 100644 content/icons/StudioPublishService.png create mode 100644 content/icons/StudioScriptDebugEventListener.png create mode 100644 content/icons/StudioService.png create mode 100644 content/icons/StudioTheme.png create mode 100644 content/icons/SunRaysEffect.png create mode 100644 content/icons/SurfaceAppearance.png create mode 100644 content/icons/SurfaceGui.png create mode 100644 content/icons/SurfaceGuiBase.png create mode 100644 content/icons/SurfaceLight.png create mode 100644 content/icons/SurfaceSelection.png create mode 100644 content/icons/SwimController.png create mode 100644 content/icons/Team.png create mode 100644 content/icons/TeamCreateService.png create mode 100644 content/icons/Teams.png create mode 100644 content/icons/TeleportAsyncResult.png create mode 100644 content/icons/TeleportOptions.png create mode 100644 content/icons/TeleportService.png create mode 100644 content/icons/TemporaryCageMeshProvider.png create mode 100644 content/icons/TemporaryScriptService.png create mode 100644 content/icons/Terrain.png create mode 100644 content/icons/TerrainDetail.png create mode 100644 content/icons/TerrainRegion.png create mode 100644 content/icons/TestService.png create mode 100644 content/icons/TextBox.png create mode 100644 content/icons/TextBoxService.png create mode 100644 content/icons/TextButton.png create mode 100644 content/icons/TextChannel.png create mode 100644 content/icons/TextChatCommand.png create mode 100644 content/icons/TextChatConfigurations.png create mode 100644 content/icons/TextChatMessage.png create mode 100644 content/icons/TextChatMessageProperties.png create mode 100644 content/icons/TextChatService.png create mode 100644 content/icons/TextFilterResult.png create mode 100644 content/icons/TextLabel.png create mode 100644 content/icons/TextService.png create mode 100644 content/icons/TextSource.png create mode 100644 content/icons/Texture.png create mode 100644 content/icons/ThirdPartyUserService.png create mode 100644 content/icons/ThreadState.png create mode 100644 content/icons/TimerService.png create mode 100644 content/icons/ToastNotificationService.png create mode 100644 content/icons/Tool.png create mode 100644 content/icons/ToolScript.png create mode 100644 content/icons/ToolboxService.png create mode 100644 content/icons/Torque.png create mode 100644 content/icons/TorsionSpringConstraint.png create mode 100644 content/icons/TotalCountTimeIntervalItem.png create mode 100644 content/icons/TouchInputService.png create mode 100644 content/icons/TouchTransmitter.png create mode 100644 content/icons/TracerService.png create mode 100644 content/icons/TrackerStreamAnimation.png create mode 100644 content/icons/Trail.png create mode 100644 content/icons/Translator.png create mode 100644 content/icons/TremoloSoundEffect.png create mode 100644 content/icons/TriangleMeshPart.png create mode 100644 content/icons/TrussPart.png create mode 100644 content/icons/Tween.png create mode 100644 content/icons/TweenBase.png create mode 100644 content/icons/TweenService.png create mode 100644 content/icons/UGCAvatarService.png create mode 100644 content/icons/UGCValidationService.png create mode 100644 content/icons/UIAspectRatioConstraint.png create mode 100644 content/icons/UIBase.png create mode 100644 content/icons/UIComponent.png create mode 100644 content/icons/UIConstraint.png create mode 100644 content/icons/UICorner.png create mode 100644 content/icons/UIGradient.png create mode 100644 content/icons/UIGridLayout.png create mode 100644 content/icons/UIGridStyleLayout.png create mode 100644 content/icons/UILayout.png create mode 100644 content/icons/UIListLayout.png create mode 100644 content/icons/UIPadding.png create mode 100644 content/icons/UIPageLayout.png create mode 100644 content/icons/UIScale.png create mode 100644 content/icons/UISizeConstraint.png create mode 100644 content/icons/UIStroke.png create mode 100644 content/icons/UITableLayout.png create mode 100644 content/icons/UITextSizeConstraint.png create mode 100644 content/icons/UnionOperation.png create mode 100644 content/icons/UniversalConstraint.png create mode 100644 content/icons/UnvalidatedAssetService.png create mode 100644 content/icons/UserGameSettings.png create mode 100644 content/icons/UserInputService.png create mode 100644 content/icons/UserService.png create mode 100644 content/icons/UserSettings.png create mode 100644 content/icons/UserStorageService.png create mode 100644 content/icons/VRService.png create mode 100644 content/icons/ValueBase.png create mode 100644 content/icons/Vector3Curve.png create mode 100644 content/icons/Vector3Value.png create mode 100644 content/icons/VectorForce.png create mode 100644 content/icons/VehicleController.png create mode 100644 content/icons/VehicleSeat.png create mode 100644 content/icons/VelocityMotor.png create mode 100644 content/icons/VersionControlService.png create mode 100644 content/icons/VideoCaptureService.png create mode 100644 content/icons/VideoFrame.png create mode 100644 content/icons/ViewportFrame.png create mode 100644 content/icons/VirtualInputManager.png create mode 100644 content/icons/VirtualUser.png create mode 100644 content/icons/VisibilityService.png create mode 100644 content/icons/Visit.png create mode 100644 content/icons/VoiceChannel.png create mode 100644 content/icons/VoiceChatInternal.png create mode 100644 content/icons/VoiceChatService.png create mode 100644 content/icons/VoiceSource.png create mode 100644 content/icons/WedgePart.png create mode 100644 content/icons/Weld.png create mode 100644 content/icons/WeldConstraint.png create mode 100644 content/icons/WireframeHandleAdornment.png create mode 100644 content/icons/Workspace.png create mode 100644 content/icons/WorldModel.png create mode 100644 content/icons/WorldRoot.png create mode 100644 content/icons/WrapLayer.png create mode 100644 content/icons/WrapLayerYellowWarning.png create mode 100644 content/icons/WrapTarget.png create mode 100644 content/icons/WrapTargetYellowWarning.png create mode 100644 content/icons/shield_go.png create mode 100644 content/sky/null_plainsky512_bk.jpg create mode 100644 content/sky/null_plainsky512_dn.jpg create mode 100644 content/sky/null_plainsky512_ft.jpg create mode 100644 content/sky/null_plainsky512_lf.jpg create mode 100644 content/sky/null_plainsky512_rt.jpg create mode 100644 content/sky/null_plainsky512_up.jpg create mode 100644 examples/City.rbxl create mode 100644 examples/Classic-Crossroads.rbxl create mode 100644 examples/Dilapidated-House.rbxm create mode 100644 examples/Suburban.rbxl create mode 100644 examples/Western-Lounge.rbxm create mode 100644 favicon.ico create mode 100644 images/assets.png create mode 100644 images/billboard.png create mode 100644 images/car.png create mode 100644 images/cashier.png create mode 100644 images/crossroads8k.png create mode 100644 images/explorer.png create mode 100644 images/fridge.png create mode 100644 images/house.png create mode 100644 images/library.png create mode 100644 images/lounge.png create mode 100644 images/render.png create mode 100644 images/screen.png create mode 100644 images/script.png create mode 100644 images/suburban8k.png create mode 100644 images/three.png create mode 100644 index.html diff --git a/README.md b/README.md new file mode 100644 index 0000000..66fa177 --- /dev/null +++ b/README.md @@ -0,0 +1,138 @@ +# Studio Lite +A web viewer for _Roblox[^1]_ place and model files, with a gorgeous interface. + +![Screenshot of Studio Lite](images/screen.png) + +## This is still in alpha +Expect bugs and unfinished features + +## Acknowledgements +Studio Lite uses the [rbxBinaryParser](https://github.com/MrSprinkleToes/rbxBinaryParser) library by [MrSprinkleToes](https://github.com/MrSprinkleToes). Additionally, some code, mostly mesh parsing code, is taken from [roblox-in-webbrowser](https://github.com/MrSprinkleToes/roblox-in-webbrowser) and [roblox-web-viewer](https://github.com/MrSprinkleToes/roblox-web-viewer). + +These other libraries are also used: +* [THREE.js](https://threejs.org/) for rendering +* [7.css](https://khang-nd.github.io/7.css/) for that gorgeous user interface +* [jsTree](https://www.jstree.com/) for displaying interactive trees + +## Included assets +For demo purposes, Studio Lite includes some downloaded assets in the `asset/` directory and some place files in `examples/`. Please note that these files are copyright of their respective owners. + +The _Roblox[^1]_ Studio icons, used in the title bar and Explorer view, and stored under the `content/icons/` directory, are copyright of Roblox Corporation. + +Other assets within the `content/` directory, as well as the `favicon.ico` in the root of the source tree, are also copyright of Roblox Corporation. + +Studio Lite is not affiliated with, or endorsed by Roblox Corporation. + +## Features +### Read RBXL and RBXM files +![City.rbxl with a part selected in Explorer](images/explorer.png) +![Script viewer](images/script.png) +![THREE.js Scene Explorer](images/three.png) + +These file types can be opened by Studio Lite. Keep in mind that there is no support for files in the XML format (though it is a high priority), so you'll encounter issues especially with older places (which often have RBXL extension but contain XML data). + +You can use the Explorer and Properties views to browse the contents of the DataModel. You can click on scripts to view their code. Parts selected in the Explorer are highlighted in the renderer, and you can also zoom to the currently selected part. + +### Asset support +![Closeup of a billboard](images/billboard.png) +![Drinks in a fridge](images/fridge.png) +![View of convenience store](images/cashier.png) +![Library with many books](images/library.png) +![View of the City template out a car windshield](images/car.png) +![List of missing assets](images/assets.png) + +Studio Lite can load decals and meshes accurately! In light of _Roblox[^1]_'s API changes, you must manually download assets using AssetDelivery and place them in the `asset/` folder. This is made easy as you get a list of all missing assets along with their type upon loading a Place. + +### Perfect for renders +![Render Image dialog](images/render.png) + +You can render the current view to a PNG file at any resolution you want. Do you want [a top-down view of Crossroads in 8K resolution](images/crossroads8k.png)? No problem. + +_Also, here's [an 8K render of the Suburban map](images/suburban8k.png), for those interested. Caution, large file, about 2 MB!_ + +![Western Lounge thumbnail](images/lounge.png) +![Dilapidated House thumbnail](images/house.png) + +You can also hide the skybox, leaving a transparent background. This is useful for thumbnails. You can open a model file, hide the skybox and render a 420x420 image. This will produce a thumbnail similar to those on the _Roblox[^1]_ website. (see examples above) + +## How to use +Studio Lite makes many network requests, so I've refrained from hosting a live demo in fear of rate limits. It is very easy to run yourself, though, being a fully client-side application. + +All you need is a decent computer and an HTTP server. Download these files (you can clone the repo or just download as ZIP) and run a web server in the root directory. + +If you have Python installed, it's very easy to run a local server: `python -m http.server`. Then you can access Studio Lite on `localhost:8000`. Otherwise, use your preferred method of starting up a quick server (you can use Node.js or PHP). + +If you have any issues or are unsatisfied with your experience, please open an issue! + +## How to download assets +Read the first section to learn how the download process works. Then read the second section, which shows you how to get the AssetIDs you need to download. + +### The download process itself +Due to _Roblox[^1]_ API changes, you must be logged in to access AssetDelivery. Therefore, you must be signed into your _Roblox[^1]_ account on the browser. + +While my experimentation has shown that you can download _Roblox[^1]_-owned assets anonymously, authentication is required otherwise. + +To download an asset, copy the Asset ID (the long number) and navigate to the URL below, first replacing `[assetid]` with the Asset ID you've copied. + +AssetDelivery URL: `https://assetdelivery.roblox.com/v1/asset?id=[assetid]` + +This will download a file with a random name. Rename it like you're told in the second section. + +### Downloading all assets in a Place +1. Open a Place containing un-downloaded assets. +2. Look in the console. If it says that there are missing assets, then go to `File > Missing assets` like it tells you. +3. Browse the list. For each line, if it is a decal, download the asset and rename it to `[assetid].png`, where `[assetid]` is the AssetID. If it is a mesh, do the same but use `.mesh` extension. Download all of the mesh's textures (if any) with the `.png` extension. +4. If you're done, reload the page and open your Place again. You shouldn't get the console warning, and `File > Missing assets` should say all assets have loaded successfully. + +### Possible errors while downloading +You may encounter some errors during asset downloads, which will get you a JSON response. + +##### Authentication required / User not authorized +JSON response: `{"errors":[{"code":0,"message":"Authentication required to access Asset."}]}` + +Alternatively: `{"errors":[{"code":1,"message":"User is not authorized to access Asset."}]}` + +You need to log in to download the asset. If you're logged in on the _Roblox[^1]_ website, but still get this error, the asset could be private or something. Idk. + +##### Requested asset is archived +JSON response: `{"errors":[{"code":0,"message":"Requested asset is archived"}]}` + +Exactly what it says on the tin. You're not getting the asset :) + +You could put a placeholder image in its place, to silence the Missing assets error... + +## Roadmap (WIP) +- [ ] Fix bugs +- - [ ] Issues with mesh Scale and Offset (see comments in `StudioLiteRenderer.renderPart`, around where it says `// Give meshes special treatment`) +- - [ ] Upside down decals (see paintings in suburban house and piano in western lounge) +- - [ ] Merry-go-round in Suburban playground is broken (base renders sideways) +- [ ] Support XML format +- [ ] Support all primitive shapes +- - [x] Block +- - [x] Ball +- - [x] Wedge +- - [x] Cylinder (for the most part, see bugs) +- - [ ] Truss +- [ ] Cool effects +- - [ ] Show light for parts with [Light](https://create.roblox.com/docs/reference/engine/classes/Light) children +- - [ ] ParticleEmitter support +- - [ ] Fire and Smoke +- - [ ] Glow for parts with Neon material +- [ ] Completionist questline (impossible) +- - [ ] Support part materials +- - [ ] Basic support for rendering Smooth Terrain (really, this is a problem of reading terrain voxels, which might very well be impossible) +- - [ ] hmm... ~~Edit Mode~~ (lol no... but maybe one day?) + +## Licensing +Studio Lite is **MIT licensed**. However, the following files and directories in the source tree are exempt from licensing: +* `asset/` (non-free assets) +* `content/` (non-free assets) +* `examples/` (non-free assets) +* `favicon.ico` (non-free asset) +* `app/rendering/mesh/MeshParser.js` (contains mesh parsing code from `roblox-in-webbrowser`/`roblox-web-viewer`, which are unlicensed. Please see **Acknowledgements**) +* `app/controls/FlyCamera.js` (contains camera code from `roblox-web-viewer`, which is unlicensed. See **Acknowledgements**) + +## How you can help +Contributions are welcome! You don't need to write any code, I'll be very happy if you told me what you didn't like, or what you'd like added. + +[^1]: _Roblox_ is a registered trademark of Roblox Corporation. \ No newline at end of file diff --git a/app/app.css b/app/app.css new file mode 100644 index 0000000..86206c4 --- /dev/null +++ b/app/app.css @@ -0,0 +1,241 @@ +body { + margin: 0; + font-family: sans-serif; + --window-background-color: #805ba5; +} + +dialog { + background-color: #ffffffff; + border: none; + padding: 0; +} + +.rightPane { + height: calc(100vh - 29px - 29px - 27px + 4px); + width: 400px; + position: absolute; + top: 56px; + left: calc(100vw - 400px); + background-color: white; + overflow: hidden; + z-index: 2; +} + +.console { + position: absolute; + height: calc(200px - 22px); + width: calc(100vw - 400px); + top: calc(100vh - 206px); + background-color: white; + overflow: hidden; +} + +.title { + height: 20px; + padding: 5px; + border-bottom: 5px solid black; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.title-bar-text { + width: 100%; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.tree, .tree2, .properties { + --height: calc(50vh - 29px - 14.5px - 17px - 13.5px - 6px + 2px); + overflow: scroll; + width: 385px; +} + +.tree, .tree2 { + height: calc(var(--height) - 23px); +} + +.properties { + height: var(--height); +} + +table { + min-width: 100%; +} + +th, td { + text-align: left; +} + +/* taken from 7.css "highlighted" rule */ +table > tbody > tr:hover { + background: var(--item-highlighted-background); + border: var(--listview-border) var(--item-highlighted-border); + border-radius: var(--border-radius); +} + +.message, .onboarding { + position: absolute; + width: calc(100vw - 400px); + height: calc(100vh - 200px - 29px - 29px); + background-color: rgba(221, 221, 221, .5); + display: flex; + justify-content: center; + align-items: center; + color: white; + font-size: 22px; + text-shadow: 2px 0 #000, -2px 0 #000, 0 2px #000, 0 -2px #000, + 1px 1px #000, -1px -1px #000, 1px -1px #000, -1px 1px #000; + cursor: url(../content/Textures/ArrowFarCursor.png), auto; +} + +.onboarding { + flex-direction: column; +} + +.onboarding > h1 { + width: fit-content; + font-size: 44px; +} + +.onboarding > button { + font-size: 40px; +} + +.onboarding > :is(button, input, label), +#stats, #stats > * { + cursor: url(../content/Textures/ArrowCursor.png), auto !important; +} + +.editor { + position: absolute; + width: calc(100vw - 410px); + height: calc(100vh - 215px - 29px - 29px); + background-color: white; + color: black; + padding: 5px; + font-size: 22px; + font-family: monospace; + overflow: scroll; + z-index: 10001; +} + +.log { + height: calc(100% - 35px); + width: calc(100% - 12px); + overflow: scroll; + font-family: monospace; + font-size: 18px; +} + +pre { + border: none; +} + +body > .title-bar { + position: absolute; + width: calc(100vw - 14px); + z-index: 10002; + top: 0; + left: 0; +} + +body > ul[role=menubar] { + position: absolute; + top: 29px; + left: 0; + width: 100vw; + z-index: 10002; +} + +canvas { + margin-top: 58px; + cursor: url(../content/Textures/ArrowFarCursor.png), auto; +} + +.status-bar { + position: absolute; + top: calc(100vh - 27px); + width: calc(100vw - 2px); + margin: 0; + z-index: 3; +} + +.flexcenter { + display: flex; + align-items: center; + justify-content: center; +} + +.status-bar-field > *[role=progressbar] { + width: 100%; +} + +.marquee.error:before { + background: linear-gradient(to right,transparent,var(--progress-color-error),transparent 35%); +} + +/* yellow is not for paused, but for fetching :) */ +.marquee.paused:before { + background: linear-gradient(to right,transparent,var(--progress-color-paused),transparent 35%); +} + +.title-bar-icon { + padding-left: 20px; + background-repeat: no-repeat; + background-position: left bottom; +} + +.icon-studio { + background-image: url(../content/icons/StudioService.png); +} + +#notepad .window-body { + width: 700px; + height: 400px; +} + +#notepad textarea { + width: 100%; + height: calc(100% - 29px); + resize: none; + font-size: 16px; + font-family: monospace; +} + +.title-bar, .status-bar-field { + height: 21px; +} + +*[role=menubar] { + height: 29px; +} + +.status-bar { + height: 25px; +} + +.title-bar, *[role=menubar], *[role=tablist], .tree2, .message, .onboarding, .tree, td:first-child, .status-bar { + user-select: none; +} + +.menu[role=tablist] { + height: 23px; +} + +.github { + color: black; + padding-left: 5px !important; + padding-right: 5px !important; + text-shadow: 0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff; +} + +.github::before { + background: none !important; +} + +.title-bar.active .github, .title-bar.active .github::before { + background: var(--control-background) !important; +} \ No newline at end of file diff --git a/app/app.js b/app/app.js new file mode 100644 index 0000000..e76ae53 --- /dev/null +++ b/app/app.js @@ -0,0 +1,697 @@ +import Stats from './thirdparty/three/stats.module.js'; +import { + StudioLiteRenderer, + partClasses +} from './rendering/StudioLiteRenderer.js'; +import { + sleep, + rgbToHex +} from './etc/Helpers.js'; + +const titleBar = document.body.querySelector(".title-bar"); +const sstat = document.body.querySelector("#menuitem-stats"); +const saxes = document.body.querySelector("#menuitem-axes"); +const sbx2 = document.body.querySelector("#menuitem-hoverbox"); +const sbox = document.body.querySelector("#menuitem-selectionbox"); +const szoom = document.body.querySelector("#menuitem-zoomto"); +const ssky = document.body.querySelector("#menuitem-skybox"); +const log = document.body.querySelector(".log"); +const msg = document.body.querySelector(".message"); +const editor = document.body.querySelector(".editor"); +const bar = document.body.querySelector(".status-bar-field > *[role=progressbar]"); +const status = document.body.querySelector(".status-bar-field.status"); +const menurender = document.body.querySelector("#menuitem-renderimage"); +menurender.setAttribute("aria-disabled", true); +let sal = document.body.querySelector(".onboarding"); +let statusLastText = "Ready"; +szoom.setAttribute("aria-disabled", true); + +var jsTreeData = []; + +const threeIcons = { + "AmbientLight": "Lighting", + "DirectionalLight": "Lighting", + "Mesh": "Part", + "BoxHelper": "SelectionBox" +} + +function threeNodeToTreeData(node) { + let data = []; + for (const child of node) { + data.push({ + node: child, + text: child.name.length > 0 ? child.name : child.type, + icon: `content/icons/${threeIcons[child.type] ? threeIcons[child.type] : "BaseScript"}.png`, + children: threeNodeToTreeData(child.children) + }); + } + return data; +} +let treeRefresh2 = () => {}; + +let renderer = new StudioLiteRenderer({ + get width() { + return window.innerWidth - 400; + }, + get height() { + return window.innerHeight - 200 - 29 - 34; + }, + sharedFunctions: { + print: print, + treeRefresh2: () => { treeRefresh2(); } + }, + sharedObjects: { + jsTreeData: jsTreeData + } +}); +document.body.appendChild(renderer.domElement); + +const stats = Stats(); +document.body.appendChild(stats.dom); +stats.dom.id = "stats"; +stats.dom.style.display = "none"; +if (sstat.checked) stats.dom.style.display = "block"; +sstat.addEventListener("input", () => { + if (sstat.checked) { + stats.dom.style.display = "block"; + } else { + stats.dom.style.display = "none"; + } +}); + +let rendering = false; +var animate = function () { + if (rendering) renderer.render(); + stats.update(); +} + +renderer.setAnimationLoop(animate); + +function print(s) { + const date = new Date(); + const el = document.createElement("span"); + const br = document.createElement("br"); + if (typeof s === "object") s = JSON.stringify(s); + el.innerText = `${date.toLocaleTimeString("us")}.${date.getMilliseconds().toString().padStart(3, '0')} - ${s}`; + log.appendChild(el); + log.appendChild(br); + log.scrollTo(0, log.scrollHeight); +} + +window.console.log = (...args) => { + let s = ""; + for (let t of args) { + if (typeof t === "object") t = JSON.stringify(t); + s += t + " "; + } + s = s.substring(0, s.length - 1).split("\n"); + for (const t of s) print(t); +} + +function setTitle(t) { + t = `${t} - Studio Lite (alpha-1)`; + document.title = t; + titleBar.querySelector(".title-bar-text").innerText = t; +} + +let file = ""; + +let placeName = "Start Page"; + +function barError() { + bar.classList.add("error"); +} + +function objToTreeData(obj) { + let keys = Object.keys(obj); + let data = []; + for (let key of keys) { + let d = {}; + d.text = key; + if (typeof obj[key] === "object") { + d.children = objToTreeData(obj[key]); + } else { + d.text += ": " + obj[key].toString(); + d.children = []; + } + data.push(d); + } + return data; +} + +async function start() { + bar.className = "marquee paused"; + status.innerText = "Busy"; + rendering = false; + titleBar.classList.add("active"); + try { document.body.removeChild(document.body.querySelector("#remoteload")); } catch (ignored) {}; + document.body.removeChild(sal); + sal = null; + msg.querySelector("span").innerText = "Loading Place. Please wait..."; + msg.style.display = "flex"; + const url = new URL(file, window.location.href); + try { + if (typeof file === "string") { + print (`DataModel Loading ${url}`); + placeName = url.href.split("/").pop(); + status.innerText = `Fetching ${placeName}`; + let fileData = null; + try { + fileData = await fetch(url); + if (fileData.status !== 200) throw new Error(); + } catch (ignored) { + print('Failed to fetch. Please reload.'); + barError(); + throw new Error("Failed to fetch. Please reload."); + } + window.data = await fileData.arrayBuffer(); + // we read it successfully, make the bar green from now on! + bar.classList.remove("paused"); + status.innerText = `Loading ${placeName}`; + await sleep(200); + } else { + print (`DataModel Loading ${file.name}`); + placeName = file.name; + status.innerText = `Fetching ${placeName}`; + window.data = await file.arrayBuffer(); + // we read it successfully, make the bar green from now on! + bar.classList.remove("paused"); + status.innerText = `Loading ${placeName}`; + await sleep(200); + } + } catch (ignored) { + print('The file could not be read. Please reload.'); + barError(); + throw new Error("The file could not be read. Please reload."); + } + setTitle(placeName); + statusLastText = status.innerText; + try { + await renderer.loadPlace(window.data); + } catch (ignored) { + print('The file could not be read. Please reload.'); + barError(); + throw new Error("The file could not be read. Please reload."); + } + delete window.data; + + renderer.toggleAxes(saxes.checked); + saxes.addEventListener("input", () => { + renderer.toggleAxes(saxes.checked); + treeRefresh2(); + }) + + renderer.showSkybox(ssky.checked); + ssky.addEventListener("input", () => { + renderer.showSkybox(ssky.checked); + }) + renderer.useSelectionBox = sbox.checked; + sbox.addEventListener("input", () => { + renderer.useSelectionBox = sbox.checked; + renderer.removeSelectionBoxesIfNeeded(); + }) + renderer.useSelectionBox2 = sbx2.checked; + sbx2.addEventListener("input", () => { + renderer.useSelectionBox2 = sbx2.checked; + renderer.removeSelectionBoxesIfNeeded(); + }) + + $(".tree").jstree({'core' : { + 'data' : jsTreeData + }}); + + let treeRef = $(".tree").jstree(true); + + const zoomTo = () => { + try { + const instance = treeRef.get_selected(true)[0].original.instance; + if (partClasses.indexOf(instance.ClassName) !== -1) { + try { + renderer.zoomTo(instance.CFrame || instance.CoordinateFrame, false); + } catch (ignored) {}; + } + } catch (ignored) {}; + }; + + szoom.setAttribute("aria-disabled", true); + szoom.addEventListener("click", zoomTo); + document.addEventListener("keydown", e => { + switch (e.code) { + case "KeyF": + zoomTo(); + break; + } + }); + + const hiddenProperties = ["Children", "Source", "CollisionGroupData", "PhysicsGrid", "SmoothGrid", "MaterialColors"]; + const dropdownProperties = [ + "BackSurface", "BackSurfaceInput", "BottomSurfaceInput", + "FrontSurface", "FrontSurfaceInput", "LeftSurface", + "LeftSurfaceInput", "Material", "RightSurface", + "RightSurfaceInput", "TopSurface", "TopSurfaceInput", + "Shape", "Classic", "DevCameraOcclusionMode", + "DevComputerCameraMovementMode", "DevComputerMovementMode", "DevTouchCameraMovementMode", + "DevTouchMovementMode", "EnableDynamicHeads", "GameSettingsAvatar", + "GameSettingsR15Collision", "ScreenOrientation", "VirtualCursorMode", + "Technology", "VolumetricAudio", "AmbientReverb", + "ClientAnimatorThrottling", "InterpolationThrottling", "InterpolationThrottling", + "MeshPartHeadsAndAccessories", "ModelStreamingMode", "PhysicsSteppingMethod", + "RejectCharacterDeletions", "ReplicateInstanceDestroySetting", "Retargeting", + "StreamOutBehavior", "StreamingIntegrityMode", "Face", + "RenderFidelity", "CameraType", "FieldOfViewMode", + "RunContext", "SelectionBehaviorDown", "SelectionBehaviorLeft", + "SelectionBehaviorRight", "SelectionBehaviorUp", "SizingMode", + "ZIndexBehavior", "RollOffMode", "AutomaticSize", + "BorderMode", "SizeConstraint", "Style", + "LevelOfDetail", "HorizontalAlignment", "VerticalAlignment", + "TextXAlignment", "TextYAlignment", "ScaleType", + "AspectType", "DominantAxis", "BottomSurface", + "CollisionType", "DisplayDistanceType", "HealthDisplayType", + "NameOcclusion", "RigType" + ]; + const colorProperties = [ + "Color3", "TintColor", "Ambient", "ColorShift_Top", "ColorShift_Bottom", + "FogColor", "OutdoorAmbient", "BackgroundColor3", "BorderColor3", "ImageColor3", + "TextColor3", "PlaceholderColor3", "TextStrokeColor3" + ]; + + function parsePropValue(prop, value) { + switch (prop) { + default: + return value.toString(); + } + } + + $('.tree').on("changed.jstree", async function (e, data) { + const original = treeRef.get_node(data.selected[0]).original; + let instance = original.instance; + (async () => { + if (original.id) renderer.updateSelectionBox(renderer.getThreeId(original.id)); + })(); + if (instance.CFrame) renderer.setAxesPosition(instance.CFrame.Position.X, instance.CFrame.Position.Y, instance.CFrame.Position.Z); + if (partClasses.indexOf(instance.ClassName) !== -1 && (instance.CFrame || instance.CoordinateFrame)) + szoom.removeAttribute("aria-disabled"); + else + szoom.setAttribute("aria-disabled", true); + document.body.querySelector("#propertiesTitle").innerText = `Properties - ${instance.ClassName} "${instance.Name}"`; + let keys = Object.keys(instance); + let objviewIndex = 0; + let treedatatemp = null; + propTable.innerHTML = ""; + propSpinner.style.display = "block"; + propTable.style.display = "none"; + if (["Script", "LocalScript", "ModuleScript"].indexOf(instance.ClassName) !== -1) { + setTitle(instance.Name); + editor.style.display = "block"; + editor.innerHTML = ""; + const pre = document.createElement("pre"); + pre.innerText = instance.Source; + editor.appendChild(pre); + rendering = false; + } else { + rendering = true; + setTitle(placeName); + editor.innerHTML = ""; + editor.style.display = "none"; + } + for (let key of keys) { + if (hiddenProperties.indexOf(key) === -1) { + let row = document.createElement("tr"); + let one = document.createElement("td"); + let two = document.createElement("td"); + one.innerText = key; + if (typeof instance[key] === "object") { + let objview = document.createElement("div"); + if (colorProperties.indexOf(key) !== -1) { + const val = instance[key]; + let clr = document.createElement("input"); + clr.type = "color"; + clr.disabled = true; + clr.value = rgbToHex(val.R*255, val.G*255, val.B*255); + two.appendChild(clr); + } + two.appendChild(objview); + objview.id = `objview-${objviewIndex}`; + treedatatemp = {'core' : { + 'data' : objToTreeData(instance[key]) + }}; + } else if ([true, false].indexOf(instance[key]) !== -1) { + let chk = document.createElement("input"); + chk.disabled = "true"; + chk.type = "checkbox"; + chk.id = "checkbox-" + key; + if (instance[key]) chk.checked = true; + let txt = document.createElement("label"); + txt.for = "checkbox-" + key; + two.appendChild(chk); + two.appendChild(txt); + } else if (typeof instance[key] === "number") { + let nr = document.createElement("input"); + nr.type = "number"; + nr.min = instance[key]; + nr.max = instance[key]; + nr.value = instance[key]; + nr.disabled = true; + two.appendChild(nr); + } else if (dropdownProperties.indexOf(key) !== -1) { + let sel = document.createElement("select"); + let opt = document.createElement("option"); + opt.innerText = instance[key]; + opt.selected = true; + sel.disabled = true; + sel.appendChild(opt); + two.appendChild(sel); + } else { + two.innerText = parsePropValue(key, instance[key]); + } + row.appendChild(one); + row.appendChild(two); + propTable.appendChild(row); + if (treedatatemp !== null) { + $(`#objview-${objviewIndex}`).jstree(treedatatemp); + objviewIndex++; + treedatatemp = null; + } + } + } + propSpinner.style.display = "none"; + propTable.style.display = "table-row-group"; + }); + + rendering = true; + msg.style.display = "none"; + statusLastText = "Busy"; + status.innerText = "Busy"; + + async function postQueue() { + if (renderer.mAssetManager.hasRbxGameAsset) print("This Place contains rbxgameasset:// paths. Studio Lite cannot resolve them, as they are relative to the published game!"); + if (renderer.mAssetManager.computeMissingAssetsList()) print("Some assets failed to load! See File > Missing assets for more info."); + treeRefresh2(); + menurender.removeAttribute("aria-disabled"); + menurender.addEventListener("click", () => { + rendering = false; + const dlg = document.body.querySelector("#render"); + const btn = dlg.querySelector("#dorender"); + const img = dlg.querySelector("img"); + const width = dlg.querySelector("#renderwidth"); + const height = dlg.querySelector("#renderheight"); + width.value = renderer.conf.width; + height.value = renderer.conf.height; + let doRender = () => { + img.src = renderer.renderImage(width.value, height.value); + } + let close = () => { + dlg.removeEventListener("cancel", close); + dlg.querySelector(".close").removeEventListener("click", close); + dlg.querySelector(".ok").removeEventListener("click", close); + btn.removeEventListener("click", doRender); + img.src = ""; + dlg.close(); + titleBar.classList.add("active"); + rendering = true; + } + dlg.addEventListener("cancel", close); + titleBar.classList.remove("active"); + dlg.showModal(); + dlg.querySelector(".close").addEventListener("click", close); + dlg.querySelector(".ok").addEventListener("click", close); + btn.addEventListener("click", doRender); + }); + } + + let waitForQueuedOps = setInterval(() => { + if (renderer.queueSize === 0) { + clearInterval(waitForQueuedOps); + waitForQueuedOps = null; + bar.className = "animate"; + statusLastText = "Ready"; + status.innerText = "Ready"; + postQueue(); + } + }, 1000); +} + +sal.style.display = "flex"; + +const menuabout = document.body.querySelector("#menuitem-about"); +document.body.querySelector("#menuitem-reload").addEventListener("click", () => window.location.reload()); +menuabout.addEventListener("click", () => { + const dlg = document.body.querySelector("#about"); + let close = () => { + dlg.removeEventListener("cancel", close); + dlg.querySelector(".close").removeEventListener("click", close); + dlg.querySelector(".ok").removeEventListener("click", close); + dlg.querySelector(".view-notice").removeEventListener("click", viewNotice); + dlg.close(); + titleBar.classList.add("active"); + } + dlg.addEventListener("cancel", close); + titleBar.classList.remove("active"); + dlg.showModal(); + dlg.querySelector(".close").addEventListener("click", close); + dlg.querySelector(".ok").addEventListener("click", close); + dlg.querySelector(".view-notice").addEventListener("click", viewNotice); +}); + +const menuassets = document.body.querySelector("#menuitem-missingassets"); +menuassets.addEventListener("click", () => { + openNotepad("missing_assets.txt", renderer.mAssetManager.missingAssets); +}); + +function viewNotice() { + openNotepad("notice.txt", `Studio Lite is built upon MrSprinkleToes' rbxBinaryParser [https://github.com/MrSprinkleToes/rbxBinaryParser]. +Additionally, some code from roblox-in-webbrowser [https://github.com/MrSprinkleToes/roblox-in-webbrowser] and roblox-web-viewer [https://github.com/MrSprinkleToes/roblox-web-viewer] is used. +Please see the README for more information. + +The THREE.js library [https://threejs.org] is used for rendering the game view. +The THREE.js add-ons PointerLockControls and Stats are also included within the application. + +jsTree [https://www.jstree.com] is used for displaying interactive trees in the Explorer and Properties views. + +7.css [https://khang-nd.github.io/7.css] is used for theming the user interface. + +Roblox Studio icons and other assets stored within the content/ directory, as well as the favicon.ico, are Copyright © Roblox Corporation. +The assets saved within the asset/ directory and the example files in examples/ are copyright of their respective owners. + +Studio Lite is not affiliated in any way, shape or form with Roblox Corporation.`, true); +} + +function openNotepad(fileName, text, nested = false) { + const dlg = document.body.querySelector("#notepad"); + const title = dlg.querySelector("#dialog-title"); + const textarea = dlg.querySelector("textarea"); + title.innerText = `${fileName} - Notepad`; + textarea.value = text; + let close = () => { + dlg.removeEventListener("cancel", close); + dlg.querySelector(".close").removeEventListener("click", close); + dlg.close(); + title.innerText = "Notepad"; + textarea.innerText = ""; + if (!nested) titleBar.classList.add("active"); + } + dlg.addEventListener("cancel", close); + titleBar.classList.remove("active"); + dlg.showModal(); + dlg.querySelector(".close").addEventListener("click", close); +} + +const menuchangelog = document.body.querySelector("#menuitem-changelog"); +menuchangelog.addEventListener("click", () => openNotepad("changelog.txt", `Studio Lite Changelog + +New in alpha-1: +- Initial release.`)); + +const examples = [ + "examples/Classic-Crossroads.rbxl", + "examples/City.rbxl", + "examples/Suburban.rbxl", + "examples/Western-Lounge.rbxm", + "examples/Dilapidated-House.rbxm" +]; + +const buttons = sal.querySelectorAll("button"); +buttons[0].addEventListener("click", async () => { + let dlg = document.body.querySelector("#remoteload"); + let txt = dlg.querySelector("input"); + let btn = dlg.querySelector(".open"); + let exp = dlg.querySelector("#examples"); + exp.innerHTML = ""; + for (const e of examples) { + let el = document.createElement("li"); + el.role = "option"; + el.innerText = e; + el.addEventListener("click", () => { + txt.value = el.innerText; + txt.dispatchEvent(new Event("input")); + }); + exp.appendChild(el); + } + let close = () => { + dlg.removeEventListener("cancel", close); + dlg.querySelector(".close").removeEventListener("click", close); + dlg.querySelector(".cancel").removeEventListener("click", close); + btn.removeEventListener("click", doLoad); + txt.removeEventListener("keyup", keyup); + txt.removeEventListener("input", input); + titleBar.classList.add("active"); + dlg.close(); + } + dlg.addEventListener("cancel", close); + titleBar.classList.remove("active"); + dlg.showModal(); + dlg.querySelector(".close").addEventListener("click", close); + dlg.querySelector(".cancel").addEventListener("click", close); + let doLoad = () => { + doLoad = null; + file = txt.value; + close(); close = null; + try { document.body.removeChild(dlg); } catch (ignored) {}; + dlg = null; txt = null; btn = null; + start(); + }; + btn.addEventListener("click", doLoad); + let keyup = ({key}) => { + if (!btn.disabled && key === "Enter") doLoad(); + }; + txt.addEventListener("keyup", keyup); + let input = () => { + if (txt.value.trim().length > 0) { + btn.disabled = false; + } else { + btn.disabled = true; + } + }; + txt.addEventListener("input", input); +}) + +const browse = sal.querySelector("input[type=file]"); +browse.addEventListener("input", () => { + file = browse.files[0]; + start(); +}) + +window.addEventListener("resize", () => { + renderer.resize(); +}) + +const tree = document.body.querySelector(".tree"); +const tree2 = document.body.querySelector(".tree2"); +const datamodeltab = document.body.querySelector("button[aria-controls=datamodel-explorer]"); +const scenetab = document.body.querySelector("button[aria-controls=scene-explorer]"); +tree2.style.display = "none"; +datamodeltab.addEventListener("mousedown", () => { + datamodeltab.ariaSelected = true; + scenetab.ariaSelected = false; + tree2.style.display = "none"; + tree.style.display = "block"; +}); +let treeRefresh2Pending = false; +scenetab.addEventListener("mousedown", () => { + datamodeltab.ariaSelected = false; + scenetab.ariaSelected = true; + tree.style.display = "none"; + rendering = true; + setTitle(placeName); + editor.innerHTML = ""; + editor.style.display = "none"; + tree2.style.display = "block"; + (async () => { + if (treeRefresh2Pending) { + treeRefresh2(); + treeRefresh2Pending = false; + } + })(); +}); +datamodeltab.disabled = false; +scenetab.disabled = false; + +$(".tree2").jstree({'core' : { + 'data': [] +}}); + +let treeRef2 = $(".tree2").jstree(true); +let propTable = document.body.querySelector(".properties > table > tbody"); +let propSpinner = document.body.querySelector(".properties > .loader"); + +treeRefresh2 = () => { + // don't render what we can't see! + if (tree2.style.display === "none") { treeRefresh2Pending = true; return; } + treeRef2.settings.core.data = threeNodeToTreeData([renderer.scene]); + treeRef2.refresh(); +} + +$('.tree2').on("changed.jstree", async function (e, data) { + let node = treeRef2.get_node(data.selected[0]).original; + if (node) {} else return; + node = node.node.object; + document.body.querySelector("#propertiesTitle").innerText = `Properties - ${node.type} "${node.name ? node.name : node.type}"`; + let keys = Object.keys(node); + let objviewIndex = 0; + let treedatatemp = null; + propTable.innerHTML = ""; + propSpinner.style.display = "block"; + propTable.style.display = "none"; + for (let key of keys) { + if (key !== "children") { + let row = document.createElement("tr"); + let one = document.createElement("td"); + let two = document.createElement("td"); + one.innerText = key; + if (typeof node[key] === "object") { + let objview = document.createElement("div"); + two.appendChild(objview); + objview.id = `objview-${objviewIndex}`; + treedatatemp = {'core' : { + 'data' : objToTreeData(node[key]) + }}; + } else if (key === "color") { + let clr = document.createElement("input"); + clr.type = "color"; + clr.disabled = true; + clr.value = "#" + node[key].toString(16); + two.appendChild(clr); + let span = document.createElement("span"); + span.innerHTML = ` ${clr.value}`; + two.appendChild(span); + } else if ([true, false].indexOf(node[key]) !== -1) { + let chk = document.createElement("input"); + chk.disabled = "true"; + chk.type = "checkbox"; + chk.id = "checkbox-" + key; + if (node[key]) chk.checked = true; + let txt = document.createElement("label"); + txt.for = "checkbox-" + key; + two.appendChild(chk); + two.appendChild(txt); + } else if (typeof node[key] === "number") { + let nr = document.createElement("input"); + nr.type = "number"; + nr.min = node[key]; + nr.max = node[key]; + nr.value = node[key]; + nr.disabled = true; + two.appendChild(nr); + } else { + two.innerText = node[key].toString(); + } + row.appendChild(one); + row.appendChild(two); + propTable.appendChild(row); + if (treedatatemp !== null) { + $(`#objview-${objviewIndex}`).jstree(treedatatemp); + objviewIndex++; + treedatatemp = null; + } + } + } + propSpinner.style.display = "none"; + propTable.style.display = "table-row-group"; +}); + +setTitle("Start Page"); +print("Welcome to Studio Lite (alpha-1)!"); + +rendering = true; + +treeRefresh2(); \ No newline at end of file diff --git a/app/controls/FlyCamera.js b/app/controls/FlyCamera.js new file mode 100644 index 0000000..68b0ec2 --- /dev/null +++ b/app/controls/FlyCamera.js @@ -0,0 +1,135 @@ +import { PointerLockControls } from "./PointerLockControls.js"; + +export default class FlyCamera { + /** + * + * @param {*} cam THREE.PerspectiveCamera to control + * @param {*} domElement The DOM element to listen for click & key events on + */ + constructor(cam, domElement) { + this.cam = cam; + this.domElement = domElement; + this.movementSpeed = 0; + this.horizontalMovementSpeed = 0; + this.verticalMovementSpeed = 0; + this.flySpeed = 5; + // this.lookSpeed = 0.005; + this.controls = new PointerLockControls(this.cam, this.domElement); + + /** + * Locks mouse on click + */ + domElement.addEventListener('click', () => { + this.controls.lock(); + }); + /** + * Sets movement directions based on key presses + */ + window.addEventListener("keydown", (e) => { + if (!this.controls.isLocked) return; + switch (e.code) { + case "KeyW": + this.moveForward = true; + break; + case "KeyS": + this.moveBackward = true; + break; + case "KeyA": + this.moveLeft = true; + break; + case "KeyD": + this.moveRight = true; + break; + case "KeyE": + this.moveUp = true; + break; + case "KeyQ": + this.moveDown = true; + break; + } + }); + /** + * Sets movement directions based on key releases + */ + window.addEventListener("keyup", (e) => { + if (!this.controls.isLocked) return; + switch (e.code) { + case "KeyW": + this.moveForward = false; + break; + case "KeyS": + this.moveBackward = false; + break; + case "KeyA": + this.moveLeft = false; + break; + case "KeyD": + this.moveRight = false; + break; + case "KeyE": + this.moveUp = false; + break; + case "KeyQ": + this.moveDown = false; + break; + } + }); + } + /** + * Updates this.cam position based on movement directions + * @param {number} dt + */ + update(dt) { + if (!this.controls.isLocked) return; + // console.log(this.moveForward); + if (this.moveForward) { + // console.log("forward"); + if (this.movementSpeed < 50) { + this.movementSpeed += this.flySpeed; + } + } else if (this.moveBackward) { + if (this.movementSpeed > -50) { + this.movementSpeed -= this.flySpeed; + } + } else { + if (this.movementSpeed > 0) { + this.movementSpeed -= this.flySpeed; + } else if (this.movementSpeed < 0) { + this.movementSpeed += this.flySpeed; + } + } + if (this.moveLeft) { + if (this.horizontalMovementSpeed > -50) { + this.horizontalMovementSpeed -= this.flySpeed; + } + } else if (this.moveRight) { + if (this.horizontalMovementSpeed < 50) { + this.horizontalMovementSpeed += this.flySpeed; + } + } else { + if (this.horizontalMovementSpeed > 0) { + this.horizontalMovementSpeed -= this.flySpeed; + } else if (this.horizontalMovementSpeed < 0) { + this.horizontalMovementSpeed += this.flySpeed; + } + } + if (this.moveUp) { + if (this.verticalMovementSpeed < 50) { + this.verticalMovementSpeed += this.flySpeed; + } + } else if (this.moveDown) { + if (this.verticalMovementSpeed > -50) { + this.verticalMovementSpeed -= this.flySpeed; + } + } else { + if (this.verticalMovementSpeed > 0) { + this.verticalMovementSpeed -= this.flySpeed; + } else if (this.verticalMovementSpeed < 0) { + this.verticalMovementSpeed += this.flySpeed; + } + } + this.cam.translateX(this.horizontalMovementSpeed * dt); + this.cam.translateY(this.verticalMovementSpeed * dt); + this.cam.translateZ(-this.movementSpeed * dt); + } +} \ No newline at end of file diff --git a/app/controls/PointerLockControls.js b/app/controls/PointerLockControls.js new file mode 100644 index 0000000..133da64 --- /dev/null +++ b/app/controls/PointerLockControls.js @@ -0,0 +1,272 @@ +import { + Controls, + Euler, + Vector3 +} from '../thirdparty/three/three.core.js'; + +const _euler = new Euler( 0, 0, 0, 'YXZ' ); +const _vector = new Vector3(); + +/** + * Fires when the user moves the mouse. + * + * @event PointerLockControls#change + * @type {Object} + */ +const _changeEvent = { type: 'change' }; + +/** + * Fires when the pointer lock status is "locked" (in other words: the mouse is captured). + * + * @event PointerLockControls#lock + * @type {Object} + */ +const _lockEvent = { type: 'lock' }; + +/** + * Fires when the pointer lock status is "unlocked" (in other words: the mouse is not captured anymore). + * + * @event PointerLockControls#unlock + * @type {Object} + */ +const _unlockEvent = { type: 'unlock' }; + +const _MOUSE_SENSITIVITY = 0.002; +const _PI_2 = Math.PI / 2; + +/** + * The implementation of this class is based on the [Pointer Lock API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API}. + * `PointerLockControls` is a perfect choice for first person 3D games. + * + * ```js + * const controls = new PointerLockControls( camera, document.body ); + * + * // add event listener to show/hide a UI (e.g. the game's menu) + * controls.addEventListener( 'lock', function () { + * + * menu.style.display = 'none'; + * + * } ); + * + * controls.addEventListener( 'unlock', function () { + * + * menu.style.display = 'block'; + * + * } ); + * ``` + * + * @augments Controls + * @three_import import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js'; + */ +class PointerLockControls extends Controls { + + /** + * Constructs a new controls instance. + * + * @param {Camera} camera - The camera that is managed by the controls. + * @param {?HTMLDOMElement} domElement - The HTML element used for event listeners. + */ + constructor( camera, domElement = null ) { + + super( camera, domElement ); + + /** + * Whether the controls are locked or not. + * + * @type {boolean} + * @readonly + * @default false + */ + this.isLocked = false; + + /** + * Camera pitch, lower limit. Range is '[0, Math.PI]' in radians. + * + * @type {number} + * @default 0 + */ + this.minPolarAngle = 0; + + /** + * Camera pitch, upper limit. Range is '[0, Math.PI]' in radians. + * + * @type {number} + * @default Math.PI + */ + this.maxPolarAngle = Math.PI; + + /** + * Multiplier for how much the pointer movement influences the camera rotation. + * + * @type {number} + * @default 1 + */ + this.pointerSpeed = 1.0; + + // event listeners + + this._onMouseMove = onMouseMove.bind( this ); + this._onPointerlockChange = onPointerlockChange.bind( this ); + this._onPointerlockError = onPointerlockError.bind( this ); + + if ( this.domElement !== null ) { + + this.connect( this.domElement ); + + } + + } + + connect( element ) { + + super.connect( element ); + + this.domElement.ownerDocument.addEventListener( 'mousemove', this._onMouseMove ); + this.domElement.ownerDocument.addEventListener( 'pointerlockchange', this._onPointerlockChange ); + this.domElement.ownerDocument.addEventListener( 'pointerlockerror', this._onPointerlockError ); + + } + + disconnect() { + + this.domElement.ownerDocument.removeEventListener( 'mousemove', this._onMouseMove ); + this.domElement.ownerDocument.removeEventListener( 'pointerlockchange', this._onPointerlockChange ); + this.domElement.ownerDocument.removeEventListener( 'pointerlockerror', this._onPointerlockError ); + + } + + dispose() { + + this.disconnect(); + + } + + getObject() { + + console.warn( 'THREE.PointerLockControls: getObject() has been deprecated. Use controls.object instead.' ); // @deprecated r169 + + return this.object; + + } + + /** + * Returns the look direction of the camera. + * + * @param {Vector3} v - The target vector that is used to store the method's result. + * @return {Vector3} The normalized direction vector. + */ + getDirection( v ) { + + return v.set( 0, 0, - 1 ).applyQuaternion( this.object.quaternion ); + + } + + /** + * Moves the camera forward parallel to the xz-plane. Assumes camera.up is y-up. + * + * @param {number} distance - The signed distance. + */ + moveForward( distance ) { + + if ( this.enabled === false ) return; + + // move forward parallel to the xz-plane + // assumes camera.up is y-up + + const camera = this.object; + + _vector.setFromMatrixColumn( camera.matrix, 0 ); + + _vector.crossVectors( camera.up, _vector ); + + camera.position.addScaledVector( _vector, distance ); + + } + + /** + * Moves the camera sidewards parallel to the xz-plane. + * + * @param {number} distance - The signed distance. + */ + moveRight( distance ) { + + if ( this.enabled === false ) return; + + const camera = this.object; + + _vector.setFromMatrixColumn( camera.matrix, 0 ); + + camera.position.addScaledVector( _vector, distance ); + + } + + /** + * Activates the pointer lock. + * + * @param {boolean} [unadjustedMovement=false] - Disables OS-level adjustment for mouse acceleration, and accesses raw mouse input instead. + * Setting it to true will disable mouse acceleration. + */ + lock( unadjustedMovement = false ) { + + this.domElement.requestPointerLock( { + unadjustedMovement + } ); + + } + + /** + * Exits the pointer lock. + */ + unlock() { + + this.domElement.ownerDocument.exitPointerLock(); + + } + +} + +// event listeners + +function onMouseMove( event ) { + + if ( this.enabled === false || this.isLocked === false ) return; + + const camera = this.object; + _euler.setFromQuaternion( camera.quaternion ); + + _euler.y -= event.movementX * _MOUSE_SENSITIVITY * this.pointerSpeed; + _euler.x -= event.movementY * _MOUSE_SENSITIVITY * this.pointerSpeed; + + _euler.x = Math.max( _PI_2 - this.maxPolarAngle, Math.min( _PI_2 - this.minPolarAngle, _euler.x ) ); + + camera.quaternion.setFromEuler( _euler ); + + this.dispatchEvent( _changeEvent ); + +} + +function onPointerlockChange() { + + if ( this.domElement.ownerDocument.pointerLockElement === this.domElement ) { + + this.dispatchEvent( _lockEvent ); + + this.isLocked = true; + + } else { + + this.dispatchEvent( _unlockEvent ); + + this.isLocked = false; + + } + +} + +function onPointerlockError() { + + console.error( 'THREE.PointerLockControls: Unable to use Pointer Lock API' ); + +} + +export { PointerLockControls }; diff --git a/app/datamodel/DataModelUtils.js b/app/datamodel/DataModelUtils.js new file mode 100644 index 0000000..2e23b14 --- /dev/null +++ b/app/datamodel/DataModelUtils.js @@ -0,0 +1,5 @@ +export function findByClassName(parent, className) { + for (let child of parent) { + if (child && child.ClassName === className) return child; + } +} \ No newline at end of file diff --git a/app/etc/Helpers.js b/app/etc/Helpers.js new file mode 100644 index 0000000..9340fe2 --- /dev/null +++ b/app/etc/Helpers.js @@ -0,0 +1,12 @@ +export function sleep(ms) { return new Promise((r) => { setTimeout(r, ms); }); } + +/* https://stackoverflow.com/a/5624139 */ +function componentToHex(c) { + var hex = c.toString(16); + return hex.length == 1 ? "0" + hex : hex; +} + +export function rgbToHex(r, g, b) { + return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); +} +/* https://stackoverflow.com/a/5624139 */ \ No newline at end of file diff --git a/app/http/AssetManager.js b/app/http/AssetManager.js new file mode 100644 index 0000000..0d665ae --- /dev/null +++ b/app/http/AssetManager.js @@ -0,0 +1,79 @@ +import { tryToFetch_status } from "./TryToFetch.js"; + +export default class AssetManager { + constructor(conf) { + this.conf = conf; + this.parseCache = {}; + this.failedAssets = []; + this.texturesOfFailedMeshes = {}; + this.missingAssets = `You haven't opened a Place yet. Open a Place to get insights on missing assets.`; + this.hasRbxGameAsset = false; + } + + getAssetId(path) { + if (path.split("://")[0] === "rbxassetid") return path.split("://").pop().trim(); + if (path.split("://")[0] === "http") return path.split("=").pop().trim(); + if (!this.hasRbxGameAsset && path.split("://")[0] === "rbxgameasset") this.hasRbxGameAsset = true; + return false; + } + + pushFailedMesh(assetId, meshTexture) { + if (this.texturesOfFailedMeshes[assetId]) {} else this.texturesOfFailedMeshes[assetId] = []; + if (this.texturesOfFailedMeshes[assetId].indexOf(meshTexture) === -1) this.texturesOfFailedMeshes[assetId].push(meshTexture); + } + + async parseAssetPath(path, type = "decal", meshTexture = "N/A") { + if (meshTexture === false) meshTexture = "N/A"; + const assetId = this.getAssetId(path); + if (type === "mesh" && this.parseCache[path] && this.parseCache[path].length === 0) this.pushFailedMesh(assetId, meshTexture); + if (this.parseCache[path]) return this.parseCache[path]; + //status.innerText = "Loading assets..."; + let href = ""; + if (path.split("://")[0] === "rbxasset") href = "content/" + path.split("://").pop(); + if (assetId) href = "asset/" + assetId.trim() + (type === "decal" ? ".png" : ".mesh"); + if (this.failedAssets.indexOf(assetId) !== -1) { this.parseCache[path] = ""; return this.parseCache[path]; } + if (href.trim().length === 0) { + if (path.trim().length === 0) + //print("parseAssetPath was called with an empty string!"); + ; + else + if (path.split("://")[0] !== "rbxgameasset") this.conf.sharedFunctions.print(`Asset path ${path} could not be resolved! This might be a deficiency in Studio Lite, please open an issue!`); + href = ""; + } else { + if (path.trim().length === 0) { this.parseCache[path] = ""; return this.parseCache[path]; } + const fetchResult = await tryToFetch_status(href); + if (fetchResult === 200) { this.parseCache[path] = href; return href; } else { + if (fetchResult === 404 && assetId !== false && this.failedAssets.indexOf(assetId) === -1) { + this.failedAssets.push(assetId); + } + if (type === "mesh" && fetchResult === 404 && assetId !== false && meshTexture !== false) this.pushFailedMesh(assetId, meshTexture); + this.parseCache[path] = ""; + return this.parseCache[path]; + } + } + this.parseCache[path] = href; + //status.innerText = statusLastText; + return href; + } + + computeMissingAssetsList() { + if (this.failedAssets.length > 0) { + this.missingAssets = `Below are listed all the assets in this Place that have failed to load, likely because they aren't saved on the server. +To fix this, download the missing assets using the AssetDelivery API and place them in the asset/ directory. +The name must be given as [assetid].[extension], where the extension is: +.png for image assets +.mesh for meshes + +AssetID listing starts here:`; + for (const i in this.failedAssets) { + const asset = this.failedAssets[i]; + const textures = this.texturesOfFailedMeshes[asset]; + this.missingAssets += `\n${textures ? "Mesh" : "Decal"} ${asset.trim()}${textures ? `, texture ${textures.join(", ")}` : ""}`; + } + return true; + } else { + this.missingAssets = "All assets in this Place have loaded successfully."; + return false; + } + } +} \ No newline at end of file diff --git a/app/http/TryToFetch.js b/app/http/TryToFetch.js new file mode 100644 index 0000000..8e96fc9 --- /dev/null +++ b/app/http/TryToFetch.js @@ -0,0 +1,12 @@ +export async function tryToFetch_status(url) { + if (url.trim().length === 0) return false; + try { + let r = await fetch(url, {method: "HEAD"}); + return r.status; + } catch (ignored) { return false; } +} + +export async function tryToFetch(url) { + if (await tryToFetch_status(url) === 200) return true; + return false; +} \ No newline at end of file diff --git a/app/rendering/StudioLiteRenderer.js b/app/rendering/StudioLiteRenderer.js new file mode 100644 index 0000000..301b9a1 --- /dev/null +++ b/app/rendering/StudioLiteRenderer.js @@ -0,0 +1,495 @@ +import { + Scene, + PerspectiveCamera, + PCFSoftShadowMap, + TextureLoader, + Clock, + Matrix4, + DirectionalLight, + AmbientLight, + Color, + SphereGeometry, + CylinderGeometry, + BufferAttribute, + BufferGeometry, + Mesh, + MeshPhongMaterial, + BackSide, + MeshBasicMaterial, + BoxGeometry, + DataTexture, + SRGBColorSpace, + AxesHelper, + BoxHelper, + Raycaster, + Vector2 +} from '../thirdparty/three/three.core.js'; +import { decode } from "../thirdparty/rbxBinaryParser.js"; +import FlyCamera from '../controls/FlyCamera.js'; +import { WebGLRenderer } from '../thirdparty/three/three.module.js'; +import { + findByClassName +} from '../datamodel/DataModelUtils.js'; +import { parseMesh } from './mesh/MeshParser.js'; +import { + tryToFetch +} from '../http/TryToFetch.js'; +import AssetManager from '../http/AssetManager.js'; + +const decalSides = ["Right", "Left", "Top", "Bottom", "Back", "Front"]; +export const partClasses = ["Part", "SpawnLocation", "WedgePart", "Seat", "VehicleSeat"]; + +export class StudioLiteRenderer { + constructor(conf) { + this.conf = conf; + this.queue = { + total: 0, + completed: 0 + } + this.texturesOfFailedMeshes = {}; + this.imagePlaceholder = false; + this.mAssetManager = new AssetManager({ + sharedFunctions: { + print: this.conf.sharedFunctions.print + } + }); + this.scene = new Scene(); + this.camera = new PerspectiveCamera(75, this.conf.width/this.conf.height, 0.1, 15000); + this.renderer = new WebGLRenderer({ + antialias: true, + alpha: true + }); + this.renderer.autoClear = false; + this.renderer.setSize(this.conf.width, this.conf.height); + this.renderer.shadowMap.enabled = true; + this.renderer.shadowMap.style = PCFSoftShadowMap; + this.domElement = this.renderer.domElement; + this.loader = new TextureLoader(); + this.loader.crossOrigin = "Anonymous"; + this.clock = new Clock(); + let sun = new DirectionalLight(new Color(1, 1, 1), 1); + sun.position.set(0, 10, 1); + this.scene.add(sun); + let light = new AmbientLight(new Color(1, 1, 1), .5); + this.scene.add(light); + this.controls = new FlyCamera(this.camera, this.domElement); + this.setSkybox({ + SkyboxBk: "rbxasset://sky/null_plainsky512_bk.jpg", + SkyboxDn: "rbxasset://sky/null_plainsky512_dn.jpg", + SkyboxFt: "rbxasset://sky/null_plainsky512_ft.jpg", + SkyboxLf: "rbxasset://sky/null_plainsky512_lf.jpg", + SkyboxRt: "rbxasset://sky/null_plainsky512_rt.jpg", + SkyboxUp: "rbxasset://sky/null_plainsky512_up.jpg" + }); + this.axesHelper = new AxesHelper(20); + this.scene.add(this.axesHelper); + this.raycaster = new Raycaster(); + this.threeids = []; + this.pointer = new Vector2(); + this.useSelectionBox = false; + this.useSelectionBox2 = false; + this.domElement.addEventListener("mousemove", (event) => { + if (!this.useSelectionBox2) return; + const rect = event.target.getBoundingClientRect(); + this.pointer.x = ( (event.clientX - rect.left) / this.conf.width ) * 2 - 1; + this.pointer.y = - ( (event.clientY - rect.top) / this.conf.height ) * 2 + 1; + }); + this.noWorkspace = false; + } + + render() { + if (this.controls) this.controls.update(this.clock.getDelta()); + this.renderer.render(this.scene, this.camera); + if (this.useSelectionBox2) { + this.raycaster.setFromCamera(this.pointer, this.camera); + const intersects = this.raycaster.intersectObjects(this.scene.children, false); + if (intersects.length > 0) { + this.updateSelectionBox2(intersects[0].object); + } + } + } + + renderImage(width = this.conf.width, height = this.conf.height) { + if (this.selectionBox) this.scene.remove(this.selectionBox); + if (this.selectionBox2) this.scene.remove(this.selectionBox2); + this.renderer.setSize(width, height); + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.render(this.scene, this.camera); + const result = this.domElement.toDataURL(); + this.resize(); + if (this.selectionBox) this.scene.add(this.selectionBox); + if (this.selectionBox2) this.scene.add(this.selectionBox2); + return result; + } + + setAnimationLoop(cb) { + this.renderer.setAnimationLoop(cb); + } + + resize() { + this.renderer.setSize(this.conf.width, this.conf.height); + this.camera.aspect = this.conf.width / this.conf.height; + this.camera.updateProjectionMatrix(); + } + + toggleAxes(axes) { + if (axes) { + this.scene.add(this.axesHelper); + } else { + this.scene.remove(this.axesHelper); + } + } + + setAxesPosition(x, y, z) { + this.axesHelper.position.set(x, y, z); + } + + zoomTo(cameraFrame, rotate = true) { + this.camera.position.set(cameraFrame.Position.X, cameraFrame.Position.Y, cameraFrame.Position.Z); + if (rotate) this.camera.setRotationFromMatrix(new Matrix4().fromArray([ + cameraFrame.Components[3], cameraFrame.Components[6], cameraFrame.Components[9], 0, + cameraFrame.Components[4], cameraFrame.Components[7], cameraFrame.Components[10], 0, + cameraFrame.Components[5], cameraFrame.Components[8], cameraFrame.Components[11], 0, + 0, 0, 0, 1 + ])); + } + + updateSelectionBox(threeid) { + if (!this.useSelectionBox) return; + if (threeid !== 1) { + const mesh = this.scene.getObjectById(threeid); + if (this.selectionBox) { + this.selectionBox.setFromObject(mesh); + } else { + this.selectionBox = new BoxHelper(mesh, new Color(1, 1, 1)); + this.scene.add(this.selectionBox); + this.conf.sharedFunctions.treeRefresh2(); + } + } + } + + updateSelectionBox2(mesh) { + if (!this.useSelectionBox2) return; + if (this.selectionBox2) { + if (mesh !== this.skybox) this.selectionBox2.setFromObject(mesh); + } else { + this.selectionBox2 = new BoxHelper(mesh, new Color(1, 1, 1)); + this.scene.add(this.selectionBox2); + this.conf.sharedFunctions.treeRefresh2(); + } + } + + removeSelectionBoxesIfNeeded() { + if (!this.useSelectionBox && this.selectionBox) { + this.scene.remove(this.selectionBox); + this.selectionBox.dispose(); + this.selectionBox = null; + } + if (!this.useSelectionBox2 && this.selectionBox2) { + this.scene.remove(this.selectionBox2); + this.selectionBox2.dispose(); + this.selectionBox2 = null; + } + this.conf.sharedFunctions.treeRefresh2(); + } + + showSkybox(show) { + if (show) + this.scene.add(this.skybox); + else + this.scene.remove(this.skybox); + } + + getThreeId(id) { + return this.threeids[id]; + } + + async setSkybox(sky) { + if (this.skybox) this.scene.remove(this.skybox); + this.skybox = null + var material = [] + material[0] = await this.mAssetManager.parseAssetPath(sky.SkyboxFt); + material[1] = await this.mAssetManager.parseAssetPath(sky.SkyboxBk); + material[2] = await this.mAssetManager.parseAssetPath(sky.SkyboxUp); + material[3] = await this.mAssetManager.parseAssetPath(sky.SkyboxDn); + material[4] = await this.mAssetManager.parseAssetPath(sky.SkyboxRt); + material[5] = await this.mAssetManager.parseAssetPath(sky.SkyboxLf); + for (var i = 0; i < material.length; i++) { + material[i] = new MeshBasicMaterial({map: this.loadColorTexture(material[i])}) + material[i].side = BackSide + } + var geometry = new BoxGeometry(10000, 10000, 10000) + this.skybox = new Mesh(geometry, material) + this.skybox.position.set(0, 0, 0) + this.skybox.name = "Skybox"; + this.scene.add(this.skybox) + console.log("skybox added") + this.conf.sharedFunctions.treeRefresh2(); + } + + queueOperation(cb) { + (async () => { + this.queue.total++; + await cb(); + this.queue.completed++; + })(); + } + + get queueSize() { + return this.queue.total - this.queue.completed; + } + + async renderPart(part, forceNoMesh = false, mappedid) { + const transparent = part.Transparency > 0; + let geometry, material, decals = []; + let offset = {x: 0, y: 0, z: 0}; + let scale = {x: 1, y: 1, z: 1}; + + // Look for mesh data + const mesh = findByClassName(part.Children, "SpecialMesh"); + if (typeof mesh !== "object" && part.ClassName === "MeshPart") mesh = part; + + // Decide part color + let color = new Color(1, 1, 1); + if (part.Color3) { + color = new Color(part.Color3.R, part.Color3.G, part.Color3.B); + } else if (part.BrickColor) { + color = new Color(part.BrickColor.Color.R/255, part.BrickColor.Color.G/255, part.BrickColor.Color.B/255) + } + + // Give meshes special treatment + const blockMesh = mesh && mesh !== part ? mesh : findByClassName(part.Children, "BlockMesh"); + if (blockMesh) { + scale = { + x: blockMesh.Scale.X, + y: blockMesh.Scale.Y, + z: blockMesh.Scale.Z + }; + // offset stays y-only for now. offset coordinates are somehow relative to rotation? tf?? + // to see what I mean, uncomment X and Z, then open City.rbxl from the examples. + // Look at the stop signs. whaat? I ain't figuring this one out. + offset = { + x: 0,//blockMesh.Offset.X, + y: blockMesh.Offset.Y, + z: 0,//blockMesh.Offset.Z + }; + } + + // If ball or cylinder, decide geometry + if (part.Shape == "Ball") { + geometry = new SphereGeometry(part.Size.X / 2, 10, 10) + } else if (part.Shape === "Cylinder" || (mesh && mesh.MeshType === "Head")) { + let x, y, z; + if (part.Shape === "Cylinder") { + x = part.Size.X; + y = part.Size.Y; + z = part.Size.Z; + } else { + x = part.Size.Y; + y = part.Size.X; + z = part.Size.Z; + } + const cylinderRadius = Math.min(y, z) / 2; + geometry = new CylinderGeometry(cylinderRadius, cylinderRadius, x, 16, 16); + } else if (!forceNoMesh && mesh && (mesh.MeshType === "FileMesh" || part.ClassName === "MeshPart")) { + // Look, a mesh! Let's queue that so it doesn't block place loading. + this.queueOperation(async () => { + try { + var meshData = await this.getMesh(mesh.MeshId, this.mAssetManager.getAssetId(mesh.TextureId)); + var { positions, normal, uv } = await parseMesh(meshData, mesh.MeshId); + const geometry = new BufferGeometry(); + const positionNumComponents = 3; + const normalNumComponents = 3; + const uvNumComponents = 3; + geometry.setAttribute( + "position", + new BufferAttribute( + new Float32Array(positions), + positionNumComponents + ) + ); + geometry.setAttribute( + "normal", + new BufferAttribute(new Float32Array(normal), normalNumComponents) + ); + geometry.setAttribute( + "uv", + new BufferAttribute(new Float32Array(uv), uvNumComponents) + ); + geometry.computeBoundingBox(); + let box = geometry.boundingBox; + let x = box.max.x - box.min.x; + let y = box.max.y - box.min.y; + let z = box.max.z - box.min.z; + geometry.scale(part.Size.X / x, part.Size.Y / y, part.Size.Z / z); + + material = new MeshPhongMaterial( { + map: this.loadColorTexture(await this.mAssetManager.parseAssetPath(mesh.TextureId)), + transparent: transparent, + opacity: part.transparency*-1+1, + specular: 0x222222 + } ) + + let cube = new Mesh(geometry, material); + cube.receiveShadow = true + cube.castShadow = true + cube.name = part.Name; + cube.position.set(part.CFrame.Position.X, part.CFrame.Position.Y, part.CFrame.Position.Z); + cube.setRotationFromMatrix(new Matrix4().fromArray([ + part.CFrame.Components[3], part.CFrame.Components[6], part.CFrame.Components[9], 0, + part.CFrame.Components[4], part.CFrame.Components[7], part.CFrame.Components[10], 0, + part.CFrame.Components[5], part.CFrame.Components[8], part.CFrame.Components[11], 0, + 0, 0, 0, 1 + ])); + this.scene.add(cube); + if (mappedid) this.threeids[mappedid] = cube.id; + // That didn't work! Let's load the part meshless instead. + } catch (e) { + // forceNoMesh = true skips the mesh code, so this part will follow the regular code path. + this.renderPart(part, true); + } + }); + return; + } else { + geometry = new BoxGeometry( part.Size.X * scale.x, part.Size.Y * scale.y, part.Size.Z * scale.z ) + } + + // Render wedgepart + if (part.ClassName === "WedgePart") { + let pos = geometry.attributes.position; + for(let i = 0; i < pos.count; i++){ + if (pos.getZ(i) < 0 && pos.getY(i) > 0) pos.setY(i, (part.Size.Y / 2) * -1); // change Y-coord by condition + } + geometry.computeVertexNormals(); // don't forget to re-compute normals + } + + // Enumerate decals + for (let child of part.Children) { + if (child.ClassName === "Decal" || child.ClassName === "Texture") { + decals.push(child); + } + } + + // Stage two. We will queue this if there are decals, to not block. + const renderPartStageTwo = async () => { + if (decals.length > 0) { + // Build a decal material. + material = [null, null, null, null, null, null]; + let index; + for (let decal of decals) { + index = decalSides.indexOf(decal.Face); + if (index !== -1) { + material[index] = new MeshPhongMaterial({ + map: this.loadColorTexture(await this.mAssetManager.parseAssetPath(decal.Texture)), + transparent: decal.Transparency > 0, + opacity: decal.Transparency*-1+1, + specular: 0x222222 + }); + } + } + for (let i in material) { + if (material[i] === null) material[i] = new MeshPhongMaterial({ + color: color, + transparent: transparent, + opacity: part.Transparency*-1+1, + specular: 0x222222 + }); + } + } else { + // No decals? Just one material, then. + material = new MeshPhongMaterial( { + color: color, + transparent: transparent, + opacity: part.Transparency*-1+1, + specular: 0x222222 + } ) + } + + // Create the mesh for our part. + var cube = new Mesh( geometry, material ) + cube.receiveShadow = true + cube.castShadow = true + cube.name = part.Name; + cube.position.set(part.CFrame.Position.X + offset.x, part.CFrame.Position.Y + offset.y, part.CFrame.Position.Z + offset.z); + // Degrees aren't enough! We need to set the exact rotation matrix. + // If we use just CFrame.Orientation, it will lead to incorrect placements => destroyed buildings. + cube.setRotationFromMatrix(new Matrix4().fromArray([ + part.CFrame.Components[3], part.CFrame.Components[6], part.CFrame.Components[9], 0, + part.CFrame.Components[4], part.CFrame.Components[7], part.CFrame.Components[10], 0, + part.CFrame.Components[5], part.CFrame.Components[8], part.CFrame.Components[11], 0, + 0, 0, 0, 1 + ])); + // This is needed for cylinders to rotate correctly. No idea why. + if (part.Shape === "Cylinder") cube.rotation.z += Math.PI / 2; + //cube.rotation.set(MathUtils.degToRad(part.CFrame.Orientation.X), MathUtils.degToRad(part.CFrame.Orientation.Y), MathUtils.degToRad(part.CFrame.Orientation.Z)); + this.scene.add( cube ) + if (mappedid) this.threeids[mappedid] = cube.id; + }; + + // If there are no assets to load, render the part synchronously. + // If there are assets, move rendering to the background, + // so it doesn't block everything else if the user's connection is slow. + // (it is just a HEAD request, tho...) + if (decals.length > 0) { + this.queueOperation(renderPartStageTwo); + } else await renderPartStageTwo(); + } + + async traverse(instance, treeData, render = false) { + for (let child of instance.Children) { + if (child) { + let item = {'text': child.Name, 'icon': `content/icons/${child.ClassName}.png`, 'children': [], 'instance': child, 'id': this.threeids.push(1) - 1}; + treeData.push(item); + if (render && partClasses.indexOf(child.ClassName) !== -1) { + await this.renderPart(child, false, item.id); + } + await this.traverse(child, item.children, render ? true : child.ClassName === "Workspace" || this.noWorkspace); + } + } + } + + loadColorTexture( path ) { + if (path.trim().length === 0) return new DataTexture(new Uint8Array(4), 1, 1); + this.conf.sharedFunctions.print("Load texture " + new URL(path, window.location.href)); + const texture = this.loader.load( path ); + texture.colorSpace = SRGBColorSpace; + return texture; + } + + async getMesh(mesh, texture) { + const path = await this.mAssetManager.parseAssetPath(mesh, "mesh", texture); + if (path.trim().length === 0) throw new Error(); + var d = await fetch(path); + var data = await d.arrayBuffer(); + return data; + } + + async loadPlace(ab) { + this.data = decode(ab); + const workspace = findByClassName(this.data, "Workspace"); + if (workspace) this.noWorkspace = false; else this.noWorkspace = true; + try { + const robloxCamera = findByClassName((this.noWorkspace ? findByClassName(this.data, "Model") : workspace).Children, "Camera"); + const cameraFrame = robloxCamera.CFrame || robloxCamera.CoordinateFrame; + this.zoomTo(cameraFrame); + } catch (ignored) { + this.conf.sharedFunctions.print("Could not determine camera position!"); + } + this.queueOperation(async () => { + try { + const sky = findByClassName(findByClassName(this.data, "Lighting").Children, "Sky"); + if (!sky) throw new Error(); + try { + for (const key of ["Bk", "Dn", "Ft", "Lf", "Rt", "Up"]) { + if (await tryToFetch(await this.mAssetManager.parseAssetPath(sky["Skybox" + key]))) {} else { throw new Error(); } + } + await this.setSkybox(sky); + } catch (ignored) { + this.conf.sharedFunctions.print("Could not load sky!"); + } + } catch (ignored) {}; + }); + await this.traverse({"Children": this.data}, this.conf.sharedObjects.jsTreeData); + } +} \ No newline at end of file diff --git a/app/rendering/mesh/MeshParser.js b/app/rendering/mesh/MeshParser.js new file mode 100644 index 0000000..7057b79 --- /dev/null +++ b/app/rendering/mesh/MeshParser.js @@ -0,0 +1,153 @@ +function parse1xMesh(MESHDATA, is10) { + var vectors = MESHDATA.replace(/]/g, "").split("["); + var h = vectors.shift(); + var positions = []; + var normal = []; + var uv = []; + // 1.00 assets are scaled up by 2x in the file- + var offset = is10 ? 0.5 : 1; + + function toVector(vstring, offst) { + var a = []; + for (var i of vstring.split(",")) { + a.push(parseFloat(i) * offst); + } + return a; + } + for (var i = 0; i < vectors.length; i += 3) { + positions.push(...toVector(vectors[i], offset)); + normal.push(...toVector(vectors[i + 1], 1)); + uv.push(...toVector(vectors[i + 2], 1)); + } + console.log( + `Parsed version 1 mesh\n\nDetails:\nVectors: ${vectors.length} (/ 3 = ${ + vectors.length / 3 + })\n\nHeader:`, + h + ); + vectors = null; + return { + positions, + normal, + uv + }; +} + +function parse2x3xMesh(dv) { + var headerStart = 13; + var MeshHeader = { + sizeof_MeshHeader: dv.getUint16(headerStart, true), + sizeof_Vertex: dv.getUint8(headerStart + 2, true), + sizeof_Face: dv.getUint8(headerStart + 3, true), + numVerts: dv.getUint32(headerStart + 4, true), + numFaces: dv.getUint32(headerStart + 8, true) + }; + if (MeshHeader.sizeof_MeshHeader > 12) { + // v3 header + MeshHeader.sizeof_LOD = dv.getUint16(headerStart + 4, true); + MeshHeader.numLODs = dv.getUint16(headerStart + 6, true); + MeshHeader.numVerts = dv.getUint16(headerStart + 8, true); + MeshHeader.numFaces = dv.getUint16(headerStart + 12, true); + } + console.log("Parsing version 2/3 mesh\n\nDetails:\n" + JSON.stringify(MeshHeader)); + var i = headerStart + MeshHeader.sizeof_MeshHeader; + var verticies = []; + var verticiesEnd = + headerStart + + MeshHeader.sizeof_MeshHeader + + MeshHeader.numVerts * MeshHeader.sizeof_Vertex; + while (i < verticiesEnd) { + var vertex = { + px: dv.getFloat32(i, true), + py: dv.getFloat32(i + 4, true), + pz: dv.getFloat32(i + 8, true), + nx: dv.getFloat32(i + 12, true), + ny: dv.getFloat32(i + 16, true), + nz: dv.getFloat32(i + 20, true), + u: dv.getFloat32(i + 24, true), + v: dv.getFloat32(i + 28, true), + w: dv.getFloat32(i + 32, true), + r: 255, + g: 255, + b: 255, + a: 255 + }; + if (MeshHeader.sizeof_Vertex >= 40) { + vertex.r = dv.getUint8(i + 36, true); + vertex.g = dv.getUint8(i + 37, true); + vertex.b = dv.getUint8(i + 38, true); + vertex.a = dv.getUint8(i + 39, true); + } + if (MeshHeader.sizeof_MeshHeader > 12) vertex.u = vertex.u; + verticies.push(vertex); + i += MeshHeader.sizeof_Vertex; + } + + var faces = []; + var facesEnd = verticiesEnd + MeshHeader.numFaces * MeshHeader.sizeof_Face; + while (i < facesEnd) { + faces.push({ + a: dv.getUint32(i, true), + b: dv.getUint32(i + 4, true), + c: dv.getUint32(i + 8, true) + }); + i += MeshHeader.sizeof_Face; + } + + var LODs = []; + if (MeshHeader.sizeof_MeshHeader > 12) { + var lodsEnd = facesEnd + MeshHeader.numLODs * MeshHeader.sizeof_LOD; + while (i < lodsEnd) { + LODs.push(dv.getUint32(i, true)); + i += MeshHeader.sizeof_LOD; + } + } + + console.log({ + MeshHeader, + verticies, + faces, + LODs + }); + + var positions = []; + var normal = []; + var uv = []; + + for (var faceIdx in faces) { + if (LODs.length > 1 && faceIdx > LODs[1]) break; + var face = faces[faceIdx]; + for (var i in face) { + var vertex = verticies[face[i]]; + positions.push(vertex.px, vertex.py, vertex.pz); + normal.push(vertex.nx, vertex.ny, vertex.nz); + uv.push(vertex.u, 1 - vertex.v, vertex.w); + } + } + + return { + positions, + normal, + uv + }; +} + +let meshCache = {}; +export function parseMesh(data, meshId) { + if (meshCache[meshId]) return meshCache[meshId]; + let returnValue; + var stringData = new TextDecoder().decode(data); + if (stringData.startsWith("version 1.0")) { + returnValue = parse1xMesh(stringData, stringData.startsWith("version 1.0")); + } else if ( + stringData.startsWith("version 2.0") || + stringData.startsWith("version 3.0") + ) { + console.log("Parsing v2/3 mesh, header: ", stringData.substring(0, 12)); + returnValue = parse2x3xMesh(new DataView(data)); + } else { + console.log("unsupported mesh " + stringData.split("\n")[0]); + } + meshCache[meshId] = returnValue; + return returnValue; +} \ No newline at end of file diff --git a/app/thirdparty/7.css b/app/thirdparty/7.css new file mode 100644 index 0000000..d0c275e --- /dev/null +++ b/app/thirdparty/7.css @@ -0,0 +1,4 @@ +/*! 7.css v0.18.0 - https://khang-nd.github.io/7.css */:root{--font:9pt "Segoe UI","SegoeUI","Noto Sans",sans-serif;--surface:#f0f0f0;--button-highlight:#fff;--button-face:#f2f2f2;--button-face-hover:#eaf6fd;--button-face-active:#c4e5f6;--button-face-disabled:#f4f4f4;--button-shade-light:#ebebeb;--button-shade-light-default:#c3dcea;--button-shade-light-hovered:#bee6fd;--button-shade-light-active:#98d1ef;--button-shade-dark:#cfcfcf;--button-shadow:inset 0 0 0 1px #fffc;--button-shadow-active:inset 1px 1px 0 #0003,inset -1px 1px 0 #0001;--button-border:1px solid;--button-border-color:#8e8f8f;--button-border-color-default:#5586a3;--button-border-color-hovered:#3c7fb1;--button-border-color-active:#6d91ab;--button-border-color-disabled:#aeb2b5;--button-text-color-disabled:#838383;--button-gradient:linear-gradient(to bottom,var(--button-face) 45%,var(--button-shade-light) 45%,var(--button-shade-dark));--button-gradient-hovered:linear-gradient(to bottom,var(--button-face-hover) 45%,var(--button-shade-light-hovered) 45%,#a7d9f5);--button-gradient-active:linear-gradient(to bottom,#e5f4fc,var(--button-face-active) 30% 50%,var(--button-shade-light-active) 50%,#68b3db);--item-highlighted-border:#aaddfa;--item-highlighted-background:linear-gradient(180deg,#fff9,#e6ecf5cc 90%,#fffc);--element-spacing:8px;--grouped-element-spacing:6px;--border-radius:3px;--border-width:1px}body{color:#222;font-family:Segoe UI,SegoeUI,Noto Sans,sans-serif;font-size:9pt}.surface{background:var(--surface)}h1{font-size:5rem}h2{font-size:2.5rem}h3{font-size:2rem}h4{font-size:1.5rem}u{border-bottom:.5px solid #222;text-decoration:none}code,code *{font-family:monospace}pre{background:#fff;border:1px solid var(--button-border-color);display:block;margin:0;padding:12px 8px}summary:focus-visible{outline:1px dotted #000}:root{--balloon-border-color:#0006;--balloon-tail-top:url("data:image/svg+xml;charset=utf-8,%3Csvg width='20' height='20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M.5 1.5v18h18l-18-18Z' fill='%23fff' stroke='%23fff'/%3E%3Cpath d='M1 19.5H.5v-18l18 18H18' stroke='%23939393'/%3E%3C/svg%3E");--balloon-tail-bottom:url("data:image/svg+xml;charset=utf-8,%3Csvg width='20' height='20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M.5 1.5v18h18l-18-18Z' fill='%23ddd' stroke='%23ddd'/%3E%3Cpath d='M1 19.5H.5v-18l18 18H18' stroke='%23939393'/%3E%3C/svg%3E");--balloon-tail-size:18px;--balloon-tail-offset:1em}[role=tooltip]{background:linear-gradient(to bottom,#fff,var(--button-shade-light));border:1px solid var(--balloon-border-color);border-radius:var(--border-radius);box-shadow:5px 5px 3px -3px var(--balloon-border-color);padding:1em 1em 1em 2.5em;position:relative}[role=tooltip]:before{background:var(--balloon-tail-top);content:"";height:var(--balloon-tail-size);left:var(--balloon-tail-offset);position:absolute;top:calc(var(--balloon-tail-size)*-1);width:var(--balloon-tail-size)}[role=tooltip][id]{position:absolute}[role=tooltip].is-top:before{background:var(--balloon-tail-bottom);bottom:calc(var(--balloon-tail-size)*-1);top:unset;transform:scale(-1)}[role=tooltip].is-top.is-right:before{transform:scaleY(-1)}[role=tooltip].is-left:before{left:unset;right:var(--balloon-tail-offset)}[role=tooltip].is-left.is-bottom:before{transform:scaleX(-1)}[role=button],button{background:var(--button-gradient);border:var(--button-border);border-color:var(--button-border-color);border-radius:var(--border-radius);box-shadow:var(--button-shadow);box-sizing:border-box;color:#222;font:var(--font);min-height:23px;min-width:75px;padding:0 12px;position:relative;text-align:center;z-index:0}[role=button]:before,button:before{background:var(--button-gradient-hovered);border-radius:var(--border-radius);box-shadow:var(--button-shadow)}[role=button]:after,[role=button]:before,button:after,button:before{content:"";height:100%;left:0;margin:0;opacity:0;padding:0;position:absolute;top:0;transition:opacity .3s;width:100%;z-index:-1}[role=button]:after,button:after{background:var(--button-gradient-active);border-radius:2px;box-shadow:var(--button-shadow-active)}[role=button]:disabled,button:disabled{background:var(--button-face-disabled);border-color:var(--button-border-color-disabled);color:var(--button-text-color-disabled)}[role=button]:not(:disabled):hover,button:not(:disabled):hover{border-color:var(--button-border-color-hovered);transition:border-color .3s}[role=button]:not(:disabled):hover:before,button:not(:disabled):hover:before{opacity:1;transition:opacity .3s}[role=button]:not(:disabled):not(:hover),button:not(:disabled):not(:hover){border-color:var(--button-border-color);transition:border-color 1s linear}[role=button]:not(:disabled):not(:hover):before,button:not(:disabled):not(:hover):before{opacity:0;transition:opacity 1s linear}[role=button]:not(:disabled).active,[role=button]:not(:disabled):active,button:not(:disabled).active,button:not(:disabled):active{border-color:var(--button-border-color-active);transition:border-color .3s}[role=button]:not(:disabled).active:after,[role=button]:not(:disabled):active:after,button:not(:disabled).active:after,button:not(:disabled):active:after{opacity:1;transition:opacity .3s}[role=button].focused,[role=button]:focus-visible,button.focused,button:focus-visible{box-shadow:inset 0 0 0 2px var(--button-shade-light-active);outline:1px dotted #000;outline-offset:-4px}[role=button].default,[role=button].focused,[role=button]:focus,button.default,button.focused,button:focus{-webkit-animation:pulse-anim 1s ease infinite alternate;animation:pulse-anim 1s ease infinite alternate;background-image:var(--button-gradient-hovered);border-color:var(--button-border-color-default)}@-webkit-keyframes pulse-anim{0%{box-shadow:inset 0 0 3px 1px #34deffdd}to{box-shadow:inset 0 0 1px 1px #34deffdd}}@keyframes pulse-anim{0%{box-shadow:inset 0 0 3px 1px #34deffdd}to{box-shadow:inset 0 0 1px 1px #34deffdd}}:root{--checkbox-width:14px;--checkbox-label-spacing:6px;--checkbox-total-width-precalc:0;--checkbox-total-width:calc(var(--checkbox-total-width-precalc));--checkmark-top:0;--checkmark-left:2px}input[type=checkbox]{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:none;border:none;font:var(--font);margin:0;opacity:0}input[type=checkbox]+label{align-items:center;display:inline-flex;font:var(--font);margin-left:var(--checkbox-total-width);position:relative}input[type=checkbox]+label:before{background:#f6f6f6;border:1px solid;border-color:var(--button-border-color);box-shadow:inset 0 0 0 1px #f4f4f4,inset 1px 1px 0 1px #aeaeae,inset -1px -1px 0 1px #ddd,inset 3px 3px 6px #ccc;box-sizing:border-box;content:"";display:inline-block;height:var(--checkbox-width);margin-right:var(--checkbox-label-spacing);transition:.4s;width:var(--checkbox-width)}input[type=checkbox]+label:hover:before{background:#e9f7fe;border-color:var(--button-border-color-hovered);box-shadow:inset 0 0 0 1px #def9fa,inset 1px 1px 0 1px #79c6f9,inset -1px -1px 0 1px #c6e9fc,inset 3px 3px 6px #b1dffd}input[type=checkbox]:focus-visible+label{outline:1px dotted #000}input[type=checkbox]:checked+label:after{color:#4a5f97;content:"\2714";display:block;font-weight:700;left:var(--checkmark-left);position:absolute;top:var(--checkmark-top)}input[type=checkbox]:disabled+label{opacity:.6}:root{--chevron-size:5px}details{margin-top:0}details>summary{cursor:pointer;display:inline;margin-bottom:0;position:relative}details>summary:before{border:var(--chevron-size) solid transparent;border-left-color:#000;border-radius:3px;content:"";position:absolute;right:100%;top:calc(50% - var(--chevron-size))}details>summary::-webkit-details-marker,details>summary::marker{display:none}details[open]>summary:before{top:calc(50% - var(--chevron-size)/2);transform:rotate(45deg)}:root{--combobox-chevron-size:4px}.combobox{display:inline-block;position:relative}.combobox input[type=text]{padding-right:20px;width:100%}.combobox button{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik0xMSA2SDR2MWgxdjFoMXYxaDF2MWgxVjloMVY4aDFWN2gxVjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+") 50% no-repeat,var(--button-gradient);min-width:16px;padding:0;position:absolute;right:0}.combobox button,.combobox button:before{border-bottom-left-radius:0;border-top-left-radius:0}.combobox button:before{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik0xMSA2SDR2MWgxdjFoMXYxaDF2MWgxVjloMVY4aDFWN2gxVjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+") 50% no-repeat,var(--button-gradient-hovered)}.combobox button:after{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik0xMSA2SDR2MWgxdjFoMXYxaDF2MWgxVjloMVY4aDFWN2gxVjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+") 50% no-repeat,var(--button-gradient-active);border-bottom-left-radius:0;border-top-left-radius:0}.combobox button:focus{box-shadow:none;outline:none}select:not([multiple]){-webkit-appearance:none;-moz-appearance:none;appearance:none;background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik0xMSA2SDR2MWgxdjFoMXYxaDF2MWgxVjloMVY4aDFWN2gxVjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),var(--button-gradient);background-position:100%;background-repeat:no-repeat;border:var(--button-border);border-color:var(--button-border-color);border-radius:var(--border-radius);box-shadow:var(--button-shadow);box-sizing:border-box;color:#222;font:var(--font);padding:2px 30px 2px 3px;position:relative}select:not([multiple]):hover{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik0xMSA2SDR2MWgxdjFoMXYxaDF2MWgxVjloMVY4aDFWN2gxVjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),var(--button-gradient-hovered);border-color:var(--button-border-color-hovered)}select:not([multiple]):active{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik0xMSA2SDR2MWgxdjFoMXYxaDF2MWgxVjloMVY4aDFWN2gxVjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),var(--button-gradient-active);border-color:var(--button-border-color-active);box-shadow:var(--button-shadow-active);outline:none}select:not([multiple]):focus{box-shadow:inset 0 0 0 2px var(--button-shade-light-active);outline:1px dotted #000;outline-offset:-4px}fieldset{border:1px solid #cdd7db;border-radius:var(--border-radius);box-shadow:inset 0 0 0 1px #fff;margin:0;padding:calc(var(--border-width)*2 + var(--element-spacing));-webkit-padding-before:var(--element-spacing);padding-block-start:var(--element-spacing)}fieldset legend{font:var(--font)}.field-row{align-items:center;display:flex}.field-row>*+*{margin-left:var(--grouped-element-spacing)}.field-row-stacked{display:flex;flex-direction:column}.field-row-stacked *+*,[class^=field-row]+[class^=field-row]{margin-top:var(--grouped-element-spacing)}[role=listbox],select[multiple]{background:#fff;border:1px solid #c0c1cd;display:block;font:var(--font);overflow-y:scroll}[role=listbox].has-shadow,select[multiple].has-shadow{box-shadow:4px 4px 3px -2px #999}[role=listbox].has-hover li:hover,select[multiple].has-hover li:hover{background-color:#2a90ff;color:#fff}[role=listbox]:focus,select[multiple]:focus{outline:none}[role=listbox] [role=option],[role=listbox] option,select[multiple] [role=option],select[multiple] option{padding:2px}[role=listbox] [role=option]:focus,[role=listbox] [role=option][aria-selected],[role=listbox] option:focus,[role=listbox] option[aria-selected],select[multiple] [role=option]:focus,select[multiple] [role=option][aria-selected],select[multiple] option:focus,select[multiple] option[aria-selected]{background-color:#2a90ff;color:#fff}:root{--listview-chevron-size:5px;--listview-background:#fff;--listview-border:1px solid;--listview-border-color:#eee;--listview-border-color-header:#d7d7d7;--listview-gradient:linear-gradient(180deg,#fff 45%,#fafafa 0,#f0f0f0);--listview-header-border-color-highlight:#a7d8f5;--listview-header-gradient-highlight:linear-gradient(180deg,#f3f9fc 45%,#e4f0f8 0,#d9eaf5);--listview-header-chevron-background:linear-gradient(to bottom right,#667f91 45%,#90c1e2 65%,#cce3f2)}table{background-color:var(--listview-background);border:1px solid #c0c1cd;border-collapse:collapse;font:var(--font);position:relative;table-layout:fixed;text-align:left;white-space:nowrap}table td,table th{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}table.has-shadow{box-shadow:4px 4px 3px -2px #999}table>thead>tr>*{background:var(--listview-gradient);border:var(--listview-border) var(--listview-border-color-header);box-sizing:border-box;cursor:default;font-weight:400;height:22px;padding:0 var(--grouped-element-spacing);position:sticky;top:0}table>thead>tr>.highlighted{background:var(--listview-header-gradient-highlight);border:var(--listview-border) var(--listview-header-border-color-highlight);border-radius:var(--border-radius)}table>thead>tr>.highlighted:not(:last-child){border-right-color:var(--listview-header-border-color-highlight)}table>thead>tr>.highlighted.indicator:before{background:var(--listview-header-chevron-background);-webkit-clip-path:polygon(0 0,50% 100%,100% 0);clip-path:polygon(0 0,50% 100%,100% 0);content:"";height:var(--listview-chevron-size);position:absolute;right:50%;top:0;width:calc(var(--listview-chevron-size)*1.2)}table>thead>tr>.highlighted.indicator.up:before{-webkit-clip-path:polygon(0 100%,50% 0,100% 100%);clip-path:polygon(0 100%,50% 0,100% 100%)}table>tbody>tr{cursor:default}table>tbody>tr.highlighted{background:var(--item-highlighted-background);border:var(--listview-border) var(--item-highlighted-border);border-radius:var(--border-radius)}table>tbody>tr.highlighted>:not(:last-child){border-right:none}table>tbody>tr>*{height:14px;padding:2px var(--element-spacing)}table>tbody>tr>:not(:last-child){border-right:var(--listview-border) var(--listview-border-color)}:root{--menu-padding:2px;--item-offset-left:30px}ul[role]{cursor:default;list-style:none;margin:0;padding:0}ul[role=menubar]{background:linear-gradient(#fff 20%,#f1f4fa 25%,#f1f4fa 43%,#d4dbee 48%,#e6eaf6);display:flex}ul[role=menubar]>[role=menuitem]{padding:6px 10px;position:relative}ul[role=menubar]>[role=menuitem]:focus,ul[role=menubar]>[role=menuitem]:focus-within,ul[role=menubar]>[role=menuitem]:hover{background:#39f;color:#fff;outline:none}ul[role=menubar]>[role=menuitem]:focus-within~[role=menuitem]:focus,ul[role=menubar]>[role=menuitem]:focus-within~[role=menuitem]:focus-within,ul[role=menubar]>[role=menuitem]:focus~[role=menuitem]:focus,ul[role=menubar]>[role=menuitem]:focus~[role=menuitem]:focus-within,ul[role=menubar]>[role=menuitem]:hover~[role=menuitem]:focus,ul[role=menubar]>[role=menuitem]:hover~[role=menuitem]:focus-within{background:transparent;color:inherit}ul[role=menubar]>[role=menuitem]:focus-within:has(~[role=menuitem]:hover),ul[role=menubar]>[role=menuitem]:focus:has(~[role=menuitem]:hover),ul[role=menubar]>[role=menuitem]:hover:has(~[role=menuitem]:hover){background:transparent;color:inherit}ul[role=menu]{background:var(--surface);border:1px solid #0006;box-shadow:4px 4px 3px -2px #00000080;color:initial;min-width:150px;padding:var(--menu-padding);position:relative}ul[role=menu]:before{box-shadow:inset 1px 0 #00000026,inset -1px 0 #fff;content:"";height:calc(100% - 4px);left:var(--item-offset-left);pointer-events:none;position:absolute;width:2px}[role=menuitem] ul[role=menu]{display:none;left:0;position:absolute;top:100%;z-index:99}ul[role=menu] [role=menuitem]>[role=menu]{left:100%;top:-4px}ul[role=menu]>[role=menuitem]>a,ul[role=menu]>[role=menuitem]>button,ul[role=menu]>[role=menuitem]>label,ul[role=menu]>[role=menuitem][aria-haspopup=true]{all:unset;border:1px solid transparent;border-radius:3px;box-sizing:border-box;display:flex;justify-content:space-between;padding:4px 10px 4px 32px;position:relative;white-space:nowrap;width:100%}ul[role=menu]>[role=menuitem]>a:focus-visible,ul[role=menu]>[role=menuitem]>a:hover,ul[role=menu]>[role=menuitem]>button:focus-visible,ul[role=menu]>[role=menuitem]>button:hover,ul[role=menu]>[role=menuitem]>label:focus-visible,ul[role=menu]>[role=menuitem]>label:hover,ul[role=menu]>[role=menuitem][aria-haspopup=true]:focus-visible,ul[role=menu]>[role=menuitem][aria-haspopup=true]:hover{background:var(--item-highlighted-background);border-color:var(--item-highlighted-border)}ul[role=menu]>[role=menuitem]>button:after,ul[role=menu]>[role=menuitem]>button:hover:before{content:none}ul[role=menu]>[role=menuitem][aria-haspopup=true]:after{border:4px solid transparent;border-left-color:currentcolor;content:"";position:absolute;right:2px;top:50%;transform:translateY(-50%)}ul [role=menuitem]{position:relative}ul [role=menuitem]>input[type]{display:none}ul [role=menuitem]>input[type]+label{display:block;position:relative}ul [role=menuitem]>input[type]+label:before{all:unset;background:var(--item-highlighted-background);border-radius:inherit;box-shadow:0 0 0 1px #b3d3f9;box-sizing:border-box;height:22px;left:0;position:absolute;top:0;width:22px}ul [role=menuitem]>input[type]:checked+label:before{content:""}ul [role=menuitem]>input[type][type=radio]:checked+label:after{background:radial-gradient(circle at 75% 25%,#d5d4ea,#333583);border:1px solid #1a1490;box-shadow:none;left:8px;top:50%;transform:translateY(-50%)}ul [role=menuitem]>input[type][type=checkbox]:checked+label:after{color:#0c12a1;font-size:10pt;left:6px;top:50%;transform:translateY(-52%)}ul [role=menuitem]:focus-within>[role=menu],ul [role=menuitem]:focus>[role=menu]{display:block}ul [role=menuitem]:focus-within:has(~[role=menuitem]:hover)>[role=menu],ul [role=menuitem]:focus:has(~[role=menuitem]:hover)>[role=menu]{display:none}ul [role=menuitem][aria-disabled]{opacity:.5;pointer-events:none}ul [role=menuitem].has-divider:after{box-shadow:inset 0 1px #00000026,inset 0 -1px #fff;content:"";display:block;height:2px;margin:3px 0 2px;margin-left:var(--item-offset-left);pointer-events:none}ul [role=menuitem] img{left:2px;pointer-events:none;position:absolute;top:50%;transform:translateY(-50%);z-index:1}ul [role=menuitem] span{margin-left:32px}ul.can-hover [role=menuitem]:hover>[role=menu]{display:block}ul.can-hover [role=menuitem]:hover~[role=menuitem]:focus,ul.can-hover [role=menuitem]:hover~[role=menuitem]:focus-within{background:transparent;color:inherit}ul.can-hover [role=menuitem]:hover~[role=menuitem]:focus-within>[role=menu],ul.can-hover [role=menuitem]:hover~[role=menuitem]:focus>[role=menu]{display:none}:root{--progress-color-normal:#0bd82c;--progress-color-paused:#e6df1b;--progress-color-error:#ef0000}[role=progressbar]{background:radial-gradient(circle at 0 50%,#0000001f 10px,transparent 30px),radial-gradient(circle at 100% 50%,#0000001f 10px,transparent 30px),linear-gradient(180deg,#f3f3f3af,#fcfcfcaf 3px,#dbdbdbaf 6px,#cacacaaf 0,#d5d5d5af),#ddd;border:1px solid var(--button-border-color);border-radius:var(--border-radius);box-shadow:inset 0 0 0 1px #f3f3f388,0 0 0 1px #eaeaea88;height:15px;margin:2px 0;overflow:hidden}[role=progressbar]>div{background-color:var(--progress-color-normal);background-image:linear-gradient(180deg,#f3f3f3af,#fcfcfcaf 3px,#dbdbdbaf 6px,transparent 0),radial-gradient(circle at 0 50%,#0000002f 10px,transparent 30px),radial-gradient(circle at 100% 50%,#0000002f 10px,transparent 30px),linear-gradient(180deg,transparent 65%,#ffffff55),linear-gradient(180deg,transparent 6px,#cacaca33 0,#d5d5d533);box-shadow:inset 0 0 0 1px #ffffff1f;height:100%;overflow:hidden}[role=progressbar].paused>div{background-color:var(--progress-color-paused)}[role=progressbar].error>div{background-color:var(--progress-color-error)}[role=progressbar].animate>div:before,[role=progressbar].marquee:before{-webkit-animation:progressbar 3s linear infinite;animation:progressbar 3s linear infinite;background:linear-gradient(90deg,transparent,#ffffff80,transparent 40%);content:"";display:block;height:100%}[role=progressbar].marquee:before{background:linear-gradient(to right,transparent,var(--progress-color-normal),transparent 35%);opacity:.5}@-webkit-keyframes progressbar{0%{transform:translateX(-40%)}60%{transform:translateX(100%)}to{transform:translateX(100%)}}@keyframes progressbar{0%{transform:translateX(-40%)}60%{transform:translateX(100%)}to{transform:translateX(100%)}}:root{--radio-width:14px;--radio-label-spacing:6px;--radio-total-width-precalc:var(--radio-width) + var(--radio-label-spacing);--radio-total-width:calc(var(--radio-total-width-precalc));--radio-dot-width:8px;--radio-dot-offset:calc(var(--radio-width)/2);--radio-dot-top:calc(var(--radio-dot-offset) - var(--radio-dot-width)/2);--radio-dot-left:calc(var(--radio-total-width)*-1 + var(--radio-width)/2 - var( + --radio-dot-width + )/2)}input[type=radio]{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:0;border:none;margin:0;opacity:0;position:fixed}input[type=radio]+label{align-items:center;display:inline-flex;font:var(--font);margin-left:var(--radio-total-width);position:relative}input[type=radio]+label:before{background:#f6f6f6;border:1px solid;border-color:var(--button-border-color);border-radius:50%;box-shadow:inset 0 0 0 1.5px #f4f4f4,inset 1px 1px 0 1.5px #aeaeae,inset -1px 0 0 1.5px #ddd,inset 3px 3px 6px #ccc;box-sizing:border-box;content:"";display:inline-block;height:var(--radio-width);left:calc(var(--radio-total-width)*-1);margin-right:var(--radio-label-spacing);position:absolute;top:0;transition:.4s;width:var(--radio-width)}input[type=radio]+label:hover:before{border-color:var(--button-border-color-hovered);box-shadow:inset 0 0 0 1.5px #def9fa,inset 1px 1px 0 1.5px #79c6f9,inset -1px -1px 0 1.5px #c6e9fc,inset 3px 3px 6px #b1dffd}input[type=radio]:checked+label:after{background:#7cd3eb;border:1.5px solid #27506d;border-radius:50%;box-shadow:inset -1px -1px 0 .5px #16638f,inset -1px -1px 0 1px #1985c0;box-sizing:border-box;content:"";display:block;height:var(--radio-dot-width);left:var(--radio-dot-left);position:absolute;top:var(--radio-dot-top);width:var(--radio-dot-width)}input[type=radio]:focus-visible+label{outline:1px dotted #000}input[type=radio]:disabled+label{opacity:.6}:root{--scrollbar-y:linear-gradient(to right,#e5e5e5,var(--surface) 20%);--scrollbar-x:linear-gradient(to bottom,#e5e5e5,var(--surface) 20%)}.has-scrollbar::-webkit-scrollbar{width:16px}.has-scrollbar::-webkit-scrollbar:horizontal{height:17px}.has-scrollbar::-webkit-scrollbar-corner{background:var(--button-face)}.has-scrollbar::-webkit-scrollbar-track:vertical{background:var(--scrollbar-y)}.has-scrollbar::-webkit-scrollbar-track:horizontal{background:var(--scrollbar-x)}.has-scrollbar::-webkit-scrollbar-thumb{background-color:var(--button-face);border:var(--button-border);border-color:var(--button-border-color);border-radius:var(--border-radius);box-shadow:var(--button-shadow)}.has-scrollbar::-webkit-scrollbar-thumb:vertical{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAKCAIAAADpZ+PpAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAADrSURBVChTTc5LboJQGAXguyoCu4ERCzAGlRk7UOwGWIDh0s4M4kxb06RSq/jAB6AxJkJ4lTDrue3AnvyzP+fLId+/yfM8juP7PQmCCOf7B3e+ZD+O40RRVFW12VQUpd3r9U3T2m4OpKoqWZYNwzBZLEqfh0N7NnvfrPcEWlEUWZb9mWF4Ph6D0ylcLbfM5HkeJrhGA2hb15/QXnv+w7RYXsDatjOdvnmrHSnLEizMNE2v11sUXQBCnn98kbquBUGQJAlmq9WB2e3qg4HJdqKkaRql1HGc0WgMcDJ5dd0F24kediZJ8t/ELT69H+8py0CYSIO5AAAAAElFTkSuQmCC") no-repeat 50%,linear-gradient(to right,var(--button-face) 45%,var(--button-shade-light) 45%,var(--button-shade-dark))}.has-scrollbar::-webkit-scrollbar-thumb:horizontal{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAJCAYAAAALpr0TAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAADcSURBVChTNZBLqoUwEEQrURQUxZGCvy24ACfiityJi7tv8GauQoPxk5tquA2RQ9vVVYk6z9NZaxFFEe77htYazjk8z4MwDIVZ+rourOuKaZrwvi+WZcE8z1BKCbPPCjk4DAO2bRP1OI7wLiL6Mbd7J408z1GWpQwWRYGqqiQG+03TgMu0MacfUN4qANmn8UOv9MjW3sKaSm7iIdOSlziOQ3LScd93aPonSYK6riVLlmVo21aYfVqzND9pmqLrOlGT+76XbcxLZkb19/l3fEP+oF0cx8KMEASBsDEGX2/CgZCHkg+8AAAAAElFTkSuQmCC") no-repeat 50%,linear-gradient(to bottom,var(--button-face) 45%,var(--button-shade-light) 45%,var(--button-shade-dark))}.has-scrollbar::-webkit-scrollbar-thumb:hover:vertical{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAKCAIAAADpZ+PpAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAADrSURBVChTTc5LboJQGAXguyoCu4ERCzAGlRk7UOwGWIDh0s4M4kxb06RSq/jAB6AxJkJ4lTDrue3AnvyzP+fLId+/yfM8juP7PQmCCOf7B3e+ZD+O40RRVFW12VQUpd3r9U3T2m4OpKoqWZYNwzBZLEqfh0N7NnvfrPcEWlEUWZb9mWF4Ph6D0ylcLbfM5HkeJrhGA2hb15/QXnv+w7RYXsDatjOdvnmrHSnLEizMNE2v11sUXQBCnn98kbquBUGQJAlmq9WB2e3qg4HJdqKkaRql1HGc0WgMcDJ5dd0F24kediZJ8t/ELT69H+8py0CYSIO5AAAAAElFTkSuQmCC") no-repeat 50%,linear-gradient(to right,var(--button-face-hover) 45%,var(--button-shade-light-hovered) 45%);border-color:var(--button-border-color-hovered)}.has-scrollbar::-webkit-scrollbar-thumb:hover:horizontal{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAJCAYAAAALpr0TAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAADcSURBVChTNZBLqoUwEEQrURQUxZGCvy24ACfiityJi7tv8GauQoPxk5tquA2RQ9vVVYk6z9NZaxFFEe77htYazjk8z4MwDIVZ+rourOuKaZrwvi+WZcE8z1BKCbPPCjk4DAO2bRP1OI7wLiL6Mbd7J408z1GWpQwWRYGqqiQG+03TgMu0MacfUN4qANmn8UOv9MjW3sKaSm7iIdOSlziOQ3LScd93aPonSYK6riVLlmVo21aYfVqzND9pmqLrOlGT+76XbcxLZkb19/l3fEP+oF0cx8KMEASBsDEGX2/CgZCHkg+8AAAAAElFTkSuQmCC") no-repeat 50%,linear-gradient(to bottom,var(--button-face-hover) 45%,var(--button-shade-light-hovered) 45%);border-color:var(--button-border-color-hovered)}.has-scrollbar::-webkit-scrollbar-thumb:active:vertical{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAKCAIAAADpZ+PpAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAADrSURBVChTTc5LboJQGAXguyoCu4ERCzAGlRk7UOwGWIDh0s4M4kxb06RSq/jAB6AxJkJ4lTDrue3AnvyzP+fLId+/yfM8juP7PQmCCOf7B3e+ZD+O40RRVFW12VQUpd3r9U3T2m4OpKoqWZYNwzBZLEqfh0N7NnvfrPcEWlEUWZb9mWF4Ph6D0ylcLbfM5HkeJrhGA2hb15/QXnv+w7RYXsDatjOdvnmrHSnLEizMNE2v11sUXQBCnn98kbquBUGQJAlmq9WB2e3qg4HJdqKkaRql1HGc0WgMcDJ5dd0F24kediZJ8t/ELT69H+8py0CYSIO5AAAAAElFTkSuQmCC") no-repeat 50%,linear-gradient(to right,var(--button-face-active) 45%,var(--button-shade-light-active) 45%);border-color:var(--button-border-color-active)}.has-scrollbar::-webkit-scrollbar-thumb:active:horizontal{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAJCAYAAAALpr0TAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAADcSURBVChTNZBLqoUwEEQrURQUxZGCvy24ACfiityJi7tv8GauQoPxk5tquA2RQ9vVVYk6z9NZaxFFEe77htYazjk8z4MwDIVZ+rourOuKaZrwvi+WZcE8z1BKCbPPCjk4DAO2bRP1OI7wLiL6Mbd7J408z1GWpQwWRYGqqiQG+03TgMu0MacfUN4qANmn8UOv9MjW3sKaSm7iIdOSlziOQ3LScd93aPonSYK6riVLlmVo21aYfVqzND9pmqLrOlGT+76XbcxLZkb19/l3fEP+oF0cx8KMEASBsDEGX2/CgZCHkg+8AAAAAElFTkSuQmCC") no-repeat 50%,linear-gradient(to bottom,var(--button-face-active) 45%,var(--button-shade-light-active) 45%);border-color:var(--button-border-color-active)}.has-scrollbar::-webkit-scrollbar-button:horizontal:end:decrement,.has-scrollbar::-webkit-scrollbar-button:horizontal:start:increment,.has-scrollbar::-webkit-scrollbar-button:vertical:end:decrement,.has-scrollbar::-webkit-scrollbar-button:vertical:start:increment{display:none}.has-scrollbar::-webkit-scrollbar-button{border:var(--button-border) transparent}.has-scrollbar::-webkit-scrollbar-button:vertical{height:17px}.has-scrollbar::-webkit-scrollbar-button:vertical:start{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik04IDZIN3YxSDZ2MUg1djFINHYxaDdWOWgtMVY4SDlWN0g4VjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),var(--scrollbar-y)}.has-scrollbar::-webkit-scrollbar-button:vertical:end{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik0xMSA2SDR2MWgxdjFoMXYxaDF2MWgxVjloMVY4aDFWN2gxVjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),var(--scrollbar-y)}.has-scrollbar::-webkit-scrollbar-button:horizontal{width:16px}.has-scrollbar::-webkit-scrollbar-button:horizontal:start{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIxMDAlIiB4Mj0iMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik05IDRIOHYxSDd2MUg2djFINXYxaDF2MWgxdjFoMXYxaDFWNFoiIGZpbGw9InVybCgjYSkiLz48L3N2Zz4="),var(--scrollbar-x)}.has-scrollbar::-webkit-scrollbar-button:horizontal:end{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIxMDAlIiB4Mj0iMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik03IDRINnY3aDF2LTFoMVY5aDFWOGgxVjdIOVY2SDhWNUg3VjRaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),var(--scrollbar-x)}.has-scrollbar::-webkit-scrollbar-button:hover{background-color:var(--button-face);border-color:var(--button-border-color);border-radius:var(--border-radius);box-shadow:var(--button-shadow)}.has-scrollbar::-webkit-scrollbar-button:hover:vertical{height:17px}.has-scrollbar::-webkit-scrollbar-button:hover:vertical:start{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik04IDZIN3YxSDZ2MUg1djFINHYxaDdWOWgtMVY4SDlWN0g4VjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),linear-gradient(to right,var(--button-face-hover) 45%,var(--button-shade-light-hovered) 45%);border-color:var(--button-border-color-hovered)}.has-scrollbar::-webkit-scrollbar-button:hover:vertical:end{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik0xMSA2SDR2MWgxdjFoMXYxaDF2MWgxVjloMVY4aDFWN2gxVjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),linear-gradient(to right,var(--button-face-hover) 45%,var(--button-shade-light-hovered) 45%);border-color:var(--button-border-color-hovered)}.has-scrollbar::-webkit-scrollbar-button:hover:horizontal{width:16px}.has-scrollbar::-webkit-scrollbar-button:hover:horizontal:start{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIxMDAlIiB4Mj0iMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik05IDRIOHYxSDd2MUg2djFINXYxaDF2MWgxdjFoMXYxaDFWNFoiIGZpbGw9InVybCgjYSkiLz48L3N2Zz4="),linear-gradient(to bottom,var(--button-face-hover) 45%,var(--button-shade-light-hovered) 45%);border-color:var(--button-border-color-hovered)}.has-scrollbar::-webkit-scrollbar-button:hover:horizontal:end{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIxMDAlIiB4Mj0iMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik03IDRINnY3aDF2LTFoMVY5aDFWOGgxVjdIOVY2SDhWNUg3VjRaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),linear-gradient(to bottom,var(--button-face-hover) 45%,var(--button-shade-light-hovered) 45%);border-color:var(--button-border-color-hovered)}.has-scrollbar::-webkit-scrollbar-button:active{background-color:var(--button-face);border-color:var(--button-border-color);border-radius:var(--border-radius);box-shadow:var(--button-shadow)}.has-scrollbar::-webkit-scrollbar-button:active:vertical{height:17px}.has-scrollbar::-webkit-scrollbar-button:active:vertical:start{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik04IDZIN3YxSDZ2MUg1djFINHYxaDdWOWgtMVY4SDlWN0g4VjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),linear-gradient(to right,var(--button-face-active) 45%,var(--button-shade-light-active) 45%);border-color:var(--button-border-color-active)}.has-scrollbar::-webkit-scrollbar-button:active:vertical:end{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik0xMSA2SDR2MWgxdjFoMXYxaDF2MWgxVjloMVY4aDFWN2gxVjZaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),linear-gradient(to right,var(--button-face-active) 45%,var(--button-shade-light-active) 45%);border-color:var(--button-border-color-active)}.has-scrollbar::-webkit-scrollbar-button:active:horizontal{width:16px}.has-scrollbar::-webkit-scrollbar-button:active:horizontal:start{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIxMDAlIiB4Mj0iMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik05IDRIOHYxSDd2MUg2djFINXYxaDF2MWgxdjFoMXYxaDFWNFoiIGZpbGw9InVybCgjYSkiLz48L3N2Zz4="),linear-gradient(to bottom,var(--button-face-active) 45%,var(--button-shade-light-active) 45%);border-color:var(--button-border-color-active)}.has-scrollbar::-webkit-scrollbar-button:active:horizontal:end{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iMCUiIHkxPSIxMDAlIiB4Mj0iMCUiIHkyPSIwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzMzMztzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6I2FhYTtzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGQ9Ik03IDRINnY3aDF2LTFoMVY5aDFWOGgxVjdIOVY2SDhWNUg3VjRaIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+"),linear-gradient(to bottom,var(--button-face-active) 45%,var(--button-shade-light-active) 45%);border-color:var(--button-border-color-active)}:root{--search-icon:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggc3Ryb2tlPSIjMjA3MGI5IiBkPSJNMTAuNSAxQzguMDIgMSA2IDMuMDIgNiA1LjVhNC40NSA0LjQ1IDAgMCAwIDEgMi43OTNMMi4wMjMgMTMuMjdsLjcwNC43MUw3LjcwNyA5Yy43Ny42MTcgMS43MzQgMSAyLjc5MyAxIDIuNDggMCA0LjUtMi4wMiA0LjUtNC41UzEyLjk4IDEgMTAuNSAxWm0wIDFDMTIuNDM4IDIgMTQgMy41NjMgMTQgNS41IDE0IDcuNDM4IDEyLjQzNyA5IDEwLjUgOUEzLjQ5NCAzLjQ5NCAwIDAgMSA3IDUuNUM3IDMuNTYyIDguNTYzIDIgMTAuNSAyWiIvPjwvc3ZnPg==");--search-button:var(--search-icon) no-repeat center}[type=search]{background-color:var(--button-highlight);border:1px solid transparent;border-radius:2px;box-shadow:inset 1px 1px 0 var(--button-border-color),inset -1px -1px 0 #ccc;box-sizing:border-box;font:var(--font);height:24px;min-width:187px;padding:3px 6px}[type=search]:-moz-placeholder-shown{background-image:var(--search-icon);background-position:calc(100% - 8px);background-repeat:no-repeat;background-size:14px}[type=search]:placeholder-shown{background-image:var(--search-icon);background-position:calc(100% - 8px);background-repeat:no-repeat;background-size:14px}[type=search]:focus{outline:none}[type=search]::-moz-placeholder{font-style:italic}[type=search]::placeholder{font-style:italic}.searchbox [type=search]{padding-right:26px}.searchbox [type=search]+[aria-label=search]{background:var(--search-button),var(--button-gradient);background-size:14px;border-radius:0;min-height:22px;min-width:26px;padding:0;position:absolute;right:1px;top:1px}.searchbox [type=search]+[aria-label=search]:before{background:var(--search-button),var(--button-gradient-hovered);background-size:14px;border-radius:0}.searchbox [type=search]+[aria-label=search]:after{background:var(--search-button),var(--button-gradient-active);background-size:14px;border-radius:0}.searchbox [type=search]+[aria-label=search]:focus-visible{outline:1px dotted #000;outline-offset:-4px}.searchbox{display:inline-block;position:relative}:root{--thumb-w:10px;--thumb-h:18px;--thumb-icon:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAASCAYAAABit09LAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAC7SURBVHgBlZLBCYQwEEVj9CDYgRfbswF7sRAbsArPdhBICDmEzPoDE9CdXeKH0eHP48fINOrSPM+k/mhd16YDtCyLmqZJhM7zxIs6PAF570WQAzJIRLkksd89DUl939eB1Ym3b0wpiQBmIYSXiTFGZYwRgWEY6o8uIPQLZGlu2rYtP54L3g3c912N45gHSEahh4dZERZj2zZyztFxHLnQw/vaLIattbmeULkMdg6XxLFaa3WB7MlCirTIHxVUkxicbwSEAAAAAElFTkSuQmCC");--thumb-icon-box:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAASCAYAAABit09LAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAABrSURBVHgB7dLNCcAgDAXgWASjm9TJ3Egns8N4SGv6c2gbyQA+kED40IPPwJGUEsEgpRRjO8o5i6i11gfZe7HVCojIJ4QA6D3vnXM8F1DmBUkL1TdOOIRGC2X7hcIvPu1ZY/wFV83OhzTF3QGRrxiDB3GCSQAAAABJRU5ErkJggg==");--thumb-icon-active:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAASCAYAAABit09LAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACsSURBVHgB3ZKxCoMwEIYvJWOn0r10LHTuVDp1KIU+RN+gT9FZ6AP0LYqDY+nQWXAScXMQdRYh+ouRqEF0cPGHHJfcl7sbfkaFroYlqEefx5lxQK/blu6rjRZ6R34RLcFxAWSkmRZEbUkeLWigZgVymZhuoid264lGjwMvTkhmtYsqvKEGMQQY43jYNwoy//7t0j31b8DPXyBOcVYe5Kr9mDpKdoY6ndoCrDNyDnRZRNbxQWFyAAAAAElFTkSuQmCC");--thumb-icon-box-active:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAASCAYAAABit09LAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAABmSURBVHgB7dKxCYAwEAXQfyEKYhrBThdwCwsLyRKukFGcRiyyh0tY2kcT0fJIn/zijg+v/IQnerUOTDYzkfToWkbOQcM6+ZX5OMNvVIVeFehqEbopXyIQmQzTgf969qFlIfkTM9wbGH4SS8YdBX4AAAAASUVORK5CYII=")}input[type=range]{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;padding:10px 1px;width:100%}input[type=range]:focus-visible{outline:1px dotted #000}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;background:var(--thumb-icon);height:var(--thumb-h);transform:translateY(-7px);width:var(--thumb-w)}input[type=range]::-webkit-slider-thumb:active{background:var(--thumb-icon-active)}input[type=range]::-moz-range-thumb{background:var(--thumb-icon);border:0;border-radius:0;height:var(--thumb-h);width:var(--thumb-w)}input[type=range]::-moz-range-thumb:active{background:var(--thumb-icon-active)}input[type=range]::-webkit-slider-runnable-track{background:var(--surface);box-shadow:inset 1px 1px 1px #999,inset -1px 0 #999,0 1px #fff;box-sizing:border-box;height:3px;width:100%}input[type=range]::-moz-range-track{background:var(--surface);box-shadow:inset 1px 1px 1px #999,inset -1px 0 #999,0 1px #fff;box-sizing:border-box;height:3px;width:100%}input[type=range].has-box-indicator::-webkit-slider-thumb{background:var(--thumb-icon-box)}input[type=range].has-box-indicator::-webkit-slider-thumb:active{background:var(--thumb-icon-box-active)}input[type=range].has-box-indicator::-moz-range-thumb{background:var(--thumb-icon-box)}input[type=range].has-box-indicator::-moz-range-thumb:active{background:var(--thumb-icon-box-active)}.is-vertical{display:inline-block;height:150px;transform:translateY(50%);width:4px}.is-vertical>input[type=range]{height:4px;margin:0 calc(var(--grouped-element-spacing) + var(--range-spacing)) 0 var(--range-spacing);transform:rotate(270deg) translateX(calc(-50% + var(--element-spacing)));transform-origin:left;width:150px}.is-vertical>input[type=range]::-webkit-slider-thumb{transform:translateY(-8px) scaleX(-1)}.is-vertical>input[type=range]::-moz-range-thumb{transform:translateY(2px) scaleX(-1)}.is-vertical>input[type=range].has-box-indicator::-webkit-slider-thumb{transform:translateY(-9px) scaleX(-1)}.is-vertical>input[type=range].has-box-indicator::-moz-range-thumb{transform:translateY(0) scaleX(-1)}.loader,.spinner{background:url("data:image/png;base64,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") 50%;color:transparent;display:inline-block;height:20px;width:20px}.loader.animate,.spinner.animate{background-image:url("data:image/gif;base64,R0lGODlhIAAgAPcAAAIRDmyhxGqfw5S707zV5Njm7+nw9unx9tfm773X4pDBy4ayy8HZ5dbl7sfc6L3W47XT37TR373W5Mbe5ePt9MDa4Yazy4muwcre6LrU46LF15C60YS3yJe+1HyyxYSzzJC9zqHL0rrY38rf54evvn6erLvS26TG14i3zXiux5S/0pW/03axwp/F1qTK08PW4HygqJu0vZi6yHWrwnWtxHOxv3Wvv5i9x5u1vXiQmZu1vnChsWOjuWSiuXClrpu8unWWlHuUm3qcp1iSpIq7yVmdm6/EynielHeboU14f0uKlEmXpEmWkkuMgE12dH6WnF2ZnjaPlBmSmgmKlzqEkRZgXzlgaGyJjlCrsSmusi6/whKgqQVtbSJuaCxnWmePh1O8wD7Sz4bt7HrO0Atydyx9cWyQknOjjmPRyqPt6vz9/drs6abX0G68vR6Ehyt8dy93YpDm4uz+/eH6+cTu7CGnpVCwsBh+fUiEeS7a2qn7+9r+/c7384Pg0TG/rz2+uzyzsByOiEbv6bT+/9v//3338inc1U7Wz1fSwWLY0FXVyVrSzBOrpkqqlF7e1TPt5WL9/Fj8+ob49kfr5ELf1h7TxBHKuinRxkjZ0Ijo4EnZzhfFu0G5qnbg1hfx3Rf18DX282z18ZH18KL18Kb174Xv5mPm4C/a0iHQxEXOs0/jwyjvzy/w4iLt4iLr3l7w6Dfo1yjcyjnWvmPerXbmt1jhrEDcqz/cmVfgqZS71Njn7+nx99fn7sDY45S/0MHZ5sfd6LzW47TS4LTQ4L3X48zg6djo7sDZ5IWzysnd6LvV46HF2I+70Iy6zoS0yXyvx4S0y6PJ1rzX4cvg6IuwwX6crLzR23esxpO/0H2xx427zabI1rzS236eqpu4wZi7yHWswnStxHSvwnWtwJi9xpu3vWqosJzIz3C1wmGswGSkt3apsajBxXWUlIDEy2/DyXrO01i9xnzE0om8xlyboYSpq3mXmFG7xGHX2Xrh413HzVaWnUyChU5xeEnFzaTy8yH+JUNyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWNzIFByb2Nlc3NvcgAAIf8LTkVUU0NBUEUyLjADAQAAACH5BAUBAAAALAAAAAAgACAABwj/AAEIHEiwoMGDCBMqXMiwocOHECNKnBgxgACKBwcQKGDgAIIECjACWMCggYMHECJImEChgoWJFzBk0LCBQwcPH0CEEDGCRMQSJk6gSKGC4AoWLVy8gAExhowZNBDWsHEDx8McOnbwUNjDxw8gDoMIGUJEIZEiRo40RJJEyRKGTJo4ecIQShQpUxhSqWLlCkMsWbRsYcili5cvDMGEETOGIZkyZs4wRJNGzRo2Ctu4eQPHYRw5c+gorGPnDh6HefTs4dMHoZ8/gAJBFDSIUCFDhwgiSqRoEaNGEB09ghRJ0iRKlSxdwpRJ0yZOEjt5+gQqlKhRpEqZOoUqFUZVq1i1GnL1ClYsWbNECqRVy9YtXOrjy59Pv779+AEBACH5BAUBAAAALAAAAAAgACAAhwERDmyhxGqfw5S71LzV5Njn7+nx9unx99fn7sDY45S/0Iazy8HZ5tbl7sfd6LzW47TS4LTQ4L3X48zg6djo7sDZ5IWzyomuwcnd6LvV46HF2I+70Iy6zoS0yXyvx4S0y5C9zqPJ1rzX4cvg6IuwwX6crLzR26TG14i3zXesxpS/0pO/0H2xx427zabI1rzS236eqpu4wZi7yHWswnStxHSvwnWtwJi9xpu3vWqosJzIz3C1wmGswGSkt3apsajBxXWUlIDEy2/DyXrO01i9xnzE0om8xlyboYSpq3mXmFG7xGHX2Xrh413HzVaWnUyChU5xeH6WnEnFzaTy89Hz9JjHzRhwexdeYDdmZGqMizbP1+f+/vj6+rrV2AVncCJpZ0tzdGmRiSnY2tn8/Pn8+8bd3wtscixwbjBjXXqdlj/d0aP49vj+/tnq6ZfS0XK5ux16fSttbjNiYHnp5Nn+/pL39T3b0yOhn0+nphhvbk95eD3ZxCn7+Ej5+Fjy7zjdzkvBsj24rjyopR5+eh3gzRD181n38lzw5SXWxFfTymHNwjvFsWLSx1rLwRSdllWelRfuwC7z65X59Ybx60fh2CjUxCzQwxHJtSnLvUjQx4fg2UnRxRi5rUezoyboqxnr2i/r4mjt54Xv5qv07p7x55Xt5GPh0zDQxyPFuFDHs1bjqy3iwj7l1y7l1yLg0iThy2Lp2y/Xu0HNt3/VwnvktmTctlHRskjWoFngnQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj/AAEIHEiwoMGDCBMqXMiwocOHECNKnBgxgACKBwcQKGDgAIIECjACWMCggYMHECJImEChgoWJFzBk0LCBQwcPH0CEEDGCRMQSJk6gSKGC4AoWLVy8gAExhowZNBDWsHEDx8McOnbwUNjDxw8gDYMIGUKkiEIjR5AkaahkCZMmDJ08gRKFoZQpVKowtHIFSxaGWrZw6cLQyxcwYRiKGUOmDEMzZ9CkYahmDZs2bhS+gRNHjsM5dOrYCZDwDp48ehzu4dPHzx+EgAIJGgSRUCFDhxAlIqhoEaNGjh5FhBRJ0iRKlSxdwpRJ0yZOnSZ6+gQqlKhRpEqZOoUqFUZVq1i1G3L1ClYsWbNECqRVy9YtXKTVy59Pv779+yIDAgAh+QQFAQAAACwAAAAAIAAgAIcCEg9socRqoMOUu9O81eTY5+/p8fbq8fbX5++/1+SUvNKGs8vA2ObW5e/I3Oi91uS10eC00eC91+PI3ujW5u3A2eWGs8qAusvK4Oq61eKixdiQvNCKt818r8d8rsiEtMuQvM+lyNm71uLM3+mJrsBkv8q75Oqk2OOIw9V2r8eTv9GUv9F6sMaIuMukx9a70tt+nqtcxM6e5eqg5ut20t1tvtB1rcN1rMGavsictr6B2+HP+Pmv7/JtzdlkpLd4qLSgub94kphZ0tvF8/T6/f7j7fCr0tuJvMdalqF6n6Z6k5ke39rf/P36+/zV5OdRkZ1LfodNcHZ9l5si49zp///4+vq81dkKZ3QXW2FDam9rjIw+09Kd/f3S9/iXyc8FZHIiZGo0YGI/zsg6+Phk8/QlyswLbHItbG8mVld9mppg1L4S5eAs8fEd2ttPzc1zuLsdeXwra24X2qww7epP6+YVzcQjoZdPpKQYbGxPd3hJ14x18OtG6uNI49tn3NZxysVDuKg9pJ0feXYn25MR4NlZ6+RQ59Ym0bhc0MhnycIuuKVVyLlax7gUlIxZmpUi4awV49aB8umZ8elI29AozsEcx7QjxLEoxa1IzLqH29ZJyb0Yr6JNqqI13aww5tIv5dFj5tyI6uKl7+ep7+aO6dl85NUwzLcmu61WwbJn3bU4170s2cdI39Um18Yi1L862r5V2b9EyquD08B947Ri3qhS0qVcyrJ01rUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/wABCBxIsKDBgwgTKlzIsKHDhxAjSpwYMYAAigcHEChg4ACCBAowAljAoIGDBxAiSJhAoYKFiRcwZNCwgUMHDx9AhBAxgkTEEiZOoEihguAKFi1cvIDxMIaMGTRqILRxA0eOhzp28Oih0McPIEEaChlCpIgRhUeQJFHScAmTJk4YPoESRQrDKVSqWGF4BUsWLQy3cOniheEXMGEALxQzhkwZhmbOoEnDUM0aNm3cKHwDJ04Yh3Lm0Kmj0M4dPHkc6tnDp48fhH8ABRIEcRChQoYOISKYSNEiRo0cRXwEKZKkSZQqWbqEKZOmTZwmdvL0CVQoUaNIlTJ1ChXGVKpWsRpq5eoVrFiyRAqcRauWrVvq48ufT7++/fgBAQAh+QQFAQAAACwAAAAAIAAgAIcCEw9socRqn8N/wtmQwdi71uXY5+/p8fbp8ffX5u+91uSUvNRp0uK+6PDW7PLI3+q91eS10OG0z+DG2+jW5e7A2OaHsstw1OB94uvS9vm+7/Sh3OiQyNqEts18rsh9rsmEs8yQutGhxdi61ePK3umJrcF44ejz/v/n/f2k6/J2ydqIx9mVvtN4rsaHt82kx9e60dt+nash5tvh+/v8/v7t9fey2eR1rsR1q8KZusibtL2F7+z5///3+frW5+1ko7lwobGbtb14kJhc0tCc+fnk7vC51t6Lu8lZkqN6naZ6k5o1z8Vd+vmV9/mc3uJJi5lMfIhNbnZ+lpwtzK428fEj7vAVusIKZXUWV2M4X2ZsiY43xp8n6egj4+MFuL4FZHEjYmosV11MxZEc2c4v2NkKt7oLbXIta28mVFd+mZt5zKQY0qIt0NEewsRayMVxubkeenwra240YGIhzIgYz8pP29YZwb0nqJRPp6IYbGxPd3hayJBD2cxX4tg92c1M0sZYwbNTv7I8ppseenZO2qUr2stZ49lf39Ut0bddz8Frx78xsKdMwbJaxbgTk4xZmpUzzK4V08lK4s6f8OVH18EowrcRuKMrv60qwKZHyLCH2s5KxLoYrJ9OqaE+1bEf2Lto6dtj49CF5Nqf6d+q6+OI49GK5tdG0bgmuaFavrFi3qg71K4ay6kx0MA+1McjzLQpyq1Ezq9Fy5x11rdfy6lfyK2C0b8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/wABCBxIsKDBgwgTKlzIsKHDhxAjSpwYMYAAigYHEChg4ACCBAoWYATAoIGDBxAiSFAwgUIFCxIvYMigYQOHDh4+gAghYgSJEhFNnECRQsUKgixauHgBI8ZDGTNo1LCB8AaOHDoe7uDRw4fCH0CCCGk4hMiJIkYUHkGSREnDJUyaOGH4BEoUKQynUKliheEVLFm0MNzCpYsXhl/AhBG8UMwYMmUYmjmDJg1DNWvYtHGj8A2cOHIczqFTx47CO3jy6HG4h08fP38QAgokaBBEQoUMHUKUiKCiRYwaOXoUEVIkSZMoVbJ0CVMmTZs4dZro6ROoUKJGkSpl6hSqVBhVrRpi1crVK1ixZI0kOItWLVvr48ufT7++/fgBAQAh+QQFAQAAACwAAAAAIAAgAIcBEQ2Bz+NxvddjqMhqn8NY1+mD4++16/PX8ffp8/fq8vfX5vC91uWUvNRb3d586fLu/f/r/f7W9/q96/G13ei00+K91eTG3OjW5e7A2OWHsstb2tiO9/T8///9/v75+/247fOJ0uF8wNV8tMyEs8yQutCixdi61ePK3eiJrsFo4+X1///w9vnZ6PCp0uGUvtJ3rceIts2kxte70Nt+nqtA1cif/Pzb///t9PfK3+l1rcR1rMGZu8ibtL1O3dSc+/uQ9PaY3ORko7lwoLGctb54kJluzqZl7t568/Vb4+dtztiKu8lZkqN6nKd6k5pTu5RH39lL4eNJzdNJi5lMfIhOb3d+lpw9voY30scZycwJqLAKZHUXV2M5YWhsiY86xIApxrokwsYFoqoFZXEiYmssV1xsiY5buZMfvrAuwsQKpakLbXIta3AnVVh+mZt/yqQfuZQsu7wetLZgxcNwu7YdfHora240X2Exr4sYtLRPzcsbvLpGsatPqaAYbWtPeHhvu5oUt6hBzsU9zcQuxLQ5tKJIuK09pZweeXZCxpdf19Jb2s5V08lMy75izbxsxsAvsaVMvrVbwroTk4xYmZVAyqYWybhK1ciF5NNN0bkpvasRr58UsZo9v7BIx66K3M9Kx7YYrJ9NqaFNybciyrRK2ciE5dmF4NOd5Nue5dqO4NVn18Jz3dYsvqJZv6571r5CzKkvy6wrx7Etx7cvx7Qrwao1waVRx6mE07mB0b5kxqxlxawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/wABCBxIsKDBgwgTKlzIsKHDhxAjSpz4MICAAQQoGixg4ACCBAoWMGig0cEDCBEkTKBQwcIFDBk0SNzAoYOHDyBCiBhBooSJEyhSRFSxwgOLFi4IvoARQ8YMGg9r2LiBIwdCHTt49Hjo4weQIAqFDCFSpKGRI0iSKFG4hEkTJw2fQIkiheEUKlWsMLyCJYsWhlu4dPHC8AuYMGIYjiFTxgzDM2jSqGG4hk0bNwzfwIkjZ45COnXs3HGIJ4+ePQr59PHzxyGgQIIGEUJYyNAhRBATKVrEqJEjgo8gRZI0iVLESpYuYcqkaROnTp4+gQolauIoUqVMnUKVStUqVq1caR18BSuWrFm0atm6hUsjwVy6drmfT7++/fv48w8MCAAh+QQFAQAAACwAAAAAIAAgAIcBEg5a2exM1elEyuFDwNtswdov5uKZ+vjj+/33//7v/f7q+vzV8fa82+mSvNR12Nli6e3m/f79///+/v/+///j+vu/8PS95/DH4uzW5e6/2OWGsst+08Vf7OjQ/v7q///5+/zt9Pjj7vS/4OqF0N+EytqQxdihxdi71eLJ3emJrcFQ38a5+vur+vyx9PfU5O2/2OSQwNN4rsaIt8ykx9e60dt+natfw5qS7++Z9PZ26/Bp1N91rsR1rMKYusictL5W0qqb6+5x4+lZ0dtjorlwobGbtb14kJh4y6Jq28F63eFYztVxzNOKu8lYkqN6nKd6k5pYtoxHx8FLy9FJvsdJi5lMfIhOb3d+lpxDtYc3ubIZsbcJmKMKZXUXWGQ4X2ZsiY5Tq5IprKEkrbEFl58FZHEiYmosV11jspAiop0vra8KnaELbHIsa3AmVFd+mZslnYstpKUdo6Vjw8F1vLodfnkrbG01YGI3ooAYnZxPv74esK4+rKlSqqMYbmtQd3dzuJcYnpc9vLc9wLo2uLA7sKk9sqg9o50fenZJrJchtKhe0cZMyLxHv7hsy79rx74xsaZMv7RbwbwUk4xZmJRUwq0lwbBJzcCI3dJKybQpuaQSq50SrJo2vK5PxreJ285Sy7sZr51NqaFRxq8mvK0vyLN/3tSM3tOd4tqe49tm1MU6yLQ+wq9YwKxKxK04xakrw6ojv64tw7Qwwq8atJtNwaxpw7BoxK8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/wABCBxIsKDBgwgTKlzIsKHDhxAjSpz4MICAAQQKUCxo4ACCBAoWMGjgYOMDCBEkTKBQwcIFDBk0bJDIoYOHDyBCiBhBooSJEyhSqIi4gkULFy9gEIwhYwaNGjYe3sCRQ8cOhDx6+PjxEEgQIUMUEili5EhDJEmULGGisImTJ1AaRpEyhQrDKlauYGGYRcsWLgy7ePkChmEYMWPIMCxj5kzhhWjSqFnDkE0bN28YBoATR84chXTq2LnjEE8ePXsU8unj549DQIEEDSKEsJChQ4ggJlK0iFEjRwQfQYokaRKliJUsXcKUSdMmTp08fQIVStTEUaRKmTqFKhUmVatYtRvaCMDVK1ixZM2iVYt8QVu33MufT7++/fvzAwIAIfkEBQEAAAAsAAAAACAAIACHAQoJWdvgKOLiCfLoIN/oM97dYNndT9rNafryuv7++P///v//////vfn5fN7rc8feUvDOuvv71v7+//7//f7+/P3+4Pz91vX5vubvf7vRYurE1fn7uvn6ofn6pvXz4vHv6vL22+vu4u3zpuvxoeTsuuHryuDpia7BUN6luvPzpPLyiOvvbdvletDeg8rbcsPXiMbXpcfXutHbfp2sXcWIlOjfmevorervYtHSc7LIdazCmLrIm7S9U9WW2/T1b9/YWs3OY6S5cKGxnLW+eJCYbc62etfRWMjJecjPirvJWZKjep2me5OaXbKLSLCwS7i+Sba/SYuaS32ITm94fpacR7J9N5+jGaCfCJ2XCmV2F1hjOF9nbImOUa6BK5GVI6GYabrABWRxI2FrK1Zca6yRJIiEL5uWCpeHC29wLGtvJ1VYfpmbK4d5LI6QHZGUbL2+e72/JYF/LG1tNF9iQJN6GIiHT7OyIqalKaOcUaijGG5rT3d4HI2HPa6qPrayOrOtO6+rPrCqPaOeH3p2T6OTFJ+UWce9TMG3NrSndcrEa8e+MLKlS7+0WsO6E5OLWJiUS7OfOr+0TMi5h9nQTca2KbikEqybEaudKrenV8e9iNrPWs3BILKfTaufWsOtJrejL8CyZdPDleHan+PaneLbhtvRZtPFL8OwLrunVsGqTr+vNb+oNcSvIsGrI7+uNsO0N76sT8CwacOwasOxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACP8AAQgcSLCgwYMIEypcyLChw4cQI0qc+DCAgAEEChigSPAAggQKFjBY0MDBA44QIkiYsIBChQkWLmDIMFHDBg4dPHwAEULECBIlTJyIiCKFihUsWhB08QJGDBkzHtKoYeMGDoQ5dOzg8bCHjx9AFAYRMoSIwyJGjiBRmETJEiYNmzh5AoVhFClTqDCsYuUKFoZZtGzhwrCLly9gGIYRM4bwQjJlzJxhiCaNmjUN2bRx80YhnDhy5jikU8fOHYV48ujZ4zAAnz5+/iAEFEjQIIiEChk6hCgRQUWLGDVy9CgipEiSJlGqZOkSpkyaNnHqNNHTJ1ChRI0iVcrUKVSpOAIYULWKVStXr2DFEl9Q1iz28OPLn0+/fvyAACH5BAUBAAAALAAAAAAgACAAhwESDnHYx0rTzSTf1jfe2Tnj3UHi3V/VuXbp2rH59tT8/er///n///3//+P//57x9kTb7WTbz7z19OX7+9P6+rz7+7/6++L9/P7+/v7+/+f9/m3d6nnZzcz09rvy863w8Jbs6p3r7Jvj6b7k6uPu8+70+Pn7/Or9/tL3+nLP3GXAs7/t76np7Ije5W/Q2XrR1r/Y5NPk7bHu86vq8Lrl63Ksume+kZbZ16Di4ofa32fHz2/I2HbO25nN15q6wmjEoarf23rUz3HL0WGzxnCsupy2v3iPmIHIuKPY1Vm/u3jIyoe9y1mUpHudp3qTmWumk0qhl0qsp0mrsUmLmkx8iE1vd36WnF+YjziHhhmCiAmDiAlldhdYYzdfZ2yJjmOdjyt4eCSIgi+VkQVlcSNiayxXXXijmSdwby6LgTyblA1wcSxsbydVWH6ZmzFxay1+eh2KgW+8unW7vCmCgixtbTRfYkuAexh2dU+pqCOfniOemk+moxdta093dx59ej2loT2wqzuvqzuwqT6wqj2inx95dleZlBWTjFnCuku+tTGxpnDIwW3HwDCxpUy/tF3EuxWVi1mZlE6roR2xoE/Hu4bY0E/EuSq4phKsmxGrnSi1qEzDuIva003Huiu1qUyrnV7CsC66qS/AsmPRxYnd06Lk3Z3i24Xa0mXRxjDCsie3pFnArk/AsDe+rC/CrijCsCO/rS6/rzy/r0+/r2nDsGrCsQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj/AAEIHEiwoMGDCBMqXMiwocOHECNKnPgwgIABBAoYoEjwAIIEChYwaODgAQSOESRMoFDBwgUMGRpo2DCRQwcPH0CEEDGCRAkTJ1CkiKhiBYsWLl4QhBFDxgwaNR7auIEjhw6EO3j08PHwB5AgQhQOIVLEiMMjSJIoUbiESRMnDZ9AiSKF4RQqVawwvIIlixaGW7h08cLwC5gwYhiOIVOG8EIzZ9CkYahmDZs2Dd28gRNHoZw5dOo4tHMHTx6Fevbw6fPQzx9AgRAKGkSoEERDhxAlUrSIIKNGjh5BihRR0iRKlSxdwpRJ0yZOnTx9mggqlKhRpEqZOoUqlapVHAGwF2rl6hWsWLJmhS9Iq9b69/Djy59PH35AACH5BAUBAAAALAAAAAAgACAAhwERDXjWwljPuTvTrDXduUvUyWDa02PTu33d2bTx8db5+u/9/e/+/tP9/bH8/Hvw80jg43HNzsPx8eH4+Mf09bzy87Tz9bP297z7/NX9/uv//+z9/nD382Pa4nXNxMjv8sLv78Dv75Tj4qfi6XzW3X3Y5Ynj7Lfy9vn7/f3+/v3//5br8m3V4Wm+qcrp7qTg5YjX3nDO0X7PzqjV4dno8PH2+PT//nHY4H2vo5bNzpnY1nbL0WnD0Mvg6e309tv7/KPr71+/yGmsmJvPy5XP0m/EyprX4pHm6pvj5WO1vI/CtZbLxFy1rX3ExXfG1FvDzHvEynOttG+ikl+flF+pn0mfoEmjr0yVn014gHyYnmOUizd3chlxcglxfgptfRdZZThgaGyJjm2SkS1kZyRycgR4bgVncSJiaixXXX+dnShcXy58cFCcmBFxdSxtbydUWH6ZmzRhYi10bSeKem27snK6uiB8fSxsbTRfYU53dxdua0+moyOenCOdnU+koxhtbE93dx55dj2ioD2vqjyvqzuwqj6wqj2inh95dliZlBSUjVrBu0u9tzGvp2zGwDSxqUy/tV7EvRiXjlialE6poRitnkrFuobY0UrBti23qhKrnCi0qEjBtorZ0krEuRuuoE+roVm/rzG6qzHBs2TQxoXa0aDi3J/i3ITa0mTRxzDBsie2plm+sE/Brza8rSu/rifBsCO/ri2/rzi+rU/AsGnDsGrDsQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj/AAEIHEiwoMGDCBMqXMiwocOHECNKnPgwgIABBAoYoEjwAIIEChYwaODgAQSOESRMoFDBwgUMGTRs4NBBoocPIEKIGEGihIkTKFKoWMECYgsXL2DEkEFwBo0aKWzceIgjh44dPBD28PEDSBCHQoYQKaLQyBEkSRwqWcKkiUInT6BEaShlCpUqDK1cwZKFoZYtXLow9PIFTBiGYsaQKcPQzBk0hxemUbOGDcM2bt7AaRhHzhw6CuvYuYPHYR49e/go7OPnD6CHgQQNIoSwkKFDiCAmUrSIUSNHBB09ghRJ0qSIlCpZuoQpkyZNmzh18vQJ1MRQokaRKmXqFKpUqlaxG+IIoJWrV7BiyZpFi3zBWrbcy59Pv779+/MDAgAh+QQFAQAAACwAAAAAIAAgAIcBEQ1V0LBLzaw9ybdYz7p61cVo0LeD1Nm36e3c9/fy/P3q+vzV+Pqz9fRz7ONY1s1xy8HB7erW8vPH7fK87e+07e+z7fK98fbH9vnW+/y6+vtQ7+Z32Nx/vsbI7Ozm9far5eKj3+SP1918zNp8zt+E1uSP6O+h9Pi+/P3S/v527O9f2dd2tKu+3+Sk2d2H0tJyzMqO0dR60d1y2+Wk8/fm///z//9u8O2Eq6Shx8mhz9J1v8lvusyy2uXt9Pf7/v7h/fw2199xm5mcxcOGwMFgsrnV5+33+fv5/v+L4uZ2qJd7tad7tbiFwsa41t/k7vDz/f2e7O9rzNRxoY6OsKhvq5xImpac2d2Y7vBg19lRuMFlkIZBe2oYb14Ja3IWoaoiur84s7dNqK9wjpEsW1skYmsEaW4FipQil50riYxcmZ6Bm50pVlkuc24fg3YLe4EsfH8mXmJ4nqA0YWIsdWpFmI58wrxyuLsde30sbG41YWNPd3cYb2tPqaEiopcjnZxPpaQYbWtPeHgdenU9op89sKo8r6o8r6s+r6s9op4fenZZmZYTk4tZwbtMvbcwr6htxsExr6hMvLdawbwVlI1amZVOqaEYq59KxLqG2NFIwLYptKgSq50Sqp0ptKlIwbaH19FKw7oYrJ9avrEotacwwLNkz8aF2tKe4duF2tNj0Mcwv7MntaZbvrFPv7A4vK0tvrAivq8svrA4vK5Pv7FqwrIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/wABCBxIsKDBgwgTKlzIsKHDhxAjSpwIMYCAAQQKUCRo4ACCBAoWMGjg4MFGCBEkTKBQwcIFDBk0bOAgsYOHDyBCiBhBooSJEyhSqFgBkUULFy9gxCAoYwaNGjZuPMSRQ8cOHgcD9PDxA0gQh0KGECmi0MgRJEkcKlnCpIlCJ0+gRJHCcAqVKlYYXsGSRQvDLVy6eGH4BUwYMQzHkCljhuEZNGnUMFzDpo0bhm/gxJHTcA6dOnYU3sGTR4/DPXz6+FH4B1AgQQ8HESpkCOEhRIkUQVzEqJGjR5AIQookaRKlShEtXcKUSdMmTp08fQIVSpSliaNIlTJ1ChWqVKpWsRxqtRGAq1ewYsWSNYtW+YK1ar2fT7++/fv46QcEACH5BAUBAAAALAAAAAAgACAAhwEUD3/Tu1rQqEjCrVG3w2jGyIDUx4XB0IrJ17nl5uz4++n4+er4+tX0+Lbs8Hze3lzWuXnCwb/j6Nbt8sfp7b7o67Tl67Tm773r8sfw9db2+bzz9mDh0IC7vNTr7M7q66TZ25zU3YTL13zH2XzI2oTP35Dc56Hp8Lvz98j4+l/t23mlqbvY3avX2ZXR0XbDxJ7P3IHN2W/P3Ijo76T2+bj6+03g2KnDyZrCynW2w3G3w2HS3Xbt8qD6/Jr8/ErSznWVlaC/v3GrrmKpt2vX4K3198/+/3vn6XqamIKsp3+ut4a+w6rT3eTt8Pn+/sP6+kDc0neek12OfkyQf1CYl9Xk5/r7/OD8/SfX2mKUgneblTF7bghrcLvV2fj6+uj+/jTO1m2RjSxmWCNtZgVmcJfHzNP09J7w8knFy4GcnShVWS5vbwpzbCe4u2Td3T7P0VG9wjVgYixxbTaPh4nFxmLCxR2uryu2tyGoqn/Gyk93dxhvalOsoyemliKnp0+4uBiTkz2Ulh96dj2knj2xqTuvqz2wqz2joB2AfFmYlRWTjFnBu0y9tjGvp2zGwG3GwS+vp0u8tlrCvBSUjVmZlU+qohisoErDu4bX0UjAtim0qRGqnRKrnUnAtobY0UrDuhmsoE2poVq+sSi1qDDAs2PQx4Xa0p7i253h24XZ0mPQxii1p1q+sk+/sDa8rSy+ryK+sCO+ryu+rza9rU+/sWrCsgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj/AAEIHEiwoMGDCBMqXMiwocOHECNKnPgwgIABBAoYoEjwAIIEChYwaODgAQSOESRMoFDBwgUMGTRs4DCxg4cPIEKIGEGihIkTKFKoiLiCRQsXL2AQjCFjBo0aNiDewJFDB8IdPHr4+OEQSBAhQxIGIFLEyBGHSJIoWaKQSRMnT6AwjCJlChWGVaxcwcIwi5YtXBh28fIFDMMwYsaQYVjGzBk0DNOoWcOGYRs3b+A0jCNnDh2FdezcwZOnoZ49fPoo9PMHUKCHggYRKoSwkKFDiCAmUrSIUSNHBB9BiiRpEqWIlSxdwpRJ0yZOmjp5+gQq1ERRo0iVMnUKVSpVpFaxG+IIoJWrV7BiyZpFi3zBWrXcy59Pv779+/MDAgAh+QQFAQAAACwAAAAAIAAgAIcBEg50v8JersNUtLxkyLqB08OKv8+Nx9DM5uzb8PPp9fjp9vnW8PW55u2F0tt0y8uBuMfA3OfW6e/K5uq94Oa13ei03+q85e7G6/LW8va87fJp1M+FtbjP5um63d+kz9mQx9GEvtJ9vdJ8wdWEy9yQ1eOh4eu77fLI8fVo4sl9naq719fF3eSNxcmNwc6Ux9OGyddyyNiI3Oel6vC58fNV16+ctr2YvsV1s7tytLxnytV13OWY7PCT7e1Qzph6lpqnv8Rwpa5jpLlbzddx5+ub9PVP3cd6mJh8pqNgnKOJvMVsz9dY4eV69vdj7utf0r99l5tNeXNbkY1fnKRe1dp69fZe+fk9zMhlkIZeh4EgcmAJbG6ZytDQ9vek/v4909BolYdNfHMtdmwFaW+71dn4+vrn//8i49x/nZsoXlYucm4JbXDG3d76+/vY+/sf39o1YGMsbm0egXh5vruY0NLZ6er2/f6m7O1Z09tPeHcYbmtUraNDsKkwysuT7++H8fJb1NcfeXY9pZ49sqc7sKkxv7w91NJJ3dwk0dJYx8tYmZQVlIxZwbtMvbYxr6htx8FuxsExsqpMx8Ja1NASv7s7u7xPqqIYrJ9KxLqG19FIwLcptKgSq50Sqp0ptaiG2NFJxLoYsqZDt7FavrEntacwv7Rj0MaF2tOd4due4tuF2dIvwLMotadZvrJPv7A4vK0svq8ivq8jvq8tvq84va1Pv7FqwrIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/wABCBxIsKDBgwgTKlzIsKHDhxAjSpwIMYCAAQQKUCRo4ACCBAoWMGjg4MFGCBEkTKBQwcIFDBk0bJjIoYOHDyBCiBhBooSJEyhSRFSxgkULFy8IwoghYwaNGhBt3MCRA6GOHTx6+HD4A0gQIQqHEClixOERJEmUKFzCpImTJwyhRJEyhSGVKlauMMSSRcsWhly6ePnCEEwYMWMYkilj5gxDNGnUrGHIpo2bNw3hxJEzRyGdOnbu4GmYR88ePgr7+PkD6GEgQYMIISxk6BCiRA8VLWLUyNEjgpAiSZpEqVJES5cwZdK0iVMnT5o+gQolauIoUqVMnUKVSpWpVaxabRoE4OoVrFiyZtGqNb6gLVvt48ufT7++ffkBAQAh+QQFAQAAACwAAAAAIAAgAIcBEw6At8tkqMNfqcB5u8uaxdHD3ubX6vDp8vfq8/jW7PO64OmJzNhvzb2Gs8vA2uTY6e7L4ui82uS11uW02Oa83urH5u7W7vO+5u9xzM6GsrrJ4Oe71uCiydaQv8+Et898tMx8t8+DxNKb1N2k3eO75+3J7fN0zsp8oKfE2t231dyMv8iNu8+SwM6e0tx9z9OI1d+k5enB7u9X1KCbtrycwsZ9uL5xsrtpxNJ21tm+7u6j5+Rgw5h6lZmeuL5wpK9jpbdbyMt13tqc6eZU1aSAmp5/pKhZl6CLu8lxzMuO3uKC5eNp4sN2zKJ+lpxNdHVXio1Wlp9Ly8tR4t9s5uVHxI1qi4s3amIha2URbnUKub8W4uI66uo0xp1rk4pVfXwyeHAFaW4Svr018e8p8vAszqx8oJczaF8udmwJbnB53dH6/Pth+/kz08AzY18tbW4dfHtwura33dzd7ur2/v5o9/Vb085PeHcYbWxRqKNBraq46eTi+/nh//5g6+cfeXY9pZ1Dtao6sqaI2djN9vPc/f2p+fgc5tpYmZUVlIxZwrpLvbYwr6hsxsBezckuy8Zu7uu5/PzT//5h5eFOqaEZrJ9KxLqG19FJwLYotKkRq50Sq54pt6tIzMWH5+RQ6eQ27eZF5dxk3NBbvrEntaYwv7Nkz8eE2tKd4dyd4duF2tNj08sv0Mch08w22dWB3dlPwLA2vK0tvq8jvq8ivq8rvrAauKhJxbh51c1qwrIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/wABCBxIsKDBgwgTKlzIsKHDhxAjSpwIMYCAAQQoGixg4ACCBAoWMGig0cEDCBEkTKBQwcIFDBkmatjAoYOHDyBCiBhBooSJExFRpFCxgkULgi5ewIghYwZEGjVs3ECII4eOHTwc9vDxA4jCIEKGEHFYxMgRJAqTKFnCpAlDJ0+gRGEoZQqVKgytXMGShaGWLVy6MPTyBUwYhmLGkCnD0MwZNGkYqlnDpk1DN2/gxFEoZw6dOnYa3sGTR4/CPXz6+Hn4B1AgQQgHESpk6NBDRIkULWLUiKCjR5AiSZoUkVIlS5cwZdK0iVMnT59AhRIlcRSpUqZOoUqlahWrVq5eaRuEFUvWLFq1bN3CpbFgrlzt48ufT7++/fsDAwIAIfkEBQEAAAAsAAAAACAAIACHARANa6LDZqPDmMHSvNbi2Ofv6PH26fL31+jxvNrojsPWg8LNhbPKwdvk2+nwx93ovdbjtdHhtNLhvNvkxuLp1uvxv+Hre8DOia6/yd7ou9bhocjWkLvQhLPMfK/JfLLJicLLqNPdotPduuDpyertd8u9fKCov9bbpMrTjr3Oe7LGlL/Sm8zWdL7KiMvYq+Hh2vHyYcejm7i8rMjRe7O/ebPCa8HMdc/PpOHdltjVcreedpGXm7e8cKWvY6a1XMfHjtranN7cXsGkgJqefKCnWJSii7vJecrLb87PgdnVf9bJesqgfZebUXV4S4GFSY6XSLzATM3NT8zEVriPbImOOGVmKGhtFG15CqSrFsS/Ns+5OMN/b4+PLGBaJG1nBWlvBLKnaOHbTt3WOcKAfp6ZQm5rO3t3Cm5wFc29XOrjMuPYTcCMNGdgLHJsHnp8crm6Y9TQUuXjK+/tEujHb9CmTnl3GG1sT6ajKKObZ93XcvX0GPf3GtbDH3l2PaSfRrWuQrSrpuHfzPXzwP/+VPv6Ntq9WJmUFJONWcK6TL61Ma+nbcbBhtjWrunmyvb12f7+zf//YOrhTqqhGKyfSsS6htjRSMC2KbSpErGkEr2yMNPLfO/s2/z8zv7+xf7/VvbwVeDQWr2xKLWnMMCzZM/GhdrTnePenunlhe3pf/Tyffr4oPr7TevtW+PbT7+wNr2tLL6wI7+yI8m+HtPLJt/bN+TiU+LjasKyYse5ctXNgd/bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACP8AAQgcSLCgwYMIEypcyLChw4cQI0qcGDGAgAAUDQ4gUMDAAQQJFCzIyKCBgwcQIkiYQKGChQsTMWTQsIFDBw8fQIQQMYJEiYgmTqBIoWIFQRYtXLyAEQOijBk0aiC0cQNHDh0Od/Do4UPhDyBBhDgcQqSIEYVHkCRRsoQhkyZOnjCEEkXKFIZUqli5whBLFi1bGHLp4uULQzBhxIxhSKaMmTMM0aRRs6YhmzZu3iiEE0fOHDoN69i5g0dhHj17+Dzs4+cPIISBBA0iVOihoUOIEilaRJBRI0ePIEWKKGkSpUqWLmHKpGkTp06ePoGSGErUKFKlTJ1ClUrVKlatMrocegUrlqxZtGrZyljwFq5cutjLn0+/vv37+AEEBAAh+QQFAQAAACwAAAAAIAAgAIcBEg5socRqn8OTvNG81eTY5vDp8fbq8fbX5u+91uSSvtSFtMnG2+fW5u7H3Oi10eC00d+92OLG3+fW5++/3Od9vcWJrsHJ3ui81uKhxtaQutCEs8x9rsh8s8SiydWZxtKhytq73ePR6+yEx718nqq709ukyNaJucx4r8WUv9KOw8x2s8mIxc694uPE5eRwsauduL6fwMt2r798ssdvuMR4yMWa1dKXzM10tpl3kJect7x1prJjpbd0wcqR0NKh1NRsuqN7lZp6nqZZlKKKu8l5yMhZuryEysp5w7x/yKB9l5tUdHtMfodIjJlIs7tLvLlJtaxhr49riY04YWYcX2YLZ3UKn5s3vrNFw6tLrYpxjZEtWlwpaW4JaHMFqJVu2Mxg0sc+uoCAnJwtXVsyc3IKbnBFxr4r0MIew6tYuIs7aWU0dHMee3tzubtSz8EvzcQr0cwaypx5zKFOeXcYbmtPpKQjn5sVzstP6OIu4NkgzYYeeXY9o58/satFs68s09I97exE8+938u1OzoVYmJQUkotZwrpNvrYxsKdpyMOe3dmm5uJ99PRj+voQ9vMe4atPqqIYrJ9KxLuF19FIysEpy8MgzsZz39mt7evB9fPc/Pyo/v4y/PsX69192MBavrEotagwwbRj2NCF6eWn9fPJ/Pva/v7P/v68//6R/fwu6uV14NVOwLMyxron2dAp5+BP9fST+PdU+fQq5ttr1s9D1tBC3NhL4uJa5ecAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/wABCBxIsKDBgwgTKlzIsKHDhxAjSpwYMYAAigcHEChg4ACCBAowAljAoIGDBA8gRJAwgUKFiRYuYMigYQOHDh4+gAghYkREEiVMnECRgqCKFSxauHgBEUYMGTMQ0qhh4wYOhzl07OChsIePH0AcBhEyhIjCIkaOIEnCUMkSJk0YOnkCJQpDKVOoVGFo5QqWLAy1bOHShaGXL2DCMBQzhkwZhmbOoEnTUM0aNm0UunkDJ46chnPo1LGj8A6ePHoe7uHTxw/CP4ACCRr0kFAhQ4cQJSKoaBGjRo4eRYQUSdIkSpUsXcKUSdMmTp08SfwEKpSoUaRKmTqFKpWqVRhZtRty9QrWpliyZokcSKuWrVu41sufT7++/fvrAwIAIfkEBQEAAAAsAAAAACAAIACHAQoJbKHEap/DlLzUvNXk2Ofv6fH26vH21+bvvdbklLvUhrPLwdjl1uXux9zovNbktNHgs9PevNngxt3nwNzifr26ia3Byd7ou9XiosXYkLrQhLPMfLDHirzJosnVkL7MocfWwd/h4u/ygLu1fpysu9HcpMfXiLfNeK3GlL/SksDPd7DEh8LFrNfVutradqmonLS+mLrIdavCda3EcbW/j8fMoM7OnMXGf66eeJCYnLW9cKCxY6K5crnAdLq5rc/Sca+de5Oaep2nWZKji7vJgsHHWKuxeri5c7CnfpacTnB3S3uHSYuaSairUbGmSamUZayLbImOOF9nGFllCWR1CZuNgMvCbsCzSLF4cY2RLFddJGJrBWRxH6yeIrWbMKmbRbR5gZudKldaLm1xCmtxR7y5LLeuIqScXbSJNF9iLGxvHXl9c7i7XcfAHb6yK8G0HriLTnd3GGxrT6SkI52cGsXCUNzVbN3XR9OXH3l2PaKfPbCqObOvJ83IPd7cPeHcG9bAW8uDWZiUFZOMWcG8S8vFK8bBWc/NT9XSI9zYTOvpWu7sEd7bIt6NT6qiGLGlSdXPhu3qZe3qrO7rnujlnujkq+3qZfPxh/v6Svb2FO3qHeeqUMS6IdDHMObil/z62/7/4f7+2/7+lv/+MPz7F/fzHPG6bNjTLd7aOPDwqv//uP//qf//Mvv8E/nrSOXGaeLiPOPlIubpCvXoKOrfWebbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACP8AAQgcSLCgwYMIEypcyLChw4cQI0qcGDGAAIoHBxAoYOAAggQKMAJYwKCBgwcQIkiY0IBChYkWLmDIoGEDhw4ePoAIIWJERBIlTJxAkYKgihUsWrh4ARFGDBkzENKoYeMGDoc5dOzgobCHjx9AHAYRMoSIwiJGjiBpmETJEiYMmzh5AoVhFClTqDCsYuUKFoZZtGzhwrCLly9gGIYRM4YMwzJmzqBpmEbNGjYK27h5A8dhHDlz6CisY+cOnod59Ozhg7CPnz+AAj0UNIhQIUOHCCJKpGgRo0YRHT2CFEnSJEqVLF3ClEnTpomcOnn6BCpUKFGjSJUyhfEUqlSqVq0YYtXK1SuRAmHFkjWLVi308OPLn0+/PvqAACH5BAUBAAAALAAAAAAgACAAhwEQDmyhxGqfw5S71LzV5Njn8Onx9eny9tfm773W5JO80oayy8DZ5dbl78fc6LXS37TT3b3X4sbc6Nbn7cbf5IS8wYmtwcre6LrV46HF15C60YSzzHyzw6HG14m7yJC70KHK08/k6M/l54ewvn6cq7zR3KTH14e3zHitxpS/0navw4fBwqjP0rrU2Huhp5u0vZi6yHWswXWtxHe0wJnD0JvExanByHiRmZu1vXCgsWSiuWKptHGrsZ+/w3KZmHyUmnqdplmTo4q7yYm8yliepnqvq3amm36WnE5vd0t8h0mLmkmgnIG6s2Sklm+jkWyJjjhfZxlZZAlkdQqIeDqfikWXhVubiHGNkS1XXSNiawVlckymqSSWhyyFfF+YjoGbnShVWS5tcQlscRWelCyiliOOgGqokDRfYixsbh18fm+7vWHEwx6po0O0qEyvnE93dxhubU+wrx+urhy+u0/NyCu4rU68kxyDfz69uz3QzjTJxy3HwD3U0T3QzRS3qmLCikqqpxLAvWPo5n3v7abl4p/d2lHVzSjQyUzf3Frj4RHNyTy8oDDMyjTp5qj8/Nr9/MH19Kzt63Pg3B/Z1Cni3Ujo5Ifx7krq5xXg2S3Trjvg4JH6+bz//9D+/dr+/8j9/af8+4X6+mP28zDu6hro3jHguT7k513x74/9+6j//0/+/in8+yD59R7y5ifnyVzhtELq2zvp3jTk2ibn0krjxnHmvgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj/AAEIHEiwoMGDCBMqXMiwocOHECNKnBgxgACKBwcQKGDgAIIECjACWMCggQMCDyBEkDCBQoWJFi5gyKBhA4cOHj6ACCFiREQSJUycQJGCYAoVK1i0cAHxBYwYMhDOoFHDxsMbOHLoULiDRw8fDn8ACSJE4RAiRYw0PIIkiRKGS5g0ccLwCZQoUhhOoVLFCsMrWLJoYbiFSxcvDL+ACSOG4RgyZcw0PIMmjRqFa9i0cROg4Rs4ceQonEOnjp2Hd/Dk0YNwD58+fv48BBRI0CBChQgaOoQokaJFERk1cvQIUiRJkyhVsnQJU6aJmjZx6uTpE6hQokaRKoXR1ClUqVStGGLVytUrkQJhxZI1i1Yt9PDjy59Pvz76gAAh+QQFAQAAACwAAAAAIAAgAIcBEA1socRqn8OUu9O81eTY5/Do8fbp8fbX5u+91uSSv86KvsaHsszB2eXW5e7H3Oi81uO1096009291uPH3Ofa6e7L4eiCtsOJrsHK3em71OKhxdiQutCEtcqKucuPvc6DtsmQvM+mzdbB3eHJ4OaIr75+nqu80dulxteIt814rceUv9KTvtF2scKSwsyqzta91dqAo6uctL6Zush1rMF1rsR7tcR8tMCewcigur94j5ibtb1wobFko7ljpbdwpa6bubt2lJZ7k5t6nadYkqOKu8mLu8lYm52MtK98oZl+lpxOb3hLe4dJiplJmpKArqlXi356mplsiY44YGcZWWUJZXUkhYIYd2Y4c21njYxxjZEsWF4jZW0FbHkqio0ifXYsbmtjlIp+nJ4nYGMuiIwKi48Kg38wj4I6iHlvpZAqh4ktp6khtbZdxchov74dlZQ2mY1ipZo1pKcZx8Zy5uZn1NQetLJPvLsYl489mHlcwsYt29qm+vnM9PSn4d8uxL4+ycY9wL4ZoJl7s59K1di3/v3Z/f3K9/au6eaE2ddZ0ckqysNM19Na2tcTu7dAt5Zs2d1f6urF/v/O/v7a/fx88/Ew494R19AR0Mkp1s9I3tmH6+hK4d0V0co2x6xj4t8/9++g/f18/v9//PyF+/qd+Ped9/SF8e9k7eov494e3NFC071C598r8Osa+fQf+fYj8/Ej7+sk6+Mj59gx3cNh37Zi585O4sYw5LE93axc37R45rgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/wABCBxIsKDBgwgTKlzIsKHDhxAjSpwYMYAAigcHEChg4ACCBAoWYGTQwMEDCBEkTKBQwcKFiRgyaNjAoYOHDyBCiBhBokREEydQpFCxgiCLFi5ewIgBUcYMGjUQ2riBI8dDHTt49FDo4weQIA6FDCFSRKGRI0iSNFSyhEkThk6eQInCUMoUKlUYWrmCJQtDLVu4dGHo5QuYMAzFjCFThqGZM2jSNFSzhk0bhW7ewInjUM4cOnUU2rmDJ49DPXv49PGD8A+gQIIGPSRUyNAhRIkIKlrEqJGjRxAhRZI0iVIlS5cwZdK0iVMnTxI/gQolahSpUqZOoUqlahVGVq1cvRyCFUvWLFq1MA60dQtXLl271MufT7++/fv4AQQEADs=")}:root{--tab-border:1px solid #888;--tab-border-color:#888;--tab-bg:#fff}menu[role=tablist]{display:flex;list-style-type:none;margin:0 0 -2px;padding-left:3px;position:relative;text-indent:0}menu[role=tablist] button{border-radius:0;color:#222;display:block;min-width:unset;padding:2px 6px;text-decoration:none;z-index:1}menu[role=tablist] button[aria-selected=true]{background:var(--tab-bg);border-bottom:0;box-shadow:none;margin:-2px 0 1px -3px;padding-bottom:4px;position:relative;z-index:8}menu[role=tablist] button[aria-selected=true]:after,menu[role=tablist] button[aria-selected=true]:before{content:none}menu[role=tablist] button[aria-selected=true]:hover{border-color:var(--tab-border-color)}menu[role=tablist] button[aria-selected=true].active,menu[role=tablist] button[aria-selected=true]:active,menu[role=tablist] button[aria-selected=true]:focus{-webkit-animation:none;animation:none;border-color:var(--tab-border-color)}menu[role=tablist] button[aria-selected=true]:focus-visible{outline:1px dotted #222;outline-offset:-4px}menu[role=tablist] button:before{border-radius:0}menu[role=tablist] button:after{content:none}menu[role=tablist] button:disabled{opacity:.6}menu[role=tablist].justified button{flex-grow:1;text-align:center}[role=tabpanel]{background:var(--tab-bg);border:var(--tab-border);clear:both;margin-bottom:9px;padding:14px;position:relative;z-index:2}input[type=email],input[type=number],input[type=password],input[type=text],input[type=url]{height:23px}input[type=email],input[type=number],input[type=password],input[type=text],input[type=url],textarea{background-color:var(--button-highlight);border:1px solid #ccc;border-radius:2px;border-top:1px solid var(--button-border-color);box-sizing:border-box;font:var(--font);padding:3px 4px 5px}input[type=email]:focus,input[type=number]:focus,input[type=password]:focus,input[type=text]:focus,input[type=url]:focus,textarea:focus{border-color:var(--button-shade-light-hovered);border-top-color:var(--button-shade-light-active);outline:none}:root{--treeview-square-size:8px;--treeview-spacing:20px}ul.tree-view{display:block;font:var(--font);margin:0;padding:6px 6px 6px var(--treeview-spacing)}ul.tree-view li{list-style-type:none;margin-top:4px;position:relative}ul.tree-view a{color:#000;text-decoration:none}ul.tree-view ul{margin-top:4px;padding-left:var(--treeview-spacing)}ul.tree-view.has-container{background:#fff;border:1px solid var(--button-border-color)}ul.tree-view.has-collapse-button details>summary::-webkit-details-marker,ul.tree-view.has-collapse-button details>summary::marker{display:none}ul.tree-view.has-collapse-button details>summary:before{background:linear-gradient(to bottom,var(--button-face) 45%,var(--button-shade-light));border:1px solid #919191;border-radius:1px;color:#4b63a7;content:"\002b";font-size:8pt;font-weight:700;height:var(--treeview-square-size);left:calc(var(--treeview-square-size)*2*-1);line-height:calc(var(--treeview-square-size) - 50% + var(--treeview-square-size)/2);margin:0;right:unset;text-align:center;top:calc(50% - var(--treeview-square-size)/2);width:var(--treeview-square-size)}ul.tree-view.has-collapse-button details[open]>summary:before{content:"\2013";transform:none}ul.tree-view.has-connector ul{position:relative}ul.tree-view.has-connector ul:before{border-left:1px dotted #000;content:"";height:calc(100% - var(--treeview-square-size));left:var(--treeview-square-size);position:absolute;top:0}ul.tree-view.has-connector ul li:before{border-bottom:1px dotted #000;content:"";position:absolute;right:calc(100% + var(--treeview-square-size)/4);top:var(--treeview-square-size);width:calc(var(--treeview-spacing)/2)}:root{--link-color:#06c;--link-color-hovered:#39f;--primary-color:#039;--secondary-color:#000}a{color:var(--link-color);text-decoration:none}a:focus-visible{outline:1px dotted var(--link-color)}a:focus,a:hover{color:var(--link-color-hovered);text-decoration:underline}.instruction{color:var(--secondary-color);font:var(--font);font-weight:400;margin:0 0 20px}.instruction-primary{color:var(--primary-color);font-size:12pt}.header{font:var(--font);font-weight:400}.header-document{color:var(--secondary-color);font-family:Calibri,Noto Sans,sans-serif;font-size:17pt}.header-group{color:var(--primary-color);font-size:11pt}:root{--window-spacing:6px;--window-border:1px solid;--window-border-radius:6px;--window-border-color:#000000b3;--window-background-color:#4580c4;--window-background-glass-stripes:linear-gradient(135deg,#fff5 70px,transparent 100px),linear-gradient(225deg,#fff5 70px,transparent 100px),linear-gradient(54deg,#0002 0 4%,#6661 6% 6%,#0002 8% 10%,#0002 15% 16%,#aaa1 17% 18%,#0002 23% 24%,#bbb2 25% 26%,#0002 31% 33%,#0002 34% 34.5%,#bbb2 36% 40%,#0002 41% 41.5%,#bbb2 44% 45%,#bbb2 46% 47%,#0002 48% 49%,#0002 50% 50.5%,#0002 56% 56.5%,#bbb2 57% 63%,#0002 67% 69%,#bbb2 69.5% 70%,#0002 73.5% 74%,#bbb2 74.5% 79%,#0002 80% 84%,#aaa2 85% 86%,#0002 87%,#bbb1 90%) left center/100vw 100vh no-repeat fixed;--window-background:linear-gradient(to right,#ffffff66,#0000001a,#ffffff33),var(--window-background-color);--control-border-color:#0000004d;--control-border-radius:5px;--control-inset-shadow:inset 0 0 0 1px #fffa;--control-background:linear-gradient(#ffffff80,#ffffff4d 45%,#0000001a 50%,#0000001a 75%,#ffffff80);--control-background-hovered:radial-gradient(circle at bottom,#2aceda,transparent 65%),linear-gradient(#b6d9ee 50%,#1a6ca1 0);--control-background-active:radial-gradient(circle at bottom,#0bfdfa,transparent 65%),linear-gradient(#86a7bc 50%,#092747 0);--control-background-close:radial-gradient(circle at -60% 50%,#0007 5% 10%,#0000 50%),radial-gradient(circle at 160% 50%,#0007 5% 10%,#0000 50%),linear-gradient(#e0a197e5,#cf796a 25% 50%,#d54f36 50%);--control-background-close-hovered:radial-gradient(circle at 50% 170%,#f4e676 10% 20%,#0000 60%),radial-gradient(circle at -60% 50%,#000a 5% 10%,#0000 50%),radial-gradient(circle at 160% 50%,#000a 5% 10%,#0000 50%),linear-gradient(#fb9d8b,#ee6d56 25% 50%,#d42809 50%);--control-background-close-active:radial-gradient(circle at 50% 170%,#dcc03f 10% 20%,#0000 60%),radial-gradient(circle at -60% 50%,#000 5% 10%,#0000 50%),radial-gradient(circle at 160% 50%,#000 5% 10%,#0000 50%),linear-gradient(#d1a894,#b67562 25% 50%,#7d0d01 50%)}.window{border:var(--window-border) var(--window-border-color);box-shadow:2px 2px 10px 1px var(--window-border-color),inset 0 0 0 1px #fffa;font:var(--font);position:relative;z-index:0}.window,.window:before{border-radius:var(--window-border-radius)}.window:before{background:linear-gradient(transparent 20%,#ffffffb3 40%,transparent 41%),var(--window-background);background-color:var(--window-background-color);box-shadow:inset 0 0 0 1px #fffd;content:"";height:100%;left:0;position:absolute;top:0;width:100%;z-index:-1}.window-body{background:var(--surface);border:var(--window-border) var(--window-border-color);box-shadow:0 0 0 1px #fff9;margin:var(--window-spacing);margin-top:0}.window-body.has-space{padding:var(--window-spacing)}.window-body pre{margin:calc(var(--window-spacing)*-1)}.window footer,.window-footer{background:var(--surface);border:var(--window-border) var(--window-border-color);border-top:0;box-shadow:0 .5px 1px .5px #fff;margin:var(--window-spacing);margin-top:calc(var(--window-spacing)*-1 - 1px);padding:10px;position:relative}.window footer:before,.window-footer:before{box-shadow:inset 0 1px #0000004d,inset 0 -1px #fff;content:"";height:2px;left:0;position:absolute;top:0;width:100%}.window.is-bright .window-body{background:#fff}.window.is-bright .window-footer,.window.is-bright footer{background:#eee;box-shadow:inset 0 1px 3px #ddd,0 1px 0 #fff9,1px 1px 0 #fff9,-1px 1px 0 #fff9}.window.is-bright .window-footer:before,.window.is-bright footer:before{content:none}.window.glass:before{opacity:.6}.window.glass:after{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border:none;border-radius:var(--window-border-radius);content:"";height:100%;left:0;position:absolute;top:0;width:100%;z-index:-10}.window.glass>.title-bar{background:var(--window-background-glass-stripes)}.window>.title-bar{border:0;box-shadow:inset 0 1px 0 #fffd,inset 1px 0 0 #fffd,inset -1px 0 0 #fffd}.window fieldset{margin-bottom:9px}.window[role=dialog]{left:50%;opacity:0;position:fixed;top:50%;transform:translate(-50%,-50%);transition-duration:.2s;transition-property:visibility,opacity;visibility:hidden;z-index:999}.window[role=dialog]:target{opacity:1;visibility:visible}.title-bar{align-items:center;background:var(--window-background);background-color:var(--window-background-color);border:var(--window-border) var(--window-border-color);border-radius:var(--window-border-radius) var(--window-border-radius) 0 0;box-shadow:inset 0 0 0 1px #fff9;display:flex;font:var(--font);justify-content:space-between;padding:var(--window-spacing);padding-top:0}.title-bar-text{color:#000;letter-spacing:0;line-height:15px;padding-top:var(--window-spacing);text-shadow:0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff,0 0 10px #fff}.title-bar-controls{background:#fff3;border:var(--window-border) var(--control-border-color);border-radius:0 0 var(--control-border-radius) var(--control-border-radius);border-top:0;box-shadow:0 1px 0 #fffa,1px 0 0 #fffa,-1px 0 0 #fffa;display:flex}.title-bar-controls button{background:none;border:0;border-radius:0;border-right:var(--window-border) var(--control-border-color);box-shadow:none;box-sizing:border-box;min-height:19px;min-width:29px;padding:0;position:relative}.title-bar-controls button:after{content:none}.title-bar-controls button:active,.title-bar-controls button:hover{background:none}.title-bar-controls button:disabled:before{opacity:.4}.title-bar-controls button:before{border-radius:0;bottom:0;box-shadow:inset 0 0 0 1px #fff5;content:"";left:0;opacity:1;position:absolute;right:0;top:0}.title-bar-controls button:not(:hover):before{opacity:1;transition:none}.title-bar-controls button.is-minimize:before,.title-bar-controls button[aria-label=Minimize]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAFCAYAAABxeg0vAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAA7SURBVHgBlY+xDQAgDMNaiQ9B8AHcxAlI/NYtKwj6QOohUzxYc+1HAqQ3e03qXNpwwcyE5QsAaEGjDRf8ZAza6Bz6VQAAAABJRU5ErkJggg==") no-repeat center 10px}.title-bar-controls button.is-maximize:before,.title-bar-controls button[aria-label=Maximize]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAYAAACALL/6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAABsSURBVHgBlZHBCYAwDEVT6YaKbqArOILgBLqBosP1VkhAaQ6S1lKad+ihPy8kxLT9+IACG57r2KqKu2GCBpTYtEMOOQELzrnv4z53I4vDjjJnwXsPJWTOAiJGHVNB5pGwLjPk+AlEBLUY7eFebCosBHOR7vYAAAAASUVORK5CYII=") no-repeat 50%}.title-bar-controls button.is-help:before,.title-bar-controls button[aria-label=Help]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAMBAMAAACtsOGuAAAAG1BMVEUAAABTVmb////39/fa2trm5ubj4+Pq6urg4OByvnYHAAAAAXRSTlMAQObYZgAAADtJREFUCNdjYBQUFGAQVFISZBBSUlJkEDYUNmQQFBAvZGBgDA1kYBBLE2RgkGgUYGAQBDIYRBwhBJgLAKBIBQ2X+PZ0AAAAAElFTkSuQmCC") no-repeat 50%}.title-bar-controls button.is-restore:before,.title-bar-controls button[aria-label=Restore]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACVSURBVHgBlVDLCoMwENwU/7ClvRYK7b2lCIJHEQQ/QEHwqujfBXJIQMnihg34iHPJ7GNm2AhYcL2/JwhAxIuhq3aXb48PiFBna2YFERVHzoQLnAQmSCmxeL5+3rBtSsdpBwVKKTcY+1rY197G+8RRoLVejed94igwxrgB/zXeJ+4Jijz2Erjg+8/WE7ZAt6EgSUsIxQwaJEWv7G6SSgAAAABJRU5ErkJggg==") no-repeat 50%}.title-bar-controls button.is-close,.title-bar-controls button[aria-label=Close]{min-width:48px}.title-bar-controls button.is-close:before,.title-bar-controls button[aria-label=Close]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAABi8KSDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACUSURBVHgBlZFNCoQwDIVbmRvOMHOAAd0K/uDGlYKiCG4VPICi9yu0oCSQoFUXFtKEl6+voZXvr7sKay1TL690FOexY+Hz87i2decOuDKQsNGVe8AGYTRJIh0Y+orBvxszCPllOymlxN06jNE26Qnwg4zdHQLrMhFaawwAqAadDPE1ijwUxhiMKCmxCZk06OMYTz5lAx3xWDeXkLNAAAAAAElFTkSuQmCC") no-repeat 50%}.title-bar-controls button:first-child,.title-bar-controls button:first-child:before{border-bottom-left-radius:var(--control-border-radius)}.title-bar-controls button:last-child,.title-bar-controls button:last-child:before{border:0;border-bottom-right-radius:var(--control-border-radius)}.title-bar-controls button:focus{-webkit-animation:none;animation:none;outline:none}.title-bar.active .title-bar-controls,.window.active .title-bar .title-bar-controls{border-color:var(--window-border-color)}.title-bar.active .title-bar-controls button,.window.active .title-bar .title-bar-controls button{border-color:var(--window-border-color);box-shadow:var(--control-inset-shadow)}.title-bar.active .title-bar-controls button:after,.window.active .title-bar .title-bar-controls button:after{content:none}.title-bar.active .title-bar-controls button.is-minimize,.title-bar.active .title-bar-controls button[aria-label=Minimize],.window.active .title-bar .title-bar-controls button.is-minimize,.window.active .title-bar .title-bar-controls button[aria-label=Minimize]{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAFCAYAAABxeg0vAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAA7SURBVHgBlY+xDQAgDMNaiQ9B8AHcxAlI/NYtKwj6QOohUzxYc+1HAqQ3e03qXNpwwcyE5QsAaEGjDRf8ZAza6Bz6VQAAAABJRU5ErkJggg==") no-repeat center 10px,var(--control-background)}.title-bar.active .title-bar-controls button.is-minimize:before,.title-bar.active .title-bar-controls button[aria-label=Minimize]:before,.window.active .title-bar .title-bar-controls button.is-minimize:before,.window.active .title-bar .title-bar-controls button[aria-label=Minimize]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAFCAYAAABxeg0vAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAA7SURBVHgBlY+xDQAgDMNaiQ9B8AHcxAlI/NYtKwj6QOohUzxYc+1HAqQ3e03qXNpwwcyE5QsAaEGjDRf8ZAza6Bz6VQAAAABJRU5ErkJggg==") no-repeat center 10px,var(--control-background-hovered);border-bottom-left-radius:var(--control-border-radius);box-shadow:0 0 7px 3px #5dc4f0,var(--control-inset-shadow);content:"";opacity:0;transition:opacity .3s linear}.title-bar.active .title-bar-controls button.is-minimize:focus-visible:before,.title-bar.active .title-bar-controls button.is-minimize:hover:before,.title-bar.active .title-bar-controls button[aria-label=Minimize]:focus-visible:before,.title-bar.active .title-bar-controls button[aria-label=Minimize]:hover:before,.window.active .title-bar .title-bar-controls button.is-minimize:focus-visible:before,.window.active .title-bar .title-bar-controls button.is-minimize:hover:before,.window.active .title-bar .title-bar-controls button[aria-label=Minimize]:focus-visible:before,.window.active .title-bar .title-bar-controls button[aria-label=Minimize]:hover:before{opacity:1;transition:opacity .1s linear}.title-bar.active .title-bar-controls button.is-minimize:active:before,.title-bar.active .title-bar-controls button[aria-label=Minimize]:active:before,.window.active .title-bar .title-bar-controls button.is-minimize:active:before,.window.active .title-bar .title-bar-controls button[aria-label=Minimize]:active:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAFCAYAAABxeg0vAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAA7SURBVHgBlY+xDQAgDMNaiQ9B8AHcxAlI/NYtKwj6QOohUzxYc+1HAqQ3e03qXNpwwcyE5QsAaEGjDRf8ZAza6Bz6VQAAAABJRU5ErkJggg==") no-repeat center 10px,var(--control-background-active)}.title-bar.active .title-bar-controls button.is-maximize,.title-bar.active .title-bar-controls button[aria-label=Maximize],.window.active .title-bar .title-bar-controls button.is-maximize,.window.active .title-bar .title-bar-controls button[aria-label=Maximize]{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAYAAACALL/6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAABsSURBVHgBlZHBCYAwDEVT6YaKbqArOILgBLqBosP1VkhAaQ6S1lKad+ihPy8kxLT9+IACG57r2KqKu2GCBpTYtEMOOQELzrnv4z53I4vDjjJnwXsPJWTOAiJGHVNB5pGwLjPk+AlEBLUY7eFebCosBHOR7vYAAAAASUVORK5CYII=") no-repeat 50%,var(--control-background)}.title-bar.active .title-bar-controls button.is-maximize:before,.title-bar.active .title-bar-controls button[aria-label=Maximize]:before,.window.active .title-bar .title-bar-controls button.is-maximize:before,.window.active .title-bar .title-bar-controls button[aria-label=Maximize]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAYAAACALL/6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAABsSURBVHgBlZHBCYAwDEVT6YaKbqArOILgBLqBosP1VkhAaQ6S1lKad+ihPy8kxLT9+IACG57r2KqKu2GCBpTYtEMOOQELzrnv4z53I4vDjjJnwXsPJWTOAiJGHVNB5pGwLjPk+AlEBLUY7eFebCosBHOR7vYAAAAASUVORK5CYII=") no-repeat 50%,var(--control-background-hovered);box-shadow:0 0 7px 3px #5dc4f0,var(--control-inset-shadow);content:"";opacity:0;transition:opacity .3s linear}.title-bar.active .title-bar-controls button.is-maximize:focus-visible:before,.title-bar.active .title-bar-controls button.is-maximize:hover:before,.title-bar.active .title-bar-controls button[aria-label=Maximize]:focus-visible:before,.title-bar.active .title-bar-controls button[aria-label=Maximize]:hover:before,.window.active .title-bar .title-bar-controls button.is-maximize:focus-visible:before,.window.active .title-bar .title-bar-controls button.is-maximize:hover:before,.window.active .title-bar .title-bar-controls button[aria-label=Maximize]:focus-visible:before,.window.active .title-bar .title-bar-controls button[aria-label=Maximize]:hover:before{opacity:1;transition:opacity .1s linear}.title-bar.active .title-bar-controls button.is-maximize:active:before,.title-bar.active .title-bar-controls button[aria-label=Maximize]:active:before,.window.active .title-bar .title-bar-controls button.is-maximize:active:before,.window.active .title-bar .title-bar-controls button[aria-label=Maximize]:active:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAYAAACALL/6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAABsSURBVHgBlZHBCYAwDEVT6YaKbqArOILgBLqBosP1VkhAaQ6S1lKad+ihPy8kxLT9+IACG57r2KqKu2GCBpTYtEMOOQELzrnv4z53I4vDjjJnwXsPJWTOAiJGHVNB5pGwLjPk+AlEBLUY7eFebCosBHOR7vYAAAAASUVORK5CYII=") no-repeat 50%,var(--control-background-active)}.title-bar.active .title-bar-controls button.is-help,.title-bar.active .title-bar-controls button[aria-label=Help],.window.active .title-bar .title-bar-controls button.is-help,.window.active .title-bar .title-bar-controls button[aria-label=Help]{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAMBAMAAACtsOGuAAAAG1BMVEUAAABTVmb////39/fa2trm5ubj4+Pq6urg4OByvnYHAAAAAXRSTlMAQObYZgAAADtJREFUCNdjYBQUFGAQVFISZBBSUlJkEDYUNmQQFBAvZGBgDA1kYBBLE2RgkGgUYGAQBDIYRBwhBJgLAKBIBQ2X+PZ0AAAAAElFTkSuQmCC") no-repeat 50%,var(--control-background)}.title-bar.active .title-bar-controls button.is-help:before,.title-bar.active .title-bar-controls button[aria-label=Help]:before,.window.active .title-bar .title-bar-controls button.is-help:before,.window.active .title-bar .title-bar-controls button[aria-label=Help]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAMBAMAAACtsOGuAAAAG1BMVEUAAABTVmb////39/fa2trm5ubj4+Pq6urg4OByvnYHAAAAAXRSTlMAQObYZgAAADtJREFUCNdjYBQUFGAQVFISZBBSUlJkEDYUNmQQFBAvZGBgDA1kYBBLE2RgkGgUYGAQBDIYRBwhBJgLAKBIBQ2X+PZ0AAAAAElFTkSuQmCC") no-repeat 50%,var(--control-background-hovered);box-shadow:0 0 7px 3px #5dc4f0,var(--control-inset-shadow);content:"";opacity:0;transition:opacity .3s linear}.title-bar.active .title-bar-controls button.is-help:focus-visible:before,.title-bar.active .title-bar-controls button.is-help:hover:before,.title-bar.active .title-bar-controls button[aria-label=Help]:focus-visible:before,.title-bar.active .title-bar-controls button[aria-label=Help]:hover:before,.window.active .title-bar .title-bar-controls button.is-help:focus-visible:before,.window.active .title-bar .title-bar-controls button.is-help:hover:before,.window.active .title-bar .title-bar-controls button[aria-label=Help]:focus-visible:before,.window.active .title-bar .title-bar-controls button[aria-label=Help]:hover:before{opacity:1;transition:opacity .1s linear}.title-bar.active .title-bar-controls button.is-help:active:before,.title-bar.active .title-bar-controls button[aria-label=Help]:active:before,.window.active .title-bar .title-bar-controls button.is-help:active:before,.window.active .title-bar .title-bar-controls button[aria-label=Help]:active:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAMBAMAAACtsOGuAAAAG1BMVEUAAABTVmb////39/fa2trm5ubj4+Pq6urg4OByvnYHAAAAAXRSTlMAQObYZgAAADtJREFUCNdjYBQUFGAQVFISZBBSUlJkEDYUNmQQFBAvZGBgDA1kYBBLE2RgkGgUYGAQBDIYRBwhBJgLAKBIBQ2X+PZ0AAAAAElFTkSuQmCC") no-repeat 50%,var(--control-background-active)}.title-bar.active .title-bar-controls button.is-restore,.title-bar.active .title-bar-controls button[aria-label=Restore],.window.active .title-bar .title-bar-controls button.is-restore,.window.active .title-bar .title-bar-controls button[aria-label=Restore]{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACVSURBVHgBlVDLCoMwENwU/7ClvRYK7b2lCIJHEQQ/QEHwqujfBXJIQMnihg34iHPJ7GNm2AhYcL2/JwhAxIuhq3aXb48PiFBna2YFERVHzoQLnAQmSCmxeL5+3rBtSsdpBwVKKTcY+1rY197G+8RRoLVejed94igwxrgB/zXeJ+4Jijz2Erjg+8/WE7ZAt6EgSUsIxQwaJEWv7G6SSgAAAABJRU5ErkJggg==") no-repeat 50%,var(--control-background)}.title-bar.active .title-bar-controls button.is-restore:before,.title-bar.active .title-bar-controls button[aria-label=Restore]:before,.window.active .title-bar .title-bar-controls button.is-restore:before,.window.active .title-bar .title-bar-controls button[aria-label=Restore]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACVSURBVHgBlVDLCoMwENwU/7ClvRYK7b2lCIJHEQQ/QEHwqujfBXJIQMnihg34iHPJ7GNm2AhYcL2/JwhAxIuhq3aXb48PiFBna2YFERVHzoQLnAQmSCmxeL5+3rBtSsdpBwVKKTcY+1rY197G+8RRoLVejed94igwxrgB/zXeJ+4Jijz2Erjg+8/WE7ZAt6EgSUsIxQwaJEWv7G6SSgAAAABJRU5ErkJggg==") no-repeat 50%,var(--control-background-hovered);box-shadow:0 0 7px 3px #5dc4f0,var(--control-inset-shadow);content:"";opacity:0;transition:opacity .3s linear}.title-bar.active .title-bar-controls button.is-restore:focus-visible:before,.title-bar.active .title-bar-controls button.is-restore:hover:before,.title-bar.active .title-bar-controls button[aria-label=Restore]:focus-visible:before,.title-bar.active .title-bar-controls button[aria-label=Restore]:hover:before,.window.active .title-bar .title-bar-controls button.is-restore:focus-visible:before,.window.active .title-bar .title-bar-controls button.is-restore:hover:before,.window.active .title-bar .title-bar-controls button[aria-label=Restore]:focus-visible:before,.window.active .title-bar .title-bar-controls button[aria-label=Restore]:hover:before{opacity:1;transition:opacity .1s linear}.title-bar.active .title-bar-controls button.is-restore:active:before,.title-bar.active .title-bar-controls button[aria-label=Restore]:active:before,.window.active .title-bar .title-bar-controls button.is-restore:active:before,.window.active .title-bar .title-bar-controls button[aria-label=Restore]:active:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACVSURBVHgBlVDLCoMwENwU/7ClvRYK7b2lCIJHEQQ/QEHwqujfBXJIQMnihg34iHPJ7GNm2AhYcL2/JwhAxIuhq3aXb48PiFBna2YFERVHzoQLnAQmSCmxeL5+3rBtSsdpBwVKKTcY+1rY197G+8RRoLVejed94igwxrgB/zXeJ+4Jijz2Erjg+8/WE7ZAt6EgSUsIxQwaJEWv7G6SSgAAAABJRU5ErkJggg==") no-repeat 50%,var(--control-background-active)}.title-bar.active .title-bar-controls button.is-close,.title-bar.active .title-bar-controls button[aria-label=Close],.window.active .title-bar .title-bar-controls button.is-close,.window.active .title-bar .title-bar-controls button[aria-label=Close]{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAABi8KSDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACUSURBVHgBlZFNCoQwDIVbmRvOMHOAAd0K/uDGlYKiCG4VPICi9yu0oCSQoFUXFtKEl6+voZXvr7sKay1TL690FOexY+Hz87i2decOuDKQsNGVe8AGYTRJIh0Y+orBvxszCPllOymlxN06jNE26Qnwg4zdHQLrMhFaawwAqAadDPE1ijwUxhiMKCmxCZk06OMYTz5lAx3xWDeXkLNAAAAAAElFTkSuQmCC") no-repeat 50%,var(--control-background),var(--control-background-close);box-shadow:var(--control-inset-shadow)}.title-bar.active .title-bar-controls button.is-close:before,.title-bar.active .title-bar-controls button[aria-label=Close]:before,.window.active .title-bar .title-bar-controls button.is-close:before,.window.active .title-bar .title-bar-controls button[aria-label=Close]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAABi8KSDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACUSURBVHgBlZFNCoQwDIVbmRvOMHOAAd0K/uDGlYKiCG4VPICi9yu0oCSQoFUXFtKEl6+voZXvr7sKay1TL690FOexY+Hz87i2decOuDKQsNGVe8AGYTRJIh0Y+orBvxszCPllOymlxN06jNE26Qnwg4zdHQLrMhFaawwAqAadDPE1ijwUxhiMKCmxCZk06OMYTz5lAx3xWDeXkLNAAAAAAElFTkSuQmCC") no-repeat 50%,var(--control-background),var(--control-background-close-hovered);border-bottom-right-radius:var(--control-border-radius);box-shadow:0 0 7px 3px #e68e75,var(--control-inset-shadow);content:"";opacity:0;transition:opacity .3s linear}.title-bar.active .title-bar-controls button.is-close:focus-visible:before,.title-bar.active .title-bar-controls button.is-close:hover:before,.title-bar.active .title-bar-controls button[aria-label=Close]:focus-visible:before,.title-bar.active .title-bar-controls button[aria-label=Close]:hover:before,.window.active .title-bar .title-bar-controls button.is-close:focus-visible:before,.window.active .title-bar .title-bar-controls button.is-close:hover:before,.window.active .title-bar .title-bar-controls button[aria-label=Close]:focus-visible:before,.window.active .title-bar .title-bar-controls button[aria-label=Close]:hover:before{opacity:1;transition:opacity .1s linear}.title-bar.active .title-bar-controls button.is-close:active:before,.title-bar.active .title-bar-controls button[aria-label=Close]:active:before,.window.active .title-bar .title-bar-controls button.is-close:active:before,.window.active .title-bar .title-bar-controls button[aria-label=Close]:active:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAABi8KSDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACUSURBVHgBlZFNCoQwDIVbmRvOMHOAAd0K/uDGlYKiCG4VPICi9yu0oCSQoFUXFtKEl6+voZXvr7sKay1TL690FOexY+Hz87i2decOuDKQsNGVe8AGYTRJIh0Y+orBvxszCPllOymlxN06jNE26Qnwg4zdHQLrMhFaawwAqAadDPE1ijwUxhiMKCmxCZk06OMYTz5lAx3xWDeXkLNAAAAAAElFTkSuQmCC") no-repeat 50%,var(--control-background),var(--control-background-close-active)}.title-bar.active .title-bar-controls button:disabled.is-maximize,.title-bar.active .title-bar-controls button:disabled[aria-label=Maximize],.window.active .title-bar .title-bar-controls button:disabled.is-maximize,.window.active .title-bar .title-bar-controls button:disabled[aria-label=Maximize]{background:var(--control-background)}.title-bar.active .title-bar-controls button:disabled.is-maximize:before,.title-bar.active .title-bar-controls button:disabled[aria-label=Maximize]:before,.window.active .title-bar .title-bar-controls button:disabled.is-maximize:before,.window.active .title-bar .title-bar-controls button:disabled[aria-label=Maximize]:before{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAYAAACALL/6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAABsSURBVHgBlZHBCYAwDEVT6YaKbqArOILgBLqBosP1VkhAaQ6S1lKad+ihPy8kxLT9+IACG57r2KqKu2GCBpTYtEMOOQELzrnv4z53I4vDjjJnwXsPJWTOAiJGHVNB5pGwLjPk+AlEBLUY7eFebCosBHOR7vYAAAAASUVORK5CYII=") no-repeat 50%;content:"";opacity:.4}.status-bar{background:var(--surface);border:var(--window-border) var(--window-border-color);border-top:0;box-shadow:0 1px 0 #fff9,1px 0 0 #fff9,-1px 0 0 #fff9;display:flex;margin:var(--window-spacing);margin-top:calc(var(--window-spacing)*-1)}.status-bar-field{border-right:var(--window-border) #cfcfcf;flex-grow:1;margin:0;padding:2px 3px}.status-bar-field:last-child{border-right:0} +/*# sourceMappingURL=7.css.map */ \ No newline at end of file diff --git a/app/thirdparty/jstree/32px.png b/app/thirdparty/jstree/32px.png new file mode 100644 index 0000000000000000000000000000000000000000..a1c565e9c6505dc6a7902adfaa32b5296a247aaf GIT binary patch literal 2988 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 bQ6H~ez@PFK18bMK-wyz7Vrg7th!6W0g2h5i literal 0 HcmV?d00001 diff --git a/app/thirdparty/jstree/jquery.min.js b/app/thirdparty/jstree/jquery.min.js new file mode 100644 index 0000000..a5195a3 --- /dev/null +++ b/app/thirdparty/jstree/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.12.1 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.1",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; +}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML="
a",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:l.htmlSerialize?[0,"",""]:[1,"X
","
"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.rnamespace||a.rnamespace.test(g.namespace))&&(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("