@xenon-device-management/xenon 2.11.1 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/lib/package.json +1 -1
  2. package/lib/public/assets/{AnnotationOverlay-Dt5AmXCR.js → AnnotationOverlay-Crkn72_3.js} +1 -1
  3. package/lib/public/assets/{ApiKeyGate-CS05jXd7.js → ApiKeyGate-BThVlj_j.js} +1 -1
  4. package/lib/public/assets/{BugReportButton-ejWk5lof.js → BugReportButton-Dwa0GnBh.js} +1 -1
  5. package/lib/public/assets/DeviceMosaicView-Ccc-pOls.js +2 -0
  6. package/lib/public/assets/{EmptyState-DyojFa86.js → EmptyState-BeuTrlN_.js} +1 -1
  7. package/lib/public/assets/{FieldGroup-Dm-U3Ucr.js → FieldGroup-DBIaNxl1.js} +1 -1
  8. package/lib/public/assets/{FilterMenu-B3hgDfy_.js → FilterMenu-BgSAS6iT.js} +1 -1
  9. package/lib/public/assets/{Menu-DFNsTx2i.js → Menu-GCbP6gYN.js} +1 -1
  10. package/lib/public/assets/{Modal-BdWYrwfK.js → Modal-ByESeBRC.js} +1 -1
  11. package/lib/public/assets/RecordingPage-Bwyf3WMl.js +1 -0
  12. package/lib/public/assets/{RecordingsPage-FAUS-RwG.js → RecordingsPage-7kM1rB3i.js} +2 -2
  13. package/lib/public/assets/{SegmentedControl-EBzIUjnM.js → SegmentedControl-B8tTU8kD.js} +1 -1
  14. package/lib/public/assets/{SettingCard-BQ8wMHrz.js → SettingCard-Clg_Ijbc.js} +1 -1
  15. package/lib/public/assets/{Table-DDahAwGb.js → Table-CIaR0QWV.js} +1 -1
  16. package/lib/public/assets/{activity-CFEfukVD.js → activity-Bengh9SD.js} +1 -1
  17. package/lib/public/assets/{ai-settings-iPPNZMnS.js → ai-settings-G9SymiPH.js} +2 -2
  18. package/lib/public/assets/{api-keys-DS979X_e.js → api-keys-CrGlbfn-.js} +1 -1
  19. package/lib/public/assets/{apps-DQnxhScG.js → apps-DIbcGVlU.js} +3 -3
  20. package/lib/public/assets/{arrow-left-CIqcStpJ.js → arrow-left-BtJIXXMY.js} +1 -1
  21. package/lib/public/assets/{arrow-right-Pw0XgjBJ.js → arrow-right-zm-NagQh.js} +1 -1
  22. package/lib/public/assets/{arrow-up-right-DWaEiSQf.js → arrow-up-right-DdU8YEYp.js} +1 -1
  23. package/lib/public/assets/{auth-shell-DvJ8qKdR.js → auth-shell-CHmBFmOz.js} +2 -2
  24. package/lib/public/assets/{builds-page-BIWuhGph.js → builds-page-JkzWKRpU.js} +1 -1
  25. package/lib/public/assets/{button-B1XDl_TT.js → button-CqhPBGRj.js} +1 -1
  26. package/lib/public/assets/{calendar-BPrY2NZL.js → calendar-C7eYYJTo.js} +1 -1
  27. package/lib/public/assets/{check-DjbzNVbd.js → check-DpbIM4E0.js} +1 -1
  28. package/lib/public/assets/{chevron-right-J_WfelGu.js → chevron-right-Dl4X1PRz.js} +1 -1
  29. package/lib/public/assets/{circle-check-CGwn46BE.js → circle-check-Du3sjbfV.js} +1 -1
  30. package/lib/public/assets/{circle-x-Rfn2Zmq3.js → circle-x-BSSqhpXi.js} +1 -1
  31. package/lib/public/assets/{clock-BAD4KA9j.js → clock-DMT60v1C.js} +1 -1
  32. package/lib/public/assets/{copy-CcNlsrXH.js → copy-BKNyOehd.js} +1 -1
  33. package/lib/public/assets/device-explorer-CHv1miyr.css +1 -0
  34. package/lib/public/assets/device-explorer-CoPR8DW3.js +279 -0
  35. package/lib/public/assets/{download-CoBA2mT_.js → download-BM6Xn22t.js} +1 -1
  36. package/lib/public/assets/{forgot-password-BrV3pKRK.js → forgot-password-B8WqMqBT.js} +1 -1
  37. package/lib/public/assets/{index-DQa193-A.css → index-BTYMAqNW.css} +1 -1
  38. package/lib/public/assets/index-ClrpAMAT.js +219 -0
  39. package/lib/public/assets/{index-BHI_dBXi.js → index-DauQh6ie.js} +1 -1
  40. package/lib/public/assets/{input-Bo2b9153.js → input-CyKdLnEx.js} +1 -1
  41. package/lib/public/assets/{line-chart-X7ZCpjWB.js → line-chart-EIBXwYGo.js} +1 -1
  42. package/lib/public/assets/{list-checks-Cqso6ROH.js → list-checks-fWsgD9bI.js} +1 -1
  43. package/lib/public/assets/{lock-D9WyaPyU.js → lock-CVCe56TH.js} +1 -1
  44. package/lib/public/assets/{login-DqIYeZ2q.js → login-BJ8a7yVD.js} +1 -1
  45. package/lib/public/assets/{maintenance-settings-C7pWE0--.js → maintenance-settings-DcRmTLS6.js} +1 -1
  46. package/lib/public/assets/{monitor-ZC2MoScA.js → monitor-Bw1YQZnL.js} +1 -1
  47. package/lib/public/assets/{mouse-pointer-2-DXh-LIn9.js → mouse-pointer-2-C01jbqkO.js} +1 -1
  48. package/lib/public/assets/{network-CivILLOW.js → network-CBGUjJDJ.js} +1 -1
  49. package/lib/public/assets/{overview-ClDfJNL5.js → overview-Cxe8aQ7C.js} +1 -1
  50. package/lib/public/assets/{page-header-CV-WOQ7B.js → page-header-B92DKLiq.js} +1 -1
  51. package/lib/public/assets/play-Ck0L-0_m.js +11 -0
  52. package/lib/public/assets/{plus-DOp8RUCs.js → plus-Dq3tCy2N.js} +1 -1
  53. package/lib/public/assets/{profile-page-Ckx1bcSx.js → profile-page--dkDiKbr.js} +2 -2
  54. package/lib/public/assets/recording-group-store-5BYIFFN9.js +26 -0
  55. package/lib/public/assets/{reset-password-CZDSfFZ6.js → reset-password-KYWlfjia.js} +1 -1
  56. package/lib/public/assets/{runbook-page-BXe7SL5K.js → runbook-page-mnsxgS1d.js} +1 -1
  57. package/lib/public/assets/{select-Bo_2fqDM.js → select-BBOIZTYm.js} +1 -1
  58. package/lib/public/assets/{selector-detail-redirect-D_aNBNim.js → selector-detail-redirect-CcI2j_Su.js} +1 -1
  59. package/lib/public/assets/{selector-health-page-BP4XhSI4.js → selector-health-page-BdJb_x5L.js} +2 -2
  60. package/lib/public/assets/{session-detail-page-DN8MPDsL.js → session-detail-page-BjLaJy8z.js} +1 -1
  61. package/lib/public/assets/{settings-rFQ6qW9Q.js → settings-B6cpMhsx.js} +1 -1
  62. package/lib/public/assets/{stat-tile-D8taj4dL.js → stat-tile-BU9e4s36.js} +1 -1
  63. package/lib/public/assets/{tablet-Cz9pTLGh.js → tablet-hgbEwrWq.js} +1 -1
  64. package/lib/public/assets/{teams-DkFhPU6N.js → teams-uiiG4hZM.js} +1 -1
  65. package/lib/public/assets/{trash-2-DMkIlO0b.js → trash-2-NK_Iazmg.js} +1 -1
  66. package/lib/public/assets/{upload-Dg76vQUo.js → upload-BUX8TNFi.js} +1 -1
  67. package/lib/public/assets/{use-builds-data-iSxxYh9G.js → use-builds-data-DZszmFyl.js} +1 -1
  68. package/lib/public/assets/{use-password-reset-mode-DsNcDXiv.js → use-password-reset-mode-BK4B9kRC.js} +1 -1
  69. package/lib/public/assets/{users-Bu1HulwN.js → users-BDh1xjad.js} +1 -1
  70. package/lib/public/assets/{users-BShiNYd9.js → users-BU4XBbMT.js} +1 -1
  71. package/lib/public/assets/{video-off-BJ_s_mLK.js → video-off-BOjNwT4R.js} +1 -1
  72. package/lib/public/assets/webhook-settings-BMzyUcx5.js +1 -0
  73. package/lib/public/assets/{zap-BXZlQKN8.js → zap-DTWwVMUg.js} +1 -1
  74. package/lib/public/index.html +2 -2
  75. package/lib/src/device-managers/iOSTracker.js +14 -1
  76. package/lib/src/device-managers/ios/IOSDiscoveryService.js +9 -5
  77. package/lib/src/device-managers/ios/usbmuxd.js +46 -0
  78. package/lib/test/unit/ios-usbmuxd-missing.spec.js +111 -0
  79. package/lib/tsconfig.tsbuildinfo +1 -1
  80. package/package.json +1 -1
  81. package/lib/public/assets/DeviceMosaicView-C9AypMcW.js +0 -2
  82. package/lib/public/assets/RecordingPage-FIRd8b5d.js +0 -11
  83. package/lib/public/assets/device-explorer-D2AqrrLN.css +0 -1
  84. package/lib/public/assets/device-explorer-Dl1QGKQN.js +0 -268
  85. package/lib/public/assets/index-DklX18ye.js +0 -219
  86. package/lib/public/assets/keycodes-B5mWBGMd.js +0 -26
  87. package/lib/public/assets/webhook-settings-CJxMc7-Q.js +0 -1
