@xenon-device-management/xenon 2.11.0 → 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.
- package/lib/package.json +1 -1
- package/lib/public/assets/{AnnotationOverlay-BQPQ5bPF.js → AnnotationOverlay-Crkn72_3.js} +1 -1
- package/lib/public/assets/{ApiKeyGate-Bd7Pumwv.js → ApiKeyGate-BThVlj_j.js} +1 -1
- package/lib/public/assets/{BugReportButton-iC7fxPxl.js → BugReportButton-Dwa0GnBh.js} +1 -1
- package/lib/public/assets/DeviceMosaicView-Ccc-pOls.js +2 -0
- package/lib/public/assets/{EmptyState-wZeJbGhN.js → EmptyState-BeuTrlN_.js} +1 -1
- package/lib/public/assets/{FieldGroup-tpRfmhlE.js → FieldGroup-DBIaNxl1.js} +1 -1
- package/lib/public/assets/{FilterMenu-BZwOppId.js → FilterMenu-BgSAS6iT.js} +1 -1
- package/lib/public/assets/{Menu-CahoAx8L.js → Menu-GCbP6gYN.js} +1 -1
- package/lib/public/assets/{Modal-mcM5W_Ji.js → Modal-ByESeBRC.js} +1 -1
- package/lib/public/assets/RecordingPage-Bwyf3WMl.js +1 -0
- package/lib/public/assets/{RecordingsPage-BOez3f_9.js → RecordingsPage-7kM1rB3i.js} +2 -2
- package/lib/public/assets/{SegmentedControl-qMSiMN1d.js → SegmentedControl-B8tTU8kD.js} +1 -1
- package/lib/public/assets/{SettingCard-rcPtJ7HG.js → SettingCard-Clg_Ijbc.js} +1 -1
- package/lib/public/assets/{Table-J3uognu0.js → Table-CIaR0QWV.js} +1 -1
- package/lib/public/assets/{activity-_5pNSfKT.js → activity-Bengh9SD.js} +1 -1
- package/lib/public/assets/{ai-settings-DTPRbkei.js → ai-settings-G9SymiPH.js} +2 -2
- package/lib/public/assets/{api-keys-CxkIUo76.js → api-keys-CrGlbfn-.js} +1 -1
- package/lib/public/assets/{apps-Bv0pAfxz.js → apps-DIbcGVlU.js} +3 -3
- package/lib/public/assets/{arrow-left-uY7F6z1K.js → arrow-left-BtJIXXMY.js} +1 -1
- package/lib/public/assets/{arrow-right-BbAm_2Wa.js → arrow-right-zm-NagQh.js} +1 -1
- package/lib/public/assets/{arrow-up-right-x4H5NuvE.js → arrow-up-right-DdU8YEYp.js} +1 -1
- package/lib/public/assets/{auth-shell-CtMFhbnC.js → auth-shell-CHmBFmOz.js} +2 -2
- package/lib/public/assets/{builds-page-B_O5uBSZ.js → builds-page-JkzWKRpU.js} +1 -1
- package/lib/public/assets/{button-CQoMQEj_.js → button-CqhPBGRj.js} +1 -1
- package/lib/public/assets/{calendar-BZkpCqlL.js → calendar-C7eYYJTo.js} +1 -1
- package/lib/public/assets/{check-CAB6RYuc.js → check-DpbIM4E0.js} +1 -1
- package/lib/public/assets/{chevron-right-ec0unu3u.js → chevron-right-Dl4X1PRz.js} +1 -1
- package/lib/public/assets/{circle-check-Dfg-gpjg.js → circle-check-Du3sjbfV.js} +1 -1
- package/lib/public/assets/{circle-x-cbPq6Btp.js → circle-x-BSSqhpXi.js} +1 -1
- package/lib/public/assets/{clock-DU9cBLi8.js → clock-DMT60v1C.js} +1 -1
- package/lib/public/assets/{copy-VM9kWPpE.js → copy-BKNyOehd.js} +1 -1
- package/lib/public/assets/device-explorer-CHv1miyr.css +1 -0
- package/lib/public/assets/device-explorer-CoPR8DW3.js +279 -0
- package/lib/public/assets/{download-WgW4AVid.js → download-BM6Xn22t.js} +1 -1
- package/lib/public/assets/{forgot-password-BGRpjTtt.js → forgot-password-B8WqMqBT.js} +1 -1
- package/lib/public/assets/{index-DQa193-A.css → index-BTYMAqNW.css} +1 -1
- package/lib/public/assets/index-ClrpAMAT.js +219 -0
- package/lib/public/assets/{index-DNDdHt3h.js → index-DauQh6ie.js} +1 -1
- package/lib/public/assets/{input-DwiVcO3Q.js → input-CyKdLnEx.js} +1 -1
- package/lib/public/assets/{line-chart-PE5e9PeN.js → line-chart-EIBXwYGo.js} +1 -1
- package/lib/public/assets/{list-checks-Bgn9GEEO.js → list-checks-fWsgD9bI.js} +1 -1
- package/lib/public/assets/{lock-Cb7My6hc.js → lock-CVCe56TH.js} +1 -1
- package/lib/public/assets/{login-CDmyzSpl.js → login-BJ8a7yVD.js} +1 -1
- package/lib/public/assets/{maintenance-settings-Bq6pKoBt.js → maintenance-settings-DcRmTLS6.js} +1 -1
- package/lib/public/assets/{monitor-BZSwrnPV.js → monitor-Bw1YQZnL.js} +1 -1
- package/lib/public/assets/{mouse-pointer-2-BbFj8y8i.js → mouse-pointer-2-C01jbqkO.js} +1 -1
- package/lib/public/assets/{network-DpwYGB0-.js → network-CBGUjJDJ.js} +1 -1
- package/lib/public/assets/{overview-B4_IO-X8.js → overview-Cxe8aQ7C.js} +1 -1
- package/lib/public/assets/{page-header-BpLEuo7i.js → page-header-B92DKLiq.js} +1 -1
- package/lib/public/assets/play-Ck0L-0_m.js +11 -0
- package/lib/public/assets/{plus-DHZS0EGU.js → plus-Dq3tCy2N.js} +1 -1
- package/lib/public/assets/{profile-page-DsHDIq-Y.js → profile-page--dkDiKbr.js} +2 -2
- package/lib/public/assets/recording-group-store-5BYIFFN9.js +26 -0
- package/lib/public/assets/{reset-password-DuUjhw_l.js → reset-password-KYWlfjia.js} +1 -1
- package/lib/public/assets/{runbook-page-BI_ayvLd.js → runbook-page-mnsxgS1d.js} +1 -1
- package/lib/public/assets/{select-xiba9PSx.js → select-BBOIZTYm.js} +1 -1
- package/lib/public/assets/{selector-detail-redirect-Emz2obK_.js → selector-detail-redirect-CcI2j_Su.js} +1 -1
- package/lib/public/assets/{selector-health-page-zpwrgalC.js → selector-health-page-BdJb_x5L.js} +2 -2
- package/lib/public/assets/{session-detail-page-BhlTJ1Oq.js → session-detail-page-BjLaJy8z.js} +1 -1
- package/lib/public/assets/{settings-B-mabJFm.js → settings-B6cpMhsx.js} +1 -1
- package/lib/public/assets/{stat-tile-lT8WcPgu.js → stat-tile-BU9e4s36.js} +1 -1
- package/lib/public/assets/{tablet-DM8dp75P.js → tablet-hgbEwrWq.js} +1 -1
- package/lib/public/assets/{teams-CRkb5-Fe.js → teams-uiiG4hZM.js} +1 -1
- package/lib/public/assets/{trash-2-Dxgryn4o.js → trash-2-NK_Iazmg.js} +1 -1
- package/lib/public/assets/{upload-Ci0vz0BP.js → upload-BUX8TNFi.js} +1 -1
- package/lib/public/assets/{use-builds-data-DaaqMjjL.js → use-builds-data-DZszmFyl.js} +1 -1
- package/lib/public/assets/{use-password-reset-mode-BvIyZtaF.js → use-password-reset-mode-BK4B9kRC.js} +1 -1
- package/lib/public/assets/{users-CWYHk75q.js → users-BDh1xjad.js} +1 -1
- package/lib/public/assets/{users-BT8qx3ea.js → users-BU4XBbMT.js} +1 -1
- package/lib/public/assets/{video-off-BvY08g6I.js → video-off-BOjNwT4R.js} +1 -1
- package/lib/public/assets/webhook-settings-BMzyUcx5.js +1 -0
- package/lib/public/assets/{zap-qG2Li6rI.js → zap-DTWwVMUg.js} +1 -1
- package/lib/public/index.html +2 -2
- package/lib/src/device-managers/iOSTracker.js +14 -1
- package/lib/src/device-managers/ios/IOSDiscoveryService.js +9 -5
- package/lib/src/device-managers/ios/usbmuxd.js +46 -0
- package/lib/src/gateway/nodeSessionMetrics.js +5 -2
- package/lib/src/services/metrics/NodeMetricsCollector.js +4 -2
- package/lib/src/services/metrics/SessionMetricsService.js +5 -1
- package/lib/src/services/metrics/nodeMetrics.js +33 -3
- package/lib/src/sessions/RemoteSession.js +1 -1
- package/lib/test/unit/dashboard-events-metrics.spec.js +1 -0
- package/lib/test/unit/hub-node-session-metrics.spec.js +83 -13
- package/lib/test/unit/ios-usbmuxd-missing.spec.js +111 -0
- package/lib/test/unit/node-metrics-collector.spec.js +53 -0
- package/lib/test/unit/node-session-metrics-route.spec.js +2 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/lib/public/assets/DeviceMosaicView-CNdES7nm.js +0 -2
- package/lib/public/assets/RecordingPage-B4dFBndn.js +0 -11
- package/lib/public/assets/device-explorer-D2AqrrLN.css +0 -1
- package/lib/public/assets/device-explorer-ai0usQ8m.js +0 -268
- package/lib/public/assets/index-C33GjwPr.js +0 -219
- package/lib/public/assets/keycodes-CvCtpVJD.js +0 -26
- package/lib/public/assets/webhook-settings-aHIlSJFP.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as p,t as z,r as c,X as m,j as e,S as k,A as N,
|
|
1
|
+
import{c as p,t as z,r as c,X as m,j as e,S as k,A as N,Q as I,V as $}from"./index-ClrpAMAT.js";/* empty css */import{S,A as F}from"./SettingCard-Clg_Ijbc.js";import{P as B}from"./page-header-B92DKLiq.js";import{L as T}from"./lock-CVCe56TH.js";import{C as b}from"./circle-check-Du3sjbfV.js";import{A as E}from"./activity-Bengh9SD.js";import"./button-CqhPBGRj.js";import"./utils-CDN07tui.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -18,4 +18,4 @@ import{c as p,t as z,r as c,X as m,j as e,S as k,A as N,P as I,Q as $}from"./ind
|
|
|
18
18
|
*
|
|
19
19
|
* This source code is licensed under the ISC license.
|
|
20
20
|
* See the LICENSE file in the root directory of this source tree.
|
|
21
|
-
*/const
|
|
21
|
+
*/const V=[["path",{d:"M10 8h4",key:"1sr2af"}],["path",{d:"M12 21v-9",key:"17s77i"}],["path",{d:"M12 8V3",key:"13r4qs"}],["path",{d:"M17 16h4",key:"h1uq16"}],["path",{d:"M19 12V3",key:"o1uvq1"}],["path",{d:"M19 21v-5",key:"qua636"}],["path",{d:"M3 14h4",key:"bcjad9"}],["path",{d:"M5 10V3",key:"cb8scm"}],["path",{d:"M5 21v-7",key:"1w1uti"}]],O=p("sliders-vertical",V),_={aiProvider:"gemini",aiModel:"",aiBaseUrl:"",geminiModel:"",openaiModel:"",anthropicModel:"",ollamaModel:"",geminiSet:!1,openaiSet:!1,anthropicSet:!1,aiTemperature:1,aiMaxTokens:4096,aiTopP:1},X=(s,i)=>s.aiProvider===i.aiProvider&&s.aiTemperature===i.aiTemperature&&s.aiMaxTokens===i.aiMaxTokens&&s.aiTopP===i.aiTopP,o=s=>{switch(s){case"gemini":return"gemini-3-flash-preview";case"openai":return"gpt-4o";case"anthropic":return"claude-sonnet-4-6";case"ollama":return"llama3";default:return"—"}},Y=s=>{switch(s){case"ollama":return"http://localhost:11434";default:return"Provider default"}},se=()=>{const{toast:s}=z(),[i,r]=c.useState(_),[h,u]=c.useState(_),[w,g]=c.useState(!0),[x,v]=c.useState(!1),[f,j]=c.useState(!1);c.useEffect(()=>{P()},[]);const P=async()=>{g(!0);try{const a=await m.getGlobalConfig(),n={aiProvider:a.aiProvider||"gemini",aiModel:a.aiModel||"",aiBaseUrl:a.aiBaseUrl||"",geminiModel:a.geminiModel||"",openaiModel:a.openaiModel||"",anthropicModel:a.anthropicModel||"",ollamaModel:a.ollamaModel||"",geminiSet:!!a.geminiSet,openaiSet:!!a.openaiSet,anthropicSet:!!a.anthropicSet,aiTemperature:typeof a.aiTemperature=="number"?a.aiTemperature:1,aiMaxTokens:typeof a.aiMaxTokens=="number"?a.aiMaxTokens:4096,aiTopP:typeof a.aiTopP=="number"?a.aiTopP:1};r(n),u(n)}catch(a){console.error("Failed to load AISettings",a),s("Failed to access AI configuration.","error")}finally{g(!1)}},C=async()=>{v(!0);try{await m.updateGlobalConfig({aiProvider:i.aiProvider,aiTemperature:i.aiTemperature,aiMaxTokens:i.aiMaxTokens,aiTopP:i.aiTopP}),u(i),s("AI engine configuration saved.","success")}catch(a){console.error("Failed to save AISettings",a),s($(a),"error")}finally{v(!1)}},A=async()=>{j(!0);const a=Date.now();try{const n=await m.testAIConfig({aiProvider:i.aiProvider}),l=Date.now()-a;n.success?s(`${n.message} (${l}ms)`,"success"):s(n.message,"error")}catch(n){s(`Connection failed: ${(n==null?void 0:n.message)||"unknown error"}`,"error")}finally{j(!1)}},d=[{id:"gemini",name:"Google Gemini",description:`${o("gemini")} — Multimodal reasoning`,icon:e.jsx("span",{className:"ai-provider-glyph",children:"G"}),isConfigured:!!i.geminiSet},{id:"openai",name:"OpenAI",description:`${o("openai")} — OpenAI v1 compatible`,icon:e.jsx(D,{size:18}),isConfigured:!!i.openaiSet},{id:"anthropic",name:"Anthropic",description:`${o("anthropic")} — Advanced analysis`,icon:e.jsx(k,{size:18}),isConfigured:!!i.anthropicSet},{id:"ollama",name:"Ollama",description:"Local / self-hosted — no API key required",icon:e.jsx(R,{size:18}),isConfigured:!!i.ollamaModel||!!i.aiModel||!!i.aiBaseUrl}],t=d.find(a=>a.id===i.aiProvider),y=d.filter(a=>a.isConfigured).length,M=!X(i,h);return w?e.jsxs("div",{className:"settings-loading",children:[e.jsx(N,{className:"animate-spin",size:32}),e.jsx("span",{children:"Synchronizing Global State..."})]}):e.jsxs("div",{className:"settings-container",children:[e.jsx(B,{icon:I,title:"AI engine",subtitle:e.jsxs(e.Fragment,{children:["All credentials and endpoints are managed via environment variables.",e.jsxs("span",{className:"page-header-subnote",children:[e.jsx(T,{size:12}),"Select the active provider from configured options below."]})]})}),e.jsx("div",{className:"settings-content",children:e.jsxs("div",{className:"settings-grid settings-grid--two-equal",children:[e.jsx(S,{icon:e.jsx(k,{size:16}),title:"Provider registry",titleExtra:e.jsxs("span",{className:`provider-count-pill ${y>0?"is-ok":"is-empty"}`,children:[y," / ",d.length," configured"]}),description:"Providers are activated via environment variables. Select a configured engine to activate.",children:e.jsx("div",{className:"provider-list",children:d.map(a=>{const n=i.aiProvider===a.id,l=a.isConfigured;return e.jsxs("button",{type:"button",className:`provider-row ${n?"is-active":""} ${l?"":"is-disabled"}`,onClick:()=>l&&r({...i,aiProvider:a.id}),disabled:!l,title:l?`Activate ${a.name}`:`Set XENON_${a.id.toUpperCase()}_API_KEY to enable`,children:[e.jsx("div",{className:"provider-row__icon",children:a.icon}),e.jsxs("div",{className:"provider-row__body",children:[e.jsx("div",{className:"provider-row__name",children:a.name}),e.jsx("div",{className:"provider-row__desc",children:a.description}),e.jsx("div",{className:"provider-row__status",children:n?e.jsxs("span",{className:"provider-status provider-status--active",children:[e.jsx(b,{size:11}),a.isConfigured?"Active":"Active — no key"]}):a.isConfigured?e.jsxs("span",{className:"provider-status provider-status--ready",children:[e.jsx(b,{size:11}),"READY"]}):e.jsxs("span",{className:"provider-status provider-status--off",children:[e.jsx(T,{size:10}),"Not set"]})})]})]},a.id)})})}),e.jsxs(S,{icon:e.jsx(L,{size:16}),title:"Runtime configuration",description:"Environmental overrides for AI model endpoints and identifiers.",children:[e.jsxs("div",{className:"ai-config-display",children:[e.jsxs("div",{className:"ai-config-row",children:[e.jsx("span",{className:"ai-config-label",children:"Active provider"}),e.jsxs("span",{className:"ai-config-value",children:[t==null?void 0:t.icon,(t==null?void 0:t.name)||"—"]})]}),e.jsxs("div",{className:"ai-config-row",children:[e.jsx("span",{className:"ai-config-label",children:"Model"}),e.jsxs("span",{className:"ai-config-value mono",children:[e.jsxs("span",{children:[i.aiProvider==="gemini"&&(i.geminiModel||i.aiModel||o("gemini")),i.aiProvider==="openai"&&(i.openaiModel||i.aiModel||o("openai")),i.aiProvider==="anthropic"&&(i.anthropicModel||i.aiModel||o("anthropic")),i.aiProvider==="ollama"&&(i.ollamaModel||i.aiModel||o("ollama"))]}),e.jsx("span",{className:"ai-config-default",children:"Default"})]})]}),e.jsxs("div",{className:"ai-config-row",children:[e.jsx("span",{className:"ai-config-label",children:"Base URL"}),e.jsxs("span",{className:"ai-config-value mono",children:[e.jsx("span",{children:i.aiBaseUrl||Y(i.aiProvider)}),!i.aiBaseUrl&&e.jsx("span",{className:"ai-config-default",children:"Default"})]})]})]}),e.jsxs("div",{className:"model-params",children:[e.jsxs("div",{className:"model-params__header",children:[e.jsx(O,{size:14}),e.jsx("span",{children:"Model Parameters"})]}),e.jsxs("div",{className:"model-param",children:[e.jsxs("div",{className:"model-param__label-row",children:[e.jsx("label",{htmlFor:"ai-temp",children:"Temperature"}),e.jsx("span",{className:"model-param__value",children:i.aiTemperature.toFixed(1)})]}),e.jsx("input",{id:"ai-temp",type:"range",min:0,max:2,step:.1,value:i.aiTemperature,onChange:a=>r({...i,aiTemperature:parseFloat(a.target.value)}),className:"model-param__slider"})]}),e.jsxs("div",{className:"model-param",children:[e.jsx("div",{className:"model-param__label-row",children:e.jsx("label",{htmlFor:"ai-max-tokens",children:"Max tokens"})}),e.jsx("div",{className:"setting-input-wrapper",children:e.jsx("input",{id:"ai-max-tokens",type:"number",min:256,step:128,value:i.aiMaxTokens,onChange:a=>r({...i,aiMaxTokens:parseInt(a.target.value,10)||0})})})]}),e.jsxs("div",{className:"model-param",children:[e.jsxs("div",{className:"model-param__label-row",children:[e.jsx("label",{htmlFor:"ai-top-p",children:"Top P"}),e.jsx("span",{className:"model-param__value",children:i.aiTopP.toFixed(2)})]}),e.jsx("input",{id:"ai-top-p",type:"range",min:0,max:1,step:.01,value:i.aiTopP,onChange:a=>r({...i,aiTopP:parseFloat(a.target.value)}),className:"model-param__slider"})]})]}),e.jsxs("button",{type:"button",className:"test-connection-btn",onClick:A,disabled:f||!(t!=null&&t.isConfigured),children:[f?e.jsx(N,{size:14,className:"animate-spin"}):e.jsx(E,{size:14}),e.jsx("span",{children:"Test Connection"})]})]})]})}),(M||x)&&e.jsx(F,{onSave:C,onDiscard:()=>r(h),isSaving:x,isDirty:M,saveLabel:"Save configuration"})]})};export{se as AISettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as le,r as a,j as e,A as $,V as g,y as oe}from"./index-C33GjwPr.js";/* empty css */import{a as L}from"./time-D-gjmE1o.js";import{T as ce,a as de,b as z,c as l,d as me,e as o}from"./Table-J3uognu0.js";import{F as m}from"./FieldGroup-tpRfmhlE.js";import{P as O}from"./page-header-BpLEuo7i.js";import{M as B}from"./Modal-mcM5W_Ji.js";import{B as u}from"./button-CQoMQEj_.js";import{I as H}from"./input-DwiVcO3Q.js";import{S as M}from"./select-xiba9PSx.js";import{P as v}from"./plus-DHZS0EGU.js";import{T as pe}from"./trash-2-Dxgryn4o.js";import{C as he}from"./check-CAB6RYuc.js";import{C as xe}from"./copy-VM9kWPpE.js";import"./index-DNDdHt3h.js";import"./utils-CDN07tui.js";const U=["read","sessions","devices","admin"],W={"7d":"7 days","30d":"30 days","90d":"90 days","1y":"1 year",never:"No expiry"},ue={"7d":7,"30d":30,"90d":90,"1y":365};function Y(i){return i==="never"?null:new Date(Date.now()+ue[i]*864e5).toISOString()}function q(i){if(!i)return"Never";const n=Date.now()-new Date(i).getTime();return n<6e4?"Just now":n<36e5?`${Math.floor(n/6e4)}m ago`:n<864e5?`${Math.floor(n/36e5)}h ago`:`${Math.floor(n/864e5)}d ago`}const Ee=()=>{const{toast:i}=le(),[n,w]=a.useState([]),[b,J]=a.useState([]),[X,N]=a.useState(!0),[G,k]=a.useState(!1),[V,d]=a.useState(!1),[r,y]=a.useState(null),[C,S]=a.useState(null),[T,_]=a.useState(!1),[p,A]=a.useState(""),[j,I]=a.useState({read:!0,sessions:!0,devices:!1,admin:!1}),[R,P]=a.useState(300),[E,D]=a.useState(""),[h,F]=a.useState("30d"),[x,K]=a.useState(!1),Q=s=>{var t;return s?((t=b.find(c=>c.id===s))==null?void 0:t.name)||s.slice(0,8):"Shared"},f=async()=>{N(!0);try{const[s,t]=await Promise.all([fetch("/xenon/api/apikeys",{credentials:"include"}),fetch("/xenon/api/teams",{credentials:"include"})]);if(s.status===403){k(!0),w([]);return}if(!s.ok)throw new Error(`HTTP ${s.status}`);w(await s.json()),t.ok&&J(await t.json()),k(!1)}catch(s){i(`Failed to load API keys: ${s.message}`,"error")}finally{N(!1)}};a.useEffect(()=>{f()},[]);const Z=()=>{A(""),I({read:!0,sessions:!0,devices:!1,admin:!1}),P(300),D(""),F("30d")},ee=async()=>{const s=U.filter(t=>j[t]);if(!p.trim()){i("Key name is required","error");return}if(s.length===0){i("Select at least one scope","error");return}K(!0);try{const t=await fetch("/xenon/api/apikeys",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:p.trim(),scopes:s,rateLimit:R,teamId:E||null,expiresAt:Y(h)})});if(!t.ok)throw new Error(`HTTP ${t.status}`);const c=await t.json();d(!1),Z(),y({name:p.trim(),raw:c.key}),await f()}catch(t){i(`Create failed: ${t.message}`,"error")}finally{K(!1)}},se=async s=>{S(s);try{const t=await fetch(`/xenon/api/apikeys/${s}`,{method:"DELETE",credentials:"include"});if(!t.ok)throw new Error(`HTTP ${t.status}`);i("Key revoked","success"),await f()}catch(t){i(`Revoke failed: ${t.message}`,"error")}finally{S(null)}},te=async s=>{try{await navigator.clipboard.writeText(s),_(!0),setTimeout(()=>_(!1),1500)}catch{i("Copy failed — select the text manually","error")}};if(X)return e.jsxs("div",{className:"settings-loading",children:[e.jsx($,{className:"animate-spin",size:32}),e.jsx("span",{children:"Loading API keys…"})]});if(G)return e.jsx("div",{className:"settings-container",children:e.jsx(O,{icon:g,title:"API keys",subtitle:e.jsxs(e.Fragment,{children:["Your key lacks the ",e.jsx("code",{children:"admin"})," scope. Ask an administrator to issue an admin key so you can manage access for other users."]})})});const ae=n.length,ie=n.filter(s=>s.scopes.includes("admin")).length,ne=n.filter(s=>s.lastUsedAt&&Date.now()-new Date(s.lastUsedAt).getTime()<864e5).length;return e.jsxs("div",{className:"settings-container",children:[e.jsx(O,{icon:g,title:"API keys",subtitle:e.jsxs(e.Fragment,{children:["Issue scoped credentials for humans (dashboard login) and machines (CI, WebDriver clients via ",e.jsx("code",{children:"xe:options.accessKey"})," + ",e.jsx("code",{children:"xe:options.token"}),"). Keys are shown only once at creation — copy the value before closing the dialog."]}),action:e.jsxs("button",{type:"button",className:"page-header-action",onClick:()=>d(!0),children:[e.jsx(v,{size:16}),e.jsx("span",{children:"Create new key"})]})}),e.jsxs("div",{className:"settings-content",children:[n.length>0&&e.jsxs("div",{className:"stat-strip",children:[e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:ae}),e.jsx("div",{className:"stat-strip__label",children:"Total keys"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value stat-strip__value--accent",children:ie}),e.jsx("div",{className:"stat-strip__label",children:"Admin scope"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:ne}),e.jsx("div",{className:"stat-strip__label",children:"Active in last 24h"})]})]}),n.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx("div",{className:"empty-state__icon",children:e.jsx(g,{size:28})}),e.jsx("h3",{className:"empty-state__title",children:"No API keys yet"}),e.jsx("p",{className:"empty-state__copy",children:"Issue your first key to authenticate WebDriver clients or CI pipelines. Keys are shown only once at creation — copy the value before closing the dialog."}),e.jsxs("button",{type:"button",className:"page-header-action empty-state__action",onClick:()=>d(!0),children:[e.jsx(v,{size:16}),e.jsx("span",{children:"Create your first key"})]})]}):e.jsx("div",{className:"data-card",children:e.jsxs(ce,{children:[e.jsx(de,{children:e.jsxs(z,{children:[e.jsx(l,{children:"Name"}),e.jsx(l,{children:"Team"}),e.jsx(l,{children:"Scopes"}),e.jsx(l,{children:"Rate limit"}),e.jsx(l,{children:"Last used"}),e.jsx(l,{children:"Created"}),e.jsx(l,{children:"Expires"}),e.jsx(l,{style:{textAlign:"right"},children:"Actions"})]})}),e.jsx(me,{children:n.map(s=>e.jsxs(z,{children:[e.jsxs(o,{children:[e.jsx("strong",{children:s.name}),e.jsx("div",{className:"row-meta-mono",children:s.id.slice(0,8)})]}),e.jsx(o,{children:e.jsx("span",{className:`pill-chip ${s.teamId?"pill-chip--team":"pill-chip--shared"}`,children:Q(s.teamId)})}),e.jsx(o,{children:e.jsx("div",{className:"scope-chips",children:s.scopes.split(",").map(t=>{const c=t.trim(),re=c==="admin";return e.jsx("span",{className:`pill-chip ${re?"pill-chip--admin":"pill-chip--scope"}`,children:c},t)})})}),e.jsxs(o,{className:"row-mono",children:[s.rateLimit,"/min"]}),e.jsx(o,{className:"row-mono",children:q(s.lastUsedAt)}),e.jsx(o,{className:"row-mono",children:q(s.createdAt)}),e.jsx(o,{className:"row-mono",children:s.expiresAt?new Date(s.expiresAt).getTime()<=Date.now()?e.jsx("span",{style:{color:"var(--red)"},children:"expired"}):L(s.expiresAt):"Never"}),e.jsx(o,{style:{textAlign:"right"},children:e.jsxs("button",{type:"button",className:"row-action row-action--danger",disabled:C===s.id,onClick:()=>{window.confirm(`Revoke "${s.name}"? Any client using this key will immediately fail.`)&&se(s.id)},children:[e.jsx(pe,{size:13}),C===s.id?"Revoking…":"Revoke"]})})]},s.id))})]})})]}),e.jsx(B,{open:V,title:"Create API key",width:520,onClose:()=>d(!1),footer:e.jsxs(e.Fragment,{children:[e.jsx(u,{variant:"secondary",onClick:()=>d(!1),disabled:x,children:"Cancel"}),e.jsxs(u,{variant:"primary",onClick:ee,disabled:x,children:[x?e.jsx($,{className:"animate-spin",size:18}):e.jsx(v,{size:18}),x?"Creating…":"Create key"]})]}),children:e.jsxs("div",{style:{display:"flex",flexDirection:"column"},children:[e.jsx(m,{label:"Name",htmlFor:"apikey-name",children:e.jsx(H,{id:"apikey-name",type:"text",value:p,onChange:s=>A(s.target.value),placeholder:"alice-laptop, ci-main, etc.",className:"w-full",autoFocus:!0})}),e.jsx(m,{label:"Scopes",description:e.jsxs(e.Fragment,{children:[e.jsx("code",{children:"admin"})," grants full access including API-key management."," ",e.jsx("code",{children:"sessions"})," is required for WebDriver sessions (",e.jsx("code",{children:"xe:options.accessKey"})," + ",e.jsx("code",{children:"xe:options.token"}),")."]}),children:e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:8},children:U.map(s=>e.jsxs("label",{style:ye,children:[e.jsx("input",{type:"checkbox",checked:j[s],onChange:t=>I({...j,[s]:t.target.checked})}),e.jsx("span",{children:s})]},s))})}),e.jsx(m,{label:"Rate limit (requests/min)",htmlFor:"apikey-ratelimit",children:e.jsx(H,{id:"apikey-ratelimit",type:"number",min:10,step:10,value:R,onChange:s=>P(parseInt(s.target.value)||300),className:"w-full"})}),e.jsx(m,{label:"Default team",description:e.jsxs(e.Fragment,{children:["Keys without a team can only reach shared-pool devices. Admins can override at session time via ",e.jsx("code",{children:"xe:options.team"}),"."]}),htmlFor:"apikey-team",children:e.jsxs(M,{id:"apikey-team",value:E,onChange:s=>D(s.target.value),className:"w-full",children:[e.jsx("option",{value:"",children:"No team (shared pool only)"}),b.map(s=>e.jsx("option",{value:s.id,children:s.name},s.id))]})}),e.jsx(m,{label:"Expires after",description:h==="never"?"Key never expires. Rotate manually when needed.":`Key will stop working on ${L(Y(h))}.`,htmlFor:"apikey-expiry",children:e.jsx(M,{id:"apikey-expiry",value:h,onChange:s=>F(s.target.value),className:"w-full",children:Object.keys(W).map(s=>e.jsx("option",{value:s,children:W[s]},s))})})]})}),e.jsx(B,{open:!!r,title:r?`Key created: ${r.name}`:"",width:560,onClose:()=>y(null),closeOnOverlayClick:!1,footer:e.jsxs(e.Fragment,{children:[e.jsxs(u,{variant:"primary",onClick:()=>r&&te(r.raw),disabled:!r,children:[T?e.jsx(he,{size:18}):e.jsx(xe,{size:18}),T?"Copied":"Copy to clipboard"]}),e.jsx(u,{variant:"secondary",onClick:()=>y(null),children:"I've saved it"})]}),children:r&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16},children:[e.jsxs("div",{style:{background:"var(--status-busy-bg)",border:"1px solid var(--status-busy-border)",borderRadius:6,padding:12,display:"flex",gap:8,alignItems:"flex-start"},children:[e.jsx(oe,{size:18,style:{flexShrink:0,marginTop:2}}),e.jsxs("div",{children:[e.jsx("strong",{children:"This key will not be shown again."})," Copy it now and store it in your password manager, CI secret store, or client config."]})]}),e.jsx("div",{style:{fontFamily:"monospace",padding:12,background:"rgb(var(--rgb-black) / 0.3)",borderRadius:6,wordBreak:"break-all",fontSize:"0.9em"},children:r.raw})]})})]})},ye={display:"flex",alignItems:"center",gap:6,padding:"6px 12px",background:"rgb(var(--rgb-white) / 0.04)",borderRadius:6,cursor:"pointer",fontFamily:"monospace",fontSize:"0.9em"};export{Ee as ApiKeys};
|
|
1
|
+
import{t as le,r as a,j as e,A as $,W as g,y as oe}from"./index-ClrpAMAT.js";/* empty css */import{a as L}from"./time-D-gjmE1o.js";import{T as ce,a as de,b as z,c as l,d as me,e as o}from"./Table-CIaR0QWV.js";import{F as m}from"./FieldGroup-DBIaNxl1.js";import{P as O}from"./page-header-B92DKLiq.js";import{M as B}from"./Modal-ByESeBRC.js";import{B as u}from"./button-CqhPBGRj.js";import{I as H}from"./input-CyKdLnEx.js";import{S as M}from"./select-BBOIZTYm.js";import{P as v}from"./plus-Dq3tCy2N.js";import{T as pe}from"./trash-2-NK_Iazmg.js";import{C as he}from"./check-DpbIM4E0.js";import{C as xe}from"./copy-BKNyOehd.js";import"./index-DauQh6ie.js";import"./utils-CDN07tui.js";const W=["read","sessions","devices","admin"],U={"7d":"7 days","30d":"30 days","90d":"90 days","1y":"1 year",never:"No expiry"},ue={"7d":7,"30d":30,"90d":90,"1y":365};function Y(i){return i==="never"?null:new Date(Date.now()+ue[i]*864e5).toISOString()}function q(i){if(!i)return"Never";const n=Date.now()-new Date(i).getTime();return n<6e4?"Just now":n<36e5?`${Math.floor(n/6e4)}m ago`:n<864e5?`${Math.floor(n/36e5)}h ago`:`${Math.floor(n/864e5)}d ago`}const Ee=()=>{const{toast:i}=le(),[n,w]=a.useState([]),[b,J]=a.useState([]),[X,N]=a.useState(!0),[G,k]=a.useState(!1),[Q,d]=a.useState(!1),[r,y]=a.useState(null),[C,S]=a.useState(null),[T,_]=a.useState(!1),[p,A]=a.useState(""),[j,I]=a.useState({read:!0,sessions:!0,devices:!1,admin:!1}),[R,P]=a.useState(300),[E,D]=a.useState(""),[h,F]=a.useState("30d"),[x,K]=a.useState(!1),V=s=>{var t;return s?((t=b.find(c=>c.id===s))==null?void 0:t.name)||s.slice(0,8):"Shared"},f=async()=>{N(!0);try{const[s,t]=await Promise.all([fetch("/xenon/api/apikeys",{credentials:"include"}),fetch("/xenon/api/teams",{credentials:"include"})]);if(s.status===403){k(!0),w([]);return}if(!s.ok)throw new Error(`HTTP ${s.status}`);w(await s.json()),t.ok&&J(await t.json()),k(!1)}catch(s){i(`Failed to load API keys: ${s.message}`,"error")}finally{N(!1)}};a.useEffect(()=>{f()},[]);const Z=()=>{A(""),I({read:!0,sessions:!0,devices:!1,admin:!1}),P(300),D(""),F("30d")},ee=async()=>{const s=W.filter(t=>j[t]);if(!p.trim()){i("Key name is required","error");return}if(s.length===0){i("Select at least one scope","error");return}K(!0);try{const t=await fetch("/xenon/api/apikeys",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:p.trim(),scopes:s,rateLimit:R,teamId:E||null,expiresAt:Y(h)})});if(!t.ok)throw new Error(`HTTP ${t.status}`);const c=await t.json();d(!1),Z(),y({name:p.trim(),raw:c.key}),await f()}catch(t){i(`Create failed: ${t.message}`,"error")}finally{K(!1)}},se=async s=>{S(s);try{const t=await fetch(`/xenon/api/apikeys/${s}`,{method:"DELETE",credentials:"include"});if(!t.ok)throw new Error(`HTTP ${t.status}`);i("Key revoked","success"),await f()}catch(t){i(`Revoke failed: ${t.message}`,"error")}finally{S(null)}},te=async s=>{try{await navigator.clipboard.writeText(s),_(!0),setTimeout(()=>_(!1),1500)}catch{i("Copy failed — select the text manually","error")}};if(X)return e.jsxs("div",{className:"settings-loading",children:[e.jsx($,{className:"animate-spin",size:32}),e.jsx("span",{children:"Loading API keys…"})]});if(G)return e.jsx("div",{className:"settings-container",children:e.jsx(O,{icon:g,title:"API keys",subtitle:e.jsxs(e.Fragment,{children:["Your key lacks the ",e.jsx("code",{children:"admin"})," scope. Ask an administrator to issue an admin key so you can manage access for other users."]})})});const ae=n.length,ie=n.filter(s=>s.scopes.includes("admin")).length,ne=n.filter(s=>s.lastUsedAt&&Date.now()-new Date(s.lastUsedAt).getTime()<864e5).length;return e.jsxs("div",{className:"settings-container",children:[e.jsx(O,{icon:g,title:"API keys",subtitle:e.jsxs(e.Fragment,{children:["Issue scoped credentials for humans (dashboard login) and machines (CI, WebDriver clients via ",e.jsx("code",{children:"xe:options.accessKey"})," + ",e.jsx("code",{children:"xe:options.token"}),"). Keys are shown only once at creation — copy the value before closing the dialog."]}),action:e.jsxs("button",{type:"button",className:"page-header-action",onClick:()=>d(!0),children:[e.jsx(v,{size:16}),e.jsx("span",{children:"Create new key"})]})}),e.jsxs("div",{className:"settings-content",children:[n.length>0&&e.jsxs("div",{className:"stat-strip",children:[e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:ae}),e.jsx("div",{className:"stat-strip__label",children:"Total keys"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value stat-strip__value--accent",children:ie}),e.jsx("div",{className:"stat-strip__label",children:"Admin scope"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:ne}),e.jsx("div",{className:"stat-strip__label",children:"Active in last 24h"})]})]}),n.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx("div",{className:"empty-state__icon",children:e.jsx(g,{size:28})}),e.jsx("h3",{className:"empty-state__title",children:"No API keys yet"}),e.jsx("p",{className:"empty-state__copy",children:"Issue your first key to authenticate WebDriver clients or CI pipelines. Keys are shown only once at creation — copy the value before closing the dialog."}),e.jsxs("button",{type:"button",className:"page-header-action empty-state__action",onClick:()=>d(!0),children:[e.jsx(v,{size:16}),e.jsx("span",{children:"Create your first key"})]})]}):e.jsx("div",{className:"data-card",children:e.jsxs(ce,{children:[e.jsx(de,{children:e.jsxs(z,{children:[e.jsx(l,{children:"Name"}),e.jsx(l,{children:"Team"}),e.jsx(l,{children:"Scopes"}),e.jsx(l,{children:"Rate limit"}),e.jsx(l,{children:"Last used"}),e.jsx(l,{children:"Created"}),e.jsx(l,{children:"Expires"}),e.jsx(l,{style:{textAlign:"right"},children:"Actions"})]})}),e.jsx(me,{children:n.map(s=>e.jsxs(z,{children:[e.jsxs(o,{children:[e.jsx("strong",{children:s.name}),e.jsx("div",{className:"row-meta-mono",children:s.id.slice(0,8)})]}),e.jsx(o,{children:e.jsx("span",{className:`pill-chip ${s.teamId?"pill-chip--team":"pill-chip--shared"}`,children:V(s.teamId)})}),e.jsx(o,{children:e.jsx("div",{className:"scope-chips",children:s.scopes.split(",").map(t=>{const c=t.trim(),re=c==="admin";return e.jsx("span",{className:`pill-chip ${re?"pill-chip--admin":"pill-chip--scope"}`,children:c},t)})})}),e.jsxs(o,{className:"row-mono",children:[s.rateLimit,"/min"]}),e.jsx(o,{className:"row-mono",children:q(s.lastUsedAt)}),e.jsx(o,{className:"row-mono",children:q(s.createdAt)}),e.jsx(o,{className:"row-mono",children:s.expiresAt?new Date(s.expiresAt).getTime()<=Date.now()?e.jsx("span",{style:{color:"var(--red)"},children:"expired"}):L(s.expiresAt):"Never"}),e.jsx(o,{style:{textAlign:"right"},children:e.jsxs("button",{type:"button",className:"row-action row-action--danger",disabled:C===s.id,onClick:()=>{window.confirm(`Revoke "${s.name}"? Any client using this key will immediately fail.`)&&se(s.id)},children:[e.jsx(pe,{size:13}),C===s.id?"Revoking…":"Revoke"]})})]},s.id))})]})})]}),e.jsx(B,{open:Q,title:"Create API key",width:520,onClose:()=>d(!1),footer:e.jsxs(e.Fragment,{children:[e.jsx(u,{variant:"secondary",onClick:()=>d(!1),disabled:x,children:"Cancel"}),e.jsxs(u,{variant:"primary",onClick:ee,disabled:x,children:[x?e.jsx($,{className:"animate-spin",size:18}):e.jsx(v,{size:18}),x?"Creating…":"Create key"]})]}),children:e.jsxs("div",{style:{display:"flex",flexDirection:"column"},children:[e.jsx(m,{label:"Name",htmlFor:"apikey-name",children:e.jsx(H,{id:"apikey-name",type:"text",value:p,onChange:s=>A(s.target.value),placeholder:"alice-laptop, ci-main, etc.",className:"w-full",autoFocus:!0})}),e.jsx(m,{label:"Scopes",description:e.jsxs(e.Fragment,{children:[e.jsx("code",{children:"admin"})," grants full access including API-key management."," ",e.jsx("code",{children:"sessions"})," is required for WebDriver sessions (",e.jsx("code",{children:"xe:options.accessKey"})," + ",e.jsx("code",{children:"xe:options.token"}),")."]}),children:e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:8},children:W.map(s=>e.jsxs("label",{style:ye,children:[e.jsx("input",{type:"checkbox",checked:j[s],onChange:t=>I({...j,[s]:t.target.checked})}),e.jsx("span",{children:s})]},s))})}),e.jsx(m,{label:"Rate limit (requests/min)",htmlFor:"apikey-ratelimit",children:e.jsx(H,{id:"apikey-ratelimit",type:"number",min:10,step:10,value:R,onChange:s=>P(parseInt(s.target.value)||300),className:"w-full"})}),e.jsx(m,{label:"Default team",description:e.jsxs(e.Fragment,{children:["Keys without a team can only reach shared-pool devices. Admins can override at session time via ",e.jsx("code",{children:"xe:options.team"}),"."]}),htmlFor:"apikey-team",children:e.jsxs(M,{id:"apikey-team",value:E,onChange:s=>D(s.target.value),className:"w-full",children:[e.jsx("option",{value:"",children:"No team (shared pool only)"}),b.map(s=>e.jsx("option",{value:s.id,children:s.name},s.id))]})}),e.jsx(m,{label:"Expires after",description:h==="never"?"Key never expires. Rotate manually when needed.":`Key will stop working on ${L(Y(h))}.`,htmlFor:"apikey-expiry",children:e.jsx(M,{id:"apikey-expiry",value:h,onChange:s=>F(s.target.value),className:"w-full",children:Object.keys(U).map(s=>e.jsx("option",{value:s,children:U[s]},s))})})]})}),e.jsx(B,{open:!!r,title:r?`Key created: ${r.name}`:"",width:560,onClose:()=>y(null),closeOnOverlayClick:!1,footer:e.jsxs(e.Fragment,{children:[e.jsxs(u,{variant:"primary",onClick:()=>r&&te(r.raw),disabled:!r,children:[T?e.jsx(he,{size:18}):e.jsx(xe,{size:18}),T?"Copied":"Copy to clipboard"]}),e.jsx(u,{variant:"secondary",onClick:()=>y(null),children:"I've saved it"})]}),children:r&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16},children:[e.jsxs("div",{style:{background:"var(--status-busy-bg)",border:"1px solid var(--status-busy-border)",borderRadius:6,padding:12,display:"flex",gap:8,alignItems:"flex-start"},children:[e.jsx(oe,{size:18,style:{flexShrink:0,marginTop:2}}),e.jsxs("div",{children:[e.jsx("strong",{children:"This key will not be shown again."})," Copy it now and store it in your password manager, CI secret store, or client config."]})]}),e.jsx("div",{style:{fontFamily:"monospace",padding:12,background:"rgb(var(--rgb-black) / 0.3)",borderRadius:6,wordBreak:"break-all",fontSize:"0.9em"},children:r.raw})]})})]})},ye={display:"flex",alignItems:"center",gap:6,padding:"6px 12px",background:"rgb(var(--rgb-white) / 0.04)",borderRadius:6,cursor:"pointer",fontFamily:"monospace",fontSize:"0.9em"};export{Ee as ApiKeys};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{c as k,j as e,r as i,A as K,t as ve,b as je,X as p,
|
|
1
|
+
import{c as k,j as e,r as i,A as K,t as ve,b as je,X as p,J as fe,q as V,z as ye,v as ge}from"./index-ClrpAMAT.js";import{f as Ne}from"./time-D-gjmE1o.js";import{c as be,B as x}from"./button-CqhPBGRj.js";import{c as ke}from"./utils-CDN07tui.js";import{P as we}from"./page-header-B92DKLiq.js";import{S as Z}from"./select-BBOIZTYm.js";import{M as J}from"./Modal-ByESeBRC.js";import{F as Q}from"./FieldGroup-DBIaNxl1.js";import{U as ee,T as q}from"./upload-BUX8TNFi.js";import{C as Ce}from"./check-DpbIM4E0.js";import{C as Ae}from"./copy-BKNyOehd.js";import{Z as Se}from"./zap-DTWwVMUg.js";import{D as ze}from"./download-BM6Xn22t.js";import{T as Me}from"./trash-2-NK_Iazmg.js";import"./index-DauQh6ie.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const Te=[["path",{d:"M12 6.528V3a1 1 0 0 1 1-1h0",key:"11qiee"}],["path",{d:"M18.237 21A15 15 0 0 0 22 11a6 6 0 0 0-10-4.472A6 6 0 0 0 2 11a15.1 15.1 0 0 0 3.763 10 3 3 0 0 0 3.648.648 5.5 5.5 0 0 1 5.178 0A3 3 0 0 0 18.237 21",key:"110c12"}]],
|
|
6
|
+
*/const Te=[["path",{d:"M12 6.528V3a1 1 0 0 1 1-1h0",key:"11qiee"}],["path",{d:"M18.237 21A15 15 0 0 0 22 11a6 6 0 0 0-10-4.472A6 6 0 0 0 2 11a15.1 15.1 0 0 0 3.763 10 3 3 0 0 0 3.648.648 5.5 5.5 0 0 1 5.178 0A3 3 0 0 0 18.237 21",key:"110c12"}]],H=k("apple",Te);/**
|
|
7
7
|
* @license lucide-react v0.555.0 - ISC
|
|
8
8
|
*
|
|
9
9
|
* This source code is licensed under the ISC license.
|
|
@@ -23,4 +23,4 @@ import{c as k,j as e,r as i,A as K,t as ve,b as je,X as p,H as fe,q as V,z as ye
|
|
|
23
23
|
*
|
|
24
24
|
* This source code is licensed under the ISC license.
|
|
25
25
|
* See the LICENSE file in the root directory of this source tree.
|
|
26
|
-
*/const Ue=[["path",{d:"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z",key:"m3kijz"}],["path",{d:"m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z",key:"1fmvmk"}],["path",{d:"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0",key:"1f8sc4"}],["path",{d:"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5",key:"qeys4"}]],W=k("rocket",Ue),Re=be("badge-base",{variants:{variant:{default:"badge-variant-default",success:"badge-variant-success",warning:"badge-variant-warning",error:"badge-variant-error",outline:"badge-variant-outline",secondary:"badge-variant-secondary"}},defaultVariants:{variant:"default"}});function Y({className:r,variant:c,...n}){return e.jsx("div",{className:ke(Re({variant:c}),r),...n})}const ae=({id:r,value:c,teams:n,onChange:m,disabled:h})=>e.jsxs(Z,{id:r,value:c,disabled:h,className:"w-full",onChange:l=>m(l.target.value),children:[e.jsx("option",{value:"",children:"Shared"}),n.map(l=>e.jsx("option",{value:l.id,children:l.name},l.id))]}),te="Members of the team can see and run it. Shared apps are open to everyone.",_e=({open:r,teams:c,teamId:n,onTeamChange:m,onChooseFile:h,onClose:l})=>e.jsx(J,{open:r,onClose:l,title:"Upload app",footer:e.jsxs(e.Fragment,{children:[e.jsx(x,{variant:"secondary",onClick:l,children:"Cancel"}),e.jsxs(x,{variant:"primary",onClick:h,children:[e.jsx(ee,{size:14,className:"mr-1"}),"Choose file…"]})]}),children:e.jsx(Q,{label:"Team",htmlFor:"upload-app-team",description:te,children:e.jsx(ae,{id:"upload-app-team",value:n,teams:c,onChange:m})})}),Le=({app:r,teams:c,onMove:n,onClose:m})=>{const[h,l]=i.useState(""),[d,f]=i.useState(!1),[y,u]=i.useState(null);i.useEffect(()=>{l((r==null?void 0:r.teamId)??""),u(null)},[r]);const g=async()=>{f(!0),u(null);try{await n(h||null)}catch(v){u((v==null?void 0:v.message)||"Could not move the app")}finally{f(!1)}};return e.jsxs(J,{open:!!r,onClose:m,title:"Move to team",footer:e.jsxs(e.Fragment,{children:[e.jsx(x,{variant:"secondary",onClick:m,disabled:d,children:"Cancel"}),e.jsxs(x,{variant:"primary",onClick:g,disabled:d,children:[d?e.jsx(K,{size:14,className:"mr-1 animate-spin"}):e.jsx(se,{size:14,className:"mr-1"}),"Move"]})]}),children:[e.jsx("p",{className:"app-move-name",children:r==null?void 0:r.name}),e.jsx(Q,{label:"Team",htmlFor:"move-app-team",description:te,error:y??void 0,children:e.jsx(ae,{id:"move-app-team",value:h,teams:c,onChange:l,disabled:d})})]})},X=r=>{var c;return((c=r.team)==null?void 0:c.name)??(r.teamId?String(r.teamId).slice(0,8):"Shared")},ss=()=>{const{toast:r,removeToast:c}=ve(),[n,m]=i.useState([]),[h,l]=i.useState([]),[d,f]=i.useState(!1),[y,u]=i.useState(""),[g,v]=i.useState(!1),[re,R]=i.useState(null),[w,_]=i.useState({android:!0,ios:!0}),[S,ie]=i.useState("desc"),[C,z]=i.useState(null),[M,T]=i.useState(""),D=i.useRef(null),{me:j}=je(),N=(j==null?void 0:j.role)==="ADMIN"||(j==null?void 0:j.role)==="SUPER_ADMIN",[L,B]=i.useState([]),[ne,I]=i.useState(!1),[E,G]=i.useState(""),[F,$]=i.useState(null),b=i.useCallback(async()=>{f(!0);try{const s=await p.getApps();m(Array.isArray(s)?s:[])}catch(s){console.error("Failed to fetch apps",s)}finally{f(!1)}},[]),U=i.useCallback(async()=>{try{const s=await p.getDevices();l(Array.isArray(s)?s:[])}catch(s){console.error("Failed to fetch devices",s)}},[]);i.useEffect(()=>{b(),U();const s=setInterval(U,1e4);return()=>clearInterval(s)},[b,U]),i.useEffect(()=>{N&&p.listTeams().then(B).catch(()=>B([]))},[N]);const O=()=>{var s;N?(G(""),I(!0)):(s=D.current)==null||s.click()},le=async s=>{F&&(await p.setAppTeam(F.id,s),r(s?"App moved to team":"App shared with everyone","success"),$(null),await b())},ce=async s=>{var o;const a=(o=s.target.files)==null?void 0:o[0];if(!a)return;const t=N&&E?E:null;I(!1),v(!0);try{await p.uploadApp(a,t),await b()}catch(ue){console.error("Upload failed",ue)}finally{v(!1),s.target&&(s.target.value="")}},oe=async(s,a)=>{if(window.confirm(`Permanently remove artifact "${a}"?`))try{await p.deleteApp(s),m(t=>t.filter(o=>o.id!==s))}catch(t){console.error("Delete failed",t)}},de=(s,a)=>{navigator.clipboard.writeText(s),R(`${a}-${s}`),setTimeout(()=>R(null),2e3)},me=async(s,a)=>{const t=r(`Deploying app to ${a}...`,"loading",0);try{const o=await p.installRepositoryApp(a,s);o.success?(r("App deployed successfully","success"),z(null),T("")):r(`Deployment failed: ${o.error}`,"error")}catch(o){r(`Execution Error: ${o.message}`,"error")}finally{c(t)}},A=n.filter(s=>{const a=s.name.toLowerCase().includes(y.toLowerCase())||s.packageName&&s.packageName.toLowerCase().includes(y.toLowerCase()),t=w.android&&s.platform==="android"||w.ios&&s.platform==="ios";return a&&t}).sort((s,a)=>{const t=new Date(s.createdAt).getTime(),o=new Date(a.createdAt).getTime();return S==="desc"?o-t:t-o}),he=s=>{if(!s)return"0 B";const a=1024,t=Math.floor(Math.log(s)/Math.log(a));return parseFloat((s/Math.pow(a,t)).toFixed(1))+" "+["B","KB","MB","GB"][t]},pe=s=>Ne(s),P=s=>{_(a=>({...a,[s]:!a[s]}))},xe=s=>{const a=s.toLowerCase();return a.includes("wda-signed")||a.includes("wda-resign")||a.includes("webdriveragent")};return e.jsxs("div",{className:"apps-container device-explorer-container",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsx(we,{icon:fe,title:"Apps",subtitle:"Signed builds available for installation across your device fleet."}),e.jsxs("div",{className:"device-explorer-header-container",children:[e.jsxs("div",{className:"device-explorer-header-left-container",children:[e.jsx("div",{className:"device-explorer-header-entry",children:e.jsxs("div",{className:"device-explorer-header-value",children:[e.jsxs("button",{className:`device-explorer-header__platform-btn ${w.android&&"selected"}`,onClick:()=>P("android"),children:[e.jsx(V,{size:18,color:"currentColor"})," Android"]}),e.jsxs("button",{className:`device-explorer-header__platform-btn ${w.ios&&"selected"}`,onClick:()=>P("ios"),children:[e.jsx(q,{size:18,color:"currentColor"})," iOS"]})]})}),e.jsx("div",{className:"device-explorer-header-entry",children:e.jsx("div",{className:"device-explorer-header-value",children:e.jsxs("div",{className:"device-explorer-search-wrapper",children:[e.jsx(ye,{size:16,color:"#94a3b8",className:"device-explorer-search-icon"}),e.jsx("input",{type:"text",className:"device-explorer-header-text-filter",placeholder:"Filter by bundle or name...",value:y,onChange:s=>u(s.target.value)})]})})}),e.jsx("div",{className:"device-explorer-header-filter-count",children:e.jsxs(Y,{variant:"secondary",children:[e.jsx("span",{className:"font-bold",children:A.length})," of"," ",e.jsx("span",{className:"font-bold",children:n.length})," ",n.length===1?"artifact":"artifacts"]})})]}),e.jsxs("div",{className:"device-explorer-header-right-container",children:[e.jsx("button",{className:"icon-btn-secondary sort-btn",onClick:()=>ie(s=>s==="desc"?"asc":"desc"),title:S==="desc"?"Newest First":"Oldest First",children:S==="desc"?e.jsx(Ie,{size:18}):e.jsx($e,{size:18})}),e.jsxs(x,{size:"sm",variant:"secondary",onClick:()=>b(),disabled:d,children:[e.jsx(K,{size:14,className:`mr-1 ${d&&"animate-spin"}`}),"Refresh"]}),e.jsx("input",{ref:D,type:"file",accept:".apk,.ipa",onChange:ce,hidden:!0}),e.jsxs(x,{size:"sm",variant:"primary",onClick:O,disabled:g,children:[e.jsx(ee,{size:14,className:"mr-1"}),"Upload app"]})]})]}),e.jsx("main",{className:"apps-registry-content",children:d&&n.length===0?e.jsxs("div",{className:"empty-data-vignette",children:[e.jsx("div",{className:"processing-loader"}),e.jsx("p",{className:"text-muted text-xs font-bold tracking-widest",children:"SYNCING REGISTRY..."})]}):e.jsxs(e.Fragment,{children:[A.length>0&&e.jsxs("div",{className:"registry-table-header",children:[e.jsx("div",{children:"Artifact bundle"}),e.jsx("div",{children:"Version"}),e.jsx("div",{children:"Size"}),e.jsx("div",{children:"Team"}),e.jsx("div",{children:"Registry date"}),e.jsx("div",{style:{textAlign:"right"},children:"Management"})]}),e.jsx("div",{className:"registry-list",children:A.map(s=>{const a=h.filter(t=>t.platform===s.platform&&!t.busy&&!t.offline);return e.jsxs("div",{className:`artifact-row ${s.platform}`,children:[e.jsxs("div",{className:"col-app-info",children:[e.jsx("div",{className:"app-platform-badge",children:s.platform==="android"?e.jsx(V,{size:18}):e.jsx(q,{size:18})}),e.jsxs("div",{className:"app-text-block",children:[e.jsxs("div",{className:"app-display-name",title:s.name,children:[s.name,xe(s.name)&&e.jsx(Y,{variant:"outline",className:"ml-2 text-[10px] h-4 py-0 border-primary text-primary",children:"WDA"})]}),e.jsxs("div",{className:"app-package-id",children:[e.jsx("code",{children:s.packageName||"internal.bundle"}),s.packageName&&e.jsx("div",{className:"copy-hint",title:`Copy ${s.packageName}`,onClick:()=>de(s.packageName,"pkg"),children:re===`pkg-${s.packageName}`?e.jsx(Ce,{size:10,className:"text-primary"}):e.jsx(Ae,{size:10})})]})]})]}),e.jsx("div",{className:"col-version",children:s.version||"v1.0.0"}),e.jsx("div",{className:"col-size",children:he(s.size)}),e.jsx("div",{className:"col-team",title:X(s),children:X(s)}),e.jsx("div",{className:"col-timestamp",children:pe(s.createdAt)}),e.jsxs("div",{className:"col-actions",children:[e.jsxs("div",{className:"deploy-anchor",children:[e.jsx("button",{className:`instant-deploy-trigger ${C===s.id&&"active"}`,onClick:()=>{C===s.id?(z(null),T("")):z(s.id)},children:C===s.id?e.jsxs(e.Fragment,{children:[e.jsx(ge,{size:12})," CANCEL"]}):e.jsxs(e.Fragment,{children:[e.jsx(Se,{size:12})," Deploy"]})}),C===s.id&&e.jsx("div",{className:"deployment-flyout",children:a.length>0?e.jsxs("div",{className:"deploy-actions-group",children:[e.jsxs(Z,{selectSize:"sm",className:"min-w-[280px]",autoFocus:!0,value:M,onChange:t=>T(t.target.value),children:[e.jsx("option",{value:"",children:"SELECT TARGET..."}),a.map(t=>e.jsxs("option",{value:t.udid,children:[t.name," (",t.udid,")"]},t.udid))]}),e.jsx("button",{className:"confirm-deploy-btn",disabled:!M,onClick:()=>me(s.id,M),title:"Confirm deployment",children:e.jsx(W,{size:14})})]}):e.jsx("div",{className:"target-device-select empty",children:"NO TARGETS"})})]}),e.jsx("button",{className:"utility-icon-btn",onClick:()=>window.open(`/xenon/api/apps/${s.id}/download`,"_blank"),children:e.jsx(ze,{size:14})}),N&&e.jsx("button",{className:"utility-icon-btn","aria-label":`Move ${s.name} to team`,title:"Move to team",onClick:()=>$(s),children:e.jsx(se,{size:14})}),e.jsx("button",{className:"utility-icon-btn danger",onClick:()=>oe(s.id,s.name),children:e.jsx(Me,{size:14})})]})]},s.id)})}),A.length===0&&n.length>0&&!d&&e.jsxs("div",{className:"empty-registry-technical",children:[e.jsx("div",{className:"empty-icon-container",children:e.jsx(H,{size:48,className:"text-primary opacity-40"})}),e.jsx("h2",{className:"empty-title brand-font",children:"No matching artifacts"}),e.jsxs("p",{className:"empty-description",children:[n.length," ",n.length===1?"artifact is":"artifacts are"," registered, but none match the current filter."]}),e.jsx("div",{className:"empty-actions",children:e.jsx(x,{size:"sm",variant:"default",onClick:()=>{u(""),_({android:!0,ios:!0})},children:"Clear filters"})})]}),n.length===0&&!d&&e.jsxs("div",{className:"empty-registry-technical",children:[e.jsx("div",{className:"empty-icon-container",children:e.jsx(H,{size:48,className:"text-primary opacity-40 animate-pulse"})}),e.jsx("h2",{className:"empty-title brand-font",children:"No apps yet"}),e.jsxs("p",{className:"empty-description",children:["Upload ",e.jsx("code",{className:"text-primary",children:".apk"})," or"," ",e.jsx("code",{className:"text-primary",children:".ipa"})," artifacts to enable versioned installs across your device fleet."]}),e.jsx("div",{className:"empty-actions",children:e.jsx("button",{type:"button",className:"upload-trigger-massive",onClick:O,disabled:g,children:e.jsxs("span",{className:"massive-upload-content",children:[e.jsx(W,{size:24,className:"mb-2"}),e.jsx("span",{children:"Upload your first app"})]})})})]})]})}),e.jsx(_e,{open:ne,teams:L,teamId:E,onTeamChange:G,onChooseFile:()=>{var s;return(s=D.current)==null?void 0:s.click()},onClose:()=>I(!1)}),e.jsx(Le,{app:F,teams:L,onMove:le,onClose:()=>$(null)}),g&&e.jsx("div",{className:"upload-overlay-technical",children:e.jsxs("div",{className:"upload-card-technical",children:[e.jsx("div",{className:"processing-loader"}),e.jsx("h2",{className:"brand-font",style:{fontSize:"20px",marginBottom:"8px"},children:"Artifact ingestion"}),e.jsx("p",{className:"text-muted text-xs",children:"VERIFYING CHECKSUM & DEPLOYING TO REGISTRY..."})]})})]})};export{ss as default};
|
|
26
|
+
*/const Ue=[["path",{d:"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z",key:"m3kijz"}],["path",{d:"m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z",key:"1fmvmk"}],["path",{d:"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0",key:"1f8sc4"}],["path",{d:"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5",key:"qeys4"}]],W=k("rocket",Ue),Re=be("badge-base",{variants:{variant:{default:"badge-variant-default",success:"badge-variant-success",warning:"badge-variant-warning",error:"badge-variant-error",outline:"badge-variant-outline",secondary:"badge-variant-secondary"}},defaultVariants:{variant:"default"}});function Y({className:r,variant:c,...n}){return e.jsx("div",{className:ke(Re({variant:c}),r),...n})}const ae=({id:r,value:c,teams:n,onChange:m,disabled:h})=>e.jsxs(Z,{id:r,value:c,disabled:h,className:"w-full",onChange:l=>m(l.target.value),children:[e.jsx("option",{value:"",children:"Shared"}),n.map(l=>e.jsx("option",{value:l.id,children:l.name},l.id))]}),te="Members of the team can see and run it. Shared apps are open to everyone.",_e=({open:r,teams:c,teamId:n,onTeamChange:m,onChooseFile:h,onClose:l})=>e.jsx(J,{open:r,onClose:l,title:"Upload app",footer:e.jsxs(e.Fragment,{children:[e.jsx(x,{variant:"secondary",onClick:l,children:"Cancel"}),e.jsxs(x,{variant:"primary",onClick:h,children:[e.jsx(ee,{size:14,className:"mr-1"}),"Choose file…"]})]}),children:e.jsx(Q,{label:"Team",htmlFor:"upload-app-team",description:te,children:e.jsx(ae,{id:"upload-app-team",value:n,teams:c,onChange:m})})}),Le=({app:r,teams:c,onMove:n,onClose:m})=>{const[h,l]=i.useState(""),[d,f]=i.useState(!1),[y,u]=i.useState(null);i.useEffect(()=>{l((r==null?void 0:r.teamId)??""),u(null)},[r]);const g=async()=>{f(!0),u(null);try{await n(h||null)}catch(v){u((v==null?void 0:v.message)||"Could not move the app")}finally{f(!1)}};return e.jsxs(J,{open:!!r,onClose:m,title:"Move to team",footer:e.jsxs(e.Fragment,{children:[e.jsx(x,{variant:"secondary",onClick:m,disabled:d,children:"Cancel"}),e.jsxs(x,{variant:"primary",onClick:g,disabled:d,children:[d?e.jsx(K,{size:14,className:"mr-1 animate-spin"}):e.jsx(se,{size:14,className:"mr-1"}),"Move"]})]}),children:[e.jsx("p",{className:"app-move-name",children:r==null?void 0:r.name}),e.jsx(Q,{label:"Team",htmlFor:"move-app-team",description:te,error:y??void 0,children:e.jsx(ae,{id:"move-app-team",value:h,teams:c,onChange:l,disabled:d})})]})},X=r=>{var c;return((c=r.team)==null?void 0:c.name)??(r.teamId?String(r.teamId).slice(0,8):"Shared")},ss=()=>{const{toast:r,removeToast:c}=ve(),[n,m]=i.useState([]),[h,l]=i.useState([]),[d,f]=i.useState(!1),[y,u]=i.useState(""),[g,v]=i.useState(!1),[re,R]=i.useState(null),[w,_]=i.useState({android:!0,ios:!0}),[S,ie]=i.useState("desc"),[C,z]=i.useState(null),[M,T]=i.useState(""),D=i.useRef(null),{me:j}=je(),N=(j==null?void 0:j.role)==="ADMIN"||(j==null?void 0:j.role)==="SUPER_ADMIN",[L,B]=i.useState([]),[ne,I]=i.useState(!1),[E,G]=i.useState(""),[F,$]=i.useState(null),b=i.useCallback(async()=>{f(!0);try{const s=await p.getApps();m(Array.isArray(s)?s:[])}catch(s){console.error("Failed to fetch apps",s)}finally{f(!1)}},[]),U=i.useCallback(async()=>{try{const s=await p.getDevices();l(Array.isArray(s)?s:[])}catch(s){console.error("Failed to fetch devices",s)}},[]);i.useEffect(()=>{b(),U();const s=setInterval(U,1e4);return()=>clearInterval(s)},[b,U]),i.useEffect(()=>{N&&p.listTeams().then(B).catch(()=>B([]))},[N]);const O=()=>{var s;N?(G(""),I(!0)):(s=D.current)==null||s.click()},le=async s=>{F&&(await p.setAppTeam(F.id,s),r(s?"App moved to team":"App shared with everyone","success"),$(null),await b())},ce=async s=>{var o;const a=(o=s.target.files)==null?void 0:o[0];if(!a)return;const t=N&&E?E:null;I(!1),v(!0);try{await p.uploadApp(a,t),await b()}catch(ue){console.error("Upload failed",ue)}finally{v(!1),s.target&&(s.target.value="")}},oe=async(s,a)=>{if(window.confirm(`Permanently remove artifact "${a}"?`))try{await p.deleteApp(s),m(t=>t.filter(o=>o.id!==s))}catch(t){console.error("Delete failed",t)}},de=(s,a)=>{navigator.clipboard.writeText(s),R(`${a}-${s}`),setTimeout(()=>R(null),2e3)},me=async(s,a)=>{const t=r(`Deploying app to ${a}...`,"loading",0);try{const o=await p.installRepositoryApp(a,s);o.success?(r("App deployed successfully","success"),z(null),T("")):r(`Deployment failed: ${o.error}`,"error")}catch(o){r(`Execution Error: ${o.message}`,"error")}finally{c(t)}},A=n.filter(s=>{const a=s.name.toLowerCase().includes(y.toLowerCase())||s.packageName&&s.packageName.toLowerCase().includes(y.toLowerCase()),t=w.android&&s.platform==="android"||w.ios&&s.platform==="ios";return a&&t}).sort((s,a)=>{const t=new Date(s.createdAt).getTime(),o=new Date(a.createdAt).getTime();return S==="desc"?o-t:t-o}),he=s=>{if(!s)return"0 B";const a=1024,t=Math.floor(Math.log(s)/Math.log(a));return parseFloat((s/Math.pow(a,t)).toFixed(1))+" "+["B","KB","MB","GB"][t]},pe=s=>Ne(s),P=s=>{_(a=>({...a,[s]:!a[s]}))},xe=s=>{const a=s.toLowerCase();return a.includes("wda-signed")||a.includes("wda-resign")||a.includes("webdriveragent")};return e.jsxs("div",{className:"apps-container device-explorer-container",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsx(we,{icon:fe,title:"Apps",subtitle:"Signed builds available for installation across your device fleet."}),e.jsxs("div",{className:"device-explorer-header-container",children:[e.jsxs("div",{className:"device-explorer-header-left-container",children:[e.jsx("div",{className:"device-explorer-header-entry",children:e.jsxs("div",{className:"device-explorer-header-value",children:[e.jsxs("button",{className:`device-explorer-header__platform-btn ${w.android&&"selected"}`,onClick:()=>P("android"),children:[e.jsx(V,{size:18,color:"currentColor"})," Android"]}),e.jsxs("button",{className:`device-explorer-header__platform-btn ${w.ios&&"selected"}`,onClick:()=>P("ios"),children:[e.jsx(H,{size:18,color:"currentColor"})," iOS"]})]})}),e.jsx("div",{className:"device-explorer-header-entry",children:e.jsx("div",{className:"device-explorer-header-value",children:e.jsxs("div",{className:"device-explorer-search-wrapper",children:[e.jsx(ye,{size:16,color:"#94a3b8",className:"device-explorer-search-icon"}),e.jsx("input",{type:"text",className:"device-explorer-header-text-filter",placeholder:"Filter by bundle or name...",value:y,onChange:s=>u(s.target.value)})]})})}),e.jsx("div",{className:"device-explorer-header-filter-count",children:e.jsxs(Y,{variant:"secondary",children:[e.jsx("span",{className:"font-bold",children:A.length})," of"," ",e.jsx("span",{className:"font-bold",children:n.length})," ",n.length===1?"artifact":"artifacts"]})})]}),e.jsxs("div",{className:"device-explorer-header-right-container",children:[e.jsx("button",{className:"icon-btn-secondary sort-btn",onClick:()=>ie(s=>s==="desc"?"asc":"desc"),title:S==="desc"?"Newest First":"Oldest First",children:S==="desc"?e.jsx(Ie,{size:18}):e.jsx($e,{size:18})}),e.jsxs(x,{size:"sm",variant:"secondary",onClick:()=>b(),disabled:d,children:[e.jsx(K,{size:14,className:`mr-1 ${d&&"animate-spin"}`}),"Refresh"]}),e.jsx("input",{ref:D,type:"file",accept:".apk,.ipa",onChange:ce,hidden:!0}),e.jsxs(x,{size:"sm",variant:"primary",onClick:O,disabled:g,children:[e.jsx(ee,{size:14,className:"mr-1"}),"Upload app"]})]})]}),e.jsx("main",{className:"apps-registry-content",children:d&&n.length===0?e.jsxs("div",{className:"empty-data-vignette",children:[e.jsx("div",{className:"processing-loader"}),e.jsx("p",{className:"text-muted text-xs font-bold tracking-widest",children:"SYNCING REGISTRY..."})]}):e.jsxs(e.Fragment,{children:[A.length>0&&e.jsxs("div",{className:"registry-table-header",children:[e.jsx("div",{children:"Artifact bundle"}),e.jsx("div",{children:"Version"}),e.jsx("div",{children:"Size"}),e.jsx("div",{children:"Team"}),e.jsx("div",{children:"Registry date"}),e.jsx("div",{style:{textAlign:"right"},children:"Management"})]}),e.jsx("div",{className:"registry-list",children:A.map(s=>{const a=h.filter(t=>t.platform===s.platform&&!t.busy&&!t.offline);return e.jsxs("div",{className:`artifact-row ${s.platform}`,children:[e.jsxs("div",{className:"col-app-info",children:[e.jsx("div",{className:"app-platform-badge",children:s.platform==="android"?e.jsx(V,{size:18}):e.jsx(H,{size:18})}),e.jsxs("div",{className:"app-text-block",children:[e.jsxs("div",{className:"app-display-name",title:s.name,children:[s.name,xe(s.name)&&e.jsx(Y,{variant:"outline",className:"ml-2 text-[10px] h-4 py-0 border-primary text-primary",children:"WDA"})]}),e.jsxs("div",{className:"app-package-id",children:[e.jsx("code",{children:s.packageName||"internal.bundle"}),s.packageName&&e.jsx("div",{className:"copy-hint",title:`Copy ${s.packageName}`,onClick:()=>de(s.packageName,"pkg"),children:re===`pkg-${s.packageName}`?e.jsx(Ce,{size:10,className:"text-primary"}):e.jsx(Ae,{size:10})})]})]})]}),e.jsx("div",{className:"col-version",children:s.version||"v1.0.0"}),e.jsx("div",{className:"col-size",children:he(s.size)}),e.jsx("div",{className:"col-team",title:X(s),children:X(s)}),e.jsx("div",{className:"col-timestamp",children:pe(s.createdAt)}),e.jsxs("div",{className:"col-actions",children:[e.jsxs("div",{className:"deploy-anchor",children:[e.jsx("button",{className:`instant-deploy-trigger ${C===s.id&&"active"}`,onClick:()=>{C===s.id?(z(null),T("")):z(s.id)},children:C===s.id?e.jsxs(e.Fragment,{children:[e.jsx(ge,{size:12})," CANCEL"]}):e.jsxs(e.Fragment,{children:[e.jsx(Se,{size:12})," Deploy"]})}),C===s.id&&e.jsx("div",{className:"deployment-flyout",children:a.length>0?e.jsxs("div",{className:"deploy-actions-group",children:[e.jsxs(Z,{selectSize:"sm",className:"min-w-[280px]",autoFocus:!0,value:M,onChange:t=>T(t.target.value),children:[e.jsx("option",{value:"",children:"SELECT TARGET..."}),a.map(t=>e.jsxs("option",{value:t.udid,children:[t.name," (",t.udid,")"]},t.udid))]}),e.jsx("button",{className:"confirm-deploy-btn",disabled:!M,onClick:()=>me(s.id,M),title:"Confirm deployment",children:e.jsx(W,{size:14})})]}):e.jsx("div",{className:"target-device-select empty",children:"NO TARGETS"})})]}),e.jsx("button",{className:"utility-icon-btn",onClick:()=>window.open(`/xenon/api/apps/${s.id}/download`,"_blank"),children:e.jsx(ze,{size:14})}),N&&e.jsx("button",{className:"utility-icon-btn","aria-label":`Move ${s.name} to team`,title:"Move to team",onClick:()=>$(s),children:e.jsx(se,{size:14})}),e.jsx("button",{className:"utility-icon-btn danger",onClick:()=>oe(s.id,s.name),children:e.jsx(Me,{size:14})})]})]},s.id)})}),A.length===0&&n.length>0&&!d&&e.jsxs("div",{className:"empty-registry-technical",children:[e.jsx("div",{className:"empty-icon-container",children:e.jsx(q,{size:48,className:"text-primary opacity-40"})}),e.jsx("h2",{className:"empty-title brand-font",children:"No matching artifacts"}),e.jsxs("p",{className:"empty-description",children:[n.length," ",n.length===1?"artifact is":"artifacts are"," registered, but none match the current filter."]}),e.jsx("div",{className:"empty-actions",children:e.jsx(x,{size:"sm",variant:"default",onClick:()=>{u(""),_({android:!0,ios:!0})},children:"Clear filters"})})]}),n.length===0&&!d&&e.jsxs("div",{className:"empty-registry-technical",children:[e.jsx("div",{className:"empty-icon-container",children:e.jsx(q,{size:48,className:"text-primary opacity-40 animate-pulse"})}),e.jsx("h2",{className:"empty-title brand-font",children:"No apps yet"}),e.jsxs("p",{className:"empty-description",children:["Upload ",e.jsx("code",{className:"text-primary",children:".apk"})," or"," ",e.jsx("code",{className:"text-primary",children:".ipa"})," artifacts to enable versioned installs across your device fleet."]}),e.jsx("div",{className:"empty-actions",children:e.jsx("button",{type:"button",className:"upload-trigger-massive",onClick:O,disabled:g,children:e.jsxs("span",{className:"massive-upload-content",children:[e.jsx(W,{size:24,className:"mb-2"}),e.jsx("span",{children:"Upload your first app"})]})})})]})]})}),e.jsx(_e,{open:ne,teams:L,teamId:E,onTeamChange:G,onChooseFile:()=>{var s;return(s=D.current)==null?void 0:s.click()},onClose:()=>I(!1)}),e.jsx(Le,{app:F,teams:L,onMove:le,onClose:()=>$(null)}),g&&e.jsx("div",{className:"upload-overlay-technical",children:e.jsxs("div",{className:"upload-card-technical",children:[e.jsx("div",{className:"processing-loader"}),e.jsx("h2",{className:"brand-font",style:{fontSize:"20px",marginBottom:"8px"},children:"Artifact ingestion"}),e.jsx("p",{className:"text-muted text-xs",children:"VERIFYING CHECKSUM & DEPLOYING TO REGISTRY..."})]})})]})};export{ss as default};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{c as i,j as e,n,S as o}from"./index-
|
|
1
|
+
import{c as i,j as e,n,S as o}from"./index-ClrpAMAT.js";import{N as l}from"./network-CBGUjJDJ.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const d=[["path",{d:"M18 8V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h8",key:"10dyio"}],["path",{d:"M10 19v-3.96 3.15",key:"1irgej"}],["path",{d:"M7 19h5",key:"qswx4l"}],["rect",{width:"6",height:"10",x:"16",y:"12",rx:"2",key:"1egngj"}]],c=i("monitor-smartphone",d),x=[{icon:o,title:"Self-healing selectors",body:"Broken locators recover through six escalating tiers before a test fails."},{icon:c,title:"Live Android & iOS devices",body:"Watch, drive and record real devices from the browser."},{icon:l,title:"Hub–node scaling",body:"One hub orchestrates device labs across machines."}];function b({children:t}){return e.jsxs("div",{className:"grid min-h-screen w-full grid-cols-1 bg-[var(--bg)] text-[var(--text)] md:grid-cols-[minmax(0,5fr)_minmax(0,7fr)]",children:[e.jsxs("aside",{className:"relative hidden overflow-hidden border-r border-[rgb(var(--rgb-fg)/0.06)] bg-[var(--surface-sunken)] md:flex md:flex-col",children:[e.jsx("div",{"aria-hidden":"true",className:"pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_90%_60%_at_0%_0%,rgb(var(--rgb-accent)/0.14),transparent_60%)]"}),e.jsx("div",{"aria-hidden":"true",className:"pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,rgb(var(--rgb-white)/0.03)_1px,transparent_1px),linear-gradient(to_bottom,rgb(var(--rgb-white)/0.03)_1px,transparent_1px)] bg-[size:48px_48px] [mask-image:linear-gradient(to_bottom,black,transparent_85%)]"}),e.jsxs("div",{className:"relative flex flex-1 flex-col justify-between px-12 py-10",children:[e.jsx(n,{className:"h-8 w-auto self-start object-contain"}),e.jsxs("div",{className:"max-w-md",children:[e.jsxs("h2",{className:"text-4xl font-semibold leading-tight tracking-tight",children:["Your device lab,",e.jsx("br",{}),e.jsx("span",{className:"text-[var(--color-accent)]",children:"under control."})]}),e.jsx("p",{className:"mt-4 text-sm leading-relaxed text-[var(--text-muted)]",children:"Appium orchestration for the devices you own — with self-healing tests, live streaming and recordable proof of what ran."}),e.jsx("ul",{className:"mt-10 space-y-6",children:x.map(({icon:a,title:r,body:s})=>e.jsxs("li",{className:"flex gap-4",children:[e.jsx("span",{className:"grid h-9 w-9 shrink-0 place-items-center rounded-lg border border-[var(--accent-border)] bg-[var(--accent-subtle)]",children:e.jsx(a,{className:"h-4 w-4 text-[var(--color-accent)]","aria-hidden":"true"})}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium text-[var(--text)]",children:r}),e.jsx("div",{className:"mt-0.5 text-sm text-[var(--text-muted)]",children:s})]})]},r))})]}),e.jsxs("footer",{className:"flex items-center justify-between border-t border-[rgb(var(--rgb-fg)/0.06)] pt-5 text-xs text-[var(--text-muted)]",children:[e.jsxs("span",{children:["Xenon v","2.
|
|
6
|
+
*/const d=[["path",{d:"M18 8V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h8",key:"10dyio"}],["path",{d:"M10 19v-3.96 3.15",key:"1irgej"}],["path",{d:"M7 19h5",key:"qswx4l"}],["rect",{width:"6",height:"10",x:"16",y:"12",rx:"2",key:"1egngj"}]],c=i("monitor-smartphone",d),x=[{icon:o,title:"Self-healing selectors",body:"Broken locators recover through six escalating tiers before a test fails."},{icon:c,title:"Live Android & iOS devices",body:"Watch, drive and record real devices from the browser."},{icon:l,title:"Hub–node scaling",body:"One hub orchestrates device labs across machines."}];function b({children:t}){return e.jsxs("div",{className:"grid min-h-screen w-full grid-cols-1 bg-[var(--bg)] text-[var(--text)] md:grid-cols-[minmax(0,5fr)_minmax(0,7fr)]",children:[e.jsxs("aside",{className:"relative hidden overflow-hidden border-r border-[rgb(var(--rgb-fg)/0.06)] bg-[var(--surface-sunken)] md:flex md:flex-col",children:[e.jsx("div",{"aria-hidden":"true",className:"pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_90%_60%_at_0%_0%,rgb(var(--rgb-accent)/0.14),transparent_60%)]"}),e.jsx("div",{"aria-hidden":"true",className:"pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,rgb(var(--rgb-white)/0.03)_1px,transparent_1px),linear-gradient(to_bottom,rgb(var(--rgb-white)/0.03)_1px,transparent_1px)] bg-[size:48px_48px] [mask-image:linear-gradient(to_bottom,black,transparent_85%)]"}),e.jsxs("div",{className:"relative flex flex-1 flex-col justify-between px-12 py-10",children:[e.jsx(n,{className:"h-8 w-auto self-start object-contain"}),e.jsxs("div",{className:"max-w-md",children:[e.jsxs("h2",{className:"text-4xl font-semibold leading-tight tracking-tight",children:["Your device lab,",e.jsx("br",{}),e.jsx("span",{className:"text-[var(--color-accent)]",children:"under control."})]}),e.jsx("p",{className:"mt-4 text-sm leading-relaxed text-[var(--text-muted)]",children:"Appium orchestration for the devices you own — with self-healing tests, live streaming and recordable proof of what ran."}),e.jsx("ul",{className:"mt-10 space-y-6",children:x.map(({icon:a,title:r,body:s})=>e.jsxs("li",{className:"flex gap-4",children:[e.jsx("span",{className:"grid h-9 w-9 shrink-0 place-items-center rounded-lg border border-[var(--accent-border)] bg-[var(--accent-subtle)]",children:e.jsx(a,{className:"h-4 w-4 text-[var(--color-accent)]","aria-hidden":"true"})}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium text-[var(--text)]",children:r}),e.jsx("div",{className:"mt-0.5 text-sm text-[var(--text-muted)]",children:s})]})]},r))})]}),e.jsxs("footer",{className:"flex items-center justify-between border-t border-[rgb(var(--rgb-fg)/0.06)] pt-5 text-xs text-[var(--text-muted)]",children:[e.jsxs("span",{children:["Xenon v","2.12.0"," · Self-hosted device lab"]}),e.jsx("a",{href:"/xenon/api-docs",target:"_blank",rel:"noreferrer",className:"text-[var(--text-muted)] underline-offset-4 hover:text-[var(--text)] hover:underline",children:"API docs"})]})]})]}),e.jsx("main",{className:"flex items-center justify-center px-6 py-10",children:e.jsx("div",{className:"w-full max-w-[400px] rounded-xl border border-[var(--border)] bg-[var(--surface)] px-8 py-9 shadow-[var(--shadow-lg)]",children:t})})]})}export{b as A};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as ee,r as h,p as te,X,j as e,z as V,R as _,f as se,T as ae,q as re,u as ne,i as le,t as oe,M as ie}from"./index-
|
|
1
|
+
import{c as ee,r as h,p as te,X,j as e,z as V,R as _,f as se,T as ae,q as re,u as ne,i as le,t as oe,M as ie}from"./index-ClrpAMAT.js";import{s as ce,b as L,P as de,T as B,i as xe,f as q,a as ue,c as me,d as pe,p as he,e as fe,r as ve,C as be,g as ge,h as je,j as A,k as Ne,l as W,S as we,m as ye,n as Se,u as Ce,o as $e}from"./use-builds-data-DZszmFyl.js";import{I as J}from"./input-CyKdLnEx.js";import{L as ke,a as Me}from"./list-checks-fWsgD9bI.js";import{B as O}from"./button-CqhPBGRj.js";import{D as Ee}from"./download-BM6Xn22t.js";import{s as Te}from"./labels-C21SA4JG.js";import{C as Re}from"./circle-x-BSSqhpXi.js";import{C as Be}from"./circle-check-Du3sjbfV.js";import{C as Le}from"./chevron-right-Dl4X1PRz.js";import{T as Ie}from"./tablet-hgbEwrWq.js";import{M as _e}from"./monitor-Bw1YQZnL.js";import{S}from"./stat-tile-BU9e4s36.js";import{P as De}from"./page-header-B92DKLiq.js";import{S as Ae}from"./select-BBOIZTYm.js";import{E as F}from"./EmptyState-BeuTrlN_.js";import"./time-D-gjmE1o.js";import"./utils-CDN07tui.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as x,j as z}from"./index-
|
|
1
|
+
import{r as x,j as z}from"./index-ClrpAMAT.js";import{a as j,c as g}from"./utils-CDN07tui.js";const v=a=>typeof a=="boolean"?`${a}`:a===0?"0":a,b=j,k=(a,e)=>t=>{var l;if((e==null?void 0:e.variants)==null)return b(a,t==null?void 0:t.class,t==null?void 0:t.className);const{variants:d,defaultVariants:r}=e,y=Object.keys(d).map(n=>{const s=t==null?void 0:t[n],o=r==null?void 0:r[n];if(s===null)return null;const i=v(s)||v(o);return d[n][i]}),c=t&&Object.entries(t).reduce((n,s)=>{let[o,i]=s;return i===void 0||(n[o]=i),n},{}),f=e==null||(l=e.compoundVariants)===null||l===void 0?void 0:l.reduce((n,s)=>{let{class:o,className:i,...V}=s;return Object.entries(V).every(N=>{let[m,u]=N;return Array.isArray(u)?u.includes({...r,...c}[m]):{...r,...c}[m]===u})?[...n,o,i]:n},[]);return b(a,y,f,t==null?void 0:t.class,t==null?void 0:t.className)},C=k("btn-base",{variants:{variant:{default:"btn-primary",primary:"btn-primary",secondary:"btn-secondary",outline:"btn-secondary",ghost:"btn-ghost",tonal:"btn-tonal",link:"btn-link",destructive:"btn-danger",danger:"btn-danger"},size:{default:"btn-size-md",md:"btn-size-md",sm:"btn-size-sm",lg:"btn-size-lg",icon:"btn-size-icon"}},defaultVariants:{variant:"primary",size:"md"}}),O=x.forwardRef(({className:a,variant:e,size:t,...l},d)=>z.jsx("button",{className:g(C({variant:e,size:t,className:a})),ref:d,...l}));O.displayName="Button";export{O as B,k as c};
|
|
@@ -0,0 +1 @@
|
|
|
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)}}.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;container:log-pane / inline-size}.logcat-root .btn-base:focus-visible,.log-field-btn:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:1px}.log-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:6px;min-height:42px;box-sizing:border-box;padding:6px 8px;background:color-mix(in srgb,var(--surface-2) 60%,transparent);border:1px solid var(--border);border-bottom:none;border-radius:var(--radius-md) var(--radius-md) 0 0}.log-status{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 8px;border-radius:var(--radius-sm);background:rgb(var(--rgb-fg) / .05);color:var(--text);font-size:11px;font-weight:600;white-space:nowrap}.log-live-dot{width:8px;height:8px;border-radius:50%;background:var(--text-muted);flex-shrink:0}.log-live-dot.active{background:var(--color-success);animation:logcat-live-pulse 2s infinite}.log-live-dot.is-error{background:var(--color-danger)}@keyframes logcat-live-pulse{0%,to{opacity:1}50%{opacity:.6}}.log-filter,.log-find{position:relative;display:flex;align-items:center}.log-filter{flex:1 1 160px;min-width:120px}.log-find{flex:0 0 110px}.log-field{height:28px;padding:0 8px;font-size:12px}.log-filter-input{padding-right:48px}.log-find-input{padding-right:40px}.log-field-buttons{position:absolute;right:4px;display:flex;gap:2px}.log-field-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--text-muted);cursor:pointer}.log-field-btn:hover{color:var(--text);background:rgb(var(--rgb-fg) / .08)}.log-find-count{position:absolute;right:8px;font-size:10px;font-variant-numeric:tabular-nums;color:var(--text-muted);pointer-events:none}.logcat-root .btn-base.log-icon-btn{width:28px;height:28px}.log-toolbar-divider{width:1px;height:20px;background:var(--border)}.log-actions{display:flex;align-items:center;gap:6px}.logcat-root .btn-base.is-recording{color:var(--color-danger);border-color:color-mix(in srgb,var(--color-danger) 45%,transparent);background:color-mix(in srgb,var(--color-danger) 12%,transparent)}.logcat-root .btn-base.is-recording svg{fill:currentColor}.log-syntax{max-width:300px;padding:6px 8px;color:var(--text);font-size:12px}.log-syntax p{margin:0 0 8px;color:var(--text-muted)}.log-syntax p:last-child{margin-bottom:0}.log-syntax dl{display:grid;gap:4px;margin:0 0 8px}.log-syntax dl>div{display:flex;align-items:baseline;gap:8px}.log-syntax dd{margin:0;color:var(--text-muted)}.log-syntax code,.log-state code{padding:1px 4px;border-radius:3px;background:rgb(var(--rgb-fg) / .06);color:var(--text);font-family:JetBrains Mono,monospace;font-size:11px;overflow-wrap:anywhere}.log-levels{display:flex;align-items:center;gap:8px;min-height:30px;box-sizing:border-box;padding:2px 8px;background:color-mix(in srgb,var(--surface-2) 35%,transparent);border:1px solid var(--border);border-bottom:none}.log-level-buttons{display:flex;align-items:center;flex-wrap:wrap;gap:2px;min-width:0}.logcat-root .btn-base.log-level-btn{height:22px;padding:0 8px;gap:5px;color:var(--text-muted);font-size:11px;font-weight:500}.logcat-root .btn-base.log-level-btn.is-included{background:rgb(var(--rgb-fg) / .06);color:var(--text)}.logcat-root .btn-base.log-level-btn[aria-pressed=true]{border-color:var(--border-strong);color:var(--text)}.log-level-count{color:var(--text-muted);font-variant-numeric:tabular-nums;font-weight:600}.log-level-btn.lvl-W.has-lines .log-level-count{color:var(--color-warning)}.log-level-btn.lvl-E.has-lines .log-level-count,.log-level-btn.lvl-F.has-lines .log-level-count{color:var(--color-danger)}.log-shown{margin-left:auto;color:var(--text-muted);font-size:11px;font-variant-numeric:tabular-nums;white-space:nowrap}.log-body{position:relative;display:flex;flex-direction:column;flex:1;min-height:0;border:1px solid var(--border);border-radius:0 0 var(--radius-md) var(--radius-md);color:var(--text)}:root[data-theme=light] .log-body{background:var(--bg)}.log-banner{display:flex;align-items:center;gap:8px;margin:8px 8px 0;padding:6px 8px 6px 10px;border-radius:var(--radius-sm);color:var(--text);font-size:12px;line-height:1.4}.log-banner>span{flex:1;min-width:0}.log-banner.is-denied{background:color-mix(in srgb,var(--color-danger) 10%,transparent);border:1px solid color-mix(in srgb,var(--color-danger) 30%,transparent)}.log-banner.is-denied>svg{color:var(--color-danger)}.log-banner.is-exhausted{background:color-mix(in srgb,var(--color-warning) 10%,transparent);border:1px solid color-mix(in srgb,var(--color-warning) 30%,transparent)}.log-banner.is-exhausted>svg{color:var(--color-warning)}.log-main,.log-list-wrap{position:relative;display:flex;flex-direction:column;flex:1;min-height:0}.log-dropped-note{padding:4px 10px;border-bottom:1px solid var(--border);background:rgb(var(--rgb-fg) / .03);color:var(--text-muted);font-size:11px}.log-list{flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;overflow-anchor:none;color:var(--text);font-family:JetBrains Mono,monospace;font-size:11.5px;line-height:18px}.log-list:focus{outline:none}.log-list:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:-2px}.log-list-sizer{position:relative;width:100%}.log-row{position:absolute;top:0;left:0;width:100%;box-sizing:border-box;display:grid;grid-template-columns:62px 18px minmax(0,140px) minmax(0,1fr);column-gap:6px;align-items:baseline;padding:1px 8px;cursor:default}.log-time,.log-tag,.log-pkg{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.log-time,.log-pkg{color:var(--text-muted)}.log-time{font-variant-numeric:tabular-nums}.log-badge{display:inline-flex;align-self:start;margin-top:1px;justify-content:center;width:16px;height:16px;border-radius:3px;background:rgb(var(--rgb-fg) / .06);color:var(--text-muted);font-size:10px;font-weight:700;line-height:16px}.log-msg{grid-column:2 / -1;min-width:0;white-space:pre-wrap;overflow-wrap:anywhere}.log-list.is-nowrap .log-msg{overflow:hidden;text-overflow:ellipsis;white-space:pre}@container log-pane (min-width: 720px){.log-row{grid-template-columns:62px 18px minmax(0,140px) minmax(0,150px) minmax(0,1fr)}.log-msg{grid-column:auto}}.log-row:hover{background:rgb(var(--rgb-fg) / .03)}.log-row.lvl-V .log-msg,.log-row.lvl-D .log-msg{color:var(--text-muted)}.log-row.lvl-I .log-badge{background:color-mix(in srgb,var(--color-info) 16%,transparent);color:var(--blue-400)}.log-row.lvl-W .log-badge{background:color-mix(in srgb,var(--color-warning) 18%,transparent);color:var(--color-warning)}.log-row.lvl-E,.log-row.lvl-F{background:color-mix(in srgb,var(--color-danger) 10%,transparent);box-shadow:inset 2px 0 0 var(--color-danger)}.log-row.lvl-E .log-badge,.log-row.lvl-F .log-badge{background:color-mix(in srgb,var(--color-danger) 20%,transparent);color:var(--red-200)}.log-row.is-synthetic .log-msg{grid-column:3 / -1;color:var(--color-warning);font-style:italic}.log-row.is-hit{background:color-mix(in srgb,var(--color-warning) 8%,transparent)}.log-row.is-active-hit{outline:1px solid var(--color-warning);outline-offset:-1px}.log-mark{border-radius:2px;background:color-mix(in srgb,var(--color-warning) 40%,transparent);color:inherit}.log-row[aria-selected=true]{background:color-mix(in srgb,var(--color-highlight) 20%,transparent)}.log-list:focus .log-row.is-active{outline:1px solid var(--color-focus-ring);outline-offset:-1px}.logcat-root .btn-base.log-new-pill{position:absolute;left:50%;bottom:10px;z-index:2;transform:translate(-50%);border-radius:999px;background:var(--surface-2);box-shadow:0 2px 8px rgb(var(--rgb-black) / calc(.4 * var(--shadow-k)))}.log-state{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:24px;color:var(--text-muted);font-size:12px;text-align:center;pointer-events:none}.log-state>*{pointer-events:auto}.log-state p{margin:0}.log-details{flex:0 0 auto;max-height:40%;overflow-y:auto;padding:8px 12px 10px;border-top:1px solid var(--border-strong);background:var(--surface);color:var(--text);font-size:12px}.log-details-head{display:flex;align-items:center;gap:8px}.log-details-title{flex:1;min-width:0;margin:0;overflow:hidden;font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.logcat-root .btn-base.log-details-close{order:1;width:26px;height:26px}.log-details-note,.log-details-left{margin:6px 0 0;color:var(--text-muted)}.log-details-left{color:var(--color-warning)}.log-details-fields{display:flex;flex-wrap:wrap;gap:4px 16px;margin:6px 0 0}.log-details-fields>div{display:flex;gap:6px;min-width:0}.log-details-fields dt{color:var(--text-muted)}.log-details-fields dd{margin:0;font-family:JetBrains Mono,monospace;overflow-wrap:anywhere}.log-details-msg{margin:8px 0 0;padding:6px 8px;border-radius:var(--radius-sm);background:rgb(var(--rgb-fg) / .04);font-family:JetBrains Mono,monospace;font-size:11.5px;white-space:pre-wrap;overflow-wrap:anywhere;-webkit-user-select:text;user-select:text}.log-details-actions{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.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}.shots-root{display:flex;flex-direction:column;flex:1;min-height:0;container:shots-pane / inline-size}.shots-root .btn-base:focus-visible,.shots-thumb:focus-visible,.shots-color:focus-visible{outline:2px solid var(--color-focus-ring);outline-offset:1px}.shots-head{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:10px 14px;border-bottom:1px solid var(--border)}.shots-title{display:flex;align-items:center;gap:8px;margin:0;color:var(--text);font-family:Inter,sans-serif;font-size:13px;font-weight:600}.shots-title svg{color:var(--color-accent)}.shots-kept{color:var(--text-dim);font-size:12px}.shots-actions-gap{flex:1}.shots-body{display:flex;flex-direction:column;flex:1;min-height:0}.shots-rail{display:flex;align-items:stretch;gap:10px;padding:10px 14px;border-bottom:1px solid var(--border)}.shots-take{flex-shrink:0}.shots-list{display:flex;gap:8px;overflow-x:auto;min-width:0}.shots-list .shots-thumb{width:56px;flex-shrink:0}@container shots-pane (min-width: 720px){.shots-body{flex-direction:row}.shots-rail{flex-direction:column;width:196px;flex-shrink:0;border-bottom:none;border-right:1px solid var(--border)}.shots-list{display:grid;grid-template-columns:1fr 1fr;grid-auto-rows:max-content;align-content:start;overflow-x:hidden;overflow-y:auto;min-height:0;flex:1;padding:2px}.shots-list .shots-thumb{width:auto}}.shots-thumb{position:relative;aspect-ratio:9 / 16;border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;background:rgb(var(--rgb-well) / calc(.4 * var(--well-k)));cursor:pointer}.shots-thumb:hover{border-color:var(--border-strong)}.shots-thumb.is-active{border-color:var(--color-accent);box-shadow:0 0 0 1px var(--color-accent)}.shots-thumb.is-compared{border-color:var(--color-info)}.shots-thumb img{position:absolute;top:0;right:0;bottom:0;left:0;display:block;width:100%;height:100%;object-fit:cover}.shots-thumb.is-pending{cursor:default;animation:shots-pulse 1.2s ease-in-out infinite}@keyframes shots-pulse{50%{opacity:.5}}.shots-thumb-label{position:absolute;inset:auto 0 0 0;display:flex;justify-content:space-between;gap:4px;padding:2px 5px;background:var(--surface);color:var(--text-muted);font-family:JetBrains Mono,monospace;font-size:10px;line-height:14px}.shots-thumb-n{display:inline-flex;align-items:center;gap:2px;color:var(--text);font-weight:600}.shots-list .shots-thumb-time{display:none}@container shots-pane (min-width: 720px){.shots-list .shots-thumb-time{display:inline}}.shots-thumb-side{position:absolute;top:4px;left:4px;min-width:18px;padding:0 4px;border-radius:var(--radius-sm);background:var(--color-info);color:var(--color-on-accent);font-size:11px;font-weight:700;text-align:center}.shots-preview{display:flex;flex-direction:column;flex:1;min-width:0;min-height:0}.shots-picture{position:relative;flex:1;min-height:0;padding:16px;background:rgb(var(--rgb-well) / calc(.3 * var(--well-k)))}.shots-picture-frame{position:relative;width:100%;height:100%}.shots-picture-frame img{display:block;width:100%;height:100%;object-fit:contain}.shots-picture-frame img.is-zoomable{cursor:zoom-in}.shots-picture.is-actual{overflow:auto}.shots-picture.is-actual .shots-picture-frame{width:max-content;height:auto}.shots-picture.is-actual .shots-picture-frame img{width:auto;height:auto;max-width:none;cursor:zoom-out}.shots-footer{display:flex;flex-direction:column;gap:8px;padding:10px 14px;border-top:1px solid var(--border)}.shots-details{margin:0;color:var(--text-muted);font-size:12px;overflow-wrap:anywhere}.shots-actions{display:flex;align-items:center;flex-wrap:wrap;gap:6px}.shots-shapes{display:flex;align-items:center;gap:4px}.shots-shapes .is-pressed{border-color:var(--color-info);background:var(--surface-2)}.shots-color{width:28px;height:28px;padding:0;border:1px solid var(--border);border-radius:var(--radius-sm);background:transparent;cursor:pointer}.shots-delete:hover:not(:disabled){color:var(--red-400)}.shots-compare{display:grid;grid-template-rows:1fr 1fr;gap:1px;flex:1;min-height:0;background:var(--border)}@container shots-pane (min-width: 720px){.shots-compare{grid-template-rows:none;grid-template-columns:1fr 1fr}}.shots-compare-side{position:relative;display:flex;flex-direction:column;min-width:0;min-height:0;margin:0;background:var(--bg)}.shots-compare-side .shots-details{padding:8px 14px;border-top:1px solid var(--border)}.shots-compare-tag{position:absolute;z-index:1;top:8px;left:8px;min-width:20px;padding:1px 6px;border-radius:var(--radius-sm);background:var(--color-info);color:var(--color-on-accent);font-size:12px;font-weight:700;text-align:center}.shots-compare-empty{margin:auto;padding:16px;color:var(--text-muted);font-size:12px;text-align:center}.shots-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;flex:1;padding:24px;color:var(--text-muted);text-align:center}.shots-empty-title{margin:0;color:var(--text);font-size:13px;font-weight:600}.shots-empty-hint{max-width:320px;margin:0 0 8px;font-size:12px;line-height:1.5}
|