@soba-so/react 0.0.9 → 0.0.11

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/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client"
2
- var ye=class extends Error{status;constructor(t,n){super(t),this.name="ConnectError",this.status=n}},de=class{session;baseUrl;doFetch;constructor(t){this.session=t.session,this.baseUrl=(t.baseUrl??"").replace(/\/+$/,""),this.doFetch=t.fetchImpl??fetch.bind(globalThis)}context(){return this.request("GET","/v1/connect")}async machines(){return(await this.request("GET","/v1/machines")).machines}lookup(t){return this.request("GET",`/v1/device/lookup?code=${encodeURIComponent(t)}`)}approve(t){return this.request("POST","/v1/device/approve",{user_code:t})}deny(t){return this.request("POST","/v1/device/deny",{user_code:t})}plans(){return this.request("GET","/v1/plans")}selectPlan(t){return this.request("POST","/v1/plans/select",{plan:t})}checkoutPlan(t,n){return this.request("POST","/v1/plans/checkout",{plan:t,...n?.successUrl?{success_url:n.successUrl}:{},...n?.cancelUrl?{cancel_url:n.cancelUrl}:{}})}leavePlan(){return this.request("DELETE","/v1/plans/select")}approveRuntime(t,n){return this.request("POST","/v1/runtimes/approve",{machine_id:t,runtime_id:n})}async request(t,n,o){let s=await this.doFetch(`${this.baseUrl}${n}`,{method:t,headers:{authorization:`Bearer ${this.session}`,...o?{"content-type":"application/json"}:{}},...o?{body:JSON.stringify(o)}:{}}),r={};try{r=await s.json()}catch{}if(!s.ok){let m=typeof r.error=="string"?r.error:`Request failed (${s.status})`;throw new ye(m,s.status)}return r}};function Ee(e){return e.authenticated===!0?{tone:"ok",text:"signed in"}:e.authenticated===!1?{tone:"warn",text:e.auth_hint??"signed out on that machine"}:{tone:"unknown",text:"could not tell"}}function _e(e){return e.state==="busy"?{tone:"busy",text:`serving ${e.active} of ${e.capacity}`}:e.state==="online"?{tone:"ok",text:"connected"}:{tone:"off",text:"asleep or offline"}}import{jsx as O,jsxs as se}from"react/jsx-runtime";function G({machines:e,onApproveRuntime:t}){return e.length?O("div",{children:e.map(n=>{let o=_e(n);return se("div",{className:"sc-machine",children:[se("div",{className:"sc-row-between",children:[se("div",{className:"sc-row",children:[O("span",{className:`sc-dot sc-dot-${o.tone}`,"aria-hidden":"true"}),O("strong",{children:n.label??"This machine"})]}),O("span",{className:"sc-note",children:o.text})]}),O("p",{className:"sc-note",children:[n.platform,n.arch,n.version&&`worker ${n.version}`,n.always_on&&"always on"].filter(Boolean).join(" \xB7 ")}),se("ul",{className:"sc-runtimes",children:[n.runtimes.map(s=>{let r=Ee(s);return s.quarantined?se("li",{className:"sc-row-between",children:[O("span",{children:s.display_name}),t?O("button",{type:"button",className:"sc-btn",onClick:()=>t(n.id,s.id),children:"New here. Let it serve"}):O("span",{className:"sc-tone-warn",children:"new, not serving yet"})]},s.id):se("li",{className:"sc-row-between",children:[O("span",{children:s.display_name}),O("span",{className:`sc-tone-${r.tone}`,children:r.text})]},s.id)}),!n.runtimes.length&&O("li",{className:"sc-note",children:"No runtime advertised. Install Claude Code, Codex or Ollama on that machine."})]})]},n.id)})}):O("p",{className:"sc-note",children:"Nothing connected yet."})}import{useCallback as ve,useEffect as W,useId as St,useMemo as me,useRef as Pt,useState as L}from"react";import{jsx as z,jsxs as xt}from"react/jsx-runtime";function Me({className:e}){return xt("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:[z("path",{d:"M18.125 7.039A8.6 8.6 0 1 0 18.125 16.961A6 6 0 0 1 18.125 7.039Z",fill:"currentColor"}),z("path",{d:"M19.925 7.039A8.6 8.6 0 0 1 19.925 16.961A6 6 0 0 0 19.925 7.039Z",fill:"currentColor"})]})}function Xe({className:e}){return z("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:z("path",{fill:"currentColor",d:"M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z"})})}function Qe({className:e}){return z("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:z("path",{fill:"currentColor",d:"M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"})})}function et({className:e}){return z("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:z("path",{d:"M4 5h16v11H4zM9 20h6M12 16v4",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}var tt={claude:Xe,chatgpt:Qe,local:et};var pe=[{id:"claude",label:"Continue with Claude",title:"The Claude plan you already pay for",cost:"Nothing beyond the plan",prerequisite:"Claude Code installed, and signed in",hint:"Install it from claude.ai/code, then run `claude` once and sign in.",expects:["claude-code"]},{id:"chatgpt",label:"Continue with ChatGPT",title:"The ChatGPT plan you already pay for",cost:"Nothing beyond the plan",prerequisite:"Codex installed, and signed in",hint:"Install Codex, then run `codex` once and sign in.",expects:["codex"]},{id:"local",label:"Use a model on this machine",title:"A model on your own machine",cost:"Free. You bought the hardware",prerequisite:"Ollama running, with a model pulled",hint:"Install Ollama, then `ollama pull` a model before pairing.",expects:["ollama","openai-api"]}];var nt="soba.connect.choice",Nt=180*24*60*60*1e3;function kt(e){let t=2166136261;for(let n=0;n<e.length;n++)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return(t>>>0).toString(36)}function Re(e,t){return e?t?`${nt}.${e}.${kt(t)}`:`${nt}.${e}`:null}function Te(e){if(!e||typeof localStorage>"u")return null;try{let t=localStorage.getItem(e);if(!t)return null;let n=JSON.parse(t);if(Date.now()-Date.parse(n.at)>Nt)return null;let o=pe.find(s=>s.id===n.choice);return o?o.id:null}catch{return null}}function Ie(e,t){if(!(!e||typeof localStorage>"u"))try{localStorage.setItem(e,JSON.stringify({choice:t,at:new Date().toISOString()}))}catch{}}function Ae(e,t){if(!e)return{kind:"unasked"};if(!t)return{kind:"bare"};let n=t.runtimes??[];if(n.length===0)return{kind:"bare"};let o=n.find(s=>e.expects.includes(s.id));return o?o.quarantined?{kind:"held",runtime:o}:o.authenticated===!1?{kind:"signed-out",runtime:o}:o.authenticated===null||o.authenticated===void 0?{kind:"unsure",runtime:o}:{kind:"matched",runtime:o}:{kind:"missing",found:n}}function Oe(e){return e.kind!=="bare"&&e.kind!=="missing"}function Le(e){return e.kind==="matched"||e.kind==="signed-out"||e.kind==="unsure"||e.kind==="held"}import{Fragment as ot,jsx as c,jsxs as b}from"react/jsx-runtime";var st=2e3,Et=1e4,_t=15e3,Mt=9e4;function Rt(e){let t=Math.max(0,Math.round(e/1e3));return`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`}function $e({client:e,initialCode:t,onConnected:n,showStatus:o=!0,initialContext:s=null,initialMachines:r,onClose:m,headingId:h,theme:u}){let v=!!s&&r!==void 0,[d,a]=L(v?t?"code":o&&(r?.length??0)>0?"manage":"choose":"loading"),[f,R]=L(s),[w,T]=L(r??[]),[x,I]=L(null),[N,Y]=L(t??""),[g,B]=L(null),[j,U]=L(null),[V,q]=L(!1),[H,ke]=L(0),[K,ae]=L(()=>Date.now()),[ie,fe]=L(null),[X,Se]=L(null),Q=St(),ee=h??Q,te=Pt(null);W(()=>{if(!e||v)return;let i=!0;return Promise.all([e.context(),e.machines()]).then(([C,P])=>{i&&(R(C),T(P),t?a("code"):o&&P.length>0?a("manage"):a("choose"))}).catch(C=>{i&&(U(C.message),a("choose"))}),()=>{i=!1}},[e,t,o,v]),W(()=>{r&&T(r)},[r]),W(()=>{if(!e||d!=="manage")return;let i=!0,C=setInterval(async()=>{try{let P=await e.machines();i&&T(P)}catch{}},Et);return()=>{i=!1,clearInterval(C)}},[d,e]),W(()=>{if(!e||d!=="waiting")return;let i=!0,C=setInterval(async()=>{try{let P=await e.machines();if(!i)return;T(P);let ne=te.current;if(!ne)return;let l=P.filter(A=>!ne.has(A.id)),k=l.find(A=>A.state!=="offline")??l[0];k&&(Se(k.id),a("connected"),n?.(P))}catch{}},st);return()=>{i=!1,clearInterval(C)}},[d,e,n]);let ce=ve(async()=>{if(e){U(null),q(!0);try{let i=await e.lookup(N);B(i),a("confirm")}catch(i){U(i.message)}finally{q(!1)}}},[e,N]),ge=ve(async()=>{if(e){U(null),q(!0);try{try{te.current=new Set((await e.machines()).map(i=>i.id))}catch{te.current=new Set(w.map(i=>i.id))}await e.approve(N),a("waiting"),ke(Date.now())}catch(i){U(i.message)}finally{q(!1)}}},[e,N,w]),be=ve(async()=>{if(e){q(!0);try{await e.deny(N),a("denied")}catch(i){U(i.message)}finally{q(!1)}}},[e,N]),le=me(()=>f?.connect_url??null,[f]),D=me(()=>Re(f?.publishable_key??null),[f?.publishable_key]);W(()=>fe(Te(D)),[D]);let S=me(()=>w.find(i=>i.id===X),[w,X]),p=me(()=>Ae(x,S),[x,S]);W(()=>{if(!e||d!=="connected"||Oe(p))return;let i=Date.now()+_t,C=setInterval(async()=>{if(Date.now()>i)return clearInterval(C);try{T(await e.machines())}catch{}},st);return()=>clearInterval(C)},[e,d,p]),W(()=>{d!=="connected"||!x||Le(p)&&Ie(D,x.id)},[d,x,p,D]);let E=me(()=>{if(!g)return null;if(g.approved||g.denied)return"answered";let i=g.expires_at?Date.parse(g.expires_at):Number.NaN;return Number.isFinite(i)&&i<=K?"expired":"live"},[g,K]);function F({verdict:i,choice:C}){if(i.kind==="unasked"||i.kind==="matched")return null;if(i.kind==="signed-out")return b("p",{className:"sc-note sc-tone-warn",children:[i.runtime.display_name," is on that machine but"," ",i.runtime.auth_hint??"signed out",". ",C?.hint]});if(i.kind==="unsure")return b("p",{className:"sc-note",children:[i.runtime.display_name," is there. We could not tell whether it is signed in \u2014 the first run will say for certain."]});if(i.kind==="held")return b("p",{className:"sc-note sc-tone-warn",children:[i.runtime.display_name," appeared after pairing, so it is waiting for you to let it serve."]});if(i.kind==="missing"){let P=i.found.map(ne=>ne.display_name).join(", ");return b("p",{className:"sc-note sc-tone-warn",children:["That machine is not advertising ",C?.prerequisite.split(",")[0]??"what you picked",". It has ",P,", and runs will go there instead. ",C?.hint]})}return c("p",{className:"sc-note sc-tone-warn",children:"No runtime advertised yet. Install Claude Code, Codex or Ollama on that machine and it will appear here."})}W(()=>{if(!(d==="confirm"&&E==="live"||d==="waiting"))return;let C=setInterval(()=>ae(Date.now()),1e3);return()=>clearInterval(C)},[d,E]);let ue=ve(async(i,C)=>{if(e)try{await e.approveRuntime(i,C),T(await e.machines())}catch(P){U(P.message)}},[e]);return d==="loading"?c("div",{className:"soba-connect",...u?{"data-theme":u}:{},children:c("div",{className:"sc-card",children:c("p",{className:"sc-note",children:"Loading\u2026"})})}):b("div",{className:"soba-connect",...u?{"data-theme":u}:{},children:[m&&c("button",{type:"button",className:"sc-modal-close",onClick:m,"aria-label":"Close",children:"\xD7"}),d==="manage"&&b("div",{className:"sc-card",children:[c("h2",{className:"sc-title",children:"Your compute"}),b("p",{className:"sc-sub",children:[f?.app.name??"This app"," runs on these machines, while they are awake."]}),c(G,{machines:w,onApproveRuntime:ue}),j&&c("p",{className:"sc-error",children:j}),c("button",{type:"button",className:"sc-btn",style:{marginTop:16},onClick:()=>a("choose"),children:"Connect another machine"})]}),d==="choose"&&b("div",{className:"sc-card",children:[c("span",{className:"sc-mark","aria-hidden":"true",children:c(Me,{})}),c("h2",{className:"sc-h",id:ee,children:"Connect your AI"}),c("p",{className:"sc-p",children:"Use access you already have. Nothing here is charged to you."}),c("div",{className:"sc-opts",children:pe.map(i=>{let C=tt[i.id];return b("button",{type:"button",className:"sc-opt","aria-pressed":x?.id===i.id,onClick:()=>I(i),children:[C&&c(C,{className:"sc-opt-mark"}),c("span",{className:"sc-opt-label",children:i.label}),ie===i.id&&c("span",{className:"sc-opt-last",children:"last used"})]},i.id)})}),x&&b("div",{className:"sc-stack",style:{marginTop:16},children:[c("p",{className:"sc-note",children:x.hint}),le?b(ot,{children:[c("p",{className:"sc-label",children:"Install Soba Connect on the machine you want to use"}),c("a",{className:"sc-btn sc-btn-primary",href:"https://soba.so/soba-connect",target:"_blank",rel:"noreferrer noopener",children:"Get Soba Connect"}),c("p",{className:"sc-label",children:"Then paste this link into it"}),c("code",{className:"sc-code",children:le}),c("p",{className:"sc-note",children:"It will show you a short code. Nothing is pasted back: the credential is written straight to that machine."}),c("button",{type:"button",className:"sc-btn",onClick:()=>a("code"),children:"I have a code"})]}):c("p",{className:"sc-error",children:"This app has no publishable key yet, so there is nothing to pair against."})]})]}),d==="code"&&b("div",{className:"sc-card",children:[c("h2",{className:"sc-title",children:"Enter the code from that machine"}),c("p",{className:"sc-sub",children:"Eight characters, shown by Soba Connect once you paste the link."}),b("form",{className:"sc-stack",onSubmit:i=>{i.preventDefault(),ce()},children:[c("input",{className:"sc-input",value:N,onChange:i=>Y(i.target.value),placeholder:"ACDE-F234",autoComplete:"off",autoFocus:!0,"aria-label":"Pairing code"}),j&&c("p",{className:"sc-error",children:j}),c("button",{type:"submit",className:"sc-btn sc-btn-primary",disabled:V||N.length<8,children:V?"Checking\u2026":"Continue"})]})]}),d==="confirm"&&g&&b("div",{className:"sc-card",children:[c("h2",{className:"sc-title",children:"Attach this machine to your account?"}),b("p",{className:"sc-sub",children:["Once you approve, ",f?.app.name??"this app"," may send your runs to it. It can never see the account or the keys on it."]}),b("ul",{className:"sc-facts",children:[c(he,{k:"Code",v:g.user_code}),c(he,{k:"Machine",v:g.hostname??"not stated"}),c(he,{k:"System",v:[g.platform,g.arch].filter(Boolean).join(" / ")||"not stated"}),c(he,{k:"Asked by",v:g.client??"not stated"}),g.labels.length>0&&c(he,{k:"Labels",v:g.labels.join(", ")})]}),c("p",{className:"sc-note",style:{marginTop:12},children:"Every line above is what that machine said about itself. If none of it looks like a computer of yours, say no."}),E==="expired"&&c("p",{className:"sc-error",children:"That code has expired. Ask the machine for a new one \u2014 it prints a fresh code each time it starts."}),E==="answered"&&c("p",{className:"sc-error",children:"That code has already been answered. If it was not you, deny the next one."}),j&&c("p",{className:"sc-error",children:j}),b("div",{className:"sc-row",style:{marginTop:16},children:[c("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:()=>void ge(),disabled:V||E!=="live",children:"Approve"}),c("button",{type:"button",className:"sc-btn",onClick:()=>void be(),disabled:V||E==="answered",children:"No, deny it"}),c("button",{type:"button",className:"sc-btn sc-btn-quiet",onClick:()=>a("code"),disabled:V,children:"Back"})]}),E==="live"&&g.expires_at&&b("p",{className:"sc-note",style:{marginTop:10},children:["This code expires in ",Rt(Date.parse(g.expires_at)-K),"."]})]}),d==="waiting"&&b("div",{className:"sc-card",children:[c("h2",{className:"sc-title",id:ee,children:"Approved. Waiting for it to connect\u2026"}),c("p",{className:"sc-sub",children:"The worker is starting on that machine. This page will change on its own the moment it arrives."}),c("p",{className:"sc-note",children:"If nothing happens, look at Soba Connect on that machine: it says what it is doing."}),H>0&&K-H>Mt&&b("div",{className:"sc-stack",style:{marginTop:14},children:[c("p",{className:"sc-note sc-tone-warn",children:"Still nothing. Soba Connect may not be running on that machine, or it may not have finished starting. This keeps watching either way."}),c("button",{type:"button",className:"sc-btn",onClick:()=>a("choose"),children:"Start over"})]})]}),d==="connected"&&b("div",{className:"sc-card",children:[c("h2",{className:"sc-title",id:ee,children:"Connected"}),b("p",{className:"sc-sub",children:[f?.app.name??"This app"," will use this machine from now on, while it is awake."]}),c(F,{verdict:p,choice:x}),o&&b(ot,{children:[c(G,{machines:w,onApproveRuntime:ue}),c("button",{type:"button",className:"sc-btn",style:{marginTop:16},onClick:()=>a("manage"),children:"Done"})]})]}),d==="denied"&&b("div",{className:"sc-card",children:[c("h2",{className:"sc-title",id:ee,children:"Declined"}),c("p",{className:"sc-sub",children:"That machine was not attached to your account, and the terminal has been told so."}),c("button",{type:"button",className:"sc-btn",style:{marginTop:16},onClick:()=>a("choose"),children:"Back to the start"})]})]})}function he({k:e,v:t}){return b("li",{className:"sc-fact",children:[c("span",{className:"sc-fact-key",children:e}),c("span",{children:t})]})}import{useEffect as Tt,useRef as qe}from"react";var Ce=0,Ue=null;function rt(){if(typeof document>"u")return()=>{};Ce===0&&(Ue=document.body.style.overflow,document.body.style.overflow="hidden"),Ce+=1;let e=!1;return()=>{e||(e=!0,Ce-=1,Ce===0&&(document.body.style.overflow=Ue??"",Ue=null))}}import{jsx as at}from"react/jsx-runtime";function Be({open:e,onClose:t,labelledBy:n,theme:o,children:s}){let r=qe(null),m=qe(null),h=qe(null);return Tt(()=>{let u=r.current;if(u){if(!e){u.open&&u.close();return}return u.open||u.showModal(),document.activeElement===u&&m.current?.focus(),rt()}},[e]),at("dialog",{ref:r,className:"soba-connect sc-modal","aria-labelledby":n,...o?{"data-theme":o}:{},onCancel:u=>{u.preventDefault(),t()},onPointerDown:u=>{h.current=u.target},onClick:u=>{u.target===u.currentTarget&&h.current===u.currentTarget&&t()},children:at("div",{className:"sc-modal-sheet",ref:m,tabIndex:-1,children:s})})}import{createContext as It,useContext as At}from"react";var De=It(null);function _(){let e=At(De);if(!e)throw new Error("useSoba() must be used inside a <SobaProvider>.");return e}import{jsx as oe}from"react/jsx-runtime";function Ot({className:e}){let{compute:t}=_(),n=e?`soba-connect ${e}`:"soba-connect";return t.loading&&!t.machines.length?oe("div",{className:n,children:oe("p",{className:"sc-note",children:"Loading\u2026"})}):t.error&&!t.machines.length?oe("div",{className:n,children:oe("p",{className:"sc-error",children:t.error.message})}):oe("div",{className:n,children:oe(G,{machines:t.machines})})}import{useEffect as $t,useRef as dt,useState as Ut}from"react";import{useId as Lt}from"react";import{createContext as it,useContext as ct}from"react";var Fe=it(null);function lt(){return ct(Fe)}var je=it({context:null,machines:void 0,theme:"light"});function ut(){return ct(je)}import{jsx as re,jsxs as Ve}from"react/jsx-runtime";function He({open:e,onOpenChange:t,initialCode:n,onConnected:o,showStatus:s}){let{error:r}=_(),m=lt(),h=ut(),u=()=>t(!1),v=Lt();return Ve(Be,{open:e,onClose:u,labelledBy:v,theme:h.theme,children:[r?Ve("div",{className:"sc-card",children:[re("h2",{className:"sc-title",id:v,children:"Could not start"}),re("p",{className:"sc-error",children:r.message})]}):!m&&!h.context?Ve("div",{className:"sc-card",children:[re("h2",{className:"sc-title",id:v,children:"One moment"}),re("p",{className:"sc-note",children:"Getting your compute\u2026"})]}):re($e,{client:m,onClose:u,headingId:v,theme:h.theme,initialContext:h.context,...h.machines!==void 0?{initialMachines:h.machines}:{},...n?{initialCode:n}:{},...o?{onConnected:o}:{},...s===void 0?{}:{showStatus:s}}),re("p",{className:"sc-modal-foot",children:"Secured by Soba"})]})}import{Fragment as pt,jsx as Ge,jsxs as mt}from"react/jsx-runtime";function ze({children:e,variant:t,className:n,initialCode:o,onConnected:s,defaultOpen:r,open:m,onOpenChange:h,showConnected:u=!0}){let{compute:v}=_(),[d,a]=Ut(r??!!o),f=dt(null),R=m!==void 0,w=R?m:d,T=B=>{R||a(B),h?.(B)},x=dt(w);$t(()=>{x.current&&!w&&f.current?.focus(),x.current=w},[w]);let I=v.machines.find(B=>B.state!=="offline")??v.machines[0],N=I?.runtimes?.find(B=>!B.quarantined)??I?.runtimes?.[0],Y=u&&I!==void 0,g=I?.state==="online"?"ok":I?.state==="busy"?"busy":"off";return mt(pt,{children:[Ge("button",{ref:f,type:"button",className:["sc-btn",Y?"sc-btn-connected":t==="outline"?"":"sc-btn-primary",n].filter(Boolean).join(" "),onClick:()=>T(!0),children:e??(Y?mt(pt,{children:[Ge("i",{className:`sc-dot sc-dot-${g}`,"aria-hidden":"true"}),N?.display_name??"Connected",I?.label?` \xB7 ${I.label}`:""]}):"Connect compute")}),Ge(He,{open:w,onOpenChange:T,...o?{initialCode:o}:{},...s?{onConnected:s}:{}})]})}import{jsx as We,jsxs as Bt}from"react/jsx-runtime";function qt({initialCode:e,onConnected:t,className:n,showStatus:o=!0}){let{compute:s}=_(),r=s.machines.length>0;return Bt("div",{className:n?`soba-connect ${n}`:"soba-connect",children:[o&&We(G,{machines:s.machines}),We("div",{style:{marginTop:o&&r?14:0},children:We(ze,{variant:o&&r?"outline":"primary",...e?{initialCode:e}:{},...t?{onConnected:t}:{}})})]})}var Dt=new Set(["delta","thinking","status","done","error"]);function we(e){let t;try{t=JSON.parse(e)}catch{return null}if(!t||typeof t!="object")return null;let n=t,o=n.type==="event"?n.event:n;if(!o||typeof o!="object")return null;let s=o;if(typeof s.type!="string"||!Dt.has(s.type))return null;let r={type:s.type};return typeof s.text=="string"&&(r.text=s.text),typeof s.message=="string"&&(r.message=s.message),typeof s.tool=="string"&&(r.tool=s.tool),typeof s.tier=="string"&&(r.tier=s.tier),s.usage&&typeof s.usage=="object"&&(r.usage=s.usage),r}async function*Ke(e){let t=e.body;if(!t)throw new Error("That run response had no body to stream.");let n=(e.headers.get("content-type")??"").includes("ndjson"),o=t.getReader(),s=new TextDecoder,r="",m=[];try{for(;;){let u=await o.read();if(u.done)break;for(r+=s.decode(u.value,{stream:!0});;){let v=r.indexOf(`
3
- `);if(v===-1)break;let d=ft(r.slice(0,v));if(r=r.slice(v+1),n){let a=d.trim()?we(d):null;a&&(yield a);continue}if(d===""){let a=m.join(`
4
- `);if(m=[],a==="[DONE]")return;let f=a?we(a):null;f&&(yield f);continue}ht(d,m)}}!n&&r&&ht(ft(r),m);let h=n?r.trim():m.join(`
5
- `);if(h&&h!=="[DONE]"){let u=we(h);u&&(yield u)}}finally{o.cancel().catch(()=>{})}}function ht(e,t){if(!e||e.startsWith(":"))return;let n=e.indexOf(":");if(n===-1||e.slice(0,n)!=="data")return;let o=e.slice(n+1);t.push(o.startsWith(" ")?o.slice(1):o)}function ft(e){return e.endsWith("\r")?e.slice(0,-1):e}async function Ft(e){let t="";for await(let n of e)if(n.type==="delta"&&n.text&&(t+=n.text),n.type==="error")throw new Error(n.message??"The run ended with an error.");return t}import{useState as gt}from"react";import{jsx as bt,jsxs as Vt}from"react/jsx-runtime";function jt({plan:e,successUrl:t,cancelUrl:n,label:o,className:s}){let{plan:r}=_(),[m,h]=gt(!1),[u,v]=gt(null);async function d(){h(!0),v(null);try{let a=await r.checkout(e.id,{...t?{successUrl:t}:{},...n?{cancelUrl:n}:{}});window.location.assign(a)}catch(a){v(a.message),h(!1)}}return Vt("div",{className:s?`soba-connect ${s}`:"soba-connect",children:[bt("button",{type:"button",className:"sc-btn sc-btn-primary",disabled:m,onClick:()=>void d(),children:m?"Opening\u2026":o??`Subscribe \u2014 $${e.price.toLocaleString()}/${e.interval}`}),u&&bt("p",{className:"sc-error",children:u})]})}import{useState as yt}from"react";import{Fragment as Wt,jsx as y,jsxs as M}from"react/jsx-runtime";var Ht={"user-hardware":"your own machine","user-subscription":"your own AI subscription","open-weights":"open models we host",frontier:"frontier models"},Gt=new Set(["user-hardware","user-subscription"]);function xe(e){return e?`soba-connect ${e}`:"soba-connect"}function zt({onSelect:e,successUrl:t,cancelUrl:n,showCompute:o=!0,className:s}){let{plan:r}=_(),[m,h]=yt(null),[u,v]=yt(null);if(r.error)return y("div",{className:xe(s),children:y("div",{className:"sc-card",children:y("p",{className:"sc-error",children:r.error.message})})});if(r.loading)return y("div",{className:xe(s),children:y("div",{className:"sc-card",children:y("p",{className:"sc-note",children:"Loading plans\u2026"})})});if(r.plans.length===0)return y("div",{className:xe(s),children:y("div",{className:"sc-card",children:y("p",{className:"sc-note",children:"This app has no plans yet."})})});async function d(a){h(a.id),v(null);try{if(a.selectable)await r.select(a.id);else if(e)e(a);else{let f=await r.checkout(a.id,{...t?{successUrl:t}:{},...n?{cancelUrl:n}:{}});window.location.assign(f);return}}catch(f){v(f.message)}finally{h(null)}}return M("div",{className:xe(s),children:[y("div",{className:"sc-plans",children:r.plans.map(a=>{let f=r.current?.plan_id===a.id;return M("div",{className:f?"sc-plan sc-plan-current":"sc-plan",children:[M("div",{className:"sc-row-between",children:[y("span",{className:"sc-title",children:a.name}),f&&y("span",{className:"sc-plan-badge",children:"Current"})]}),a.description&&y("p",{className:"sc-sub",children:a.description}),y("p",{className:"sc-plan-price",children:a.price===0?y("span",{className:"sc-plan-amount",children:"Free"}):M(Wt,{children:[M("span",{className:"sc-plan-amount",children:["$",a.price.toLocaleString()]}),M("span",{className:"sc-plan-interval",children:["/",a.interval]})]})}),M("div",{className:"sc-facts",children:[M("div",{className:"sc-fact",children:[y("span",{className:"sc-fact-key",children:"Included"}),y("span",{children:a.included_units===null?"Unlimited":`${a.included_units.toLocaleString()} ${a.unit}${a.included_units===1?"":"s"}`})]}),a.overage_per_unit>0&&M("div",{className:"sc-fact",children:[y("span",{className:"sc-fact-key",children:"Then"}),M("span",{children:["$",a.overage_per_unit," / ",a.unit]})]}),a.trial_days>0&&M("div",{className:"sc-fact",children:[y("span",{className:"sc-fact-key",children:"Trial"}),M("span",{children:[a.trial_days," days"]})]}),o&&M("div",{className:"sc-plan-compute",children:[y("span",{className:"sc-fact-key",children:"Runs on"}),a.route_allow===null||a.route_allow.length===0?y("span",{children:a.route_allow===null?"any compute":"no compute"}):y("ul",{className:"sc-compute",children:a.route_allow.map(R=>y("li",{className:Gt.has(R)?"sc-compute-own":void 0,children:Ht[R]??R},R))})]})]}),y("button",{type:"button",className:f?"sc-btn":"sc-btn sc-btn-primary",disabled:f||m!==null,onClick:()=>void d(a),children:f?"Your plan":m===a.id?a.selectable?"Switching\u2026":"Opening\u2026":a.selectable?"Choose":`Subscribe \u2014 $${a.price.toLocaleString()}/${a.interval}`})]},a.id)})}),u&&y("p",{className:"sc-error",children:u})]})}import{useCallback as J,useEffect as Z,useMemo as Ze,useRef as Jt,useState as $}from"react";var Ne=class{#t;#s=null;#n=null;#e;#o=new Set;constructor(t){this.#e=t,this.#t=t.token??null}get token(){return this.#t}get expiresAt(){return this.#s}get canRefresh(){return!!this.#e.endpoint}get refreshAt(){return!this.canRefresh||this.#s===null?null:Math.max(Date.now()+1e4,this.#s-6e4)}subscribe(t){return this.#o.add(t),()=>this.#o.delete(t)}async ensure(){return this.#t?this.#t:this.refresh()}async refresh(){if(this.#n)return this.#n;let t=this.#e.endpoint;if(!t)throw new Error("This Soba session cannot be refreshed. Pass `sessionEndpoint` so the provider can mint a new one.");let n=this.#e.fetchImpl??fetch.bind(globalThis);this.#n=(async()=>{let o=await n(t,{method:"POST",headers:{"content-type":"application/json"},credentials:"same-origin",body:JSON.stringify(this.#e.user?{user:this.#e.user}:{})});if(!o.ok)throw new Error(`Could not start a Soba session (${o.status} from ${t}).`);let s=await o.json(),r=s.session??s.token;if(!r)throw new Error(`${t} answered without a \`session\`. See @soba-so/react's README.`);let m=s.expires_in??s.expiresIn;this.#t=r,this.#s=typeof m=="number"?Date.now()+m*1e3:null;for(let h of this.#o)h();return r})();try{return await this.#n}finally{this.#n=null}}};function vt(e,t=fetch.bind(globalThis)){return async(n,o)=>{let s=await t(n,o);if(s.status!==401||!e.canRefresh)return s;let r;try{r=await e.refresh()}catch{return s}return t(n,Kt(o,r))}}function Kt(e,t){let n=new Headers(e?.headers);return n.set("authorization",`Bearer ${t}`),{...e,headers:n}}var Ct="data-soba-react",wt=!1;function Je(){if(wt||typeof document>"u"||(wt=!0,document.querySelector(`style[${Ct}]`)))return;let e=document.createElement("style");e.setAttribute(Ct,""),e.textContent=`.soba-connect {
2
+ var kn=class extends Error{status;constructor(n,t){super(n),this.name="ConnectError",this.status=t}},Xe=class{session;baseUrl;doFetch;constructor(n){this.session=n.session,this.baseUrl=(n.baseUrl??"").replace(/\/+$/,""),this.doFetch=n.fetchImpl??fetch.bind(globalThis)}context(){return this.request("GET","/v1/connect")}async machines(){return(await this.request("GET","/v1/machines")).machines}lookup(n){return this.request("GET",`/v1/device/lookup?code=${encodeURIComponent(n)}`)}approve(n){return this.request("POST","/v1/device/approve",{user_code:n})}claim(n){return this.request("POST","/v1/device/claim",{pairing_nonce:n})}deny(n){return this.request("POST","/v1/device/deny",{user_code:n})}plans(){return this.request("GET","/v1/plans")}selectPlan(n){return this.request("POST","/v1/plans/select",{plan:n})}checkoutPlan(n,t){return this.request("POST","/v1/plans/checkout",{plan:n,...t?.successUrl?{success_url:t.successUrl}:{},...t?.cancelUrl?{cancel_url:t.cancelUrl}:{}})}leavePlan(){return this.request("DELETE","/v1/plans/select")}hosted(){return this.request("GET","/v1/hosted")}startHosted(){return this.request("POST","/v1/hosted/start")}disconnectHosted(n){return this.request("DELETE",n?`/v1/hosted?provider=${encodeURIComponent(n)}`:"/v1/hosted")}approveRuntime(n,t){return this.request("POST","/v1/runtimes/approve",{machine_id:n,runtime_id:t})}async request(n,t,s){let o=await this.doFetch(`${this.baseUrl}${t}`,{method:n,headers:{authorization:`Bearer ${this.session}`,...s?{"content-type":"application/json"}:{}},...s?{body:JSON.stringify(s)}:{}}),i={};try{i=await o.json()}catch{}if(!o.ok){let a=typeof i.error=="string"?i.error:`Request failed (${o.status})`;throw new kn(a,o.status)}return i}};function Qe(e){let n=/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());if(!n?.[1])return"#ffffff";let t=n[1].length===3?[...n[1]].map(i=>i+i).join(""):n[1],s=i=>{let a=Number.parseInt(t.slice(i*2,i*2+2),16)/255;return a<=.04045?a/12.92:((a+.055)/1.055)**2.4};return .2126*s(0)+.7152*s(1)+.0722*s(2)>.45?"#101012":"#ffffff"}function qn(e){let n=/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());if(!n?.[1])return null;let t=n[1].length===3?[...n[1]].map(s=>s+s).join(""):n[1];return[0,1,2].map(s=>Number.parseInt(t.slice(s*2,s*2+2),16))}function Ve(e,n,t){let s=qn(e),o=qn(n);return!s||!o?e:`#${s.map((a,m)=>Math.round(a+(o[m]-a)*t)).map(a=>a.toString(16).padStart(2,"0")).join("")}`}function en(e,n){if(!qn(e))return{};let t=Qe(e),s=n?.trim();return{"--sc-ground":e,"--sc-shell":e,"--sc-sheet":Ve(e,t,.07),"--sc-raised":Ve(e,t,.13),"--sc-line":Ve(e,t,.18),"--sc-line-2":Ve(e,t,.28),"--sc-text":t,"--sc-text-2":Ve(t,e,.15),"--sc-muted":Ve(t,e,.38),...s?{"--sc-accent":s,"--sc-accent-fg":Qe(s)}:{"--sc-accent":t,"--sc-accent-fg":e}}}function Bn(e){return e.authenticated===!0?{tone:"ok",text:"signed in"}:e.authenticated===!1?{tone:"warn",text:e.auth_hint??"signed out on that machine"}:{tone:"unknown",text:"could not tell"}}function Hn(e){let{platform:n,arch:t}=e;if(!n)return null;let s=n==="darwin"||n==="macos",o=s?"Mac":n==="win32"||n==="windows"?"Windows PC":"Linux machine";return s?`${t==="aarch64"||t==="arm64"?"Apple silicon ":""}${o}`:o}function nn(e){return e.find(n=>n.state==="offline")??null}function tn(e){return e.state==="busy"?{tone:"busy",text:`serving ${e.active} of ${e.capacity}`}:e.state==="online"?{tone:"ok",text:"connected"}:{tone:"off",text:"asleep or offline"}}import{jsx as de,jsxs as us}from"react/jsx-runtime";function W({className:e}){return us("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:[de("path",{d:"M18.125 7.039A8.6 8.6 0 1 0 18.125 16.961A6 6 0 0 1 18.125 7.039Z",fill:"currentColor"}),de("path",{d:"M19.925 7.039A8.6 8.6 0 0 1 19.925 16.961A6 6 0 0 0 19.925 7.039Z",fill:"currentColor"})]})}function Rt({className:e}){return de("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:de("path",{fill:"currentColor",d:"M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z"})})}function Oe({className:e}){return de("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:de("path",{fill:"currentColor",d:"M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"})})}function We({className:e}){return de("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:de("path",{d:"M4 5h16v11H4zM9 20h6M12 16v4",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function Te({className:e}){return de("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:de("path",{d:"M5 6h14v10H5zM2.5 19.5h19",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}var pe={claude:Rt,chatgpt:Oe,local:We};var ne=[{id:"claude",costClass:"user-subscription",short:"Claude Code",label:"Continue with Claude",title:"The Claude plan you already pay for",cost:"Nothing beyond the plan",prerequisite:"Claude Code installed and signed in",hint:"Install it from claude.ai/code, then run `claude` once and sign in.",install:"https://claude.com/product/claude-code",expects:["claude-code"]},{id:"chatgpt",costClass:"user-subscription",short:"Codex",label:"Continue with ChatGPT",title:"The ChatGPT plan you already pay for",cost:"Nothing beyond the plan",prerequisite:"Codex installed and signed in",hint:"Install Codex, then run `codex` once and sign in.",install:"https://learn.chatgpt.com/codex/cli",expects:["codex"]},{id:"local",costClass:"user-hardware",short:"Local models",label:"Use a model on this machine",title:"A model on your own machine",cost:"Free. You bought the hardware",prerequisite:"Ollama running, with a model pulled",hint:"Install Ollama, then `ollama pull` a model before pairing.",install:"https://ollama.com",expects:["ollama","openai-api"]}],Et=["claude","chatgpt"];function Fn(){return ne.filter(e=>Et.includes(e.id))}function Vn(e){return ne.filter(n=>n.costClass===e)}function sn(e){return ne.find(n=>n.expects.includes(e))??null}import{jsx as H,jsxs as Ie}from"react/jsx-runtime";function Ge({machines:e,onApproveRuntime:n}){return e.length?H("div",{children:e.map(t=>{let s=tn(t),o=Hn(t);return Ie("div",{className:"sc-machine",children:[Ie("div",{className:"sc-idrow",children:[H("span",{className:"sc-opt-tile","aria-hidden":"true",children:H(Te,{className:"sc-opt-mark"})}),Ie("span",{className:"sc-opt-text",children:[H("span",{className:"sc-opt-label",children:t.label??"This machine"}),(o||t.always_on)&&Ie("span",{className:"sc-machine-meta",children:[o&&H("span",{children:o}),t.always_on&&H("span",{className:"sc-machine-tag",children:"always on"})]})]}),Ie("span",{className:"sc-machine-state",children:[H("span",{className:`sc-dot sc-dot-${s.tone}`,"aria-hidden":"true"}),s.text]})]}),Ie("ul",{className:"sc-runtimes",children:[t.runtimes.map(i=>H(ds,{runtime:i,...n?{onApprove:()=>n(t.id,i.id)}:{}},i.id)),!t.runtimes.length&&H("li",{className:"sc-note",children:"No runtime advertised. Install Claude Code, Codex or Ollama on that machine."})]})]},t.id)})}):H("p",{className:"sc-note",children:"Nothing connected yet."})}function ds({runtime:e,onApprove:n}){let t=sn(e.id),s=t?pe[t.id]:null,o=Bn(e);return Ie("li",{className:"sc-runtime",children:[H("span",{className:"sc-runtime-tile","aria-hidden":"true",children:s&&H(s,{className:"sc-runtime-mark"})}),H("span",{className:"sc-runtime-name",children:e.display_name}),e.quarantined?n?H("button",{type:"button",className:"sc-conn-action",onClick:n,children:"Let it serve"}):H("span",{className:"sc-runtime-verdict sc-tone-warn",children:"new, not serving yet"}):H("span",{className:`sc-runtime-verdict sc-tone-${o.tone}`,children:o.text})]})}import{useCallback as me,useEffect as re,useId as fs,useMemo as xe,useRef as je,useState as R}from"react";var on=[{slug:"mac-arm",label:"macOS, Apple silicon"},{slug:"mac-intel",label:"macOS, Intel"},{slug:"windows",label:"Windows"},{slug:"linux",label:"Linux"}];function rn(e){if(!e)return"";try{return new URL(e).origin}catch{return""}}var Wn="soba";function Lt(){return`${Wn}://show`}function Sn(e,n,t){let s=`${Wn}://connect?url=${encodeURIComponent(e)}`;return n&&(s+=`&nonce=${encodeURIComponent(n)}`),t&&(s+=`&want=${encodeURIComponent(t)}`),s}function an(){let e=globalThis.crypto;if(!e?.getRandomValues)return null;let n=e.getRandomValues(new Uint8Array(32)),t="";for(let s of n)t+=String.fromCharCode(s);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var ps=1600;function Gn(e={}){return zn(e)}async function jn(e,n={}){if(typeof window>"u"||typeof document>"u")return"unknown";let t=zn(n);try{window.location.href=Sn(e,n.nonce,n.want)}catch{return"absent"}return t}async function Yn(e={}){if(typeof window>"u"||typeof document>"u")return"unknown";let n=zn(e);try{window.location.href=Lt()}catch{return"absent"}return n}async function zn(e){if(typeof window>"u"||typeof document>"u")return"unknown";let n=e.graceMs??ps,t=document.visibilityState==="visible"&&document.hasFocus(),s=!1,o=()=>{s=!0},i=()=>{document.visibilityState==="hidden"&&(s=!0)};return window.addEventListener("blur",o),window.addEventListener("pagehide",o),document.addEventListener("visibilitychange",i),await new Promise(a=>setTimeout(a,n)),window.removeEventListener("blur",o),window.removeEventListener("pagehide",o),document.removeEventListener("visibilitychange",i),t?s?"opened":"absent":"unknown"}var Ot="soba.connect.choice",ms=180*24*60*60*1e3;function hs(e){let n=2166136261;for(let t=0;t<e.length;t++)n^=e.charCodeAt(t),n=Math.imul(n,16777619);return(n>>>0).toString(36)}function Kn(e,n){return e?n?`${Ot}.${e}.${hs(n)}`:`${Ot}.${e}`:null}function Jn(e){if(!e||typeof localStorage>"u")return null;try{let n=localStorage.getItem(e);if(!n)return null;let t=JSON.parse(n);if(Date.now()-Date.parse(t.at)>ms)return null;let s=ne.find(o=>o.id===t.choice);return s?s.id:null}catch{return null}}function Zn(e,n){if(!(!e||typeof localStorage>"u"))try{localStorage.setItem(e,JSON.stringify({choice:n,at:new Date().toISOString()}))}catch{}}import{Fragment as un,jsx as r,jsxs as w}from"react/jsx-runtime";var Xn=2e3,gs=1e4,bs=9e4,ys=6e4;function Qn(e,n,t,s=[],o){return e?"code":n&&(t.length>0||s.length>0)?"manage":o?"launch":"choose"}function ws(e){let n=Math.max(0,Math.round(e/1e3));return`${Math.floor(n/60)}:${String(n%60).padStart(2,"0")}`}function nt({client:e,initialCode:n,initialChoice:t,onConnected:s,showStatus:o=!0,initialContext:i=null,initialMachines:a,onClose:m,headingId:c,theme:p,reason:g}){let b=!!i&&a!==void 0,[h,f]=R(b?Qn(n,o,a??[],[],t):"loading"),[d,N]=R(i),[k,x]=R(a??[]),[U,D]=R(n??""),[C,$]=R(null),[q,A]=R(null),[J,z]=R(!1),[F,ce]=R(0),[Pe,yn]=R(()=>Date.now()),[K,Ce]=R(null),[wn,Ne]=R(!1),[he,Z]=R(!1),[In,Ke]=R("browser"),[Ue,vn]=R(null),[le,te]=R([]),[qe,$n]=R(0),[_e,Be]=R(null),se=je(null),[M,S]=R(t??null),[Me,X]=R(null),Je=xe(()=>{let l=d?.accent?.trim(),v=d?.background?.trim();if(!(!l&&!v))return v?{...en(v,l),background:v,borderRadius:"inherit"}:{"--sc-accent":l,"--sc-accent-fg":Qe(l)}},[d?.accent,d?.background]),Cn=fs(),oe=c??Cn,ke=je(null);re(()=>{if(!e||b)return;let l=!0;return Promise.all([e.context(),e.machines()]).then(([v,_])=>{l&&(N(v),x(_),f(Qn(n,o,_)))}).catch(v=>{l&&(A(v.message),f("choose"))}),()=>{l=!1}},[e,n,o,b]),re(()=>{h!=="loading"||!b||f(Qn(n,o,a??[]))},[h,b,n,o,a]),re(()=>{a&&x(a)},[a]);let He=je(!1),Fe=je(h);Fe.current=h;let Q=je(le);Q.current=le;let V=!!d?.hosted_available,Nn=d?.hosted!==!1;re(()=>{if(!e||h!=="manage")return;let l=!0,v=setInterval(async()=>{try{let _=await e.machines();if(!l)return;x(_);let L=!V||He.current;_.length===0&&Q.current.length===0&&L&&Fe.current==="manage"&&f("choose")}catch{}},gs);return()=>{l=!1,clearInterval(v)}},[h,e,V]);let y=Kn(d?.publishable_key??null);re(()=>{X(Jn(y))},[y]),re(()=>{if(!e||!V)return;let l=!0;return e.hosted().then(v=>{l&&(te(v.credentials),!He.current&&(He.current=!0,v.credentials.length>0&&o&&Fe.current==="choose"&&f("manage")))}).catch(()=>{}),()=>{l=!1}},[e,V,o]),re(()=>{if(!e||h!=="hosted")return;let l=!0,v=async()=>{try{let Se=await e.hosted();if(!l)return!1;if(te(Se.credentials),Se.credentials.length>0)return f("hosted_connected"),Be(null),!0}catch{}return!1},_=async()=>{se.current?.closed&&(se.current=null,!await v()&&l&&f("choose"))},L=setInterval(()=>{v(),_()},Xn),Le=setInterval(_,400),ge=Se=>{let Mt=Se.data;Mt?.source==="soba"&&Mt.type==="hosted_result"&&v()};return window.addEventListener("message",ge),()=>{l=!1,clearInterval(L),clearInterval(Le),window.removeEventListener("message",ge),se.current=null}},[e,h]);let B=me(()=>{if(!e)return;let l=window.open("","soba-connect-plan","width=520,height=760,noopener=no");se.current=l,f("hosted"),$n(Date.now()),Be(null),A(null),e.startHosted().then(({url:v})=>{if(l&&!l.closed){l.location.href=v;return}Be(v)}).catch(v=>{l?.close(),se.current=null,A(v.message),f("choose")})},[e]),ue=me(async l=>{if(e){z(!0);try{await e.disconnectHosted(l),te((await e.hosted()).credentials)}catch(v){A(v.message)}finally{z(!1)}}},[e]);re(()=>{if(!e||h!=="waiting")return;let l=!0,v=setInterval(async()=>{try{let _=await e.machines();if(!l)return;x(_);let L=ke.current;if(!L)return;let Le=_.filter(Se=>!L.has(Se.id)),ge=Le.find(Se=>Se.state!=="offline")??Le[0];ge&&(vn(ge.id),M&&Zn(y,M),f("connected"),s?.(_))}catch{}},Xn);return()=>{l=!1,clearInterval(v)}},[h,e,s,M,y]);let St=me(async()=>{if(e){A(null),z(!0);try{let l=await e.lookup(U);$(l),f("confirm")}catch(l){A(l.message)}finally{z(!1)}}},[e,U]),Re=me(async()=>{if(e){A(null),z(!0);try{try{ke.current=new Set((await e.machines()).map(l=>l.id))}catch{ke.current=new Set(k.map(l=>l.id))}await e.approve(U),f("waiting"),ce(Date.now())}catch(l){A(l.message)}finally{z(!1)}}},[e,U,k]),An=me(async()=>{if(e){z(!0);try{await e.deny(U),Ke("browser"),f("denied")}catch(l){A(l.message)}finally{z(!1)}}},[e,U]),T=xe(()=>d?.connect_url??null,[d]),[ee,xt]=R(()=>an()),rs=xe(()=>T?Sn(T,ee??void 0,M??void 0):null,[T,ee,M]),as=xe(()=>rn(T),[T]),is=me(l=>{if(k.length===0)return null;let v=ne.find(L=>L.id===l);if(!v)return null;let _=k.flatMap(L=>L.runtimes??[]).filter(L=>v.expects.includes(L.id));return _.length===0?{tone:"dim",text:"not installed"}:_.some(L=>L.authenticated===!0)?{tone:"ok",text:"ready"}:_.every(L=>L.authenticated===!1)?{tone:"warn",text:"needs signing in"}:{tone:"dim",text:"installed"}},[k]),cs=me((l=null)=>{S(l),A(null),Ce(null),Ne(!1),Z(!1),Dn.current=!1,xt(an()),f("launch")},[]),Dn=je(!!t);re(()=>{h!=="launch"||!T||Dn.current||(Dn.current=!0,Ne(!0),jn(T,{...ee?{nonce:ee}:{},...M?{want:M}:{}}).then(Ce))},[h,T,ee,M]);let Pt=me(()=>{Ne(!0),Gn().then(Ce)},[]),ls=me(()=>{he&&(Z(!1),xt(an())),Pt()},[he,Pt]),Ze=xe(()=>{let l=d?.runtimes;return l?ne.filter(v=>l.includes(v.id)):Fn()},[d?.runtimes]),fe=xe(()=>{let l=ne.find(v=>v.id===M);return l?{choice:l,Mark:pe[l.id]??null}:null},[M]),Un=xe(()=>k.find(l=>l.id===Ue),[k,Ue]);re(()=>{let l=ee;if(!e||h!=="launch"||!l)return;let v=!1,_=Date.now()+15e4,L=setInterval(async()=>{if(Date.now()>_){clearInterval(L),Z(!0);return}try{let Le=await e.claim(l);if(v)return;if(Le.declined){clearInterval(L),Ce(null),Ke("machine"),f("denied");return}if(!Le.claimed)return;clearInterval(L);try{ke.current=new Set((await e.machines()).map(ge=>ge.id))}catch{ke.current=new Set(k.map(ge=>ge.id))}f("waiting"),ce(Date.now())}catch{}},Xn);return()=>{v=!0,clearInterval(L)}},[e,h,k,ee]);let Ee=xe(()=>{if(!C)return null;if(C.approved||C.denied)return"answered";let l=C.expires_at?Date.parse(C.expires_at):Number.NaN;return Number.isFinite(l)&&l<=Pe?"expired":"live"},[C,Pe]);re(()=>{if(!(h==="confirm"&&Ee==="live"||h==="waiting"||h==="hosted"))return;let v=setInterval(()=>yn(Date.now()),1e3);return()=>clearInterval(v)},[h,Ee]);let _t=me(async(l,v)=>{if(e)try{await e.approveRuntime(l,v),x(await e.machines())}catch(_){A(_.message)}},[e]);return h==="loading"?r("div",{className:"soba-connect",...p?{"data-theme":p}:{},style:Je,children:r("div",{className:"sc-card",children:r("p",{className:"sc-note",children:"Loading\u2026"})})}):w("div",{className:"soba-connect",...p?{"data-theme":p}:{},style:Je,children:[m&&r("button",{type:"button",className:"sc-modal-close",onClick:m,"aria-label":"Close",children:"\xD7"}),h==="manage"&&w("div",{className:"sc-card",children:[r("h2",{className:"sc-title",children:"Your compute"}),w("p",{className:"sc-sub",children:[r(cn,{context:d})," ",k.length>0&&le.length>0?"runs on your connected plan, and on these machines while they are awake.":le.length>0?"runs on the plan you connected. Nothing here is charged to you.":"runs on these machines, while they are awake."]}),w("div",{className:"sc-conns",children:[le.map(l=>w("div",{className:"sc-conn",children:[r("span",{className:"sc-opt-tile","aria-hidden":"true",children:r(Oe,{className:"sc-opt-mark"})}),w("div",{className:"sc-opt-text",children:[r("span",{className:"sc-opt-label",children:l.provider==="openai-chatgpt"?"ChatGPT plan":l.provider}),r("span",{className:"sc-opt-sub",children:l.account_label??"signed in"})]}),r("button",{type:"button",className:"sc-conn-action",onClick:()=>void ue(l.provider),disabled:J,children:"Disconnect"}),w("p",{className:"sc-conn-note",children:[r(cn,{context:d})," stops using it. To withdraw the grant entirely, remove it in your OpenAI settings."]})]},l.provider)),r(Ge,{machines:k,onApproveRuntime:_t})]}),q&&r("p",{className:"sc-error",children:q}),r("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>f("choose"),children:k.length>0?"Connect another machine":"Connect compute"})]}),h==="choose"&&w("div",{className:"sc-card",children:[r(vs,{context:d}),r("h2",{className:"sc-h",id:oe,children:g==="payment_required"?"Carry on with your own AI":g==="no_compute"?"This run needs a machine":"Connect your AI"}),r("p",{className:"sc-p",children:"Use compute you already have."}),T&&Ze.length>0&&w(un,{children:[r("p",{className:"sc-opt-group",children:"On your machine"}),r("div",{className:"sc-opts",children:Ze.map(l=>{let v=pe[l.id];return w("button",{type:"button",className:"sc-opt",onClick:()=>cs(l.id),children:[r("span",{className:"sc-opt-tile","aria-hidden":"true",children:v&&r(v,{className:"sc-opt-mark"})}),r("span",{className:"sc-opt-text",children:r("span",{className:"sc-opt-label",children:l.label})}),(()=>{let _=is(l.id);return _?r("span",{className:`sc-opt-has sc-opt-has-${_.tone}`,children:_.text}):Me===l.id?r("span",{className:"sc-opt-last",children:"last used"}):r(xn,{className:"sc-opt-go"})})()]},l.id)})}),w("p",{className:"sc-opt-note",children:["Your accounts stay there. ",Tt(d)," never sees them."]})]}),Nn&&w(un,{children:[T&&Ze.length>0&&r("div",{className:"sc-or","aria-hidden":"true",children:r("span",{children:"or"})}),T&&Ze.length>0&&r("p",{className:"sc-opt-group",children:"In your browser"}),r("div",{className:"sc-opts",children:w("button",{type:"button",className:"sc-opt",onClick:V?B:void 0,disabled:!V||!e,children:[r("span",{className:"sc-opt-tile","aria-hidden":"true",children:r(Oe,{className:"sc-opt-mark"})}),r("span",{className:"sc-opt-text",children:r("span",{className:"sc-opt-label",children:"Sign in with ChatGPT"})}),V?r(xn,{className:"sc-opt-go"}):r("span",{className:"sc-opt-last",children:"soon"})]})}),r("p",{className:"sc-opt-note",children:V?"Nothing to install.":"Nothing to install. Not switched on here yet."})]}),(!T||Ze.length===0)&&(!V||!Nn)&&r("p",{className:"sc-error",style:{marginTop:16},children:"This app has no publishable key yet, so there is nothing to pair against."}),q&&r("p",{className:"sc-error",children:q}),T&&d?.show_code===!0&&r("div",{className:"sc-opt-alt",children:r("button",{type:"button",className:"sc-alt-link",onClick:()=>f("code"),children:"I have a code"})})]}),h==="launch"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("choose")}),r("p",{className:"sc-head-title",children:"Soba Connect"})]}),r(Pn,{mark:fe?.Mark??W,still:he||!wn&&K===null}),r("h2",{className:"sc-h",id:oe,children:he?"No answer from this machine":K==="absent"?"Nothing opened":K===null?"Opening Soba Connect\u2026":"Approve it on this machine"}),he?r("p",{className:"sc-p",children:"Soba Connect did not answer. It may not be open, or nobody was there. Try again when you are ready."}):K==="absent"?r("p",{className:"sc-p",children:"Nothing opened on this machine. Open it yourself below, or install it if it is not here yet."}):r("p",{className:"sc-p",children:K===null?"Approve it there and this page does the rest.":"This page finishes on its own."}),fe&&w("p",{className:"sc-prereq",children:[fe.Mark&&r(fe.Mark,{className:"sc-rt-mark"}),"Needs ",fe.choice.prerequisite]}),w("div",{className:"sc-stack",style:{marginTop:18},children:[r("a",{className:K==="absent"||he?"sc-btn sc-btn-primary":"sc-btn",href:rs??"#",onClick:ls,children:he?"Try again":K==="absent"?"Open Soba Connect":"Open it again"}),r("p",{className:"sc-note",children:K===null?"Your browser will ask permission first.":"Your browser asks permission the first time."}),fe&&K==="absent"&&r("p",{className:"sc-note",children:r(Cs,{text:fe.choice.hint})}),w("div",{className:"sc-foot-strip",children:[r("span",{children:"Not installed on this machine?"}),w("button",{type:"button",className:"sc-foot-go",onClick:()=>f("get"),children:["Get it",r(xn,{})]})]})]})]}),h==="get"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("launch")}),r("p",{className:"sc-head-title",children:"Get Soba Connect"})]}),r("div",{className:"sc-opts",children:on.map(l=>w("a",{className:"sc-opt",href:`${as}/download/${l.slug}`,target:"_blank",rel:"noreferrer noopener",children:[r("span",{className:"sc-opt-tile","aria-hidden":"true",children:r(Te,{className:"sc-opt-mark"})}),r("span",{className:"sc-opt-text",children:r("span",{className:"sc-opt-label",children:l.label})}),r(xn,{className:"sc-opt-go"})]},l.slug))}),r("p",{className:"sc-opt-note",children:"Install it, then come back here and press the row you started with."})]}),h==="code"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("choose")}),r("p",{className:"sc-head-title",children:"Soba Connect"})]}),r("h2",{className:"sc-h",id:oe,children:"Enter the code from that machine"}),r("p",{className:"sc-p",children:"Eight characters, shown by Soba Connect once you paste the link."}),w("form",{className:"sc-stack",style:{marginTop:16},onSubmit:l=>{l.preventDefault(),St()},children:[r("input",{className:"sc-input",value:U,onChange:l=>D(l.target.value),placeholder:"ACDE-F234",autoComplete:"off",autoFocus:!0,"aria-label":"Pairing code"}),q&&r("p",{className:"sc-error",children:q}),r("button",{type:"submit",className:"sc-btn sc-btn-primary",disabled:J||U.length<8,children:J?"Checking\u2026":"Continue"})]})]}),h==="confirm"&&C&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("code")}),r("p",{className:"sc-head-title",children:"Soba Connect"})]}),r("h2",{className:"sc-title",children:"Attach this machine to your account?"}),w("p",{className:"sc-sub",children:[r(cn,{context:d})," may send your runs to it once you approve. It can never see the account or the keys on it."]}),w("ul",{className:"sc-facts",children:[r(ln,{k:"Code",v:C.user_code}),r(ln,{k:"Machine",v:C.hostname??"not stated"}),r(ln,{k:"System",v:[C.platform,C.arch].filter(Boolean).join(" / ")||"not stated"}),r(ln,{k:"Asked by",v:C.client??"not stated"}),C.labels.length>0&&r(ln,{k:"Labels",v:C.labels.join(", ")})]}),r("p",{className:"sc-note",style:{marginTop:12},children:"Every line above is what that machine said about itself. If none of it looks like a computer of yours, say no."}),Ee==="expired"&&r("p",{className:"sc-error",children:"That code has expired. Ask the machine for a new one. It prints a fresh code each time it starts."}),Ee==="answered"&&r("p",{className:"sc-error",children:"That code has already been answered. If it was not you, deny the next one."}),q&&r("p",{className:"sc-error",children:q}),w("div",{className:"sc-row",style:{marginTop:16},children:[r("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:()=>void Re(),disabled:J||Ee!=="live",children:"Approve"}),r("button",{type:"button",className:"sc-btn",onClick:()=>void An(),disabled:J||Ee==="answered",children:"No, deny it"})]}),Ee==="live"&&C.expires_at&&w("p",{className:"sc-note",style:{marginTop:10},children:["This code expires in ",ws(Date.parse(C.expires_at)-Pe),"."]})]}),h==="waiting"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("choose")}),r("p",{className:"sc-head-title",children:fe?.choice.short??"Soba Connect"})]}),r(Pn,{mark:fe?.Mark??W}),r("h2",{className:"sc-h",id:oe,children:"Approved. Waiting for it to connect"}),r("p",{className:"sc-p",children:"Nothing more to do here. This page changes when it arrives."}),F>0&&Pe-F>bs&&r("p",{className:"sc-note sc-tone-warn",style:{marginTop:14,textAlign:"center"},children:"Still nothing. Look at Soba Connect on that machine: it says what it is doing. This keeps watching either way."})]}),h==="connected"&&w("div",{className:"sc-card",children:[r(et,{tone:"ok"}),r("h2",{className:"sc-h",id:oe,children:Un?.label?`${Un.label} is connected`:"Connected"}),w("p",{className:"sc-p",children:[r(cn,{context:d})," will use ",Un?.label?"it":"this machine"," from now on, while it is awake."]}),o&&w(un,{children:[r("div",{style:{marginTop:16},children:r(Ge,{machines:k,onApproveRuntime:_t})}),r("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:14},onClick:()=>f("manage"),children:"Done"})]})]}),h==="hosted"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("choose")}),r("p",{className:"sc-head-title",children:"ChatGPT"})]}),_e?r(Pn,{mark:Oe,still:!0}):r(Pn,{mark:Oe}),r("h2",{className:"sc-h",id:oe,children:_e?"Your browser blocked the window":"Finish signing in to ChatGPT"}),r("p",{className:"sc-p",children:_e?"Nothing opened. Open the sign-in yourself below. A link you click is allowed where a window we open is not.":"Approve it in the window that opened."}),w("div",{className:"sc-stack",style:{marginTop:18},children:[_e&&r("a",{className:"sc-btn sc-btn-primary",href:_e,target:"soba-connect-plan",rel:"noreferrer",children:"Open the ChatGPT sign-in"}),q&&r("p",{className:"sc-error",children:q}),qe>0&&Pe-qe>ys&&r("p",{className:"sc-note sc-tone-warn",children:"Still nothing. The window may have been closed before it finished, or the sign-in may have been declined. This keeps watching either way."})]})]}),h==="hosted_connected"&&w("div",{className:"sc-card",children:[r(et,{tone:"ok"}),r("h2",{className:"sc-h",id:oe,children:"ChatGPT is connected"}),w("p",{className:"sc-p",children:[r(cn,{context:d})," will run on your ChatGPT plan",le[0]?.account_label?` (${le[0].account_label})`:"",". Nothing more to pay, nothing to install."]}),r("p",{className:"sc-opt-note",style:{textAlign:"center"},children:"It runs on our side, so it has no access to your files or your terminal."}),o&&w(un,{children:[r("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>f("manage"),children:"Done"}),r("div",{className:"sc-opt-alt",children:r("button",{type:"button",className:"sc-alt-link",onClick:()=>f("choose"),children:"Connect a machine too"})})]})]}),h==="denied"&&w("div",{className:"sc-card",children:[r(et,{tone:"off"}),r("h2",{className:"sc-h",id:oe,children:"Declined"}),r("p",{className:"sc-p",children:In==="machine"?"Nothing was connected. You can ask again whenever you like.":"That machine was not attached to your account, and the terminal has been told so."}),r("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>f("choose"),children:"Back to the start"})]})]})}function Tt(e){return e?.app.name??"this app"}function It(e){let n=e?.app.icon_urls;if(n?.length)return n;let t=e?.app.icon_url;return t?[t]:[]}function vs({context:e}){let n=It(e),[t,s]=R(0),o=n[t];return e?.app.mark==="soba"?r(W,{className:"sc-app-mark"}):o?r("img",{className:"sc-app-mark",src:o,alt:"","aria-hidden":"true",onError:()=>s(i=>i+1)}):null}function cn({context:e}){let n=It(e),[t,s]=R(0),o=n[t],i=e?.app.mark==="soba";return w("span",{className:"sc-app",children:[i&&r(W,{className:"sc-app-icon"}),!i&&o&&r("img",{className:"sc-app-icon",src:o,alt:"",onError:()=>s(a=>a+1)}),Tt(e)]})}function Ye({onClick:e}){return r("button",{type:"button",className:"sc-head-back",onClick:e,"aria-label":"Back",children:r("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",children:r("path",{d:"M15 5 8 12l7 7",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})}function xn({className:e}){return r("svg",{className:e,viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",children:r("path",{d:"M9 5l7 7-7 7",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function Pn({mark:e,still:n}){return w("span",{className:"sc-waiting","aria-hidden":"true",children:[!n&&r("svg",{className:"sc-waiting-orbit",viewBox:"0 0 100 100","aria-hidden":"true",focusable:"false",children:r("circle",{className:"sc-waiting-arc",cx:"50",cy:"50",r:"46"})}),r(e,{className:"sc-waiting-mark"})]})}function et({tone:e}){return w("span",{className:`sc-result sc-result-${e}`,"aria-hidden":"true",children:[r("svg",{className:"sc-result-ring",viewBox:"0 0 100 100","aria-hidden":"true",focusable:"false",children:r("circle",{className:"sc-result-circle",cx:"50",cy:"50",r:"46"})}),r("svg",{className:"sc-result-glyph",viewBox:"0 0 100 100","aria-hidden":"true",focusable:"false",children:r("path",{className:"sc-result-path",d:e==="ok"?"M33 51.5 44.5 63 68 39":"M34 50h32"})}),e==="ok"&&r("span",{className:"sc-result-halo"})]})}function Cs({text:e}){return r(un,{children:e.split("`").map((n,t)=>t%2===1?r("code",{className:"sc-inline-code",children:n},t):n)})}function ln({k:e,v:n}){return w("li",{className:"sc-fact",children:[r("span",{className:"sc-fact-key",children:e}),r("span",{children:n})]})}import{useEffect as Ns,useRef as st}from"react";var _n=0,tt=null;function $t(){if(typeof document>"u")return()=>{};_n===0&&(tt=document.body.style.overflow,document.body.style.overflow="hidden"),_n+=1;let e=!1;return()=>{e||(e=!0,_n-=1,_n===0&&(document.body.style.overflow=tt??"",tt=null))}}import{jsx as At}from"react/jsx-runtime";function dn({open:e,onClose:n,labelledBy:t,theme:s,style:o,children:i}){let a=st(null),m=st(null),c=st(null);return Ns(()=>{let p=a.current;if(p){if(!e){p.open&&p.close();return}return p.open||p.showModal(),document.activeElement===p&&m.current?.focus(),$t()}},[e]),At("dialog",{ref:a,className:"soba-connect sc-modal","aria-labelledby":t,...s?{"data-theme":s}:{},style:o,onCancel:p=>{p.preventDefault(),n()},onPointerDown:p=>{c.current=p.target},onClick:p=>{p.target===p.currentTarget&&c.current===p.currentTarget&&n()},children:At("div",{className:"sc-modal-sheet",ref:m,tabIndex:-1,children:i})})}function be(e){let n=`${e.unit}s`;return e.reward==="unlimited"?`Unlimited ${n} on your own AI`:e.reward==="included"&&e.includedUnits!==null?`${xs(e.includedUnits)} ${n} a month once you connect`:e.reward==="credit"&&e.creditMicros>0?`${Ss(e.creditMicros)} back each month you stay connected`:null}function ye(e){return e==="unlimited"||e==="included"}var ks=new Set(["user-hardware","user-subscription"]);function ae(e){return e===null||e.length===0?!1:e.every(n=>ks.has(n))}var Ss=e=>(e/1e6).toLocaleString("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}),xs=e=>e.toLocaleString("en-US");import{createContext as Ps,useContext as _s}from"react";var ot=Ps(null);function I(){let e=_s(ot);if(!e)throw new Error("useSoba() must be used inside a <SobaProvider>.");return e}import{createContext as Dt,useContext as Ut}from"react";var rt=Dt(null);function qt(){return Ut(rt)}var at=Dt({context:null,machines:void 0,theme:"light"});function O(){return Ut(at)}import{jsx as pn}from"react/jsx-runtime";function Ms({className:e}){let{theme:n}=O(),t=e?`soba-connect ${e}`:"soba-connect";return pn("div",{className:t,"data-theme":n,children:pn(it,{})})}function it(){let{compute:e}=I();return e.loading&&!e.machines.length?pn("p",{className:"sc-note",children:"Loading\u2026"}):e.error&&!e.machines.length?pn("p",{className:"sc-error",children:e.error.message}):pn(Ge,{machines:e.machines})}import{useEffect as Es,useRef as Bt,useState as Ls}from"react";import{useId as Rs}from"react";import{jsx as ze,jsxs as Mn}from"react/jsx-runtime";function mn({open:e,onOpenChange:n,initialCode:t,onConnected:s,showStatus:o,reason:i}){let{error:a}=I(),m=qt(),c=O(),p=()=>n(!1),g=Rs(),b=c.context?.background?.trim(),h=b?en(b,c.context?.accent):void 0;return Mn(dn,{open:e,onClose:p,labelledBy:g,theme:c.theme,style:h,children:[a?Mn("div",{className:"sc-card",children:[ze("h2",{className:"sc-title",id:g,children:"Could not start"}),ze("p",{className:"sc-error",children:a.message})]}):!m&&!c.context?Mn("div",{className:"sc-card",children:[ze("h2",{className:"sc-title",id:g,children:"One moment"}),ze("p",{className:"sc-note",children:"Getting your compute\u2026"})]}):ze(nt,{client:m,onClose:p,headingId:g,theme:c.theme,initialContext:c.context,...c.machines!==void 0?{initialMachines:c.machines}:{},...t?{initialCode:t}:{},...s?{onConnected:s}:{},...o===void 0?{}:{showStatus:o},...i?{reason:i}:{}}),Mn("p",{className:"sc-modal-foot",children:[ze(W,{className:"sc-foot-mark"}),"Secured by Soba"]})]})}import{Fragment as ct,jsx as $e,jsxs as hn}from"react/jsx-runtime";function Ae({children:e,variant:n,className:t,initialCode:s,onConnected:o,defaultOpen:i,open:a,onOpenChange:m,showConnected:c=!0}){let{compute:p,connect:g}=I(),{theme:b}=O(),[h,f]=Ls(i??!!s),d=Bt(null),N=a!==void 0,k=!N&&!i&&!s&&g.hasModal,x=N?a:k?g.isOpen:h,U=F=>{k?F?g.open("manual"):g.close():N||f(F),m?.(F)},D=Bt(x);Es(()=>{D.current&&!x&&d.current?.focus(),D.current=x},[x]);let C=p.machines.find(F=>F.state!=="offline")??p.machines[0],$=C?.runtimes?.find(F=>!F.quarantined)??C?.runtimes?.[0],q=c&&C!==void 0,A=C?tn(C):null,J=$?sn($.id):void 0,z=(J?pe[J.id]:void 0)??($?We:Te);return hn(ct,{children:[$e("button",{ref:d,type:"button","data-theme":b,className:["sc-btn",q?"sc-btn-connected":"sc-btn-icon",!q&&n==="primary"?"sc-btn-primary":"",t].filter(Boolean).join(" "),onClick:()=>U(!0),children:e??(q?hn(ct,{children:[$e("span",{className:"sc-runtime-tile","aria-hidden":"true",children:$e(z,{className:"sc-runtime-mark"})}),hn("span",{className:"sc-btn-connected-text",children:[$?.display_name??"Connected",C?.label&&hn("span",{className:"sc-btn-connected-where",children:[" on ",C.label]})]}),$e("i",{className:`sc-dot sc-dot-${A?.tone??"off"}`,"aria-hidden":"true"}),A&&$e("span",{className:"sc-sr",children:A.text})]}):hn(ct,{children:[$e(W,{className:"sc-btn-mark"}),"Connect compute"]}))}),!k&&$e(mn,{open:x,onOpenChange:U,...s?{initialCode:s}:{},...o?{onConnected:o}:{}})]})}import{jsx as lt,jsxs as Ts}from"react/jsx-runtime";function Os({initialCode:e,onConnected:n,className:t,showStatus:s=!0}){let{theme:o}=O();return Ts("div",{className:t?`soba-connect ${t}`:"soba-connect","data-theme":o,children:[s&&lt(it,{}),lt("div",{className:"sc-compute-act",children:lt(Ae,{...e?{initialCode:e}:{},...n?{onConnected:n}:{}})})]})}import{useId as Bs,useState as Hs}from"react";import{useCallback as Is,useState as $s}from"react";function Rn(){let[e,n]=$s(null);return{open:Is(()=>{n(null),Yn().then(n)},[]),launch:e,note:e==="absent"?"Nothing opened here. That machine may be a different computer, or asleep.":null}}import{useCallback as Ht,useMemo as Ft}from"react";function fn(e){if(!e)return null;if(typeof e=="string")return e;if(typeof Response<"u"&&e instanceof Response)return Vt(e.status);let n=e,t=n.error;return typeof t?.code=="string"?t.code:typeof t?.type=="string"?t.type:typeof n.code=="string"?n.code:typeof n.status=="number"?Vt(n.status):n.cause&&n.cause!==e?fn(n.cause):null}function Vt(e){return e===402?"payment_required":e===409?"no_compute":null}function ut(...e){let[n,t]=e,{plan:s,compute:o,connect:i}=I(),a=t?.predict??e.length===0,m=Ds(As(n),o)??(a?Us(s,o):null),c=s.plan,p=s.plans,g=Ft(()=>{if(m!=="payment_required")return null;let d=c?.price??0,N=c?.included_units??0;return p.find(k=>k.id!==c?.id&&k.price>d&&(k.included_units===null||k.included_units>N))??null},[m,p,c]),b=Ht(async()=>{if(!g)return;if(g.selectable){await s.select(g.id);return}let d=await s.checkout(g.id);window.location.assign(d)},[g,s]),h=i.open,f=Ht(()=>{m&&h(m)},[h,m]);return Ft(()=>{if(!m)return null;let d=c?be({unit:c.unit,reward:c.connected_reward,includedUnits:c.connected_included_units,creditMicros:c.connected_credit*1e6}):null,N=c&&ye(c.connected_reward)?d:null;return{reason:m,...qs(m,{connectOffer:N,connected:o.connected,online:o.online,machine:nn(o.machines)?.label??null,unit:c?.unit??"message",interval:c?.interval??"month",upgrade:g!==null,resets:s.current?.period_end??null}),connectOffer:N,upgradeTo:g,connect:f,upgrade:b}},[m,c,o,g,f,b,s.current?.period_end])}function As(e){let n=fn(e);return n==="payment_required"||n==="no_compute"?n:null}function Ds(e,n){return e==="no_compute"&&n.connected&&n.online?null:e}function Us(e,n){let t=e.plan;return!t||n.loading?null:ae(t.route_allow)&&!n.online?"no_compute":e.remaining===0&&t.overage==="stop"?"payment_required":null}function qs(e,n){if(e==="payment_required"){let t=`No ${n.unit}s left this ${n.interval}`;return n.connectOffer&&!n.connected?{title:t,body:`${n.connectOffer}. Connecting takes a minute and costs nothing.`}:n.connectOffer&&!n.online?{title:t,body:`${n.connectOffer}. Waking ${n.machine??"your machine"} is enough.`}:n.upgrade?{title:t,body:n.resets?`A larger plan carries on now. This one comes back on ${Wt(n.resets)}.`:"A larger plan carries on now, or wait for this one to renew."}:{title:t,body:n.resets?`Your allowance comes back on ${Wt(n.resets)}.`:"Your allowance comes back at the start of the next period."}}return n.connected&&!n.online?{title:`${n.machine??"Your machine"} can't be reached`,body:"This run needs it awake and connected. Open Soba Connect on that machine, or connect another one."}:{title:"Nothing connected yet",body:"This app runs on AI you already pay for, on a machine of your own. Connect one and this run has somewhere to go."}}function Wt(e){let n=new Date(e);return Number.isNaN(n.getTime())?e:n.toLocaleDateString(void 0,{day:"numeric",month:"long"})}import{Fragment as dt,jsx as E,jsxs as we}from"react/jsx-runtime";function Fs(e){let{at:n=.25,className:t,error:s,fallback:o=null}=e,i=e.predict??!("error"in e),{plan:a,compute:m,connect:c}=I(),{theme:p}=O(),[g,b]=Hs(null),h=Bs(),f=E(dt,{children:o}),d=a.plan;if(!d||a.loading||m.loading)return f;let N=e.allow!==void 0?e.allow:d.route_allow;if(m.connected)return m.online?f:E(Gt,{className:t,theme:p,stalled:!0,children:E(Vs,{machine:nn(m.machines)?.label??null,ownCompute:ae(N),onConnectAnother:()=>c.open("no_compute")})});let k=(()=>{let C=fn(s);return C==="payment_required"||C==="no_compute"})();if(!i&&!k)return f;let x=ae(N)?Gs(d.unit,ae(d.route_allow)):ye(d.connected_reward)?js(a,d,n):null;if(!x)return f;let U=!i||x.meter!==null&&x.meter.left===0,D=g??U;return we(Gt,{className:t,theme:p,children:[E("div",{className:"sc-nudge-top",children:we("div",{className:"sc-nudge-say",children:[E("p",{className:"sc-nudge-title",children:x.title}),E("p",{className:"sc-nudge-detail",children:x.detail}),we("button",{type:"button",className:"sc-btn sc-btn-quiet sc-nudge-more","aria-expanded":D,"aria-controls":h,onClick:()=>b(!D),children:[D?"Hide the details":"How it works",E(Ys,{})]})]})}),D?E("ol",{className:"sc-nudge-steps",id:h,children:Ws(c.app?.name,rn(c.connectUrl)).map(C=>we("li",{children:[C.opens?E("button",{type:"button",className:"sc-step-lead",onClick:()=>c.open("manual"),children:C.lead}):E("strong",{children:C.lead}),C.detail?E("span",{children:C.detail}):null,C.links.length>0?we("span",{className:"sc-step-links",children:[C.linksLead,C.links.map($=>E("a",{href:$.href,target:"_blank",rel:"noreferrer noopener",children:$.label},$.href))]}):null]},C.lead))}):null,E(Ae,{variant:"primary"})]})}function Gt({className:e,theme:n,stalled:t,children:s}){return E("div",{className:e?`soba-connect sc-fill ${e}`:"soba-connect sc-fill","data-theme":n,children:E("div",{className:t?"sc-nudge sc-nudge-stalled":"sc-nudge",children:s})})}function Vs({machine:e,ownCompute:n,onConnectAnother:t}){let s=Rn();return we(dt,{children:[E("div",{className:"sc-nudge-top",children:we("div",{className:"sc-nudge-say",children:[we("p",{className:"sc-nudge-title",children:[e??"Your machine"," can\u2019t be reached"]}),E("p",{className:"sc-nudge-detail",children:n?"Soba Connect there has stopped reporting in, so runs have nowhere to go until it is back.":"Soba Connect there has stopped reporting in, so nothing will run on your own AI until it is back."}),s.note&&E("p",{className:"sc-nudge-note",children:s.note}),s.launch==="absent"&&E("button",{type:"button",className:"sc-btn sc-btn-quiet sc-nudge-more",onClick:t,children:"Connect another machine"})]})}),E("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:s.open,children:"Open Soba Connect"})]})}function Ws(e,n){return[{lead:"Download Soba Connect",detail:"",linksLead:n?"Get it for":void 0,links:n?on.map(t=>({label:t.label,href:`${n}/download/${t.slug}`})):[]},{lead:"Connect compute",detail:"Press this, then approve the pairing when the app asks.",opens:!0,links:[]},{lead:"Let your AIs serve",detail:`It finds what is installed on that machine. Allow one, and ${e??"this app"} sends every run there.`,linksLead:"Nothing on it yet?",links:ne.map(t=>({label:t.short,href:t.install}))}]}function Gs(e,n){return{title:n?"This plan runs on your own AI.":`These ${e}s run on your own AI.`,detail:`Connect a machine and your ${e}s run there, free, on access you already have.`,meter:null}}function js(e,n,t){let{remaining:s,included:o}=e;if(s===null||o===null||o===0||s>Math.ceil(o*t))return null;let i=be({unit:n.unit,reward:n.connected_reward,includedUnits:n.connected_included_units,creditMicros:n.connected_credit*1e6});return i?{title:s===0?`No ${n.unit}s left this month.`:`${s} ${n.unit}${s===1?"":"s"} left this month.`,detail:we(dt,{children:[i,"."]}),meter:{left:s,of:o}}:null}function Ys(){return E("svg",{viewBox:"0 0 16 16","aria-hidden":"true",focusable:"false",className:"sc-nudge-chev",children:E("path",{d:"M4.5 6.5 8 10l3.5-3.5",fill:"none",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round",strokeLinejoin:"round"})})}var zs=new Set(["delta","thinking","status","done","error"]);function En(e){let n;try{n=JSON.parse(e)}catch{return null}if(!n||typeof n!="object")return null;let t=n,s=t.type==="event"?t.event:t;if(!s||typeof s!="object")return null;let o=s;if(typeof o.type!="string"||!zs.has(o.type))return null;let i={type:o.type};return typeof o.text=="string"&&(i.text=o.text),typeof o.message=="string"&&(i.message=o.message),typeof o.tool=="string"&&(i.tool=o.tool),typeof o.tier=="string"&&(i.tier=o.tier),o.usage&&typeof o.usage=="object"&&(i.usage=o.usage),i}async function*pt(e){let n=e.body;if(!n)throw new Error("That run response had no body to stream.");let t=(e.headers.get("content-type")??"").includes("ndjson"),s=n.getReader(),o=new TextDecoder,i="",a=[];try{for(;;){let c=await s.read();if(c.done)break;for(i+=o.decode(c.value,{stream:!0});;){let p=i.indexOf(`
3
+ `);if(p===-1)break;let g=Yt(i.slice(0,p));if(i=i.slice(p+1),t){let b=g.trim()?En(g):null;b&&(yield b);continue}if(g===""){let b=a.join(`
4
+ `);if(a=[],b==="[DONE]")return;let h=b?En(b):null;h&&(yield h);continue}jt(g,a)}}!t&&i&&jt(Yt(i),a);let m=t?i.trim():a.join(`
5
+ `);if(m&&m!=="[DONE]"){let c=En(m);c&&(yield c)}}finally{s.cancel().catch(()=>{})}}function jt(e,n){if(!e||e.startsWith(":"))return;let t=e.indexOf(":");if(t===-1||e.slice(0,t)!=="data")return;let s=e.slice(t+1);n.push(s.startsWith(" ")?s.slice(1):s)}function Yt(e){return e.endsWith("\r")?e.slice(0,-1):e}async function Ks(e){let n="";for await(let t of e)if(t.type==="delta"&&t.text&&(n+=t.text),t.type==="error")throw new Error(t.message??"The run ended with an error.");return n}import{useId as Js,useState as zt}from"react";import{jsx as G,jsxs as Ln}from"react/jsx-runtime";function Zs({reason:e}){return G("span",{className:"sc-limit-mark","aria-hidden":"true",children:e==="no_compute"?G(We,{}):G(W,{})})}function Xs(e){let{error:n,variant:t="card",onDismiss:s,className:o}=e,i=ut(n,{predict:e.predict??!("error"in e)}),a=Js(),m=O();if(!i)return null;let c=G(Qs,{offer:i,headingId:a,onDismiss:s});return t==="dialog"?G(dn,{open:!0,onClose:()=>s?.(),labelledBy:a,theme:m.theme,children:c}):G("div",{className:o?`soba-connect ${o}`:"soba-connect","data-theme":m.theme,children:c})}function Qs({offer:e,headingId:n,onDismiss:t}){let{compute:s}=I(),[o,i]=zt(!1),[a,m]=zt(null),c=e.reason==="no_compute"&&s.connected&&!s.online,p=c||e.connectOffer!==null||!s.connected,g=Rn();async function b(){i(!0),m(null);try{await e.upgrade()}catch(h){m(h.message)}finally{i(!1)}}return Ln("div",{className:"sc-card sc-limit",children:[Ln("div",{className:"sc-limit-head",children:[G(Zs,{reason:e.reason}),Ln("div",{children:[G("h2",{className:"sc-limit-title",id:n,children:e.title}),G("p",{className:"sc-limit-body",children:e.body})]})]}),a&&G("p",{className:"sc-error",children:a}),c&&g.note&&G("p",{className:"sc-limit-note",children:g.note}),Ln("div",{className:"sc-limit-actions",children:[t&&G("button",{type:"button",className:"sc-btn sc-btn-quiet",onClick:t,disabled:o,children:"Not now"}),e.upgradeTo&&G("button",{type:"button",className:p?"sc-btn":"sc-btn sc-btn-primary",onClick:()=>void b(),disabled:o,children:o?"Opening\u2026":e.upgradeTo.selectable?`Switch to ${e.upgradeTo.name}`:`${e.upgradeTo.name} for $${e.upgradeTo.price.toLocaleString()}/${e.upgradeTo.interval}`}),p&&G("button",{type:"button",className:c?"sc-btn":"sc-btn sc-btn-primary",onClick:e.connect,disabled:o,children:c?"Connect another machine":"Connect compute"}),c&&G("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:g.open,disabled:o,children:"Open Soba Connect"})]})]})}import{useMemo as eo}from"react";function gn(){let{plan:e,compute:n,connect:t}=I();return eo(()=>{let s=e.plan,o=e.current,i={plan:s,assignment:o,loading:e.loading,error:e.error,periodEnd:o?.period_end?new Date(o.period_end):null};if(!s)return{...i,state:"none",trialDaysLeft:null,ceiling:null,raised:!1,uncounted:!1,used:0,remaining:null,percent:null,unlimited:!1,reward:null,summary:"Nothing is assigned to this account, so runs are bounded by whatever the app allows."};let a=so(o?.trial_ends_at??null),m=s.connected_reward==="included"&&n.connected&&s.connected_included_units!==null,c=m?s.connected_included_units:s.included_units,p=s.connected_reward==="unlimited"&&n.connected,g=c===null,b=e.used??0,h=c===null?null:Math.max(0,c-b),f=c&&c>0?Math.min(100,Math.round(b/c*100)):null,d=c!==null&&b>=c,N=a!==null?"trial":g?"unlimited":d?s.overage==="meter"?"metered":"spent":"within";return{...i,state:N,trialDaysLeft:a,ceiling:c,raised:m,uncounted:p,used:b,remaining:h,percent:f,unlimited:g,reward:no(s,m||p,n.connected,()=>t.open("manual")),summary:to({plan:s,assignment:o,used:b,ceiling:c,trialDaysLeft:a,raised:m,uncounted:p,state:N})}},[e,n.connected,t])}function no(e,n,t,s){let o=be({unit:e.unit,reward:e.connected_reward,includedUnits:e.connected_included_units,creditMicros:e.connected_credit*1e6});return o?{line:o,inForce:n,required:!1,connected:t,actionable:ye(e.connected_reward)&&!t,open:s}:ae(e.route_allow)&&!t?{line:"Nothing connected yet, so nothing can run.",inForce:!1,required:!0,connected:t,actionable:!0,open:s}:null}function to(e){let{plan:n,assignment:t,used:s,ceiling:o,trialDaysLeft:i,raised:a,uncounted:m,state:c}=e,p=`${n.unit}${s===1?"":"s"}`,g=m?" Runs your own AI serves do not count toward it.":"";if(c==="trial"&&i!==null){let f=n.price===0?"it continues free":`it is $${n.price.toLocaleString()} a ${n.interval}`;return`${i} ${i===1?"day":"days"} left of your trial, then ${f}.`}if(c==="unlimited")return`${s.toLocaleString()} ${p} this period. No ceiling on this plan.`;if(c==="metered"){let f=s-(o??0);return n.overage_per_unit>0?`${f.toLocaleString()} past the allowance, billed at $${n.overage_per_unit} a ${n.unit}.${g}`:`${f.toLocaleString()} past the allowance.${g}`}if(c==="spent")return t?.period_end?`Allowance spent. It comes back on ${Kt(t.period_end)}.${g}`:`Allowance spent. It comes back at the start of the next period.${g}`;let b=Math.max(0,(o??0)-s),h=a?` Raised from ${(n.included_units??0).toLocaleString()} while your own AI is connected.`:t?.period_end?` Resets ${Kt(t.period_end)}.`:"";return`${b.toLocaleString()} of ${(o??0).toLocaleString()} ${n.unit}s left.${h}${g}`}function so(e){if(!e)return null;let n=new Date(e).getTime()-Date.now();return Number.isNaN(n)||n<=0?null:Math.max(1,Math.ceil(n/864e5))}function Kt(e){let n=new Date(e);return Number.isNaN(n.getTime())?e:n.toLocaleDateString(void 0,{day:"numeric",month:"long"})}import{Fragment as ro,jsx as j,jsxs as ie}from"react/jsx-runtime";function mt({heading:e="Current plan",showUsage:n=!0,showName:t=!0,className:s}){let o=gn(),{theme:i}=O(),a=h=>j("section",{className:s?`soba-connect sc-fill ${s}`:"soba-connect sc-fill","data-theme":i,children:ie("div",{className:"sc-card sc-current",children:[e&&j("h2",{className:"sc-section-title",children:e}),h]})});if(o.error)return a(j("p",{className:"sc-error",children:o.error.message}));if(o.loading)return a(j("p",{className:"sc-note",children:"Loading\u2026"}));if(!o.plan)return a(ie("div",{className:"sc-current-main",children:[j("p",{className:"sc-current-name",children:"No plan"}),j("p",{className:"sc-sub",children:o.summary})]}));let{plan:m,trialDaysLeft:c,percent:p,unlimited:g,reward:b}=o;return a(ie(ro,{children:[ie("div",{className:"sc-current-grid",children:[(t||c!==null)&&ie("div",{className:"sc-current-main",children:[t?ie("p",{className:"sc-current-name",children:[m.name,c!==null&&ie("span",{className:"sc-trial-badge",children:[c," ",c===1?"day":"days"," left"]})]}):c!==null&&j("p",{className:"sc-current-trial",children:ie("span",{className:"sc-trial-badge",children:[c," ",c===1?"day":"days"," left"]})}),t&&m.description&&j("p",{className:"sc-sub",children:m.description})]}),n&&ie("div",{className:"sc-usage",children:[ie("div",{className:"sc-row-between",children:[j("span",{className:"sc-fact-key",children:"Usage"}),j("span",{className:p!==null&&p>=100?"sc-usage-figure sc-usage-over":"sc-usage-figure",children:g?"Unlimited":p===null?"Metered":`${p}% used`})]}),p!==null&&j("div",{className:"sc-meter",role:"presentation",children:p>0&&j("span",{className:p>=100?"sc-meter-fill sc-meter-full":"sc-meter-fill",style:{width:`${p}%`}})}),j("p",{className:"sc-usage-line",children:o.summary})]})]}),b&&ie("div",{className:"sc-current-foot",children:[j("p",{className:b.required?"sc-plan-reward-line sc-plan-reward-need":b.inForce?"sc-plan-reward-line":"sc-plan-reward-line sc-plan-reward-open",children:b.required?b.line:b.inForce?`In force: ${oo(b.line)}.`:b.line}),(b.actionable||b.connected)&&j(Ae,{})]})]}))}var oo=e=>e.charAt(0).toLowerCase()+e.slice(1);import{useCallback as ao,useMemo as io,useState as Jt}from"react";var co={"user-hardware":"your own machine","user-subscription":"your own AI subscription","open-weights":"open models we host",frontier:"frontier models"},lo=new Set(["user-hardware","user-subscription"]);function ht(e={}){let{plan:n,compute:t,connect:s}=I(),[o,i]=Jt(null),[a,m]=Jt(null),{featured:c,onSelect:p,successUrl:g,cancelUrl:b}=e,h=ao(async d=>{i(d.id),m(null);try{if(d.selectable)await n.select(d.id);else if(p)p(d);else{let N=await n.checkout(d.id,{...g?{successUrl:g}:{},...b?{cancelUrl:b}:{}});window.location.assign(N);return}}catch(N){throw m(N.message),N}finally{(d.selectable||p)&&i(null)}},[n,p,g,b]),f=io(()=>n.plans.map(d=>{let N=n.current?.plan_id===d.id;return{plan:d,current:N,featured:c===d.id&&!N,price:uo(d),allowance:d.included_units===null?`Unlimited ${d.unit}s`:`${d.included_units.toLocaleString()} ${d.unit}${d.included_units===1?"":"s"}`,allowanceNote:po(d),computeLabel:d.route_allow===null?"any compute":d.route_allow.length===0?"no compute":null,compute:(d.route_allow??[]).map(k=>({costClass:k,label:co[k]??k,owned:lo.has(k),runtimes:Vn(k).map(x=>x.id)})),connect:mo(d,N,t.connected,()=>s.open("manual")),cta:{label:ho(d,N,o===d.id),disabled:N||o!==null,busy:o===d.id,take:()=>h(d)}}}),[n.plans,n.current,c,t.connected,s,o,h]);return{offers:f,current:f.find(d=>d.current)??null,loading:n.loading,error:n.error,failed:a}}function uo(e){return e.price===0?{amount:"Free",interval:null,free:!0}:{amount:`$${e.price.toLocaleString()}`,interval:e.interval,free:!1}}function po(e){let n=[];return e.included_units===null?n.push("No ceiling on this plan"):(n.push(`Included each ${e.interval}`),e.overage==="meter"&&e.overage_per_unit>0?n.push(`then $${e.overage_per_unit} a ${e.unit}`):e.included_units>0&&n.push(`then ${e.unit}s stop`)),e.trial_days>0&&n.push(`${e.trial_days}-day trial`),n.join(" \xB7 ")}function mo(e,n,t,s){let o=be({unit:e.unit,reward:e.connected_reward,includedUnits:e.connected_included_units,creditMicros:e.connected_credit*1e6}),i=ae(e.route_allow)&&!t;if(!o&&!i)return null;let a=ye(e.connected_reward);return{key:o?"Connect your own":"To use this",line:o??(n?"Nothing connected yet, so nothing can run.":"Runs only on compute you connect."),reward:o!==null,actionable:n&&(a||i)&&!t,open:s}}function ho(e,n,t){return n?"Your plan":t?e.selectable?"Switching\u2026":"Opening\u2026":e.selectable?"Choose":`Subscribe for $${e.price.toLocaleString()}/${e.interval}`}import{jsx as u,jsxs as P}from"react/jsx-runtime";function On(e){return e?`soba-connect sc-fill ${e}`:"soba-connect sc-fill"}function ft({onSelect:e,successUrl:n,cancelUrl:t,showCompute:s=!0,showConnect:o=!1,variant:i="cards",featured:a,className:m}){let{offers:c,loading:p,error:g,failed:b}=ht({...a?{featured:a}:{},...e?{onSelect:e}:{},...n?{successUrl:n}:{},...t?{cancelUrl:t}:{}}),{theme:h}=O();if(g)return u("div",{className:On(m),"data-theme":h,children:u("div",{className:"sc-card",children:u("p",{className:"sc-error",children:g.message})})});if(p)return u("div",{className:On(m),"data-theme":h,children:u("div",{className:"sc-card",children:u("p",{className:"sc-note",children:"Loading plans\u2026"})})});if(c.length===0)return u("div",{className:On(m),"data-theme":h,children:u("div",{className:"sc-card",children:u("p",{className:"sc-note",children:"This app has no plans yet."})})});let f={showCompute:s,showConnect:o};return P("div",{className:On(m),"data-theme":h,"data-variant":i,children:[i==="rows"?u(go,{offers:c,shelf:f}):i==="table"?u(bo,{offers:c,shelf:f}):u(fo,{offers:c,shelf:f}),b&&u("p",{className:"sc-error",children:b})]})}function fo({offers:e,shelf:n}){return u("div",{className:"sc-plans",children:e.map(t=>P("div",{className:Zt("sc-plan",t),children:[P("div",{className:"sc-row-between",children:[u("span",{className:"sc-title",children:t.plan.name}),u(gt,{offer:t})]}),u("p",{className:"sc-sub",children:t.plan.description}),u(bt,{price:t.price,free:"forever"}),u(vt,{offer:t,shelf:n}),u(Xt,{offer:t}),u("div",{className:"sc-plan-band",children:n.showCompute&&u(wt,{offer:t})}),u("div",{className:"sc-plan-band",children:u(yt,{offer:t})})]},t.plan.id))})}function go({offers:e,shelf:n}){return u("ul",{className:"sc-plan-rows",children:e.map(t=>P("li",{className:Zt("sc-plan-row",t),children:[P("div",{className:"sc-row-main",children:[P("span",{className:"sc-row-name",children:[u("span",{className:"sc-title",children:t.plan.name}),u(gt,{offer:t})]}),t.plan.description&&u("p",{className:"sc-sub",children:t.plan.description}),u(Xt,{offer:t}),n.showCompute&&u(wt,{offer:t,inline:!0}),u(yt,{offer:t,inline:!0})]}),P("div",{className:"sc-row-side",children:[u(bt,{price:t.price,free:"forever",small:!0}),u(vt,{offer:t,shelf:n})]})]},t.plan.id))})}function bo({offers:e,shelf:n}){let t=e.some(a=>a.plan.overage_per_unit>0),s=e.some(a=>a.plan.trial_days>0),o=e.some(a=>a.connect!==null),i=a=>[a.current?"sc-col-current":"",a.featured?"sc-col-featured":""].filter(Boolean).join(" ")||void 0;return u("div",{className:"sc-table-scroll",children:P("table",{className:"sc-plan-table",children:[u("thead",{children:P("tr",{children:[u("td",{}),e.map(a=>P("th",{scope:"col",className:i(a),children:[P("span",{className:"sc-row-name",children:[u("span",{className:"sc-title",children:a.plan.name}),u(gt,{offer:a})]}),u(bt,{price:a.price,small:!0})]},a.plan.id))]})}),P("tbody",{children:[P("tr",{children:[u("th",{scope:"row",children:"Included"}),e.map(a=>u("td",{className:i(a),children:a.allowance},a.plan.id))]}),t&&P("tr",{children:[u("th",{scope:"row",children:"Then"}),e.map(a=>u("td",{className:i(a),children:a.plan.overage_per_unit>0?`$${a.plan.overage_per_unit} / ${a.plan.unit}`:u("span",{className:"sc-muted-cell",children:"Stops"})},a.plan.id))]}),s&&P("tr",{children:[u("th",{scope:"row",children:"Trial"}),e.map(a=>u("td",{className:i(a),children:a.plan.trial_days>0?`${a.plan.trial_days} days`:u("span",{className:"sc-muted-cell",children:"None"})},a.plan.id))]}),n.showCompute&&P("tr",{children:[u("th",{scope:"row",children:"Runs on"}),e.map(a=>u("td",{className:i(a),children:u(wt,{offer:a,bare:!0})},a.plan.id))]}),o&&P("tr",{children:[u("th",{scope:"row",children:"Connect your own"}),e.map(a=>u("td",{className:i(a),children:u(yt,{offer:a,bare:!0})},a.plan.id))]}),P("tr",{className:"sc-table-buy",children:[u("td",{}),e.map(a=>u("td",{className:i(a),children:u(vt,{offer:a,shelf:n})},a.plan.id))]})]})]})})}function Zt(e,n){return[e,n.current?"sc-plan-current":"",n.featured?"sc-plan-featured":""].filter(Boolean).join(" ")}function gt({offer:e}){return e.current?u("span",{className:"sc-plan-badge",children:"Current"}):e.featured?u("span",{className:"sc-plan-badge-soft",children:"Recommended"}):null}function bt({price:e,small:n,free:t}){return P("p",{className:n?"sc-plan-price sc-plan-price-sm":"sc-plan-price",children:[u("span",{className:"sc-plan-amount",children:e.amount}),e.interval?P("span",{className:"sc-plan-interval",children:["/",e.interval]}):t&&u("span",{className:"sc-plan-interval sc-plan-after",children:t})]})}function Xt({offer:e}){return P("p",{className:"sc-plan-allowance",children:[u("span",{className:"sc-plan-figure",children:e.allowance}),u("span",{className:"sc-plan-qualifier",children:e.allowanceNote})]})}function yt({offer:e,inline:n,bare:t}){let s=e.connect;if(!s)return t?u("span",{className:"sc-muted-cell",children:"None"}):null;let o=s.reward?"sc-plan-reward-line":"sc-plan-reward-line sc-plan-reward-need",i=s.actionable?P("button",{type:"button",className:`${o} sc-plan-reward-act`,"aria-label":"Connect compute",onClick:s.open,children:[u("span",{className:"sc-reward-said",children:s.line}),P("span",{className:"sc-reward-do","aria-hidden":!0,children:[u(W,{className:"sc-reward-mark"}),"Connect compute"]})]}):u("p",{className:o,children:s.line});return t?i:u("div",{className:n?"sc-plan-reward sc-plan-reward-inline":"sc-plan-reward",children:i})}function wt({offer:e,inline:n,bare:t}){let s=e.computeLabel?u("ul",{className:n?"sc-compute sc-compute-inline":"sc-compute",children:u("li",{children:e.computeLabel})}):u("ul",{className:n?"sc-compute sc-compute-inline":"sc-compute",children:e.compute.map(o=>P("li",{className:o.owned?"sc-compute-own":void 0,children:[o.label,u(yo,{runtimes:o.runtimes})]},o.costClass))});return t?s:P("div",{className:n?"sc-plan-compute sc-plan-compute-inline":"sc-plan-compute",children:[u("span",{className:"sc-fact-key",children:"Runs on"}),s]})}function vt({offer:e,shelf:n}){let t=e.connect;return n.showConnect&&t?.actionable?P("button",{type:"button",className:"sc-btn sc-btn-primary sc-btn-icon",onClick:t.open,children:[u(W,{className:"sc-btn-mark"}),"Connect compute"]}):u("button",{type:"button",className:e.current?"sc-btn":"sc-btn sc-btn-primary",disabled:e.cta.disabled,onClick:()=>void e.cta.take().catch(()=>{}),children:e.cta.label})}function yo({runtimes:e}){return e.length===0?null:u("span",{className:"sc-compute-marks",children:e.map(n=>{let t=pe[n];return t?u(t,{className:"sc-rt-mark"},n):null})})}import{jsx as Ct,jsxs as Qt}from"react/jsx-runtime";function wo({heading:e,plansHeading:n,showUsage:t=!0,showName:s=!0,className:o,...i}){let{plan:a,loading:m}=gn(),{theme:c}=O(),p=n??(m?"Plans":a?"Change plan":"Choose a plan");return Qt("div",{className:o?`soba-connect sc-fill sc-billing ${o}`:"soba-connect sc-fill sc-billing","data-theme":c,children:[Ct(mt,{...e===void 0?{}:{heading:e},showUsage:t,showName:s}),Qt("section",{className:"sc-billing-plans",children:[p&&Ct("h2",{className:"sc-section-title",children:p}),Ct(ft,{...i})]})]})}import{useState as es}from"react";import{jsx as ns,jsxs as Co}from"react/jsx-runtime";function vo({plan:e,successUrl:n,cancelUrl:t,label:s,className:o}){let{plan:i}=I(),{theme:a}=O(),[m,c]=es(!1),[p,g]=es(null);async function b(){c(!0),g(null);try{let h=await i.checkout(e.id,{...n?{successUrl:n}:{},...t?{cancelUrl:t}:{}});window.location.assign(h)}catch(h){g(h.message),c(!1)}}return Co("div",{className:o?`soba-connect ${o}`:"soba-connect","data-theme":a,children:[ns("button",{type:"button",className:"sc-btn sc-btn-primary",disabled:m,onClick:()=>void b(),children:m?"Opening\u2026":s??`Subscribe for $${e.price.toLocaleString()}/${e.interval}`}),p&&ns("p",{className:"sc-error",children:p})]})}import{useCallback as ve,useEffect as De,useMemo as bn,useRef as ko,useState as Y}from"react";var Tn=class{#n;#s=null;#t=null;#e;#o=new Set;constructor(n){this.#e=n,this.#n=n.token??null}get token(){return this.#n}get expiresAt(){return this.#s}get canRefresh(){return!!this.#e.endpoint}get refreshAt(){return!this.canRefresh||this.#s===null?null:Math.max(Date.now()+1e4,this.#s-6e4)}subscribe(n){return this.#o.add(n),()=>this.#o.delete(n)}async ensure(){return this.#n?this.#n:this.refresh()}async refresh(){if(this.#t)return this.#t;let n=this.#e.endpoint;if(!n)throw new Error("This Soba session cannot be refreshed. Pass `sessionEndpoint` so the provider can mint a new one.");let t=this.#e.fetchImpl??fetch.bind(globalThis);this.#t=(async()=>{let s=await t(n,{method:"POST",headers:{"content-type":"application/json"},credentials:"same-origin",body:JSON.stringify(this.#e.user?{user:this.#e.user}:{})});if(!s.ok)throw new Error(`Could not start a Soba session (${s.status} from ${n}).`);let o=await s.json(),i=o.session??o.token;if(!i)throw new Error(`${n} answered without a \`session\`. See @soba-so/react's README.`);let a=o.expires_in??o.expiresIn;this.#n=i,this.#s=typeof a=="number"?Date.now()+a*1e3:null;for(let m of this.#o)m();return i})();try{return await this.#t}finally{this.#t=null}}};function ts(e,n=fetch.bind(globalThis)){return async(t,s)=>{let o=await n(t,s);if(o.status!==401||!e.canRefresh)return o;let i;try{i=await e.refresh()}catch{return o}return n(t,No(s,i))}}function No(e,n){let t=new Headers(e?.headers);return t.set("authorization",`Bearer ${n}`),{...e,headers:t}}var ss="data-soba-react",os=!1;function Nt(){if(os||typeof document>"u"||(os=!0,document.querySelector(`style[${ss}]`)))return;let e=document.createElement("style");e.setAttribute(ss,""),e.textContent=`.soba-connect {
6
6
  --sc-ground: #ffffff;
7
7
  --sc-sheet: #ffffff;
8
8
  --sc-raised: #f6f6f7;
@@ -15,16 +15,50 @@ var ye=class extends Error{status;constructor(t,n){super(t),this.name="ConnectEr
15
15
  --sc-accent-fg: #ffffff;
16
16
  --sc-ok: #22a06b;
17
17
  --sc-warn: #b06f14;
18
+
19
+ --sc-font-size: 15px;
20
+ --sc-fs-label: max(11px, calc(var(--sc-font-size) * 0.77));
21
+
22
+ --sc-fs-small: max(12px, calc(var(--sc-font-size) * 0.87));
23
+ --sc-fs-body: var(--sc-font-size);
24
+ --sc-fs-title: calc(var(--sc-font-size) * 1.13);
25
+ --sc-fs-display: calc(var(--sc-font-size) * 2.45);
26
+
27
+
28
+ --sc-r-sm: 6px;
18
29
  --sc-r: 10px;
30
+ --sc-r-lg: 14px;
31
+ --sc-r-pill: 999px;
32
+
33
+
34
+ --sc-shadow-1: 0 1px 2px rgb(0 0 0 / 5%);
35
+ --sc-shadow-2: 0 1px 2px rgb(0 0 0 / 4%), 0 8px 24px -12px rgb(0 0 0 / 18%);
36
+
37
+
38
+ --sc-tile: 32px;
19
39
 
20
40
  --sc-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
41
+
42
+ --sc-font:
43
+ ui-sans-serif, system-ui, -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
21
44
 
22
45
  box-sizing: border-box;
46
+
47
+ width: 100%;
23
48
  max-width: 560px;
24
49
  margin: 0 auto;
25
50
  color: var(--sc-text, #1a1a1c);
26
- font-family: "Inter", ui-sans-serif, -apple-system, "Helvetica Neue", Arial, sans-serif;
27
- font-size: 15px;
51
+ font-family: var(
52
+ --sc-font,
53
+ ui-sans-serif,
54
+ system-ui,
55
+ -apple-system,
56
+ "Segoe UI",
57
+ "Helvetica Neue",
58
+ Arial,
59
+ sans-serif
60
+ );
61
+ font-size: var(--sc-font-size, 15px);
28
62
  line-height: 1.5;
29
63
  letter-spacing: -0.005em;
30
64
  }
@@ -37,18 +71,19 @@ var ye=class extends Error{status;constructor(t,n){super(t),this.name="ConnectEr
37
71
  .sc-card {
38
72
  background: var(--sc-sheet, #ffffff);
39
73
  border: 1px solid var(--sc-line, #e9e9eb);
40
- border-radius: var(--sc-r, 10px);
41
- padding: 20px;
74
+
75
+ border-radius: var(--sc-r-lg, 14px);
76
+ padding: 18px;
42
77
  }
43
78
  .sc-card + .sc-card {
44
79
  margin-top: 12px;
45
80
  }
46
81
 
47
82
  .sc-title {
48
- font-size: 20px;
83
+ font-size: var(--sc-fs-title, 17px);
49
84
  font-weight: 650;
50
85
  letter-spacing: -0.02em;
51
- margin: 0 0 4px;
86
+ margin: 0;
52
87
  }
53
88
  .sc-sub {
54
89
  color: var(--sc-muted, #6b6b73);
@@ -61,42 +96,11 @@ var ye=class extends Error{status;constructor(t,n){super(t),this.name="ConnectEr
61
96
  letter-spacing: -0.005em;
62
97
  }
63
98
 
64
- .sc-choices {
65
- display: grid;
66
- gap: 8px;
67
- }
68
- .sc-choice {
69
- display: block;
70
- width: 100%;
71
- text-align: left;
72
- background: var(--sc-sheet, #ffffff);
73
- border: 1px solid var(--sc-line-2, #dcdce0);
74
- border-radius: var(--sc-r, 10px);
75
- padding: 12px 14px;
76
- cursor: pointer;
77
- font: inherit;
78
- color: inherit;
79
- }
80
- .sc-choice:hover {
81
- background: var(--sc-raised, #f6f6f7);
82
- }
83
- .sc-choice[aria-pressed="true"] {
84
- border-color: var(--sc-accent, #18181b);
85
- box-shadow: inset 0 0 0 1px var(--sc-accent, #18181b);
86
- }
87
- .sc-choice-title {
88
- font-weight: 550;
89
- }
90
- .sc-choice-meta {
91
- color: var(--sc-muted, #6b6b73);
92
- font-size: 13px;
93
- }
94
-
95
99
  .sc-code {
96
100
  display: block;
97
101
  background: var(--sc-raised, #f6f6f7);
98
102
  border: 1px solid var(--sc-line, #e9e9eb);
99
- border-radius: 8px;
103
+ border-radius: var(--sc-r-sm, 6px);
100
104
  padding: 12px 14px;
101
105
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
102
106
  font-size: 13px;
@@ -122,8 +126,8 @@ var ye=class extends Error{status;constructor(t,n){super(t),this.name="ConnectEr
122
126
 
123
127
  .sc-btn {
124
128
  font: inherit;
125
- font-weight: 550;
126
- border-radius: 8px;
129
+ font-weight: 500;
130
+ border-radius: var(--sc-r-sm, 6px);
127
131
  padding: 9px 14px;
128
132
  border: 1px solid var(--sc-line-2, #dcdce0);
129
133
  background: var(--sc-sheet, #ffffff);
@@ -155,12 +159,12 @@ a.sc-btn {
155
159
 
156
160
  .sc-input {
157
161
  font: inherit;
158
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
162
+ font-family: var(--sc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
159
163
  letter-spacing: 0.08em;
160
164
  text-transform: uppercase;
161
165
  padding: 10px 12px;
162
166
  border: 1px solid var(--sc-line-2, #dcdce0);
163
- border-radius: 8px;
167
+ border-radius: var(--sc-r-sm, 6px);
164
168
  background: var(--sc-sheet, #ffffff);
165
169
  color: inherit;
166
170
  width: 100%;
@@ -195,11 +199,31 @@ a.sc-btn {
195
199
 
196
200
  .sc-error {
197
201
  color: var(--sc-warn, #b06f14);
198
- font-size: 14px;
202
+ font-size: var(--sc-fs-body);
203
+ }
204
+
205
+ .sc-note-strong {
206
+ font-weight: 600;
207
+ color: var(--sc-text, #1a1a1c);
208
+ }
209
+ .sc-note-act {
210
+ appearance: none;
211
+ border: 0;
212
+ background: none;
213
+ padding: 0;
214
+ font: inherit;
215
+ color: var(--sc-text-2, #3f3f46);
216
+ text-decoration: underline;
217
+ text-underline-offset: 2px;
218
+ cursor: pointer;
219
+ }
220
+ .sc-note-act:disabled {
221
+ opacity: 0.5;
222
+ cursor: default;
199
223
  }
200
224
  .sc-note {
201
225
  color: var(--sc-muted, #6b6b73);
202
- font-size: 13px;
226
+ font-size: var(--sc-fs-small);
203
227
  }
204
228
 
205
229
  .sc-facts {
@@ -229,22 +253,141 @@ a.sc-btn {
229
253
  padding-top: 0;
230
254
  margin-top: 0;
231
255
  }
256
+
257
+ .sc-machine-meta {
258
+ display: flex;
259
+ flex-wrap: wrap;
260
+ align-items: center;
261
+ gap: 3px 10px;
262
+
263
+ margin-top: 1px;
264
+ font-size: var(--sc-fs-small);
265
+ line-height: 1.35;
266
+ color: var(--sc-muted, #6b6b73);
267
+ }
268
+
269
+ .sc-machine-tag {
270
+ font-size: var(--sc-fs-label);
271
+ font-weight: 600;
272
+ padding: 1px 6px;
273
+ border-radius: var(--sc-r-sm, 6px);
274
+ background: var(--sc-raised, #f6f6f7);
275
+ }
276
+
277
+ .sc-machine-state {
278
+ display: inline-flex;
279
+ align-items: center;
280
+ gap: 6px;
281
+ font-size: var(--sc-fs-small);
282
+ color: var(--sc-muted, #6b6b73);
283
+ white-space: nowrap;
284
+ }
285
+
232
286
  .sc-runtimes {
233
287
  display: grid;
234
- gap: 4px;
235
- margin: 8px 0 0;
236
- padding: 0;
288
+ gap: 2px;
289
+ margin: 12px 0 0;
290
+
291
+ --sc-branch: calc(var(--sc-tile, 32px) + 11px);
292
+ padding: 0 0 0 var(--sc-branch);
237
293
  list-style: none;
238
- font-size: 14px;
294
+ font-size: var(--sc-fs-small);
295
+ }
296
+
297
+ .sc-compute-act {
298
+ margin-top: 16px;
299
+ }
300
+
301
+ .sc-compute-act:first-child {
302
+ margin-top: 0;
303
+ }
304
+
305
+ .sc-note + .sc-compute-act,
306
+ .sc-error + .sc-compute-act {
307
+ margin-top: 9px;
308
+ }
309
+
310
+ .sc-runtime {
311
+ position: relative;
312
+ display: grid;
313
+ grid-template-columns: auto 1fr auto;
314
+ align-items: center;
315
+ gap: 9px;
316
+ min-height: 26px;
317
+ }
318
+
319
+ .sc-runtime::before {
320
+ content: "";
321
+ position: absolute;
322
+ left: calc(var(--sc-tile, 32px) / 2 - var(--sc-branch));
323
+ top: -2px;
324
+ bottom: -2px;
325
+ width: 1px;
326
+ background: var(--sc-line-2, #dcdce0);
327
+ }
328
+
329
+ .sc-runtime:first-child::before {
330
+ top: -13px;
331
+ }
332
+
333
+ .sc-runtime:last-child::before {
334
+ bottom: auto;
335
+ height: calc(50% + 2px);
336
+ }
337
+
338
+ .sc-runtime:first-child:last-child::before {
339
+ height: calc(50% + 13px);
340
+ }
341
+
342
+ .sc-runtime::after {
343
+ content: "";
344
+ position: absolute;
345
+ left: calc(var(--sc-tile, 32px) / 2 - var(--sc-branch));
346
+ top: 50%;
347
+ width: 22px;
348
+ height: 1px;
349
+ background: var(--sc-line-2, #dcdce0);
350
+ }
351
+
352
+ .sc-runtime-tile {
353
+ width: 22px;
354
+ height: 22px;
355
+ flex: none;
356
+ display: grid;
357
+ place-items: center;
358
+ border-radius: var(--sc-r-sm, 6px);
359
+ border: 1px solid var(--sc-line, #e9e9eb);
360
+ background: var(--sc-raised, #f6f6f7);
361
+ }
362
+
363
+ .sc-runtime-mark {
364
+ width: 13px;
365
+ height: 13px;
366
+ color: var(--sc-text-2, #3f3f46);
367
+ }
368
+
369
+ .sc-runtime-verdict {
370
+ font-size: var(--sc-fs-label);
371
+ white-space: nowrap;
372
+ }
373
+
374
+ .sc-runtime-name {
375
+ min-width: 0;
376
+ overflow: hidden;
377
+ text-overflow: ellipsis;
378
+ white-space: nowrap;
239
379
  }
240
380
 
241
381
  .soba-connect[data-theme="dark"],
242
- .soba-connect[data-theme="system"] {
382
+ .soba-connect[data-theme="system"],
383
+ .sc-btn[data-theme="dark"],
384
+ .sc-btn[data-theme="system"] {
243
385
  color-scheme: dark;
244
386
  }
245
387
 
246
388
  @media (prefers-color-scheme: dark) {
247
- .soba-connect[data-theme="system"] {
389
+ .soba-connect[data-theme="system"],
390
+ .sc-btn[data-theme="system"] {
248
391
  --sc-ground: #0f0f11;
249
392
  --sc-sheet: #161618;
250
393
  --sc-raised: #1d1d20;
@@ -255,10 +398,17 @@ a.sc-btn {
255
398
  --sc-muted: #8d8d95;
256
399
  --sc-accent: #f2f2f3;
257
400
  --sc-accent-fg: #131316;
401
+
402
+ --sc-ok: #4cb782;
403
+ --sc-warn: #f2994a;
404
+
405
+ --sc-shadow-1: 0 1px 2px rgb(0 0 0 / 34%);
406
+ --sc-shadow-2: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px -12px rgb(0 0 0 / 64%);
258
407
  }
259
408
  }
260
409
 
261
- .soba-connect[data-theme="dark"] {
410
+ .soba-connect[data-theme="dark"],
411
+ .sc-btn[data-theme="dark"] {
262
412
  --sc-ground: #0f0f11;
263
413
  --sc-sheet: #161618;
264
414
  --sc-raised: #1d1d20;
@@ -269,6 +419,18 @@ a.sc-btn {
269
419
  --sc-muted: #8d8d95;
270
420
  --sc-accent: #f2f2f3;
271
421
  --sc-accent-fg: #131316;
422
+
423
+ --sc-ok: #4cb782;
424
+ --sc-warn: #f2994a;
425
+
426
+ --sc-shadow-1: 0 1px 2px rgb(0 0 0 / 34%);
427
+ --sc-shadow-2: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px -12px rgb(0 0 0 / 64%);
428
+ }
429
+
430
+ .soba-connect.sc-fill {
431
+ max-width: none;
432
+
433
+ margin-inline: 0;
272
434
  }
273
435
 
274
436
  .sc-plans {
@@ -282,23 +444,93 @@ a.sc-btn {
282
444
  .sc-plan {
283
445
  display: flex;
284
446
  flex-direction: column;
285
- gap: 10px;
286
- padding: 16px;
447
+ gap: 0;
448
+ padding: 18px;
287
449
  border: 1px solid var(--sc-line, #e5e5e7);
288
- border-radius: var(--sc-r, 10px);
450
+ border-radius: var(--sc-r-lg, 14px);
289
451
  background: var(--sc-sheet, #fff);
290
452
  }
291
453
 
454
+ @supports (grid-template-rows: subgrid) {
455
+ .sc-plan {
456
+ display: grid;
457
+ grid-row: span 7;
458
+ grid-template-rows: subgrid;
459
+
460
+ row-gap: 0;
461
+ }
462
+
463
+
464
+ .sc-plan > .sc-btn {
465
+ align-self: stretch;
466
+ }
467
+ }
468
+
469
+ .sc-plan > * + * {
470
+ margin-top: 7px;
471
+ }
472
+
473
+ .sc-plan > .sc-plan-price {
474
+ margin-top: 12px;
475
+ }
476
+
477
+ .sc-plan > .sc-btn {
478
+ margin-top: 12px;
479
+ }
480
+
481
+ .sc-plan > .sc-btn + .sc-plan-allowance {
482
+ margin-top: 15px;
483
+ }
484
+
485
+ .sc-plan > .sc-plan-band:empty {
486
+ margin-top: 0;
487
+ }
488
+
489
+ .sc-plan-band {
490
+ display: flex;
491
+ flex-direction: column;
492
+ align-items: stretch;
493
+ }
494
+ .sc-plan-band:empty {
495
+ min-height: 0;
496
+ }
497
+
498
+ .sc-plan > .sc-sub {
499
+ margin: 0;
500
+ }
501
+
292
502
  .sc-plan-current {
293
- border-color: var(--sc-text, #18181b);
503
+ background: var(--sc-raised, #f6f6f7);
504
+ border-color: var(--sc-line, #e9e9eb);
505
+ }
506
+
507
+ .sc-plan-allowance {
508
+ margin: 0;
509
+ display: flex;
510
+ flex-direction: column;
511
+ gap: 2px;
512
+ }
513
+ .sc-plan-figure {
514
+ font-size: var(--sc-fs-body, 15px);
515
+ font-weight: 600;
516
+ letter-spacing: -0.01em;
517
+ font-variant-numeric: tabular-nums;
518
+ }
519
+ .sc-plan-qualifier {
520
+ font-size: var(--sc-fs-label, 11.5px);
521
+ line-height: 1.45;
522
+ color: var(--sc-muted, #6b6b73);
294
523
  }
295
524
 
296
525
  .sc-plan-badge {
297
- font-size: 11px;
526
+ font-size: var(--sc-fs-label, 11px);
298
527
  padding: 2px 6px;
299
- border-radius: 999px;
528
+ border-radius: var(--sc-r-pill, 999px);
300
529
  background: var(--sc-text, #18181b);
301
530
  color: var(--sc-sheet, #fff);
531
+
532
+ border: 1px solid transparent;
533
+ white-space: nowrap;
302
534
  }
303
535
 
304
536
  .sc-plan-price {
@@ -309,7 +541,7 @@ a.sc-btn {
309
541
  }
310
542
 
311
543
  .sc-plan-amount {
312
- font-size: 28px;
544
+ font-size: var(--sc-fs-display, 24px);
313
545
  font-weight: 600;
314
546
  letter-spacing: -0.02em;
315
547
 
@@ -317,13 +549,16 @@ a.sc-btn {
317
549
  }
318
550
 
319
551
  .sc-plan-interval {
320
- font-size: 13px;
552
+ font-size: var(--sc-fs-small, 13px);
321
553
  color: var(--sc-muted, #6b6b73);
322
554
  }
323
555
 
324
- .sc-plan .sc-btn {
325
- margin-top: auto;
556
+ .sc-plan > .sc-btn {
326
557
  width: 100%;
558
+ justify-content: center;
559
+ border-radius: var(--sc-r-pill, 999px);
560
+ padding-block: 0.72em;
561
+ font-weight: 550;
327
562
  }
328
563
 
329
564
  .sc-plan .sc-facts {
@@ -348,8 +583,14 @@ a.sc-btn {
348
583
 
349
584
  .sc-plan-compute {
350
585
  display: grid;
351
- gap: 4px;
352
- font-size: 14px;
586
+
587
+ align-content: start;
588
+ gap: 3px;
589
+ font-size: 13.5px;
590
+ }
591
+
592
+ .sc-plan-compute > .sc-fact-key {
593
+ font-size: var(--sc-fs-label, 11.5px);
353
594
  }
354
595
 
355
596
  .sc-compute {
@@ -357,7 +598,8 @@ a.sc-btn {
357
598
  margin: 0;
358
599
  padding: 0;
359
600
  display: grid;
360
- gap: 3px;
601
+
602
+ gap: 6px;
361
603
  }
362
604
 
363
605
  .sc-compute li {
@@ -377,6 +619,14 @@ a.sc-btn {
377
619
  color: var(--sc-text-2, #3f3f46);
378
620
  }
379
621
 
622
+ .sc-compute-marks {
623
+ display: inline-flex;
624
+ align-items: center;
625
+ gap: 5px;
626
+ margin-left: 7px;
627
+ vertical-align: -2px;
628
+ }
629
+
380
630
  .sc-compute li.sc-compute-own::before {
381
631
  content: "\u2713";
382
632
  color: var(--sc-ok, #22a06b);
@@ -384,8 +634,13 @@ a.sc-btn {
384
634
  top: 1px;
385
635
  }
386
636
 
637
+ @supports not (grid-template-rows: subgrid) {
638
+ .sc-plan .sc-sub {
639
+ min-height: 2.8em;
640
+ }
641
+ }
642
+
387
643
  .sc-plan .sc-sub {
388
- min-height: 2.8em;
389
644
  margin: 0;
390
645
  }
391
646
 
@@ -413,23 +668,69 @@ a.sc-btn {
413
668
  place-items: center;
414
669
  }
415
670
 
671
+ .sc-modal:not([open]) {
672
+ display: none;
673
+ }
674
+
416
675
  .sc-modal::backdrop {
417
- background: rgb(15 15 17 / 55%);
676
+ background: rgb(15 15 17 / 42%);
677
+ backdrop-filter: blur(4px);
418
678
  }
419
679
 
420
680
  .sc-modal-sheet {
421
681
  position: relative;
422
682
  width: 100%;
423
683
 
424
- max-width: 420px;
425
- background: var(--sc-sheet, #ffffff);
426
- border: 1.5px solid var(--sc-line, #e9e9eb);
427
- border-radius: 14px;
428
- box-shadow: 0 24px 60px -12px rgb(15 15 17 / 22%);
684
+ max-width: 380px;
685
+
686
+ background: var(--sc-shell, var(--sc-sheet, #ffffff));
687
+ border: 1px solid var(--sc-line, #e9e9eb);
688
+ border-radius: var(--sc-r-lg, 14px);
689
+
690
+ box-shadow:
691
+ 0 1px 2px rgb(15 15 17 / 6%),
692
+ 0 12px 28px -8px rgb(15 15 17 / 16%),
693
+ 0 36px 64px -28px rgb(15 15 17 / 24%);
429
694
 
430
695
  outline: none;
431
696
  }
432
697
 
698
+ @keyframes sc-sheet-in {
699
+ from {
700
+ opacity: 0;
701
+ transform: translateY(8px) scale(0.985);
702
+ }
703
+ }
704
+
705
+ @keyframes sc-scrim-in {
706
+ from {
707
+ opacity: 0;
708
+ }
709
+ }
710
+
711
+ .sc-modal[open] .sc-modal-sheet {
712
+ animation: sc-sheet-in 190ms cubic-bezier(0.2, 0.8, 0.2, 1);
713
+ }
714
+
715
+ .sc-modal[open]::backdrop {
716
+ animation: sc-scrim-in 190ms ease;
717
+ }
718
+
719
+ @media (prefers-reduced-motion: reduce) {
720
+ .sc-modal[open] .sc-modal-sheet,
721
+ .sc-modal[open]::backdrop {
722
+ animation: none;
723
+ }
724
+ .sc-opt,
725
+ .sc-opt-tile,
726
+ .sc-alt-link {
727
+ transition: none;
728
+ }
729
+ .sc-opt:active {
730
+ transform: none;
731
+ }
732
+ }
733
+
433
734
  .sc-modal-close {
434
735
  position: absolute;
435
736
  top: 10px;
@@ -442,7 +743,7 @@ a.sc-btn {
442
743
  font-size: 20px;
443
744
  line-height: 1;
444
745
  padding: 4px 8px;
445
- border-radius: 6px;
746
+ border-radius: var(--sc-r-sm, 6px);
446
747
  cursor: pointer;
447
748
  }
448
749
 
@@ -452,129 +753,1648 @@ a.sc-btn {
452
753
  }
453
754
 
454
755
  .sc-modal-sheet .sc-card {
455
- padding: 26px 24px 22px;
756
+ padding: 24px 22px 18px;
456
757
  border: 0;
457
758
  border-radius: 0;
458
759
  background: transparent;
459
760
  box-shadow: none;
460
761
  }
461
762
 
763
+ .sc-modal-sheet .sc-machine {
764
+ border: 1px solid var(--sc-line, #e9e9eb);
765
+ border-radius: var(--sc-r, 10px);
766
+ padding: 11px 12px;
767
+ margin-top: 14px;
768
+ }
769
+
770
+ .sc-conns {
771
+ display: grid;
772
+ gap: 14px;
773
+ }
774
+
775
+ .sc-modal-sheet .sc-machine:first-child {
776
+ margin-top: 0;
777
+ }
778
+
779
+ .sc-modal-sheet .sc-title {
780
+ font-size: 17px;
781
+ font-weight: 600;
782
+ margin-bottom: 5px;
783
+ }
784
+
785
+ .sc-modal-sheet .sc-sub {
786
+ font-size: 13.5px;
787
+ line-height: 1.45;
788
+ margin-bottom: 15px;
789
+ }
790
+
462
791
  .sc-modal-foot {
792
+ display: flex;
793
+ align-items: center;
794
+ justify-content: center;
795
+ gap: 6px;
463
796
  padding: 11px 14px;
464
- border-top: 1.5px solid var(--sc-line, #e9e9eb);
797
+ border-top: 1px solid var(--sc-line, #e9e9eb);
465
798
  text-align: center;
466
799
  font-size: 12.5px;
467
800
  color: var(--sc-muted, #6b6b73);
468
801
  }
469
802
 
470
- .sc-mark {
471
- width: 44px;
472
- height: 44px;
473
- margin: 0 auto 14px;
474
- border-radius: 11px;
475
-
476
- background: var(--sc-accent, #18181b);
477
- display: grid;
478
- place-items: center;
803
+ .sc-foot-mark {
804
+ width: 13px;
805
+ height: 13px;
806
+ flex: none;
807
+ opacity: 0.75;
479
808
  }
480
809
 
481
- .sc-mark svg {
482
- width: 24px;
483
- height: 24px;
484
- color: var(--sc-accent-fg, #ffffff);
810
+ .sc-app-mark {
811
+ display: block;
812
+ width: 38px;
813
+ height: 38px;
814
+ margin: 0 auto 12px;
815
+ border-radius: var(--sc-r, 10px);
816
+ object-fit: contain;
485
817
  }
486
818
 
487
819
  .sc-h {
488
- font-size: 19px;
489
- font-weight: 700;
820
+ font-size: 17px;
821
+ font-weight: 600;
490
822
  letter-spacing: -0.02em;
491
823
  margin: 0;
492
824
  text-align: center;
493
825
  }
494
826
 
495
827
  .sc-p {
496
- font-size: 14px;
828
+ font-size: 13.5px;
829
+ line-height: 1.45;
497
830
  color: var(--sc-muted, #6b6b73);
498
- margin: 7px auto 0;
499
- max-width: 40ch;
831
+ margin: 5px auto 0;
832
+
833
+ max-width: 34ch;
500
834
  text-align: center;
501
835
  }
502
836
 
503
837
  .sc-opts {
504
838
  display: grid;
505
- gap: 10px;
506
- margin-top: 20px;
839
+ gap: 8px;
840
+ margin-top: 16px;
507
841
  text-align: left;
508
842
  }
509
843
 
510
844
  .sc-opt {
511
- display: flex;
845
+ display: grid;
846
+
847
+ grid-template-columns: auto 1fr auto;
512
848
  align-items: center;
513
- gap: 10px;
849
+ gap: 11px;
514
850
  width: 100%;
515
- padding: 12px 14px;
516
- border: 1.5px solid var(--sc-line-2, #dcdce0);
517
- border-radius: 9px;
851
+ padding: 9px 11px;
852
+ border: 1px solid var(--sc-line-2, #dcdce0);
853
+ border-radius: var(--sc-r, 10px);
518
854
  background: var(--sc-sheet, #ffffff);
519
855
  color: var(--sc-text, #1a1a1c);
520
856
  font: inherit;
521
- font-size: 14.5px;
522
- font-weight: 600;
523
857
  text-align: left;
524
858
  cursor: pointer;
859
+
860
+ transition:
861
+ background-color 120ms ease,
862
+ border-color 120ms ease;
525
863
  }
526
864
 
527
865
  .sc-opt:hover {
528
866
  background: var(--sc-raised, #f6f6f7);
867
+ border-color: var(--sc-muted, #6b6b73);
529
868
  }
530
869
 
531
- .sc-opt[aria-pressed="true"] {
532
- border-color: var(--sc-accent, #18181b);
870
+ .sc-opt:hover .sc-opt-tile {
871
+ background: var(--sc-sheet, #ffffff);
872
+ }
873
+
874
+ .sc-opt:active {
875
+ transform: translateY(0.5px);
876
+ }
877
+
878
+ .sc-opt:disabled {
879
+ opacity: 0.55;
880
+ cursor: default;
881
+ }
882
+
883
+ .sc-opt:disabled:hover {
884
+ background: var(--sc-sheet, #ffffff);
885
+ border-color: var(--sc-line-2, #dcdce0);
886
+ }
887
+
888
+ .sc-opt-tile {
889
+ position: relative;
890
+ width: 32px;
891
+ height: 32px;
892
+ flex: none;
893
+ display: grid;
894
+ place-items: center;
895
+ border-radius: var(--sc-r, 10px);
896
+ border: 1px solid var(--sc-line, #e9e9eb);
897
+ background: var(--sc-raised, #f6f6f7);
898
+ transition: background-color 120ms ease;
533
899
  }
534
900
 
535
901
  .sc-opt-mark {
536
- width: 17px;
537
- height: 17px;
902
+ width: 18px;
903
+ height: 18px;
538
904
  flex: none;
539
-
540
905
  color: currentColor;
541
906
  }
542
907
 
543
- .sc-opt-label {
908
+ .sc-opt-text {
544
909
  min-width: 0;
545
910
  }
546
911
 
912
+ .sc-opt-label {
913
+ display: block;
914
+ font-size: var(--sc-fs-body);
915
+
916
+ font-weight: 500;
917
+ letter-spacing: -0.01em;
918
+ }
919
+
920
+ .sc-opt-sub {
921
+ display: block;
922
+ margin-top: 1px;
923
+ font-size: 12.5px;
924
+ line-height: 1.35;
925
+ color: var(--sc-muted, #6b6b73);
926
+ }
927
+
547
928
  .sc-opt-last {
548
- margin-left: auto;
549
929
  flex: none;
550
930
  font-size: 11px;
551
931
  font-weight: 600;
552
932
  color: var(--sc-muted, #6b6b73);
553
933
  background: var(--sc-raised, #f6f6f7);
554
- border-radius: 5px;
934
+ border-radius: var(--sc-r-sm, 6px);
555
935
  padding: 3px 7px;
936
+ white-space: nowrap;
556
937
  }
557
938
 
558
- .sc-btn-quiet {
559
- border-color: transparent;
939
+ .sc-opt-group {
940
+ margin: 16px 0 7px;
941
+ font-size: 12.5px;
942
+ font-weight: 600;
943
+ color: var(--sc-text-2, #3f3f46);
944
+ }
945
+
946
+ .sc-opt-note {
947
+ margin: 8px 0 0;
948
+ font-size: 12.5px;
949
+ line-height: 1.45;
950
+ color: var(--sc-muted, #6b6b73);
951
+ }
952
+
953
+ .sc-or {
954
+ display: flex;
955
+ align-items: center;
956
+ gap: 12px;
957
+ margin: 16px 0;
958
+ color: var(--sc-muted, #6b6b73);
959
+ font-size: 12.5px;
960
+ }
961
+
962
+ .sc-or::before,
963
+ .sc-or::after {
964
+ content: "";
965
+ flex: 1;
966
+ height: 1px;
967
+ background: var(--sc-line, #e9e9eb);
968
+ }
969
+
970
+ .sc-opt-runtimes {
971
+ display: flex;
972
+ flex-wrap: wrap;
973
+ gap: 3px 11px;
974
+ margin-top: 7px;
975
+ }
976
+
977
+ .sc-rt {
978
+ display: inline-flex;
979
+ align-items: center;
980
+ gap: 5px;
981
+ font-size: 11.5px;
982
+ line-height: 1.3;
983
+ color: var(--sc-muted, #6b6b73);
984
+ white-space: nowrap;
985
+ }
986
+
987
+ .sc-rt-mark {
988
+ width: 12px;
989
+ height: 12px;
990
+ flex: none;
991
+ opacity: 0.85;
992
+ }
993
+
994
+ .sc-opt-alt {
995
+ margin-top: 12px;
996
+ padding-top: 11px;
997
+ border-top: 1px solid var(--sc-line, #e9e9eb);
998
+ text-align: center;
999
+ }
1000
+
1001
+ .sc-alt-link {
1002
+ font: inherit;
1003
+ font-size: 13px;
1004
+ font-weight: 500;
1005
+ padding: 5px 8px;
1006
+ border: 0;
1007
+ border-radius: var(--sc-r-sm, 6px);
560
1008
  background: transparent;
561
1009
  color: var(--sc-muted, #6b6b73);
1010
+ cursor: pointer;
1011
+ transition: color 120ms ease;
562
1012
  }
563
1013
 
564
- .sc-btn-quiet:hover {
1014
+ .sc-alt-link:hover {
1015
+ color: var(--sc-text, #1a1a1c);
1016
+ }
1017
+
1018
+ .sc-conn,
1019
+ .sc-idrow {
1020
+ display: grid;
1021
+ grid-template-columns: auto 1fr auto;
1022
+ align-items: center;
1023
+ gap: 12px;
1024
+ }
1025
+
1026
+ .sc-conn {
1027
+ padding: 10px 12px;
1028
+ border: 1px solid var(--sc-line, #e9e9eb);
1029
+ border-radius: var(--sc-r, 10px);
1030
+ background: var(--sc-sheet, #ffffff);
1031
+ }
1032
+
1033
+ .sc-conn-note {
1034
+ grid-column: 1 / -1;
1035
+ margin: 2px 0 0;
1036
+ font-size: 12px;
1037
+ line-height: 1.4;
1038
+ color: var(--sc-muted, #6b6b73);
1039
+ }
1040
+
1041
+ .sc-conn-action {
1042
+ font: inherit;
1043
+ font-size: var(--sc-fs-small);
1044
+ font-weight: 500;
1045
+ padding: 5px 9px;
1046
+ border: 1px solid transparent;
1047
+ border-radius: var(--sc-r-sm, 6px);
1048
+ background: transparent;
1049
+ color: var(--sc-muted, #6b6b73);
1050
+ cursor: pointer;
1051
+ }
1052
+
1053
+ .sc-conn-action:hover:not(:disabled) {
1054
+ border-color: var(--sc-line-2, #dcdce0);
1055
+ color: var(--sc-text, #1a1a1c);
1056
+ }
1057
+
1058
+ .sc-conn-action:disabled {
1059
+ opacity: 0.5;
1060
+ cursor: default;
1061
+ }
1062
+
1063
+ .sc-btn-wide {
1064
+ width: 100%;
1065
+ }
1066
+
1067
+ .sc-head {
1068
+ display: grid;
1069
+ grid-template-columns: 30px 1fr 30px;
1070
+ align-items: center;
1071
+
1072
+ margin: -8px 0 14px;
1073
+ }
1074
+
1075
+ .sc-head-title {
1076
+ margin: 0;
1077
+ text-align: center;
1078
+ font-size: 14px;
1079
+ font-weight: 600;
1080
+ letter-spacing: -0.01em;
1081
+ }
1082
+
1083
+ .sc-head-back {
1084
+ display: grid;
1085
+ place-items: center;
1086
+ width: 30px;
1087
+ height: 30px;
1088
+ padding: 0;
1089
+ border: 0;
1090
+ border-radius: var(--sc-r-sm, 6px);
1091
+ background: transparent;
1092
+ color: var(--sc-muted, #6b6b73);
1093
+ cursor: pointer;
1094
+ }
1095
+
1096
+ .sc-head-back:hover {
565
1097
  background: var(--sc-raised, #f6f6f7);
566
1098
  color: var(--sc-text, #1a1a1c);
567
1099
  }
568
1100
 
569
- .sc-btn-connected {
570
- display: inline-flex;
1101
+ .sc-head-back svg {
1102
+ width: 17px;
1103
+ height: 17px;
1104
+ }
1105
+
1106
+ .sc-foot-strip {
1107
+ display: flex;
571
1108
  align-items: center;
572
- gap: 9px;
573
- font-family: var(--sc-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
1109
+ justify-content: space-between;
1110
+ gap: 12px;
1111
+ margin-top: 16px;
1112
+ padding: 10px 10px 10px 13px;
1113
+ border-radius: var(--sc-r, 10px);
1114
+ background: var(--sc-raised, #f6f6f7);
574
1115
  font-size: 13px;
1116
+ color: var(--sc-muted, #6b6b73);
1117
+ text-align: left;
575
1118
  }
576
1119
 
577
- .sc-btn-connected .sc-dot {
1120
+ .sc-foot-go {
1121
+ display: inline-flex;
1122
+ align-items: center;
1123
+ gap: 3px;
1124
+ flex: none;
1125
+ padding: 5px 9px;
1126
+ border-radius: var(--sc-r-sm, 6px);
1127
+ background: var(--sc-sheet, #ffffff);
1128
+ border: 1px solid var(--sc-line-2, #dcdce0);
1129
+ color: var(--sc-text, #1a1a1c);
1130
+ font-size: 12.5px;
1131
+ font-weight: 600;
1132
+ text-decoration: none;
1133
+ white-space: nowrap;
1134
+ }
1135
+
1136
+ .sc-foot-go:hover {
1137
+ border-color: var(--sc-muted, #6b6b73);
1138
+ }
1139
+
1140
+ .sc-foot-go svg {
1141
+ width: 13px;
1142
+ height: 13px;
1143
+ }
1144
+
1145
+ .sc-opt-go {
1146
+ width: 15px;
1147
+ height: 15px;
578
1148
  flex: none;
1149
+ color: var(--sc-line-2, #dcdce0);
1150
+ }
1151
+
1152
+ .sc-opt:hover .sc-opt-go {
1153
+ color: var(--sc-muted, #6b6b73);
1154
+ }
1155
+
1156
+ .sc-waiting {
1157
+ position: relative;
1158
+ display: grid;
1159
+ place-items: center;
1160
+ width: 84px;
1161
+ height: 84px;
1162
+
1163
+ margin: 0 auto 10px;
1164
+ }
1165
+
1166
+ .sc-waiting-orbit {
1167
+ position: absolute;
1168
+ inset: 0;
1169
+ width: 100%;
1170
+ height: 100%;
1171
+ color: var(--sc-accent, #18181b);
1172
+ animation: sc-turn 1100ms linear infinite;
1173
+ }
1174
+
1175
+ .sc-waiting-arc {
1176
+ fill: none;
1177
+ stroke: currentColor;
1178
+ stroke-width: 3;
1179
+ stroke-linecap: round;
1180
+ stroke-dasharray: 72 217;
1181
+ }
1182
+
1183
+ .sc-waiting-mark {
1184
+ width: 44px;
1185
+ height: 44px;
1186
+ color: var(--sc-text, #1a1a1c);
1187
+ }
1188
+
1189
+ @keyframes sc-turn {
1190
+ to {
1191
+ transform: rotate(1turn);
1192
+ }
1193
+ }
1194
+
1195
+ .sc-result {
1196
+ position: relative;
1197
+ display: grid;
1198
+ place-items: center;
1199
+ width: 84px;
1200
+ height: 84px;
1201
+ margin: 2px auto 18px;
1202
+
1203
+ animation: sc-land 520ms cubic-bezier(0.34, 1.4, 0.64, 1);
1204
+ }
1205
+
1206
+ .sc-result-ok {
1207
+ color: var(--sc-ok, #22a06b);
1208
+ }
1209
+
1210
+ .sc-result-off {
1211
+ color: var(--sc-muted, #6b6b73);
1212
+ --sc-ring: var(--sc-line-2, #dcdce0);
1213
+ }
1214
+
1215
+ .sc-result-ring,
1216
+ .sc-result-glyph {
1217
+ position: absolute;
1218
+ inset: 0;
1219
+ width: 100%;
1220
+ height: 100%;
1221
+ }
1222
+
1223
+ .sc-result-ring {
1224
+ transform: rotate(-90deg);
1225
+ }
1226
+
1227
+ .sc-result-circle {
1228
+ fill: none;
1229
+
1230
+ stroke: var(--sc-ring, currentColor);
1231
+ stroke-width: 3;
1232
+
1233
+ stroke-dasharray: 289;
1234
+ stroke-dashoffset: 289;
1235
+ animation: sc-sweep 560ms cubic-bezier(0.22, 0.9, 0.3, 1) forwards;
1236
+ }
1237
+
1238
+ .sc-result-path {
1239
+ fill: none;
1240
+ stroke: currentColor;
1241
+ stroke-width: 4.5;
1242
+ stroke-linecap: round;
1243
+ stroke-linejoin: round;
1244
+ stroke-dasharray: 60;
1245
+ stroke-dashoffset: 60;
1246
+ animation: sc-draw 300ms 380ms cubic-bezier(0.3, 0.8, 0.4, 1) forwards;
1247
+ }
1248
+
1249
+ .sc-result-halo {
1250
+ position: absolute;
1251
+ inset: 0;
1252
+ border-radius: 50%;
1253
+ border: 2px solid currentColor;
1254
+ opacity: 0;
1255
+ animation: sc-pulse 640ms 420ms cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
1256
+ }
1257
+
1258
+ @keyframes sc-land {
1259
+ from {
1260
+ opacity: 0;
1261
+ transform: scale(0.9);
1262
+ }
1263
+ }
1264
+
1265
+ @keyframes sc-sweep {
1266
+ to {
1267
+ stroke-dashoffset: 0;
1268
+ }
1269
+ }
1270
+
1271
+ @keyframes sc-draw {
1272
+ to {
1273
+ stroke-dashoffset: 0;
1274
+ }
1275
+ }
1276
+
1277
+ @keyframes sc-pulse {
1278
+ from {
1279
+ opacity: 0.4;
1280
+ transform: scale(1);
1281
+ }
1282
+ to {
1283
+ opacity: 0;
1284
+ transform: scale(1.32);
1285
+ }
1286
+ }
1287
+
1288
+ @media (prefers-reduced-motion: reduce) {
1289
+
1290
+ .sc-waiting-orbit {
1291
+ animation: none;
1292
+ color: var(--sc-line-2, #dcdce0);
1293
+ }
1294
+
1295
+ .sc-waiting-arc {
1296
+ stroke-dasharray: none;
1297
+ }
1298
+
1299
+
1300
+ .sc-result {
1301
+ animation: none;
1302
+ }
1303
+
1304
+ .sc-result-circle,
1305
+ .sc-result-path {
1306
+ animation: none;
1307
+ stroke-dashoffset: 0;
1308
+ }
1309
+
1310
+
1311
+ .sc-result-halo {
1312
+ display: none;
1313
+ }
1314
+ }
1315
+
1316
+ .sc-prereq {
1317
+ display: flex;
1318
+ align-items: center;
1319
+ justify-content: center;
1320
+ gap: 6px;
1321
+ margin: 10px 0 0;
1322
+ font-size: 12.5px;
1323
+ color: var(--sc-muted, #6b6b73);
1324
+ }
1325
+
1326
+ .sc-opt:focus-visible,
1327
+ .sc-btn:focus-visible,
1328
+ .sc-step-lead:focus-visible,
1329
+ .sc-step-links a:focus-visible,
1330
+ .sc-alt-link:focus-visible,
1331
+ .sc-conn-action:focus-visible,
1332
+ .sc-input:focus-visible,
1333
+ .sc-modal-close:focus-visible {
1334
+ outline: 2px solid var(--sc-accent, #18181b);
1335
+ outline-offset: 2px;
1336
+ }
1337
+
1338
+ .sc-app {
1339
+ display: inline-flex;
1340
+ align-items: center;
1341
+ gap: 4px;
1342
+ }
1343
+
1344
+ .sc-app:has(.sc-app-icon) {
1345
+ vertical-align: -3px;
1346
+ }
1347
+
1348
+ .sc-app-icon {
1349
+ width: 13px;
1350
+ height: 13px;
1351
+ flex: none;
1352
+ border-radius: 3px;
1353
+
1354
+ object-fit: contain;
1355
+ }
1356
+
1357
+ .sc-link {
1358
+ color: inherit;
1359
+ text-decoration: underline;
1360
+ text-underline-offset: 2px;
1361
+ }
1362
+
1363
+ .sc-btn-quiet {
1364
+ border-color: transparent;
1365
+ background: transparent;
1366
+ color: var(--sc-muted, #6b6b73);
1367
+ }
1368
+
1369
+ .sc-btn-quiet:hover {
1370
+ background: var(--sc-raised, #f6f6f7);
1371
+ color: var(--sc-text, #1a1a1c);
1372
+ }
1373
+
1374
+ .sc-btn-connected {
1375
+ display: inline-flex;
1376
+ align-items: center;
1377
+ gap: 8px;
1378
+
1379
+ max-width: 100%;
1380
+ min-width: 0;
1381
+
1382
+ padding: 4px 13px 4px 4px;
1383
+ border-radius: var(--sc-r-pill, 999px);
1384
+ border-color: var(--sc-line, #e9e9eb);
1385
+
1386
+ box-shadow: var(--sc-shadow-1);
1387
+ font-size: var(--sc-fs-small);
1388
+ font-weight: 500;
1389
+
1390
+ letter-spacing: -0.005em;
1391
+ transition:
1392
+ background-color 120ms ease,
1393
+ border-color 120ms ease,
1394
+ box-shadow 120ms ease;
1395
+ }
1396
+
1397
+ .sc-btn-connected:hover {
1398
+ background: var(--sc-raised, #f6f6f7);
1399
+ border-color: var(--sc-line-2, #dcdce0);
1400
+ }
1401
+
1402
+ .sc-btn-connected:active {
1403
+ transform: translateY(0.5px);
1404
+ }
1405
+
1406
+ .sc-btn-connected .sc-runtime-tile {
1407
+ border-radius: 50%;
1408
+ }
1409
+
1410
+ .sc-btn-connected:hover .sc-runtime-tile {
1411
+ background: var(--sc-sheet, #ffffff);
1412
+ }
1413
+
1414
+ .sc-btn-connected .sc-dot {
1415
+ flex: none;
1416
+ margin-left: 1px;
1417
+ }
1418
+
1419
+ .sc-btn-connected .sc-dot-ok {
1420
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--sc-ok, #22a06b) 16%, transparent);
1421
+ }
1422
+
1423
+ .sc-btn-connected .sc-dot-busy {
1424
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--sc-warn, #b06f14) 16%, transparent);
1425
+ }
1426
+
1427
+ @media (prefers-reduced-motion: no-preference) {
1428
+ .sc-btn-connected .sc-dot-ok {
1429
+ animation: sc-pulse-ok 3s ease-out infinite;
1430
+ }
1431
+ .sc-btn-connected .sc-dot-busy {
1432
+ animation: sc-pulse-busy 1.8s ease-out infinite;
1433
+ }
1434
+ }
1435
+
1436
+ @keyframes sc-pulse-ok {
1437
+ 0%,
1438
+ 70%,
1439
+ 100% {
1440
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--sc-ok, #22a06b) 16%, transparent);
1441
+ }
1442
+ 35% {
1443
+ box-shadow: 0 0 0 5px color-mix(in srgb, var(--sc-ok, #22a06b) 7%, transparent);
1444
+ }
1445
+ }
1446
+
1447
+ @keyframes sc-pulse-busy {
1448
+ 0%,
1449
+ 70%,
1450
+ 100% {
1451
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--sc-warn, #b06f14) 16%, transparent);
1452
+ }
1453
+ 35% {
1454
+ box-shadow: 0 0 0 5px color-mix(in srgb, var(--sc-warn, #b06f14) 7%, transparent);
1455
+ }
1456
+ }
1457
+
1458
+ @media (prefers-reduced-motion: reduce) {
1459
+ .sc-btn-connected {
1460
+ transition: none;
1461
+ }
1462
+ .sc-btn-connected:active {
1463
+ transform: none;
1464
+ }
1465
+ }
1466
+
1467
+ .sc-btn-connected-text {
1468
+ min-width: 0;
1469
+ overflow: hidden;
1470
+ text-overflow: ellipsis;
1471
+ white-space: nowrap;
1472
+ }
1473
+
1474
+ .sc-btn-connected-where {
1475
+ color: var(--sc-muted, #6b6b73);
1476
+ font-weight: 400;
1477
+ }
1478
+
1479
+ .sc-sr {
1480
+ position: absolute;
1481
+ width: 1px;
1482
+ height: 1px;
1483
+ padding: 0;
1484
+ margin: -1px;
1485
+ overflow: hidden;
1486
+ clip-path: inset(50%);
1487
+ white-space: nowrap;
1488
+ border: 0;
1489
+ }
1490
+
1491
+ .soba-connect:has(> .sc-limit) {
1492
+ max-width: none;
1493
+ }
1494
+
1495
+ .soba-connect .sc-limit {
1496
+ max-width: none;
1497
+
1498
+ container-type: inline-size;
1499
+ container-name: sc-limit;
1500
+ }
1501
+ .sc-limit-actions {
1502
+ display: flex;
1503
+ flex-wrap: wrap-reverse;
1504
+ justify-content: flex-end;
1505
+ gap: 8px;
1506
+ margin-top: 16px;
1507
+ }
1508
+ .sc-limit-actions .sc-btn {
1509
+
1510
+ flex: 0 1 auto;
1511
+ min-width: max-content;
1512
+ }
1513
+
1514
+ @container sc-limit (max-width: 480px) {
1515
+ .sc-limit-actions {
1516
+ flex-direction: column-reverse;
1517
+ align-items: stretch;
1518
+ }
1519
+ .sc-limit-actions .sc-btn {
1520
+ width: 100%;
1521
+ }
1522
+ }
1523
+
1524
+ .sc-nudge {
1525
+
1526
+ display: grid;
1527
+ grid-template-columns: minmax(0, 1fr) auto;
1528
+ column-gap: 18px;
1529
+ padding: 16px 18px 15px;
1530
+ border: 1px solid var(--sc-line, #e9e9eb);
1531
+
1532
+ border-radius: var(--sc-r, 10px);
1533
+ background: var(--sc-sheet, #ffffff);
1534
+ box-shadow: var(--sc-shadow-1);
1535
+ }
1536
+
1537
+ .sc-nudge-top {
1538
+ grid-column: 1;
1539
+ min-width: 0;
1540
+ }
1541
+ .sc-nudge-say {
1542
+ min-width: 0;
1543
+ }
1544
+
1545
+ .sc-nudge > .sc-btn {
1546
+ grid-column: 2;
1547
+ align-self: end;
1548
+ justify-self: end;
1549
+ }
1550
+
1551
+ .sc-nudge:not(:has(.sc-nudge-steps)) > .sc-btn {
1552
+ grid-row: 1;
1553
+ align-self: center;
1554
+ }
1555
+
1556
+ .soba-connect:has(> .sc-nudge) {
1557
+ container-type: inline-size;
1558
+ container-name: sc-nudge;
1559
+ }
1560
+
1561
+ @container sc-nudge (max-width: 460px) {
1562
+ .sc-nudge {
1563
+ grid-template-columns: minmax(0, 1fr);
1564
+ }
1565
+
1566
+ .sc-nudge > .sc-btn,
1567
+ .sc-nudge:not(:has(.sc-nudge-steps)) > .sc-btn {
1568
+ grid-column: 1;
1569
+ grid-row: auto;
1570
+ align-self: start;
1571
+ margin-top: 14px;
1572
+ }
1573
+ }
1574
+ .sc-nudge-title {
1575
+ margin: 0;
1576
+ font-size: var(--sc-fs-title);
1577
+ font-weight: 600;
1578
+ line-height: 1.3;
1579
+ letter-spacing: -0.01em;
1580
+ color: var(--sc-text, #1a1a1c);
1581
+ }
1582
+ .sc-nudge-detail {
1583
+ margin: 3px 0 0;
1584
+ font-size: var(--sc-fs-body);
1585
+ line-height: 1.5;
1586
+ color: var(--sc-muted, #6b6b73);
1587
+ }
1588
+
1589
+ .sc-nudge-stalled .sc-nudge-title {
1590
+ color: var(--sc-warn, #b06f14);
1591
+ }
1592
+
1593
+ .sc-nudge-note {
1594
+ margin: 6px 0 0;
1595
+ font-size: var(--sc-fs-small, 12px);
1596
+ line-height: 1.45;
1597
+ color: var(--sc-muted, #6b6b73);
1598
+ }
1599
+
1600
+ .sc-nudge-more {
1601
+ display: inline-flex;
1602
+ align-self: start;
1603
+ align-items: center;
1604
+ gap: 5px;
1605
+ margin: 9px 0 0 -8px;
1606
+ padding: 3px 8px;
1607
+ font-size: var(--sc-fs-body);
1608
+ }
1609
+ .sc-nudge-chev {
1610
+ flex: none;
1611
+ width: 13px;
1612
+ height: 13px;
1613
+ transition: transform 150ms ease;
1614
+ }
1615
+ .sc-nudge-more[aria-expanded="true"] > .sc-nudge-chev {
1616
+ transform: rotate(180deg);
1617
+ }
1618
+ @media (prefers-reduced-motion: reduce) {
1619
+ .sc-nudge-chev {
1620
+ transition: none;
1621
+ }
1622
+ }
1623
+
1624
+ .sc-nudge-steps {
1625
+ grid-column: 1;
1626
+ counter-reset: sc-step;
1627
+ margin: 11px 0 2px;
1628
+ padding: 0;
1629
+ list-style: none;
1630
+ }
1631
+ .sc-nudge-steps li {
1632
+ position: relative;
1633
+ display: grid;
1634
+ grid-template-columns: 20px minmax(0, 1fr);
1635
+
1636
+ gap: 0 12px;
1637
+ padding-bottom: 14px;
1638
+ font-size: var(--sc-fs-body);
1639
+ line-height: 1.5;
1640
+ }
1641
+ .sc-nudge-steps li:last-child {
1642
+ padding-bottom: 0;
1643
+ }
1644
+
1645
+ .sc-nudge-steps li::before {
1646
+ counter-increment: sc-step;
1647
+ content: counter(sc-step);
1648
+ grid-column: 1;
1649
+ grid-row: 1;
1650
+ display: grid;
1651
+ place-items: center;
1652
+ width: 20px;
1653
+ height: 20px;
1654
+ border: 1px solid var(--sc-line-2, #dcdce0);
1655
+ border-radius: 50%;
1656
+ background: var(--sc-sheet, #ffffff);
1657
+ font-size: var(--sc-fs-small);
1658
+ font-weight: 600;
1659
+ font-variant-numeric: tabular-nums;
1660
+ line-height: 1;
1661
+ color: var(--sc-muted, #6b6b73);
1662
+ }
1663
+
1664
+ .sc-nudge-steps li:not(:last-child)::after {
1665
+ content: "";
1666
+ position: absolute;
1667
+
1668
+ left: 9.5px;
1669
+ top: 23px;
1670
+ bottom: 2px;
1671
+ width: 1px;
1672
+ background: var(--sc-line, #e9e9eb);
1673
+ }
1674
+
1675
+ .sc-nudge-steps strong {
1676
+ grid-column: 2;
1677
+ font-weight: 600;
1678
+ color: var(--sc-text, #1a1a1c);
1679
+ }
1680
+ .sc-nudge-steps span {
1681
+ grid-column: 2;
1682
+ color: var(--sc-muted, #6b6b73);
1683
+ }
1684
+
1685
+ .sc-step-lead {
1686
+ grid-column: 2;
1687
+ justify-self: start;
1688
+ padding: 0;
1689
+ border: 0;
1690
+ background: none;
1691
+ font: inherit;
1692
+ font-weight: 600;
1693
+ color: var(--sc-text, #1a1a1c);
1694
+ text-align: left;
1695
+ cursor: pointer;
1696
+ text-decoration: underline;
1697
+ text-decoration-color: color-mix(in srgb, currentcolor 30%, transparent);
1698
+ text-underline-offset: 3px;
1699
+ }
1700
+ .sc-step-lead:hover {
1701
+ text-decoration-color: currentcolor;
1702
+ }
1703
+
1704
+ .sc-step-links {
1705
+ grid-column: 2;
1706
+ margin-top: 3px;
1707
+
1708
+ font-size: var(--sc-fs-small);
1709
+ color: var(--sc-muted, #6b6b73);
1710
+ }
1711
+ .sc-step-links a {
1712
+ color: var(--sc-text-2, #3f3f46);
1713
+
1714
+ text-decoration: underline;
1715
+ text-decoration-color: color-mix(in srgb, currentcolor 35%, transparent);
1716
+ text-underline-offset: 2px;
1717
+ }
1718
+ .sc-step-links a:hover {
1719
+ color: var(--sc-text, #1a1a1c);
1720
+ text-decoration-color: currentcolor;
1721
+ }
1722
+ .sc-step-links a:not(:last-child)::after {
1723
+ content: "\xB7";
1724
+
1725
+ margin: 0 5px;
1726
+ color: var(--sc-muted, #6b6b73);
1727
+ text-decoration: none;
1728
+ display: inline-block;
1729
+ }
1730
+
1731
+ .sc-step-links a:first-of-type {
1732
+ margin-left: 6px;
1733
+ }
1734
+
1735
+ .sc-nudge .sc-btn-primary {
1736
+ flex: none;
1737
+ margin-left: auto;
1738
+ padding: 8px 15px;
1739
+ font-size: var(--sc-fs-small);
1740
+ }
1741
+
1742
+ .sc-plan-reward {
1743
+ display: flex;
1744
+ flex-direction: column;
1745
+ align-items: flex-start;
1746
+ gap: 6px;
1747
+ }
1748
+
1749
+ .sc-plan-reward-line {
1750
+ position: relative;
1751
+ margin: 0;
1752
+ padding-left: 16px;
1753
+ font-size: 13px;
1754
+ line-height: 1.45;
1755
+ color: var(--sc-text-2, #3f3f46);
1756
+ }
1757
+ .sc-plan-reward-line::before {
1758
+ content: "\u2713";
1759
+ position: absolute;
1760
+ left: 2px;
1761
+ top: 1px;
1762
+ font-size: 11px;
1763
+ color: var(--sc-ok, #22a06b);
1764
+ }
1765
+
1766
+ .sc-btn-icon {
1767
+ display: inline-flex;
1768
+ align-items: center;
1769
+ gap: 7px;
1770
+ }
1771
+ .sc-btn-mark {
1772
+ width: 13px;
1773
+ height: 13px;
1774
+ flex: none;
1775
+ }
1776
+
1777
+ .soba-connect.sc-compact {
1778
+ width: auto;
1779
+ max-width: none;
1780
+ margin: 0;
1781
+ font-size: 13px;
1782
+ }
1783
+ .sc-compact .sc-compute-act {
1784
+ margin-top: 0;
1785
+ }
1786
+ .sc-compact .sc-btn {
1787
+ padding: 4px 9px;
1788
+ font-size: 12px;
1789
+ line-height: 18px;
1790
+ }
1791
+ .sc-compact .sc-btn-icon {
1792
+ gap: 6px;
1793
+ }
1794
+ .sc-compact .sc-btn-mark {
1795
+ width: 12px;
1796
+ height: 12px;
1797
+ }
1798
+
1799
+ .sc-plan-reward-open {
1800
+ padding-left: 0;
1801
+ }
1802
+ .sc-plan-reward-open::before {
1803
+ content: none;
1804
+ }
1805
+
1806
+ .sc-plan-reward-need {
1807
+ color: var(--sc-muted, #6b6b73);
1808
+ }
1809
+ .sc-plan-reward-need::before {
1810
+ content: "\u2013";
1811
+ font-weight: 400;
1812
+ color: var(--sc-line-2, #dcdce0);
1813
+ }
1814
+
1815
+ .sc-plan .sc-plan-reward-line {
1816
+ padding: 9px 11px 9px 27px;
1817
+ border: 1px solid var(--sc-line, #e9e9eb);
1818
+ border-radius: var(--sc-r-sm, 6px);
1819
+ background: var(--sc-sheet, #ffffff);
1820
+ }
1821
+
1822
+ .sc-plan .sc-plan-reward-line::before {
1823
+ left: 11px;
1824
+ top: 9px;
1825
+ }
1826
+
1827
+ .sc-plan .sc-plan-reward-open {
1828
+ padding-left: 11px;
1829
+ }
1830
+
1831
+ .sc-plan-reward-act {
1832
+ display: grid;
1833
+ width: 100%;
1834
+ border: 0;
1835
+ background: transparent;
1836
+ font-family: inherit;
1837
+ font-weight: 400;
1838
+ text-align: left;
1839
+ cursor: pointer;
1840
+ transition:
1841
+ border-color 120ms ease,
1842
+ background-color 120ms ease;
1843
+ }
1844
+
1845
+ .sc-plan-reward-act::before {
1846
+ transition: opacity 120ms ease;
1847
+ }
1848
+
1849
+ .sc-plan-reward-act > span {
1850
+ grid-area: 1 / 1;
1851
+ transition:
1852
+ opacity 120ms ease,
1853
+ visibility 120ms;
1854
+ }
1855
+
1856
+ .sc-plan-reward-act .sc-reward-do {
1857
+ display: inline-flex;
1858
+ align-items: center;
1859
+ gap: 7px;
1860
+
1861
+ margin-left: -16px;
1862
+ color: var(--sc-text, #1a1a1c);
1863
+ font-weight: 500;
1864
+ opacity: 0;
1865
+ visibility: hidden;
1866
+ }
1867
+
1868
+ .sc-reward-mark {
1869
+ width: 13px;
1870
+ height: 13px;
1871
+ flex: none;
1872
+ }
1873
+
1874
+ .sc-plan-reward-act:hover,
1875
+ .sc-plan-reward-act:focus-visible {
1876
+ border-color: var(--sc-line-2, #dcdce0);
1877
+ background: var(--sc-raised, #f6f6f7);
1878
+ }
1879
+
1880
+ .sc-plan-reward-act:hover .sc-reward-said,
1881
+ .sc-plan-reward-act:focus-visible .sc-reward-said {
1882
+ opacity: 0;
1883
+ visibility: hidden;
1884
+ }
1885
+
1886
+ .sc-plan-reward-act:hover .sc-reward-do,
1887
+ .sc-plan-reward-act:focus-visible .sc-reward-do {
1888
+ opacity: 1;
1889
+ visibility: visible;
1890
+ }
1891
+
1892
+ .sc-plan-reward-act:hover::before,
1893
+ .sc-plan-reward-act:focus-visible::before {
1894
+ opacity: 0;
1895
+ }
1896
+
1897
+ @media (prefers-reduced-motion: reduce) {
1898
+ .sc-plan-reward-act,
1899
+ .sc-plan-reward-act > span {
1900
+ transition: none;
1901
+ }
1902
+ }
1903
+
1904
+ .sc-current-foot .sc-plan-reward-line {
1905
+ padding: 9px 11px 9px 27px;
1906
+ border: 1px solid var(--sc-line, #e9e9eb);
1907
+ border-radius: var(--sc-r-sm, 6px);
1908
+ background: var(--sc-raised, #f6f6f7);
1909
+ }
1910
+
1911
+ .sc-current-foot .sc-plan-reward-line::before {
1912
+ left: 11px;
1913
+ top: 9px;
1914
+ }
1915
+
1916
+ .sc-current-foot .sc-plan-reward-need::before {
1917
+ content: "!";
1918
+ font-weight: 600;
1919
+ color: var(--sc-muted, #6b6b73);
1920
+ }
1921
+
1922
+ .sc-current-foot .sc-btn {
1923
+ border-radius: var(--sc-r-pill, 999px);
1924
+ padding-block: 0.6em;
1925
+ }
1926
+
1927
+ .sc-billing {
1928
+ display: flex;
1929
+ flex-direction: column;
1930
+ gap: 28px;
1931
+ }
1932
+
1933
+ .sc-billing-plans {
1934
+ display: flex;
1935
+ flex-direction: column;
1936
+ gap: 10px;
1937
+ }
1938
+
1939
+ .sc-current {
1940
+ display: flex;
1941
+ flex-direction: column;
1942
+ gap: 14px;
1943
+ }
1944
+
1945
+ .sc-section-title {
1946
+ margin: 0;
1947
+ font-size: var(--sc-fs-label, 11.5px);
1948
+ font-weight: 600;
1949
+ color: var(--sc-muted, #6b6b73);
1950
+ }
1951
+
1952
+ .sc-current-grid {
1953
+ display: flex;
1954
+ flex-wrap: wrap;
1955
+ gap: 12px 32px;
1956
+ align-items: flex-start;
1957
+ }
1958
+
1959
+ .sc-current-main {
1960
+ flex: 3 1 260px;
1961
+ min-width: 0;
1962
+ display: flex;
1963
+ flex-direction: column;
1964
+ gap: 5px;
1965
+ }
1966
+
1967
+ .sc-current-trial {
1968
+ margin: 0;
1969
+ display: flex;
1970
+ align-items: center;
1971
+ }
1972
+
1973
+ .sc-current-name {
1974
+ margin: 0;
1975
+ display: flex;
1976
+ align-items: center;
1977
+ gap: 10px;
1978
+ font-size: var(--sc-fs-title, 17px);
1979
+ font-weight: 600;
1980
+ letter-spacing: -0.025em;
1981
+ line-height: 1.1;
1982
+ }
1983
+
1984
+ .sc-trial-badge {
1985
+ font-size: 11.5px;
1986
+ font-weight: 500;
1987
+ padding: 3px 8px;
1988
+ border-radius: var(--sc-r-pill, 999px);
1989
+ background: var(--sc-raised, #f6f6f7);
1990
+ color: var(--sc-text-2, #3f3f46);
1991
+ white-space: nowrap;
1992
+ }
1993
+
1994
+ .sc-current-foot {
1995
+ display: flex;
1996
+ flex-wrap: wrap;
1997
+ align-items: center;
1998
+ justify-content: space-between;
1999
+ gap: 10px 16px;
2000
+ padding-top: 12px;
2001
+ border-top: 1px solid var(--sc-line, #e9e9eb);
2002
+ }
2003
+ .sc-current-foot .sc-plan-reward-line {
2004
+ flex: 1 1 240px;
2005
+ }
2006
+
2007
+ .sc-usage {
2008
+ flex: 2 1 240px;
2009
+ min-width: 0;
2010
+ display: flex;
2011
+ flex-direction: column;
2012
+ gap: 7px;
2013
+
2014
+ padding-top: 7px;
2015
+ }
2016
+
2017
+ .sc-usage .sc-fact-key {
2018
+ font-size: var(--sc-fs-label, 11.5px);
2019
+ font-weight: 600;
2020
+ }
2021
+
2022
+ .sc-usage-figure {
2023
+ font-size: var(--sc-fs-title, 17px);
2024
+ font-weight: 600;
2025
+ letter-spacing: -0.01em;
2026
+ font-variant-numeric: tabular-nums;
2027
+ }
2028
+
2029
+ .sc-usage-line {
2030
+ margin: 0;
2031
+ font-size: 12.5px;
2032
+ line-height: 1.45;
2033
+ color: var(--sc-muted, #6b6b73);
2034
+ }
2035
+
2036
+ .sc-meter {
2037
+ height: 7px;
2038
+ border-radius: var(--sc-r-pill, 999px);
2039
+
2040
+ background: var(--sc-line-2, #dcdce0);
2041
+ overflow: hidden;
2042
+ }
2043
+ .sc-meter-fill {
2044
+ display: block;
2045
+ height: 100%;
2046
+ border-radius: var(--sc-r-pill, 999px);
2047
+ background: var(--sc-text, #18181b);
2048
+ transition: width 240ms ease;
2049
+
2050
+ min-width: 6px;
2051
+ }
2052
+
2053
+ .sc-meter-full {
2054
+ background: var(--sc-warn, #b06f14);
2055
+ }
2056
+
2057
+ .sc-plan-rows {
2058
+ list-style: none;
2059
+ margin: 0;
2060
+ padding: 0;
2061
+ border: 1px solid var(--sc-line, #e9e9eb);
2062
+ border-radius: var(--sc-r, 10px);
2063
+
2064
+ overflow: hidden;
2065
+ background: var(--sc-sheet, #fff);
2066
+ }
2067
+
2068
+ .sc-plan-row {
2069
+ display: flex;
2070
+ flex-wrap: wrap;
2071
+ align-items: flex-start;
2072
+ gap: 12px 24px;
2073
+ padding: 18px 20px;
2074
+ }
2075
+ .sc-plan-row + .sc-plan-row {
2076
+ border-top: 1px solid var(--sc-line, #e9e9eb);
2077
+ }
2078
+
2079
+ .sc-row-main {
2080
+ flex: 1 1 300px;
2081
+ min-width: 0;
2082
+ display: flex;
2083
+ flex-direction: column;
2084
+ gap: 6px;
2085
+ }
2086
+
2087
+ .sc-row-side {
2088
+ flex: 0 0 auto;
2089
+ margin-left: auto;
2090
+ display: flex;
2091
+ flex-direction: column;
2092
+ align-items: flex-end;
2093
+ gap: 12px;
2094
+ text-align: right;
2095
+ }
2096
+ .sc-row-side .sc-btn {
2097
+ white-space: nowrap;
2098
+ }
2099
+
2100
+ .sc-row-name {
2101
+ display: flex;
2102
+ align-items: center;
2103
+ gap: 8px;
2104
+ }
2105
+ .sc-plan-row .sc-sub {
2106
+ margin: 0;
2107
+ max-width: 62ch;
2108
+ }
2109
+
2110
+ .sc-row-allowance {
2111
+ margin: 4px 0 0;
2112
+ display: flex;
2113
+ flex-direction: column;
2114
+ gap: 1px;
2115
+ }
2116
+ .sc-row-figure {
2117
+ font-size: 14px;
2118
+ font-weight: 550;
2119
+ font-variant-numeric: tabular-nums;
2120
+ }
2121
+ .sc-row-qualifier {
2122
+ font-size: 12.5px;
2123
+ color: var(--sc-muted, #6b6b73);
2124
+ }
2125
+
2126
+ .sc-plan-compute-inline .sc-fact-key {
2127
+ min-width: 0;
2128
+
2129
+ white-space: nowrap;
2130
+ }
2131
+ .sc-plan-compute-inline {
2132
+ display: flex;
2133
+ align-items: baseline;
2134
+ gap: 8px;
2135
+ font-size: 13.5px;
2136
+ }
2137
+ .sc-compute-inline {
2138
+ display: flex;
2139
+ flex-wrap: wrap;
2140
+ gap: 2px 14px;
2141
+ }
2142
+
2143
+ .sc-plan-reward-inline {
2144
+ flex-direction: row;
2145
+ align-items: baseline;
2146
+ flex-wrap: wrap;
2147
+ gap: 2px 12px;
2148
+ }
2149
+
2150
+ .sc-table-scroll {
2151
+ overflow-x: auto;
2152
+ }
2153
+
2154
+ .sc-plan-table {
2155
+ width: 100%;
2156
+ border-collapse: collapse;
2157
+ text-align: left;
2158
+ }
2159
+
2160
+ .sc-plan-table th[scope="col"] {
2161
+ min-width: 148px;
2162
+ }
2163
+
2164
+ .sc-plan-table th,
2165
+ .sc-plan-table td {
2166
+ padding: 12px;
2167
+ vertical-align: top;
2168
+ border-bottom: 1px solid var(--sc-line, #e9e9eb);
2169
+ }
2170
+
2171
+ .sc-plan-table thead th {
2172
+ border-bottom-color: var(--sc-line-2, #dcdce0);
2173
+ }
2174
+
2175
+ .sc-plan-table tbody th[scope="row"] {
2176
+ font-weight: 400;
2177
+ color: var(--sc-muted, #6b6b73);
2178
+ white-space: nowrap;
2179
+ }
2180
+
2181
+ .sc-plan-table .sc-title {
2182
+ display: block;
2183
+ }
2184
+ .sc-plan-table .sc-plan-price {
2185
+ margin-top: 4px;
2186
+ }
2187
+
2188
+ .sc-table-buy td {
2189
+ border-bottom: none;
2190
+ padding-top: 14px;
2191
+ }
2192
+ .sc-table-buy .sc-btn {
2193
+ width: 100%;
2194
+ }
2195
+
2196
+ .sc-muted-cell {
2197
+ color: var(--sc-muted, #6b6b73);
2198
+ }
2199
+
2200
+ .sc-plan-table .sc-plan-reward-line {
2201
+ margin-bottom: 6px;
2202
+ }
2203
+ .sc-plan-table .sc-btn {
2204
+ padding: 6px 12px;
2205
+ font-size: 13px;
2206
+ }
2207
+
2208
+ .sc-plan-featured {
2209
+ background: var(--sc-raised, #f6f6f7);
2210
+ border-color: var(--sc-line-2, #dcdce0);
2211
+ box-shadow: var(--sc-shadow-2);
2212
+ }
2213
+
2214
+ li.sc-plan-row.sc-plan-featured {
2215
+ box-shadow: none;
2216
+ background: var(--sc-raised, #f6f6f7);
2217
+ }
2218
+ li.sc-plan-row.sc-plan-current {
2219
+ background: var(--sc-raised, #f6f6f7);
2220
+ box-shadow: inset 2px 0 0 var(--sc-text, #18181b);
2221
+ }
2222
+ .sc-plan-table .sc-col-featured {
2223
+ background: var(--sc-raised, #f6f6f7);
2224
+ }
2225
+ .sc-plan-table .sc-col-current {
2226
+ box-shadow: inset 2px 0 0 var(--sc-text, #18181b);
2227
+ }
2228
+
2229
+ .sc-plan-badge-soft {
2230
+ font-size: var(--sc-fs-label, 11px);
2231
+ padding: 2px 6px;
2232
+ border-radius: var(--sc-r-pill, 999px);
2233
+ border: 1px solid var(--sc-line-2, #dcdce0);
2234
+ color: var(--sc-text-2, #3f3f46);
2235
+ white-space: nowrap;
2236
+ }
2237
+
2238
+ .sc-plan-after {
2239
+ margin-left: 5px;
2240
+ }
2241
+
2242
+ .sc-plan-price-sm .sc-plan-amount {
2243
+ font-size: 20px;
2244
+ }
2245
+
2246
+ .sc-limit-head {
2247
+ display: flex;
2248
+ align-items: flex-start;
2249
+ gap: 11px;
2250
+ }
2251
+ .sc-limit-mark {
2252
+ flex: none;
2253
+ display: grid;
2254
+ place-items: center;
2255
+ width: 30px;
2256
+ height: 30px;
2257
+ border-radius: var(--sc-r-sm, 6px);
2258
+ background: var(--sc-raised, #f6f6f7);
2259
+ color: var(--sc-text-2, #3f3f46);
2260
+ }
2261
+ .sc-limit-mark svg {
2262
+ width: 16px;
2263
+ height: 16px;
2264
+ }
2265
+ .sc-limit-title {
2266
+ margin: 0;
2267
+ font-size: var(--sc-fs-body);
2268
+ font-weight: 600;
2269
+
2270
+ line-height: 1.35;
2271
+ }
2272
+ .sc-limit-body {
2273
+ margin: 3px 0 0;
2274
+ font-size: var(--sc-fs-small);
2275
+ color: var(--sc-muted, #6b6b73);
2276
+ }
2277
+
2278
+ .sc-limit-note {
2279
+ margin: 10px 0 0;
2280
+ font-size: var(--sc-fs-small);
2281
+ color: var(--sc-muted, #6b6b73);
2282
+ }
2283
+
2284
+ .sc-modal-sheet .sc-limit-head {
2285
+ flex-direction: column;
2286
+ align-items: center;
2287
+ text-align: center;
2288
+ gap: 0;
2289
+ }
2290
+
2291
+ .sc-modal-sheet .sc-limit-mark {
2292
+ width: 38px;
2293
+ height: 38px;
2294
+ margin-bottom: 12px;
2295
+ border: 1px solid var(--sc-line, #e9e9eb);
2296
+ border-radius: var(--sc-r, 10px);
2297
+ }
2298
+
2299
+ .sc-modal-sheet .sc-limit-mark svg {
2300
+ width: 18px;
2301
+ height: 18px;
2302
+ }
2303
+
2304
+ .sc-modal-sheet .sc-limit-title {
2305
+ font-size: var(--sc-fs-title);
2306
+ letter-spacing: -0.02em;
2307
+ }
2308
+
2309
+ .sc-modal-sheet .sc-limit-body {
2310
+ font-size: var(--sc-fs-small);
2311
+ line-height: 1.45;
2312
+
2313
+ max-width: 34ch;
2314
+ margin: 5px auto 0;
2315
+ }
2316
+
2317
+ .sc-modal-sheet .sc-limit-actions {
2318
+ margin-top: 18px;
2319
+ }
2320
+
2321
+ .sc-modal-sheet .sc-limit-actions .sc-btn {
2322
+ padding: 11px 14px;
2323
+ border-radius: var(--sc-r, 10px);
2324
+ font-weight: 500;
2325
+ }
2326
+
2327
+ .sc-modal-sheet .sc-limit-actions .sc-btn-quiet {
2328
+ position: relative;
2329
+ margin-top: 6px;
2330
+ font-size: var(--sc-fs-small);
2331
+ }
2332
+
2333
+ .sc-modal-sheet .sc-limit-actions .sc-btn-quiet::before {
2334
+ content: "";
2335
+ position: absolute;
2336
+ top: -7px;
2337
+ left: 0;
2338
+ right: 0;
2339
+ border-top: 1px solid var(--sc-line, #e9e9eb);
2340
+ }
2341
+
2342
+ .sc-limit-actions .sc-btn-quiet {
2343
+ flex: 0 0 auto;
2344
+ }
2345
+
2346
+ @keyframes sc-card-in {
2347
+ from {
2348
+ opacity: 0;
2349
+ transform: translateY(3px);
2350
+ }
2351
+ }
2352
+
2353
+ .sc-modal-sheet .sc-card {
2354
+ animation: sc-card-in 140ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
2355
+ }
2356
+
2357
+ .sc-modal-sheet {
2358
+ interpolate-size: allow-keywords;
2359
+ transition: height 200ms cubic-bezier(0.2, 0.8, 0.2, 1);
2360
+ }
2361
+
2362
+ @keyframes sc-arrive {
2363
+ from {
2364
+ opacity: 0;
2365
+ transform: translateY(4px);
2366
+ }
2367
+ }
2368
+
2369
+ .sc-modal-sheet .sc-machine {
2370
+ animation: sc-arrive 200ms cubic-bezier(0.2, 0.8, 0.2, 1) 60ms both;
2371
+ }
2372
+
2373
+ @media (prefers-reduced-motion: reduce) {
2374
+ .sc-modal-sheet .sc-card,
2375
+ .sc-modal-sheet .sc-machine {
2376
+ animation: none;
2377
+ }
2378
+ .sc-modal-sheet {
2379
+ transition: none;
2380
+ }
2381
+ }
2382
+
2383
+ .sc-opt-has {
2384
+ flex: none;
2385
+ font-size: 11px;
2386
+ font-weight: 600;
2387
+ border-radius: var(--sc-r-sm, 6px);
2388
+ padding: 3px 7px;
2389
+ background: var(--sc-raised, #f6f6f7);
2390
+ color: var(--sc-muted, #6b6b73);
2391
+ }
2392
+
2393
+ .sc-opt-has-ok {
2394
+ color: var(--sc-ok, #22a06b);
2395
+ }
2396
+
2397
+ .sc-opt-has-warn {
2398
+ color: var(--sc-warn, #b06f14);
579
2399
  }
580
- `,document.head.appendChild(e)}import{jsx as Ye}from"react/jsx-runtime";var Zt="https://www.soba.so",Yt=15e3;function Xt(e){let{children:t,session:n,sessionEndpoint:o,user:s,runEndpoint:r,theme:m,initialMachines:h,initialConnect:u=null,initialPlans:v,initialCurrentPlan:d=null,baseUrl:a=Zt,pollMs:f=Yt,injectStyles:R=!0,fetchImpl:w,onError:T}=e,[x,I]=$(n??null),[N,Y]=$(null),[g,B]=$(u),[j,U]=$(null),[V,q]=$(u===null),[H,ke]=$(h??[]),[K,ae]=$(null),[ie,fe]=$(h===void 0),[X,Se]=$(v??[]),[Q,ee]=$(d),[te,ce]=$(null),[ge,be]=$(v===void 0),le=Jt(T);le.current=T;let D=J(l=>{Y(l),le.current?.(l)},[]);Z(()=>{R&&Je()},[R]);let S=Ze(()=>new Ne({...n?{token:n}:{},...o?{endpoint:o}:{},...s?{user:s}:{},...w?{fetchImpl:w}:{}}),[n,o,s,w]);Z(()=>{let l=!0,k=S.subscribe(()=>{l&&I(S.token)});return!S.token&&!S.canRefresh?D(new Error("<SobaProvider> needs a `session` or a `sessionEndpoint`. A browser cannot mint one: that takes your secret key.")):S.ensure().then(()=>l&&I(S.token),A=>l&&D(A)),()=>{l=!1,k()}},[S,D]),Z(()=>{N&&(q(!1),fe(!1),be(!1),U(l=>l??N),ae(l=>l??N),ce(l=>l??N))},[N]),Z(()=>{let l=S.refreshAt;if(l===null)return;let k=setTimeout(()=>{S.refresh().catch(A=>D(A))},Math.max(0,l-Date.now()));return()=>clearTimeout(k)},[S,D,x]);let p=Ze(()=>x?new de({session:x,baseUrl:a,fetchImpl:vt(S,w??fetch.bind(globalThis))}):null,[x,a,S,w]);Z(()=>{if(!p)return;let l=!0;return q(!0),p.context().then(k=>{l&&(B(k),U(null),q(!1))},k=>{l&&(U(k),q(!1))}),()=>{l=!1}},[p]);let E=J(async()=>{if(p)try{let l=await p.machines();ke(l),ae(null)}catch(l){ae(l)}finally{fe(!1)}},[p]),F=J(async()=>{if(p)try{let l=await p.plans();Se(l.plans),ee(l.current),ce(null)}catch(l){ce(l)}finally{be(!1)}},[p]);Z(()=>{p&&F()},[p,F]);let ue=J(async l=>{if(!p)throw new Error("No session yet.");await p.selectPlan(l),await F()},[p,F]),i=J(async(l,k)=>{if(!p)throw new Error("No session yet.");let A=await p.checkoutPlan(l,k);if(!A.url)throw new Error("Checkout could not be started.");return A.url},[p]),C=J(async()=>{if(!p)throw new Error("No session yet.");await p.leavePlan(),await F()},[p,F]);Z(()=>{if(!p)return;let l=!0;E();let k=setInterval(()=>{typeof document<"u"&&document.hidden||l&&E()},f);return()=>{l=!1,clearInterval(k)}},[p,E,f]);let P=J(async l=>{if(!r)throw new Error("Pass `runEndpoint` to <SobaProvider> to start runs from the browser. It is your own route: it holds your secret key, calls soba.run(), and forwards the stream.");let{signal:k,...A}=l,Pe=await(w??fetch.bind(globalThis))(r,{method:"POST",headers:{"content-type":"application/json",accept:"text/event-stream"},credentials:"same-origin",body:JSON.stringify(A),...k?{signal:k}:{}});if(!Pe.ok)throw new Error(`${r} answered ${Pe.status}.`);return Ke(Pe)},[r,w]),ne=Ze(()=>({session:x,client:p,error:N,plan:{plans:X,current:Q,plan:Q?X.find(l=>l.id===Q.plan_id)??null:null,loading:ge,error:te,select:ue,checkout:i,leave:C,refresh:F},compute:{machines:H,connected:H.length>0,online:H.some(l=>l.state!=="offline"),loading:ie,error:K,refresh:E},connect:{app:g?.app??null,command:g?.command??null,publishableKey:g?.publishable_key??null,loading:V,error:j},run:P}),[x,p,N,H,ie,K,E,X,Q,ge,te,ue,i,C,F,g,V,j,P]);return Ye(Fe.Provider,{value:p,children:Ye(je.Provider,{value:{context:g,machines:ie?void 0:H,theme:m??g?.theme??"light"},children:Ye(De.Provider,{value:ne,children:t})})})}export{Ot as ComputeStatus,ze as ConnectButton,qt as ConnectCompute,He as ConnectModal,jt as SobaCheckout,zt as SobaPlans,Xt as SobaProvider,Ft as collectText,Je as injectStyles,we as parseEvent,Ke as readEvents,_ as useSoba};
2400
+ `,document.head.appendChild(e)}import{jsx as kt,jsxs as _o}from"react/jsx-runtime";var So="https://www.soba.so",xo=15e3;function Po(e){let{children:n,session:t,sessionEndpoint:s,user:o,runEndpoint:i,theme:a,initialMachines:m,initialConnect:c=null,initialPlans:p,initialCurrentPlan:g=null,baseUrl:b=So,pollMs:h=xo,injectStyles:f=!0,modal:d=!0,fetchImpl:N,onError:k}=e,[x,U]=Y(t??null),[D,C]=Y(null),[$,q]=Y(c),[A,J]=Y(null),[z,F]=Y(c===null),[ce,Pe]=Y(m??[]),[yn,K]=Y(null),[Ce,wn]=Y(m===void 0),[Ne,he]=Y(p??[]),[Z,In]=Y(g),[Ke,Ue]=Y(null),[vn,le]=Y(p===void 0),[te,qe]=Y(null),[$n,_e]=Y(!1),Be=ko(k);Be.current=k;let se=ve(y=>{C(y),Be.current?.(y)},[]);De(()=>{f&&Nt()},[f]);let M=bn(()=>new Tn({...t?{token:t}:{},...s?{endpoint:s}:{},...o?{user:o}:{},...N?{fetchImpl:N}:{}}),[t,s,o,N]);De(()=>{let y=!0,B=M.subscribe(()=>{y&&U(M.token)});return!M.token&&!M.canRefresh?se(new Error("<SobaProvider> needs a `session` or a `sessionEndpoint`. A browser cannot mint one: that takes your secret key.")):M.ensure().then(()=>y&&U(M.token),ue=>y&&se(ue)),()=>{y=!1,B()}},[M,se]),De(()=>{D&&(F(!1),wn(!1),le(!1),J(y=>y??D),K(y=>y??D),Ue(y=>y??D))},[D]),De(()=>{let y=M.refreshAt;if(y===null)return;let B=setTimeout(()=>{M.refresh().catch(ue=>se(ue))},Math.max(0,y-Date.now()));return()=>clearTimeout(B)},[M,se,x]);let S=bn(()=>x?new Xe({session:x,baseUrl:b,fetchImpl:ts(M,N??fetch.bind(globalThis))}):null,[x,b,M,N]);De(()=>{if(!S)return;let y=!0;return F(!0),S.context().then(B=>{y&&(q(B),J(null),F(!1))},B=>{y&&(J(B),F(!1))}),()=>{y=!1}},[S]);let Me=ve(async()=>{if(S)try{let y=await S.machines();Pe(Array.isArray(y)?y:[]),K(null)}catch(y){K(y)}finally{wn(!1)}},[S]),X=ve(async()=>{if(S)try{let y=await S.plans();he(y.plans),In(y.current),Ue(null)}catch(y){Ue(y)}finally{le(!1)}},[S]);De(()=>{S&&X()},[S,X]);let Je=ve(async y=>{if(!S)throw new Error("No session yet.");await S.selectPlan(y),await X()},[S,X]),Cn=ve(async(y,B)=>{if(!S)throw new Error("No session yet.");let ue=await S.checkoutPlan(y,B);if(!ue.url)throw new Error("Checkout could not be started.");return ue.url},[S]),oe=ve(async()=>{if(!S)throw new Error("No session yet.");await S.leavePlan(),await X()},[S,X]);De(()=>{if(!S)return;let y=!0;Me();let B=setInterval(()=>{typeof document<"u"&&document.hidden||y&&Me()},h);return()=>{y=!1,clearInterval(B)}},[S,Me,h]);let ke=ve(async y=>{if(!i)throw new Error("Pass `runEndpoint` to <SobaProvider> to start runs from the browser. It is your own route: it holds your secret key, calls soba.run(), and forwards the stream.");let{signal:B,...ue}=y,Re=await(N??fetch.bind(globalThis))(i,{method:"POST",headers:{"content-type":"application/json",accept:"text/event-stream"},credentials:"same-origin",body:JSON.stringify(ue),...B?{signal:B}:{}});if(!Re.ok){let T=await Re.json().catch(()=>null),ee=new Error(T?.error?.message??`${i} answered ${Re.status}.`);throw ee.status=Re.status,T?.error?.code&&(ee.code=T.error.code),T?.error&&(ee.error=T.error),ee}let An=pt(Re);return async function*(){try{yield*An}finally{X()}}()},[i,N,X]),He=ve((y="manual")=>{d&&(_e(!0),qe(y))},[d]),Fe=ve(()=>qe(null),[]),Q=bn(()=>Z?Ne.find(y=>y.id===Z.plan_id)??null:null,[Ne,Z]),V=bn(()=>Q?Q.connected_reward==="included"&&ce.length>0&&Q.connected_included_units!==null?Q.connected_included_units:Q.included_units:null,[Q,ce]),Nn=bn(()=>({session:x,client:S,error:D,plan:{plans:Ne,current:Z,plan:Q,used:Z?.units_used??null,included:V,remaining:V!==null&&Z?Math.max(0,V-Z.units_used):null,unlimited:Q!==null&&V===null,loading:vn,error:Ke,select:Je,checkout:Cn,leave:oe,refresh:X},compute:{machines:ce,connected:ce.length>0,online:ce.some(y=>y.state!=="offline"),loading:Ce,error:yn,refresh:Me},connect:{app:$?.app??null,command:$?.command??null,connectUrl:$?.connect_url??null,publishableKey:$?.publishable_key??null,loading:z,error:A,open:He,close:Fe,isOpen:te!==null,hasModal:d},run:ke}),[x,S,D,Q,V,te,He,Fe,d,ce,Ce,yn,Me,Ne,Z,vn,Ke,Je,Cn,oe,X,$,z,A,ke]);return kt(rt.Provider,{value:S,children:kt(at.Provider,{value:{context:$,machines:Ce?void 0:ce,theme:a??$?.theme??"light"},children:_o(ot.Provider,{value:Nn,children:[n,d&&$n&&kt(mn,{open:te!==null,onOpenChange:y=>qe(y?te??"manual":null),...te&&te!=="manual"?{reason:te}:{}})]})})})}export{Ms as ComputeStatus,Ae as ConnectButton,Os as ConnectCompute,mn as ConnectModal,Fs as ConnectNudge,Xs as RunLimit,wo as SobaBilling,vo as SobaCheckout,mt as SobaCurrentPlan,ft as SobaPlans,Po as SobaProvider,Ks as collectText,Nt as injectStyles,En as parseEvent,pt as readEvents,fn as sobaErrorCode,gn as useCurrentPlan,ht as usePlans,ut as useRunLimit,I as useSoba};