@@ -1 +1 @@
1
- {"root":["../src/InternalHttpClient.ts","../src/PluginContext.ts","../src/XenonCapabilityManager.ts","../src/chromeUtils.ts","../src/config.ts","../src/device-utils.ts","../src/index.ts","../src/logger.ts","../src/plugin.ts","../src/prisma.ts","../src/app/appiumBasePath.ts","../src/app/index.ts","../src/app/insertBeforeRoutes.ts","../src/app/registerCommandAuth.ts","../src/app/swagger-docs.ts","../src/app/swagger.ts","../src/app/routers/androidH264Config.ts","../src/app/routers/apikeys.ts","../src/app/routers/apps.ts","../src/app/routers/audit.ts","../src/app/routers/auth.ts","../src/app/routers/bug-report.ts","../src/app/routers/build-export.ts","../src/app/routers/capabilities.ts","../src/app/routers/config.ts","../src/app/routers/control.ts","../src/app/routers/dashboard.ts","../src/app/routers/grid.ts","../src/app/routers/interceptor.ts","../src/app/routers/iosStreamPort.ts","../src/app/routers/nodePhoneControl.ts","../src/app/routers/ports.ts","../src/app/routers/processes.ts","../src/app/routers/profile.ts","../src/app/routers/profileIdentity.ts","../src/app/routers/projects.ts","../src/app/routers/recordingRequests.ts","../src/app/routers/recordings.ts","../src/app/routers/reservation.ts","../src/app/routers/sdk-leases.ts","../src/app/routers/sdk-version.ts","../src/app/routers/selector-health.ts","../src/app/routers/sessionInsights.ts","../src/app/routers/streamLeave.ts","../src/app/routers/streamStartConflict.ts","../src/app/routers/streamType.ts","../src/app/routers/teams.ts","../src/app/routers/users.ts","../src/app/routers/webhook.ts","../src/app/ws/h264StreamWs.ts","../src/app/ws/logcatWs.ts","../src/app/ws/nodeSocketRelay.ts","../src/app/ws/upgradeRouter.ts","../src/commands/handle.ts","../src/commands/index.ts","../src/dashboard/asset-manager.ts","../src/dashboard/commands.ts","../src/dashboard/event-manager.ts","../src/dashboard/services/app-service.ts","../src/dashboard/services/failure-analysis-service.ts","../src/dashboard/services/session-service.ts","../src/data-service/CircuitBreaker.ts","../src/data-service/config-service.ts","../src/data-service/db.ts","../src/data-service/device-service.ts","../src/data-service/device-store.interface.ts","../src/data-service/device-store.ts","../src/data-service/deviceClaims.ts","../src/data-service/deviceColumns.ts","../src/data-service/deviceFieldOwners.ts","../src/data-service/pending-sessions-service.ts","../src/data-service/pluginArgs.ts","../src/data-service/prisma-service.ts","../src/data-service/prisma-store.ts","../src/data-service/queue-service.ts","../src/data-service/web-config-service.ts","../src/device-managers/AndroidDeviceManager.ts","../src/device-managers/ChromeDriverManager.ts","../src/device-managers/HealthMonitorService.ts","../src/device-managers/IOSDeviceManager.ts","../src/device-managers/NodeDevices.ts","../src/device-managers/clipboardErrors.ts","../src/device-managers/deviceIdentity.ts","../src/device-managers/iOSTracker.ts","../src/device-managers/index.ts","../src/device-managers/localDeviceHosts.ts","../src/device-managers/ownDeviceRow.ts","../src/device-managers/android/AndroidH264StreamService.ts","../src/device-managers/android/AndroidStreamService.ts","../src/device-managers/android/DeviceLockManager.ts","../src/device-managers/android/H264Multiplexer.ts","../src/device-managers/android/LogcatMultiplexer.ts","../src/device-managers/android/LogcatStreamService.ts","../src/device-managers/android/ScrcpyServerSession.ts","../src/device-managers/android/androidIdentity.ts","../src/device-managers/android/androidStreamReuse.ts","../src/device-managers/android/clipboardBroadcast.ts","../src/device-managers/android/displayState.ts","../src/device-managers/android/h264NalParser.ts","../src/device-managers/android/previewHold.ts","../src/device-managers/android/scrcpyVersion.ts","../src/device-managers/cloud/CapabilityManager.ts","../src/device-managers/cloud/Devices.ts","../src/device-managers/ios/IOSDiscoveryService.ts","../src/device-managers/ios/IOSLogStreamService.ts","../src/device-managers/ios/IOSStreamService.ts","../src/device-managers/ios/IOSTunnels.ts","../src/device-managers/ios/WDAClient.ts","../src/device-managers/ios/appleIdentity.ts","../src/device-managers/ios/goIosBinary.ts","../src/device-managers/ios/iosAppIds.ts","../src/device-managers/ios/iosBattery.ts","../src/device-managers/ios/iosStreamDiagnostics.ts","../src/device-managers/ios/tunnelProcess.ts","../src/enums/Capabilities.ts","../src/enums/Cloud.ts","../src/enums/Platform.ts","../src/enums/SessionType.ts","../src/enums/SocketEvents.ts","../src/gateway/createHandoff.ts","../src/gateway/defaultGateway.ts","../src/gateway/forwardToNode.ts","../src/gateway/hubSessionToken.ts","../src/gateway/internalCall.ts","../src/gateway/nodeSessionMetrics.ts","../src/gateway/nodeSessionStatus.ts","../src/gateway/nodeWebDriverUrl.ts","../src/gateway/sessionCreate.ts","../src/gateway/sessionGateway.ts","../src/gateway/sessionLocator.ts","../src/generated/client/default.d.ts","../src/generated/client/default.js","../src/generated/client/edge.d.ts","../src/generated/client/edge.js","../src/generated/client/index-browser.js","../src/generated/client/index.d.ts","../src/generated/client/index.js","../src/generated/client/wasm.d.ts","../src/generated/client/wasm.js","../src/generated/client/runtime/edge-esm.js","../src/generated/client/runtime/edge.js","../src/generated/client/runtime/index-browser.d.ts","../src/generated/client/runtime/index-browser.js","../src/generated/client/runtime/library.d.ts","../src/generated/client/runtime/library.js","../src/generated/client/runtime/react-native.js","../src/generated/client/runtime/wasm.js","../src/helpers/UniversalMjpegProxy.ts","../src/helpers/ffmpegPath.ts","../src/helpers/index.ts","../src/helpers/networkAddresses.ts","../src/helpers/singleFlight.ts","../src/interceptors/CommandInterceptor.ts","../src/interfaces/ICloudManager.ts","../src/interfaces/IDevice.ts","../src/interfaces/IDeviceFilterOptions.ts","../src/interfaces/IDeviceManager.ts","../src/interfaces/IOptions.ts","../src/interfaces/IPluginArgs.ts","../src/interfaces/ISessionCapability.ts","../src/logging/sessionContext.ts","../src/middleware/authMiddleware.ts","../src/middleware/commandAuth.ts","../src/middleware/commandCaller.ts","../src/middleware/controlDevice.ts","../src/middleware/csrfMiddleware.ts","../src/middleware/deviceAccessGuard.ts","../src/middleware/deviceTeamGuard.ts","../src/middleware/leaseTokenMiddleware.ts","../src/middleware/loginRateLimiter.ts","../src/middleware/rateLimitMiddleware.ts","../src/middleware/roleGuard.ts","../src/middleware/scopeGuard.ts","../src/middleware/sessionListingFilter.ts","../src/middleware/sessionUpgradeGuard.ts","../src/middleware/verifyCredential.ts","../src/scripts/generate-database-migration.ts","../src/scripts/goIosVersion.ts","../src/scripts/initialize-database.ts","../src/scripts/install-go-ios.ts","../src/scripts/prepare-prisma.ts","../src/scripts/run-migrations.ts","../src/services/AICommandService.ts","../src/services/AIService.ts","../src/services/ApiKeyService.ts","../src/services/CircuitBreaker.ts","../src/services/CleanupService.ts","../src/services/DeviceReconciler.ts","../src/services/DisplayStateService.ts","../src/services/EmailService.ts","../src/services/EventBus.ts","../src/services/EventLogService.ts","../src/services/InspectorService.ts","../src/services/InterceptorService.ts","../src/services/MetricsService.ts","../src/services/NetworkConditioningService.ts","../src/services/NotificationService.ts","../src/services/OrphanSweeper.ts","../src/services/PasswordResetService.ts","../src/services/PortAllocator.ts","../src/services/ProcessMetricsService.ts","../src/services/ProcessRegistry.ts","../src/services/RequestLogService.ts","../src/services/ResourceIsolationService.ts","../src/services/SecurityService.ts","../src/services/SelectorStateService.ts","../src/services/SelectorVerificationJob.ts","../src/services/ServerManager.ts","../src/services/SessionHeartbeatService.ts","../src/services/SessionLifecycleService.ts","../src/services/ShutdownCoordinator.ts","../src/services/SocketClient.ts","../src/services/SocketServer.ts","../src/services/TeamService.ts","../src/services/TracingService.ts","../src/services/UserService.ts","../src/services/UserSessionService.ts","../src/services/VideoPipelineService.ts","../src/services/fillMissingScreenSize.ts","../src/services/passwordResetLink.ts","../src/services/passwordResetMode.ts","../src/services/sessionTokenGate.ts","../src/services/artifacts/ArtifactStore.ts","../src/services/autowait/AutowaitService.ts","../src/services/autowait/waitFor.ts","../src/services/bug-report/BugReportService.ts","../src/services/bug-report/archive.ts","../src/services/bug-report/har-collector.ts","../src/services/bug-report/manifest.ts","../src/services/bug-report/readme.ts","../src/services/bug-report/types.ts","../src/services/bug-report/video-slice.ts","../src/services/bug-report/window.ts","../src/services/device-access/DeviceTeamResolver.ts","../src/services/device-access/LiveSessionOwners.ts","../src/services/device-access/SessionOwnerResolver.ts","../src/services/device-access/actor.ts","../src/services/device-access/appVisibility.ts","../src/services/device-access/callerTeamIds.ts","../src/services/device-access/deviceAccessPolicy.ts","../src/services/device-access/deviceVisibility.ts","../src/services/device-access/leaseOverride.ts","../src/services/device-access/queueVisibility.ts","../src/services/device-access/sessionVisibility.ts","../src/services/device-access/ticketActorAccess.ts","../src/services/healing/FuzzyXmlHealingProvider.ts","../src/services/healing/HealEtalonService.ts","../src/services/healing/HealedLocatorGenerator.ts","../src/services/healing/HealingMetrics.ts","../src/services/healing/HealingOrchestrator.ts","../src/services/healing/LlmHealingProvider.ts","../src/services/healing/OcrHealingProvider.ts","../src/services/healing/ResilioTreeHealingProvider.ts","../src/services/healing/VisualAiHealingProvider.ts","../src/services/healing/types.ts","../src/services/identity/bootstrap.ts","../src/services/identity/sessionCleanupCron.ts","../src/services/identity/userAuthorization.ts","../src/services/inspector/verifyLocator.ts","../src/services/interceptor/AndroidProxyAdapter.ts","../src/services/interceptor/CertManager.ts","../src/services/interceptor/HarBuilder.ts","../src/services/interceptor/HostFilter.ts","../src/services/interceptor/MitmProxyHost.ts","../src/services/interceptor/MockEngine.ts","../src/services/interceptor/RequestBuffer.ts","../src/services/interceptor/SessionArchive.ts","../src/services/interceptor/types.ts","../src/services/lease/LeaseOrphanSweeper.ts","../src/services/lease/LeaseService.ts","../src/services/lease/buildCapabilityBag.ts","../src/services/lease/leaseSessionCaps.ts","../src/services/lease/leaseToken.ts","../src/services/logcat/PackageResolver.ts","../src/services/logcat/logSource.ts","../src/services/logcat/logcatParse.ts","../src/services/logcat/ostraceParse.ts","../src/services/metrics/AndroidMetricsSampler.ts","../src/services/metrics/IOSMetricsSampler.ts","../src/services/metrics/NodeMetricsCollector.ts","../src/services/metrics/NodeMetricsStore.ts","../src/services/metrics/SessionMetricsService.ts","../src/services/metrics/androidMetrics.ts","../src/services/metrics/iosMetrics.ts","../src/services/metrics/metricsBody.ts","../src/services/metrics/nodeMetrics.ts","../src/services/metrics/types.ts","../src/services/omni-vision/OmniVisionService.ts","../src/services/omni-vision/VisionAssertionService.ts","../src/services/ports/PortAllocatorClient.ts","../src/services/ports/PortAllocatorService.ts","../src/services/recording/RecordingOrchestrator.ts","../src/services/recording/activeRecordings.ts","../src/services/recording/annotation-render.ts","../src/services/recording/annotationImage.ts","../src/services/recording/busy-precheck.ts","../src/services/recording/concurrency-gate.ts","../src/services/recording/ensureMjpegForRecording.ts","../src/services/recording/manualLock.ts","../src/services/recording/nodeRecordingSource.ts","../src/services/recording/probeDuration.ts","../src/services/recording/proof-bundle.ts","../src/services/recording/recording-store.ts","../src/services/recording/recordingCleanup.ts","../src/services/recording/recordingFiles.ts","../src/services/recording/recordingSummary.ts","../src/services/recording/recordingTiming.ts","../src/services/selector-health/access.ts","../src/services/selector-health/healingTrend.ts","../src/services/selector-health/people.ts","../src/services/selector-health/selectorDetail.ts","../src/services/selector-health/selectorKeys.ts","../src/services/selector-health/selectorList.ts","../src/services/selector-health/stateView.ts","../src/services/session/appCapability.ts","../src/services/session/nodeCreateCaps.ts","../src/services/session/sessionCredentials.ts","../src/services/session/sessionIdentity.ts","../src/services/session/xenonOptions.ts","../src/services/telemetry/attributes.ts","../src/services/token/AppDownloadTicketService.ts","../src/services/token/JwtKeyService.ts","../src/services/token/StreamTicketService.ts","../src/services/token/mcpScopes.ts","../src/services/token/singleUseLedger.ts","../src/sessions/CloudSession.ts","../src/sessions/LocalSession.ts","../src/sessions/RemoteSession.ts","../src/sessions/SessionManager.ts","../src/sessions/XenonSession.ts","../src/sessions/appiumUmbrella.ts","../src/types/CLIArgs.ts","../src/types/CloudArgs.ts","../src/types/CloudSchema.ts","../src/types/DeviceType.ts","../src/types/DeviceUpdate.ts","../src/types/IOSDevice.ts","../src/types/Platform.ts","../src/types/SessionStatus.ts","../src/types/express.d.ts","../src/types/healing.d.ts","../src/types/identity.ts","../src/validators/CapabilityValidator.ts","../test/e2e/e2ehelper.ts","../test/e2e/plugin-harness.ts","../test/e2e/plugin.spec.ts","../test/e2e/startup-verification.spec.ts","../test/e2e/telemetry_verification.spec.ts","../test/e2e/video-recording-test.spec.js","../test/e2e/android/conf.spec.js","../test/e2e/android/conf2.spec.js","../test/e2e/android/conf3.spec.js","../test/e2e/hubnode/forward-request.spec.ts","../test/e2e/hubnode/hubnode.spec.ts","../test/e2e/ios/conf1.spec.js","../test/e2e/ios/conf2.spec.js","../test/helpers/appium-umbrella.ts","../test/helpers/artifact-store.ts","../test/helpers/container-registration.ts","../test/helpers/fake-device-table.ts","../test/helpers/loki-stores.ts","../test/helpers/loopbackRequest.ts","../test/helpers/loopbackServer.ts","../test/helpers/own-node-id.ts","../test/helpers/scratch-database.ts","../test/helpers/scratch-port-leases.ts","../test/helpers/seedUser.ts","../test/helpers/selector-health-fixture.ts","../test/helpers/test-container.ts","../test/integration/androidDevices.spec.ts","../test/integration/audit-ingest.spec.ts","../test/integration/auth-flow.spec.ts","../test/integration/auth-rate-limit.spec.ts","../test/integration/bug-report-route.spec.ts","../test/integration/cliArgs.js","../test/integration/cross-workflow.spec.ts","../test/integration/forgot-password-rate-limit.spec.ts","../test/integration/forgot-password.spec.ts","../test/integration/healing-events-sessionfilter.spec.ts","../test/integration/legacy-deprecation-headers.spec.ts","../test/integration/migration.spec.ts","../test/integration/node-pair-auth-rest.spec.ts","../test/integration/ports-router.spec.ts","../test/integration/prisma-device-store-add-devices.spec.ts","../test/integration/prisma-device-store-team-filter.spec.ts","../test/integration/profile-tokens.spec.ts","../test/integration/recordings-router.spec.ts","../test/integration/reset-revokes-sessions.spec.ts","../test/integration/role-matrix.spec.ts","../test/integration/sdk-leases-router.spec.ts","../test/integration/sdk-version.spec.ts","../test/integration/selector-health-endpoint.spec.ts","../test/integration/selector-state-flow.spec.ts","../test/integration/team-membership-migration.spec.ts","../test/integration/team-visibility-apps.spec.ts","../test/integration/team-visibility-control.spec.ts","../test/integration/team-visibility-dashboard.spec.ts","../test/integration/team-visibility-grid.spec.ts","../test/integration/team-visibility-leases.spec.ts","../test/integration/team-visibility-recordings.spec.ts","../test/integration/team-visibility-sessions.spec.ts","../test/integration/users-flow.spec.ts","../test/integration/users-lockout.spec.ts","../test/integration/ios/01iOSSimulator.spec.ts","../test/integration/ios/02iOSDevices.spec.ts","../test/setup/scratch-default-database.js","../test/unit/AndroidDeviceManager.spec.ts","../test/unit/ApiKeyService.test.ts","../test/unit/AppDownloadTicketService.spec.ts","../test/unit/ArtifactStore.spec.ts","../test/unit/AutowaitService.spec.ts","../test/unit/CapabilitiesRouter.spec.ts","../test/unit/ChromeDriverManager.spec.js","../test/unit/CleanupService.spec.ts","../test/unit/CommandInterceptor.autowait.spec.ts","../test/unit/DeviceModel.spec.ts","../test/unit/EmailService.test.ts","../test/unit/EventLogService.spec.ts","../test/unit/FuzzyXmlHealingProvider.test.ts","../test/unit/GetAdbOriginal.js","../test/unit/HealingCascade.test.ts","../test/unit/IOSDeviceManager.spec.js","../test/unit/JwtKeyService.spec.ts","../test/unit/McpScopes.spec.ts","../test/unit/OrphanSweeper.test.ts","../test/unit/PasswordResetService.test.ts","../test/unit/PortAllocator.test.ts","../test/unit/ProcessRegistry.test.ts","../test/unit/ProjectsRouter.spec.ts","../test/unit/RemoteIOs.spec.js","../test/unit/ResilioTreeHealingProvider.test.ts","../test/unit/SessionHeartbeatWrite.test.ts","../test/unit/SessionLifecycleCaps.spec.ts","../test/unit/SessionTokenGate.spec.ts","../test/unit/StreamTicketService.spec.ts","../test/unit/TeamService.test.ts","../test/unit/TokenEndpoint.spec.ts","../test/unit/UserService.test.ts","../test/unit/UserSessionService.test.ts","../test/unit/XenonCapabilityManager.spec.ts","../test/unit/active-recordings.spec.ts","../test/unit/aggregate-hotspots-session-scope.spec.ts","../test/unit/aggregate-hotspots-tuple-key.spec.ts","../test/unit/android-clipboard.spec.ts","../test/unit/android-h264-config.spec.ts","../test/unit/android-h264-service.spec.ts","../test/unit/android-identity.spec.ts","../test/unit/android-preview-hold.spec.ts","../test/unit/android-stream-adb-path.spec.ts","../test/unit/android-stream-encoder.spec.ts","../test/unit/android-stream-fast-start.spec.ts","../test/unit/android-stream-release.spec.ts","../test/unit/android-stream-reuse-service.spec.ts","../test/unit/android-stream-reuse.spec.ts","../test/unit/android-stream-stall-eof.spec.ts","../test/unit/annotation-image.spec.ts","../test/unit/annotation-render.spec.ts","../test/unit/apple-identity.spec.ts","../test/unit/apps-download.spec.ts","../test/unit/apps-team-visibility.spec.ts","../test/unit/auth-disabled-resolution.spec.ts","../test/unit/auth-me-auth-disabled.test.ts","../test/unit/authMiddleware.appTicket.spec.ts","../test/unit/authMiddleware.bearer.spec.ts","../test/unit/authMiddleware.mcpAudience.spec.ts","../test/unit/authMiddleware.streamTicket.spec.ts","../test/unit/authMiddleware.test.ts","../test/unit/boot-go-ios-reap.spec.ts","../test/unit/bootstrap-identity.test.ts","../test/unit/build-export.spec.ts","../test/unit/busy-precheck.spec.ts","../test/unit/cliargs-admin-only.spec.ts","../test/unit/clipboard-route.spec.ts","../test/unit/command-auth-appium-server.spec.ts","../test/unit/command-auth.spec.ts","../test/unit/command-caller.spec.ts","../test/unit/commands.spec.js","../test/unit/composite-geometry.spec.ts","../test/unit/concurrency-gate.spec.ts","../test/unit/config.spec.js","../test/unit/container-registration.spec.ts","../test/unit/control-device-lookup.spec.ts","../test/unit/control-forward-decision.spec.ts","../test/unit/control-lookup-failure.spec.ts","../test/unit/create-error-message.spec.ts","../test/unit/create-handoff.spec.ts","../test/unit/dashboard-events-metrics.spec.ts","../test/unit/dashboard-events-team-scope.spec.ts","../test/unit/device-access-guard.spec.ts","../test/unit/device-access-policy.spec.ts","../test/unit/device-columns.spec.ts","../test/unit/device-service.spec.ts","../test/unit/device-store-clear-at-boot.spec.ts","../test/unit/device-sync-lost-update.spec.ts","../test/unit/device-team-guard.spec.ts","../test/unit/device-team-resolver.spec.ts","../test/unit/device-utils.spec.ts","../test/unit/display-state.spec.ts","../test/unit/enrich-devices-team-names.test.ts","../test/unit/event-manager-regression-hook.spec.ts","../test/unit/extract-access-key-token-pair.test.ts","../test/unit/extract-team-cap.spec.ts","../test/unit/ffmpeg-path.spec.ts","../test/unit/fill-missing-screen-size.spec.ts","../test/unit/findAndLockDevice-leasemerge.spec.ts","../test/unit/go-ios-version.spec.ts","../test/unit/grid-admin-only.spec.ts","../test/unit/h264-multiplexer.spec.ts","../test/unit/h264-nal-parser.spec.ts","../test/unit/h264-ws-frame.spec.ts","../test/unit/healing-instrumentation.spec.ts","../test/unit/healing-no-cost.spec.ts","../test/unit/healing-state-endpoints.spec.ts","../test/unit/healing-tier-gate.spec.ts","../test/unit/healing-trend.spec.ts","../test/unit/health-monitor-own-phones.spec.ts","../test/unit/health-monitor-stream-lookup.spec.ts","../test/unit/helpers.spec.ts","../test/unit/hub-boot-sweep-recovery.spec.ts","../test/unit/hub-create-once.spec.ts","../test/unit/hub-create-session-umbrella.spec.ts","../test/unit/hub-gateway-create-appium-server.spec.ts","../test/unit/hub-node-control-forward.spec.ts","../test/unit/hub-node-gateway-appium-server.spec.ts","../test/unit/hub-node-race.spec.ts","../test/unit/hub-node-same-host.spec.ts","../test/unit/hub-node-session-metrics.spec.ts","../test/unit/hub-register-removal.spec.ts","../test/unit/hub-remote-session-heartbeat.spec.ts","../test/unit/hub-routed-session-recovery.spec.ts","../test/unit/hub-session-token.spec.ts","../test/unit/insert-before-routes.spec.ts","../test/unit/inspector-hierarchy.spec.ts","../test/unit/install-repository-app-team.spec.ts","../test/unit/internal-call.spec.ts","../test/unit/ios-discovery-same-host.spec.ts","../test/unit/ios-go-ios-tunnel-env.spec.ts","../test/unit/ios-idle-hold.spec.ts","../test/unit/ios-no-network-fallback.spec.ts","../test/unit/ios-stream-appium-tunnel.spec.ts","../test/unit/ios-stream-port-leases.spec.ts","../test/unit/ios-stream-port.spec.ts","../test/unit/ios-tunnel-process.spec.ts","../test/unit/ios-tunnels.spec.ts","../test/unit/ios-wda-status-identity.spec.ts","../test/unit/iosBattery.spec.ts","../test/unit/iosStreamDiagnostics.spec.ts","../test/unit/is-xenon-running.spec.ts","../test/unit/logcat-multiplexer.spec.ts","../test/unit/logcat-parse.spec.ts","../test/unit/logcat-stream-service.spec.ts","../test/unit/logcat-ws.spec.ts","../test/unit/loginRateLimiter.test.ts","../test/unit/loopback-request.spec.ts","../test/unit/manualLock.test.ts","../test/unit/mark-node-busy-loki.spec.ts","../test/unit/mjpeg-proxy-cache.spec.ts","../test/unit/network-addresses.test.ts","../test/unit/node-create-caps.spec.ts","../test/unit/node-gateway-create-appium-server.spec.ts","../test/unit/node-hub-session-owner.spec.ts","../test/unit/node-metrics-collector.spec.ts","../test/unit/node-metrics-store.spec.ts","../test/unit/node-phone-control.spec.ts","../test/unit/node-recording-relay.spec.ts","../test/unit/node-session-metrics-route.spec.ts","../test/unit/node-socket-relay.spec.ts","../test/unit/normalize-eol.spec.js","../test/unit/omni-vision.spec.ts","../test/unit/ostrace-parse.spec.ts","../test/unit/package-resolver.spec.ts","../test/unit/passwordResetMode.test.ts","../test/unit/plugin.spec.ts","../test/unit/port-allocator-os-probe.spec.ts","../test/unit/port-allocator-pairs.spec.ts","../test/unit/port-exhaustion.spec.ts","../test/unit/prisma.spec.ts","../test/unit/probe-duration.spec.ts","../test/unit/profile-router.test.ts","../test/unit/profileIdentity.spec.ts","../test/unit/proof-bundle.spec.ts","../test/unit/queue-requester.spec.ts","../test/unit/queue-team-scope-routes.spec.ts","../test/unit/queue-visibility.spec.ts","../test/unit/rateLimitMiddleware.test.ts","../test/unit/recording-cleanup.spec.ts","../test/unit/recording-downloads-visibility.spec.ts","../test/unit/recording-files.spec.ts","../test/unit/recording-instrumentation.spec.ts","../test/unit/recording-orchestrator.spec.ts","../test/unit/recording-requests.spec.ts","../test/unit/recording-source-ended.spec.ts","../test/unit/recording-store.spec.ts","../test/unit/recording-summary.spec.ts","../test/unit/recording-timing.spec.ts","../test/unit/recordings-library-routes.spec.ts","../test/unit/recordings-write-visibility.spec.ts","../test/unit/remote-session-create.spec.ts","../test/unit/remux-to-standard-mp4.spec.ts","../test/unit/reservation-team-visibility.spec.ts","../test/unit/reset-link.test.ts","../test/unit/roleGuard.test.ts","../test/unit/run-migrations-fail-fast.test.ts","../test/unit/run-migrations.test.ts","../test/unit/schema-required-args.spec.ts","../test/unit/scrcpy-server-session.spec.ts","../test/unit/scrcpy-version.spec.ts","../test/unit/screenshot-route.spec.ts","../test/unit/selector-event-model.spec.ts","../test/unit/selector-health-actions.spec.ts","../test/unit/selector-health-detail.spec.ts","../test/unit/selector-health-list.spec.ts","../test/unit/selector-state-service.spec.ts","../test/unit/selector-verification-job.spec.ts","../test/unit/selector-verification-missed-regression.spec.ts","../test/unit/session-app-resolution.spec.ts","../test/unit/session-assets.spec.ts","../test/unit/session-attribution-wiring.spec.ts","../test/unit/session-create-layer.spec.ts","../test/unit/session-credential-strip.spec.ts","../test/unit/session-credentials.spec.ts","../test/unit/session-identity.spec.ts","../test/unit/session-list-insights.spec.ts","../test/unit/session-listing-auth.spec.ts","../test/unit/session-locator.spec.ts","../test/unit/session-log-indexes.spec.ts","../test/unit/session-metrics-lifecycle.spec.ts","../test/unit/session-metrics-parse.spec.ts","../test/unit/session-metrics-route.spec.ts","../test/unit/session-metrics-samplers.spec.ts","../test/unit/session-metrics-service.spec.ts","../test/unit/session-node-calls.spec.ts","../test/unit/session-owner-resolver.spec.ts","../test/unit/session-recovery-metrics.spec.ts","../test/unit/session-recovery-routing.spec.ts","../test/unit/session-upgrade-guard.spec.ts","../test/unit/session-visibility.spec.ts","../test/unit/shutdown-drain-remote.spec.ts","../test/unit/shutdown-sync-nets.spec.ts","../test/unit/single-flight.spec.ts","../test/unit/socket-team-scope.integration.spec.ts","../test/unit/socketServer.bearer.spec.ts","../test/unit/socketServer.scopedEmit.spec.ts","../test/unit/socketServer.sessionCookie.spec.ts","../test/unit/stored-session-capabilities.spec.ts","../test/unit/stream-leave-route.spec.ts","../test/unit/stream-leave.spec.ts","../test/unit/stream-own-device-row.spec.ts","../test/unit/stream-start-conflict.spec.ts","../test/unit/stream-status-type.spec.ts","../test/unit/stream-stop-ownership.spec.ts","../test/unit/stream-stop-recording.spec.ts","../test/unit/stream-ticket-identity.spec.ts","../test/unit/stream-viewer-hangup.spec.ts","../test/unit/stream-watchdog-timers.spec.ts","../test/unit/sync-dir.spec.ts","../test/unit/team-filter.test.ts","../test/unit/tracing-service-init.spec.ts","../test/unit/upgrade-router.spec.ts","../test/unit/upload-install-route.spec.ts","../test/unit/userAuthorization.test.ts","../test/unit/users-router.test.ts","../test/unit/verify-credential.spec.ts","../test/unit/verify-locator.spec.ts","../test/unit/video-pipeline-args.spec.ts","../test/unit/video-pipeline-exit.spec.ts","../test/unit/video-pipeline-outputpath.spec.ts","../test/unit/wda-cap-injection.spec.ts","../test/unit/webdriver-info-route.spec.ts","../test/unit/ws-upgrade-routing-appium-server.spec.ts","../test/unit/xenon-options.spec.ts","../test/unit/bug-report/archive.spec.ts","../test/unit/bug-report/har-collector.spec.ts","../test/unit/bug-report/manifest.spec.ts","../test/unit/bug-report/readme.spec.ts","../test/unit/bug-report/route.spec.ts","../test/unit/bug-report/service.spec.ts","../test/unit/bug-report/video-slice.spec.ts","../test/unit/bug-report/window.spec.ts","../test/unit/fixtures/device.config.js","../test/unit/fixtures/devices.js","../test/unit/interceptor/AndroidProxyAdapter.spec.ts","../test/unit/interceptor/CertManager.spec.ts","../test/unit/interceptor/HarBuilder.spec.ts","../test/unit/interceptor/HostFilter.spec.ts","../test/unit/interceptor/MitmProxyHost.spec.ts","../test/unit/interceptor/MockEngine.spec.ts","../test/unit/interceptor/RequestBuffer.spec.ts","../test/unit/interceptor/SessionArchive.spec.ts","../test/unit/lease/LeaseOrphanSweeper.spec.ts","../test/unit/lease/LeaseService.spec.ts","../test/unit/lease/allocate-lease-branch.spec.ts","../test/unit/lease/buildCapabilityBag.spec.ts","../test/unit/lease/lease-override.spec.ts","../test/unit/lease/lease-reap-held-phone.spec.ts","../test/unit/lease/lease-session-ownership.spec.ts","../test/unit/lease/lease-sweeper-expiry.spec.ts","../test/unit/lease/lease-team-visibility.spec.ts","../test/unit/lease/lease-token-log-filter.spec.ts","../test/unit/lease/lease-token-oracle.spec.ts","../test/unit/lease/leaseToken.spec.ts","../test/unit/lease/nodePairAuth.spec.ts","../test/unit/lease/session-lease-proof.spec.ts","../test/unit/ports/PortAllocatorService.spec.ts"],"version":"5.9.3"}
1
+ {"root":["../src/InternalHttpClient.ts","../src/PluginContext.ts","../src/XenonCapabilityManager.ts","../src/chromeUtils.ts","../src/config.ts","../src/device-utils.ts","../src/index.ts","../src/logger.ts","../src/plugin.ts","../src/prisma.ts","../src/app/appiumBasePath.ts","../src/app/index.ts","../src/app/insertBeforeRoutes.ts","../src/app/registerCommandAuth.ts","../src/app/swagger-docs.ts","../src/app/swagger.ts","../src/app/routers/androidH264Config.ts","../src/app/routers/apikeys.ts","../src/app/routers/apps.ts","../src/app/routers/audit.ts","../src/app/routers/auth.ts","../src/app/routers/bug-report.ts","../src/app/routers/build-export.ts","../src/app/routers/capabilities.ts","../src/app/routers/config.ts","../src/app/routers/control.ts","../src/app/routers/dashboard.ts","../src/app/routers/grid.ts","../src/app/routers/interceptor.ts","../src/app/routers/iosStreamPort.ts","../src/app/routers/nodePhoneControl.ts","../src/app/routers/ports.ts","../src/app/routers/processes.ts","../src/app/routers/profile.ts","../src/app/routers/profileIdentity.ts","../src/app/routers/projects.ts","../src/app/routers/recordingRequests.ts","../src/app/routers/recordings.ts","../src/app/routers/reservation.ts","../src/app/routers/sdk-leases.ts","../src/app/routers/sdk-version.ts","../src/app/routers/selector-health.ts","../src/app/routers/sessionInsights.ts","../src/app/routers/streamLeave.ts","../src/app/routers/streamStartConflict.ts","../src/app/routers/streamType.ts","../src/app/routers/teams.ts","../src/app/routers/users.ts","../src/app/routers/webhook.ts","../src/app/ws/h264StreamWs.ts","../src/app/ws/logcatWs.ts","../src/app/ws/nodeSocketRelay.ts","../src/app/ws/upgradeRouter.ts","../src/commands/handle.ts","../src/commands/index.ts","../src/dashboard/asset-manager.ts","../src/dashboard/commands.ts","../src/dashboard/event-manager.ts","../src/dashboard/services/app-service.ts","../src/dashboard/services/failure-analysis-service.ts","../src/dashboard/services/session-service.ts","../src/data-service/CircuitBreaker.ts","../src/data-service/config-service.ts","../src/data-service/db.ts","../src/data-service/device-service.ts","../src/data-service/device-store.interface.ts","../src/data-service/device-store.ts","../src/data-service/deviceClaims.ts","../src/data-service/deviceColumns.ts","../src/data-service/deviceFieldOwners.ts","../src/data-service/pending-sessions-service.ts","../src/data-service/pluginArgs.ts","../src/data-service/prisma-service.ts","../src/data-service/prisma-store.ts","../src/data-service/queue-service.ts","../src/data-service/web-config-service.ts","../src/device-managers/AndroidDeviceManager.ts","../src/device-managers/ChromeDriverManager.ts","../src/device-managers/HealthMonitorService.ts","../src/device-managers/IOSDeviceManager.ts","../src/device-managers/NodeDevices.ts","../src/device-managers/clipboardErrors.ts","../src/device-managers/deviceIdentity.ts","../src/device-managers/iOSTracker.ts","../src/device-managers/index.ts","../src/device-managers/localDeviceHosts.ts","../src/device-managers/ownDeviceRow.ts","../src/device-managers/android/AndroidH264StreamService.ts","../src/device-managers/android/AndroidStreamService.ts","../src/device-managers/android/DeviceLockManager.ts","../src/device-managers/android/H264Multiplexer.ts","../src/device-managers/android/LogcatMultiplexer.ts","../src/device-managers/android/LogcatStreamService.ts","../src/device-managers/android/ScrcpyServerSession.ts","../src/device-managers/android/androidIdentity.ts","../src/device-managers/android/androidStreamReuse.ts","../src/device-managers/android/clipboardBroadcast.ts","../src/device-managers/android/displayState.ts","../src/device-managers/android/h264NalParser.ts","../src/device-managers/android/previewHold.ts","../src/device-managers/android/scrcpyVersion.ts","../src/device-managers/cloud/CapabilityManager.ts","../src/device-managers/cloud/Devices.ts","../src/device-managers/ios/IOSDiscoveryService.ts","../src/device-managers/ios/IOSLogStreamService.ts","../src/device-managers/ios/IOSStreamService.ts","../src/device-managers/ios/IOSTunnels.ts","../src/device-managers/ios/WDAClient.ts","../src/device-managers/ios/appleIdentity.ts","../src/device-managers/ios/goIosBinary.ts","../src/device-managers/ios/iosAppIds.ts","../src/device-managers/ios/iosBattery.ts","../src/device-managers/ios/iosStreamDiagnostics.ts","../src/device-managers/ios/tunnelProcess.ts","../src/device-managers/ios/usbmuxd.ts","../src/enums/Capabilities.ts","../src/enums/Cloud.ts","../src/enums/Platform.ts","../src/enums/SessionType.ts","../src/enums/SocketEvents.ts","../src/gateway/createHandoff.ts","../src/gateway/defaultGateway.ts","../src/gateway/forwardToNode.ts","../src/gateway/hubSessionToken.ts","../src/gateway/internalCall.ts","../src/gateway/nodeSessionMetrics.ts","../src/gateway/nodeSessionStatus.ts","../src/gateway/nodeWebDriverUrl.ts","../src/gateway/sessionCreate.ts","../src/gateway/sessionGateway.ts","../src/gateway/sessionLocator.ts","../src/generated/client/default.d.ts","../src/generated/client/default.js","../src/generated/client/edge.d.ts","../src/generated/client/edge.js","../src/generated/client/index-browser.js","../src/generated/client/index.d.ts","../src/generated/client/index.js","../src/generated/client/wasm.d.ts","../src/generated/client/wasm.js","../src/generated/client/runtime/edge-esm.js","../src/generated/client/runtime/edge.js","../src/generated/client/runtime/index-browser.d.ts","../src/generated/client/runtime/index-browser.js","../src/generated/client/runtime/library.d.ts","../src/generated/client/runtime/library.js","../src/generated/client/runtime/react-native.js","../src/generated/client/runtime/wasm.js","../src/helpers/UniversalMjpegProxy.ts","../src/helpers/ffmpegPath.ts","../src/helpers/index.ts","../src/helpers/networkAddresses.ts","../src/helpers/singleFlight.ts","../src/interceptors/CommandInterceptor.ts","../src/interfaces/ICloudManager.ts","../src/interfaces/IDevice.ts","../src/interfaces/IDeviceFilterOptions.ts","../src/interfaces/IDeviceManager.ts","../src/interfaces/IOptions.ts","../src/interfaces/IPluginArgs.ts","../src/interfaces/ISessionCapability.ts","../src/logging/sessionContext.ts","../src/middleware/authMiddleware.ts","../src/middleware/commandAuth.ts","../src/middleware/commandCaller.ts","../src/middleware/controlDevice.ts","../src/middleware/csrfMiddleware.ts","../src/middleware/deviceAccessGuard.ts","../src/middleware/deviceTeamGuard.ts","../src/middleware/leaseTokenMiddleware.ts","../src/middleware/loginRateLimiter.ts","../src/middleware/rateLimitMiddleware.ts","../src/middleware/roleGuard.ts","../src/middleware/scopeGuard.ts","../src/middleware/sessionListingFilter.ts","../src/middleware/sessionUpgradeGuard.ts","../src/middleware/verifyCredential.ts","../src/scripts/generate-database-migration.ts","../src/scripts/goIosVersion.ts","../src/scripts/initialize-database.ts","../src/scripts/install-go-ios.ts","../src/scripts/prepare-prisma.ts","../src/scripts/run-migrations.ts","../src/services/AICommandService.ts","../src/services/AIService.ts","../src/services/ApiKeyService.ts","../src/services/CircuitBreaker.ts","../src/services/CleanupService.ts","../src/services/DeviceReconciler.ts","../src/services/DisplayStateService.ts","../src/services/EmailService.ts","../src/services/EventBus.ts","../src/services/EventLogService.ts","../src/services/InspectorService.ts","../src/services/InterceptorService.ts","../src/services/MetricsService.ts","../src/services/NetworkConditioningService.ts","../src/services/NotificationService.ts","../src/services/OrphanSweeper.ts","../src/services/PasswordResetService.ts","../src/services/PortAllocator.ts","../src/services/ProcessMetricsService.ts","../src/services/ProcessRegistry.ts","../src/services/RequestLogService.ts","../src/services/ResourceIsolationService.ts","../src/services/SecurityService.ts","../src/services/SelectorStateService.ts","../src/services/SelectorVerificationJob.ts","../src/services/ServerManager.ts","../src/services/SessionHeartbeatService.ts","../src/services/SessionLifecycleService.ts","../src/services/ShutdownCoordinator.ts","../src/services/SocketClient.ts","../src/services/SocketServer.ts","../src/services/TeamService.ts","../src/services/TracingService.ts","../src/services/UserService.ts","../src/services/UserSessionService.ts","../src/services/VideoPipelineService.ts","../src/services/fillMissingScreenSize.ts","../src/services/passwordResetLink.ts","../src/services/passwordResetMode.ts","../src/services/sessionTokenGate.ts","../src/services/artifacts/ArtifactStore.ts","../src/services/autowait/AutowaitService.ts","../src/services/autowait/waitFor.ts","../src/services/bug-report/BugReportService.ts","../src/services/bug-report/archive.ts","../src/services/bug-report/har-collector.ts","../src/services/bug-report/manifest.ts","../src/services/bug-report/readme.ts","../src/services/bug-report/types.ts","../src/services/bug-report/video-slice.ts","../src/services/bug-report/window.ts","../src/services/device-access/DeviceTeamResolver.ts","../src/services/device-access/LiveSessionOwners.ts","../src/services/device-access/SessionOwnerResolver.ts","../src/services/device-access/actor.ts","../src/services/device-access/appVisibility.ts","../src/services/device-access/callerTeamIds.ts","../src/services/device-access/deviceAccessPolicy.ts","../src/services/device-access/deviceVisibility.ts","../src/services/device-access/leaseOverride.ts","../src/services/device-access/queueVisibility.ts","../src/services/device-access/sessionVisibility.ts","../src/services/device-access/ticketActorAccess.ts","../src/services/healing/FuzzyXmlHealingProvider.ts","../src/services/healing/HealEtalonService.ts","../src/services/healing/HealedLocatorGenerator.ts","../src/services/healing/HealingMetrics.ts","../src/services/healing/HealingOrchestrator.ts","../src/services/healing/LlmHealingProvider.ts","../src/services/healing/OcrHealingProvider.ts","../src/services/healing/ResilioTreeHealingProvider.ts","../src/services/healing/VisualAiHealingProvider.ts","../src/services/healing/types.ts","../src/services/identity/bootstrap.ts","../src/services/identity/sessionCleanupCron.ts","../src/services/identity/userAuthorization.ts","../src/services/inspector/verifyLocator.ts","../src/services/interceptor/AndroidProxyAdapter.ts","../src/services/interceptor/CertManager.ts","../src/services/interceptor/HarBuilder.ts","../src/services/interceptor/HostFilter.ts","../src/services/interceptor/MitmProxyHost.ts","../src/services/interceptor/MockEngine.ts","../src/services/interceptor/RequestBuffer.ts","../src/services/interceptor/SessionArchive.ts","../src/services/interceptor/types.ts","../src/services/lease/LeaseOrphanSweeper.ts","../src/services/lease/LeaseService.ts","../src/services/lease/buildCapabilityBag.ts","../src/services/lease/leaseSessionCaps.ts","../src/services/lease/leaseToken.ts","../src/services/logcat/PackageResolver.ts","../src/services/logcat/logSource.ts","../src/services/logcat/logcatParse.ts","../src/services/logcat/ostraceParse.ts","../src/services/metrics/AndroidMetricsSampler.ts","../src/services/metrics/IOSMetricsSampler.ts","../src/services/metrics/NodeMetricsCollector.ts","../src/services/metrics/NodeMetricsStore.ts","../src/services/metrics/SessionMetricsService.ts","../src/services/metrics/androidMetrics.ts","../src/services/metrics/iosMetrics.ts","../src/services/metrics/metricsBody.ts","../src/services/metrics/nodeMetrics.ts","../src/services/metrics/types.ts","../src/services/omni-vision/OmniVisionService.ts","../src/services/omni-vision/VisionAssertionService.ts","../src/services/ports/PortAllocatorClient.ts","../src/services/ports/PortAllocatorService.ts","../src/services/recording/RecordingOrchestrator.ts","../src/services/recording/activeRecordings.ts","../src/services/recording/annotation-render.ts","../src/services/recording/annotationImage.ts","../src/services/recording/busy-precheck.ts","../src/services/recording/concurrency-gate.ts","../src/services/recording/ensureMjpegForRecording.ts","../src/services/recording/manualLock.ts","../src/services/recording/nodeRecordingSource.ts","../src/services/recording/probeDuration.ts","../src/services/recording/proof-bundle.ts","../src/services/recording/recording-store.ts","../src/services/recording/recordingCleanup.ts","../src/services/recording/recordingFiles.ts","../src/services/recording/recordingSummary.ts","../src/services/recording/recordingTiming.ts","../src/services/selector-health/access.ts","../src/services/selector-health/healingTrend.ts","../src/services/selector-health/people.ts","../src/services/selector-health/selectorDetail.ts","../src/services/selector-health/selectorKeys.ts","../src/services/selector-health/selectorList.ts","../src/services/selector-health/stateView.ts","../src/services/session/appCapability.ts","../src/services/session/nodeCreateCaps.ts","../src/services/session/sessionCredentials.ts","../src/services/session/sessionIdentity.ts","../src/services/session/xenonOptions.ts","../src/services/telemetry/attributes.ts","../src/services/token/AppDownloadTicketService.ts","../src/services/token/JwtKeyService.ts","../src/services/token/StreamTicketService.ts","../src/services/token/mcpScopes.ts","../src/services/token/singleUseLedger.ts","../src/sessions/CloudSession.ts","../src/sessions/LocalSession.ts","../src/sessions/RemoteSession.ts","../src/sessions/SessionManager.ts","../src/sessions/XenonSession.ts","../src/sessions/appiumUmbrella.ts","../src/types/CLIArgs.ts","../src/types/CloudArgs.ts","../src/types/CloudSchema.ts","../src/types/DeviceType.ts","../src/types/DeviceUpdate.ts","../src/types/IOSDevice.ts","../src/types/Platform.ts","../src/types/SessionStatus.ts","../src/types/express.d.ts","../src/types/healing.d.ts","../src/types/identity.ts","../src/validators/CapabilityValidator.ts","../test/e2e/e2ehelper.ts","../test/e2e/plugin-harness.ts","../test/e2e/plugin.spec.ts","../test/e2e/startup-verification.spec.ts","../test/e2e/telemetry_verification.spec.ts","../test/e2e/video-recording-test.spec.js","../test/e2e/android/conf.spec.js","../test/e2e/android/conf2.spec.js","../test/e2e/android/conf3.spec.js","../test/e2e/hubnode/forward-request.spec.ts","../test/e2e/hubnode/hubnode.spec.ts","../test/e2e/ios/conf1.spec.js","../test/e2e/ios/conf2.spec.js","../test/helpers/appium-umbrella.ts","../test/helpers/artifact-store.ts","../test/helpers/container-registration.ts","../test/helpers/fake-device-table.ts","../test/helpers/loki-stores.ts","../test/helpers/loopbackRequest.ts","../test/helpers/loopbackServer.ts","../test/helpers/own-node-id.ts","../test/helpers/scratch-database.ts","../test/helpers/scratch-port-leases.ts","../test/helpers/seedUser.ts","../test/helpers/selector-health-fixture.ts","../test/helpers/test-container.ts","../test/integration/androidDevices.spec.ts","../test/integration/audit-ingest.spec.ts","../test/integration/auth-flow.spec.ts","../test/integration/auth-rate-limit.spec.ts","../test/integration/bug-report-route.spec.ts","../test/integration/cliArgs.js","../test/integration/cross-workflow.spec.ts","../test/integration/forgot-password-rate-limit.spec.ts","../test/integration/forgot-password.spec.ts","../test/integration/healing-events-sessionfilter.spec.ts","../test/integration/legacy-deprecation-headers.spec.ts","../test/integration/migration.spec.ts","../test/integration/node-pair-auth-rest.spec.ts","../test/integration/ports-router.spec.ts","../test/integration/prisma-device-store-add-devices.spec.ts","../test/integration/prisma-device-store-team-filter.spec.ts","../test/integration/profile-tokens.spec.ts","../test/integration/recordings-router.spec.ts","../test/integration/reset-revokes-sessions.spec.ts","../test/integration/role-matrix.spec.ts","../test/integration/sdk-leases-router.spec.ts","../test/integration/sdk-version.spec.ts","../test/integration/selector-health-endpoint.spec.ts","../test/integration/selector-state-flow.spec.ts","../test/integration/team-membership-migration.spec.ts","../test/integration/team-visibility-apps.spec.ts","../test/integration/team-visibility-control.spec.ts","../test/integration/team-visibility-dashboard.spec.ts","../test/integration/team-visibility-grid.spec.ts","../test/integration/team-visibility-leases.spec.ts","../test/integration/team-visibility-recordings.spec.ts","../test/integration/team-visibility-sessions.spec.ts","../test/integration/users-flow.spec.ts","../test/integration/users-lockout.spec.ts","../test/integration/ios/01iOSSimulator.spec.ts","../test/integration/ios/02iOSDevices.spec.ts","../test/setup/scratch-default-database.js","../test/unit/AndroidDeviceManager.spec.ts","../test/unit/ApiKeyService.test.ts","../test/unit/AppDownloadTicketService.spec.ts","../test/unit/ArtifactStore.spec.ts","../test/unit/AutowaitService.spec.ts","../test/unit/CapabilitiesRouter.spec.ts","../test/unit/ChromeDriverManager.spec.js","../test/unit/CleanupService.spec.ts","../test/unit/CommandInterceptor.autowait.spec.ts","../test/unit/DeviceModel.spec.ts","../test/unit/EmailService.test.ts","../test/unit/EventLogService.spec.ts","../test/unit/FuzzyXmlHealingProvider.test.ts","../test/unit/GetAdbOriginal.js","../test/unit/HealingCascade.test.ts","../test/unit/IOSDeviceManager.spec.js","../test/unit/JwtKeyService.spec.ts","../test/unit/McpScopes.spec.ts","../test/unit/OrphanSweeper.test.ts","../test/unit/PasswordResetService.test.ts","../test/unit/PortAllocator.test.ts","../test/unit/ProcessRegistry.test.ts","../test/unit/ProjectsRouter.spec.ts","../test/unit/RemoteIOs.spec.js","../test/unit/ResilioTreeHealingProvider.test.ts","../test/unit/SessionHeartbeatWrite.test.ts","../test/unit/SessionLifecycleCaps.spec.ts","../test/unit/SessionTokenGate.spec.ts","../test/unit/StreamTicketService.spec.ts","../test/unit/TeamService.test.ts","../test/unit/TokenEndpoint.spec.ts","../test/unit/UserService.test.ts","../test/unit/UserSessionService.test.ts","../test/unit/XenonCapabilityManager.spec.ts","../test/unit/active-recordings.spec.ts","../test/unit/aggregate-hotspots-session-scope.spec.ts","../test/unit/aggregate-hotspots-tuple-key.spec.ts","../test/unit/android-clipboard.spec.ts","../test/unit/android-h264-config.spec.ts","../test/unit/android-h264-service.spec.ts","../test/unit/android-identity.spec.ts","../test/unit/android-preview-hold.spec.ts","../test/unit/android-stream-adb-path.spec.ts","../test/unit/android-stream-encoder.spec.ts","../test/unit/android-stream-fast-start.spec.ts","../test/unit/android-stream-release.spec.ts","../test/unit/android-stream-reuse-service.spec.ts","../test/unit/android-stream-reuse.spec.ts","../test/unit/android-stream-stall-eof.spec.ts","../test/unit/annotation-image.spec.ts","../test/unit/annotation-render.spec.ts","../test/unit/apple-identity.spec.ts","../test/unit/apps-download.spec.ts","../test/unit/apps-team-visibility.spec.ts","../test/unit/auth-disabled-resolution.spec.ts","../test/unit/auth-me-auth-disabled.test.ts","../test/unit/authMiddleware.appTicket.spec.ts","../test/unit/authMiddleware.bearer.spec.ts","../test/unit/authMiddleware.mcpAudience.spec.ts","../test/unit/authMiddleware.streamTicket.spec.ts","../test/unit/authMiddleware.test.ts","../test/unit/boot-go-ios-reap.spec.ts","../test/unit/bootstrap-identity.test.ts","../test/unit/build-export.spec.ts","../test/unit/busy-precheck.spec.ts","../test/unit/cliargs-admin-only.spec.ts","../test/unit/clipboard-route.spec.ts","../test/unit/command-auth-appium-server.spec.ts","../test/unit/command-auth.spec.ts","../test/unit/command-caller.spec.ts","../test/unit/commands.spec.js","../test/unit/composite-geometry.spec.ts","../test/unit/concurrency-gate.spec.ts","../test/unit/config.spec.js","../test/unit/container-registration.spec.ts","../test/unit/control-device-lookup.spec.ts","../test/unit/control-forward-decision.spec.ts","../test/unit/control-lookup-failure.spec.ts","../test/unit/create-error-message.spec.ts","../test/unit/create-handoff.spec.ts","../test/unit/dashboard-events-metrics.spec.ts","../test/unit/dashboard-events-team-scope.spec.ts","../test/unit/device-access-guard.spec.ts","../test/unit/device-access-policy.spec.ts","../test/unit/device-columns.spec.ts","../test/unit/device-service.spec.ts","../test/unit/device-store-clear-at-boot.spec.ts","../test/unit/device-sync-lost-update.spec.ts","../test/unit/device-team-guard.spec.ts","../test/unit/device-team-resolver.spec.ts","../test/unit/device-utils.spec.ts","../test/unit/display-state.spec.ts","../test/unit/enrich-devices-team-names.test.ts","../test/unit/event-manager-regression-hook.spec.ts","../test/unit/extract-access-key-token-pair.test.ts","../test/unit/extract-team-cap.spec.ts","../test/unit/ffmpeg-path.spec.ts","../test/unit/fill-missing-screen-size.spec.ts","../test/unit/findAndLockDevice-leasemerge.spec.ts","../test/unit/go-ios-version.spec.ts","../test/unit/grid-admin-only.spec.ts","../test/unit/h264-multiplexer.spec.ts","../test/unit/h264-nal-parser.spec.ts","../test/unit/h264-ws-frame.spec.ts","../test/unit/healing-instrumentation.spec.ts","../test/unit/healing-no-cost.spec.ts","../test/unit/healing-state-endpoints.spec.ts","../test/unit/healing-tier-gate.spec.ts","../test/unit/healing-trend.spec.ts","../test/unit/health-monitor-own-phones.spec.ts","../test/unit/health-monitor-stream-lookup.spec.ts","../test/unit/helpers.spec.ts","../test/unit/hub-boot-sweep-recovery.spec.ts","../test/unit/hub-create-once.spec.ts","../test/unit/hub-create-session-umbrella.spec.ts","../test/unit/hub-gateway-create-appium-server.spec.ts","../test/unit/hub-node-control-forward.spec.ts","../test/unit/hub-node-gateway-appium-server.spec.ts","../test/unit/hub-node-race.spec.ts","../test/unit/hub-node-same-host.spec.ts","../test/unit/hub-node-session-metrics.spec.ts","../test/unit/hub-register-removal.spec.ts","../test/unit/hub-remote-session-heartbeat.spec.ts","../test/unit/hub-routed-session-recovery.spec.ts","../test/unit/hub-session-token.spec.ts","../test/unit/insert-before-routes.spec.ts","../test/unit/inspector-hierarchy.spec.ts","../test/unit/install-repository-app-team.spec.ts","../test/unit/internal-call.spec.ts","../test/unit/ios-discovery-same-host.spec.ts","../test/unit/ios-go-ios-tunnel-env.spec.ts","../test/unit/ios-idle-hold.spec.ts","../test/unit/ios-no-network-fallback.spec.ts","../test/unit/ios-stream-appium-tunnel.spec.ts","../test/unit/ios-stream-port-leases.spec.ts","../test/unit/ios-stream-port.spec.ts","../test/unit/ios-tunnel-process.spec.ts","../test/unit/ios-tunnels.spec.ts","../test/unit/ios-usbmuxd-missing.spec.ts","../test/unit/ios-wda-status-identity.spec.ts","../test/unit/iosBattery.spec.ts","../test/unit/iosStreamDiagnostics.spec.ts","../test/unit/is-xenon-running.spec.ts","../test/unit/logcat-multiplexer.spec.ts","../test/unit/logcat-parse.spec.ts","../test/unit/logcat-stream-service.spec.ts","../test/unit/logcat-ws.spec.ts","../test/unit/loginRateLimiter.test.ts","../test/unit/loopback-request.spec.ts","../test/unit/manualLock.test.ts","../test/unit/mark-node-busy-loki.spec.ts","../test/unit/mjpeg-proxy-cache.spec.ts","../test/unit/network-addresses.test.ts","../test/unit/node-create-caps.spec.ts","../test/unit/node-gateway-create-appium-server.spec.ts","../test/unit/node-hub-session-owner.spec.ts","../test/unit/node-metrics-collector.spec.ts","../test/unit/node-metrics-store.spec.ts","../test/unit/node-phone-control.spec.ts","../test/unit/node-recording-relay.spec.ts","../test/unit/node-session-metrics-route.spec.ts","../test/unit/node-socket-relay.spec.ts","../test/unit/normalize-eol.spec.js","../test/unit/omni-vision.spec.ts","../test/unit/ostrace-parse.spec.ts","../test/unit/package-resolver.spec.ts","../test/unit/passwordResetMode.test.ts","../test/unit/plugin.spec.ts","../test/unit/port-allocator-os-probe.spec.ts","../test/unit/port-allocator-pairs.spec.ts","../test/unit/port-exhaustion.spec.ts","../test/unit/prisma.spec.ts","../test/unit/probe-duration.spec.ts","../test/unit/profile-router.test.ts","../test/unit/profileIdentity.spec.ts","../test/unit/proof-bundle.spec.ts","../test/unit/queue-requester.spec.ts","../test/unit/queue-team-scope-routes.spec.ts","../test/unit/queue-visibility.spec.ts","../test/unit/rateLimitMiddleware.test.ts","../test/unit/recording-cleanup.spec.ts","../test/unit/recording-downloads-visibility.spec.ts","../test/unit/recording-files.spec.ts","../test/unit/recording-instrumentation.spec.ts","../test/unit/recording-orchestrator.spec.ts","../test/unit/recording-requests.spec.ts","../test/unit/recording-source-ended.spec.ts","../test/unit/recording-store.spec.ts","../test/unit/recording-summary.spec.ts","../test/unit/recording-timing.spec.ts","../test/unit/recordings-library-routes.spec.ts","../test/unit/recordings-write-visibility.spec.ts","../test/unit/remote-session-create.spec.ts","../test/unit/remux-to-standard-mp4.spec.ts","../test/unit/reservation-team-visibility.spec.ts","../test/unit/reset-link.test.ts","../test/unit/roleGuard.test.ts","../test/unit/run-migrations-fail-fast.test.ts","../test/unit/run-migrations.test.ts","../test/unit/schema-required-args.spec.ts","../test/unit/scrcpy-server-session.spec.ts","../test/unit/scrcpy-version.spec.ts","../test/unit/screenshot-route.spec.ts","../test/unit/selector-event-model.spec.ts","../test/unit/selector-health-actions.spec.ts","../test/unit/selector-health-detail.spec.ts","../test/unit/selector-health-list.spec.ts","../test/unit/selector-state-service.spec.ts","../test/unit/selector-verification-job.spec.ts","../test/unit/selector-verification-missed-regression.spec.ts","../test/unit/session-app-resolution.spec.ts","../test/unit/session-assets.spec.ts","../test/unit/session-attribution-wiring.spec.ts","../test/unit/session-create-layer.spec.ts","../test/unit/session-credential-strip.spec.ts","../test/unit/session-credentials.spec.ts","../test/unit/session-identity.spec.ts","../test/unit/session-list-insights.spec.ts","../test/unit/session-listing-auth.spec.ts","../test/unit/session-locator.spec.ts","../test/unit/session-log-indexes.spec.ts","../test/unit/session-metrics-lifecycle.spec.ts","../test/unit/session-metrics-parse.spec.ts","../test/unit/session-metrics-route.spec.ts","../test/unit/session-metrics-samplers.spec.ts","../test/unit/session-metrics-service.spec.ts","../test/unit/session-node-calls.spec.ts","../test/unit/session-owner-resolver.spec.ts","../test/unit/session-recovery-metrics.spec.ts","../test/unit/session-recovery-routing.spec.ts","../test/unit/session-upgrade-guard.spec.ts","../test/unit/session-visibility.spec.ts","../test/unit/shutdown-drain-remote.spec.ts","../test/unit/shutdown-sync-nets.spec.ts","../test/unit/single-flight.spec.ts","../test/unit/socket-team-scope.integration.spec.ts","../test/unit/socketServer.bearer.spec.ts","../test/unit/socketServer.scopedEmit.spec.ts","../test/unit/socketServer.sessionCookie.spec.ts","../test/unit/stored-session-capabilities.spec.ts","../test/unit/stream-leave-route.spec.ts","../test/unit/stream-leave.spec.ts","../test/unit/stream-own-device-row.spec.ts","../test/unit/stream-start-conflict.spec.ts","../test/unit/stream-status-type.spec.ts","../test/unit/stream-stop-ownership.spec.ts","../test/unit/stream-stop-recording.spec.ts","../test/unit/stream-ticket-identity.spec.ts","../test/unit/stream-viewer-hangup.spec.ts","../test/unit/stream-watchdog-timers.spec.ts","../test/unit/sync-dir.spec.ts","../test/unit/team-filter.test.ts","../test/unit/tracing-service-init.spec.ts","../test/unit/upgrade-router.spec.ts","../test/unit/upload-install-route.spec.ts","../test/unit/userAuthorization.test.ts","../test/unit/users-router.test.ts","../test/unit/verify-credential.spec.ts","../test/unit/verify-locator.spec.ts","../test/unit/video-pipeline-args.spec.ts","../test/unit/video-pipeline-exit.spec.ts","../test/unit/video-pipeline-outputpath.spec.ts","../test/unit/wda-cap-injection.spec.ts","../test/unit/webdriver-info-route.spec.ts","../test/unit/ws-upgrade-routing-appium-server.spec.ts","../test/unit/xenon-options.spec.ts","../test/unit/bug-report/archive.spec.ts","../test/unit/bug-report/har-collector.spec.ts","../test/unit/bug-report/manifest.spec.ts","../test/unit/bug-report/readme.spec.ts","../test/unit/bug-report/route.spec.ts","../test/unit/bug-report/service.spec.ts","../test/unit/bug-report/video-slice.spec.ts","../test/unit/bug-report/window.spec.ts","../test/unit/fixtures/device.config.js","../test/unit/fixtures/devices.js","../test/unit/interceptor/AndroidProxyAdapter.spec.ts","../test/unit/interceptor/CertManager.spec.ts","../test/unit/interceptor/HarBuilder.spec.ts","../test/unit/interceptor/HostFilter.spec.ts","../test/unit/interceptor/MitmProxyHost.spec.ts","../test/unit/interceptor/MockEngine.spec.ts","../test/unit/interceptor/RequestBuffer.spec.ts","../test/unit/interceptor/SessionArchive.spec.ts","../test/unit/lease/LeaseOrphanSweeper.spec.ts","../test/unit/lease/LeaseService.spec.ts","../test/unit/lease/allocate-lease-branch.spec.ts","../test/unit/lease/buildCapabilityBag.spec.ts","../test/unit/lease/lease-override.spec.ts","../test/unit/lease/lease-reap-held-phone.spec.ts","../test/unit/lease/lease-session-ownership.spec.ts","../test/unit/lease/lease-sweeper-expiry.spec.ts","../test/unit/lease/lease-team-visibility.spec.ts","../test/unit/lease/lease-token-log-filter.spec.ts","../test/unit/lease/lease-token-oracle.spec.ts","../test/unit/lease/leaseToken.spec.ts","../test/unit/lease/nodePairAuth.spec.ts","../test/unit/lease/session-lease-proof.spec.ts","../test/unit/ports/PortAllocatorService.spec.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenon-device-management/xenon",
3
- "version": "2.11.1",
3
+ "version": "2.12.0",
4
4
  "description": "Xenon - Intelligent Mobile Infrastructure. A self-healing device orchestration platform for Appium.",
5
5
  "main": "./lib/src/index.js",
6
6
  "exports": {
@@ -1,2 +0,0 @@
1
- import{r as d,j as r,z as $e,w as Me,X as D,v as Pe,e as Le,Y as Be,T as He,Z as We}from"./index-DklX18ye.js";import{p as Ve}from"./labels-C21SA4JG.js";import{C as ze}from"./circle-check-CGwn46BE.js";import{C as xe,M as Ue,A as ee,H as Fe,a as Ge,S as be,b as Ke,I as Ye,h as ve}from"./keycodes-B5mWBGMd.js";import{f as Xe,A as qe}from"./AnnotationOverlay-Dt5AmXCR.js";import{V as Je}from"./video-off-BJ_s_mLK.js";import{P as Ze}from"./plus-DOp8RUCs.js";import{a as Qe}from"./SegmentedControl-EBzIUjnM.js";import{v as et,a as tt,c as rt,s as nt,R as ot,b as st,g as at,d as le,e as it}from"./recordings-BWe1ydXm.js";import{D as oe}from"./download-CoBA2mT_.js";import{B as de}from"./button-B1XDl_TT.js";import{C as ct}from"./clock-BAD4KA9j.js";import{a as lt}from"./page-header-CV-WOQ7B.js";import"./utils-CDN07tui.js";function dt(e,t){return e!=="auto"?e:t<=1?"1":t===2?"2x1":t<=4?"2x2":"3x2"}const ut={selected:new Set,layout:"auto",tiles:[],groupId:null,compositeEnabled:!1,downloadableVideoCount:0,recordingPhase:"idle",recording:!1,startedAt:null,annotateMode:!1,shape:"RECT",color:"#ff3333",overlayAnnotations:{},errorBanner:null,banner:null};function ft(e,t){var n;switch(t.type){case"SET_LAYOUT":return{...e,layout:t.layout};case"TOGGLE_SELECTED":{const o=new Set(e.selected);return o.has(t.udid)?o.delete(t.udid):o.add(t.udid),{...e,selected:o}}case"CLEAR_SELECTED":return{...e,selected:new Set};case"SET_TILES":return{...e,tiles:t.tiles};case"ADD_TILE":return e.tiles.some(o=>o.udid===t.tile.udid)?e:{...e,tiles:[...e.tiles,t.tile]};case"PATCH_TILE_DIMS":{let o=!1;const i=e.tiles.map(g=>g.udid!==t.udid||g.screenWidth&&g.screenHeight?g:(o=!0,{...g,screenWidth:t.screenWidth,screenHeight:t.screenHeight,aspect:t.aspect??g.aspect}));return o?{...e,tiles:i}:e}case"REMOVE_TILE":return e.recordingPhase!=="idle"?e:{...e,tiles:e.tiles.filter(o=>o.udid!==t.udid)};case"BIND_RECORDING_IDS":{const o=e.tiles.map(i=>({...i,recordingId:t.map[i.udid]??i.recordingId}));return{...e,tiles:o}}case"SET_RECORDING_PHASE":{const o=t.phase;return{...e,recordingPhase:o,recording:o==="recording"||o==="stopping"}}case"START_RECORDING":{const o=e.tiles.map(i=>({...i,recordingId:t.tileIds[i.udid]??i.recordingId}));return{...e,groupId:t.groupId,compositeEnabled:t.compositeEnabled===!0,downloadableVideoCount:0,recordingPhase:"recording",recording:!0,annotateMode:!1,startedAt:t.startedAt,overlayAnnotations:{},tiles:o}}case"REHYDRATE_RECORDING":{const o=e.tiles.map(i=>({...i,recordingId:t.tileIds[i.udid]??i.recordingId}));return{...e,groupId:t.groupId,compositeEnabled:t.compositeEnabled,downloadableVideoCount:0,recordingPhase:"recording",recording:!0,annotateMode:!1,startedAt:t.startedAt,overlayAnnotations:t.overlayAnnotations,tiles:o}}case"STOP_RECORDING":{const o=e.tiles.map(i=>({...i,recordingId:void 0}));return{...e,recording:!1,recordingPhase:"idle",annotateMode:!1,overlayAnnotations:{},downloadableVideoCount:t.downloadableVideoCount??e.downloadableVideoCount,compositeEnabled:t.compositeEnabled!==void 0?t.compositeEnabled:e.compositeEnabled,tiles:o}}case"SET_ANNOTATE_MODE":return{...e,annotateMode:t.enabled};case"SET_SHAPE":return{...e,shape:t.shape};case"SET_COLOR":return{...e,color:t.color};case"SET_OVERLAY_ANNOTATIONS":return{...e,overlayAnnotations:{...e.overlayAnnotations,[t.recordingId]:t.annotations}};case"CLEAR_OVERLAY_ANNOTATIONS":return{...e,overlayAnnotations:{}};case"SET_ERROR_BANNER":return{...e,errorBanner:t.message,banner:t.message?{tone:"error",message:t.message}:null};case"SET_BANNER":return{...e,banner:t.banner,errorBanner:((n=t.banner)==null?void 0:n.tone)==="error"?t.banner.message:null};default:return e}}const ye=d.createContext(null);function ht(){const e=d.useContext(ye);if(!e)throw new Error("useMosaic must be used inside <MosaicContext.Provider>");return e}function pt(){return d.useReducer(ft,ut)}function mt(e){const t=Math.max(0,Math.floor(e/1e3)),n=Math.floor(t/3600),o=Math.floor(t%3600/60),i=t%60;return n>0?`${n}:${String(o).padStart(2,"0")}:${String(i).padStart(2,"0")}`:`${o}:${String(i).padStart(2,"0")}`}function gt(e){switch(e){case"automation":return"In automation";case"manual_other":return"Manual control by another user";case"manual_self":return"On your grid";case"recording_other_group":return"Recording in another group";default:return e?"Busy":null}}const ue=[{id:"ios",label:"iOS",match:e=>e==="ios"},{id:"android",label:"Android",match:e=>e==="android"},{id:"tvos",label:"tvOS",match:e=>e==="tvos"},{id:"androidtv",label:"Android TV",match:e=>e==="androidtv"||e==="android-tv"},{id:"other",label:"Other",match:()=>!0}],Y={available:"bg-[var(--color-success)]",inUse:"bg-[var(--color-warning)]",offline:"bg-[rgb(var(--rgb-offline))]"},xt=[["available",Y.available],["in use",Y.inUse],["offline",Y.offline]];function fe(e){return Ve(e)}function bt({devices:e,inMosaic:t,onToggle:n,status:o="ready"}){const[i,g]=d.useState(""),[u,N]=d.useState({}),p=d.useMemo(()=>{const l=i.trim().toLowerCase();return l?e.filter(v=>v.udid.toLowerCase().includes(l)||(v.name??"").toLowerCase().includes(l)||(v.altName??"").toLowerCase().includes(l)||(v.platform??"").toLowerCase().includes(l)):e},[e,i]),E=d.useMemo(()=>{const l=ue.map(f=>({id:f.id,label:f.label,rows:[]})),v=f=>l.find((j,y)=>ue[y].match(f))??l[l.length-1];for(const f of p)v((f.platform??"").toLowerCase()).rows.push(f);return l.filter(f=>f.rows.length>0)},[p]);if(e.length===0){const l=o==="loading"?"Loading devices…":o==="error"?"Couldn’t load devices. Retrying…":"No devices online.";return r.jsx("div",{role:"status",className:"text-xs text-[var(--text-dim)] p-3",children:l})}return r.jsxs("div",{className:"flex flex-col gap-2",children:[r.jsxs("div",{className:"relative",children:[r.jsx($e,{"aria-hidden":!0,size:12,className:"absolute left-2 top-1/2 -translate-y-1/2 text-[var(--text-dim)]"}),r.jsx("input",{type:"text",value:i,placeholder:"Filter devices...",onChange:l=>g(l.target.value),className:"w-full pl-7 pr-2 py-1.5 text-xs rounded border border-[var(--border)] bg-transparent placeholder:text-[var(--text-dim)] focus:outline-none focus:border-[var(--color-info)]"})]}),E.map(l=>{const v=u[l.id];return r.jsxs("section",{className:"flex flex-col gap-1",children:[r.jsxs("button",{type:"button","aria-expanded":!v,onClick:()=>N(f=>({...f,[l.id]:!f[l.id]})),className:"flex items-center justify-between w-full text-[11px] text-[var(--text-dim)] hover:text-[rgb(var(--rgb-fg))] px-1 py-0.5",children:[r.jsxs("span",{className:"flex items-center gap-1.5",children:[r.jsx(Me,{"aria-hidden":!0,size:12,className:`transition-transform ${v?"-rotate-90":"rotate-0"}`}),l.label]}),r.jsx("span",{children:l.rows.length})]}),!v&&r.jsx("ul",{className:"flex flex-col gap-1 text-sm",children:l.rows.map(f=>{const j=f.busyReason==="manual_self",y=t.has(f.udid),x=!!f.busy&&!j&&!y||!!f.offline,R=f.offline?"Offline":gt(f.busyReason),O=!x,T=[f.name??f.udid,f.platform&&fe(f.platform)].concat(x&&R?[R]:[]).filter(Boolean).join(", ");return r.jsx("li",{children:r.jsxs("button",{type:"button",disabled:x,draggable:!x,onDragStart:w=>{w.dataTransfer.effectAllowed="copy",w.dataTransfer.setData("application/x-xenon-udid",f.udid),w.dataTransfer.setData("text/plain",f.udid)},onClick:()=>n(f.udid),"aria-label":T,"aria-pressed":y,className:`w-full flex items-center gap-2 px-2 py-1.5 rounded text-left border transition-colors ${x?"opacity-60 cursor-not-allowed border-transparent":y?"border-[rgb(var(--rgb-accent)/0.4)] bg-[rgb(var(--rgb-accent)/0.05)] hover:bg-[rgb(var(--rgb-accent)/0.1)]":"border-transparent hover:border-[var(--border)] hover:bg-[var(--surface-2)]"}`,title:x?`${R} — release first`:y?"Click to remove from the grid":"Click to add to the grid (or drag to a cell)",children:[y?r.jsx(ze,{"aria-hidden":!0,size:14,className:"shrink-0 text-[var(--color-accent-soft)]"}):r.jsx(xe,{"aria-hidden":!0,size:14,className:"shrink-0 text-[var(--text-dim)]"}),r.jsx("span",{"aria-hidden":!0,className:`inline-block w-1.5 h-1.5 rounded-full ${f.offline?Y.offline:O?Y.available:Y.inUse}`}),r.jsx("span",{className:"font-medium flex-1 truncate text-[13px]",children:f.name??f.udid}),f.platform&&r.jsx("span",{className:"text-[11px] px-1.5 py-0.5 rounded bg-[var(--surface-2)] text-[var(--text-dim)]",children:fe(f.platform)})]})},f.udid)})})]},l.id)}),i&&E.length===0&&r.jsxs("div",{className:"text-xs text-[var(--text-dim)] px-1 py-2",children:['No devices match "',i,'".']}),r.jsx("div",{className:"text-[10px] text-[var(--text-dim)] px-1 pt-2 flex items-center gap-3",children:xt.map(([l,v])=>r.jsxs("span",{className:"inline-flex items-center gap-1",children:[r.jsx("span",{className:`w-1.5 h-1.5 rounded-full inline-block ${v}`}),l]},l))})]})}const vt=[{id:"1",label:"1",icon:r.jsx(wt,{})},{id:"2x1",label:"2×1",icon:r.jsx(Et,{})},{id:"2x2",label:"2×2",icon:r.jsx(Nt,{})},{id:"3x2",label:"3×2",icon:r.jsx(Rt,{})},{id:"auto",label:"Auto",icon:r.jsx(St,{})}];function yt({value:e,onChange:t}){return r.jsx("div",{role:"tablist",className:"inline-flex border border-[var(--border)] rounded-md overflow-hidden text-xs bg-[rgb(var(--rgb-white)/0.02)]",children:vt.map(n=>{const o=e===n.id;return r.jsxs("button",{role:"tab","aria-selected":o,onClick:()=>t(n.id),className:`flex items-center gap-1.5 px-2.5 py-1.5 border-r border-[var(--border)] last:border-r-0 transition-colors ${o?"bg-[var(--surface-2)] text-[rgb(var(--rgb-fg))]":"text-[var(--text-dim)] hover:bg-[var(--surface-2)] hover:text-[rgb(var(--rgb-fg))]"}`,title:`Layout: ${n.label}`,children:[r.jsx("span",{className:"w-3.5 h-3.5 inline-flex items-center justify-center",children:n.icon}),r.jsx("span",{children:n.label})]},n.id)})})}function B(e){return r.jsx("rect",{rx:1.2,ry:1.2,fill:"currentColor",...e})}function wt(){return r.jsx("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:B({x:2,y:2,width:10,height:10})})}function Et(){return r.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[B({x:1.5,y:3,width:5,height:8}),B({x:7.5,y:3,width:5,height:8})]})}function Nt(){return r.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[B({x:1.5,y:1.5,width:5,height:5}),B({x:7.5,y:1.5,width:5,height:5}),B({x:1.5,y:7.5,width:5,height:5}),B({x:7.5,y:7.5,width:5,height:5})]})}function Rt(){return r.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[B({x:1,y:1.5,width:3.3,height:5}),B({x:5.35,y:1.5,width:3.3,height:5}),B({x:9.7,y:1.5,width:3.3,height:5}),B({x:1,y:7.5,width:3.3,height:5}),B({x:5.35,y:7.5,width:3.3,height:5}),B({x:9.7,y:7.5,width:3.3,height:5})]})}function St(){return r.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",fill:"none",stroke:"currentColor",strokeWidth:"1.4",children:[r.jsx("rect",{x:"2",y:"2",width:"10",height:"10",rx:"1.5"}),r.jsx("circle",{cx:"7",cy:"7",r:"1.5",fill:"currentColor",stroke:"none"})]})}function jt(e,t,n,o,i,g,u=!1){const N=Xe(n.width,n.height,g);let p=(e-n.left-N.left)/N.width,E=(t-n.top-N.top)/N.height;return!(p>=0&&p<=1&&E>=0&&E<=1)&&!u?null:(p=Math.min(1,Math.max(0,p)),E=Math.min(1,Math.max(0,E)),{x:Math.round(p*o),y:Math.round(E*i)})}const Tt=5e3;function Ct(e,t){if(e.httpStatus===404)return{ended:!0,startedAt:t};if(e.httpStatus!==200)return{ended:!1,startedAt:t};const n=e.body??{};return n.status!=="running"?{ended:!0,startedAt:t}:t&&n.startedAt&&n.startedAt!==t?{ended:!0,startedAt:t}:{ended:!1,startedAt:t??n.startedAt}}function At(e,t,n,o=Tt){const i=d.useRef(n);i.current=n,d.useEffect(()=>{if(!t)return;let g=!1,u=!1,N;const p=async()=>{if(!(u||g)){u=!0;try{const l=await fetch(`/xenon/api/control/${encodeURIComponent(e)}/stream/status`),v=l.ok?await l.json().catch(()=>{}):void 0;if(g)return;const f=Ct({httpStatus:l.status,body:v},N);N=f.startedAt,f.ended&&(g=!0,i.current())}catch{}finally{u=!1}}};p();const E=setInterval(p,o);return()=>{g=!0,clearInterval(E)}},[e,t,o])}const Dt=3,It=45e3,he=[2e3,5e3,1e4];function _t(e){const t=Math.max(0,Math.min(e,he.length-1));return he[t]}function kt(e){return e<Dt}function pe(e){var n;const t=(e.lastError||"").toLowerCase();if(/did not find test app|not installed|webdriveragentrunner|applicationverification/.test(t))return"WebDriverAgent is not installed on this device. Install and trust WDA, then retry.";if(/unsupported ios version|manualpairingtunnelstart/.test(t))return"This device’s iOS version is not supported for live streaming on this host.";if(/port range for purpose 'tunnel' is exhausted/.test(t))return"No free tunnel ports on this host (12100–12199 are in use). Stop another iPhone’s preview, then retry.";if(/go-ios tunnel .* exited before it was ready/.test(t)){const o=(n=/exited before it was ready \([^)]*\): (.+)$/.exec(e.lastError||""))==null?void 0:n[1];return`The device tunnel stopped while starting${o?` (go-ios: ${o.trim()})`:""}. Retry; if it keeps failing, unlock the iPhone and check it trusts this Mac.`}return/go-ios tunnel .* came up on port/.test(t)?"The device tunnel started on an unexpected port and was stopped. Retry.":/econnrefused|econnreset|connection reset|tunnel/.test(t)?"Lost the connection to the device tunnel. Reconnect the device, then retry.":e.lastError&&e.lastError.trim()?e.lastError.trim():"We couldn’t start the live stream for this device."}function Ot(e){for(let t=0;t+4<e.length;t++){const n=e[t]===0&&e[t+1]===0&&e[t+2]===0&&e[t+3]===1,o=e[t]===0&&e[t+1]===0&&e[t+2]===1;if(!n&&!o)continue;const i=t+(n?4:3);if((e[i]&31)===7){const g=u=>u.toString(16).padStart(2,"0");return`avc1.${g(e[i+1])}${g(e[i+2])}${g(e[i+3])}`}}return"avc1.42e01e"}const $t=({wsUrl:e,onFatal:t,onReady:n,onFrameSize:o,className:i})=>{const g=d.useRef(null),u=d.useRef(t);u.current=t;const N=d.useRef(n);N.current=n;const p=d.useRef(o);return p.current=o,d.useEffect(()=>{var T;const E=window,l=g.current;if(typeof E.VideoDecoder>"u"||!l){(T=u.current)==null||T.call(u);return}const v=l.getContext("2d");let f=!1,j=!1,y=!0,x=0;const R=new E.VideoDecoder({output:w=>{var C,$;if(f){w.close();return}(l.width!==w.displayWidth||l.height!==w.displayHeight)&&(l.width=w.displayWidth,l.height=w.displayHeight,(C=p.current)==null||C.call(p,w.displayWidth,w.displayHeight)),v==null||v.drawImage(w,0,0),w.close(),y&&(y=!1,($=N.current)==null||$.call(N))},error:()=>{var w;return(w=u.current)==null?void 0:w.call(u)}}),O=new WebSocket(e);return O.binaryType="arraybuffer",O.onerror=()=>{var w;return(w=u.current)==null?void 0:w.call(u)},O.onclose=()=>{var w;f||(w=u.current)==null||w.call(u)},O.onmessage=w=>{var m;const C=w.data,$=new DataView(C).getUint8(0),V=new Uint8Array(C,1);if($===0){if(j)return;try{R.configure({codec:Ot(V),optimizeForLatency:!0}),j=!0}catch{(m=u.current)==null||m.call(u)}return}if(!(!j||R.state!=="configured"))try{R.decode(new E.EncodedVideoChunk({type:$===1?"key":"delta",timestamp:x,data:V})),x+=11111}catch{}},()=>{f=!0;try{O.close()}catch{}try{R.state!=="closed"&&R.close()}catch{}}},[e]),r.jsx("canvas",{ref:g,className:i,style:{width:"100%",height:"100%",objectFit:"contain",display:"block"}})};function Mt(e,t,n){return(e==="android"||e==="androidtv"||e==="android-tv")&&t==="h264"&&n?"h264":"mjpeg"}const Pt=10,Lt=500;function Bt({udid:e,name:t,recordingId:n,annotateMode:o,shape:i,color:g,aspect:u="9 / 16",screenWidth:N,screenHeight:p,platform:E,onAnnotation:l,overlayAnnotations:v,onOverlayAnnotationsChange:f,onRemove:j}){const[y,x]=d.useState("connecting"),[R,O]=d.useState(),T=d.useCallback((a,h)=>{if(!(a>0)||!(h>0))return;const _=a/h;O(k=>k!==void 0&&Math.abs(k-_)<.001?k:_)},[]),[w,C]=d.useState(0),[$,V]=d.useState(null),m=d.useRef(0),s=d.useRef(null),[c,b]=d.useState(""),[S,H]=d.useState([]),[U,M]=d.useState(!1),z=d.useRef(null),W=d.useRef(null),P=E==="android"||E==="androidtv"||E==="android-tv",A=E==="ios"||E==="tvos";d.useEffect(()=>{let a=!1;if(n){V(null),x("connecting"),C(Date.now()),D.startStream(e).catch(()=>{});return}const h=typeof window.VideoDecoder<"u";return(async()=>{try{const _=encodeURIComponent(e),k=await fetch(`/xenon/api/control/${_}/stream/status`);if(!k.ok)return;const I=await k.json();if(Mt(E||"",I==null?void 0:I.type,h)!=="h264"||!(I!=null&&I.h264Path))return;const G=await fetch(`/xenon/api/control/${_}/stream/ticket`,{method:"POST"});if(!G.ok)return;const{ticket:L}=await G.json();if(a||!L)return;const Z=`${window.location.protocol==="https:"?"wss":"ws"}://${window.location.host}${I.h264Path}?ticket=${encodeURIComponent(L)}`;V(Z)}catch{}})(),()=>{a=!0}},[e,E,n]);const F=!o&&!!N&&!!p,re=(a,h,_,k=!1)=>jt(a,h,_,N,p,R,k),Re=(a,h,_)=>{const k=Date.now()+Math.random(),I=a-_.left,G=h-_.top;H(L=>[...L,{id:k,x:I,y:G}]),window.setTimeout(()=>{H(L=>L.filter(q=>q.id!==k))},500)},Se=a=>{if(!F||y==="unavailable"||a.button!==0)return;const h=a.currentTarget;h.focus(),re(a.clientX,a.clientY,h.getBoundingClientRect())&&(h.setPointerCapture(a.pointerId),W.current={startX:a.clientX,startY:a.clientY,startTime:Date.now(),rect:h.getBoundingClientRect()},Re(a.clientX,a.clientY,W.current.rect))},je=async a=>{var Z,ce;const h=W.current;if(W.current=null,!h||!F)return;try{a.currentTarget.releasePointerCapture(a.pointerId)}catch{}const _=a.clientX-h.startX,k=a.clientY-h.startY,I=Math.hypot(_,k),G=Date.now()-h.startTime,L=re(h.startX,h.startY,h.rect,!0),q=I<Pt;try{if(q&&G<Lt)await D.tap(e,L.x,L.y);else if(q)await((ce=(Z=D).touchAndHold)==null?void 0:ce.call(Z,e,L.x,L.y,G));else{const Q=re(a.clientX,a.clientY,h.rect,!0);await D.swipe(e,L.x,L.y,Q.x,Q.y)}}catch(Q){console.error(`[DeviceTile] gesture failed for ${e}`,Q)}},Te=()=>{W.current=null},Ce=async a=>{if(!F||y==="unavailable"||a.metaKey||a.ctrlKey||a.altKey)return;const h=a.key;try{if(h.length===1){a.preventDefault(),await D.typeText(e,h);return}if(h==="Backspace"){a.preventDefault(),P?await D.pressKey(e,67):await D.typeText(e,"\b");return}if(h==="Enter"){a.preventDefault(),P?await D.pressKey(e,66):await D.typeText(e,`
2
- `);return}if(h==="Tab"){a.preventDefault(),await D.typeText(e," ");return}h==="Escape"&&P&&(a.preventDefault(),await D.pressKey(e,ee.BACK))}catch(_){console.error(`[DeviceTile] keystroke "${h}" failed for ${e}`,_)}},Ae=()=>D.pressKey(e,P?ee.HOME:Ye.HOME).catch(a=>console.error(`[DeviceTile] home failed for ${e}`,a)),De=()=>D.pressKey(e,ee.BACK).catch(a=>console.error(`[DeviceTile] back failed for ${e}`,a)),Ie=()=>D.pressKey(e,ee.APP_SWITCH).catch(a=>console.error(`[DeviceTile] app-switch failed for ${e}`,a)),_e=async()=>{try{const a=await D.getScreenshot(e),h=(a==null?void 0:a.screenshot)??(a==null?void 0:a.value)??a;if(!h)return;const _=await fetch(`data:image/png;base64,${h}`).then(G=>G.blob()),k=URL.createObjectURL(_),I=document.createElement("a");I.href=k,I.download=`${t||e}-${Date.now()}.png`,document.body.appendChild(I),I.click(),I.remove(),setTimeout(()=>URL.revokeObjectURL(k),1e3)}catch(a){console.error(`[DeviceTile] screenshot failed for ${e}`,a)}};d.useEffect(()=>{console.log(`[DeviceTile] Rendering ${e} in state: ${y}`)},[e,y]);const ke=`/xenon/api/control/${encodeURIComponent(e)}/stream?t=${w}`,ie=d.useCallback(async()=>{try{const a=await fetch(`/xenon/api/control/${encodeURIComponent(e)}/stream/status`);if(!a.ok)throw new Error(String(a.status));const h=await a.json();b(pe({lastError:h==null?void 0:h.lastError,status:h==null?void 0:h.status}))}catch{b(pe({}))}},[e]),ne=d.useCallback(()=>{const a=m.current;kt(a)?(m.current=a+1,s.current&&clearTimeout(s.current),s.current=setTimeout(()=>{x("connecting"),C(Date.now())},_t(a))):(x("unavailable"),ie())},[ie]);d.useEffect(()=>{if(y!=="connecting")return;const a=setTimeout(ne,It);return()=>clearTimeout(a)},[y,w,ne]),At(e,y==="live"&&!$,()=>{console.warn(`[DeviceTile] MJPEG stream ended for ${e}; reconnecting`),x("connecting"),C(Date.now())}),d.useEffect(()=>()=>{s.current&&clearTimeout(s.current)},[]);const Oe=()=>{s.current&&clearTimeout(s.current),m.current=0,b(""),x("connecting"),C(Date.now())},X=!!n,J=t||e.slice(0,16)+"…";return r.jsxs("div",{className:"flex items-stretch justify-center w-full h-full min-h-0 min-w-0 gap-2",children:[r.jsxs("div",{className:"theme-dark relative bg-[var(--black)] rounded-lg overflow-hidden border border-[var(--border)] group max-h-full max-w-full self-center",style:{aspectRatio:u,height:"100%"},children:[y==="connecting"&&r.jsxs("div",{role:"status","aria-live":"polite",className:"flex flex-col items-center justify-center gap-1 px-4 text-center bg-[rgb(var(--rgb-well)/0.8)] text-[var(--text-dim)] absolute inset-0 z-20 pointer-events-none",children:[r.jsx("div",{"aria-hidden":!0,className:"w-10 h-10 mb-3 border-4 border-[var(--border)] border-t-[var(--text-dim)] rounded-full animate-spin"}),r.jsx("div",{className:"font-semibold text-[var(--text)]",children:"Starting stream…"}),r.jsx("div",{className:"text-xs text-[var(--text-dim)] truncate max-w-full",children:J}),r.jsx("div",{className:"text-[11px] mt-3 text-[var(--text-dim)] leading-snug",children:A?"iPhone streams can take up to 20 seconds to start.":"Connecting to the device…"})]}),y==="unavailable"&&r.jsx("div",{role:"alert",className:"flex items-center justify-center bg-[var(--black)] text-[var(--text-dim)] absolute inset-0 z-20",children:r.jsxs("div",{className:"text-center p-6",children:[r.jsx(Je,{"aria-hidden":!0,size:36,className:"mx-auto mb-3 text-[var(--text-dim)]"}),r.jsx("div",{className:"font-semibold text-[var(--text)]",children:"Connection failed"}),r.jsx("p",{className:"text-xs mt-2 text-[var(--text-dim)] leading-relaxed max-w-[240px] mx-auto",children:c||"We couldn’t start the live stream for this device."}),r.jsx("button",{type:"button",className:"mt-5 text-sm font-semibold px-4 py-2 rounded bg-[var(--color-accent)] hover:bg-[var(--color-accent-strong)] text-[var(--color-on-accent)] transition-colors",onClick:Oe,children:"Retry"})]})}),$?r.jsx($t,{wsUrl:$,className:"absolute inset-0 w-full h-full object-contain bg-black select-none pointer-events-none",onReady:()=>x("live"),onFrameSize:T,onFatal:()=>{console.warn(`[DeviceTile] H.264 fatal for ${e}; falling back to MJPEG`),V(null),x("connecting"),C(Date.now())}}):r.jsx(Ue,{src:ke,alt:J,className:"absolute inset-0 w-full h-full object-contain bg-black select-none pointer-events-none",draggable:!1,style:{opacity:y==="live"?1:0,transition:"opacity 0.3s ease-in-out"},onLoad:a=>{console.log(`[DeviceTile] Image LOADED for ${e}`),T(a.currentTarget.naturalWidth,a.currentTarget.naturalHeight),m.current=0,s.current&&clearTimeout(s.current),x("live")},onError:a=>{console.error(`[DeviceTile] Image ERROR for ${e}`,a),ne()}},w),F&&y!=="unavailable"&&r.jsx("div",{ref:z,className:`absolute inset-0 z-[35] touch-none outline-none ${U?"ring-2 ring-[rgb(var(--rgb-accent)/0.6)] ring-inset rounded-lg":""}`,tabIndex:0,onPointerDown:Se,onPointerUp:je,onPointerCancel:Te,onKeyDown:Ce,onFocus:()=>M(!0),onBlur:()=>M(!1)}),r.jsx("div",{className:"absolute inset-0 z-20 pointer-events-none overflow-hidden",children:S.map(a=>r.jsx("span",{className:"absolute block w-10 h-10 rounded-full border-2 border-[var(--color-accent-soft)] animate-ping",style:{left:a.x-20,top:a.y-20}},a.id))}),X&&r.jsx(qe,{enabled:o,shape:i,color:g,committed:v,mediaAspect:R,onCommittedChange:f,onCommit:(a,h)=>l(n,a,h)}),X&&o&&y==="live"&&r.jsx("div",{className:"absolute top-3 left-14 right-3 z-30 flex justify-end pointer-events-none",children:r.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-[var(--color-info)] text-white text-[10px] font-semibold shadow-lg whitespace-nowrap overflow-hidden text-ellipsis",children:"Annotating · Esc to stop"})}),X&&r.jsx("div",{className:"absolute top-3 left-3 z-30 pointer-events-none",children:r.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-[var(--red-600)] text-white text-[9px] font-black shadow-lg",children:"REC"})}),r.jsxs("div",{className:"absolute top-3 left-3 z-30 flex flex-col gap-1.5 pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity duration-150",children:[y==="live"&&r.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-[var(--color-success)] text-[var(--color-on-success)] text-[11px] font-semibold shadow-lg w-fit",children:"Live"}),r.jsx("span",{className:"px-2 py-1 rounded bg-[rgb(var(--rgb-well)/0.8)] text-[var(--text)] text-[11px] font-medium backdrop-blur-md border border-[rgb(var(--rgb-fg)/0.1)] shadow-xl truncate max-w-[180px]",children:J})]})]}),r.jsx(Ht,{streamState:y,recording:X,isIOS:A,isAndroid:P,onClose:!X&&j?()=>j(e):void 0,sendHome:Ae,sendBack:De,sendAppSwitch:Ie,captureScreenshot:_e,displayName:J})]})}const te="w-7 h-7 flex items-center justify-center rounded-md hover:bg-[var(--surface-2)] hover:text-[var(--text)] transition-colors";function Ht({streamState:e,recording:t,isIOS:n,isAndroid:o,onClose:i,sendHome:g,sendBack:u,sendAppSwitch:N,captureScreenshot:p,displayName:E}){const l=e==="live";return!i&&!l?null:r.jsxs("div",{className:"self-stretch w-9 flex flex-col items-center justify-between gap-1 py-2 rounded-lg bg-[var(--surface)] border border-[var(--border)] text-[var(--text-dim)]",children:[r.jsx("div",{className:"flex flex-col items-center gap-1",children:i&&r.jsx("button",{type:"button","aria-label":`Remove ${E}`,title:"Remove from the grid",onClick:i,className:"w-7 h-7 flex items-center justify-center rounded-md hover:bg-[rgb(var(--rgb-red)/0.15)] hover:text-[var(--color-danger)] transition-colors",children:r.jsx(Pe,{"aria-hidden":!0,size:16})})}),l&&r.jsxs("div",{className:"flex flex-col items-center gap-1.5 my-auto",children:[(o||n)&&r.jsx("button",{type:"button","aria-label":"Home",title:"Home",onClick:g,className:te,children:r.jsx(Fe,{"aria-hidden":!0,size:15})}),o&&r.jsx("button",{type:"button","aria-label":"Back",title:"Back",onClick:u,className:te,children:r.jsx(Ge,{"aria-hidden":!0,size:16})}),o&&r.jsx("button",{type:"button","aria-label":"Recent apps",title:"Recent apps",onClick:N,className:te,children:r.jsx(be,{"aria-hidden":!0,size:13})})]}),l&&r.jsx("div",{className:"flex flex-col items-center gap-1",children:r.jsx("button",{type:"button","aria-label":"Screenshot",title:"Screenshot",onClick:p,className:te,children:r.jsx(Ke,{"aria-hidden":!0,size:15})})})]})}const Wt={1:"1fr","2x1":"1fr 1fr","2x2":"1fr 1fr","3x2":"1fr 1fr 1fr"},Vt={1:"1fr","2x1":"1fr","2x2":"1fr 1fr","3x2":"1fr 1fr"},zt={1:1,"2x1":2,"2x2":4,"3x2":6};function Ut({layout:e,tiles:t,annotateMode:n,shape:o,color:i,onAnnotation:g,overlayAnnotationsByRecording:u,onOverlayAnnotationsChange:N,onRemove:p,onDropDevice:E}){const l=dt(e,t.length),v=zt[l];t.length;const f=t.length,j=e==="auto"?Math.max(f,1):v,y=Math.max(0,j-f);return r.jsxs("div",{style:{display:"grid",gap:8,gridTemplateColumns:Wt[l],gridTemplateRows:Vt[l]},className:"h-full",children:[t.map(x=>r.jsx(Bt,{udid:x.udid,name:x.name,mjpegPort:x.mjpegPort,recordingId:x.recordingId,aspect:x.aspect,screenWidth:x.screenWidth,screenHeight:x.screenHeight,platform:x.platform,annotateMode:n,shape:o,color:i,overlayAnnotations:x.recordingId?u==null?void 0:u[x.recordingId]:void 0,onOverlayAnnotationsChange:x.recordingId&&N?R=>N(x.recordingId,R):void 0,onAnnotation:g,onRemove:p},x.udid)),Array.from({length:y},(x,R)=>r.jsx(Ft,{onDropDevice:E},`empty-${R}`))]})}function Ft({onDropDevice:e}){const[t,n]=d.useState(!1);return r.jsxs("div",{onDragOver:o=>{e&&(o.preventDefault(),o.dataTransfer.dropEffect="copy",t||n(!0))},onDragLeave:()=>n(!1),onDrop:o=>{if(n(!1),!e)return;o.preventDefault();const i=o.dataTransfer.getData("application/x-xenon-udid")||o.dataTransfer.getData("text/plain");i&&e(i)},className:`flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed transition-colors ${t?"border-[rgb(var(--rgb-accent)/0.6)] bg-[rgb(var(--rgb-accent)/0.05)]":"border-[var(--border)] bg-[rgb(var(--rgb-fg)/0.02)]"} text-[var(--text-dim)] min-h-[120px]`,children:[r.jsx("div",{"aria-hidden":"true",className:`w-8 h-8 rounded-full flex items-center justify-center ${t?"bg-[rgb(var(--rgb-accent)/0.15)] text-[var(--color-accent-soft)]":"bg-[rgb(var(--rgb-fg)/0.05)] text-[rgb(var(--rgb-fg)/0.6)]"}`,children:r.jsx(Ze,{size:16})}),r.jsx("div",{className:"text-xs font-medium",children:"Drag a device here"}),r.jsx("div",{className:"text-[10px] opacity-70",children:"or click one in the list"})]})}function Gt(e,t){return t==="starting"?"Starting…":e<=1?"Record":`Record ${e} devices`}const K={"aria-hidden":!0,size:14,className:"shrink-0"};function Kt({selectedUdids:e,onClearMarks:t}){const{state:n,dispatch:o}=ht(),[i,g]=d.useState(()=>Date.now());d.useEffect(()=>{if(n.recordingPhase!=="recording"&&n.recordingPhase!=="stopping")return;g(Date.now());const m=window.setInterval(()=>g(Date.now()),250);return()=>window.clearInterval(m)},[n.recordingPhase]);const u=n.startedAt&&(n.recordingPhase==="recording"||n.recordingPhase==="stopping")?i-n.startedAt:0,N=n.recordingPhase==="starting"||n.recordingPhase==="stopping",p=n.recordingPhase==="idle"&&e.length>0&&!N,E=n.recordingPhase==="recording"||n.recording&&n.tiles.some(m=>!!m.recordingId),l=E&&!N,v=l,f=v&&n.annotateMode,j=!!n.groupId&&n.recordingPhase==="idle",y=e.length>1||n.downloadableVideoCount>1,x=j&&n.compositeEnabled,R=j&&!n.compositeEnabled&&(n.downloadableVideoCount===1||n.downloadableVideoCount===0&&e.length<=1),O=async()=>{var m;if(p){o({type:"SET_RECORDING_PHASE",phase:"starting"}),o({type:"SET_BANNER",banner:null});try{const s=await nt(e);if(!((m=s.recordings)!=null&&m.length)){o({type:"SET_RECORDING_PHASE",phase:"idle"}),o({type:"SET_BANNER",banner:{tone:"error",message:"Recording did not start. Check that live preview is working, then try again."}});return}const c={};for(const S of s.recordings)c[S.udid]=S.id;const b=e.length-s.recordings.length;o({type:"START_RECORDING",groupId:s.groupId,startedAt:Date.now(),tileIds:c,compositeEnabled:s.compositeEnabled===!0}),b>0?o({type:"SET_BANNER",banner:{tone:"error",message:`Recording started on ${s.recordings.length} of ${e.length} devices (${b} failed).`}}):o({type:"SET_BANNER",banner:null})}catch(s){if(o({type:"SET_RECORDING_PHASE",phase:"idle"}),s instanceof ot)if(s.body.error==="device_busy"){const c=(s.body.busyDevices??[]).map(b=>`${b.udid} (${b.reason})`).join(", ");o({type:"SET_BANNER",banner:{tone:"error",message:`Cannot start — these devices are busy: ${c}`}})}else o({type:"SET_BANNER",banner:{tone:"error",message:`Server-wide recording cap reached (${s.body.active}/${s.body.limit}).`}});else o({type:"SET_BANNER",banner:{tone:"error",message:`Recording failed: ${s.message}`}})}}},T=async()=>{if(!(!n.groupId||n.recordingPhase!=="recording")){o({type:"SET_RECORDING_PHASE",phase:"stopping"});try{const m=await st(n.groupId),s=(m.recordings??[]).filter(b=>b.status==="STOPPED"&&(b.sizeBytes??0)>=1024),c=(m.recordings??[]).filter(b=>b.status!=="STOPPED");o({type:"STOP_RECORDING",downloadableVideoCount:s.length,compositeEnabled:n.compositeEnabled}),s.length===0?o({type:"SET_BANNER",banner:{tone:"error",message:c.length>0?`Recording failed on ${c.length} device(s). Nothing to download.`:"Recording stopped but no playable video was produced."}}):c.length>0?o({type:"SET_BANNER",banner:{tone:"info",message:`${s.length} ready, ${c.length} failed. Download with the button above.`}}):o({type:"SET_BANNER",banner:{tone:"info",message:s.length===1?"Video ready. Download it with the button above.":`${s.length} videos ready. Download them with the button above.`}})}catch(m){o({type:"STOP_RECORDING"}),o({type:"SET_BANNER",banner:{tone:"error",message:`Stop failed: ${m.message}`}})}}},w=m=>{const s=m==="annotate";s&&!v||s!==n.annotateMode&&o({type:"SET_ANNOTATE_MODE",enabled:s})};d.useEffect(()=>{if(!n.annotateMode)return;const m=s=>{var b;if(s.key!=="Escape"||s.repeat)return;const c=s.target;c&&((b=c.closest)!=null&&b.call(c,"input, textarea, select")||c.isContentEditable)||o({type:"SET_ANNOTATE_MODE",enabled:!1})};return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[n.annotateMode,o]);const C=()=>{v&&t()},$=Object.values(n.overlayAnnotations).some(m=>((m==null?void 0:m.length)??0)>0),V=[{id:"RECT",label:"Rect"},{id:"CIRCLE",label:"Circle"},{id:"ARROW",label:"Arrow"},{id:"FREEHAND",label:"Draw"}];return r.jsxs("div",{className:"flex items-center gap-2 flex-wrap justify-end",children:[n.recordingPhase==="recording"||n.recordingPhase==="stopping"?r.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2 py-1 rounded text-xs font-mono tabular-nums bg-[rgb(var(--rgb-red-600)/0.2)] text-[var(--red-200)] border border-[rgb(var(--rgb-red)/0.4)]",title:"Recording elapsed time",children:[r.jsx("span",{className:"inline-block w-1.5 h-1.5 rounded-full bg-[var(--red)] animate-pulse"}),"REC ",mt(u),n.recordingPhase==="stopping"?" · Stopping…":""]}):r.jsxs("button",{type:"button",onClick:O,disabled:!p,title:e.length===0?"Add a device to the grid first":"Record every device on the grid",className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded bg-[var(--red-600)] text-white disabled:opacity-40 disabled:cursor-not-allowed light:disabled:bg-transparent light:disabled:text-[var(--text)] light:disabled:ring-1 light:disabled:ring-inset light:disabled:ring-[color:var(--border)]",children:[r.jsx(xe,{...K,size:10,fill:"currentColor"}),Gt(e.length,n.recordingPhase)]}),r.jsxs("button",{type:"button",onClick:T,disabled:!l,className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] disabled:opacity-40 disabled:cursor-not-allowed",children:[r.jsx(be,{...K,size:12}),n.recordingPhase==="stopping"?"Stopping…":"Stop"]}),r.jsx(Qe,{size:"sm",value:n.annotateMode?"annotate":"interact",onChange:w,segments:[{value:"interact",label:"Interact",title:"Tap, swipe and type on the devices (Esc)",keyShortcuts:"Escape"},{value:"annotate",label:"Annotate",title:v?"Draw marks on the recording":"Start recording to annotate",disabled:!v}]}),E&&r.jsxs("div",{className:"flex items-center gap-1 ml-1 pl-2 border-l border-[var(--border)]",children:[V.map(m=>r.jsx("button",{type:"button",disabled:!f,"aria-pressed":n.shape===m.id,onClick:()=>o({type:"SET_SHAPE",shape:m.id}),className:`px-2 py-1 text-xs rounded border disabled:opacity-40 disabled:cursor-not-allowed ${n.shape===m.id?"bg-[var(--surface-2)] border-[var(--color-info)] text-[rgb(var(--rgb-fg))]":"border-[var(--border)] opacity-80 hover:opacity-100"}`,children:m.label},m.id)),r.jsx("input",{type:"color",value:n.color,disabled:!f,onChange:m=>o({type:"SET_COLOR",color:m.target.value}),title:"Annotation color","aria-label":"Annotation color",className:"w-7 h-7 rounded border border-[var(--border)] bg-transparent cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed"}),r.jsx("button",{type:"button",onClick:C,disabled:!v||!$,title:"Clear marks from the preview and the recording",className:"px-2 py-1 text-xs rounded border border-[var(--border)] hover:bg-[var(--surface-2)] disabled:opacity-40 disabled:cursor-not-allowed",children:"Clear marks"})]}),j&&R&&r.jsxs("a",{href:et(n.groupId),className:"ml-1 inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",download:!0,children:[r.jsx(oe,{...K}),"Download video"]}),j&&!R&&r.jsxs("a",{href:tt(n.groupId),className:"ml-1 inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",download:`videos-${n.groupId}.zip`,title:"ZIP of mp4 files only (no JSON extras)",children:[r.jsx(oe,{...K}),"Download ",y?"videos":"video"]}),x&&r.jsxs("a",{href:rt(n.groupId),className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",download:`side-by-side-${n.groupId}.mp4`,title:"All devices in one side-by-side video",children:[r.jsx(oe,{...K}),"Side-by-side"]}),j&&n.groupId&&r.jsxs(Le,{to:`/recordings/${encodeURIComponent(n.groupId)}`,className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",children:[r.jsx(Be,{...K}),"Open in Recordings"]})]})}function Yt({remainingSec:e,onContinue:t,onReleaseNow:n}){return r.jsx("div",{role:"dialog","aria-modal":"true","aria-labelledby":"idle-warning-title",className:"fixed inset-0 z-40 bg-black/60 flex items-center justify-center",children:r.jsxs("div",{className:"bg-[var(--bg)] border border-[var(--border)] rounded-lg w-full max-w-md p-6",children:[r.jsx("h3",{id:"idle-warning-title",className:"text-base font-semibold mb-2",children:"Are you still there?"}),r.jsxs("p",{className:"text-sm text-[var(--text-dim)] mb-4",children:["Your devices will be released in"," ",r.jsxs("span",{className:"text-[var(--text)] font-mono font-semibold",children:[e,"s"]})," due to inactivity. Click ",r.jsx("strong",{children:"Continue Session"})," to keep them locked."]}),r.jsxs("div",{className:"flex justify-end gap-2",children:[r.jsx("button",{type:"button",onClick:n,className:"h-9 px-3 rounded-md border border-[var(--border)] text-sm text-[var(--text-dim)] hover:text-[var(--text)]",children:"Release now"}),r.jsx("button",{type:"button",autoFocus:!0,onClick:t,className:"h-9 px-4 rounded-md bg-[var(--color-accent)] text-[var(--color-on-accent)] text-sm font-medium",children:"Continue session"})]})]})})}function Xt({message:e,onRestore:t,onDismiss:n}){return r.jsxs("div",{role:"status",className:"text-sm rounded border border-[var(--border)] bg-[var(--surface-2)] text-[var(--text)] px-3 py-2 flex items-center gap-2",children:[r.jsx(ct,{"aria-hidden":!0,size:14,className:"shrink-0 text-[var(--text-dim)]"}),r.jsx("span",{className:"flex-1",children:e}),t&&r.jsx(de,{variant:"tonal",size:"sm",onClick:t,children:"Restore devices"}),r.jsx(de,{variant:"ghost",size:"sm",onClick:n,children:"Dismiss"})]})}function we(e){var t;return((t=e.marketingName)==null?void 0:t.trim())||e.name||e.udid}function Ee(e){if(!e)return"9 / 16";const t=Number(e.screenWidth),n=Number(e.screenHeight);if(Number.isFinite(t)&&Number.isFinite(n)&&t>0&&n>0)return`${t} / ${n}`;const o=(e.platform||"").toLowerCase();return o==="tvos"||o==="androidtv"||o==="android-tv"?"16 / 9":"9 / 16"}function se(e){const t=Number(e.screenWidth),n=Number(e.screenHeight);return{udid:e.udid,name:we(e),mjpegPort:0,aspect:Ee(e),screenWidth:Number.isFinite(t)&&t>0?t:void 0,screenHeight:Number.isFinite(n)&&n>0?n:void 0,platform:e.platform}}function qt(e,t){return t?"blocked":e?"remove":"add"}function ae(e,t,n){return!n||!e?!1:e===`manual_${n}_${t}`}function Jt(e,t){if(!e.busy)return;const n=ve(e);return n?n.startsWith("manual_")?ae(n,e.udid,t)?"manual_self":"manual_other":"automation":"unknown"}function Zt(e,t){return e.busy?ae(ve(e),e.udid,t):!1}function Qt(e,t){return e>0&&t==="idle"}function er(e,t,n){const o=[],i=[];for(const g of e){const u=t.find(p=>p.udid===g.udid),N=(u==null?void 0:u.name)||g.name||g.udid;u?u.offline?i.push({name:N,reason:"offline"}):u.busy&&!ae(u.session_id,u.udid,n)?i.push({name:N,reason:"in_use"}):o.push(u):i.push({name:N,reason:"gone"})}return{restore:o,skipped:i}}const Ne=(e,t)=>`${e} ${t}${e===1?"":"s"}`;function tr(e,t){return`Released ${Ne(e,"device")} after ${t} minutes without activity.`}const rr={in_use:"is now in use by someone else.",offline:"is offline.",gone:"is no longer connected."};function nr(e,t){return t.length===0?null:[e>0?`Restored ${Ne(e,"device")}.`:"No devices restored.",...t.map(o=>`${o.name} ${rr[o.reason]}`)].join(" ")}function or(){let e=Promise.resolve();return{enqueue(t){const n=e.then(t,t);return e=n.then(()=>{},()=>{}),n}}}const me=["mousemove","mousedown","keydown","touchstart","wheel"];function sr({idleAfterMs:e,warningSec:t,onWarning:n,onTimeout:o,enabled:i}){const[g,u]=d.useState(!1),[N,p]=d.useState(null),E=d.useRef(null),l=d.useRef(null),v=d.useRef(!1),f=d.useRef(n),j=d.useRef(o);f.current=n,j.current=o;function y(){E.current&&(clearTimeout(E.current),E.current=null),l.current&&(clearInterval(l.current),l.current=null)}function x(){v.current=!0,u(!0),p(t),f.current(t);let T=t;l.current=setInterval(()=>{T-=1,T<=0?(y(),v.current=!1,u(!1),p(null),j.current()):p(T)},1e3)}function R(){y(),v.current=!1,u(!1),p(null);const T=e-t*1e3;E.current=setTimeout(x,Math.max(0,T))}function O(){i&&R()}return d.useEffect(()=>{if(!i){y(),v.current=!1,u(!1),p(null);return}function T(){v.current||R()}return me.forEach(w=>window.addEventListener(w,T,{passive:!0})),R(),()=>{me.forEach(w=>window.removeEventListener(w,T)),y()}},[i,e,t]),{warning:g,remainingSec:N,reset:O}}const ge=5*60*1e3,ar=30;function ir(e,t){return{udid:e.udid,name:we(e),altName:e.name,platform:e.platform,busy:e.busy,busyReason:Jt(e,t),mjpegServerPort:e.mjpegServerPort,offline:!!e.offline}}function Er(){const[e,t]=pt(),[n,o]=d.useState([]),[i,g]=d.useState("loading"),[u,N]=d.useState(0),[p,E]=d.useState(null),l=d.useRef(!1),v=d.useRef(or());d.useEffect(()=>{let s=!1;return fetch("/xenon/api/auth/me",{credentials:"include"}).then(c=>c.ok?c.json():null).then(c=>{!s&&(c!=null&&c.userId)&&E(c.userId)}).catch(()=>{}),()=>{s=!0}},[]),d.useEffect(()=>{let s=!1;const c=async()=>{try{const S=await D.getDevices();if(s)return;o(Array.isArray(S)?S:[]),g("ready")}catch{s||g("error")}};c();const b=window.setInterval(c,5e3);return()=>{s=!0,window.clearInterval(b)}},[u]),d.useEffect(()=>{let s=!1;if(!(!p||l.current))return l.current=!0,(async()=>{var S;let c=[],b=[];try{const H=await D.getDevices();c=Array.isArray(H)?H:[];const U=c.filter(z=>Zt(z,p));if(b=(await Promise.all(U.map(async z=>{try{const W=await fetch(`/xenon/api/control/${encodeURIComponent(z.udid)}/stream/status`);if(!W.ok)return null;const P=await W.json();return(P==null?void 0:P.status)==="running"?z:null}catch{return null}}))).filter(z=>z!==null).map(se),s)return;b.length>0&&t({type:"SET_TILES",tiles:b})}catch{}try{const{serverNow:H,groups:U}=await at(),M=U[0];if(s||!M)return;const z=new Set(b.map(A=>A.udid)),W=M.recordings.filter(A=>!z.has(A.udid)).map(A=>c.find(F=>F.udid===A.udid)).filter(A=>!!A).map(se);W.length>0&&t({type:"SET_TILES",tiles:[...b,...W]});const P={};for(const A of M.annotations){let F;try{F=JSON.parse(A.geometry)}catch{continue}(P[S=A.recordingId]??(P[S]=[])).push({shape:A.shape,color:A.color,geometry:F,text:A.text??void 0})}t({type:"REHYDRATE_RECORDING",groupId:M.groupId,startedAt:Date.now()-(H-Date.parse(M.startedAt)),tileIds:Object.fromEntries(M.recordings.map(A=>[A.udid,A.id])),compositeEnabled:M.compositeEnabled,overlayAnnotations:P})}catch{}})(),()=>{s=!0}},[p,t]),d.useEffect(()=>{for(const s of e.tiles){if(s.screenWidth&&s.screenHeight)continue;const c=n.find(H=>H.udid===s.udid);if(!c)continue;const b=Number(c.screenWidth),S=Number(c.screenHeight);Number.isFinite(b)&&b>0&&Number.isFinite(S)&&S>0&&t({type:"PATCH_TILE_DIMS",udid:s.udid,screenWidth:b,screenHeight:S,aspect:Ee(c)})}},[n,e.tiles,t]);const f=d.useMemo(()=>new Set(e.tiles.map(s=>s.udid)),[e.tiles]),j=d.useMemo(()=>n.map(s=>ir(s,p)),[n,p]),y=async s=>{t({type:"ADD_TILE",tile:se(s)});const c=await D.startStream(s.udid).catch(()=>null);We(c)&&t({type:"REMOVE_TILE",udid:s.udid})},x=async s=>{const c=qt(e.tiles.some(S=>S.udid===s),e.recording);if(c==="blocked"){t({type:"SET_ERROR_BANNER",message:"Stop recording before changing the devices on the grid."});return}if(c==="remove"){await R(s);return}const b=n.find(S=>S.udid===s);b&&await y(b)},R=async s=>{t({type:"REMOVE_TILE",udid:s});try{await fetch(`/xenon/api/control/${encodeURIComponent(s)}/stream/leave`,{method:"POST"})}catch{}N(c=>c+1)},O=(s,c,b)=>{if(!e.groupId)return;const S=e.groupId,H=e.startedAt?Date.now()-e.startedAt:0,U={recordingId:s,timecodeMs:H,shape:c.shape,geometry:JSON.stringify(c.geometry),color:c.color,text:c.text};v.current.enqueue(async()=>{try{return await le(S,b?{...U,image:b}:U)}catch(M){if(!b)throw M;return le(S,U)}}).catch(M=>t({type:"SET_ERROR_BANNER",message:`Annotation failed: ${M.message}`}))},T=()=>{if(!e.groupId)return;const s=e.groupId,c=e.startedAt?Date.now()-e.startedAt:0;t({type:"CLEAR_OVERLAY_ANNOTATIONS"}),v.current.enqueue(()=>it(s,c)).catch(()=>t({type:"SET_ERROR_BANNER",message:"Couldn't clear marks from the recording. They will still appear in the video."}))},w=()=>{for(const s of e.tiles){const c=`/xenon/api/control/${encodeURIComponent(s.udid)}/stream/leave`;try{navigator.sendBeacon?navigator.sendBeacon(c):fetch(c,{method:"POST",keepalive:!0}).catch(()=>{})}catch{}}e.tiles.forEach(s=>t({type:"REMOVE_TILE",udid:s.udid}))},[C,$]=d.useState(null),V=async()=>{const s=C==null?void 0:C.tiles;if(!s)return;const c=er(s,n,p);for(const S of c.restore)await y(S);const b=nr(c.restore.length,c.skipped);$(b?{message:b,tiles:null}:null),N(S=>S+1)},m=sr({idleAfterMs:ge,warningSec:ar,enabled:Qt(e.tiles.length,e.recordingPhase),onWarning:()=>{},onTimeout:()=>{const s=e.tiles;w(),$({message:tr(s.length,ge/6e4),tiles:s})}});return r.jsxs(ye.Provider,{value:{state:e,dispatch:t},children:[r.jsxs("div",{className:"flex flex-col h-full p-4 gap-3",children:[r.jsxs("header",{className:"flex items-center justify-between gap-3",children:[r.jsxs("div",{className:"flex items-center gap-3",children:[r.jsx(lt,{icon:He,children:"Live devices"}),r.jsx(yt,{value:e.layout,onChange:s=>t({type:"SET_LAYOUT",layout:s})})]}),r.jsx(Kt,{selectedUdids:e.tiles.map(s=>s.udid),onClearMarks:T})]}),e.banner&&r.jsxs("div",{role:"alert",className:`text-sm rounded border px-3 py-2 flex items-center gap-2 ${e.banner.tone==="error"?"border-[rgb(var(--rgb-red)/0.4)] bg-[rgb(var(--rgb-red)/0.1)] text-[var(--red-100)]":"border-[rgb(var(--rgb-success)/0.4)] bg-[rgb(var(--rgb-success)/0.1)] text-[var(--text)]"}`,children:[r.jsx("span",{className:"flex-1",children:e.banner.message}),r.jsx("button",{type:"button",className:"text-xs opacity-80 hover:opacity-100",onClick:()=>t({type:"SET_BANNER",banner:null}),children:"Dismiss"})]}),C&&r.jsx(Xt,{message:C.message,onRestore:C.tiles&&!e.recording?V:void 0,onDismiss:()=>$(null)}),r.jsxs("div",{className:"grid grid-cols-[260px_1fr] gap-3 flex-1 min-h-0",children:[r.jsxs("aside",{className:"flex flex-col gap-2 border border-[var(--border)] rounded p-3 overflow-y-auto min-h-0",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{className:"text-xs text-[var(--text-dim)]",children:"Devices"}),r.jsx("button",{className:"text-xs underline opacity-70 hover:opacity-100",onClick:()=>N(s=>s+1),children:"Refresh"})]}),r.jsx(bt,{devices:j,inMosaic:f,onToggle:x,status:i}),r.jsx("p",{className:"mt-2 text-[11px] text-[var(--text-dim)] leading-relaxed",children:"Click a device to add it to the grid. Record captures every device on the grid; after Stop, download the video."})]}),r.jsx("main",{className:"border border-[var(--border)] rounded p-2 overflow-y-auto h-full min-h-0",children:r.jsx(Ut,{layout:e.layout,tiles:e.tiles,annotateMode:e.annotateMode,shape:e.shape,color:e.color,overlayAnnotationsByRecording:e.overlayAnnotations,onOverlayAnnotationsChange:(s,c)=>t({type:"SET_OVERLAY_ANNOTATIONS",recordingId:s,annotations:c}),onAnnotation:O,onRemove:R,onDropDevice:x})})]})]}),m.warning&&m.remainingSec!==null&&r.jsx(Yt,{remainingSec:m.remainingSec,onContinue:m.reset,onReleaseNow:w})]})}export{Er as default};
@@ -1,11 +0,0 @@
1
- import{c as q,r as c,i as Q,u as X,b as ee,t as te,j as e,e as B,A as ne,Y as re}from"./index-DklX18ye.js";import{f as Z,a as se,c as ae,h as ie,i as G,j as oe,k as ce,m as le}from"./recordings-BWe1ydXm.js";import{P as ue}from"./page-header-CV-WOQ7B.js";import{B as C}from"./button-B1XDl_TT.js";import{E as $}from"./EmptyState-DyojFa86.js";import{M as de}from"./Modal-BdWYrwfK.js";import{P as fe,M as me,a as ge}from"./Menu-DFNsTx2i.js";import{A as pe}from"./AnnotationOverlay-Dt5AmXCR.js";import{t as O,v as he,R as ye,P as be,n as ke,c as z,o as ve,a as R,f as xe,p as je,S as V,b as Me,d as we}from"./recordings-n-GTW3aT.js";import{A as Re}from"./arrow-left-CIqcStpJ.js";import{T as Ne}from"./trash-2-DMkIlO0b.js";import{D as Se}from"./download-CoBA2mT_.js";import"./utils-CDN07tui.js";import"./index-BHI_dBXi.js";import"./check-DjbzNVbd.js";/**
2
- * @license lucide-react v0.555.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const Ee=[["rect",{x:"14",y:"3",width:"5",height:"18",rx:"1",key:"kaeet6"}],["rect",{x:"5",y:"3",width:"5",height:"18",rx:"1",key:"1wsw3u"}]],Ie=q("pause",Ee);/**
7
- * @license lucide-react v0.555.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */const Ce=[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]],De=q("play",Ce);function Ae(n){const t=[{key:"zip",label:"All videos (zip)",url:se(n.groupId)}];return n.hasComposite&&t.push({key:"composite",label:"Side-by-side video",url:ae(n.groupId)}),t.push({key:"bundle",label:"Proof bundle",url:ie(n.groupId)}),n.phones.filter(l=>l.status!=="FAILED"&&l.status!=="DISCARDED").forEach(l=>{t.push({key:`video-${l.recordingId}`,label:`${l.name}: video`,url:G(n.groupId,l.recordingId,!0)}),l.annotationCount>0&&t.push({key:`annotated-${l.recordingId}`,label:`${l.name}: video with annotations`,url:oe(n.groupId,l.recordingId)})}),t}function Te(n,t){return t?t.role==="ADMIN"||t.role==="SUPER_ADMIN"?!0:!!n.startedBy&&!!t.userId&&n.startedBy.id===t.userId:!1}function _e(n){if(n instanceof Z){if(n.code==="not_owner")return"Only the person who recorded it, or an admin, can delete it.";if(n.code==="recording_in_progress")return"It’s still recording. Stop it on Live devices first.";if(n.status===404)return"It was already deleted, or it’s on phones you can’t see."}return`Couldn’t delete the recording: ${n instanceof Error?n.message:String(n)}`}function Pe(n){const t=document.createElement("a");t.href=n,t.download="",document.body.appendChild(t),t.click(),document.body.removeChild(t)}const Le={now:()=>performance.now(),schedule:n=>window.requestAnimationFrame(()=>n()),cancel:n=>window.cancelAnimationFrame(n)},$e=100,Fe=3,Be=.05;function Y(n){return n.ended||Number.isFinite(n.duration)&&n.currentTime>=n.duration-Be}function Oe(n,t=Le){const l=c.useRef(new Map),k=c.useRef(new Map),u=c.useRef(new Map),d=c.useRef({baseMs:0,since:null,running:!1,waiting:!1}),p=c.useRef(null),N=c.useRef(-1/0),v=c.useRef(n);v.current=n;const[D,w]=c.useState({timeMs:0,playing:!1,waiting:!1}),x=()=>d.current.since===null?d.current.baseMs:d.current.baseMs+(t.now()-d.current.since),h=(s,a)=>{l.current.forEach((i,M)=>{var P;const m=k.current.get(M);if(!m||i.error)return;const T=O(s,m.offsetMs,m.durationMs);let I=T==="before"?0:T==="after"?m.durationMs:he(s,m.offsetMs);Number.isFinite(i.duration)&&(I=Math.min(I,i.duration*1e3));const F=d.current.running?ye:be;ke(i.currentTime*1e3,I,F)&&(i.currentTime=I/1e3),a&&T==="playing"?i.paused&&!Y(i)&&((P=i.play())==null||P.catch(()=>{})):i.paused||i.pause()})},j=s=>Array.from(l.current.entries()).some(([a,i])=>{const M=k.current.get(a);return!!M&&!i.error&&!Y(i)&&O(s,M.offsetMs,M.durationMs)==="playing"&&i.readyState<Fe}),g=s=>{const a=t.now();!s&&a-N.current<$e||(N.current=a,w({timeMs:x(),playing:d.current.running,waiting:d.current.waiting}))},y=()=>{p.current!==null&&t.cancel(p.current),p.current=null},A=()=>{p.current=null;const s=d.current;if(!s.running)return;const a=x();if(a>=v.current){Object.assign(s,{baseMs:v.current,since:null,running:!1,waiting:!1}),h(v.current,!1),g(!0);return}const i=j(a);i!==s.waiting?(s.baseMs=a,s.since=i?null:t.now(),s.waiting=i,h(a,!i),g(!0)):(h(a,!i),g(!1)),p.current=t.schedule(A)},S=()=>{const s=d.current;x()>=v.current?s.baseMs=0:s.baseMs=x(),Object.assign(s,{since:t.now(),running:!0,waiting:!1}),h(s.baseMs,!0),g(!0),y(),p.current=t.schedule(A)},b=()=>{const s=d.current;Object.assign(s,{baseMs:x(),since:null,running:!1,waiting:!1}),y(),h(s.baseMs,!1),g(!0)},f=s=>{const a=d.current,i=z(s,v.current);a.baseMs=i,a.since=a.running&&!a.waiting?t.now():null,h(i,a.running&&!a.waiting),g(!0)},_=c.useCallback((s,a)=>{k.current.set(s,a);let i=u.current.get(s);return i||(i=M=>{if(M){l.current.set(s,M);const m=d.current;h(x(),m.running&&!m.waiting)}else l.current.delete(s)},u.current.set(s,i)),i},[]);return c.useEffect(()=>y,[]),{...D,play:S,pause:b,toggle:()=>d.current.running?b():S(),seek:f,bind:_}}const ze=()=>{},W="Stop the recording on Live devices first.",Ue=1e3;function Ke(n){const t=n;return!t||!t.closest?!1:!!t.closest('input:not([type="range"]):not([type="checkbox"]), select, textarea, [contenteditable="true"], [role="dialog"], [role="menu"]')}function He({groupId:n,phone:t,timeMs:l,marks:k,showMarks:u,bind:d}){const[p,N]=c.useState(!1),[v,D]=c.useState(void 0),w=t.status==="FAILED"||t.status==="DISCARDED",x=O(l,t.offsetMs,t.durationMs),h=Me(k,l).map(we).filter(g=>g!==null);let j=null;return w?j=`Recording failed: ${t.failReason??"unknown reason"}`:p?j="Video no longer available":x==="before"&&t.offsetMs>=Ue&&(j=`Starts at ${R(t.offsetMs)}`),e.jsxs("figure",{className:"rec-tile theme-dark","aria-label":t.name,children:[e.jsx("figcaption",{className:"rec-tile-name",title:t.name,children:t.name}),e.jsxs("div",{className:"rec-tile-screen",children:[!w&&e.jsx("video",{className:"rec-tile-video",muted:!0,playsInline:!0,preload:"auto",src:G(n,t.recordingId),ref:d(t.recordingId,{offsetMs:t.offsetMs,durationMs:t.durationMs}),onError:()=>N(!0),onLoadedMetadata:g=>{const y=g.currentTarget;y.videoWidth>0&&y.videoHeight>0&&D(y.videoWidth/y.videoHeight)}}),!w&&u&&e.jsx(pe,{enabled:!1,shape:"RECT",color:"currentColor",onCommit:ze,committed:h,mediaAspect:v}),j&&e.jsx("div",{className:"rec-tile-note",children:j})]})]})}function Ve({detail:n}){const[t,l]=c.useState(!1),k=c.useRef(null);return e.jsxs(e.Fragment,{children:[e.jsxs(C,{ref:k,variant:"secondary","aria-haspopup":"menu","aria-expanded":t,onClick:()=>l(u=>!u),children:[e.jsx(Se,{size:14,"aria-hidden":"true"}),"Download"]}),e.jsx(fe,{open:t,onClose:()=>l(!1),anchorRef:k,children:e.jsx(me,{children:Ae(n.summary).map(u=>e.jsx(ge,{onClick:()=>{l(!1),Pe(u.url)},children:u.label},u.key))})})]})}function ot(){var K;const{groupId:n=""}=Q(),t=X(),{me:l}=ee(),{toast:k}=te(),[u,d]=c.useState(null),[p,N]=c.useState(null),[v,D]=c.useState(0),[w,x]=c.useState(!0),[h,j]=c.useState(!1),[g,y]=c.useState(!1),[A,S]=c.useState(null);c.useEffect(()=>{let r=!0;return N(null),d(null),ce(n).then(o=>r&&d(ve(o))).catch(o=>{r&&N({missing:o instanceof Z&&o.status===404,message:o instanceof Error?o.message:String(o)})}),()=>{r=!1}},[n,v]);const b=(u==null?void 0:u.summary.durationMs)??0,f=Oe(b),_=c.useRef(f);_.current=f;const s=c.useRef(!0);if(c.useEffect(()=>(s.current=!0,()=>{s.current=!1}),[]),c.useEffect(()=>{if(!u||u.summary.status==="recording")return;const r=o=>{var L,H;if(o.metaKey||o.ctrlKey||o.altKey||Ke(o.target)||o.key===" "&&((H=(L=o.target)==null?void 0:L.closest)!=null&&H.call(L,"button, a, label")))return;if(o.key===" "&&o.repeat){o.preventDefault();return}const E=_.current;o.key===" "?(o.preventDefault(),E.toggle()):o.key==="ArrowRight"?(o.preventDefault(),E.seek(z(E.timeMs+V,b))):o.key==="ArrowLeft"&&(o.preventDefault(),E.seek(z(E.timeMs-V,b)))};return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[u,b]),p)return p.missing?e.jsx($,{title:"This recording isn't available",description:"It may have been deleted, or it's on phones you can't see.",action:e.jsx(B,{className:"rec-link",to:"/recordings",children:"Back to Recordings"})}):e.jsx($,{title:"Couldn't load this recording",description:p.message,action:e.jsxs(C,{variant:"secondary",onClick:()=>D(r=>r+1),children:[e.jsx(ne,{size:14,"aria-hidden":"true"}),"Retry"]})});if(!u)return e.jsx($,{title:"Loading recording…"});const{summary:a,bookmarks:i,annotations:M}=u,m=a.status==="recording",T=a.phones.map(r=>r.name).join(", "),I=r=>{var o;return((o=a.phones.find(E=>E.recordingId===r))==null?void 0:o.name)??""},F=[T,a.durationMs===null?null:`Length ${R(a.durationMs)}`,`Recorded by ${((K=a.startedBy)==null?void 0:K.name)??"Unknown"}`].filter(Boolean).join(" · "),P=Te(a,l),U=()=>{j(!1),S(null)},J=async()=>{y(!0),S(null);try{await le(n)}catch(r){s.current&&(y(!1),S(_e(r)));return}k("Recording deleted","success"),s.current&&t("/recordings")};return e.jsxs("div",{className:"rec-page",children:[e.jsx("nav",{className:"rec-backbar",children:e.jsxs(B,{className:"rec-link",to:"/recordings",children:[e.jsx(Re,{size:14,"aria-hidden":"true"})," Recordings"]})}),e.jsx(ue,{icon:re,title:xe(a.startedAt),subtitle:F,action:e.jsxs(e.Fragment,{children:[!m&&a.status!=="failed"&&e.jsx(Ve,{detail:u}),P&&e.jsxs(e.Fragment,{children:[e.jsxs(C,{variant:"danger",disabled:m,"aria-describedby":m?"rec-delete-reason":void 0,title:m?W:void 0,onClick:()=>{S(null),j(!0)},children:[e.jsx(Ne,{size:14,"aria-hidden":"true"}),"Delete"]}),m&&e.jsx("span",{id:"rec-delete-reason",className:"sr-only",children:W})]})]})}),m?e.jsx($,{title:"Still recording",description:"Stop it on Live devices to play it here.",action:e.jsx(B,{className:"rec-link",to:"/devices/live",children:"Open Live devices"})}):e.jsxs("div",{className:`rec-body${i.length>0?" rec-body--with-list":""}`,children:[e.jsxs("div",{className:"rec-player",children:[e.jsx("div",{className:"rec-grid",children:a.phones.map(r=>e.jsx(He,{groupId:n,phone:r,timeMs:f.timeMs,marks:M.filter(o=>o.recordingId===r.recordingId),showMarks:w,bind:f.bind},r.recordingId))}),e.jsxs("div",{className:"rec-transport",children:[e.jsx(C,{variant:"secondary",size:"icon","aria-label":f.playing?"Pause":"Play",onClick:f.toggle,children:f.playing?e.jsx(Ie,{size:14,"aria-hidden":"true"}):e.jsx(De,{size:14,"aria-hidden":"true"})}),e.jsxs("span",{className:"rec-num rec-clock",children:[R(f.timeMs)," / ",R(b)]}),e.jsxs("div",{className:"rec-timeline",children:[e.jsx("input",{type:"range",className:"rec-range","aria-label":"Timeline","aria-valuetext":`${R(f.timeMs)} of ${R(b)}`,min:0,max:b,step:100,value:f.timeMs,onChange:r=>f.seek(Number(r.target.value))}),i.map(r=>e.jsx("button",{type:"button",className:"rec-mark",style:{left:`${je(r.timecodeMs,b)}%`},title:r.label,"aria-label":`Bookmark: ${r.label}, ${R(r.timecodeMs)}`,onClick:()=>f.seek(r.timecodeMs)},r.id))]}),e.jsx("span",{role:"status",className:"rec-waiting",children:f.waiting?"Buffering…":""}),a.annotationCount>0&&e.jsxs("label",{className:"rec-toggle",children:[e.jsx("input",{type:"checkbox",checked:w,onChange:r=>x(r.target.checked)}),"Annotations"]})]})]}),i.length>0&&e.jsxs("section",{className:"rec-bookmarks","aria-labelledby":"rec-bookmarks-title",children:[e.jsx("h2",{id:"rec-bookmarks-title",className:"rec-bookmarks-title",children:"Bookmarks"}),e.jsx("ol",{className:"rec-bookmark-list",children:i.map(r=>e.jsx("li",{children:e.jsxs("button",{type:"button",className:"rec-bookmark",onClick:()=>f.seek(r.timecodeMs),children:[e.jsx("span",{className:"rec-bookmark-label",children:r.label}),e.jsxs("span",{className:"rec-num rec-bookmark-meta",children:[R(r.timecodeMs)," · ",I(r.recordingId)]})]})},r.id))})]})]}),e.jsxs(de,{open:h,title:"Delete this recording?",onClose:()=>{g||U()},footer:e.jsxs(e.Fragment,{children:[e.jsx(C,{variant:"secondary",onClick:U,disabled:g,children:"Cancel"}),e.jsx(C,{variant:"danger",onClick:J,disabled:g,children:"Delete"})]}),children:[e.jsx("p",{children:"Its videos, bookmarks and annotations are removed for everyone."}),A&&e.jsx("p",{role:"alert",className:"rec-error",children:A})]})]})}export{ot as default};
@@ -1 +0,0 @@
1
- .dc2{position:relative;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);font-family:Inter,sans-serif;display:flex;flex-direction:column;transition:border-color var(--motion-fast),box-shadow var(--motion-fast)}.dc2:hover{border-color:var(--border-strong);box-shadow:var(--shadow-md)}.dc2-band{display:flex;justify-content:space-between;align-items:center;gap:10px;min-height:30px;padding:7px 12px;font-size:11px;font-weight:600;border-radius:var(--radius-md) var(--radius-md) 0 0}.dc2-band-label{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}.dc2-band-dot{width:6px;height:6px;border-radius:50%;background:currentColor}.dc2-band-activity{min-width:0;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dc2-band-ready{background:var(--surface-2);color:var(--status-ready-fg)}.dc2-band-busy{background:var(--status-busy-bg);color:var(--status-busy-fg)}:root[data-theme=light] .dc2-band-busy{color:var(--text)}:root[data-theme=light] .dc2-band-busy .dc2-band-dot{background:var(--status-busy-fg)}.dc2-band-reserved{background:var(--status-reserved-bg);color:var(--blue-400)}:root[data-theme=light] .dc2-band-reserved{color:var(--status-reserved-fg)}.dc2-band-maintenance,.dc2-band-offline{background:var(--status-offline-bg);color:var(--status-offline-fg)}.dc2-body{flex:1;display:flex;flex-direction:column;gap:10px;padding:12px}.dc2-dim .dc2-icon,.dc2-dim .dc2-meta>:not(.dc2-tag):not(.dc2-team):not(.dc2-team-picker){opacity:.55}.dc2-dim .dc2-title{color:var(--text-muted)}.dc2-head{display:flex;align-items:center;gap:12px;min-width:0}.dc2-icon{flex:none;width:44px;height:56px;border-radius:10px;background:var(--surface-2);color:var(--text-muted);display:flex;align-items:center;justify-content:center}.dc2-id{min-width:0}.dc2-title{color:var(--text);font-size:15px;font-weight:600;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dc2-subtitle{margin-top:2px;color:var(--text-muted);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dc2-meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px;min-height:20px}.dc2-tag{color:var(--text-dim);font-size:11px}.dc2-dim .dc2-tag{color:var(--status-offline-tag)}.dc2-dim .dc2-team{color:var(--status-offline-tag);background-color:color-mix(in srgb,var(--accent-subtle) 55%,transparent);border-color:color-mix(in srgb,var(--accent-border) 55%,transparent)}.dc2-foot{display:flex;align-items:center;gap:6px;padding:10px 12px;border-top:1px solid var(--border)}.dc2-spacer{flex:1}.dc2-unavailable{min-width:0;margin:0;color:var(--text-dim);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dc2-health{display:flex;gap:6px;flex-wrap:wrap}.reservation-modal-body{display:flex;flex-direction:column;gap:20px}.reservation-modal-body p{color:var(--text-dim);font-size:13px;line-height:1.6;margin:0}.device-id-badge{display:inline-flex;align-items:center;gap:8px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));padding:8px 16px;border-radius:6px;border:1px solid var(--border);font-family:JetBrains Mono,monospace;font-size:11px;width:fit-content;margin-bottom:12px}.reservation-input{width:100%;background-color:rgb(var(--rgb-well) / calc(.3 * var(--well-k)));border:1px solid var(--border);border-radius:6px;padding:12px 16px;color:var(--text);font-size:13px;box-sizing:border-box;transition:all .2s;font-family:JetBrains Mono,monospace}.reservation-input:focus{outline:none;border-color:var(--color-accent);box-shadow:none}.duration-selector{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:8px}.duration-option{background-color:rgb(var(--rgb-well) / calc(.3 * var(--well-k)));border:1px solid var(--border);color:var(--text-dim);padding:10px;border-radius:6px;font-size:11px;cursor:pointer;text-align:center;transition:all .2s;font-weight:800;font-family:JetBrains Mono,monospace}.duration-option:hover{border-color:var(--text-muted);background-color:rgb(var(--rgb-fg) / .02)}.duration-option.active{background-color:rgb(var(--rgb-accent) / .05);border-color:var(--color-accent);color:var(--color-accent);box-shadow:none}.btn-cancel{background:transparent;border:1px solid var(--border);color:var(--text-dim);padding:10px 24px;border-radius:6px;font-size:12px;font-weight:700;cursor:pointer;transition:all .2s}.btn-reserve{background:var(--color-accent);color:var(--bg);border:none;padding:10px 24px;border-radius:6px;font-size:12px;font-weight:800;cursor:pointer;transition:all .2s;box-shadow:none}.btn-reserve:hover:not(:disabled){background:var(--color-accent);box-shadow:none}.btn-reserve:disabled{background-color:var(--border);color:var(--text-dim);cursor:not-allowed;box-shadow:none;filter:grayscale(1);opacity:.5}.title-icon{color:var(--color-accent)}.tag-modal-body{display:flex;flex-direction:column;gap:20px}.device-id-badge{display:inline-flex;align-items:center;gap:8px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));padding:8px 16px;border-radius:6px;border:1px solid var(--border);font-family:JetBrains Mono,monospace;font-size:11px}.device-id-badge .label{color:var(--text-dim);font-weight:800;font-size:11px}.device-id-badge .value{color:var(--color-accent);font-weight:800}.tags-display-section label{display:block;font-size:11px;font-weight:800;color:var(--text-dim);margin-bottom:8px}.input-with-button{display:flex;gap:8px}.input-with-button input{flex:1;background:rgb(var(--rgb-well) / calc(.3 * var(--well-k)));border:1px solid var(--border);border-radius:6px;padding:10px 14px;color:var(--text);font-size:13px;transition:all .2s;font-family:JetBrains Mono,monospace}.input-with-button input:focus{outline:none;border-color:var(--color-accent);box-shadow:none}.add-inline-btn{background:var(--color-accent);color:var(--bg);border:none;border-radius:6px;width:40px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s}.add-inline-btn:hover:not(:disabled){background:var(--color-accent);box-shadow:none}.add-inline-btn:disabled{background:var(--border);color:var(--text-dim);cursor:not-allowed;filter:grayscale(1);opacity:.5}.tags-list{display:flex;flex-wrap:wrap;gap:8px;min-height:48px;padding:12px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border-radius:6px;border:1px dashed var(--border)}.tag-pill-editable{display:flex;align-items:center;gap:6px;background:rgb(var(--rgb-accent) / .05);color:var(--color-accent);padding:6px 12px;border-radius:6px;font-size:11px;font-weight:800;border:1px solid rgb(var(--rgb-accent) / .3);box-shadow:none}.remove-tag{background:transparent;border:none;color:var(--color-accent);cursor:pointer;padding:2px;border-radius:4px;display:flex;align-items:center;justify-content:center;transition:all .2s;opacity:.7}.remove-tag:hover{background:rgb(var(--rgb-accent) / .2);opacity:1}.btn-cancel{padding:10px 24px;border-radius:6px;background:transparent;border:1px solid var(--border);color:var(--text-dim);font-weight:700;cursor:pointer;transition:all .2s;font-size:12px}.btn-cancel:hover{color:var(--text);border-color:var(--text-muted)}.btn-save{padding:10px 24px;border-radius:6px;background:var(--color-accent);border:none;color:var(--bg);font-weight:800;cursor:pointer;transition:all .2s;box-shadow:none;font-size:12px}.btn-save:hover:not(:disabled){background:var(--color-accent);box-shadow:none}.btn-save:disabled{background-color:var(--border);color:var(--text-dim);cursor:not-allowed;box-shadow:none;filter:grayscale(1);opacity:.5}.dc2-more{flex:none;background:transparent;border:1px solid var(--border);color:var(--text-muted);border-radius:var(--radius-md);width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background var(--motion-fast),color var(--motion-fast)}.dc2-more:hover{background:var(--surface-2);color:var(--text)}.device-explorer-card-container{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px;padding:16px;flex:1}.device-explorer-card-container::-webkit-scrollbar{width:6px}.device-explorer-card-container::-webkit-scrollbar-thumb{background:var(--border);border-radius:8px}.devtable.tbl{table-layout:fixed;width:100%}.devtable-col-status{width:150px}.devtable-col-platform{width:120px}.devtable-col-type{width:80px}.devtable-col-team{width:120px}.devtable-col-tags,.devtable-col-host{width:150px}.devtable-col-actions{width:220px}.devtable.tbl thead th,.devtable.tbl tbody td,.devtable.tbl tbody th.devtable-rowheader{padding:8px 12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.devtable.tbl tbody td,.devtable.tbl tbody th.devtable-rowheader{padding-top:5px;padding-bottom:5px}.devtable.tbl tbody th.devtable-rowheader{font-weight:400;text-align:left;vertical-align:middle;color:var(--text);border-bottom:1px solid var(--border)}.devtable.tbl tbody tr:last-child th.devtable-rowheader{border-bottom:none}.devtable.tbl th:first-child,.devtable.tbl td:first-child{padding-left:20px}.devtable.tbl th:last-child,.devtable.tbl td:last-child{padding-right:20px}.devtable.tbl tbody td.devtable-actions{white-space:normal;overflow:visible;text-overflow:clip;vertical-align:middle}.devtable.tbl thead th{position:sticky;top:var(--de2-sticky-h, 0px);background:var(--surface);z-index:1}.devtable-line{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.devtable-muted{color:var(--text-muted);font-size:11px}.devtable-row.is-offline .devtable-status-dot{opacity:.55}.devtable-row.is-offline .devtable-title{color:var(--text-muted)}.devtable-sort{display:inline-flex;align-items:center;gap:4px;background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer}.devtable-sort:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:1px}.devtable-tag{display:inline-block;margin-right:4px;color:var(--text-muted);font-size:11px}.devtable-row.is-offline .devtable-tag{color:var(--status-offline-tag)}.devtable-actions-inner{display:flex;align-items:center;gap:6px}.device-explorer-container{display:flex;flex-direction:column;width:100%;gap:var(--space-4)}.device-explorer-header-container{display:flex;align-items:center;justify-content:space-between;padding:4px 24px;background:#0f0f1ae6;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border-bottom:2px solid var(--border);position:sticky;top:0;z-index:15;gap:var(--space-8);flex-wrap:nowrap;box-shadow:0 10px 30px rgb(var(--rgb-black) / calc(.4 * var(--shadow-k)))}.device-explorer-header-left-container{display:flex;align-items:center;gap:24px;flex:1;min-width:0}.device-explorer-header-entry{display:flex;flex-direction:column;gap:4px;min-width:0}.device-explorer-header-entry-header{font-size:11px;font-weight:700;color:var(--text-dim)}.device-explorer-header-value{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.device-explorer-header-value>.device-explorer-header__platform-btn+.device-explorer-header__platform-btn{margin-left:4px}.device-explorer-header__platform-btn,.device-explorer-header__device-state{display:flex;align-items:center;gap:6px;padding:6px 12px;border-radius:6px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border:1px solid var(--border);color:var(--text-muted);font-size:12px;font-weight:600;cursor:pointer;transition:all .2s ease}.device-explorer-header__platform-btn:hover,.device-explorer-header__device-state:hover{background:rgb(var(--rgb-fg) / .03);color:var(--text);border-color:var(--border)}.device-explorer-header__platform-btn.selected,.device-explorer-header__device-state.selected{background:rgb(var(--rgb-accent) / .05);color:var(--color-accent);border-color:rgb(var(--rgb-accent) / .3);box-shadow:none}.device-explorer-header__device-state.ready.selected{border-color:var(--color-success);box-shadow:none}.device-explorer-header__device-state.busy.selected{background:rgb(var(--rgb-amber-alt) / .05);color:var(--status-busy-fg);border-color:rgb(var(--rgb-amber-alt) / .3);box-shadow:none}.device-explorer-header__device-state.offline.selected{background:#4a4a6a1a;color:var(--text-dim);border-color:var(--text-dim)}.device-explorer-search-wrapper{position:relative;width:320px}.device-explorer-search-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);pointer-events:none;opacity:.5}.device-explorer-header-text-filter{width:100%;height:32px;padding:0 12px 0 36px;border-radius:6px;border:1px solid var(--border);background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));font-family:JetBrains Mono,monospace;font-size:12px;color:var(--text);transition:all .2s ease}.device-explorer-header-text-filter:focus{outline:none;border-color:var(--color-accent);background:rgb(var(--rgb-well) / calc(.6 * var(--well-k)));box-shadow:none}.device-explorer-header-text-filter::placeholder{color:var(--text-dim);font-size:11px}.device-explorer-header-right-container{display:flex;align-items:center;gap:12px}.device-explorer-header-filter-count{display:flex;align-items:center;gap:8px;padding-right:16px;border-right:1px solid var(--border)}@media (max-width: 1024px){.device-explorer-header-container{flex-direction:column;align-items:stretch;gap:var(--space-4);padding:var(--space-4)}.device-explorer-header-left-container{flex-wrap:wrap;gap:var(--space-4)}.device-explorer-header-entry{flex:1;min-width:120px}.device-explorer-search-wrapper{width:100%}.device-explorer-header-right-container{justify-content:space-between;width:100%}}@media (max-width: 640px){.device-explorer-header-left-container{display:flex;flex-direction:column;align-items:stretch;gap:var(--space-3)}.device-explorer-header-entry,.device-explorer-header-value,.device-explorer-header-filter-count{width:100%;min-width:0}.device-explorer-header-filter-count{padding-right:0;border-right:none;justify-content:flex-start}.device-explorer-header-right-container{flex-direction:row;flex-wrap:wrap;align-items:center;gap:var(--space-2);width:100%}}.device-explorer-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:80px 40px;background:#0f0f1a66;border:1px dashed var(--border);border-radius:var(--radius-md);text-align:center;margin:60px auto 40px;max-width:600px;gap:var(--space-4)}.device-explorer-empty-icon{width:64px;height:64px;background:rgb(var(--rgb-accent) / .05);border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--color-accent);margin-bottom:8px;border:1px solid rgb(var(--rgb-accent) / .1)}.device-explorer-empty h3{font-size:1.5rem;font-weight:700;color:var(--text);margin:0;font-family:Outfit,sans-serif}.device-explorer-empty p{color:var(--text-muted);font-size:14px;max-width:400px;line-height:1.6;margin:0}.device-explorer-empty .Button{margin-top:8px}.device-control-modal-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:var(--bg);z-index:6000;display:flex;flex-direction:column;padding:0;margin:0;animation:modal-fade-in .25s ease-out}.device-control-modal{flex:1;width:100%;height:100%;overflow:hidden;display:flex;flex-direction:column;background:var(--bg)}@keyframes modal-fade-in{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.de2-sticky-group{position:sticky;top:0;z-index:15;background:var(--bg);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);box-shadow:0 6px 16px -8px rgb(var(--rgb-black) / calc(.5 * var(--shadow-k)))}.de2-toolbar{display:flex;gap:10px;align-items:center;padding:12px 20px;border-bottom:1px solid var(--border);background:transparent;box-shadow:none;flex-wrap:wrap}.de2-toolbar-row{flex:1 1 100%;display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}.de2-search-wrap{position:relative;display:flex;align-items:center;flex:0 1 320px;min-width:200px}.de2-search-icon{position:absolute;left:9px;color:var(--text-dim);pointer-events:none}.de2-key{position:absolute;right:7px;padding:0 5px;border:1px solid var(--border);border-radius:4px;color:var(--text-dim);font-family:JetBrains Mono,ui-monospace,monospace;font-size:10px;line-height:16px;pointer-events:none}.de2-result .btn-base.btn-size-icon{width:28px;height:28px}.de2-result{margin-left:auto;display:flex;align-items:center;gap:10px;color:var(--text-muted);font-size:12px;white-space:nowrap}.de2-search{width:100%;height:28px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:0 28px;color:var(--text);font-family:Inter,sans-serif;font-size:12px;outline:none}.de2-search::placeholder{color:var(--text-dim)}.de2-search:focus{border-color:var(--border-strong)}.device-explorer-empty h3{color:var(--text);font-family:Inter,sans-serif;font-weight:700;letter-spacing:-.01em}:root[data-theme=light] .device-explorer-header-container{background:rgb(var(--rgb-white) / .9)}:root[data-theme=light] .device-explorer-empty{background:var(--surface-2)}.device-control-view{display:flex;flex-direction:column;height:100%;width:100%;background:var(--bg);color:var(--text);overflow:hidden;font-family:Inter,sans-serif}*{scrollbar-width:thin;scrollbar-color:var(--border) transparent}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:8px;-webkit-transition:background .2s;transition:background .2s}::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.control-view-top-bar{display:flex;align-items:center;padding:0 24px;height:64px;background:var(--surface);border-bottom:2px solid var(--border);gap:24px;z-index:100;position:relative}.device-info-mini{display:flex;align-items:center;gap:16px}.device-pill{font-size:11px;font-weight:800;padding:2px 10px;border-radius:6px}.platform-pill{background:rgb(var(--rgb-accent) / .05);color:var(--color-accent);border:1px solid rgb(var(--rgb-accent) / .2)}.version-pill{background:rgb(var(--rgb-amber-alt) / .05);color:var(--status-busy-fg);border:1px solid rgb(var(--rgb-amber-alt) / .2)}.reserved-pill{background:rgb(var(--rgb-sky-400) / .1);color:var(--sky-400);border:1px solid rgb(var(--rgb-sky-400) / .3);animation:pulse-reserved-pill 2s infinite ease-in-out}.device-name-text{font-family:Outfit,sans-serif;font-weight:800;font-size:14px;color:var(--text)}.code-font{font-family:JetBrains Mono,monospace;font-size:11px;color:var(--text-dim);background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));padding:4px 10px;border-radius:6px;border:1px solid var(--border)}.udid-chip{display:inline-flex;align-items:center;gap:6px;padding:3px 4px 3px 10px;font-family:JetBrains Mono,monospace;font-size:11px;color:var(--text-dim);background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border-radius:6px;border:1px solid var(--border);max-width:280px}.udid-chip__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.udid-chip__copy{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:transparent;border-radius:4px;color:var(--text-muted);cursor:pointer;transition:background .15s,color .15s;flex-shrink:0}.udid-chip__copy:hover{background:rgb(var(--rgb-fg) / .05);color:var(--color-accent)}.back-to-devices-btn{background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));color:var(--text-dim);border:1px solid var(--border);padding:8px 16px;border-radius:6px;font-size:11px;font-weight:800;display:flex;align-items:center;gap:8px;transition:all .2s;cursor:pointer}.back-to-devices-btn:hover{background:rgb(var(--rgb-fg) / .03);border-color:var(--color-accent);color:var(--color-accent)}.control-view-main{display:flex;flex-direction:row;flex:1;overflow:hidden;padding:24px;gap:32px;background:var(--bg);justify-content:center;align-items:stretch;min-height:0}.control-view-main.is-landscape{align-items:flex-start}.control-view-main.omni-mode{gap:20px}.control-view-main.omni-mode .device-preview-column{min-width:0;flex-shrink:1}.control-view-main.omni-mode .device-stream-canvas{max-width:100%;max-height:100%}.device-preview-column{display:flex;flex-direction:row-reverse;align-items:center;justify-content:center;gap:24px;flex-shrink:1;min-width:0;max-width:42%}.control-view-main.is-landscape .device-preview-column{max-width:none;flex-direction:column}.device-screen-wrapper{position:relative;padding:12px;background:var(--black);border-radius:48px;box-shadow:0 0 0 2px #334155,0 20px 50px rgb(var(--rgb-black) / calc(.6 * var(--shadow-k)));border:1px solid rgb(var(--rgb-white) / .1);transition:all .5s cubic-bezier(.16,1,.3,1)}.device-screen-wrapper:hover{transform:translateY(-4px) scale(1.005);box-shadow:0 0 0 2px var(--color-accent),0 30px 60px rgb(var(--rgb-black) / calc(.8 * var(--shadow-k)))}.device-stream-canvas{position:relative;background:var(--black);border-radius:28px;overflow:hidden;cursor:crosshair;transition:box-shadow .3s ease,border-color .3s ease;outline:none;border:2px solid transparent;user-select:none;-webkit-user-select:none}.device-stream-canvas.focused{border-color:var(--color-accent);box-shadow:none}.device-stream-image{pointer-events:none;-webkit-user-select:none;user-select:none;-webkit-user-drag:none}.device-stream-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;width:100%;color:var(--text-muted);gap:16px;background:radial-gradient(circle at center,var(--surface) 0%,var(--bg) 100%)}.device-screen-off{position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:16px;text-align:center;color:var(--text-muted);background:rgb(var(--rgb-black) / .55);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.device-screen-off p{margin:6px 0 0;font-size:13px;font-weight:600;color:var(--text)}.device-screen-off span{font-size:11px;line-height:1.5;opacity:.75;max-width:220px}.device-screen-off button{margin-top:10px}.device-footer-actions{display:flex;flex-direction:column;flex-wrap:wrap;align-content:center;justify-content:center;width:auto;flex-shrink:0;background:color-mix(in srgb,var(--surface-2) 80%,transparent);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:16px;border:1px solid rgb(var(--rgb-fg) / .08);padding:6px;gap:6px;box-shadow:0 10px 25px -5px rgb(var(--rgb-black) / calc(.4 * var(--shadow-k)))}.footer-action-btn{flex:0 0 auto;display:flex;align-items:center;justify-content:center;gap:8px;width:36px;height:36px;padding:0;color:var(--text-muted);font-size:11px;font-weight:700;border:none;background:transparent;border-radius:var(--radius-sm);transition:all .2s ease}.footer-action-btn:hover{background:rgb(var(--rgb-fg) / .05);color:var(--text)}.footer-action-btn.active{background:rgb(var(--rgb-fg) / .04);color:var(--color-accent);box-shadow:inset 0 -2px 0 0 var(--color-accent)}.footer-divider{width:24px;height:1px;background:var(--border);margin:4px auto;flex-shrink:0}.control-view-main.is-landscape .device-footer-actions{flex-direction:row;width:100%}.control-view-main.is-landscape .footer-divider{width:1px;height:24px;margin:auto 4px}.hint-text{display:block;font-size:11px;color:var(--text-muted);font-style:italic;margin-top:4px}.device-interactions-column{flex:1;display:flex;flex-direction:column;gap:0;min-width:450px;max-width:1200px;height:100%;overflow:hidden;min-height:0}.interaction-tabs{display:flex;gap:4px;background:var(--surface);padding:4px;border-radius:6px;border:1px solid var(--border);margin-bottom:16px;flex-shrink:0}.tab-btn{flex:1 1 0;min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:8px 6px;background:transparent;border:none;font-size:11px;font-weight:800;color:var(--text-dim);border-radius:4px;cursor:pointer;transition:all .2s;white-space:nowrap}.tab-btn>svg{flex-shrink:0;opacity:.7;transition:opacity .15s}.tab-btn>span{min-width:0;overflow:hidden;text-overflow:ellipsis}.tab-btn:hover>svg,.tab-btn.active>svg{opacity:1}.tab-btn:hover{color:var(--text);background:rgb(var(--rgb-fg) / .02)}.tab-btn.active{color:var(--bg);background:var(--color-accent);box-shadow:none}.interactions-scroll-area{flex:1;overflow-y:auto;overflow-x:hidden;padding-right:8px;display:flex;flex-direction:column}.action-card{background:rgb(var(--rgb-well) / calc(.2 * var(--well-k)));border-radius:6px;padding:20px;border:1px solid var(--border);transition:all .2s;display:flex;flex-direction:column;gap:16px}.action-card:hover{background:rgb(var(--rgb-fg) / .01);border-color:var(--color-accent);box-shadow:0 4px 20px rgb(var(--rgb-black) / calc(.4 * var(--shadow-k)))}.btn-sm{padding:8px 16px;font-size:11px}.type-input-field.compact{padding:10px;font-size:13px}.install-app-section,.uninstall-app-section{flex:1;display:flex;flex-direction:column;gap:12px;min-width:0}.btn-premium,.dc-btn-secondary{padding:10px 20px;border-radius:var(--radius-sm);font-weight:700;font-size:11px;cursor:pointer;transition:all .2s cubic-bezier(.16,1,.3,1);display:flex;align-items:center;justify-content:center;gap:8px;border:none}.btn-premium{background:var(--color-accent);color:var(--color-on-accent)}.btn-premium:hover:not(:disabled){background:var(--color-accent-strong);transform:translateY(-1px);box-shadow:none}.dc-btn-secondary{background:rgb(var(--rgb-fg) / .05);color:var(--text);border:1px solid var(--border)}.dc-btn-secondary:hover:not(:disabled){background:rgb(var(--rgb-fg) / .1);color:var(--text);border-color:var(--text-muted)}.dc-btn-secondary.active{background:var(--primary-soft);color:var(--color-accent);border-color:var(--color-accent)}.btn-sm{padding:6px 12px!important;font-size:11px!important}.type-input-field{width:100%;padding:10px 14px;border-radius:var(--radius-sm);border:1px solid var(--border);background:rgb(var(--rgb-well) / calc(.3 * var(--well-k)));font-size:13px;color:var(--text);transition:all .2s ease}.type-input-field::placeholder{color:var(--text-dim)}.type-input-field:focus{outline:none;border-color:var(--color-accent);background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));box-shadow:0 0 0 3px var(--primary-soft)}.animate-pulse{animation:pulse-op 1.5s infinite}@keyframes pulse-op{0%,to{opacity:1}50%{opacity:.4}}.tab-content{animation:slideUpFade .4s cubic-bezier(.16,1,.3,1);display:flex;flex-direction:column;flex:1;min-height:0}@keyframes slideUpFade{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.btn-destructive{background:var(--status-error-fg);color:var(--white);border:1px solid transparent;padding:10px 20px;border-radius:var(--radius-sm);font-weight:700;font-size:11px;display:flex;align-items:center;gap:8px;cursor:pointer;transition:background .2s ease,transform .2s ease,box-shadow .2s ease}.btn-destructive:hover:not(:disabled){background:var(--red-600);transform:translateY(-1px);box-shadow:none}.btn-destructive:disabled{opacity:.5;cursor:not-allowed}.type-input-field.tiny{padding:8px 12px;font-size:12px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.action-card-header{display:flex;justify-content:flex-end;align-items:flex-start;margin-bottom:12px}.screenshot-workspace{display:flex;gap:20px;flex:1;min-height:0;overflow:hidden}.screenshot-gallery-sidebar{width:180px;display:flex;flex-direction:column;gap:16px;flex-shrink:0;min-height:0}.screenshot-workspace.is-empty .screenshot-main-preview{display:none}.screenshot-workspace.is-empty .screenshot-gallery-sidebar{width:100%;align-items:center;justify-content:center;gap:24px}.screenshot-workspace.is-empty .screenshot-thumbnails-list{order:1;flex:none;overflow:visible}.screenshot-workspace.is-empty .take-screenshot-btn{order:2;width:auto;min-width:200px;flex:none}.take-screenshot-btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%}.screenshot-thumbnails-list{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:10px;padding-right:4px;min-height:0}.screenshot-thumb-item{position:relative;border-radius:8px;overflow:hidden;aspect-ratio:9/16;background:rgb(var(--rgb-black) / .4);border:2px solid transparent;cursor:pointer;transition:all .2s ease;flex-shrink:0}.screenshot-thumb-item:hover{border-color:rgb(var(--rgb-accent) / .4)}.screenshot-thumb-item.active{border-color:var(--color-accent);box-shadow:none}.screenshot-thumb-item img{width:100%;height:100%;object-fit:cover;opacity:.7;transition:opacity .2s ease}.screenshot-thumb-item:hover img,.screenshot-thumb-item.active img{opacity:1}.thumb-time{position:absolute;bottom:0;left:0;right:0;background:rgb(var(--rgb-black) / .7);color:#fff;font-size:11px;padding:2px 4px;text-align:center;font-family:JetBrains Mono,monospace}.thumb-delete-btn{position:absolute;top:4px;right:4px;width:20px;height:20px;border-radius:4px;background:rgb(var(--rgb-red) / .8);color:#fff;border:none;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s ease}.screenshot-thumb-item:hover .thumb-delete-btn{opacity:1}.thumb-delete-btn:hover{background:var(--status-error-fg)}.screenshot-main-preview{flex:1;background:rgb(var(--rgb-black) / .3);border-radius:8px;display:flex;align-items:center;justify-content:center;overflow:hidden;position:relative;border:1px solid rgb(var(--rgb-white) / .05);min-height:0}.preview-container{display:flex;flex-direction:column;width:100%;height:100%;position:relative}.preview-image-wrapper{flex:1;position:relative;min-height:0}.preview-image-wrapper img{position:absolute;top:20px;bottom:20px;left:20px;right:20px;max-width:calc(100% - 40px);max-height:calc(100% - 40px);object-fit:contain;margin:auto;border-radius:4px;box-shadow:0 10px 40px rgb(var(--rgb-black) / calc(.5 * var(--shadow-k)))}.preview-footer{padding:16px 24px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border-top:1px solid rgb(var(--rgb-fg) / .05);display:flex;justify-content:space-between;align-items:center}.preview-meta{display:flex;align-items:center;gap:8px;font-size:11px;color:var(--text-muted)}.meta-label{font-weight:700;opacity:.5}.meta-divider{opacity:.2}.preview-actions{display:flex;gap:12px}.btn-text-only{background:transparent;border:none;color:var(--text-muted);font-size:11px;font-weight:700;letter-spacing:.05em;cursor:pointer;padding:4px 8px;border-radius:4px}.btn-text-only:hover{color:var(--red);background:rgb(var(--rgb-red) / .05)}.empty-gallery-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:24px 12px;color:var(--text-muted);font-size:11px;text-align:center}.empty-gallery-icon{opacity:.4}.empty-gallery-title{font-weight:700;font-size:12px;color:var(--text);margin:0}.empty-gallery-hint{margin:0;font-size:11px;color:var(--text-muted);line-height:1.4;max-width:160px}.empty-gallery-hint strong{color:var(--color-accent);font-weight:700}.interactions-scroll-area.terminal-mode{overflow:hidden;padding:0;display:flex;flex-direction:column;height:100%;min-height:0}.omni-inspector-tab-wrapper{flex:1;min-height:0;display:flex;flex-direction:column}.interactions-scroll-area.terminal-mode .action-card.full-height{height:100%;min-height:0;border-radius:0;border:none}.interactions-scroll-area.screenshot-mode{overflow:hidden;height:100%;min-height:0;display:flex;flex-direction:column;padding:0}.interactions-scroll-area.screenshot-mode .tab-content{display:flex;flex-direction:column;flex:1 1 0%;min-height:0;padding:0}.interactions-scroll-area.screenshot-mode .action-card.screenshot-card{display:flex;flex-direction:column;flex:1;min-height:0;margin-bottom:0;border-radius:0;border:none;padding:0;overflow:hidden}@media (max-width: 900px){.control-view-main{flex-direction:column;padding:16px;gap:16px;overflow-y:auto}.device-preview-column{min-width:0;width:100%;max-width:420px;margin:0 auto}.device-interactions-column{width:100%;max-width:100%;min-width:0}}.device-stream-canvas.is-inspecting{cursor:crosshair}.terminal-container{display:flex;flex-direction:column;background-color:var(--bg);color:var(--text);font-family:JetBrains Mono,monospace;border-radius:6px;overflow:hidden;height:100%;max-height:100%;width:100%;min-height:0;border:1px solid var(--border);box-shadow:0 20px 50px rgb(var(--rgb-black) / calc(.5 * var(--shadow-k)));position:relative}.terminal-header{display:flex;align-items:center;justify-content:space-between;padding:12px 20px;background-color:rgb(var(--rgb-black) / .4);border-bottom:2px solid var(--border)}.terminal-controls{display:flex;gap:8px;width:60px}.dot{width:8px;height:8px;border-radius:4px;border:1px solid rgb(var(--rgb-fg) / .1)}.dot.red{background-color:var(--red-alt)}.dot.yellow{background-color:#fc0}.dot.green{background-color:var(--color-accent)}.terminal-title{font-size:11px;font-weight:800;color:var(--text-dim)}.terminal-actions{display:flex;justify-content:flex-end;width:60px}.terminal-action-btn{background:transparent;border:1px solid var(--border);color:var(--text-dim);font-size:11px;font-weight:800;padding:4px 10px;border-radius:6px;cursor:pointer;transition:all .2s}.terminal-action-btn:hover{color:var(--text);background:rgb(var(--rgb-white) / .05);border-color:var(--text-muted)}.terminal-history{flex:1;overflow-y:auto;overflow-x:hidden;padding:20px;font-size:12px;line-height:1.6;scrollbar-width:thin;scrollbar-color:var(--color-accent) var(--bg);min-height:0}.terminal-history::-webkit-scrollbar{width:6px}.terminal-history::-webkit-scrollbar-track{background:transparent}.terminal-history::-webkit-scrollbar-thumb{background-color:var(--border);border-radius:4px}.terminal-history::-webkit-scrollbar-thumb:hover{background-color:var(--color-accent)}.terminal-line{margin-bottom:6px;white-space:pre-wrap;word-break:normal;overflow-wrap:anywhere}.terminal-line.command{color:var(--color-accent);font-weight:600}.terminal-line.output{color:var(--text)}.terminal-line.error{color:var(--red-alt)}.terminal-line.system{color:var(--text-dim);font-style:italic;border-bottom:1px dashed var(--border);padding-bottom:6px;margin-bottom:12px}.terminal-input-area{display:flex;align-items:center;padding:16px 20px;background-color:rgb(var(--rgb-black) / .4);border-top:2px solid var(--border)}.terminal-prompt{color:var(--color-accent);margin-right:12px;font-weight:800;-webkit-user-select:none;user-select:none}.terminal-input{flex:1;background:transparent;border:none;color:var(--text);font-family:inherit;font-size:13px;outline:none;font-weight:500}.terminal-input::placeholder{color:rgb(var(--rgb-white) / .1)}.terminal-loading-indicator{display:inline-block;width:8px;height:16px;background-color:var(--color-accent);animation:blink 1s step-end infinite;vertical-align:middle;margin-left:8px;border-radius:4px}@keyframes blink{0%,to{opacity:1}50%{opacity:0}}.omni-inspector-container{display:flex;flex-direction:column;height:100%;background:var(--bg);color:var(--text);font-family:Inter,sans-serif;overflow:hidden;position:relative}.omni-main-content{flex:1;display:flex;gap:16px;padding:16px;overflow:hidden;height:100%}.omni-screenshot-panel{width:380px;min-width:320px;flex-shrink:0;display:flex;flex-direction:column;background:var(--surface);border-radius:6px;border:1px solid var(--border);overflow:hidden}.omni-screenshot-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;background:rgb(var(--rgb-black) / .4);border-bottom:2px solid var(--border)}.omni-screenshot-title{font-size:11px;font-weight:800;color:var(--text);opacity:.9}.omni-mode-toggle{display:flex;background:rgb(var(--rgb-well) / calc(.3 * var(--well-k)));padding:2px;border-radius:6px;border:1px solid var(--border)}.omni-mode-btn{display:flex;align-items:center;gap:6px;padding:4px 10px;background:transparent;border:none;border-radius:4px;color:var(--text-dim);font-size:11px;font-weight:800;cursor:pointer;transition:all .2s}.omni-mode-btn.active{background:var(--color-accent);color:var(--bg);box-shadow:none}.omni-refresh-btn{display:flex;align-items:center;gap:6px;padding:6px 12px;background:var(--color-accent);color:var(--bg);border:none;border-radius:6px;font-size:11px;font-weight:800;cursor:pointer;transition:all .2s}.omni-refresh-btn:hover:not(:disabled){background:var(--color-accent);box-shadow:none}.omni-refresh-btn:disabled{opacity:.5;cursor:not-allowed}.omni-screenshot-container{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;padding:12px;background:#161b22b3;position:relative;overflow:hidden}.omni-screenshot-wrapper{position:relative;max-width:100%;max-height:100%;height:100%;display:flex;align-items:center;justify-content:center;-webkit-user-select:none;user-select:none}.omni-screenshot-wrapper.interactable{cursor:crosshair}.omni-screenshot-img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;border-radius:4px;display:block}.omni-overlay{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.omni-overlay>*{pointer-events:auto}.omni-hit-area{position:absolute;cursor:pointer;background:transparent;transition:background .15s ease}.omni-hit-area:hover{background:rgb(var(--rgb-accent) / .2)}.omni-frame-hover{position:absolute;border:2px solid var(--color-accent);background:rgb(var(--rgb-accent) / .1);pointer-events:none;border-radius:6px}.omni-frame-select{position:absolute;border:2px solid var(--color-accent);background:rgb(var(--rgb-accent) / .2);pointer-events:none;box-shadow:none;border-radius:6px}.omni-frame-match{position:absolute;pointer-events:none;border-radius:6px;border-style:dashed;border-width:2px;animation:omni-match-pulse 1.6s ease-out 1}.omni-frame-match.unique{border-color:var(--color-success);background:rgb(var(--rgb-success) / .12);box-shadow:none}.omni-frame-match.multi{border-color:var(--amber, var(--amber));background:rgb(var(--rgb-amber) / .1);box-shadow:none}@keyframes omni-match-pulse{0%{opacity:0;transform:scale(.96)}35%{opacity:1;transform:scale(1)}to{opacity:1;transform:scale(1)}}.omni-loading-overlay{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;background:rgb(var(--rgb-black) / .8);color:var(--text-muted);font-size:11px}.omni-spinner{width:24px;height:24px;border:2px solid var(--border);border-top-color:var(--color-accent);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.omni-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;color:var(--text-muted);text-align:center;padding:32px;font-size:12px}.omni-empty-state svg{opacity:.3}.omni-empty-state.small{padding:24px;font-size:11px}.omni-tree-panel{flex:1;min-width:0;display:flex;flex-direction:column;background:rgb(var(--rgb-well) / calc(.2 * var(--well-k)));border-radius:6px;border:1px solid var(--border);overflow:hidden;min-height:0}.omni-tree-content{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:4px;scrollbar-width:thin;scrollbar-color:var(--border) transparent}.omni-tree-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;row-gap:8px;column-gap:8px;padding:12px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border-bottom:2px solid var(--border)}.omni-tree-title{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:800;color:var(--text);opacity:.9}.omni-action-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;background:rgb(var(--rgb-fg) / .02);border:1px solid var(--border);border-radius:6px;color:var(--text-dim);cursor:pointer;transition:all .2s}.omni-action-btn:hover{background:rgb(var(--rgb-fg) / .05);color:var(--color-accent);border-color:var(--color-accent)}.omni-tree-search{display:flex;align-items:center;gap:8px;margin:12px;padding:8px 12px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border:1px solid var(--border);border-radius:6px;transition:all .2s}.omni-tree-search:focus-within{border-color:var(--color-accent);box-shadow:none}.omni-tree-search input{flex:1;background:transparent;border:none;color:var(--text);font-size:11px;outline:none;font-family:JetBrains Mono,monospace}.omni-details-panel{flex:1;min-width:280px;max-width:360px;display:flex;flex-direction:column;background:var(--surface);border-radius:6px;border:1px solid var(--border);overflow:hidden;min-height:0}.omni-details-content{flex:1;min-height:0;overflow-y:auto;padding:16px;scrollbar-width:thin;scrollbar-color:var(--border) transparent}.omni-split{flex:1;display:flex;min-width:0;min-height:0}.omni-split>.omni-tree-panel{flex:0 0 auto;min-width:0}.omni-split>.omni-details-panel{flex:1 1 0;min-width:0;max-width:none}.omni-split-divider{position:relative;flex:0 0 12px;display:flex;align-items:center;justify-content:center;cursor:col-resize;touch-action:none;outline:none}.omni-split-divider:before{content:"";position:absolute;top:0;bottom:0;left:5px;width:2px;background:transparent}.omni-split-divider:hover:before,.omni-split-divider.is-dragging:before{background:var(--border-strong)}.omni-split-divider:focus-visible:before{background:var(--color-focus-ring)}.omni-split-divider__grip{position:relative;width:4px;height:28px;border-radius:2px;background:var(--text-dim)}.omni-split-divider:hover .omni-split-divider__grip,.omni-split-divider.is-dragging .omni-split-divider__grip{background:var(--text-muted)}@media (forced-colors: active){.omni-split-divider:before,.omni-split-divider:hover:before,.omni-split-divider.is-dragging:before,.omni-split-divider__grip,.omni-split-divider:hover .omni-split-divider__grip,.omni-split-divider.is-dragging .omni-split-divider__grip{background:CanvasText}.omni-split-divider:focus-visible:before{background:Highlight}}.omni-header-left{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.omni-tree-actions{display:flex;gap:6px;align-items:center;flex-shrink:0;margin-left:auto}.omni-clear-btn{background:transparent;border:none;color:var(--text-muted);cursor:pointer;font-size:16px;padding:0 4px;line-height:1;border-radius:3px}.omni-clear-btn:hover{color:var(--text);background:rgb(var(--rgb-fg) / .08)}.omni-info-table,.omni-locators-list{display:flex;flex-direction:column;gap:6px}.omni-details-header{display:flex;align-items:center;gap:8px;padding:12px 16px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border-bottom:2px solid var(--border);font-size:11px;font-weight:800;color:var(--text);opacity:.9}.omni-section{margin-bottom:24px}.omni-section-header{font-size:11px;font-weight:800;color:var(--text-dim);margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border)}.omni-info-row{display:flex;gap:16px;padding:12px 16px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border-radius:6px;border:1px solid var(--border);min-height:44px;align-items:center}.omni-info-key{width:60px;flex-shrink:0;font-size:11px;font-weight:800;color:var(--text-dim)}.omni-info-value{flex:1;font-size:11px;color:var(--text);word-break:break-all}.omni-info-row--path{align-items:flex-start}.omni-crumbs{flex:1;min-width:0}.omni-crumbs ol{display:flex;flex-wrap:wrap;align-items:center;gap:2px 0;margin:0;padding:0;list-style:none;min-width:0}.omni-crumbs li{display:flex;align-items:center;min-width:0}.omni-crumbs li+li:before{content:"›";content:"›" / "";padding:0 4px;color:var(--text-dim)}.omni-crumb{max-width:16ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:1px 4px;border:0;border-radius:3px;background:transparent;font-family:JetBrains Mono,Fira Code,monospace;font-size:11px;color:var(--text-muted);cursor:pointer}.omni-crumb:hover{background:rgb(var(--rgb-fg) / .06);color:var(--text)}.omni-crumb:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:1px}.omni-crumb.is-current{color:var(--text);font-weight:600;cursor:default}.omni-layout-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.omni-layout-item{display:flex;flex-direction:column;gap:6px;padding:12px 8px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border-radius:6px;border:1px solid var(--border);text-align:center;min-height:60px;justify-content:center}.omni-layout-label{font-size:11px;font-weight:800;color:var(--text-dim)}.omni-layout-value{font-size:12px;font-weight:800;color:var(--color-accent);font-family:JetBrains Mono,monospace}.omni-locator-row{display:flex;align-items:center;gap:12px;padding:12px 16px;background:rgb(var(--rgb-well) / calc(.6 * var(--well-k)));border-radius:6px;border:1px solid var(--border);border-left:3px solid var(--color-accent);transition:all .2s;min-height:48px}.omni-locator-strategy{flex-shrink:0;font-size:11px;font-weight:800;background:rgb(var(--rgb-accent) / .05);color:var(--color-accent);padding:2px 6px;border-radius:6px}.omni-locator-value{flex:1;font-family:JetBrains Mono,monospace;font-size:11px;color:var(--text-muted);word-break:break-all;line-height:1.5}.omni-copy-btn{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:rgb(var(--rgb-fg) / .03);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-muted);cursor:pointer;transition:all .2s ease}.omni-copy-btn:hover{background:var(--color-accent);border-color:var(--color-accent);color:var(--color-on-accent)}.omni-locator-actions{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}.omni-locators-note{display:flex;align-items:flex-start;gap:6px;margin:0 0 8px;padding:8px 10px;border:1px dashed var(--border-strong);border-radius:6px;font-size:11px;line-height:1.5;color:var(--text-muted)}.omni-locators-note>svg{flex-shrink:0;margin-top:2px}.omni-match-badge{display:inline-flex;align-items:center;gap:3px;padding:1px 6px;border-radius:4px;font-size:11px;font-weight:600;border:1px solid transparent;line-height:1.4;white-space:nowrap}.omni-match-badge.unique{background:rgb(var(--rgb-success) / .12);border-color:rgb(var(--rgb-success) / .4);color:var(--color-success)}.omni-match-badge.multi{background:rgb(var(--rgb-amber) / .12);border-color:rgb(var(--rgb-amber) / .4);color:var(--amber, var(--amber))}.omni-match-badge.zero{background:rgb(var(--rgb-red) / .12);border-color:rgb(var(--rgb-red) / .4);color:var(--red, var(--red))}.omni-match-badge.unsupported{background:rgb(var(--rgb-fg) / .04);border-color:var(--border);color:var(--text-dim)}.omni-copy-btn.copied{background:var(--color-accent);border-color:var(--color-accent);color:var(--color-on-accent)}.omni-attributes-table{display:flex;flex-direction:column;gap:4px;background:#161b22b3;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:var(--radius-sm);border:1px solid var(--border);padding:8px;max-height:200px;overflow-y:auto}.omni-attr-row{display:flex;gap:8px;padding:6px 8px;border-radius:4px;transition:background .2s ease}.omni-attr-row:hover{background:rgb(var(--rgb-fg) / .03)}.omni-attr-key{width:120px;flex-shrink:0;font-size:11px;font-weight:600;color:var(--text-muted);font-family:Fira Code,monospace}.omni-attr-value{flex:1;font-size:11px;color:#e2e8f0;font-family:Fira Code,monospace;word-break:break-all}.omni-tree-content::-webkit-scrollbar,.omni-details-content::-webkit-scrollbar,.omni-attributes-table::-webkit-scrollbar{width:6px}.omni-tree-content::-webkit-scrollbar-track,.omni-details-content::-webkit-scrollbar-track,.omni-attributes-table::-webkit-scrollbar-track{background:transparent}.omni-tree-content::-webkit-scrollbar-thumb,.omni-details-content::-webkit-scrollbar-thumb,.omni-attributes-table::-webkit-scrollbar-thumb{background:var(--border);border-radius:8px}.omni-tree-content::-webkit-scrollbar-thumb:hover,.omni-details-content::-webkit-scrollbar-thumb:hover,.omni-attributes-table::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.omni-quick-actions{display:flex;flex-direction:column;gap:16px}.omni-input-group{display:flex;flex-direction:column;gap:8px}.omni-input-field{width:100%;background:rgb(var(--rgb-well) / calc(.3 * var(--well-k)));border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 12px;color:var(--text);font-size:12px;outline:none;transition:all .2s ease}.omni-input-field:focus{border-color:var(--color-accent);background:rgb(var(--rgb-well) / calc(.5 * var(--well-k)))}.omni-gestures-container{display:flex;flex-direction:column;align-items:center;gap:12px;padding:16px;background:rgb(var(--rgb-well) / calc(.2 * var(--well-k)));border-radius:var(--radius-md);border:1px solid var(--border)}.omni-dpad{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);gap:8px;width:120px;height:120px}.omni-dpad-btn{display:flex;align-items:center;justify-content:center;background:rgb(var(--rgb-fg) / .03);border:1px solid rgb(var(--rgb-fg) / .05);border-radius:8px;color:var(--text-muted);cursor:pointer;transition:all .2s ease}.omni-dpad-btn:hover{background:var(--color-accent);color:var(--color-on-accent);transform:scale(1.1)}.omni-clipboard-box{display:flex;gap:8px;align-items:center}.omni-clipboard-val{flex:1;background:#161b22b3;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid var(--border);border-radius:4px;padding:8px;font-family:Fira Code,monospace;font-size:11px;color:var(--sky-400);min-height:32px;overflow-x:auto;white-space:nowrap}.omni-details-tabs{display:flex;background:rgb(var(--rgb-well) / calc(.5 * var(--well-k)));border-bottom:1px solid var(--border);flex-shrink:0}.omni-details-tab{display:flex;align-items:center;gap:5px;flex:1;padding:10px 8px;border:none;background:transparent;color:var(--text-muted);font-size:11px;font-weight:700;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s ease;justify-content:center;min-width:0;white-space:nowrap}.omni-details-tab>svg{flex-shrink:0}.omni-details-tab>span{min-width:0;overflow:hidden;text-overflow:ellipsis}.omni-details-tab:hover:not(:disabled){color:var(--text);background:rgb(var(--rgb-fg) / .03)}.omni-details-tab.active{color:var(--color-accent);border-bottom-color:var(--color-accent);background:rgb(var(--rgb-accent) / .04)}.omni-details-tab:disabled{opacity:.3;cursor:not-allowed}.omni-locator-row{display:flex;align-items:flex-start;gap:10px;padding:10px 14px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border-radius:6px;border:1px solid var(--border);border-left:3px solid var(--color-accent);transition:all .15s;cursor:pointer}.omni-locator-row:hover{background:rgb(var(--rgb-fg) / .02);border-color:var(--color-accent)}.omni-locator-row.selected-for-code{border-color:var(--color-accent);background:rgb(var(--rgb-accent) / .06);box-shadow:none}.omni-locator-left{flex:1;display:flex;flex-direction:column;gap:4px;min-width:0}.omni-locator-top{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.omni-stability-badge{display:inline-flex;align-items:center;gap:3px;font-size:11px;font-weight:800;padding:2px 6px;border-radius:4px}.omni-stability-badge.stable{background:rgb(var(--rgb-accent) / .12);color:var(--color-accent);border:1px solid rgb(var(--rgb-accent) / .25)}.omni-stability-badge.moderate{background:rgb(var(--rgb-amber-400) / .1);color:var(--amber-400);border:1px solid rgb(var(--rgb-amber-400) / .25)}.omni-stability-badge.fragile{background:#f43f5e1a;color:#f43f5e;border:1px solid rgba(244,63,94,.25)}.omni-stability-reason{font-size:10px;color:var(--text-muted);font-style:italic;line-height:1.3}.omni-section-badge{font-size:11px;font-weight:600;background:rgb(var(--rgb-accent) / .08);color:var(--color-accent);padding:2px 6px;border-radius:4px;margin-left:6px;vertical-align:middle}.omni-inspector-container.omni-embedded{height:100%}.omni-inspector-container.omni-embedded .omni-main-content{padding:0;gap:12px}.omni-summary-panel{display:flex;flex-direction:column;gap:18px}.omni-summary-hero{display:flex;align-items:flex-start;gap:12px;padding:14px;background:rgb(var(--rgb-accent) / .04);border:1px solid rgb(var(--rgb-accent) / .15);border-radius:8px;color:var(--color-accent)}.omni-summary-hero>svg{flex-shrink:0;margin-top:2px}.omni-summary-title{font-size:13px;font-weight:700;color:var(--text);margin-bottom:2px}.omni-summary-subtitle{font-size:11px;color:var(--text-muted);line-height:1.5}.omni-summary-stats{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}.omni-summary-stat{display:flex;flex-direction:column;gap:4px;padding:10px 12px;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));border:1px solid var(--border);border-radius:6px}.omni-summary-stat__label{font-size:11px;font-weight:700;color:var(--text-dim)}.omni-summary-stat__value{font-size:14px;font-weight:700;color:var(--color-accent);font-family:JetBrains Mono,monospace;word-break:break-all}.omni-summary-roles{display:flex;flex-direction:column;gap:4px}.omni-summary-role{display:flex;align-items:center;gap:10px;padding:8px 10px;background:rgb(var(--rgb-well) / calc(.25 * var(--well-k)));border:1px solid var(--border);border-radius:6px}.omni-summary-role__name{flex:1;font-size:12px;color:var(--text)}.omni-summary-role__count{font-size:11px;font-weight:700;color:var(--color-accent);background:rgb(var(--rgb-accent) / .06);padding:2px 8px;border-radius:4px;font-family:JetBrains Mono,monospace}.omni-search-hint{display:flex;align-items:center;gap:5px;padding:4px 14px;font-size:10px;color:var(--text-muted);border-bottom:1px solid var(--border)}.omni-codegen-panel{display:flex;flex-direction:column;gap:12px}.omni-codegen-frameworks{display:flex;gap:4px;flex-wrap:wrap}.omni-fw-btn{flex:1;padding:6px 4px;background:rgb(var(--rgb-fg) / .03);border:1px solid var(--border);border-radius:6px;color:var(--text-muted);font-size:10px;font-weight:700;cursor:pointer;transition:all .15s;white-space:nowrap}.omni-fw-btn:hover{background:rgb(var(--rgb-fg) / .06);color:var(--text)}.omni-fw-btn.active{background:rgb(var(--rgb-accent) / .08);border-color:rgb(var(--rgb-accent) / .4);color:var(--color-accent)}.omni-codegen-locator-selector{display:flex;align-items:center;gap:8px}.omni-codegen-label{font-size:11px;font-weight:700;color:var(--text-muted);white-space:nowrap}.omni-codegen-output{display:flex;flex-direction:column;border-radius:8px;border:1px solid var(--border);overflow:hidden}.omni-codegen-header{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;background:rgb(var(--rgb-well) / calc(.5 * var(--well-k)));border-bottom:1px solid var(--border)}.omni-codegen-lang{font-size:11px;font-weight:700;color:var(--color-accent)}.omni-codegen-pre{margin:0;padding:14px;background:#161b22b3;color:#e2e8f0;font-family:Fira Code,JetBrains Mono,monospace;font-size:11px;line-height:1.6;overflow-x:auto;white-space:pre-wrap;overflow-wrap:anywhere}.omni-codegen-pre code{font-family:inherit;font-size:inherit;color:inherit}.omni-verify-line{display:flex;align-items:center;gap:4px;margin-top:3px;font-size:10px;line-height:1.4}.omni-verify-line.is-ok{color:var(--color-success)}.omni-verify-line.is-warn{color:var(--amber-400)}.omni-verify-line.is-error{color:var(--red-400)}.omni-locators-empty{padding:10px 12px;font-size:11px;line-height:1.6;color:var(--text);opacity:.6}.omni-tree-error{display:flex;align-items:center;gap:6px;margin:8px;padding:8px 10px;border:1px solid rgb(var(--rgb-red-400) / .35);border-radius:8px;background:rgb(var(--rgb-red-400) / .08);color:var(--red-400);font-size:11px;line-height:1.5}.omni-tree-error>span{flex:1;min-width:0}.omni-tree-error-retry{flex-shrink:0;padding:3px 8px;border:1px solid rgb(var(--rgb-red-400) / .4);border-radius:6px;background:transparent;color:inherit;font-size:11px;font-weight:700;cursor:pointer}.omni-tree-error-retry:hover{background:rgb(var(--rgb-red-400) / .15)}:root[data-theme=light] .omni-screenshot-container,:root[data-theme=light] .omni-attributes-table,:root[data-theme=light] .omni-clipboard-val{background:var(--surface-2)}:root[data-theme=light] .omni-attr-value{color:var(--text)}:root[data-theme=light] .omni-stability-badge.fragile{background:rgb(var(--rgb-red) / .08);color:var(--red);border-color:rgb(var(--rgb-red) / .25)}:root[data-theme=light] .omni-codegen-pre{background:var(--surface)}.omni-summary-role__icon{display:inline-flex;color:var(--text-muted)}.omni-capture-meta{display:flex;align-items:center;gap:6px;padding:4px 12px;color:var(--text-muted);font-size:11px}.omni-capture-source{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;text-underline-offset:3px;cursor:help}.omni-capture-meta.is-stale{margin:6px 10px 0;padding:6px 8px 6px 10px;border:1px solid rgb(var(--rgb-amber) / .35);border-radius:var(--radius-sm);background:rgb(var(--rgb-amber) / .1);color:var(--text)}.omni-capture-meta.is-stale svg{flex:none;color:var(--color-warning)}.omni-capture-meta.is-stale span{flex:1;min-width:0}.omni-capture-refresh{flex:none;height:24px;padding:0 8px;border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--surface);color:var(--text);font-size:11px;font-weight:600;cursor:pointer}.omni-capture-refresh:hover{background:var(--surface-2)}.omni-capture-refresh:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:1px}.omni-overlay.is-stale{opacity:.35}.omni-checks-panel{display:flex;flex-direction:column;gap:10px}.omni-checks-summary{display:flex;flex-wrap:wrap;gap:12px;margin:0;font-size:12px;font-weight:600}.omni-checks-summary span{display:inline-flex;align-items:center;gap:4px}.omni-checks-summary .is-pass{color:var(--color-success)}.omni-checks-summary .is-warn{color:var(--color-warning)}.omni-checks-summary .is-fail{color:var(--color-danger)}.omni-checks-list{display:flex;flex-direction:column;gap:6px;margin:0;padding:0;list-style:none}.omni-check{display:flex;align-items:flex-start;gap:8px;padding:8px 10px;border:1px solid var(--border);border-radius:6px;background:rgb(var(--rgb-well) / calc(.25 * var(--well-k)))}.omni-check-icon{display:inline-flex;flex:none;margin-top:1px;color:var(--text-muted)}.omni-check.is-pass .omni-check-icon{color:var(--color-success)}.omni-check.is-warn .omni-check-icon{color:var(--color-warning)}.omni-check.is-fail .omni-check-icon{color:var(--color-danger)}.omni-check.is-fail{border-color:var(--status-error-border)}.omni-check-body{min-width:0}.omni-check-label{color:var(--text);font-size:12px;font-weight:600}.omni-check-detail{margin-top:2px;color:var(--text-muted);font-size:11px;line-height:1.45;overflow-wrap:anywhere}.omni-tree{display:flex;flex-direction:column;min-width:0}.omni-tree-row{display:flex;align-items:center;gap:4px;height:26px;min-width:0;padding:0 8px 0 6px;border-radius:4px;font-size:12px;color:var(--text-dim);white-space:nowrap;overflow:hidden;cursor:pointer;flex-shrink:0}.omni-tree-row:hover,.omni-tree-row.is-hovered{background:rgb(var(--rgb-fg) / .05)}.omni-tree-row.is-selected{background:rgb(var(--rgb-accent) / .12);box-shadow:inset 2px 0 0 var(--color-accent)}.omni-tree-row:focus{outline:none}.omni-tree-row:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:-2px}.omni-tree-row__lead{display:flex;align-items:center;align-self:stretch;flex-shrink:0}.omni-tree-row__indent{flex-shrink:0;align-self:stretch;background-image:linear-gradient(to right,var(--border) 1px,transparent 1px);background-size:10px 100%;background-position:5px 0;background-repeat:repeat-x}.omni-tree-row__caret,.omni-tree-row__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--text-muted)}.omni-tree-row__caret{width:12px}.omni-tree-row__icon{margin-left:4px}.omni-tree-row__caret.is-locked{cursor:default;opacity:.4}.omni-tree-row__label{display:flex;flex:1 1 auto;align-items:center;min-width:0;overflow:hidden}.omni-tree-row__head{display:block;flex:0 1 auto;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.omni-tree-row__tail{display:flex;flex:0 0 auto;align-items:center;min-width:0;max-width:100%}.omni-tree-row__name{display:flex;flex:0 1 auto;align-items:center;min-width:0}.omni-tree-row__part,.omni-tree-row__type{min-width:0;overflow:hidden;text-overflow:ellipsis}.omni-tree-row__part{font-family:JetBrains Mono,Fira Code,monospace;flex:0 1 auto}.omni-tree-row__part.is-target{flex:0 0 auto;max-width:100%;color:var(--text)}.omni-tree-row__part.is-match{color:var(--color-highlight)}.omni-tree-row__part.is-current{text-decoration:underline;text-underline-offset:3px}.omni-tree-row__sep{flex:0 0 auto;padding:0 4px;color:var(--text-dim)}.omni-tree-row__type{flex:0 1 auto;margin-left:4px;font-size:11px;color:var(--text-dim)}.omni-tree-row__count{flex-shrink:0;margin-left:auto;padding-left:6px;font-family:JetBrains Mono,monospace;font-size:10px;color:var(--text-dim)}:root[data-theme=light] .omni-tree-row__part.is-match{color:var(--color-info)}:root[data-theme=light] .omni-tree-row.is-selected,:root[data-theme=light] .omni-tree-row.is-selected .omni-tree-row__sep,:root[data-theme=light] .omni-tree-row.is-selected .omni-tree-row__type,:root[data-theme=light] .omni-tree-row.is-selected .omni-tree-row__count{color:var(--text-muted)}.logcat-root{display:flex;flex-direction:column;flex:1;min-height:0}.log-toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;row-gap:6px;background:color-mix(in srgb,var(--surface-2) 60%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);padding:8px 16px;border-radius:var(--radius-md) var(--radius-md) 0 0;border:1px solid var(--border);border-bottom:none}.log-filter-group,.log-actions-group{display:flex;gap:8px;align-items:center;min-width:0;flex-wrap:wrap}.log-stat-pill{font-size:11px;background:rgb(var(--rgb-accent) / .1);color:var(--color-accent);padding:3px 8px;border-radius:4px;font-weight:700;display:flex;align-items:center;gap:6px}.log-live-dot{width:8px;height:8px;border-radius:50%;background:var(--text-muted);flex-shrink:0;transition:background .3s ease}.log-live-dot.active{background:var(--color-success);box-shadow:none;animation:logcat-live-pulse 2s infinite}@keyframes logcat-live-pulse{0%,to{opacity:1;box-shadow:none}50%{opacity:.6;box-shadow:none}}.log-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;text-align:center;min-height:200px}.log-empty-title{font-family:Outfit,sans-serif;font-size:14px;font-weight:700;color:var(--text);margin:0 0 6px;letter-spacing:.02em}.log-empty-subtitle{font-size:12px;color:var(--text-muted);max-width:300px;margin:0;line-height:1.5}.logcat-query{flex:1;min-width:160px}.logcat-count{opacity:.6}.logcat-rows{flex:1;overflow-y:auto;font-family:JetBrains Mono,monospace;font-size:11.5px;line-height:1.6;padding:8px 12px}.logcat-row{display:grid;grid-template-columns:56px 70px minmax(0,150px) minmax(0,160px) 12px;gap:4px 8px;align-items:baseline;padding:1px 0}.logcat-row:hover{background:rgb(var(--rgb-fg) / .03)}.logcat-time,.logcat-pid,.logcat-pkg,.logcat-tag{color:var(--text-muted);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.logcat-tag{color:#7dd3fc}.logcat-msg{grid-column:1 / -1;padding-left:8px;color:var(--text);min-width:0;white-space:pre-wrap;overflow-wrap:anywhere}.logcat-level{font-weight:700;text-align:center;border-radius:3px}.lvl-V,.lvl-D{color:var(--text-muted)}.lvl-I{color:var(--color-accent)}.lvl-W{color:var(--amber-400)}.lvl-E,.lvl-F{color:var(--red-400)}.logcat-row.is-hit{background:color-mix(in srgb,var(--color-accent) 12%,transparent)}.logcat-row.is-active-hit{background:color-mix(in srgb,var(--color-accent) 22%,transparent);box-shadow:inset 2px 0 0 var(--color-accent)}.logcat-rows.no-wrap{overflow-x:auto}.logcat-rows.no-wrap .logcat-row{grid-template-columns:56px 70px minmax(0,150px) minmax(0,160px) 12px minmax(0,1fr);width:max-content;min-width:100%}.logcat-rows.no-wrap .logcat-msg{grid-column:auto;padding-left:0;white-space:pre;overflow:hidden;text-overflow:ellipsis}.logcat-input-wrap{position:relative;display:flex;align-items:center}.logcat-find{width:120px}.logcat-query{padding-right:22px}.logcat-input-btn{position:absolute;right:4px;display:flex;align-items:center;justify-content:center;padding:2px;border:0;border-radius:3px;background:transparent;color:var(--text-muted);cursor:pointer}.logcat-input-btn:hover{color:var(--text);background:rgb(var(--rgb-fg) / .08)}.logcat-hit-count{position:absolute;right:8px;font-size:10px;font-variant-numeric:tabular-nums;color:var(--text-muted);pointer-events:none}.dc-btn-secondary.is-recording{color:var(--red-400);border-color:color-mix(in srgb,var(--red-400) 45%,transparent);background:color-mix(in srgb,var(--red-400) 12%,transparent)}.dc-btn-secondary.is-recording svg{fill:currentColor}.logcat-icon-btn{padding:4px 6px}.logcat-icon-btn:disabled{opacity:.4;cursor:default}.logcat-row.is-synthetic .logcat-msg{color:var(--amber-400);font-style:italic}.log-live-dot.is-error{background:var(--red-400);box-shadow:none}.logcat-status-banner{display:flex;align-items:center;gap:8px;padding:8px 10px;margin-bottom:8px;border-radius:var(--radius-sm);font-family:Outfit,sans-serif;font-size:12px;line-height:1.4}.logcat-status-banner.is-denied{background:rgb(var(--rgb-red-400) / .1);border:1px solid rgb(var(--rgb-red-400) / .3);color:#fecdd3}.logcat-status-banner.is-exhausted{background:rgb(var(--rgb-amber-400) / .1);border:1px solid rgb(var(--rgb-amber-400) / .3);color:#fde68a}:root[data-theme=light] .logcat-rows{background:var(--bg);border-radius:0 0 var(--radius-md) var(--radius-md)}.actions-panel{display:flex;flex-direction:column;gap:12px}.actions-section{display:flex;flex-direction:column;gap:10px;padding:14px 16px;border:1px solid var(--border);border-radius:var(--radius-md);background:rgb(var(--rgb-well) / calc(.2 * var(--well-k)))}.actions-section-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.actions-section-title{display:flex;align-items:center;gap:8px;margin:0;color:var(--text);font-family:Inter,sans-serif;font-size:13px;font-weight:600}.actions-section-title svg{color:var(--color-accent)}.actions-section-tools{display:flex;align-items:center;gap:8px}.actions-section-tools [aria-disabled=true]{opacity:.5;cursor:not-allowed}.actions-apps-tools{display:flex;align-items:center;gap:6px}.actions-search{position:relative;flex:1;display:flex;align-items:center}.actions-search .type-input-field{padding-left:28px}.actions-search-icon{position:absolute;left:9px;color:var(--text-dim);pointer-events:none}.actions-apps-list{list-style:none;margin:0;padding:0;max-height:216px;overflow-y:auto;border:1px solid var(--border);border-radius:var(--radius-sm)}.actions-apps-list:empty{display:none}.actions-app-row{display:flex;align-items:center;gap:8px;min-height:36px;padding:0 4px 0 10px;border-bottom:1px solid var(--border)}.actions-app-row:last-child{border-bottom:none}.actions-app-row:hover{background:rgb(var(--rgb-fg) / .03)}.actions-app-id{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text);font-family:JetBrains Mono,ui-monospace,monospace;font-size:12px}.actions-app-note{color:var(--text-muted);font-size:11px}.actions-app-tools{display:flex;align-items:center;gap:2px}.actions-app-uninstall{color:var(--status-error-fg)}.actions-list-note{display:flex;align-items:center;gap:10px;margin:0;color:var(--text-muted);font-size:12px}.actions-library-menu{min-width:240px;max-height:320px;overflow-y:auto}.actions-field-row{display:flex;align-items:center;gap:8px}.actions-field-label{flex:0 0 76px;color:var(--text-muted);font-size:12px;font-weight:500}.actions-field-row .type-input-field{flex:1;min-width:0}.actions-field-row .type-input-field,.actions-search .type-input-field{height:32px;padding-top:0;padding-bottom:0}.actions-field-hint{margin:0 0 0 84px;color:var(--text-muted);font-size:11px}.actions-status{min-height:16px;margin:0;color:var(--text-muted);font-size:11px}.actions-swipe{flex-direction:row;align-items:center;justify-content:space-between}.actions-swipe-buttons{display:flex;gap:6px}.actions-confirm-text{margin:0;line-height:1.6}.actions-confirm-text code{font-family:JetBrains Mono,ui-monospace,monospace;font-size:12px;word-break:break-all}.actions-confirm-device{white-space:nowrap}